Simbody

SimTKcpodes.h

Go to the documentation of this file.
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_
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines