AdamsStateInterpolator.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.interpolators;

  18. import org.hipparchus.linear.Array2DRowRealMatrix;
  19. import org.hipparchus.ode.EquationsMapper;
  20. import org.hipparchus.ode.ODEStateAndDerivative;
  21. import org.hipparchus.ode.sampling.AbstractODEStateInterpolator;
  22. import org.hipparchus.util.FastMath;

  23. /**
  24.  * This class implements an interpolator for integrators using Nordsieck representation.
  25.  *
  26.  * <p>This interpolator computes dense output around the current point.
  27.  * The interpolation equation is based on Taylor series formulas.
  28.  *
  29.  * @see org.hipparchus.ode.nonstiff.AdamsBashforthIntegrator
  30.  * @see org.hipparchus.ode.nonstiff.AdamsMoultonIntegrator
  31.  */

  32. public class AdamsStateInterpolator extends AbstractODEStateInterpolator {

  33.     /** Serializable version identifier */
  34.     private static final long serialVersionUID = 20160402L;

  35.     /** Step size used in the first scaled derivative and Nordsieck vector. */
  36.     private double scalingH;

  37.     /** Reference state.
  38.      * <p>Sometimes, the reference state is the same as globalPreviousState,
  39.      * sometimes it is the same as globalCurrentState, so we use a separate
  40.      * field to avoid any confusion.
  41.      * </p>
  42.      */
  43.     private final ODEStateAndDerivative reference;

  44.     /** First scaled derivative. */
  45.     private double[] scaled;

  46.     /** Nordsieck vector. */
  47.     private Array2DRowRealMatrix nordsieck;

  48.     /** Simple constructor.
  49.      * @param stepSize step size used in the scaled and Nordsieck arrays
  50.      * @param reference reference state from which Taylor expansion are estimated
  51.      * @param scaled first scaled derivative
  52.      * @param nordsieck Nordsieck vector
  53.      * @param isForward integration direction indicator
  54.      * @param globalPreviousState start of the global step
  55.      * @param globalCurrentState end of the global step
  56.      * @param equationsMapper mapper for ODE equations primary and secondary components
  57.      */
  58.     public AdamsStateInterpolator(final double stepSize, final ODEStateAndDerivative reference,
  59.                                   final double[] scaled, final Array2DRowRealMatrix nordsieck,
  60.                                   final boolean isForward,
  61.                                   final ODEStateAndDerivative globalPreviousState,
  62.                                   final ODEStateAndDerivative globalCurrentState,
  63.                                   final EquationsMapper equationsMapper) {
  64.         this(stepSize, reference, scaled, nordsieck,
  65.              isForward, globalPreviousState, globalCurrentState,
  66.              globalPreviousState, globalCurrentState, equationsMapper);
  67.     }

  68.     /** Simple constructor.
  69.      * @param stepSize step size used in the scaled and Nordsieck arrays
  70.      * @param reference reference state from which Taylor expansion are estimated
  71.      * @param scaled first scaled derivative
  72.      * @param nordsieck Nordsieck vector
  73.      * @param isForward integration direction indicator
  74.      * @param globalPreviousState start of the global step
  75.      * @param globalCurrentState end of the global step
  76.      * @param softPreviousState start of the restricted step
  77.      * @param softCurrentState end of the restricted step
  78.      * @param equationsMapper mapper for ODE equations primary and secondary components
  79.      */
  80.     private AdamsStateInterpolator(final double stepSize, final ODEStateAndDerivative reference,
  81.                                    final double[] scaled, final Array2DRowRealMatrix nordsieck,
  82.                                    final boolean isForward,
  83.                                    final ODEStateAndDerivative globalPreviousState,
  84.                                    final ODEStateAndDerivative globalCurrentState,
  85.                                    final ODEStateAndDerivative softPreviousState,
  86.                                    final ODEStateAndDerivative softCurrentState,
  87.                                    final EquationsMapper equationsMapper) {
  88.         super(isForward, globalPreviousState, globalCurrentState,
  89.               softPreviousState, softCurrentState, equationsMapper);
  90.         this.scalingH  = stepSize;
  91.         this.reference = reference;
  92.         this.scaled    = scaled.clone();
  93.         this.nordsieck = new Array2DRowRealMatrix(nordsieck.getData(), false);
  94.     }

  95.     /** Create a new instance.
  96.      * @param newForward integration direction indicator
  97.      * @param newGlobalPreviousState start of the global step
  98.      * @param newGlobalCurrentState end of the global step
  99.      * @param newSoftPreviousState start of the restricted step
  100.      * @param newSoftCurrentState end of the restricted step
  101.      * @param newMapper equations mapper for the all equations
  102.      * @return a new instance
  103.      */
  104.     @Override
  105.     protected AdamsStateInterpolator create(boolean newForward,
  106.                                             ODEStateAndDerivative newGlobalPreviousState,
  107.                                             ODEStateAndDerivative newGlobalCurrentState,
  108.                                             ODEStateAndDerivative newSoftPreviousState,
  109.                                             ODEStateAndDerivative newSoftCurrentState,
  110.                                             EquationsMapper newMapper) {
  111.         return new AdamsStateInterpolator(scalingH, reference, scaled, nordsieck,
  112.                                           newForward,
  113.                                           newGlobalPreviousState, newGlobalCurrentState,
  114.                                           newSoftPreviousState, newSoftCurrentState,
  115.                                           newMapper);

  116.     }

  117.     /** Get the first scaled derivative.
  118.      * @return first scaled derivative
  119.      */
  120.     public double[] getScaled() {
  121.         return scaled.clone();
  122.     }

  123.     /** Get the Nordsieck vector.
  124.      * @return Nordsieck vector
  125.      */
  126.     public Array2DRowRealMatrix getNordsieck() {
  127.         return new Array2DRowRealMatrix(nordsieck.getData());
  128.     }

  129.     /** {@inheritDoc} */
  130.     @Override
  131.     protected ODEStateAndDerivative computeInterpolatedStateAndDerivatives(final EquationsMapper equationsMapper,
  132.                                                                            final double time, final double theta,
  133.                                                                            final double thetaH, final double oneMinusThetaH) {
  134.         return taylor(equationsMapper, reference, time, scalingH, scaled, nordsieck);
  135.     }

  136.     /** Estimate state by applying Taylor formula.
  137.      * @param equationsMapper mapper for ODE equations primary and secondary components
  138.      * @param reference reference state
  139.      * @param time time at which state must be estimated
  140.      * @param stepSize step size used in the scaled and Nordsieck arrays
  141.      * @param scaled first scaled derivative
  142.      * @param nordsieck Nordsieck vector
  143.      * @return estimated state
  144.      */
  145.     public static ODEStateAndDerivative taylor(final EquationsMapper equationsMapper,
  146.                                                final ODEStateAndDerivative reference,
  147.                                                final double time, final double stepSize,
  148.                                                final double[] scaled,
  149.                                                final Array2DRowRealMatrix nordsieck) {

  150.         final double x = time - reference.getTime();
  151.         final double normalizedAbscissa = x / stepSize;

  152.         double[] stateVariation       = new double[scaled.length];
  153.         double[] estimatedDerivatives = new double[scaled.length];

  154.         // apply Taylor formula from high order to low order,
  155.         // for the sake of numerical accuracy
  156.         final double[][] nData = nordsieck.getDataRef();
  157.         for (int i = nData.length - 1; i >= 0; --i) {
  158.             final int order = i + 2;
  159.             final double[] nDataI = nData[i];
  160.             final double power = FastMath.pow(normalizedAbscissa, order);
  161.             for (int j = 0; j < nDataI.length; ++j) {
  162.                 final double d = nDataI[j] * power;
  163.                 stateVariation[j]          = stateVariation[j] + d;
  164.                 estimatedDerivatives[j] = estimatedDerivatives[j] + d * order;
  165.             }
  166.         }

  167.         double[] estimatedState = reference.getCompleteState();
  168.         for (int j = 0; j < stateVariation.length; ++j) {
  169.             stateVariation[j]       = stateVariation[j] + scaled[j] * normalizedAbscissa;
  170.             estimatedState[j]       = estimatedState[j] + stateVariation[j];
  171.             estimatedDerivatives[j] = (estimatedDerivatives[j] + scaled[j] * normalizedAbscissa) / x;
  172.         }

  173.         return equationsMapper.mapStateAndDerivative(time, estimatedState, estimatedDerivatives);

  174.     }

  175. }