Go to the documentation of this file.00001 #ifndef OPENTISSUE_DYNAMICS_PSYS_FORCES_PSYS_PRESSURE_SOFTBODY_H
00002 #define OPENTISSUE_DYNAMICS_PSYS_FORCES_PSYS_PRESSURE_SOFTBODY_H
00003
00004
00005
00006
00007
00008
00009
00010 #include <OpenTissue/configuration.h>
00011
00012 #include <OpenTissue/dynamics/psys/mass_spring_system/psys_surface_mesh.h>
00013 #include <vector>
00014 #include <iostream>
00015
00016 namespace OpenTissue
00017 {
00018 namespace psys
00019 {
00020
00033 template< typename types >
00034 class PressureSoftBody
00035 : public types::force_type
00036 {
00037 public:
00038
00039 typedef typename types::math_types math_types;
00040 typedef typename math_types::real_type real_type;
00041 typedef typename math_types::vector3_type vector3_type;
00042 typedef typename types::coupling_type coupling_type;
00043 typedef typename types::mesh_type mesh_type;
00044 typedef typename mesh_type::face_type face_type;
00045 typedef typename mesh_type::face_iterator face_iterator;
00046 typedef typename mesh_type::face_vertex_circulator face_vertex_circulator;
00047
00048 protected:
00049
00050 coupling_type * m_coupling;
00051
00052 real_type m_P1;
00053 real_type m_Pa;
00054 real_type m_Pb;
00055 real_type m_Fa;
00056 real_type m_Fb;
00057 real_type m_Fc;
00058
00059 enum {
00060 m_X = 0,
00061 m_Y = 1,
00062 m_Z = 2
00063 };
00064
00065 int m_A;
00066 int m_B;
00067 int m_C;
00068
00069 protected:
00070
00071 std::vector<real_type> m_area;
00072 std::vector<real_type> m_d;
00073 std::vector<vector3_type> m_normal;
00074
00075 real_type m_initial_pressure_inside;
00076 real_type m_initial_volume;
00077 real_type m_nRT;
00078
00079 public:
00080
00081 PressureSoftBody()
00082 : m_initial_pressure_inside(10.0)
00083 {}
00084
00085 virtual ~PressureSoftBody() {}
00086
00087 public:
00088
00089 void init(coupling_type const & coupling)
00090 {
00091 m_coupling = const_cast<coupling_type*>( &coupling );
00092
00093 std::size_t N = m_coupling->mesh().size_faces();
00094
00095 m_normal.resize( N);
00096 m_d.resize(N);
00097 m_area.resize(N);
00098
00099
00100 m_initial_volume = compute_volume_integral(m_coupling->mesh());
00101 m_nRT = m_initial_pressure_inside * m_initial_volume;
00102
00103 std::cout << "PressureSoftBody::init(): initial volume = "
00104 << m_initial_volume
00105 << std::endl;
00106 std::cout << "PressureSoftBody::init(): initial pressure = "
00107 << m_initial_pressure_inside
00108 << std::endl;
00109 std::cout << "PressureSoftBody::init(): initial gas rhs = "
00110 << m_nRT
00111 << std::endl;
00112 }
00113
00114 void set_initial_pressure(real_type const & pressure)
00115 {
00116 if(pressure>0)
00117 {
00118 m_initial_pressure_inside = pressure;
00119 if(m_initial_volume)
00120 {
00121 m_nRT = m_initial_pressure_inside * m_initial_volume;
00122 }
00123 else
00124 {
00125 m_nRT = 0;
00126 }
00127 }
00128 }
00129
00130 real_type const & initial_pressure() const { return m_initial_pressure_inside; }
00131
00132 public:
00133
00134 void apply()
00135 {
00136 using std::fabs;
00137
00138 if(!m_coupling)
00139 return;
00140
00141
00142 real_type V = compute_volume_integral(m_coupling->mesh());
00143 real_type pressure = m_nRT/V;
00144
00145 if(pressure<=0)
00146 return;
00147
00148 mesh::compute_angle_weighted_vertex_normals( m_coupling->mesh() );
00149
00150 face_iterator f = m_coupling->mesh().face_begin();
00151 face_iterator end = m_coupling->mesh().face_end();
00152 for (int i=0;f!= end;++f,++i)
00153 {
00154 real_type N = valency(*f);
00155 real_type face_pressure = (fabs(m_area[i])*0.5*pressure);
00156 real_type vertex_pressure = face_pressure/N;
00157 typename mesh_type::face_vertex_circulator v(*f),vend;
00158 for(;v!=vend;++v)
00159 m_coupling->particle( *v ).force() += vertex_pressure*v->m_normal;
00160 }
00161 }
00162
00163 protected:
00164
00165 real_type const compute_volume_integral(mesh_type & mesh)
00166 {
00167 real_type volume = 0;
00168 face_iterator f = mesh.face_begin();
00169 face_iterator end = mesh.face_end();
00170 for (int i=0;f!= end;++f,++i)
00171 {
00172 face_vertex_circulator p1(*f);
00173 face_vertex_circulator p2(*f);++p2;
00174 face_vertex_circulator p3(*f);++p3;++p3;
00175
00176 vector3_type u1,u2,u1xu2;
00177
00178 u1 = p2->m_coord - p1->m_coord;
00179 u2 = p3->m_coord - p2->m_coord;
00180 u1xu2 = u1 % u2;
00181 m_area[i] = std::sqrt( u1xu2*u1xu2 );
00182 m_normal[i] = unit(u1xu2);
00183 m_d[i] = m_normal[i] * p1->m_coord;
00184
00185 vector3_type n(m_normal[i]);
00186
00187 real_type nx = std::fabs(n(m_X));
00188 real_type ny = std::fabs(n(m_Y));
00189 real_type nz = std::fabs(n(m_Z));
00190
00191 if(!(nx || ny || nz))
00192 continue;
00193
00194
00195 if(nx > ny && nx > nz)
00196 m_C = m_X;
00197 else
00198 m_C = (ny > nz) ? m_Y : m_Z;
00199 m_A = (m_C + 1) % 3;
00200 m_B = (m_C + 2) % 3;
00201
00202 compute_face_integral(*f,n,m_d[i]);
00203
00204 volume += n(m_X) * ((m_A == m_X) ? m_Fa : ((m_B == m_X) ? m_Fb : m_Fc));
00205 }
00206 return volume;
00207 }
00208
00209 void compute_face_integral(face_type & f,vector3_type & n,const real_type & d)
00210 {
00211 compute_projection_integral(f);
00212 real_type w = -d;
00213 real_type k1 = 1 / n(m_C);
00214 real_type k2 = k1 * k1;
00215 m_Fa = k1 * m_Pa;
00216 m_Fb = k1 * m_Pb;
00217 m_Fc = -k2 * (n(m_A)*m_Pa + n(m_B)*m_Pb + w*m_P1);
00218 }
00219
00220 void compute_projection_integral(face_type & f)
00221 {
00222 m_P1 = m_Pa = m_Pb = static_cast<real_type>(0.0);
00223 face_vertex_circulator v1(f),vend;
00224 face_vertex_circulator v2(f);++v2;
00225 for(;v1!=vend;++v1,++v2)
00226 {
00227 real_type a0 = v1->m_coord(m_A);
00228 real_type b0 = v1->m_coord(m_B);
00229 real_type a1 = v2->m_coord(m_A);
00230 real_type b1 = v2->m_coord(m_B);
00231 real_type da = a1 - a0;
00232 real_type db = b1 - b0;
00233 real_type a0_2 = a0 * a0;
00234 real_type b0_2 = b0 * b0;
00235 real_type C1 = a1 + a0;
00236 real_type Ca = a1*C1 + a0_2;
00237 real_type Cb = b1*(b1 + b0) + b0_2;
00238 m_P1 += db*C1;
00239 m_Pa += db*Ca;
00240 m_Pb += da*Cb;
00241 }
00242 m_P1 /= static_cast<real_type>( 2.0);
00243 m_Pa /= static_cast<real_type>( 6.0);
00244 m_Pb /= static_cast<real_type>(-6.0);
00245 }
00246
00247 };
00248
00249 }
00250 }
00251
00252
00253 #endif