Simbody
|
00001 #ifndef SimTK_SIMMATH_CPODES_H_ 00002 #define SimTK_SIMMATH_CPODES_H_ 00003 00004 /* -------------------------------------------------------------------------- * 00005 * SimTK Core: SimTK Simmath (CPodes) * 00006 * -------------------------------------------------------------------------- * 00007 * This is part of the SimTK Core biosimulation toolkit originating from * 00008 * Simbios, the NIH National Center for Physics-Based Simulation of * 00009 * Biological Structures at Stanford, funded under the NIH Roadmap for * 00010 * Medical Research, grant U54 GM072970. See https://simtk.org. * 00011 * * 00012 * Portions copyright (c) 2006-10 Stanford University and the Authors. * 00013 * Authors: Michael Sherman * 00014 * Contributors: * 00015 * * 00016 * Permission is hereby granted, free of charge, to any person obtaining a * 00017 * copy of this software and associated documentation files (the "Software"), * 00018 * to deal in the Software without restriction, including without limitation * 00019 * the rights to use, copy, modify, merge, publish, distribute, sublicense, * 00020 * and/or sell copies of the Software, and to permit persons to whom the * 00021 * Software is furnished to do so, subject to the following conditions: * 00022 * * 00023 * The above copyright notice and this permission notice shall be included in * 00024 * all copies or substantial portions of the Software. * 00025 * * 00026 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * 00027 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * 00028 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * 00029 * THE AUTHORS, CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, * 00030 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR * 00031 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE * 00032 * USE OR OTHER DEALINGS IN THE SOFTWARE. * 00033 * -------------------------------------------------------------------------- */ 00034 00041 #include "SimTKcommon.h" 00042 #include "simmath/internal/common.h" 00043 00044 #include <cstdio> // Needed for "FILE". 00045 00046 namespace SimTK { 00047 00057 class SimTK_SIMMATH_EXPORT CPodesSystem { 00058 public: 00059 virtual ~CPodesSystem() {} 00060 // The default implementations of these virtual functions 00061 // just throw an "unimplemented virtual function" exception. 00062 00063 // At least one of these two must be supplied by the concrete class. 00064 virtual int explicitODE(Real t, const Vector& y, Vector& fout) const; 00065 virtual int implicitODE(Real t, const Vector& y, const Vector& yp, 00066 Vector& fout) const; 00067 00068 virtual int constraint(Real t, const Vector& y, 00069 Vector& cout) const; 00070 virtual int project(Real t, const Vector& ycur, Vector& corr, 00071 Real epsProj, Vector& err) const; // err is in/out 00072 virtual int quadrature(Real t, const Vector& y, 00073 Vector& qout) const; 00074 virtual int root(Real t, const Vector& y, const Vector& yp, 00075 Vector& gout) const; 00076 virtual int weight(const Vector& y, Vector& weights) const; 00077 virtual void errorHandler(int error_code, const char* module, 00078 const char* function, char* msg) const; 00079 00080 //TODO: Jacobian functions 00081 }; 00082 00083 00084 // These static functions are private to the current (client-side) compilation 00085 // unit. They are used to navigate the client-side CPodesSystem virtual function 00086 // table, which cannot be done on the library side. Note that these are defined 00087 // in the SimTK namespace so don't need "SimTK" in their names. 00088 static int explicitODE_static(const CPodesSystem& sys, 00089 Real t, const Vector& y, Vector& fout) 00090 { return sys.explicitODE(t,y,fout); } 00091 00092 static int implicitODE_static(const CPodesSystem& sys, 00093 Real t, const Vector& y, const Vector& yp, Vector& fout) 00094 { return sys.implicitODE(t,y,yp,fout); } 00095 00096 static int constraint_static(const CPodesSystem& sys, 00097 Real t, const Vector& y, Vector& cout) 00098 { return sys.constraint(t,y,cout); } 00099 00100 static int project_static(const CPodesSystem& sys, 00101 Real t, const Vector& ycur, Vector& corr, 00102 Real epsProj, Vector& err) 00103 { return sys.project(t,ycur,corr,epsProj,err); } 00104 00105 static int quadrature_static(const CPodesSystem& sys, 00106 Real t, const Vector& y, Vector& qout) 00107 { return sys.quadrature(t,y,qout); } 00108 00109 static int root_static(const CPodesSystem& sys, 00110 Real t, const Vector& y, const Vector& yp, Vector& gout) 00111 { return sys.root(t,y,yp,gout); } 00112 00113 static int weight_static(const CPodesSystem& sys, 00114 const Vector& y, Vector& weights) 00115 { return sys.weight(y,weights); } 00116 00117 static void errorHandler_static(const CPodesSystem& sys, 00118 int error_code, const char* module, 00119 const char* function, char* msg) 00120 { sys.errorHandler(error_code,module,function,msg); } 00121 00130 class SimTK_SIMMATH_EXPORT CPodes { 00131 public: 00132 // no default constructor 00133 // copy constructor and default assignment are suppressed 00134 00135 enum ODEType { 00136 UnspecifiedODEType=0, 00137 ExplicitODE, 00138 ImplicitODE 00139 }; 00140 00141 enum LinearMultistepMethod { 00142 UnspecifiedLinearMultistepMethod=0, 00143 BDF, 00144 Adams 00145 }; 00146 00147 enum NonlinearSystemIterationType { 00148 UnspecifiedNonlinearSystemIterationType=0, 00149 Newton, 00150 Functional 00151 }; 00152 00153 enum ToleranceType { 00154 UnspecifiedToleranceType=0, 00155 ScalarScalar, 00156 ScalarVector, 00157 WeightFunction 00158 }; 00159 00160 enum ProjectionNorm { 00161 UnspecifiedProjectionNorm=0, 00162 L2Norm, 00163 ErrorNorm 00164 }; 00165 00166 enum ConstraintLinearity { 00167 UnspecifiedConstraintLinearity=0, 00168 Linear, 00169 Nonlinear 00170 }; 00171 00172 enum ProjectionFactorizationType { 00173 UnspecifiedProjectionFactorizationType=0, 00174 ProjectWithLU, 00175 ProjectWithQR, 00176 ProjectWithSchurComplement, 00177 ProjectWithQRPivot // for handling redundancy 00178 }; 00179 00180 enum StepMode { 00181 UnspecifiedStepMode=0, 00182 Normal, 00183 OneStep, 00184 NormalTstop, 00185 OneStepTstop 00186 }; 00187 00188 explicit CPodes 00189 (ODEType ode=UnspecifiedODEType, 00190 LinearMultistepMethod lmm=UnspecifiedLinearMultistepMethod, 00191 NonlinearSystemIterationType nls=UnspecifiedNonlinearSystemIterationType) 00192 { 00193 // Perform construction of the CPodesRep on the library side. 00194 librarySideCPodesConstructor(ode, lmm, nls); 00195 // But fill in function pointers from the client side. 00196 clientSideCPodesConstructor(); 00197 } 00198 00199 // Values for 'flag' return values. These are just the "normal" return 00200 // values; there are many more which are all negative and represent 00201 // error conditions. 00202 static const int Success = 0; 00203 static const int TstopReturn = 1; 00204 static const int RootReturn = 2; 00205 static const int Warning = 99; 00206 static const int TooMuchWork = -1; 00207 static const int TooClose = -27; 00208 00209 // These values should be used by user routines. "Success" is the 00210 // same as above. A positive return value means "recoverable error", 00211 // i.e., CPodes should cut the step size and try again, while a 00212 // negative number means "unrecoverable error" which will kill 00213 // CPODES altogether with a CP_xxx_FAIL error. The particular numerical 00214 // values here have no significance, just + vs. -. 00215 static const int RecoverableError = 9999; 00216 static const int UnrecoverableError = -9999; 00217 00218 ~CPodes(); 00219 00220 // Depending on the setting of ode_type at construction, init() 00221 // and reInit() will tell CPodes to use either the explicitODE() 00222 // or implicitODE() function from the CPodesSystem, so the user 00223 // MUST have overridden at least one of those virtual methods. 00224 int init(CPodesSystem& sys, 00225 Real t0, const Vector& y0, const Vector& yp0, 00226 ToleranceType tt, Real reltol, void* abstol); 00227 00228 int reInit(CPodesSystem& sys, 00229 Real t0, const Vector& y0, const Vector& yp0, 00230 ToleranceType tt, Real reltol, void* abstol); 00231 00232 // This tells CPodes to make use of the user's constraint() 00233 // method from CPodesSystem, and perform projection internally. 00234 int projInit(ProjectionNorm, ConstraintLinearity, 00235 const Vector& ctol); 00236 00237 // This tells CPodes to make use of the user's project() 00238 // method from CPodesSystem. 00239 int projDefine(); 00240 00241 // These tell CPodes to make use of the user's quadrature() 00242 // method from CPodesSystem. 00243 int quadInit(const Vector& q0); 00244 int quadReInit(const Vector& q0); 00245 00246 // This tells CPodes to make use of the user's root() method 00247 // from CPodesSystem. 00248 int rootInit(int nrtfn); 00249 00250 // This tells CPodes to make use of the user's errorHandler() 00251 // method from CPodesSystem. 00252 int setErrHandlerFn(); 00253 00254 // These tells CPodes to make use of the user's weight() 00255 // method from CPodesSystem. 00256 int setEwtFn(); 00257 00258 // TODO: these routines should enable methods that are defined 00259 // in the CPodesSystem, but a proper interface to the Jacobian 00260 // routines hasn't been implemented yet. 00261 int dlsSetJacFn(void* jac, void* jac_data); 00262 int dlsProjSetJacFn(void* jacP, void* jacP_data); 00263 00264 00265 int step(Real tout, Real* tret, 00266 Vector& y_inout, Vector& yp_inout, StepMode=Normal); 00267 00268 int setErrFile(FILE* errfp); 00269 int setMaxOrd(int maxord); 00270 int setMaxNumSteps(int mxsteps); 00271 int setMaxHnilWarns(int mxhnil); 00272 int setStabLimDet(bool stldet) ; 00273 int setInitStep(Real hin); 00274 int setMinStep(Real hmin); 00275 int setMaxStep(Real hmax); 00276 int setStopTime(Real tstop); 00277 int setMaxErrTestFails(int maxnef); 00278 00279 int setMaxNonlinIters(int maxcor); 00280 int setMaxConvFails(int maxncf); 00281 int setNonlinConvCoef(Real nlscoef); 00282 00283 int setProjUpdateErrEst(bool proj_err); 00284 int setProjFrequency(int proj_freq); 00285 int setProjTestCnstr(bool test_cnstr); 00286 int setProjLsetupFreq(int proj_lset_freq); 00287 int setProjNonlinConvCoef(Real prjcoef); 00288 00289 int setQuadErrCon(bool errconQ, 00290 int tol_typeQ, Real reltolQ, void* abstolQ); 00291 00292 int setTolerances(int tol_type, Real reltol, void* abstol); 00293 00294 int setRootDirection(Array_<int>& rootdir); 00295 00296 int getDky(Real t, int k, Vector& dky); 00297 00298 int getQuad(Real t, Vector& yQout); 00299 int getQuadDky(Real t, int k, Vector& dky); 00300 00301 int getWorkSpace(int* lenrw, int* leniw); 00302 int getNumSteps(int* nsteps); 00303 int getNumFctEvals(int* nfevals); 00304 int getNumLinSolvSetups(int* nlinsetups); 00305 int getNumErrTestFails(int* netfails); 00306 int getLastOrder(int* qlast); 00307 int getCurrentOrder(int* qcur); 00308 int getNumStabLimOrderReds(int* nslred); 00309 int getActualInitStep(Real* hinused); 00310 int getLastStep(Real* hlast); 00311 int getCurrentStep(Real* hcur); 00312 int getCurrentTime(Real* tcur); 00313 int getTolScaleFactor(Real* tolsfac); 00314 int getErrWeights(Vector& eweight); 00315 int getEstLocalErrors(Vector& ele) ; 00316 int getNumGEvals(int* ngevals); 00317 int getRootInfo(int* rootsfound); 00318 int getIntegratorStats(int* nsteps, 00319 int* nfevals, int* nlinsetups, 00320 int* netfails, int* qlast, 00321 int* qcur, Real* hinused, Real* hlast, 00322 Real* hcur, Real* tcur); 00323 00324 int getNumNonlinSolvIters(int* nniters); 00325 int getNumNonlinSolvConvFails(int* nncfails); 00326 int getNonlinSolvStats(int* nniters, int* nncfails); 00327 int getProjNumProj(int* nproj); 00328 int getProjNumCnstrEvals(int* nce); 00329 int getProjNumLinSolvSetups(int* nsetupsP); 00330 int getProjNumFailures(int* nprf) ; 00331 int getProjStats(int* nproj, 00332 int* nce, int* nsetupsP, 00333 int* nprf); 00334 int getQuadNumFunEvals(int* nqevals); 00335 int getQuadErrWeights(Vector& eQweight); 00336 char* getReturnFlagName(int flag); 00337 00338 00339 int dlsGetWorkSpace(int* lenrwLS, int* leniwLS); 00340 int dlsGetNumJacEvals(int* njevals); 00341 int dlsGetNumFctEvals(int* nfevalsLS); 00342 int dlsGetLastFlag(int* flag); 00343 char* dlsGetReturnFlagName(int flag); 00344 00345 int dlsProjGetNumJacEvals(int* njPevals); 00346 int dlsProjGetNumFctEvals(int* ncevalsLS); 00347 00348 int lapackDense(int N); 00349 int lapackBand(int N, int mupper, int mlower); 00350 int lapackDenseProj(int Nc, int Ny, ProjectionFactorizationType); 00351 00352 private: 00353 // This is how we get the client-side virtual functions to 00354 // be callable from library-side code while maintaining binary 00355 // compatibility. 00356 typedef int (*ExplicitODEFunc)(const CPodesSystem&, 00357 Real t, const Vector& y, Vector& fout); 00358 typedef int (*ImplicitODEFunc)(const CPodesSystem&, 00359 Real t, const Vector& y, const Vector& yp, 00360 Vector& fout); 00361 typedef int (*ConstraintFunc) (const CPodesSystem&, 00362 Real t, const Vector& y, Vector& cout); 00363 typedef int (*ProjectFunc) (const CPodesSystem&, 00364 Real t, const Vector& ycur, Vector& corr, 00365 Real epsProj, Vector& err); 00366 typedef int (*QuadratureFunc) (const CPodesSystem&, 00367 Real t, const Vector& y, Vector& qout); 00368 typedef int (*RootFunc) (const CPodesSystem&, 00369 Real t, const Vector& y, const Vector& yp, 00370 Vector& gout); 00371 typedef int (*WeightFunc) (const CPodesSystem&, 00372 const Vector& y, Vector& weights); 00373 typedef void (*ErrorHandlerFunc)(const CPodesSystem&, 00374 int error_code, const char* module, 00375 const char* function, char* msg); 00376 00377 // Note that these routines do not tell CPodes to use the supplied 00378 // functions. They merely provide the client-side addresses of functions 00379 // which understand how to find the user's virtual functions, should those 00380 // actually be provided. Control over whether to actually call any of these 00381 // is handled elsewhere, with user-visible methods. These private methods 00382 // are to be called only upon construction of the CPodes object here. They 00383 // are not even dependent on which user-supplied concrete CPodesSystem is 00384 // being used. 00385 void registerExplicitODEFunc(ExplicitODEFunc); 00386 void registerImplicitODEFunc(ImplicitODEFunc); 00387 void registerConstraintFunc(ConstraintFunc); 00388 void registerProjectFunc(ProjectFunc); 00389 void registerQuadratureFunc(QuadratureFunc); 00390 void registerRootFunc(RootFunc); 00391 void registerWeightFunc(WeightFunc); 00392 void registerErrorHandlerFunc(ErrorHandlerFunc); 00393 00394 00395 // This is the library-side part of the CPodes constructor. This must 00396 // be done prior to the client side construction. 00397 void librarySideCPodesConstructor(ODEType, LinearMultistepMethod, NonlinearSystemIterationType); 00398 00399 // Note that this routine MUST be called from client-side code so that 00400 // it picks up exactly the static routines above which will agree with 00401 // the client about the layout of the CPodesSystem virtual function table. 00402 void clientSideCPodesConstructor() { 00403 registerExplicitODEFunc(explicitODE_static); 00404 registerImplicitODEFunc(implicitODE_static); 00405 registerConstraintFunc(constraint_static); 00406 registerProjectFunc(project_static); 00407 registerQuadratureFunc(quadrature_static); 00408 registerRootFunc(root_static); 00409 registerWeightFunc(weight_static); 00410 registerErrorHandlerFunc(errorHandler_static); 00411 } 00412 00413 // FOR INTERNAL USE ONLY 00414 private: 00415 class CPodesRep* rep; 00416 friend class CPodesRep; 00417 00418 const CPodesRep& getRep() const {assert(rep); return *rep;} 00419 CPodesRep& updRep() {assert(rep); return *rep;} 00420 00421 // Suppress copy constructor and default assigment operator. 00422 CPodes(const CPodes&); 00423 CPodes& operator=(const CPodes&); 00424 }; 00425 00426 } // namespace SimTK 00427 00428 #endif // SimTK_CPODES_H_