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 java.io.IOException; 21 import java.io.ObjectInput; 22 import java.io.ObjectOutput; 23 24 import org.apache.commons.math.ode.AbstractIntegrator; 25 import org.apache.commons.math.ode.sampling.AbstractStepInterpolator; 26 27 /** This class represents an interpolator over the last step during an 28 * ODE integration for Runge-Kutta and embedded Runge-Kutta integrators. 29 * 30 * @see RungeKuttaIntegrator 31 * @see EmbeddedRungeKuttaIntegrator 32 * 33 * @version $Revision: 783103 $ $Date: 2009-06-09 15:33:19 -0400 (Tue, 09 Jun 2009) $ 34 * @since 1.2 35 */ 36 37 abstract class RungeKuttaStepInterpolator 38 extends AbstractStepInterpolator { 39 40 /** Simple constructor. 41 * This constructor builds an instance that is not usable yet, the 42 * {@link #reinitialize} method should be called before using the 43 * instance in order to initialize the internal arrays. This 44 * constructor is used only in order to delay the initialization in 45 * some cases. The {@link RungeKuttaIntegrator} and {@link 46 * EmbeddedRungeKuttaIntegrator} classes use the prototyping design 47 * pattern to create the step interpolators by cloning an 48 * uninitialized model and latter initializing the copy. 49 */ 50 protected RungeKuttaStepInterpolator() { 51 super(); 52 yDotK = null; 53 integrator = null; 54 } 55 56 /** Copy constructor. 57 58 * <p>The copied interpolator should have been finalized before the 59 * copy, otherwise the copy will not be able to perform correctly any 60 * interpolation and will throw a {@link NullPointerException} 61 * later. Since we don't want this constructor to throw the 62 * exceptions finalization may involve and since we don't want this 63 * method to modify the state of the copied interpolator, 64 * finalization is <strong>not</strong> done automatically, it 65 * remains under user control.</p> 66 67 * <p>The copy is a deep copy: its arrays are separated from the 68 * original arrays of the instance.</p> 69 70 * @param interpolator interpolator to copy from. 71 72 */ 73 public RungeKuttaStepInterpolator(final RungeKuttaStepInterpolator interpolator) { 74 75 super(interpolator); 76 77 if (interpolator.currentState != null) { 78 final int dimension = currentState.length; 79 80 yDotK = new double[interpolator.yDotK.length][]; 81 for (int k = 0; k < interpolator.yDotK.length; ++k) { 82 yDotK[k] = new double[dimension]; 83 System.arraycopy(interpolator.yDotK[k], 0, 84 yDotK[k], 0, dimension); 85 } 86 87 } else { 88 yDotK = null; 89 } 90 91 // we cannot keep any reference to the equations in the copy 92 // the interpolator should have been finalized before 93 integrator = null; 94 95 } 96 97 /** Reinitialize the instance 98 * <p>Some Runge-Kutta integrators need fewer functions evaluations 99 * than their counterpart step interpolators. So the interpolator 100 * should perform the last evaluations they need by themselves. The 101 * {@link RungeKuttaIntegrator RungeKuttaIntegrator} and {@link 102 * EmbeddedRungeKuttaIntegrator EmbeddedRungeKuttaIntegrator} 103 * abstract classes call this method in order to let the step 104 * interpolator perform the evaluations it needs. These evaluations 105 * will be performed during the call to <code>doFinalize</code> if 106 * any, i.e. only if the step handler either calls the {@link 107 * AbstractStepInterpolator#finalizeStep finalizeStep} method or the 108 * {@link AbstractStepInterpolator#getInterpolatedState 109 * getInterpolatedState} method (for an interpolator which needs a 110 * finalization) or if it clones the step interpolator.</p> 111 * @param integrator integrator being used 112 * @param y reference to the integrator array holding the state at 113 * the end of the step 114 * @param yDotK reference to the integrator array holding all the 115 * intermediate slopes 116 * @param forward integration direction indicator 117 */ 118 public void reinitialize(final AbstractIntegrator integrator, 119 final double[] y, final double[][] yDotK, final boolean forward) { 120 reinitialize(y, forward); 121 this.yDotK = yDotK; 122 this.integrator = integrator; 123 } 124 125 /** {@inheritDoc} */ 126 @Override 127 public void writeExternal(final ObjectOutput out) 128 throws IOException { 129 130 // save the state of the base class 131 writeBaseExternal(out); 132 133 // save the local attributes 134 final int n = (currentState == null) ? -1 : currentState.length; 135 final int kMax = (yDotK == null) ? -1 : yDotK.length; 136 out.writeInt(kMax); 137 for (int k = 0; k < kMax; ++k) { 138 for (int i = 0; i < n; ++i) { 139 out.writeDouble(yDotK[k][i]); 140 } 141 } 142 143 // we do not save any reference to the equations 144 145 } 146 147 /** {@inheritDoc} */ 148 @Override 149 public void readExternal(final ObjectInput in) 150 throws IOException { 151 152 // read the base class 153 final double t = readBaseExternal(in); 154 155 // read the local attributes 156 final int n = (currentState == null) ? -1 : currentState.length; 157 final int kMax = in.readInt(); 158 yDotK = (kMax < 0) ? null : new double[kMax][]; 159 for (int k = 0; k < kMax; ++k) { 160 yDotK[k] = (n < 0) ? null : new double[n]; 161 for (int i = 0; i < n; ++i) { 162 yDotK[k][i] = in.readDouble(); 163 } 164 } 165 166 integrator = null; 167 168 if (currentState != null) { 169 // we can now set the interpolated time and state 170 setInterpolatedTime(t); 171 } else { 172 interpolatedTime = t; 173 } 174 175 } 176 177 /** Slopes at the intermediate points */ 178 protected double[][] yDotK; 179 180 /** Reference to the integrator. */ 181 protected AbstractIntegrator integrator; 182 183 }