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-7 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 
00049 SimTK_DEFINE_UNIQUE_INDEX_TYPE(EventId);
00050 
00098 class SimTK_SimTKCOMMON_EXPORT System {
00099 public:
00100     class Guts; // local; name is System::Guts
00101     friend class Guts;
00102 private:
00103     // This is the only data member in this class. Also, any class derived from
00104     // System must have *NO* data members at all (data goes in the Guts class).
00105     Guts* guts;
00106 public:
00107     System() : guts(0) { }
00108     System(const System&);
00109     System& operator=(const System&);
00110     ~System();
00111 
00112     const String& getName()    const;
00113     const String& getVersion() const;
00114 
00115 
00116     class ProjectOptions {
00117         unsigned long optionSet;
00118         explicit ProjectOptions(unsigned int o) : optionSet(o) { }
00119     public:
00120 
00121         enum Option {
00122             None   = 0x00,
00123 
00124             Q      = 0x01,
00125             U      = 0x02,
00126             QError = 0x04,
00127             UError = 0x08,
00128 
00129             PositionOnly = (Q|QError),
00130             VelocityOnly = (U|UError),
00131             All          = (PositionOnly|VelocityOnly)
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     long getNumRealizationsOfThisStage(Stage) const;
00177 
00181     long getNumRealizeCalls() const;
00182 
00183         // Projection
00184 
00187     long getNumQProjections() const;
00188     long getNumUProjections() const;
00189     long getNumQErrorEstimateProjections() const;
00190     long getNumUErrorEstimateProjections() const;
00191 
00194     long getNumProjectCalls() const;
00195 
00196         // Event handling and reporting
00197 
00201     long getNumHandlerCallsThatChangedStage(Stage) const;
00202 
00205     long getNumHandleEventCalls() const;
00206 
00209     long getNumReportEventCalls() const;
00210 
00211 
00213         // REALIZATION //
00215 
00229     const State& realizeTopology() const;
00230 
00231 
00244     const State& getDefaultState() const;
00245     State&       updDefaultState();
00246 
00262     void realizeModel(State&) const;
00263 
00271     void realize(const State& s, Stage g = Stage::HighestRuntime) const;
00272 
00273     // Generate all decorative geometry computable at a specific stage. This will
00274     // throw an exception if the state hasn't already been realized
00275     // to that stage. Note that the list is not inclusive -- you have to
00276     // request geometry from each stage to get all of it.
00277     // This routine asks each subsystem in succession to generate its decorative geometry
00278     // and append it to the end of the vector.
00279     // If the stage is Stage::Topology, realizeTopology() must already have
00280     // been called but the State is ignored.
00281     void calcDecorativeGeometryAndAppend(const State&, Stage, std::vector<DecorativeGeometry>&) const;
00282 
00284         // THE CONTINUOUS SYSTEM //
00286 
00287             // UNCONSTRAINED
00288 
00296     Real calcTimescale(const State&) const;
00297 
00313     void calcYUnitWeights(const State&, Vector& weights) const;
00314 
00315             // CONSTRAINED
00316 
00332     void project(State&, Real consAccuracy, const Vector& yweights,
00333                  const Vector& ootols, Vector& yerrest, ProjectOptions=ProjectOptions::All) const;
00334 
00343     void calcYErrUnitTolerances(const State&, Vector& tolerances) const;
00344 
00345 
00347         // THE DISCRETE SYSTEM //
00349 
00350     class EventTriggerInfo;
00351 
00357     void setHasTimeAdvancedEvents(bool); // default=false
00358     bool hasTimeAdvancedEvents() const;
00359 
00376 
00377     void handleEvents
00378         (State&, Event::Cause, const std::vector<EventId>& eventIds,
00379         Real accuracy, const Vector& yWeights, const Vector& ooConstraintTols,
00380         Stage& lowestModified, bool& shouldTerminate) const;
00381     
00384     
00385     void reportEvents(const State& s, Event::Cause cause, const std::vector<EventId>& eventIds) const;
00386 
00396     void calcEventTriggerInfo(const State&, std::vector<EventTriggerInfo>&) const;
00397 
00403     void calcTimeOfNextScheduledEvent(const State&, Real& tNextEvent, std::vector<EventId>& eventIds, bool includeCurrentTime) const;
00404 
00408     void calcTimeOfNextScheduledReport(const State&, Real& tNextEvent, std::vector<EventId>& eventIds, bool includeCurrentTime) const;
00409     
00410     //TODO: these operators should be provided by the Vector class where they
00411     //can be performed more efficiently.
00412 
00413     static Real calcWeightedRMSNorm(const Vector& values, const Vector& weights) {
00414         assert(weights.size() == values.size());
00415         if (values.size()==0) return 0;
00416         Real sumsq = 0;
00417         for (int i=0; i<values.size(); ++i) {
00418             const Real wv = weights[i]*values[i];
00419             sumsq += wv*wv;
00420         }
00421         return std::sqrt(sumsq/weights.size());
00422     }
00423 
00424     static Real calcWeightedInfinityNorm(const Vector& values, const Vector& weights) {
00425         assert(weights.size() == values.size());
00426         if (values.size()==0) return 0;
00427         Real maxval = 0;
00428         for (int i=0; i<values.size(); ++i) {
00429             const Real wv = std::abs(weights[i]*values[i]);
00430             if (wv > maxval) maxval=wv;
00431         }
00432         return maxval;
00433     }
00434 
00437     SubsystemIndex adoptSubsystem(Subsystem& child);
00438 
00440     int getNSubsystems() const;
00442     const Subsystem& getSubsystem(SubsystemIndex)   const;
00444     Subsystem&       updSubsystem(SubsystemIndex);
00446     const DefaultSystemSubsystem& getDefaultSubsystem() const;
00448     DefaultSystemSubsystem& updDefaultSubsystem();
00449 
00450     // Internal use only
00451     bool isOwnerHandle() const;
00452     bool isEmptyHandle() const;
00453 
00454     // There can be multiple handles on the same System.
00455     bool isSameSystem(const System& otherSystem) const;
00456 
00461     bool systemTopologyHasBeenRealized() const;
00462 
00463     // dynamic_cast the returned reference to a reference to your concrete Guts
00464     // class.
00465     const System::Guts& getSystemGuts() const {assert(guts); return *guts;}
00466     System::Guts&       updSystemGuts()       {assert(guts); return *guts;}
00467 
00468     // Put new *unowned* Guts into this *empty* handle and take over ownership.
00469     // If this handle is already in use, or if Guts is already owned this
00470     // routine will throw an exception.
00471     void adoptSystemGuts(System::Guts* g);
00472 
00473     explicit System(System::Guts* g) : guts(g) { }
00474     bool hasGuts() const {return guts!=0;}
00475 
00476 private:
00477     class EventTriggerInfoRep;
00478 };
00479 
00480 inline static System::ProjectOptions operator|(System::ProjectOptions::Option  o1,    System::ProjectOptions::Option o2)    {return System::ProjectOptions(o1) |= o2;}
00481 inline static System::ProjectOptions operator|(System::ProjectOptions          opts,  System::ProjectOptions::Option o)     {return opts |= o;}
00482 inline static System::ProjectOptions operator|(System::ProjectOptions::Option  o,     System::ProjectOptions         opts)  {return opts |= o;}
00483 inline static System::ProjectOptions operator&(System::ProjectOptions::Option  o1,    System::ProjectOptions::Option o2)    {return System::ProjectOptions(o1) &= o2;}
00484 inline static System::ProjectOptions operator&(System::ProjectOptions          opts,  System::ProjectOptions::Option o)     {return opts &= o;}
00485 inline static System::ProjectOptions operator&(System::ProjectOptions::Option  o,     System::ProjectOptions         opts)  {return opts &= o;}
00486 inline static System::ProjectOptions operator~(System::ProjectOptions::Option  o)                                           {return ~System::ProjectOptions(o);}
00487 inline static System::ProjectOptions operator-(System::ProjectOptions          opts,  System::ProjectOptions::Option o)     {return opts -= o;}
00488 inline static System::ProjectOptions operator-(System::ProjectOptions          opts1, System::ProjectOptions         opts2) {return opts1 -= opts2;}
00489 
00490 
00491 
00502 class SimTK_SimTKCOMMON_EXPORT System::EventTriggerInfo {
00503 public:
00504     EventTriggerInfo();
00505     explicit EventTriggerInfo(EventId eventId);
00506     ~EventTriggerInfo();
00507     EventTriggerInfo(const EventTriggerInfo&);
00508     EventTriggerInfo& operator=(const EventTriggerInfo&);
00509 
00510     EventId getEventId() const; // returns -1 if not set
00511     bool shouldTriggerOnRisingSignTransition()  const; // default=true
00512     bool shouldTriggerOnFallingSignTransition() const; // default=true
00513     Real getRequiredLocalizationTimeWindow()    const; // default=0.1
00514 
00515     // These return the modified 'this', like assignment operators.
00516     EventTriggerInfo& setEventId(EventId);
00517     EventTriggerInfo& setTriggerOnRisingSignTransition(bool);
00518     EventTriggerInfo& setTriggerOnFallingSignTransition(bool);
00519     EventTriggerInfo& setRequiredLocalizationTimeWindow(Real);
00520 
00521     Event::Trigger calcTransitionMask() const {
00522         unsigned mask = 0;
00523         if (shouldTriggerOnRisingSignTransition()) {
00524             mask |= Event::NegativeToPositive;
00525         }
00526         if (shouldTriggerOnFallingSignTransition()) {
00527             mask |= Event::PositiveToNegative;
00528         }
00529         return Event::Trigger(mask);
00530     }
00531 
00532     Event::Trigger calcTransitionToReport
00533        (Event::Trigger transitionSeen) const
00534     {
00535         // report -1 to 1 or 1 to -1 as appropriate
00536         if (transitionSeen & Event::Rising)
00537             return Event::NegativeToPositive;
00538         if (transitionSeen & Event::Falling)
00539             return Event::PositiveToNegative;
00540         assert(!"impossible event transition situation");
00541         return Event::NoEventTrigger;
00542     }
00543 
00544 private:
00545     // opaque implementation for binary compatibility
00546     System::EventTriggerInfoRep* rep;
00547 
00548     const System::EventTriggerInfoRep& getRep() const {assert(rep); return *rep;}
00549     System::EventTriggerInfoRep&       updRep()       {assert(rep); return *rep;}
00550 };
00551 
00552 } // namespace SimTK
00553 
00554 #endif // SimTK_SimTKCOMMON_SYSTEM_H_

Generated by  doxygen 1.6.2