Simbody
3.4 (development)
|
00001 #ifndef SimTK_SimTKCOMMON_SYSTEM_H_ 00002 #define SimTK_SimTKCOMMON_SYSTEM_H_ 00003 00004 /* -------------------------------------------------------------------------- * 00005 * Simbody(tm): SimTKcommon * 00006 * -------------------------------------------------------------------------- * 00007 * This is part of the SimTK biosimulation toolkit originating from * 00008 * Simbios, the NIH National Center for Physics-Based Simulation of * 00009 * Biological Structures at Stanford, funded under the NIH Roadmap for * 00010 * Medical Research, grant U54 GM072970. See https://simtk.org/home/simbody. * 00011 * * 00012 * Portions copyright (c) 2006-13 Stanford University and the Authors. * 00013 * Authors: Michael Sherman * 00014 * Contributors: Peter Eastman * 00015 * * 00016 * Licensed under the Apache License, Version 2.0 (the "License"); you may * 00017 * not use this file except in compliance with the License. You may obtain a * 00018 * copy of the License at http://www.apache.org/licenses/LICENSE-2.0. * 00019 * * 00020 * Unless required by applicable law or agreed to in writing, software * 00021 * distributed under the License is distributed on an "AS IS" BASIS, * 00022 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * 00023 * See the License for the specific language governing permissions and * 00024 * limitations under the License. * 00025 * -------------------------------------------------------------------------- */ 00026 00027 #include "SimTKcommon/basics.h" 00028 #include "SimTKcommon/Simmatrix.h" 00029 #include "SimTKcommon/internal/State.h" 00030 #include "SimTKcommon/internal/Subsystem.h" 00031 00032 #include <cassert> 00033 00034 namespace SimTK { 00035 00036 class DecorativeGeometry; 00037 class DefaultSystemSubsystem; 00038 class ScheduledEventHandler; 00039 class ScheduledEventReporter; 00040 class TriggeredEventHandler; 00041 class TriggeredEventReporter; 00042 class RealizeOptions; 00043 class RealizeResults; 00044 class ProjectOptions; 00045 class ProjectResults; 00046 00047 //============================================================================== 00048 // SYSTEM 00049 //============================================================================== 00096 class SimTK_SimTKCOMMON_EXPORT System { 00097 public: 00098 class Guts; // local; name is System::Guts 00099 00100 00101 //------------------------------------------------------------------------------ 00124 System& setUpDirection(const CoordinateDirection& up); 00125 00133 System& setUseUniformBackground(bool useUniformBackground); 00134 00148 System& setDefaultTimeScale(Real tc); 00149 00157 System& setDefaultLengthScale(Real lc); 00158 00164 void setHasTimeAdvancedEvents(bool); // default=false 00165 00167 CoordinateDirection getUpDirection() const; 00170 bool getUseUniformBackground() const; 00173 Real getDefaultTimeScale() const; 00176 Real getDefaultLengthScale() const; 00179 bool hasTimeAdvancedEvents() const; 00183 //------------------------------------------------------------------------------ 00192 inline void addEventHandler(ScheduledEventHandler* handler); 00195 inline void addEventHandler(TriggeredEventHandler* handler); 00198 inline void addEventReporter(ScheduledEventReporter* handler) const; 00201 inline void addEventReporter(TriggeredEventReporter* handler) const; 00205 //------------------------------------------------------------------------------ 00234 const State& realizeTopology() const; 00235 00250 const State& getDefaultState() const; 00253 State& updDefaultState(); 00254 00273 void realizeModel(State& state) const; 00274 00282 void realize(const State& state, Stage stage = Stage::HighestRuntime) const; 00286 //------------------------------------------------------------------------------ 00367 void project(State& state, Real accuracy=-1) const; 00368 00384 void projectQ(State& state, Real accuracy=-1) const; 00385 00403 void projectU(State& state, Real accuracy=-1) const; 00404 00440 void projectQ(State& state, Vector& qErrEst, 00441 const ProjectOptions& options, ProjectResults& results) const; 00442 00466 void projectU(State& state, Vector& uErrEst, 00467 const ProjectOptions& options, ProjectResults& results) const; 00468 00469 00487 void prescribe(State& state) const { 00488 realize(state, Stage::Time); 00489 prescribeQ(state); 00490 realize(state, Stage::Position); 00491 prescribeU(state); 00492 } 00493 00512 bool prescribeQ(State& state) const; 00513 00529 bool prescribeU(State& state) const; 00533 //------------------------------------------------------------------------------ 00572 void handleEvents(State& state, 00573 Event::Cause cause, 00574 const Array_<EventId>& eventIds, 00575 const HandleEventsOptions& options, 00576 HandleEventsResults& results) const; 00577 00581 void reportEvents(const State& state, 00582 Event::Cause cause, 00583 const Array_<EventId>& eventIds) const; 00584 00593 void calcEventTriggerInfo(const State& state, 00594 Array_<EventTriggerInfo>& triggerInfo) const; 00595 00601 void calcTimeOfNextScheduledEvent(const State& state, 00602 Real& tNextEvent, 00603 Array_<EventId>& eventIds, 00604 bool includeCurrentTime) const; 00605 00609 void calcTimeOfNextScheduledReport(const State& state, 00610 Real& tNextEvent, 00611 Array_<EventId>& eventIds, 00612 bool includeCurrentTime) const; 00616 //------------------------------------------------------------------------------ 00645 void relax(State& state, Stage stage, Real accuracy=-1) const; 00649 //------------------------------------------------------------------------------ 00670 void multiplyByN(const State& state, const Vector& u, 00671 Vector& dq) const; 00673 void multiplyByNTranspose(const State& state, const Vector& fq, 00674 Vector& fu) const; 00676 void multiplyByNPInv(const State& state, const Vector& dq, 00677 Vector& u) const; 00679 void multiplyByNPInvTranspose(const State& state, const Vector& fu, 00680 Vector& fq) const; 00684 //------------------------------------------------------------------------------ 00694 void resetAllCountersToZero(); 00695 00696 // Realization 00697 00701 int getNumRealizationsOfThisStage(Stage) const; 00702 00706 int getNumRealizeCalls() const; 00707 00708 // Prescribed motion 00709 00711 int getNumPrescribeQCalls() const; 00713 int getNumPrescribeUCalls() const; 00714 00715 // Projection 00716 00719 int getNumProjectQCalls() const; 00721 int getNumFailedProjectQCalls() const; 00724 int getNumQProjections() const; 00727 int getNumQErrorEstimateProjections() const; 00728 00731 int getNumProjectUCalls() const; 00733 int getNumFailedProjectUCalls() const; 00736 int getNumUProjections() const; 00739 int getNumUErrorEstimateProjections() const; 00740 00741 // Event handling and reporting 00742 00746 int getNumHandlerCallsThatChangedStage(Stage) const; 00747 00750 int getNumHandleEventCalls() const; 00751 00754 int getNumReportEventCalls() const; 00758 //------------------------------------------------------------------------------ 00765 System() : guts(0) { } 00767 System(const System&); 00769 System& operator=(const System&); 00772 ~System(); 00773 00775 const String& getName() const; 00777 const String& getVersion() const; 00778 00781 SubsystemIndex adoptSubsystem(Subsystem& child); 00782 00784 int getNumSubsystems() const; 00786 const Subsystem& getSubsystem(SubsystemIndex) const; 00788 Subsystem& updSubsystem(SubsystemIndex); 00791 const DefaultSystemSubsystem& getDefaultSubsystem() const; 00794 DefaultSystemSubsystem& updDefaultSubsystem(); 00795 00799 inline operator const Subsystem&() const; // implemented below 00803 inline operator Subsystem&(); 00804 00809 bool systemTopologyHasBeenRealized() const; 00810 00818 StageVersion getSystemTopologyCacheVersion() const; 00819 00825 void setSystemTopologyCacheVersion(StageVersion topoVersion) const; 00826 00836 void invalidateSystemTopologyCache() const; 00837 00845 void calcDecorativeGeometryAndAppend(const State&, Stage, 00846 Array_<DecorativeGeometry>&) const; 00847 00848 00851 bool isSameSystem(const System& otherSystem) const; 00852 00853 00857 const Guts& getSystemGuts() const {assert(guts); return *guts;} 00861 Guts& updSystemGuts() {assert(guts); return *guts;} 00862 00866 void adoptSystemGuts(System::Guts* g); 00867 00869 explicit System(System::Guts* g) : guts(g) { } 00871 bool hasGuts() const {return guts!=0;} 00872 00874 bool isOwnerHandle() const; 00876 bool isEmptyHandle() const; 00879 private: 00880 friend class Guts; 00881 // This is the only data member in this class. Also, any class derived from 00882 // System must have *NO* data members at all (data goes in the Guts class). 00883 Guts* guts; 00884 }; 00885 00886 00895 class SimTK_SimTKCOMMON_EXPORT DefaultSystemSubsystem : public Subsystem { 00896 public: 00897 explicit DefaultSystemSubsystem(System& sys); 00898 void addEventHandler(ScheduledEventHandler* handler); 00899 void addEventHandler(TriggeredEventHandler* handler); 00900 void addEventReporter(ScheduledEventReporter* handler) const; 00901 void addEventReporter(TriggeredEventReporter* handler) const; 00902 EventId createEventId(SubsystemIndex subsys, const State& state) const; 00903 void findSubsystemEventIds 00904 (SubsystemIndex subsys, const State& state, 00905 const Array_<EventId>& allEvents, 00906 Array_<EventId>& eventsForSubsystem) const; 00907 // don't let doxygen see this private class 00909 class Guts; 00911 private: 00912 const Guts& getGuts() const; 00913 Guts& updGuts(); 00914 }; 00915 00916 inline void System::addEventHandler(ScheduledEventHandler* handler) 00917 { updDefaultSubsystem().addEventHandler(handler); } 00918 inline void System::addEventHandler(TriggeredEventHandler* handler) 00919 { updDefaultSubsystem().addEventHandler(handler); } 00920 inline void System::addEventReporter(ScheduledEventReporter* handler) const 00921 { getDefaultSubsystem().addEventReporter(handler); } 00922 inline void System::addEventReporter(TriggeredEventReporter* handler) const 00923 { getDefaultSubsystem().addEventReporter(handler); } 00924 00925 inline System::operator const Subsystem&() const {return getDefaultSubsystem();} 00926 inline System::operator Subsystem&() {return updDefaultSubsystem();} 00927 00928 00929 //============================================================================== 00930 // PROJECT OPTIONS and PROJECT RESULTS 00931 //============================================================================== 00935 class ProjectOptions { 00936 public: 00937 enum Option { 00939 None = 0x0000, 00944 LocalOnly = 0x0001, 00948 DontThrow = 0x0002, 00951 UseInfinityNorm = 0x0004, 00955 ForceProjection = 0x0008, 00959 ForceFullNewton = 0x0010 00960 }; 00961 00963 ProjectOptions() {clear();} 00967 explicit ProjectOptions(Real accuracy) 00968 { clear(); setRequiredAccuracy(accuracy); } 00971 explicit ProjectOptions(Option opt) 00972 { clear(); setOption(opt); } 00973 00977 ProjectOptions& clear() 00978 { optionSet=0; setAccuracyDefaults(); return *this; } 00979 00984 ProjectOptions& setRequiredAccuracy(Real accuracy) { 00985 requiredAccuracy = accuracy > 0 ? accuracy 00986 : getDefaultRequiredAccuracy(); 00987 return *this; 00988 } 00989 00992 ProjectOptions& setOvershootFactor(Real overshoot) { 00993 assert(0 < overshoot && overshoot <= 1); 00994 desiredOvershoot = overshoot; 00995 return *this; 00996 } 00997 01000 ProjectOptions& setProjectionLimit(Real limit) { 01001 assert(limit > 0); 01002 projectionLimit = limit; 01003 return *this; 01004 } 01005 01008 ProjectOptions& clearOption(Option opt) 01009 { optionSet &= ~(unsigned)opt; return *this; } 01011 ProjectOptions& setOption (Option opt) 01012 { optionSet |= (unsigned)opt; return *this; } 01013 01015 Real getRequiredAccuracy() const {return requiredAccuracy;} 01018 Real getOvershootFactor() const {return desiredOvershoot;} 01020 Real getProjectionLimit() const {return projectionLimit;} 01021 01022 bool isOptionSet(Option opt) const {return (optionSet&(unsigned)opt) != 0;} 01023 01024 static Real getDefaultRequiredAccuracy() {return Real(1e-4);} 01025 static Real getDefaultOvershootFactor() {return Real(0.1);} //i.e., 1e-5 01026 01027 // Set operators: not, or, and, set difference 01028 ProjectOptions& operator|=(const ProjectOptions& opts) 01029 { optionSet |= opts.optionSet; return *this; } 01030 ProjectOptions& operator&=(const ProjectOptions& opts) 01031 { optionSet &= opts.optionSet; return *this; } 01032 ProjectOptions& operator-=(const ProjectOptions& opts) 01033 { optionSet &= ~opts.optionSet; return *this; } 01034 01035 ProjectOptions& operator|=(Option opt) {setOption(opt); return *this;} 01036 ProjectOptions& operator-=(Option opt) {clearOption(opt); return *this;} 01037 01038 private: 01039 Real requiredAccuracy; 01040 Real desiredOvershoot; // try for accuracy*overshoot 01041 Real projectionLimit; // abort if initial norm is worse than this 01042 unsigned optionSet; 01043 01044 void setAccuracyDefaults() { 01045 requiredAccuracy = getDefaultRequiredAccuracy(); 01046 desiredOvershoot = getDefaultOvershootFactor(); 01047 projectionLimit = Infinity; // we'll try from however far away 01048 } 01049 }; 01050 01052 class ProjectResults { 01053 public: 01054 ProjectResults() {clear();} 01055 01056 enum Status { 01058 Invalid = -1, 01061 Succeeded = 0, 01064 FailedToAchieveAccuracy = 1, 01069 FailedToConverge = 2 01070 }; 01071 01074 ProjectResults& clear() { 01075 m_exitStatus = Invalid; 01076 m_anyChangeMade = m_projectionLimitExceeded = false; 01077 m_numIterations = 0; 01078 m_worstError = -1; 01079 m_normOnEntrance = m_normOnExit = NaN; 01080 return *this; 01081 } 01082 bool isValid() const {return m_exitStatus != Invalid;} 01083 Status getExitStatus() const {return m_exitStatus;} 01084 01085 bool getAnyChangeMade() const {assert(isValid());return m_anyChangeMade;} 01086 int getNumIterations() const {assert(isValid());return m_numIterations;} 01087 Real getNormOnEntrance() const {assert(isValid());return m_normOnEntrance;} 01088 Real getNormOnExit() const {assert(isValid());return m_normOnExit;} 01089 int getWorstErrorOnEntrance() const 01090 { assert(isValid());return m_worstError; } 01091 bool getProjectionLimitExceeded() const 01092 { assert(isValid());return m_projectionLimitExceeded; } 01093 01094 ProjectResults& setExitStatus(Status status) 01095 { m_exitStatus=status; return *this; } 01096 ProjectResults& setAnyChangeMade(bool changeMade) 01097 { m_anyChangeMade=changeMade; return *this; } 01098 ProjectResults& setProjectionLimitExceeded(bool limitExceeded) 01099 { m_projectionLimitExceeded=limitExceeded; return *this; } 01100 ProjectResults& setNumIterations(int numIterations) 01101 { m_numIterations=numIterations; return *this; } 01102 ProjectResults& setNormOnEntrance(Real norm, int worstError) 01103 { m_normOnEntrance=norm; m_worstError=worstError; return *this; } 01104 ProjectResults& setNormOnExit(Real norm) 01105 { m_normOnExit=norm; return *this; } 01106 private: 01107 Status m_exitStatus; 01108 bool m_anyChangeMade; 01109 bool m_projectionLimitExceeded; 01110 int m_numIterations; 01111 int m_worstError; // index of worst error on entrance 01112 Real m_normOnEntrance; // in selected rms or infinity norm 01113 Real m_normOnExit; 01114 }; 01115 01116 01117 01118 //============================================================================== 01119 // REALIZE OPTIONS and REALIZE RESULTS 01120 //============================================================================== 01122 class RealizeOptions { 01123 unsigned int optionSet; 01124 explicit RealizeOptions(unsigned o) : optionSet(o) { } 01125 public: 01126 01127 enum Option { 01128 None = 0x00, 01129 DontThrow = 0x01 01130 }; 01131 01132 01133 RealizeOptions() : optionSet(0) { } 01134 01135 // This is an implicit conversion 01136 RealizeOptions(Option opt) : optionSet((unsigned)opt) { } 01137 01138 // Implicit conversion to bool when needed 01139 operator bool() const {return optionSet != 0;} 01140 bool isEmpty() const {return optionSet==0;} 01141 01142 bool isOptionSet(Option opt) const {return (optionSet&(unsigned)opt) != 0;} 01143 void clear() {optionSet=0;} 01144 void clearOption(Option opt) {optionSet &= ~(unsigned)opt;} 01145 void setOption (Option opt) {optionSet |= (unsigned)opt;} 01146 01147 // Set operators: or, and 01148 RealizeOptions& operator|=(RealizeOptions opts) {optionSet |= opts.optionSet; return *this;} 01149 RealizeOptions& operator&=(RealizeOptions opts) {optionSet &= opts.optionSet; return *this;} 01150 01151 RealizeOptions& operator|=(Option opt) {setOption(opt); return *this;} 01152 RealizeOptions& operator-=(Option opt) {clearOption(opt); return *this;} 01153 }; 01154 01156 class RealizeResults { 01157 }; 01158 01159 01160 01161 01162 } // namespace SimTK 01163 01164 #endif // SimTK_SimTKCOMMON_SYSTEM_H_