1dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond/*
2dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * Licensed to the Apache Software Foundation (ASF) under one or more
3dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * contributor license agreements.  See the NOTICE file distributed with
4dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * this work for additional information regarding copyright ownership.
5dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * The ASF licenses this file to You under the Apache License, Version 2.0
6dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * (the "License"); you may not use this file except in compliance with
7dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * the License.  You may obtain a copy of the License at
8dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond *
9dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond *      http://www.apache.org/licenses/LICENSE-2.0
10dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond *
11dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * Unless required by applicable law or agreed to in writing, software
12dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * distributed under the License is distributed on an "AS IS" BASIS,
13dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * See the License for the specific language governing permissions and
15dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * limitations under the License.
16dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond */
17dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
18dee0849a9704d532af0b550146cbafbaa6ee1d19Raymondpackage org.apache.commons.math.ode.sampling;
19dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
20dee0849a9704d532af0b550146cbafbaa6ee1d19Raymondimport java.io.IOException;
21dee0849a9704d532af0b550146cbafbaa6ee1d19Raymondimport java.io.ObjectInput;
22dee0849a9704d532af0b550146cbafbaa6ee1d19Raymondimport java.io.ObjectOutput;
23dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
24dee0849a9704d532af0b550146cbafbaa6ee1d19Raymondimport org.apache.commons.math.ode.DerivativeException;
25dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
26dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond/** This abstract class represents an interpolator over the last step
27dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * during an ODE integration.
28dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond *
29dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * <p>The various ODE integrators provide objects extending this class
30dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * to the step handlers. The handlers can use these objects to
31dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * retrieve the state vector at intermediate times between the
32dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * previous and the current grid points (dense output).</p>
33dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond *
34dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @see org.apache.commons.math.ode.FirstOrderIntegrator
35dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @see org.apache.commons.math.ode.SecondOrderIntegrator
36dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @see StepHandler
37dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond *
38dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @version $Revision: 1073158 $ $Date: 2011-02-21 22:46:52 +0100 (lun. 21 févr. 2011) $
39dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @since 1.2
40dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond *
41dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond */
42dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
43dee0849a9704d532af0b550146cbafbaa6ee1d19Raymondpublic abstract class AbstractStepInterpolator
44dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond  implements StepInterpolator {
45dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
46dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond  /** current time step */
47dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond  protected double h;
48dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
49dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond  /** current state */
50dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond  protected double[] currentState;
51dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
52dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond  /** interpolated time */
53dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond  protected double interpolatedTime;
54dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
55dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond  /** interpolated state */
56dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond  protected double[] interpolatedState;
57dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
58dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond  /** interpolated derivatives */
59dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond  protected double[] interpolatedDerivatives;
60dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
61dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond  /** global previous time */
62dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond  private double globalPreviousTime;
63dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
64dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond  /** global current time */
65dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond  private double globalCurrentTime;
66dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
67dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond  /** soft previous time */
68dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond  private double softPreviousTime;
69dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
70dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond  /** soft current time */
71dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond  private double softCurrentTime;
72dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
73dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond  /** indicate if the step has been finalized or not. */
74dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond  private boolean finalized;
75dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
76dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond  /** integration direction. */
77dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond  private boolean forward;
78dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
79dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond  /** indicator for dirty state. */
80dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond  private boolean dirtyState;
81dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
82dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
83dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond  /** Simple constructor.
84dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond   * This constructor builds an instance that is not usable yet, the
85dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond   * {@link #reinitialize} method should be called before using the
86dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond   * instance in order to initialize the internal arrays. This
87dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond   * constructor is used only in order to delay the initialization in
88dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond   * some cases. As an example, the {@link
89dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond   * org.apache.commons.math.ode.nonstiff.EmbeddedRungeKuttaIntegrator}
90dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond   * class uses the prototyping design pattern to create the step
91dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond   * interpolators by cloning an uninitialized model and latter
92dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond   * initializing the copy.
93dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond   */
94dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond  protected AbstractStepInterpolator() {
95dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    globalPreviousTime      = Double.NaN;
96dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    globalCurrentTime       = Double.NaN;
97dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    softPreviousTime        = Double.NaN;
98dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    softCurrentTime         = Double.NaN;
99dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    h                       = Double.NaN;
100dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    interpolatedTime        = Double.NaN;
101dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    currentState            = null;
102dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    interpolatedState       = null;
103dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    interpolatedDerivatives = null;
104dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    finalized               = false;
105dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    this.forward            = true;
106dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    this.dirtyState         = true;
107dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond  }
108dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
109dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond  /** Simple constructor.
110dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond   * @param y reference to the integrator array holding the state at
111dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond   * the end of the step
112dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond   * @param forward integration direction indicator
113dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond   */
114dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond  protected AbstractStepInterpolator(final double[] y, final boolean forward) {
115dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
116dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    globalPreviousTime = Double.NaN;
117dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    globalCurrentTime  = Double.NaN;
118dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    softPreviousTime   = Double.NaN;
119dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    softCurrentTime    = Double.NaN;
120dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    h                  = Double.NaN;
121dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    interpolatedTime   = Double.NaN;
122dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
123dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    currentState            = y;
124dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    interpolatedState       = new double[y.length];
125dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    interpolatedDerivatives = new double[y.length];
126dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
127dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    finalized         = false;
128dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    this.forward      = forward;
129dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    this.dirtyState   = true;
130dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
131dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond  }
132dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
133dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond  /** Copy constructor.
134dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
135dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond   * <p>The copied interpolator should have been finalized before the
136dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond   * copy, otherwise the copy will not be able to perform correctly
137dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond   * any derivative computation and will throw a {@link
138dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond   * NullPointerException} later. Since we don't want this constructor
139dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond   * to throw the exceptions finalization may involve and since we
140dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond   * don't want this method to modify the state of the copied
141dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond   * interpolator, finalization is <strong>not</strong> done
142dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond   * automatically, it remains under user control.</p>
143dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond   *
144dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond   * <p>The copy is a deep copy: its arrays are separated from the
145dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond   * original arrays of the instance.</p>
146dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond   *
147dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond   * @param interpolator interpolator to copy from.
148dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond   *
149dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond   */
150dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond  protected AbstractStepInterpolator(final AbstractStepInterpolator interpolator) {
151dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
152dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    globalPreviousTime = interpolator.globalPreviousTime;
153dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    globalCurrentTime  = interpolator.globalCurrentTime;
154dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    softPreviousTime   = interpolator.softPreviousTime;
155dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    softCurrentTime    = interpolator.softCurrentTime;
156dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    h                  = interpolator.h;
157dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    interpolatedTime   = interpolator.interpolatedTime;
158dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
159dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    if (interpolator.currentState != null) {
160dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      currentState            = interpolator.currentState.clone();
161dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      interpolatedState       = interpolator.interpolatedState.clone();
162dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      interpolatedDerivatives = interpolator.interpolatedDerivatives.clone();
163dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    } else {
164dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      currentState            = null;
165dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      interpolatedState       = null;
166dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      interpolatedDerivatives = null;
167dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    }
168dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
169dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    finalized  = interpolator.finalized;
170dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    forward    = interpolator.forward;
171dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    dirtyState = interpolator.dirtyState;
172dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
173dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond  }
174dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
175dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond  /** Reinitialize the instance
176dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond   * @param y reference to the integrator array holding the state at
177dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond   * the end of the step
178dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond   * @param isForward integration direction indicator
179dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond   */
180dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond  protected void reinitialize(final double[] y, final boolean isForward) {
181dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
182dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    globalPreviousTime = Double.NaN;
183dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    globalCurrentTime  = Double.NaN;
184dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    softPreviousTime   = Double.NaN;
185dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    softCurrentTime    = Double.NaN;
186dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    h                  = Double.NaN;
187dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    interpolatedTime   = Double.NaN;
188dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
189dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    currentState            = y;
190dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    interpolatedState       = new double[y.length];
191dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    interpolatedDerivatives = new double[y.length];
192dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
193dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    finalized         = false;
194dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    this.forward      = isForward;
195dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    this.dirtyState   = true;
196dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
197dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond  }
198dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
199dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond  /** {@inheritDoc} */
200dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond   public StepInterpolator copy() throws DerivativeException {
201dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
202dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     // finalize the step before performing copy
203dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     finalizeStep();
204dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
205dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     // create the new independent instance
206dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     return doCopy();
207dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
208dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond   }
209dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
210dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond   /** Really copy the finalized instance.
211dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    * <p>This method is called by {@link #copy()} after the
212dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    * step has been finalized. It must perform a deep copy
213dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    * to have an new instance completely independent for the
214dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    * original instance.
215dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    * @return a copy of the finalized instance
216dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    */
217dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond   protected abstract StepInterpolator doCopy();
218dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
219dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond  /** Shift one step forward.
220dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond   * Copy the current time into the previous time, hence preparing the
221dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond   * interpolator for future calls to {@link #storeTime storeTime}
222dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond   */
223dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond  public void shift() {
224dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    globalPreviousTime = globalCurrentTime;
225dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    softPreviousTime   = globalPreviousTime;
226dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    softCurrentTime    = globalCurrentTime;
227dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond  }
228dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
229dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond  /** Store the current step time.
230dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond   * @param t current time
231dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond   */
232dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond  public void storeTime(final double t) {
233dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
234dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    globalCurrentTime = t;
235dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    softCurrentTime   = globalCurrentTime;
236dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    h                 = globalCurrentTime - globalPreviousTime;
237dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    setInterpolatedTime(t);
238dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
239dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    // the step is not finalized anymore
240dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    finalized  = false;
241dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
242dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond  }
243dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
244dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond  /** Restrict step range to a limited part of the global step.
245dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond   * <p>
246dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond   * This method can be used to restrict a step and make it appear
247dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond   * as if the original step was smaller. Calling this method
248dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond   * <em>only</em> changes the value returned by {@link #getPreviousTime()},
249dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond   * it does not change any other property
250dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond   * </p>
251dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond   * @param softPreviousTime start of the restricted step
252dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond   * @since 2.2
253dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond   */
254dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond  public void setSoftPreviousTime(final double softPreviousTime) {
255dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      this.softPreviousTime = softPreviousTime;
256dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond  }
257dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
258dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond  /** Restrict step range to a limited part of the global step.
259dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond   * <p>
260dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond   * This method can be used to restrict a step and make it appear
261dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond   * as if the original step was smaller. Calling this method
262dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond   * <em>only</em> changes the value returned by {@link #getCurrentTime()},
263dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond   * it does not change any other property
264dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond   * </p>
265dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond   * @param softCurrentTime end of the restricted step
266dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond   * @since 2.2
267dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond   */
268dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond  public void setSoftCurrentTime(final double softCurrentTime) {
269dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      this.softCurrentTime  = softCurrentTime;
270dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond  }
271dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
272dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond  /**
273dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond   * Get the previous global grid point time.
274dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond   * @return previous global grid point time
275dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond   * @since 2.2
276dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond   */
277dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond  public double getGlobalPreviousTime() {
278dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    return globalPreviousTime;
279dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond  }
280dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
281dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond  /**
282dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond   * Get the current global grid point time.
283dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond   * @return current global grid point time
284dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond   * @since 2.2
285dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond   */
286dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond  public double getGlobalCurrentTime() {
287dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    return globalCurrentTime;
288dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond  }
289dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
290dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond  /**
291dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond   * Get the previous soft grid point time.
292dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond   * @return previous soft grid point time
293dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond   * @see #setSoftPreviousTime(double)
294dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond   */
295dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond  public double getPreviousTime() {
296dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    return softPreviousTime;
297dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond  }
298dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
299dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond  /**
300dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond   * Get the current soft grid point time.
301dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond   * @return current soft grid point time
302dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond   * @see #setSoftCurrentTime(double)
303dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond   */
304dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond  public double getCurrentTime() {
305dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    return softCurrentTime;
306dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond  }
307dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
308dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond  /** {@inheritDoc} */
309dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond  public double getInterpolatedTime() {
310dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    return interpolatedTime;
311dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond  }
312dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
313dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond  /** {@inheritDoc} */
314dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond  public void setInterpolatedTime(final double time) {
315dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      interpolatedTime = time;
316dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      dirtyState       = true;
317dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond  }
318dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
319dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond  /** {@inheritDoc} */
320dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond  public boolean isForward() {
321dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    return forward;
322dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond  }
323dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
324dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond  /** Compute the state and derivatives at the interpolated time.
325dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond   * This is the main processing method that should be implemented by
326dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond   * the derived classes to perform the interpolation.
327dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond   * @param theta normalized interpolation abscissa within the step
328dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond   * (theta is zero at the previous time step and one at the current time step)
329dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond   * @param oneMinusThetaH time gap between the interpolated time and
330dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond   * the current time
331dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond   * @throws DerivativeException this exception is propagated to the caller if the
332dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond   * underlying user function triggers one
333dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond   */
334dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond  protected abstract void computeInterpolatedStateAndDerivatives(double theta,
335dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                                                                 double oneMinusThetaH)
336dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    throws DerivativeException;
337dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
338dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond  /** {@inheritDoc} */
339dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond  public double[] getInterpolatedState() throws DerivativeException {
340dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
341dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      // lazy evaluation of the state
342dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      if (dirtyState) {
343dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond          final double oneMinusThetaH = globalCurrentTime - interpolatedTime;
344dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond          final double theta = (h == 0) ? 0 : (h - oneMinusThetaH) / h;
345dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond          computeInterpolatedStateAndDerivatives(theta, oneMinusThetaH);
346dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond          dirtyState = false;
347dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      }
348dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
349dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      return interpolatedState;
350dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
351dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond  }
352dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
353dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond  /** {@inheritDoc} */
354dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond  public double[] getInterpolatedDerivatives() throws DerivativeException {
355dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
356dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      // lazy evaluation of the state
357dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      if (dirtyState) {
358dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond          final double oneMinusThetaH = globalCurrentTime - interpolatedTime;
359dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond          final double theta = (h == 0) ? 0 : (h - oneMinusThetaH) / h;
360dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond          computeInterpolatedStateAndDerivatives(theta, oneMinusThetaH);
361dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond          dirtyState = false;
362dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      }
363dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
364dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      return interpolatedDerivatives;
365dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
366dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond  }
367dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
368dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond  /**
369dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond   * Finalize the step.
370dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond   *
371dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond   * <p>Some embedded Runge-Kutta integrators need fewer functions
372dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond   * evaluations than their counterpart step interpolators. These
373dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond   * interpolators should perform the last evaluations they need by
374dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond   * themselves only if they need them. This method triggers these
375dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond   * extra evaluations. It can be called directly by the user step
376dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond   * handler and it is called automatically if {@link
377dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond   * #setInterpolatedTime} is called.</p>
378dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond   *
379dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond   * <p>Once this method has been called, <strong>no</strong> other
380dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond   * evaluation will be performed on this step. If there is a need to
381dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond   * have some side effects between the step handler and the
382dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond   * differential equations (for example update some data in the
383dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond   * equations once the step has been done), it is advised to call
384dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond   * this method explicitly from the step handler before these side
385dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond   * effects are set up. If the step handler induces no side effect,
386dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond   * then this method can safely be ignored, it will be called
387dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond   * transparently as needed.</p>
388dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond   *
389dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond   * <p><strong>Warning</strong>: since the step interpolator provided
390dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond   * to the step handler as a parameter of the {@link
391dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond   * StepHandler#handleStep handleStep} is valid only for the duration
392dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond   * of the {@link StepHandler#handleStep handleStep} call, one cannot
393dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond   * simply store a reference and reuse it later. One should first
394dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond   * finalize the instance, then copy this finalized instance into a
395dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond   * new object that can be kept.</p>
396dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond   *
397dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond   * <p>This method calls the protected <code>doFinalize</code> method
398dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond   * if it has never been called during this step and set a flag
399dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond   * indicating that it has been called once. It is the <code>
400dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond   * doFinalize</code> method which should perform the evaluations.
401dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond   * This wrapping prevents from calling <code>doFinalize</code> several
402dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond   * times and hence evaluating the differential equations too often.
403dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond   * Therefore, subclasses are not allowed not reimplement it, they
404dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond   * should rather reimplement <code>doFinalize</code>.</p>
405dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond   *
406dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond   * @throws DerivativeException this exception is propagated to the
407dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond   * caller if the underlying user function triggers one
408dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond   */
409dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond  public final void finalizeStep()
410dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    throws DerivativeException {
411dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    if (! finalized) {
412dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      doFinalize();
413dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      finalized = true;
414dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    }
415dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond  }
416dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
417dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond  /**
418dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond   * Really finalize the step.
419dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond   * The default implementation of this method does nothing.
420dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond   * @throws DerivativeException this exception is propagated to the
421dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond   * caller if the underlying user function triggers one
422dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond   */
423dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond  protected void doFinalize()
424dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    throws DerivativeException {
425dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond  }
426dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
427dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond  /** {@inheritDoc} */
428dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond  public abstract void writeExternal(ObjectOutput out)
429dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    throws IOException;
430dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
431dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond  /** {@inheritDoc} */
432dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond  public abstract void readExternal(ObjectInput in)
433dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    throws IOException, ClassNotFoundException;
434dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
435dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond  /** Save the base state of the instance.
436dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond   * This method performs step finalization if it has not been done
437dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond   * before.
438dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond   * @param out stream where to save the state
439dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond   * @exception IOException in case of write error
440dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond   */
441dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond  protected void writeBaseExternal(final ObjectOutput out)
442dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    throws IOException {
443dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
444dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    if (currentState == null) {
445dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        out.writeInt(-1);
446dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    } else {
447dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        out.writeInt(currentState.length);
448dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    }
449dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    out.writeDouble(globalPreviousTime);
450dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    out.writeDouble(globalCurrentTime);
451dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    out.writeDouble(softPreviousTime);
452dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    out.writeDouble(softCurrentTime);
453dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    out.writeDouble(h);
454dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    out.writeBoolean(forward);
455dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
456dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    if (currentState != null) {
457dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        for (int i = 0; i < currentState.length; ++i) {
458dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            out.writeDouble(currentState[i]);
459dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
460dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    }
461dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
462dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    out.writeDouble(interpolatedTime);
463dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
464dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    // we do not store the interpolated state,
465dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    // it will be recomputed as needed after reading
466dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
467dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    // finalize the step (and don't bother saving the now true flag)
468dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    try {
469dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      finalizeStep();
470dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    } catch (DerivativeException e) {
471dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        IOException ioe = new IOException(e.getLocalizedMessage());
472dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        ioe.initCause(e);
473dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        throw ioe;
474dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    }
475dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
476dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond  }
477dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
478dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond  /** Read the base state of the instance.
479dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond   * This method does <strong>neither</strong> set the interpolated
480dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond   * time nor state. It is up to the derived class to reset it
481dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond   * properly calling the {@link #setInterpolatedTime} method later,
482dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond   * once all rest of the object state has been set up properly.
483dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond   * @param in stream where to read the state from
484dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond   * @return interpolated time be set later by the caller
485dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond   * @exception IOException in case of read error
486dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond   */
487dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond  protected double readBaseExternal(final ObjectInput in)
488dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    throws IOException {
489dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
490dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    final int dimension = in.readInt();
491dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    globalPreviousTime  = in.readDouble();
492dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    globalCurrentTime   = in.readDouble();
493dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    softPreviousTime    = in.readDouble();
494dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    softCurrentTime     = in.readDouble();
495dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    h                   = in.readDouble();
496dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    forward             = in.readBoolean();
497dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    dirtyState          = true;
498dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
499dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    if (dimension < 0) {
500dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        currentState = null;
501dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    } else {
502dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        currentState  = new double[dimension];
503dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        for (int i = 0; i < currentState.length; ++i) {
504dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            currentState[i] = in.readDouble();
505dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
506dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    }
507dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
508dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    // we do NOT handle the interpolated time and state here
509dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    interpolatedTime        = Double.NaN;
510dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    interpolatedState       = (dimension < 0) ? null : new double[dimension];
511dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    interpolatedDerivatives = (dimension < 0) ? null : new double[dimension];
512dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
513dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    finalized = true;
514dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
515dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    return in.readDouble();
516dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
517dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond  }
518dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
519dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond}
520