View Javadoc
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  
18  package org.apache.commons.math4.legacy.ode;
19  
20  
21  /** This class converts second order differential equations to first
22   * order ones.
23   *
24   * <p>This class is a wrapper around a {@link
25   * SecondOrderDifferentialEquations} which allow to use a {@link
26   * FirstOrderIntegrator} 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   * SecondOrderDifferentialEquations#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 FirstOrderIntegrator
51   * @see FirstOrderDifferentialEquations
52   * @see SecondOrderDifferentialEquations
53   * @since 1.2
54   */
55  
56  public class FirstOrderConverter implements FirstOrderDifferentialEquations {
57  
58      /** Underlying second order equations set. */
59      private final SecondOrderDifferentialEquations equations;
60  
61      /** second order problem dimension. */
62      private final int dimension;
63  
64      /** state vector. */
65      private final double[] z;
66  
67      /** first time derivative of the state vector. */
68      private final double[] zDot;
69  
70      /** second time derivative of the state vector. */
71      private final double[] zDDot;
72  
73    /** Simple constructor.
74     * Build a converter around a second order equations set.
75     * @param equations second order equations set to convert
76     */
77    public FirstOrderConverter (final SecondOrderDifferentialEquations equations) {
78        this.equations = equations;
79        dimension      = equations.getDimension();
80        z              = new double[dimension];
81        zDot           = new double[dimension];
82        zDDot          = new double[dimension];
83    }
84  
85    /** Get the dimension of the problem.
86     * <p>The dimension of the first order problem is twice the
87     * dimension of the underlying second order problem.</p>
88     * @return dimension of the problem
89     */
90    @Override
91  public int getDimension() {
92      return 2 * dimension;
93    }
94  
95    /** Get the current time derivative of the state vector.
96     * @param t current value of the independent <I>time</I> variable
97     * @param y array containing the current value of the state vector
98     * @param yDot placeholder array where to put the time derivative of the state vector
99     */
100   @Override
101 public void computeDerivatives(final double t, final double[] y, final double[] yDot) {
102 
103     // split the state vector in two
104     System.arraycopy(y, 0,         z,    0, dimension);
105     System.arraycopy(y, dimension, zDot, 0, dimension);
106 
107     // apply the underlying equations set
108     equations.computeSecondDerivatives(t, z, zDot, zDDot);
109 
110     // build the result state derivative
111     System.arraycopy(zDot,  0, yDot, 0,         dimension);
112     System.arraycopy(zDDot, 0, yDot, dimension, dimension);
113   }
114 }