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 
00051 
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::HighestValid) 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 
00387 
00388     enum EventCause {
00389         TriggeredEvents    =1,
00390         ScheduledEvents    =2,
00391         TimeAdvancedEvent  =3,
00392         TerminationEvent   =4,
00393 
00394         InvalidEventCause  = -1
00395     };
00396     static const char* getEventCauseName(EventCause);
00397 
00398 
00415 
00416     void handleEvents
00417        (State&, EventCause, const std::vector<EventId>& eventIds,
00418         Real accuracy, const Vector& yWeights, const Vector& ooConstraintTols,
00419         Stage& lowestModified, bool& shouldTerminate) const;
00420     
00423     
00424     void reportEvents(const State& s, EventCause cause, const std::vector<EventId>& eventIds) const;
00425 
00435     void calcEventTriggerInfo(const State&, std::vector<EventTriggerInfo>&) const;
00436 
00442     void calcTimeOfNextScheduledEvent(const State&, Real& tNextEvent, std::vector<EventId>& eventIds, bool includeCurrentTime) const;
00443 
00447     void calcTimeOfNextScheduledReport(const State&, Real& tNextEvent, std::vector<EventId>& eventIds, bool includeCurrentTime) const;
00448     
00449     //TODO: these operators should be provided by the Vector class where they
00450     //can be perfomed more efficiently.
00451 
00452     static Real calcWeightedRMSNorm(const Vector& values, const Vector& weights) {
00453         assert(weights.size() == values.size());
00454         if (values.size()==0) return 0;
00455         Real sumsq = 0;
00456         for (int i=0; i<values.size(); ++i) {
00457             const Real wv = weights[i]*values[i];
00458             sumsq += wv*wv;
00459         }
00460         return std::sqrt(sumsq/weights.size());
00461     }
00462 
00463     static Real calcWeightedInfinityNorm(const Vector& values, const Vector& weights) {
00464         assert(weights.size() == values.size());
00465         if (values.size()==0) return 0;
00466         Real maxval = 0;
00467         for (int i=0; i<values.size(); ++i) {
00468             const Real wv = std::abs(weights[i]*values[i]);
00469             if (wv > maxval) maxval=wv;
00470         }
00471         return maxval;
00472     }
00473 
00476     SubsystemIndex adoptSubsystem(Subsystem& child);
00477 
00479     int getNSubsystems() const;
00481     const Subsystem& getSubsystem(SubsystemIndex)   const;
00483     Subsystem&       updSubsystem(SubsystemIndex);
00485     const DefaultSystemSubsystem& getDefaultSubsystem() const;
00487     DefaultSystemSubsystem& updDefaultSubsystem();
00488 
00489     // Internal use only
00490     bool isOwnerHandle() const;
00491     bool isEmptyHandle() const;
00492 
00493     // There can be multiple handles on the same System.
00494     bool isSameSystem(const System& otherSystem) const;
00495 
00500     bool systemTopologyHasBeenRealized() const;
00501 
00502     // dynamic_cast the returned reference to a reference to your concrete Guts
00503     // class.
00504     const System::Guts& getSystemGuts() const {assert(guts); return *guts;}
00505     System::Guts&       updSystemGuts()       {assert(guts); return *guts;}
00506 
00507     // Put new *unowned* Guts into this *empty* handle and take over ownership.
00508     // If this handle is already in use, or if Guts is already owned this
00509     // routine will throw an exception.
00510     void adoptSystemGuts(System::Guts* g);
00511 
00512     explicit System(System::Guts* g) : guts(g) { }
00513     bool hasGuts() const {return guts!=0;}
00514 
00515 private:
00516     class EventTriggerInfoRep;
00517 };
00518 
00519 inline static System::ProjectOptions operator|(System::ProjectOptions::Option  o1,    System::ProjectOptions::Option o2)    {return System::ProjectOptions(o1) |= o2;}
00520 inline static System::ProjectOptions operator|(System::ProjectOptions          opts,  System::ProjectOptions::Option o)     {return opts |= o;}
00521 inline static System::ProjectOptions operator|(System::ProjectOptions::Option  o,     System::ProjectOptions         opts)  {return opts |= o;}
00522 inline static System::ProjectOptions operator&(System::ProjectOptions::Option  o1,    System::ProjectOptions::Option o2)    {return System::ProjectOptions(o1) &= o2;}
00523 inline static System::ProjectOptions operator&(System::ProjectOptions          opts,  System::ProjectOptions::Option o)     {return opts &= o;}
00524 inline static System::ProjectOptions operator&(System::ProjectOptions::Option  o,     System::ProjectOptions         opts)  {return opts &= o;}
00525 inline static System::ProjectOptions operator~(System::ProjectOptions::Option  o)                                           {return ~System::ProjectOptions(o);}
00526 inline static System::ProjectOptions operator-(System::ProjectOptions          opts,  System::ProjectOptions::Option o)     {return opts -= o;}
00527 inline static System::ProjectOptions operator-(System::ProjectOptions          opts1, System::ProjectOptions         opts2) {return opts1 -= opts2;}
00528 
00529 
00530 
00541 class SimTK_SimTKCOMMON_EXPORT System::EventTriggerInfo {
00542 public:
00543     EventTriggerInfo();
00544     explicit EventTriggerInfo(EventId eventId);
00545     ~EventTriggerInfo();
00546     EventTriggerInfo(const EventTriggerInfo&);
00547     EventTriggerInfo& operator=(const EventTriggerInfo&);
00548 
00549     EventId getEventId() const; // returns -1 if not set
00550     bool shouldTriggerOnRisingSignTransition()  const; // default=true
00551     bool shouldTriggerOnFallingSignTransition() const; // default=true
00552     Real getRequiredLocalizationTimeWindow()    const; // default=0.1
00553 
00554     // These return the modified 'this', like assignment operators.
00555     EventTriggerInfo& setEventId(EventId);
00556     EventTriggerInfo& setTriggerOnRisingSignTransition(bool);
00557     EventTriggerInfo& setTriggerOnFallingSignTransition(bool);
00558     EventTriggerInfo& setRequiredLocalizationTimeWindow(Real);
00559 
00560     // TODO: switch to SignTransitionSet and trash EventStatus altogether.
00561     EventStatus::EventTrigger calcTransitionMask() const {
00562         unsigned mask = 0;
00563         if (shouldTriggerOnRisingSignTransition()) {
00564             mask |= EventStatus::NegativeToPositive;
00565         }
00566         if (shouldTriggerOnFallingSignTransition()) {
00567             mask |= EventStatus::PositiveToNegative;
00568         }
00569         return EventStatus::EventTrigger(mask);
00570     }
00571 
00572     EventStatus::EventTrigger calcTransitionToReport
00573        (EventStatus::EventTrigger transitionSeen) const
00574     {
00575         // report -1 to 1 or 1 to -1 as appropriate
00576         if (transitionSeen & EventStatus::Rising)
00577             return EventStatus::NegativeToPositive;
00578         if (transitionSeen & EventStatus::Falling)
00579             return EventStatus::PositiveToNegative;
00580         assert(!"impossible event transition situation");
00581         return EventStatus::NoEventTrigger;
00582     }
00583 
00584 private:
00585     // opaque implementation for future binary compatibility
00586     System::EventTriggerInfoRep* rep;
00587 
00588     const System::EventTriggerInfoRep& getRep() const {assert(rep); return *rep;}
00589     System::EventTriggerInfoRep&       updRep()       {assert(rep); return *rep;}
00590 };
00591 
00592 } // namespace SimTK
00593 
00594 #endif // SimTK_SimTKCOMMON_SYSTEM_H_

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