00001 #ifndef OPENTISSUE_DYNAMICS_MBD_UTIL_STEPPERS_MBD_DYNAMICS_STEPPER_H
00002 #define OPENTISSUE_DYNAMICS_MBD_UTIL_STEPPERS_MBD_DYNAMICS_STEPPER_H
00003
00004
00005
00006
00007
00008
00009
00010 #include <OpenTissue/configuration.h>
00011
00012 #include <OpenTissue/dynamics/mbd/interfaces/mbd_stepper_interface.h>
00013
00014 #include <OpenTissue/dynamics/mbd/mbd_get_ncp_formulation.h>
00015 #include <OpenTissue/dynamics/mbd/mbd_get_cached_solution_vector.h>
00016 #include <OpenTissue/dynamics/mbd/mbd_set_cached_solution_vector.h>
00017 #include <OpenTissue/dynamics/mbd/mbd_get_external_force_vector.h>
00018 #include <OpenTissue/dynamics/mbd/mbd_get_position_vector.h>
00019 #include <OpenTissue/dynamics/mbd/mbd_set_position_vector.h>
00020 #include <OpenTissue/dynamics/mbd/mbd_compute_position_update.h>
00021 #include <OpenTissue/dynamics/mbd/mbd_get_velocity_vector.h>
00022 #include <OpenTissue/dynamics/mbd/mbd_set_velocity_vector.h>
00023
00024 #include <OpenTissue/utility/utility_timer.h>
00025
00026 namespace OpenTissue
00027 {
00028 namespace mbd
00029 {
00030
00031 template< typename mbd_types, typename solver_type >
00032 class DynamicsStepper
00033 : public StepperInterface<mbd_types>
00034 {
00035 public:
00036
00037 typedef typename mbd_types::math_policy math_policy;
00038 typedef typename math_policy::value_traits value_traits;
00039 typedef typename math_policy::index_type size_type;
00040 typedef typename math_policy::real_type real_type;
00041 typedef typename math_policy::vector_type vector_type;
00042 typedef typename math_policy::matrix_type matrix_type;
00043 typedef typename math_policy::idx_vector_type idx_vector_type;
00044 typedef typename mbd_types::group_type group_type;
00045
00046 protected:
00047
00048 solver_type m_solver;
00049 vector_type m_f_ext;
00050 vector_type m_s;
00051 matrix_type m_invM;
00052 matrix_type m_J;
00053 idx_vector_type m_pi;
00054 vector_type m_mu;
00055 vector_type m_b;
00056 vector_type m_rhs;
00057 vector_type m_gamma;
00058 vector_type m_lo;
00059 vector_type m_hi;
00060 vector_type m_x;
00061 vector_type m_u;
00062 vector_type m_tmp;
00063
00064 public:
00065
00066 class node_traits{};
00067 class edge_traits{};
00068 class constraint_traits{};
00069
00070 protected:
00071
00072 bool m_warm_starting;
00073 bool m_use_stabilization;
00074 bool m_use_friction;
00075 bool m_use_bounce;
00076
00077 real_type m_query_time;
00078 real_type m_assembly_time;
00079 real_type m_solver_time;
00080 real_type m_update_time;
00081 real_type m_total_time;
00082
00083 public:
00084
00085 bool & warm_starting() { return m_warm_starting; }
00086 bool & use_stabilization() { return m_use_stabilization; }
00087 bool & use_friction() { return m_use_friction; }
00088 bool & use_bounce() { return m_use_bounce; }
00089
00090 bool const & warm_starting() const { return m_warm_starting; }
00091 bool const & use_stabilization() const { return m_use_stabilization; }
00092 bool const & use_friction() const { return m_use_friction; }
00093 bool const & use_bounce() const { return m_use_bounce; }
00094
00095 real_type const & query_time() const { return m_query_time; }
00096 real_type const & assembly_time() const { return m_assembly_time; }
00097 real_type const & solver_time() const { return m_solver_time; }
00098 real_type const & update_time() const { return m_update_time; }
00099 real_type const & total_time() const { return m_total_time; }
00100
00101 solver_type const * get_solver() const { return &m_solver; }
00102 solver_type * get_solver() { return &m_solver; }
00103
00104 public:
00105
00106 DynamicsStepper()
00107 : m_warm_starting(false)
00108 , m_use_stabilization(false)
00109 , m_use_friction(true)
00110 , m_use_bounce(true)
00111 {}
00112
00113 virtual ~DynamicsStepper(){}
00114
00115 public:
00116
00117 void run(group_type & group, real_type const & time_step)
00118 {
00119 OpenTissue::utility::Timer<real_type> watch1,watch2;
00120
00121 watch1.start();
00122 watch2.start();
00123
00124 if( time_step < value_traits::zero() )
00125 throw std::invalid_argument("DynamicsStepper::run(): time step must be non-negative");
00126
00127 real_type fps = (time_step>value_traits::zero()) ? (value_traits::one()/time_step) : value_traits::zero();
00128
00129 mbd::get_ncp_formulation(
00130 group
00131 , fps
00132 , m_J
00133 , m_invM
00134 , m_lo
00135 , m_hi
00136 , m_pi
00137 , m_mu
00138 , m_gamma
00139 , m_rhs
00140 , this->use_stabilization()
00141 , this->use_friction()
00142 , this->use_bounce()
00143 , this->use_stabilization()
00144 );
00145
00146 watch1.stop();
00147 m_query_time = watch1();
00148 watch1.start();
00149
00150 mbd::get_velocity_vector(group, m_u);
00151
00152 mbd::get_external_force_vector(group, m_f_ext, true);
00153
00154 math_policy::prod(m_f_ext,time_step);
00155
00156 size_type m;
00157 size_type n;
00158 math_policy::get_dimensions(m_J,m,n);
00159
00160 if(m>0)
00161 {
00162
00163
00164 math_policy::resize(m_b,m);
00165 if(time_step>value_traits::zero())
00166 {
00167
00168 math_policy::prod(m_invM , m_f_ext, m_u, m_tmp );
00169 math_policy::prod_minus(m_J, m_tmp, m_rhs, m_b);
00170 }
00171 else
00172 {
00173
00174 math_policy::prod_minus(m_J,m_u,m_rhs,m_b);
00175 }
00176 math_policy::prod(m_gamma,fps);
00177
00178 watch1.stop();
00179 m_assembly_time = watch1();
00180 watch1.start();
00181
00182 math_policy::resize(m_x,m);
00183
00184 if(this->warm_starting())
00185 mbd::get_cached_solution_vector(group,m,m_x);
00186
00187 m_solver.run( m_J, m_invM, m_gamma, m_b, m_lo, m_hi, m_pi, m_mu, m_x );
00188
00189 if(this->warm_starting())
00190 mbd::set_cached_solution_vector(group,m,m_x);
00191
00192 watch1.stop();
00193 m_solver_time = watch1();
00194 watch1.start();
00195
00196 }
00197
00198
00199 if(time_step>value_traits::zero())
00200 {
00201
00202 if(m>0)
00203 {
00204 math_policy::prod_trans(m_J, m_x, m_f_ext, m_tmp);
00205 math_policy::prod_add( m_invM, m_tmp, m_u);
00206 }
00207 else
00208 math_policy::prod_add( m_invM, m_f_ext, m_u);
00209 }
00210 else
00211 {
00212
00213 if(m>0)
00214 {
00215 math_policy::prod_trans(m_J, m_x, m_tmp);
00216 math_policy::prod_add( m_invM, m_tmp, m_u);
00217 }
00218 }
00219 mbd::set_velocity_vector(group,m_u);
00220
00221
00222 if(time_step>value_traits::zero())
00223 {
00224 mbd::get_position_vector(group, m_s);
00225 mbd::compute_position_update(group,m_s,m_u,time_step,m_s);
00226 mbd::set_position_vector(group,m_s);
00227
00228 }
00229
00230 watch1.stop();
00231 watch2.stop();
00232 m_update_time = watch1();
00233 m_total_time = watch2();
00234 }
00235
00236 void error_correction(group_type & )
00237 {
00238 throw std::logic_error("DynamicsStepper(): error correction is not defined for this type of stepper");
00239 }
00240
00241 void resolve_collisions(group_type & group)
00242 {
00243 bool tmp1 = this->use_stabilization();
00244 this->use_stabilization() = false;
00245
00246 run(group,value_traits::zero());
00247
00248 this->use_stabilization() = tmp1;
00249 }
00250
00251 };
00252
00253 }
00254 }
00255
00256 #endif