Go to the documentation of this file.00001 #ifndef OPENTISSUE_DYNAMICS_MESHLESS_DEFORMATION_MESHLESS_DEFORMATION_CLUSTER_H
00002 #define OPENTISSUE_DYNAMICS_MESHLESS_DEFORMATION_MESHLESS_DEFORMATION_CLUSTER_H
00003
00004
00005
00006
00007
00008
00009
00010 #include <OpenTissue/configuration.h>
00011
00012 #include <OpenTissue/dynamics/meshless_deformation/meshless_deformation_particle.h>
00013 #include <OpenTissue/core/math/math_polar_decomposition.h>
00014 #include <OpenTissue/core/math/big/big_lu.h>
00015
00016 #include <boost/iterator/indirect_iterator.hpp>
00017 #include <boost/cast.hpp>
00018
00019 #include <list>
00020
00021 namespace OpenTissue
00022 {
00023 namespace meshless_deformation
00024 {
00025 namespace detail
00026 {
00027
00031 template<typename math_types>
00032 class Cluster
00033 {
00034 public:
00035
00036 typedef Particle<math_types> particle_type;
00037 typedef typename math_types::value_traits value_traits;
00038 typedef typename math_types::real_type real_type;
00039 typedef typename math_types::vector3_type vector3_type;
00040 typedef typename math_types::matrix3x3_type matrix3x3_type;
00041 typedef typename std::list<particle_type*> particle_ptr_container;
00042 typedef typename particle_ptr_container::iterator particle_ptr_iterator;
00043 typedef boost::indirect_iterator<particle_ptr_iterator,particle_type> particle_iterator;
00044
00045 protected:
00046
00047 particle_ptr_container m_particles;
00048
00049 private:
00050
00051 vector3_type m_t;
00052 vector3_type m_t0;
00053 real_type m_mass;
00054 matrix3x3_type m_A_qq[3][3];
00055 matrix3x3_type m_A_pq[3];
00056 matrix3x3_type m_A;
00057 matrix3x3_type m_Q;
00058 matrix3x3_type m_M;
00059 matrix3x3_type m_R;
00060 matrix3x3_type m_S;
00061 matrix3x3_type m_Sp;
00062
00063 private:
00064
00065
00066
00067 real_type m_beta;
00068 real_type m_tau;
00069 real_type m_c_yield;
00070 real_type m_c_creep;
00071 real_type m_c_max;
00072
00073 public:
00074
00075 Cluster()
00076 : m_Sp(
00077 value_traits::one() ,value_traits::zero(),value_traits::zero()
00078 , value_traits::zero(),value_traits::one() ,value_traits::zero()
00079 , value_traits::zero(),value_traits::zero(),value_traits::one()
00080 )
00081 , m_beta(value_traits::half() )
00082 , m_tau( value_traits::one() )
00083 , m_c_yield( value_traits::infinity() )
00084 , m_c_creep( value_traits::zero() )
00085 , m_c_max( value_traits::zero() )
00086 {}
00087
00088 public:
00089
00090 void bind_particle(particle_type & particle) { m_particles.push_back(&particle); }
00091
00092 void set_beta(real_type const & beta)
00093 {
00094 assert(beta>=value_traits::zero() || !"set_beta(): beta must be non-negative");
00095 assert(beta<=value_traits::one() || !"set_beta(): beta must be less than one");
00096 m_beta = beta;
00097 }
00098
00099 real_type const & get_beta()const { return m_beta; }
00100
00101 void set_tau(real_type const & tau)
00102 {
00103 assert(tau>=value_traits::zero() || !"set_tau(): tau must be non-negative");
00104 m_tau = tau;
00105 }
00106
00107 real_type const & get_tau()const { return m_tau; }
00108
00109 void set_yield(real_type const & c_yield)
00110 {
00111 assert(c_yield>=value_traits::zero() || !"set_yield(): yield must be non-negative");
00112 m_c_yield = c_yield;
00113 }
00114
00115 real_type const & get_yield()const { return m_c_yield; }
00116
00117 void set_creep(real_type const & c_creep)
00118 {
00119 assert(c_creep>=value_traits::zero() || !"set_creep(): creep must be non-negative");
00120 m_c_creep = c_creep;
00121 }
00122
00123 real_type const & get_creep()const { return m_c_creep; }
00124
00125 void set_max(real_type const & c_max)
00126 {
00127 assert(c_max>=value_traits::zero() || !"set_max(): max must be non-negative");
00128 m_c_max = c_max;
00129 }
00130
00131 real_type const & get_max()const { return m_c_max; }
00132
00133 public:
00134
00135 void init()
00136 {
00137 particle_iterator begin = m_particles.begin();
00138 particle_iterator end = m_particles.end();
00139 particle_iterator particle;
00140
00141 m_mass = value_traits::zero();
00142 for(particle=begin;particle!=end;++particle)
00143 m_mass += particle->m_mass;
00144
00145 m_t0.clear();
00146 for(particle=begin;particle!=end;++particle)
00147 m_t0 += particle->m_mass * particle->m_x0;
00148 m_t0 /= m_mass;
00149
00150 compute_q();
00151 }
00152
00153 void run(real_type const & dt)
00154 {
00155 if( m_c_yield < value_traits::infinity() )
00156 compute_q();
00157
00158 compute_p();
00159
00160 matrix3x3_type B = m_A_pq[0] * m_A_qq[0][0];
00161 OpenTissue::math::polar_decomposition::eigen( B, m_R, m_S);
00162
00163 plasticity_update(dt);
00164
00165 compute_goal(dt);
00166 }
00167
00168 private:
00169
00170 void compute_q()
00171 {
00172 particle_iterator begin = m_particles.begin();
00173 particle_iterator end = m_particles.end();
00174 particle_iterator particle;
00175
00176 for(particle=begin;particle!=end;++particle)
00177 particle->m_q[0] = m_Sp*(particle->m_x0 - m_t0);
00178
00179 for(particle=begin;particle!=end;++particle)
00180 particle->m_q[1] = vector3_type (
00181 particle->m_q[0](0)*particle->m_q[0](0)
00182 , particle->m_q[0](1)*particle->m_q[0](1)
00183 , particle->m_q[0](2)*particle->m_q[0](2)
00184 );
00185
00186 for(particle=begin;particle!=end;++particle)
00187 particle->m_q[2] = vector3_type (
00188 particle->m_q[0](0)*particle->m_q[0](1)
00189 , particle->m_q[0](1)*particle->m_q[0](2)
00190 , particle->m_q[0](2)*particle->m_q[0](0)
00191 );
00192
00193
00194
00195
00196 m_A_qq[0][0].clear();
00197 m_A_qq[0][1].clear();
00198 m_A_qq[0][2].clear();
00199
00200 m_A_qq[1][0].clear();
00201 m_A_qq[1][1].clear();
00202 m_A_qq[1][2].clear();
00203
00204 m_A_qq[2][0].clear();
00205 m_A_qq[2][1].clear();
00206 m_A_qq[2][2].clear();
00207 for(particle=begin;particle!=end;++particle)
00208 {
00209 m_A_qq[0][0] += particle->m_mass * outer_prod(particle->m_q[0],particle->m_q[0]);
00210 m_A_qq[1][1] += particle->m_mass * outer_prod(particle->m_q[1],particle->m_q[1]);
00211 m_A_qq[2][2] += particle->m_mass * outer_prod(particle->m_q[2],particle->m_q[2]);
00212 m_A_qq[0][1] += particle->m_mass * outer_prod(particle->m_q[0],particle->m_q[1]);
00213 m_A_qq[1][2] += particle->m_mass * outer_prod(particle->m_q[1],particle->m_q[2]);
00214 m_A_qq[2][0] += particle->m_mass * outer_prod(particle->m_q[2],particle->m_q[0]);
00215 }
00216 m_A_qq[1][0] = trans(m_A_qq[0][1]);
00217 m_A_qq[2][1] = trans(m_A_qq[1][2]);
00218 m_A_qq[0][2] = trans(m_A_qq[2][0]);
00219
00220 {
00221 typename ublas::matrix<real_type> A(9,9),invA(9,9);
00222
00223 for(size_t r=0;r<9;++r)
00224 for(size_t c=0;c<9;++c)
00225 A(r,c) = m_A_qq[r/3][c/3](r%3,c%3);
00226
00227
00228 math::big::lu_invert(A,invA);
00229
00230 for(size_t r=0;r<9;++r)
00231 for(size_t c=0;c<9;++c)
00232 m_A_qq[r/3][c/3](r%3,c%3) = invA(r,c);
00233 }
00234 }
00235
00236 void compute_p()
00237 {
00238 particle_iterator begin = m_particles.begin();
00239 particle_iterator end = m_particles.end();
00240 particle_iterator particle;
00241
00242 m_t.clear();
00243 for(particle=begin;particle!=end;++particle)
00244 m_t += particle->m_mass * particle->x();
00245 m_t /= m_mass;
00246
00247 for(particle=begin;particle!=end;++particle)
00248 particle->m_p = particle->x() - m_t;
00249
00250
00251
00252
00253 m_A_pq[0].clear();
00254 m_A_pq[1].clear();
00255 m_A_pq[2].clear();
00256 for(particle=begin;particle!=end;++particle)
00257 {
00258 m_A_pq[0] += particle->m_mass * outer_prod(particle->m_p,particle->m_q[0]);
00259 m_A_pq[1] += particle->m_mass * outer_prod(particle->m_p,particle->m_q[1]);
00260 m_A_pq[2] += particle->m_mass * outer_prod(particle->m_p,particle->m_q[2]);
00261 }
00262 }
00263
00264 void compute_goal(real_type const & dt)
00265 {
00266 using std::min;
00267
00268 static real_type const third = value_traits::one()/value_traits::three();
00269 static real_type const tiny = boost::numeric_cast<real_type>(10e-7);
00270
00271 particle_iterator begin = m_particles.begin();
00272 particle_iterator end = m_particles.end();
00273 particle_iterator particle;
00274
00275 m_A = m_A_pq[0]*m_A_qq[0][0] + m_A_pq[1]*m_A_qq[1][0] + m_A_pq[2]*m_A_qq[2][0];
00276 m_Q = m_A_pq[0]*m_A_qq[0][1] + m_A_pq[1]*m_A_qq[1][1] + m_A_pq[2]*m_A_qq[2][1];
00277 m_M = m_A_pq[0]*m_A_qq[0][2] + m_A_pq[1]*m_A_qq[1][2] + m_A_pq[2]*m_A_qq[2][2];
00278 {
00279 m_A /= pow(det(m_A),third);
00280
00281
00282
00283 }
00284
00285 m_A = m_beta*m_A + (value_traits::one() - m_beta)*m_R;
00286 m_Q = m_beta*m_Q;
00287 m_M = m_beta*m_M;
00288
00289
00290 m_Q = truncate(m_Q,tiny);
00291 m_M = truncate(m_M,tiny);
00292
00293 for(particle=begin;particle!=end;++particle)
00294 particle->m_g = (m_A * particle->m_q[0]) + (m_Q * particle->m_q[1]) + (m_M * particle->m_q[2]) + m_t;
00295
00296 real_type alpha = min( m_tau/dt, value_traits::one() );
00297 for(particle=begin;particle!=end;++particle)
00298 particle->m_f_goal += alpha*(particle->m_g - particle->x())/dt;
00299 }
00300
00301 void plasticity_update( real_type const & dt )
00302 {
00303 static real_type const third = value_traits::one()/value_traits::three();
00304 static matrix3x3_type const I = math::diag(value_traits::one());
00305
00306 if(norm_2(m_S-I) < m_c_yield)
00307 return;
00308 m_Sp = (I + dt*m_c_creep*(m_S-I))*m_Sp;
00309 if(norm_2(m_Sp-I) >= m_c_max)
00310 m_Sp = I + m_c_max*(m_Sp-I)/ norm_2(m_Sp-I);
00311 m_Sp /= pow(det(m_Sp),third);
00312 }
00313
00314 };
00315
00316 }
00317 }
00318 }
00319
00320
00321 #endif