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-9 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 
00039 namespace SimTK {
00040 
00041 class Subsystem;
00042 class DecorativeGeometry;
00043 class DefaultSystemSubsystem;
00044 
00048 SimTK_DEFINE_UNIQUE_INDEX_TYPE(EventId);
00049 
00092 class SimTK_SimTKCOMMON_EXPORT System {
00093 public:
00094     class Guts; // local; name is System::Guts
00095     friend class Guts;
00096 private:
00097     // This is the only data member in this class. Also, any class derived from
00098     // System must have *NO* data members at all (data goes in the Guts class).
00099     Guts* guts;
00100 public:
00101     System() : guts(0) { }
00102     System(const System&);
00103     System& operator=(const System&);
00104     ~System();
00105 
00106     const String& getName()    const;
00107     const String& getVersion() const;
00108 
00109 
00110     class ProjectOptions {
00111         unsigned long optionSet;
00112         explicit ProjectOptions(unsigned int o) : optionSet(o) { }
00113     public:
00114 
00115         enum Option {
00116             None   = 0x00,
00117 
00118             Q      = 0x01,
00119             U      = 0x02,
00120             QError = 0x04,
00121             UError = 0x08,
00122 
00123             PositionOnly = (Q|QError),
00124             VelocityOnly = (U|UError),
00125             All          = (PositionOnly|VelocityOnly),
00126 
00127             // This option says we expect the state to be close to a 
00128             // solution already and restricts projection to move downhill
00129             // in the local vicinity. This should be used during any
00130             // continuous integration to prevent erroneous jumps in the state.
00131             LocalOnly = 0x1000
00132         };
00133 
00134         ProjectOptions() : optionSet(0) { }
00135 
00136         // This is an implicit conversion
00137         ProjectOptions(Option opt) : optionSet((unsigned long)opt) { }
00138 
00139         // Implicit conversion to bool when needed
00140         operator bool() const {return optionSet != 0;}
00141         bool hasAnyPositionOptions() const {return (optionSet&(unsigned long)PositionOnly) != 0;}
00142         bool hasAnyVelocityOptions() const {return (optionSet&(unsigned long)VelocityOnly) != 0;}
00143         bool isEmpty() const {return optionSet==0;}
00144 
00145         bool isOptionSet(Option opt) const {return (optionSet&(unsigned long)opt) != 0;}
00146         void clear() {optionSet=0;}
00147         void clearOption(Option opt) {optionSet &= ~(unsigned long)opt;}
00148         void setOption  (Option opt) {optionSet |= (unsigned long)opt;}
00149 
00150         // Set operators: not, or, and, set difference
00151         ProjectOptions operator~() const {return ProjectOptions( (~optionSet) & (unsigned long)All );}
00152         ProjectOptions& operator|=(ProjectOptions opts) {optionSet |= opts.optionSet; return *this;}
00153         ProjectOptions& operator&=(ProjectOptions opts) {optionSet &= opts.optionSet; return *this;}
00154         ProjectOptions& operator-=(ProjectOptions opts) {optionSet &= ~opts.optionSet; return *this;}
00155 
00156         ProjectOptions& operator|=(Option opt) {setOption(opt); return *this;}
00157         ProjectOptions& operator-=(Option opt) {clearOption(opt); return *this;}
00158     };
00159 
00161         // STATISTICS //
00163 
00169     void resetAllCountersToZero();
00170 
00171         // Realization
00172 
00176     int getNumRealizationsOfThisStage(Stage) const;
00177 
00181     int getNumRealizeCalls() const;
00182 
00183         // Prescribed motion
00184 
00188     int getNumPrescribeCalls() const;
00189 
00190         // Projection
00191 
00194     int getNumQProjections() const;
00195     int getNumUProjections() const;
00196     int getNumQErrorEstimateProjections() const;
00197     int getNumUErrorEstimateProjections() const;
00198 
00201     int getNumProjectCalls() const;
00202 
00203         // Event handling and reporting
00204 
00208     int getNumHandlerCallsThatChangedStage(Stage) const;
00209 
00212     int getNumHandleEventCalls() const;
00213 
00216     int getNumReportEventCalls() const;
00217 
00218 
00220         // REALIZATION //
00222 
00235     const State& realizeTopology() const;
00236 
00249     const State& getDefaultState() const;
00250     State&       updDefaultState();
00251 
00267     void realizeModel(State&) const;
00268 
00276     void realize(const State& s, Stage g = Stage::HighestRuntime) const;
00277 
00285     void calcDecorativeGeometryAndAppend(const State&, Stage, 
00286                                          Array_<DecorativeGeometry>&) const;
00287 
00289         // THE CONTINUOUS SYSTEM //
00291 
00292             // UNCONSTRAINED
00293 
00301     Real calcTimescale(const State&) const;
00302 
00318     void calcYUnitWeights(const State&, Vector& weights) const;
00319 
00320             // CONSTRAINED
00321 
00336     void prescribe(State&, Stage) const;
00337 
00355     void project(State&, Real consAccuracy, const Vector& yWeights,
00356                  const Vector& cWeights, Vector& yerrest, 
00357                  ProjectOptions=ProjectOptions::All) const;
00358 
00367     void calcYErrUnitTolerances(const State&, Vector& tolerances) const;
00368 
00369             // FAST VARIABLES
00370 
00391     void relax(State&, Stage, Real accuracy, 
00392                const Vector& yWeights, const Vector& cWeights) const;
00393 
00394 
00396         // THE DISCRETE (SLOW) SYSTEM //
00398 
00399     class EventTriggerInfo;
00400 
00406     void setHasTimeAdvancedEvents(bool); // default=false
00407     bool hasTimeAdvancedEvents() const;
00408 
00427     void handleEvents
00428         (State&, Event::Cause, const Array_<EventId>& eventIds,
00429         Real accuracy, const Vector& yWeights, const Vector& cWeights,
00430         Stage& lowestModified, bool& shouldTerminate) const;
00431     
00435     void reportEvents(const State& s, Event::Cause cause, 
00436                       const Array_<EventId>& eventIds) const;
00437 
00447     void calcEventTriggerInfo(const State&, Array_<EventTriggerInfo>&) const;
00448 
00454     void calcTimeOfNextScheduledEvent(const State&, Real& tNextEvent, 
00455                                       Array_<EventId>& eventIds, bool includeCurrentTime) const;
00456 
00460     void calcTimeOfNextScheduledReport(const State&, Real& tNextEvent, 
00461                                        Array_<EventId>& eventIds, bool includeCurrentTime) const;
00462     
00463     //TODO: these operators should be provided by the Vector class where they
00464     //can be performed more efficiently.
00465 
00466     static Real calcWeightedRMSNorm(const Vector& values, const Vector& weights) {
00467         assert(weights.size() == values.size());
00468         if (values.size()==0) return 0;
00469         Real sumsq = 0;
00470         for (int i=0; i<values.size(); ++i) {
00471             const Real wv = weights[i]*values[i];
00472             sumsq += wv*wv;
00473         }
00474         return std::sqrt(sumsq/weights.size());
00475     }
00476 
00477     static Real calcWeightedInfinityNorm(const Vector& values, const Vector& weights) {
00478         assert(weights.size() == values.size());
00479         if (values.size()==0) return 0;
00480         Real maxval = 0;
00481         for (int i=0; i<values.size(); ++i) {
00482             const Real wv = std::abs(weights[i]*values[i]);
00483             if (wv > maxval) maxval=wv;
00484         }
00485         return maxval;
00486     }
00487 
00490     SubsystemIndex adoptSubsystem(Subsystem& child);
00491 
00493     int getNSubsystems() const;
00495     const Subsystem& getSubsystem(SubsystemIndex)   const;
00497     Subsystem&       updSubsystem(SubsystemIndex);
00499     const DefaultSystemSubsystem& getDefaultSubsystem() const;
00501     DefaultSystemSubsystem& updDefaultSubsystem();
00502 
00503     // Internal use only
00504     bool isOwnerHandle() const;
00505     bool isEmptyHandle() const;
00506 
00507     // There can be multiple handles on the same System.
00508     bool isSameSystem(const System& otherSystem) const;
00509 
00514     bool systemTopologyHasBeenRealized() const;
00515 
00516     // dynamic_cast the returned reference to a reference to your concrete Guts
00517     // class.
00518     const System::Guts& getSystemGuts() const {assert(guts); return *guts;}
00519     System::Guts&       updSystemGuts()       {assert(guts); return *guts;}
00520 
00521     // Put new *unowned* Guts into this *empty* handle and take over ownership.
00522     // If this handle is already in use, or if Guts is already owned this
00523     // routine will throw an exception.
00524     void adoptSystemGuts(System::Guts* g);
00525 
00526     explicit System(System::Guts* g) : guts(g) { }
00527     bool hasGuts() const {return guts!=0;}
00528 
00529 private:
00530     class EventTriggerInfoRep;
00531 };
00532 
00533 inline static System::ProjectOptions operator|(System::ProjectOptions::Option  o1,    System::ProjectOptions::Option o2)    {return System::ProjectOptions(o1) |= o2;}
00534 inline static System::ProjectOptions operator|(System::ProjectOptions          opts,  System::ProjectOptions::Option o)     {return opts |= o;}
00535 inline static System::ProjectOptions operator|(System::ProjectOptions::Option  o,     System::ProjectOptions         opts)  {return opts |= o;}
00536 inline static System::ProjectOptions operator&(System::ProjectOptions::Option  o1,    System::ProjectOptions::Option o2)    {return System::ProjectOptions(o1) &= o2;}
00537 inline static System::ProjectOptions operator&(System::ProjectOptions          opts,  System::ProjectOptions::Option o)     {return opts &= o;}
00538 inline static System::ProjectOptions operator&(System::ProjectOptions::Option  o,     System::ProjectOptions         opts)  {return opts &= o;}
00539 inline static System::ProjectOptions operator~(System::ProjectOptions::Option  o)                                           {return ~System::ProjectOptions(o);}
00540 inline static System::ProjectOptions operator-(System::ProjectOptions          opts,  System::ProjectOptions::Option o)     {return opts -= o;}
00541 inline static System::ProjectOptions operator-(System::ProjectOptions          opts1, System::ProjectOptions         opts2) {return opts1 -= opts2;}
00542 
00543 
00544 
00555 class SimTK_SimTKCOMMON_EXPORT System::EventTriggerInfo {
00556 public:
00557     EventTriggerInfo();
00558     explicit EventTriggerInfo(EventId eventId);
00559     ~EventTriggerInfo();
00560     EventTriggerInfo(const EventTriggerInfo&);
00561     EventTriggerInfo& operator=(const EventTriggerInfo&);
00562 
00563     EventId getEventId() const; // returns -1 if not set
00564     bool shouldTriggerOnRisingSignTransition()  const; // default=true
00565     bool shouldTriggerOnFallingSignTransition() const; // default=true
00566     Real getRequiredLocalizationTimeWindow()    const; // default=0.1
00567 
00568     // These return the modified 'this', like assignment operators.
00569     EventTriggerInfo& setEventId(EventId);
00570     EventTriggerInfo& setTriggerOnRisingSignTransition(bool);
00571     EventTriggerInfo& setTriggerOnFallingSignTransition(bool);
00572     EventTriggerInfo& setRequiredLocalizationTimeWindow(Real);
00573 
00574     Event::Trigger calcTransitionMask() const {
00575         unsigned mask = 0;
00576         if (shouldTriggerOnRisingSignTransition()) {
00577             mask |= Event::NegativeToPositive;
00578         }
00579         if (shouldTriggerOnFallingSignTransition()) {
00580             mask |= Event::PositiveToNegative;
00581         }
00582         return Event::Trigger(mask);
00583     }
00584 
00585     Event::Trigger calcTransitionToReport
00586        (Event::Trigger transitionSeen) const
00587     {
00588         // report -1 to 1 or 1 to -1 as appropriate
00589         if (transitionSeen & Event::Rising)
00590             return Event::NegativeToPositive;
00591         if (transitionSeen & Event::Falling)
00592             return Event::PositiveToNegative;
00593         assert(!"impossible event transition situation");
00594         return Event::NoEventTrigger;
00595     }
00596 
00597 private:
00598     // opaque implementation for binary compatibility
00599     System::EventTriggerInfoRep* rep;
00600 
00601     const System::EventTriggerInfoRep& getRep() const {assert(rep); return *rep;}
00602     System::EventTriggerInfoRep&       updRep()       {assert(rep); return *rep;}
00603 };
00604 
00605 } // namespace SimTK
00606 
00607 #endif // SimTK_SimTKCOMMON_SYSTEM_H_

Generated on Thu Aug 12 16:37:30 2010 for SimTKcore by  doxygen 1.6.1