Simbody  3.4 (development)
Subsystem.h
Go to the documentation of this file.
00001 #ifndef SimTK_SimTKCOMMON_SUBSYSTEM_H_
00002 #define SimTK_SimTKCOMMON_SUBSYSTEM_H_
00003 
00004 /* -------------------------------------------------------------------------- *
00005  *                       Simbody(tm): SimTKcommon                             *
00006  * -------------------------------------------------------------------------- *
00007  * This is part of the SimTK 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/home/simbody.  *
00011  *                                                                            *
00012  * Portions copyright (c) 2006-12 Stanford University and the Authors.        *
00013  * Authors: Michael Sherman                                                   *
00014  * Contributors:                                                              *
00015  *                                                                            *
00016  * Licensed under the Apache License, Version 2.0 (the "License"); you may    *
00017  * not use this file except in compliance with the License. You may obtain a  *
00018  * copy of the License at http://www.apache.org/licenses/LICENSE-2.0.         *
00019  *                                                                            *
00020  * Unless required by applicable law or agreed to in writing, software        *
00021  * distributed under the License is distributed on an "AS IS" BASIS,          *
00022  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   *
00023  * See the License for the specific language governing permissions and        *
00024  * limitations under the License.                                             *
00025  * -------------------------------------------------------------------------- */
00026 
00027 #include "SimTKcommon/basics.h"
00028 #include "SimTKcommon/Simmatrix.h"
00029 #include "SimTKcommon/internal/State.h"
00030 #include "SimTKcommon/internal/Measure.h"
00031 
00032 #include <cassert>
00033 
00034 namespace SimTK {
00035 
00036 class System;
00037 
00038 
00061 class SimTK_SimTKCOMMON_EXPORT Subsystem {
00062 public:
00063     class Guts; // local; name is Subsystem::Guts
00064     friend class Guts;
00065 private:
00066     // This is the only data member in this class. Also, any class derived from
00067     // Subsystem must have *NO* data members at all (data goes in the Guts class).
00068     Guts* guts;
00069 public:
00070     Subsystem() : guts(0) { } // an empty handle
00071     Subsystem(const Subsystem&);
00072     Subsystem& operator=(const Subsystem&);
00073     ~Subsystem();
00074 
00075     const String& getName()    const;
00076     const String& getVersion() const;
00077 
00078     // These call the corresponding State method, supplying this Subsystem's
00079     // SubsystemIndex. The returned indices are local to this Subsystem.
00080     QIndex allocateQ(State&, const Vector& qInit) const;
00081     UIndex allocateU(State&, const Vector& uInit) const;
00082     ZIndex allocateZ(State&, const Vector& zInit) const;
00083 
00084     DiscreteVariableIndex allocateDiscreteVariable
00085        (State&, Stage invalidates, AbstractValue* v) const;
00086     DiscreteVariableIndex allocateAutoUpdateDiscreteVariable
00087        (State&, Stage invalidates, AbstractValue* v, Stage updateDependsOn) const; 
00088 
00089     CacheEntryIndex allocateCacheEntry
00090        (const State&, Stage dependsOn, Stage computedBy, AbstractValue* v) const;
00091     CacheEntryIndex allocateCacheEntry   
00092        (const State& state, Stage g, AbstractValue* v) const 
00093     {   return allocateCacheEntry(state, g, g, v); }
00094     CacheEntryIndex allocateLazyCacheEntry   
00095        (const State& state, Stage earliest, AbstractValue* v) const 
00096     {   return allocateCacheEntry(state, earliest, Stage::Infinity, v); }
00097 
00098     QErrIndex allocateQErr         (const State&, int nqerr) const;
00099     UErrIndex allocateUErr         (const State&, int nuerr) const;
00100     UDotErrIndex allocateUDotErr      (const State&, int nudoterr) const;
00101     EventTriggerByStageIndex allocateEventTriggersByStage
00102        (const State&, Stage, int ntriggers) const;
00103 
00104     // These return views on State shared global resources. The views
00105     // are private to this subsystem, but the global resources themselves
00106     // are not allocated until the *System* advances to stage Model.
00107     // Note that there is no subsystem equivalent of the State's "y"
00108     // vector because in general a subsystem's state variables will
00109     // not be contiguous. However, a subsystem's q's, u's, and z's
00110     // will all be contiguous within those arrays.
00111     const Vector& getQ(const State&) const;
00112     const Vector& getU(const State&) const;
00113     const Vector& getZ(const State&) const;
00114     const Vector& getQDot(const State&) const;
00115     const Vector& getUDot(const State&) const;
00116     const Vector& getZDot(const State&) const;
00117     const Vector& getQDotDot(const State&) const;
00118     const Vector& getQErr(const State&) const;
00119     const Vector& getUErr(const State&) const;
00120     const Vector& getUDotErr(const State&) const;
00121     const Vector& getMultipliers(const State&) const;
00122     const Vector& getEventTriggersByStage(const State&, Stage) const;
00123 
00124     // These return writable access to this subsystem's partition in the
00125     // State pool of continuous variables. These can be called at Stage::Model
00126     // or higher, and if necesary they invalidate the Position (q), Velocity (u),
00127     // or Dynamics (z) stage respectively.
00128     Vector& updQ(State&) const; // invalidates Stage::Position
00129     Vector& updU(State&) const; // invalidates Stage::Velocity
00130     Vector& updZ(State&) const; // invalidates Stage::Dynamics
00131 
00132     // For convenience.
00133     void setQ(State& s, const Vector& q) const {
00134         assert(q.size() == getNQ(s));
00135         updQ(s) = q;
00136     }
00137     void setU(State& s, const Vector& u) const {
00138         assert(u.size() == getNU(s));
00139         updU(s) = u;
00140     }
00141     void setZ(State& s, const Vector& z) const {
00142         assert(z.size() == getNZ(s));
00143         updZ(s) = z;
00144     }
00145 
00146     // These update the State cache which is mutable; hence, const State. They
00147     // can be called only if the previous stage has already been realized, e.g.,
00148     // updQDot() is allowed only while realizing the Velocity stage, requiring
00149     // that Position stage has already been realized.
00150     Vector& updQDot(const State&) const;
00151     Vector& updUDot(const State&) const;
00152     Vector& updZDot(const State&) const;
00153     Vector& updQDotDot(const State&) const;
00154     Vector& updQErr(const State&) const;
00155     Vector& updUErr(const State&) const;
00156     Vector& updUDotErr(const State&) const;
00157     Vector& updMultipliers(const State&) const;
00158     Vector& updEventTriggersByStage(const State&, Stage) const;
00159 
00160     // These pull out the State entries which belong exclusively to
00161     // this Subsystem. These variables and cache entries are available
00162     // as soon as this subsystem is at stage Model.
00163     Stage getStage(const State&) const;
00164     const AbstractValue& getDiscreteVariable(const State& s, DiscreteVariableIndex dx) const;
00165 
00166     Real getDiscreteVarLastUpdateTime(const State& s, DiscreteVariableIndex dx) const
00167     {   return s.getDiscreteVarLastUpdateTime(getMySubsystemIndex(),dx); }
00168     CacheEntryIndex getDiscreteVarUpdateIndex(const State& s, DiscreteVariableIndex dx) const
00169     {   return s.getDiscreteVarUpdateIndex(getMySubsystemIndex(),dx); }
00170     const AbstractValue& getDiscreteVarUpdateValue(const State& s, DiscreteVariableIndex dx) const
00171     {   return s.getDiscreteVarUpdateValue(getMySubsystemIndex(),dx); }
00172     AbstractValue& updDiscreteVarUpdateValue(const State& s, DiscreteVariableIndex dx) const
00173     {   return s.updDiscreteVarUpdateValue(getMySubsystemIndex(),dx); }
00174     bool isDiscreteVarUpdateValueRealized(const State& s, DiscreteVariableIndex dx) const
00175     {   return s.isDiscreteVarUpdateValueRealized(getMySubsystemIndex(),dx); }
00176     void markDiscreteVarUpdateValueRealized(const State& s, DiscreteVariableIndex dx) const
00177     {   return s.markDiscreteVarUpdateValueRealized(getMySubsystemIndex(),dx); }
00178 
00179     // State is *not* mutable here -- must have write access to change state variables.
00180     AbstractValue& updDiscreteVariable(State&, DiscreteVariableIndex) const;
00181 
00182     const AbstractValue& getCacheEntry(const State&, CacheEntryIndex) const;
00183     // State is mutable here.
00184     AbstractValue& updCacheEntry(const State&, CacheEntryIndex) const;
00185 
00186     bool isCacheValueRealized(const State&, CacheEntryIndex) const;
00187     void markCacheValueRealized(const State&, CacheEntryIndex) const;
00188     void markCacheValueNotRealized(const State&, CacheEntryIndex) const;
00189 
00190     // Dimensions. These are valid at System Stage::Model while access to the 
00191     // various arrays may have stricter requirements. Hence it is better to use
00192     // these routines than to get a reference to a Vector above and ask for 
00193     // its size().
00194 
00195     SystemQIndex getQStart      (const State&) const;
00196     int getNQ          (const State&) const;
00197     SystemUIndex getUStart      (const State&) const;
00198     int getNU          (const State&) const;
00199     SystemZIndex getZStart      (const State&) const;
00200     int getNZ          (const State&) const;
00201     SystemQErrIndex getQErrStart   (const State&) const;
00202     int getNQErr       (const State&) const;
00203     SystemUErrIndex getUErrStart   (const State&) const;
00204     int getNUErr       (const State&) const;
00205     SystemUDotErrIndex getUDotErrStart(const State&) const;
00206     int getNUDotErr    (const State&) const;
00207     SystemMultiplierIndex getMultipliersStart (const State&) const;
00208     int getNMultipliers     (const State&) const;
00209     SystemEventTriggerByStageIndex getEventTriggerStartByStage(const State&, Stage) const;
00210     int getNEventTriggersByStage   (const State&, Stage) const;
00211 
00212     bool isInSystem() const;
00213     bool isInSameSystem(const Subsystem& otherSubsystem) const;
00214 
00215     const System& getSystem() const;
00216     System&       updSystem();
00217 
00218     SubsystemIndex getMySubsystemIndex() const;
00219 
00220     // Is this handle the owner of this rep? This is true if the
00221     // handle is empty or if its rep points back here.
00222     bool isOwnerHandle() const;
00223     bool isEmptyHandle() const;
00224 
00225     // There can be multiple handles on the same Subsystem.
00226     bool isSameSubsystem(const Subsystem& otherSubsystem) const;
00227 
00228     bool subsystemTopologyHasBeenRealized() const;
00229     void invalidateSubsystemTopologyCache() const;
00230 
00231     // Add a new Measure to this Subsystem. This method is generally used by Measure
00232     // constructors to install a newly-constructed Measure into its Subsystem.
00233     MeasureIndex adoptMeasure(AbstractMeasure&);
00234 
00235     AbstractMeasure getMeasure(MeasureIndex) const;
00236     template <class T> Measure_<T> getMeasure_(MeasureIndex mx) const
00237     {   return Measure_<T>::getAs(getMeasure(mx));}
00238 
00239     // dynamic_cast the returned reference to a reference to your concrete Guts
00240     // class.
00241     const Subsystem::Guts& getSubsystemGuts() const {assert(guts); return *guts;}
00242     Subsystem::Guts&       updSubsystemGuts()       {assert(guts); return *guts;}
00243 
00244     // Put new Guts into this *empty* handle and take over ownership.
00245     // If this handle is already in use, this routine will throw
00246     // an exception.
00247     void adoptSubsystemGuts(Subsystem::Guts* g);
00248     void setSystem(System&, SubsystemIndex);
00249 
00250     explicit Subsystem(Subsystem::Guts* g) : guts(g) { }
00251     bool hasGuts() const {return guts!=0;}
00252 };
00253 
00254 } // namespace SimTK
00255 
00256 #endif // SimTK_SimTKCOMMON_SUBSYSTEM_H_
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines