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    
018    package org.apache.commons.math3.ode.nonstiff;
019    
020    import org.apache.commons.math3.exception.DimensionMismatchException;
021    import org.apache.commons.math3.exception.MaxCountExceededException;
022    import org.apache.commons.math3.exception.NoBracketingException;
023    import org.apache.commons.math3.exception.NumberIsTooSmallException;
024    import org.apache.commons.math3.linear.Array2DRowRealMatrix;
025    import org.apache.commons.math3.ode.ExpandableStatefulODE;
026    import org.apache.commons.math3.ode.MultistepIntegrator;
027    
028    
029    /** Base class for {@link AdamsBashforthIntegrator Adams-Bashforth} and
030     * {@link AdamsMoultonIntegrator Adams-Moulton} integrators.
031     * @version $Id: AdamsIntegrator.java 1416643 2012-12-03 19:37:14Z tn $
032     * @since 2.0
033     */
034    public abstract class AdamsIntegrator extends MultistepIntegrator {
035    
036        /** Transformer. */
037        private final AdamsNordsieckTransformer transformer;
038    
039        /**
040         * Build an Adams integrator with the given order and step control parameters.
041         * @param name name of the method
042         * @param nSteps number of steps of the method excluding the one being computed
043         * @param order order of the method
044         * @param minStep minimal step (sign is irrelevant, regardless of
045         * integration direction, forward or backward), the last step can
046         * be smaller than this
047         * @param maxStep maximal step (sign is irrelevant, regardless of
048         * integration direction, forward or backward), the last step can
049         * be smaller than this
050         * @param scalAbsoluteTolerance allowed absolute error
051         * @param scalRelativeTolerance allowed relative error
052         * @exception NumberIsTooSmallException if order is 1 or less
053         */
054        public AdamsIntegrator(final String name, final int nSteps, final int order,
055                               final double minStep, final double maxStep,
056                               final double scalAbsoluteTolerance,
057                               final double scalRelativeTolerance)
058            throws NumberIsTooSmallException {
059            super(name, nSteps, order, minStep, maxStep,
060                  scalAbsoluteTolerance, scalRelativeTolerance);
061            transformer = AdamsNordsieckTransformer.getInstance(nSteps);
062        }
063    
064        /**
065         * Build an Adams integrator with the given order and step control parameters.
066         * @param name name of the method
067         * @param nSteps number of steps of the method excluding the one being computed
068         * @param order order of the method
069         * @param minStep minimal step (sign is irrelevant, regardless of
070         * integration direction, forward or backward), the last step can
071         * be smaller than this
072         * @param maxStep maximal step (sign is irrelevant, regardless of
073         * integration direction, forward or backward), the last step can
074         * be smaller than this
075         * @param vecAbsoluteTolerance allowed absolute error
076         * @param vecRelativeTolerance allowed relative error
077         * @exception IllegalArgumentException if order is 1 or less
078         */
079        public AdamsIntegrator(final String name, final int nSteps, final int order,
080                               final double minStep, final double maxStep,
081                               final double[] vecAbsoluteTolerance,
082                               final double[] vecRelativeTolerance)
083            throws IllegalArgumentException {
084            super(name, nSteps, order, minStep, maxStep,
085                  vecAbsoluteTolerance, vecRelativeTolerance);
086            transformer = AdamsNordsieckTransformer.getInstance(nSteps);
087        }
088    
089        /** {@inheritDoc} */
090        @Override
091        public abstract void integrate(final ExpandableStatefulODE equations, final double t)
092            throws NumberIsTooSmallException, DimensionMismatchException,
093                   MaxCountExceededException, NoBracketingException;
094    
095        /** {@inheritDoc} */
096        @Override
097        protected Array2DRowRealMatrix initializeHighOrderDerivatives(final double h, final double[] t,
098                                                                      final double[][] y,
099                                                                      final double[][] yDot) {
100            return transformer.initializeHighOrderDerivatives(h, t, y, yDot);
101        }
102    
103        /** Update the high order scaled derivatives for Adams integrators (phase 1).
104         * <p>The complete update of high order derivatives has a form similar to:
105         * <pre>
106         * 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>
107         * </pre>
108         * this method computes the P<sup>-1</sup> A P r<sub>n</sub> part.</p>
109         * @param highOrder high order scaled derivatives
110         * (h<sup>2</sup>/2 y'', ... h<sup>k</sup>/k! y(k))
111         * @return updated high order derivatives
112         * @see #updateHighOrderDerivativesPhase2(double[], double[], Array2DRowRealMatrix)
113         */
114        public Array2DRowRealMatrix updateHighOrderDerivativesPhase1(final Array2DRowRealMatrix highOrder) {
115            return transformer.updateHighOrderDerivativesPhase1(highOrder);
116        }
117    
118        /** Update the high order scaled derivatives Adams integrators (phase 2).
119         * <p>The complete update of high order derivatives has a form similar to:
120         * <pre>
121         * 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>
122         * </pre>
123         * this method computes the (s<sub>1</sub>(n) - s<sub>1</sub>(n+1)) P<sup>-1</sup> u part.</p>
124         * <p>Phase 1 of the update must already have been performed.</p>
125         * @param start first order scaled derivatives at step start
126         * @param end first order scaled derivatives at step end
127         * @param highOrder high order scaled derivatives, will be modified
128         * (h<sup>2</sup>/2 y'', ... h<sup>k</sup>/k! y(k))
129         * @see #updateHighOrderDerivativesPhase1(Array2DRowRealMatrix)
130         */
131        public void updateHighOrderDerivativesPhase2(final double[] start,
132                                                     final double[] end,
133                                                     final Array2DRowRealMatrix highOrder) {
134            transformer.updateHighOrderDerivativesPhase2(start, end, highOrder);
135        }
136    
137    }