• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.math.ode.nonstiff;
19 
20 import org.apache.commons.math.ode.DerivativeException;
21 import org.apache.commons.math.ode.AbstractIntegrator;
22 import org.apache.commons.math.ode.sampling.StepInterpolator;
23 
24 /**
25  * This class represents an interpolator over the last step during an
26  * ODE integration for the 5(4) Dormand-Prince integrator.
27  *
28  * @see DormandPrince54Integrator
29  *
30  * @version $Revision: 1073158 $ $Date: 2011-02-21 22:46:52 +0100 (lun. 21 févr. 2011) $
31  * @since 1.2
32  */
33 
34 class DormandPrince54StepInterpolator
35   extends RungeKuttaStepInterpolator {
36 
37     /** Last row of the Butcher-array internal weights, element 0. */
38     private static final double A70 =    35.0 /  384.0;
39 
40     // element 1 is zero, so it is neither stored nor used
41 
42     /** Last row of the Butcher-array internal weights, element 2. */
43     private static final double A72 =   500.0 / 1113.0;
44 
45     /** Last row of the Butcher-array internal weights, element 3. */
46     private static final double A73 =   125.0 /  192.0;
47 
48     /** Last row of the Butcher-array internal weights, element 4. */
49     private static final double A74 = -2187.0 / 6784.0;
50 
51     /** Last row of the Butcher-array internal weights, element 5. */
52     private static final double A75 =    11.0 /   84.0;
53 
54     /** Shampine (1986) Dense output, element 0. */
55     private static final double D0 =  -12715105075.0 /  11282082432.0;
56 
57     // element 1 is zero, so it is neither stored nor used
58 
59     /** Shampine (1986) Dense output, element 2. */
60     private static final double D2 =   87487479700.0 /  32700410799.0;
61 
62     /** Shampine (1986) Dense output, element 3. */
63     private static final double D3 =  -10690763975.0 /   1880347072.0;
64 
65     /** Shampine (1986) Dense output, element 4. */
66     private static final double D4 =  701980252875.0 / 199316789632.0;
67 
68     /** Shampine (1986) Dense output, element 5. */
69     private static final double D5 =   -1453857185.0 /    822651844.0;
70 
71     /** Shampine (1986) Dense output, element 6. */
72     private static final double D6 =      69997945.0 /     29380423.0;
73 
74     /** Serializable version identifier */
75     private static final long serialVersionUID = 4104157279605906956L;
76 
77     /** First vector for interpolation. */
78     private double[] v1;
79 
80     /** Second vector for interpolation. */
81     private double[] v2;
82 
83     /** Third vector for interpolation. */
84     private double[] v3;
85 
86     /** Fourth vector for interpolation. */
87     private double[] v4;
88 
89     /** Initialization indicator for the interpolation vectors. */
90     private boolean vectorsInitialized;
91 
92   /** Simple constructor.
93    * This constructor builds an instance that is not usable yet, the
94    * {@link #reinitialize} method should be called before using the
95    * instance in order to initialize the internal arrays. This
96    * constructor is used only in order to delay the initialization in
97    * some cases. The {@link EmbeddedRungeKuttaIntegrator} uses the
98    * prototyping design pattern to create the step interpolators by
99    * cloning an uninitialized model and latter initializing the copy.
100    */
DormandPrince54StepInterpolator()101   public DormandPrince54StepInterpolator() {
102     super();
103     v1 = null;
104     v2 = null;
105     v3 = null;
106     v4 = null;
107     vectorsInitialized = false;
108   }
109 
110   /** Copy constructor.
111    * @param interpolator interpolator to copy from. The copy is a deep
112    * copy: its arrays are separated from the original arrays of the
113    * instance
114    */
DormandPrince54StepInterpolator(final DormandPrince54StepInterpolator interpolator)115   public DormandPrince54StepInterpolator(final DormandPrince54StepInterpolator interpolator) {
116 
117     super(interpolator);
118 
119     if (interpolator.v1 == null) {
120 
121       v1 = null;
122       v2 = null;
123       v3 = null;
124       v4 = null;
125       vectorsInitialized = false;
126 
127     } else {
128 
129       v1 = interpolator.v1.clone();
130       v2 = interpolator.v2.clone();
131       v3 = interpolator.v3.clone();
132       v4 = interpolator.v4.clone();
133       vectorsInitialized = interpolator.vectorsInitialized;
134 
135     }
136 
137   }
138 
139   /** {@inheritDoc} */
140   @Override
doCopy()141   protected StepInterpolator doCopy() {
142     return new DormandPrince54StepInterpolator(this);
143   }
144 
145 
146   /** {@inheritDoc} */
147   @Override
reinitialize(final AbstractIntegrator integrator, final double[] y, final double[][] yDotK, final boolean forward)148   public void reinitialize(final AbstractIntegrator integrator,
149                            final double[] y, final double[][] yDotK, final boolean forward) {
150     super.reinitialize(integrator, y, yDotK, forward);
151     v1 = null;
152     v2 = null;
153     v3 = null;
154     v4 = null;
155     vectorsInitialized = false;
156   }
157 
158   /** {@inheritDoc} */
159   @Override
storeTime(final double t)160   public void storeTime(final double t) {
161     super.storeTime(t);
162     vectorsInitialized = false;
163   }
164 
165   /** {@inheritDoc} */
166   @Override
computeInterpolatedStateAndDerivatives(final double theta, final double oneMinusThetaH)167   protected void computeInterpolatedStateAndDerivatives(final double theta,
168                                           final double oneMinusThetaH)
169     throws DerivativeException {
170 
171     if (! vectorsInitialized) {
172 
173       if (v1 == null) {
174         v1 = new double[interpolatedState.length];
175         v2 = new double[interpolatedState.length];
176         v3 = new double[interpolatedState.length];
177         v4 = new double[interpolatedState.length];
178       }
179 
180       // no step finalization is needed for this interpolator
181 
182       // we need to compute the interpolation vectors for this time step
183       for (int i = 0; i < interpolatedState.length; ++i) {
184           final double yDot0 = yDotK[0][i];
185           final double yDot2 = yDotK[2][i];
186           final double yDot3 = yDotK[3][i];
187           final double yDot4 = yDotK[4][i];
188           final double yDot5 = yDotK[5][i];
189           final double yDot6 = yDotK[6][i];
190           v1[i] = A70 * yDot0 + A72 * yDot2 + A73 * yDot3 + A74 * yDot4 + A75 * yDot5;
191           v2[i] = yDot0 - v1[i];
192           v3[i] = v1[i] - v2[i] - yDot6;
193           v4[i] = D0 * yDot0 + D2 * yDot2 + D3 * yDot3 + D4 * yDot4 + D5 * yDot5 + D6 * yDot6;
194       }
195 
196       vectorsInitialized = true;
197 
198     }
199 
200     // interpolate
201     final double eta = 1 - theta;
202     final double twoTheta = 2 * theta;
203     final double dot2 = 1 - twoTheta;
204     final double dot3 = theta * (2 - 3 * theta);
205     final double dot4 = twoTheta * (1 + theta * (twoTheta - 3));
206     for (int i = 0; i < interpolatedState.length; ++i) {
207       interpolatedState[i] =
208           currentState[i] - oneMinusThetaH * (v1[i] - theta * (v2[i] + theta * (v3[i] + eta * v4[i])));
209       interpolatedDerivatives[i] = v1[i] + dot2 * v2[i] + dot3 * v3[i] + dot4 * v4[i];
210     }
211 
212   }
213 
214 }
215