00001 #ifndef OPENTISSUE_DYNAMICS_MBD_UTIL_MBD_KINETIC_ENERGY_SLEEPY_POLICY_H 00002 #define OPENTISSUE_DYNAMICS_MBD_UTIL_MBD_KINETIC_ENERGY_SLEEPY_POLICY_H 00003 // 00004 // OpenTissue, A toolbox for physical based simulation and animation. 00005 // Copyright (C) 2007 Department of Computer Science, University of Copenhagen 00006 // 00007 #include <OpenTissue/configuration.h> 00008 00009 namespace OpenTissue 00010 { 00011 namespace mbd 00012 { 00013 00020 template< typename mbd_types> 00021 class KineticEnergySleepyPolicy 00022 { 00023 protected: 00024 00025 typedef typename mbd_types::math_policy::real_type real_type; 00026 typedef typename mbd_types::math_policy::value_traits value_traits; 00027 typedef typename mbd_types::math_policy::vector3_type vector3_type; 00028 typedef typename mbd_types::group_type group_type; 00029 typedef typename mbd_types::body_type body_type; 00030 typedef typename group_type::indirect_body_iterator indirect_body_iterator; 00031 00032 protected: 00033 00034 int m_max_entries; 00035 00036 public: 00037 00038 class node_traits 00039 { 00040 public: 00041 00042 real_type m_ksp_energy[5]; 00043 int m_ksp_energy_idx; 00044 00045 public: 00046 00047 node_traits() 00048 : m_ksp_energy_idx(0) 00049 { 00050 //--- Initialize kinetic energy to some absurd high value 00051 for(int i=0;i<5;++i) 00052 m_ksp_energy[i]= value_traits::infinity(); 00053 } 00054 00055 }; 00056 00057 class edge_traits{}; 00058 class constraint_traits{}; 00059 00060 public: 00061 00062 KineticEnergySleepyPolicy() 00063 : m_max_entries(5) 00064 {} 00065 00072 void evaluate(body_type * body) 00073 { 00074 //--- Fixed bodies must trivially be sleepy, so there is no need to perform any calculations 00075 if(body->is_fixed()) 00076 { 00077 body->set_sleepy(true); 00078 return; 00079 } 00080 00081 // bool was_sleepy = body->is_sleepy(); 00082 //--- Compute kinetic energy and store it in the node traits 00083 body->m_ksp_energy[body->m_ksp_energy_idx] = body->compute_kinetic_energy(); 00084 int last_idx = body->m_ksp_energy_idx; 00085 body->m_ksp_energy_idx = (body->m_ksp_energy_idx + 1)%m_max_entries; 00086 00087 //--- Loop over the kinetic energy stored in the last 00088 //--- m_max_entries iterations, and test that the energy in 00089 //--- each iteration is below a threshold. This is an absolute test. 00090 real_type threshold = body->get_mass()*0.00001; 00091 //real_type threshold = body->get_mass()*0.004802; 00092 for(int i=0;i<m_max_entries;++i) 00093 { 00094 int cur = (last_idx-i)%m_max_entries; 00095 if(cur<0) cur += m_max_entries; 00096 int prev = (cur-1)%m_max_entries; 00097 if(prev<0) prev += m_max_entries; 00098 if(body->m_ksp_energy[cur] > threshold ) 00099 { 00100 body->set_sleepy(false); 00101 return; 00102 } 00103 } 00104 00105 //--- Loop over the kinetic energies one more time, this time 00106 //--- computing the energy change over the last m_max_entries 00107 real_type dE = value_traits::zero(); 00108 for(int i=0;i<m_max_entries;++i) 00109 { 00110 int cur = (last_idx-i)%m_max_entries; 00111 if(cur<0) cur += m_max_entries; 00112 int prev = (cur-1)%m_max_entries; 00113 if(prev<0) prev += m_max_entries; 00114 dE += body->m_ksp_energy[cur] - body->m_ksp_energy[prev]; 00115 } 00116 //if(was_sleepy && 2.*dE < threshold) 00117 //{ 00118 // body->set_sleepy(true); 00119 // return; 00120 //} 00121 //--- If the energy is decreasing then we say that the body 00122 //--- is sleepy, this is the relative test. 00123 real_type slack = 0.0001*threshold; 00124 if(dE>slack) 00125 body->set_sleepy(false); 00126 else 00127 body->set_sleepy(true); 00128 } 00129 00139 void evaluate(indirect_body_iterator begin,indirect_body_iterator end) 00140 { 00141 for(indirect_body_iterator body=begin;body!=end;++body) 00142 evaluate(&(*body)); 00143 } 00144 00145 void clear(){} 00146 00147 }; 00148 00149 } // namespace mbd 00150 00151 } // namespace OpenTissue 00152 00153 #endif // OPENTISSUE_DYNAMICS_MBD_UTIL_MBD_KINETIC_ENERGY_SLEEPY_POLICY_H