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