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;
19
20 /**
21 * This class represents an interpolator over the last step during an
22 * ODE integration for the 5(4) Dormand-Prince integrator.
23 *
24 * @see DormandPrince54Integrator
25 *
26 * @version $Revision: 620312 $ $Date: 2008-02-10 12:28:59 -0700 (Sun, 10 Feb 2008) $
27 * @since 1.2
28 */
29
30 class DormandPrince54StepInterpolator
31 extends RungeKuttaStepInterpolator {
32
33 /** Simple constructor.
34 * This constructor builds an instance that is not usable yet, the
35 * {@link #reinitialize} method should be called before using the
36 * instance in order to initialize the internal arrays. This
37 * constructor is used only in order to delay the initialization in
38 * some cases. The {@link EmbeddedRungeKuttaIntegrator} uses the
39 * prototyping design pattern to create the step interpolators by
40 * cloning an uninitialized model and latter initializing the copy.
41 */
42 public DormandPrince54StepInterpolator() {
43 super();
44 v1 = null;
45 v2 = null;
46 v3 = null;
47 v4 = null;
48 vectorsInitialized = false;
49 }
50
51 /** Copy constructor.
52 * @param interpolator interpolator to copy from. The copy is a deep
53 * copy: its arrays are separated from the original arrays of the
54 * instance
55 */
56 public DormandPrince54StepInterpolator(DormandPrince54StepInterpolator interpolator) {
57
58 super(interpolator);
59
60 if (interpolator.v1 == null) {
61
62 v1 = null;
63 v2 = null;
64 v3 = null;
65 v4 = null;
66 vectorsInitialized = false;
67
68 } else {
69
70 v1 = (double[]) interpolator.v1.clone();
71 v2 = (double[]) interpolator.v2.clone();
72 v3 = (double[]) interpolator.v3.clone();
73 v4 = (double[]) interpolator.v4.clone();
74 vectorsInitialized = interpolator.vectorsInitialized;
75
76 }
77
78 }
79
80 /** Really copy the finalized instance.
81 * @return a copy of the finalized instance
82 */
83 protected StepInterpolator doCopy() {
84 return new DormandPrince54StepInterpolator(this);
85 }
86
87
88 /** Reinitialize the instance
89 * @param equations set of differential equations being integrated
90 * @param y reference to the integrator array holding the state at
91 * the end of the step
92 * @param yDotK reference to the integrator array holding all the
93 * intermediate slopes
94 * @param forward integration direction indicator
95 */
96 public void reinitialize(FirstOrderDifferentialEquations equations,
97 double[] y, double[][] yDotK, boolean forward) {
98 super.reinitialize(equations, y, yDotK, forward);
99 v1 = null;
100 v2 = null;
101 v3 = null;
102 v4 = null;
103 vectorsInitialized = false;
104 }
105
106 /** Store the current step time.
107 * @param t current time
108 */
109 public void storeTime(double t) {
110 super.storeTime(t);
111 vectorsInitialized = false;
112 }
113
114 /** Compute the state at the interpolated time.
115 * @param theta normalized interpolation abscissa within the step
116 * (theta is zero at the previous time step and one at the current time step)
117 * @param oneMinusThetaH time gap between the interpolated time and
118 * the current time
119 * @throws DerivativeException this exception is propagated to the caller if the
120 * underlying user function triggers one
121 */
122 protected void computeInterpolatedState(double theta,
123 double oneMinusThetaH)
124 throws DerivativeException {
125
126 if (! vectorsInitialized) {
127
128 if (v1 == null) {
129 v1 = new double[interpolatedState.length];
130 v2 = new double[interpolatedState.length];
131 v3 = new double[interpolatedState.length];
132 v4 = new double[interpolatedState.length];
133 }
134
135 // no step finalization is needed for this interpolator
136
137 // we need to compute the interpolation vectors for this time step
138 for (int i = 0; i < interpolatedState.length; ++i) {
139 v1[i] = h * (a70 * yDotK[0][i] + a72 * yDotK[2][i] + a73 * yDotK[3][i] +
140 a74 * yDotK[4][i] + a75 * yDotK[5][i]);
141 v2[i] = h * yDotK[0][i] - v1[i];
142 v3[i] = v1[i] - v2[i] - h * yDotK[6][i];
143 v4[i] = h * (d0 * yDotK[0][i] + d2 * yDotK[2][i] + d3 * yDotK[3][i] +
144 d4 * yDotK[4][i] + d5 * yDotK[5][i] + d6 * yDotK[6][i]);
145 }
146
147 vectorsInitialized = true;
148
149 }
150
151 // interpolate
152 double eta = oneMinusThetaH / h;
153 for (int i = 0; i < interpolatedState.length; ++i) {
154 interpolatedState[i] = currentState[i] -
155 eta * (v1[i] - theta * (v2[i] + theta * (v3[i] + eta * v4[i])));
156 }
157
158 }
159
160 /** First vector for interpolation. */
161 private double[] v1;
162
163 /** Second vector for interpolation. */
164 private double[] v2;
165
166 /** Third vector for interpolation. */
167 private double[] v3;
168
169 /** Fourth vector for interpolation. */
170 private double[] v4;
171
172 /** Initialization indicator for the interpolation vectors. */
173 private boolean vectorsInitialized;
174
175 /** Last row of the Butcher-array internal weights, element 0. */
176 private static final double a70 = 35.0 / 384.0;
177
178 // element 1 is zero, so it is neither stored nor used
179
180 /** Last row of the Butcher-array internal weights, element 2. */
181 private static final double a72 = 500.0 / 1113.0;
182
183 /** Last row of the Butcher-array internal weights, element 3. */
184 private static final double a73 = 125.0 / 192.0;
185
186 /** Last row of the Butcher-array internal weights, element 4. */
187 private static final double a74 = -2187.0 / 6784.0;
188
189 /** Last row of the Butcher-array internal weights, element 5. */
190 private static final double a75 = 11.0 / 84.0;
191
192 /** Shampine (1986) Dense output, element 0. */
193 private static final double d0 = -12715105075.0 / 11282082432.0;
194
195 // element 1 is zero, so it is neither stored nor used
196
197 /** Shampine (1986) Dense output, element 2. */
198 private static final double d2 = 87487479700.0 / 32700410799.0;
199
200 /** Shampine (1986) Dense output, element 3. */
201 private static final double d3 = -10690763975.0 / 1880347072.0;
202
203 /** Shampine (1986) Dense output, element 4. */
204 private static final double d4 = 701980252875.0 / 199316789632.0;
205
206 /** Shampine (1986) Dense output, element 5. */
207 private static final double d5 = -1453857185.0 / 822651844.0;
208
209 /** Shampine (1986) Dense output, element 6. */
210 private static final double d6 = 69997945.0 / 29380423.0;
211
212 /** Serializable version identifier */
213 private static final long serialVersionUID = 4104157279605906956L;
214
215 }