/// <summary>
        /// Sets the initial parameters of the DifferentialEquationSystem class.
        /// </summary>
        /// <param name="expressions">List of expressions</param>
        /// <param name="leftVariables">List of left variables</param>
        /// <param name="constants">List of constants</param>
        /// <param name="timeVariable">Start time (presents in the expressions)</param>
        /// <param name="tEnd">End time</param>
        /// <param name="tau">Calculation step</param>
        public DifferentialEquationSystem(List <string> expressions, List <DEVariable> leftVariables,
                                          List <DEVariable> constants, DEVariable timeVariable, double tEnd, double tau)
        {
            // Setting up of variables and constants
            if (leftVariables != null)
            {
                this.LeftVariables = DifferentialEquationSystemHelpers.ConvertDEVariablesToVariables(leftVariables);
            }

            if (constants != null)
            {
                this.Constants = DifferentialEquationSystemHelpers.ConvertDEVariablesToVariables(constants);
            }

            if (timeVariable != null)
            {
                this.TimeVariable = timeVariable;
            }

            // Setting up of all variables
            List <Variable> allVariables = new List <Variable>();

            if (this.LeftVariables != null)
            {
                allVariables.AddRange(this.LeftVariables);
            }

            if (this.Constants != null && this.Constants.Count > 0)
            {
                allVariables.AddRange(this.Constants);
            }

            if (this.TimeVariable != null)
            {
                allVariables.Add(this.TimeVariable);
            }

            // Setting up of all expressions
            if (expressions == null || expressions.Count == 0)
            {
                throw new ArgumentException("Container 'expressions' of the constructor cannot be null or empty! Nothing in the differential equation system.");
            }
            else
            {
                this.Expressions = expressions;
                List <Expression> expressionSystem = new List <Expression>();
                foreach (string expression in expressions)
                {
                    expressionSystem.Add(new Expression(expression, allVariables));
                }

                this.ExpressionSystem = expressionSystem;
            }

            this.TEnd = tEnd;
            this.Tau  = tau;

            DifferentialEquationSystemHelpers.CheckVariables(this.ExpressionSystem, this.LeftVariables, this.TimeVariable, this.Tau, this.TEnd);
        }
Example #2
0
        /// <summary>
        /// Sync Euler calculation body
        /// </summary>
        /// <param name="variablesAtAllStep">Container where the intermediate parameters are supposed to be saved</param>
        /// <returns>List of result variables</returns>
        private List <DEVariable> EulerSync(List <List <DEVariable> > variablesAtAllStep = null)
        {
            // Put left variables, constants and time variable in the one containier
            List <Variable> allVars;
            List <Variable> currentLeftVariables = new List <Variable>();
            List <Variable> nextLeftVariables    = new List <Variable>();

            // Copy this.LeftVariables to the current one and to the nex one
            // To leave this.LeftVariables member unchanged (for further calculations)
            DifferentialEquationSystemHelpers.CopyVariables(this.LeftVariables, currentLeftVariables);
            DifferentialEquationSystemHelpers.CopyVariables(this.LeftVariables, nextLeftVariables);

            // Setting of current time (to leave this.TimeVariable unchanged)
            Variable currentTime = new Variable(this.TimeVariable);

            // If it is required to save intermediate calculations - save the start values
            if (variablesAtAllStep != null)
            {
                // This is the first record for intermediate calculations containier
                // It has to be clear
                variablesAtAllStep.Clear();

                DifferentialEquationSystemHelpers.SaveLeftVariableToStatistics(variablesAtAllStep, this.LeftVariables, currentTime);
            }

            do
            {
                // Combinig of variables
                allVars = DifferentialEquationSystemHelpers.CollectVariables(currentLeftVariables, this.Constants, currentTime);

                // Calculation
                for (int i = 0; i < nextLeftVariables.Count; i++)
                {
                    nextLeftVariables[i].Value = currentLeftVariables[i].Value + this.Tau * this.ExpressionSystem[i].GetResultValue(allVars);
                }

                // Saving of all variables at current iteration
                if (variablesAtAllStep != null)
                {
                    DifferentialEquationSystemHelpers.SaveLeftVariableToStatistics(variablesAtAllStep, nextLeftVariables, currentTime);
                }

                // Next variables are becoming the current ones for the next iteration
                DifferentialEquationSystemHelpers.CopyVariables(nextLeftVariables, currentLeftVariables);

                // calculation time incrimentation
                currentTime.Value += this.Tau;
            } while (currentTime.Value < this.TEnd);

            List <DEVariable> result = new List <DEVariable>();

            DifferentialEquationSystemHelpers.CopyVariables(currentLeftVariables, result);
            return(result);
        }
        /// <summary>
        /// Main method which performs a calculation
        /// </summary>
        /// <param name="calculationType">Name of the calculation method</param>
        /// <param name="results">Containier where result variables are supposed to be saved</param>
        /// <param name="variablesAtAllStep">Container of variables at each calculation step</param>
        /// <param name="async">Flag which specifies if it is calculated in parallel mode</param>
        /// <returns>Calculation time</returns>
        public double Calculate(CalculationTypeName calculationType, out List <DEVariable> results, List <List <DEVariable> > variablesAtAllStep = null)
        {
            // Checking the correctness of input variables
            DifferentialEquationSystemHelpers.CheckVariables(this.ExpressionSystem, this.LeftVariables, this.TimeVariable, this.Tau, this.TEnd);

            Func <List <List <DEVariable> >, List <DEVariable> > F = this.DefineSuitableMethod(calculationType);

            Stopwatch stopwatch = new Stopwatch();

            stopwatch.Start();
            results = F(variablesAtAllStep);
            stopwatch.Stop();

            return(stopwatch.ElapsedMilliseconds / 1000.0);
        }
        private async Task <ConcurrentDictionary <CalculationTypeName, double> > CalculateForMethodGroupAsync(List <CalculationTypeName> calculationTypes, ConcurrentDictionary <CalculationTypeName,
                                                                                                                                                                                 List <DEVariable> > results, ConcurrentDictionary <CalculationTypeName, List <List <DEVariable> > > variablesAtAllSteps = null, bool async = false)
        {
            ConcurrentDictionary <CalculationTypeName, double> timeResults = new ConcurrentDictionary <CalculationTypeName, double>();

            // Checking the correctness of input variables
            DifferentialEquationSystemHelpers.CheckVariables(this.ExpressionSystem, this.LeftVariables, this.TimeVariable, this.Tau, this.TEnd);

            List <Task> calculationTasks = new List <Task>();

            foreach (CalculationTypeName calculationType in calculationTypes)
            {
                Func <List <List <DEVariable> >, List <DEVariable> > F = this.DefineSuitableMethod(calculationType);

                Task calculationTask = new Task(() =>
                {
                    Stopwatch stopwatch = new Stopwatch();
                    List <DEVariable> localResult;
                    List <List <DEVariable> > variablesAtAllStepsForMethod = new List <List <DEVariable> >();

                    stopwatch.Start();
                    localResult = F(variablesAtAllStepsForMethod);
                    stopwatch.Stop();

                    results.TryAdd(calculationType, localResult);
                    timeResults.TryAdd(calculationType, stopwatch.ElapsedMilliseconds / 1000.0);

                    if (variablesAtAllSteps != null)
                    {
                        variablesAtAllSteps.TryAdd(calculationType, variablesAtAllStepsForMethod);
                    }
                });

                calculationTask.Start();
                calculationTasks.Add(calculationTask);
            }

            await Task.WhenAll(calculationTasks);

            return(timeResults);
        }
        /// <summary>
        /// Method which calculates a differential equation system with several specified methods.
        /// </summary>
        /// <param name="calculationTypes">List of calculation types which the system is supposed to be calculated with</param>
        /// <param name="results">Container where results will be saved</param>
        /// <param name="variablesAtAllSteps">Container of variables at each calculation step for all methods</param>
        /// <param name="async">Flag which specifies if it is calculated in parallel mode</param>
        /// <returns>Containier with calculation time</returns>
        public Dictionary <CalculationTypeName, double> CalculateWithGroupOfMethodsSync(List <CalculationTypeName> calculationTypes, out Dictionary <CalculationTypeName,
                                                                                                                                                     List <DEVariable> > results, Dictionary <CalculationTypeName, List <List <DEVariable> > > variablesAtAllSteps = null)
        {
            results = new Dictionary <CalculationTypeName, List <DEVariable> >();
            Dictionary <CalculationTypeName, double> timeResults = new Dictionary <CalculationTypeName, double>();

            // Checking the correctness of input variables
            DifferentialEquationSystemHelpers.CheckVariables(this.ExpressionSystem, this.LeftVariables, this.TimeVariable, this.Tau, this.TEnd);

            List <List <DEVariable> > variablesForEachMethod = null;

            if (variablesAtAllSteps != null)
            {
                variablesForEachMethod = new List <List <DEVariable> >();
            }

            foreach (CalculationTypeName calculationType in calculationTypes)
            {
                Func <List <List <DEVariable> >, List <DEVariable> > F = this.DefineSuitableMethod(calculationType);

                List <DEVariable> methodResults;

                Stopwatch stopwatch = new Stopwatch();
                stopwatch.Start();
                methodResults = F(variablesForEachMethod);
                stopwatch.Stop();

                results.Add(calculationType, methodResults);
                timeResults.Add(calculationType, stopwatch.ElapsedMilliseconds / 1000.0);

                if (variablesAtAllSteps != null)
                {
                    variablesAtAllSteps.Add(calculationType, variablesForEachMethod);
                }
            }

            return(timeResults);
        }
Example #6
0
        /// <summary>
        /// Method calculates a differential equation system with RK2 method
        /// </summary>
        /// <param name="variablesAtAllStep">Container where the intermediate parameters are supposed to be saved</param>
        /// <returns>List of result variables</returns>
        private List <DEVariable> RK2Async(List <List <DEVariable> > variablesAtAllStep)
        {
            // Put left variables, constants and time variable in the one containier
            List <Variable> allVars;
            List <Variable> currentLeftVariables = new List <Variable>();
            List <Variable> halfStepVariables    = new List <Variable>();
            List <Variable> nextLeftVariables    = new List <Variable>();

            // Copy this.LeftVariables to the current one and to the nex one
            // To leave this.LeftVariables member unchanged (for further calculations)
            DifferentialEquationSystemHelpers.CopyVariables(this.LeftVariables, currentLeftVariables);
            DifferentialEquationSystemHelpers.CopyVariables(this.LeftVariables, halfStepVariables);
            DifferentialEquationSystemHelpers.CopyVariables(this.LeftVariables, nextLeftVariables);

            // Setting of current time (to leave this.TimeVariable unchanged)
            Variable currentTime = new Variable(this.TimeVariable);

            if (variablesAtAllStep != null)
            {
                // This is the first record for intermediate calculations containier
                // It has to be clear
                variablesAtAllStep.Clear();

                // Copying of the initial left variables to the separate list which when is going to "variablesAtAllStep" containier
                DifferentialEquationSystemHelpers.SaveLeftVariableToStatistics(variablesAtAllStep, this.LeftVariables, currentTime);
            }

            do
            {
                allVars = DifferentialEquationSystemHelpers.CollectVariables(currentLeftVariables, this.Constants, currentTime);

                Parallel.For(0, halfStepVariables.Count, (i) =>
                {
                    halfStepVariables[i].Value = currentLeftVariables[i].Value + this.Tau / 2 * this.ExpressionSystem[i].GetResultValue(allVars);
                });

                allVars = DifferentialEquationSystemHelpers.CollectVariables(halfStepVariables, this.Constants,
                                                                             new Variable(currentTime.Name, currentTime.Value + this.Tau / 2));

                double[] halfValues = new double[currentLeftVariables.Count];
                Parallel.For(0, currentLeftVariables.Count, (i) =>
                {
                    halfValues[i] = this.ExpressionSystem[i].GetResultValue(allVars);
                });

                Parallel.For(0, currentLeftVariables.Count, (i) =>
                {
                    nextLeftVariables[i].Value = currentLeftVariables[i].Value + this.Tau * halfValues[i];
                });

                // Saving of all variables at current iteration
                if (variablesAtAllStep != null)
                {
                    DifferentialEquationSystemHelpers.SaveLeftVariableToStatistics(variablesAtAllStep, nextLeftVariables,
                                                                                   new Variable(currentTime.Name, currentTime.Value + this.Tau));
                }

                // Next variables are becoming the current ones for the next iteration
                DifferentialEquationSystemHelpers.CopyVariables(nextLeftVariables, currentLeftVariables);

                // calculation time incrimentation
                currentTime.Value += this.Tau;
            } while (currentTime.Value < this.TEnd);

            List <DEVariable> result = new List <DEVariable>();

            DifferentialEquationSystemHelpers.CopyVariables(currentLeftVariables, result);
            return(result);
        }
        /// <summary>
        /// Method calculates a differential equation system with RK4 method
        /// </summary>
        /// <param name="variablesAtAllStep">Container where the intermediate parameters are supposed to be saved</param>
        /// <returns>List of result variables</returns>
        private List <DEVariable> RK4Async(List <List <DEVariable> > variablesAtAllStep)
        {
            // Put left variables, constants and time variable in the one containier
            List <Variable> allVars;
            List <Variable> currentLeftVariables = new List <Variable>();
            List <Variable> leftVariablesK1      = new List <Variable>();
            List <Variable> leftVariablesK2      = new List <Variable>();
            List <Variable> leftVariablesK3      = new List <Variable>();
            List <Variable> nextLeftVariables    = new List <Variable>();

            // Copy this.LeftVariables to the current one and to the nex one
            // To leave this.LeftVariables member unchanged (for further calculations)
            DifferentialEquationSystemHelpers.CopyVariables(this.LeftVariables, currentLeftVariables);
            DifferentialEquationSystemHelpers.CopyVariables(this.LeftVariables, leftVariablesK1);
            DifferentialEquationSystemHelpers.CopyVariables(this.LeftVariables, leftVariablesK2);
            DifferentialEquationSystemHelpers.CopyVariables(this.LeftVariables, leftVariablesK3);
            DifferentialEquationSystemHelpers.CopyVariables(this.LeftVariables, nextLeftVariables);

            // Setting of current time (to leave this.TimeVariable unchanged)
            Variable currentTime = new Variable(this.TimeVariable);

            if (variablesAtAllStep != null)
            {
                // This is the first record for intermediate calculations containier
                // It has to be clear
                variablesAtAllStep.Clear();

                // Copying of the initial left variables to the separate list which when is going to "variablesAtAllStep" containier
                DifferentialEquationSystemHelpers.SaveLeftVariableToStatistics(variablesAtAllStep, this.LeftVariables, currentTime);
            }

            do
            {
                // Preparation of variables for K1 calculation
                allVars = DifferentialEquationSystemHelpers.CollectVariables(currentLeftVariables, this.Constants, currentTime);

                // K1 calculation
                double[] K1 = new double[currentLeftVariables.Count];
                Parallel.For(0, K1.Length, (i) =>
                {
                    K1[i] = this.ExpressionSystem[i].GetResultValue(allVars);
                });

                // Preparation of variables for K2 calculation
                Parallel.For(0, currentLeftVariables.Count, (i) =>
                {
                    leftVariablesK1[i].Value = currentLeftVariables[i].Value + this.Tau / 2 * K1[i];
                });

                allVars = DifferentialEquationSystemHelpers.CollectVariables(leftVariablesK1, this.Constants,
                                                                             new Variable(currentTime.Name, currentTime.Value + this.Tau / 2));

                // K2 calculation
                double[] K2 = new double[currentLeftVariables.Count];
                Parallel.For(0, K2.Length, (i) =>
                {
                    K2[i] = this.ExpressionSystem[i].GetResultValue(allVars);
                });

                Parallel.For(0, currentLeftVariables.Count, (i) =>
                {
                    leftVariablesK2[i].Value = currentLeftVariables[i].Value + this.Tau / 2 * K2[i];
                });

                allVars = DifferentialEquationSystemHelpers.CollectVariables(leftVariablesK2, this.Constants,
                                                                             new Variable(currentTime.Name, currentTime.Value + this.Tau / 2));

                // K3 calculation
                double[] K3 = new double[currentLeftVariables.Count];
                Parallel.For(0, K3.Length, (i) =>
                {
                    K3[i] = this.ExpressionSystem[i].GetResultValue(allVars);
                });

                Parallel.For(0, currentLeftVariables.Count, (i) =>
                {
                    leftVariablesK3[i].Value = currentLeftVariables[i].Value + this.Tau * K3[i];
                });

                allVars = DifferentialEquationSystemHelpers.CollectVariables(leftVariablesK3, this.Constants,
                                                                             new Variable(currentTime.Name, currentTime.Value + this.Tau));

                // K4 calculation
                double[] K4 = new double[currentLeftVariables.Count];
                Parallel.For(0, K4.Length, (i) =>
                {
                    K4[i] = this.ExpressionSystem[i].GetResultValue(allVars);
                });

                Parallel.For(0, currentLeftVariables.Count, (i) =>
                {
                    nextLeftVariables[i].Value = currentLeftVariables[i].Value + this.Tau / 6 * (K1[i] + 2 * K2[i] + 2 * K3[i] + K4[i]);
                });

                // Saving of all variables at current iteration
                if (variablesAtAllStep != null)
                {
                    DifferentialEquationSystemHelpers.SaveLeftVariableToStatistics(variablesAtAllStep, nextLeftVariables,
                                                                                   new Variable(currentTime.Name, currentTime.Value + this.Tau));
                }

                // Next variables are becoming the current ones for the next iteration
                DifferentialEquationSystemHelpers.CopyVariables(nextLeftVariables, currentLeftVariables);

                currentTime.Value += this.Tau;
            } while (currentTime.Value < this.TEnd);

            List <DEVariable> result = new List <DEVariable>();

            DifferentialEquationSystemHelpers.CopyVariables(currentLeftVariables, result);
            return(result);
        }
Example #8
0
        /// <summary>
        /// Method calculates a differential equation system with Extrapolation Adams One method
        /// </summary>
        /// <param name="variablesAtAllStep">Container where the intermediate parameters are supposed to be saved</param>
        /// <returns>List of result variables</returns>
        private List <DEVariable> AdamsExtrapolationOneSync(List <List <DEVariable> > variablesAtAllStep = null)
        {
            #region Calculation preparation
            List <Variable> allVars;
            List <Variable> currentLeftVariables = new List <Variable>();
            List <Variable> nextLeftVariables    = new List <Variable>();

            // Copy this.LeftVariables to the current one and to the nex one
            // To leave this.LeftVariables member unchanged (for further calculations)
            DifferentialEquationSystemHelpers.CopyVariables(this.LeftVariables, currentLeftVariables);
            DifferentialEquationSystemHelpers.CopyVariables(this.LeftVariables, nextLeftVariables);

            // Setting of current time (to leave this.TimeVariable unchanged)
            Variable currentTime = new Variable(this.TimeVariable);

            // If it is required to save intermediate calculations - save the start values
            if (variablesAtAllStep != null)
            {
                // This is the first record for intermediate calculations containier
                // It has to be clear
                variablesAtAllStep.Clear();
                DifferentialEquationSystemHelpers.SaveLeftVariableToStatistics(variablesAtAllStep, this.LeftVariables, currentTime);
            }
            #endregion

            #region First variables
            // Varables at "timestart + tau" is supposed to be calculated with other method
            // It was chosen to use Euler method
            // Generated a new instance for its calculation
            DifferentialEquationSystem differentialEquationSystem = new DifferentialEquationSystem(this.ExpressionSystem, this.LeftVariables, this.Constants,
                                                                                                   this.TimeVariable, this.TimeVariable.Value + this.Tau, this.Tau);

            // Calculation
            List <Variable> firstLeftVariables;
            differentialEquationSystem.Calculate(CalculationTypeName.Euler, out List <DEVariable> bufer);
            firstLeftVariables = DifferentialEquationSystemHelpers.ConvertDEVariablesToVariables(bufer);

            // Save the second variables calculated with Euler method
            if (variablesAtAllStep != null)
            {
                DifferentialEquationSystemHelpers.SaveLeftVariableToStatistics(variablesAtAllStep, firstLeftVariables, new Variable(currentTime.Name, currentTime.Value + this.Tau));
            }
            #endregion

            allVars = DifferentialEquationSystemHelpers.CollectVariables(currentLeftVariables, this.Constants, currentTime);

            double[,] Q = new double[2, this.ExpressionSystem.Count];
            for (int i = 0; i < this.ExpressionSystem.Count; i++)
            {
                Q[0, i] = this.Tau * this.ExpressionSystem[i].GetResultValue(allVars);
            }

            currentTime.Value += this.Tau;
            allVars            = DifferentialEquationSystemHelpers.CollectVariables(firstLeftVariables, this.Constants, currentTime);

            for (int i = 0; i < this.ExpressionSystem.Count; i++)
            {
                Q[1, i] = this.Tau * this.ExpressionSystem[i].GetResultValue(allVars);
            }

            do
            {
                for (int i = 0; i < nextLeftVariables.Count; i++)
                {
                    nextLeftVariables[i].Value = currentLeftVariables[i].Value + 0.5 * (3 * Q[1, i] - Q[0, i]);
                }

                allVars = DifferentialEquationSystemHelpers.CollectVariables(nextLeftVariables, this.Constants, new Variable(currentTime.Name, currentTime.Value + this.Tau));

                for (int i = 0; i < nextLeftVariables.Count; i++)
                {
                    Q[0, i] = Q[1, i];
                    Q[1, i] = this.Tau * this.ExpressionSystem[i].GetResultValue(allVars);
                }

                if (variablesAtAllStep != null)
                {
                    DifferentialEquationSystemHelpers.SaveLeftVariableToStatistics(variablesAtAllStep, nextLeftVariables, new Variable(currentTime.Name, currentTime.Value + this.Tau));
                }

                DifferentialEquationSystemHelpers.CopyVariables(nextLeftVariables, currentLeftVariables);

                // calculation time incrimentation
                currentTime.Value += this.Tau;
            } while (currentTime.Value < this.TEnd);

            List <DEVariable> result = new List <DEVariable>();
            DifferentialEquationSystemHelpers.CopyVariables(currentLeftVariables, result);
            return(result);
        }
Example #9
0
        /// <summary>
        /// Method calculates a differential equation system with Extrapolation Adams Three method
        /// </summary>
        /// <param name="variablesAtAllStep">Container where the intermediate parameters are supposed to be saved</param>
        /// <returns>List of result variables</returns>
        private List <DEVariable> AdamsExtrapolationThreeAsync(List <List <DEVariable> > variablesAtAllStep = null)
        {
            #region Calculation preparation

            List <Variable> allVars;
            List <Variable> currentLeftVariables = new List <Variable>();
            List <Variable> nextLeftVariables    = new List <Variable>();

            // Copy this.LeftVariables to the current one and to the nex one
            // To leave this.LeftVariables member unchanged (for further calculations)
            DifferentialEquationSystemHelpers.CopyVariables(this.LeftVariables, currentLeftVariables);
            DifferentialEquationSystemHelpers.CopyVariables(this.LeftVariables, nextLeftVariables);

            // Setting of current time (to leave this.TimeVariable unchanged)
            Variable currentTime = new Variable(this.TimeVariable);

            // If it is required to save intermediate calculations - save the start values
            if (variablesAtAllStep != null)
            {
                // This is the first record for intermediate calculations containier
                // It has to be clear
                variablesAtAllStep.Clear();
                DifferentialEquationSystemHelpers.SaveLeftVariableToStatistics(variablesAtAllStep, this.LeftVariables, currentTime);
            }

            #endregion

            #region First variables

            DifferentialEquationSystem differentialEquationSystem = new DifferentialEquationSystem(this.ExpressionSystem, this.LeftVariables, this.Constants,
                                                                                                   this.TimeVariable, this.TimeVariable.Value + 3 * this.Tau, this.Tau);
            List <List <DEVariable> > firstVariables = new List <List <DEVariable> >();

            differentialEquationSystem.Calculate(CalculationTypeName.Euler, out List <DEVariable> bufer, firstVariables);

            List <Variable> firstLeftVariables;
            List <Variable> secondLeftVariables;
            List <Variable> thirdLeftVariables;

            firstLeftVariables  = DifferentialEquationSystemHelpers.ConvertDEVariablesToVariables(firstVariables[1]);
            secondLeftVariables = DifferentialEquationSystemHelpers.ConvertDEVariablesToVariables(firstVariables[2]);
            thirdLeftVariables  = DifferentialEquationSystemHelpers.ConvertDEVariablesToVariables(firstVariables[3]);

            firstLeftVariables.RemoveAt(firstLeftVariables.Count - 1);
            secondLeftVariables.RemoveAt(secondLeftVariables.Count - 1);
            thirdLeftVariables.RemoveAt(thirdLeftVariables.Count - 1);

            if (variablesAtAllStep != null)
            {
                DifferentialEquationSystemHelpers.SaveLeftVariableToStatistics(variablesAtAllStep, firstLeftVariables, new Variable(currentTime.Name, currentTime.Value + this.Tau));
                DifferentialEquationSystemHelpers.SaveLeftVariableToStatistics(variablesAtAllStep, secondLeftVariables, new Variable(currentTime.Name, currentTime.Value + 2 * this.Tau));
                DifferentialEquationSystemHelpers.SaveLeftVariableToStatistics(variablesAtAllStep, thirdLeftVariables, new Variable(currentTime.Name, currentTime.Value + 3 * this.Tau));
            }

            #endregion

            double[,] Q = new double[4, this.ExpressionSystem.Count];

            allVars = DifferentialEquationSystemHelpers.CollectVariables(currentLeftVariables, this.Constants, currentTime);
            Parallel.For(0, this.ExpressionSystem.Count, (i) =>
            {
                Q[0, i] = this.Tau * this.ExpressionSystem[i].GetResultValue(allVars);
            });

            currentTime.Value += this.Tau;
            allVars            = DifferentialEquationSystemHelpers.CollectVariables(firstLeftVariables, this.Constants, currentTime);

            Parallel.For(0, this.ExpressionSystem.Count, (i) =>
            {
                Q[1, i] = this.Tau * this.ExpressionSystem[i].GetResultValue(allVars);
            });

            currentTime.Value += this.Tau;
            allVars            = DifferentialEquationSystemHelpers.CollectVariables(secondLeftVariables, this.Constants, currentTime);

            Parallel.For(0, this.ExpressionSystem.Count, (i) =>
            {
                Q[2, i] = this.Tau * this.ExpressionSystem[i].GetResultValue(allVars);
            });

            currentTime.Value += this.Tau;
            allVars            = DifferentialEquationSystemHelpers.CollectVariables(thirdLeftVariables, this.Constants, currentTime);

            Parallel.For(0, this.ExpressionSystem.Count, (i) =>
            {
                Q[3, i] = this.Tau * this.ExpressionSystem[i].GetResultValue(allVars);
            });

            DifferentialEquationSystemHelpers.CopyVariables(thirdLeftVariables, currentLeftVariables);

            do
            {
                Parallel.For(0, nextLeftVariables.Count, (i) =>
                {
                    nextLeftVariables[i].Value = currentLeftVariables[i].Value + 1.0 / 24 * (55 * Q[3, i] - 59 * Q[2, i] + 37 * Q[1, i] - 9 * Q[0, i]);
                });

                allVars = DifferentialEquationSystemHelpers.CollectVariables(nextLeftVariables, this.Constants, new Variable(currentTime.Name, currentTime.Value + this.Tau));

                Parallel.For(0, nextLeftVariables.Count, (i) =>
                {
                    Q[0, i] = Q[1, i];
                    Q[1, i] = Q[2, i];
                    Q[2, i] = Q[3, i];
                    Q[3, i] = this.Tau * this.ExpressionSystem[i].GetResultValue(allVars);
                });

                if (variablesAtAllStep != null)
                {
                    DifferentialEquationSystemHelpers.SaveLeftVariableToStatistics(variablesAtAllStep, nextLeftVariables,
                                                                                   new Variable(currentTime.Name, currentTime.Value + this.Tau));
                }

                DifferentialEquationSystemHelpers.CopyVariables(nextLeftVariables, currentLeftVariables);

                currentTime.Value += this.Tau;
            } while (currentTime.Value < this.TEnd);

            List <DEVariable> result = new List <DEVariable>();
            DifferentialEquationSystemHelpers.CopyVariables(currentLeftVariables, result);
            return(result);
        }
        /// <summary>
        /// Method calculates a differential equation system with Miln method
        /// </summary>
        /// <param name="variablesAtAllStep">Container where the intermediate parameters are supposed to be saved</param>
        /// <returns>List of result variables</returns>
        private List <DEVariable> MilnSync(List <List <DEVariable> > variablesAtAllStep = null)
        {
            #region Calculation preparation

            List <Variable> allVars;
            List <Variable> currentLeftVariables = new List <Variable>();
            List <Variable> milnPredicted        = new List <Variable>();
            List <Variable> nextLeftVariables    = new List <Variable>();

            // Copy this.LeftVariables to the current one and to the nex one
            // To leave this.LeftVariables member unchanged (for further calculations)
            DifferentialEquationSystemHelpers.CopyVariables(this.LeftVariables, currentLeftVariables);
            DifferentialEquationSystemHelpers.CopyVariables(this.LeftVariables, milnPredicted);
            DifferentialEquationSystemHelpers.CopyVariables(this.LeftVariables, nextLeftVariables);

            // Setting of current time (to leave this.TimeVariable unchanged)
            Variable currentTime = new Variable(this.TimeVariable);

            // If it is required to save intermediate calculations - save the start values
            if (variablesAtAllStep != null)
            {
                // This is the first record for intermediate calculations containier
                // It has to be clear
                variablesAtAllStep.Clear();
                DifferentialEquationSystemHelpers.SaveLeftVariableToStatistics(variablesAtAllStep, this.LeftVariables, currentTime);
            }

            #endregion

            #region First variables

            DifferentialEquationSystem differentialEquationSystem = new DifferentialEquationSystem(this.ExpressionSystem, this.LeftVariables, this.Constants,
                                                                                                   this.TimeVariable, this.TimeVariable.Value + 3 * this.Tau, this.Tau);
            List <List <DEVariable> > firstVariables = new List <List <DEVariable> >();
            List <DEVariable>         bufer;

            differentialEquationSystem.Calculate(CalculationTypeName.Euler, out bufer, firstVariables);

            List <Variable> firstLeftVariables;
            List <Variable> secondLeftVariables;
            List <Variable> thirdLeftVariables;

            firstLeftVariables  = DifferentialEquationSystemHelpers.ConvertDEVariablesToVariables(firstVariables[1]);
            secondLeftVariables = DifferentialEquationSystemHelpers.ConvertDEVariablesToVariables(firstVariables[2]);
            thirdLeftVariables  = DifferentialEquationSystemHelpers.ConvertDEVariablesToVariables(firstVariables[3]);

            firstLeftVariables.RemoveAt(firstLeftVariables.Count - 1);
            secondLeftVariables.RemoveAt(secondLeftVariables.Count - 1);
            thirdLeftVariables.RemoveAt(thirdLeftVariables.Count - 1);

            if (variablesAtAllStep != null)
            {
                DifferentialEquationSystemHelpers.SaveLeftVariableToStatistics(variablesAtAllStep, firstLeftVariables, new Variable(currentTime.Name, currentTime.Value + this.Tau));
                DifferentialEquationSystemHelpers.SaveLeftVariableToStatistics(variablesAtAllStep, secondLeftVariables, new Variable(currentTime.Name, currentTime.Value + 2 * this.Tau));
                DifferentialEquationSystemHelpers.SaveLeftVariableToStatistics(variablesAtAllStep, thirdLeftVariables, new Variable(currentTime.Name, currentTime.Value + 3 * this.Tau));
            }

            #endregion

            double[,] Q          = new double[4, this.ExpressionSystem.Count];
            double[,] prevValues = new double[4, this.ExpressionSystem.Count];

            allVars = DifferentialEquationSystemHelpers.CollectVariables(currentLeftVariables, this.Constants, currentTime);
            for (int i = 0; i < this.ExpressionSystem.Count; i++)
            {
                Q[0, i]          = this.ExpressionSystem[i].GetResultValue(allVars);
                prevValues[0, i] = currentLeftVariables[i].Value;
            }

            currentTime.Value += this.Tau;
            allVars            = DifferentialEquationSystemHelpers.CollectVariables(firstLeftVariables, this.Constants, currentTime);

            for (int i = 0; i < this.ExpressionSystem.Count; i++)
            {
                Q[1, i]          = this.ExpressionSystem[i].GetResultValue(allVars);
                prevValues[1, i] = firstLeftVariables[i].Value;
            }

            currentTime.Value += this.Tau;
            allVars            = DifferentialEquationSystemHelpers.CollectVariables(secondLeftVariables, this.Constants, currentTime);

            for (int i = 0; i < this.ExpressionSystem.Count; i++)
            {
                Q[2, i]          = this.ExpressionSystem[i].GetResultValue(allVars);
                prevValues[2, i] = secondLeftVariables[i].Value;
            }

            currentTime.Value += this.Tau;
            allVars            = DifferentialEquationSystemHelpers.CollectVariables(thirdLeftVariables, this.Constants, currentTime);
            for (int i = 0; i < this.ExpressionSystem.Count; i++)
            {
                Q[3, i]          = this.ExpressionSystem[i].GetResultValue(allVars);
                prevValues[3, i] = thirdLeftVariables[i].Value;
            }

            DifferentialEquationSystemHelpers.CopyVariables(thirdLeftVariables, currentLeftVariables);

            do
            {
                for (int i = 0; i < milnPredicted.Count; i++)
                {
                    milnPredicted[i].Value = prevValues[0, i] + 4 * this.Tau / 3 * (2 * Q[1, i] - Q[2, i] + 2 * Q[3, i]);
                }

                double[] predictedValues = new double[milnPredicted.Count];
                allVars = DifferentialEquationSystemHelpers.CollectVariables(milnPredicted, this.Constants, new Variable(currentTime.Name, currentTime.Value + this.Tau));
                for (int i = 0; i < predictedValues.Length; i++)
                {
                    predictedValues[i] = this.ExpressionSystem[i].GetResultValue(allVars);
                }

                for (int i = 0; i < nextLeftVariables.Count; i++)
                {
                    nextLeftVariables[i].Value = prevValues[2, i] + this.Tau / 3 * (Q[2, i] + 4 * this.ExpressionSystem[i].GetResultValue(DifferentialEquationSystemHelpers.CollectVariables(currentLeftVariables, this.Constants, currentTime)) + predictedValues[i]);
                }

                allVars = DifferentialEquationSystemHelpers.CollectVariables(nextLeftVariables, this.Constants, new Variable(currentTime.Name, currentTime.Value + this.Tau));

                for (int i = 0; i < nextLeftVariables.Count; i++)
                {
                    Q[0, i] = Q[1, i];
                    Q[1, i] = Q[2, i];
                    Q[2, i] = Q[3, i];
                    Q[3, i] = this.ExpressionSystem[i].GetResultValue(allVars);

                    prevValues[0, i] = prevValues[1, i];
                    prevValues[1, i] = prevValues[2, i];
                    prevValues[2, i] = prevValues[3, i];
                    prevValues[3, i] = nextLeftVariables[i].Value;
                }

                if (variablesAtAllStep != null)
                {
                    DifferentialEquationSystemHelpers.SaveLeftVariableToStatistics(variablesAtAllStep, nextLeftVariables,
                                                                                   new Variable(currentTime.Name, currentTime.Value + this.Tau));
                }

                DifferentialEquationSystemHelpers.CopyVariables(nextLeftVariables, currentLeftVariables);

                currentTime.Value += this.Tau;
            } while (currentTime.Value < this.TEnd);

            List <DEVariable> result = new List <DEVariable>();
            DifferentialEquationSystemHelpers.CopyVariables(currentLeftVariables, result);
            return(result);
        }
        /// <summary>
        /// Method calculates a differential equation system with Forecast-Correction method
        /// </summary>
        /// <param name="variablesAtAllStep">Container where the intermediate parameters are supposed to be saved</param>
        /// <returns>List of result variables</returns>
        private List <DEVariable> ForecastCorrectionAsync(List <List <DEVariable> > variablesAtAllStep = null)
        {
            // Put left variables, constants and time variable in the one containier
            List <Variable> allVars;
            List <Variable> currentLeftVariables   = new List <Variable>();
            List <Variable> predictedLeftVariables = new List <Variable>();
            List <Variable> nextLeftVariables      = new List <Variable>();

            // Copy this.LeftVariables to the current one and to the nex one
            // To leave this.LeftVariables member unchanged (for further calculations)
            DifferentialEquationSystemHelpers.CopyVariables(this.LeftVariables, currentLeftVariables);
            DifferentialEquationSystemHelpers.CopyVariables(this.LeftVariables, predictedLeftVariables);
            DifferentialEquationSystemHelpers.CopyVariables(this.LeftVariables, nextLeftVariables);

            Variable currentTime = new Variable(this.TimeVariable);

            if (variablesAtAllStep != null)
            {
                // This is the first record for intermediate calculations containier
                // It has to be clear
                variablesAtAllStep.Clear();

                DifferentialEquationSystemHelpers.SaveLeftVariableToStatistics(variablesAtAllStep, this.LeftVariables, currentTime);
            }

            do
            {
                // Combinig of variables to calculate the next step results
                allVars = DifferentialEquationSystemHelpers.CollectVariables(currentLeftVariables, this.Constants, currentTime);

                // Calculation of functions values for the next steps
                double[] FCurrent = new double[this.ExpressionSystem.Count];
                Parallel.For(0, currentLeftVariables.Count, (i) =>
                {
                    FCurrent[i] = this.ExpressionSystem[i].GetResultValue(allVars);
                });

                // Calculation of variables for the next steps
                Parallel.For(0, predictedLeftVariables.Count, (i) =>
                {
                    predictedLeftVariables[i].Value = currentLeftVariables[i].Value + this.Tau * this.ExpressionSystem[i].GetResultValue(allVars);
                });

                // Combinig of variables with ones taken from the previous iteration (variables for the next step)
                allVars = DifferentialEquationSystemHelpers.CollectVariables(predictedLeftVariables, this.Constants,
                                                                             new Variable(currentTime.Name, currentTime.Value + this.Tau));

                // Calculation of the next variables
                double[] FPredicted = new double[this.ExpressionSystem.Count];
                Parallel.For(0, predictedLeftVariables.Count, (i) =>
                {
                    FPredicted[i] = this.ExpressionSystem[i].GetResultValue(allVars);
                });

                // Calculation of the next variables
                Parallel.For(0, predictedLeftVariables.Count, (i) =>
                {
                    nextLeftVariables[i].Value = currentLeftVariables[i].Value + this.Tau * (FCurrent[i] + FPredicted[i]) / 2;
                });


                if (variablesAtAllStep != null)
                {
                    DifferentialEquationSystemHelpers.SaveLeftVariableToStatistics(variablesAtAllStep, nextLeftVariables,
                                                                                   new Variable(currentTime.Name, currentTime.Value + this.Tau));
                }

                DifferentialEquationSystemHelpers.CopyVariables(nextLeftVariables, currentLeftVariables);

                currentTime.Value += this.Tau;
            } while (currentTime.Value < this.TEnd);

            List <DEVariable> result = new List <DEVariable>();

            DifferentialEquationSystemHelpers.CopyVariables(currentLeftVariables, result);
            return(result);
        }
        /// <summary>
        /// Method calculates a differential equation system with Forecast-Correction method
        /// </summary>
        /// <param name="variablesAtAllStep">Container where the intermediate parameters are supposed to be saved</param>
        /// <returns>List of result variables</returns>
        private List <DEVariable> ForecastCorrectionSync(List <List <DEVariable> > variablesAtAllStep = null)
        {
            // Put left variables, constants and time variable in the one containier
            List <Variable> allVars;
            List <Variable> currentLeftVariables   = new List <Variable>();
            List <Variable> predictedLeftVariables = new List <Variable>();
            List <Variable> nextLeftVariables      = new List <Variable>();

            // Copy this.LeftVariables to the current one and to the nex one
            // To leave this.LeftVariables member unchanged (for further calculations)
            DifferentialEquationSystemHelpers.CopyVariables(this.LeftVariables, currentLeftVariables);
            DifferentialEquationSystemHelpers.CopyVariables(this.LeftVariables, predictedLeftVariables);
            DifferentialEquationSystemHelpers.CopyVariables(this.LeftVariables, nextLeftVariables);

            // Setting of current time (to leave this.TimeVariable unchanged)
            Variable currentTime = new Variable(this.TimeVariable);

            if (variablesAtAllStep != null)
            {
                // This is the first record for intermediate calculations containier
                // It has to be clear
                variablesAtAllStep.Clear();

                DifferentialEquationSystemHelpers.SaveLeftVariableToStatistics(variablesAtAllStep, this.LeftVariables, currentTime);
            }

            do
            {
                // Combinig of variables to calculate the next step results
                allVars = DifferentialEquationSystemHelpers.CollectVariables(currentLeftVariables, this.Constants, currentTime);

                // Calculation of functions values for the next steps
                List <double> FCurrent = new List <double>();
                for (int i = 0; i < currentLeftVariables.Count; i++)
                {
                    FCurrent.Add(this.ExpressionSystem[i].GetResultValue(allVars));
                }

                // Calculation of variables for the next steps
                for (int i = 0; i < predictedLeftVariables.Count; i++)
                {
                    predictedLeftVariables[i].Value = currentLeftVariables[i].Value + this.Tau * this.ExpressionSystem[i].GetResultValue(allVars);
                }

                // Combinig of variables with ones taken from the previous iteration (variables for the next step)
                allVars = DifferentialEquationSystemHelpers.CollectVariables(predictedLeftVariables, this.Constants,
                                                                             new Variable(currentTime.Name, currentTime.Value + this.Tau));

                // Calculation of predicted variables
                List <double> FPredicted = new List <double>();
                for (int i = 0; i < predictedLeftVariables.Count; i++)
                {
                    FPredicted.Add(this.ExpressionSystem[i].GetResultValue(allVars));
                }

                // Calculation of the next variables
                for (int i = 0; i < predictedLeftVariables.Count; i++)
                {
                    nextLeftVariables[i].Value = currentLeftVariables[i].Value + this.Tau * (FCurrent[i] + FPredicted[i]) / 2;
                }

                // Saving of all variables at current iteration
                if (variablesAtAllStep != null)
                {
                    DifferentialEquationSystemHelpers.SaveLeftVariableToStatistics(variablesAtAllStep, nextLeftVariables,
                                                                                   new Variable(currentTime.Name, currentTime.Value + this.Tau));
                }

                // Next variables are becoming the current ones for the next iteration
                DifferentialEquationSystemHelpers.CopyVariables(nextLeftVariables, currentLeftVariables);

                // calculation time incrimentation
                currentTime.Value += this.Tau;
            } while (currentTime.Value < this.TEnd);

            List <DEVariable> result = new List <DEVariable>();

            DifferentialEquationSystemHelpers.CopyVariables(currentLeftVariables, result);
            return(result);
        }