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