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