SimTKcpodes.h

Go to the documentation of this file.
00001 #ifndef SimTK_CPODES_H_
00002 #define SimTK_CPODES_H_
00003 
00004 /* -------------------------------------------------------------------------- *
00005  *                      SimTK Core: SimTK 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-7 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 
00043 #include <cstdio> // Needed for "FILE".
00044 
00045 /* Shared libraries are messy in Visual Studio. We have to distinguish three
00046  * cases:
00047  *   (1) this header is being used to build the SimTKcpodes shared library (dllexport)
00048  *   (2) this header is being used by a *client* of the SimTKcpodes shared
00049  *       library (dllimport)
00050  *   (3) we are building the SimTKcpodes static library, or the client is
00051  *       being compiled with the expectation of linking with the
00052  *       SimTKcpodes static library (nothing special needed)
00053  * In the CMake script for building this library, we define one of the symbols
00054  *     SimTK_CPODES_BUILDING_{SHARED|STATIC}_LIBRARY
00055  * Client code normally has no special symbol defined, in which case we'll
00056  * assume it wants to use the shared library. However, if the client defines
00057  * the symbol SimTK_USE_STATIC_LIBRARIES we'll suppress the dllimport so
00058  * that the client code can be linked with static libraries. Note that
00059  * the client symbol is not library dependent, while the library symbols
00060  * affect only the SimTKcpodes library, meaning that other libraries can
00061  * be clients of this one. However, we are assuming all-static or all-shared.
00062 */
00063 
00064 #ifdef WIN32
00065     #if defined(SimTK_CPODES_BUILDING_SHARED_LIBRARY)
00066         #define SimTK_CPODES_EXPORT __declspec(dllexport)
00067     #elif defined(SimTK_CPODES_BUILDING_STATIC_LIBRARY) || defined(SimTK_USE_STATIC_LIBRARIES)
00068         #define SimTK_CPODES_EXPORT
00069     #else
00070         /* i.e., a client of a shared library */
00071         #define SimTK_CPODES_EXPORT __declspec(dllimport)
00072     #endif
00073 #else
00074     /* Linux, Mac */
00075     #define SimTK_CPODES_EXPORT
00076 #endif
00077 
00078 /* Every SimTK Core library must provide these two routines, with the library
00079  * name appearing after the "version_" and "about_".
00080  */
00081 #ifdef __cplusplus
00082 extern "C" {
00083 #endif
00084     SimTK_CPODES_EXPORT void SimTK_version_SimTKcpodes(int* major, int* minor, int* build);
00085     SimTK_CPODES_EXPORT void SimTK_about_SimTKcpodes(const char* key, int maxlen, char* value);
00086 #ifdef __cplusplus
00087 }
00088 #endif
00089 
00090 namespace SimTK {
00091 
00101 class SimTK_CPODES_EXPORT CPodesSystem {
00102 public:
00103     // The default implementations of these virtual functions
00104     // just throw an "unimplemented virtual function" exception. 
00105 
00106     // At least one of these two must be supplied by the concrete class.
00107     virtual int  explicitODE(Real t, const Vector& y, Vector& fout) const;
00108     virtual int  implicitODE(Real t, const Vector& y, const Vector& yp, 
00109                              Vector& fout) const;
00110 
00111     virtual int  constraint(Real t, const Vector& y, 
00112                             Vector& cout) const;
00113     virtual int  project(Real t, const Vector& ycur, Vector& corr,
00114                          Real epsProj, Vector& err) const; // err is in/out
00115     virtual int  quadrature(Real t, const Vector& y, 
00116                             Vector& qout) const;
00117     virtual int  root(Real t, const Vector& y, const Vector& yp,
00118                       Vector& gout) const;
00119     virtual int  weight(const Vector& y, Vector& weights) const;
00120     virtual void errorHandler(int error_code, const char* module,
00121                               const char* function, char* msg) const;
00122 
00123     //TODO: Jacobian functions
00124 };
00125 
00126 
00127 // These static functions are private to the current (client-side) compilation
00128 // unit. They are used to navigate the client-side CPodesSystem virtual function
00129 // table, which cannot be done on the library side. Note that these are defined
00130 // in the SimTK namespace so don't need "SimTK" in their names.
00131 static int explicitODE_static(const CPodesSystem& sys, 
00132                               Real t, const Vector& y, Vector& fout) 
00133   { return sys.explicitODE(t,y,fout); }
00134 
00135 static int implicitODE_static(const CPodesSystem& sys, 
00136                               Real t, const Vector& y, const Vector& yp, Vector& fout)
00137   { return sys.implicitODE(t,y,yp,fout); }
00138 
00139 static int constraint_static(const CPodesSystem& sys, 
00140                              Real t, const Vector& y, Vector& cout)
00141   { return sys.constraint(t,y,cout); }
00142 
00143 static int project_static(const CPodesSystem& sys, 
00144                           Real t, const Vector& ycur, Vector& corr,
00145                           Real epsProj, Vector& err)
00146   { return sys.project(t,ycur,corr,epsProj,err); }
00147 
00148 static int quadrature_static(const CPodesSystem& sys, 
00149                              Real t, const Vector& y, Vector& qout)
00150   { return sys.quadrature(t,y,qout); }
00151 
00152 static int root_static(const CPodesSystem& sys, 
00153                        Real t, const Vector& y, const Vector& yp, Vector& gout)
00154   { return sys.root(t,y,yp,gout); }
00155 
00156 static int weight_static(const CPodesSystem& sys, 
00157                          const Vector& y, Vector& weights)
00158   { return sys.weight(y,weights); }
00159 
00160 static void errorHandler_static(const CPodesSystem& sys, 
00161                                 int error_code, const char* module, 
00162                                 const char* function, char* msg)
00163   { sys.errorHandler(error_code,module,function,msg); }
00164 
00173 class SimTK_CPODES_EXPORT CPodes {
00174 public:
00175     // no default constructor
00176     // copy constructor and default assignment are suppressed
00177 
00178     enum ODEType {
00179         UnspecifiedODEType=0,
00180         ExplicitODE,
00181         ImplicitODE
00182     };
00183 
00184     enum LinearMultistepMethod {
00185         UnspecifiedLinearMultistepMethod=0,
00186         BDF,
00187         Adams
00188     };
00189 
00190     enum NonlinearSystemIterationType {
00191         UnspecifiedNonlinearSystemIterationType=0,
00192         Newton,
00193         Functional
00194     };
00195 
00196     enum ToleranceType {
00197         UnspecifiedToleranceType=0,
00198         ScalarScalar,
00199         ScalarVector,
00200         WeightFunction
00201     };
00202 
00203     enum ProjectionNorm {
00204         UnspecifiedProjectionNorm=0,
00205         L2Norm,
00206         ErrorNorm
00207     };
00208 
00209     enum ConstraintLinearity {
00210         UnspecifiedConstraintLinearity=0,
00211         Linear,
00212         Nonlinear
00213     };
00214 
00215     enum ProjectionFactorizationType {
00216         UnspecifiedProjectionFactorizationType=0,
00217         ProjectWithLU,
00218         ProjectWithQR,
00219         ProjectWithSchurComplement,
00220         ProjectWithQRPivot  // for handling redundancy
00221     };
00222 
00223     enum StepMode {
00224         UnspecifiedStepMode=0,
00225         Normal,
00226         OneStep,
00227         NormalTstop,
00228         OneStepTstop
00229     };
00230 
00231     explicit CPodes
00232        (ODEType                      ode=UnspecifiedODEType, 
00233         LinearMultistepMethod        lmm=UnspecifiedLinearMultistepMethod, 
00234         NonlinearSystemIterationType nls=UnspecifiedNonlinearSystemIterationType)
00235     {
00236         // Perform construction of the CPodesRep on the library side.
00237         librarySideCPodesConstructor(ode, lmm, nls);
00238         // But fill in function pointers from the client side.
00239         clientSideCPodesConstructor();
00240     }
00241 
00242     // Values for 'flag' return values. These are just the "normal" return
00243     // values; there are many more which are all negative and represent
00244     // error conditions.
00245     static const int Success     = 0;
00246     static const int TstopReturn = 1;
00247     static const int RootReturn  = 2;
00248     static const int Warning     = 99;
00249     static const int TooMuchWork = -1;
00250     static const int TooClose    = -27;
00251 
00252     // These values should be used by user routines. "Success" is the
00253     // same as above. A positive return value means "recoverable error",
00254     // i.e., CPodes should cut the step size and try again, while a
00255     // negative number means "unrecoverable error" which will kill
00256     // CPODES altogether with a CP_xxx_FAIL error. The particular numerical
00257     // values here have no significance, just + vs. -.
00258     static const int RecoverableError = 9999;
00259     static const int UnrecoverableError = -9999;
00260 
00261     ~CPodes();
00262 
00263     // Depending on the setting of ode_type at construction, init()
00264     // and reInit() will tell CPodes to use either the explicitODE()
00265     // or implicitODE() function from the CPodesSystem, so the user
00266     // MUST have overridden at least one of those virtual methods.
00267     int init(CPodesSystem& sys,
00268              Real t0, const Vector& y0, const Vector& yp0,
00269              ToleranceType tt, Real reltol, void* abstol);
00270 
00271     int reInit(CPodesSystem& sys,
00272                Real t0, const Vector& y0, const Vector& yp0,
00273                ToleranceType tt, Real reltol, void* abstol);
00274 
00275     // This tells CPodes to make use of the user's constraint()
00276     // method from CPodesSystem, and perform projection internally.
00277     int projInit(ProjectionNorm, ConstraintLinearity,
00278                  const Vector& ctol);
00279 
00280     // This tells CPodes to make use of the user's project()
00281     // method from CPodesSystem.
00282     int projDefine();
00283 
00284     // These tell CPodes to make use of the user's quadrature()
00285     // method from CPodesSystem.
00286     int quadInit(const Vector& q0);
00287     int quadReInit(const Vector& q0);
00288 
00289     // This tells CPodes to make use of the user's root() method
00290     // from CPodesSystem.
00291     int rootInit(int nrtfn);
00292 
00293     // This tells CPodes to make use of the user's errorHandler() 
00294     // method from CPodesSystem.
00295     int setErrHandlerFn();
00296 
00297     // These tells CPodes to make use of the user's weight() 
00298     // method from CPodesSystem.
00299     int setEwtFn();
00300 
00301     // TODO: these routines should enable methods that are defined
00302     // in the CPodesSystem, but a proper interface to the Jacobian
00303     // routines hasn't been implemented yet.
00304     int dlsSetJacFn(void* jac, void* jac_data);
00305     int dlsProjSetJacFn(void* jacP, void* jacP_data);
00306 
00307 
00308     int step(Real tout, Real* tret, 
00309              Vector& y_inout, Vector& yp_inout, StepMode=Normal);
00310 
00311     int setErrFile(FILE* errfp);
00312     int setMaxOrd(int maxord);
00313     int setMaxNumSteps(long mxsteps);
00314     int setMaxHnilWarns(int mxhnil);
00315     int setStabLimDet(bool stldet) ;
00316     int setInitStep(Real hin);
00317     int setMinStep(Real hmin);
00318     int setMaxStep(Real hmax);
00319     int setStopTime(Real tstop);
00320     int setMaxErrTestFails(int maxnef);
00321 
00322     int setMaxNonlinIters(int maxcor);
00323     int setMaxConvFails(int maxncf);
00324     int setNonlinConvCoef(Real nlscoef);
00325 
00326     int setProjUpdateErrEst(bool proj_err);
00327     int setProjFrequency(long proj_freq);
00328     int setProjTestCnstr(bool test_cnstr);
00329     int setProjLsetupFreq(long proj_lset_freq);
00330     int setProjNonlinConvCoef(Real prjcoef);
00331 
00332     int setQuadErrCon(bool errconQ, 
00333                       int tol_typeQ, Real reltolQ, void* abstolQ);
00334 
00335     int setTolerances(int tol_type, Real reltol, void* abstol);
00336     
00337     int setRootDirection(std::vector<int>& rootdir);
00338 
00339     int getDky(Real t, int k, Vector& dky);
00340 
00341     int getQuad(Real t, Vector& yQout);
00342     int getQuadDky(Real t, int k, Vector& dky);
00343 
00344     int getWorkSpace(long* lenrw, long* leniw);
00345     int getNumSteps(long* nsteps);
00346     int getNumFctEvals(long* nfevals);
00347     int getNumLinSolvSetups(long* nlinsetups);
00348     int getNumErrTestFails(long* netfails);
00349     int getLastOrder(int* qlast);
00350     int getCurrentOrder(int* qcur);
00351     int getNumStabLimOrderReds(long* nslred);
00352     int getActualInitStep(Real* hinused);
00353     int getLastStep(Real* hlast);
00354     int getCurrentStep(Real* hcur);
00355     int getCurrentTime(Real* tcur);
00356     int getTolScaleFactor(Real* tolsfac);
00357     int getErrWeights(Vector& eweight);
00358     int getEstLocalErrors(Vector& ele) ;
00359     int getNumGEvals(long* ngevals);
00360     int getRootInfo(int* rootsfound);
00361     int getIntegratorStats(long* nsteps,
00362                            long* nfevals, long* nlinsetups,
00363                            long* netfails, int* qlast,
00364                            int* qcur, Real* hinused, Real* hlast,
00365                            Real* hcur, Real* tcur);
00366 
00367     int getNumNonlinSolvIters(long* nniters);
00368     int getNumNonlinSolvConvFails(long* nncfails);
00369     int getNonlinSolvStats(long* nniters, long* nncfails);
00370     int getProjNumProj(long* nproj);
00371     int getProjNumCnstrEvals(long* nce);
00372     int getProjNumLinSolvSetups(long* nsetupsP);
00373     int getProjNumFailures(long* nprf) ;
00374     int getProjStats(long* nproj,
00375                      long* nce, long* nsetupsP,
00376                      long* nprf);
00377     int getQuadNumFunEvals(long* nqevals);
00378     int getQuadErrWeights(Vector& eQweight);
00379     char* getReturnFlagName(int flag);
00380 
00381 
00382     int dlsGetWorkSpace(long* lenrwLS, long* leniwLS);
00383     int dlsGetNumJacEvals(long* njevals);
00384     int dlsGetNumFctEvals(long* nfevalsLS);
00385     int dlsGetLastFlag(int* flag);
00386     char* dlsGetReturnFlagName(int flag);
00387 
00388     int dlsProjGetNumJacEvals(long* njPevals);
00389     int dlsProjGetNumFctEvals(long* ncevalsLS);
00390 
00391     int lapackDense(int N);
00392     int lapackBand(int N, int mupper, int mlower);
00393     int lapackDenseProj(int Nc, int Ny, ProjectionFactorizationType);
00394 
00395 private:
00396     // This is how we get the client-side virtual functions to
00397     // be callable from library-side code while maintaining binary
00398     // compatibility.
00399     typedef int (*ExplicitODEFunc)(const CPodesSystem&, 
00400                                    Real t, const Vector& y, Vector& fout);
00401     typedef int (*ImplicitODEFunc)(const CPodesSystem&, 
00402                                    Real t, const Vector& y, const Vector& yp,
00403                                    Vector& fout);
00404     typedef int (*ConstraintFunc) (const CPodesSystem&, 
00405                                    Real t, const Vector& y, Vector& cout);
00406     typedef int (*ProjectFunc)    (const CPodesSystem&, 
00407                                    Real t, const Vector& ycur, Vector& corr,
00408                                    Real epsProj, Vector& err);
00409     typedef int (*QuadratureFunc) (const CPodesSystem&, 
00410                                    Real t, const Vector& y, Vector& qout);
00411     typedef int (*RootFunc)       (const CPodesSystem&, 
00412                                    Real t, const Vector& y, const Vector& yp, 
00413                                    Vector& gout);
00414     typedef int (*WeightFunc)     (const CPodesSystem&, 
00415                                    const Vector& y, Vector& weights);
00416     typedef void (*ErrorHandlerFunc)(const CPodesSystem&, 
00417                                      int error_code, const char* module, 
00418                                      const char* function, char* msg);
00419 
00420     // Note that these routines do not tell CPodes to use the supplied
00421     // functions. They merely provide the client-side addresses of functions
00422     // which understand how to find the user's virtual functions, should those
00423     // actually be provided. Control over whether to actually call any of these
00424     // is handled elsewhere, with user-visible methods. These private methods
00425     // are to be called only upon construction of the CPodes object here. They
00426     // are not even dependent on which user-supplied concrete CPodesSystem is
00427     // being used.
00428     void registerExplicitODEFunc(ExplicitODEFunc);
00429     void registerImplicitODEFunc(ImplicitODEFunc);
00430     void registerConstraintFunc(ConstraintFunc);
00431     void registerProjectFunc(ProjectFunc);
00432     void registerQuadratureFunc(QuadratureFunc);
00433     void registerRootFunc(RootFunc);
00434     void registerWeightFunc(WeightFunc);
00435     void registerErrorHandlerFunc(ErrorHandlerFunc);
00436 
00437 
00438     // This is the library-side part of the CPodes constructor. This must
00439     // be done prior to the client side construction.
00440     void librarySideCPodesConstructor(ODEType, LinearMultistepMethod, NonlinearSystemIterationType);
00441 
00442     // Note that this routine MUST be called from client-side code so that
00443     // it picks up exactly the static routines above which will agree with
00444     // the client about the layout of the CPodesSystem virtual function table.
00445     void clientSideCPodesConstructor() {
00446         registerExplicitODEFunc(explicitODE_static);
00447         registerImplicitODEFunc(implicitODE_static);
00448         registerConstraintFunc(constraint_static);
00449         registerProjectFunc(project_static);
00450         registerQuadratureFunc(quadrature_static);
00451         registerRootFunc(root_static);
00452         registerWeightFunc(weight_static);
00453         registerErrorHandlerFunc(errorHandler_static);
00454     }
00455 
00456     // FOR INTERNAL USE ONLY
00457 private:
00458     class CPodesRep* rep;
00459     friend class CPodesRep;
00460 
00461     const CPodesRep& getRep() const {assert(rep); return *rep;}
00462     CPodesRep&       updRep()       {assert(rep); return *rep;}
00463 
00464     // Suppress copy constructor and default assigment operator.
00465     CPodes(const CPodes&);
00466     CPodes& operator=(const CPodes&);
00467 };
00468 
00469 } // namespace SimTK
00470 
00471 #endif // SimTK_CPODES_H_

Generated on Fri Sep 26 07:44:16 2008 for SimTKcore by  doxygen 1.5.6