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 }