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