Simbody
|
00001 #ifndef SimTK_SimTKCOMMON_SUBSYSTEM_H_ 00002 #define SimTK_SimTKCOMMON_SUBSYSTEM_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: * 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/Measure.h" 00039 00040 #include <cassert> 00041 00042 namespace SimTK { 00043 00044 class System; 00045 00046 00069 class SimTK_SimTKCOMMON_EXPORT Subsystem { 00070 public: 00071 class Guts; // local; name is Subsystem::Guts 00072 friend class Guts; 00073 private: 00074 // This is the only data member in this class. Also, any class derived from 00075 // Subsystem must have *NO* data members at all (data goes in the Guts class). 00076 Guts* guts; 00077 public: 00078 Subsystem() : guts(0) { } // an empty handle 00079 Subsystem(const Subsystem&); 00080 Subsystem& operator=(const Subsystem&); 00081 ~Subsystem(); 00082 00083 const String& getName() const; 00084 const String& getVersion() const; 00085 00086 // These call the corresponding State method, supplying this Subsystem's 00087 // SubsystemIndex. The returned indices are local to this Subsystem. 00088 QIndex allocateQ(State&, const Vector& qInit) const; 00089 UIndex allocateU(State&, const Vector& uInit) const; 00090 ZIndex allocateZ(State&, const Vector& zInit) const; 00091 00092 DiscreteVariableIndex allocateDiscreteVariable 00093 (State&, Stage invalidates, AbstractValue* v) const; 00094 DiscreteVariableIndex allocateAutoUpdateDiscreteVariable 00095 (State&, Stage invalidates, AbstractValue* v, Stage updateDependsOn) const; 00096 00097 CacheEntryIndex allocateCacheEntry 00098 (const State&, Stage dependsOn, Stage computedBy, AbstractValue* v) const; 00099 CacheEntryIndex allocateCacheEntry 00100 (const State& state, Stage g, AbstractValue* v) const 00101 { return allocateCacheEntry(state, g, g, v); } 00102 CacheEntryIndex allocateLazyCacheEntry 00103 (const State& state, Stage earliest, AbstractValue* v) const 00104 { return allocateCacheEntry(state, earliest, Stage::Infinity, v); } 00105 00106 QErrIndex allocateQErr (const State&, int nqerr) const; 00107 UErrIndex allocateUErr (const State&, int nuerr) const; 00108 UDotErrIndex allocateUDotErr (const State&, int nudoterr) const; 00109 EventTriggerByStageIndex allocateEventTriggersByStage 00110 (const State&, Stage, int ntriggers) const; 00111 00112 // These return views on State shared global resources. The views 00113 // are private to this subsystem, but the global resources themselves 00114 // are not allocated until the *System* advances to stage Model. 00115 // Note that there is no subsystem equivalent of the State's "y" 00116 // vector because in general a subsystem's state variables will 00117 // not be contiguous. However, a subsystem's q's, u's, and z's 00118 // will all be contiguous within those arrays. 00119 const Vector& getQ(const State&) const; 00120 const Vector& getU(const State&) const; 00121 const Vector& getZ(const State&) const; 00122 const Vector& getQDot(const State&) const; 00123 const Vector& getUDot(const State&) const; 00124 const Vector& getZDot(const State&) const; 00125 const Vector& getQDotDot(const State&) const; 00126 const Vector& getQErr(const State&) const; 00127 const Vector& getUErr(const State&) const; 00128 const Vector& getUDotErr(const State&) const; 00129 const Vector& getMultipliers(const State&) const; 00130 const Vector& getEventTriggersByStage(const State&, Stage) const; 00131 00132 // These return writable access to this subsystem's partition in the 00133 // State pool of continuous variables. These can be called at Stage::Model 00134 // or higher, and if necesary they invalidate the Position (q), Velocity (u), 00135 // or Dynamics (z) stage respectively. 00136 Vector& updQ(State&) const; // invalidates Stage::Position 00137 Vector& updU(State&) const; // invalidates Stage::Velocity 00138 Vector& updZ(State&) const; // invalidates Stage::Dynamics 00139 00140 // For convenience. 00141 void setQ(State& s, const Vector& q) const { 00142 assert(q.size() == getNQ(s)); 00143 updQ(s) = q; 00144 } 00145 void setU(State& s, const Vector& u) const { 00146 assert(u.size() == getNU(s)); 00147 updU(s) = u; 00148 } 00149 void setZ(State& s, const Vector& z) const { 00150 assert(z.size() == getNZ(s)); 00151 updZ(s) = z; 00152 } 00153 00154 // These update the State cache which is mutable; hence, const State. They 00155 // can be called only if the previous stage has already been realized, e.g., 00156 // updQDot() is allowed only while realizing the Velocity stage, requiring 00157 // that Position stage has already been realized. 00158 Vector& updQDot(const State&) const; 00159 Vector& updUDot(const State&) const; 00160 Vector& updZDot(const State&) const; 00161 Vector& updQDotDot(const State&) const; 00162 Vector& updQErr(const State&) const; 00163 Vector& updUErr(const State&) const; 00164 Vector& updUDotErr(const State&) const; 00165 Vector& updMultipliers(const State&) const; 00166 Vector& updEventTriggersByStage(const State&, Stage) const; 00167 00168 // These pull out the State entries which belong exclusively to 00169 // this Subsystem. These variables and cache entries are available 00170 // as soon as this subsystem is at stage Model. 00171 Stage getStage(const State&) const; 00172 const AbstractValue& getDiscreteVariable(const State& s, DiscreteVariableIndex dx) const; 00173 00174 Real getDiscreteVarLastUpdateTime(const State& s, DiscreteVariableIndex dx) const 00175 { return s.getDiscreteVarLastUpdateTime(getMySubsystemIndex(),dx); } 00176 CacheEntryIndex getDiscreteVarUpdateIndex(const State& s, DiscreteVariableIndex dx) const 00177 { return s.getDiscreteVarUpdateIndex(getMySubsystemIndex(),dx); } 00178 const AbstractValue& getDiscreteVarUpdateValue(const State& s, DiscreteVariableIndex dx) const 00179 { return s.getDiscreteVarUpdateValue(getMySubsystemIndex(),dx); } 00180 AbstractValue& updDiscreteVarUpdateValue(const State& s, DiscreteVariableIndex dx) const 00181 { return s.updDiscreteVarUpdateValue(getMySubsystemIndex(),dx); } 00182 bool isDiscreteVarUpdateValueRealized(const State& s, DiscreteVariableIndex dx) const 00183 { return s.isDiscreteVarUpdateValueRealized(getMySubsystemIndex(),dx); } 00184 void markDiscreteVarUpdateValueRealized(const State& s, DiscreteVariableIndex dx) const 00185 { return s.markDiscreteVarUpdateValueRealized(getMySubsystemIndex(),dx); } 00186 00187 // State is *not* mutable here -- must have write access to change state variables. 00188 AbstractValue& updDiscreteVariable(State&, DiscreteVariableIndex) const; 00189 00190 const AbstractValue& getCacheEntry(const State&, CacheEntryIndex) const; 00191 // State is mutable here. 00192 AbstractValue& updCacheEntry(const State&, CacheEntryIndex) const; 00193 00194 bool isCacheValueRealized(const State&, CacheEntryIndex) const; 00195 void markCacheValueRealized(const State&, CacheEntryIndex) const; 00196 void markCacheValueNotRealized(const State&, CacheEntryIndex) const; 00197 00198 // Dimensions. These are valid at System Stage::Model while access to the 00199 // various arrays may have stricter requirements. Hence it is better to use 00200 // these routines than to get a reference to a Vector above and ask for 00201 // its size(). 00202 00203 SystemQIndex getQStart (const State&) const; 00204 int getNQ (const State&) const; 00205 SystemUIndex getUStart (const State&) const; 00206 int getNU (const State&) const; 00207 SystemZIndex getZStart (const State&) const; 00208 int getNZ (const State&) const; 00209 SystemQErrIndex getQErrStart (const State&) const; 00210 int getNQErr (const State&) const; 00211 SystemUErrIndex getUErrStart (const State&) const; 00212 int getNUErr (const State&) const; 00213 SystemUDotErrIndex getUDotErrStart(const State&) const; 00214 int getNUDotErr (const State&) const; 00215 SystemMultiplierIndex getMultipliersStart (const State&) const; 00216 int getNMultipliers (const State&) const; 00217 SystemEventTriggerByStageIndex getEventTriggerStartByStage(const State&, Stage) const; 00218 int getNEventTriggersByStage (const State&, Stage) const; 00219 00220 bool isInSystem() const; 00221 bool isInSameSystem(const Subsystem& otherSubsystem) const; 00222 00223 const System& getSystem() const; 00224 System& updSystem(); 00225 00226 SubsystemIndex getMySubsystemIndex() const; 00227 00228 // Is this handle the owner of this rep? This is true if the 00229 // handle is empty or if its rep points back here. 00230 bool isOwnerHandle() const; 00231 bool isEmptyHandle() const; 00232 00233 // There can be multiple handles on the same Subsystem. 00234 bool isSameSubsystem(const Subsystem& otherSubsystem) const; 00235 00236 bool subsystemTopologyHasBeenRealized() const; 00237 void invalidateSubsystemTopologyCache() const; 00238 00239 // Add a new Measure to this Subsystem. This method is generally used by Measure 00240 // constructors to install a newly-constructed Measure into its Subsystem. 00241 MeasureIndex adoptMeasure(AbstractMeasure&); 00242 00243 AbstractMeasure getMeasure(MeasureIndex) const; 00244 template <class T> Measure_<T> getMeasure_(MeasureIndex mx) const 00245 { return Measure_<T>::getAs(getMeasure(mx));} 00246 00247 // dynamic_cast the returned reference to a reference to your concrete Guts 00248 // class. 00249 const Subsystem::Guts& getSubsystemGuts() const {assert(guts); return *guts;} 00250 Subsystem::Guts& updSubsystemGuts() {assert(guts); return *guts;} 00251 00252 // Put new Guts into this *empty* handle and take over ownership. 00253 // If this handle is already in use, this routine will throw 00254 // an exception. 00255 void adoptSubsystemGuts(Subsystem::Guts* g); 00256 void setSystem(System&, SubsystemIndex); 00257 00258 explicit Subsystem(Subsystem::Guts* g) : guts(g) { } 00259 bool hasGuts() const {return guts!=0;} 00260 }; 00261 00262 } // namespace SimTK 00263 00264 #endif // SimTK_SimTKCOMMON_SUBSYSTEM_H_