DormandPrince853StepInterpolator.java

  1. /*
  2.  * Licensed to the Apache Software Foundation (ASF) 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 ASF 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.  *      http://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.apache.commons.math4.legacy.ode.nonstiff;

  18. import java.io.IOException;
  19. import java.io.ObjectInput;
  20. import java.io.ObjectOutput;

  21. import org.apache.commons.math4.legacy.exception.MaxCountExceededException;
  22. import org.apache.commons.math4.legacy.ode.AbstractIntegrator;
  23. import org.apache.commons.math4.legacy.ode.EquationsMapper;
  24. import org.apache.commons.math4.legacy.ode.sampling.StepInterpolator;

  25. /**
  26.  * This class represents an interpolator over the last step during an
  27.  * ODE integration for the 8(5,3) Dormand-Prince integrator.
  28.  *
  29.  * @see DormandPrince853Integrator
  30.  *
  31.  * @since 1.2
  32.  */

  33. class DormandPrince853StepInterpolator
  34.   extends RungeKuttaStepInterpolator {

  35.     /** Serializable version identifier. */
  36.     private static final long serialVersionUID = 20111120L;

  37.     /** Propagation weights, element 1. */
  38.     private static final double B_01 =         104257.0 / 1920240.0;

  39.     // elements 2 to 5 are zero, so they are neither stored nor used

  40.     /** Propagation weights, element 6. */
  41.     private static final double B_06 =        3399327.0 / 763840.0;

  42.     /** Propagation weights, element 7. */
  43.     private static final double B_07 =       66578432.0 / 35198415.0;

  44.     /** Propagation weights, element 8. */
  45.     private static final double B_08 =    -1674902723.0 / 288716400.0;

  46.     /** Propagation weights, element 9. */
  47.     private static final double B_09 = 54980371265625.0 / 176692375811392.0;

  48.     /** Propagation weights, element 10. */
  49.     private static final double B_10 =        -734375.0 / 4826304.0;

  50.     /** Propagation weights, element 11. */
  51.     private static final double B_11 =      171414593.0 / 851261400.0;

  52.     /** Propagation weights, element 12. */
  53.     private static final double B_12 =         137909.0 / 3084480.0;

  54.     /** Time step for stage 14 (interpolation only). */
  55.     private static final double C14    = 1.0 / 10.0;

  56.     /** Internal weights for stage 14, element 1. */
  57.     private static final double K14_01 =       13481885573.0 / 240030000000.0      - B_01;

  58.     // elements 2 to 5 are zero, so they are neither stored nor used

  59.     /** Internal weights for stage 14, element 6. */
  60.     private static final double K14_06 =                 0.0                       - B_06;

  61.     /** Internal weights for stage 14, element 7. */
  62.     private static final double K14_07 =      139418837528.0 / 549975234375.0      - B_07;

  63.     /** Internal weights for stage 14, element 8. */
  64.     private static final double K14_08 =   -11108320068443.0 / 45111937500000.0    - B_08;

  65.     /** Internal weights for stage 14, element 9. */
  66.     private static final double K14_09 = -1769651421925959.0 / 14249385146080000.0 - B_09;

  67.     /** Internal weights for stage 14, element 10. */
  68.     private static final double K14_10 =          57799439.0 / 377055000.0         - B_10;

  69.     /** Internal weights for stage 14, element 11. */
  70.     private static final double K14_11 =      793322643029.0 / 96734250000000.0    - B_11;

  71.     /** Internal weights for stage 14, element 12. */
  72.     private static final double K14_12 =        1458939311.0 / 192780000000.0      - B_12;

  73.     /** Internal weights for stage 14, element 13. */
  74.     private static final double K14_13 =             -4149.0 / 500000.0;

  75.     /** Time step for stage 15 (interpolation only). */
  76.     private static final double C15    = 1.0 / 5.0;


  77.     /** Internal weights for stage 15, element 1. */
  78.     private static final double K15_01 =     1595561272731.0 / 50120273500000.0    - B_01;

  79.     // elements 2 to 5 are zero, so they are neither stored nor used

  80.     /** Internal weights for stage 15, element 6. */
  81.     private static final double K15_06 =      975183916491.0 / 34457688031250.0    - B_06;

  82.     /** Internal weights for stage 15, element 7. */
  83.     private static final double K15_07 =    38492013932672.0 / 718912673015625.0   - B_07;

  84.     /** Internal weights for stage 15, element 8. */
  85.     private static final double K15_08 = -1114881286517557.0 / 20298710767500000.0 - B_08;

  86.     /** Internal weights for stage 15, element 9. */
  87.     private static final double K15_09 =                 0.0                       - B_09;

  88.     /** Internal weights for stage 15, element 10. */
  89.     private static final double K15_10 =                 0.0                       - B_10;

  90.     /** Internal weights for stage 15, element 11. */
  91.     private static final double K15_11 =    -2538710946863.0 / 23431227861250000.0 - B_11;

  92.     /** Internal weights for stage 15, element 12. */
  93.     private static final double K15_12 =        8824659001.0 / 23066716781250.0    - B_12;

  94.     /** Internal weights for stage 15, element 13. */
  95.     private static final double K15_13 =      -11518334563.0 / 33831184612500.0;

  96.     /** Internal weights for stage 15, element 14. */
  97.     private static final double K15_14 =        1912306948.0 / 13532473845.0;

  98.     /** Time step for stage 16 (interpolation only). */
  99.     private static final double C16    = 7.0 / 9.0;


  100.     /** Internal weights for stage 16, element 1. */
  101.     private static final double K16_01 =      -13613986967.0 / 31741908048.0       - B_01;

  102.     // elements 2 to 5 are zero, so they are neither stored nor used

  103.     /** Internal weights for stage 16, element 6. */
  104.     private static final double K16_06 =       -4755612631.0 / 1012344804.0        - B_06;

  105.     /** Internal weights for stage 16, element 7. */
  106.     private static final double K16_07 =    42939257944576.0 / 5588559685701.0     - B_07;

  107.     /** Internal weights for stage 16, element 8. */
  108.     private static final double K16_08 =    77881972900277.0 / 19140370552944.0    - B_08;

  109.     /** Internal weights for stage 16, element 9. */
  110.     private static final double K16_09 =    22719829234375.0 / 63689648654052.0    - B_09;

  111.     /** Internal weights for stage 16, element 10. */
  112.     private static final double K16_10 =                 0.0                       - B_10;

  113.     /** Internal weights for stage 16, element 11. */
  114.     private static final double K16_11 =                 0.0                       - B_11;

  115.     /** Internal weights for stage 16, element 12. */
  116.     private static final double K16_12 =                 0.0                       - B_12;

  117.     /** Internal weights for stage 16, element 13. */
  118.     private static final double K16_13 =       -1199007803.0 / 857031517296.0;

  119.     /** Internal weights for stage 16, element 14. */
  120.     private static final double K16_14 =      157882067000.0 / 53564469831.0;

  121.     /** Internal weights for stage 16, element 15. */
  122.     private static final double K16_15 =     -290468882375.0 / 31741908048.0;

  123.     /** Interpolation weights.
  124.      * (beware that only the non-null values are in the table)
  125.      */
  126.     private static final double[][] D = {

  127.       {        -17751989329.0 / 2106076560.0,               4272954039.0 / 7539864640.0,
  128.               -118476319744.0 / 38604839385.0,            755123450731.0 / 316657731600.0,
  129.         3692384461234828125.0 / 1744130441634250432.0,     -4612609375.0 / 5293382976.0,
  130.               2091772278379.0 / 933644586600.0,             2136624137.0 / 3382989120.0,
  131.                     -126493.0 / 1421424.0,                    98350000.0 / 5419179.0,
  132.                   -18878125.0 / 2053168.0,                 -1944542619.0 / 438351368.0},

  133.       {         32941697297.0 / 3159114840.0,             456696183123.0 / 1884966160.0,
  134.              19132610714624.0 / 115814518155.0,       -177904688592943.0 / 474986597400.0,
  135.        -4821139941836765625.0 / 218016305204281304.0,      30702015625.0 / 3970037232.0,
  136.             -85916079474274.0 / 2800933759800.0,           -5919468007.0 / 634310460.0,
  137.                     2479159.0 / 157936.0,                    -18750000.0 / 602131.0,
  138.                   -19203125.0 / 2053168.0,                 15700361463.0 / 438351368.0},

  139.       {         12627015655.0 / 631822968.0,              -72955222965.0 / 188496616.0,
  140.             -13145744952320.0 / 69488710893.0,          30084216194513.0 / 56998391688.0,
  141.         -296858761006640625.0 / 25648977082856624.0,         569140625.0 / 82709109.0,
  142.                -18684190637.0 / 18672891732.0,                69644045.0 / 89549712.0,
  143.                   -11847025.0 / 4264272.0,                  -978650000.0 / 16257537.0,
  144.                   519371875.0 / 6159504.0,                  5256837225.0 / 438351368.0},

  145.       {          -450944925.0 / 17550638.0,               -14532122925.0 / 94248308.0,
  146.               -595876966400.0 / 2573655959.0,             188748653015.0 / 527762886.0,
  147.         2545485458115234375.0 / 27252038150535163.0,       -1376953125.0 / 36759604.0,
  148.                 53995596795.0 / 518691437.0,                 210311225.0 / 7047894.0,
  149.                    -1718875.0 / 39484.0,                      58000000.0 / 602131.0,
  150.                    -1546875.0 / 39484.0,                   -1262172375.0 / 8429834.0}
  151.     };

  152.     /** Last evaluations. */
  153.     private double[][] yDotKLast;

  154.     /** Vectors for interpolation. */
  155.     private double[][] v;

  156.     /** Initialization indicator for the interpolation vectors. */
  157.     private boolean vectorsInitialized;

  158.   /** Simple constructor.
  159.    * This constructor builds an instance that is not usable yet, the
  160.    * {@link #reinitialize} method should be called before using the
  161.    * instance in order to initialize the internal arrays. This
  162.    * constructor is used only in order to delay the initialization in
  163.    * some cases. The {@link EmbeddedRungeKuttaIntegrator} uses the
  164.    * prototyping design pattern to create the step interpolators by
  165.    * cloning an uninitialized model and latter initializing the copy.
  166.    */
  167.   // CHECKSTYLE: stop RedundantModifier
  168.   // the public modifier here is needed for serialization
  169.   public DormandPrince853StepInterpolator() {
  170.     super();
  171.     yDotKLast = null;
  172.     v         = null;
  173.     vectorsInitialized = false;
  174.   }
  175.   // CHECKSTYLE: resume RedundantModifier

  176.   /** Copy constructor.
  177.    * @param interpolator interpolator to copy from. The copy is a deep
  178.    * copy: its arrays are separated from the original arrays of the
  179.    * instance
  180.    */
  181.   DormandPrince853StepInterpolator(final DormandPrince853StepInterpolator interpolator) {

  182.     super(interpolator);

  183.     if (interpolator.currentState == null) {

  184.       yDotKLast = null;
  185.       v         = null;
  186.       vectorsInitialized = false;
  187.     } else {

  188.       final int dimension = interpolator.currentState.length;

  189.       yDotKLast    = new double[3][];
  190.       for (int k = 0; k < yDotKLast.length; ++k) {
  191.         yDotKLast[k] = new double[dimension];
  192.         System.arraycopy(interpolator.yDotKLast[k], 0, yDotKLast[k], 0,
  193.                          dimension);
  194.       }

  195.       v = new double[7][];
  196.       for (int k = 0; k < v.length; ++k) {
  197.         v[k] = new double[dimension];
  198.         System.arraycopy(interpolator.v[k], 0, v[k], 0, dimension);
  199.       }

  200.       vectorsInitialized = interpolator.vectorsInitialized;
  201.     }
  202.   }

  203.   /** {@inheritDoc} */
  204.   @Override
  205.   protected StepInterpolator doCopy() {
  206.     return new DormandPrince853StepInterpolator(this);
  207.   }

  208.   /** {@inheritDoc} */
  209.   @Override
  210.   public void reinitialize(final AbstractIntegrator integrator,
  211.                            final double[] y, final double[][] yDotK, final boolean forward,
  212.                            final EquationsMapper primaryMapper,
  213.                            final EquationsMapper[] secondaryMappers) {

  214.     super.reinitialize(integrator, y, yDotK, forward, primaryMapper, secondaryMappers);

  215.     final int dimension = currentState.length;

  216.     yDotKLast = new double[3][];
  217.     for (int k = 0; k < yDotKLast.length; ++k) {
  218.       yDotKLast[k] = new double[dimension];
  219.     }

  220.     v = new double[7][];
  221.     for (int k = 0; k < v.length; ++k) {
  222.       v[k]  = new double[dimension];
  223.     }

  224.     vectorsInitialized = false;
  225.   }

  226.   /** {@inheritDoc} */
  227.   @Override
  228.   public void storeTime(final double t) {
  229.     super.storeTime(t);
  230.     vectorsInitialized = false;
  231.   }

  232.   /** {@inheritDoc} */
  233.   @Override
  234.   protected void computeInterpolatedStateAndDerivatives(final double theta,
  235.                                           final double oneMinusThetaH)
  236.       throws MaxCountExceededException {

  237.     if (! vectorsInitialized) {

  238.       if (v == null) {
  239.         v = new double[7][];
  240.         for (int k = 0; k < 7; ++k) {
  241.           v[k] = new double[interpolatedState.length];
  242.         }
  243.       }

  244.       // perform the last evaluations if they have not been done yet
  245.       finalizeStep();

  246.       // compute the interpolation vectors for this time step
  247.       for (int i = 0; i < interpolatedState.length; ++i) {
  248.           final double yDot1  = yDotK[0][i];
  249.           final double yDot6  = yDotK[5][i];
  250.           final double yDot7  = yDotK[6][i];
  251.           final double yDot8  = yDotK[7][i];
  252.           final double yDot9  = yDotK[8][i];
  253.           final double yDot10 = yDotK[9][i];
  254.           final double yDot11 = yDotK[10][i];
  255.           final double yDot12 = yDotK[11][i];
  256.           final double yDot13 = yDotK[12][i];
  257.           final double yDot14 = yDotKLast[0][i];
  258.           final double yDot15 = yDotKLast[1][i];
  259.           final double yDot16 = yDotKLast[2][i];
  260.           v[0][i] = B_01 * yDot1  + B_06 * yDot6 + B_07 * yDot7 +
  261.                     B_08 * yDot8  + B_09 * yDot9 + B_10 * yDot10 +
  262.                     B_11 * yDot11 + B_12 * yDot12;
  263.           v[1][i] = yDot1 - v[0][i];
  264.           v[2][i] = v[0][i] - v[1][i] - yDotK[12][i];
  265.           for (int k = 0; k < D.length; ++k) {
  266.               v[k+3][i] = D[k][0] * yDot1  + D[k][1]  * yDot6  + D[k][2]  * yDot7  +
  267.                           D[k][3] * yDot8  + D[k][4]  * yDot9  + D[k][5]  * yDot10 +
  268.                           D[k][6] * yDot11 + D[k][7]  * yDot12 + D[k][8]  * yDot13 +
  269.                           D[k][9] * yDot14 + D[k][10] * yDot15 + D[k][11] * yDot16;
  270.           }
  271.       }

  272.       vectorsInitialized = true;
  273.     }

  274.     final double eta      = 1 - theta;
  275.     final double twoTheta = 2 * theta;
  276.     final double theta2   = theta * theta;
  277.     final double dot1 = 1 - twoTheta;
  278.     final double dot2 = theta * (2 - 3 * theta);
  279.     final double dot3 = twoTheta * (1 + theta * (twoTheta -3));
  280.     final double dot4 = theta2 * (3 + theta * (5 * theta - 8));
  281.     final double dot5 = theta2 * (3 + theta * (-12 + theta * (15 - 6 * theta)));
  282.     final double dot6 = theta2 * theta * (4 + theta * (-15 + theta * (18 - 7 * theta)));

  283.     if (previousState != null && theta <= 0.5) {
  284.         for (int i = 0; i < interpolatedState.length; ++i) {
  285.             interpolatedState[i] = previousState[i] +
  286.                     theta * h * (v[0][i] +
  287.                             eta * (v[1][i] +
  288.                                     theta * (v[2][i] +
  289.                                             eta * (v[3][i] +
  290.                                                     theta * (v[4][i] +
  291.                                                             eta * (v[5][i] +
  292.                                                                     theta * (v[6][i])))))));
  293.             interpolatedDerivatives[i] =  v[0][i] + dot1 * v[1][i] + dot2 * v[2][i] +
  294.                     dot3 * v[3][i] + dot4 * v[4][i] +
  295.                     dot5 * v[5][i] + dot6 * v[6][i];
  296.         }
  297.     } else {
  298.         for (int i = 0; i < interpolatedState.length; ++i) {
  299.             interpolatedState[i] = currentState[i] -
  300.                     oneMinusThetaH * (v[0][i] -
  301.                             theta * (v[1][i] +
  302.                                     theta * (v[2][i] +
  303.                                             eta * (v[3][i] +
  304.                                                     theta * (v[4][i] +
  305.                                                             eta * (v[5][i] +
  306.                                                                     theta * (v[6][i])))))));
  307.             interpolatedDerivatives[i] =  v[0][i] + dot1 * v[1][i] + dot2 * v[2][i] +
  308.                     dot3 * v[3][i] + dot4 * v[4][i] +
  309.                     dot5 * v[5][i] + dot6 * v[6][i];
  310.         }
  311.     }
  312.   }

  313.   /** {@inheritDoc} */
  314.   @Override
  315.   protected void doFinalize() throws MaxCountExceededException {

  316.       if (currentState == null) {
  317.           // we are finalizing an uninitialized instance
  318.           return;
  319.       }

  320.       double s;
  321.       final double[] yTmp = new double[currentState.length];
  322.       final double pT = getGlobalPreviousTime();

  323.       // k14
  324.       for (int j = 0; j < currentState.length; ++j) {
  325.           s = K14_01 * yDotK[0][j]  + K14_06 * yDotK[5][j]  + K14_07 * yDotK[6][j] +
  326.                   K14_08 * yDotK[7][j]  + K14_09 * yDotK[8][j]  + K14_10 * yDotK[9][j] +
  327.                   K14_11 * yDotK[10][j] + K14_12 * yDotK[11][j] + K14_13 * yDotK[12][j];
  328.           yTmp[j] = currentState[j] + h * s;
  329.       }
  330.       integrator.computeDerivatives(pT + C14 * h, yTmp, yDotKLast[0]);

  331.       // k15
  332.       for (int j = 0; j < currentState.length; ++j) {
  333.           s = K15_01 * yDotK[0][j]  + K15_06 * yDotK[5][j]  + K15_07 * yDotK[6][j] +
  334.                   K15_08 * yDotK[7][j]  + K15_09 * yDotK[8][j]  + K15_10 * yDotK[9][j] +
  335.                   K15_11 * yDotK[10][j] + K15_12 * yDotK[11][j] + K15_13 * yDotK[12][j] +
  336.                   K15_14 * yDotKLast[0][j];
  337.           yTmp[j] = currentState[j] + h * s;
  338.       }
  339.       integrator.computeDerivatives(pT + C15 * h, yTmp, yDotKLast[1]);

  340.       // k16
  341.       for (int j = 0; j < currentState.length; ++j) {
  342.           s = K16_01 * yDotK[0][j]  + K16_06 * yDotK[5][j]  + K16_07 * yDotK[6][j] +
  343.                   K16_08 * yDotK[7][j]  + K16_09 * yDotK[8][j]  + K16_10 * yDotK[9][j] +
  344.                   K16_11 * yDotK[10][j] + K16_12 * yDotK[11][j] + K16_13 * yDotK[12][j] +
  345.                   K16_14 * yDotKLast[0][j] +  K16_15 * yDotKLast[1][j];
  346.           yTmp[j] = currentState[j] + h * s;
  347.       }
  348.       integrator.computeDerivatives(pT + C16 * h, yTmp, yDotKLast[2]);
  349.   }

  350.   /** {@inheritDoc} */
  351.   @Override
  352.   public void writeExternal(final ObjectOutput out)
  353.     throws IOException {

  354.     try {
  355.         // save the local attributes
  356.         finalizeStep();
  357.     } catch (MaxCountExceededException mcee) {
  358.         final IOException ioe = new IOException(mcee.getLocalizedMessage());
  359.         ioe.initCause(mcee);
  360.         throw ioe;
  361.     }

  362.     final int dimension = (currentState == null) ? -1 : currentState.length;
  363.     out.writeInt(dimension);
  364.     for (int i = 0; i < dimension; ++i) {
  365.       out.writeDouble(yDotKLast[0][i]);
  366.       out.writeDouble(yDotKLast[1][i]);
  367.       out.writeDouble(yDotKLast[2][i]);
  368.     }

  369.     // save the state of the base class
  370.     super.writeExternal(out);
  371.   }

  372.   /** {@inheritDoc} */
  373.   @Override
  374.   public void readExternal(final ObjectInput in)
  375.     throws IOException, ClassNotFoundException {

  376.     // read the local attributes
  377.     yDotKLast = new double[3][];
  378.     final int dimension = in.readInt();
  379.     yDotKLast[0] = (dimension < 0) ? null : new double[dimension];
  380.     yDotKLast[1] = (dimension < 0) ? null : new double[dimension];
  381.     yDotKLast[2] = (dimension < 0) ? null : new double[dimension];

  382.     for (int i = 0; i < dimension; ++i) {
  383.       yDotKLast[0][i] = in.readDouble();
  384.       yDotKLast[1][i] = in.readDouble();
  385.       yDotKLast[2][i] = in.readDouble();
  386.     }

  387.     // read the base state
  388.     super.readExternal(in);
  389.   }
  390. }