AdamsFieldStepInterpolator.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.util.Arrays;

  19. import org.apache.commons.math4.legacy.core.RealFieldElement;
  20. import org.apache.commons.math4.legacy.linear.Array2DRowFieldMatrix;
  21. import org.apache.commons.math4.legacy.ode.FieldEquationsMapper;
  22. import org.apache.commons.math4.legacy.ode.FieldODEStateAndDerivative;
  23. import org.apache.commons.math4.legacy.ode.sampling.AbstractFieldStepInterpolator;
  24. import org.apache.commons.math4.legacy.core.MathArrays;

  25. /**
  26.  * This class implements an interpolator for Adams integrators using Nordsieck representation.
  27.  *
  28.  * <p>This interpolator computes dense output around the current point.
  29.  * The interpolation equation is based on Taylor series formulas.
  30.  *
  31.  * @see AdamsBashforthFieldIntegrator
  32.  * @see AdamsMoultonFieldIntegrator
  33.  * @param <T> the type of the field elements
  34.  * @since 3.6
  35.  */

  36. class AdamsFieldStepInterpolator<T extends RealFieldElement<T>> extends AbstractFieldStepInterpolator<T> {

  37.     /** Step size used in the first scaled derivative and Nordsieck vector. */
  38.     private T scalingH;

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

  46.     /** First scaled derivative. */
  47.     private final T[] scaled;

  48.     /** Nordsieck vector. */
  49.     private final Array2DRowFieldMatrix<T> nordsieck;

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

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

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

  119.     /** {@inheritDoc} */
  120.     @Override
  121.     protected FieldODEStateAndDerivative<T> computeInterpolatedStateAndDerivatives(final FieldEquationsMapper<T> equationsMapper,
  122.                                                                                    final T time, final T theta,
  123.                                                                                    final T thetaH, final T oneMinusThetaH) {
  124.         return taylor(reference, time, scalingH, scaled, nordsieck);
  125.     }

  126.     /** Estimate state by applying Taylor formula.
  127.      * @param reference reference state
  128.      * @param time time at which state must be estimated
  129.      * @param stepSize step size used in the scaled and Nordsieck arrays
  130.      * @param scaled first scaled derivative
  131.      * @param nordsieck Nordsieck vector
  132.      * @return estimated state
  133.      * @param <S> the type of the field elements
  134.      */
  135.     public static <S extends RealFieldElement<S>> FieldODEStateAndDerivative<S> taylor(final FieldODEStateAndDerivative<S> reference,
  136.                                                                                        final S time, final S stepSize,
  137.                                                                                        final S[] scaled,
  138.                                                                                        final Array2DRowFieldMatrix<S> nordsieck) {

  139.         final S x = time.subtract(reference.getTime());
  140.         final S normalizedAbscissa = x.divide(stepSize);

  141.         S[] stateVariation = MathArrays.buildArray(time.getField(), scaled.length);
  142.         Arrays.fill(stateVariation, time.getField().getZero());
  143.         S[] estimatedDerivatives = MathArrays.buildArray(time.getField(), scaled.length);
  144.         Arrays.fill(estimatedDerivatives, time.getField().getZero());

  145.         // apply Taylor formula from high order to low order,
  146.         // for the sake of numerical accuracy
  147.         final S[][] nData = nordsieck.getDataRef();
  148.         for (int i = nData.length - 1; i >= 0; --i) {
  149.             final int order = i + 2;
  150.             final S[] nDataI = nData[i];
  151.             final S power = normalizedAbscissa.pow(order);
  152.             for (int j = 0; j < nDataI.length; ++j) {
  153.                 final S d = nDataI[j].multiply(power);
  154.                 stateVariation[j]          = stateVariation[j].add(d);
  155.                 estimatedDerivatives[j] = estimatedDerivatives[j].add(d.multiply(order));
  156.             }
  157.         }

  158.         S[] estimatedState = reference.getState();
  159.         for (int j = 0; j < stateVariation.length; ++j) {
  160.             stateVariation[j]    = stateVariation[j].add(scaled[j].multiply(normalizedAbscissa));
  161.             estimatedState[j] = estimatedState[j].add(stateVariation[j]);
  162.             estimatedDerivatives[j] =
  163.                 estimatedDerivatives[j].add(scaled[j].multiply(normalizedAbscissa)).divide(x);
  164.         }

  165.         return new FieldODEStateAndDerivative<>(time, estimatedState, estimatedDerivatives);
  166.     }
  167. }