DormandPrince54StepInterpolator.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 org.apache.commons.math4.legacy.ode.AbstractIntegrator;
  19. import org.apache.commons.math4.legacy.ode.EquationsMapper;
  20. import org.apache.commons.math4.legacy.ode.sampling.StepInterpolator;

  21. /**
  22.  * This class represents an interpolator over the last step during an
  23.  * ODE integration for the 5(4) Dormand-Prince integrator.
  24.  *
  25.  * @see DormandPrince54Integrator
  26.  *
  27.  * @since 1.2
  28.  */

  29. class DormandPrince54StepInterpolator
  30.   extends RungeKuttaStepInterpolator {

  31.     /** Last row of the Butcher-array internal weights, element 0. */
  32.     private static final double A70 =    35.0 /  384.0;

  33.     // element 1 is zero, so it is neither stored nor used

  34.     /** Last row of the Butcher-array internal weights, element 2. */
  35.     private static final double A72 =   500.0 / 1113.0;

  36.     /** Last row of the Butcher-array internal weights, element 3. */
  37.     private static final double A73 =   125.0 /  192.0;

  38.     /** Last row of the Butcher-array internal weights, element 4. */
  39.     private static final double A74 = -2187.0 / 6784.0;

  40.     /** Last row of the Butcher-array internal weights, element 5. */
  41.     private static final double A75 =    11.0 /   84.0;

  42.     /** Shampine (1986) Dense output, element 0. */
  43.     private static final double D0 =  -12715105075.0 /  11282082432.0;

  44.     // element 1 is zero, so it is neither stored nor used

  45.     /** Shampine (1986) Dense output, element 2. */
  46.     private static final double D2 =   87487479700.0 /  32700410799.0;

  47.     /** Shampine (1986) Dense output, element 3. */
  48.     private static final double D3 =  -10690763975.0 /   1880347072.0;

  49.     /** Shampine (1986) Dense output, element 4. */
  50.     private static final double D4 =  701980252875.0 / 199316789632.0;

  51.     /** Shampine (1986) Dense output, element 5. */
  52.     private static final double D5 =   -1453857185.0 /    822651844.0;

  53.     /** Shampine (1986) Dense output, element 6. */
  54.     private static final double D6 =      69997945.0 /     29380423.0;

  55.     /** Serializable version identifier. */
  56.     private static final long serialVersionUID = 20111120L;

  57.     /** First vector for interpolation. */
  58.     private double[] v1;

  59.     /** Second vector for interpolation. */
  60.     private double[] v2;

  61.     /** Third vector for interpolation. */
  62.     private double[] v3;

  63.     /** Fourth vector for interpolation. */
  64.     private double[] v4;

  65.     /** Initialization indicator for the interpolation vectors. */
  66.     private boolean vectorsInitialized;

  67.   /** Simple constructor.
  68.    * This constructor builds an instance that is not usable yet, the
  69.    * {@link #reinitialize} method should be called before using the
  70.    * instance in order to initialize the internal arrays. This
  71.    * constructor is used only in order to delay the initialization in
  72.    * some cases. The {@link EmbeddedRungeKuttaIntegrator} uses the
  73.    * prototyping design pattern to create the step interpolators by
  74.    * cloning an uninitialized model and latter initializing the copy.
  75.    */
  76.   // CHECKSTYLE: stop RedundantModifier
  77.   // the public modifier here is needed for serialization
  78.   public DormandPrince54StepInterpolator() {
  79.     super();
  80.     v1 = null;
  81.     v2 = null;
  82.     v3 = null;
  83.     v4 = null;
  84.     vectorsInitialized = false;
  85.   }
  86.   // CHECKSTYLE: resume RedundantModifier

  87.   /** Copy constructor.
  88.    * @param interpolator interpolator to copy from. The copy is a deep
  89.    * copy: its arrays are separated from the original arrays of the
  90.    * instance
  91.    */
  92.   DormandPrince54StepInterpolator(final DormandPrince54StepInterpolator interpolator) {

  93.     super(interpolator);

  94.     if (interpolator.v1 == null) {

  95.       v1 = null;
  96.       v2 = null;
  97.       v3 = null;
  98.       v4 = null;
  99.       vectorsInitialized = false;
  100.     } else {

  101.       v1 = interpolator.v1.clone();
  102.       v2 = interpolator.v2.clone();
  103.       v3 = interpolator.v3.clone();
  104.       v4 = interpolator.v4.clone();
  105.       vectorsInitialized = interpolator.vectorsInitialized;
  106.     }
  107.   }

  108.   /** {@inheritDoc} */
  109.   @Override
  110.   protected StepInterpolator doCopy() {
  111.     return new DormandPrince54StepInterpolator(this);
  112.   }


  113.   /** {@inheritDoc} */
  114.   @Override
  115.   public void reinitialize(final AbstractIntegrator integrator,
  116.                            final double[] y, final double[][] yDotK, final boolean forward,
  117.                            final EquationsMapper primaryMapper,
  118.                            final EquationsMapper[] secondaryMappers) {
  119.     super.reinitialize(integrator, y, yDotK, forward, primaryMapper, secondaryMappers);
  120.     v1 = null;
  121.     v2 = null;
  122.     v3 = null;
  123.     v4 = null;
  124.     vectorsInitialized = false;
  125.   }

  126.   /** {@inheritDoc} */
  127.   @Override
  128.   public void storeTime(final double t) {
  129.     super.storeTime(t);
  130.     vectorsInitialized = false;
  131.   }

  132.   /** {@inheritDoc} */
  133.   @Override
  134.   protected void computeInterpolatedStateAndDerivatives(final double theta,
  135.                                           final double oneMinusThetaH) {

  136.     if (! vectorsInitialized) {

  137.       if (v1 == null) {
  138.         v1 = new double[interpolatedState.length];
  139.         v2 = new double[interpolatedState.length];
  140.         v3 = new double[interpolatedState.length];
  141.         v4 = new double[interpolatedState.length];
  142.       }

  143.       // no step finalization is needed for this interpolator

  144.       // we need to compute the interpolation vectors for this time step
  145.       for (int i = 0; i < interpolatedState.length; ++i) {
  146.           final double yDot0 = yDotK[0][i];
  147.           final double yDot2 = yDotK[2][i];
  148.           final double yDot3 = yDotK[3][i];
  149.           final double yDot4 = yDotK[4][i];
  150.           final double yDot5 = yDotK[5][i];
  151.           final double yDot6 = yDotK[6][i];
  152.           v1[i] = A70 * yDot0 + A72 * yDot2 + A73 * yDot3 + A74 * yDot4 + A75 * yDot5;
  153.           v2[i] = yDot0 - v1[i];
  154.           v3[i] = v1[i] - v2[i] - yDot6;
  155.           v4[i] = D0 * yDot0 + D2 * yDot2 + D3 * yDot3 + D4 * yDot4 + D5 * yDot5 + D6 * yDot6;
  156.       }

  157.       vectorsInitialized = true;
  158.     }

  159.     // interpolate
  160.     final double eta = 1 - theta;
  161.     final double twoTheta = 2 * theta;
  162.     final double dot2 = 1 - twoTheta;
  163.     final double dot3 = theta * (2 - 3 * theta);
  164.     final double dot4 = twoTheta * (1 + theta * (twoTheta - 3));
  165.     if (previousState != null && theta <= 0.5) {
  166.         for (int i = 0; i < interpolatedState.length; ++i) {
  167.             interpolatedState[i] =
  168.                     previousState[i] + theta * h * (v1[i] + eta * (v2[i] + theta * (v3[i] + eta * v4[i])));
  169.             interpolatedDerivatives[i] = v1[i] + dot2 * v2[i] + dot3 * v3[i] + dot4 * v4[i];
  170.         }
  171.     } else {
  172.         for (int i = 0; i < interpolatedState.length; ++i) {
  173.             interpolatedState[i] =
  174.                     currentState[i] - oneMinusThetaH * (v1[i] - theta * (v2[i] + theta * (v3[i] + eta * v4[i])));
  175.             interpolatedDerivatives[i] = v1[i] + dot2 * v2[i] + dot3 * v3[i] + dot4 * v4[i];
  176.         }
  177.     }
  178.   }
  179. }