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; 23dee0849a9704d532af0b550146cbafbaa6ee1d19Raymondimport java.util.Arrays; 24dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 25dee0849a9704d532af0b550146cbafbaa6ee1d19Raymondimport org.apache.commons.math.ode.DerivativeException; 26dee0849a9704d532af0b550146cbafbaa6ee1d19Raymondimport org.apache.commons.math.linear.Array2DRowRealMatrix; 27dee0849a9704d532af0b550146cbafbaa6ee1d19Raymondimport org.apache.commons.math.util.FastMath; 28dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 29dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond/** 30dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * This class implements an interpolator for integrators using Nordsieck representation. 31dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * 32dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * <p>This interpolator computes dense output around the current point. 33dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * The interpolation equation is based on Taylor series formulas. 34dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * 35dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @see org.apache.commons.math.ode.nonstiff.AdamsBashforthIntegrator 36dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @see org.apache.commons.math.ode.nonstiff.AdamsMoultonIntegrator 37dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @version $Revision: 1073158 $ $Date: 2011-02-21 22:46:52 +0100 (lun. 21 févr. 2011) $ 38dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @since 2.0 39dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond */ 40dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 41dee0849a9704d532af0b550146cbafbaa6ee1d19Raymondpublic class NordsieckStepInterpolator extends AbstractStepInterpolator { 42dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 43dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond /** Serializable version identifier */ 44dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond private static final long serialVersionUID = -7179861704951334960L; 45dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 46dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond /** State variation. */ 47dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond protected double[] stateVariation; 48dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 49dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond /** Step size used in the first scaled derivative and Nordsieck vector. */ 50dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond private double scalingH; 51dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 52dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond /** Reference time for all arrays. 53dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * <p>Sometimes, the reference time is the same as previousTime, 54dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * sometimes it is the same as currentTime, so we use a separate 55dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * field to avoid any confusion. 56dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * </p> 57dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond */ 58dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond private double referenceTime; 59dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 60dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond /** First scaled derivative. */ 61dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond private double[] scaled; 62dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 63dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond /** Nordsieck vector. */ 64dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond private Array2DRowRealMatrix nordsieck; 65dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 66dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond /** Simple constructor. 67dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * This constructor builds an instance that is not usable yet, the 68dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * {@link AbstractStepInterpolator#reinitialize} method should be called 69dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * before using the instance in order to initialize the internal arrays. This 70dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * constructor is used only in order to delay the initialization in 71dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * some cases. 72dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond */ 73dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond public NordsieckStepInterpolator() { 74dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 75dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 76dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond /** Copy constructor. 77dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @param interpolator interpolator to copy from. The copy is a deep 78dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * copy: its arrays are separated from the original arrays of the 79dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * instance 80dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond */ 81dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond public NordsieckStepInterpolator(final NordsieckStepInterpolator interpolator) { 82dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond super(interpolator); 83dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond scalingH = interpolator.scalingH; 84dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond referenceTime = interpolator.referenceTime; 85dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond if (interpolator.scaled != null) { 86dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond scaled = interpolator.scaled.clone(); 87dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 88dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond if (interpolator.nordsieck != null) { 89dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond nordsieck = new Array2DRowRealMatrix(interpolator.nordsieck.getDataRef(), true); 90dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 91dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond if (interpolator.stateVariation != null) { 92dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond stateVariation = interpolator.stateVariation.clone(); 93dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 94dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 95dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 96dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond /** {@inheritDoc} */ 97dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond @Override 98dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond protected StepInterpolator doCopy() { 99dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond return new NordsieckStepInterpolator(this); 100dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 101dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 102dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond /** Reinitialize the instance. 103dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * <p>Beware that all arrays <em>must</em> be references to integrator 104dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * arrays, in order to ensure proper update without copy.</p> 105dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @param y reference to the integrator array holding the state at 106dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * the end of the step 107dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @param forward integration direction indicator 108dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond */ 109dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond @Override 110dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond public void reinitialize(final double[] y, final boolean forward) { 111dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond super.reinitialize(y, forward); 112dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond stateVariation = new double[y.length]; 113dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 114dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 115dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond /** Reinitialize the instance. 116dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * <p>Beware that all arrays <em>must</em> be references to integrator 117dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * arrays, in order to ensure proper update without copy.</p> 118dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @param time time at which all arrays are defined 119dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @param stepSize step size used in the scaled and nordsieck arrays 120dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @param scaledDerivative reference to the integrator array holding the first 121dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * scaled derivative 122dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @param nordsieckVector reference to the integrator matrix holding the 123dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * nordsieck vector 124dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond */ 125dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond public void reinitialize(final double time, final double stepSize, 126dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond final double[] scaledDerivative, 127dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond final Array2DRowRealMatrix nordsieckVector) { 128dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond this.referenceTime = time; 129dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond this.scalingH = stepSize; 130dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond this.scaled = scaledDerivative; 131dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond this.nordsieck = nordsieckVector; 132dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 133dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond // make sure the state and derivatives will depend on the new arrays 134dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond setInterpolatedTime(getInterpolatedTime()); 135dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 136dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 137dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 138dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond /** Rescale the instance. 139dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * <p>Since the scaled and Nordiseck arrays are shared with the caller, 140dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * this method has the side effect of rescaling this arrays in the caller too.</p> 141dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @param stepSize new step size to use in the scaled and nordsieck arrays 142dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond */ 143dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond public void rescale(final double stepSize) { 144dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 145dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond final double ratio = stepSize / scalingH; 146dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond for (int i = 0; i < scaled.length; ++i) { 147dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond scaled[i] *= ratio; 148dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 149dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 150dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond final double[][] nData = nordsieck.getDataRef(); 151dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond double power = ratio; 152dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond for (int i = 0; i < nData.length; ++i) { 153dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond power *= ratio; 154dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond final double[] nDataI = nData[i]; 155dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond for (int j = 0; j < nDataI.length; ++j) { 156dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond nDataI[j] *= power; 157dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 158dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 159dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 160dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond scalingH = stepSize; 161dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 162dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 163dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 164dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond /** 165dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * Get the state vector variation from current to interpolated state. 166dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * <p>This method is aimed at computing y(t<sub>interpolation</sub>) 167dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * -y(t<sub>current</sub>) accurately by avoiding the cancellation errors 168dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * that would occur if the subtraction were performed explicitly.</p> 169dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * <p>The returned vector is a reference to a reused array, so 170dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * it should not be modified and it should be copied if it needs 171dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * to be preserved across several calls.</p> 172dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @return state vector at time {@link #getInterpolatedTime} 173dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @see #getInterpolatedDerivatives() 174dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @throws DerivativeException if this call induces an automatic 175dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * step finalization that throws one 176dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond */ 177dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond public double[] getInterpolatedStateVariation() 178dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond throws DerivativeException { 179dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond // compute and ignore interpolated state 180dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond // to make sure state variation is computed as a side effect 181dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond getInterpolatedState(); 182dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond return stateVariation; 183dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 184dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 185dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond /** {@inheritDoc} */ 186dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond @Override 187dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond protected void computeInterpolatedStateAndDerivatives(final double theta, final double oneMinusThetaH) { 188dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 189dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond final double x = interpolatedTime - referenceTime; 190dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond final double normalizedAbscissa = x / scalingH; 191dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 192dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond Arrays.fill(stateVariation, 0.0); 193dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond Arrays.fill(interpolatedDerivatives, 0.0); 194dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 195dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond // apply Taylor formula from high order to low order, 196dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond // for the sake of numerical accuracy 197dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond final double[][] nData = nordsieck.getDataRef(); 198dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond for (int i = nData.length - 1; i >= 0; --i) { 199dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond final int order = i + 2; 200dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond final double[] nDataI = nData[i]; 201dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond final double power = FastMath.pow(normalizedAbscissa, order); 202dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond for (int j = 0; j < nDataI.length; ++j) { 203dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond final double d = nDataI[j] * power; 204dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond stateVariation[j] += d; 205dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond interpolatedDerivatives[j] += order * d; 206dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 207dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 208dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 209dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond for (int j = 0; j < currentState.length; ++j) { 210dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond stateVariation[j] += scaled[j] * normalizedAbscissa; 211dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond interpolatedState[j] = currentState[j] + stateVariation[j]; 212dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond interpolatedDerivatives[j] = 213dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond (interpolatedDerivatives[j] + scaled[j] * normalizedAbscissa) / x; 214dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 215dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 216dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 217dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 218dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond /** {@inheritDoc} */ 219dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond @Override 220dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond public void writeExternal(final ObjectOutput out) 221dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond throws IOException { 222dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 223dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond // save the state of the base class 224dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond writeBaseExternal(out); 225dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 226dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond // save the local attributes 227dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond out.writeDouble(scalingH); 228dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond out.writeDouble(referenceTime); 229dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 230dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond final int n = (currentState == null) ? -1 : currentState.length; 231dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond if (scaled == null) { 232dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond out.writeBoolean(false); 233dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } else { 234dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond out.writeBoolean(true); 235dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond for (int j = 0; j < n; ++j) { 236dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond out.writeDouble(scaled[j]); 237dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 238dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 239dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 240dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond if (nordsieck == null) { 241dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond out.writeBoolean(false); 242dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } else { 243dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond out.writeBoolean(true); 244dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond out.writeObject(nordsieck); 245dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 246dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 247dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond // we don't save state variation, it will be recomputed 248dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 249dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 250dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 251dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond /** {@inheritDoc} */ 252dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond @Override 253dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond public void readExternal(final ObjectInput in) 254dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond throws IOException, ClassNotFoundException { 255dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 256dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond // read the base class 257dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond final double t = readBaseExternal(in); 258dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 259dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond // read the local attributes 260dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond scalingH = in.readDouble(); 261dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond referenceTime = in.readDouble(); 262dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 263dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond final int n = (currentState == null) ? -1 : currentState.length; 264dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond final boolean hasScaled = in.readBoolean(); 265dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond if (hasScaled) { 266dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond scaled = new double[n]; 267dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond for (int j = 0; j < n; ++j) { 268dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond scaled[j] = in.readDouble(); 269dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 270dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } else { 271dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond scaled = null; 272dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 273dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 274dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond final boolean hasNordsieck = in.readBoolean(); 275dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond if (hasNordsieck) { 276dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond nordsieck = (Array2DRowRealMatrix) in.readObject(); 277dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } else { 278dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond nordsieck = null; 279dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 280dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 281dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond if (hasScaled && hasNordsieck) { 282dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond // we can now set the interpolated time and state 283dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond stateVariation = new double[n]; 284dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond setInterpolatedTime(t); 285dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } else { 286dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond stateVariation = null; 287dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 288dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 289dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 290dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 291dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond} 292