00001 #ifndef OPENTISSUE_DYNAMICS_EDM_EDM_SOLID_H
00002 #define OPENTISSUE_DYNAMICS_EDM_EDM_SOLID_H
00003
00004
00005
00006
00007
00008
00009
00010 #include <OpenTissue/configuration.h>
00011
00012 #include <OpenTissue/core/math/math_functions.h>
00013
00014 #include <cmath>
00015 #include <cassert>
00016 #include <vector>
00017
00018
00019 namespace OpenTissue
00020 {
00021
00022 namespace edm
00023 {
00024
00025 template<typename edm_types>
00026 class Solid
00027 : public edm_types::model_type
00028 {
00029 public:
00030 typedef typename edm_types::model_type base_type;
00031 typedef typename edm_types::value_traits value_traits;
00032 typedef typename edm_types::real_type real_type;
00033 typedef typename edm_types::vector3_type vector3_type;
00034 typedef typename edm_types::tensor2_type tensor2_type;
00035 typedef typename edm_types::tensor3_type tensor3_type;
00036 typedef typename edm_types::Particle particle_type;
00037 typedef typename base_type::EDMMatrix EDMMatrix;
00038 typedef typename base_type::EDMVector EDMVector;
00039
00040 struct SolidParticle
00041 : public particle_type
00042 {
00043 SolidParticle()
00044 : particle_type()
00045 {}
00046 virtual ~SolidParticle() {}
00047
00048 tensor3_type e;
00049 tensor3_type p;
00050 tensor2_type u;
00051 tensor3_type G0;
00052 tensor3_type P0;
00053 tensor2_type N0;
00054 };
00055
00056 typedef std::vector<SolidParticle> SolidParticles;
00057
00058 protected:
00059
00060 size_t m_L, m_M, m_N;
00061 bool m_wrap_L, m_wrap_M, m_wrap_N;
00062
00063 private:
00064
00065 real_type m_h1, m_h2, m_h3;
00066 SolidParticles m_P;
00067
00068 public:
00069
00070 Solid()
00071 : base_type(edm_types::EDM_Solid)
00072 , m_L(0)
00073 , m_M(0)
00074 , m_N(0)
00075 , m_wrap_L(false)
00076 , m_wrap_M(false)
00077 , m_wrap_N(false)
00078 , m_h1(value_traits::one())
00079 , m_h2(value_traits::one())
00080 , m_h3(value_traits::one())
00081 {}
00082
00083 virtual ~Solid() {}
00084
00085 public:
00086
00087 bool initialize(size_t L, size_t M, size_t N)
00088 {
00089 if ( !m_P.empty() || L < 3 || M < 3 || N < 3 )
00090 return false;
00091
00092
00093 m_P.resize((m_L = L)*(m_M = M)*(m_N = N));
00094 real_type const du = m_h1 = value_traits::one() / ( L - 1 );
00095 real_type const dv = m_h2 = value_traits::one() / ( M - 1 );
00096 real_type const dw = m_h3 = value_traits::one() / ( N - 1 );
00097 real_type u, v, w;
00098 u = v = w = value_traits::zero();
00099 for ( size_t n = 0; n < N; n++, w += dw, v = 0 )
00100 for ( size_t m = 0; m < M; m++, v += dv, u = 0 )
00101 for ( size_t l = 0; l < L; l++, u += du )
00102 grid( l, m, n ).r = position( this->m_rest, u, v, w );
00103
00104
00105 for ( size_t n = 0; n < N; ++n )
00106 for ( size_t m = 0; m < M; ++m )
00107 for ( size_t l = 0; l < L; ++l )
00108 {
00109 SolidParticle & a = grid( l, m, n );
00110 a.G0 = metrix( l, m, n );
00111 a.N0 = spatial( l, m, n );
00112 a.P0 = pillar( l, m, n );
00113 }
00114
00115 u = v = w = value_traits::zero();
00116 for ( size_t n = 0; n < N; n++, w += dw, v = 0 )
00117 for ( size_t m = 0; m < M; m++, v += dv, u = 0 )
00118 for ( size_t l = 0; l < L; l++, u += du )
00119 {
00120 SolidParticle & a = grid( l, m, n );
00121 a.r = position( this->m_init, u, v, w );
00122 a.o = a.r;
00123 a.v *= value_traits::zero();
00124
00125
00126
00127 if ( l == 0 || l == L - 1 )
00128 {
00129 a.t.u = math::clamp_zero_one(w);
00130 a.t.v = math::clamp_zero_one(v);
00131 }
00132 else if ( m == 0 || m == M - 1 )
00133 {
00134 a.t.u = math::clamp_zero_one(w);
00135 a.t.v = math::clamp_zero_one(u);
00136 }
00137 else if ( n == 0 || n == N - 1 )
00138 {
00139 a.t.u = math::clamp_zero_one(v);
00140 a.t.v = math::clamp_zero_one(u);
00141 }
00142 }
00143
00144
00145 compute_surface_normals();
00146
00147 return true;
00148 }
00149
00150 Solid & wrapping(bool L, bool M, bool N)
00151 {
00152 m_wrap_L = L;
00153 m_wrap_M = M;
00154 m_wrap_N = N;
00155 return *this;
00156 }
00157
00158 size_t get_num_L(bool include_wrapping = false) const
00159 {
00160 return size_t(m_L + (!include_wrapping ? 0 : m_wrap_L ? 1 : 0));
00161 }
00162
00163 size_t get_num_M(bool include_wrapping = false) const
00164 {
00165 return size_t(m_M + (!include_wrapping ? 0 : m_wrap_M ? 1 : 0));
00166 }
00167
00168 size_t get_num_N(bool include_wrapping = false) const
00169 {
00170 return size_t(m_N + (!include_wrapping ? 0 : m_wrap_N ? 1 : 0));
00171 }
00172
00173 SolidParticle const & particle(size_t l, size_t m, size_t n) const
00174 {
00175 return grid(l, m, n);
00176 }
00177
00178
00179 size_t nodes() const
00180 {
00181 return size_t(this->m_max_nodes);
00182 }
00183
00184 size_t index_adjust(long l, long m, long n) const
00185 {
00186
00187 using std::min;
00188 using std::max;
00189
00190 size_t const l_ = m_wrap_L ? l % ( ( l < 0 ? -1 : 1 ) * static_cast<long>( m_L ) ) + ( l < 0 ? m_L : 0 ) : static_cast<size_t>( max( 0L, min( l, static_cast<long>( m_L - 1 ) ) ) );
00191 size_t const m_ = m_wrap_M ? m % ( ( m < 0 ? -1 : 1 ) * static_cast<long>( m_M ) ) + ( m < 0 ? m_M : 0 ) : static_cast<size_t>( max( 0L, min( m, static_cast<long>( m_M - 1 ) ) ) );
00192 size_t const n_ = m_wrap_N ? n % ( ( n < 0 ? -1 : 1 ) * static_cast<long>( m_N ) ) + ( n < 0 ? m_N : 0 ) : static_cast<size_t>( max( 0L, min( n, static_cast<long>( m_N - 1 ) ) ) );
00193 return size_t(n_*(m_L*m_M) + m_*m_L + l_);
00194 }
00195
00196 Solid & set_natural_position(size_t idx, vector3_type const & r)
00197 {
00198 assert(idx < this->m_max_nodes || !"set_natural_position: idx out of range.");
00199 this->m_rest[idx] = r;
00200 return set_initial_position(idx, r);
00201 }
00202
00203 Solid & set_initial_position(size_t idx, vector3_type const & r)
00204 {
00205 assert(idx < this->m_max_nodes || !"set_natural_position: idx out of range.");
00206 this->m_init[idx] = r;
00207 return *this;
00208 }
00209
00210
00211 Solid & set_fixed(size_t l, size_t m, size_t n, bool fixed)
00212 {
00213 assert(l < m_L && m < m_M && n < m_N);
00214 grid(l, m, n).f = fixed ;
00215 return *this;
00216 }
00217
00218 Solid & set_mass(size_t l, size_t m, size_t n, real_type const & mass)
00219 {
00220 assert(l < m_L && m < m_M && n < m_N);
00221 grid(l, m, n).m = mass;
00222 return *this;
00223 }
00224
00225 Solid & set_damping(size_t l, size_t m, size_t n, real_type const & damping)
00226 {
00227 assert(l < m_L && m < m_M && n < m_N);
00228 grid(l, m, n).g = damping;
00229 return *this;
00230 }
00231
00232 Solid & set_tension(size_t l, size_t m, size_t n, tensor3_type const & tension)
00233 {
00234 assert(l < m_L && m < m_M && n < m_N);
00235 grid(l, m, n).e = tension;
00236 set_pillar(l, m, n, tension);
00237 return *this;
00238 }
00239
00240 Solid & set_pillar(size_t l, size_t m, size_t n, tensor3_type const & pillar)
00241 {
00242 assert(l < m_L && m < m_M && n < m_N);
00243 grid(l, m, n).p = pillar;
00244 return *this;
00245 }
00246
00247 Solid & set_spatial(size_t l, size_t m, size_t n, tensor2_type const & spatial)
00248 {
00249 assert(l < m_L && m < m_M && n < m_N);
00250 grid(l, m, n).u = spatial;
00251 return *this;
00252 }
00253
00254 protected:
00255
00256 bool index_check(long l, long m, long n) const
00257 {
00258 return ( m_wrap_L ? true : 0 <= l && l < static_cast<long>( m_L ) ) && ( m_wrap_M ? true : 0 <= m && m < static_cast<long>( m_M ) ) && ( m_wrap_N ? true : 0 <= n && n < static_cast<long>( m_N ) );
00259 }
00260
00261 SolidParticle const & grid_adjust(long l, long m, long n) const
00262 {
00263 return m_P[index_adjust(l, m, n)];
00264 }
00265
00266 vector3_type const & r(long l, long m, long n) const
00267 {
00268 return grid_adjust(l, m, n).r;
00269 }
00270
00271 private:
00272
00273 virtual vector3_type position(vector3_type const * a, real_type const & u, real_type const & v, real_type const & w ) const = 0;
00274 virtual vector3_type normal(size_t l, size_t m, size_t n) const = 0;
00275
00276 private:
00277
00278 void compute_stiffness(EDMMatrix & K) const
00279 {
00280 typedef std::vector<tensor3_type> Tensors;
00281 typedef std::vector<tensor2_type> Tensorx;
00282
00283
00284 Tensors alpha( m_P.size() );
00285 Tensors rho( m_P.size() );
00286 Tensorx nu( m_P.size() );
00287 for ( size_t n = 0; n < m_N; ++n )
00288 for ( size_t m = 0; m < m_M; ++m )
00289 for ( size_t l = 0; l < m_L; ++l )
00290 {
00291 size_t const i = index_adjust( l, m, n );
00292 SolidParticle const & a = grid( l, m, n );
00293
00294 tensor3_type& alpha_ = alpha[ i ];
00295 tensor3_type m_ = metrix( l, m, n );
00296 alpha_.t0[ 0 ] = this->m_strength * a.e.t0[ 0 ] * ( m_.t0[ 0 ] - a.G0.t0[ 0 ] );
00297 alpha_.t1[ 1 ] = this->m_strength * a.e.t1[ 1 ] * ( m_.t1[ 1 ] - a.G0.t1[ 1 ] );
00298 alpha_.t2[ 2 ] = this->m_strength * a.e.t2[ 2 ] * ( m_.t2[ 2 ] - a.G0.t2[ 2 ] );
00299 alpha_.t0[ 1 ] = this->m_strength * a.e.t0[ 1 ] * ( m_.t0[ 1 ] - a.G0.t0[ 1 ] );
00300 alpha_.t1[ 0 ] = this->m_strength * a.e.t1[ 0 ] * ( m_.t1[ 0 ] - a.G0.t1[ 0 ] );
00301 alpha_.t0[ 2 ] = this->m_strength * a.e.t0[ 2 ] * ( m_.t0[ 2 ] - a.G0.t0[ 2 ] );
00302 alpha_.t2[ 0 ] = this->m_strength * a.e.t2[ 0 ] * ( m_.t2[ 0 ] - a.G0.t2[ 0 ] );
00303 alpha_.t1[ 2 ] = this->m_strength * a.e.t1[ 2 ] * ( m_.t1[ 2 ] - a.G0.t1[ 2 ] );
00304 alpha_.t2[ 1 ] = this->m_strength * a.e.t2[ 1 ] * ( m_.t2[ 1 ] - a.G0.t2[ 1 ] );
00305
00306 tensor3_type& rho_ = rho[ i ];
00307 tensor3_type p_ = pillar( l, m, n );
00308 rho_.t0[ 0 ] = this->m_strength * a.p.t0[ 0 ] * ( p_.t0[ 0 ] - a.P0.t0[ 0 ] );
00309 rho_.t1[ 1 ] = this->m_strength * a.p.t1[ 1 ] * ( p_.t1[ 1 ] - a.P0.t1[ 1 ] );
00310 rho_.t2[ 2 ] = this->m_strength * a.p.t2[ 2 ] * ( p_.t2[ 2 ] - a.P0.t2[ 2 ] );
00311
00312 tensor2_type& nu_ = nu[ i ];
00313 tensor2_type x_ = spatial( l, m, n );
00314 nu_.t0[ 0 ] = this->m_strength * a.u.t0[ 0 ] * ( x_.t0[ 0 ] - a.N0.t0[ 0 ] );
00315 nu_.t0[ 1 ] = this->m_strength * a.u.t0[ 1 ] * ( x_.t0[ 1 ] - a.N0.t0[ 1 ] );
00316 nu_.t1[ 0 ] = this->m_strength * a.u.t1[ 0 ] * ( x_.t1[ 0 ] - a.N0.t1[ 0 ] );
00317 nu_.t1[ 1 ] = this->m_strength * a.u.t1[ 1 ] * ( x_.t1[ 1 ] - a.N0.t1[ 1 ] );
00318 }
00319
00320 real_type const inv_h1h1 = 1. / ( m_h1 * m_h1 );
00321 real_type const inv_h2h2 = 1. / ( m_h2 * m_h2 );
00322 real_type const inv_h3h3 = 1. / ( m_h3 * m_h3 );
00323 real_type const inv_len2 = 1. / ( m_h1 * m_h1 + m_h2 * m_h2 + m_h3 * m_h3 );
00324 real_type const inv_4h1h1 = 0.25 * inv_h1h1;
00325 real_type const inv_4h2h2 = 0.25 * inv_h2h2;
00326 real_type const inv_4h3h3 = 0.25 * inv_h3h3;
00327 real_type const iLL12 = 1. / ( m_h1 * m_h1 + m_h2 * m_h2 );
00328 real_type const iLL13 = 1. / ( m_h1 * m_h1 + m_h3 * m_h3 );
00329 real_type const iLL23 = 1. / ( m_h2 * m_h2 + m_h3 * m_h3 );
00330 size_t const LMN = m_L*m_M*m_N;
00331
00332 for ( size_t n = 0; n < m_N; ++n )
00333 for ( size_t m = 0; m < m_M; ++m )
00334 for ( size_t l = 0; l < m_L; ++l )
00335 {
00336
00337 tensor3_type const & plM1_m_n = rho[index_adjust(l-1, m, n)];
00338 tensor3_type const & plP1_m_n = rho[index_adjust(l+1, m ,n)];
00339 tensor3_type const & pl_mM1_n = rho[index_adjust(l, m-1, n)];
00340 tensor3_type const & pl_mP1_n = rho[index_adjust(l, m+1, n)];
00341 tensor3_type const & pl_m_nM1 = rho[index_adjust(l, m, n-1)];
00342 tensor3_type const & pl_m_nP1 = rho[index_adjust(l, m, n+1)];
00343
00344 real_type Pl_m_n = 0;
00345 real_type PlP2_m_n = 0;
00346 real_type PlM2_m_n = 0;
00347 real_type Pl_mP2_n = 0;
00348 real_type Pl_mM2_n = 0;
00349 real_type Pl_m_nP2 = 0;
00350 real_type Pl_m_nM2 = 0;
00351
00352
00353 if ( index_check( l + 2, m, n ) )
00354 {
00355 real_type const tmp = - inv_4h1h1 * plP1_m_n.t0[ 0 ];
00356 PlP2_m_n += + tmp;
00357 Pl_m_n += - tmp;
00358 }
00359
00360
00361 if ( index_check( l - 2, m, n ) )
00362 {
00363 real_type const tmp = + inv_4h1h1 * plM1_m_n.t0[ 0 ];
00364 Pl_m_n += + tmp;
00365 PlM2_m_n += - tmp;
00366 }
00367
00368
00369 if ( index_check( l, m + 2, n ) )
00370 {
00371 real_type const tmp = - inv_4h2h2 * pl_mP1_n.t1[ 1 ];
00372 Pl_mP2_n += + tmp;
00373 Pl_m_n += - tmp;
00374 }
00375
00376
00377 if ( index_check( l, m - 2, n ) )
00378 {
00379 real_type const tmp = + inv_4h2h2 * pl_mM1_n.t1[ 1 ];
00380 Pl_m_n += + tmp;
00381 Pl_mM2_n += - tmp;
00382 }
00383
00384
00385 if ( index_check( l, m, n + 2 ) )
00386 {
00387 real_type const tmp = - inv_4h3h3 * pl_m_nP1.t2[ 2 ];
00388 Pl_m_nP2 += + tmp;
00389 Pl_m_n += - tmp;
00390 }
00391
00392
00393 if ( index_check( l, m, n - 2 ) )
00394 {
00395 real_type const tmp = + inv_4h3h3 * pl_m_nM1.t2[ 2 ];
00396 Pl_m_n += + tmp;
00397 Pl_m_nM2 += - tmp;
00398 }
00399
00400
00401
00402 tensor2_type const & vl_m_n = nu[index_adjust(l, m, n)];
00403 tensor2_type const & vlP1_mM1_nM1 = nu[index_adjust(l+1, m-1, n-1)];
00404 tensor2_type const & vlP1_mP1_nM1 = nu[index_adjust(l+1, m+1, n-1)];
00405 tensor2_type const & vlM1_mM1_nM1 = nu[index_adjust(l-1, m-1, n-1)];
00406 tensor2_type const & vlM1_mP1_nM1 = nu[index_adjust(l-1, m+1, n-1)];
00407
00408 real_type Vl_m_n = 0;
00409 real_type VlM1_mP1_nP1 = 0;
00410 real_type VlP1_mM1_nM1 = 0;
00411 real_type VlM1_mM1_nP1 = 0;
00412 real_type VlP1_mP1_nM1 = 0;
00413 real_type VlP1_mP1_nP1 = 0;
00414 real_type VlM1_mM1_nM1 = 0;
00415 real_type VlP1_mM1_nP1 = 0;
00416 real_type VlM1_mP1_nM1 = 0;
00417
00418
00419 if ( index_check( l - 1, m + 1, n + 1 ) )
00420 {
00421 real_type const tmp = - inv_len2 * vl_m_n.t0[ 0 ];
00422 VlM1_mP1_nP1 += + tmp;
00423 Vl_m_n += - tmp;
00424 }
00425
00426
00427 if ( index_check( l + 1, m - 1, n - 1 ) )
00428 {
00429 real_type const tmp = + inv_len2 * vlP1_mM1_nM1.t0[ 0 ];
00430 Vl_m_n += + tmp;
00431 VlP1_mM1_nM1 += - tmp;
00432 }
00433
00434
00435 if ( index_check( l - 1, m - 1, n + 1 ) )
00436 {
00437 real_type const tmp = - inv_len2 * vl_m_n.t0[ 1 ];
00438 VlM1_mM1_nP1 += + tmp;
00439 Vl_m_n += - tmp;
00440 }
00441
00442
00443 if ( index_check( l + 1, m + 1, n - 1 ) )
00444 {
00445 real_type const tmp = + inv_len2 * vlP1_mP1_nM1.t0[ 1 ];
00446 Vl_m_n += + tmp;
00447 VlP1_mP1_nM1 += - tmp;
00448 }
00449
00450
00451 if ( index_check( l + 1, m + 1, n + 1 ) )
00452 {
00453 real_type const tmp = - inv_len2 * vl_m_n.t1[ 0 ];
00454 VlP1_mP1_nP1 += + tmp;
00455 Vl_m_n += - tmp;
00456 }
00457
00458
00459 if ( index_check( l - 1, m - 1, n - 1 ) )
00460 {
00461 real_type const tmp = + inv_len2 * vlM1_mM1_nM1.t1[ 0 ];
00462 Vl_m_n += + tmp;
00463 VlM1_mM1_nM1 += - tmp;
00464 }
00465
00466
00467 if ( index_check( l + 1, m - 1, n + 1 ) )
00468 {
00469 real_type const tmp = - inv_len2 * vl_m_n.t1[ 1 ];
00470 VlP1_mM1_nP1 += + tmp;
00471 Vl_m_n += - tmp;
00472 }
00473
00474
00475 if ( index_check( l - 1, m + 1, n - 1 ) )
00476 {
00477 real_type const tmp = + inv_len2 * vlM1_mP1_nM1.t1[ 1 ];
00478 Vl_m_n += + tmp;
00479 VlM1_mP1_nM1 += - tmp;
00480 }
00481
00482
00483
00484 tensor3_type const & al_m_n = alpha[index_adjust(l, m, n)];
00485 tensor3_type const & alM1_m_n = alpha[index_adjust(l-1, m, n)];
00486 tensor3_type const & al_mM1_n = alpha[index_adjust(l, m-1, n)];
00487 tensor3_type const & al_m_nM1 = alpha[index_adjust(l, m, n-1)];
00488 tensor3_type const & alM1_mM1_n = alpha[index_adjust(l-1, m-1, n)];
00489 tensor3_type const & alP1_mM1_n = alpha[index_adjust(l+1, m-1, n)];
00490 tensor3_type const & alM1_m_nM1 = alpha[index_adjust(l-1, m, n-1)];
00491 tensor3_type const & alP1_m_nM1 = alpha[index_adjust(l+1, m, n-1)];
00492 tensor3_type const & al_mM1_nM1 = alpha[index_adjust(l, m-1, n-1)];
00493 tensor3_type const & al_mP1_nM1 = alpha[index_adjust(l ,m+1, n-1)];
00494
00495 real_type SlP2_m_n = PlP2_m_n;
00496 real_type SlM2_m_n = PlM2_m_n;
00497 real_type Sl_mP2_n = Pl_mP2_n;
00498 real_type Sl_mM2_n = Pl_mM2_n;
00499 real_type Sl_m_nP2 = Pl_m_nP2;
00500 real_type Sl_m_nM2 = Pl_m_nM2;
00501 real_type SlP1_mM1_nP1 = VlP1_mM1_nP1;
00502 real_type SlM1_mP1_nM1 = VlM1_mP1_nM1;
00503 real_type SlP1_mM1_nM1 = VlP1_mM1_nM1;
00504 real_type SlM1_mM1_nP1 = VlM1_mM1_nP1;
00505 real_type SlP1_mP1_nM1 = VlP1_mP1_nM1;
00506 real_type SlM1_mP1_nP1 = VlM1_mP1_nP1;
00507 real_type SlP1_mP1_nP1 = VlP1_mP1_nP1;
00508 real_type SlM1_mM1_nM1 = VlM1_mM1_nM1;
00509 real_type SlP1_m_n = 0;
00510 real_type Sl_mP1_n = 0;
00511 real_type Sl_m_nP1 = 0;
00512 real_type Sl_m_n = Vl_m_n + Pl_m_n;
00513 real_type SlM1_m_n = 0;
00514 real_type Sl_mM1_n = 0;
00515 real_type Sl_m_nM1 = 0;
00516 real_type SlM1_mP1_n = 0;
00517 real_type SlM1_m_nP1 = 0;
00518 real_type SlP1_mM1_n = 0;
00519 real_type Sl_mM1_nP1 = 0;
00520 real_type SlP1_m_nM1 = 0;
00521 real_type Sl_mP1_nM1 = 0;
00522 real_type SlP1_mP1_n = 0;
00523 real_type SlM1_mM1_n = 0;
00524 real_type SlP1_m_nP1 = 0;
00525 real_type SlM1_m_nM1 = 0;
00526 real_type Sl_mP1_nP1 = 0;
00527 real_type Sl_mM1_nM1 = 0;
00528
00529
00530 if ( index_check( l + 1, m, n ) )
00531 {
00532 real_type const tmp = inv_h1h1 * al_m_n.t0[ 0 ];
00533 SlP1_m_n += - tmp;
00534 Sl_m_n += + tmp;
00535 }
00536
00537
00538 if ( index_check( l - 1, m, n ) )
00539 {
00540 real_type const tmp = inv_h1h1 * alM1_m_n.t0[ 0 ];
00541 Sl_m_n += + tmp;
00542 SlM1_m_n += - tmp;
00543 }
00544
00545
00546 if ( index_check( l, m + 1, n ) )
00547 {
00548 real_type const tmp = inv_h2h2 * al_m_n.t1[ 1 ];
00549 Sl_mP1_n += - tmp;
00550 Sl_m_n += + tmp;
00551 }
00552
00553
00554 if ( index_check( l, m - 1, n ) )
00555 {
00556 real_type const tmp = inv_h2h2 * al_mM1_n.t1[ 1 ];
00557 Sl_m_n += + tmp;
00558 Sl_mM1_n += - tmp;
00559 }
00560
00561
00562 if ( index_check( l, m, n + 1 ) )
00563 {
00564 real_type const tmp = inv_h3h3 * al_m_n.t2[ 2 ];
00565 Sl_m_nP1 += - tmp;
00566 Sl_m_n += + tmp;
00567 }
00568
00569
00570 if ( index_check( l, m, n - 1 ) )
00571 {
00572 real_type const tmp = inv_h3h3 * al_m_nM1.t2[ 2 ];
00573 Sl_m_n += + tmp;
00574 Sl_m_nM1 += - tmp;
00575 }
00576
00577
00578 if ( index_check( l + 1, m + 1, n ) )
00579 {
00580 real_type const tmp = - iLL12 * al_m_n.t0[ 1 ];
00581 SlP1_mP1_n += + tmp;
00582 Sl_m_n += - tmp;
00583 }
00584
00585
00586 if ( index_check( l - 1, m - 1, n ) )
00587 {
00588 real_type const tmp = + iLL12 * alM1_mM1_n.t0[ 1 ];
00589 Sl_m_n += + tmp;
00590 SlM1_mM1_n += - tmp;
00591 }
00592
00593
00594 if ( index_check( l - 1, m + 1, n ) )
00595 {
00596 real_type const tmp = - iLL12 * al_m_n.t1[ 0 ];
00597 SlM1_mP1_n += + tmp;
00598 Sl_m_n += - tmp;
00599 }
00600
00601
00602 if ( index_check( l + 1, m - 1, n ) )
00603 {
00604 real_type const tmp = + iLL12 * alP1_mM1_n.t1[ 0 ];
00605 Sl_m_n += + tmp;
00606 SlP1_mM1_n += - tmp;
00607 }
00608
00609
00610 if ( index_check( l + 1, m, n + 1 ) )
00611 {
00612 real_type const tmp = - iLL13 * al_m_n.t0[ 2 ];
00613 SlP1_m_nP1 += + tmp;
00614 Sl_m_n += - tmp;
00615 }
00616
00617
00618 if ( index_check( l - 1, m, n - 1 ) )
00619 {
00620 real_type const tmp = + iLL13 * alM1_m_nM1.t0[ 2 ];
00621 Sl_m_n += + tmp;
00622 SlM1_m_nM1 += - tmp;
00623 }
00624
00625
00626 if ( index_check( l - 1, m, n + 1 ) )
00627 {
00628 real_type const tmp = - iLL13 * al_m_n.t2[ 0 ];
00629 SlM1_m_nP1 += + tmp;
00630 Sl_m_n += - tmp;
00631 }
00632
00633
00634 if ( index_check( l + 1, m, n - 1 ) )
00635 {
00636 real_type const tmp = + iLL13 * alP1_m_nM1.t2[ 0 ];
00637 Sl_m_n += + tmp;
00638 SlP1_m_nM1 += - tmp;
00639 }
00640
00641
00642 if ( index_check( l, m + 1, n + 1 ) )
00643 {
00644 real_type const tmp = - iLL23 * al_m_n.t1[ 2 ];
00645 Sl_mP1_nP1 += + tmp;
00646 Sl_m_n += - tmp;
00647 }
00648
00649
00650 if ( index_check( l, m - 1, n - 1 ) )
00651 {
00652 real_type const tmp = + iLL23 * al_mM1_nM1.t1[ 2 ];
00653 Sl_m_n += + tmp;
00654 Sl_mM1_nM1 += - tmp;
00655 }
00656
00657
00658 if ( index_check( l, m - 1, n + 1 ) )
00659 {
00660 real_type const tmp = - iLL23 * al_m_n.t2[ 1 ];
00661 Sl_mM1_nP1 += + tmp;
00662 Sl_m_n += - tmp;
00663 }
00664
00665
00666 if ( index_check( l, m + 1, n - 1 ) )
00667 {
00668 real_type const tmp = + iLL23 * al_mP1_nM1.t2[ 1 ];
00669 Sl_m_n += + tmp;
00670 Sl_mP1_nM1 += - tmp;
00671 }
00672
00673 EDMVector row( LMN );
00674 row.clear();
00675 row( index_adjust( l + 2, m , n ) ) += zeroize( SlP2_m_n );
00676 row( index_adjust( l - 2, m , n ) ) += zeroize( SlM2_m_n );
00677 row( index_adjust( l , m + 2, n ) ) += zeroize( Sl_mP2_n );
00678 row( index_adjust( l , m - 2, n ) ) += zeroize( Sl_mM2_n );
00679 row( index_adjust( l , m , n + 2 ) ) += zeroize( Sl_m_nP2 );
00680 row( index_adjust( l , m , n - 2 ) ) += zeroize( Sl_m_nM2 );
00681 row( index_adjust( l + 1, m + 1, n ) ) += zeroize( SlP1_mP1_n );
00682 row( index_adjust( l - 1, m - 1, n ) ) += zeroize( SlM1_mM1_n );
00683 row( index_adjust( l + 1, m , n + 1 ) ) += zeroize( SlP1_m_nP1 );
00684 row( index_adjust( l - 1, m , n - 1 ) ) += zeroize( SlM1_m_nM1 );
00685 row( index_adjust( l , m + 1, n + 1 ) ) += zeroize( Sl_mP1_nP1 );
00686 row( index_adjust( l , m - 1, n - 1 ) ) += zeroize( Sl_mM1_nM1 );
00687 row( index_adjust( l + 1, m - 1, n + 1 ) ) += zeroize( SlP1_mM1_nP1 );
00688 row( index_adjust( l - 1, m + 1, n - 1 ) ) += zeroize( SlM1_mP1_nM1 );
00689 row( index_adjust( l + 1, m - 1, n - 1 ) ) += zeroize( SlP1_mM1_nM1 );
00690 row( index_adjust( l - 1, m - 1, n + 1 ) ) += zeroize( SlM1_mM1_nP1 );
00691 row( index_adjust( l + 1, m + 1, n - 1 ) ) += zeroize( SlP1_mP1_nM1 );
00692 row( index_adjust( l - 1, m + 1, n + 1 ) ) += zeroize( SlM1_mP1_nP1 );
00693 row( index_adjust( l - 1, m - 1, n - 1 ) ) += zeroize( SlM1_mM1_nM1 );
00694 row( index_adjust( l + 1, m + 1, n + 1 ) ) += zeroize( SlP1_mP1_nP1 );
00695 row( index_adjust( l , m , n - 1 ) ) += zeroize( Sl_m_nM1 );
00696 row( index_adjust( l + 1, m , n - 1 ) ) += zeroize( SlP1_m_nM1 );
00697 row( index_adjust( l , m + 1, n - 1 ) ) += zeroize( Sl_mP1_nM1 );
00698 row( index_adjust( l , m - 1, n ) ) += zeroize( Sl_mM1_n );
00699 row( index_adjust( l + 1, m - 1, n ) ) += zeroize( SlP1_mM1_n );
00700 row( index_adjust( l - 1, m , n ) ) += zeroize( SlM1_m_n );
00701 row( index_adjust( l , m , n ) ) += zeroize( Sl_m_n );
00702 row( index_adjust( l + 1, m , n ) ) += zeroize( SlP1_m_n );
00703 row( index_adjust( l - 1, m + 1, n ) ) += zeroize( SlM1_mP1_n );
00704 row( index_adjust( l , m + 1, n ) ) += zeroize( Sl_mP1_n );
00705 row( index_adjust( l , m - 1, n + 1 ) ) += zeroize( Sl_mM1_nP1 );
00706 row( index_adjust( l - 1, m , n + 1 ) ) += zeroize( SlM1_m_nP1 );
00707 row( index_adjust( l , m , n + 1 ) ) += zeroize( Sl_m_nP1 );
00708
00709 ublas::row(K, index_adjust( l, m, n) ) = row;
00710 }
00711 }
00712
00713 SolidParticle & grid(size_t l, size_t m, size_t n)
00714 {
00715 return m_P[n*(m_L*m_M) + m*m_L + l];
00716 }
00717
00718 SolidParticle const & grid(size_t l, size_t m, size_t n) const
00719 {
00720 return m_P[n*(m_L*m_M) + m*m_L + l];
00721 }
00722
00723 tensor3_type metrix(size_t l, size_t m, size_t n) const
00724 {
00725 vector3_type const v1 = D1Pb( l, m, n );
00726 vector3_type const v2 = D2Pb( l, m, n );
00727 vector3_type const v3 = D3Pb( l, m, n );
00728
00729 vector3_type const v12 = index_check( l + 1, m + 1, n ) ? ( r( l + 1, m + 1, n ) - r( l, m, n ) ) : vector3_type();
00730 vector3_type const v21 = index_check( l - 1, m + 1, n ) ? ( r( l - 1, m + 1, n ) - r( l, m, n ) ) : vector3_type();
00731 vector3_type const v13 = index_check( l + 1, m, n + 1 ) ? ( r( l + 1, m, n + 1 ) - r( l, m, n ) ) : vector3_type();
00732 vector3_type const v31 = index_check( l - 1, m, n + 1 ) ? ( r( l - 1, m, n + 1 ) - r( l, m, n ) ) : vector3_type();
00733 vector3_type const v23 = index_check( l, m + 1, n + 1 ) ? ( r( l, m + 1, n + 1 ) - r( l, m, n ) ) : vector3_type();
00734 vector3_type const v32 = index_check( l, m - 1, n + 1 ) ? ( r( l, m - 1, n + 1 ) - r( l, m, n ) ) : vector3_type();
00735 real_type const iLL12 = 1. / ( m_h1 * m_h1 + m_h2 * m_h2 );
00736 real_type const iLL13 = 1. / ( m_h1 * m_h1 + m_h3 * m_h3 );
00737 real_type const iLL23 = 1. / ( m_h2 * m_h2 + m_h3 * m_h3 );
00738
00739 tensor3_type G;
00740 G.t0[ 0 ] = v1 * v1;
00741 G.t1[ 1 ] = v2 * v2;
00742 G.t2[ 2 ] = v3 * v3;
00743
00744 G.t0[ 1 ] = ( v12 * v12 ) * iLL12;
00745 G.t1[ 0 ] = ( v21 * v21 ) * iLL12;
00746 G.t0[ 2 ] = ( v13 * v13 ) * iLL13;
00747 G.t2[ 0 ] = ( v31 * v31 ) * iLL13;
00748 G.t1[ 2 ] = ( v23 * v23 ) * iLL23;
00749 G.t2[ 1 ] = ( v32 * v32 ) * iLL23;
00750
00751
00752
00753
00754
00755
00756
00757
00758
00759 return tensor3_type(G);
00760 }
00761
00762 tensor2_type spatial(size_t l, size_t m, size_t n) const
00763 {
00764 vector3_type const v1 = index_check( l - 1, m + 1, n + 1 ) ? ( r( l - 1, m + 1, n + 1 ) - r( l, m, n ) ) : vector3_type();
00765 vector3_type const v2 = index_check( l - 1, m - 1, n + 1 ) ? ( r( l - 1, m - 1, n + 1 ) - r( l, m, n ) ) : vector3_type();
00766 vector3_type const v3 = index_check( l + 1, m + 1, n + 1 ) ? ( r( l + 1, m + 1, n + 1 ) - r( l, m, n ) ) : vector3_type();
00767 vector3_type const v4 = index_check( l + 1, m - 1, n + 1 ) ? ( r( l + 1, m - 1, n + 1 ) - r( l, m, n ) ) : vector3_type();
00768 real_type const iLen = 1. / ( m_h1 * m_h1 + m_h2 * m_h2 + m_h3 * m_h3 );
00769
00770 tensor2_type N;
00771
00772
00773
00774
00775
00776
00777 N.t0[ 0 ] = ( v1 * v1 );
00778 N.t0[ 0 ] *= N.t0[ 0 ] * iLen;
00779 N.t0[ 1 ] = ( v2 * v2 );
00780 N.t0[ 1 ] *= N.t0[ 1 ] * iLen;
00781 N.t1[ 0 ] = ( v3 * v3 );
00782 N.t1[ 0 ] *= N.t1[ 0 ] * iLen;
00783 N.t1[ 1 ] = ( v4 * v4 );
00784 N.t1[ 1 ] *= N.t1[ 1 ] * iLen;
00785
00786 return tensor2_type(N);
00787 }
00788
00789 tensor3_type pillar(size_t l, size_t m, size_t n) const
00790 {
00791 vector3_type const v1 = index_check( l + 1, m, n ) && index_check( l - 1, m, n ) ? ( r( l + 1, m, n ) - r( l - 1, m, n ) ) / ( 2. * m_h1 ) : vector3_type();
00792 vector3_type const v2 = index_check( l, m + 1, n ) && index_check( l, m - 1, n ) ? ( r( l, m + 1, n ) - r( l, m - 1, n ) ) / ( 2. * m_h2 ) : vector3_type();
00793 vector3_type const v3 = index_check( l, m, n + 1 ) && index_check( l, m, n - 1 ) ? ( r( l, m, n + 1 ) - r( l, m, n - 1 ) ) / ( 2. * m_h3 ) : vector3_type();
00794
00795 tensor3_type P;
00796 P.t0[ 0 ] = v1 * v1;
00797 P.t1[ 1 ] = v2 * v2;
00798 P.t2[ 2 ] = v3 * v3;
00799
00800 return tensor3_type(P);
00801 }
00802
00803 void compute_surface_normals()
00804 {
00805 for (size_t n = 0; n < m_N; ++n)
00806 for (size_t m = 0; m < m_M; ++m)
00807 for (size_t l = 0; l < m_L; ++l)
00808 grid(l, m, n).n = normal(l, m, n);
00809 }
00810
00811 size_t particle_count() const
00812 {
00813 return size_t(static_cast<size_t>(m_P.size()));
00814 }
00815
00816 particle_type & get_particle(size_t idx)
00817 {
00818 return m_P[idx];
00819 }
00820
00821 particle_type const & get_particle(size_t idx) const
00822 {
00823 return m_P[idx];
00824 }
00825
00826 vector3_type D1Pb(size_t l, size_t m, size_t n) const
00827 {
00828 return vector3_type(index_check(l+1,m,n)?(r(l+1,m,n)-r(l,m,n))/m_h1:vector3_type(value_traits::zero()));
00829 }
00830
00831 vector3_type D2Pb(size_t l, size_t m, size_t n) const
00832 {
00833 return vector3_type(index_check(l,m+1,n)?(r(l,m+1,n)-r(l,m,n))/m_h2:vector3_type(value_traits::zero()));
00834 }
00835
00836 vector3_type D3Pb(size_t l, size_t m, size_t n) const
00837 {
00838 return vector3_type(index_check(l,m,n+1)?(r(l,m,n+1)-r(l,m,n))/m_h3:vector3_type(value_traits::zero()));
00839 }
00840
00841 };
00842
00843 }
00844
00845 }
00846
00847
00848 #endif