Esempio n. 1
0
        /// <summary>
        /// Solves ODE system on segment
        /// </summary>
        /// <param name="problem"></param>
        /// <param name="partialSumOrder"></param>
        /// <param name="iterCount"></param>
        /// <param name="nodes">Nodes should be inside problem segment</param>
        /// <returns></returns>
        public DiscreteFunction2D[] Solve(CauchyProblem problem, int partialSumOrder, int iterCount, double[] nodes)
        {
            // To apply iter method we should linear transform problem segment to orthogonality segment.
            // Let's denote orthogonality segment by [a0,b0] and problem segment by [a,b].
            // We want to transform problem y'(x)=f(x,y(x)), x \in [a,b], y(a)=y0 to equivalent
            // problem on [a0,b0]. For this purpose we use transform x = (t-a0)(b-a)/(b0-a0)+a:
            // z(t)=y(x)=y(t-a0)(b-a)/(b0-a0)+a). Let's rewrite original problem in terms of z(t) and t:
            // z'(t)=y'(x)*(b-a)/(b0-a0)=f((t-a0)(b-a)/(b0-a0)+a, z(t))*(b-a)/(b0-a0), z(a0)=y(a).
            // Finally, with notation h=(b-a)/(b0-a0) we have:
            // z'(t)=h * f(h(t-a0)+a, z(t)), z(a0)=y(a).
            // So to solve original problem on [a,b] we can solve new problem on [a0,b0] and then use inverse
            // transform to get y(x) from z(t).
            var(a, b)   = problem.Segment;
            var(a0, b0) = _spectralOdeOperator.OrthogonalitySegment;
            var h = problem.Segment.Length / _spectralOdeOperator.OrthogonalitySegment.Length;

            var transformedRightSides = problem.RightSides.Select(fj =>
                                                                  new DynFunc <double>(fj.ArgsCount, doubles =>
            {
                var newDoubles = new double[doubles.Length];
                Array.Copy(doubles, newDoubles, doubles.Length);
                newDoubles[0] = h * (doubles[0] - a0) + a;
                return(h * fj.Invoke(newDoubles));
            })).ToArray();


            var dfs = SolveOnOrthogonalitySegment(transformedRightSides, problem.InitialValues,
                                                  partialSumOrder, iterCount, nodes.Select(x => (x - a) / h + a0).ToArray());

            // dfs is defined on [a0,b0] and we should transform it to [a,b]
            return(dfs.Select(df =>
                              new DiscreteFunction2D(df.X.Select(x => h * (x - a0) + a).ToArray(),
                                                     df.Y)).ToArray());
        }
Esempio n. 2
0
        public List <DiscreteFunction2D[]> Solve(CauchyProblem problem, int chunksCount,
                                                 int partialSumOrder, int iterCount, int chunkNodesCount)
        {
            var dfs = new List <DiscreteFunction2D[]>();

            var(a, b) = problem.Segment;
            var h        = (b - a) / chunksCount;
            var initVals = new double[problem.InitialValues.Length];

            Array.Copy(problem.InitialValues, initVals, initVals.Length);
            for (int j = 0; j < chunksCount; j++)
            {
                var chunk          = new Segment(a + j * h, a + (j + 1) * h);
                var chunkNodes     = chunk.GetUniformPartition(chunkNodesCount);
                var problemOnChunk = new CauchyProblem(problem.RightSides, initVals, chunk);
                var dfsOnChunk     = Solve(problemOnChunk, partialSumOrder, iterCount, chunkNodes);
                dfs.Add(dfsOnChunk);
                initVals = dfsOnChunk.Select(df => df.Y.Last()).ToArray();
            }
            return(dfs);
        }