001/*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements.  See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License.  You may obtain a copy of the License at
008 *
009 *      http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017
018package org.apache.commons.math4.legacy.ode.nonstiff;
019
020import org.apache.commons.math4.legacy.exception.DimensionMismatchException;
021import org.apache.commons.math4.legacy.exception.MaxCountExceededException;
022import org.apache.commons.math4.legacy.exception.NoBracketingException;
023import org.apache.commons.math4.legacy.exception.NumberIsTooSmallException;
024import org.apache.commons.math4.legacy.linear.Array2DRowRealMatrix;
025import org.apache.commons.math4.legacy.ode.ExpandableStatefulODE;
026import org.apache.commons.math4.legacy.ode.MultistepIntegrator;
027
028
029/** Base class for {@link AdamsBashforthIntegrator Adams-Bashforth} and
030 * {@link AdamsMoultonIntegrator Adams-Moulton} integrators.
031 * @since 2.0
032 */
033public abstract class AdamsIntegrator extends MultistepIntegrator {
034
035    /** Transformer. */
036    private final AdamsNordsieckTransformer transformer;
037
038    /**
039     * Build an Adams integrator with the given order and step control parameters.
040     * @param name name of the method
041     * @param nSteps number of steps of the method excluding the one being computed
042     * @param order order of the method
043     * @param minStep minimal step (sign is irrelevant, regardless of
044     * integration direction, forward or backward), the last step can
045     * be smaller than this
046     * @param maxStep maximal step (sign is irrelevant, regardless of
047     * integration direction, forward or backward), the last step can
048     * be smaller than this
049     * @param scalAbsoluteTolerance allowed absolute error
050     * @param scalRelativeTolerance allowed relative error
051     * @exception NumberIsTooSmallException if order is 1 or less
052     */
053    public AdamsIntegrator(final String name, final int nSteps, final int order,
054                           final double minStep, final double maxStep,
055                           final double scalAbsoluteTolerance,
056                           final double scalRelativeTolerance)
057        throws NumberIsTooSmallException {
058        super(name, nSteps, order, minStep, maxStep,
059              scalAbsoluteTolerance, scalRelativeTolerance);
060        transformer = AdamsNordsieckTransformer.getInstance(nSteps);
061    }
062
063    /**
064     * Build an Adams integrator with the given order and step control parameters.
065     * @param name name of the method
066     * @param nSteps number of steps of the method excluding the one being computed
067     * @param order order of the method
068     * @param minStep minimal step (sign is irrelevant, regardless of
069     * integration direction, forward or backward), the last step can
070     * be smaller than this
071     * @param maxStep maximal step (sign is irrelevant, regardless of
072     * integration direction, forward or backward), the last step can
073     * be smaller than this
074     * @param vecAbsoluteTolerance allowed absolute error
075     * @param vecRelativeTolerance allowed relative error
076     * @exception IllegalArgumentException if order is 1 or less
077     */
078    public AdamsIntegrator(final String name, final int nSteps, final int order,
079                           final double minStep, final double maxStep,
080                           final double[] vecAbsoluteTolerance,
081                           final double[] vecRelativeTolerance)
082        throws IllegalArgumentException {
083        super(name, nSteps, order, minStep, maxStep,
084              vecAbsoluteTolerance, vecRelativeTolerance);
085        transformer = AdamsNordsieckTransformer.getInstance(nSteps);
086    }
087
088    /** {@inheritDoc} */
089    @Override
090    public abstract void integrate(ExpandableStatefulODE equations, double t)
091        throws NumberIsTooSmallException, DimensionMismatchException,
092               MaxCountExceededException, NoBracketingException;
093
094    /** {@inheritDoc} */
095    @Override
096    protected Array2DRowRealMatrix initializeHighOrderDerivatives(final double h, final double[] t,
097                                                                  final double[][] y,
098                                                                  final double[][] yDot) {
099        return transformer.initializeHighOrderDerivatives(h, t, y, yDot);
100    }
101
102    /** Update the high order scaled derivatives for Adams integrators (phase 1).
103     * <p>The complete update of high order derivatives has a form similar to:
104     * <div style="white-space: pre"><code>
105     * r<sub>n+1</sub> = (s<sub>1</sub>(n) - s<sub>1</sub>(n+1)) P<sup>-1</sup> u + P<sup>-1</sup> A P r<sub>n</sub>
106     * </code></div>
107     * this method computes the P<sup>-1</sup> A P r<sub>n</sub> part.
108     * @param highOrder high order scaled derivatives
109     * (h<sup>2</sup>/2 y'', ... h<sup>k</sup>/k! y(k))
110     * @return updated high order derivatives
111     * @see #updateHighOrderDerivativesPhase2(double[], double[], Array2DRowRealMatrix)
112     */
113    public Array2DRowRealMatrix updateHighOrderDerivativesPhase1(final Array2DRowRealMatrix highOrder) {
114        return transformer.updateHighOrderDerivativesPhase1(highOrder);
115    }
116
117    /** Update the high order scaled derivatives Adams integrators (phase 2).
118     * <p>The complete update of high order derivatives has a form similar to:
119     * <div style="white-space: pre"><code>
120     * r<sub>n+1</sub> = (s<sub>1</sub>(n) - s<sub>1</sub>(n+1)) P<sup>-1</sup> u + P<sup>-1</sup> A P r<sub>n</sub>
121     * </code></div>
122     * this method computes the (s<sub>1</sub>(n) - s<sub>1</sub>(n+1)) P<sup>-1</sup> u part.
123     * <p>Phase 1 of the update must already have been performed.</p>
124     * @param start first order scaled derivatives at step start
125     * @param end first order scaled derivatives at step end
126     * @param highOrder high order scaled derivatives, will be modified
127     * (h<sup>2</sup>/2 y'', ... h<sup>k</sup>/k! y(k))
128     * @see #updateHighOrderDerivativesPhase1(Array2DRowRealMatrix)
129     */
130    public void updateHighOrderDerivativesPhase2(final double[] start,
131                                                 final double[] end,
132                                                 final Array2DRowRealMatrix highOrder) {
133        transformer.updateHighOrderDerivativesPhase2(start, end, highOrder);
134    }
135}