summaryrefslogtreecommitdiff
path: root/src/main/java/org/apache/commons/math/ode/sampling/StepNormalizer.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/java/org/apache/commons/math/ode/sampling/StepNormalizer.java')
-rw-r--r--src/main/java/org/apache/commons/math/ode/sampling/StepNormalizer.java161
1 files changed, 161 insertions, 0 deletions
diff --git a/src/main/java/org/apache/commons/math/ode/sampling/StepNormalizer.java b/src/main/java/org/apache/commons/math/ode/sampling/StepNormalizer.java
new file mode 100644
index 0000000..73bcc23
--- /dev/null
+++ b/src/main/java/org/apache/commons/math/ode/sampling/StepNormalizer.java
@@ -0,0 +1,161 @@
+/*
+ * 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.math.ode.sampling;
+
+import org.apache.commons.math.ode.DerivativeException;
+import org.apache.commons.math.util.FastMath;
+
+/**
+ * This class wraps an object implementing {@link FixedStepHandler}
+ * into a {@link StepHandler}.
+
+ * <p>This wrapper allows to use fixed step handlers with general
+ * integrators which cannot guaranty their integration steps will
+ * remain constant and therefore only accept general step
+ * handlers.</p>
+ *
+ * <p>The stepsize used is selected at construction time. The {@link
+ * FixedStepHandler#handleStep handleStep} method of the underlying
+ * {@link FixedStepHandler} object is called at the beginning time of
+ * the integration t0 and also at times t0+h, t0+2h, ... If the
+ * integration range is an integer multiple of the stepsize, then the
+ * last point handled will be the endpoint of the integration tend, if
+ * not, the last point will belong to the interval [tend - h ;
+ * tend].</p>
+ *
+ * <p>There is no constraint on the integrator, it can use any
+ * timestep it needs (time steps longer or shorter than the fixed time
+ * step and non-integer ratios are all allowed).</p>
+ *
+ * @see StepHandler
+ * @see FixedStepHandler
+ * @version $Revision: 1073158 $ $Date: 2011-02-21 22:46:52 +0100 (lun. 21 févr. 2011) $
+ * @since 1.2
+ */
+
+public class StepNormalizer implements StepHandler {
+
+ /** Fixed time step. */
+ private double h;
+
+ /** Underlying step handler. */
+ private final FixedStepHandler handler;
+
+ /** Last step time. */
+ private double lastTime;
+
+ /** Last State vector. */
+ private double[] lastState;
+
+ /** Last Derivatives vector. */
+ private double[] lastDerivatives;
+
+ /** Integration direction indicator. */
+ private boolean forward;
+
+ /** Simple constructor.
+ * @param h fixed time step (sign is not used)
+ * @param handler fixed time step handler to wrap
+ */
+ public StepNormalizer(final double h, final FixedStepHandler handler) {
+ this.h = FastMath.abs(h);
+ this.handler = handler;
+ reset();
+ }
+
+ /** Determines whether this handler needs dense output.
+ * This handler needs dense output in order to provide data at
+ * regularly spaced steps regardless of the steps the integrator
+ * uses, so this method always returns true.
+ * @return always true
+ */
+ public boolean requiresDenseOutput() {
+ return true;
+ }
+
+ /** Reset the step handler.
+ * Initialize the internal data as required before the first step is
+ * handled.
+ */
+ public void reset() {
+ lastTime = Double.NaN;
+ lastState = null;
+ lastDerivatives = null;
+ forward = true;
+ }
+
+ /**
+ * Handle the last accepted step
+ * @param interpolator interpolator for the last accepted step. For
+ * efficiency purposes, the various integrators reuse the same
+ * object on each call, so if the instance wants to keep it across
+ * all calls (for example to provide at the end of the integration a
+ * continuous model valid throughout the integration range), it
+ * should build a local copy using the clone method and store this
+ * copy.
+ * @param isLast true if the step is the last one
+ * @throws DerivativeException this exception is propagated to the
+ * caller if the underlying user function triggers one
+ */
+ public void handleStep(final StepInterpolator interpolator, final boolean isLast)
+ throws DerivativeException {
+
+ if (lastState == null) {
+
+ lastTime = interpolator.getPreviousTime();
+ interpolator.setInterpolatedTime(lastTime);
+ lastState = interpolator.getInterpolatedState().clone();
+ lastDerivatives = interpolator.getInterpolatedDerivatives().clone();
+
+ // take the integration direction into account
+ forward = interpolator.getCurrentTime() >= lastTime;
+ if (! forward) {
+ h = -h;
+ }
+
+ }
+
+ double nextTime = lastTime + h;
+ boolean nextInStep = forward ^ (nextTime > interpolator.getCurrentTime());
+ while (nextInStep) {
+
+ // output the stored previous step
+ handler.handleStep(lastTime, lastState, lastDerivatives, false);
+
+ // store the next step
+ lastTime = nextTime;
+ interpolator.setInterpolatedTime(lastTime);
+ System.arraycopy(interpolator.getInterpolatedState(), 0,
+ lastState, 0, lastState.length);
+ System.arraycopy(interpolator.getInterpolatedDerivatives(), 0,
+ lastDerivatives, 0, lastDerivatives.length);
+
+ nextTime += h;
+ nextInStep = forward ^ (nextTime > interpolator.getCurrentTime());
+
+ }
+
+ if (isLast) {
+ // there will be no more steps,
+ // the stored one should be flagged as being the last
+ handler.handleStep(lastTime, lastState, lastDerivatives, true);
+ }
+
+ }
+
+}