Simbody
|
00001 #ifndef SimTK_SimTKCOMMON_SUBSYSTEM_GUTS_H_ 00002 #define SimTK_SimTKCOMMON_SUBSYSTEM_GUTS_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: * 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 #include <cassert> 00040 00041 namespace SimTK { 00042 00043 class System; 00044 class DecorativeGeometry; 00045 00046 00050 class SimTK_SimTKCOMMON_EXPORT Subsystem::Guts { 00051 public: 00052 Guts(const Guts&); 00053 Guts& operator=(const Guts&); 00054 00055 // This constructor is for use by concrete Subsystems. Note that this 00056 // serves as a default constructor since both arguments have defaults. 00057 explicit Guts(const String& name="<NONAME>", 00058 const String& version="0.0.0"); 00059 virtual ~Guts(); 00060 00061 const String& getName() const; 00062 const String& getVersion() const; 00063 00064 // Use these to allocate state variables and cache entries that are owned 00065 // by this Subsystem. 00066 00067 // qdot, qdotdot also allocated in cache 00068 QIndex allocateQ(State& s, const Vector& qInit) const; 00069 // udot is also allocated in the cache 00070 UIndex allocateU(State& s, const Vector& uInit) const; 00071 // zdot is also allocated in the cache 00072 ZIndex allocateZ(State& s, const Vector& zInit) const; 00073 00074 DiscreteVariableIndex allocateDiscreteVariable(State& s, Stage g, AbstractValue* v) const; 00075 DiscreteVariableIndex allocateAutoUpdateDiscreteVariable 00076 (State&, Stage invalidates, AbstractValue* v, Stage updateDependsOn) const; 00077 00078 // Cache entries 00079 CacheEntryIndex allocateCacheEntry 00080 (const State&, Stage dependsOn, Stage computedBy, AbstractValue* v) const; 00081 CacheEntryIndex allocateCacheEntry 00082 (const State& state, Stage g, AbstractValue* v) const 00083 { return allocateCacheEntry(state, g, g, v); } 00084 CacheEntryIndex allocateLazyCacheEntry 00085 (const State& state, Stage earliest, AbstractValue* v) const 00086 { return allocateCacheEntry(state, earliest, Stage::Infinity, v); } 00087 00088 // qerr, uerr, udoterr are all cache entries, not variables 00089 // allocating udoterr also allocates matching multipliers 00090 QErrIndex allocateQErr(const State& s, int nqerr) const; 00091 UErrIndex allocateUErr(const State& s, int nuerr) const; 00092 UDotErrIndex allocateUDotErr(const State& s, int nudoterr) const; 00093 EventTriggerByStageIndex allocateEventTriggersByStage(const State&, Stage, int ntriggers) const; 00094 00095 00096 // These return views on State shared global resources. The views 00097 // are private to this subsystem, but the global resources themselves 00098 // are not allocated until the *System* advances to stage Model. 00099 // Note that there is no subsystem equivalent of the State's "y" 00100 // vector because in general a subsystem's state variables will 00101 // not be contiguous. However, a subsystem's q's, u's, and z's 00102 // will all be contiguous within those arrays. 00103 const Vector& getQ(const State&) const; 00104 const Vector& getU(const State&) const; 00105 const Vector& getZ(const State&) const; 00106 const Vector& getQDot(const State&) const; 00107 const Vector& getUDot(const State&) const; 00108 const Vector& getZDot(const State&) const; 00109 const Vector& getQDotDot(const State&) const; 00110 const Vector& getQErr(const State&) const; 00111 const Vector& getUErr(const State&) const; 00112 const Vector& getUDotErr(const State&) const; 00113 const Vector& getMultipliers(const State&) const; 00114 const Vector& getEventTriggersByStage(const State&, Stage) const; 00115 00116 // These return writable access to this subsystem's partition in the 00117 // State pool of continuous variables. These can be called at Stage::Model 00118 // or higher, and if necesary they invalidate the Position (q), Velocity (u), 00119 // or Dynamics (z) stage respectively. 00120 Vector& updQ(State&) const; // invalidates Stage::Position 00121 Vector& updU(State&) const; // invalidates Stage::Velocity 00122 Vector& updZ(State&) const; // invalidates Stage::Dynamics 00123 00124 // For convenience. 00125 void setQ(State& s, const Vector& q) const { 00126 assert(q.size() == getNQ(s)); 00127 updQ(s) = q; 00128 } 00129 void setU(State& s, const Vector& u) const { 00130 assert(u.size() == getNU(s)); 00131 updU(s) = u; 00132 } 00133 void setZ(State& s, const Vector& z) const { 00134 assert(z.size() == getNZ(s)); 00135 updZ(s) = z; 00136 } 00137 00138 // These update the State cache which is mutable; hence, const State. They 00139 // can be called only if the previous stage has already been realized, e.g., 00140 // updQDot() is allowed only while realizing the Velocity stage, requiring 00141 // that Position stage has already been realized. 00142 Vector& updQDot(const State&) const; 00143 Vector& updUDot(const State&) const; 00144 Vector& updZDot(const State&) const; 00145 Vector& updQDotDot(const State&) const; 00146 Vector& updQErr(const State&) const; 00147 Vector& updUErr(const State&) const; 00148 Vector& updUDotErr(const State&) const; 00149 Vector& updMultipliers(const State&) const; 00150 Vector& updEventTriggersByStage(const State&, Stage) const; 00151 00152 // These pull out the State entries which belong exclusively to 00153 // this Subsystem. These variables and cache entries are available 00154 // as soon as this subsystem is at stage Model. 00155 Stage getStage(const State&) const; 00156 const AbstractValue& getDiscreteVariable(const State&, DiscreteVariableIndex) const; 00157 00158 Real getDiscreteVarLastUpdateTime(const State& s, DiscreteVariableIndex dx) const 00159 { return s.getDiscreteVarLastUpdateTime(getMySubsystemIndex(),dx); } 00160 CacheEntryIndex getDiscreteVarUpdateIndex(const State& s, DiscreteVariableIndex dx) const 00161 { return s.getDiscreteVarUpdateIndex(getMySubsystemIndex(),dx); } 00162 const AbstractValue& getDiscreteVarUpdateValue(const State& s, DiscreteVariableIndex dx) const 00163 { return s.getDiscreteVarUpdateValue(getMySubsystemIndex(),dx); } 00164 AbstractValue& updDiscreteVarUpdateValue(const State& s, DiscreteVariableIndex dx) const 00165 { return s.updDiscreteVarUpdateValue(getMySubsystemIndex(),dx); } 00166 bool isDiscreteVarUpdateValueRealized(const State& s, DiscreteVariableIndex dx) const 00167 { return s.isDiscreteVarUpdateValueRealized(getMySubsystemIndex(),dx); } 00168 void markDiscreteVarUpdateValueRealized(const State& s, DiscreteVariableIndex dx) const 00169 { return s.markDiscreteVarUpdateValueRealized(getMySubsystemIndex(),dx); } 00170 00171 // State is *not* mutable here -- must have write access to change state variables. 00172 AbstractValue& updDiscreteVariable(State&, DiscreteVariableIndex) const; 00173 const AbstractValue& getCacheEntry(const State&, CacheEntryIndex) const; 00174 // State is mutable here. 00175 AbstractValue& updCacheEntry(const State&, CacheEntryIndex) const; 00176 00177 bool isCacheValueRealized(const State&, CacheEntryIndex) const; 00178 void markCacheValueRealized(const State&, CacheEntryIndex) const; 00179 void markCacheValueNotRealized(const State&, CacheEntryIndex) const; 00180 00181 // Dimensions. These are valid at System Stage::Model while access to the various 00182 // arrays may have stricter requirements. Hence it is better to use these 00183 // routines than to get a reference to a Vector above and ask for its size(). 00184 00185 SystemQIndex getQStart (const State&) const; 00186 int getNQ (const State&) const; 00187 SystemUIndex getUStart (const State&) const; 00188 int getNU (const State&) const; 00189 SystemZIndex getZStart (const State&) const; 00190 int getNZ (const State&) const; 00191 SystemQErrIndex getQErrStart (const State&) const; 00192 int getNQErr (const State&) const; 00193 SystemUErrIndex getUErrStart (const State&) const; 00194 int getNUErr (const State&) const; 00195 SystemUDotErrIndex getUDotErrStart(const State&) const; 00196 int getNUDotErr (const State&) const; 00197 SystemMultiplierIndex getMultipliersStart(const State&) const; 00198 int getNMultipliers(const State&) const; 00199 SystemEventTriggerByStageIndex getEventTriggerStartByStage(const State&, Stage) const; 00200 int getNEventTriggersByStage(const State&, Stage) const; 00201 00202 MeasureIndex adoptMeasure(AbstractMeasure& m); 00203 AbstractMeasure getMeasure(MeasureIndex) const; 00204 template <class T> Measure_<T> getMeasure_(MeasureIndex mx) const 00205 { return Measure_<T>::getAs(getMeasure(mx));} 00206 00207 bool isInSystem() const; 00208 bool isInSameSystem(const Subsystem& otherSubsystem) const; 00209 00210 const System& getSystem() const; 00211 System& updSystem(); 00212 00213 SubsystemIndex getMySubsystemIndex() const; 00214 00215 // Internal use only 00216 const Subsystem& getOwnerSubsystemHandle() const; 00217 Subsystem& updOwnerSubsystemHandle(); 00218 void setOwnerSubsystemHandle(Subsystem&); 00219 bool hasOwnerSubsystemHandle() const; 00220 00221 void setSystem(System&, SubsystemIndex); 00222 00223 class GutsRep; 00224 explicit Guts(GutsRep* r) : rep(r) { } 00225 bool hasRep() const {return rep!=0;} 00226 const GutsRep& getRep() const {assert(rep); return *rep;} 00227 GutsRep& updRep() const {assert(rep); return *rep;} 00228 void setRep(GutsRep& r) {assert(!rep); rep = &r;} 00229 00230 bool subsystemTopologyHasBeenRealized() const; 00231 void invalidateSubsystemTopologyCache() const; 00232 00233 // These are wrappers for the virtual methods defined below. They 00234 // are used to ensure good behavior. 00235 00236 Subsystem::Guts* clone() const; 00237 00238 // Realize this subsystem's part of the State from Stage-1 to Stage 00239 // for the indicated stage. After doing some checking, these routines 00240 // call the concrete subsystem's corresponding virtual method, and 00241 // on return they make sure the stage has been properly updated. 00242 // Note that these will do nothing if the Subsystem stage is already 00243 // at or greater than the indicated stage. 00244 void realizeSubsystemTopology (State&) const; 00245 void realizeSubsystemModel (State&) const; 00246 void realizeSubsystemInstance (const State&) const; 00247 void realizeSubsystemTime (const State&) const; 00248 void realizeSubsystemPosition (const State&) const; 00249 void realizeSubsystemVelocity (const State&) const; 00250 void realizeSubsystemDynamics (const State&) const; 00251 void realizeSubsystemAcceleration(const State&) const; 00252 void realizeSubsystemReport (const State&) const; 00253 00254 // Calculate weights and tolerances. 00255 00256 // Given the current values of our own position variables, 00257 // calculate a "unit weighting" for changes to these position 00258 // variables. 00259 // @param[out] weights must be resizable or already the right size 00260 // @pre State must be realized to >= Stage::Position (this subsystem). 00261 void calcQUnitWeights(const State&, Vector& weights) const; 00262 00263 // Given the current values of our own position variables, 00264 // calculate a "unit weighting" for changes to our velocity 00265 // variables. 00266 // @param[out] weights must be resizable or already the right size 00267 // @pre State must be realized to >= Stage::Position (this subsystem). 00268 void calcUUnitWeights(const State&, Vector& weights) const; 00269 00270 // Given the current values of our own position variables, 00271 // calculate a "unit weighting" for changes to our auxiliary 00272 // variables. 00273 // @param[out] weights must be resizable or already the right size 00274 // @pre State must be realized to >= Stage::Position (this subsystem). 00275 void calcZUnitWeights(const State&, Vector& weights) const; 00276 00277 // Calculate a "unit tolerance" for errors in each of this subsystem's 00278 // position-level constraints. 00279 // @param[out] tolerances must be resizable or already the right size 00280 // @pre State must be realized to >= Stage::Model (this subsystem). 00281 // @remark Tolerances are expected to be constant during a study; typically 00282 // they just reflect the units in which the contraint equations 00283 // are calculated, e.g. angles or lengths. 00284 void calcQErrUnitTolerances(const State&, Vector& tolerances) const; 00285 00286 // Calculate a "unit tolerance" for errors in each of this subsystem's 00287 // velocity-level constraints. 00288 // @param[out] tolerances must be resizable or already the right size 00289 // @pre State must be realized to >= Stage::Model (this subsystem). 00290 // @remark Tolerances are expected to be constant during a study; typically 00291 // they just reflect the units in which the contraint equations 00292 // are calculated, e.g. angles/time or lengths/time. 00293 void calcUErrUnitTolerances(const State&, Vector& tolerances) const; 00294 00295 // Generate decorative geometry computable at a specific stage. This will 00296 // throw an exception if this subsystem's state hasn't already been realized 00297 // to that stage. Note that the list is not inclusive -- you have to 00298 // request geometry from each stage to get all of it. 00299 // The generated geometry will be *appended* to the supplied output vector. 00300 void calcDecorativeGeometryAndAppend 00301 (const State&, Stage, Array_<DecorativeGeometry>&) const; 00302 00303 void createScheduledEvent(const State& state, EventId& eventId) const; 00304 void createTriggeredEvent(const State& state, EventId& eventId, 00305 EventTriggerByStageIndex& triggerFunctionIndex, 00306 Stage stage) const; 00307 00308 // These methods are called by the corresponding methods of System. 00309 // Each subsystem is responsible for defining its own events, and 00310 // System then combines the information from them, and dispatches events 00311 // to the appropriate subsystems for handling when they occur. 00312 virtual void calcEventTriggerInfo 00313 (const State&, Array_<EventTriggerInfo>&) const; 00314 virtual void calcTimeOfNextScheduledEvent 00315 (const State&, Real& tNextEvent, Array_<EventId>& eventIds, 00316 bool includeCurrentTime) const; 00317 virtual void calcTimeOfNextScheduledReport 00318 (const State&, Real& tNextEvent, Array_<EventId>& eventIds, 00319 bool includeCurrentTime) const; 00320 virtual void handleEvents 00321 (State&, Event::Cause, const Array_<EventId>& eventIds, 00322 Real accuracy, const Vector& yWeights, const Vector& ooConstraintTols, 00323 Stage& lowestModified, bool& shouldTerminate) const; 00324 virtual void reportEvents 00325 (const State&, Event::Cause, const Array_<EventId>& eventIds) const; 00326 00327 protected: 00328 // These virtual methods should be overridden in concrete Subsystems as 00329 // necessary. They should never be called directly; instead call the 00330 // wrapper routines above, which have the same name but without the "Impl" 00331 // (implementation) at the end. 00332 00333 // The "realize..." wrappers will call the "realize...Impl" methods below 00334 // only when the current stage for the Subsystem is the one just prior 00335 // to the stage being realized. For example, realizeSubsystemVelocityImpl() 00336 // is called by realizeSubsystemVelocity() only when the passed-in State 00337 // shows this subsystem's stage to be exactly Stage::Position. 00338 // 00339 // The default implementations provided here do nothing. That means the 00340 // wrappers will simply check that the current stage is correct and 00341 // advance it if necessary. 00342 00343 // The destructor is already virtual; see above. 00344 00345 virtual Subsystem::Guts* cloneImpl() const = 0; 00346 00347 virtual int realizeSubsystemTopologyImpl(State& s) const; 00348 virtual int realizeSubsystemModelImpl(State& s) const; 00349 virtual int realizeSubsystemInstanceImpl(const State& s) const; 00350 virtual int realizeSubsystemTimeImpl(const State& s) const; 00351 virtual int realizeSubsystemPositionImpl(const State& s) const; 00352 virtual int realizeSubsystemVelocityImpl(const State& s) const; 00353 virtual int realizeSubsystemDynamicsImpl(const State& s) const; 00354 virtual int realizeSubsystemAccelerationImpl(const State& s) const; 00355 virtual int realizeSubsystemReportImpl(const State& s) const; 00356 00357 virtual int calcQUnitWeightsImpl(const State& s, Vector& weights) const; 00358 virtual int calcUUnitWeightsImpl(const State& s, Vector& weights) const; 00359 virtual int calcZUnitWeightsImpl(const State& s, Vector& weights) const; 00360 virtual int calcQErrUnitTolerancesImpl(const State& s, Vector& tolerances) const; 00361 virtual int calcUErrUnitTolerancesImpl(const State& s, Vector& tolerances) const; 00362 virtual int calcDecorativeGeometryAndAppendImpl 00363 (const State&, Stage, Array_<DecorativeGeometry>&) const; 00364 00365 void advanceToStage(const State& s, Stage g) const; 00366 00367 private: 00368 // this is the only data member in the base class 00369 GutsRep* rep; // opaque implementation of Subsystem::Guts base class. 00370 00371 friend class GutsRep; 00372 }; 00373 00374 } // namespace SimTK 00375 00376 #endif // SimTK_SimTKCOMMON_SUBSYSTEM_GUTS_H_