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