001/* The abstract base class of the ODE solvers.
002
003 Copyright (c) 1998-2013 The Regents of the University of California.
004 All rights reserved.
005 Permission is hereby granted, without written agreement and without
006 license or royalty fees, to use, copy, modify, and distribute this
007 software and its documentation for any purpose, provided that the above
008 copyright notice and the following two paragraphs appear in all copies
009 of this software.
010
011 IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY
012 FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
013 ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
014 THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF
015 SUCH DAMAGE.
016
017 THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
018 INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
019 MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE
020 PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF
021 CALIFORNIA HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES,
022 ENHANCEMENTS, OR MODIFICATIONS.
023
024 PT_COPYRIGHT_VERSION_2
025 COPYRIGHTENDKEY
026
027 */
028package ptolemy.domains.continuous.kernel;
029
030import ptolemy.kernel.util.IllegalActionException;
031
032///////////////////////////////////////////////////////////////////
033//// ContinuousODESolver
034
035/**
036 Abstract base class for ODE solvers. A complete integration
037 consists of one or more rounds of executions. One round of execution requires
038 the model time to be advanced and this advancement is handled by the
039 Continuous director. Derived classes need to tell how many rounds
040 of execution are necessary and how much time to advance for each round.
041 <P>
042 How many rounds are needed in one integration is solver dependent. For some
043 solving algorithms, (i.e. the so called explicit methods) the number of
044 rounds is fixed. For some others (i.e. implicit methods), the number of
045 rounds can not be decided beforehand.
046 <P>
047 A round counter is a counter for the number of rounds in one integration.
048 It helps the solvers to decide how to behave under different rounds.
049 The round counter can be increased by the calling the _incrementRound()
050 method. The _reset() method always resets the counter to 0. These methods are
051 protected because they are only used by Continuous directors.
052 <p>
053 Conceptually, ODE solvers do not maintain simulation parameters,
054 like step sizes and error tolerance. They get these parameters from the
055 director. So the same set of parameters are shared by all the solvers
056 in a simulation.
057
058 @author Haiyang Zheng, Edward A. Lee
059 @version $Id$
060 @since Ptolemy II 6.0
061 @Pt.ProposedRating Green (hyzheng)
062 @Pt.AcceptedRating Green (hyzheng)
063 */
064public abstract class ContinuousODESolver {
065
066    ///////////////////////////////////////////////////////////////////
067    ////                         public methods                    ////
068
069    /** Return the number of auxiliary variables that an integrator should
070     *  provide when solving the ODE. Auxiliary variables are variables
071     *  in integrators to store integrator-dependent intermediate results
072     *  when solving an ODE.
073     *  <br>
074     *  For example, the fixed-step solvers need 0 auxiliary variable, but
075     *  the RK23 solver needs 4 auxiliary variables to store the temporary
076     *  derivatives at different time points during an integration.
077     *  @return The number of auxiliary variables.
078     */
079    public abstract int getIntegratorAuxVariableCount();
080
081    /** Perform one integration step. The fire() method of integrators
082     *  delegates to this method. Derived classes need to implement
083     *  the details. This method does not produce any outputs.
084     *  @param integrator The integrator that calls this method.
085     *  @exception IllegalActionException Not thrown in this base class.
086     */
087    public abstract void integratorIntegrate(ContinuousIntegrator integrator)
088            throws IllegalActionException;
089
090    /** Return true if the current integration step is accurate from the
091     *  argument integrator's point of view. The isStepSizeAccurate() method
092     *  of integrators delegates to this method.
093     *  Derived classes need to implement the details.
094     *  @param integrator The integrator that calls this method.
095     *  @return True if the integrator finds the step accurate.
096     */
097    public abstract boolean integratorIsAccurate(
098            ContinuousIntegrator integrator);
099
100    /** The suggestedStepSize() method of the integrator delegates to this
101     *  method. Derived classes need to implement the details.
102     *  @param integrator The integrator that calls this method.
103     *  @return The suggested next step size by the given integrator.
104     */
105    public abstract double integratorSuggestedStepSize(
106            ContinuousIntegrator integrator);
107
108    ///////////////////////////////////////////////////////////////////
109    ////                         protected methods                 ////
110
111    /** Report a debug message via the director.
112     *  @param message The message.
113     */
114    protected final void _debug(String message) {
115        _director._reportDebugMessage(message);
116    }
117
118    /** Get the current round factor. If the rounds are
119     *  finished, then return 1.0.
120     *  @return The current round factor.
121     *  @see #_isStepFinished()
122     */
123    protected abstract double _getRoundTimeIncrement();
124
125    /** Return the current round.
126     *  @return The current round.
127     */
128    protected abstract int _getRound();
129
130    /** Return true if debugging is turned on in the director.
131     *  @return True if debugging is turned on.
132     */
133    protected final boolean _isDebugging() {
134        return _director._isDebugging();
135    }
136
137    /** Return true if the current integration step is finished. For example,
138     *  solvers with a fixed number of rounds in an integration step will
139     *  return true when that number of rounds are complete. Solvers that
140     *  iterate to a solution will return true when the solution is found.
141     *  @return Return true if the solver has finished an integration step.
142     */
143    protected abstract boolean _isStepFinished();
144
145    /** Make this solver the solver of the given Director. This method
146     *  should only be called by CT directors, when they instantiate solvers
147     *  according to the ODESolver parameters.
148     *  @param director The CT director that contains this solver.
149     */
150    protected final void _makeSolverOf(ContinuousDirector director) {
151        _director = director;
152    }
153
154    /** Reset the solver, indicating to it that we are starting an
155     *  integration step. This method also sets a flag indicating that
156     *  we have not converged to a solution if the ODE solver is implicit.
157     */
158    protected abstract void _reset();
159
160    /** Set the round for the next integration step.
161     *  This must be between zero and the value returned by
162     *  getIntegratorAuxVariableCount().
163     *  @param round The round for the next integration step.
164     *  @see #getIntegratorAuxVariableCount()
165     */
166    protected abstract void _setRound(int round);
167
168    ///////////////////////////////////////////////////////////////////
169    ////                         protected variables               ////
170
171    /** The Continuous director that contains this solver. */
172    protected ContinuousDirector _director = null;
173}