Simbody
|
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_