Simbody

System.h

Go to the documentation of this file.
00001 #ifndef SimTK_SimTKCOMMON_SYSTEM_H_
00002 #define SimTK_SimTKCOMMON_SYSTEM_H_
00003 
00004 /* -------------------------------------------------------------------------- *
00005  *                      SimTK Core: SimTKcommon                               *
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: Peter Eastman                                                *
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 
00035 #include "SimTKcommon/basics.h"
00036 #include "SimTKcommon/Simmatrix.h"
00037 #include "SimTKcommon/internal/State.h"
00038 #include "SimTKcommon/internal/Subsystem.h"
00039 
00040 #include <cassert>
00041 
00042 namespace SimTK {
00043 
00044 class DecorativeGeometry;
00045 class DefaultSystemSubsystem;
00046 class ScheduledEventHandler;
00047 class ScheduledEventReporter;
00048 class TriggeredEventHandler;
00049 class TriggeredEventReporter;
00050 
00093 class SimTK_SimTKCOMMON_EXPORT System {
00094 public:
00095     class Guts; // local; name is System::Guts
00096     friend class Guts;
00097 private:
00098     // This is the only data member in this class. Also, any class derived from
00099     // System must have *NO* data members at all (data goes in the Guts class).
00100     Guts* guts;
00101 public:
00102     System() : guts(0) { }
00103     System(const System&);
00104     System& operator=(const System&);
00105     ~System();
00106 
00107     const String& getName()    const;
00108     const String& getVersion() const;
00109 
00113     inline void addEventHandler(ScheduledEventHandler* handler);
00117     inline void addEventHandler(TriggeredEventHandler* handler);
00121     inline void addEventReporter(ScheduledEventReporter* handler) const;
00125     inline void addEventReporter(TriggeredEventReporter* handler) const;
00126 
00138     System& setUpDirection(const CoordinateDirection& up);
00140     CoordinateDirection getUpDirection() const;
00141 
00150     System& setUseUniformBackground(bool useUniformBackground);
00153     bool getUseUniformBackground() const;
00154 
00155 
00156     class ProjectOptions {
00157         unsigned int optionSet;
00158         explicit ProjectOptions(unsigned o) : optionSet(o) { }
00159     public:
00160 
00161         enum Option {
00162             None   = 0x00,
00163 
00164             Q      = 0x01,
00165             U      = 0x02,
00166             QError = 0x04,
00167             UError = 0x08,
00168 
00169             PositionOnly = (Q|QError),
00170             VelocityOnly = (U|UError),
00171             All          = (PositionOnly|VelocityOnly),
00172 
00173             // This option says we expect the state to be close to a 
00174             // solution already and restricts projection to move downhill
00175             // in the local vicinity. This should be used during any
00176             // continuous integration to prevent erroneous jumps in the state.
00177             LocalOnly = 0x1000
00178         };
00179 
00180         ProjectOptions() : optionSet(0) { }
00181 
00182         // This is an implicit conversion
00183         ProjectOptions(Option opt) : optionSet((unsigned)opt) { }
00184 
00185         // Implicit conversion to bool when needed
00186         operator bool() const {return optionSet != 0;}
00187         bool hasAnyPositionOptions() const {return (optionSet&(unsigned)PositionOnly) != 0;}
00188         bool hasAnyVelocityOptions() const {return (optionSet&(unsigned)VelocityOnly) != 0;}
00189         bool isEmpty() const {return optionSet==0;}
00190 
00191         bool isOptionSet(Option opt) const {return (optionSet&(unsigned)opt) != 0;}
00192         void clear() {optionSet=0;}
00193         void clearOption(Option opt) {optionSet &= ~(unsigned)opt;}
00194         void setOption  (Option opt) {optionSet |= (unsigned)opt;}
00195 
00196         // Set operators: not, or, and, set difference
00197         ProjectOptions operator~() const {return ProjectOptions( (~optionSet) & (unsigned)All );}
00198         ProjectOptions& operator|=(ProjectOptions opts) {optionSet |= opts.optionSet; return *this;}
00199         ProjectOptions& operator&=(ProjectOptions opts) {optionSet &= opts.optionSet; return *this;}
00200         ProjectOptions& operator-=(ProjectOptions opts) {optionSet &= ~opts.optionSet; return *this;}
00201 
00202         ProjectOptions& operator|=(Option opt) {setOption(opt); return *this;}
00203         ProjectOptions& operator-=(Option opt) {clearOption(opt); return *this;}
00204     };
00205 
00207         // STATISTICS //
00209 
00215     void resetAllCountersToZero();
00216 
00217         // Realization
00218 
00222     int getNumRealizationsOfThisStage(Stage) const;
00223 
00227     int getNumRealizeCalls() const;
00228 
00229         // Prescribed motion
00230 
00234     int getNumPrescribeCalls() const;
00235 
00236         // Projection
00237 
00240     int getNumQProjections() const;
00241     int getNumUProjections() const;
00242     int getNumQErrorEstimateProjections() const;
00243     int getNumUErrorEstimateProjections() const;
00244 
00247     int getNumProjectCalls() const;
00248 
00249         // Event handling and reporting
00250 
00254     int getNumHandlerCallsThatChangedStage(Stage) const;
00255 
00258     int getNumHandleEventCalls() const;
00259 
00262     int getNumReportEventCalls() const;
00263 
00264 
00266         // REALIZATION //
00268 
00281     const State& realizeTopology() const;
00282 
00295     const State& getDefaultState() const;
00296     State&       updDefaultState();
00297 
00313     void realizeModel(State&) const;
00314 
00322     void realize(const State& s, Stage g = Stage::HighestRuntime) const;
00323 
00331     void calcDecorativeGeometryAndAppend(const State&, Stage, 
00332                                          Array_<DecorativeGeometry>&) const;
00333 
00335         // THE CONTINUOUS SYSTEM //
00337 
00338             // UNCONSTRAINED
00339 
00347     Real calcTimescale(const State&) const;
00348 
00364     void calcYUnitWeights(const State&, Vector& weights) const;
00365 
00366             // CONSTRAINED
00367 
00382     void prescribe(State&, Stage) const;
00383 
00401     void project(State&, Real consAccuracy, const Vector& yWeights,
00402                  const Vector& cWeights, Vector& yerrest, 
00403                  ProjectOptions=ProjectOptions::All) const;
00404 
00413     void calcYErrUnitTolerances(const State&, Vector& tolerances) const;
00414 
00415             // FAST VARIABLES
00416 
00437     void relax(State&, Stage, Real accuracy, 
00438                const Vector& yWeights, const Vector& cWeights) const;
00439 
00440 
00442         // THE DISCRETE (SLOW) SYSTEM //
00444 
00450     void setHasTimeAdvancedEvents(bool); // default=false
00451     bool hasTimeAdvancedEvents() const;
00452 
00471     void handleEvents
00472         (State&, Event::Cause, const Array_<EventId>& eventIds,
00473         Real accuracy, const Vector& yWeights, const Vector& cWeights,
00474         Stage& lowestModified, bool& shouldTerminate) const;
00475     
00479     void reportEvents(const State& s, Event::Cause cause, 
00480                       const Array_<EventId>& eventIds) const;
00481 
00491     void calcEventTriggerInfo(const State&, Array_<EventTriggerInfo>&) const;
00492 
00498     void calcTimeOfNextScheduledEvent(const State&, Real& tNextEvent, 
00499                                       Array_<EventId>& eventIds, bool includeCurrentTime) const;
00500 
00504     void calcTimeOfNextScheduledReport(const State&, Real& tNextEvent, 
00505                                        Array_<EventId>& eventIds, bool includeCurrentTime) const;
00506     
00507     //TODO: these operators should be provided by the Vector class where they
00508     //can be performed more efficiently.
00509 
00510     static Real calcWeightedRMSNorm(const Vector& values, const Vector& weights) {
00511         assert(weights.size() == values.size());
00512         if (values.size()==0) return 0;
00513         Real sumsq = 0;
00514         for (int i=0; i<values.size(); ++i) {
00515             const Real wv = weights[i]*values[i];
00516             sumsq += wv*wv;
00517         }
00518         return std::sqrt(sumsq/weights.size());
00519     }
00520 
00521     static Real calcWeightedInfinityNorm(const Vector& values, const Vector& weights) {
00522         assert(weights.size() == values.size());
00523         if (values.size()==0) return 0;
00524         Real maxval = 0;
00525         for (int i=0; i<values.size(); ++i) {
00526             const Real wv = std::abs(weights[i]*values[i]);
00527             if (wv > maxval) maxval=wv;
00528         }
00529         return maxval;
00530     }
00531 
00534     SubsystemIndex adoptSubsystem(Subsystem& child);
00535 
00537     int getNumSubsystems() const;
00539     const Subsystem& getSubsystem(SubsystemIndex)   const;
00541     Subsystem&       updSubsystem(SubsystemIndex);
00543     const DefaultSystemSubsystem& getDefaultSubsystem() const;
00545     DefaultSystemSubsystem& updDefaultSubsystem();
00546 
00550     inline operator const Subsystem&() const; // implemented below
00554     inline operator Subsystem&();
00555 
00556     // Internal use only
00557     bool isOwnerHandle() const;
00558     bool isEmptyHandle() const;
00559 
00560     // There can be multiple handles on the same System.
00561     bool isSameSystem(const System& otherSystem) const;
00562 
00567     bool systemTopologyHasBeenRealized() const;
00568 
00569     // dynamic_cast the returned reference to a reference to your concrete Guts
00570     // class.
00571     const System::Guts& getSystemGuts() const {assert(guts); return *guts;}
00572     System::Guts&       updSystemGuts()       {assert(guts); return *guts;}
00573 
00574     // Put new *unowned* Guts into this *empty* handle and take over ownership.
00575     // If this handle is already in use, or if Guts is already owned this
00576     // routine will throw an exception.
00577     void adoptSystemGuts(System::Guts* g);
00578 
00579     explicit System(System::Guts* g) : guts(g) { }
00580     bool hasGuts() const {return guts!=0;}
00581 
00582 private:
00583     // OBSOLETE
00584     // Part of our ongoing crusade to turn getN's into getNums for API consistency.
00585     int getNSubsystems() const {return getNumSubsystems();}
00586 };
00587 
00588 
00597 class SimTK_SimTKCOMMON_EXPORT DefaultSystemSubsystem : public Subsystem {
00598 public:
00599     explicit DefaultSystemSubsystem(System& sys);
00600     void addEventHandler(ScheduledEventHandler* handler);
00601     void addEventHandler(TriggeredEventHandler* handler);
00602     void addEventReporter(ScheduledEventReporter* handler) const;
00603     void addEventReporter(TriggeredEventReporter* handler) const;
00604     EventId createEventId(SubsystemIndex subsys, const State& state) const;
00605     void findSubsystemEventIds
00606        (SubsystemIndex subsys, const State& state, 
00607         const Array_<EventId>& allEvents, 
00608         Array_<EventId>& eventsForSubsystem) const;
00609   // don't let doxygen see this private class
00611     class Guts;
00613 private:
00614     const Guts& getGuts() const;
00615     Guts& updGuts();
00616 };
00617 
00618 inline void System::addEventHandler(ScheduledEventHandler* handler)
00619 {   updDefaultSubsystem().addEventHandler(handler); }
00620 inline void System::addEventHandler(TriggeredEventHandler* handler)
00621 {   updDefaultSubsystem().addEventHandler(handler); }
00622 inline void System::addEventReporter(ScheduledEventReporter* handler) const
00623 {   getDefaultSubsystem().addEventReporter(handler); }
00624 inline void System::addEventReporter(TriggeredEventReporter* handler) const
00625 {   getDefaultSubsystem().addEventReporter(handler); }
00626 
00627 inline System::operator const Subsystem&() const {return getDefaultSubsystem();}
00628 inline System::operator Subsystem&() {return updDefaultSubsystem();}
00629 
00630 inline static System::ProjectOptions operator|(System::ProjectOptions::Option  o1,    System::ProjectOptions::Option o2)    {return System::ProjectOptions(o1) |= o2;}
00631 inline static System::ProjectOptions operator|(System::ProjectOptions          opts,  System::ProjectOptions::Option o)     {return opts |= o;}
00632 inline static System::ProjectOptions operator|(System::ProjectOptions::Option  o,     System::ProjectOptions         opts)  {return opts |= o;}
00633 inline static System::ProjectOptions operator&(System::ProjectOptions::Option  o1,    System::ProjectOptions::Option o2)    {return System::ProjectOptions(o1) &= o2;}
00634 inline static System::ProjectOptions operator&(System::ProjectOptions          opts,  System::ProjectOptions::Option o)     {return opts &= o;}
00635 inline static System::ProjectOptions operator&(System::ProjectOptions::Option  o,     System::ProjectOptions         opts)  {return opts &= o;}
00636 inline static System::ProjectOptions operator~(System::ProjectOptions::Option  o)                                           {return ~System::ProjectOptions(o);}
00637 inline static System::ProjectOptions operator-(System::ProjectOptions          opts,  System::ProjectOptions::Option o)     {return opts -= o;}
00638 inline static System::ProjectOptions operator-(System::ProjectOptions          opts1, System::ProjectOptions         opts2) {return opts1 -= opts2;}
00639 
00640 } // namespace SimTK
00641 
00642 #endif // SimTK_SimTKCOMMON_SYSTEM_H_
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines