00001 #ifndef OPENTISSUE_DYNAMICS_EDM_EDM_MODEL_H
00002 #define OPENTISSUE_DYNAMICS_EDM_EDM_MODEL_H
00003
00004
00005
00006
00007
00008
00009
00010 #include <OpenTissue/configuration.h>
00011
00012 #include <OpenTissue/core/math/big/big_types.h>
00013 #include <OpenTissue/core/math/big/big_conjugate_gradient.h>
00014
00015 #include <cmath>
00016 #include <list>
00017 #include <map>
00018 #include <vector>
00019
00020
00021 namespace OpenTissue
00022 {
00023
00024 namespace edm
00025 {
00026
00027 template<typename edm_types>
00028 class Model
00029 : public edm_types::model_traits
00030 {
00031 public:
00032
00033 typedef typename edm_types::value_traits value_traits;
00034 typedef typename edm_types::real_type real_type;
00035 typedef typename edm_types::vector3_type vector3_type;
00036 typedef typename edm_types::model_id_type model_id_type;
00037 typedef typename edm_types::Particle particle_type;
00038 typedef typename edm_types::force_type force_type;
00039 typedef typename edm_types::object_type object_type;
00040
00041 typedef std::list<force_type const *> Forces;
00042 typedef std::list<object_type const *> Objects;
00043 typedef std::map<particle_type const *, Forces> EDMLocalForces;
00044 typedef typename ublas::compressed_matrix<real_type> EDMMatrix;
00045 typedef typename ublas::vector<real_type> EDMVector;
00046
00047 private:
00048
00049 virtual void compute_stiffness(EDMMatrix & K) const = 0;
00050 virtual void compute_surface_normals() = 0;
00051 virtual size_t particle_count() const = 0;
00052 virtual particle_type const & get_particle(size_t idx) const = 0;
00053 virtual particle_type & get_particle(size_t idx) = 0;
00054
00055 protected:
00056
00057
00058 Forces m_Fs;
00059 EDMLocalForces m_LFs;
00060 Objects m_Os;
00061 real_type m_dt;
00062 real_type m_strength;
00063 vector3_type * m_rest;
00064 vector3_type * m_init;
00065 size_t m_max_nodes;
00066
00067 private:
00068
00069 model_id_type m_type;
00070
00071 public:
00072
00073 Model(model_id_type type)
00074 : m_dt(value_traits::zero())
00075 , m_strength(value_traits::one())
00076 , m_rest(0)
00077 , m_init(0)
00078 , m_max_nodes(0)
00079 , m_type(type)
00080 {
00081 }
00082
00083 virtual ~Model()
00084 {
00085 delete[] m_rest;
00086 delete[] m_init;
00087 }
00088
00089 model_id_type const & type() const
00090 {
00091 return m_type;
00092 }
00093
00094 real_type & strength()
00095 {
00096 return m_strength;
00097 }
00098
00099 real_type const & strength() const
00100 {
00101 return m_strength;
00102 }
00103
00104 real_type & timestep()
00105 {
00106 return m_dt;
00107 }
00108
00109 real_type const & timestep() const
00110 {
00111 return m_dt;
00112 }
00113
00114 public:
00115
00116 Model & add(force_type const & f)
00117 {
00118 remove(f);
00119 m_Fs.push_back(&f);
00120 return *this;
00121 }
00122
00123 Model & remove(force_type const & f)
00124 {
00125 m_Fs.remove(&f);
00126 return *this;
00127 }
00128
00129 Model & add(particle_type const & a, force_type const & f)
00130 {
00131 remove(a, f);
00132 Forces& F = m_LFs[&a];
00133 F.push_back(&f);
00134 return *this;
00135 }
00136
00137 Model & remove(particle_type const & a, force_type const & f)
00138 {
00139 Forces& F = m_LFs[&a];
00140 F.remove(&f);
00141 return *this;
00142 }
00143
00144 Model & add(object_type const & o)
00145 {
00146 remove(o);
00147 m_Os.push_back(&o);
00148 return *this;
00149 }
00150
00151 Model & remove(object_type const & o)
00152 {
00153 m_Os.remove(&o);
00154 return *this;
00155 }
00156
00157 public:
00158
00159 size_t num_particles() const
00160 {
00161 return size_t(particle_count());
00162 }
00163
00164 vector3_type const & position(size_t idx) const
00165 {
00166 return get_particle(idx).r;
00167 }
00168
00169 particle_type const & particle(size_t idx) const
00170 {
00171 return get_particle(idx);
00172 }
00173
00174 bool lock_particle(size_t idx)
00175 {
00176 if (idx >= particle_count())
00177 return false;
00178 get_particle(idx).f = true;
00179 return true;
00180 }
00181
00182 bool unlock_particle(size_t idx)
00183 {
00184 if (idx >= particle_count())
00185 return false;
00186 get_particle(idx).f = false;
00187 return true;
00188 }
00189
00190 bool move_particle(size_t idx, vector3_type const & displacement)
00191 {
00192 if (idx >= particle_count())
00193 return false;
00194 get_particle(idx).r += displacement;
00195 return true;
00196 }
00197
00198 protected:
00199
00200 vector3_type compute_external_forces(particle_type const & a) const
00201 {
00202 vector3_type f(value_traits::zero());
00203 typename Forces::const_iterator F, endF = m_Fs.end();
00204
00205 for (F = m_Fs.begin(); F != endF; ++F)
00206 f += (*F)->apply(a);
00207
00208 typename EDMLocalForces::const_iterator LF = m_LFs.find(&a);
00209 if (LF != m_LFs.end())
00210 {
00211 endF = LF->second.end();
00212 for (F = LF->second.begin(); F != endF; ++F)
00213 f += (*F)->apply(a);
00214 }
00215 return vector3_type(f);
00216 }
00217
00218 bool collision_projection(vector3_type & r) const
00219 {
00220 bool collision = false;
00221 typename Objects::const_iterator O, end = m_Os.end();
00222 for (O = m_Os.begin(); O != end; ++O)
00223 {
00224 real_type const penetration = (*O)->eval(r);
00225 if (penetration >= 0)
00226 continue;
00227 vector3_type const n = (*O)->normal(r);
00228 r += (*O)->dist(r)*n;
00229 collision = true;
00230 }
00231 return collision;
00232 }
00233
00234 void set(size_t num_nodes)
00235 {
00236 delete[] m_rest;
00237 delete[] m_init;
00238 m_rest = new vector3_type[num_nodes];
00239 m_init = new vector3_type[num_nodes];
00240 m_max_nodes = num_nodes;
00241 }
00242
00243 public:
00244
00245 void run(bool compute_elasticity)
00246 {
00247 size_t const size = particle_count();
00248 EDMMatrix K(size, size);
00249 K.clear();
00250 compute_stiffness(K);
00251
00252 if (compute_elasticity)
00253 {
00254 EDMVector rX(size), rY(size), rZ(size);
00255 rX.clear(); rY.clear(); rZ.clear();
00256 for (size_t i = 0; i < size; ++i)
00257 {
00258 particle_type & a = get_particle(i);
00259 rX(i) = a.r(0);
00260 rY(i) = a.r(1);
00261 rZ(i) = a.r(2);
00262 }
00263 EDMVector eX(size), eY(size), eZ(size);
00264 eX.clear(); eY.clear(); eZ.clear();
00265 ublas::axpy_prod( K, rX, eX, true );
00266 ublas::axpy_prod( K, rY, eY, true );
00267 ublas::axpy_prod( K, rZ, eZ, true );
00268 for (size_t i = 0; i < size; ++i)
00269 get_particle(i).E = vector3_type(eX(i), eY(i), eZ(i));
00270 }
00271
00272 EDMVector gX(size), gY(size), gZ(size);
00273 gX.clear(); gY.clear(); gZ.clear();
00274 for (size_t i = 0; i < size; ++i)
00275 {
00276 particle_type & a = get_particle(i);
00277 real_type const mc1 = (1./(m_dt*m_dt))*a.m + (.5*(1./m_dt))*a.g;
00278 real_type const mc2 = a.m/m_dt - .5*a.g;
00279 a.F = compute_external_forces(a);
00280 K(i, i) += mc1;
00281 gX(i) = a.F(0) + mc1*a.r(0) + mc2*a.v(0);
00282 gY(i) = a.F(1) + mc1*a.r(1) + mc2*a.v(1);
00283 gZ(i) = a.F(2) + mc1*a.r(2) + mc2*a.v(2);
00284 }
00285
00286 EDMVector rX(size), rY(size), rZ(size);
00287 rX.clear(); rY.clear(); rZ.clear();
00288
00289 static real_type const EDM_CG_TOLERANCE = 0.00001;
00290
00291 real_type const E = EDM_CG_TOLERANCE*size;
00292
00293 size_t iterations;
00294
00295 math::big::conjugate_gradient(K, rX, gX, size, E*E, iterations);
00296 math::big::conjugate_gradient(K, rY, gY, size, E*E, iterations);
00297 math::big::conjugate_gradient(K, rZ, gZ, size, E*E, iterations);
00298
00299
00300 for (size_t i = 0; i < size; ++i)
00301 {
00302 particle_type & a = get_particle(i);
00303 a.o = a.r;
00304 if (!a.f)
00305 a.r = vector3_type(rX(i), rY(i), rZ(i));
00306 vector3_type new_r = a.r;
00307 if (collision_projection(new_r))
00308 a.r = new_r;
00309 a.v = (a.r - a.o)/m_dt;
00310 }
00311
00312 compute_surface_normals();
00313 }
00314
00315 };
00316
00317
00324
00325 template<typename real_type>
00326 inline real_type zeroize(real_type const & val, real_type const & epsilon = static_cast<real_type>(1./8192))
00327 {
00328 using std::fabs;
00329 return real_type(fabs(val) < epsilon ? math::ValueTraits<real_type>::zero() : val);
00330 }
00331
00332 }
00333
00334 }
00335
00336
00337 #endif