00001 #ifndef SimTK_SimTKCOMMON_MEASURE_IMPLEMENTATION_H_
00002 #define SimTK_SimTKCOMMON_MEASURE_IMPLEMENTATION_H_
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
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
00052
00056 class SimTK_SimTKCOMMON_EXPORT AbstractMeasure::Implementation {
00057 protected:
00058
00059
00060
00061 explicit Implementation(const std::string& name="<NONAME>")
00062 : measureName(name), copyNumber(0), mySubsystem(0), refCount(0) {}
00063
00064
00065
00066
00067 Implementation(const Implementation& src)
00068 : measureName(src.measureName), copyNumber(src.copyNumber+1),
00069 mySubsystem(0), refCount(0) {}
00070
00071
00072
00073
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
00082
00083
00084 int incrRefCount() const {return ++refCount;}
00085
00086
00087 int decrRefCount() const {return --refCount;}
00088
00089
00090 int getRefCount() const {return refCount;}
00091
00092 const std::string& getName() const {return measureName;}
00093 int getCopyNumber() const {return copyNumber;}
00094
00095
00096
00097
00098 Implementation* clone() const {return cloneVirtual();}
00099
00100
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
00111
00112
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 = ⊂ 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
00143
00144
00145
00146 virtual ~Implementation() {}
00147 virtual Implementation* cloneVirtual() const = 0;
00148
00149 virtual void realizeTopology(State&)const = 0;
00150
00151 virtual void realizeMeasureModelVirtual(State&) const {}
00152 virtual void realizeMeasureInstanceVirtual(const State&) const {}
00153 virtual void realizeMeasureTimeVirtual(const State&) const {}
00154 virtual void realizeMeasurePositionVirtual(const State&) const {}
00155 virtual void realizeMeasureVelocityVirtual(const State&) const {}
00156 virtual void realizeMeasureDynamicsVirtual(const State&) const {}
00157 virtual void realizeMeasureAccelerationVirtual(const State&) const {}
00158 virtual void realizeMeasureReportVirtual(const State&) const {}
00159
00160 virtual void initializeVirtual(State&) const {}
00161 virtual int
00162 getNumTimeDerivativesVirtual() const {return 0;}
00163 virtual Stage
00164 getDependsOnStageVirtual(int order) const = 0;
00165
00166 private:
00167 std::string measureName;
00168 int copyNumber;
00169
00170
00171 Subsystem* mySubsystem;
00172 MeasureIndex myIndex;
00173
00174
00175
00176 mutable int refCount;
00177
00178 friend class AbstractMeasure;
00179 friend class Subsystem::Guts;
00180 friend class Subsystem::Guts::GutsRep;
00181 };
00182
00184
00186
00187
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
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
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
00224
00225
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
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
00314
00315 return getUncachedValueVirtual(s,derivOrder);
00316 }
00317
00318 protected:
00319
00320
00321
00322 explicit Implementation(int numValues=1) : derivIx(numValues) {}
00323
00324
00325
00326 void realizeTopology(State& s) const {
00327 Implementation* mutableThis = const_cast<Implementation*>(this);
00328
00329 for (int i=0; i < getNumCacheEntries(); ++i) {
00330 const Stage dependsOn = getDependsOnStage(i);
00331 mutableThis->derivIx[i] =
00332 this->getSubsystem().allocateLazyCacheEntry
00333 (s, dependsOn, new Value<T>());
00334 }
00335
00336
00337 realizeMeasureTopologyVirtual(s);
00338 }
00339
00340 int getNumCacheEntries() const {return (int)derivIx.size();}
00341
00342 const T& getCacheEntry(const State& s, int derivOrder) const {
00343 SimTK_ERRCHK2(0 <= derivOrder && derivOrder < getNumCacheEntries(),
00344 "Measure_<T>::Implementation::getCacheEntry()",
00345 "Derivative order %d is out of range; only %d cache entries"
00346 " were allocated.", derivOrder, getNumCacheEntries());
00347
00348 return Value<T>::downcast(
00349 this->getSubsystem().getCacheEntry(s, derivIx[derivOrder]));
00350 }
00351
00352 T& updCacheEntry(const State& s, int derivOrder) const {
00353 SimTK_ERRCHK2(0 <= derivOrder && derivOrder < getNumCacheEntries(),
00354 "Measure_<T>::Implementation::updCacheEntry()",
00355 "Derivative order %d is out of range; only %d cache entries"
00356 " were allocated.", derivOrder, getNumCacheEntries());
00357
00358 return Value<T>::updDowncast(
00359 this->getSubsystem().updCacheEntry(s, derivIx[derivOrder]));
00360 }
00361
00362 bool isCacheValueRealized(const State& s, int derivOrder) const {
00363 SimTK_ERRCHK2(0 <= derivOrder && derivOrder < getNumCacheEntries(),
00364 "Measure_<T>::Implementation::isCacheValueRealized()",
00365 "Derivative order %d is out of range; only %d cache entries"
00366 " were allocated.", derivOrder, getNumCacheEntries());
00367
00368 return this->getSubsystem().isCacheValueRealized(s, derivIx[derivOrder]);
00369 }
00370
00371 void markCacheValueRealized(const State& s, int derivOrder) const {
00372 SimTK_ERRCHK2(0 <= derivOrder && derivOrder < getNumCacheEntries(),
00373 "Measure_<T>::Implementation::markCacheValueRealized()",
00374 "Derivative order %d is out of range; only %d cache entries"
00375 " were allocated.", derivOrder, getNumCacheEntries());
00376
00377 this->getSubsystem().markCacheValueRealized(s, derivIx[derivOrder]);
00378 }
00379
00380
00381
00382
00383
00384 virtual void realizeMeasureTopologyVirtual(State&) const {}
00385 virtual void
00386 calcCachedValueVirtual(const State&, int derivOrder, T& value) const
00387 { SimTK_ERRCHK1_ALWAYS(!"implemented",
00388 "Measure_<T>::Implementation::calcCachedValueVirtual()",
00389 "This method should have been overridden by the derived"
00390 " Measure but was not. It is needed to calculate the"
00391 " cached value for derivOrder=%d.", derivOrder); }
00392
00393
00394
00395
00396 virtual const T&
00397 getUncachedValueVirtual(const State&, int derivOrder) const
00398 { SimTK_ERRCHK1_ALWAYS(!"implemented",
00399 "Measure_<T>::Implementation::getUncachedValueVirtual()",
00400 "This method should have been overridden by the derived"
00401 " Measure but was not. It is needed to return the uncached"
00402 " value at derivOrder=%d.", derivOrder);
00403 return *reinterpret_cast<T*>(0);
00404 }
00405
00406
00407 static const T& getValueZero() {
00408 static T zero(0);
00409 return zero;
00410 }
00411
00412 static const T& getValueOne() {
00413 static T one(1);
00414 return one;
00415 }
00416
00417 private:
00418 Array_<CacheEntryIndex> derivIx;
00419 };
00420
00421
00422
00424
00426
00427 template <class T>
00428 class Measure_<T>::Constant::Implementation
00429 : public Measure_<T>::Implementation
00430 {
00431 public:
00432
00433 Implementation() : Measure_<T>::Implementation(0) {}
00434 explicit Implementation(const T& value)
00435 : Measure_<T>::Implementation(0), value(value) {}
00436
00437
00438
00439 virtual void setValue(const T& v) {
00440 value = v;
00441 this->invalidateTopologyCache();
00442 }
00443
00444
00445
00446
00447
00448 const T& getUncachedValueVirtual(const State&, int derivOrder) const
00449 { return derivOrder>0 ? this->getValueZero() : value; }
00450
00451
00452 Implementation* cloneVirtual() const {return new Implementation(*this);}
00453 Stage getDependsOnStageVirtual(int derivOrder) const
00454 { return derivOrder>0 ? Stage::Empty : Stage::Topology; }
00455 int getNumTimeDerivativesVirtual() const
00456 { return std::numeric_limits<int>::max(); }
00457
00458 private:
00459 T value;
00460 };
00461
00463
00465
00466 template <class T>
00467 class Measure_<T>::Zero::Implementation
00468 : public Constant::Implementation
00469 {
00470 public:
00471 Implementation() : Constant::Implementation(T(0)) {}
00472
00473
00474
00475 void setValue(const T&) {
00476 SimTK_ERRCHK_ALWAYS(!"invalid", "Measure_<T>::Zero::setValue()",
00477 "You can't change the value of Zero!");
00478 }
00479
00480
00481 Implementation* cloneVirtual() const {return new Implementation(*this);}
00482 Stage getDependsOnStageVirtual(int) const
00483 { return Stage::Empty; }
00484 };
00485
00487
00489
00490
00491 template <class T>
00492 class Measure_<T>::One::Implementation
00493 : public Constant::Implementation
00494 {
00495 public:
00496 Implementation() : Constant::Implementation(T(1)) {}
00497
00498
00499
00500 void setValue(const T&) {
00501 SimTK_ERRCHK_ALWAYS(!"invalid", "Measure_<T>::One::setValue()",
00502 "You can't change the value of One!");
00503 }
00504
00505 Implementation* cloneVirtual() const {return new Implementation(*this);}
00506 Stage getDependsOnStageVirtual(int) const
00507 { return Stage::Empty; }
00508 };
00509
00510
00512
00514
00515 template <class T>
00516 class Measure_<T>::Time::Implementation {};
00517
00518 template <>
00519 class Measure_<Real>::Time::Implementation
00520 : public Measure_<Real>::Implementation
00521 {
00522 public:
00523
00524 Implementation() : Measure_<Real>::Implementation(0) {}
00525
00526
00527
00528
00529
00530 const Real& getUncachedValueVirtual(const State& s, int derivOrder) const
00531 { return derivOrder==0 ? s.getTime()
00532 : (derivOrder==1 ? this->getValueOne()
00533 : this->getValueZero()); }
00534
00535
00536 Implementation* cloneVirtual() const {return new Implementation(*this);}
00537 Stage getDependsOnStageVirtual(int derivOrder) const
00538 { return derivOrder>0 ? Stage::Empty : Stage::Time; }
00539
00540
00541 int getNumTimeDerivativesVirtual() const
00542 { return std::numeric_limits<int>::max(); }
00543 };
00544
00546
00548
00549 template <class T>
00550 class Measure_<T>::Variable::Implementation
00551 : public Measure_<T>::Implementation
00552 {
00553 public:
00554
00555
00556
00557 Implementation() : Measure_<T>::Implementation(0) {}
00558
00559 Implementation(Stage invalidates, const T& defaultValue)
00560 : Measure_<T>::Implementation(0),
00561 invalidatedStage(invalidates), defaultValue(defaultValue) {}
00562
00563
00564 Implementation(const Implementation& source)
00565 : Measure_<T>::Implementation(0),
00566 invalidatedStage(source.invalidatedStage),
00567 defaultValue(source.defaultValue) {}
00568
00569 void setDefaultValue(const T& v) {
00570 defaultValue = v;
00571 this->invalidateTopologyCache();
00572 }
00573
00574 void setInvalidatedStage(Stage invalidates) {
00575 invalidatedStage = invalidates;
00576 this->invalidateTopologyCache();
00577 }
00578
00579 const T& getDefaultValue() const {return defaultValue;}
00580 Stage getInvalidatedStage() const {return invalidatedStage;}
00581
00582 void setValue(State& state, const T& value) const
00583 { updVarValue(state) = value; }
00584
00585
00586 Implementation* cloneVirtual() const {return new Implementation(*this);}
00587
00588 int getNumTimeDerivativesVirtual() const
00589 { return std::numeric_limits<int>::max(); }
00590
00591
00592
00593 Stage getDependsOnStageVirtual(int derivOrder) const
00594 { return derivOrder>0 ? Stage::Empty : Stage::Model;}
00595
00596 const T& getUncachedValueVirtual(const State& s, int derivOrder) const
00597 { return derivOrder>0 ? this->getValueZero() : getVarValue(s); }
00598
00599
00600
00601 void realizeMeasureTopologyVirtual(State& s) const {
00602 discreteVarIndex = this->getSubsystem().allocateDiscreteVariable
00603 (s, invalidatedStage, new Value<T>(defaultValue));
00604 }
00605 private:
00606 const T& getVarValue(const State& s) const {
00607 assert(discreteVarIndex.isValid());
00608 return Value<T>::downcast(
00609 this->getSubsystem().getDiscreteVariable(s, discreteVarIndex));
00610 }
00611 T& updVarValue(State& s) const {
00612 assert(discreteVarIndex.isValid());
00613 return Value<T>::downcast(
00614 this->getSubsystem().updDiscreteVariable(s, discreteVarIndex));
00615 }
00616
00617
00618 Stage invalidatedStage;
00619 T defaultValue;
00620
00621
00622 mutable DiscreteVariableIndex discreteVarIndex;
00623 };
00624
00626
00628
00629 template <class T>
00630 class Measure_<T>::Sinusoid::Implementation
00631 : public Measure_<T>::Implementation
00632 {
00633 static const int NumDerivs = 3;
00634 public:
00635 Implementation()
00636 : Measure_<T>::Implementation(NumDerivs+1),
00637 a(CNT<T>::getNaN()), w(CNT<T>::getNaN()), p(CNT<T>::getNaN()) {}
00638
00639 Implementation(const T& amplitude,
00640 const T& frequency,
00641 const T& phase=T(0))
00642 : Measure_<T>::Implementation(NumDerivs+1),
00643 a(amplitude), w(frequency), p(phase) {}
00644
00645
00646
00647
00648 Implementation* cloneVirtual() const {return new Implementation(*this);}
00649
00650 int getNumTimeDerivativesVirtual() const {return NumDerivs;}
00651
00652 Stage getDependsOnStageVirtual(int order) const
00653 { return Stage::Time; }
00654
00655 void calcCachedValueVirtual(const State& s, int derivOrder, T& value) const {
00656
00657
00658 using std::sin; using std::cos;
00659
00660 assert(NumDerivs == 3);
00661 const Real t = s.getTime();
00662 const T arg = w*t + p;
00663
00664 switch (derivOrder) {
00665 case 0: value = a*sin(arg); break;
00666 case 1: value = w*a*cos(arg); break;
00667 case 2: value = -w*w*a*sin(arg); break;
00668 case 3: value = -w*w*w*a*cos(arg); break;
00669 default: SimTK_ASSERT1_ALWAYS(!"out of range",
00670 "Measure::Sinusoid::Implementation::calcCachedValueVirtual():"
00671 " derivOrder %d is out of range 0-3.", derivOrder);
00672 }
00673 }
00674
00675
00676
00677 private:
00678
00679 T a, w, p;
00680
00681
00682
00683 };
00684
00686
00688
00689 template <class T>
00690 class Measure_<T>::Plus::Implementation
00691 : public Measure_<T>::Implementation
00692 {
00693 public:
00694
00695
00696 Implementation() {}
00697
00698 Implementation(const Measure_<T>& left,
00699 const Measure_<T>& right)
00700 : left(left), right(right) {}
00701
00702
00703
00704
00705
00706
00707
00708 Implementation* cloneVirtual() const
00709 { return new Implementation(*this); }
00710
00711
00712
00713 int getNumTimeDerivativesVirtual() const {return 0;}
00714
00715
00716
00717 Stage getDependsOnStageVirtual(int order) const
00718 { return Stage(std::max(left.getDependsOnStage(order),
00719 right.getDependsOnStage(order))); }
00720
00721
00722 void calcCachedValueVirtual(const State& s, int derivOrder, T& value) const {
00723 value = left.getValue(s,derivOrder) + right.getValue(s,derivOrder);
00724 }
00725
00726
00727
00728 private:
00729
00730 const Measure_<T> left;
00731 const Measure_<T> right;
00732
00733
00734
00735 };
00736
00738
00740
00741 template <class T>
00742 class Measure_<T>::Minus::Implementation
00743 : public Measure_<T>::Implementation
00744 {
00745 public:
00746
00747
00748 Implementation() {}
00749
00750 Implementation(const Measure_<T>& left,
00751 const Measure_<T>& right)
00752 : left(left), right(right) {}
00753
00754
00755
00756
00757
00758
00759
00760 Implementation* cloneVirtual() const
00761 { return new Implementation(*this); }
00762
00763
00764
00765 int getNumTimeDerivativesVirtual() const {return 0;}
00766
00767
00768
00769 Stage getDependsOnStageVirtual(int order) const
00770 { return Stage(std::max(left.getDependsOnStage(order),
00771 right.getDependsOnStage(order))); }
00772
00773
00774 void calcCachedValueVirtual(const State& s, int derivOrder, T& value) const {
00775 value = left.getValue(s,derivOrder) - right.getValue(s,derivOrder);
00776 }
00777
00778
00779
00780 private:
00781
00782 const Measure_<T> left;
00783 const Measure_<T> right;
00784
00785
00786
00787 };
00788
00789
00791
00793
00794 template <class T>
00795 class Measure_<T>::Scale::Implementation
00796 : public Measure_<T>::Implementation
00797 {
00798 public:
00799
00800
00801 Implementation() : factor(NaN) {}
00802
00803 Implementation(Real factor, const Measure_<T>& operand)
00804 : factor(factor), operand(operand) {}
00805
00806
00807
00808
00809 void setScaleFactor(Real sf) {
00810 factor = sf;
00811 this->invalidateTopologyCache();
00812 }
00813
00814
00815
00816
00817 Implementation* cloneVirtual() const
00818 { return new Implementation(*this); }
00819
00820
00821
00822 int getNumTimeDerivativesVirtual() const {return 0;}
00823
00824
00825
00826 Stage getDependsOnStageVirtual(int order) const
00827 { return operand.getDependsOnStage(order); }
00828
00829
00830 void calcCachedValueVirtual(const State& s, int derivOrder, T& value) const {
00831 value = factor * operand.getValue(s,derivOrder);
00832 }
00833
00834
00835
00836 private:
00837
00838 const Real factor;
00839 const Measure_<T> operand;
00840
00841
00842
00843 };
00844
00846
00848
00849 template <class T>
00850 class Measure_<T>::Integrate::Implementation
00851 : public Measure_<T>::Implementation {
00852 public:
00853
00854
00855
00856
00857
00858
00859 Implementation() : Measure_<T>::Implementation(0) {}
00860
00861
00862
00863 Implementation(const Measure_<T>& deriv, const Measure_<T>& ic)
00864 : Measure_<T>::Implementation(0),
00865 derivMeasure(deriv), icMeasure(ic) {}
00866
00867
00868
00869 Implementation(const Implementation& source)
00870 : Measure_<T>::Implementation(0),
00871 derivMeasure(source.derivMeasure), icMeasure(source.icMeasure) {}
00872
00873 void setValue(State& s, const T& value) const
00874 { assert(zIndex >= 0);
00875 this->getSubsystem().updZ(s)[zIndex] = value; }
00876
00877 const Measure_<T>& getDerivativeMeasure() const
00878 { SimTK_ERRCHK(!derivMeasure.isEmptyHandle(),
00879 "Measure_<T>::Integrate::getDerivativeMeasure()",
00880 "No derivative measure is available for this integrated measure.");
00881 return derivMeasure; }
00882
00883 const Measure_<T>& getInitialConditionMeasure() const
00884 { SimTK_ERRCHK(!icMeasure.isEmptyHandle(),
00885 "Measure_<T>::Integrate::getInitialConditionMeasure()",
00886 "No initial condition measure is available for this "
00887 "integrated measure.");
00888 return icMeasure; }
00889
00890 void setDerivativeMeasure(const Measure_<T>& d)
00891 { derivMeasure = d; this->invalidateTopologyCache(); }
00892 void setInitialConditionMeasure(const Measure_<T>& ic)
00893 { icMeasure = ic; this->invalidateTopologyCache(); }
00894
00895
00896
00897
00898 Implementation* cloneVirtual() const
00899 { return new Implementation(*this); }
00900
00901 int getNumTimeDerivativesVirtual() const {return 1;}
00902
00903
00904
00905 const T& getUncachedValueVirtual(const State& s, int derivOrder) const
00906 { if (derivOrder>0)
00907 return getDerivativeMeasure().getValue(s);
00908 else {
00909 assert(zIndex.isValid());
00910 return this->getSubsystem().getZ(s)[zIndex];
00911 }
00912 }
00913 Stage getDependsOnStageVirtual(int derivOrder) const
00914 { return derivOrder>0 ? getDerivativeMeasure().getDependsOnStage(0)
00915 : Stage::Time; }
00916
00917 void initializeVirtual(State& s) const {
00918 assert(zIndex.isValid());
00919 Real& z = this->getSubsystem().updZ(s)[zIndex];
00920 if (!icMeasure.isEmptyHandle())
00921 z = icMeasure.getValue(s);
00922 else z = 0;
00923 }
00924
00925 void realizeMeasureTopologyVirtual(State& s) const {
00926 static const Vector zero(1, Real(0));
00927 zIndex = this->getSubsystem().allocateZ(s, zero);
00928 }
00929
00930 void realizeMeasureAccelerationVirtual(const State& s) const {
00931 assert(zIndex.isValid());
00932 Real& zdot = this->getSubsystem().updZDot(s)[zIndex];
00933 if (!derivMeasure.isEmptyHandle())
00934 zdot = derivMeasure.getValue(s);
00935 else zdot = 0;
00936 }
00937
00938 private:
00939
00940 const Measure_<T> derivMeasure;
00941 const Measure_<T> icMeasure;
00942
00943
00944 mutable ZIndex zIndex;
00945 };
00946
00948
00950
00951
00952
00953
00954
00955
00956
00957
00958 template <class T>
00959 class Measure_Differentiate_Result {
00960 public:
00961 Measure_Differentiate_Result() : derivIsGood(false) {}
00962 T operand;
00963 T operandDot;
00964 bool derivIsGood;
00965 };
00966
00967
00968
00969 template <class T> inline std::ostream&
00970 operator<<(std::ostream& o,
00971 const Measure_Differentiate_Result<T>&)
00972 { assert(!"not implemented"); return o; }
00973
00974 template <class T>
00975 class Measure_<T>::Differentiate::Implementation
00976 : public Measure_<T>::Implementation
00977 {
00978 typedef Measure_Differentiate_Result<T> Result;
00979 public:
00980
00981 Implementation() : Measure_<T>::Implementation(0) {}
00982
00983 Implementation(const Measure_<T>& operand)
00984 : Measure_<T>::Implementation(0),
00985 operand(operand), forceUseApprox(false), isApproxInUse(false) {}
00986
00987
00988
00989
00990 void setForceUseApproximation(bool mustApproximate) {
00991 forceUseApprox = mustApproximate;
00992 this->invalidateTopologyCache();
00993 }
00994
00995 void setOperandMeasure(const Measure_<T>& operand) {
00996 this->operand = operand;
00997 this->invalidateTopologyCache();
00998 }
00999
01000 bool getForceUseApproximation() const {return forceUseApprox;}
01001 bool isUsingApproximation() const {return isApproxInUse;}
01002 const Measure_<T>& getOperandMeasure() const {return operand;}
01003
01004
01005
01006
01007 Implementation* cloneVirtual() const
01008 { return new Implementation(*this); }
01009
01010
01011 int getNumTimeDerivativesVirtual() const
01012 { if (!isApproxInUse) return operand.getNumTimeDerivatives()-1;
01013 else return 0; }
01014
01015 Stage getDependsOnStageVirtual(int order) const
01016 { if (!isApproxInUse) return operand.getDependsOnStage(order+1);
01017 else return operand.getDependsOnStage(order); }
01018
01019
01020
01021
01022
01023 const T& getUncachedValueVirtual(const State& s, int derivOrder) const
01024 { if (!isApproxInUse)
01025 return operand.getValue(s, derivOrder+1);
01026
01027 ensureDerivativeIsRealized(s);
01028 const Subsystem& subsys = this->getSubsystem();
01029 const Result& result = Value<Result>::downcast
01030 (subsys.getDiscreteVarUpdateValue(s,resultIx));
01031 return result.operandDot;
01032 }
01033
01034 void initializeVirtual(State& s) const {
01035 if (!isApproxInUse) return;
01036
01037 assert(resultIx.isValid());
01038 const Subsystem& subsys = this->getSubsystem();
01039 Result& result = Value<Result>::updDowncast
01040 (subsys.updDiscreteVariable(s,resultIx));
01041 result.operand = operand.getValue(s);
01042 result.operandDot = this->getValueZero();
01043 result.derivIsGood = false;
01044 }
01045
01046 void realizeMeasureTopologyVirtual(State& s) const {
01047 isApproxInUse = (forceUseApprox || operand.getNumTimeDerivatives()==0);
01048 if (!isApproxInUse)
01049 return;
01050
01051 resultIx = this->getSubsystem()
01052 .allocateAutoUpdateDiscreteVariable(s, operand.getDependsOnStage(0),
01053 new Value<Result>(), operand.getDependsOnStage(0));
01054 }
01055
01056 void ensureDerivativeIsRealized(const State& s) const {
01057 assert(resultIx.isValid());
01058 const Subsystem& subsys = this->getSubsystem();
01059 if (subsys.isDiscreteVarUpdateValueRealized(s,resultIx))
01060 return;
01061
01062 const Real t0 = subsys.getDiscreteVarLastUpdateTime(s,resultIx);
01063 const Result& prevResult = Value<Result>::downcast
01064 (subsys.getDiscreteVariable(s,resultIx));
01065 const T& f0 = prevResult.operand;
01066 const T& fdot0 = prevResult.operandDot;
01067 const bool good0 = prevResult.derivIsGood;
01068
01069 const Real t = s.getTime();
01070 Result& result = Value<Result>::updDowncast
01071 (subsys.updDiscreteVarUpdateValue(s,resultIx));
01072 T& f = result.operand;
01073 T& fdot = result.operandDot;
01074 bool& good = result.derivIsGood;
01075
01076 f = operand.getValue(s);
01077 good = false;
01078 if (!isFinite(t0))
01079 fdot = this->getValueZero();
01080 else if (t == t0) {
01081 fdot = fdot0;
01082 good = good0;
01083 } else {
01084 fdot = (f-f0)/(t-t0);
01085 if (good0)
01086 fdot = Real(2)*fdot - fdot0;
01087 good = true;
01088 }
01089 subsys.markDiscreteVarUpdateValueRealized(s,resultIx);
01090 }
01091 private:
01092
01093 Measure_<T> operand;
01094 bool forceUseApprox;
01095
01096
01097 mutable bool isApproxInUse;
01098 mutable DiscreteVariableIndex resultIx;
01099 };
01100
01101
01102 }
01103
01104
01105
01106
01107 #endif // SimTK_SimTKCOMMON_MEASURE_IMPLEMENTATION_H_