FirstOrderConverter.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.  *      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. /*
  18.  * This is not the original file distributed by the Apache Software Foundation
  19.  * It has been modified by the Hipparchus project
  20.  */

  21. package org.hipparchus.ode;

  22. /** This class converts second order differential equations to first
  23.  * order ones.
  24.  *
  25.  * <p>This class is a wrapper around a {@link SecondOrderODE} which
  26.  * allow to use a {@link ODEIntegrator} to integrate it.</p>
  27.  *
  28.  * <p>The transformation is done by changing the n dimension state
  29.  * vector to a 2n dimension vector, where the first n components are
  30.  * the initial state variables and the n last components are their
  31.  * first time derivative. The first time derivative of this state
  32.  * vector then really contains both the first and second time
  33.  * derivative of the initial state vector, which can be handled by the
  34.  * underlying second order equations set.</p>
  35.  *
  36.  * <p>One should be aware that the data is duplicated during the
  37.  * transformation process and that for each call to {@link
  38.  * #computeDerivatives computeDerivatives}, this wrapper does copy 4n
  39.  * scalars : 2n before the call to {@link
  40.  * SecondOrderODE#computeSecondDerivatives
  41.  * computeSecondDerivatives} in order to dispatch the y state vector
  42.  * into z and zDot, and 2n after the call to gather zDot and zDDot
  43.  * into yDot. Since the underlying problem by itself perhaps also
  44.  * needs to copy data and dispatch the arrays into domain objects,
  45.  * this has an impact on both memory and CPU usage. The only way to
  46.  * avoid this duplication is to perform the transformation at the
  47.  * problem level, i.e. to implement the problem as a first order one
  48.  * and then avoid using this class.</p>
  49.  *
  50.  * @see ODEIntegrator
  51.  * @see OrdinaryDifferentialEquation
  52.  * @see SecondOrderODE
  53.  */

  54. public class FirstOrderConverter implements OrdinaryDifferentialEquation {

  55.     /** Underlying second order equations set. */
  56.     private final SecondOrderODE equations;

  57.     /** second order problem dimension. */
  58.     private final int dimension;

  59.     /** Simple constructor.
  60.      * Build a converter around a second order equations set.
  61.      * @param equations second order equations set to convert
  62.      */
  63.     public FirstOrderConverter (final SecondOrderODE equations) {
  64.         this.equations = equations;
  65.         dimension      = equations.getDimension();
  66.     }

  67.     /** {@inheritDoc}
  68.      * <p>The dimension of the first order problem is twice the
  69.      * dimension of the underlying second order problem.</p>
  70.      * @return dimension of the problem
  71.      */
  72.     @Override
  73.     public int getDimension() {
  74.         return 2 * dimension;
  75.     }

  76.     /** {@inheritDoc} */
  77.     @Override
  78.     public double[] computeDerivatives(final double t, final double[] y) {

  79.         final double[] yDot = new double[y.length];

  80.         // split the state vector in two
  81.         final double[] z    = new double[dimension];
  82.         final double[] zDot = new double[dimension];
  83.         System.arraycopy(y, 0,         z,    0, dimension);
  84.         System.arraycopy(y, dimension, zDot, 0, dimension);

  85.         // apply the underlying equations set
  86.         final double[] zDDot = equations.computeSecondDerivatives(t, z, zDot);

  87.         // build the result state derivative
  88.         System.arraycopy(zDot,  0, yDot, 0,         dimension);
  89.         System.arraycopy(zDDot, 0, yDot, dimension, dimension);

  90.         return yDot;

  91.     }

  92. }