DormandPrince54Integrator.java

  1. /*
  2.  * Licensed to the Hipparchus project under one or more
  3.  * contributor license agreements.  See the NOTICE file distributed with
  4.  * this work for additional information regarding copyright ownership.
  5.  * The Hipparchus project licenses this file to You under the Apache License, Version 2.0
  6.  * (the "License"); you may not use this file except in compliance with
  7.  * the License.  You may obtain a copy of the License at
  8.  *
  9.  *      https://www.apache.org/licenses/LICENSE-2.0
  10.  *
  11.  * Unless required by applicable law or agreed to in writing, software
  12.  * distributed under the License is distributed on an "AS IS" BASIS,
  13.  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14.  * See the License for the specific language governing permissions and
  15.  * limitations under the License.
  16.  */

  17. package org.hipparchus.ode.nonstiff;

  18. import org.hipparchus.ode.EquationsMapper;
  19. import org.hipparchus.ode.ODEStateAndDerivative;
  20. import org.hipparchus.ode.nonstiff.interpolators.DormandPrince54StateInterpolator;
  21. import org.hipparchus.util.FastMath;


  22. /**
  23.  * This class implements the 5(4) Dormand-Prince integrator for Ordinary
  24.  * Differential Equations.

  25.  * <p>This integrator is an embedded Runge-Kutta integrator
  26.  * of order 5(4) used in local extrapolation mode (i.e. the solution
  27.  * is computed using the high order formula) with stepsize control
  28.  * (and automatic step initialization) and continuous output. This
  29.  * method uses 7 functions evaluations per step. However, since this
  30.  * is an <i>fsal</i>, the last evaluation of one step is the same as
  31.  * the first evaluation of the next step and hence can be avoided. So
  32.  * the cost is really 6 functions evaluations per step.</p>
  33.  *
  34.  * <p>This method has been published (whithout the continuous output
  35.  * that was added by Shampine in 1986) in the following article :</p>
  36.  * <pre>
  37.  *  A family of embedded Runge-Kutta formulae
  38.  *  J. R. Dormand and P. J. Prince
  39.  *  Journal of Computational and Applied Mathematics
  40.  *  volume 6, no 1, 1980, pp. 19-26
  41.  * </pre>
  42.  *
  43.  */

  44. public class DormandPrince54Integrator extends EmbeddedRungeKuttaIntegrator {

  45.     /** Name of integration scheme. */
  46.     public static final String METHOD_NAME = "Dormand-Prince 5 (4)";

  47.     /** Error array, element 1. */
  48.     static final double E1 =     71.0 / 57600.0;

  49.     // element 2 is zero, so it is neither stored nor used

  50.     /** Error array, element 3. */
  51.     static final double E3 =    -71.0 / 16695.0;

  52.     /** Error array, element 4. */
  53.     static final double E4 =     71.0 / 1920.0;

  54.     /** Error array, element 5. */
  55.     static final double E5 = -17253.0 / 339200.0;

  56.     /** Error array, element 6. */
  57.     static final double E6 =     22.0 / 525.0;

  58.     /** Error array, element 7. */
  59.     static final double E7 =     -1.0 / 40.0;

  60.     /** Simple constructor.
  61.      * Build a fifth order Dormand-Prince integrator with the given step bounds
  62.      * @param minStep minimal step (sign is irrelevant, regardless of
  63.      * integration direction, forward or backward), the last step can
  64.      * be smaller than this
  65.      * @param maxStep maximal step (sign is irrelevant, regardless of
  66.      * integration direction, forward or backward), the last step can
  67.      * be smaller than this
  68.      * @param scalAbsoluteTolerance allowed absolute error
  69.      * @param scalRelativeTolerance allowed relative error
  70.      */
  71.     public DormandPrince54Integrator(final double minStep, final double maxStep,
  72.                                      final double scalAbsoluteTolerance,
  73.                                      final double scalRelativeTolerance) {
  74.         super(METHOD_NAME, 6,
  75.               minStep, maxStep, scalAbsoluteTolerance, scalRelativeTolerance);
  76.     }

  77.     /** Simple constructor.
  78.      * Build a fifth order Dormand-Prince integrator with the given step bounds
  79.      * @param minStep minimal step (sign is irrelevant, regardless of
  80.      * integration direction, forward or backward), the last step can
  81.      * be smaller than this
  82.      * @param maxStep maximal step (sign is irrelevant, regardless of
  83.      * integration direction, forward or backward), the last step can
  84.      * be smaller than this
  85.      * @param vecAbsoluteTolerance allowed absolute error
  86.      * @param vecRelativeTolerance allowed relative error
  87.      */
  88.     public DormandPrince54Integrator(final double minStep, final double maxStep,
  89.                                      final double[] vecAbsoluteTolerance,
  90.                                      final double[] vecRelativeTolerance) {
  91.         super(METHOD_NAME, 6,
  92.               minStep, maxStep, vecAbsoluteTolerance, vecRelativeTolerance);
  93.     }

  94.     /** {@inheritDoc} */
  95.     @Override
  96.     public double[] getC() {
  97.         return new double[] {
  98.             1.0 / 5.0, 3.0 / 10.0, 4.0 / 5.0, 8.0 / 9.0, 1.0, 1.0
  99.         };
  100.     }

  101.     /** {@inheritDoc} */
  102.     @Override
  103.     public double[][] getA() {
  104.         return new double[][] {
  105.             { 1.0 / 5.0 },
  106.             { 3.0 / 40.0, 9.0 / 40.0 },
  107.             { 44.0 / 45.0, -56.0 / 15.0, 32.0 / 9.0 },
  108.             { 19372.0 / 6561.0, -25360.0 / 2187.0, 64448.0 / 6561.0,  -212.0 / 729.0 },
  109.             { 9017.0 / 3168.0, -355.0 / 33.0, 46732.0 / 5247.0, 49.0 / 176.0, -5103.0 / 18656.0 },
  110.             { 35.0 / 384.0, 0.0, 500.0 / 1113.0, 125.0 / 192.0, -2187.0 / 6784.0, 11.0 / 84.0 }
  111.         };
  112.     }

  113.     /** {@inheritDoc} */
  114.     @Override
  115.     public double[] getB() {
  116.         return new double[] {
  117.             35.0 / 384.0, 0.0, 500.0 / 1113.0, 125.0 / 192.0, -2187.0 / 6784.0, 11.0 / 84.0, 0.0
  118.         };
  119.     }

  120.     /** {@inheritDoc} */
  121.     @Override
  122.     protected DormandPrince54StateInterpolator
  123.     createInterpolator(final boolean forward, double[][] yDotK,
  124.                        final ODEStateAndDerivative globalPreviousState,
  125.                        final ODEStateAndDerivative globalCurrentState,
  126.                        final EquationsMapper mapper) {
  127.         return new DormandPrince54StateInterpolator(forward, yDotK,
  128.                                                    globalPreviousState, globalCurrentState,
  129.                                                    globalPreviousState, globalCurrentState,
  130.                                                    mapper);
  131.     }

  132.     /** {@inheritDoc} */
  133.     @Override
  134.     public int getOrder() {
  135.         return 5;
  136.     }

  137.     /** {@inheritDoc} */
  138.     @Override
  139.     protected double estimateError(final double[][] yDotK,
  140.                                    final double[] y0, final double[] y1,
  141.                                    final double h) {

  142.         final StepsizeHelper helper = getStepSizeHelper();
  143.         double error = 0;

  144.         for (int j = 0; j < helper.getMainSetDimension(); ++j) {
  145.             final double errSum = E1 * yDotK[0][j] +  E3 * yDotK[2][j] +
  146.                                   E4 * yDotK[3][j] +  E5 * yDotK[4][j] +
  147.                                   E6 * yDotK[5][j] +  E7 * yDotK[6][j];

  148.             final double tol = helper.getTolerance(j, FastMath.max(FastMath.abs(y0[j]), FastMath.abs(y1[j])));
  149.             final double ratio  = h * errSum / tol;
  150.             error += ratio * ratio;

  151.         }

  152.         return FastMath.sqrt(error / helper.getMainSetDimension());

  153.     }

  154. }