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.  *      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;


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

  52. public class FirstOrderConverter implements FirstOrderDifferentialEquations {

  53.     /** Underlying second order equations set. */
  54.     private final SecondOrderDifferentialEquations equations;

  55.     /** second order problem dimension. */
  56.     private final int dimension;

  57.     /** state vector. */
  58.     private final double[] z;

  59.     /** first time derivative of the state vector. */
  60.     private final double[] zDot;

  61.     /** second time derivative of the state vector. */
  62.     private final double[] zDDot;

  63.   /** Simple constructor.
  64.    * Build a converter around a second order equations set.
  65.    * @param equations second order equations set to convert
  66.    */
  67.   public FirstOrderConverter (final SecondOrderDifferentialEquations equations) {
  68.       this.equations = equations;
  69.       dimension      = equations.getDimension();
  70.       z              = new double[dimension];
  71.       zDot           = new double[dimension];
  72.       zDDot          = new double[dimension];
  73.   }

  74.   /** Get the dimension of the problem.
  75.    * <p>The dimension of the first order problem is twice the
  76.    * dimension of the underlying second order problem.</p>
  77.    * @return dimension of the problem
  78.    */
  79.   @Override
  80. public int getDimension() {
  81.     return 2 * dimension;
  82.   }

  83.   /** Get the current time derivative of the state vector.
  84.    * @param t current value of the independent <I>time</I> variable
  85.    * @param y array containing the current value of the state vector
  86.    * @param yDot placeholder array where to put the time derivative of the state vector
  87.    */
  88.   @Override
  89. public void computeDerivatives(final double t, final double[] y, final double[] yDot) {

  90.     // split the state vector in two
  91.     System.arraycopy(y, 0,         z,    0, dimension);
  92.     System.arraycopy(y, dimension, zDot, 0, dimension);

  93.     // apply the underlying equations set
  94.     equations.computeSecondDerivatives(t, z, zDot, zDDot);

  95.     // build the result state derivative
  96.     System.arraycopy(zDot,  0, yDot, 0,         dimension);
  97.     System.arraycopy(zDDot, 0, yDot, dimension, dimension);
  98.   }
  99. }