RungeKuttaStepInterpolator.java
- /*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- package org.apache.commons.math4.legacy.ode.nonstiff;
- import java.io.IOException;
- import java.io.ObjectInput;
- import java.io.ObjectOutput;
- import org.apache.commons.math4.legacy.ode.AbstractIntegrator;
- import org.apache.commons.math4.legacy.ode.EquationsMapper;
- import org.apache.commons.math4.legacy.ode.sampling.AbstractStepInterpolator;
- /** This class represents an interpolator over the last step during an
- * ODE integration for Runge-Kutta and embedded Runge-Kutta integrators.
- *
- * @see RungeKuttaIntegrator
- * @see EmbeddedRungeKuttaIntegrator
- *
- * @since 1.2
- */
- abstract class RungeKuttaStepInterpolator
- extends AbstractStepInterpolator {
- /** Previous state. */
- protected double[] previousState;
- /** Slopes at the intermediate points. */
- protected double[][] yDotK;
- /** Reference to the integrator. */
- protected AbstractIntegrator integrator;
- /** Simple constructor.
- * This constructor builds an instance that is not usable yet, the
- * {@link #reinitialize} method should be called before using the
- * instance in order to initialize the internal arrays. This
- * constructor is used only in order to delay the initialization in
- * some cases. The {@link RungeKuttaIntegrator} and {@link
- * EmbeddedRungeKuttaIntegrator} classes use the prototyping design
- * pattern to create the step interpolators by cloning an
- * uninitialized model and latter initializing the copy.
- */
- protected RungeKuttaStepInterpolator() {
- previousState = null;
- yDotK = null;
- integrator = null;
- }
- /** Copy constructor.
- * <p>The copied interpolator should have been finalized before the
- * copy, otherwise the copy will not be able to perform correctly any
- * interpolation and will throw a {@link NullPointerException}
- * later. Since we don't want this constructor to throw the
- * exceptions finalization may involve and since we don't want this
- * method to modify the state of the copied interpolator,
- * finalization is <strong>not</strong> done automatically, it
- * remains under user control.</p>
- * <p>The copy is a deep copy: its arrays are separated from the
- * original arrays of the instance.</p>
- * @param interpolator interpolator to copy from.
- */
- RungeKuttaStepInterpolator(final RungeKuttaStepInterpolator interpolator) {
- super(interpolator);
- if (interpolator.currentState != null) {
- previousState = interpolator.previousState.clone();
- yDotK = new double[interpolator.yDotK.length][];
- for (int k = 0; k < interpolator.yDotK.length; ++k) {
- yDotK[k] = interpolator.yDotK[k].clone();
- }
- } else {
- previousState = null;
- yDotK = null;
- }
- // we cannot keep any reference to the equations in the copy
- // the interpolator should have been finalized before
- integrator = null;
- }
- /** Reinitialize the instance
- * <p>Some Runge-Kutta integrators need fewer functions evaluations
- * than their counterpart step interpolators. So the interpolator
- * should perform the last evaluations they need by themselves. The
- * {@link RungeKuttaIntegrator RungeKuttaIntegrator} and {@link
- * EmbeddedRungeKuttaIntegrator EmbeddedRungeKuttaIntegrator}
- * abstract classes call this method in order to let the step
- * interpolator perform the evaluations it needs. These evaluations
- * will be performed during the call to <code>doFinalize</code> if
- * any, i.e. only if the step handler either calls the {@link
- * AbstractStepInterpolator#finalizeStep finalizeStep} method or the
- * {@link AbstractStepInterpolator#getInterpolatedState
- * getInterpolatedState} method (for an interpolator which needs a
- * finalization) or if it clones the step interpolator.</p>
- * @param rkIntegrator integrator being used
- * @param y reference to the integrator array holding the state at
- * the end of the step
- * @param yDotArray reference to the integrator array holding all the
- * intermediate slopes
- * @param forward integration direction indicator
- * @param primaryMapper equations mapper for the primary equations set
- * @param secondaryMappers equations mappers for the secondary equations sets
- */
- public void reinitialize(final AbstractIntegrator rkIntegrator,
- final double[] y, final double[][] yDotArray, final boolean forward,
- final EquationsMapper primaryMapper,
- final EquationsMapper[] secondaryMappers) {
- reinitialize(y, forward, primaryMapper, secondaryMappers);
- this.previousState = null;
- this.yDotK = yDotArray;
- this.integrator = rkIntegrator;
- }
- /** {@inheritDoc} */
- @Override
- public void shift() {
- previousState = currentState.clone();
- super.shift();
- }
- /** {@inheritDoc} */
- @Override
- public void writeExternal(final ObjectOutput out)
- throws IOException {
- // save the state of the base class
- writeBaseExternal(out);
- // save the local attributes
- final int n = (currentState == null) ? -1 : currentState.length;
- for (int i = 0; i < n; ++i) {
- out.writeDouble(previousState[i]);
- }
- final int kMax = (yDotK == null) ? -1 : yDotK.length;
- out.writeInt(kMax);
- for (int k = 0; k < kMax; ++k) {
- for (int i = 0; i < n; ++i) {
- out.writeDouble(yDotK[k][i]);
- }
- }
- // we do not save any reference to the equations
- }
- /** {@inheritDoc} */
- @Override
- public void readExternal(final ObjectInput in)
- throws IOException, ClassNotFoundException {
- // read the base class
- final double t = readBaseExternal(in);
- // read the local attributes
- final int n = (currentState == null) ? -1 : currentState.length;
- if (n < 0) {
- previousState = null;
- } else {
- previousState = new double[n];
- for (int i = 0; i < n; ++i) {
- previousState[i] = in.readDouble();
- }
- }
- final int kMax = in.readInt();
- yDotK = (kMax < 0) ? null : new double[kMax][];
- for (int k = 0; k < kMax; ++k) {
- yDotK[k] = (n < 0) ? null : new double[n];
- for (int i = 0; i < n; ++i) {
- yDotK[k][i] = in.readDouble();
- }
- }
- integrator = null;
- if (currentState != null) {
- // we can now set the interpolated time and state
- setInterpolatedTime(t);
- } else {
- interpolatedTime = t;
- }
- }
- }