/// <summary>
        /// Calculates the <see cref="BalancedFieldLengthOutput"/> based on <paramref name="calculation"/>.
        /// </summary>
        /// <param name="calculation">The <see cref="BalancedFieldLengthCalculation"/> to calculate for.</param>
        /// <returns>A <see cref="BalancedFieldLengthOutput"/>.</returns>
        /// <exception cref="ArgumentNullException">Thrown when <paramref name="calculation"/> is <c>null</c>.</exception>
        /// <exception cref="CreateKernelDataException">Thrown when the calculation input
        /// could not be created for the kernel.</exception>
        /// <exception cref="KernelCalculationException">Thrown when <see cref="AggregatedDistanceOutput"/>
        /// could not be calculated.</exception>
        public BalancedFieldLengthOutput Calculate(BalancedFieldLengthCalculation calculation)
        {
            if (calculation == null)
            {
                throw new ArgumentNullException(nameof(calculation));
            }

            GeneralSimulationSettingsData generalSimulationSettings = calculation.SimulationSettings;
            double density     = generalSimulationSettings.Density;
            int    endVelocity = generalSimulationSettings.EndFailureVelocity;
            double gravitationalAcceleration = generalSimulationSettings.GravitationalAcceleration;

            EngineData   engineData        = calculation.EngineData;
            int          nrOfFailedEngines = engineData.NrOfFailedEngines;
            AircraftData aircraftData      = AircraftDataFactory.Create(calculation.AircraftData, engineData);

            var integrator = new EulerIntegrator();

            var outputs = new List <AggregatedDistanceOutput>();

            for (int i = 0; i < endVelocity; i++)
            {
                var calculationInput = new CalculationInput(generalSimulationSettings,
                                                            i,
                                                            aircraftData,
                                                            integrator,
                                                            nrOfFailedEngines,
                                                            density,
                                                            gravitationalAcceleration);
                AggregatedDistanceOutput output = CalculateDistances(calculationInput);
                outputs.Add(output);
            }

            return(BalancedFieldLengthOutputFactory.Create(outputs));
        }
Example #2
0
        public static void Calculate_WithArguments_ExecutesDistanceCalculatorsAndReturnsExpectedOutput()
        {
            // Setup
            var random = new Random(21);

            AircraftData        aircraftData              = AircraftDataTestFactory.CreateRandomAircraftData();
            var                 integrator                = Substitute.For <IIntegrator>();
            int                 nrOfFailedEngines         = random.Next();
            double              density                   = random.NextDouble();
            double              gravitationalAcceleration = random.NextDouble();
            CalculationSettings calculationSettings       = CalculationSettingsTestFactory.CreateDistanceCalculatorSettings();

            var abortedTakeOffDistanceCalculator = Substitute.For <IDistanceCalculator>();
            var abortedTakeOffDistanceOutput     = new DistanceCalculatorOutput(calculationSettings.FailureSpeed, random.NextDouble());

            abortedTakeOffDistanceCalculator.Calculate().Returns(abortedTakeOffDistanceOutput);

            var continuedTakeOffDistanceCalculator = Substitute.For <IDistanceCalculator>();
            var continuedTakeOffDistanceOutput     = new DistanceCalculatorOutput(calculationSettings.FailureSpeed, random.NextDouble());

            continuedTakeOffDistanceCalculator.Calculate().Returns(continuedTakeOffDistanceOutput);

            var distanceCalculatorFactory = Substitute.For <IDistanceCalculatorFactory>();

            distanceCalculatorFactory.CreateAbortedTakeOffDistanceCalculator(Arg.Is(aircraftData),
                                                                             Arg.Is(integrator),
                                                                             Arg.Is(density),
                                                                             Arg.Is(gravitationalAcceleration),
                                                                             Arg.Is(calculationSettings))
            .Returns(abortedTakeOffDistanceCalculator);
            distanceCalculatorFactory.CreateContinuedTakeOffDistanceCalculator(Arg.Is(aircraftData),
                                                                               Arg.Is(integrator),
                                                                               Arg.Is(nrOfFailedEngines),
                                                                               Arg.Is(density),
                                                                               Arg.Is(gravitationalAcceleration),
                                                                               Arg.Is(calculationSettings))
            .Returns(continuedTakeOffDistanceCalculator);

            var aggregatedCalculator = new Calculator.AggregatedDistanceCalculator.AggregatedDistanceCalculator(distanceCalculatorFactory);

            // Call
            AggregatedDistanceOutput output = aggregatedCalculator.Calculate(aircraftData, integrator, nrOfFailedEngines, density, gravitationalAcceleration, calculationSettings);

            // Assert
            Assert.AreEqual(calculationSettings.FailureSpeed, output.FailureSpeed);
            Assert.AreEqual(abortedTakeOffDistanceOutput.Distance, output.AbortedTakeOffDistance);
            Assert.AreEqual(continuedTakeOffDistanceOutput.Distance, output.ContinuedTakeOffDistance);
        }
Example #3
0
        public void GivenKernel_WhenCalculationsAreMadeForVelocityRange_ThenReturnsExpectedOutputsAndBalancedFieldLength(AircraftData aircraftData,
                                                                                                                         IntegrationReferenceData integrationReferenceData)
        {
            // Given
            var integrator        = new EulerIntegrator();
            var calculationKernel = new AggregatedDistanceCalculatorKernel();

            // When
            var outputs = new List <AggregatedDistanceOutput>();

            for (int i = 0; i < 90; i++)
            {
                var calculationSettings         = new CalculationSettings(i, maximumTimeSteps, timeStep);
                AggregatedDistanceOutput result = calculationKernel.Calculate(aircraftData,
                                                                              integrator,
                                                                              1,
                                                                              density,
                                                                              gravitationalAcceleration,
                                                                              calculationSettings);
                outputs.Add(result);
            }

            BalancedFieldLength balancedFieldLength = BalancedFieldLengthCalculator.CalculateBalancedFieldLength(outputs);

            // Then
            IEnumerable <ReferenceOutput> referenceOutputs = GetReferenceOutputs(integrationReferenceData.FileName);
            int expectedLength = referenceOutputs.Count();

            Assert.AreEqual(expectedLength, outputs.Count, "Number of reference data entries do not match with actual number of entries");

            int velocity = 0;

            foreach (ReferenceOutput referenceOutput in referenceOutputs)
            {
                Assert.AreEqual(referenceOutput.Velocity, outputs[velocity].FailureSpeed);
                Assert.AreEqual(referenceOutput.ContinuedTakeOffDistance, outputs[velocity].ContinuedTakeOffDistance, tolerance);
                Assert.AreEqual(referenceOutput.AbortedTakeOffDistance, outputs[velocity].AbortedTakeOffDistance, tolerance);

                velocity++;
            }

            Assert.AreEqual(integrationReferenceData.Velocity, balancedFieldLength.Velocity, tolerance);
            Assert.AreEqual(integrationReferenceData.Distance, balancedFieldLength.Distance, tolerance);
        }
Example #4
0
        /// <summary>
        /// Calculates the balanced field length by determining the intersection between the distances covered by the rejected
        /// and the continued take off.
        /// </summary>
        /// <param name="outputs">The collection of <see cref="AggregatedDistanceOutput"/> to determine the balanced field length for.</param>
        /// <returns>An <see cref="BalancedFieldLength"/> containing the information at which balanced field length occurs.</returns>
        /// <exception cref="ArgumentNullException">Thrown when <see cref="outputs"/> is <c>null</c>.</exception>
        /// <exception cref="ArgumentException">Thrown when <paramref name="outputs"/>
        /// <list type="bullet">
        /// <item>contains a duplicate definition for a certain failure speed,</item>
        /// <item>is empty,</item>
        /// <item>contains only one element.</item>
        /// </list></exception>
        /// <remarks>This method will sort <paramref name="outputs"/> in an ascending order based on the failure speed.
        /// The intersection is determined based on this sorted list.</remarks>
        public static BalancedFieldLength CalculateBalancedFieldLength(IEnumerable <AggregatedDistanceOutput> outputs)
        {
            if (outputs == null)
            {
                throw new ArgumentNullException(nameof(outputs));
            }

            IEnumerable <AggregatedDistanceOutput> sortedOutputs = SortOutputs(outputs);

            if (sortedOutputs.Count() <= 1)
            {
                throw new ArgumentException(Resources.BalancedFieldLengthCalculator_Cannot_determine_crossing_from_empty_or_single_item_collection);
            }

            AggregatedDistanceOutput previousOutput = sortedOutputs.First();

            for (int i = 1; i < sortedOutputs.Count(); i++)
            {
                AggregatedDistanceOutput currentOutput = sortedOutputs.ElementAt(i);

                // Create line segments
                var continuedTakeOffSegment = new LineSegment(new Point2D(previousOutput.FailureSpeed, previousOutput.ContinuedTakeOffDistance),
                                                              new Point2D(currentOutput.FailureSpeed, currentOutput.ContinuedTakeOffDistance));

                var abortedTakeOffSegment = new LineSegment(new Point2D(previousOutput.FailureSpeed, previousOutput.AbortedTakeOffDistance),
                                                            new Point2D(currentOutput.FailureSpeed, currentOutput.AbortedTakeOffDistance));

                // Determine whether lines cross
                Point2D crossingPoint = Geometry2DHelper.DetermineLineIntersection(continuedTakeOffSegment, abortedTakeOffSegment);

                // Determine if the result is valid
                if (!double.IsNaN(crossingPoint.X) && !double.IsNaN(crossingPoint.Y))
                {
                    double intersectionDistance = crossingPoint.Y;
                    return(new BalancedFieldLength(crossingPoint.X, intersectionDistance));
                }

                previousOutput = currentOutput;
            }

            return(new BalancedFieldLength(double.NaN, double.NaN));
        }