Interfaces and normalizer for step handling.
This corresponds to a continuous output feature. It basically allow to navigate throughout current step instead of having only discrete grid points. It is a major feature of our ode package. JIRA: MATH-1288
This commit is contained in:
parent
4685d0376a
commit
5c647c12e6
|
@ -0,0 +1,69 @@
|
||||||
|
/*
|
||||||
|
* 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.math3.ode.sampling;
|
||||||
|
|
||||||
|
import org.apache.commons.math3.RealFieldElement;
|
||||||
|
import org.apache.commons.math3.ode.FieldODEStateAndDerivative;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This interface represents a handler that should be called after
|
||||||
|
* each successful fixed step.
|
||||||
|
|
||||||
|
* <p>This interface should be implemented by anyone who is interested
|
||||||
|
* in getting the solution of an ordinary differential equation at
|
||||||
|
* fixed time steps. Objects implementing this interface should be
|
||||||
|
* wrapped within an instance of {@link FieldStepNormalizer} that itself
|
||||||
|
* is used as the general {@link FieldStepHandler} by the integrator. The
|
||||||
|
* {@link FieldStepNormalizer} object is called according to the integrator
|
||||||
|
* internal algorithms and it calls objects implementing this
|
||||||
|
* interface as necessary at fixed time steps.</p>
|
||||||
|
*
|
||||||
|
* @see FieldStepHandler
|
||||||
|
* @see FieldStepNormalizer
|
||||||
|
* @see FieldStepInterpolator
|
||||||
|
* @param <T> the type of the field elements
|
||||||
|
* @since 3.6
|
||||||
|
*/
|
||||||
|
|
||||||
|
public interface FieldFixedStepHandler<T extends RealFieldElement<T>> {
|
||||||
|
|
||||||
|
/** Initialize step handler at the start of an ODE integration.
|
||||||
|
* <p>
|
||||||
|
* This method is called once at the start of the integration. It
|
||||||
|
* may be used by the step handler to initialize some internal data
|
||||||
|
* if needed.
|
||||||
|
* </p>
|
||||||
|
* @param initialState initial time, state vector and derivative
|
||||||
|
* @param finalTime target time for the integration
|
||||||
|
*/
|
||||||
|
void init(FieldODEStateAndDerivative<T> initialState, T finalTime);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle the last accepted step
|
||||||
|
* @param state current value of the independent <i>time</i> variable,
|
||||||
|
* state vector and derivative
|
||||||
|
* For efficiency purposes, the {@link FieldStepNormalizer} class reuses
|
||||||
|
* the same array 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 complete array of all
|
||||||
|
* steps), it should build a local copy store this copy.
|
||||||
|
* @param isLast true if the step is the last one
|
||||||
|
*/
|
||||||
|
void handleStep(FieldODEStateAndDerivative<T> state, boolean isLast);
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,75 @@
|
||||||
|
/*
|
||||||
|
* 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.math3.ode.sampling;
|
||||||
|
|
||||||
|
import org.apache.commons.math3.RealFieldElement;
|
||||||
|
import org.apache.commons.math3.exception.MaxCountExceededException;
|
||||||
|
import org.apache.commons.math3.ode.FieldODEStateAndDerivative;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This interface represents a handler that should be called after
|
||||||
|
* each successful step.
|
||||||
|
*
|
||||||
|
* <p>The ODE integrators compute the evolution of the state vector at
|
||||||
|
* some grid points that depend on their own internal algorithm. Once
|
||||||
|
* they have found a new grid point (possibly after having computed
|
||||||
|
* several evaluation of the derivative at intermediate points), they
|
||||||
|
* provide it to objects implementing this interface. These objects
|
||||||
|
* typically either ignore the intermediate steps and wait for the
|
||||||
|
* last one, store the points in an ephemeris, or forward them to
|
||||||
|
* specialized processing or output methods.</p>
|
||||||
|
*
|
||||||
|
* @see org.apache.commons.math3.ode.FieldFirstOrderIntegrator
|
||||||
|
* @see FieldStepInterpolator
|
||||||
|
* @param <T> the type of the field elements
|
||||||
|
* @since 3.6
|
||||||
|
*/
|
||||||
|
|
||||||
|
public interface FieldStepHandler<T extends RealFieldElement<T>> {
|
||||||
|
|
||||||
|
/** Initialize step handler at the start of an ODE integration.
|
||||||
|
* <p>
|
||||||
|
* This method is called once at the start of the integration. It
|
||||||
|
* may be used by the step handler to initialize some internal data
|
||||||
|
* if needed.
|
||||||
|
* </p>
|
||||||
|
* @param initialState initial time, state vector and derivative
|
||||||
|
* @param finalTime target time for the integration
|
||||||
|
*/
|
||||||
|
void init(FieldODEStateAndDerivative<T> initialState, T finalTime);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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, as the
|
||||||
|
* {@link org.apache.commons.math3.ode.ContinuousOutputModel
|
||||||
|
* ContinuousOutputModel} class does), it should build a local copy
|
||||||
|
* using the clone method of the interpolator and store this copy.
|
||||||
|
* Keeping only a reference to the interpolator and reusing it will
|
||||||
|
* result in unpredictable behavior (potentially crashing the application).
|
||||||
|
* @param isLast true if the step is the last one
|
||||||
|
* @exception MaxCountExceededException if the interpolator throws one because
|
||||||
|
* the number of functions evaluations is exceeded
|
||||||
|
*/
|
||||||
|
void handleStep(FieldStepInterpolator<T> interpolator, boolean isLast)
|
||||||
|
throws MaxCountExceededException;
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,78 @@
|
||||||
|
/*
|
||||||
|
* 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.math3.ode.sampling;
|
||||||
|
|
||||||
|
import java.io.Externalizable;
|
||||||
|
|
||||||
|
import org.apache.commons.math3.RealFieldElement;
|
||||||
|
import org.apache.commons.math3.ode.FieldODEStateAndDerivative;
|
||||||
|
|
||||||
|
/** This interface represents an interpolator over the last step
|
||||||
|
* during an ODE integration.
|
||||||
|
*
|
||||||
|
* <p>The various ODE integrators provide objects implementing this
|
||||||
|
* interface to the step handlers. These objects are often custom
|
||||||
|
* objects tightly bound to the integrator internal algorithms. The
|
||||||
|
* handlers can use these objects to retrieve the state vector at
|
||||||
|
* intermediate times between the previous and the current grid points
|
||||||
|
* (this feature is often called dense output).</p>
|
||||||
|
*
|
||||||
|
* @param <T> the type of the field elements
|
||||||
|
* @see org.apache.commons.math3.ode.FieldFirstOrderIntegrator
|
||||||
|
* @see FieldStepHandler
|
||||||
|
* @since 3.6
|
||||||
|
*/
|
||||||
|
|
||||||
|
public interface FieldStepInterpolator<T extends RealFieldElement<T>> extends Externalizable {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the state at previous grid point time.
|
||||||
|
* @return state at previous grid point time
|
||||||
|
*/
|
||||||
|
FieldODEStateAndDerivative<T> getPreviousState();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the state at current grid point time.
|
||||||
|
* @return state at current grid point time
|
||||||
|
*/
|
||||||
|
FieldODEStateAndDerivative<T> getCurrentState();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the state at interpolated time.
|
||||||
|
* <p>Setting the time outside of the current step is allowed, but
|
||||||
|
* should be used with care since the accuracy of the interpolator will
|
||||||
|
* probably be very poor far from this step. This allowance has been
|
||||||
|
* added to simplify implementation of search algorithms near the
|
||||||
|
* step endpoints.</p>
|
||||||
|
* @param time time of the interpolated point
|
||||||
|
* @return state at interpolated time
|
||||||
|
*/
|
||||||
|
FieldODEStateAndDerivative<T> getInterpolatedState(T time);
|
||||||
|
|
||||||
|
/** Check if the natural integration direction is forward.
|
||||||
|
* <p>This method provides the integration direction as specified by
|
||||||
|
* the integrator itself, it avoid some nasty problems in
|
||||||
|
* degenerated cases like null steps due to cancellation at step
|
||||||
|
* initialization, step control or discrete events
|
||||||
|
* triggering.</p>
|
||||||
|
* @return true if the integration variable (time) increases during
|
||||||
|
* integration
|
||||||
|
*/
|
||||||
|
boolean isForward();
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,272 @@
|
||||||
|
/*
|
||||||
|
* 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.math3.ode.sampling;
|
||||||
|
|
||||||
|
import org.apache.commons.math3.RealFieldElement;
|
||||||
|
import org.apache.commons.math3.exception.MaxCountExceededException;
|
||||||
|
import org.apache.commons.math3.ode.FieldODEStateAndDerivative;
|
||||||
|
import org.apache.commons.math3.util.FastMath;
|
||||||
|
import org.apache.commons.math3.util.Precision;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class wraps an object implementing {@link FieldFixedStepHandler}
|
||||||
|
* into a {@link FieldStepHandler}.
|
||||||
|
|
||||||
|
* <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
|
||||||
|
* FieldFixedStepHandler#handleStep handleStep} method of the underlying
|
||||||
|
* {@link FieldFixedStepHandler} object is called at normalized times. The
|
||||||
|
* normalized times can be influenced by the {@link StepNormalizerMode} and
|
||||||
|
* {@link StepNormalizerBounds}.</p>
|
||||||
|
*
|
||||||
|
* <p>There is no constraint on the integrator, it can use any time step
|
||||||
|
* it needs (time steps longer or shorter than the fixed time step and
|
||||||
|
* non-integer ratios are all allowed).</p>
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* <table border="1" align="center">
|
||||||
|
* <tr BGCOLOR="#CCCCFF"><td colspan=6><font size="+2">Examples (step size = 0.5)</font></td></tr>
|
||||||
|
* <tr BGCOLOR="#EEEEFF"><font size="+1"><td>Start time</td><td>End time</td>
|
||||||
|
* <td>Direction</td><td>{@link StepNormalizerMode Mode}</td>
|
||||||
|
* <td>{@link StepNormalizerBounds Bounds}</td><td>Output</td></font></tr>
|
||||||
|
* <tr><td>0.3</td><td>3.1</td><td>forward</td><td>{@link StepNormalizerMode#INCREMENT INCREMENT}</td><td>{@link StepNormalizerBounds#NEITHER NEITHER}</td><td>0.8, 1.3, 1.8, 2.3, 2.8</td></tr>
|
||||||
|
* <tr><td>0.3</td><td>3.1</td><td>forward</td><td>{@link StepNormalizerMode#INCREMENT INCREMENT}</td><td>{@link StepNormalizerBounds#FIRST FIRST}</td><td>0.3, 0.8, 1.3, 1.8, 2.3, 2.8</td></tr>
|
||||||
|
* <tr><td>0.3</td><td>3.1</td><td>forward</td><td>{@link StepNormalizerMode#INCREMENT INCREMENT}</td><td>{@link StepNormalizerBounds#LAST LAST}</td><td>0.8, 1.3, 1.8, 2.3, 2.8, 3.1</td></tr>
|
||||||
|
* <tr><td>0.3</td><td>3.1</td><td>forward</td><td>{@link StepNormalizerMode#INCREMENT INCREMENT}</td><td>{@link StepNormalizerBounds#BOTH BOTH}</td><td>0.3, 0.8, 1.3, 1.8, 2.3, 2.8, 3.1</td></tr>
|
||||||
|
* <tr><td>0.3</td><td>3.1</td><td>forward</td><td>{@link StepNormalizerMode#MULTIPLES MULTIPLES}</td><td>{@link StepNormalizerBounds#NEITHER NEITHER}</td><td>0.5, 1.0, 1.5, 2.0, 2.5, 3.0</td></tr>
|
||||||
|
* <tr><td>0.3</td><td>3.1</td><td>forward</td><td>{@link StepNormalizerMode#MULTIPLES MULTIPLES}</td><td>{@link StepNormalizerBounds#FIRST FIRST}</td><td>0.3, 0.5, 1.0, 1.5, 2.0, 2.5, 3.0</td></tr>
|
||||||
|
* <tr><td>0.3</td><td>3.1</td><td>forward</td><td>{@link StepNormalizerMode#MULTIPLES MULTIPLES}</td><td>{@link StepNormalizerBounds#LAST LAST}</td><td>0.5, 1.0, 1.5, 2.0, 2.5, 3.0, 3.1</td></tr>
|
||||||
|
* <tr><td>0.3</td><td>3.1</td><td>forward</td><td>{@link StepNormalizerMode#MULTIPLES MULTIPLES}</td><td>{@link StepNormalizerBounds#BOTH BOTH}</td><td>0.3, 0.5, 1.0, 1.5, 2.0, 2.5, 3.0, 3.1</td></tr>
|
||||||
|
* <tr><td>0.0</td><td>3.0</td><td>forward</td><td>{@link StepNormalizerMode#INCREMENT INCREMENT}</td><td>{@link StepNormalizerBounds#NEITHER NEITHER}</td><td>0.5, 1.0, 1.5, 2.0, 2.5, 3.0</td></tr>
|
||||||
|
* <tr><td>0.0</td><td>3.0</td><td>forward</td><td>{@link StepNormalizerMode#INCREMENT INCREMENT}</td><td>{@link StepNormalizerBounds#FIRST FIRST}</td><td>0.0, 0.5, 1.0, 1.5, 2.0, 2.5, 3.0</td></tr>
|
||||||
|
* <tr><td>0.0</td><td>3.0</td><td>forward</td><td>{@link StepNormalizerMode#INCREMENT INCREMENT}</td><td>{@link StepNormalizerBounds#LAST LAST}</td><td>0.5, 1.0, 1.5, 2.0, 2.5, 3.0</td></tr>
|
||||||
|
* <tr><td>0.0</td><td>3.0</td><td>forward</td><td>{@link StepNormalizerMode#INCREMENT INCREMENT}</td><td>{@link StepNormalizerBounds#BOTH BOTH}</td><td>0.0, 0.5, 1.0, 1.5, 2.0, 2.5, 3.0</td></tr>
|
||||||
|
* <tr><td>0.0</td><td>3.0</td><td>forward</td><td>{@link StepNormalizerMode#MULTIPLES MULTIPLES}</td><td>{@link StepNormalizerBounds#NEITHER NEITHER}</td><td>0.5, 1.0, 1.5, 2.0, 2.5, 3.0</td></tr>
|
||||||
|
* <tr><td>0.0</td><td>3.0</td><td>forward</td><td>{@link StepNormalizerMode#MULTIPLES MULTIPLES}</td><td>{@link StepNormalizerBounds#FIRST FIRST}</td><td>0.0, 0.5, 1.0, 1.5, 2.0, 2.5, 3.0</td></tr>
|
||||||
|
* <tr><td>0.0</td><td>3.0</td><td>forward</td><td>{@link StepNormalizerMode#MULTIPLES MULTIPLES}</td><td>{@link StepNormalizerBounds#LAST LAST}</td><td>0.5, 1.0, 1.5, 2.0, 2.5, 3.0</td></tr>
|
||||||
|
* <tr><td>0.0</td><td>3.0</td><td>forward</td><td>{@link StepNormalizerMode#MULTIPLES MULTIPLES}</td><td>{@link StepNormalizerBounds#BOTH BOTH}</td><td>0.0, 0.5, 1.0, 1.5, 2.0, 2.5, 3.0</td></tr>
|
||||||
|
* <tr><td>3.1</td><td>0.3</td><td>backward</td><td>{@link StepNormalizerMode#INCREMENT INCREMENT}</td><td>{@link StepNormalizerBounds#NEITHER NEITHER}</td><td>2.6, 2.1, 1.6, 1.1, 0.6</td></tr>
|
||||||
|
* <tr><td>3.1</td><td>0.3</td><td>backward</td><td>{@link StepNormalizerMode#INCREMENT INCREMENT}</td><td>{@link StepNormalizerBounds#FIRST FIRST}</td><td>3.1, 2.6, 2.1, 1.6, 1.1, 0.6</td></tr>
|
||||||
|
* <tr><td>3.1</td><td>0.3</td><td>backward</td><td>{@link StepNormalizerMode#INCREMENT INCREMENT}</td><td>{@link StepNormalizerBounds#LAST LAST}</td><td>2.6, 2.1, 1.6, 1.1, 0.6, 0.3</td></tr>
|
||||||
|
* <tr><td>3.1</td><td>0.3</td><td>backward</td><td>{@link StepNormalizerMode#INCREMENT INCREMENT}</td><td>{@link StepNormalizerBounds#BOTH BOTH}</td><td>3.1, 2.6, 2.1, 1.6, 1.1, 0.6, 0.3</td></tr>
|
||||||
|
* <tr><td>3.1</td><td>0.3</td><td>backward</td><td>{@link StepNormalizerMode#MULTIPLES MULTIPLES}</td><td>{@link StepNormalizerBounds#NEITHER NEITHER}</td><td>3.0, 2.5, 2.0, 1.5, 1.0, 0.5</td></tr>
|
||||||
|
* <tr><td>3.1</td><td>0.3</td><td>backward</td><td>{@link StepNormalizerMode#MULTIPLES MULTIPLES}</td><td>{@link StepNormalizerBounds#FIRST FIRST}</td><td>3.1, 3.0, 2.5, 2.0, 1.5, 1.0, 0.5</td></tr>
|
||||||
|
* <tr><td>3.1</td><td>0.3</td><td>backward</td><td>{@link StepNormalizerMode#MULTIPLES MULTIPLES}</td><td>{@link StepNormalizerBounds#LAST LAST}</td><td>3.0, 2.5, 2.0, 1.5, 1.0, 0.5, 0.3</td></tr>
|
||||||
|
* <tr><td>3.1</td><td>0.3</td><td>backward</td><td>{@link StepNormalizerMode#MULTIPLES MULTIPLES}</td><td>{@link StepNormalizerBounds#BOTH BOTH}</td><td>3.1, 3.0, 2.5, 2.0, 1.5, 1.0, 0.5, 0.3</td></tr>
|
||||||
|
* <tr><td>3.0</td><td>0.0</td><td>backward</td><td>{@link StepNormalizerMode#INCREMENT INCREMENT}</td><td>{@link StepNormalizerBounds#NEITHER NEITHER}</td><td>2.5, 2.0, 1.5, 1.0, 0.5, 0.0</td></tr>
|
||||||
|
* <tr><td>3.0</td><td>0.0</td><td>backward</td><td>{@link StepNormalizerMode#INCREMENT INCREMENT}</td><td>{@link StepNormalizerBounds#FIRST FIRST}</td><td>3.0, 2.5, 2.0, 1.5, 1.0, 0.5, 0.0</td></tr>
|
||||||
|
* <tr><td>3.0</td><td>0.0</td><td>backward</td><td>{@link StepNormalizerMode#INCREMENT INCREMENT}</td><td>{@link StepNormalizerBounds#LAST LAST}</td><td>2.5, 2.0, 1.5, 1.0, 0.5, 0.0</td></tr>
|
||||||
|
* <tr><td>3.0</td><td>0.0</td><td>backward</td><td>{@link StepNormalizerMode#INCREMENT INCREMENT}</td><td>{@link StepNormalizerBounds#BOTH BOTH}</td><td>3.0, 2.5, 2.0, 1.5, 1.0, 0.5, 0.0</td></tr>
|
||||||
|
* <tr><td>3.0</td><td>0.0</td><td>backward</td><td>{@link StepNormalizerMode#MULTIPLES MULTIPLES}</td><td>{@link StepNormalizerBounds#NEITHER NEITHER}</td><td>2.5, 2.0, 1.5, 1.0, 0.5, 0.0</td></tr>
|
||||||
|
* <tr><td>3.0</td><td>0.0</td><td>backward</td><td>{@link StepNormalizerMode#MULTIPLES MULTIPLES}</td><td>{@link StepNormalizerBounds#FIRST FIRST}</td><td>3.0, 2.5, 2.0, 1.5, 1.0, 0.5, 0.0</td></tr>
|
||||||
|
* <tr><td>3.0</td><td>0.0</td><td>backward</td><td>{@link StepNormalizerMode#MULTIPLES MULTIPLES}</td><td>{@link StepNormalizerBounds#LAST LAST}</td><td>2.5, 2.0, 1.5, 1.0, 0.5, 0.0</td></tr>
|
||||||
|
* <tr><td>3.0</td><td>0.0</td><td>backward</td><td>{@link StepNormalizerMode#MULTIPLES MULTIPLES}</td><td>{@link StepNormalizerBounds#BOTH BOTH}</td><td>3.0, 2.5, 2.0, 1.5, 1.0, 0.5, 0.0</td></tr>
|
||||||
|
* </table>
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @param <T> the type of the field elements
|
||||||
|
* @see FieldStepHandler
|
||||||
|
* @see FieldFixedStepHandler
|
||||||
|
* @see StepNormalizerMode
|
||||||
|
* @see StepNormalizerBounds
|
||||||
|
* @since 3.6
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class FieldStepNormalizer<T extends RealFieldElement<T>> implements FieldStepHandler<T> {
|
||||||
|
/** Fixed time step. */
|
||||||
|
private double h;
|
||||||
|
|
||||||
|
/** Underlying step handler. */
|
||||||
|
private final FieldFixedStepHandler<T> handler;
|
||||||
|
|
||||||
|
/** First step state. */
|
||||||
|
private FieldODEStateAndDerivative<T> first;
|
||||||
|
|
||||||
|
/** Last step step. */
|
||||||
|
private FieldODEStateAndDerivative<T> last;
|
||||||
|
|
||||||
|
/** Integration direction indicator. */
|
||||||
|
private boolean forward;
|
||||||
|
|
||||||
|
/** The step normalizer bounds settings to use. */
|
||||||
|
private final StepNormalizerBounds bounds;
|
||||||
|
|
||||||
|
/** The step normalizer mode to use. */
|
||||||
|
private final StepNormalizerMode mode;
|
||||||
|
|
||||||
|
/** Simple constructor. Uses {@link StepNormalizerMode#INCREMENT INCREMENT}
|
||||||
|
* mode, and {@link StepNormalizerBounds#FIRST FIRST} bounds setting, for
|
||||||
|
* backwards compatibility.
|
||||||
|
* @param h fixed time step (sign is not used)
|
||||||
|
* @param handler fixed time step handler to wrap
|
||||||
|
*/
|
||||||
|
public FieldStepNormalizer(final double h, final FieldFixedStepHandler<T> handler) {
|
||||||
|
this(h, handler, StepNormalizerMode.INCREMENT,
|
||||||
|
StepNormalizerBounds.FIRST);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Simple constructor. Uses {@link StepNormalizerBounds#FIRST FIRST}
|
||||||
|
* bounds setting.
|
||||||
|
* @param h fixed time step (sign is not used)
|
||||||
|
* @param handler fixed time step handler to wrap
|
||||||
|
* @param mode step normalizer mode to use
|
||||||
|
* @since 3.0
|
||||||
|
*/
|
||||||
|
public FieldStepNormalizer(final double h, final FieldFixedStepHandler<T> handler,
|
||||||
|
final StepNormalizerMode mode) {
|
||||||
|
this(h, handler, mode, StepNormalizerBounds.FIRST);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Simple constructor. Uses {@link StepNormalizerMode#INCREMENT INCREMENT}
|
||||||
|
* mode.
|
||||||
|
* @param h fixed time step (sign is not used)
|
||||||
|
* @param handler fixed time step handler to wrap
|
||||||
|
* @param bounds step normalizer bounds setting to use
|
||||||
|
* @since 3.0
|
||||||
|
*/
|
||||||
|
public FieldStepNormalizer(final double h, final FieldFixedStepHandler<T> handler,
|
||||||
|
final StepNormalizerBounds bounds) {
|
||||||
|
this(h, handler, StepNormalizerMode.INCREMENT, bounds);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Simple constructor.
|
||||||
|
* @param h fixed time step (sign is not used)
|
||||||
|
* @param handler fixed time step handler to wrap
|
||||||
|
* @param mode step normalizer mode to use
|
||||||
|
* @param bounds step normalizer bounds setting to use
|
||||||
|
* @since 3.0
|
||||||
|
*/
|
||||||
|
public FieldStepNormalizer(final double h, final FieldFixedStepHandler<T> handler,
|
||||||
|
final StepNormalizerMode mode, final StepNormalizerBounds bounds) {
|
||||||
|
this.h = FastMath.abs(h);
|
||||||
|
this.handler = handler;
|
||||||
|
this.mode = mode;
|
||||||
|
this.bounds = bounds;
|
||||||
|
first = null;
|
||||||
|
last = null;
|
||||||
|
forward = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** {@inheritDoc} */
|
||||||
|
public void init(final FieldODEStateAndDerivative<T> initialState, final T finalTime) {
|
||||||
|
|
||||||
|
first = null;
|
||||||
|
last = null;
|
||||||
|
forward = true;
|
||||||
|
|
||||||
|
// initialize the underlying handler
|
||||||
|
handler.init(initialState, finalTime);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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
|
||||||
|
* @exception MaxCountExceededException if the interpolator throws one because
|
||||||
|
* the number of functions evaluations is exceeded
|
||||||
|
*/
|
||||||
|
public void handleStep(final FieldStepInterpolator<T> interpolator, final boolean isLast)
|
||||||
|
throws MaxCountExceededException {
|
||||||
|
// The first time, update the last state with the start information.
|
||||||
|
if (last == null) {
|
||||||
|
|
||||||
|
first = interpolator.getPreviousState();
|
||||||
|
last = first;
|
||||||
|
|
||||||
|
// Take the integration direction into account.
|
||||||
|
forward = interpolator.isForward();
|
||||||
|
if (!forward) {
|
||||||
|
h = -h;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calculate next normalized step time.
|
||||||
|
T nextTime = (mode == StepNormalizerMode.INCREMENT) ?
|
||||||
|
last.getTime().add(h) :
|
||||||
|
last.getTime().getField().getZero().add((FastMath.floor(last.getTime().getReal() / h) + 1) * h);
|
||||||
|
if (mode == StepNormalizerMode.MULTIPLES &&
|
||||||
|
Precision.equals(nextTime.getReal(), last.getTime().getReal(), 1)) {
|
||||||
|
nextTime = nextTime.add(h);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Process normalized steps as long as they are in the current step.
|
||||||
|
boolean nextInStep = isNextInStep(nextTime, interpolator);
|
||||||
|
while (nextInStep) {
|
||||||
|
// Output the stored previous step.
|
||||||
|
doNormalizedStep(false);
|
||||||
|
|
||||||
|
// Store the next step as last step.
|
||||||
|
last = interpolator.getInterpolatedState(nextTime);
|
||||||
|
|
||||||
|
// Move on to the next step.
|
||||||
|
nextTime = nextTime.add(h);
|
||||||
|
nextInStep = isNextInStep(nextTime, interpolator);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isLast) {
|
||||||
|
// There will be no more steps. The stored one should be given to
|
||||||
|
// the handler. We may have to output one more step. Only the last
|
||||||
|
// one of those should be flagged as being the last.
|
||||||
|
final boolean addLast = bounds.lastIncluded() &&
|
||||||
|
last.getTime().getReal() != interpolator.getCurrentState().getTime().getReal();
|
||||||
|
doNormalizedStep(!addLast);
|
||||||
|
if (addLast) {
|
||||||
|
last = interpolator.getCurrentState();
|
||||||
|
doNormalizedStep(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a value indicating whether the next normalized time is in the
|
||||||
|
* current step.
|
||||||
|
* @param nextTime the next normalized time
|
||||||
|
* @param interpolator interpolator for the last accepted step, to use to
|
||||||
|
* get the end time of the current step
|
||||||
|
* @return value indicating whether the next normalized time is in the
|
||||||
|
* current step
|
||||||
|
*/
|
||||||
|
private boolean isNextInStep(final T nextTime, final FieldStepInterpolator<T> interpolator) {
|
||||||
|
return forward ?
|
||||||
|
nextTime.getReal() <= interpolator.getCurrentState().getTime().getReal() :
|
||||||
|
nextTime.getReal() >= interpolator.getCurrentState().getTime().getReal();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Invokes the underlying step handler for the current normalized step.
|
||||||
|
* @param isLast true if the step is the last one
|
||||||
|
*/
|
||||||
|
private void doNormalizedStep(final boolean isLast) {
|
||||||
|
if (!bounds.firstIncluded() && first.getTime().getReal() == last.getTime().getReal()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
handler.handleStep(last, isLast);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -22,6 +22,7 @@ package org.apache.commons.math3.ode.sampling;
|
||||||
* and last points. Note that if the last point coincides with a normalized
|
* and last points. Note that if the last point coincides with a normalized
|
||||||
* point, then the underlying fixed step size step handler is always called,
|
* point, then the underlying fixed step size step handler is always called,
|
||||||
* regardless of these settings.
|
* regardless of these settings.
|
||||||
|
* @see FieldStepNormalizer
|
||||||
* @see StepNormalizer
|
* @see StepNormalizer
|
||||||
* @see StepNormalizerMode
|
* @see StepNormalizerMode
|
||||||
* @since 3.0
|
* @since 3.0
|
||||||
|
|
|
@ -20,6 +20,7 @@ package org.apache.commons.math3.ode.sampling;
|
||||||
|
|
||||||
/** {@link StepNormalizer Step normalizer} modes. Determines how the step size
|
/** {@link StepNormalizer Step normalizer} modes. Determines how the step size
|
||||||
* is interpreted.
|
* is interpreted.
|
||||||
|
* @see FieldStepNormalizer
|
||||||
* @see StepNormalizer
|
* @see StepNormalizer
|
||||||
* @see StepNormalizerBounds
|
* @see StepNormalizerBounds
|
||||||
* @since 3.0
|
* @since 3.0
|
||||||
|
|
Loading…
Reference in New Issue