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}