ExplicitRungeKuttaIntegrator.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.ExpandableODE;
  19. import org.hipparchus.ode.ODEIntegrator;
  20. import org.hipparchus.ode.ODEState;
  21. import org.hipparchus.ode.OrdinaryDifferentialEquation;


  22. /**
  23.  * This interface implements the part of Runge-Kutta
  24.  * integrators for Ordinary Differential Equations
  25.  * common to fixed- and adaptive steps.
  26.  *
  27.  * <p>These methods are explicit Runge-Kutta methods, their Butcher
  28.  * arrays are as follows :</p>
  29.  * <pre>
  30.  *    0  |
  31.  *   c2  | a21
  32.  *   c3  | a31  a32
  33.  *   ... |        ...
  34.  *   cs  | as1  as2  ...  ass-1
  35.  *       |--------------------------
  36.  *       |  b1   b2  ...   bs-1  bs
  37.  * </pre>
  38.  *
  39.  * @see ButcherArrayProvider
  40.  * @see FixedStepRungeKuttaIntegrator
  41.  * @see EmbeddedRungeKuttaIntegrator
  42.  * @since 3.1
  43.  */

  44. public interface ExplicitRungeKuttaIntegrator extends ButcherArrayProvider, ODEIntegrator {

  45.     /**
  46.      * Getter for the number of stages corresponding to the Butcher array.
  47.      *
  48.      * @return number of stages
  49.      */
  50.     default int getNumberOfStages() {
  51.         return getB().length;
  52.     }

  53.     /** Fast computation of a single step of ODE integration.
  54.      * <p>This method is intended for the limited use case of
  55.      * very fast computation of only one step without using any of the
  56.      * rich features of general integrators that may take some time
  57.      * to set up (i.e. no step handlers, no events handlers, no additional
  58.      * states, no interpolators, no error control, no evaluations count,
  59.      * no sanity checks ...). It handles the strict minimum of computation,
  60.      * so it can be embedded in outer loops.</p>
  61.      * <p>
  62.      * This method is <em>not</em> used at all by the {@link #integrate(ExpandableODE, ODEState, double)}
  63.      * method. It also completely ignores the step set at construction time, and
  64.      * uses only a single step to go from {@code t0} to {@code t}.
  65.      * </p>
  66.      * <p>
  67.      * As this method does not use any of the state-dependent features of the integrator,
  68.      * it should be reasonably thread-safe <em>if and only if</em> the provided differential
  69.      * equations are themselves thread-safe.
  70.      * </p>
  71.      * @param equations differential equations to integrate
  72.      * @param t0 initial time
  73.      * @param y0 initial value of the state vector at t0
  74.      * @param t target time for the integration
  75.      * (can be set to a value smaller than {@code t0} for backward integration)
  76.      * @return state vector at {@code t}
  77.      */
  78.     default double[] singleStep(final OrdinaryDifferentialEquation equations, final double t0, final double[] y0,
  79.                                 final double t) {

  80.         // create some internal working arrays
  81.         final int stages       = getNumberOfStages();
  82.         final double[][] yDotK = new double[stages][];

  83.         // first stage
  84.         final double h = t - t0;
  85.         final ExpandableODE expandableODE = new ExpandableODE(equations);
  86.         yDotK[0] = expandableODE.computeDerivatives(t0, y0);

  87.         // next stages
  88.         applyInternalButcherWeights(expandableODE, t0, y0, h, getA(), getC(), yDotK);

  89.         // estimate the state at the end of the step
  90.         return applyExternalButcherWeights(y0, yDotK, h, getB());

  91.     }

  92.     /**
  93.      * Apply internal weights of Butcher array, with corresponding times.
  94.      * @param equations differential equations to integrate
  95.      * @param t0        initial time
  96.      * @param y0        initial value of the state vector at t0
  97.      * @param h         step size
  98.      * @param a         internal weights of Butcher array
  99.      * @param c         times of Butcher array
  100.      * @param yDotK     array where to store result
  101.      */
  102.     static void applyInternalButcherWeights(final ExpandableODE equations, final double t0, final double[] y0,
  103.                                             final double h, final double[][] a, final double[] c,
  104.                                             final double[][] yDotK) {
  105.         // create some internal working arrays
  106.         final int stages = c.length + 1;
  107.         final double[] yTmp = y0.clone();

  108.         for (int k = 1; k < stages; ++k) {

  109.             for (int j = 0; j < y0.length; ++j) {
  110.                 double sum = yDotK[0][j] * a[k - 1][0];
  111.                 for (int l = 1; l < k; ++l) {
  112.                     sum += yDotK[l][j] * a[k - 1][l];
  113.                 }
  114.                 yTmp[j] = y0[j] + h * sum;
  115.             }

  116.             yDotK[k] = equations.computeDerivatives(t0 + h * c[k - 1], yTmp);
  117.         }
  118.     }

  119.     /** Apply external weights of Butcher array, assuming internal ones have been applied.
  120.      * @param yDotK output of stages
  121.      * @param y0 initial value of the state vector at t0
  122.      * @param h step size
  123.      * @param b external weights of Butcher array
  124.      * @return state vector
  125.      */
  126.     static double[] applyExternalButcherWeights(final double[] y0, final double[][] yDotK, final double h,
  127.                                                 final double[] b) {
  128.         final double[] y = y0.clone();
  129.         final int stages = b.length;
  130.         for (int j = 0; j < y0.length; ++j) {
  131.             double sum = yDotK[0][j] * b[0];
  132.             for (int l = 1; l < stages; ++l) {
  133.                 sum += yDotK[l][j] * b[l];
  134.             }
  135.             y[j] += h * sum;
  136.         }
  137.         return y;
  138.     }
  139. }