00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #ifndef SOFA_COMPONENT_FORCEFIELD_SPHFLUIDFORCEFIELD_INL
00026 #define SOFA_COMPONENT_FORCEFIELD_SPHFLUIDFORCEFIELD_INL
00027
00028 #include <sofa/component/forcefield/SPHFluidForceField.h>
00029 #include <sofa/component/container/SpatialGridContainer.inl>
00030 #include <sofa/helper/system/config.h>
00031 #include <sofa/helper/gl/template.h>
00032 #include <math.h>
00033 #include <iostream>
00034
00035 using std::cerr;
00036 using std::endl;
00037
00038 namespace sofa
00039 {
00040
00041 namespace component
00042 {
00043
00044 namespace forcefield
00045 {
00046
00047 template<class DataTypes>
00048 SPHFluidForceField<DataTypes>::SPHFluidForceField()
00049 : particleRadius (initData(&particleRadius ,Real(1) , "radius", "Radius of a Particle")),
00050 particleMass (initData(&particleMass ,Real(1) , "mass", "Mass of a Particle")),
00051 pressureStiffness(initData(&pressureStiffness,Real(100) , "pressure", "Pressure")),
00052 density0 (initData(&density0 ,Real(1) , "density", "Density")),
00053 viscosity (initData(&viscosity ,Real(0.001f), "viscosity", "Viscosity")),
00054 surfaceTension (initData(&surfaceTension ,Real(0) , "surfaceTension", "Surface Tension")),
00055 grid(NULL)
00056 {
00057 }
00058
00059
00060 template<class DataTypes>
00061 void SPHFluidForceField<DataTypes>::init()
00062 {
00063 this->Inherit::init();
00064 this->getContext()->get(grid);
00065 if (grid==NULL)
00066 std::cout << "WARNING: SpatialGridContainer not found by SPHFluidForceField, slow O(n2) method will be used !!!" << std::endl;
00067 int n = (*this->mstate->getX()).size();
00068 particles.resize(n);
00069 for (int i=0;i<n;i++)
00070 {
00071 particles[i].neighbors.clear();
00072 #ifdef SOFA_DEBUG_SPATIALGRIDCONTAINER
00073 particles[i].neighbors2.clear();
00074 #endif
00075 particles[i].density = density0.getValue();
00076 particles[i].pressure = 0;
00077 particles[i].normal.clear();
00078 particles[i].curvature = 0;
00079 }
00080 }
00081
00082 template<class DataTypes>
00083 void SPHFluidForceField<DataTypes>::addForce(VecDeriv& f, const VecCoord& x, const VecDeriv& v)
00084 {
00085 const Real h = particleRadius.getValue();
00086 const Real h2 = h*h;
00087 const Real m = particleMass.getValue();
00088 const Real m2 = m*m;
00089 const Real k = pressureStiffness.getValue();
00090 const Real d0 = density0.getValue();
00091 const Vec3d localg = this->getContext()->getLocalGravity();
00092 Deriv g;
00093 DataTypes::set ( g, localg[0], localg[1], localg[2]);
00094
00095 const int n = x.size();
00096
00097
00098 const Real CWd = constWd(h);
00099
00100
00101
00102 const Real CgradWp = constGradWp(h);
00103
00104
00105
00106 const Real ClaplacianWv = constLaplacianWv(h);
00107
00108 const Real CgradWc = constGradWc(h);
00109 const Real ClaplacianWc = constLaplacianWc(h);
00110
00111
00112 f.resize(n);
00113 dforces.clear();
00114 particles.resize(n);
00115 for (int i=0;i<n;i++)
00116 {
00117 particles[i].neighbors.clear();
00118 #ifdef SOFA_DEBUG_SPATIALGRIDCONTAINER
00119 particles[i].neighbors2.clear();
00120 #endif
00121 particles[i].density = 0;
00122 particles[i].pressure = 0;
00123 particles[i].normal.clear();
00124 particles[i].curvature = 0;
00125 }
00126
00127
00128
00129 if (grid == NULL)
00130 {
00131 for (int i=0;i<n;i++)
00132 {
00133 const Coord& ri = x[i];
00134 for (int j=i+1;j<n;j++)
00135 {
00136 const Coord& rj = x[j];
00137 Real r2 = (rj-ri).norm2();
00138 if (r2 < h2)
00139 {
00140 Real r_h = (Real)sqrt(r2/h2);
00141 particles[i].neighbors.push_back(std::make_pair(j,r_h));
00142
00143 }
00144 }
00145 }
00146 }
00147 else
00148 {
00149 grid->updateGrid(x);
00150 grid->findNeighbors(this, h);
00151 #ifdef SOFA_DEBUG_SPATIALGRIDCONTAINER
00152
00153 for (int i=0;i<n;i++)
00154 {
00155 const Coord& ri = x[i];
00156 for (int j=i+1;j<n;j++)
00157 {
00158 const Coord& rj = x[j];
00159 Real r2 = (rj-ri).norm2();
00160 if (r2 < h2)
00161 {
00162 Real r_h = (Real)sqrt(r2/h2);
00163 particles[i].neighbors2.push_back(std::make_pair(j,r_h));
00164 }
00165 }
00166 }
00167 for (int i=0;i<n;i++)
00168 {
00169 if (particles[i].neighbors.size() != particles[i].neighbors2.size())
00170 {
00171 std::cerr << "particle "<<i<<" "<< x[i] <<" : "<<particles[i].neighbors.size()<<" neighbors on grid, "<< particles[i].neighbors2.size() << " neighbors on bruteforce.\n";
00172 std::cerr << "grid-only neighbors:";
00173 for (unsigned int j=0;j<particles[i].neighbors.size();j++)
00174 {
00175 int index = particles[i].neighbors[j].first;
00176 unsigned int j2 = 0;
00177 while (j2 < particles[i].neighbors2.size() && particles[i].neighbors2[j2].first != index)
00178 ++j2;
00179 if (j2 == particles[i].neighbors2.size())
00180 std::cerr << " "<< x[index] << "<"<< particles[i].neighbors[j].first<<","<<particles[i].neighbors[j].second<<">";
00181 }
00182 std::cerr << "\n";
00183 std::cerr << "bruteforce-only neighbors:";
00184 for (unsigned int j=0;j<particles[i].neighbors2.size();j++)
00185 {
00186 int index = particles[i].neighbors2[j].first;
00187 unsigned int j2 = 0;
00188 while (j2 < particles[i].neighbors.size() && particles[i].neighbors[j2].first != index)
00189 ++j2;
00190 if (j2 == particles[i].neighbors.size())
00191 std::cerr << " "<< x[index] << "<"<< particles[i].neighbors2[j].first<<","<<particles[i].neighbors2[j].second<<">";
00192 }
00193 std::cerr << "\n";
00194 }
00195 }
00196 #endif
00197 }
00198
00199
00200 for (int i=0;i<n;i++)
00201 {
00202 Particle& Pi = particles[i];
00203 Real density = Pi.density;
00204 density += m*Wd(0,CWd);
00205 Deriv n;
00206 for (typename std::vector< std::pair<int,Real> >::const_iterator it = Pi.neighbors.begin(); it != Pi.neighbors.end(); ++it)
00207 {
00208 const int j = it->first;
00209 const Real r_h = it->second;
00210 Particle& Pj = particles[j];
00211 Real d = m*Wd(r_h,CWd);
00212 density += d;
00213 Pj.density += d;
00214 }
00215 Pi.density = density;
00216 Pi.pressure = k*(density - d0);
00217 }
00218
00219
00220 if (surfaceTension.getValue() > 0)
00221 {
00222 for (int i=0;i<n;i++)
00223 {
00224 Particle& Pi = particles[i];
00225 for (typename std::vector< std::pair<int,Real> >::const_iterator it = Pi.neighbors.begin(); it != Pi.neighbors.end(); ++it)
00226 {
00227 const int j = it->first;
00228 const Real r_h = it->second;
00229 Particle& Pj = particles[j];
00230 Deriv n = gradWc(x[i]-x[j],r_h,CgradWc) * (m / Pj.density - m / Pi.density);
00231 Pi.normal += n;
00232 Pj.normal -= n;
00233 Real c = laplacianWc(r_h,ClaplacianWc) * (m / Pj.density - m / Pi.density);
00234 Pi.curvature += c;
00235 Pj.curvature -= c;
00236 }
00237 }
00238 }
00239
00240
00241 for (int i=0;i<n;i++)
00242 {
00243 Particle& Pi = particles[i];
00244
00245
00246
00247
00248 for (typename std::vector< std::pair<int,Real> >::const_iterator it = Pi.neighbors.begin(); it != Pi.neighbors.end(); ++it)
00249 {
00250 const int j = it->first;
00251 const Real r_h = it->second;
00252 Particle& Pj = particles[j];
00253
00254 Deriv fpressure = gradWp(x[i]-x[j],r_h,CgradWp) * ( - m2 * (Pi.pressure / (Pi.density*Pi.density) + Pj.pressure / (Pj.density*Pj.density)) );
00255 f[i] += fpressure;
00256 f[j] -= fpressure;
00257
00258
00259 Deriv fviscosity = ( v[j] - v[i] ) * ( m2 * viscosity.getValue() / (Pi.density * Pj.density) * laplacianWv(r_h,ClaplacianWv) );
00260 f[i] += fviscosity;
00261 f[j] -= fviscosity;
00262 }
00263
00264 if (surfaceTension.getValue() > 0)
00265 {
00266 Real n = Pi.normal.norm();
00267 if (n > 0.000001)
00268 {
00269 Deriv fsurface = Pi.normal * ( - m * surfaceTension.getValue() * Pi.curvature / n );
00270 f[i] += fsurface;
00271 }
00272 }
00273 }
00274 }
00275
00276 template<class DataTypes>
00277 void SPHFluidForceField<DataTypes>::addDForce(VecDeriv& f1, const VecDeriv& dx1)
00278 {
00279 const VecCoord& p1 = *this->mstate->getX();
00280 f1.resize(dx1.size());
00281 for (unsigned int i=0; i<this->dforces.size(); i++)
00282 {
00283 const DForce& df = this->dforces[i];
00284 const unsigned int ia = df.a;
00285 const unsigned int ib = df.b;
00286 const Deriv u = p1[ib]-p1[ia];
00287 const Deriv du = dx1[ib]-dx1[ia];
00288 const Deriv dforce = u * (df.df * (du*u));
00289 f1[ia] += dforce;
00290 f1[ib] -= dforce;
00291 }
00292 }
00293
00294 template <class DataTypes>
00295 double SPHFluidForceField<DataTypes>::getPotentialEnergy(const VecCoord&)
00296 {
00297 cerr<<"SPHFluidForceField::getPotentialEnergy-not-implemented !!!"<<endl;
00298 return 0;
00299 }
00300
00301
00302 template<class DataTypes>
00303 void SPHFluidForceField<DataTypes>::draw()
00304 {
00305 if (!getContext()->getShowForceFields()) return;
00306
00307
00308 const VecCoord& x = *this->mstate->getX();
00309 glDisable(GL_LIGHTING);
00310 glEnable(GL_BLEND);
00311 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
00312 glDepthMask(0);
00313 glColor3f(0,1,1);
00314 glLineWidth(1);
00315 glBegin(GL_LINES);
00316 for (unsigned int i=0;i<particles.size();i++)
00317 {
00318 Particle& Pi = particles[i];
00319 #ifdef SOFA_DEBUG_SPATIALGRIDCONTAINER
00320
00321 if (Pi.neighbors.size() != Pi.neighbors2.size())
00322 {
00323 glColor4f(1,0,0,1);
00324 for (unsigned int j=0;j<Pi.neighbors.size();j++)
00325 {
00326 int index = Pi.neighbors[j].first;
00327 unsigned int j2 = 0;
00328 while (j2 < Pi.neighbors2.size() && Pi.neighbors2[j2].first != index)
00329 ++j2;
00330 if (j2 == Pi.neighbors2.size())
00331 {
00332 helper::gl::glVertexT(x[i]);
00333 helper::gl::glVertexT(x[index]);
00334 }
00335 }
00336 glColor4f(1,0,1,1);
00337 for (unsigned int j=0;j<Pi.neighbors2.size();j++)
00338 {
00339 int index = Pi.neighbors2[j].first;
00340 unsigned int j2 = 0;
00341 while (j2 < Pi.neighbors.size() && Pi.neighbors[j2].first != index)
00342 ++j2;
00343 if (j2 == Pi.neighbors.size())
00344 {
00345 helper::gl::glVertexT(x[i]);
00346 helper::gl::glVertexT(x[index]);
00347 }
00348 }
00349 }
00350 #else
00351 for (typename std::vector< std::pair<int,Real> >::const_iterator it = Pi.neighbors.begin(); it != Pi.neighbors.end(); ++it)
00352 {
00353 const int j = it->first;
00354 const float r_h = (float)it->second;
00355 float f = r_h*2;
00356 if (f < 1)
00357 {
00358 glColor4f(0,1-f,f,1-r_h);
00359 }
00360 else
00361 {
00362 glColor4f(f-1,0,2-f,1-r_h);
00363 }
00364 helper::gl::glVertexT(x[i]);
00365 helper::gl::glVertexT(x[j]);
00366 }
00367 #endif
00368 }
00369 glEnd();
00370 glDisable(GL_BLEND);
00371 glDepthMask(1);
00372 glPointSize(5);
00373 glBegin(GL_POINTS);
00374 for (unsigned int i=0;i<particles.size();i++)
00375 {
00376 Particle& Pi = particles[i];
00377 float f = (float)(Pi.density / density0.getValue());
00378 f = 1+10*(f-1);
00379 if (f < 1)
00380 {
00381 glColor3f(0,1-f,f);
00382 }
00383 else
00384 {
00385 glColor3f(f-1,0,2-f);
00386 }
00387 helper::gl::glVertexT(x[i]);
00388 }
00389 glEnd();
00390 glPointSize(1);
00391 }
00392
00393 }
00394
00395 }
00396
00397 }
00398
00399 #endif