Simbody 3.9
Loading...
Searching...
No Matches
MeasureImplementation.h
Go to the documentation of this file.
1#ifndef SimTK_SimTKCOMMON_MEASURE_IMPLEMENTATION_H_
2#define SimTK_SimTKCOMMON_MEASURE_IMPLEMENTATION_H_
3
4/* -------------------------------------------------------------------------- *
5 * Simbody(tm): SimTKcommon *
6 * -------------------------------------------------------------------------- *
7 * This is part of the SimTK biosimulation toolkit originating from *
8 * Simbios, the NIH National Center for Physics-Based Simulation of *
9 * Biological Structures at Stanford, funded under the NIH Roadmap for *
10 * Medical Research, grant U54 GM072970. See https://simtk.org/home/simbody. *
11 * *
12 * Portions copyright (c) 2008-14 Stanford University and the Authors. *
13 * Authors: Michael Sherman *
14 * Contributors: *
15 * *
16 * Licensed under the Apache License, Version 2.0 (the "License"); you may *
17 * not use this file except in compliance with the License. You may obtain a *
18 * copy of the License at http://www.apache.org/licenses/LICENSE-2.0. *
19 * *
20 * Unless required by applicable law or agreed to in writing, software *
21 * distributed under the License is distributed on an "AS IS" BASIS, *
22 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. *
23 * See the License for the specific language governing permissions and *
24 * limitations under the License. *
25 * -------------------------------------------------------------------------- */
26
27#include "SimTKcommon/basics.h"
34
35#include <cmath>
36
37
38namespace SimTK {
39
40
41//==============================================================================
42// ABSTRACT MEASURE :: IMPLEMENTATION
43//==============================================================================
44
49protected:
52 Implementation() : copyNumber(0), mySubsystem(0), refCount(0) {}
53
58 : copyNumber(src.copyNumber+1), mySubsystem(0), refCount(0) {}
59
64 if (&src != this)
65 { copyNumber=src.copyNumber+1;
66 refCount=0; mySubsystem=0; }
67 return *this;
68 }
69
70 // destructor is virtual; below
71
72 // Increment the reference count and return its new value.
73 int incrRefCount() const {return ++refCount;}
74
75 // Decrement the reference count and return its new value.
76 int decrRefCount() const {return --refCount;}
77
78 // Get the current value of the reference counter.
79 int getRefCount() const {return refCount;}
80
81 int getCopyNumber() const {return copyNumber;}
82
86 Implementation* clone() const {return cloneVirtual();}
87
88 // realizeTopology() is pure virtual below for Measure_<T> to supply.
89 void realizeModel (State& s) const {realizeMeasureModelVirtual(s);}
90 void realizeInstance (const State& s) const {realizeMeasureInstanceVirtual(s);}
91 void realizeTime (const State& s) const {realizeMeasureTimeVirtual(s);}
92 void realizePosition (const State& s) const {realizeMeasurePositionVirtual(s);}
93 void realizeVelocity (const State& s) const {realizeMeasureVelocityVirtual(s);}
94 void realizeDynamics (const State& s) const {realizeMeasureDynamicsVirtual(s);}
95 void realizeAcceleration(const State& s) const {realizeMeasureAccelerationVirtual(s);}
96 void realizeReport (const State& s) const {realizeMeasureReportVirtual(s);}
97
101 void initialize(State& s) const {initializeVirtual(s);}
102
103 int getNumTimeDerivatives() const {return getNumTimeDerivativesVirtual();}
104
105 Stage getDependsOnStage(int derivOrder) const {
106 SimTK_ERRCHK2(0 <= derivOrder && derivOrder <= getNumTimeDerivatives(),
107 "Measure::getDependsOnStage()",
108 "derivOrder %d was out of range; this Measure allows 0-%d.",
109 derivOrder, getNumTimeDerivatives());
110 return getDependsOnStageVirtual(derivOrder);
111 }
112
113
114 void setSubsystem(Subsystem& sub, MeasureIndex mx)
115 { assert(!mySubsystem && mx.isValid());
116 mySubsystem = &sub; myIndex = mx; }
117
118 bool isInSubsystem() const {return mySubsystem != 0;}
119 const Subsystem& getSubsystem() const {assert(mySubsystem); return *mySubsystem;}
120 Subsystem& updSubsystem() {assert(mySubsystem); return *mySubsystem;}
121 MeasureIndex getSubsystemMeasureIndex() const {assert(mySubsystem); return myIndex;}
123 { return getSubsystem().getMySubsystemIndex(); }
124
126 { if (isInSubsystem()) getSubsystem().invalidateSubsystemTopologyCache(); }
127
128 Stage getStage(const State& s) const {return getSubsystem().getStage(s);}
129
130 // VIRTUALS //
131
132 virtual ~Implementation() {}
133 virtual Implementation* cloneVirtual() const = 0;
134
135 virtual void realizeTopology(State&)const = 0;
136
137 virtual void realizeMeasureModelVirtual(State&) const {}
138 virtual void realizeMeasureInstanceVirtual(const State&) const {}
139 virtual void realizeMeasureTimeVirtual(const State&) const {}
140 virtual void realizeMeasurePositionVirtual(const State&) const {}
141 virtual void realizeMeasureVelocityVirtual(const State&) const {}
142 virtual void realizeMeasureDynamicsVirtual(const State&) const {}
143 virtual void realizeMeasureAccelerationVirtual(const State&) const {}
144 virtual void realizeMeasureReportVirtual(const State&) const {}
145
146 virtual void initializeVirtual(State&) const {}
147 virtual int getNumTimeDerivativesVirtual() const {return 0;}
148 virtual Stage getDependsOnStageVirtual(int order) const = 0;
149
150private:
151 int copyNumber; // bumped each time we do a deep copy
152
153 // These are set when this Measure is adopted by a Subsystem.
154 Subsystem* mySubsystem;
155 MeasureIndex myIndex;
156
157 // Measures have shallow copy semantics so they share the Implementation
158 // objects, which are only deleted when the refCount goes to zero.
159 mutable int refCount;
160
161friend class AbstractMeasure;
162friend class Subsystem::Guts;
163};
164
165//==============================================================================
166// ABSTRACT MEASURE DEFINITIONS
167//==============================================================================
168// These had to wait for AbstractMeasure::Implementation to be defined.
169
172: impl(g)
173{ if (impl) impl->incrRefCount(); }
174
177: impl(g) {
178 SimTK_ERRCHK(hasImpl(), "AbstractMeasure::AbstractMeasure()",
179 "An empty Measure handle can't be put in a Subsystem.");
180 impl->incrRefCount();
181 sub.adoptMeasure(*this);
182}
183
184// Shallow copy constructor.
186: impl(0) {
187 if (src.impl) {
188 impl = src.impl;
189 impl->incrRefCount();
190 }
191}
192
193// Shallow assignment.
195shallowAssign(const AbstractMeasure& src) {
196 if (impl != src.impl) {
197 if (impl && impl->decrRefCount()==0) delete impl;
198 impl = src.impl;
199 impl->incrRefCount();
200 }
201 return *this;
202}
203
204// Note that even if the source and destination are currently pointing
205// to the same Implementation, we still have to make a new copy so that
206// afterwards the destination has its own, refcount==1 copy.
208deepAssign(const AbstractMeasure& src) {
209 if (&src != this) {
210 if (impl && impl->decrRefCount()==0) delete impl;
211 if (src.impl) {
212 impl = src.impl->clone();
213 impl->incrRefCount();
214 } else
215 impl = 0;
216 }
217 return *this;
218}
219
222{ if (impl && impl->decrRefCount()==0) delete impl;}
223
225isInSubsystem() const
226{ return hasImpl() && getImpl().isInSubsystem(); }
227
229getSubsystem() const
230{ return getImpl().getSubsystem(); }
231
233isSameSubsystem(const Subsystem& other) const
234{ return getSubsystem().isSameSubsystem(other); }
235
236inline MeasureIndex AbstractMeasure::
239
243
245getDependsOnStage(int derivOrder) const
246{ return getImpl().getDependsOnStage(derivOrder); }
247
249getRefCount() const
250{ return getImpl().getRefCount(); }
251
252
// Hide from Doxygen.
254// This is a helper class that makes it possible to treat Real, Vec, and
255// Vector objects uniformly.
256template <class T> class Measure_Num {
257};
258
259template <> class Measure_Num<float> {
260public:
261 typedef float Element;
262 static int size(const float&) {return 1;}
263 static const float& get(const float& v, int i) {assert(i==0); return v;}
264 static float& upd(float& v, int i) {assert(i==0); return v;}
265 static void makeNaNLike(const float&, float& nanValue)
266 { nanValue = CNT<float>::getNaN();}
267 static void makeZeroLike(const float&, float& zeroValue) {zeroValue=0.f;}
268};
269
270template <> class Measure_Num<double> {
271public:
272 typedef double Element;
273 static int size(const double&) {return 1;}
274 static const double& get(const double& v, int i) {assert(i==0); return v;}
275 static double& upd(double& v, int i) {assert(i==0); return v;}
276 static void makeNaNLike(const double&, double& nanValue)
277 { nanValue = CNT<double>::getNaN(); }
278 static void makeZeroLike(const double&, double& zeroValue) {zeroValue=0.;}
279};
280
281// We only support stride 1 (densely packed) Vec types.
282template <int M, class E>
283class Measure_Num< Vec<M,E,1> > {
284 typedef Vec<M,E,1> T;
285public:
286 typedef E Element;
287 static int size(const T&) {return M;}
288 static const E& get(const T& v, int i) {return v[i];}
289 static E& upd(T& v, int i) {return v[i];}
290 static void makeNaNLike (const T&, T& nanValue) {nanValue.setToNaN();}
291 static void makeZeroLike(const T&, T& zeroValue) {zeroValue.setToZero();}
292};
293
294// We only support column major (densely packed) Mat types.
295template <int M, int N, class E>
296class Measure_Num< Mat<M,N,E> > {
297 typedef Mat<M,N,E> T;
298public:
299 typedef E Element;
300 static int size(const T&) {return N;} // number of columns
301 static const typename T::TCol& get(const T& m, int j) {return m.col(j);}
302 static typename T::TCol& upd(T& m, int j) {return m.col(j);}
303 static void makeNaNLike (const T&, T& nanValue) {nanValue.setToNaN();}
304 static void makeZeroLike(const T&, T& zeroValue) {zeroValue.setToZero();}
305};
306
307
308template <class E>
309class Measure_Num< Vector_<E> > {
310 typedef Vector_<E> T;
311public:
312 typedef E Element;
313 static int size(const T& v) {return v.size();}
314 static const E& get(const T& v, int i) {return v[i];}
315 static E& upd(T& v, int i) {return v[i];}
316 static void makeNaNLike(const T& v, T& nanValue)
317 { nanValue.resize(v.size()); nanValue.setToNaN(); }
318 static void makeZeroLike(const T& v, T& zeroValue)
319 { zeroValue.resize(v.size()); zeroValue.setToZero(); }
320};
321
322
323template <class E>
324class Measure_Num< Rotation_<E> > {
325 typedef Rotation_<E> T;
326public:
327 typedef T Element;
328 static int size(const T&) {return 1;}
329 static const T& get(const T& v, int i) {assert(i==0); return v;}
330 static T& upd(T& v, int i) {assert(i==0); return v;}
331 static void makeNaNLike(const T&, T& nanValue)
332 { nanValue.setRotationToNaN(); }
333 static void makeZeroLike(const T&, T& zeroValue)
334 { zeroValue.setRotationToIdentityMatrix(); }
335};
336
337template <class E>
338class Measure_Num< Transform_<E> > {
339 typedef Transform_<E> T;
340public:
341 typedef T Element;
342 static int size(const T&) {return 1;}
343 static const T& get(const T& v, int i) {assert(i==0); return v;}
344 static T& upd(T& v, int i) {assert(i==0); return v;}
345 static void makeNaNLike(const T&, T& nanValue)
346 { nanValue.setToNaN(); }
347 static void makeZeroLike(const T&, T& zeroValue)
348 { zeroValue.setToZero(); }
349};
350
353//==============================================================================
354// MEASURE_<T> :: IMPLEMENTATION
355//==============================================================================
362template <class T>
364public:
365 const T& getValue(const State& s, int derivOrder) const {
366 SimTK_ERRCHK2(0 <= derivOrder && derivOrder <= getNumTimeDerivatives(),
367 "Measure_<T>::getValue()",
368 "derivOrder %d was out of range; this Measure allows 0-%d.",
369 derivOrder, getNumTimeDerivatives());
370
371 // We require the stage to have been advanced to at least the one
372 // before this measure's depends-on stage since this will get called
373 // towards the end of the depends-on stage realization.
374 if (getDependsOnStage(derivOrder) != Stage::Empty) {
375#ifndef NDEBUG
376 Stage prevStage = getDependsOnStage(derivOrder).prev();
377#endif
378
380 ( ( isInSubsystem() && getStage(s)>=prevStage)
381 || (!isInSubsystem() && s.getSystemStage()>=prevStage),
382 "Measure_<T>::getValue()",
383 "Expected State to have been realized to at least stage "
384 "%s but stage was %s.",
385 prevStage.getName().c_str(),
386 (isInSubsystem() ? getStage(s) : s.getSystemStage())
387 .getName().c_str());
388 }
389
390 if (derivOrder < getNumCacheEntries()) {
391 if (!isCacheValueRealized(s,derivOrder)) {
392 T& value = updCacheEntry(s,derivOrder);
393 calcCachedValueVirtual(s, derivOrder, value);
394 markCacheValueRealized(s,derivOrder);
395 return value;
396 }
397 return getCacheEntry(s,derivOrder);
398 }
399
400 // We can't handle it here -- punt to the concrete Measure
401 // for higher order derivatives.
402 return getUncachedValueVirtual(s,derivOrder);
403 }
404
407 void setDefaultValue(const T& defaultValue) {
408 this->defaultValue = defaultValue;
409 Measure_Num<T>::makeZeroLike(defaultValue, zeroValue);
410 this->invalidateTopologyCache();
411 }
412
416 const T& getDefaultValue() const {return defaultValue;}
417
419 { presumeValidAtDependsOnStage = presume;
420 this->invalidateTopologyCache(); }
421
423 { return presumeValidAtDependsOnStage; }
424
425protected:
426 explicit Implementation(const T& defaultValue, int numCacheEntries=1)
427 : presumeValidAtDependsOnStage(false),
428 defaultValue(defaultValue),
429 derivIx(numCacheEntries)
430 {
431 Measure_Num<T>::makeZeroLike(defaultValue, zeroValue);
432 }
433
437 explicit Implementation(int numCacheEntries=1)
438 : presumeValidAtDependsOnStage(false),
439 defaultValue(),
440 derivIx(numCacheEntries)
441 {
442 Measure_Num<T>::makeZeroLike(defaultValue, zeroValue);
443 }
444
449 : presumeValidAtDependsOnStage(source.presumeValidAtDependsOnStage),
450 defaultValue(source.defaultValue),
451 derivIx(source.derivIx.size())
452 {
453 Measure_Num<T>::makeZeroLike(defaultValue, zeroValue);
454 }
455
456
459 int size() const {return Measure_Num<T>::size(defaultValue);}
460
463 int getNumCacheEntries() const {return (int)derivIx.size();}
464
468 const T& getCacheEntry(const State& s, int derivOrder) const {
469 SimTK_ERRCHK2(0 <= derivOrder && derivOrder < getNumCacheEntries(),
470 "Measure_<T>::Implementation::getCacheEntry()",
471 "Derivative order %d is out of range; only %d cache entries"
472 " were allocated.", derivOrder, getNumCacheEntries());
473
474 return Value<T>::downcast(
475 this->getSubsystem().getCacheEntry(s, derivIx[derivOrder]));
476 }
477
481 T& updCacheEntry(const State& s, int derivOrder) const {
482 SimTK_ERRCHK2(0 <= derivOrder && derivOrder < getNumCacheEntries(),
483 "Measure_<T>::Implementation::updCacheEntry()",
484 "Derivative order %d is out of range; only %d cache entries"
485 " were allocated.", derivOrder, getNumCacheEntries());
486
488 this->getSubsystem().updCacheEntry(s, derivIx[derivOrder]));
489 }
490
493 bool isCacheValueRealized(const State& s, int derivOrder) const {
494 SimTK_ERRCHK2(0 <= derivOrder && derivOrder < getNumCacheEntries(),
495 "Measure_<T>::Implementation::isCacheValueRealized()",
496 "Derivative order %d is out of range; only %d cache entries"
497 " were allocated.", derivOrder, getNumCacheEntries());
498
499 return this->getSubsystem().isCacheValueRealized(s, derivIx[derivOrder]);
500 }
501
505 void markCacheValueRealized(const State& s, int derivOrder) const {
506 SimTK_ERRCHK2(0 <= derivOrder && derivOrder < getNumCacheEntries(),
507 "Measure_<T>::Implementation::markCacheValueRealized()",
508 "Derivative order %d is out of range; only %d cache entries"
509 " were allocated.", derivOrder, getNumCacheEntries());
510
511 this->getSubsystem().markCacheValueRealized(s, derivIx[derivOrder]);
512 }
513
518 void markCacheValueNotRealized(const State& s, int derivOrder) const {
519 SimTK_ERRCHK2(0 <= derivOrder && derivOrder < getNumCacheEntries(),
520 "Measure_<T>::Implementation::markCacheValueNotRealized()",
521 "Derivative order %d is out of range; only %d cache entries"
522 " were allocated.", derivOrder, getNumCacheEntries());
523
524 this->getSubsystem().markCacheValueNotRealized(s, derivIx[derivOrder]);
525 }
526
527 // VIRTUALS //
528
531 virtual void realizeMeasureTopologyVirtual(State&) const {}
532
535 virtual void
536 calcCachedValueVirtual(const State&, int derivOrder, T& value) const
537 { SimTK_ERRCHK1_ALWAYS(!"implemented",
538 "Measure_<T>::Implementation::calcCachedValueVirtual()",
539 "This method should have been overridden by the derived"
540 " Measure but was not. It is needed to calculate the"
541 " cached value for derivOrder=%d.", derivOrder); }
542
548 virtual const T&
549 getUncachedValueVirtual(const State&, int derivOrder) const
550 { SimTK_ERRCHK1_ALWAYS(!"implemented",
551 "Measure_<T>::Implementation::getUncachedValueVirtual()",
552 "This method should have been overridden by the derived"
553 " Measure but was not. It is needed to return the uncached"
554 " value at derivOrder=%d.", derivOrder);
555 return *reinterpret_cast<T*>(0);
556 }
557
560 const T& getValueZero() const {return zeroValue;}
561
562private:
563 // Satisfy the realizeTopology() pure virtual here now that we know the
564 // data type T. Allocate lazy- or auto-validated- cache entries depending
565 // on the setting of presumeValidAtDependsOnStage.
566 void realizeTopology(State& s) const override final {
567 // Allocate cache entries. Initialize the value cache entry to
568 // the given defaultValue; all the derivative cache entries should be
569 // initialized to a NaN of the same size.
570 if (getNumCacheEntries()) {
571 derivIx[0] = presumeValidAtDependsOnStage
573 (s, getDependsOnStage(0), new Value<T>(defaultValue))
575 (s, getDependsOnStage(0), new Value<T>(defaultValue));
576
577 if (getNumCacheEntries() > 1) {
578 T nanValue; Measure_Num<T>::makeNaNLike(defaultValue, nanValue);
579 for (int i=1; i < getNumCacheEntries(); ++i) {
580 derivIx[i] = presumeValidAtDependsOnStage
582 (s, getDependsOnStage(i), new Value<T>(nanValue))
584 (s, getDependsOnStage(i), new Value<T>(nanValue));
585 }
586 }
587 }
588
589 // Call the concrete class virtual if any.
590 realizeMeasureTopologyVirtual(s);
591 }
592
593//------------------------------------------------------------------------------
594private:
595 // TOPOLOGY STATE
596 bool presumeValidAtDependsOnStage;
597 T defaultValue;
598 T zeroValue;
599
600 // TOPOLOGY CACHE
601 mutable Array_<CacheEntryIndex> derivIx;
602};
603
604
605
606//==============================================================================
607// CONSTANT :: IMPLEMENTATION
608//==============================================================================
609template <class T>
611: public Measure_<T>::Implementation
612{
613public:
614 // We don't want the base class to allocate *any* cache entries.
616 explicit Implementation(const T& value)
617 : Measure_<T>::Implementation(value,0) {}
618
621 void setValue(const T& v) {this->setDefaultValue(v);}
622
623 // Implementations of virtual methods.
624 // Measure_<T> virtuals:
625 // No cached values.
626
627 const T& getUncachedValueVirtual(const State&, int derivOrder) const
628 override
629 { return derivOrder>0 ? this->getValueZero() : this->getDefaultValue(); }
630
631 // AbstractMeasure virtuals:
632 Implementation* cloneVirtual() const override
633 { return new Implementation(*this); }
634 Stage getDependsOnStageVirtual(int derivOrder) const override
635 { return derivOrder>0 ? Stage::Empty : Stage::Topology; }
636 int getNumTimeDerivativesVirtual() const override
637 { return std::numeric_limits<int>::max(); }
638};
639
640
641
642//==============================================================================
643// MEASURE ZERO and ONE
644//==============================================================================
645// These had to wait for Constant::Implementation to be declared.
646
647template <class T> inline
649template <class T> inline
651
653: Constant(Vector(size, Real(0))) {}
655: Constant(sub, Vector(size, Real(0))) {}
656
657template <class T> inline
659template <class T> inline
661
663: Constant(Vector(size, Real(1))) {}
665: Constant(sub, Vector(size, Real(1))) {}
666
667
668
669//==============================================================================
670// TIME :: IMPLEMENTATION
671//==============================================================================
672template <class T>
674
// Hide from Doxygen.
676template <>
678: public Measure_<Real>::Implementation
679{
680public:
681 // We don't want the base class to allocate *any* cache entries.
683
684 // Implementations of virtual methods.
685 // Measure_<Real> virtuals:
686 // No cached values.
687
688 const Real& getUncachedValueVirtual(const State& s, int derivOrder) const
689 override
690 { return derivOrder==0 ? s.getTime()
691 : (derivOrder==1 ? SimTK::One
692 : SimTK::Zero); }
693
694 // AbstractMeasure virtuals:
695 Implementation* cloneVirtual() const override
696 { return new Implementation(*this); }
697 Stage getDependsOnStageVirtual(int derivOrder) const override
698 { return derivOrder>0 ? Stage::Empty : Stage::Time; }
699
700 // Value is t, 1st derivative is 1, the rest are 0.
701 int getNumTimeDerivativesVirtual() const override
702 { return std::numeric_limits<int>::max(); }
703};
708//==============================================================================
709// VARIABLE :: IMPLEMENTATION
710//==============================================================================
711template <class T>
713: public Measure_<T>::Implementation
714{
715public:
716 // We don't want the base class to allocate *any* cache entries;
717 // we'll use the variable as its own value and zeroes for all
718 // the derivatives.
720 : Measure_<T>::Implementation(0),
721 invalidatedStage(Stage::Empty) {}
722
723 Implementation(Stage invalidated, const T& defaultValue)
724 : Measure_<T>::Implementation(defaultValue, 0),
725 invalidatedStage(invalidated) {}
726
727 // Copy constructor should not copy the variable.
729 : Measure_<T>::Implementation(source.getDefaultValue(), 0),
730 invalidatedStage(source.invalidatedStage) {}
731
732 void setInvalidatedStage(Stage invalidates) {
733 invalidatedStage = invalidates;
734 this->invalidateTopologyCache();
735 }
736
737 Stage getInvalidatedStage() const {return invalidatedStage;}
738
742 void setValue(State& state, const T& value) const
743 { updVarValue(state) = value; }
744
745 // Implementations of virtual methods.
746 Implementation* cloneVirtual() const override
747 { return new Implementation(*this); }
748
749 int getNumTimeDerivativesVirtual() const override
750 { return std::numeric_limits<int>::max(); }
751
752 // Discrete variable is available after Model stage; but all its
753 // derivatives are zero so are always available.
754 Stage getDependsOnStageVirtual(int derivOrder) const override
755 { return derivOrder>0 ? Stage::Empty : Stage::Model;}
756
757 const T& getUncachedValueVirtual(const State& s, int derivOrder) const
758 override
759 { return derivOrder>0 ? this->getValueZero() : getVarValue(s); }
760
761 // No cached values.
762
763 void realizeMeasureTopologyVirtual(State& s) const override {
764 discreteVarIndex = this->getSubsystem().allocateDiscreteVariable
765 (s, invalidatedStage, new Value<T>(this->getDefaultValue()));
766 }
767private:
768 const T& getVarValue(const State& s) const {
769 assert(discreteVarIndex.isValid());
770 return Value<T>::downcast(
771 this->getSubsystem().getDiscreteVariable(s, discreteVarIndex));
772 }
773 T& updVarValue(State& s) const {
774 assert(discreteVarIndex.isValid());
775 return Value<T>::downcast(
776 this->getSubsystem().updDiscreteVariable(s, discreteVarIndex));
777 }
778
779 // TOPOLOGY STATE
780 Stage invalidatedStage; // TODO this shouldn't be needed
781
782 // TOPOLOGY CACHE
783 mutable DiscreteVariableIndex discreteVarIndex;
784};
785
786
787
788//==============================================================================
789// RESULT :: IMPLEMENTATION
790//==============================================================================
791template <class T>
793: public Measure_<T>::Implementation
794{
795public:
796 // We want the base class to allocate a single cache entry of type T.
798 : Measure_<T>::Implementation(1),
799 dependsOnStage(Stage::Topology), invalidatedStage(Stage::Infinity) {}
800
801 Implementation(Stage dependsOn, Stage invalidated)
802 : Measure_<T>::Implementation(1),
803 dependsOnStage(dependsOn==Stage::Empty ? Stage::Topology : dependsOn),
804 invalidatedStage(invalidated)
805 { SimTK_ERRCHK2_ALWAYS(invalidated > dependsOn,"Measure::Result::ctor()",
806 "Got invalidated stage %s and dependsOn stage %s which is illegal "
807 "because the invalidated stage must be later than dependsOn.",
808 invalidated.getName().c_str(), dependsOn.getName().c_str());
809 }
810
811 // Copy constructor will not copy the cache entry index.
813 : Measure_<T>::Implementation(source),
814 dependsOnStage(source.dependsOnStage),
815 invalidatedStage(source.invalidatedStage) {}
816
817 void setDependsOnStage(Stage dependsOn) {
818 if (dependsOn == Stage::Empty) dependsOn = Stage::Topology;
819 SimTK_ERRCHK2_ALWAYS(dependsOn < getInvalidatedStage(),
820 "Measure::Result::setDependsOnStage()",
821 "The provided dependsOn stage %s is illegal because it is not "
822 "less than the current invalidated stage %s. Change the "
823 "invalidated stage first with setInvalidatedStage().",
824 dependsOn.getName().c_str(),
825 getInvalidatedStage().getName().c_str());
826
827 dependsOnStage = dependsOn;
828 this->invalidateTopologyCache();
829 }
830
831 void setInvalidatedStage(Stage invalidated) {
832 SimTK_ERRCHK2_ALWAYS(invalidated > getDependsOnStage(),
833 "Measure::Result::setInvalidatedStage()",
834 "The provided invalidated stage %s is illegal because it is not "
835 "greater than the current dependsOn stage %s. Change the "
836 "dependsOn stage first with setDependsOnStage().",
837 invalidated.getName().c_str(),
838 getDependsOnStage().getName().c_str());
839
840 invalidatedStage = invalidated;
841 this->invalidateTopologyCache();
842 }
843
844
845 Stage getDependsOnStage() const {return dependsOnStage;}
846 Stage getInvalidatedStage() const {return invalidatedStage;}
847
848
849 void markAsValid(const State& state) const
850 { const Stage subsystemStage = this->getSubsystem().getStage(state);
851 SimTK_ERRCHK3_ALWAYS(subsystemStage >= getDependsOnStage().prev(),
852 "Measure::Result::markAsValid()",
853 "This Result Measure cannot be marked valid in a State where this "
854 "measure's Subsystem has been realized only to stage %s, because "
855 "its value was declared to depend on stage %s. To mark it valid, "
856 "we require that the State have been realized at least to the "
857 "previous stage (%s in this case); that is, you must at least be "
858 "*working on* the dependsOn stage in order to claim this result is "
859 "available.",
860 subsystemStage.getName().c_str(),
861 getDependsOnStage().getName().c_str(),
862 getDependsOnStage().prev().getName().c_str());
863 this->markCacheValueRealized(state, 0); }
864
865 bool isValid(const State& state) const
866 { return this->isCacheValueRealized(state, 0); }
867
868 void markAsNotValid(const State& state) const
869 { this->markCacheValueNotRealized(state, 0);
870 state.invalidateAllCacheAtOrAbove(invalidatedStage); }
871
872 T& updValue(const State& state) const
873 { markAsNotValid(state); return this->updCacheEntry(state, 0); }
874
875
876 // Implementations of virtual methods.
877 Implementation* cloneVirtual() const override
878 { return new Implementation(*this); }
879
880 int getNumTimeDerivativesVirtual() const override {return 0;}
881
884 Stage getDependsOnStageVirtual(int derivOrder) const override
885 { return derivOrder>0 ? Stage::Empty : dependsOnStage;}
886
887 void calcCachedValueVirtual(const State&, int derivOrder, T& value) const
888 override
889 { SimTK_ERRCHK_ALWAYS(!"calcCachedValueVirtual() implemented",
890 "Measure_<T>::Result::getValue()",
891 "Measure_<T>::Result::getValue() was called when the value was not "
892 "yet valid. For most Measure types, this would have initiated "
893 "computation of the value, but Result measures must have their values "
894 "calculated and set externally, and then marked valid."); }
895
896private:
897 // TOPOLOGY STATE
898 Stage dependsOnStage;
899 Stage invalidatedStage;
900};
901
902
903
904//==============================================================================
905// SINUSOID :: IMPLEMENTATION
906//==============================================================================
907template <class T>
909: public Measure_<T>::Implementation
910{
911 static const int NumDerivs = 3;
912public:
914 : Measure_<T>::Implementation(NumDerivs+1),
915 a(CNT<T>::getNaN()), w(CNT<T>::getNaN()), p(CNT<T>::getNaN()) {}
916
917 Implementation(const T& amplitude,
918 const T& frequency,
919 const T& phase=T(0))
920 : Measure_<T>::Implementation(NumDerivs+1),
921 a(amplitude), w(frequency), p(phase) {}
922
923 // Default copy constructor is fine.
924
925 // Implementations of virtual methods.
926 Implementation* cloneVirtual() const override
927 { return new Implementation(*this); }
928
929 int getNumTimeDerivativesVirtual() const override {return NumDerivs;}
930
931 Stage getDependsOnStageVirtual(int order) const override
932 { return Stage::Time; }
933
934 void calcCachedValueVirtual(const State& s, int derivOrder, T& value) const
935 override
936 {
937 // We need to allow the compiler to select std::sin or SimTK::sin
938 // based on the argument type.
939 using std::sin; using std::cos;
940
941 assert(NumDerivs == 3);
942 const Real t = s.getTime();
943 const T arg = w*t + p;
944
945 switch (derivOrder) {
946 case 0: value = a*sin(arg); break;
947 case 1: value = w*a*cos(arg); break;
948 case 2: value = -w*w*a*sin(arg); break;
949 case 3: value = -w*w*w*a*cos(arg); break;
950 default: SimTK_ASSERT1_ALWAYS(!"out of range",
951 "Measure::Sinusoid::Implementation::calcCachedValueVirtual():"
952 " derivOrder %d is out of range 0-3.", derivOrder);
953 }
954 }
955
956 // There are no uncached values.
957
958private:
959 // TOPOLOGY STATE
960 T a, w, p;
961
962 // TOPOLOGY CACHE
963 // nothing
964};
965
966
967
968//==============================================================================
969// PLUS :: IMPLEMENTATION
970//==============================================================================
971template <class T>
972class Measure_<T>::Plus::Implementation : public Measure_<T>::Implementation {
973public:
974 // TODO: Currently allocates just one cache entry.
975 // left and right will be empty handles.
977
979 const Measure_<T>& right)
980 : left(left), right(right) {}
981
982 // Default copy constructor gives us a new Implementation object,
983 // but with references to the *same* operand measures.
984
985 // Implementations of virtual methods.
986
987 // This uses the default copy constructor.
988 Implementation* cloneVirtual() const override
989 { return new Implementation(*this); }
990
991 // TODO: Let this be settable up to the min number of derivatives
992 // provided by the arguments.
993 int getNumTimeDerivativesVirtual() const override {return 0;}
994 //{ return std::min(left.getNumTimeDerivatives(),
995 // right.getNumTimeDerivatives()); }
996
997 Stage getDependsOnStageVirtual(int order) const override
998 { return Stage(std::max(left.getDependsOnStage(order),
999 right.getDependsOnStage(order))); }
1000
1001
1002 void calcCachedValueVirtual(const State& s, int derivOrder, T& value) const
1003 override
1004 {
1005 value = left.getValue(s,derivOrder) + right.getValue(s,derivOrder);
1006 }
1007
1008 // There are no uncached values.
1009
1010private:
1011 // TOPOLOGY STATE
1012 Measure_<T> left;
1013 Measure_<T> right;
1014
1015 // TOPOLOGY CACHE
1016 // nothing
1017};
1018
1019
1020
1021//==============================================================================
1022// MINUS :: IMPLEMENTATION
1023//==============================================================================
1024template <class T>
1025class Measure_<T>::Minus::Implementation : public Measure_<T>::Implementation {
1026public:
1027 // TODO: Currently allocates just one cache entry.
1028 // left and right will be empty handles.
1030
1032 const Measure_<T>& right)
1033 : left(left), right(right) {}
1034
1035 // Default copy constructor gives us a new Implementation object,
1036 // but with references to the *same* operand measures.
1037
1038 // Implementations of virtual methods.
1039
1040 // This uses the default copy constructor.
1041 Implementation* cloneVirtual() const override
1042 { return new Implementation(*this); }
1043
1044 // TODO: Let this be settable up to the min number of derivatives
1045 // provided by the arguments.
1046 int getNumTimeDerivativesVirtual() const override {return 0;}
1047 //{ return std::min(left.getNumTimeDerivatives(),
1048 // right.getNumTimeDerivatives()); }
1049
1050 Stage getDependsOnStageVirtual(int order) const override
1051 { return Stage(std::max(left.getDependsOnStage(order),
1052 right.getDependsOnStage(order))); }
1053
1054
1055 void calcCachedValueVirtual(const State& s, int derivOrder, T& value) const
1056 override
1057 {
1058 value = left.getValue(s,derivOrder) - right.getValue(s,derivOrder);
1059 }
1060
1061 // There are no uncached values.
1062
1063private:
1064 // TOPOLOGY STATE
1065 Measure_<T> left;
1066 Measure_<T> right;
1067
1068 // TOPOLOGY CACHE
1069 // nothing
1070};
1071
1072
1073
1074//==============================================================================
1075// SCALE :: IMPLEMENTATION
1076//==============================================================================
1077template <class T>
1079: public Measure_<T>::Implementation
1080{
1081public:
1082 // TODO: Currently allocates just one cache entry.
1083 // scale will be uninitialized, operand will be empty handle.
1084 Implementation() : factor(NaN) {}
1085
1086 Implementation(Real factor, const Measure_<T>& operand)
1087 : factor(factor), operand(operand) {}
1088
1089 // Default copy constructor gives us a new Implementation object,
1090 // but with references to the *same* operand measure.
1091
1093 factor = sf;
1094 this->invalidateTopologyCache();
1095 }
1096
1098 {
1099 return operand;
1100 }
1101
1102 // Implementations of virtual methods.
1103
1104 // This uses the default copy constructor.
1105 Implementation* cloneVirtual() const override
1106 { return new Implementation(*this); }
1107
1108 // TODO: Let this be settable up to the min number of derivatives
1109 // provided by the arguments.
1110 int getNumTimeDerivativesVirtual() const override {return 0;}
1111 //{ return std::min(left.getNumTimeDerivatives(),
1112 // right.getNumTimeDerivatives()); }
1113
1114 Stage getDependsOnStageVirtual(int order) const override
1115 { return operand.getDependsOnStage(order); }
1116
1117
1118 void calcCachedValueVirtual(const State& s, int derivOrder, T& value) const
1119 override
1120 {
1121 value = factor * operand.getValue(s,derivOrder);
1122 }
1123
1124 // There are no uncached values.
1125
1126private:
1127 // TOPOLOGY STATE
1128 Real factor;
1129 Measure_<T> operand;
1130
1131 // TOPOLOGY CACHE
1132 // nothing
1133};
1134
1135
1136
1137//==============================================================================
1138// INTEGRATE :: IMPLEMENTATION
1139//==============================================================================
1146template <class T>
1148: public Measure_<T>::Implementation {
1149public:
1153
1156 Implementation(const Measure_<T>& deriv, const Measure_<T>& ic,
1157 const T& defaultValue)
1158 : Measure_<T>::Implementation(defaultValue, 1),
1159 derivMeasure(deriv), icMeasure(ic) {}
1160
1164 : Measure_<T>::Implementation(source.getDefaultValue(), 1),
1165 derivMeasure(source.derivMeasure), icMeasure(source.icMeasure) {}
1166
1170 void setValue(State& s, const T& value) const
1171 { assert(zIndex >= 0);
1172 for (int i=0; i < this->size(); ++i)
1173 this->getSubsystem().updZ(s)[zIndex+i] =
1174 Measure_Num<T>::get(value, i); }
1175
1177 { SimTK_ERRCHK(!derivMeasure.isEmptyHandle(),
1178 "Measure_<T>::Integrate::getDerivativeMeasure()",
1179 "No derivative measure is available for this integrated measure.");
1180 return derivMeasure; }
1181
1183 { SimTK_ERRCHK(!icMeasure.isEmptyHandle(),
1184 "Measure_<T>::Integrate::getInitialConditionMeasure()",
1185 "No initial condition measure is available for this "
1186 "integrated measure.");
1187 return icMeasure; }
1188
1190 { derivMeasure = d; this->invalidateTopologyCache(); }
1192 { icMeasure = ic; this->invalidateTopologyCache(); }
1193
1194 // Implementations of virtuals.
1195
1196 // This uses the copy constructor defined above.
1197 Implementation* cloneVirtual() const override
1198 { return new Implementation(*this); }
1199
1201 int getNumTimeDerivativesVirtual() const override
1202 { int integralDerivs = getDerivativeMeasure().getNumTimeDerivatives();
1203 // Careful - can't add 1 to max int and stay an int.
1204 if (integralDerivs < std::numeric_limits<int>::max())
1205 ++integralDerivs;
1206 return integralDerivs; }
1207
1208 void calcCachedValueVirtual(const State& s, int derivOrder, T& value) const
1209 override
1210 { assert(derivOrder == 0); // only one cache entry
1211 assert(Measure_Num<T>::size(value) == this->size());
1212 assert(zIndex.isValid());
1213 const Vector& allZ = this->getSubsystem().getZ(s);
1214 for (int i=0; i < this->size(); ++i)
1215 Measure_Num<T>::upd(value,i) = allZ[zIndex+i];
1216 }
1217
1218 const T& getUncachedValueVirtual(const State& s, int derivOrder) const
1219 override
1220 { assert(derivOrder > 0); // 0th entry is cached
1221 return getDerivativeMeasure().getValue(s, derivOrder-1);
1222 }
1223
1224 Stage getDependsOnStageVirtual(int derivOrder) const override
1225 { return derivOrder>0
1226 ? getDerivativeMeasure().getDependsOnStage(derivOrder-1)
1227 : Stage::Time; }
1228
1231 void initializeVirtual(State& s) const override {
1232 assert(zIndex.isValid());
1233 Vector& allZ = this->getSubsystem().updZ(s);
1234 if (!icMeasure.isEmptyHandle()) {
1235 this->getSubsystem().getSystem()
1236 .realize(s, icMeasure.getDependsOnStage());
1237 const T& ic = icMeasure.getValue(s);
1238 for (int i=0; i < this->size(); ++i)
1239 allZ[zIndex+i] = Measure_Num<T>::get(ic,i);
1240 } else {
1241 for (int i=0; i < this->size(); ++i)
1242 allZ[zIndex+i] = Measure_Num<T>::get(this->getDefaultValue(),i);
1243 }
1244 }
1245
1250 void realizeMeasureTopologyVirtual(State& s) const override {
1251 Vector init(this->size());
1252 for (int i=0; i < this->size(); ++i)
1253 init[i] = Measure_Num<T>::get(this->getDefaultValue(),i);
1254 zIndex = this->getSubsystem().allocateZ(s, init);
1255 }
1256
1259 void realizeMeasureAccelerationVirtual(const State& s) const override {
1260 assert(zIndex.isValid());
1261 Vector& allZDot = this->getSubsystem().updZDot(s);
1262 if (!derivMeasure.isEmptyHandle()) {
1263 const T& deriv = derivMeasure.getValue(s);
1264 for (int i=0; i < this->size(); ++i)
1265 allZDot[zIndex+i] = Measure_Num<T>::get(deriv,i);
1266 } else {
1267 allZDot(zIndex,this->size()) = 0; // derivative is zero
1268 }
1269 }
1270
1271private:
1272 // TOPOLOGY STATE
1273 Measure_<T> derivMeasure; // just handles
1274 Measure_<T> icMeasure;
1275
1276 // TOPOLOGY CACHE
1277 mutable ZIndex zIndex; // This is the first index if more than one z.
1278};
1279
1280
1281
1282//==============================================================================
1283// DIFFERENTIATE :: IMPLEMENTATION
1284//==============================================================================
1285
// Hide from Doxygen.
1287// This helper class is the contents of the discrete state variable and
1288// corresponding cache entry maintained by this measure. The variable is
1289// auto-update, meaning the value of the cache entry replaces the state
1290// variable at the start of each step.
1291// TODO: This was a local class in Measure_<T>::Differentiate::Implementation
1292// but VC++ 8 (2005) failed to properly instantiate the templatized operator<<()
1293// in that case; doing it this way is a workaround.
1294template <class T>
1295class Measure_Differentiate_Result {
1296public:
1297 Measure_Differentiate_Result() : derivIsGood(false) {}
1298 T operand; // previous value of operand
1299 T operandDot; // previous value of derivative
1300 bool derivIsGood; // do we think the deriv is a good one?
1301};
1304template <class T>
1306: public Measure_<T>::Implementation
1307{
1308 typedef Measure_Differentiate_Result<T> Result;
1309public:
1310 // Don't allocate any cache entries in the base class.
1312
1314 : Measure_<T>::Implementation(0),
1315 operand(operand), forceUseApprox(false), isApproxInUse(false) {}
1316
1317 // Default copy constructor gives us a new Implementation object,
1318 // but with reference to the *same* operand measure.
1319
1320 void setForceUseApproximation(bool mustApproximate) {
1321 forceUseApprox = mustApproximate;
1322 this->invalidateTopologyCache();
1323 }
1324
1325 void setOperandMeasure(const Measure_<T>& operand) {
1326 this->operand = operand;
1327 this->invalidateTopologyCache();
1328 }
1329
1330 bool getForceUseApproximation() const {return forceUseApprox;}
1331 bool isUsingApproximation() const {return isApproxInUse;}
1332 const Measure_<T>& getOperandMeasure() const {return operand;}
1333
1334 // Implementations of virtual methods.
1335
1336 // This uses the default copy constructor.
1338 { return new Implementation(*this); }
1339
1340 // This has one fewer than the operand.
1341 int getNumTimeDerivativesVirtual() const override
1342 { if (!isApproxInUse) return operand.getNumTimeDerivatives()-1;
1343 else return 0; }
1344
1345 Stage getDependsOnStageVirtual(int order) const override
1346 { if (!isApproxInUse) return operand.getDependsOnStage(order+1);
1347 else return operand.getDependsOnStage(order); }
1348
1349
1350 // We're not using the Measure_<T> base class cache services, but
1351 // we do have one of our own. It looks uncached from the base class
1352 // point of view which is why we're implementing it here.
1353 const T& getUncachedValueVirtual(const State& s, int derivOrder) const
1354 override
1355 { if (!isApproxInUse)
1356 return operand.getValue(s, derivOrder+1);
1357
1358 ensureDerivativeIsRealized(s);
1359 const Subsystem& subsys = this->getSubsystem();
1360 const Result& result = Value<Result>::downcast
1361 (subsys.getDiscreteVarUpdateValue(s,resultIx));
1362 return result.operandDot; // has a value but might not be a good one
1363 }
1364
1365 void initializeVirtual(State& s) const override {
1366 if (!isApproxInUse) return;
1367
1368 assert(resultIx.isValid());
1369 const Subsystem& subsys = this->getSubsystem();
1370 Result& result = Value<Result>::updDowncast
1371 (subsys.updDiscreteVariable(s,resultIx));
1372 this->getSubsystem().getSystem().realize(s,operand.getDependsOnStage());
1373 result.operand = operand.getValue(s);
1374 result.operandDot = this->getValueZero();
1375 result.derivIsGood = false;
1376 }
1377
1378 void realizeMeasureTopologyVirtual(State& s) const override {
1379 isApproxInUse = (forceUseApprox || operand.getNumTimeDerivatives()==0);
1380 if (!isApproxInUse)
1381 return;
1382
1383 resultIx = this->getSubsystem()
1384 .allocateAutoUpdateDiscreteVariable(s, operand.getDependsOnStage(0),
1385 new Value<Result>(), operand.getDependsOnStage(0));
1386 }
1387
1390 void realizeMeasureAccelerationVirtual(const State& s) const override {
1391 ensureDerivativeIsRealized(s);
1392 }
1393
1394 void ensureDerivativeIsRealized(const State& s) const {
1395 assert(resultIx.isValid());
1396 const Subsystem& subsys = this->getSubsystem();
1397 if (subsys.isDiscreteVarUpdateValueRealized(s,resultIx))
1398 return;
1399
1400 const Real t0 = subsys.getDiscreteVarLastUpdateTime(s,resultIx);
1401 const Result& prevResult = Value<Result>::downcast
1402 (subsys.getDiscreteVariable(s,resultIx));
1403 const T& f0 = prevResult.operand;
1404 const T& fdot0 = prevResult.operandDot; // may be invalid
1405 const bool good0 = prevResult.derivIsGood;
1406
1407 const Real t = s.getTime();
1408 Result& result = Value<Result>::updDowncast
1409 (subsys.updDiscreteVarUpdateValue(s,resultIx));
1410 T& f = result.operand; // renaming
1411 T& fdot = result.operandDot;
1412 bool& good = result.derivIsGood;
1413
1414 f = operand.getValue(s);
1415 good = false;
1416 if (!isFinite(t0))
1417 fdot = this->getValueZero();
1418 else if (t == t0) {
1419 fdot = fdot0;
1420 good = good0;
1421 } else {
1422 fdot = (f-f0)/(t-t0); // 1st order
1423 if (good0)
1424 fdot = Real(2)*fdot - fdot0; // now 2nd order
1425 good = true; // either 1st or 2nd order estimate
1426 }
1427 subsys.markDiscreteVarUpdateValueRealized(s,resultIx);
1428 }
1429private:
1430 // TOPOLOGY STATE
1431 Measure_<T> operand;
1432 bool forceUseApprox;
1433
1434 // TOPOLOGY CACHE
1435 mutable bool isApproxInUse;
1436 mutable DiscreteVariableIndex resultIx; // auto-update
1437};
1438
1439
1440
1441//==============================================================================
1442// EXTREME :: IMPLEMENTATION
1443//==============================================================================
1444template <class T>
1445class Measure_<T>::Extreme::Implementation : public Measure_<T>::Implementation
1446{
1447 typedef typename Measure_<T>::Extreme Extreme;
1448 typedef typename Extreme::Operation Operation;
1449public:
1453 : Measure_<T>::Implementation(0), operation(Extreme::MaxAbs) {}
1454
1457 Implementation(const Measure_<T>& operand, Operation op)
1458 : Measure_<T>::Implementation(0), operand(operand), operation(op) {}
1459
1460 // Default copy constructor gives us a new Implementation object,
1461 // but with reference to the *same* operand measure.
1462
1466 void setOperandMeasure(const Measure_<T>& operand) {
1467 this->operand = operand;
1468 this->invalidateTopologyCache();
1469 }
1470
1474 void setOperation(Operation op) {
1475 this->operation = op;
1476 this->invalidateTopologyCache();
1477 }
1478
1480 const Measure_<T>& getOperandMeasure() const {return operand;}
1481
1484 Operation getOperation() const {return operation;}
1485
1488 void setValue(State& s, const T& value) const {
1489 assert(extremeIx.isValid());
1490 const Subsystem& subsys = this->getSubsystem();
1491 T& prevMin = Value<T>::updDowncast
1492 (subsys.updDiscreteVariable(s,extremeIx));
1493 prevMin = value;
1494 }
1495
1500 const Subsystem& subsys = this->getSubsystem();
1501 const bool hasNewExtreme = ensureExtremeHasBeenUpdated(s);
1502 Real tUpdate;
1503 if (hasNewExtreme)
1504 tUpdate = s.getTime(); // i.e., now
1505 else
1506 tUpdate = subsys.getDiscreteVarLastUpdateTime(s,extremeIx);
1507 return tUpdate;
1508 }
1509
1510 // Implementations of virtual methods.
1511
1512 // This uses the default copy constructor.
1513 Implementation* cloneVirtual() const override
1514 { return new Implementation(*this); }
1515
1518 int getNumTimeDerivativesVirtual() const override
1519 { return operand.getNumTimeDerivatives(); }
1520
1523 Stage getDependsOnStageVirtual(int order) const override
1524 { return operand.getDependsOnStage(order); }
1525
1526
1530 const T& getUncachedValueVirtual(const State& s, int derivOrder) const
1531 override
1532 {
1533 const Subsystem& subsys = this->getSubsystem();
1534 const bool hasNewExtreme = ensureExtremeHasBeenUpdated(s);
1535 if (derivOrder > 0) {
1536 // TODO: should be handled elementwise and zero unless the
1537 // derivative is acting in the direction that changes the
1538 // extreme.
1539 return hasNewExtreme ? operand.getValue(s, derivOrder)
1540 : this->getValueZero();
1541 }
1542 if (hasNewExtreme) {
1543 const T& newExt = Value<T>::downcast
1544 (subsys.getDiscreteVarUpdateValue(s,extremeIx));
1545 return newExt;
1546 } else {
1547 const T& currentExt = Value<T>::downcast
1548 (subsys.getDiscreteVariable(s,extremeIx));
1549 return currentExt;
1550 }
1551 }
1552
1555 void initializeVirtual(State& s) const override {
1556 this->getSubsystem().getSystem().realize(s,operand.getDependsOnStage());
1557 setValue(s, operand.getValue(s));
1558 }
1559
1567 void realizeMeasureTopologyVirtual(State& s) const override {
1568 // TODO: this should be NaN once initialization is working properly.
1569 T initVal = this->getDefaultValue();
1570 switch(operation) {
1571 case Minimum: initVal = Infinity; break;
1572 case Maximum: initVal = -Infinity; break;
1573 case MinAbs: initVal = Infinity; break;
1574 case MaxAbs: initVal = 0; break;
1575 };
1576
1577 extremeIx = this->getSubsystem()
1578 .allocateAutoUpdateDiscreteVariable(s, Stage::Dynamics,
1579 new Value<T>(initVal), operand.getDependsOnStage(0));
1580
1581 isNewExtremeIx = this->getSubsystem()
1582 .allocateAutoUpdateDiscreteVariable(s, Stage::Dynamics,
1583 new Value<bool>(false), operand.getDependsOnStage(0));
1584 }
1585
1588 void realizeMeasureAccelerationVirtual(const State& s) const override {
1589 ensureExtremeHasBeenUpdated(s);
1590 }
1591
1597 bool ensureExtremeHasBeenUpdated(const State& s) const {
1598 assert(extremeIx.isValid() && isNewExtremeIx.isValid());
1599 const Subsystem& subsys = this->getSubsystem();
1600
1601 // We may have already determined whether we're at a new extreme in
1602 // which case we don't need to do it again.
1603 if (subsys.isDiscreteVarUpdateValueRealized(s, isNewExtremeIx))
1605 (subsys.getDiscreteVarUpdateValue(s,isNewExtremeIx));
1606
1607 // We're going to have to decide if we're at a new extreme, and if
1608 // so record the new extreme value in the auto-update cache entry of
1609 // the extreme value state variable.
1610
1611 // Get the previous extreme value and the current operand value.
1612 const T& prevExtreme = Value<T>::downcast
1613 (subsys.getDiscreteVariable(s,extremeIx));
1614 const T& currentVal = operand.getValue(s);
1615
1616 // Search to see if any element has reached a new extreme.
1617 bool foundNewExt = false;
1618 for (int i=0; i < this->size() && !foundNewExt; ++i)
1619 foundNewExt = isNewExtreme(Measure_Num<T>::get(currentVal,i),
1620 Measure_Num<T>::get(prevExtreme,i));
1621
1622 // Record the result and mark the auto-update cache entry valid
1623 // so we won't have to recalculate. When the integrator advances to the
1624 // next step this cache entry will be swapped with the corresponding
1625 // state and marked invalid so we'll be sure to recalculate each step.
1627 (subsys.updDiscreteVarUpdateValue(s,isNewExtremeIx)) = foundNewExt;
1628 subsys.markDiscreteVarUpdateValueRealized(s,isNewExtremeIx);
1629
1630 // Don't update the auto-update cache entry if we didn't see a new
1631 // extreme. That way no auto-update will occur and the state variable
1632 // will remain unchanged with the existing update time preserved.
1633 if (!foundNewExt)
1634 return false;
1635
1636 // We have encountered a new extreme. We'll record the new extreme
1637 // in the auto-update cache entry which will be used as the current
1638 // result until the integrator advances to the next step at which time
1639 // this will be swapped with the state variable to serve as the previous
1640 // extreme value until a further extreme is encountered.
1641 T& newExtreme = Value<T>::updDowncast
1642 (subsys.updDiscreteVarUpdateValue(s,extremeIx));
1643
1644 for (int i=0; i < this->size(); ++i)
1645 Measure_Num<T>::upd(newExtreme,i) =
1646 extremeOf(Measure_Num<T>::get(currentVal,i),
1647 Measure_Num<T>::get(prevExtreme,i));
1648
1649 // Marking this valid is what ensures that an auto-update occurs later.
1650 subsys.markDiscreteVarUpdateValueRealized(s,extremeIx);
1651 return true;
1652 }
1653private:
1654 // Return true if newVal is "more extreme" than oldExtreme, according
1655 // to the operation we're performing.
1656 bool isNewExtreme(const typename Measure_Num<T>::Element& newVal,
1657 const typename Measure_Num<T>::Element& oldExtreme) const
1658 {
1659 switch (operation) {
1660 case Extreme::Maximum: return newVal > oldExtreme;
1661 case Extreme::Minimum: return newVal < oldExtreme;
1662 case Extreme::MaxAbs: return std::abs(newVal) > std::abs(oldExtreme);
1663 case Extreme::MinAbs: return std::abs(newVal) < std::abs(oldExtreme);
1664 };
1665 SimTK_ASSERT1_ALWAYS(!"recognized",
1666 "Measure::Extreme::Implementation::isNewExtreme(): "
1667 "unrecognized operation %d", (int)operation);
1668 return false; /*NOTREACHED*/
1669 }
1670
1671 // Given the value of one element of the operand, and that value's time
1672 // derivative, determine whether the derivative is moving the element
1673 // into the "more extreme" direction, according to the operation.
1674 bool isExtremeDir(const typename Measure_Num<T>::Element& value,
1675 const typename Measure_Num<T>::Element& deriv) const
1676 {
1677 const int sv = sign(value), sd = sign(deriv);
1678 if (sd == 0) return false; // derivative is zero; not changing
1679 switch (operation) {
1680 case Extreme::Maximum: return sd == 1; // getting larger
1681 case Extreme::Minimum: return sd == -1; // getting smaller
1682 case Extreme::MaxAbs: return sv==0 || sd==sv; // abs is growing
1683 case Extreme::MinAbs: return sd == -sv;
1684 };
1685 SimTK_ASSERT1_ALWAYS(!"recognized",
1686 "Measure::Extreme::Implementation::isExtremeDir(): "
1687 "unrecognized operation %d", (int)operation);
1688 return false; /*NOTREACHED*/
1689 }
1690
1691 typename Measure_Num<T>::Element
1692 extremeOf(const typename Measure_Num<T>::Element& newVal,
1693 const typename Measure_Num<T>::Element& oldExtreme) const
1694 {
1695 return isNewExtreme(newVal,oldExtreme) ? newVal : oldExtreme;
1696 }
1697
1698 // TOPOLOGY STATE
1699 Measure_<T> operand;
1700 Operation operation;
1701
1702 // TOPOLOGY CACHE
1703 mutable DiscreteVariableIndex extremeIx; // extreme so far; auto-update
1704
1705 // This auto-update flag records whether the current value is a new
1706 // extreme. We don't really need to save it as a state variable since you
1707 // can figure this out from the timestamp, but we need to to get invalidated
1708 // by the auto-update swap so that we'll figure it out anew each step.
1709 mutable DiscreteVariableIndex isNewExtremeIx;
1710};
1711
1712
1713
1714//==============================================================================
1715// DELAY :: IMPLEMENTATION
1716//==============================================================================
// Hide from Doxygen.
1718// This helper class is the contents of the discrete state variable and
1719// corresponding cache entry maintained by this measure. The variable is
1720// auto-update, meaning the value of the cache entry replaces the state
1721// variable at the start of each step.
1722//
1723// Circular buffers look like this:
1724//
1725// oldest=0, n=0
1726// v
1727// Empty buffer: | available |
1728//
1729// By convention, oldest=0 whenever the buffer is empty.
1730//
1731//
1732// oldest next=(oldest+n)%capacity
1733// v v
1734// | available | | | | | | | available |
1735// ^ n=6 ^
1736// 0 capacity
1737// v v
1738// or | | | | | | available | | | | | | | | n=12
1739// ^ ^
1740// next oldest
1741// = (oldest+n)%capacity
1742//
1743// Number of entries = n (called size() below)
1744// Empty = n==0
1745// Full = n==capacity()
1746// Next available = (oldest+n)%capacity()
1747template <class T>
1748class Measure_Delay_Buffer {
1749public:
1750 explicit Measure_Delay_Buffer() {initDataMembers();}
1751 void clear() {initDataMembers();}
1752 int size() const {return m_size;} // # saved entries, *not* size of arrays
1753 int capacity() const {return m_times.size();}
1754 bool empty() const {return size()==0;}
1755 bool full() const {return size()==capacity();}
1756
1757 double getEntryTime(int i) const
1758 { assert(i < size()); return m_times[getArrayIndex(i)];}
1759 const T& getEntryValue(int i) const
1760 { assert(i < size()); return m_values[getArrayIndex(i)];}
1761
1762 enum {
1763 InitialAllocation = 8, // smallest allocation
1764 GrowthFactor = 2, // how fast to grow (double)
1765 MaxShrinkProofSize = 16, // won't shrink unless bigger
1766 TooBigFactor = 5 // 5X too much->maybe shrink
1767 };
1768
1769 // Add a new entry to the end of the list, throwing out old entries that
1770 // aren't needed to answer requests at tEarliest or later.
1771 void append(double tEarliest, double tNow, const T& valueNow) {
1772 forgetEntriesMuchOlderThan(tEarliest);
1773 removeEntriesLaterOrEq(tNow);
1774 if (full())
1775 makeMoreRoom();
1776 else if (capacity() > std::max((int)MaxShrinkProofSize,
1777 (int)TooBigFactor * (size()+1)))
1778 makeLessRoom(); // less than 1/TooBigFactor full
1779 const int nextFree = getArrayIndex(m_size++);
1780 m_times[nextFree] = tNow;
1781 m_values[nextFree] = valueNow;
1782 m_maxSize = std::max(m_maxSize, size());
1783 }
1784
1785 // Prepend an older entry to the beginning of the list. No cleanup is done.
1786 void prepend(double tNewOldest, const T& value) {
1787 assert(empty() || tNewOldest < m_times[m_oldest]);
1788 if (full()) makeMoreRoom();
1789 m_oldest = empty() ? 0 : getArrayIndex(-1);
1790 m_times[m_oldest] = tNewOldest;
1791 m_values[m_oldest] = value;
1792 ++m_size;
1793 m_maxSize = std::max(m_maxSize, size());
1794 }
1795
1796 // This is a specialized copy assignment for copying an old buffer
1797 // to a new one with updated contents. We are told the earliest time we'll
1798 // be asked about from now on, and won't copy any entries older than those
1799 // needed to answer that earliest request. We won't copy anything at or
1800 // newer than tNow, and finally we'll push (tNow,valueNow) as the newest
1801 // entry.
1802 void copyInAndUpdate(const Measure_Delay_Buffer& oldBuf, double tEarliest,
1803 double tNow, const T& valueNow) {
1804 // clear all current entries (no heap activity)
1805 m_oldest = m_size = 0;
1806
1807 // determine how may old entries we have to keep
1808 int firstNeeded = oldBuf.countNumUnneededOldEntries(tEarliest);
1809 int lastNeeded = oldBuf.findLastEarlier(tNow); // might be -1
1810 int numOldEntriesToKeep = lastNeeded-firstNeeded+1;
1811 int newSize = numOldEntriesToKeep+1; // includes the new one
1812
1813 int newSizeRequest = -1;
1814 if (capacity() < newSize) {
1815 newSizeRequest = std::max((int)InitialAllocation,
1816 (int)GrowthFactor * newSize);
1817 ++m_nGrows;
1818 } else if (capacity() > std::max((int)MaxShrinkProofSize,
1819 (int)TooBigFactor * newSize)) {
1820 newSizeRequest = std::max((int)MaxShrinkProofSize,
1821 (int)GrowthFactor * newSize);
1822 ++m_nShrinks;
1823 }
1824
1825 // Reallocate space if advisable.
1826 if (newSizeRequest != -1) {
1827 const double dNaN = NTraits<double>::getNaN();
1828 m_values.resize(newSizeRequest);
1829 if (m_values.capacity() > m_values.size())
1830 m_values.resize(m_values.capacity()); // don't waste any
1831 m_times.resize(m_values.size(), dNaN);
1832 }
1833
1834 m_maxCapacity = std::max(m_maxCapacity, capacity());
1835
1836 // Copy the entries we need to keep.
1837 int nxt = 0;
1838 for (int i=firstNeeded; i<=lastNeeded; ++i, ++nxt) {
1839 m_times[nxt] = oldBuf.getEntryTime(i);
1840 m_values[nxt] = oldBuf.getEntryValue(i);
1841 }
1842 // Now add the newest entry and set the size.
1843 m_times[nxt] = tNow;
1844 m_values[nxt] = valueNow;
1845 assert(nxt+1==newSize);
1846 m_size = nxt+1;
1847 m_maxSize = std::max(m_maxSize, size());
1848 }
1849
1850 // Given the current time and value and the earlier time at which the
1851 // value is needed, use the buffer and (if necessary) the current value
1852 // to estimate the delayed value.
1853 T calcValueAtTime(double tDelay, double tNow, const T& valueNow) const;
1854
1855 // Given the current time but *not* the current value of the source measure,
1856 // provide an estimate for the value at tDelay=tNow-delay using only the
1857 // buffer contents and linear interpolation or extrapolation.
1858 void calcValueAtTimeLinearOnly(double tDelay, T& delayedValue) const {
1859 if (empty()) {
1860 // Nothing in the buffer?? Shouldn't happen. Return empty Vector
1861 // or NaN for fixed-size types.
1862 Measure_Num<T>::makeNaNLike(T(), delayedValue);
1863 return;
1864 }
1865
1866 int firstLater = findFirstLaterOrEq(tDelay);
1867
1868 if (firstLater > 0) {
1869 // Normal case: tDelay is between two buffer entries.
1870 int firstEarlier = firstLater-1;
1871 double t0=getEntryTime(firstEarlier), t1=getEntryTime(firstLater);
1872 const T& v0=getEntryValue(firstEarlier);
1873 const T& v1=getEntryValue(firstLater);
1874 Real fraction = Real((tDelay-t0)/(t1-t0));
1875 delayedValue = T(v0 + fraction*(v1-v0));
1876 return;
1877 }
1878
1879 if (firstLater==0) {
1880 // Startup case: tDelay is at or before the oldest buffer entry.
1881 // Assume the value was flat before that.
1882 delayedValue = getEntryValue(firstLater);
1883 return;
1884 }
1885
1886 // tDelay is later than the latest entry in the buffer. We are going
1887 // to have to extrapolate (yuck).
1888
1889 if (size() == 1) {
1890 // Just one entry; we'll have to assume the value is flat.
1891 delayedValue = getEntryValue(0);
1892 return;
1893 }
1894
1895 // Extrapolate using the last two entries.
1896 double t0=getEntryTime(size()-2), t1=getEntryTime(size()-1);
1897 const T& v0=getEntryValue(size()-2);
1898 const T& v1=getEntryValue(size()-1);
1899 Real fraction = Real((tDelay-t0)/(t1-t0)); // > 1
1900 assert(fraction > 1.0);
1901 delayedValue = T(v0 + fraction*(v1-v0)); // Extrapolate.
1902 }
1903
1904 // Return the number of times we had to grow the buffer.
1905 int getNumGrows() const {return m_nGrows;}
1906 // Return the number of times we decided the buffer was so overallocated
1907 // that we had to shrink it.
1908 int getNumShrinks() const {return m_nShrinks;}
1909 // Return the largest number of values we ever had in the buffer.
1910 int getMaxSize() const {return m_maxSize;}
1911 // Return the largest capacity the buffer ever had.
1912 int getMaxCapacity() const {return m_maxCapacity;}
1913
1914private:
1915 // Return the i'th oldest entry
1916 // (0 -> oldest, size-1 -> newest, size -> first free, -1 -> last free)
1917 int getArrayIndex(int i) const
1918 { assert(-1<=i && i<=size());
1919 const int rawIndex = m_oldest + i;
1920 if (rawIndex < 0) return rawIndex + capacity();
1921 else return rawIndex % capacity(); }
1922
1923 // Remove all but two entries older than the given time.
1924 void forgetEntriesMuchOlderThan(double tEarliest) {
1925 const int numToRemove = countNumUnneededOldEntries(tEarliest);
1926 if (numToRemove) {
1927 m_oldest = getArrayIndex(numToRemove);
1928 m_size -= numToRemove;
1929 }
1930 }
1931
1932 // Count up how many old entries at the beginning of the buffer are so old
1933 // that they wouldn't be needed to respond to a request at time tEarliest or
1934 // later. We'll keep no more than two entries earlier than tEarliest.
1935 int countNumUnneededOldEntries(double tEarliest) const {
1936 const int firstLater = findFirstLaterOrEq(tEarliest);
1937 return std::max(0, firstLater-2);
1938 }
1939
1940 // Given the time now, delete anything at the end of the queue that is
1941 // at that same time or later.
1942 void removeEntriesLaterOrEq(double t) {
1943 int lastEarlier = findLastEarlier(t);
1944 m_size = lastEarlier+1;
1945 if (m_size==0) m_oldest=0; // restart at beginning of array
1946 }
1947
1948 // Return the entry number (0..size-1) of the first entry whose time
1949 // is >= the given time, or -1 if there is none such.
1950 int findFirstLaterOrEq(double tDelay) const {
1951 for (int i=0; i < size(); ++i)
1952 if (getEntryTime(i) >= tDelay)
1953 return i;
1954 return -1;
1955 }
1956
1957 // Return the entry number(size-1..0) of the last entry whose time
1958 // is < the given time, or -1 if there is none such.
1959 int findLastEarlier(double t) const {
1960 for (int i=size()-1; i>=0; --i)
1961 if (getEntryTime(i) < t)
1962 return i;
1963 return -1;
1964 }
1965
1966 // We don't have enough space. This is either the initial allocation or
1967 // we need to double the current space.
1968 void makeMoreRoom() {
1969 const int newSizeRequest = std::max((int)InitialAllocation,
1970 (int)GrowthFactor * size());
1971 resize(newSizeRequest);
1972 ++m_nGrows;
1973 m_maxCapacity = std::max(m_maxCapacity, capacity());
1974 }
1975
1976 // We are wasting a lot of space, reduce the heap allocation to just
1977 // double what we're using now.
1978 void makeLessRoom() {
1979 const int targetMaxSize = std::max((int)MaxShrinkProofSize,
1980 (int)GrowthFactor * size());
1981 if (capacity() > targetMaxSize) {
1982 resize(targetMaxSize);
1983 ++m_nShrinks;
1984 }
1985 }
1986
1987 // Reallocate memory to get more space or stop wasting space. The new
1988 // size request must be big enough to hold all the current contents. The
1989 // amount we actually get may be somewhat larger than the request. On
1990 // return, the times and values arrays will have been resized and the
1991 // oldest entry will now be entry 0.
1992 void resize(int newSizeRequest) {
1993 assert(newSizeRequest >= size());
1994 const double dNaN = NTraits<double>::getNaN();
1995 Array_<T,int> newValues(newSizeRequest);
1996 if (newValues.capacity() > newValues.size())
1997 newValues.resize(newValues.capacity()); // don't waste any
1998 Array_<double,int> newTimes(newValues.size(), dNaN);
1999
2000 // Pack existing values into start of new arrays.
2001 for (int i=0; i < size(); ++i) {
2002 const int ix = getArrayIndex(i);
2003 newTimes[i] = m_times[ix];
2004 newValues[i] = m_values[ix];
2005 }
2006 m_times.swap(newTimes); // switch heap space
2007 m_values.swap(newValues);
2008 m_oldest = 0; // starts at the beginning now; size unchanged
2009 }
2010
2011 // Initialize everything to its default-constructed state.
2012 void initDataMembers() {
2013 m_times.clear(); m_values.clear();
2014 m_oldest=m_size=0;
2015 m_nGrows=m_nShrinks=m_maxSize=m_maxCapacity=0;
2016 }
2017
2018 // These are circular buffers of the same size.
2019 Array_<double,int> m_times;
2020 Array_<T,int> m_values;
2021 int m_oldest; // Array index of oldest (time,value)
2022 int m_size; // number of entries in use
2023
2024 // Statistics.
2025 int m_nGrows, m_nShrinks, m_maxSize, m_maxCapacity;
2026};
2029template <class T>
2030class Measure_<T>::Delay::Implementation: public Measure_<T>::Implementation {
2031 typedef Measure_Delay_Buffer<T> Buffer;
2032public:
2033 // Allocate one cache entry in the base class for the value; we allocate
2034 // a specialized one for the buffer.
2036 : Measure_<T>::Implementation(1), m_delay(NaN),
2037 m_canUseCurrentValue(false), m_useLinearInterpolationOnly(false) {}
2038
2039 Implementation(const Measure_<T>& source, Real delay)
2040 : Measure_<T>::Implementation(1), m_source(source), m_delay(delay),
2041 m_canUseCurrentValue(false), m_useLinearInterpolationOnly(false) {}
2042
2043 // Default copy constructor gives us a new Implementation object,
2044 // but with reference to the *same* source measure.
2045
2046 void setSourceMeasure(const Measure_<T>& source) {
2047 if (!source.isSameMeasure(this->m_source)) {
2048 this->m_source = source;
2049 this->invalidateTopologyCache();
2050 }
2051 }
2052
2053 void setDelay(Real delay) {
2054 if (delay != this->m_delay) {
2055 this->m_delay = delay;
2056 this->invalidateTopologyCache();
2057 }
2058 }
2059
2060 void setUseLinearInterpolationOnly(bool linearOnly) {
2061 if (linearOnly != this->m_useLinearInterpolationOnly) {
2062 this->m_useLinearInterpolationOnly = linearOnly;
2063 this->invalidateTopologyCache();
2064 }
2065 }
2066
2067 void setCanUseCurrentValue(bool canUseCurrentValue) {
2068 if (canUseCurrentValue != this->m_canUseCurrentValue) {
2069 this->m_canUseCurrentValue = canUseCurrentValue;
2070 this->invalidateTopologyCache();
2071 }
2072 }
2073
2074 const Measure_<T>& getSourceMeasure() const {return this->m_source;}
2075 Real getDelay() const {return this->m_delay;}
2077 { return this->m_useLinearInterpolationOnly; }
2079 { return this->m_canUseCurrentValue; }
2080
2081
2082 // Implementations of virtual methods.
2083
2084 // This uses the default copy constructor.
2086 { return new Implementation(*this); }
2087
2088 // Currently no derivative supported.
2089 int getNumTimeDerivativesVirtual() const override
2090 { return 0; }
2091
2092 // If we are allowed to use the current value of the source measure to
2093 // determine the delayed value, the depends-on stage here is the same as
2094 // for the source; otherwise it is Stage::Time.
2095 Stage getDependsOnStageVirtual(int order) const override
2096 { return this->m_canUseCurrentValue ? m_source.getDependsOnStage(order)
2097 : Stage::Time; }
2098
2099 // Calculate the delayed value and return it to the Measure base class to
2100 // be put in a cache entry.
2101 void calcCachedValueVirtual(const State& s, int derivOrder, T& value) const
2102 override
2103 { const Subsystem& subsys = this->getSubsystem();
2104 const Buffer& buffer = Value<Buffer>::downcast
2105 (subsys.getDiscreteVariable(s,m_bufferIx));
2106 //TODO: use cubic interpolation if allowed
2107 buffer.calcValueAtTimeLinearOnly(s.getTime()-m_delay, value);
2108 }
2109
2110 void initializeVirtual(State& s) const override {
2111 assert(m_bufferIx.isValid());
2112 const Subsystem& subsys = this->getSubsystem();
2113 Buffer& buffer = Value<Buffer>::updDowncast
2114 (subsys.updDiscreteVariable(s,m_bufferIx));
2115 buffer.clear();
2116 this->getSubsystem().getSystem().realize(s,m_source.getDependsOnStage());
2117 buffer.append(s.getTime()-m_delay, s.getTime(), m_source.getValue(s));
2118 }
2119
2120 void realizeMeasureTopologyVirtual(State& s) const override {
2121 m_bufferIx = this->getSubsystem()
2122 .allocateAutoUpdateDiscreteVariable(s, Stage::Report,
2123 new Value<Buffer>(), getDependsOnStageVirtual(0));
2124 }
2125
2128 void realizeMeasureAccelerationVirtual(const State& s) const override {
2129 updateBuffer(s);
2130 }
2131
2132 // This uses the buffer from the state to update the one in the
2133 // corresponding cache entry. The update adds the current value of the
2134 // source to the end of the buffer and tosses out unneeded old entries.
2135 void updateBuffer(const State& s) const {
2136 assert(m_bufferIx.isValid());
2137 const Subsystem& subsys = this->getSubsystem();
2138
2139 const Buffer& prevBuffer = Value<Buffer>::downcast
2140 (subsys.getDiscreteVariable(s,m_bufferIx));
2141
2142 Buffer& nextBuffer = Value<Buffer>::updDowncast
2143 (subsys.updDiscreteVarUpdateValue(s,m_bufferIx));
2144
2145 const Real t = s.getTime();
2146 nextBuffer.copyInAndUpdate(prevBuffer, t-m_delay,
2147 t, m_source.getValue(s));
2148
2149 subsys.markDiscreteVarUpdateValueRealized(s,m_bufferIx);
2150 }
2151private:
2152 // TOPOLOGY STATE
2153 Measure_<T> m_source;
2154 Real m_delay;
2155 bool m_canUseCurrentValue;
2156 bool m_useLinearInterpolationOnly;
2157
2158 // TOPOLOGY CACHE
2159 mutable DiscreteVariableIndex m_bufferIx; // auto-update
2160};
2161
2162
2163} // namespace SimTK
2164
2165
2166
2167
2168#endif // SimTK_SimTKCOMMON_MEASURE_IMPLEMENTATION_H_
#define SimTK_ERRCHK3_ALWAYS(cond, whereChecked, fmt, a1, a2, a3)
Definition ExceptionMacros.h:293
#define SimTK_ERRCHK2_ALWAYS(cond, whereChecked, fmt, a1, a2)
Definition ExceptionMacros.h:289
#define SimTK_ERRCHK_ALWAYS(cond, whereChecked, msg)
Definition ExceptionMacros.h:281
#define SimTK_ERRCHK2(cond, whereChecked, fmt, a1, a2)
Definition ExceptionMacros.h:328
#define SimTK_ERRCHK1_ALWAYS(cond, whereChecked, fmt, a1)
Definition ExceptionMacros.h:285
#define SimTK_ASSERT1_ALWAYS(cond, msg, a1)
Definition ExceptionMacros.h:351
#define SimTK_ERRCHK(cond, whereChecked, msg)
Definition ExceptionMacros.h:324
This file declares the base class AbstractMeasure for all derived Measure handle classes,...
Operation
Definition Measure.h:841
#define SimTK_SimTKCOMMON_EXPORT
Definition SimTKcommon/include/SimTKcommon/internal/common.h:224
This is the header which should be included in user programs that would like to make use of all the S...
Declares the user-visible part of a SimTK::State, the implementation is done in a separate internal c...
Includes internal headers providing declarations for the basic SimTK Core classes.
The abstract parent of all Measure Implementation classes.
Definition MeasureImplementation.h:48
virtual void realizeMeasureAccelerationVirtual(const State &) const
Definition MeasureImplementation.h:143
void invalidateTopologyCache() const
Definition MeasureImplementation.h:125
int decrRefCount() const
Definition MeasureImplementation.h:76
void realizeAcceleration(const State &s) const
Definition MeasureImplementation.h:95
Implementation & operator=(const Implementation &src)
Base class copy assignment operator removes the Subsystem, and sets the reference count to zero.
Definition MeasureImplementation.h:63
virtual void realizeMeasureModelVirtual(State &) const
Definition MeasureImplementation.h:137
virtual Implementation * cloneVirtual() const =0
const Subsystem & getSubsystem() const
Definition MeasureImplementation.h:119
virtual int getNumTimeDerivativesVirtual() const
Definition MeasureImplementation.h:147
Subsystem & updSubsystem()
Definition MeasureImplementation.h:120
Implementation * clone() const
This is a deep copy of the concrete Implementation object, except the Subsystem will have been remove...
Definition MeasureImplementation.h:86
virtual void realizeMeasureTimeVirtual(const State &) const
Definition MeasureImplementation.h:139
void setSubsystem(Subsystem &sub, MeasureIndex mx)
Definition MeasureImplementation.h:114
int incrRefCount() const
Definition MeasureImplementation.h:73
SubsystemIndex getSubsystemIndex() const
Definition MeasureImplementation.h:122
virtual void realizeTopology(State &) const =0
void realizeDynamics(const State &s) const
Definition MeasureImplementation.h:94
virtual ~Implementation()
Definition MeasureImplementation.h:132
void realizeTime(const State &s) const
Definition MeasureImplementation.h:91
void initialize(State &s) const
This should be called at the start of a time stepping study to cause this Measure to set its state va...
Definition MeasureImplementation.h:101
virtual Stage getDependsOnStageVirtual(int order) const =0
void realizeVelocity(const State &s) const
Definition MeasureImplementation.h:93
virtual void realizeMeasurePositionVirtual(const State &) const
Definition MeasureImplementation.h:140
virtual void realizeMeasureReportVirtual(const State &) const
Definition MeasureImplementation.h:144
void realizeReport(const State &s) const
Definition MeasureImplementation.h:96
virtual void initializeVirtual(State &) const
Definition MeasureImplementation.h:146
virtual void realizeMeasureDynamicsVirtual(const State &) const
Definition MeasureImplementation.h:142
bool isInSubsystem() const
Definition MeasureImplementation.h:118
int getCopyNumber() const
Definition MeasureImplementation.h:81
Stage getDependsOnStage(int derivOrder) const
Definition MeasureImplementation.h:105
Stage getStage(const State &s) const
Definition MeasureImplementation.h:128
MeasureIndex getSubsystemMeasureIndex() const
Definition MeasureImplementation.h:121
Implementation(const Implementation &src)
Base class copy constructor removes the Subsystem and sets the reference count to zero.
Definition MeasureImplementation.h:57
Implementation()
This default constructor is for use by concrete measure implementation classes.
Definition MeasureImplementation.h:52
void realizeModel(State &s) const
Definition MeasureImplementation.h:89
int getRefCount() const
Definition MeasureImplementation.h:79
virtual void realizeMeasureInstanceVirtual(const State &) const
Definition MeasureImplementation.h:138
int getNumTimeDerivatives() const
Definition MeasureImplementation.h:103
virtual void realizeMeasureVelocityVirtual(const State &) const
Definition MeasureImplementation.h:141
void realizeInstance(const State &s) const
Definition MeasureImplementation.h:90
void realizePosition(const State &s) const
Definition MeasureImplementation.h:92
An object of this type is used as a dummy argument to make sure the automatically-generated handle co...
Definition Measure.h:156
This is the base class for all Measure handle classes.
Definition Measure.h:151
int getNumTimeDerivatives() const
Every Measure can produce a value, and some can provide one or more total derivatives with respect to...
Definition MeasureImplementation.h:241
MeasureIndex getSubsystemMeasureIndex() const
Return the MeasureIndex by which this Measure is known to the Subsystem that owns it.
Definition MeasureImplementation.h:237
Stage getDependsOnStage(int derivOrder=0) const
At what Stage can we expect the value of this AbstractMeasure or one of its time derivatives to be av...
Definition MeasureImplementation.h:245
bool isSameMeasure(const AbstractMeasure &other) const
There can be multiple handles on the same Measure.
Definition Measure.h:220
int getRefCount() const
Definition MeasureImplementation.h:249
const Subsystem & getSubsystem() const
Return a reference to the Subsystem that owns this Measure.
Definition MeasureImplementation.h:229
bool isSameSubsystem(const Subsystem &) const
Is getSubsystem() the same as the passed-in Subsystem?
Definition MeasureImplementation.h:233
const Implementation & getImpl() const
Definition Measure.h:242
AbstractMeasure(Implementation *g=0)
Provide an Implementation for this AbstractMeasure and bump its reference count.
Definition MeasureImplementation.h:171
AbstractMeasure & deepAssign(const AbstractMeasure &source)
Deep assignment clones the Implementation object pointed to by the source handle, so that this handle...
Definition MeasureImplementation.h:208
bool isInSubsystem() const
Test whether this Measure object has been adopted by a Subsystem.
Definition MeasureImplementation.h:225
bool hasImpl() const
Definition Measure.h:244
~AbstractMeasure()
Destructor decrements the Implementation's reference count and deletes the object if the count goes t...
Definition MeasureImplementation.h:221
AbstractMeasure & shallowAssign(const AbstractMeasure &)
Shallow assignment operator destructs the current Implementation object (meaning its reference count ...
Definition MeasureImplementation.h:195
Specialized information about Composite Numerical Types which allows us to define appropriate templat...
Definition CompositeNumericalTypes.h:136
This unique integer type is for selecting discrete variables.
Definition MeasureImplementation.h:612
void setValue(const T &v)
Changing the value of a Constant measure is a topological change; if this is a Vector measure you can...
Definition MeasureImplementation.h:621
Implementation(const T &value)
Definition MeasureImplementation.h:616
const T & getUncachedValueVirtual(const State &, int derivOrder) const override
This is only called when derivOrder >= the number of cache entries we have, but still <= the number o...
Definition MeasureImplementation.h:627
int getNumTimeDerivativesVirtual() const override
Definition MeasureImplementation.h:636
Implementation * cloneVirtual() const override
Definition MeasureImplementation.h:632
Implementation()
Definition MeasureImplementation.h:615
Stage getDependsOnStageVirtual(int derivOrder) const override
Definition MeasureImplementation.h:634
This creates a Measure whose value is a Topology-stage constant of any type T.
Definition Measure.h:341
Definition MeasureImplementation.h:2030
void realizeMeasureAccelerationVirtual(const State &s) const override
In case no one has updated the value of this measure yet, we have to make sure it gets updated before...
Definition MeasureImplementation.h:2128
Implementation * cloneVirtual() const override
Definition MeasureImplementation.h:2085
void realizeMeasureTopologyVirtual(State &s) const override
Concrete measures can override this to allocate Topology-stage resources.
Definition MeasureImplementation.h:2120
void setSourceMeasure(const Measure_< T > &source)
Definition MeasureImplementation.h:2046
Implementation()
Definition MeasureImplementation.h:2035
const Measure_< T > & getSourceMeasure() const
Definition MeasureImplementation.h:2074
Stage getDependsOnStageVirtual(int order) const override
Definition MeasureImplementation.h:2095
void setCanUseCurrentValue(bool canUseCurrentValue)
Definition MeasureImplementation.h:2067
void calcCachedValueVirtual(const State &s, int derivOrder, T &value) const override
Concrete measures must override this if the state cache is used for precalculated values or derivativ...
Definition MeasureImplementation.h:2101
void initializeVirtual(State &s) const override
Definition MeasureImplementation.h:2110
void updateBuffer(const State &s) const
Definition MeasureImplementation.h:2135
bool getUseLinearInterpolationOnly() const
Definition MeasureImplementation.h:2076
int getNumTimeDerivativesVirtual() const override
Definition MeasureImplementation.h:2089
void setDelay(Real delay)
Definition MeasureImplementation.h:2053
void setUseLinearInterpolationOnly(bool linearOnly)
Definition MeasureImplementation.h:2060
Real getDelay() const
Definition MeasureImplementation.h:2075
bool getCanUseCurrentValue() const
Definition MeasureImplementation.h:2078
Implementation(const Measure_< T > &source, Real delay)
Definition MeasureImplementation.h:2039
Definition MeasureImplementation.h:1307
void initializeVirtual(State &s) const override
Definition MeasureImplementation.h:1365
const Measure_< T > & getOperandMeasure() const
Definition MeasureImplementation.h:1332
void realizeMeasureAccelerationVirtual(const State &s) const override
In case no one has updated the value of this measure yet, we have to make sure it gets updated before...
Definition MeasureImplementation.h:1390
void ensureDerivativeIsRealized(const State &s) const
Definition MeasureImplementation.h:1394
const T & getUncachedValueVirtual(const State &s, int derivOrder) const override
This is only called when derivOrder >= the number of cache entries we have, but still <= the number o...
Definition MeasureImplementation.h:1353
void realizeMeasureTopologyVirtual(State &s) const override
Concrete measures can override this to allocate Topology-stage resources.
Definition MeasureImplementation.h:1378
Implementation()
Definition MeasureImplementation.h:1311
bool getForceUseApproximation() const
Definition MeasureImplementation.h:1330
bool isUsingApproximation() const
Definition MeasureImplementation.h:1331
void setForceUseApproximation(bool mustApproximate)
Definition MeasureImplementation.h:1320
Stage getDependsOnStageVirtual(int order) const override
Definition MeasureImplementation.h:1345
Implementation(const Measure_< T > &operand)
Definition MeasureImplementation.h:1313
int getNumTimeDerivativesVirtual() const override
Definition MeasureImplementation.h:1341
Implementation * cloneVirtual() const override
Definition MeasureImplementation.h:1337
void setOperandMeasure(const Measure_< T > &operand)
Definition MeasureImplementation.h:1325
Definition MeasureImplementation.h:1446
int getNumTimeDerivativesVirtual() const override
Extreme(f(t)) has the same number of derivatives as f except that they are all zero unless f(t) is a ...
Definition MeasureImplementation.h:1518
const T & getUncachedValueVirtual(const State &s, int derivOrder) const override
We're not using the Measure_<T> base class cache services, but we do have one of our own.
Definition MeasureImplementation.h:1530
Implementation()
Default constructor leaves the operand measure unspecified; no base class cache entries are allocated...
Definition MeasureImplementation.h:1452
bool ensureExtremeHasBeenUpdated(const State &s) const
Here we make sure that the cache entry is updated if the current value of the operand is more extreme...
Definition MeasureImplementation.h:1597
Implementation(const Measure_< T > &operand, Operation op)
Construct a measure that returns the extreme value taken on by the operand measure during a time step...
Definition MeasureImplementation.h:1457
void setOperation(Operation op)
Set the particular operation to be performed by this Extreme measure; this is a Topology stage change...
Definition MeasureImplementation.h:1474
void setValue(State &s, const T &value) const
Set the current extreme value stored in this Extreme measure's state variable.
Definition MeasureImplementation.h:1488
Operation getOperation() const
Return the particular operation being performed by this Extreme measure.
Definition MeasureImplementation.h:1484
Implementation * cloneVirtual() const override
Definition MeasureImplementation.h:1513
void initializeVirtual(State &s) const override
At start of a time stepping study, this should be called to set the current extreme value to the curr...
Definition MeasureImplementation.h:1555
void realizeMeasureAccelerationVirtual(const State &s) const override
In case no one has updated the value of this measure yet, we have to make sure it gets updated before...
Definition MeasureImplementation.h:1588
void setOperandMeasure(const Measure_< T > &operand)
Set the operand measure for this Extreme measure; this is a Topology stage change so you'll have to c...
Definition MeasureImplementation.h:1466
Stage getDependsOnStageVirtual(int order) const override
The depends-on stage for this measure is the same as for its operand.
Definition MeasureImplementation.h:1523
const Measure_< T > & getOperandMeasure() const
Return a reference to the operand measure for this Extreme measure.
Definition MeasureImplementation.h:1480
Real getTimeOfExtremeValue(const State &s) const
Return the time at which the extreme was last updated.
Definition MeasureImplementation.h:1499
void realizeMeasureTopologyVirtual(State &s) const override
Allocate the auto-updated state variable that holds the extreme seen so far.
Definition MeasureImplementation.h:1567
This Measure tracks extreme values attained by the elements of its source operand since the last init...
Definition Measure.h:837
This is the base Implementation class for all Measures whose value type is known.
Definition MeasureImplementation.h:363
int size() const
Return the number of elements in the data type of this Measure; for Vector measures this is determine...
Definition MeasureImplementation.h:459
int getNumCacheEntries() const
Return the number of cache entries allocated for the value and derivatives of this Measure.
Definition MeasureImplementation.h:463
Implementation(int numCacheEntries=1)
Argument numCacheEntries should be one greater than the number of derivatives; that is,...
Definition MeasureImplementation.h:437
Implementation(const T &defaultValue, int numCacheEntries=1)
Definition MeasureImplementation.h:426
bool isCacheValueRealized(const State &s, int derivOrder) const
Determine whether a particular one of this Measure's cache entries has already been realized since th...
Definition MeasureImplementation.h:493
const T & getCacheEntry(const State &s, int derivOrder) const
Get a const reference to the value stored in one of this Measure's cache entries, indexed by the deri...
Definition MeasureImplementation.h:468
T & updCacheEntry(const State &s, int derivOrder) const
Get a writable reference to the value stored in one of this Measure's cache entries,...
Definition MeasureImplementation.h:481
virtual void realizeMeasureTopologyVirtual(State &) const
Concrete measures can override this to allocate Topology-stage resources.
Definition MeasureImplementation.h:531
Implementation(const Implementation &source)
Copy constructor copies the number of cache entries from the source, but not the cache indices themse...
Definition MeasureImplementation.h:448
void setDefaultValue(const T &defaultValue)
Set a new default value for this Measure.
Definition MeasureImplementation.h:407
virtual const T & getUncachedValueVirtual(const State &, int derivOrder) const
This is only called when derivOrder >= the number of cache entries we have, but still <= the number o...
Definition MeasureImplementation.h:549
void markCacheValueNotRealized(const State &s, int derivOrder) const
Invalidate one of this Measure's cache entries.
Definition MeasureImplementation.h:518
const T & getValue(const State &s, int derivOrder) const
Definition MeasureImplementation.h:365
const T & getValueZero() const
Return a reference to a zero of the same type and size as this Measure's value.
Definition MeasureImplementation.h:560
bool getIsPresumedValidAtDependsOnStage() const
Definition MeasureImplementation.h:422
const T & getDefaultValue() const
Return a reference to the value that this Measure will use to initialize its value-level state resour...
Definition MeasureImplementation.h:416
void markCacheValueRealized(const State &s, int derivOrder) const
Mark one of this Measure's cache entries up to date; call this after you have calculated a value or d...
Definition MeasureImplementation.h:505
virtual void calcCachedValueVirtual(const State &, int derivOrder, T &value) const
Concrete measures must override this if the state cache is used for precalculated values or derivativ...
Definition MeasureImplementation.h:536
void setIsPresumedValidAtDependsOnStage(bool presume)
Definition MeasureImplementation.h:418
The implementation for Integrate measures allocates a continuous state variable or variables from the...
Definition MeasureImplementation.h:1148
void setValue(State &s, const T &value) const
Set the value of the state variables(s) that hold the integral.
Definition MeasureImplementation.h:1170
Implementation()
The derivative and initialConditions Measures will be empty handles if this is default constructed.
Definition MeasureImplementation.h:1152
void realizeMeasureAccelerationVirtual(const State &s) const override
Set the zdots to the integrand (derivative measure) value.
Definition MeasureImplementation.h:1259
Implementation * cloneVirtual() const override
Definition MeasureImplementation.h:1197
void initializeVirtual(State &s) const override
Initialize the state to the current value of the initial condition measure, if there is one,...
Definition MeasureImplementation.h:1231
void realizeMeasureTopologyVirtual(State &s) const override
Allocate one Real continuous state variable z per element of this Measure's data type T,...
Definition MeasureImplementation.h:1250
Implementation(const Measure_< T > &deriv, const Measure_< T > &ic, const T &defaultValue)
Here we're shallow-copying the Measure handles so we'll be referring to the original Measures.
Definition MeasureImplementation.h:1156
const T & getUncachedValueVirtual(const State &s, int derivOrder) const override
This is only called when derivOrder >= the number of cache entries we have, but still <= the number o...
Definition MeasureImplementation.h:1218
int getNumTimeDerivativesVirtual() const override
This measure has one more time derivative than the integrand.
Definition MeasureImplementation.h:1201
const Measure_< T > & getInitialConditionMeasure() const
Definition MeasureImplementation.h:1182
void calcCachedValueVirtual(const State &s, int derivOrder, T &value) const override
Concrete measures must override this if the state cache is used for precalculated values or derivativ...
Definition MeasureImplementation.h:1208
void setDerivativeMeasure(const Measure_< T > &d)
Definition MeasureImplementation.h:1189
const Measure_< T > & getDerivativeMeasure() const
Definition MeasureImplementation.h:1176
Stage getDependsOnStageVirtual(int derivOrder) const override
Definition MeasureImplementation.h:1224
Implementation(const Implementation &source)
Copy constructor shallow-copies the referenced measures, but we don't want to share our state variabl...
Definition MeasureImplementation.h:1163
void setInitialConditionMeasure(const Measure_< T > &ic)
Definition MeasureImplementation.h:1191
Track the value of the operand that is of maximum absolute value.
Definition Measure.h:905
Track the maximum value of the operand (signed).
Definition Measure.h:895
Track the value of the operand that is of minimum absolute value (not very useful).
Definition Measure.h:916
Track the minimum value of the operand (signed).
Definition Measure.h:885
Definition MeasureImplementation.h:1025
Implementation(const Measure_< T > &left, const Measure_< T > &right)
Definition MeasureImplementation.h:1031
Stage getDependsOnStageVirtual(int order) const override
Definition MeasureImplementation.h:1050
Implementation * cloneVirtual() const override
Definition MeasureImplementation.h:1041
Implementation()
Definition MeasureImplementation.h:1029
void calcCachedValueVirtual(const State &s, int derivOrder, T &value) const override
Concrete measures must override this if the state cache is used for precalculated values or derivativ...
Definition MeasureImplementation.h:1055
int getNumTimeDerivativesVirtual() const override
Definition MeasureImplementation.h:1046
One()
Definition MeasureImplementation.h:658
Definition MeasureImplementation.h:972
Stage getDependsOnStageVirtual(int order) const override
Definition MeasureImplementation.h:997
int getNumTimeDerivativesVirtual() const override
Definition MeasureImplementation.h:993
Implementation(const Measure_< T > &left, const Measure_< T > &right)
Definition MeasureImplementation.h:978
void calcCachedValueVirtual(const State &s, int derivOrder, T &value) const override
Concrete measures must override this if the state cache is used for precalculated values or derivativ...
Definition MeasureImplementation.h:1002
Implementation()
Definition MeasureImplementation.h:976
Implementation * cloneVirtual() const override
Definition MeasureImplementation.h:988
Definition MeasureImplementation.h:794
Stage getDependsOnStageVirtual(int derivOrder) const override
Cache value is available after its "depends on" stage has been realized; but all its derivatives are ...
Definition MeasureImplementation.h:884
void calcCachedValueVirtual(const State &, int derivOrder, T &value) const override
Concrete measures must override this if the state cache is used for precalculated values or derivativ...
Definition MeasureImplementation.h:887
Implementation * cloneVirtual() const override
Definition MeasureImplementation.h:877
Stage getDependsOnStage() const
Definition MeasureImplementation.h:845
void markAsNotValid(const State &state) const
Definition MeasureImplementation.h:868
bool isValid(const State &state) const
Definition MeasureImplementation.h:865
void markAsValid(const State &state) const
Definition MeasureImplementation.h:849
Implementation()
Definition MeasureImplementation.h:797
void setDependsOnStage(Stage dependsOn)
Definition MeasureImplementation.h:817
T & updValue(const State &state) const
Definition MeasureImplementation.h:872
int getNumTimeDerivativesVirtual() const override
Definition MeasureImplementation.h:880
Implementation(const Implementation &source)
Definition MeasureImplementation.h:812
Implementation(Stage dependsOn, Stage invalidated)
Definition MeasureImplementation.h:801
void setInvalidatedStage(Stage invalidated)
Definition MeasureImplementation.h:831
Stage getInvalidatedStage() const
Definition MeasureImplementation.h:846
Definition MeasureImplementation.h:1080
Stage getDependsOnStageVirtual(int order) const override
Definition MeasureImplementation.h:1114
void setScaleFactor(Real sf)
Definition MeasureImplementation.h:1092
Implementation()
Definition MeasureImplementation.h:1084
Implementation(Real factor, const Measure_< T > &operand)
Definition MeasureImplementation.h:1086
Implementation * cloneVirtual() const override
Definition MeasureImplementation.h:1105
int getNumTimeDerivativesVirtual() const override
Definition MeasureImplementation.h:1110
const Measure_< T > & getOperandMeasure() const
Definition MeasureImplementation.h:1097
void calcCachedValueVirtual(const State &s, int derivOrder, T &value) const override
Concrete measures must override this if the state cache is used for precalculated values or derivativ...
Definition MeasureImplementation.h:1118
Definition MeasureImplementation.h:910
Stage getDependsOnStageVirtual(int order) const override
Definition MeasureImplementation.h:931
int getNumTimeDerivativesVirtual() const override
Definition MeasureImplementation.h:929
Implementation()
Definition MeasureImplementation.h:913
void calcCachedValueVirtual(const State &s, int derivOrder, T &value) const override
Concrete measures must override this if the state cache is used for precalculated values or derivativ...
Definition MeasureImplementation.h:934
Implementation(const T &amplitude, const T &frequency, const T &phase=T(0))
Definition MeasureImplementation.h:917
Implementation * cloneVirtual() const override
Definition MeasureImplementation.h:926
Definition MeasureImplementation.h:673
Definition MeasureImplementation.h:714
void setInvalidatedStage(Stage invalidates)
Definition MeasureImplementation.h:732
Implementation(Stage invalidated, const T &defaultValue)
Definition MeasureImplementation.h:723
void realizeMeasureTopologyVirtual(State &s) const override
Concrete measures can override this to allocate Topology-stage resources.
Definition MeasureImplementation.h:763
Stage getInvalidatedStage() const
Definition MeasureImplementation.h:737
Implementation * cloneVirtual() const override
Definition MeasureImplementation.h:746
Stage getDependsOnStageVirtual(int derivOrder) const override
Definition MeasureImplementation.h:754
Implementation(const Implementation &source)
Definition MeasureImplementation.h:728
const T & getUncachedValueVirtual(const State &s, int derivOrder) const override
This is only called when derivOrder >= the number of cache entries we have, but still <= the number o...
Definition MeasureImplementation.h:757
int getNumTimeDerivativesVirtual() const override
Definition MeasureImplementation.h:749
Implementation()
Definition MeasureImplementation.h:719
void setValue(State &state, const T &value) const
Change the value of this Measure in the given state.
Definition MeasureImplementation.h:742
Zero()
Definition MeasureImplementation.h:648
This is the base handle class for all Measures whose value type is known, including all the Simbody b...
Definition Measure.h:263
Measure_ & setDefaultValue(const T &defaultValue)
Change the default value associated with this Measure.
Definition Measure.h:285
const T & getDefaultValue() const
Obtain a reference to the default value associated with this Measure.
Definition Measure.h:290
This class is basically a glorified enumerated type, type-safe and range checked but permitting conve...
Definition Stage.h:66
String getName() const
Return a printable name corresponding to the stage level currently stored in this Stage.
Definition Stage.h:144
Stage prev() const
Return the Stage before this one, with Stage::Empty returned if this Stage is already at its lowest v...
Definition Stage.h:139
@ Topology
System topology realized.
Definition Stage.h:70
@ Empty
Lower than any legitimate Stage.
Definition Stage.h:69
This object is intended to contain all state information for a SimTK::System, except topological info...
Definition State.h:280
const Stage & getSystemStage() const
This returns the global stage for this State.
const Real & getTime() const
You can call these as long as system stage >= Model.
void invalidateAllCacheAtOrAbove(Stage) const
If any subsystem or the system stage is currently at or higher than the passed-in one,...
Provide a unique integer type for identifying Subsystems.
The abstract parent of all Subsystem implementation classes.
Definition SubsystemGuts.h:47
A Subsystem is expected to be part of a larger System and to have interdependencies with other subsys...
Definition Subsystem.h:55
bool isSameSubsystem(const Subsystem &otherSubsystem) const
Determine if this Subsystem handle refers to the same Subsystem::Guts object as handle otherSubsystem...
Definition Subsystem.h:322
MeasureIndex adoptMeasure(AbstractMeasure &)
Obtain the Subsystem name if one was given on construction of the concrete Subsystem.
Definition SubsystemGuts.h:509
AbstractValue & updDiscreteVariable(State &s, DiscreteVariableIndex index) const
Definition Subsystem.h:247
CacheEntryIndex allocateCacheEntry(const State &s, Stage dependsOn, Stage computedBy, AbstractValue *v) const
Definition Subsystem.h:103
AbstractValue & updDiscreteVarUpdateValue(const State &s, DiscreteVariableIndex dx) const
Definition Subsystem.h:262
void markDiscreteVarUpdateValueRealized(const State &s, DiscreteVariableIndex dx) const
Definition Subsystem.h:268
void markCacheValueNotRealized(const State &s, CacheEntryIndex cx) const
Definition Subsystem.h:275
CacheEntryIndex allocateLazyCacheEntry(const State &state, Stage earliest, AbstractValue *v) const
Definition Subsystem.h:111
bool isDiscreteVarUpdateValueRealized(const State &s, DiscreteVariableIndex dx) const
Definition Subsystem.h:265
const AbstractValue & getDiscreteVariable(const State &s, DiscreteVariableIndex index) const
Definition Subsystem.h:245
bool isCacheValueRealized(const State &s, CacheEntryIndex cx) const
Definition Subsystem.h:271
Real getDiscreteVarLastUpdateTime(const State &s, DiscreteVariableIndex dx) const
Definition Subsystem.h:253
const AbstractValue & getDiscreteVarUpdateValue(const State &s, DiscreteVariableIndex dx) const
Definition Subsystem.h:259
void markCacheValueRealized(const State &s, CacheEntryIndex cx) const
Definition Subsystem.h:273
Concrete templatized class derived from AbstractValue, adding generic value type-specific functionali...
Definition Value.h:107
static const Value & downcast(const AbstractValue &value)
Downcast a const reference to an AbstractValue to a const reference to this type Value<T>.
Definition Value.h:219
static Value & updDowncast(AbstractValue &value)
Downcast a writable reference to an AbstractValue to a writable reference to this type Value<T>.
Definition Value.h:225
Unique integer type for Subsystem-local z indexing.
constexpr Real NaN
This is the IEEE "not a number" constant for this implementation of the default-precision Real type; ...
Definition Scalar.h:85
constexpr Real Zero
Real(0)
Definition Scalar.h:138
constexpr Real One
Real(1)
Definition Scalar.h:139
constexpr Real E
e = Real(exp(1))
Definition Scalar.h:154
constexpr Real Infinity
This is the IEEE positive infinity constant for this implementation of the default-precision Real typ...
Definition Scalar.h:89
This is the top-level SimTK namespace into which all SimTK names are placed to avoid collision with o...
Definition Assembler.h:37
unsigned int sign(unsigned char u)
Definition Scalar.h:301
bool isFinite(const negator< float > &x)
Definition negator.h:285
SimTK_Real Real
This is the default compiled-in floating point type for SimTK, either float or double.
Definition SimTKcommon/include/SimTKcommon/internal/common.h:626