Simbody
3.4 (development)
|
00001 #ifndef SimTK_SimTKCOMMON_MEASURE_IMPLEMENTATION_H_ 00002 #define SimTK_SimTKCOMMON_MEASURE_IMPLEMENTATION_H_ 00003 00004 /* -------------------------------------------------------------------------- * 00005 * Simbody(tm): SimTKcommon * 00006 * -------------------------------------------------------------------------- * 00007 * This is part of the SimTK biosimulation toolkit originating from * 00008 * Simbios, the NIH National Center for Physics-Based Simulation of * 00009 * Biological Structures at Stanford, funded under the NIH Roadmap for * 00010 * Medical Research, grant U54 GM072970. See https://simtk.org/home/simbody. * 00011 * * 00012 * Portions copyright (c) 2008-13 Stanford University and the Authors. * 00013 * Authors: Michael Sherman * 00014 * Contributors: * 00015 * * 00016 * Licensed under the Apache License, Version 2.0 (the "License"); you may * 00017 * not use this file except in compliance with the License. You may obtain a * 00018 * copy of the License at http://www.apache.org/licenses/LICENSE-2.0. * 00019 * * 00020 * Unless required by applicable law or agreed to in writing, software * 00021 * distributed under the License is distributed on an "AS IS" BASIS, * 00022 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * 00023 * See the License for the specific language governing permissions and * 00024 * limitations under the License. * 00025 * -------------------------------------------------------------------------- */ 00026 00027 #include "SimTKcommon/basics.h" 00028 #include "SimTKcommon/Simmatrix.h" 00029 #include "SimTKcommon/internal/State.h" 00030 #include "SimTKcommon/internal/Measure.h" 00031 #include "SimTKcommon/internal/Subsystem.h" 00032 #include "SimTKcommon/internal/System.h" 00033 #include "SimTKcommon/internal/SubsystemGuts.h" 00034 00035 #include <cmath> 00036 00037 00038 namespace SimTK { 00039 00040 00041 //============================================================================== 00042 // ABSTRACT MEASURE :: IMPLEMENTATION 00043 //============================================================================== 00044 00048 class SimTK_SimTKCOMMON_EXPORT AbstractMeasure::Implementation { 00049 protected: 00052 Implementation() : copyNumber(0), mySubsystem(0), refCount(0) {} 00053 00057 Implementation(const Implementation& src) 00058 : copyNumber(src.copyNumber+1), mySubsystem(0), refCount(0) {} 00059 00063 Implementation& operator=(const Implementation& src) { 00064 if (&src != this) 00065 { copyNumber=src.copyNumber+1; 00066 refCount=0; mySubsystem=0; } 00067 return *this; 00068 } 00069 00070 // destructor is virtual; below 00071 00072 // Increment the reference count and return its new value. 00073 int incrRefCount() const {return ++refCount;} 00074 00075 // Decrement the reference count and return its new value. 00076 int decrRefCount() const {return --refCount;} 00077 00078 // Get the current value of the reference counter. 00079 int getRefCount() const {return refCount;} 00080 00081 int getCopyNumber() const {return copyNumber;} 00082 00086 Implementation* clone() const {return cloneVirtual();} 00087 00088 // realizeTopology() is pure virtual below for Measure_<T> to supply. 00089 void realizeModel (State& s) const {realizeMeasureModelVirtual(s);} 00090 void realizeInstance (const State& s) const {realizeMeasureInstanceVirtual(s);} 00091 void realizeTime (const State& s) const {realizeMeasureTimeVirtual(s);} 00092 void realizePosition (const State& s) const {realizeMeasurePositionVirtual(s);} 00093 void realizeVelocity (const State& s) const {realizeMeasureVelocityVirtual(s);} 00094 void realizeDynamics (const State& s) const {realizeMeasureDynamicsVirtual(s);} 00095 void realizeAcceleration(const State& s) const {realizeMeasureAccelerationVirtual(s);} 00096 void realizeReport (const State& s) const {realizeMeasureReportVirtual(s);} 00097 00101 void initialize(State& s) const {initializeVirtual(s);} 00102 00103 int getNumTimeDerivatives() const {return getNumTimeDerivativesVirtual();} 00104 00105 Stage getDependsOnStage(int derivOrder) const { 00106 SimTK_ERRCHK2(0 <= derivOrder && derivOrder <= getNumTimeDerivatives(), 00107 "Measure::getDependsOnStage()", 00108 "derivOrder %d was out of range; this Measure allows 0-%d.", 00109 derivOrder, getNumTimeDerivatives()); 00110 return getDependsOnStageVirtual(derivOrder); 00111 } 00112 00113 00114 void setSubsystem(Subsystem& sub, MeasureIndex mx) 00115 { assert(!mySubsystem && mx.isValid()); 00116 mySubsystem = ⊂ myIndex = mx; } 00117 00118 bool isInSubsystem() const {return mySubsystem != 0;} 00119 const Subsystem& getSubsystem() const {assert(mySubsystem); return *mySubsystem;} 00120 Subsystem& updSubsystem() {assert(mySubsystem); return *mySubsystem;} 00121 MeasureIndex getSubsystemMeasureIndex() const {assert(mySubsystem); return myIndex;} 00122 SubsystemIndex getSubsystemIndex() const 00123 { return getSubsystem().getMySubsystemIndex(); } 00124 00125 void invalidateTopologyCache() const 00126 { if (isInSubsystem()) getSubsystem().invalidateSubsystemTopologyCache(); } 00127 00128 Stage getStage(const State& s) const {return getSubsystem().getStage(s);} 00129 00130 // VIRTUALS // 00131 // Ordinals must retain the same meaning from release to release 00132 // to preserve binary compatibility. 00133 00134 /* 0*/virtual ~Implementation() {} 00135 /* 1*/virtual Implementation* cloneVirtual() const = 0; 00136 00137 /* 2*/virtual void realizeTopology(State&)const = 0; 00138 00139 /* 3*/virtual void realizeMeasureModelVirtual(State&) const {} 00140 /* 4*/virtual void realizeMeasureInstanceVirtual(const State&) const {} 00141 /* 5*/virtual void realizeMeasureTimeVirtual(const State&) const {} 00142 /* 6*/virtual void realizeMeasurePositionVirtual(const State&) const {} 00143 /* 7*/virtual void realizeMeasureVelocityVirtual(const State&) const {} 00144 /* 8*/virtual void realizeMeasureDynamicsVirtual(const State&) const {} 00145 /* 9*/virtual void realizeMeasureAccelerationVirtual(const State&) const {} 00146 /*10*/virtual void realizeMeasureReportVirtual(const State&) const {} 00147 00148 /*11*/virtual void initializeVirtual(State&) const {} 00149 /*12*/virtual int 00150 getNumTimeDerivativesVirtual() const {return 0;} 00151 /*13*/virtual Stage 00152 getDependsOnStageVirtual(int order) const = 0; 00153 00154 private: 00155 int copyNumber; // bumped each time we do a deep copy 00156 00157 // These are set when this Measure is adopted by a Subsystem. 00158 Subsystem* mySubsystem; 00159 MeasureIndex myIndex; 00160 00161 // Measures have shallow copy semantics so they share the Implementation 00162 // objects, which are only deleted when the refCount goes to zero. 00163 mutable int refCount; 00164 00165 friend class AbstractMeasure; 00166 friend class Subsystem::Guts; 00167 friend class Subsystem::Guts::GutsRep; 00168 }; 00169 00170 //============================================================================== 00171 // ABSTRACT MEASURE DEFINITIONS 00172 //============================================================================== 00173 // These had to wait for AbstractMeasure::Implementation to be defined. 00174 00175 inline AbstractMeasure:: 00176 AbstractMeasure(Implementation* g) 00177 : impl(g) 00178 { if (impl) impl->incrRefCount(); } 00179 00180 inline AbstractMeasure:: 00181 AbstractMeasure(Subsystem& sub, Implementation* g, const SetHandle&) 00182 : impl(g) { 00183 SimTK_ERRCHK(hasImpl(), "AbstractMeasure::AbstractMeasure()", 00184 "An empty Measure handle can't be put in a Subsystem."); 00185 impl->incrRefCount(); 00186 sub.adoptMeasure(*this); 00187 } 00188 00189 // Shallow copy constructor. 00190 inline AbstractMeasure::AbstractMeasure(const AbstractMeasure& src) 00191 : impl(0) { 00192 if (src.impl) { 00193 impl = src.impl; 00194 impl->incrRefCount(); 00195 } 00196 } 00197 00198 // Shallow assignment. 00199 inline AbstractMeasure& AbstractMeasure:: 00200 shallowAssign(const AbstractMeasure& src) { 00201 if (impl != src.impl) { 00202 if (impl && impl->decrRefCount()==0) delete impl; 00203 impl = src.impl; 00204 impl->incrRefCount(); 00205 } 00206 return *this; 00207 } 00208 00209 // Note that even if the source and destination are currently pointing 00210 // to the same Implementation, we still have to make a new copy so that 00211 // afterwards the destination has its own, refcount==1 copy. 00212 inline AbstractMeasure& AbstractMeasure:: 00213 deepAssign(const AbstractMeasure& src) { 00214 if (&src != this) { 00215 if (impl && impl->decrRefCount()==0) delete impl; 00216 if (src.impl) { 00217 impl = src.impl->clone(); 00218 impl->incrRefCount(); 00219 } else 00220 impl = 0; 00221 } 00222 return *this; 00223 } 00224 00225 inline AbstractMeasure:: 00226 ~AbstractMeasure() 00227 { if (impl && impl->decrRefCount()==0) delete impl;} 00228 00229 inline bool AbstractMeasure:: 00230 isInSubsystem() const 00231 { return hasImpl() && getImpl().isInSubsystem(); } 00232 00233 inline const Subsystem& AbstractMeasure:: 00234 getSubsystem() const 00235 { return getImpl().getSubsystem(); } 00236 00237 inline MeasureIndex AbstractMeasure:: 00238 getSubsystemMeasureIndex() const 00239 { return getImpl().getSubsystemMeasureIndex();} 00240 00241 inline int AbstractMeasure:: 00242 getNumTimeDerivatives() const 00243 { return getImpl().getNumTimeDerivatives(); } 00244 00245 inline Stage AbstractMeasure:: 00246 getDependsOnStage(int derivOrder) const 00247 { return getImpl().getDependsOnStage(derivOrder); } 00248 00249 inline int AbstractMeasure:: 00250 getRefCount() const 00251 { return getImpl().getRefCount(); } 00252 00253 // Hide from Doxygen. 00255 // This is a helper class that makes it possible to treat Real, Vec, and 00256 // Vector objects uniformly. 00257 template <class T> class Measure_Num { 00258 }; 00259 00260 template <> class Measure_Num<float> { 00261 public: 00262 typedef float Element; 00263 static int size(const float&) {return 1;} 00264 static const float& get(const float& v, int i) {assert(i==0); return v;} 00265 static float& upd(float& v, int i) {assert(i==0); return v;} 00266 static void makeNaNLike(const float&, float& nanValue) 00267 { nanValue = CNT<float>::getNaN();} 00268 static void makeZeroLike(const float&, float& zeroValue) {zeroValue=0.f;} 00269 }; 00270 00271 template <> class Measure_Num<double> { 00272 public: 00273 typedef double Element; 00274 static int size(const double&) {return 1;} 00275 static const double& get(const double& v, int i) {assert(i==0); return v;} 00276 static double& upd(double& v, int i) {assert(i==0); return v;} 00277 static void makeNaNLike(const double&, double& nanValue) 00278 { nanValue = CNT<double>::getNaN(); } 00279 static void makeZeroLike(const double&, double& zeroValue) {zeroValue=0.;} 00280 }; 00281 00282 // We only support stride 1 (densely packed) Vec types. 00283 template <int M, class E> 00284 class Measure_Num< Vec<M,E,1> > { 00285 typedef Vec<M,E,1> T; 00286 public: 00287 typedef E Element; 00288 static int size(const T&) {return M;} 00289 static const E& get(const T& v, int i) {return v[i];} 00290 static E& upd(T& v, int i) {return v[i];} 00291 static void makeNaNLike (const T&, T& nanValue) {nanValue.setToNaN();} 00292 static void makeZeroLike(const T&, T& zeroValue) {zeroValue.setToZero();} 00293 }; 00294 00295 // We only support column major (densely packed) Mat types. 00296 template <int M, int N, class E> 00297 class Measure_Num< Mat<M,N,E> > { 00298 typedef Mat<M,N,E> T; 00299 public: 00300 typedef E Element; 00301 static int size(const T&) {return N;} // number of columns 00302 static const typename T::TCol& get(const T& m, int j) {return m.col(j);} 00303 static typename T::TCol& upd(T& m, int j) {return m.col(j);} 00304 static void makeNaNLike (const T&, T& nanValue) {nanValue.setToNaN();} 00305 static void makeZeroLike(const T&, T& zeroValue) {zeroValue.setToZero();} 00306 }; 00307 00308 00309 template <class E> 00310 class Measure_Num< Vector_<E> > { 00311 typedef Vector_<E> T; 00312 public: 00313 typedef E Element; 00314 static int size(const T& v) {return v.size();} 00315 static const E& get(const T& v, int i) {return v[i];} 00316 static E& upd(T& v, int i) {return v[i];} 00317 static void makeNaNLike(const T& v, T& nanValue) 00318 { nanValue.resize(v.size()); nanValue.setToNaN(); } 00319 static void makeZeroLike(const T& v, T& zeroValue) 00320 { zeroValue.resize(v.size()); zeroValue.setToZero(); } 00321 00322 }; 00323 00326 //============================================================================== 00327 // MEASURE_<T> :: IMPLEMENTATION 00328 //============================================================================== 00335 template <class T> 00336 class Measure_<T>::Implementation : public AbstractMeasure::Implementation { 00337 public: 00338 const T& getValue(const State& s, int derivOrder) const { 00339 SimTK_ERRCHK2(0 <= derivOrder && derivOrder <= getNumTimeDerivatives(), 00340 "Measure_<T>::getValue()", 00341 "derivOrder %d was out of range; this Measure allows 0-%d.", 00342 derivOrder, getNumTimeDerivatives()); 00343 00344 // We require the stage to have been advanced to at least the one 00345 // before this measure's depends-on stage since this will get called 00346 // towards the end of the depends-on stage realization. 00347 if (getDependsOnStage(derivOrder) != Stage::Empty) { 00348 Stage prevStage = getDependsOnStage(derivOrder).prev(); 00349 00350 SimTK_ERRCHK2 00351 ( ( isInSubsystem() && getStage(s)>=prevStage) 00352 || (!isInSubsystem() && s.getSystemStage()>=prevStage), 00353 "Measure_<T>::getValue()", 00354 "Expected State to have been realized to at least stage " 00355 "%s but stage was %s.", 00356 prevStage.getName().c_str(), 00357 (isInSubsystem() ? getStage(s) : s.getSystemStage()) 00358 .getName().c_str()); 00359 } 00360 00361 if (derivOrder < getNumCacheEntries()) { 00362 if (!isCacheValueRealized(s,derivOrder)) { 00363 T& value = updCacheEntry(s,derivOrder); 00364 calcCachedValueVirtual(s, derivOrder, value); 00365 markCacheValueRealized(s,derivOrder); 00366 return value; 00367 } 00368 return getCacheEntry(s,derivOrder); 00369 } 00370 00371 // We can't handle it here -- punt to the concrete Measure 00372 // for higher order derivatives. 00373 return getUncachedValueVirtual(s,derivOrder); 00374 } 00375 00378 void setDefaultValue(const T& defaultValue) { 00379 this->defaultValue = defaultValue; 00380 Measure_Num<T>::makeZeroLike(defaultValue, zeroValue); 00381 this->invalidateTopologyCache(); 00382 } 00383 00387 const T& getDefaultValue() const {return defaultValue;} 00388 00389 void setIsPresumedValidAtDependsOnStage(bool presume) 00390 { presumeValidAtDependsOnStage = presume; 00391 this->invalidateTopologyCache(); } 00392 00393 bool getIsPresumedValidAtDependsOnStage() const 00394 { return presumeValidAtDependsOnStage; } 00395 00396 protected: 00397 explicit Implementation(const T& defaultValue, int numCacheEntries=1) 00398 : presumeValidAtDependsOnStage(false), 00399 defaultValue(defaultValue), 00400 derivIx(numCacheEntries) 00401 { 00402 Measure_Num<T>::makeZeroLike(defaultValue, zeroValue); 00403 } 00404 00408 explicit Implementation(int numCacheEntries=1) 00409 : presumeValidAtDependsOnStage(false), 00410 defaultValue(), 00411 derivIx(numCacheEntries) 00412 { 00413 Measure_Num<T>::makeZeroLike(defaultValue, zeroValue); 00414 } 00415 00419 Implementation(const Implementation& source) 00420 : presumeValidAtDependsOnStage(source.presumeValidAtDependsOnStage), 00421 defaultValue(source.defaultValue), 00422 derivIx(source.derivIx.size()) 00423 { 00424 Measure_Num<T>::makeZeroLike(defaultValue, zeroValue); 00425 } 00426 00427 00430 int size() const {return Measure_Num<T>::size(defaultValue);} 00431 00434 int getNumCacheEntries() const {return (int)derivIx.size();} 00435 00439 const T& getCacheEntry(const State& s, int derivOrder) const { 00440 SimTK_ERRCHK2(0 <= derivOrder && derivOrder < getNumCacheEntries(), 00441 "Measure_<T>::Implementation::getCacheEntry()", 00442 "Derivative order %d is out of range; only %d cache entries" 00443 " were allocated.", derivOrder, getNumCacheEntries()); 00444 00445 return Value<T>::downcast( 00446 this->getSubsystem().getCacheEntry(s, derivIx[derivOrder])); 00447 } 00448 00452 T& updCacheEntry(const State& s, int derivOrder) const { 00453 SimTK_ERRCHK2(0 <= derivOrder && derivOrder < getNumCacheEntries(), 00454 "Measure_<T>::Implementation::updCacheEntry()", 00455 "Derivative order %d is out of range; only %d cache entries" 00456 " were allocated.", derivOrder, getNumCacheEntries()); 00457 00458 return Value<T>::updDowncast( 00459 this->getSubsystem().updCacheEntry(s, derivIx[derivOrder])); 00460 } 00461 00464 bool isCacheValueRealized(const State& s, int derivOrder) const { 00465 SimTK_ERRCHK2(0 <= derivOrder && derivOrder < getNumCacheEntries(), 00466 "Measure_<T>::Implementation::isCacheValueRealized()", 00467 "Derivative order %d is out of range; only %d cache entries" 00468 " were allocated.", derivOrder, getNumCacheEntries()); 00469 00470 return this->getSubsystem().isCacheValueRealized(s, derivIx[derivOrder]); 00471 } 00472 00476 void markCacheValueRealized(const State& s, int derivOrder) const { 00477 SimTK_ERRCHK2(0 <= derivOrder && derivOrder < getNumCacheEntries(), 00478 "Measure_<T>::Implementation::markCacheValueRealized()", 00479 "Derivative order %d is out of range; only %d cache entries" 00480 " were allocated.", derivOrder, getNumCacheEntries()); 00481 00482 this->getSubsystem().markCacheValueRealized(s, derivIx[derivOrder]); 00483 } 00484 00489 void markCacheValueNotRealized(const State& s, int derivOrder) const { 00490 SimTK_ERRCHK2(0 <= derivOrder && derivOrder < getNumCacheEntries(), 00491 "Measure_<T>::Implementation::markCacheValueNotRealized()", 00492 "Derivative order %d is out of range; only %d cache entries" 00493 " were allocated.", derivOrder, getNumCacheEntries()); 00494 00495 this->getSubsystem().markCacheValueNotRealized(s, derivIx[derivOrder]); 00496 } 00497 00498 // VIRTUALS // 00499 // Ordinals must retain the same meaning from release to release 00500 // to preserve binary compatibility. 00501 00504 /* 0*/virtual void realizeMeasureTopologyVirtual(State&) const 00505 {} 00506 00509 /* 1*/virtual void 00510 calcCachedValueVirtual(const State&, int derivOrder, T& value) const 00511 { SimTK_ERRCHK1_ALWAYS(!"implemented", 00512 "Measure_<T>::Implementation::calcCachedValueVirtual()", 00513 "This method should have been overridden by the derived" 00514 " Measure but was not. It is needed to calculate the" 00515 " cached value for derivOrder=%d.", derivOrder); } 00516 00522 /* 2*/virtual const T& 00523 getUncachedValueVirtual(const State&, int derivOrder) const 00524 { SimTK_ERRCHK1_ALWAYS(!"implemented", 00525 "Measure_<T>::Implementation::getUncachedValueVirtual()", 00526 "This method should have been overridden by the derived" 00527 " Measure but was not. It is needed to return the uncached" 00528 " value at derivOrder=%d.", derivOrder); 00529 return *reinterpret_cast<T*>(0); 00530 } 00531 00534 const T& getValueZero() const {return zeroValue;} 00535 00536 private: 00537 // Satisfy the realizeTopology() pure virtual here now that we know the 00538 // data type T. Allocate lazy- or auto-validated- cache entries depending 00539 // on the setting of presumeValidAtDependsOnStage. 00540 void realizeTopology(State& s) const FINAL_11 { 00541 // Allocate cache entries. Initialize the value cache entry to 00542 // the given defaultValue; all the derivative cache entries should be 00543 // initialized to a NaN of the same size. 00544 if (getNumCacheEntries()) { 00545 derivIx[0] = presumeValidAtDependsOnStage 00546 ? this->getSubsystem().allocateCacheEntry 00547 (s, getDependsOnStage(0), new Value<T>(defaultValue)) 00548 : this->getSubsystem().allocateLazyCacheEntry 00549 (s, getDependsOnStage(0), new Value<T>(defaultValue)); 00550 00551 if (getNumCacheEntries() > 1) { 00552 T nanValue; Measure_Num<T>::makeNaNLike(defaultValue, nanValue); 00553 for (int i=1; i < getNumCacheEntries(); ++i) { 00554 derivIx[i] = presumeValidAtDependsOnStage 00555 ? this->getSubsystem().allocateCacheEntry 00556 (s, getDependsOnStage(i), new Value<T>(nanValue)) 00557 : this->getSubsystem().allocateLazyCacheEntry 00558 (s, getDependsOnStage(i), new Value<T>(nanValue)); 00559 } 00560 } 00561 } 00562 00563 // Call the concrete class virtual if any. 00564 realizeMeasureTopologyVirtual(s); 00565 } 00566 00567 //------------------------------------------------------------------------------ 00568 private: 00569 // TOPOLOGY STATE 00570 bool presumeValidAtDependsOnStage; 00571 T defaultValue; 00572 T zeroValue; 00573 00574 // TOPOLOGY CACHE 00575 mutable Array_<CacheEntryIndex> derivIx; 00576 }; 00577 00578 00579 00580 //============================================================================== 00581 // CONSTANT :: IMPLEMENTATION 00582 //============================================================================== 00583 template <class T> 00584 class Measure_<T>::Constant::Implementation 00585 : public Measure_<T>::Implementation 00586 { 00587 public: 00588 // We don't want the base class to allocate *any* cache entries. 00589 Implementation() : Measure_<T>::Implementation(0) {} 00590 explicit Implementation(const T& value) 00591 : Measure_<T>::Implementation(value,0) {} 00592 00595 void setValue(const T& v) {this->setDefaultValue(v);} 00596 00597 // Implementations of virtual methods. 00598 // Measure_<T> virtuals: 00599 // No cached values. 00600 00601 const T& getUncachedValueVirtual(const State&, int derivOrder) const 00602 OVERRIDE_11 00603 { return derivOrder>0 ? this->getValueZero() : this->getDefaultValue(); } 00604 00605 // AbstractMeasure virtuals: 00606 Implementation* cloneVirtual() const OVERRIDE_11 00607 { return new Implementation(*this); } 00608 Stage getDependsOnStageVirtual(int derivOrder) const OVERRIDE_11 00609 { return derivOrder>0 ? Stage::Empty : Stage::Topology; } 00610 int getNumTimeDerivativesVirtual() const OVERRIDE_11 00611 { return std::numeric_limits<int>::max(); } 00612 }; 00613 00614 00615 00616 //============================================================================== 00617 // MEASURE ZERO and ONE 00618 //============================================================================== 00619 // These had to wait for Constant::Implementation to be declared. 00620 00621 template <class T> inline 00622 Measure_<T>::Zero::Zero() : Constant(T(0)) {} 00623 template <class T> inline 00624 Measure_<T>::Zero::Zero(Subsystem& sub) : Constant(sub, T(0)) {} 00625 00626 inline Measure_< Vector >::Zero::Zero(int size) 00627 : Constant(Vector(size, Real(0))) {} 00628 inline Measure_< Vector >::Zero::Zero(Subsystem& sub, int size) 00629 : Constant(sub, Vector(size, Real(0))) {} 00630 00631 template <class T> inline 00632 Measure_<T>::One::One() : Constant(T(1)) {} 00633 template <class T> inline 00634 Measure_<T>::One::One(Subsystem& sub) : Constant(sub, T(1)) {} 00635 00636 inline Measure_< Vector >::One::One(int size) 00637 : Constant(Vector(size, Real(1))) {} 00638 inline Measure_< Vector >::One::One(Subsystem& sub, int size) 00639 : Constant(sub, Vector(size, Real(1))) {} 00640 00641 00642 00643 //============================================================================== 00644 // TIME :: IMPLEMENTATION 00645 //============================================================================== 00646 template <class T> 00647 class Measure_<T>::Time::Implementation {}; 00648 00649 template <> 00650 class Measure_<Real>::Time::Implementation 00651 : public Measure_<Real>::Implementation 00652 { 00653 public: 00654 // We don't want the base class to allocate *any* cache entries. 00655 Implementation() : Measure_<Real>::Implementation(0) {} 00656 00657 // Implementations of virtual methods. 00658 // Measure_<Real> virtuals: 00659 // No cached values. 00660 00661 const Real& getUncachedValueVirtual(const State& s, int derivOrder) const 00662 OVERRIDE_11 00663 { return derivOrder==0 ? s.getTime() 00664 : (derivOrder==1 ? SimTK::One 00665 : SimTK::Zero); } 00666 00667 // AbstractMeasure virtuals: 00668 Implementation* cloneVirtual() const OVERRIDE_11 00669 { return new Implementation(*this); } 00670 Stage getDependsOnStageVirtual(int derivOrder) const OVERRIDE_11 00671 { return derivOrder>0 ? Stage::Empty : Stage::Time; } 00672 00673 // Value is t, 1st derivative is 1, the rest are 0. 00674 int getNumTimeDerivativesVirtual() const OVERRIDE_11 00675 { return std::numeric_limits<int>::max(); } 00676 }; 00677 00678 00679 00680 //============================================================================== 00681 // VARIABLE :: IMPLEMENTATION 00682 //============================================================================== 00683 template <class T> 00684 class Measure_<T>::Variable::Implementation 00685 : public Measure_<T>::Implementation 00686 { 00687 public: 00688 // We don't want the base class to allocate *any* cache entries; 00689 // we'll use the variable as its own value and zeroes for all 00690 // the derivatives. 00691 Implementation() 00692 : Measure_<T>::Implementation(0), 00693 invalidatedStage(Stage::Empty) {} 00694 00695 Implementation(Stage invalidated, const T& defaultValue) 00696 : Measure_<T>::Implementation(defaultValue, 0), 00697 invalidatedStage(invalidated) {} 00698 00699 // Copy constructor should not copy the variable. 00700 Implementation(const Implementation& source) 00701 : Measure_<T>::Implementation(source.getDefaultValue(), 0), 00702 invalidatedStage(source.invalidatedStage) {} 00703 00704 void setInvalidatedStage(Stage invalidates) { 00705 invalidatedStage = invalidates; 00706 this->invalidateTopologyCache(); 00707 } 00708 00709 Stage getInvalidatedStage() const {return invalidatedStage;} 00710 00714 void setValue(State& state, const T& value) const 00715 { updVarValue(state) = value; } 00716 00717 // Implementations of virtual methods. 00718 Implementation* cloneVirtual() const OVERRIDE_11 00719 { return new Implementation(*this); } 00720 00721 int getNumTimeDerivativesVirtual() const OVERRIDE_11 00722 { return std::numeric_limits<int>::max(); } 00723 00724 // Discrete variable is available after Model stage; but all its 00725 // derivatives are zero so are always available. 00726 Stage getDependsOnStageVirtual(int derivOrder) const OVERRIDE_11 00727 { return derivOrder>0 ? Stage::Empty : Stage::Model;} 00728 00729 const T& getUncachedValueVirtual(const State& s, int derivOrder) const 00730 OVERRIDE_11 00731 { return derivOrder>0 ? this->getValueZero() : getVarValue(s); } 00732 00733 // No cached values. 00734 00735 void realizeMeasureTopologyVirtual(State& s) const OVERRIDE_11 { 00736 discreteVarIndex = this->getSubsystem().allocateDiscreteVariable 00737 (s, invalidatedStage, new Value<T>(this->getDefaultValue())); 00738 } 00739 private: 00740 const T& getVarValue(const State& s) const { 00741 assert(discreteVarIndex.isValid()); 00742 return Value<T>::downcast( 00743 this->getSubsystem().getDiscreteVariable(s, discreteVarIndex)); 00744 } 00745 T& updVarValue(State& s) const { 00746 assert(discreteVarIndex.isValid()); 00747 return Value<T>::downcast( 00748 this->getSubsystem().updDiscreteVariable(s, discreteVarIndex)); 00749 } 00750 00751 // TOPOLOGY STATE 00752 Stage invalidatedStage; // TODO this shouldn't be needed 00753 00754 // TOPOLOGY CACHE 00755 mutable DiscreteVariableIndex discreteVarIndex; 00756 }; 00757 00758 00759 00760 //============================================================================== 00761 // RESULT :: IMPLEMENTATION 00762 //============================================================================== 00763 template <class T> 00764 class Measure_<T>::Result::Implementation 00765 : public Measure_<T>::Implementation 00766 { 00767 public: 00768 // We want the base class to allocate a single cache entry of type T. 00769 Implementation() 00770 : Measure_<T>::Implementation(1), 00771 dependsOnStage(Stage::Topology), invalidatedStage(Stage::Infinity) {} 00772 00773 Implementation(Stage dependsOn, Stage invalidated) 00774 : Measure_<T>::Implementation(1), 00775 dependsOnStage(dependsOn==Stage::Empty ? Stage::Topology : dependsOn), 00776 invalidatedStage(invalidated) 00777 { SimTK_ERRCHK2_ALWAYS(invalidated > dependsOn,"Measure::Result::ctor()", 00778 "Got invalidated stage %s and dependsOn stage %s which is illegal " 00779 "because the invalidated stage must be later than dependsOn.", 00780 invalidated.getName().c_str(), dependsOn.getName().c_str()); 00781 } 00782 00783 // Copy constructor will not copy the cache entry index. 00784 Implementation(const Implementation& source) 00785 : Measure_<T>::Implementation(source), 00786 dependsOnStage(source.dependsOnStage), 00787 invalidatedStage(source.invalidatedStage) {} 00788 00789 void setDependsOnStage(Stage dependsOn) { 00790 if (dependsOn == Stage::Empty) dependsOn = Stage::Topology; 00791 SimTK_ERRCHK2_ALWAYS(dependsOn < getInvalidatedStage(), 00792 "Measure::Result::setDependsOnStage()", 00793 "The provided dependsOn stage %s is illegal because it is not " 00794 "less than the current invalidated stage %s. Change the " 00795 "invalidated stage first with setInvalidatedStage().", 00796 dependsOn.getName().c_str(), 00797 getInvalidatedStage().getName().c_str()); 00798 00799 dependsOnStage = dependsOn; 00800 this->invalidateTopologyCache(); 00801 } 00802 00803 void setInvalidatedStage(Stage invalidated) { 00804 SimTK_ERRCHK2_ALWAYS(invalidated > getDependsOnStage(), 00805 "Measure::Result::setInvalidatedStage()", 00806 "The provided invalidated stage %s is illegal because it is not " 00807 "greater than the current dependsOn stage %s. Change the " 00808 "dependsOn stage first with setDependsOnStage().", 00809 invalidated.getName().c_str(), 00810 getDependsOnStage().getName().c_str()); 00811 00812 invalidatedStage = invalidated; 00813 this->invalidateTopologyCache(); 00814 } 00815 00816 00817 Stage getDependsOnStage() const {return dependsOnStage;} 00818 Stage getInvalidatedStage() const {return invalidatedStage;} 00819 00820 00821 void markAsValid(const State& state) const 00822 { const Stage subsystemStage = this->getSubsystem().getStage(state); 00823 SimTK_ERRCHK3_ALWAYS(subsystemStage >= getDependsOnStage().prev(), 00824 "Measure::Result::markAsValid()", 00825 "This Result Measure cannot be marked valid in a State where this " 00826 "measure's Subsystem has been realized only to stage %s, because " 00827 "its value was declared to depend on stage %s. To mark it valid, " 00828 "we require that the State have been realized at least to the " 00829 "previous stage (%s in this case); that is, you must at least be " 00830 "*working on* the dependsOn stage in order to claim this result is " 00831 "available.", 00832 subsystemStage.getName().c_str(), 00833 getDependsOnStage().getName().c_str(), 00834 getDependsOnStage().prev().getName().c_str()); 00835 this->markCacheValueRealized(state, 0); } 00836 00837 bool isValid(const State& state) const 00838 { return this->isCacheValueRealized(state, 0); } 00839 00840 void markAsNotValid(const State& state) const 00841 { this->markCacheValueNotRealized(state, 0); 00842 state.invalidateAllCacheAtOrAbove(invalidatedStage); } 00843 00844 T& updValue(const State& state) const 00845 { markAsNotValid(state); return this->updCacheEntry(state, 0); } 00846 00847 00848 // Implementations of virtual methods. 00849 Implementation* cloneVirtual() const OVERRIDE_11 00850 { return new Implementation(*this); } 00851 00852 int getNumTimeDerivativesVirtual() const OVERRIDE_11 {return 0;} 00853 00856 Stage getDependsOnStageVirtual(int derivOrder) const OVERRIDE_11 00857 { return derivOrder>0 ? Stage::Empty : dependsOnStage;} 00858 00859 void calcCachedValueVirtual(const State&, int derivOrder, T& value) const 00860 OVERRIDE_11 00861 { SimTK_ERRCHK_ALWAYS(!"calcCachedValueVirtual() implemented", 00862 "Measure_<T>::Result::getValue()", 00863 "Measure_<T>::Result::getValue() was called when the value was not " 00864 "yet valid. For most Measure types, this would have initiated " 00865 "computation of the value, but Result measures must have their values " 00866 "calculated and set externally, and then marked valid."); } 00867 00868 private: 00869 // TOPOLOGY STATE 00870 Stage dependsOnStage; 00871 Stage invalidatedStage; 00872 }; 00873 00874 00875 00876 //============================================================================== 00877 // SINUSOID :: IMPLEMENTATION 00878 //============================================================================== 00879 template <class T> 00880 class Measure_<T>::Sinusoid::Implementation 00881 : public Measure_<T>::Implementation 00882 { 00883 static const int NumDerivs = 3; 00884 public: 00885 Implementation() 00886 : Measure_<T>::Implementation(NumDerivs+1), 00887 a(CNT<T>::getNaN()), w(CNT<T>::getNaN()), p(CNT<T>::getNaN()) {} 00888 00889 Implementation(const T& amplitude, 00890 const T& frequency, 00891 const T& phase=T(0)) 00892 : Measure_<T>::Implementation(NumDerivs+1), 00893 a(amplitude), w(frequency), p(phase) {} 00894 00895 // Default copy constructor is fine. 00896 00897 // Implementations of virtual methods. 00898 Implementation* cloneVirtual() const OVERRIDE_11 00899 { return new Implementation(*this); } 00900 00901 int getNumTimeDerivativesVirtual() const OVERRIDE_11 {return NumDerivs;} 00902 00903 Stage getDependsOnStageVirtual(int order) const OVERRIDE_11 00904 { return Stage::Time; } 00905 00906 void calcCachedValueVirtual(const State& s, int derivOrder, T& value) const 00907 OVERRIDE_11 00908 { 00909 // We need to allow the compiler to select std::sin or SimTK::sin 00910 // based on the argument type. 00911 using std::sin; using std::cos; 00912 00913 assert(NumDerivs == 3); 00914 const Real t = s.getTime(); 00915 const T arg = w*t + p; 00916 00917 switch (derivOrder) { 00918 case 0: value = a*sin(arg); break; 00919 case 1: value = w*a*cos(arg); break; 00920 case 2: value = -w*w*a*sin(arg); break; 00921 case 3: value = -w*w*w*a*cos(arg); break; 00922 default: SimTK_ASSERT1_ALWAYS(!"out of range", 00923 "Measure::Sinusoid::Implementation::calcCachedValueVirtual():" 00924 " derivOrder %d is out of range 0-3.", derivOrder); 00925 } 00926 } 00927 00928 // There are no uncached values. 00929 00930 private: 00931 // TOPOLOGY STATE 00932 T a, w, p; 00933 00934 // TOPOLOGY CACHE 00935 // nothing 00936 }; 00937 00938 00939 00940 //============================================================================== 00941 // PLUS :: IMPLEMENTATION 00942 //============================================================================== 00943 template <class T> 00944 class Measure_<T>::Plus::Implementation : public Measure_<T>::Implementation { 00945 public: 00946 // TODO: Currently allocates just one cache entry. 00947 // left and right will be empty handles. 00948 Implementation() {} 00949 00950 Implementation(const Measure_<T>& left, 00951 const Measure_<T>& right) 00952 : left(left), right(right) {} 00953 00954 // Default copy constructor gives us a new Implementation object, 00955 // but with references to the *same* operand measures. 00956 00957 // Implementations of virtual methods. 00958 00959 // This uses the default copy constructor. 00960 Implementation* cloneVirtual() const OVERRIDE_11 00961 { return new Implementation(*this); } 00962 00963 // TODO: Let this be settable up to the min number of derivatives 00964 // provided by the arguments. 00965 int getNumTimeDerivativesVirtual() const OVERRIDE_11 {return 0;} 00966 //{ return std::min(left.getNumTimeDerivatives(), 00967 // right.getNumTimeDerivatives()); } 00968 00969 Stage getDependsOnStageVirtual(int order) const OVERRIDE_11 00970 { return Stage(std::max(left.getDependsOnStage(order), 00971 right.getDependsOnStage(order))); } 00972 00973 00974 void calcCachedValueVirtual(const State& s, int derivOrder, T& value) const 00975 OVERRIDE_11 00976 { 00977 value = left.getValue(s,derivOrder) + right.getValue(s,derivOrder); 00978 } 00979 00980 // There are no uncached values. 00981 00982 private: 00983 // TOPOLOGY STATE 00984 Measure_<T> left; 00985 Measure_<T> right; 00986 00987 // TOPOLOGY CACHE 00988 // nothing 00989 }; 00990 00991 00992 00993 //============================================================================== 00994 // MINUS :: IMPLEMENTATION 00995 //============================================================================== 00996 template <class T> 00997 class Measure_<T>::Minus::Implementation : public Measure_<T>::Implementation { 00998 public: 00999 // TODO: Currently allocates just one cache entry. 01000 // left and right will be empty handles. 01001 Implementation() {} 01002 01003 Implementation(const Measure_<T>& left, 01004 const Measure_<T>& right) 01005 : left(left), right(right) {} 01006 01007 // Default copy constructor gives us a new Implementation object, 01008 // but with references to the *same* operand measures. 01009 01010 // Implementations of virtual methods. 01011 01012 // This uses the default copy constructor. 01013 Implementation* cloneVirtual() const OVERRIDE_11 01014 { return new Implementation(*this); } 01015 01016 // TODO: Let this be settable up to the min number of derivatives 01017 // provided by the arguments. 01018 int getNumTimeDerivativesVirtual() const OVERRIDE_11 {return 0;} 01019 //{ return std::min(left.getNumTimeDerivatives(), 01020 // right.getNumTimeDerivatives()); } 01021 01022 Stage getDependsOnStageVirtual(int order) const OVERRIDE_11 01023 { return Stage(std::max(left.getDependsOnStage(order), 01024 right.getDependsOnStage(order))); } 01025 01026 01027 void calcCachedValueVirtual(const State& s, int derivOrder, T& value) const 01028 OVERRIDE_11 01029 { 01030 value = left.getValue(s,derivOrder) - right.getValue(s,derivOrder); 01031 } 01032 01033 // There are no uncached values. 01034 01035 private: 01036 // TOPOLOGY STATE 01037 Measure_<T> left; 01038 Measure_<T> right; 01039 01040 // TOPOLOGY CACHE 01041 // nothing 01042 }; 01043 01044 01045 01046 //============================================================================== 01047 // SCALE :: IMPLEMENTATION 01048 //============================================================================== 01049 template <class T> 01050 class Measure_<T>::Scale::Implementation 01051 : public Measure_<T>::Implementation 01052 { 01053 public: 01054 // TODO: Currently allocates just one cache entry. 01055 // scale will be uninitialized, operand will be empty handle. 01056 Implementation() : factor(NaN) {} 01057 01058 Implementation(Real factor, const Measure_<T>& operand) 01059 : factor(factor), operand(operand) {} 01060 01061 // Default copy constructor gives us a new Implementation object, 01062 // but with references to the *same* operand measure. 01063 01064 void setScaleFactor(Real sf) { 01065 factor = sf; 01066 this->invalidateTopologyCache(); 01067 } 01068 01069 const Measure_<T>& getOperandMeasure() const 01070 { 01071 return operand; 01072 } 01073 01074 // Implementations of virtual methods. 01075 01076 // This uses the default copy constructor. 01077 Implementation* cloneVirtual() const OVERRIDE_11 01078 { return new Implementation(*this); } 01079 01080 // TODO: Let this be settable up to the min number of derivatives 01081 // provided by the arguments. 01082 int getNumTimeDerivativesVirtual() const OVERRIDE_11 {return 0;} 01083 //{ return std::min(left.getNumTimeDerivatives(), 01084 // right.getNumTimeDerivatives()); } 01085 01086 Stage getDependsOnStageVirtual(int order) const OVERRIDE_11 01087 { return operand.getDependsOnStage(order); } 01088 01089 01090 void calcCachedValueVirtual(const State& s, int derivOrder, T& value) const 01091 OVERRIDE_11 01092 { 01093 value = factor * operand.getValue(s,derivOrder); 01094 } 01095 01096 // There are no uncached values. 01097 01098 private: 01099 // TOPOLOGY STATE 01100 Real factor; 01101 Measure_<T> operand; 01102 01103 // TOPOLOGY CACHE 01104 // nothing 01105 }; 01106 01107 01108 01109 //============================================================================== 01110 // INTEGRATE :: IMPLEMENTATION 01111 //============================================================================== 01118 template <class T> 01119 class Measure_<T>::Integrate::Implementation 01120 : public Measure_<T>::Implementation { 01121 public: 01124 Implementation() : Measure_<T>::Implementation(1) {} 01125 01128 Implementation(const Measure_<T>& deriv, const Measure_<T>& ic, 01129 const T& defaultValue) 01130 : Measure_<T>::Implementation(defaultValue, 1), 01131 derivMeasure(deriv), icMeasure(ic) {} 01132 01135 Implementation(const Implementation& source) 01136 : Measure_<T>::Implementation(source.getDefaultValue(), 1), 01137 derivMeasure(source.derivMeasure), icMeasure(source.icMeasure) {} 01138 01142 void setValue(State& s, const T& value) const 01143 { assert(zIndex >= 0); 01144 for (int i=0; i < this->size(); ++i) 01145 this->getSubsystem().updZ(s)[zIndex+i] = 01146 Measure_Num<T>::get(value, i); } 01147 01148 const Measure_<T>& getDerivativeMeasure() const 01149 { SimTK_ERRCHK(!derivMeasure.isEmptyHandle(), 01150 "Measure_<T>::Integrate::getDerivativeMeasure()", 01151 "No derivative measure is available for this integrated measure."); 01152 return derivMeasure; } 01153 01154 const Measure_<T>& getInitialConditionMeasure() const 01155 { SimTK_ERRCHK(!icMeasure.isEmptyHandle(), 01156 "Measure_<T>::Integrate::getInitialConditionMeasure()", 01157 "No initial condition measure is available for this " 01158 "integrated measure."); 01159 return icMeasure; } 01160 01161 void setDerivativeMeasure(const Measure_<T>& d) 01162 { derivMeasure = d; this->invalidateTopologyCache(); } 01163 void setInitialConditionMeasure(const Measure_<T>& ic) 01164 { icMeasure = ic; this->invalidateTopologyCache(); } 01165 01166 // Implementations of virtuals. 01167 01168 // This uses the copy constructor defined above. 01169 Implementation* cloneVirtual() const OVERRIDE_11 01170 { return new Implementation(*this); } 01171 01173 int getNumTimeDerivativesVirtual() const OVERRIDE_11 01174 { int integralDerivs = getDerivativeMeasure().getNumTimeDerivatives(); 01175 // Careful - can't add 1 to max int and stay an int. 01176 if (integralDerivs < std::numeric_limits<int>::max()) 01177 ++integralDerivs; 01178 return integralDerivs; } 01179 01180 void calcCachedValueVirtual(const State& s, int derivOrder, T& value) const 01181 OVERRIDE_11 01182 { assert(derivOrder == 0); // only one cache entry 01183 assert(Measure_Num<T>::size(value) == this->size()); 01184 assert(zIndex.isValid()); 01185 const Vector& allZ = this->getSubsystem().getZ(s); 01186 for (int i=0; i < this->size(); ++i) 01187 Measure_Num<T>::upd(value,i) = allZ[zIndex+i]; 01188 } 01189 01190 const T& getUncachedValueVirtual(const State& s, int derivOrder) const 01191 OVERRIDE_11 01192 { assert(derivOrder > 0); // 0th entry is cached 01193 return getDerivativeMeasure().getValue(s, derivOrder-1); 01194 } 01195 01196 Stage getDependsOnStageVirtual(int derivOrder) const OVERRIDE_11 01197 { return derivOrder>0 01198 ? getDerivativeMeasure().getDependsOnStage(derivOrder-1) 01199 : Stage::Time; } 01200 01203 void initializeVirtual(State& s) const OVERRIDE_11 { 01204 assert(zIndex.isValid()); 01205 Vector& allZ = this->getSubsystem().updZ(s); 01206 if (!icMeasure.isEmptyHandle()) { 01207 this->getSubsystem().getSystem() 01208 .realize(s, icMeasure.getDependsOnStage()); 01209 const T& ic = icMeasure.getValue(s); 01210 for (int i=0; i < this->size(); ++i) 01211 allZ[zIndex+i] = Measure_Num<T>::get(ic,i); 01212 } else { 01213 for (int i=0; i < this->size(); ++i) 01214 allZ[zIndex+i] = Measure_Num<T>::get(this->getDefaultValue(),i); 01215 } 01216 } 01217 01222 void realizeMeasureTopologyVirtual(State& s) const OVERRIDE_11 { 01223 Vector init(this->size()); 01224 for (int i=0; i < this->size(); ++i) 01225 init[i] = Measure_Num<T>::get(this->getDefaultValue(),i); 01226 zIndex = this->getSubsystem().allocateZ(s, init); 01227 } 01228 01231 void realizeMeasureAccelerationVirtual(const State& s) const OVERRIDE_11 { 01232 assert(zIndex.isValid()); 01233 Vector& allZDot = this->getSubsystem().updZDot(s); 01234 if (!derivMeasure.isEmptyHandle()) { 01235 const T& deriv = derivMeasure.getValue(s); 01236 for (int i=0; i < this->size(); ++i) 01237 allZDot[zIndex+i] = Measure_Num<T>::get(deriv,i); 01238 } else { 01239 allZDot(zIndex,this->size()) = 0; // derivative is zero 01240 } 01241 } 01242 01243 private: 01244 // TOPOLOGY STATE 01245 Measure_<T> derivMeasure; // just handles 01246 Measure_<T> icMeasure; 01247 01248 // TOPOLOGY CACHE 01249 mutable ZIndex zIndex; // This is the first index if more than one z. 01250 }; 01251 01252 01253 01254 //============================================================================== 01255 // DIFFERENTIATE :: IMPLEMENTATION 01256 //============================================================================== 01257 // Hide from Doxygen. 01259 // This helper class is the contents of the discrete state variable and 01260 // corresponding cache entry maintained by this measure. The variable is 01261 // auto-update, meaning the value of the cache entry replaces the state 01262 // variable at the start of each step. 01263 // TODO: This was a local class in Measure_<T>::Differentiate::Implementation 01264 // but VC++ 8 (2005) failed to properly instantiate the templatized operator<<() 01265 // in that case; doing it this way is a workaround. 01266 template <class T> 01267 class Measure_Differentiate_Result { 01268 public: 01269 Measure_Differentiate_Result() : derivIsGood(false) {} 01270 T operand; // previous value of operand 01271 T operandDot; // previous value of derivative 01272 bool derivIsGood; // do we think the deriv is a good one? 01273 }; 01276 template <class T> 01277 class Measure_<T>::Differentiate::Implementation 01278 : public Measure_<T>::Implementation 01279 { 01280 typedef Measure_Differentiate_Result<T> Result; 01281 public: 01282 // Don't allocate any cache entries in the base class. 01283 Implementation() : Measure_<T>::Implementation(0) {} 01284 01285 Implementation(const Measure_<T>& operand) 01286 : Measure_<T>::Implementation(0), 01287 operand(operand), forceUseApprox(false), isApproxInUse(false) {} 01288 01289 // Default copy constructor gives us a new Implementation object, 01290 // but with reference to the *same* operand measure. 01291 01292 void setForceUseApproximation(bool mustApproximate) { 01293 forceUseApprox = mustApproximate; 01294 this->invalidateTopologyCache(); 01295 } 01296 01297 void setOperandMeasure(const Measure_<T>& operand) { 01298 this->operand = operand; 01299 this->invalidateTopologyCache(); 01300 } 01301 01302 bool getForceUseApproximation() const {return forceUseApprox;} 01303 bool isUsingApproximation() const {return isApproxInUse;} 01304 const Measure_<T>& getOperandMeasure() const {return operand;} 01305 01306 // Implementations of virtual methods. 01307 01308 // This uses the default copy constructor. 01309 Implementation* cloneVirtual() const OVERRIDE_11 01310 { return new Implementation(*this); } 01311 01312 // This has one fewer than the operand. 01313 int getNumTimeDerivativesVirtual() const OVERRIDE_11 01314 { if (!isApproxInUse) return operand.getNumTimeDerivatives()-1; 01315 else return 0; } 01316 01317 Stage getDependsOnStageVirtual(int order) const OVERRIDE_11 01318 { if (!isApproxInUse) return operand.getDependsOnStage(order+1); 01319 else return operand.getDependsOnStage(order); } 01320 01321 01322 // We're not using the Measure_<T> base class cache services, but 01323 // we do have one of our own. It looks uncached from the base class 01324 // point of view which is why we're implementing it here. 01325 const T& getUncachedValueVirtual(const State& s, int derivOrder) const 01326 OVERRIDE_11 01327 { if (!isApproxInUse) 01328 return operand.getValue(s, derivOrder+1); 01329 01330 ensureDerivativeIsRealized(s); 01331 const Subsystem& subsys = this->getSubsystem(); 01332 const Result& result = Value<Result>::downcast 01333 (subsys.getDiscreteVarUpdateValue(s,resultIx)); 01334 return result.operandDot; // has a value but might not be a good one 01335 } 01336 01337 void initializeVirtual(State& s) const OVERRIDE_11 { 01338 if (!isApproxInUse) return; 01339 01340 assert(resultIx.isValid()); 01341 const Subsystem& subsys = this->getSubsystem(); 01342 Result& result = Value<Result>::updDowncast 01343 (subsys.updDiscreteVariable(s,resultIx)); 01344 this->getSubsystem().getSystem().realize(s,operand.getDependsOnStage()); 01345 result.operand = operand.getValue(s); 01346 result.operandDot = this->getValueZero(); 01347 result.derivIsGood = false; 01348 } 01349 01350 void realizeMeasureTopologyVirtual(State& s) const OVERRIDE_11 { 01351 isApproxInUse = (forceUseApprox || operand.getNumTimeDerivatives()==0); 01352 if (!isApproxInUse) 01353 return; 01354 01355 resultIx = this->getSubsystem() 01356 .allocateAutoUpdateDiscreteVariable(s, operand.getDependsOnStage(0), 01357 new Value<Result>(), operand.getDependsOnStage(0)); 01358 } 01359 01362 void realizeMeasureAccelerationVirtual(const State& s) const OVERRIDE_11 { 01363 ensureDerivativeIsRealized(s); 01364 } 01365 01366 void ensureDerivativeIsRealized(const State& s) const { 01367 assert(resultIx.isValid()); 01368 const Subsystem& subsys = this->getSubsystem(); 01369 if (subsys.isDiscreteVarUpdateValueRealized(s,resultIx)) 01370 return; 01371 01372 const Real t0 = subsys.getDiscreteVarLastUpdateTime(s,resultIx); 01373 const Result& prevResult = Value<Result>::downcast 01374 (subsys.getDiscreteVariable(s,resultIx)); 01375 const T& f0 = prevResult.operand; 01376 const T& fdot0 = prevResult.operandDot; // may be invalid 01377 const bool good0 = prevResult.derivIsGood; 01378 01379 const Real t = s.getTime(); 01380 Result& result = Value<Result>::updDowncast 01381 (subsys.updDiscreteVarUpdateValue(s,resultIx)); 01382 T& f = result.operand; // renaming 01383 T& fdot = result.operandDot; 01384 bool& good = result.derivIsGood; 01385 01386 f = operand.getValue(s); 01387 good = false; 01388 if (!isFinite(t0)) 01389 fdot = this->getValueZero(); 01390 else if (t == t0) { 01391 fdot = fdot0; 01392 good = good0; 01393 } else { 01394 fdot = (f-f0)/(t-t0); // 1st order 01395 if (good0) 01396 fdot = Real(2)*fdot - fdot0; // now 2nd order 01397 good = true; // either 1st or 2nd order estimate 01398 } 01399 subsys.markDiscreteVarUpdateValueRealized(s,resultIx); 01400 } 01401 private: 01402 // TOPOLOGY STATE 01403 Measure_<T> operand; 01404 bool forceUseApprox; 01405 01406 // TOPOLOGY CACHE 01407 mutable bool isApproxInUse; 01408 mutable DiscreteVariableIndex resultIx; // auto-update 01409 }; 01410 01411 01412 01413 //============================================================================== 01414 // EXTREME :: IMPLEMENTATION 01415 //============================================================================== 01416 template <class T> 01417 class Measure_<T>::Extreme::Implementation : public Measure_<T>::Implementation 01418 { 01419 typedef typename Measure_<T>::Extreme Extreme; 01420 typedef typename Extreme::Operation Operation; 01421 public: 01424 Implementation() 01425 : Measure_<T>::Implementation(0), operation(Extreme::MaxAbs) {} 01426 01429 Implementation(const Measure_<T>& operand, Operation op) 01430 : Measure_<T>::Implementation(0), operand(operand), operation(op) {} 01431 01432 // Default copy constructor gives us a new Implementation object, 01433 // but with reference to the *same* operand measure. 01434 01438 void setOperandMeasure(const Measure_<T>& operand) { 01439 this->operand = operand; 01440 this->invalidateTopologyCache(); 01441 } 01442 01446 void setOperation(Operation op) { 01447 this->operation = op; 01448 this->invalidateTopologyCache(); 01449 } 01450 01452 const Measure_<T>& getOperandMeasure() const {return operand;} 01453 01456 Operation getOperation() const {return operation;} 01457 01460 void setValue(State& s, const T& value) const { 01461 assert(extremeIx.isValid()); 01462 const Subsystem& subsys = this->getSubsystem(); 01463 T& prevMin = Value<T>::updDowncast 01464 (subsys.updDiscreteVariable(s,extremeIx)); 01465 prevMin = value; 01466 } 01467 01471 Real getTimeOfExtremeValue(const State& s) const { 01472 const Subsystem& subsys = this->getSubsystem(); 01473 const bool hasNewExtreme = ensureExtremeHasBeenUpdated(s); 01474 Real tUpdate; 01475 if (hasNewExtreme) 01476 tUpdate = s.getTime(); // i.e., now 01477 else 01478 tUpdate = subsys.getDiscreteVarLastUpdateTime(s,extremeIx); 01479 return tUpdate; 01480 } 01481 01482 // Implementations of virtual methods. 01483 01484 // This uses the default copy constructor. 01485 Implementation* cloneVirtual() const OVERRIDE_11 01486 { return new Implementation(*this); } 01487 01490 int getNumTimeDerivativesVirtual() const OVERRIDE_11 01491 { return operand.getNumTimeDerivatives(); } 01492 01495 Stage getDependsOnStageVirtual(int order) const OVERRIDE_11 01496 { return operand.getDependsOnStage(order); } 01497 01498 01502 const T& getUncachedValueVirtual(const State& s, int derivOrder) const 01503 OVERRIDE_11 01504 { 01505 const Subsystem& subsys = this->getSubsystem(); 01506 const bool hasNewExtreme = ensureExtremeHasBeenUpdated(s); 01507 if (derivOrder > 0) { 01508 // TODO: should be handled elementwise and zero unless the 01509 // derivative is acting in the direction that changes the 01510 // extreme. 01511 return hasNewExtreme ? operand.getValue(s, derivOrder) 01512 : this->getValueZero(); 01513 } 01514 if (hasNewExtreme) { 01515 const T& newExt = Value<T>::downcast 01516 (subsys.getDiscreteVarUpdateValue(s,extremeIx)); 01517 return newExt; 01518 } else { 01519 const T& currentExt = Value<T>::downcast 01520 (subsys.getDiscreteVariable(s,extremeIx)); 01521 return currentExt; 01522 } 01523 } 01524 01527 void initializeVirtual(State& s) const OVERRIDE_11 { 01528 this->getSubsystem().getSystem().realize(s,operand.getDependsOnStage()); 01529 setValue(s, operand.getValue(s)); 01530 } 01531 01539 void realizeMeasureTopologyVirtual(State& s) const OVERRIDE_11 { 01540 // TODO: this should be NaN once initialization is working properly. 01541 T initVal = this->getDefaultValue(); 01542 switch(operation) { 01543 case Minimum: initVal = Infinity; break; 01544 case Maximum: initVal = -Infinity; break; 01545 case MinAbs: initVal = Infinity; break; 01546 case MaxAbs: initVal = 0; break; 01547 }; 01548 01549 extremeIx = this->getSubsystem() 01550 .allocateAutoUpdateDiscreteVariable(s, Stage::Dynamics, 01551 new Value<T>(initVal), operand.getDependsOnStage(0)); 01552 01553 isNewExtremeIx = this->getSubsystem() 01554 .allocateAutoUpdateDiscreteVariable(s, Stage::Dynamics, 01555 new Value<bool>(false), operand.getDependsOnStage(0)); 01556 } 01557 01560 void realizeMeasureAccelerationVirtual(const State& s) const OVERRIDE_11 { 01561 ensureExtremeHasBeenUpdated(s); 01562 } 01563 01569 bool ensureExtremeHasBeenUpdated(const State& s) const { 01570 assert(extremeIx.isValid() && isNewExtremeIx.isValid()); 01571 const Subsystem& subsys = this->getSubsystem(); 01572 01573 // We may have already determined whether we're at a new extreme in 01574 // which case we don't need to do it again. 01575 if (subsys.isDiscreteVarUpdateValueRealized(s, isNewExtremeIx)) 01576 return Value<bool>::downcast 01577 (subsys.getDiscreteVarUpdateValue(s,isNewExtremeIx)); 01578 01579 // We're going to have to decide if we're at a new extreme, and if 01580 // so record the new extreme value in the auto-update cache entry of 01581 // the extreme value state variable. 01582 01583 // Get the previous extreme value and the current operand value. 01584 const T& prevExtreme = Value<T>::downcast 01585 (subsys.getDiscreteVariable(s,extremeIx)); 01586 const T& currentVal = operand.getValue(s); 01587 01588 // Search to see if any element has reached a new extreme. 01589 bool foundNewExt = false; 01590 for (int i=0; i < this->size() && !foundNewExt; ++i) 01591 foundNewExt = isNewExtreme(Measure_Num<T>::get(currentVal,i), 01592 Measure_Num<T>::get(prevExtreme,i)); 01593 01594 // Record the result and mark the auto-update cache entry valid 01595 // so we won't have to recalculate. When the integrator advances to the 01596 // next step this cache entry will be swapped with the corresponding 01597 // state and marked invalid so we'll be sure to recalculate each step. 01598 Value<bool>::updDowncast 01599 (subsys.updDiscreteVarUpdateValue(s,isNewExtremeIx)) = foundNewExt; 01600 subsys.markDiscreteVarUpdateValueRealized(s,isNewExtremeIx); 01601 01602 // Don't update the auto-update cache entry if we didn't see a new 01603 // extreme. That way no auto-update will occur and the state variable 01604 // will remain unchanged with the existing update time preserved. 01605 if (!foundNewExt) 01606 return false; 01607 01608 // We have encountered a new extreme. We'll record the new extreme 01609 // in the auto-update cache entry which will be used as the current 01610 // result until the integrator advances to the next step at which time 01611 // this will be swapped with the state variable to serve as the previous 01612 // extreme value until a further extreme is encountered. 01613 T& newExtreme = Value<T>::updDowncast 01614 (subsys.updDiscreteVarUpdateValue(s,extremeIx)); 01615 01616 for (int i=0; i < this->size(); ++i) 01617 Measure_Num<T>::upd(newExtreme,i) = 01618 extremeOf(Measure_Num<T>::get(currentVal,i), 01619 Measure_Num<T>::get(prevExtreme,i)); 01620 01621 // Marking this valid is what ensures that an auto-update occurs later. 01622 subsys.markDiscreteVarUpdateValueRealized(s,extremeIx); 01623 return true; 01624 } 01625 private: 01626 // Return true if newVal is "more extreme" than oldExtreme, according 01627 // to the operation we're performing. 01628 bool isNewExtreme(const typename Measure_Num<T>::Element& newVal, 01629 const typename Measure_Num<T>::Element& oldExtreme) const 01630 { 01631 switch (operation) { 01632 case Extreme::Maximum: return newVal > oldExtreme; 01633 case Extreme::Minimum: return newVal < oldExtreme; 01634 case Extreme::MaxAbs: return std::abs(newVal) > std::abs(oldExtreme); 01635 case Extreme::MinAbs: return std::abs(newVal) < std::abs(oldExtreme); 01636 }; 01637 SimTK_ASSERT1_ALWAYS(!"recognized", 01638 "Measure::Extreme::Implementation::isNewExtreme(): " 01639 "unrecognized operation %d", (int)operation); 01640 return false; /*NOTREACHED*/ 01641 } 01642 01643 // Given the value of one element of the operand, and that value's time 01644 // derivative, determine whether the derivative is moving the element 01645 // into the "more extreme" direction, according to the operation. 01646 bool isExtremeDir(const typename Measure_Num<T>::Element& value, 01647 const typename Measure_Num<T>::Element& deriv) const 01648 { 01649 const int sv = sign(value), sd = sign(deriv); 01650 if (sd == 0) return false; // derivative is zero; not changing 01651 switch (operation) { 01652 case Extreme::Maximum: return sd == 1; // getting larger 01653 case Extreme::Minimum: return sd == -1; // getting smaller 01654 case Extreme::MaxAbs: return sv==0 || sd==sv; // abs is growing 01655 case Extreme::MinAbs: return sd == -sv; 01656 }; 01657 SimTK_ASSERT1_ALWAYS(!"recognized", 01658 "Measure::Extreme::Implementation::isExtremeDir(): " 01659 "unrecognized operation %d", (int)operation); 01660 return false; /*NOTREACHED*/ 01661 } 01662 01663 typename Measure_Num<T>::Element 01664 extremeOf(const typename Measure_Num<T>::Element& newVal, 01665 const typename Measure_Num<T>::Element& oldExtreme) const 01666 { 01667 return isNewExtreme(newVal,oldExtreme) ? newVal : oldExtreme; 01668 } 01669 01670 // TOPOLOGY STATE 01671 Measure_<T> operand; 01672 Operation operation; 01673 01674 // TOPOLOGY CACHE 01675 mutable DiscreteVariableIndex extremeIx; // extreme so far; auto-update 01676 01677 // This auto-update flag records whether the current value is a new 01678 // extreme. We don't really need to save it as a state variable since you 01679 // can figure this out from the timestamp, but we need to to get invalidated 01680 // by the auto-update swap so that we'll figure it out anew each step. 01681 mutable DiscreteVariableIndex isNewExtremeIx; 01682 }; 01683 01684 01685 01686 //============================================================================== 01687 // DELAY :: IMPLEMENTATION 01688 //============================================================================== // Hide from Doxygen. 01690 // This helper class is the contents of the discrete state variable and 01691 // corresponding cache entry maintained by this measure. The variable is 01692 // auto-update, meaning the value of the cache entry replaces the state 01693 // variable at the start of each step. 01694 // 01695 // Circular buffers look like this: 01696 // 01697 // oldest=0, n=0 01698 // v 01699 // Empty buffer: | available | 01700 // 01701 // By convention, oldest=0 whenever the buffer is empty. 01702 // 01703 // 01704 // oldest next=(oldest+n)%capacity 01705 // v v 01706 // | available | | | | | | | available | 01707 // ^ n=6 ^ 01708 // 0 capacity 01709 // v v 01710 // or | | | | | | available | | | | | | | | n=12 01711 // ^ ^ 01712 // next oldest 01713 // = (oldest+n)%capacity 01714 // 01715 // Number of entries = n (called size() below) 01716 // Empty = n==0 01717 // Full = n==capacity() 01718 // Next available = (oldest+n)%capacity() 01719 template <class T> 01720 class Measure_Delay_Buffer { 01721 public: 01722 explicit Measure_Delay_Buffer() {initDataMembers();} 01723 void clear() {initDataMembers();} 01724 int size() const {return m_size;} // # saved entries, *not* size of arrays 01725 int capacity() const {return m_times.size();} 01726 bool empty() const {return size()==0;} 01727 bool full() const {return size()==capacity();} 01728 01729 double getEntryTime(int i) const 01730 { assert(i < size()); return m_times[getArrayIndex(i)];} 01731 const T& getEntryValue(int i) const 01732 { assert(i < size()); return m_values[getArrayIndex(i)];} 01733 01734 enum { 01735 InitialAllocation = 8, // smallest allocation 01736 GrowthFactor = 2, // how fast to grow (double) 01737 MaxShrinkProofSize = 16, // won't shrink unless bigger 01738 TooBigFactor = 5 // 5X too much->maybe shrink 01739 }; 01740 01741 // Add a new entry to the end of the list, throwing out old entries that 01742 // aren't needed to answer requests at tEarliest or later. 01743 void append(double tEarliest, double tNow, const T& valueNow) { 01744 forgetEntriesMuchOlderThan(tEarliest); 01745 removeEntriesLaterOrEq(tNow); 01746 if (full()) 01747 makeMoreRoom(); 01748 else if (capacity() > std::max((int)MaxShrinkProofSize, 01749 (int)TooBigFactor * (size()+1))) 01750 makeLessRoom(); // less than 1/TooBigFactor full 01751 const int nextFree = getArrayIndex(m_size++); 01752 m_times[nextFree] = tNow; 01753 m_values[nextFree] = valueNow; 01754 m_maxSize = std::max(m_maxSize, size()); 01755 } 01756 01757 // Prepend an older entry to the beginning of the list. No cleanup is done. 01758 void prepend(double tNewOldest, const T& value) { 01759 assert(empty() || tNewOldest < m_times[m_oldest]); 01760 if (full()) makeMoreRoom(); 01761 m_oldest = empty() ? 0 : getArrayIndex(-1); 01762 m_times[m_oldest] = tNewOldest; 01763 m_values[m_oldest] = value; 01764 ++m_size; 01765 m_maxSize = std::max(m_maxSize, size()); 01766 } 01767 01768 // This is a specialized copy assignment for copying an old buffer 01769 // to a new one with updated contents. We are told the earliest time we'll 01770 // be asked about from now on, and won't copy any entries older than those 01771 // needed to answer that earliest request. We won't copy anything at or 01772 // newer than tNow, and finally we'll push (tNow,valueNow) as the newest 01773 // entry. 01774 void copyInAndUpdate(const Measure_Delay_Buffer& oldBuf, double tEarliest, 01775 double tNow, const T& valueNow) { 01776 // clear all current entries (no heap activity) 01777 m_oldest = m_size = 0; 01778 01779 // determine how may old entries we have to keep 01780 int firstNeeded = oldBuf.countNumUnneededOldEntries(tEarliest); 01781 int lastNeeded = oldBuf.findLastEarlier(tNow); // might be -1 01782 int numOldEntriesToKeep = lastNeeded-firstNeeded+1; 01783 int newSize = numOldEntriesToKeep+1; // includes the new one 01784 01785 int newSizeRequest = -1; 01786 if (capacity() < newSize) { 01787 newSizeRequest = std::max((int)InitialAllocation, 01788 (int)GrowthFactor * newSize); 01789 ++m_nGrows; 01790 } else if (capacity() > std::max((int)MaxShrinkProofSize, 01791 (int)TooBigFactor * newSize)) { 01792 newSizeRequest = std::max((int)MaxShrinkProofSize, 01793 (int)GrowthFactor * newSize); 01794 ++m_nShrinks; 01795 } 01796 01797 // Reallocate space if advisable. 01798 if (newSizeRequest != -1) { 01799 const double dNaN = NTraits<double>::getNaN(); 01800 m_values.resize(newSizeRequest); 01801 if (m_values.capacity() > m_values.size()) 01802 m_values.resize(m_values.capacity()); // don't waste any 01803 m_times.resize(m_values.size(), dNaN); 01804 } 01805 01806 m_maxCapacity = std::max(m_maxCapacity, capacity()); 01807 01808 // Copy the entries we need to keep. 01809 int nxt = 0; 01810 for (int i=firstNeeded; i<=lastNeeded; ++i, ++nxt) { 01811 m_times[nxt] = oldBuf.getEntryTime(i); 01812 m_values[nxt] = oldBuf.getEntryValue(i); 01813 } 01814 // Now add the newest entry and set the size. 01815 m_times[nxt] = tNow; 01816 m_values[nxt] = valueNow; 01817 assert(nxt+1==newSize); 01818 m_size = nxt+1; 01819 m_maxSize = std::max(m_maxSize, size()); 01820 } 01821 01822 // Given the current time and value and the earlier time at which the 01823 // value is needed, use the buffer and (if necessary) the current value 01824 // to estimate the delayed value. 01825 T calcValueAtTime(double tDelay, double tNow, const T& valueNow) const; 01826 01827 // Given the current time but *not* the current value of the source measure, 01828 // provide an estimate for the value at tDelay=tNow-delay using only the 01829 // buffer contents and linear interpolation or extrapolation. 01830 void calcValueAtTimeLinearOnly(double tDelay, T& delayedValue) const { 01831 if (empty()) { 01832 // Nothing in the buffer?? Shouldn't happen. Return empty Vector 01833 // or NaN for fixed-size types. 01834 Measure_Num<T>::makeNaNLike(T(), delayedValue); 01835 return; 01836 } 01837 01838 int firstLater = findFirstLaterOrEq(tDelay); 01839 01840 if (firstLater > 0) { 01841 // Normal case: tDelay is between two buffer entries. 01842 int firstEarlier = firstLater-1; 01843 double t0=getEntryTime(firstEarlier), t1=getEntryTime(firstLater); 01844 const T& v0=getEntryValue(firstEarlier); 01845 const T& v1=getEntryValue(firstLater); 01846 Real fraction = Real((tDelay-t0)/(t1-t0)); 01847 delayedValue = T(v0 + fraction*(v1-v0)); 01848 return; 01849 } 01850 01851 if (firstLater==0) { 01852 // Startup case: tDelay is at or before the oldest buffer entry. 01853 // Assume the value was flat before that. 01854 delayedValue = getEntryValue(firstLater); 01855 return; 01856 } 01857 01858 // tDelay is later than the latest entry in the buffer. We are going 01859 // to have to extrapolate (yuck). 01860 01861 if (size() == 1) { 01862 // Just one entry; we'll have to assume the value is flat. 01863 delayedValue = getEntryValue(0); 01864 return; 01865 } 01866 01867 // Extrapolate using the last two entries. 01868 double t0=getEntryTime(size()-2), t1=getEntryTime(size()-1); 01869 const T& v0=getEntryValue(size()-2); 01870 const T& v1=getEntryValue(size()-1); 01871 Real fraction = Real((tDelay-t0)/(t1-t0)); // > 1 01872 assert(fraction > 1.0); 01873 delayedValue = T(v0 + fraction*(v1-v0)); // Extrapolate. 01874 } 01875 01876 // Return the number of times we had to grow the buffer. 01877 int getNumGrows() const {return m_nGrows;} 01878 // Return the number of times we decided the buffer was so overallocated 01879 // that we had to shrink it. 01880 int getNumShrinks() const {return m_nShrinks;} 01881 // Return the largest number of values we ever had in the buffer. 01882 int getMaxSize() const {return m_maxSize;} 01883 // Return the largest capacity the buffer ever had. 01884 int getMaxCapacity() const {return m_maxCapacity;} 01885 01886 private: 01887 // Return the i'th oldest entry 01888 // (0 -> oldest, size-1 -> newest, size -> first free, -1 -> last free) 01889 int getArrayIndex(int i) const 01890 { assert(-1<=i && i<=size()); 01891 const int rawIndex = m_oldest + i; 01892 if (rawIndex < 0) return rawIndex + capacity(); 01893 else return rawIndex % capacity(); } 01894 01895 // Remove all but two entries older than the given time. 01896 void forgetEntriesMuchOlderThan(double tEarliest) { 01897 const int numToRemove = countNumUnneededOldEntries(tEarliest); 01898 if (numToRemove) { 01899 m_oldest = getArrayIndex(numToRemove); 01900 m_size -= numToRemove; 01901 } 01902 } 01903 01904 // Count up how many old entries at the beginning of the buffer are so old 01905 // that they wouldn't be needed to respond to a request at time tEarliest or 01906 // later. We'll keep no more than two entries earlier than tEarliest. 01907 int countNumUnneededOldEntries(double tEarliest) const { 01908 const int firstLater = findFirstLaterOrEq(tEarliest); 01909 return std::max(0, firstLater-2); 01910 } 01911 01912 // Given the time now, delete anything at the end of the queue that is 01913 // at that same time or later. 01914 void removeEntriesLaterOrEq(double t) { 01915 int lastEarlier = findLastEarlier(t); 01916 m_size = lastEarlier+1; 01917 if (m_size==0) m_oldest=0; // restart at beginning of array 01918 } 01919 01920 // Return the entry number (0..size-1) of the first entry whose time 01921 // is >= the given time, or -1 if there is none such. 01922 int findFirstLaterOrEq(double tDelay) const { 01923 for (int i=0; i < size(); ++i) 01924 if (getEntryTime(i) >= tDelay) 01925 return i; 01926 return -1; 01927 } 01928 01929 // Return the entry number(size-1..0) of the last entry whose time 01930 // is < the given time, or -1 if there is none such. 01931 int findLastEarlier(double t) const { 01932 for (int i=size()-1; i>=0; --i) 01933 if (getEntryTime(i) < t) 01934 return i; 01935 return -1; 01936 } 01937 01938 // We don't have enough space. This is either the initial allocation or 01939 // we need to double the current space. 01940 void makeMoreRoom() { 01941 const int newSizeRequest = std::max((int)InitialAllocation, 01942 (int)GrowthFactor * size()); 01943 resize(newSizeRequest); 01944 ++m_nGrows; 01945 m_maxCapacity = std::max(m_maxCapacity, capacity()); 01946 } 01947 01948 // We are wasting a lot of space, reduce the heap allocation to just 01949 // double what we're using now. 01950 void makeLessRoom() { 01951 const int targetMaxSize = std::max((int)MaxShrinkProofSize, 01952 (int)GrowthFactor * size()); 01953 if (capacity() > targetMaxSize) { 01954 resize(targetMaxSize); 01955 ++m_nShrinks; 01956 } 01957 } 01958 01959 // Reallocate memory to get more space or stop wasting space. The new 01960 // size request must be big enough to hold all the current contents. The 01961 // amount we actually get may be somewhat larger than the request. On 01962 // return, the times and values arrays will have been resized and the 01963 // oldest entry will now be entry 0. 01964 void resize(int newSizeRequest) { 01965 assert(newSizeRequest >= size()); 01966 const double dNaN = NTraits<double>::getNaN(); 01967 Array_<T,int> newValues(newSizeRequest); 01968 if (newValues.capacity() > newValues.size()) 01969 newValues.resize(newValues.capacity()); // don't waste any 01970 Array_<double,int> newTimes(newValues.size(), dNaN); 01971 01972 // Pack existing values into start of new arrays. 01973 for (int i=0; i < size(); ++i) { 01974 const int ix = getArrayIndex(i); 01975 newTimes[i] = m_times[ix]; 01976 newValues[i] = m_values[ix]; 01977 } 01978 m_times.swap(newTimes); // switch heap space 01979 m_values.swap(newValues); 01980 m_oldest = 0; // starts at the beginning now; size unchanged 01981 } 01982 01983 // Initialize everything to its default-constructed state. 01984 void initDataMembers() { 01985 m_times.clear(); m_values.clear(); 01986 m_oldest=m_size=0; 01987 m_nGrows=m_nShrinks=m_maxSize=m_maxCapacity=0; 01988 } 01989 01990 // These are circular buffers of the same size. 01991 Array_<double,int> m_times; 01992 Array_<T,int> m_values; 01993 int m_oldest; // Array index of oldest (time,value) 01994 int m_size; // number of entries in use 01995 01996 // Statistics. 01997 int m_nGrows, m_nShrinks, m_maxSize, m_maxCapacity; 01998 }; 02001 template <class T> 02002 class Measure_<T>::Delay::Implementation: public Measure_<T>::Implementation { 02003 typedef Measure_Delay_Buffer<T> Buffer; 02004 public: 02005 // Allocate one cache entry in the base class for the value; we allocate 02006 // a specialized one for the buffer. 02007 Implementation() 02008 : Measure_<T>::Implementation(1), m_delay(NaN), 02009 m_canUseCurrentValue(false), m_useLinearInterpolationOnly(false) {} 02010 02011 Implementation(const Measure_<T>& source, Real delay) 02012 : Measure_<T>::Implementation(1), m_source(source), m_delay(delay), 02013 m_canUseCurrentValue(false), m_useLinearInterpolationOnly(false) {} 02014 02015 // Default copy constructor gives us a new Implementation object, 02016 // but with reference to the *same* source measure. 02017 02018 void setSourceMeasure(const Measure_<T>& source) { 02019 if (!source.isSameMeasure(this->m_source)) { 02020 this->m_source = source; 02021 this->invalidateTopologyCache(); 02022 } 02023 } 02024 02025 void setDelay(Real delay) { 02026 if (delay != this->m_delay) { 02027 this->m_delay = delay; 02028 this->invalidateTopologyCache(); 02029 } 02030 } 02031 02032 void setUseLinearInterpolationOnly(bool linearOnly) { 02033 if (linearOnly != this->m_useLinearInterpolationOnly) { 02034 this->m_useLinearInterpolationOnly = linearOnly; 02035 this->invalidateTopologyCache(); 02036 } 02037 } 02038 02039 void setCanUseCurrentValue(bool canUseCurrentValue) { 02040 if (canUseCurrentValue != this->m_canUseCurrentValue) { 02041 this->m_canUseCurrentValue = canUseCurrentValue; 02042 this->invalidateTopologyCache(); 02043 } 02044 } 02045 02046 const Measure_<T>& getSourceMeasure() const {return this->m_source;} 02047 Real getDelay() const {return this->m_delay;} 02048 bool getUseLinearInterpolationOnly() const 02049 { return this->m_useLinearInterpolationOnly; } 02050 bool getCanUseCurrentValue() const 02051 { return this->m_canUseCurrentValue; } 02052 02053 02054 // Implementations of virtual methods. 02055 02056 // This uses the default copy constructor. 02057 Implementation* cloneVirtual() const OVERRIDE_11 02058 { return new Implementation(*this); } 02059 02060 // Currently no derivative supported. 02061 int getNumTimeDerivativesVirtual() const OVERRIDE_11 02062 { return 0; } 02063 02064 // If we are allowed to use the current value of the source measure to 02065 // determine the delayed value, the depends-on stage here is the same as 02066 // for the source; otherwise it is Stage::Time. 02067 Stage getDependsOnStageVirtual(int order) const OVERRIDE_11 02068 { return this->m_canUseCurrentValue ? m_source.getDependsOnStage(order) 02069 : Stage::Time; } 02070 02071 // Calculate the delayed value and return it to the Measure base class to 02072 // be put in a cache entry. 02073 void calcCachedValueVirtual(const State& s, int derivOrder, T& value) const 02074 OVERRIDE_11 02075 { const Subsystem& subsys = this->getSubsystem(); 02076 const Buffer& buffer = Value<Buffer>::downcast 02077 (subsys.getDiscreteVariable(s,m_bufferIx)); 02078 //TODO: use cubic interpolation if allowed 02079 buffer.calcValueAtTimeLinearOnly(s.getTime()-m_delay, value); 02080 } 02081 02082 void initializeVirtual(State& s) const OVERRIDE_11 { 02083 assert(m_bufferIx.isValid()); 02084 const Subsystem& subsys = this->getSubsystem(); 02085 Buffer& buffer = Value<Buffer>::updDowncast 02086 (subsys.updDiscreteVariable(s,m_bufferIx)); 02087 buffer.clear(); 02088 this->getSubsystem().getSystem().realize(s,m_source.getDependsOnStage()); 02089 buffer.append(s.getTime()-m_delay, s.getTime(), m_source.getValue(s)); 02090 } 02091 02092 void realizeMeasureTopologyVirtual(State& s) const OVERRIDE_11 { 02093 m_bufferIx = this->getSubsystem() 02094 .allocateAutoUpdateDiscreteVariable(s, Stage::Report, 02095 new Value<Buffer>(), getDependsOnStageVirtual(0)); 02096 } 02097 02100 void realizeMeasureAccelerationVirtual(const State& s) const OVERRIDE_11 { 02101 updateBuffer(s); 02102 } 02103 02104 // This uses the buffer from the state to update the one in the 02105 // corresponding cache entry. The update adds the current value of the 02106 // source to the end of the buffer and tosses out unneeded old entries. 02107 void updateBuffer(const State& s) const { 02108 assert(m_bufferIx.isValid()); 02109 const Subsystem& subsys = this->getSubsystem(); 02110 02111 const Buffer& prevBuffer = Value<Buffer>::downcast 02112 (subsys.getDiscreteVariable(s,m_bufferIx)); 02113 02114 Buffer& nextBuffer = Value<Buffer>::updDowncast 02115 (subsys.updDiscreteVarUpdateValue(s,m_bufferIx)); 02116 02117 const Real t = s.getTime(); 02118 nextBuffer.copyInAndUpdate(prevBuffer, t-m_delay, 02119 t, m_source.getValue(s)); 02120 02121 subsys.markDiscreteVarUpdateValueRealized(s,m_bufferIx); 02122 } 02123 private: 02124 // TOPOLOGY STATE 02125 Measure_<T> m_source; 02126 Real m_delay; 02127 bool m_canUseCurrentValue; 02128 bool m_useLinearInterpolationOnly; 02129 02130 // TOPOLOGY CACHE 02131 mutable DiscreteVariableIndex m_bufferIx; // auto-update 02132 }; 02133 02134 02135 } // namespace SimTK 02136 02137 02138 02139 02140 #endif // SimTK_SimTKCOMMON_MEASURE_IMPLEMENTATION_H_