MeasureImplementation.h

Go to the documentation of this file.
00001 #ifndef SimTK_SimTKCOMMON_MEASURE_IMPLEMENTATION_H_
00002 #define SimTK_SimTKCOMMON_MEASURE_IMPLEMENTATION_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) 2008-9 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 #include "SimTKcommon/internal/Subsystem.h"
00040 #include "SimTKcommon/internal/System.h"
00041 #include "SimTKcommon/internal/SubsystemGuts.h"
00042 
00043 #include <cmath>
00044 
00045 
00046 namespace SimTK {
00047 
00048 
00050     // MEASURE::IMPLEMENTATION //
00052 
00056 class SimTK_SimTKCOMMON_EXPORT AbstractMeasure::Implementation {
00057 protected:
00058     // This constructor is for use by concrete Measure::Implementations. Note 
00059     // that this serves as a default constructor since the argument has a 
00060     // default.
00061     explicit Implementation(const std::string& name="<NONAME>")
00062     :   measureName(name), copyNumber(0), mySubsystem(0), refCount(0) {}
00063 
00064     // Base class copy constructor copies the name, removes the Subsystem
00065     // and sets the reference count to zero. This gets used by the clone()
00066     // methods in the concrete classes.
00067     Implementation(const Implementation& src)
00068     :   measureName(src.measureName), copyNumber(src.copyNumber+1),
00069         mySubsystem(0), refCount(0) {}
00070     
00071     // Base class copy assignment operator copies the name, removes the
00072     // Subsystem, and sets the reference count to zero. This is probably
00073     // not used.
00074     Implementation& operator=(const Implementation& src) {
00075         if (&src != this)
00076         {   measureName=src.measureName; copyNumber=src.copyNumber+1;
00077             refCount=0; mySubsystem=0; }
00078         return *this; 
00079     }
00080 
00081     // destructor is virtual
00082 
00083     // Increment the reference count and return its new value.
00084     int incrRefCount() const {return ++refCount;}
00085 
00086     // Decrement the reference count and return its new value.
00087     int decrRefCount() const {return --refCount;}
00088 
00089     // Get the current value of the reference counter.
00090     int getRefCount() const {return refCount;}
00091 
00092     const std::string& getName()        const {return measureName;}
00093     int                getCopyNumber()  const {return copyNumber;}
00094 
00095     // This is a deep copy of the concrete Implementation object, except the
00096     // Subsystem will have been removed. The reference count on the new object
00097     // will be zero; be sure to increment it if you put it in a handle.
00098     Implementation* clone() const {return cloneVirtual();}
00099 
00100     // realizeTopology() is pure virtual below for Measure_<T> to supply.
00101     void realizeModel       (State& s)       const {realizeMeasureModelVirtual(s);}
00102     void realizeInstance    (const State& s) const {realizeMeasureInstanceVirtual(s);}
00103     void realizeTime        (const State& s) const {realizeMeasureTimeVirtual(s);}
00104     void realizePosition    (const State& s) const {realizeMeasurePositionVirtual(s);}
00105     void realizeVelocity    (const State& s) const {realizeMeasureVelocityVirtual(s);}
00106     void realizeDynamics    (const State& s) const {realizeMeasureDynamicsVirtual(s);}
00107     void realizeAcceleration(const State& s) const {realizeMeasureAccelerationVirtual(s);}
00108     void realizeReport      (const State& s) const {realizeMeasureReportVirtual(s);}
00109 
00110     // This should be called at the start of a numerical integration study to
00111     // cause initial conditions to get set for any Measures that have integrated
00112     // state variables.
00113     void initialize(State& s) const {initializeVirtual(s);}
00114 
00115     int getNumTimeDerivatives() const {return getNumTimeDerivativesVirtual();}
00116 
00117     Stage getDependsOnStage(int derivOrder) const {
00118         SimTK_ERRCHK2(0 <= derivOrder && derivOrder <= getNumTimeDerivatives(),
00119             "Measure::getDependsOnStage()",
00120             "derivOrder %d was out of range; this Measure allows 0-%d.",
00121             derivOrder, getNumTimeDerivatives()); 
00122         return getDependsOnStageVirtual(derivOrder); 
00123     }
00124 
00125 
00126     void setSubsystem(Subsystem& sub, MeasureIndex mx) 
00127     {   assert(!mySubsystem && mx.isValid()); 
00128         mySubsystem = &sub; myIndex = mx; }
00129 
00130     bool             isInSubsystem() const {return mySubsystem != 0;}
00131     const Subsystem& getSubsystem() const {assert(mySubsystem); return *mySubsystem;}
00132     Subsystem&       updSubsystem() {assert(mySubsystem); return *mySubsystem;}
00133     MeasureIndex     getSubsystemMeasureIndex() const {assert(mySubsystem); return myIndex;}
00134     SubsystemIndex   getSubsystemIndex() const
00135     {   return getSubsystem().getMySubsystemIndex(); }
00136 
00137     void invalidateTopologyCache() const
00138     {   if (isInSubsystem()) getSubsystem().invalidateSubsystemTopologyCache(); }
00139 
00140     Stage getStage(const State& s) const {return getSubsystem().getStage(s);}
00141 
00142     // VIRTUALS //
00143     // Ordinals must retain the same meaning from release to release
00144     // to preserve binary compatibility.
00145 
00146     /* 0*/virtual ~Implementation() {}
00147     /* 1*/virtual Implementation* cloneVirtual() const = 0;
00148 
00149     /* 2*/virtual void realizeTopology(State&)const = 0;
00150 
00151     /* 3*/virtual void realizeMeasureModelVirtual(State&) const {}
00152     /* 4*/virtual void realizeMeasureInstanceVirtual(const State&) const {}
00153     /* 5*/virtual void realizeMeasureTimeVirtual(const State&) const {}
00154     /* 6*/virtual void realizeMeasurePositionVirtual(const State&) const {}
00155     /* 7*/virtual void realizeMeasureVelocityVirtual(const State&) const {}
00156     /* 8*/virtual void realizeMeasureDynamicsVirtual(const State&) const {}
00157     /* 9*/virtual void realizeMeasureAccelerationVirtual(const State&) const {}
00158     /*10*/virtual void realizeMeasureReportVirtual(const State&) const {}
00159 
00160     /*11*/virtual void initializeVirtual(State&) const {}
00161     /*12*/virtual int  
00162           getNumTimeDerivativesVirtual() const {return 0;}
00163     /*13*/virtual Stage 
00164           getDependsOnStageVirtual(int order) const = 0;
00165 
00166 private:
00167     std::string     measureName;
00168     int             copyNumber; // bumped each time we do a deep copy
00169 
00170     // These are set when this Measure is adopted by a Subsystem.
00171     Subsystem*      mySubsystem;
00172     MeasureIndex    myIndex;
00173 
00174     // Measures have shallow copy semantics so they share the Implementation 
00175     // objects, which are only deleted when the refCount goes to zero.
00176     mutable int     refCount;
00177 
00178 friend class AbstractMeasure;
00179 friend class Subsystem::Guts;
00180 friend class Subsystem::Guts::GutsRep;
00181 };
00182 
00184     // ABSTRACT MEASURE DEFINITIONS //
00186 
00187 // These had to wait for Implementation to be defined.
00188 
00189 inline AbstractMeasure::
00190 AbstractMeasure(Implementation* g) 
00191 :   impl(g)
00192 {   if (impl) impl->incrRefCount(); }
00193 
00194 inline AbstractMeasure::
00195 AbstractMeasure(Subsystem& sub, Implementation* g, const SetHandle&) 
00196 :   impl(g) {
00197     SimTK_ERRCHK(hasImpl(), "AbstractMeasure::ctor()",
00198         "An empty Measure handle can't be put in a Subsystem.");
00199     impl->incrRefCount();
00200     sub.adoptMeasure(*this);
00201 }
00202 
00203 // Shallow copy constructor.
00204 inline AbstractMeasure::AbstractMeasure(const AbstractMeasure& src) 
00205 :   impl(0) {
00206     if (src.impl) {
00207         impl = src.impl;
00208         impl->incrRefCount();
00209     }
00210 }
00211 
00212 // Shallow assignment.
00213 inline AbstractMeasure& AbstractMeasure::
00214 shallowAssign(const AbstractMeasure& src) {
00215     if (impl != src.impl) {
00216         if (impl && impl->decrRefCount()==0) delete impl;
00217         impl = src.impl;
00218         impl->incrRefCount();
00219     }
00220     return *this;
00221 }
00222 
00223 // Note that even if the source and destination are currently pointing
00224 // to the same Implementation, we still have to make a new copy so that
00225 // afterwards the destination has its own, refcount==1 copy.
00226 inline AbstractMeasure& AbstractMeasure::
00227 deepAssign(const AbstractMeasure& src) {
00228     if (&src != this) {
00229         if (impl && impl->decrRefCount()==0) delete impl;
00230         if (src.impl) {
00231             impl = src.impl->clone();
00232             impl->incrRefCount();
00233         } else
00234             impl = 0;
00235     }
00236     return *this;
00237 }
00238 
00239 inline AbstractMeasure::
00240 ~AbstractMeasure()
00241 {   if (impl && impl->decrRefCount()==0) delete impl;}
00242 
00243 inline bool AbstractMeasure::
00244 isInSubsystem() const
00245 {   return hasImpl() && getImpl().isInSubsystem(); }
00246 
00247 inline const Subsystem& AbstractMeasure::
00248 getSubsystem() const
00249 {   return getImpl().getSubsystem(); }
00250 
00251 inline MeasureIndex AbstractMeasure::
00252 getSubsystemMeasureIndex() const
00253 {   return getImpl().getSubsystemMeasureIndex();}
00254 
00255 inline int AbstractMeasure::
00256 getNumTimeDerivatives() const
00257 {   return getImpl().getNumTimeDerivatives(); }
00258 
00259 inline Stage AbstractMeasure::
00260 getDependsOnStage(int derivOrder) const
00261 {   return getImpl().getDependsOnStage(derivOrder); }
00262 
00263 inline int AbstractMeasure::
00264 getRefCount() const
00265 {   return getImpl().getRefCount(); }
00266 
00267 
00269     // MEASURE_<T>::IMPLEMENTATION //
00271 
00281 template <class T>
00282 class Measure_<T>::Implementation : public AbstractMeasure::Implementation {
00283 public:
00284     const T& getValue(const State& s, int derivOrder) const {
00285         SimTK_ERRCHK2(0 <= derivOrder && derivOrder <= getNumTimeDerivatives(),
00286             "Measure_<T>::getValue()",
00287             "derivOrder %d was out of range; this Measure allows 0-%d.",
00288             derivOrder, getNumTimeDerivatives()); 
00289 
00290         SimTK_ERRCHK2
00291             (   getDependsOnStage(derivOrder)==Stage::Empty
00292              || (isInSubsystem() 
00293                  && getStage(s)>=getDependsOnStage(derivOrder))
00294              || (!isInSubsystem() 
00295                  && s.getSystemStage()>=getDependsOnStage(derivOrder)),
00296             "Measure_<T>::getValue()",
00297             "Expected State to have been realized to at least stage "
00298             "%s but stage was %s.", 
00299             getDependsOnStage(derivOrder).getName().c_str(), 
00300             (isInSubsystem() ? getStage(s) : s.getSystemStage())
00301                 .getName().c_str());
00302 
00303         if (derivOrder < getNumCacheEntries()) {
00304             if (!isCacheValueRealized(s,derivOrder)) {
00305                 T& value = updCacheEntry(s,derivOrder);
00306                 calcCachedValueVirtual(s, derivOrder, value);
00307                 markCacheValueRealized(s,derivOrder);
00308                 return value;
00309             }
00310             return getCacheEntry(s,derivOrder);
00311         }
00312 
00313         // We can't handle it here -- punt to the concrete Measure
00314         // for higher order derivatives.
00315         return getUncachedValueVirtual(s,derivOrder); 
00316     }
00317 
00318 protected:
00319     // numValues is one greater than the number of derivatives; i.e., there
00320     // is room for the value ("0th" derivative) also. The default is to
00321     // allocate just room for the value.
00322     explicit Implementation(int numValues=1) : derivIx(numValues) {}
00323 
00324     // Satisfy the realizeTopology() pure virtual here now that we know
00325     // the data type T.
00326     void realizeTopology(State& s) const {
00327         Implementation* mutableThis = const_cast<Implementation*>(this);
00328         // Allocate cache entries.
00329         for (int i=0; i < getNumCacheEntries(); ++i) {
00330             const Stage dependsOn = getDependsOnStage(i);
00331             mutableThis->derivIx[i] =
00332                this->getSubsystem().allocateLazyCacheEntry
00333                     (s, dependsOn, new Value<T>());
00334         }
00335 
00336         // Call the concrete class virtual if any.
00337         realizeMeasureTopologyVirtual(s);
00338     }
00339 
00340     int getNumCacheEntries() const {return (int)derivIx.size();}
00341 
00342     const T& getCacheEntry(const State& s, int derivOrder) const {
00343         SimTK_ERRCHK2(0 <= derivOrder && derivOrder < getNumCacheEntries(),
00344             "Measure_<T>::Implementation::getCacheEntry()",
00345             "Derivative order %d is out of range; only %d cache entries"
00346             " were allocated.", derivOrder, getNumCacheEntries());
00347 
00348         return Value<T>::downcast(
00349             this->getSubsystem().getCacheEntry(s, derivIx[derivOrder]));
00350     }
00351 
00352     T& updCacheEntry(const State& s, int derivOrder) const {
00353         SimTK_ERRCHK2(0 <= derivOrder && derivOrder < getNumCacheEntries(),
00354             "Measure_<T>::Implementation::updCacheEntry()",
00355             "Derivative order %d is out of range; only %d cache entries"
00356             " were allocated.", derivOrder, getNumCacheEntries());
00357 
00358         return Value<T>::updDowncast(
00359             this->getSubsystem().updCacheEntry(s, derivIx[derivOrder]));
00360     }
00361 
00362     bool isCacheValueRealized(const State& s, int derivOrder) const {
00363         SimTK_ERRCHK2(0 <= derivOrder && derivOrder < getNumCacheEntries(),
00364             "Measure_<T>::Implementation::isCacheValueRealized()",
00365             "Derivative order %d is out of range; only %d cache entries"
00366             " were allocated.", derivOrder, getNumCacheEntries());
00367 
00368         return this->getSubsystem().isCacheValueRealized(s, derivIx[derivOrder]);
00369     }
00370 
00371     void markCacheValueRealized(const State& s, int derivOrder) const {
00372         SimTK_ERRCHK2(0 <= derivOrder && derivOrder < getNumCacheEntries(),
00373             "Measure_<T>::Implementation::markCacheValueRealized()",
00374             "Derivative order %d is out of range; only %d cache entries"
00375             " were allocated.", derivOrder, getNumCacheEntries());
00376 
00377         this->getSubsystem().markCacheValueRealized(s, derivIx[derivOrder]);
00378     }
00379 
00380     // VIRTUALS //
00381     // Ordinals must retain the same meaning from release to release
00382     // to preserve binary compatibility.
00383 
00384     /* 0*/virtual void realizeMeasureTopologyVirtual(State&) const {}
00385     /* 1*/virtual void 
00386     calcCachedValueVirtual(const State&, int derivOrder, T& value) const
00387     {   SimTK_ERRCHK1_ALWAYS(!"implemented", 
00388         "Measure_<T>::Implementation::calcCachedValueVirtual()",
00389         "This method should have been overridden by the derived"
00390         " Measure but was not. It is needed to calculate the"
00391         " cached value for derivOrder=%d.", derivOrder); }
00392 
00393     // This is only called when derivOrder >= the number of cache 
00394     // entries we have, but still <= the number of derivatives the
00395     // Measure says it can deliver.
00396     /* 2*/virtual const T& 
00397     getUncachedValueVirtual(const State&, int derivOrder) const
00398     {   SimTK_ERRCHK1_ALWAYS(!"implemented", 
00399             "Measure_<T>::Implementation::getUncachedValueVirtual()",
00400             "This method should have been overridden by the derived"
00401             " Measure but was not. It is needed to return the uncached"
00402             " value at derivOrder=%d.", derivOrder);
00403         return *reinterpret_cast<T*>(0);
00404     }
00405 
00406     // STATICS //
00407     static const T& getValueZero() {
00408         static T zero(0);
00409         return zero;
00410     }
00411 
00412     static const T& getValueOne() {
00413         static T one(1);
00414         return one;
00415     }
00416 
00417 private:
00418     Array_<CacheEntryIndex> derivIx;
00419 };
00420 
00421 
00422 
00424     // CONSTANT::IMPLEMENTATION //
00426 
00427 template <class T>
00428 class Measure_<T>::Constant::Implementation 
00429 :   public Measure_<T>::Implementation 
00430 {
00431 public:
00432     // We don't want the base class to allocate *any* cache entries.
00433     Implementation() : Measure_<T>::Implementation(0) {}
00434     explicit Implementation(const T& value) 
00435     :   Measure_<T>::Implementation(0), value(value) {}
00436 
00437     // Allow this to be overridden by derived classes so they can
00438     // refuse to allow their values to change.
00439     virtual void setValue(const T& v) {
00440         value = v;
00441         this->invalidateTopologyCache();
00442     }
00443 
00444     // Implementations of virtual methods.
00445     // Measure_<T> virtuals:
00446     // No cached values.
00447 
00448     const T& getUncachedValueVirtual(const State&, int derivOrder) const 
00449     {   return derivOrder>0 ? this->getValueZero() : value; }
00450 
00451     // AbstractMeasure virtuals:
00452     Implementation* cloneVirtual() const {return new Implementation(*this);}
00453     Stage getDependsOnStageVirtual(int derivOrder) const 
00454     {   return derivOrder>0 ? Stage::Empty : Stage::Topology; }
00455     int getNumTimeDerivativesVirtual() const 
00456     {   return std::numeric_limits<int>::max(); }
00457 
00458 private:
00459     T value;
00460 };
00461 
00463     // ZERO::IMPLEMENTATION //
00465 
00466 template <class T>
00467 class Measure_<T>::Zero::Implementation 
00468 :   public Constant::Implementation 
00469 {
00470 public:
00471     Implementation() : Constant::Implementation(T(0)) {} 
00472 
00473     // VIRTUALS
00474     // From Constant::Implementation:
00475     void setValue(const T&) {
00476         SimTK_ERRCHK_ALWAYS(!"invalid", "Measure_<T>::Zero::setValue()",
00477             "You can't change the value of Zero!");
00478     }
00479 
00480     // From AbstractMeasure:
00481     Implementation* cloneVirtual() const {return new Implementation(*this);}
00482     Stage getDependsOnStageVirtual(int) const 
00483     {   return Stage::Empty; }
00484 };
00485 
00487     // ONE::IMPLEMENTATION //
00489 
00490 
00491 template <class T>
00492 class Measure_<T>::One::Implementation 
00493 :   public Constant::Implementation 
00494 {
00495 public:
00496     Implementation() : Constant::Implementation(T(1)) {} 
00497 
00498     // VIRTUALS
00499     // From Constant::Implementation:
00500     void setValue(const T&) {
00501         SimTK_ERRCHK_ALWAYS(!"invalid", "Measure_<T>::One::setValue()",
00502             "You can't change the value of One!");
00503     }
00504     // From AbstractMeasure:
00505     Implementation* cloneVirtual() const {return new Implementation(*this);}
00506     Stage getDependsOnStageVirtual(int) const 
00507     {   return Stage::Empty; }
00508 };
00509 
00510 
00512     // TIME::IMPLEMENTATION //
00514 
00515 template <class T>
00516 class Measure_<T>::Time::Implementation {};
00517 
00518 template <>
00519 class Measure_<Real>::Time::Implementation 
00520 :   public Measure_<Real>::Implementation 
00521 {
00522 public:
00523     // We don't want the base class to allocate *any* cache entries.
00524     Implementation() : Measure_<Real>::Implementation(0) {}
00525 
00526     // Implementations of virtual methods.
00527     // Measure_<Real> virtuals:
00528     // No cached values.
00529 
00530     const Real& getUncachedValueVirtual(const State& s, int derivOrder) const 
00531     {   return derivOrder==0 ? s.getTime()
00532             : (derivOrder==1 ? this->getValueOne() 
00533                              : this->getValueZero()); }
00534 
00535     // AbstractMeasure virtuals:
00536     Implementation* cloneVirtual() const {return new Implementation(*this);}
00537     Stage getDependsOnStageVirtual(int derivOrder) const 
00538     {   return derivOrder>0 ? Stage::Empty : Stage::Time; }
00539 
00540     // Value is t, 1st derivative is 1, the rest are 0.
00541     int getNumTimeDerivativesVirtual() const 
00542     {   return std::numeric_limits<int>::max(); }
00543 };
00544 
00546     // VARIABLE::IMPLEMENTATION //
00548 
00549 template <class T>
00550 class Measure_<T>::Variable::Implementation 
00551 :   public Measure_<T>::Implementation 
00552 {
00553 public:
00554     // We don't want the base class to allocate *any* cache entries;
00555     // we'll use the variable as its own value and zeroes for all
00556     // the derivatives.
00557     Implementation() : Measure_<T>::Implementation(0) {}
00558 
00559     Implementation(Stage invalidates, const T& defaultValue) 
00560     :   Measure_<T>::Implementation(0),
00561         invalidatedStage(invalidates), defaultValue(defaultValue) {}
00562 
00563     // Copy constructor should not copy the variable.
00564     Implementation(const Implementation& source)
00565     :   Measure_<T>::Implementation(0),
00566         invalidatedStage(source.invalidatedStage), 
00567         defaultValue(source.defaultValue) {}
00568 
00569     void setDefaultValue(const T& v) {
00570         defaultValue = v;
00571         this->invalidateTopologyCache();
00572     }
00573 
00574     void setInvalidatedStage(Stage invalidates) {
00575         invalidatedStage = invalidates;
00576         this->invalidateTopologyCache();
00577     }
00578 
00579     const T& getDefaultValue()     const {return defaultValue;}
00580     Stage    getInvalidatedStage() const {return invalidatedStage;}
00581 
00582     void setValue(State& state, const T& value) const 
00583     {   updVarValue(state) = value; }
00584 
00585     // Implementations of virtual methods.
00586     Implementation* cloneVirtual() const {return new Implementation(*this);}
00587 
00588     int getNumTimeDerivativesVirtual() const 
00589     {   return std::numeric_limits<int>::max(); }
00590 
00591     // Discrete variable is available after Model stage; but all its 
00592     // derivatives are zero so are always available.
00593     Stage getDependsOnStageVirtual(int derivOrder) const 
00594     {   return derivOrder>0 ? Stage::Empty : Stage::Model;}
00595 
00596     const T& getUncachedValueVirtual(const State& s, int derivOrder) const 
00597     {   return derivOrder>0 ? this->getValueZero() : getVarValue(s); }
00598 
00599     // No cached values.
00600 
00601     void realizeMeasureTopologyVirtual(State& s) const {
00602         discreteVarIndex = this->getSubsystem().allocateDiscreteVariable
00603             (s, invalidatedStage, new Value<T>(defaultValue));
00604     }
00605 private:
00606     const T& getVarValue(const State& s) const {
00607         assert(discreteVarIndex.isValid());
00608         return Value<T>::downcast(
00609             this->getSubsystem().getDiscreteVariable(s, discreteVarIndex));
00610     }
00611     T& updVarValue(State& s) const {
00612         assert(discreteVarIndex.isValid());
00613         return Value<T>::downcast(
00614             this->getSubsystem().updDiscreteVariable(s, discreteVarIndex));
00615     }
00616 
00617     // TOPOLOGY STATE
00618     Stage   invalidatedStage; // TODO this shouldn't be needed
00619     T       defaultValue;
00620 
00621     // TOPOLOGY CACHE
00622     mutable DiscreteVariableIndex discreteVarIndex;
00623 };
00624 
00626     // SINUSOID::IMPLEMENTATION //
00628 
00629 template <class T>
00630 class Measure_<T>::Sinusoid::Implementation
00631 :   public Measure_<T>::Implementation 
00632 {
00633     static const int NumDerivs = 3;
00634 public:
00635     Implementation() 
00636     :   Measure_<T>::Implementation(NumDerivs+1),
00637         a(CNT<T>::getNaN()), w(CNT<T>::getNaN()), p(CNT<T>::getNaN()) {}
00638 
00639     Implementation(const T& amplitude, 
00640                    const T& frequency, 
00641                    const T& phase=T(0))
00642     :   Measure_<T>::Implementation(NumDerivs+1),
00643         a(amplitude), w(frequency), p(phase) {}
00644 
00645     // Default copy constructor is fine.
00646 
00647     // Implementations of virtual methods.
00648     Implementation* cloneVirtual() const {return new Implementation(*this);}
00649 
00650     int getNumTimeDerivativesVirtual() const {return NumDerivs;}
00651 
00652     Stage getDependsOnStageVirtual(int order) const 
00653     {   return Stage::Time; }
00654 
00655     void calcCachedValueVirtual(const State& s, int derivOrder, T& value) const {
00656         // We need to allow the compiler to select std::sin or SimTK::sin
00657         // based on the argument type.
00658         using std::sin; using std::cos;
00659 
00660         assert(NumDerivs == 3);
00661         const Real t = s.getTime();
00662         const T arg = w*t + p;
00663 
00664         switch (derivOrder) {
00665         case 0: value =        a*sin(arg); break;
00666         case 1: value =      w*a*cos(arg); break;
00667         case 2: value =   -w*w*a*sin(arg); break;
00668         case 3: value = -w*w*w*a*cos(arg); break;
00669         default: SimTK_ASSERT1_ALWAYS(!"out of range",
00670                      "Measure::Sinusoid::Implementation::calcCachedValueVirtual():"
00671                      " derivOrder %d is out of range 0-3.", derivOrder);
00672         }
00673     }
00674 
00675     // There are no uncached values.
00676 
00677 private:
00678     // TOPOLOGY STATE
00679     T a, w, p;
00680 
00681     // TOPOLOGY CACHE
00682     // nothing
00683 };
00684 
00686     // PLUS::IMPLEMENTATION //
00688 
00689 template <class T>
00690 class Measure_<T>::Plus::Implementation
00691 :   public Measure_<T>::Implementation 
00692 {
00693 public:
00694     // TODO: Currently allocates just one cache entry.
00695     // left and right will be empty handles.
00696     Implementation() {}
00697 
00698     Implementation(const Measure_<T>& left, 
00699                    const Measure_<T>& right)
00700     :   left(left), right(right) {}
00701 
00702     // Default copy constructor gives us a new Implementation object,
00703     // but with references to the *same* operand measures.
00704 
00705     // Implementations of virtual methods.
00706 
00707     // This uses the default copy constructor.
00708     Implementation* cloneVirtual() const 
00709     {   return new Implementation(*this); }
00710 
00711     // TODO: Let this be settable up to the min number of derivatives 
00712     // provided by the arguments.
00713     int getNumTimeDerivativesVirtual() const {return 0;} 
00714     //{   return std::min(left.getNumTimeDerivatives(), 
00715     //                    right.getNumTimeDerivatives()); }
00716 
00717     Stage getDependsOnStageVirtual(int order) const 
00718     {   return Stage(std::max(left.getDependsOnStage(order),
00719                               right.getDependsOnStage(order))); }
00720 
00721 
00722     void calcCachedValueVirtual(const State& s, int derivOrder, T& value) const {
00723         value = left.getValue(s,derivOrder) + right.getValue(s,derivOrder);
00724     }
00725 
00726     // There are no uncached values.
00727 
00728 private:
00729     // TOPOLOGY STATE
00730     const Measure_<T> left;
00731     const Measure_<T> right;
00732 
00733     // TOPOLOGY CACHE
00734     // nothing
00735 };
00736 
00738     // MINUS::IMPLEMENTATION //
00740 
00741 template <class T>
00742 class Measure_<T>::Minus::Implementation
00743 :   public Measure_<T>::Implementation 
00744 {
00745 public:
00746     // TODO: Currently allocates just one cache entry.
00747     // left and right will be empty handles.
00748     Implementation() {}
00749 
00750     Implementation(const Measure_<T>& left, 
00751                    const Measure_<T>& right)
00752     :   left(left), right(right) {}
00753 
00754     // Default copy constructor gives us a new Implementation object,
00755     // but with references to the *same* operand measures.
00756 
00757     // Implementations of virtual methods.
00758 
00759     // This uses the default copy constructor.
00760     Implementation* cloneVirtual() const 
00761     {   return new Implementation(*this); }
00762 
00763     // TODO: Let this be settable up to the min number of derivatives 
00764     // provided by the arguments.
00765     int getNumTimeDerivativesVirtual() const {return 0;} 
00766     //{   return std::min(left.getNumTimeDerivatives(), 
00767     //                    right.getNumTimeDerivatives()); }
00768 
00769     Stage getDependsOnStageVirtual(int order) const 
00770     {   return Stage(std::max(left.getDependsOnStage(order),
00771                               right.getDependsOnStage(order))); }
00772 
00773 
00774     void calcCachedValueVirtual(const State& s, int derivOrder, T& value) const {
00775         value = left.getValue(s,derivOrder) - right.getValue(s,derivOrder);
00776     }
00777 
00778     // There are no uncached values.
00779 
00780 private:
00781     // TOPOLOGY STATE
00782     const Measure_<T> left;
00783     const Measure_<T> right;
00784 
00785     // TOPOLOGY CACHE
00786     // nothing
00787 };
00788 
00789 
00791     // SCALE::IMPLEMENTATION //
00793 
00794 template <class T>
00795 class Measure_<T>::Scale::Implementation
00796 :   public Measure_<T>::Implementation 
00797 {
00798 public:
00799     // TODO: Currently allocates just one cache entry.
00800     // scale will be uninitialized, operand will be empty handle.
00801     Implementation() : factor(NaN) {}
00802 
00803     Implementation(Real factor, const Measure_<T>& operand)
00804     :   factor(factor), operand(operand) {}
00805 
00806     // Default copy constructor gives us a new Implementation object,
00807     // but with references to the *same* operand measure.
00808 
00809     void setScaleFactor(Real sf) {
00810         factor = sf;
00811         this->invalidateTopologyCache();
00812     }
00813 
00814     // Implementations of virtual methods.
00815 
00816     // This uses the default copy constructor.
00817     Implementation* cloneVirtual() const 
00818     {   return new Implementation(*this); }
00819 
00820     // TODO: Let this be settable up to the min number of derivatives 
00821     // provided by the arguments.
00822     int getNumTimeDerivativesVirtual() const {return 0;} 
00823     //{   return std::min(left.getNumTimeDerivatives(), 
00824     //                    right.getNumTimeDerivatives()); }
00825 
00826     Stage getDependsOnStageVirtual(int order) const 
00827     {   return operand.getDependsOnStage(order); }
00828 
00829 
00830     void calcCachedValueVirtual(const State& s, int derivOrder, T& value) const {
00831         value = factor * operand.getValue(s,derivOrder);
00832     }
00833 
00834     // There are no uncached values.
00835 
00836 private:
00837     // TOPOLOGY STATE
00838     const Real        factor;
00839     const Measure_<T> operand;
00840 
00841     // TOPOLOGY CACHE
00842     // nothing
00843 };
00844 
00846     // INTEGRATE::IMPLEMENTATION //
00848 
00849 template <class T>
00850 class Measure_<T>::Integrate::Implementation 
00851 :   public Measure_<T>::Implementation {
00852 public:
00853     // We don't want any cache entries allocated -- we'll use the
00854     // State z variable as its own value and let the derivative 
00855     // Measure supply its value.
00856 
00857     // The derivative and initialConditions Measures will be
00858     // empty handles if this is default constructed.
00859     Implementation() : Measure_<T>::Implementation(0) {}
00860 
00861     // Here we're shallow-copying the Measure handles so we'll
00862     // be referring to the original Measures.
00863     Implementation(const Measure_<T>& deriv, const Measure_<T>& ic)
00864     :   Measure_<T>::Implementation(0), 
00865         derivMeasure(deriv), icMeasure(ic) {}
00866 
00867     // Copy constructor shallow-copies the referenced measures, but
00868     // we don't want to share our state variable.
00869     Implementation(const Implementation& source)
00870     :   Measure_<T>::Implementation(0), 
00871         derivMeasure(source.derivMeasure), icMeasure(source.icMeasure) {}
00872 
00873     void setValue(State& s, const T& value) const
00874     {   assert(zIndex >= 0); 
00875         this->getSubsystem().updZ(s)[zIndex] = value; }
00876     
00877     const Measure_<T>& getDerivativeMeasure() const
00878     {   SimTK_ERRCHK(!derivMeasure.isEmptyHandle(), 
00879             "Measure_<T>::Integrate::getDerivativeMeasure()",
00880             "No derivative measure is available for this integrated measure."); 
00881         return derivMeasure; }
00882 
00883     const Measure_<T>& getInitialConditionMeasure() const
00884     {   SimTK_ERRCHK(!icMeasure.isEmptyHandle(), 
00885             "Measure_<T>::Integrate::getInitialConditionMeasure()",
00886             "No initial condition measure is available for this "
00887             "integrated measure."); 
00888         return icMeasure; }
00889 
00890     void setDerivativeMeasure(const Measure_<T>& d)
00891     {   derivMeasure = d; this->invalidateTopologyCache(); }
00892     void setInitialConditionMeasure(const Measure_<T>& ic)
00893     {   icMeasure = ic; this->invalidateTopologyCache(); }
00894 
00895     // Implementations of virtuals.
00896 
00897     // This uses the copy constructor defined above.
00898     Implementation* cloneVirtual() const 
00899     {   return new Implementation(*this); }
00900 
00901     int getNumTimeDerivativesVirtual() const {return 1;}
00902 
00903     // There are no cached values.
00904 
00905     const T& getUncachedValueVirtual(const State& s, int derivOrder) const
00906     {   if (derivOrder>0) 
00907             return getDerivativeMeasure().getValue(s);
00908         else { 
00909             assert(zIndex.isValid()); 
00910             return this->getSubsystem().getZ(s)[zIndex];
00911         }
00912     }
00913     Stage getDependsOnStageVirtual(int derivOrder) const 
00914     {   return derivOrder>0 ? getDerivativeMeasure().getDependsOnStage(0)
00915                             : Stage::Time; }
00916 
00917     void initializeVirtual(State& s) const {
00918         assert(zIndex.isValid());
00919         Real& z = this->getSubsystem().updZ(s)[zIndex];
00920         if (!icMeasure.isEmptyHandle()) 
00921              z = icMeasure.getValue(s);
00922         else z = 0;
00923     }
00924 
00925     void realizeMeasureTopologyVirtual(State& s) const {
00926         static const Vector zero(1, Real(0));
00927         zIndex = this->getSubsystem().allocateZ(s, zero);
00928     }
00929 
00930     void realizeMeasureAccelerationVirtual(const State& s) const {
00931         assert(zIndex.isValid());
00932         Real& zdot = this->getSubsystem().updZDot(s)[zIndex];
00933         if (!derivMeasure.isEmptyHandle()) 
00934              zdot = derivMeasure.getValue(s);
00935         else zdot = 0;
00936     }
00937 
00938 private:
00939     // TOPOLOGY STATE
00940     const Measure_<T> derivMeasure; // just handles
00941     const Measure_<T> icMeasure;
00942 
00943     // TOPOLOGY CACHE
00944     mutable ZIndex zIndex;
00945 };
00946 
00948     // DIFFERENTIATE::IMPLEMENTATION //
00950 
00951 // This helper class is the contents of the discrete state variable and corresponding
00952 // cache entry maintained by this measure. The variable is auto-update,
00953 // meaning the value of the cache entry replaces the state variable at the
00954 // start of each step.
00955 // TODO: This was a local class in Measure_<T>::Differentiate::Implementation
00956 // but VC++ 8 (2005) failed to properly instantiate the templatized operator<<()
00957 // in that case; doing it this way is a workaround.
00958 template <class T>
00959 class Measure_Differentiate_Result {
00960 public:
00961     Measure_Differentiate_Result() : derivIsGood(false) {}
00962     T       operand;    // previous value of operand
00963     T       operandDot; // previous value of derivative
00964     bool    derivIsGood; // do we think the deriv is a good one?
00965 };
00966 
00967 
00968 // Dummy for Value<Measure_Differentiate_Result>.
00969 template <class T> inline std::ostream& 
00970 operator<<(std::ostream& o, 
00971            const Measure_Differentiate_Result<T>&)
00972 {   assert(!"not implemented"); return o; }
00973 
00974 template <class T>
00975 class Measure_<T>::Differentiate::Implementation
00976 :   public Measure_<T>::Implementation 
00977 {
00978     typedef Measure_Differentiate_Result<T> Result;
00979 public:
00980     // Don't allocate any cache entries in the base class.
00981     Implementation() : Measure_<T>::Implementation(0) {}
00982 
00983     Implementation(const Measure_<T>& operand)
00984     :   Measure_<T>::Implementation(0),
00985         operand(operand), forceUseApprox(false), isApproxInUse(false) {}
00986 
00987     // Default copy constructor gives us a new Implementation object,
00988     // but with reference to the *same* operand measure.
00989 
00990     void setForceUseApproximation(bool mustApproximate) {
00991         forceUseApprox = mustApproximate;
00992         this->invalidateTopologyCache();
00993     }
00994 
00995     void setOperandMeasure(const Measure_<T>& operand) {
00996         this->operand = operand;
00997         this->invalidateTopologyCache();
00998     }
00999 
01000     bool getForceUseApproximation() const {return forceUseApprox;}
01001     bool isUsingApproximation() const {return isApproxInUse;}
01002     const Measure_<T>& getOperandMeasure() const {return operand;}
01003 
01004     // Implementations of virtual methods.
01005 
01006     // This uses the default copy constructor.
01007     Implementation* cloneVirtual() const 
01008     {   return new Implementation(*this); }
01009 
01010     // This has one fewer than the operand.
01011     int getNumTimeDerivativesVirtual() const
01012     {   if (!isApproxInUse) return operand.getNumTimeDerivatives()-1;
01013         else return 0; }
01014 
01015     Stage getDependsOnStageVirtual(int order) const 
01016     {   if (!isApproxInUse) return operand.getDependsOnStage(order+1);
01017         else return operand.getDependsOnStage(order); }
01018 
01019 
01020     // We're not using the Measure_<T> base class cache services, but
01021     // we do have one of our own. It looks uncached from the base class
01022     // point of view which is why we're implementing it here.
01023     const T& getUncachedValueVirtual(const State& s, int derivOrder) const
01024     {   if (!isApproxInUse) 
01025             return operand.getValue(s, derivOrder+1);
01026 
01027         ensureDerivativeIsRealized(s);
01028         const Subsystem& subsys = this->getSubsystem();
01029         const Result& result = Value<Result>::downcast
01030                                 (subsys.getDiscreteVarUpdateValue(s,resultIx));
01031         return result.operandDot; // has a value but might not be a good one
01032     }
01033 
01034     void initializeVirtual(State& s) const {
01035         if (!isApproxInUse) return;
01036 
01037         assert(resultIx.isValid());
01038         const Subsystem& subsys = this->getSubsystem();
01039         Result& result = Value<Result>::updDowncast
01040                             (subsys.updDiscreteVariable(s,resultIx));
01041         result.operand = operand.getValue(s);
01042         result.operandDot = this->getValueZero();
01043         result.derivIsGood = false;
01044     }
01045 
01046     void realizeMeasureTopologyVirtual(State& s) const {
01047         isApproxInUse = (forceUseApprox || operand.getNumTimeDerivatives()==0);
01048         if (!isApproxInUse)
01049             return;
01050 
01051         resultIx = this->getSubsystem()
01052             .allocateAutoUpdateDiscreteVariable(s, operand.getDependsOnStage(0),
01053                 new Value<Result>(), operand.getDependsOnStage(0));
01054     }
01055 
01056     void ensureDerivativeIsRealized(const State& s) const {
01057         assert(resultIx.isValid());
01058         const Subsystem& subsys = this->getSubsystem();
01059         if (subsys.isDiscreteVarUpdateValueRealized(s,resultIx))
01060             return;
01061 
01062         const Real t0 = subsys.getDiscreteVarLastUpdateTime(s,resultIx);
01063         const Result& prevResult = Value<Result>::downcast
01064            (subsys.getDiscreteVariable(s,resultIx));
01065         const T&   f0         = prevResult.operand;
01066         const T&   fdot0      = prevResult.operandDot;   // may be invalid
01067         const bool good0     = prevResult.derivIsGood;
01068 
01069         const Real t  = s.getTime();
01070         Result& result = Value<Result>::updDowncast
01071            (subsys.updDiscreteVarUpdateValue(s,resultIx));
01072         T&         f          = result.operand;          // renaming
01073         T&         fdot       = result.operandDot;
01074         bool&      good       = result.derivIsGood;
01075 
01076         f = operand.getValue(s);
01077         good = false;
01078         if (!isFinite(t0))
01079             fdot = this->getValueZero(); 
01080         else if (t == t0) {
01081             fdot = fdot0;
01082             good = good0;
01083         } else {
01084             fdot = (f-f0)/(t-t0); // 1st order
01085             if (good0)
01086                 fdot = Real(2)*fdot - fdot0; // now 2nd order
01087             good = true; // either 1st or 2nd order estimate
01088         }
01089         subsys.markDiscreteVarUpdateValueRealized(s,resultIx);
01090     }
01091 private:
01092     // TOPOLOGY STATE
01093     Measure_<T>     operand;
01094     bool            forceUseApprox;
01095 
01096     // TOPOLOGY CACHE
01097     mutable bool                    isApproxInUse;
01098     mutable DiscreteVariableIndex   resultIx;    // auto-update
01099 };
01100 
01101 
01102 } // namespace SimTK
01103 
01104 
01105 
01106 
01107 #endif // SimTK_SimTKCOMMON_MEASURE_IMPLEMENTATION_H_

Generated on Thu Aug 12 16:37:12 2010 for SimTKcore by  doxygen 1.6.1