Simbody

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 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 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     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     void setIsPresumedValidAtDependsOnStage(bool presume) 
00319     {   presumeValidAtDependsOnStage = presume;
00320         this->invalidateTopologyCache(); }
00321 
00322     bool getIsPresumedValidAtDependsOnStage() const 
00323     {   return presumeValidAtDependsOnStage; }
00324 
00325 protected:
00326     // numValues is one greater than the number of derivatives; i.e., there
00327     // is room for the value ("0th" derivative) also. The default is to
00328     // allocate just room for the value.
00329     explicit Implementation(int numValues=1) 
00330     :   presumeValidAtDependsOnStage(false), 
00331         derivIx(numValues) {}
00332 
00333     // Copy constructor copies the *number* of cache entries from the
00334     // source, but not the cache indices themselves as those must be
00335     // allocated uniquely for the copy.
00336     Implementation(const Implementation& source) 
00337     :   presumeValidAtDependsOnStage(source.presumeValidAtDependsOnStage),
00338         derivIx(source.derivIx.size()) {}
00339 
00340 
00341     // Satisfy the realizeTopology() pure virtual here now that we know
00342     // the data type T. Allocate lazy- or auto-validated- cache entries
00343     // depending on the setting of presumeValidAtDependsOnStage.
00344     void realizeTopology(State& s) const {
00345         Implementation* mutableThis = const_cast<Implementation*>(this);
00346         // Allocate cache entries.
00347         for (int i=0; i < getNumCacheEntries(); ++i) {
00348             const Stage dependsOn = getDependsOnStage(i);
00349             if (presumeValidAtDependsOnStage) {
00350                 // Allocate auto-validated cache entries.
00351                 mutableThis->derivIx[i] =
00352                    this->getSubsystem().allocateCacheEntry
00353                         (s, dependsOn, new Value<T>());
00354             } else {
00355                 // Allocate lazy cache entries.
00356                 mutableThis->derivIx[i] =
00357                    this->getSubsystem().allocateLazyCacheEntry
00358                         (s, dependsOn, new Value<T>());
00359             }
00360         }
00361 
00362         // Call the concrete class virtual if any.
00363         realizeMeasureTopologyVirtual(s);
00364     }
00365 
00366     int getNumCacheEntries() const {return (int)derivIx.size();}
00367 
00368     const T& getCacheEntry(const State& s, int derivOrder) const {
00369         SimTK_ERRCHK2(0 <= derivOrder && derivOrder < getNumCacheEntries(),
00370             "Measure_<T>::Implementation::getCacheEntry()",
00371             "Derivative order %d is out of range; only %d cache entries"
00372             " were allocated.", derivOrder, getNumCacheEntries());
00373 
00374         return Value<T>::downcast(
00375             this->getSubsystem().getCacheEntry(s, derivIx[derivOrder]));
00376     }
00377 
00378     T& updCacheEntry(const State& s, int derivOrder) const {
00379         SimTK_ERRCHK2(0 <= derivOrder && derivOrder < getNumCacheEntries(),
00380             "Measure_<T>::Implementation::updCacheEntry()",
00381             "Derivative order %d is out of range; only %d cache entries"
00382             " were allocated.", derivOrder, getNumCacheEntries());
00383 
00384         return Value<T>::updDowncast(
00385             this->getSubsystem().updCacheEntry(s, derivIx[derivOrder]));
00386     }
00387 
00388     bool isCacheValueRealized(const State& s, int derivOrder) const {
00389         SimTK_ERRCHK2(0 <= derivOrder && derivOrder < getNumCacheEntries(),
00390             "Measure_<T>::Implementation::isCacheValueRealized()",
00391             "Derivative order %d is out of range; only %d cache entries"
00392             " were allocated.", derivOrder, getNumCacheEntries());
00393 
00394         return this->getSubsystem().isCacheValueRealized(s, derivIx[derivOrder]);
00395     }
00396 
00397     void markCacheValueRealized(const State& s, int derivOrder) const {
00398         SimTK_ERRCHK2(0 <= derivOrder && derivOrder < getNumCacheEntries(),
00399             "Measure_<T>::Implementation::markCacheValueRealized()",
00400             "Derivative order %d is out of range; only %d cache entries"
00401             " were allocated.", derivOrder, getNumCacheEntries());
00402 
00403         this->getSubsystem().markCacheValueRealized(s, derivIx[derivOrder]);
00404     }
00405 
00406     void markCacheValueNotRealized(const State& s, int derivOrder) const {
00407         SimTK_ERRCHK2(0 <= derivOrder && derivOrder < getNumCacheEntries(),
00408             "Measure_<T>::Implementation::markCacheValueNotRealized()",
00409             "Derivative order %d is out of range; only %d cache entries"
00410             " were allocated.", derivOrder, getNumCacheEntries());
00411 
00412         this->getSubsystem().markCacheValueNotRealized(s, derivIx[derivOrder]);
00413     }
00414 
00415     // VIRTUALS //
00416     // Ordinals must retain the same meaning from release to release
00417     // to preserve binary compatibility.
00418 
00419     /* 0*/virtual void realizeMeasureTopologyVirtual(State&) const {}
00420     /* 1*/virtual void 
00421     calcCachedValueVirtual(const State&, int derivOrder, T& value) const
00422     {   SimTK_ERRCHK1_ALWAYS(!"implemented", 
00423         "Measure_<T>::Implementation::calcCachedValueVirtual()",
00424         "This method should have been overridden by the derived"
00425         " Measure but was not. It is needed to calculate the"
00426         " cached value for derivOrder=%d.", derivOrder); }
00427 
00428     // This is only called when derivOrder >= the number of cache 
00429     // entries we have, but still <= the number of derivatives the
00430     // Measure says it can deliver.
00431     /* 2*/virtual const T& 
00432     getUncachedValueVirtual(const State&, int derivOrder) const
00433     {   SimTK_ERRCHK1_ALWAYS(!"implemented", 
00434             "Measure_<T>::Implementation::getUncachedValueVirtual()",
00435             "This method should have been overridden by the derived"
00436             " Measure but was not. It is needed to return the uncached"
00437             " value at derivOrder=%d.", derivOrder);
00438         return *reinterpret_cast<T*>(0);
00439     }
00440 
00441     // STATICS //
00442     static const T& getValueZero() {
00443         static T zero(0);
00444         return zero;
00445     }
00446 
00447     static const T& getValueOne() {
00448         static T one(1);
00449         return one;
00450     }
00451 
00452 private:
00453     bool presumeValidAtDependsOnStage;
00454     Array_<CacheEntryIndex> derivIx;
00455 };
00456 
00457 
00458 
00460     // CONSTANT::IMPLEMENTATION //
00462 
00463 template <class T>
00464 class Measure_<T>::Constant::Implementation 
00465 :   public Measure_<T>::Implementation 
00466 {
00467 public:
00468     // We don't want the base class to allocate *any* cache entries.
00469     Implementation() : Measure_<T>::Implementation(0) {}
00470     explicit Implementation(const T& value) 
00471     :   Measure_<T>::Implementation(0), value(value) {}
00472 
00473     // Allow this to be overridden by derived classes so they can
00474     // refuse to allow their values to change.
00475     virtual void setValue(const T& v) {
00476         value = v;
00477         this->invalidateTopologyCache();
00478     }
00479 
00480     // Implementations of virtual methods.
00481     // Measure_<T> virtuals:
00482     // No cached values.
00483 
00484     const T& getUncachedValueVirtual(const State&, int derivOrder) const 
00485     {   return derivOrder>0 ? this->getValueZero() : value; }
00486 
00487     // AbstractMeasure virtuals:
00488     Implementation* cloneVirtual() const {return new Implementation(*this);}
00489     Stage getDependsOnStageVirtual(int derivOrder) const 
00490     {   return derivOrder>0 ? Stage::Empty : Stage::Topology; }
00491     int getNumTimeDerivativesVirtual() const 
00492     {   return std::numeric_limits<int>::max(); }
00493 
00494 private:
00495     T value;
00496 };
00497 
00499     // ZERO::IMPLEMENTATION //
00501 
00502 template <class T>
00503 class Measure_<T>::Zero::Implementation 
00504 :   public Constant::Implementation 
00505 {
00506 public:
00507     Implementation() : Constant::Implementation(T(0)) {} 
00508 
00509     // VIRTUALS
00510     // From Constant::Implementation:
00511     void setValue(const T&) {
00512         SimTK_ERRCHK_ALWAYS(!"invalid", "Measure_<T>::Zero::setValue()",
00513             "You can't change the value of Zero!");
00514     }
00515 
00516     // From AbstractMeasure:
00517     Implementation* cloneVirtual() const {return new Implementation(*this);}
00518     Stage getDependsOnStageVirtual(int) const 
00519     {   return Stage::Empty; }
00520 };
00521 
00523     // ONE::IMPLEMENTATION //
00525 
00526 
00527 template <class T>
00528 class Measure_<T>::One::Implementation 
00529 :   public Constant::Implementation 
00530 {
00531 public:
00532     Implementation() : Constant::Implementation(T(1)) {} 
00533 
00534     // VIRTUALS
00535     // From Constant::Implementation:
00536     void setValue(const T&) {
00537         SimTK_ERRCHK_ALWAYS(!"invalid", "Measure_<T>::One::setValue()",
00538             "You can't change the value of One!");
00539     }
00540     // From AbstractMeasure:
00541     Implementation* cloneVirtual() const {return new Implementation(*this);}
00542     Stage getDependsOnStageVirtual(int) const 
00543     {   return Stage::Empty; }
00544 };
00545 
00546 
00548     // TIME::IMPLEMENTATION //
00550 
00551 template <class T>
00552 class Measure_<T>::Time::Implementation {};
00553 
00554 template <>
00555 class Measure_<Real>::Time::Implementation 
00556 :   public Measure_<Real>::Implementation 
00557 {
00558 public:
00559     // We don't want the base class to allocate *any* cache entries.
00560     Implementation() : Measure_<Real>::Implementation(0) {}
00561 
00562     // Implementations of virtual methods.
00563     // Measure_<Real> virtuals:
00564     // No cached values.
00565 
00566     const Real& getUncachedValueVirtual(const State& s, int derivOrder) const 
00567     {   return derivOrder==0 ? s.getTime()
00568             : (derivOrder==1 ? this->getValueOne() 
00569                              : this->getValueZero()); }
00570 
00571     // AbstractMeasure virtuals:
00572     Implementation* cloneVirtual() const {return new Implementation(*this);}
00573     Stage getDependsOnStageVirtual(int derivOrder) const 
00574     {   return derivOrder>0 ? Stage::Empty : Stage::Time; }
00575 
00576     // Value is t, 1st derivative is 1, the rest are 0.
00577     int getNumTimeDerivativesVirtual() const 
00578     {   return std::numeric_limits<int>::max(); }
00579 };
00580 
00582     // VARIABLE::IMPLEMENTATION //
00584 
00585 template <class T>
00586 class Measure_<T>::Variable::Implementation 
00587 :   public Measure_<T>::Implementation 
00588 {
00589 public:
00590     // We don't want the base class to allocate *any* cache entries;
00591     // we'll use the variable as its own value and zeroes for all
00592     // the derivatives.
00593     Implementation() 
00594     :   Measure_<T>::Implementation(0),
00595         invalidatedStage(Stage::Empty), defaultValue() {}
00596 
00597     Implementation(Stage invalidated, const T& defaultValue) 
00598     :   Measure_<T>::Implementation(0),
00599         invalidatedStage(invalidated), defaultValue(defaultValue) {}
00600 
00601     // Copy constructor should not copy the variable.
00602     Implementation(const Implementation& source)
00603     :   Measure_<T>::Implementation(0),
00604         invalidatedStage(source.invalidatedStage), 
00605         defaultValue(source.defaultValue) {}
00606 
00607     void setDefaultValue(const T& v) {
00608         defaultValue = v;
00609         this->invalidateTopologyCache();
00610     }
00611 
00612     void setInvalidatedStage(Stage invalidates) {
00613         invalidatedStage = invalidates;
00614         this->invalidateTopologyCache();
00615     }
00616 
00617     const T& getDefaultValue()     const {return defaultValue;}
00618     Stage    getInvalidatedStage() const {return invalidatedStage;}
00619 
00620     void setValue(State& state, const T& value) const 
00621     {   updVarValue(state) = value; }
00622 
00623     // Implementations of virtual methods.
00624     Implementation* cloneVirtual() const {return new Implementation(*this);}
00625 
00626     int getNumTimeDerivativesVirtual() const 
00627     {   return std::numeric_limits<int>::max(); }
00628 
00629     // Discrete variable is available after Model stage; but all its 
00630     // derivatives are zero so are always available.
00631     Stage getDependsOnStageVirtual(int derivOrder) const 
00632     {   return derivOrder>0 ? Stage::Empty : Stage::Model;}
00633 
00634     const T& getUncachedValueVirtual(const State& s, int derivOrder) const 
00635     {   return derivOrder>0 ? this->getValueZero() : getVarValue(s); }
00636 
00637     // No cached values.
00638 
00639     void realizeMeasureTopologyVirtual(State& s) const {
00640         discreteVarIndex = this->getSubsystem().allocateDiscreteVariable
00641             (s, invalidatedStage, new Value<T>(defaultValue));
00642     }
00643 private:
00644     const T& getVarValue(const State& s) const {
00645         assert(discreteVarIndex.isValid());
00646         return Value<T>::downcast(
00647             this->getSubsystem().getDiscreteVariable(s, discreteVarIndex));
00648     }
00649     T& updVarValue(State& s) const {
00650         assert(discreteVarIndex.isValid());
00651         return Value<T>::downcast(
00652             this->getSubsystem().updDiscreteVariable(s, discreteVarIndex));
00653     }
00654 
00655     // TOPOLOGY STATE
00656     Stage   invalidatedStage; // TODO this shouldn't be needed
00657     T       defaultValue;
00658 
00659     // TOPOLOGY CACHE
00660     mutable DiscreteVariableIndex discreteVarIndex;
00661 };
00662 
00663 
00665     // RESULT::IMPLEMENTATION //
00667 
00668 template <class T>
00669 class Measure_<T>::Result::Implementation 
00670 :   public Measure_<T>::Implementation 
00671 {
00672 public:
00673     // We want the base class to allocate a single cache entry of type T.
00674     Implementation() 
00675     :   Measure_<T>::Implementation(1), 
00676         dependsOnStage(Stage::Topology), invalidatedStage(Stage::Infinity) {}
00677 
00678     Implementation(Stage dependsOn, Stage invalidated) 
00679     :   Measure_<T>::Implementation(1), 
00680         dependsOnStage(dependsOn==Stage::Empty ? Stage::Topology : dependsOn), 
00681         invalidatedStage(invalidated)
00682     {   SimTK_ERRCHK2_ALWAYS(invalidated > dependsOn,"Measure::Result::ctor()",
00683             "Got invalidated stage %s and dependsOn stage %s which is illegal "
00684             "because the invalidated stage must be later than dependsOn.",
00685             invalidated.getName().c_str(), dependsOn.getName().c_str());
00686     }
00687 
00688     // Copy constructor will not copy the cache entry index.
00689     Implementation(const Implementation& source)
00690     :   Measure_<T>::Implementation(source),
00691         dependsOnStage(source.dependsOnStage), 
00692         invalidatedStage(source.invalidatedStage) {} 
00693 
00694     void setDependsOnStage(Stage dependsOn) {
00695         if (dependsOn == Stage::Empty) dependsOn = Stage::Topology;
00696         SimTK_ERRCHK2_ALWAYS(dependsOn < getInvalidatedStage(),
00697             "Measure::Result::setDependsOnStage()",
00698             "The provided dependsOn stage %s is illegal because it is not "
00699             "less than the current invalidated stage %s. Change the "
00700             "invalidated stage first with setInvalidatedStage().",
00701             dependsOn.getName().c_str(), 
00702             getInvalidatedStage().getName().c_str());
00703 
00704         dependsOnStage = dependsOn;
00705         this->invalidateTopologyCache();
00706     }
00707 
00708     void setInvalidatedStage(Stage invalidated) {
00709         SimTK_ERRCHK2_ALWAYS(invalidated > getDependsOnStage(),
00710             "Measure::Result::setInvalidatedStage()",
00711             "The provided invalidated stage %s is illegal because it is not "
00712             "greater than the current dependsOn stage %s. Change the "
00713             "dependsOn stage first with setDependsOnStage().",
00714             invalidated.getName().c_str(),
00715             getDependsOnStage().getName().c_str());
00716 
00717         invalidatedStage = invalidated;
00718         this->invalidateTopologyCache();
00719     }
00720 
00721 
00722     Stage getDependsOnStage()   const {return dependsOnStage;}
00723     Stage getInvalidatedStage() const {return invalidatedStage;}
00724 
00725 
00726     void markAsValid(const State& state) const
00727     {   const Stage subsystemStage = this->getSubsystem().getStage(state);
00728         SimTK_ERRCHK3_ALWAYS(subsystemStage >= getDependsOnStage().prev(),
00729             "Measure::Result::markAsValid()",
00730             "This Result Measure cannot be marked valid in a State where this "
00731             "measure's Subsystem has been realized only to stage %s, because "
00732             "its value was declared to depend on stage %s. To mark it valid, "
00733             "we require that the State have been realized at least to the "
00734             "previous stage (%s in this case); that is, you must at least be "
00735             "*working on* the dependsOn stage in order to claim this result is "
00736             "available.",
00737             subsystemStage.getName().c_str(),
00738             getDependsOnStage().getName().c_str(),
00739             getDependsOnStage().prev().getName().c_str());
00740         this->markCacheValueRealized(state, 0); }
00741 
00742     bool isValid(const State& state) const
00743     {   return this->isCacheValueRealized(state, 0); }
00744     
00745     void markAsNotValid(const State& state) const
00746     {   this->markCacheValueNotRealized(state, 0); 
00747         state.invalidateAllCacheAtOrAbove(invalidatedStage); }
00748 
00749     T& updValue(const State& state) const 
00750     {   markAsNotValid(state); return this->updCacheEntry(state, 0); }
00751 
00752 
00753     // Implementations of virtual methods.
00754     virtual Implementation* cloneVirtual() const 
00755     {   return new Implementation(*this); }
00756 
00757     virtual int getNumTimeDerivativesVirtual() const {return 0;} 
00758 
00759     // Discrete variable is available after Model stage; but all its 
00760     // derivatives are zero so are always available.
00761     virtual Stage getDependsOnStageVirtual(int derivOrder) const 
00762     {   return derivOrder>0 ? Stage::Empty : dependsOnStage;}
00763 
00764     virtual void 
00765     calcCachedValueVirtual(const State&, int derivOrder, T& value) const
00766     {   SimTK_ERRCHK_ALWAYS(!"calcCachedValueVirtual() implemented",
00767         "Measure_<T>::Result::getValue()",
00768         "Measure_<T>::Result::getValue() was called when the value was not "
00769         "yet valid. For most Measure types, this would have initiated "
00770         "computation of the value, but Result measures must have their values "
00771         "calculated and set externally, and then marked valid."); }
00772 
00773 private:
00774     // TOPOLOGY STATE
00775     Stage   dependsOnStage;
00776     Stage   invalidatedStage;
00777 };
00778 
00779 
00781     // SINUSOID::IMPLEMENTATION //
00783 
00784 template <class T>
00785 class Measure_<T>::Sinusoid::Implementation
00786 :   public Measure_<T>::Implementation 
00787 {
00788     static const int NumDerivs = 3;
00789 public:
00790     Implementation() 
00791     :   Measure_<T>::Implementation(NumDerivs+1),
00792         a(CNT<T>::getNaN()), w(CNT<T>::getNaN()), p(CNT<T>::getNaN()) {}
00793 
00794     Implementation(const T& amplitude, 
00795                    const T& frequency, 
00796                    const T& phase=T(0))
00797     :   Measure_<T>::Implementation(NumDerivs+1),
00798         a(amplitude), w(frequency), p(phase) {}
00799 
00800     // Default copy constructor is fine.
00801 
00802     // Implementations of virtual methods.
00803     Implementation* cloneVirtual() const {return new Implementation(*this);}
00804 
00805     int getNumTimeDerivativesVirtual() const {return NumDerivs;}
00806 
00807     Stage getDependsOnStageVirtual(int order) const 
00808     {   return Stage::Time; }
00809 
00810     void calcCachedValueVirtual(const State& s, int derivOrder, T& value) const {
00811         // We need to allow the compiler to select std::sin or SimTK::sin
00812         // based on the argument type.
00813         using std::sin; using std::cos;
00814 
00815         assert(NumDerivs == 3);
00816         const Real t = s.getTime();
00817         const T arg = w*t + p;
00818 
00819         switch (derivOrder) {
00820         case 0: value =        a*sin(arg); break;
00821         case 1: value =      w*a*cos(arg); break;
00822         case 2: value =   -w*w*a*sin(arg); break;
00823         case 3: value = -w*w*w*a*cos(arg); break;
00824         default: SimTK_ASSERT1_ALWAYS(!"out of range",
00825                      "Measure::Sinusoid::Implementation::calcCachedValueVirtual():"
00826                      " derivOrder %d is out of range 0-3.", derivOrder);
00827         }
00828     }
00829 
00830     // There are no uncached values.
00831 
00832 private:
00833     // TOPOLOGY STATE
00834     T a, w, p;
00835 
00836     // TOPOLOGY CACHE
00837     // nothing
00838 };
00839 
00841     // PLUS::IMPLEMENTATION //
00843 
00844 template <class T>
00845 class Measure_<T>::Plus::Implementation
00846 :   public Measure_<T>::Implementation 
00847 {
00848 public:
00849     // TODO: Currently allocates just one cache entry.
00850     // left and right will be empty handles.
00851     Implementation() {}
00852 
00853     Implementation(const Measure_<T>& left, 
00854                    const Measure_<T>& right)
00855     :   left(left), right(right) {}
00856 
00857     // Default copy constructor gives us a new Implementation object,
00858     // but with references to the *same* operand measures.
00859 
00860     // Implementations of virtual methods.
00861 
00862     // This uses the default copy constructor.
00863     Implementation* cloneVirtual() const 
00864     {   return new Implementation(*this); }
00865 
00866     // TODO: Let this be settable up to the min number of derivatives 
00867     // provided by the arguments.
00868     int getNumTimeDerivativesVirtual() const {return 0;} 
00869     //{   return std::min(left.getNumTimeDerivatives(), 
00870     //                    right.getNumTimeDerivatives()); }
00871 
00872     Stage getDependsOnStageVirtual(int order) const 
00873     {   return Stage(std::max(left.getDependsOnStage(order),
00874                               right.getDependsOnStage(order))); }
00875 
00876 
00877     void calcCachedValueVirtual(const State& s, int derivOrder, T& value) const {
00878         value = left.getValue(s,derivOrder) + right.getValue(s,derivOrder);
00879     }
00880 
00881     // There are no uncached values.
00882 
00883 private:
00884     // TOPOLOGY STATE
00885     const Measure_<T> left;
00886     const Measure_<T> right;
00887 
00888     // TOPOLOGY CACHE
00889     // nothing
00890 };
00891 
00893     // MINUS::IMPLEMENTATION //
00895 
00896 template <class T>
00897 class Measure_<T>::Minus::Implementation
00898 :   public Measure_<T>::Implementation 
00899 {
00900 public:
00901     // TODO: Currently allocates just one cache entry.
00902     // left and right will be empty handles.
00903     Implementation() {}
00904 
00905     Implementation(const Measure_<T>& left, 
00906                    const Measure_<T>& right)
00907     :   left(left), right(right) {}
00908 
00909     // Default copy constructor gives us a new Implementation object,
00910     // but with references to the *same* operand measures.
00911 
00912     // Implementations of virtual methods.
00913 
00914     // This uses the default copy constructor.
00915     Implementation* cloneVirtual() const 
00916     {   return new Implementation(*this); }
00917 
00918     // TODO: Let this be settable up to the min number of derivatives 
00919     // provided by the arguments.
00920     int getNumTimeDerivativesVirtual() const {return 0;} 
00921     //{   return std::min(left.getNumTimeDerivatives(), 
00922     //                    right.getNumTimeDerivatives()); }
00923 
00924     Stage getDependsOnStageVirtual(int order) const 
00925     {   return Stage(std::max(left.getDependsOnStage(order),
00926                               right.getDependsOnStage(order))); }
00927 
00928 
00929     void calcCachedValueVirtual(const State& s, int derivOrder, T& value) const {
00930         value = left.getValue(s,derivOrder) - right.getValue(s,derivOrder);
00931     }
00932 
00933     // There are no uncached values.
00934 
00935 private:
00936     // TOPOLOGY STATE
00937     const Measure_<T> left;
00938     const Measure_<T> right;
00939 
00940     // TOPOLOGY CACHE
00941     // nothing
00942 };
00943 
00944 
00946     // SCALE::IMPLEMENTATION //
00948 
00949 template <class T>
00950 class Measure_<T>::Scale::Implementation
00951 :   public Measure_<T>::Implementation 
00952 {
00953 public:
00954     // TODO: Currently allocates just one cache entry.
00955     // scale will be uninitialized, operand will be empty handle.
00956     Implementation() : factor(NaN) {}
00957 
00958     Implementation(Real factor, const Measure_<T>& operand)
00959     :   factor(factor), operand(operand) {}
00960 
00961     // Default copy constructor gives us a new Implementation object,
00962     // but with references to the *same* operand measure.
00963 
00964     void setScaleFactor(Real sf) {
00965         factor = sf;
00966         this->invalidateTopologyCache();
00967     }
00968 
00969     // Implementations of virtual methods.
00970 
00971     // This uses the default copy constructor.
00972     Implementation* cloneVirtual() const 
00973     {   return new Implementation(*this); }
00974 
00975     // TODO: Let this be settable up to the min number of derivatives 
00976     // provided by the arguments.
00977     int getNumTimeDerivativesVirtual() const {return 0;} 
00978     //{   return std::min(left.getNumTimeDerivatives(), 
00979     //                    right.getNumTimeDerivatives()); }
00980 
00981     Stage getDependsOnStageVirtual(int order) const 
00982     {   return operand.getDependsOnStage(order); }
00983 
00984 
00985     void calcCachedValueVirtual(const State& s, int derivOrder, T& value) const {
00986         value = factor * operand.getValue(s,derivOrder);
00987     }
00988 
00989     // There are no uncached values.
00990 
00991 private:
00992     // TOPOLOGY STATE
00993     const Real        factor;
00994     const Measure_<T> operand;
00995 
00996     // TOPOLOGY CACHE
00997     // nothing
00998 };
00999 
01001     // INTEGRATE::IMPLEMENTATION //
01003 
01004 template <class T>
01005 class Measure_<T>::Integrate::Implementation 
01006 :   public Measure_<T>::Implementation {
01007 public:
01008     // We don't want any cache entries allocated -- we'll use the
01009     // State z variable as its own value and let the derivative 
01010     // Measure supply its value.
01011 
01012     // The derivative and initialConditions Measures will be
01013     // empty handles if this is default constructed.
01014     Implementation() : Measure_<T>::Implementation(0) {}
01015 
01016     // Here we're shallow-copying the Measure handles so we'll
01017     // be referring to the original Measures.
01018     Implementation(const Measure_<T>& deriv, const Measure_<T>& ic)
01019     :   Measure_<T>::Implementation(0), 
01020         derivMeasure(deriv), icMeasure(ic) {}
01021 
01022     // Copy constructor shallow-copies the referenced measures, but
01023     // we don't want to share our state variable.
01024     Implementation(const Implementation& source)
01025     :   Measure_<T>::Implementation(0), 
01026         derivMeasure(source.derivMeasure), icMeasure(source.icMeasure) {}
01027 
01028     void setValue(State& s, const T& value) const
01029     {   assert(zIndex >= 0); 
01030         this->getSubsystem().updZ(s)[zIndex] = value; }
01031     
01032     const Measure_<T>& getDerivativeMeasure() const
01033     {   SimTK_ERRCHK(!derivMeasure.isEmptyHandle(), 
01034             "Measure_<T>::Integrate::getDerivativeMeasure()",
01035             "No derivative measure is available for this integrated measure."); 
01036         return derivMeasure; }
01037 
01038     const Measure_<T>& getInitialConditionMeasure() const
01039     {   SimTK_ERRCHK(!icMeasure.isEmptyHandle(), 
01040             "Measure_<T>::Integrate::getInitialConditionMeasure()",
01041             "No initial condition measure is available for this "
01042             "integrated measure."); 
01043         return icMeasure; }
01044 
01045     void setDerivativeMeasure(const Measure_<T>& d)
01046     {   derivMeasure = d; this->invalidateTopologyCache(); }
01047     void setInitialConditionMeasure(const Measure_<T>& ic)
01048     {   icMeasure = ic; this->invalidateTopologyCache(); }
01049 
01050     // Implementations of virtuals.
01051 
01052     // This uses the copy constructor defined above.
01053     Implementation* cloneVirtual() const 
01054     {   return new Implementation(*this); }
01055 
01056     int getNumTimeDerivativesVirtual() const {return 1;}
01057 
01058     // There are no cached values.
01059 
01060     const T& getUncachedValueVirtual(const State& s, int derivOrder) const
01061     {   if (derivOrder>0) 
01062             return getDerivativeMeasure().getValue(s);
01063         else { 
01064             assert(zIndex.isValid()); 
01065             return this->getSubsystem().getZ(s)[zIndex];
01066         }
01067     }
01068     Stage getDependsOnStageVirtual(int derivOrder) const 
01069     {   return derivOrder>0 ? getDerivativeMeasure().getDependsOnStage(0)
01070                             : Stage::Time; }
01071 
01072     void initializeVirtual(State& s) const {
01073         assert(zIndex.isValid());
01074         Real& z = this->getSubsystem().updZ(s)[zIndex];
01075         if (!icMeasure.isEmptyHandle()) 
01076              z = icMeasure.getValue(s);
01077         else z = 0;
01078     }
01079 
01080     void realizeMeasureTopologyVirtual(State& s) const {
01081         static const Vector zero(1, Real(0));
01082         zIndex = this->getSubsystem().allocateZ(s, zero);
01083     }
01084 
01085     void realizeMeasureAccelerationVirtual(const State& s) const {
01086         assert(zIndex.isValid());
01087         Real& zdot = this->getSubsystem().updZDot(s)[zIndex];
01088         if (!derivMeasure.isEmptyHandle()) 
01089              zdot = derivMeasure.getValue(s);
01090         else zdot = 0;
01091     }
01092 
01093 private:
01094     // TOPOLOGY STATE
01095     const Measure_<T> derivMeasure; // just handles
01096     const Measure_<T> icMeasure;
01097 
01098     // TOPOLOGY CACHE
01099     mutable ZIndex zIndex;
01100 };
01101 
01103     // DIFFERENTIATE::IMPLEMENTATION //
01105 
01106 // This helper class is the contents of the discrete state variable and corresponding
01107 // cache entry maintained by this measure. The variable is auto-update,
01108 // meaning the value of the cache entry replaces the state variable at the
01109 // start of each step.
01110 // TODO: This was a local class in Measure_<T>::Differentiate::Implementation
01111 // but VC++ 8 (2005) failed to properly instantiate the templatized operator<<()
01112 // in that case; doing it this way is a workaround.
01113 template <class T>
01114 class Measure_Differentiate_Result {
01115 public:
01116     Measure_Differentiate_Result() : derivIsGood(false) {}
01117     T       operand;    // previous value of operand
01118     T       operandDot; // previous value of derivative
01119     bool    derivIsGood; // do we think the deriv is a good one?
01120 };
01121 
01122 
01123 // Dummy for Value<Measure_Differentiate_Result>.
01124 template <class T> inline std::ostream& 
01125 operator<<(std::ostream& o, 
01126            const Measure_Differentiate_Result<T>&)
01127 {   assert(!"not implemented"); return o; }
01128 
01129 template <class T>
01130 class Measure_<T>::Differentiate::Implementation
01131 :   public Measure_<T>::Implementation 
01132 {
01133     typedef Measure_Differentiate_Result<T> Result;
01134 public:
01135     // Don't allocate any cache entries in the base class.
01136     Implementation() : Measure_<T>::Implementation(0) {}
01137 
01138     Implementation(const Measure_<T>& operand)
01139     :   Measure_<T>::Implementation(0),
01140         operand(operand), forceUseApprox(false), isApproxInUse(false) {}
01141 
01142     // Default copy constructor gives us a new Implementation object,
01143     // but with reference to the *same* operand measure.
01144 
01145     void setForceUseApproximation(bool mustApproximate) {
01146         forceUseApprox = mustApproximate;
01147         this->invalidateTopologyCache();
01148     }
01149 
01150     void setOperandMeasure(const Measure_<T>& operand) {
01151         this->operand = operand;
01152         this->invalidateTopologyCache();
01153     }
01154 
01155     bool getForceUseApproximation() const {return forceUseApprox;}
01156     bool isUsingApproximation() const {return isApproxInUse;}
01157     const Measure_<T>& getOperandMeasure() const {return operand;}
01158 
01159     // Implementations of virtual methods.
01160 
01161     // This uses the default copy constructor.
01162     Implementation* cloneVirtual() const 
01163     {   return new Implementation(*this); }
01164 
01165     // This has one fewer than the operand.
01166     int getNumTimeDerivativesVirtual() const
01167     {   if (!isApproxInUse) return operand.getNumTimeDerivatives()-1;
01168         else return 0; }
01169 
01170     Stage getDependsOnStageVirtual(int order) const 
01171     {   if (!isApproxInUse) return operand.getDependsOnStage(order+1);
01172         else return operand.getDependsOnStage(order); }
01173 
01174 
01175     // We're not using the Measure_<T> base class cache services, but
01176     // we do have one of our own. It looks uncached from the base class
01177     // point of view which is why we're implementing it here.
01178     const T& getUncachedValueVirtual(const State& s, int derivOrder) const
01179     {   if (!isApproxInUse) 
01180             return operand.getValue(s, derivOrder+1);
01181 
01182         ensureDerivativeIsRealized(s);
01183         const Subsystem& subsys = this->getSubsystem();
01184         const Result& result = Value<Result>::downcast
01185                                 (subsys.getDiscreteVarUpdateValue(s,resultIx));
01186         return result.operandDot; // has a value but might not be a good one
01187     }
01188 
01189     void initializeVirtual(State& s) const {
01190         if (!isApproxInUse) return;
01191 
01192         assert(resultIx.isValid());
01193         const Subsystem& subsys = this->getSubsystem();
01194         Result& result = Value<Result>::updDowncast
01195                             (subsys.updDiscreteVariable(s,resultIx));
01196         result.operand = operand.getValue(s);
01197         result.operandDot = this->getValueZero();
01198         result.derivIsGood = false;
01199     }
01200 
01201     void realizeMeasureTopologyVirtual(State& s) const {
01202         isApproxInUse = (forceUseApprox || operand.getNumTimeDerivatives()==0);
01203         if (!isApproxInUse)
01204             return;
01205 
01206         resultIx = this->getSubsystem()
01207             .allocateAutoUpdateDiscreteVariable(s, operand.getDependsOnStage(0),
01208                 new Value<Result>(), operand.getDependsOnStage(0));
01209     }
01210 
01211     void ensureDerivativeIsRealized(const State& s) const {
01212         assert(resultIx.isValid());
01213         const Subsystem& subsys = this->getSubsystem();
01214         if (subsys.isDiscreteVarUpdateValueRealized(s,resultIx))
01215             return;
01216 
01217         const Real t0 = subsys.getDiscreteVarLastUpdateTime(s,resultIx);
01218         const Result& prevResult = Value<Result>::downcast
01219            (subsys.getDiscreteVariable(s,resultIx));
01220         const T&   f0         = prevResult.operand;
01221         const T&   fdot0      = prevResult.operandDot;   // may be invalid
01222         const bool good0     = prevResult.derivIsGood;
01223 
01224         const Real t  = s.getTime();
01225         Result& result = Value<Result>::updDowncast
01226            (subsys.updDiscreteVarUpdateValue(s,resultIx));
01227         T&         f          = result.operand;          // renaming
01228         T&         fdot       = result.operandDot;
01229         bool&      good       = result.derivIsGood;
01230 
01231         f = operand.getValue(s);
01232         good = false;
01233         if (!isFinite(t0))
01234             fdot = this->getValueZero(); 
01235         else if (t == t0) {
01236             fdot = fdot0;
01237             good = good0;
01238         } else {
01239             fdot = (f-f0)/(t-t0); // 1st order
01240             if (good0)
01241                 fdot = Real(2)*fdot - fdot0; // now 2nd order
01242             good = true; // either 1st or 2nd order estimate
01243         }
01244         subsys.markDiscreteVarUpdateValueRealized(s,resultIx);
01245     }
01246 private:
01247     // TOPOLOGY STATE
01248     Measure_<T>     operand;
01249     bool            forceUseApprox;
01250 
01251     // TOPOLOGY CACHE
01252     mutable bool                    isApproxInUse;
01253     mutable DiscreteVariableIndex   resultIx;    // auto-update
01254 };
01255 
01256 
01257 } // namespace SimTK
01258 
01259 
01260 
01261 
01262 #endif // SimTK_SimTKCOMMON_MEASURE_IMPLEMENTATION_H_
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines