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_BEHAVIORMODEL_EULERIANFLUID_GRID3D_H
00026 #define SOFA_COMPONENT_BEHAVIORMODEL_EULERIANFLUID_GRID3D_H
00027
00028 #include <sofa/defaulttype/Vec.h>
00029 #include <sofa/defaulttype/Mat.h>
00030 #include <sofa/helper/rmath.h>
00031 #include <iostream>
00032
00033
00034 namespace sofa
00035 {
00036
00037 namespace component
00038 {
00039
00040 namespace behaviormodel
00041 {
00042
00043 namespace eulerianfluid
00044 {
00045
00046 using namespace sofa::defaulttype;
00047 using namespace sofa::helper;
00048
00049 #ifndef NDEBUG
00050 #define DEBUGGRID
00051 #endif
00052
00053 class Grid3D
00054 {
00055 public:
00056
00057 typedef float real;
00058 typedef Vec<3,real> vec3;
00059
00060 struct Cell
00061 {
00062 vec3 u;
00063 int type;
00064 void clear()
00065 {
00066 u.clear();
00067 type = 0;
00068 }
00069 };
00070
00071 int nx,ny,nz,nxny,ncell;
00072
00073 enum { PART_EMPTY=0, PART_WALL=-1, PART_FULL=1 };
00074
00075 Cell* fdata;
00076 real* pressure;
00077 real* levelset;
00078
00079
00080 real t;
00081 real tend;
00082
00083 real max_pressure;
00084 Cell bcell;
00085
00086 vec3 gravity;
00087
00088 static const unsigned long* obstacles;
00089
00090 Grid3D();
00091 ~Grid3D();
00092
00093 void clear(int _nx,int _ny,int _nz);
00094
00095 template<class T>
00096 static inline T lerp(T a, T b, real f) { return a+(b-a)*f; }
00097
00098 int clamp_x(int x)
00099 {
00100 return (x<0)?0:(x>=nx)?nx-1:x;
00101 }
00102
00103 int clamp_y(int y)
00104 {
00105 return (y<0)?0:(y>=ny)?ny-1:y;
00106 }
00107
00108 int clamp_z(int z)
00109 {
00110 return (z<0)?0:(z>=nz)?nz-1:z;
00111 }
00112
00113 int clamp_in_x(int x)
00114 {
00115 return (x<1)?1:(x>=nx-1)?nx-2:x;
00116 }
00117
00118 int clamp_in_y(int y)
00119 {
00120 return (y<1)?1:(y>=ny-1)?ny-2:y;
00121 }
00122
00123 int clamp_in_z(int z)
00124 {
00125 return (z<1)?1:(z>=nz-1)?nz-2:z;
00126 }
00127
00128 int index(int x, int y, int z) const
00129 {
00130 return x + y*nx + z*nxny;
00131 }
00132
00133 int index(const vec3& p) const
00134 {
00135 return index(rnear(p[0]), rnear(p[1]), rnear(p[2]));
00136 }
00137
00138 Cell* get(int x, int y, int z, Cell* base) const
00139 {
00140 return base+index(x,y,z);
00141 }
00142
00143 const Cell* get(int x, int y, int z, const Cell* base) const
00144 {
00145 return base+index(x,y,z);
00146 }
00147
00148 Cell* get(int x, int y, int z)
00149 {
00150 #ifdef DEBUGGRID
00151 if (((unsigned)x>=(unsigned)nx) || ((unsigned)y>=(unsigned)ny) || ((unsigned)z>=(unsigned)nz))
00152 {
00153 std::cerr<<"INVALID CELL "<<x<<','<<y<<','<<z<<std::endl;
00154 return &bcell;
00155 }
00156 #endif
00157 return get(x,y,z,fdata);
00158 }
00159
00160 const Cell* get(int x, int y, int z) const
00161 {
00162 #ifdef DEBUGGRID
00163 if (((unsigned)x>=(unsigned)nx) || ((unsigned)y>=(unsigned)ny) || ((unsigned)z>=(unsigned)nz))
00164 {
00165 std::cerr<<"INVALID CELL "<<x<<','<<y<<','<<z<<std::endl;
00166 return &bcell;
00167 }
00168 #endif
00169 return get(x,y,z,fdata);
00170 }
00171
00172 Cell* get(const vec3& p)
00173 {
00174 return get(rnear(p[0]),rnear(p[1]),rnear(p[2]));
00175 }
00176
00177 const Cell* get(const vec3& p) const
00178 {
00179 return get(rnear(p[0]),rnear(p[1]),rnear(p[2]));
00180 }
00181
00182 template<int C> real interp(const Cell* base, real fx, real fy, real fz) const
00183 {
00184 return lerp( lerp( lerp(get(0,0,0,base)->u[C],get(1,0,0,base)->u[C],fx),
00185 lerp(get(0,1,0,base)->u[C],get(1,1,0,base)->u[C],fx), fy ),
00186 lerp( lerp(get(0,0,1,base)->u[C],get(1,0,1,base)->u[C],fx),
00187 lerp(get(0,1,1,base)->u[C],get(1,1,1,base)->u[C],fx), fy ),
00188 fz );
00189 }
00190
00191 template<int C> real interp(vec3 p) const
00192 {
00193 p[C] += 0.5;
00194 int ix = rfloor(p[0]);
00195 int iy = rfloor(p[1]);
00196 int iz = rfloor(p[2]);
00197 const Cell* base = get(ix,iy,iz);
00198 return interp<C>(base, p[0]-ix, p[1]-iy,p[2]-iz);
00199 }
00200
00201 vec3 interp(vec3 p) const
00202 {
00203 return vec3( interp<0>(p), interp<1>(p), interp<2>(p) );
00204 }
00205
00206 template<int C> void impulse(Cell* base, real fx, real fy, real fz, real i)
00207 {
00208 get(0,0,0,base)->u[C] += i*(1-fx)*(1-fy)*(1-fz);
00209 get(1,0,0,base)->u[C] += i*( fx)*(1-fy)*(1-fz);
00210 get(0,1,0,base)->u[C] += i*(1-fx)*( fy)*(1-fz);
00211 get(1,1,0,base)->u[C] += i*( fx)*( fy)*(1-fz);
00212 get(0,0,1,base)->u[C] += i*(1-fx)*(1-fy)*( fz);
00213 get(1,0,1,base)->u[C] += i*( fx)*(1-fy)*( fz);
00214 get(0,1,1,base)->u[C] += i*(1-fx)*( fy)*( fz);
00215 get(1,1,1,base)->u[C] += i*( fx)*( fy)*( fz);
00216 }
00217
00218 template<int C> void impulse(vec3 p, real i)
00219 {
00220 p[C] += 0.5;
00221 int ix = rfloor(p[0]);
00222 int iy = rfloor(p[1]);
00223 int iz = rfloor(p[2]);
00224 Cell* base = get(ix,iy,iz);
00225 impulse<C>(base, p[0]-ix, p[1]-iy,p[2]-iz, i);
00226 }
00227
00228 void impulse(const vec3& p, const vec3& i)
00229 {
00230 impulse<0>(p,i[0]);
00231 impulse<1>(p,i[1]);
00232 impulse<2>(p,i[2]);
00233 }
00234
00235 real* getpressure(int x, int y, int z)
00236 {
00237 return pressure + index(x,y,z);
00238 }
00239
00240 real getpressure(vec3 p)
00241 {
00242 int ix = rfloor(p[0]);
00243 int iy = rfloor(p[1]);
00244 int iz = rfloor(p[2]);
00245 real fx = p[0]-ix;
00246 real fy = p[1]-iy;
00247 real fz = p[2]-iz;
00248 real* base = getpressure(ix,iy,iz);
00249 return lerp( lerp( lerp(base[index(0,0,0)],base[index(1,0,0)],fx),
00250 lerp(base[index(0,1,0)],base[index(1,1,0)],fx), fy ),
00251 lerp( lerp(base[index(0,0,1)],base[index(1,0,1)],fx),
00252 lerp(base[index(0,1,1)],base[index(1,1,1)],fx), fy ),
00253 fz );
00254 }
00255
00256 real* getlevelset(int x, int y, int z)
00257 {
00258 return levelset + index(x,y,z);
00259 }
00260
00261 real getlevelset(vec3 p)
00262 {
00263 int ix = rfloor(p[0]);
00264 int iy = rfloor(p[1]);
00265 int iz = rfloor(p[2]);
00266 real fx = p[0]-ix;
00267 real fy = p[1]-iy;
00268 real fz = p[2]-iz;
00269 real* base = getlevelset(ix,iy,iz);
00270 return lerp( lerp( lerp(base[index(0,0,0)],base[index(1,0,0)],fx),
00271 lerp(base[index(0,1,0)],base[index(1,1,0)],fx), fy ),
00272 lerp( lerp(base[index(0,0,1)],base[index(1,0,1)],fx),
00273 lerp(base[index(0,1,1)],base[index(1,1,1)],fx), fy ),
00274 fz );
00275 }
00276
00277 void seed(real height);
00278
00279 void seed(real height, vec3 normal);
00280
00281 void seed(vec3 p0, vec3 p1, vec3 velocity=vec3(0,0,0));
00282
00283 void step(Grid3D* prev, Grid3D* temp, real dt=0.04, real diff=0.00001);
00284 void step_init(const Grid3D* prev, Grid3D* temp, real dt, real diff);
00285
00286 void step_levelset(Grid3D* prev, Grid3D* temp, real dt, real diff);
00287 void step_forces(const Grid3D* prev, Grid3D* temp, real dt, real diff, real scale=1.0);
00288 void step_surface(const Grid3D* prev, Grid3D* temp, real dt, real diff);
00289 void step_advect(const Grid3D* prev, Grid3D* temp, real dt, real diff);
00290 void step_diffuse(const Grid3D* prev, Grid3D* temp, real dt, real diff);
00291 void step_project(const Grid3D* prev, Grid3D* temp, real dt, real diff);
00292 void step_color(const Grid3D* prev, Grid3D* temp, real dt, real diff);
00293
00294
00295
00296
00297
00298 enum Status { FMM_FRONT0 = 0, FMM_FAR = -1, FMM_KNOWN = -2, FMM_BORDER = -3 };
00299 int* fmm_status;
00300 int* fmm_heap;
00301 int fmm_heap_size;
00302
00303 int fmm_pop();
00304 void fmm_push(int index);
00305 void fmm_swap(int entry1, int entry2);
00306 };
00307
00308 }
00309
00310 }
00311
00312 }
00313
00314 }
00315
00316 #endif