/// <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);
        }
        /// <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);
        }