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