00001 #ifndef OPENTISSUE_DYNAMICS_SPH_SPH_SYSTEM_H
00002 #define OPENTISSUE_DYNAMICS_SPH_SPH_SYSTEM_H
00003
00004
00005
00006
00007
00008
00009
00010 #include <OpenTissue/configuration.h>
00011
00012 #include <OpenTissue/dynamics/sph/sph_material.h>
00013 #include <vector>
00014
00015 namespace OpenTissue
00016 {
00017 namespace sph
00018 {
00019
00020 template< typename Types >
00021 class FluidHashPolicy
00022 {
00023 public:
00024 typedef typename Types::real_type real_type;
00025 typedef typename Types::particle data_type;
00026 typedef typename Types::particle query_type;
00027 typedef typename Types::particle_cptr_pair result_type;
00028 #if defined(SPHSH_PARALLEL)
00029 typedef typename Types::particle_cptr_pair_container result_container;
00030 #else
00031 typedef typename Types::particle_cptr_container result_container;
00032 #endif
00033 typedef typename Types::vector vector3_type;
00034
00035 public:
00036 void reset(result_container& results) const
00037 {
00038 results.clear();
00039 }
00040
00041 void report(const data_type& data, const query_type& query, result_container& results) const
00042 {
00043 if ((!data.fixed() || &data == &query) && data.check(query.position()))
00044 #if defined(SPHSH_PARALLEL)
00045 if (&query != &data)
00046 results.push_back(result_type(&query,&data));
00047 #else
00048 results.push_back(&data);
00049 #endif
00050 }
00051
00052 vector3_type min_coord(const typename Types::particle& p) const {return p.min();}
00053 vector3_type max_coord(const typename Types::particle& p) const {return p.max();}
00054 const vector3_type& position(const typename Types::particle& p) const {return p.position();}
00055 };
00056
00057
00061 template< typename Types,
00062 typename DensitySolver,
00063 typename PressureSolver,
00064 typename NormalSolver,
00065 typename GravityForce,
00066 typename BuoyancyForce,
00067 typename PressureForce,
00068 typename ViscosityForce,
00069 typename SurfaceForce,
00070 typename IntegratorPolicy,
00071 typename ColorField >
00072 class System
00073 {
00074 public:
00075 typedef typename Types::real_type real_type;
00076 typedef typename Types::vector vector;
00077 typedef typename Types::particle particle;
00078 typedef typename Types::particle_container particle_container;
00079 typedef typename Types::particle_cptr_container particle_cptr_container;
00080 typedef typename Types::particle_cptr_pair_container particle_cptr_pair_container;
00081 typedef typename Types::collision_detection collision_detection;
00082
00083 typedef Material<Types> fluid_material;
00084
00085 typedef FluidHashPolicy<Types> fluid_hash_policy;
00086 typedef typename Types::template hashing<fluid_hash_policy, typename fluid_hash_policy::data_type> fluid_hashing;
00087 typedef typename fluid_hashing::hash_grid fluid_hash_grid;
00088 typedef typename fluid_hashing::point_query fluid_point_query;
00089
00090 public:
00094 System()
00095 : m_integrator(NULL)
00096 , m_density(NULL)
00097 , m_pressure(NULL)
00098 , m_normal(NULL)
00099 , m_gravityForce(NULL)
00100 , m_buoyancyForce(NULL)
00101 , m_pressureForce(NULL)
00102 , m_viscosityForce(NULL)
00103 , m_surfaceForce(NULL)
00104 , m_color(NULL)
00105 , m_material(NULL)
00106 {}
00107
00111 virtual ~System()
00112 {
00113 cleanUp();
00114 }
00115
00116 public:
00122 template<typename MaterialPolicy>
00123 bool create(const MaterialPolicy& material, const vector& gravity)
00124 {
00125
00126 cleanUp();
00127
00128 m_material = &material;
00129 m_integrator = new IntegratorPolicy(material.timestep(), material.restitution());
00130 m_density = new DensitySolver;
00131 m_pressure = new PressureSolver(material.gas_stiffness(), material.density());
00132 m_normal = new NormalSolver;
00133 m_gravityForce = new GravityForce(gravity);
00134 m_buoyancyForce = new BuoyancyForce(material.buoyancy(), material.density(), gravity);
00135 m_pressureForce = new PressureForce;
00136 m_viscosityForce = new ViscosityForce(material.viscosity());
00137 m_surfaceForce = new SurfaceForce(material.tension(), material.threshold());
00138 m_color = new ColorField;
00139
00140 return true;
00141 }
00142
00146 bool initHashing(size_t size, const real_type& spacing)
00147 {
00148 if (!m_particles.empty())
00149 return false;
00150 m_search.resize(size);
00151 m_search.set_spacing(spacing);
00152 return true;
00153 }
00154
00155 collision_detection& collisionSystem()
00156 {
00157 return m_colisys;
00158 }
00159
00160 const collision_detection& collisionSystem() const
00161 {
00162 return m_colisys;
00163 }
00164
00168 template< typename PositionIterator >
00169 bool init(const PositionIterator& begin, const PositionIterator& end)
00170 {
00171 return init<PositionIterator, PositionIterator>(begin, end, end, end);
00172 }
00173
00177 template< typename PositionIterator, typename VelocityIterator >
00178 bool init(const PositionIterator& pbegin, const PositionIterator& pend, const VelocityIterator& vbegin, const VelocityIterator& vend)
00179 {
00180 VelocityIterator vel = vbegin;
00181 for (PositionIterator pos = pbegin; pos != pend; ++pos) {
00182 particle par;
00183 par.mass() = m_material->particle_mass();
00184 par.velocity().clear();
00185 par.normal().clear();
00186 par.position_old() = par.position() = *pos;
00187
00188 if (vel != vend) {
00189 par.velocity() = *vel;
00190 par.position_old() -= *vel;
00191 ++vel;
00192 }
00193
00194 m_particles.push_back(par);
00195 }
00196
00197
00198 m_cptr_particles.resize(m_particles.size());
00199 for (typename particle_container::const_iterator par = m_particles.begin(); par != m_particles.end(); ++par)
00200 m_cptr_particles.push_back(&*par);
00201
00202 #if defined(SPHSH)
00203
00204 m_search.init_data(m_particles.begin(), m_particles.end());
00205 #endif
00206
00207 if (!solve())
00208 return false;
00209
00210
00211 m_integrator->setCollisionSystem(&m_colisys);
00212 m_integrator->initialize_particles(m_particles.begin(), m_particles.end());
00213
00214 return true;
00215 }
00216
00217
00221 template< typename EmitterPolicy >
00222 bool init(EmitterPolicy& emitter, size_t particles)
00223 {
00224 particle par;
00225 par.mass() = m_material->particle_mass();
00226 par.velocity().clear();
00227 par.normal().clear();
00228 par.position_old().clear();
00229 par.position().clear();
00230
00231 for (size_t n = 0; n < particles; ++n)
00232 m_particles.push_back(par);
00233
00234
00235 if (!emitter.initialize(m_particles.begin()+m_particles.size()-particles, m_particles.end()))
00236 return false;
00237
00238
00239 m_cptr_particles.resize(m_particles.size());
00240 for (typename particle_container::const_iterator par = m_particles.begin(); par != m_particles.end(); ++par)
00241 m_cptr_particles.push_back(&*par);
00242
00243 #if defined(SPHSH)
00244
00245 m_search.init_data(m_particles.begin(), m_particles.end());
00246 #endif
00247
00248 if (!solve())
00249 return false;
00250
00251
00252 m_integrator->setCollisionSystem(&m_colisys);
00253 m_integrator->initialize_particles(m_particles.begin(), m_particles.end());
00254
00255 return true;
00256 }
00257
00261 const particle_container &particles() const
00262 {
00263 return m_particles;
00264 }
00265
00269 const fluid_material* material() const
00270 {
00271 return m_material;
00272 }
00273
00277 typename ColorField::value isoValue(const vector& pos)
00278 {
00279 static particle temp__par;
00280 temp__par.position() = pos;
00281 particle_cptr_container &particles = m_cptr_particles;
00282 #if defined(SPHSH) && !defined(SPHSH_PARALLEL)
00283
00284 m_search(temp__par, particles, typename fluid_point_query::all_tag());
00285 #endif
00286 return m_color->apply(temp__par, particles.begin(), particles.end());
00287 }
00288
00289 #if defined(SPHSH) && defined(SPHSH_PARALLEL)
00290
00294 bool solve()
00295 {
00296 if (m_particles.empty()) return false;
00297
00298 particle_cptr_pair_container particles;
00299 m_search(m_particles.begin(), m_particles.end(), particles, typename fluid_point_query::all_tag() );
00300 typename particle_container::iterator par_end = m_particles.end();
00301 typename particle_cptr_pair_container::const_iterator pair_end = particles.end();
00302
00303
00304 for (typename particle_container::iterator p = m_particles.begin(); p != par_end; ++p) {
00305 particle &par = *p;
00306 par.density() = m_density->apply(par, par);
00307 if (m_material->buoyancy() > 0)
00308 par.force() = m_buoyancyForce->apply(par, par);
00309 else
00310 par.force() = m_gravityForce->apply(par, par);
00311 par.normal() = m_normal->apply(par, par);
00312 }
00313
00314
00315 for (typename particle_cptr_pair_container::const_iterator pp = particles.begin(); pp != pair_end; ++pp) {
00316 const particle &p_i = *pp->first;
00317 const particle &p_j = *pp->second;
00318 particle &par = const_cast<particle&>(p_i);
00319 par.density() += m_density->apply(p_i, p_j);
00320 }
00321
00322
00323 for (typename particle_container::iterator p = m_particles.begin(); p != par_end; ++p) {
00324 particle &par = *p;
00325 par.pressure() = m_pressure->apply(par, par);
00326 }
00327
00328
00329 for (typename particle_cptr_pair_container::const_iterator pp = particles.begin(); pp != pair_end; ++pp) {
00330 const particle &p_i = *pp->first;
00331 const particle &p_j = *pp->second;
00332 particle &par = const_cast<particle&>(p_i);
00333 vector& f = par.force();
00334
00335
00336 par.normal() += m_normal->apply(p_i, p_j);
00337
00338
00339 f += m_pressureForce->apply(p_i, p_j);
00340
00341
00342 f += m_viscosityForce->apply(p_i, p_j);
00343
00344
00345
00346
00347 }
00348
00349 return true;
00350 }
00351
00352 #else
00353
00357 bool solve()
00358 {
00359 if (m_particles.empty()) return false;
00360
00361 particle_cptr_container &particles = m_cptr_particles;
00362
00363
00364
00365
00366
00367
00368
00369 typename particle_container::iterator end = m_particles.end();
00370
00371
00372
00373
00374 for (typename particle_container::iterator p = m_particles.begin(); p != end; ++p) {
00375 particle &par = *p;
00376
00377 #if defined(SPHSH)
00378 m_search(par, particles, typename fluid_point_query::all_tag() );
00379 #endif
00380
00381
00382
00383
00384
00385
00386
00387
00388
00389
00390
00391
00392
00393
00394
00395
00396 typename particle_cptr_container::const_iterator begin = particles.begin();
00397 typename particle_cptr_container::const_iterator end = particles.end();
00398
00399
00400
00401 par.density() = m_density->apply(par, begin, end);
00402
00403
00404 par.pressure() = m_pressure->apply(par, begin, end);
00405
00406
00407
00408 }
00409
00410
00411
00412
00413
00414 for (typename particle_container::iterator p = m_particles.begin(); p != end; ++p) {
00415 particle &par = *p;
00416
00417 #if defined(SPHSH)
00418 m_search(par, particles, typename fluid_point_query::all_tag());
00419 #endif
00420
00421 typename particle_cptr_container::const_iterator begin = particles.begin();
00422 typename particle_cptr_container::const_iterator end = particles.end();
00423
00424
00425 par.normal() = m_normal->apply(par, begin, end);
00426
00427
00428
00429
00430
00431
00432 vector& f = par.force();
00433 f.clear();
00434
00435
00436 f += m_pressureForce->apply(par, begin, end);
00437
00438
00439 f += m_viscosityForce->apply(par, begin, end);
00440
00441
00442 if (m_material->tension() > 0)
00443 f += m_surfaceForce->apply(par, begin, end);
00444
00445
00446
00447
00448
00449 if (m_material->buoyancy() > 0)
00450 f += m_buoyancyForce->apply(par, begin, end);
00451 else
00452 f += m_gravityForce->apply(par, begin, end);
00453
00454 }
00455
00456
00457 return true;
00458 }
00459 #endif
00460
00461 bool simulate()
00462 {
00463 if (!solve())
00464 return false;
00465
00466 typename particle_container::iterator pbegin = m_particles.begin();
00467 typename particle_container::iterator pend = m_particles.end();
00468
00469 m_integrator->integrate_particles(pbegin, pend);
00470
00471 #if defined(SPHSH)
00472 m_search.init_data(pbegin, pend);
00473 #endif
00474 return true;
00475 }
00476
00477 private:
00478 System& operator=(const System&){return *this;}
00479
00480 void cleanUp()
00481 {
00482 delete m_density; m_density = NULL;
00483 delete m_pressure; m_pressure = NULL;
00484 delete m_normal; m_normal = NULL;
00485 delete m_gravityForce; m_gravityForce = NULL;
00486 delete m_buoyancyForce; m_buoyancyForce = NULL;
00487 delete m_pressureForce; m_pressureForce = NULL;
00488 delete m_viscosityForce; m_viscosityForce = NULL;
00489 delete m_surfaceForce; m_surfaceForce = NULL;
00490 delete m_integrator; m_integrator = NULL;
00491 delete m_color; m_color = NULL;
00492 m_particles.clear();
00493 m_cptr_particles.clear();
00494 }
00495
00496 void incompressibility_relaxation(unsigned long iterations = 1)
00497 {
00498 #if defined(SPHSH)
00499 particle_cptr_container particles;
00500 #else
00501 particle_cptr_container &particles = m_cptr_particles;
00502 #endif
00503 for (unsigned long n = 0; n < iterations; ++n)
00504 for (typename particle_container::iterator p = m_particles.begin(); p != m_particles.end(); ++p) {
00505 particle &par = *p;
00506 #if defined(SPHSH)
00507 m_search(par, particles, typename fluid_point_query::all_tag() );
00508 #endif
00509
00510 par.density() = m_density->apply(par, particles);
00511
00512
00513 par.pressure() = m_pressure->apply(par, particles);
00514
00515 vector dx = 0;
00516 if (par.density() > m_material->density())
00517 for (typename particle_cptr_container::const_iterator p_ = particles.begin(); p_ != particles.end(); ++p_) {
00518 const particle* p = *p_;
00519 vector d = p->position()-par.position();
00520 const real_type l = length(d);
00521 if (l <= 1./32768) continue;
00522 d *= 1./l;
00523 vector disp = 0.5*m_material->timestep()*m_material->timestep()*par.pressure()*(1-l/par.radius())*d;
00524 const_cast<particle*>(p)->position() += disp;
00525 dx -= disp;
00526 }
00527 par.position() += dx;
00528 }
00529 }
00530
00531 protected:
00532 fluid_point_query m_search;
00533 collision_detection m_colisys;
00534 particle_container m_particles;
00535 particle_cptr_container m_cptr_particles;
00536 IntegratorPolicy* m_integrator;
00537 const DensitySolver* m_density;
00538 const PressureSolver* m_pressure;
00539 const NormalSolver* m_normal;
00540 const GravityForce* m_gravityForce;
00541 const BuoyancyForce* m_buoyancyForce;
00542 const PressureForce* m_pressureForce;
00543 const ViscosityForce* m_viscosityForce;
00544 const SurfaceForce* m_surfaceForce;
00545 const ColorField* m_color;
00546 const fluid_material* m_material;
00547
00548 };
00549
00550 }
00551 }
00552
00553
00554 #endif