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 #include <iostream>
00026 #include <sofa/component/behaviormodel/eulerianfluid/Grid3D.h>
00027 #include <cstring>
00028
00029 namespace sofa
00030 {
00031
00032 namespace component
00033 {
00034
00035 namespace behaviormodel
00036 {
00037
00038 namespace eulerianfluid
00039 {
00040
00041 const unsigned long* Grid3D::obstacles = NULL;
00042
00043 #define LEVELSET_MARGIN 0.01f
00044
00045
00046
00047 #define FOR_ALL_CELLS(grid,cmd) \
00048 { \
00049 int ind = index(0,0,0); \
00050 for (int z=0;z<nz;z++) \
00051 for (int y=0;y<ny;y++) \
00052 for (int x=0;x<nx;x++,ind+=index(1,0,0)) \
00053 { \
00054 cmd; \
00055 } \
00056 }
00057
00058 #define FOR_READ_INNER_CELLS(cmd) \
00059 { \
00060 int ind = index(1,1,1); \
00061 for (int z=1;z<nz-1;z++,ind+=index(0,2,0)) \
00062 for (int y=1;y<ny-1;y++,ind+=index(2,0,0)) \
00063 for (int x=1;x<nx-1;x++,ind+=index(1,0,0))\
00064 { \
00065 cmd; \
00066 } \
00067 }
00068
00069 #define FOR_INNER_CELLS(grid,cmd) \
00070 { \
00071 int ind = index(1,1,1); \
00072 for (int z=1;z<nz-1;z++,ind+=index(0,2,0)) \
00073 for (int y=1;y<ny-1;y++,ind+=index(2,0,0)) \
00074 for (int x=1;x<nx-1;x++,ind+=index(1,0,0))\
00075 { \
00076 cmd; \
00077 } \
00078 }
00079
00080
00081
00082
00083 #define FOR_SURFACE_CELLS(grid,cmd) \
00084 { \
00085 int ind = index(1,1,1); \
00086 for (int z=1;z<nz-1;z++,ind+=index(0,2,0)) \
00087 for (int y=1;y<ny-1;y++,ind+=index(2,0,0)) \
00088 for (int x=1;x<nx-1;x++,ind+=index(1,0,0))\
00089 { \
00090 cmd; \
00091 } \
00092 }
00093
00094 Grid3D::Grid3D()
00095 : nx(0), ny(0), nz(0), nxny(0), ncell(0),
00096 fdata(NULL), pressure(NULL), levelset(NULL),
00097 t(0), tend(60),
00098 max_pressure(0.0),
00099 gravity(0,-5,0),
00100 fmm_status(NULL),
00101 fmm_heap(NULL),
00102 fmm_heap_size(0)
00103 {
00104 bcell.u.clear();
00105 bcell.type=-1;
00106 }
00107
00108 Grid3D::~Grid3D()
00109 {
00110 if (fdata!=NULL) delete[] fdata;
00111 if (pressure!=NULL) delete[] pressure;
00112 if (levelset!=NULL) delete[] levelset;
00113 if (fmm_status!=NULL) delete[] fmm_status;
00114 if (fmm_heap!=NULL) delete[] fmm_heap;
00115 }
00116
00117 void Grid3D::clear(int _nx, int _ny, int _nz)
00118 {
00119 t = 0;
00120 tend = 40;
00121
00122 int old_ncell=ncell;
00123 nx=_nx; ny=_ny; nz=_nz;
00124 nxny = nx*ny; ncell = nxny*nz;
00125
00126 if (ncell != old_ncell)
00127 {
00128 if (fdata!=NULL) delete[] fdata;
00129 if (ncell>0) fdata = new Cell[ncell];
00130 else fdata = NULL;
00131 if (pressure!=NULL) delete[] pressure;
00132 if (ncell>0) pressure = new real[ncell];
00133 else pressure = NULL;
00134 if (levelset!=NULL) delete[] levelset;
00135 if (ncell>0) levelset = new real[ncell];
00136 else levelset = NULL;
00137 if (fmm_status!=NULL) delete[] fmm_status;
00138 if (ncell>0) fmm_status = new int[ncell];
00139 else fmm_status = NULL;
00140 if (fmm_heap!=NULL) delete[] fmm_heap;
00141 if (ncell>0) fmm_heap = new int[ncell];
00142 else fmm_heap = NULL;
00143 }
00144 if (ncell>0)
00145 memset(fdata,0,ncell*sizeof(Cell));
00146 if (ncell>0)
00147 memset(pressure,0,ncell*sizeof(real));
00148 if (ncell>0)
00149 memset(levelset,0,ncell*sizeof(real));
00150 }
00151
00152 void Grid3D::seed(real height)
00153 {
00154
00155 FOR_ALL_CELLS(fdata,
00156 {
00157 real d = y - height;
00158 levelset[ind] = d;
00159 });
00160 }
00161
00162 void Grid3D::seed(real height, vec3 normal)
00163 {
00164 normal.normalize();
00165 FOR_ALL_CELLS(fdata,
00166 {
00167 real d = vec3((real)x,(real)y,(real)z)*normal - height;
00168 levelset[ind] = d;
00169 });
00170 }
00171
00172 void Grid3D::seed(vec3 p0, vec3 p1, vec3 velocity)
00173 {
00174 if (p0[0]<0.5f) p0[0]=0.5f;
00175 if (p0[1]<0.5f) p0[1]=0.5f;
00176 if (p0[2]<0.5f) p0[2]=0.5f;
00177 if (p1[0]>nx-1.5f) p1[0]=nx-1.5f;
00178 if (p1[1]>ny-1.5f) p1[1]=ny-1.5f;
00179 if (p1[2]>nz-1.5f) p1[2]=nz-1.5f;
00180 if (p0[0]>=p1[0]) return;
00181 if (p0[1]>=p1[1]) return;
00182 if (p0[2]>=p1[2]) return;
00183 std::cout << "p0="<<p0<<" p1="<<p1<<std::endl;
00184 vec3 center = (p0+p1)*0.5f;
00185 vec3 dim = (p1-p0)*0.5f;
00186 FOR_ALL_CELLS(fdata,
00187 {
00188 vec3 v ((real)x,(real)y,(real)z);
00189 v -= center;
00190 v[0] = rabs(v[0]) - dim[0];
00191 v[1] = rabs(v[1]) - dim[1];
00192 v[2] = rabs(v[2]) - dim[2];
00193 real d;
00194 if (v[0] <= 0 && v[1] <= 0 && v[2] <= 0)
00195 {
00196 d = rmax(v[0],rmax(v[1],v[2]));
00197 fdata[ind].u = velocity;
00198 }
00199 else
00200 {
00201 if (v[0] < 0) v[0] = 0;
00202 if (v[1] < 0) v[1] = 0;
00203 if (v[2] < 0) v[2] = 0;
00204 d = v.norm();
00205 }
00206 levelset[ind] = d;
00207 });
00208 }
00209
00210 void Grid3D::step(Grid3D* prev, Grid3D* temp, real dt, real diff)
00211 {
00212 t = prev->t+dt;
00213 tend = prev->tend;
00214
00215
00216
00217
00218
00219 step_init(prev, temp, dt, diff);
00220
00221
00222 step_forces(prev, temp, dt, diff);
00223 step_surface(prev, temp, dt, diff);
00224 step_advect(prev, temp, dt, diff);
00225 step_diffuse(prev, temp, dt, diff);
00226 step_project(prev, temp, dt, diff);
00227 step_levelset(prev, temp, dt, diff);
00228
00229
00230
00231
00232 }
00233
00236
00237 void Grid3D::step_init(const Grid3D* prev, Grid3D* , real , real )
00238 {
00239
00240
00241
00242 int bsize = 1;
00243
00244
00245
00246
00247
00248 const unsigned char* obs = (const unsigned char*)obstacles;
00249 int lnsize = (nx+7)/8;
00250 int plsize = lnsize*ny;
00251
00252
00253
00254 FOR_ALL_CELLS(fdata,
00255 {
00256
00257 levelset[ind] = prev->levelset[ind];
00258 if (x<bsize || y<bsize || z<bsize || x>=nx-bsize || y>=ny-bsize || z>=nz-bsize
00259
00260 || (obs!=NULL && ((obs[(z)*plsize+(y)*lnsize+((x)>>3)])&(1<<((x)&7))))
00261 )
00262 {
00263 fdata[ind].type = PART_WALL;
00264 }
00265 else
00266 {
00267 if (levelset[ind] < LEVELSET_MARGIN)
00268 fdata[ind].type = PART_FULL;
00269 else
00270 fdata[ind].type = PART_EMPTY;
00271 }
00272 });
00273 }
00274
00277
00278 #define RMAX 1e10
00279
00280 void Grid3D::step_levelset(Grid3D* prev, Grid3D* temp, real dt, real )
00281 {
00282
00283
00284
00285
00286
00287
00288
00289 FOR_INNER_CELLS(levelset,
00290 {
00291
00292 if (rabs(prev->levelset[ind]) < 5)
00293 {
00294 vec3 xn ( (real)x, (real)y, (real)z );
00295
00296 vec3 un = interp(xn);
00297 vec3 xn1 = xn - un*dt;
00298
00299
00300
00301 un = (un + interp(xn1))*0.5;
00302 xn1 = xn - un*dt;
00303
00304 temp->levelset[ind] = prev->getlevelset(xn1);
00305 }
00306 else
00307 temp->levelset[ind] = prev->levelset[ind];
00308 });
00309
00310
00311
00312 FOR_ALL_CELLS(fmm_status,
00313 {
00314 fmm_status[ind] = FMM_FAR;
00315 if (fdata[ind].type == PART_WALL)
00316 {
00317
00318 real phi = 0;
00319 int n = 0;
00320 for (int dz=-1;dz<=1;dz++)
00321 if ((unsigned)(z+dz)<(unsigned)nz)
00322 for (int dy=-1;dy<=1;dy++)
00323 if ((unsigned)(y+dy)<(unsigned)ny)
00324 for (int dx=-1;dx<=1;dx++)
00325 if ((unsigned)(x+dx)<(unsigned)nx)
00326 {
00327 int ind2 = ind+index(dx,dy,dz);
00328 if (fdata[ind2].type != PART_WALL)
00329 {
00330 phi += temp->levelset[ind2];
00331 ++n;
00332 }
00333 }
00334 temp->levelset[ind] = phi/n;
00335 }
00336 });
00337
00338
00339
00340
00341 fmm_heap_size = 0;
00342 const int cmax[3] = { nx-1, ny-1, nz-1 };
00343 const int dind[3] = { 1, nx, nxny };
00344
00345
00346 FOR_ALL_CELLS(fdata,
00347 {
00348 int c[3]; c[0] = x; c[1] = y; c[2] = z;
00349 bool known = false;
00350 real phi0 = temp->levelset[ind];
00351 real inv_dist2 = 0;
00352 for (int dim = 0; dim < 3; dim++)
00353 {
00354 real dist = RMAX;
00355 bool border = false;
00356 if (c[dim]>0)
00357 {
00358 real phi1 = temp->levelset[ind-dind[dim]];
00359 if (phi1*phi0 < 0)
00360 {
00361 dist = phi0/(phi0-phi1);
00362 border = true;
00363 }
00364 }
00365 if (c[dim]<cmax[dim])
00366 {
00367 real phi1 = temp->levelset[ind+dind[dim]];
00368 if (phi1*phi0 < 0)
00369 {
00370 real d = phi0/(phi0-phi1);
00371 if (d < dist) dist = d;
00372 border = true;
00373 }
00374 }
00375 if (border)
00376 {
00377 known = true;
00378 inv_dist2 += 1 / (dist*dist);
00379 }
00380 }
00381 if (known)
00382 {
00383
00384 real phi = rabs(phi0);
00385 levelset[ind] = phi;
00386 fmm_status[ind] = FMM_KNOWN;
00387 }
00388 else
00389 {
00390 levelset[ind] = 5;
00391 fmm_status[ind] = FMM_FAR;
00392 }
00393 });
00394
00395
00396 FOR_ALL_CELLS(fdata,
00397 {
00398 if (fmm_status[ind] == FMM_KNOWN)
00399 {
00400 int c[3]; c[0] = x; c[1] = y; c[2] = z;
00401 real phi1 = levelset[ind];
00402 phi1+=1;
00403 for (int dim = 0; dim < 3; dim++)
00404 {
00405 if (c[dim]>0)
00406 {
00407 int ind2 = ind-dind[dim];
00408 if (fmm_status[ind2] >= FMM_FAR)
00409 {
00410 real phi2 = levelset[ind2];
00411 if ((phi1) < (phi2))
00412 {
00413 levelset[ind2] = phi1;
00414 fmm_push(ind2);
00415 }
00416 }
00417 }
00418 if (c[dim]<cmax[dim])
00419 {
00420 int ind2 = ind+dind[dim];
00421 if (fmm_status[ind2] >= FMM_FAR)
00422 {
00423 real phi2 = levelset[ind2];
00424 if ((phi1) < (phi2))
00425 {
00426 levelset[ind2] = phi1;
00427 fmm_push(ind2);
00428 }
00429 }
00430 }
00431 }
00432 }
00433 });
00434
00435 while (fmm_heap_size > 0)
00436 {
00437 int ind = fmm_pop();
00438 real phi1 = levelset[ind]+1;
00439 if ((phi1) >= 5) break;
00440 int c[3] = { ind % nx, (ind / nx) % ny, ind / nxny };
00441 for (int dim = 0; dim < 3; dim++)
00442 {
00443 if (c[dim]>0)
00444 {
00445 int ind2 = ind-dind[dim];
00446 if (fmm_status[ind2] >= FMM_FAR)
00447 {
00448 real phi2 = levelset[ind2];
00449 if ((phi1) < (phi2))
00450 {
00451 levelset[ind2] = phi1;
00452 fmm_push(ind2);
00453 }
00454 }
00455 }
00456 if (c[dim]<cmax[dim])
00457 {
00458 int ind2 = ind+dind[dim];
00459 if (fmm_status[ind2] >= FMM_FAR)
00460 {
00461 real phi2 = levelset[ind2];
00462 if ((phi1) < (phi2))
00463 {
00464 levelset[ind2] = phi1;
00465 fmm_push(ind2);
00466 }
00467 }
00468 }
00469 }
00470 }
00471
00472 FOR_ALL_CELLS(levelset,
00473 {
00474 if(temp->levelset[ind] < 0)
00475 {
00476 levelset[ind] = -levelset[ind];
00477 }
00478 if (levelset[ind] < LEVELSET_MARGIN)
00479 {
00480 if (fdata[ind].type == PART_EMPTY)
00481 fdata[ind].type = PART_FULL;
00482 }
00483 else
00484 {
00485 if (fdata[ind].type == PART_FULL)
00486 fdata[ind].type = PART_EMPTY;
00487 }
00488 });
00489 }
00490
00491 inline void Grid3D::fmm_swap(int entry1, int entry2)
00492 {
00493 int ind1 = fmm_heap[entry1];
00494 int ind2 = fmm_heap[entry2];
00495 fmm_heap[entry1] = ind2;
00496 fmm_heap[entry2] = ind1;
00497 fmm_status[ind1] = entry2 + FMM_FRONT0;
00498 fmm_status[ind2] = entry1 + FMM_FRONT0;
00499 }
00500
00501 int Grid3D::fmm_pop()
00502 {
00503 int res = fmm_heap[0];
00504 #ifdef FMM_VERBOSE
00505 std::cout << "fmm_pop -> <"<<(res%nx)<<','<<((res/nx)%ny)<<','<<(res/nxny)<<">="<<levelset[res]<<std::endl;
00506 #endif
00507 --fmm_heap_size;
00508 if (fmm_heap_size>0)
00509 {
00510 fmm_swap(0, fmm_heap_size);
00511 int i=0;
00512 real phi = (levelset[fmm_heap[i]]);
00513 while (i*2+1 < fmm_heap_size)
00514 {
00515 real phi1 = (levelset[fmm_heap[i*2+1]]);
00516 if (i*2+2 < fmm_heap_size)
00517 {
00518 real phi2 = (levelset[fmm_heap[i*2+2]]);
00519 if (phi1 < phi)
00520 {
00521 if (phi1 < phi2)
00522 {
00523 fmm_swap(i, i*2+1);
00524 i = i*2+1;
00525 }
00526 else
00527 {
00528 fmm_swap(i, i*2+2);
00529 i = i*2+2;
00530 }
00531 }
00532 else if (phi2 < phi)
00533 {
00534 fmm_swap(i, i*2+2);
00535 i = i*2+2;
00536 }
00537 else break;
00538 }
00539 else if (phi1 < phi)
00540 {
00541 fmm_swap(i, i*2+1);
00542 i = i*2+1;
00543 }
00544 else break;
00545 }
00546 }
00547 #ifdef FMM_VERBOSE
00548 std::cout << "fmm_heap = [";
00549 for (int i=0;i<fmm_heap_size;i++)
00550 std::cout << " <"<<(fmm_heap[i]%nx)<<','<<((fmm_heap[i]/nx)%ny)<<','<<(fmm_heap[i]/nxny)<<">="<<levelset[fmm_heap[i]];
00551 std::cout << std::endl;
00552 #endif
00553 fmm_status[res] = FMM_KNOWN;
00554 return res;
00555 }
00556
00557 void Grid3D::fmm_push(int index)
00558 {
00559 real phi = (levelset[index]);
00560 int i;
00561 if (fmm_status[index] >= FMM_FRONT0)
00562 {
00563 i = fmm_status[index] - FMM_FRONT0;
00564 #ifdef FMM_VERBOSE
00565 std::cout << "fmm update <"<<(index%nx)<<','<<((index/nx)%ny)<<','<<(index/nxny)<<">="<<levelset[index]<<" from entry "<<i<<std::endl;
00566 #endif
00567 while (i>0 && phi < (levelset[fmm_heap[(i-1)/2]]))
00568 {
00569 fmm_swap(i,(i-1)/2);
00570 i = (i-1)/2;
00571 }
00572 while (i*2+1 < fmm_heap_size)
00573 {
00574 real phi1 = (levelset[fmm_heap[i*2+1]]);
00575 if (i*2+2 < fmm_heap_size)
00576 {
00577 real phi2 = (levelset[fmm_heap[i*2+2]]);
00578 if (phi1 < phi)
00579 {
00580 if (phi1 < phi2)
00581 {
00582 fmm_swap(i, i*2+1);
00583 i = i*2+1;
00584 }
00585 else
00586 {
00587 fmm_swap(i, i*2+2);
00588 i = i*2+2;
00589 }
00590 }
00591 else if (phi2 < phi)
00592 {
00593 fmm_swap(i, i*2+2);
00594 i = i*2+2;
00595 }
00596 else break;
00597 }
00598 else if (phi1 < phi)
00599 {
00600 fmm_swap(i, i*2+1);
00601 i = i*2+1;
00602 }
00603 else break;
00604 }
00605 }
00606 else
00607 {
00608 #ifdef FMM_VERBOSE
00609 std::cout << "fmm push <"<<(index%nx)<<','<<((index/nx)%ny)<<','<<(index/nxny)<<">="<<levelset[index]<<std::endl;
00610 #endif
00611 i = fmm_heap_size;
00612 ++fmm_heap_size;
00613 fmm_heap[i] = index;
00614 fmm_status[index] = i;
00615 while (i>0 && phi < (levelset[fmm_heap[(i-1)/2]]))
00616 {
00617 fmm_swap(i,(i-1)/2);
00618 i = (i-1)/2;
00619 }
00620 }
00621 #ifdef FMM_VERBOSE
00622 std::cout << "fmm_heap = [";
00623 for (int i=0;i<fmm_heap_size;i++)
00624 std::cout << " <"<<(fmm_heap[i]%nx)<<','<<((fmm_heap[i]/nx)%ny)<<','<<(fmm_heap[i]/nxny)<<">="<<levelset[fmm_heap[i]];
00625 std::cout << std::endl;
00626 #endif
00627 }
00628
00633
00634 void Grid3D::step_forces(const Grid3D* prev, Grid3D* , real dt, real , real )
00635 {
00636
00637
00638
00639
00640
00641
00642 vec3 f = gravity * dt;
00643
00644 FOR_INNER_CELLS(fdata,
00645 {
00646 vec3 u = f;
00647 int p0 = fdata[ind].type;
00648 if (p0 < 0)
00649 u.clear();
00650 else
00651 {
00652 int p1;
00653
00654 p1 = fdata[ind+index(-1,0,0)].type;
00655 if (p1>=0 && p0+p1>0)
00656 {
00657
00658 u[0] += prev->fdata[ind].u[0];
00659
00660
00661 }
00662 else
00663 u[0] = 0;
00664
00665 p1 = fdata[ind+index(0,-1,0)].type;
00666 if (p1>=0 && p0+p1>0)
00667 {
00668
00669 u[1] += prev->fdata[ind].u[1];
00670
00671
00672 }
00673 else
00674 u[1] = 0;
00675
00676 p1 = fdata[ind+index(0,0,-1)].type;
00677 if (p1>=0 && p0+p1>0)
00678 {
00679
00680 u[2] += prev->fdata[ind].u[2];
00681
00682
00683 }
00684 else
00685 u[2] = 0;
00686 }
00687 fdata[ind].u = u;
00688 });
00689
00690
00691
00692 if (t > 0 && t < tend)
00693 {
00694 float f = 2*t;
00695 srand(*(const unsigned int*)(const void*)&f);
00696 vec3 v(4,0,-4);
00697 int cx = 1*nz/4;
00698 int cy = 3*ny/4;
00699 int cz = 3*nz/4;
00700 real r = nz/8.0f;
00701 if (t < 1) r *= t;
00702 else if (t>tend-1) r*= tend-t;
00703 int ir = rceil(r)+5;
00704
00705
00706
00707
00708
00709
00710
00711
00712
00713 for (int z=cz-ir;z<=cz+ir;z++)
00714 if ((unsigned)z<(unsigned)nz)
00715 for (int y=cy-ir;y<=cy+ir;y++)
00716 if ((unsigned)y<(unsigned)ny)
00717 for (int x=cx-ir;x<=cx+ir;x++)
00718 {
00719 real d = sqrtf((real)((z-cz)*(z-cz)+(y-cy)*(y-cy)+(x-cx)*(x-cx))) - r;
00720 int ind = index(x,y,z);
00721 if (d < LEVELSET_MARGIN)
00722 {
00723 fdata[ind].u = v;
00724 if (fdata[ind].type == PART_EMPTY)
00725 fdata[ind].type = PART_FULL;
00726 }
00727 if (d < levelset[ind])
00728 levelset[ind] = d;
00729 }
00730 }
00731 }
00732
00735
00736 void Grid3D::step_surface(const Grid3D* , Grid3D* , real , real )
00737 {
00738
00739
00740
00741
00742 enum {
00743 FACE_X0=1<<0,
00744 FACE_X1=1<<1,
00745 FACE_Y0=1<<2,
00746 FACE_Y1=1<<3,
00747 FACE_Z0=1<<4,
00748 FACE_Z1=1<<5,
00749 };
00750
00751 FOR_SURFACE_CELLS(fdata,
00752 {
00753 if (fdata[ind].type>0)
00754 {
00755
00756 int mask = 0;
00757 if (fdata[ind+index(-1,0,0)].type==0) mask|=FACE_X0;
00758 if (fdata[ind+index( 1,0,0)].type==0) mask|=FACE_X1;
00759 if (fdata[ind+index(0,-1,0)].type==0) mask|=FACE_Y0;
00760 if (fdata[ind+index(0, 1,0)].type==0) mask|=FACE_Y1;
00761 if (fdata[ind+index(0,0,-1)].type==0) mask|=FACE_Z0;
00762 if (fdata[ind+index(0,0, 1)].type==0) mask|=FACE_Z1;
00763 if (mask!=0)
00764 {
00765 real& x0 = fdata[ind].u[0];
00766 real& y0 = fdata[ind].u[1];
00767 real& z0 = fdata[ind].u[2];
00768 real& x1 = fdata[ind+index( 1,0,0)].u[0];
00769 real& y1 = fdata[ind+index(0, 1,0)].u[1];
00770 real& z1 = fdata[ind+index(0,0, 1)].u[2];
00771 real r;
00772
00773 switch (mask)
00774 {
00775
00776
00777 case FACE_X0: x0 = x1 +y1-y0+z1-z0; break;
00778 case FACE_X1: x1 = x0 +y0-y1+z0-z1; break;
00779 case FACE_Y0: y0 = x1-x0+y1 +z1-z0; break;
00780 case FACE_Y1: y1 = x0-x1+y0 +z0-z1; break;
00781 case FACE_Z0: z0 = x1-x0+y1-y0+z1 ; break;
00782 case FACE_Z1: z1 = x0-x1+y0-y1+z0 ; break;
00783
00784
00785
00786 case FACE_X0|FACE_X1: break;
00787 case FACE_Y0|FACE_Y1: break;
00788 case FACE_Z0|FACE_Z1: break;
00789
00790 case FACE_X0|FACE_Y0: r = (z1-z0)*0.5f; x0 = x1+r; y0 = y1+r; break;
00791 case FACE_X0|FACE_Y1: r = (z1-z0)*0.5f; x0 = x1+r; y1 = y0-r; break;
00792 case FACE_X0|FACE_Z0: r = (y1-y0)*0.5f; x0 = x1+r; z0 = z1+r; break;
00793 case FACE_X0|FACE_Z1: r = (y1-y0)*0.5f; x0 = x1+r; z1 = z0-r; break;
00794 case FACE_X1|FACE_Y0: r = (z1-z0)*0.5f; x1 = x0-r; y0 = y1+r; break;
00795 case FACE_X1|FACE_Y1: r = (z1-z0)*0.5f; x1 = x0-r; y1 = y0-r; break;
00796 case FACE_X1|FACE_Z0: r = (y1-y0)*0.5f; x1 = x0-r; z0 = z1+r; break;
00797 case FACE_X1|FACE_Z1: r = (y1-y0)*0.5f; x1 = x0-r; z1 = z0-r; break;
00798 case FACE_Y0|FACE_Z0: r = (x1-x0)*0.5f; y0 = y1+r; z0 = z1+r; break;
00799 case FACE_Y0|FACE_Z1: r = (x1-x0)*0.5f; y0 = y1+r; z1 = z0-r; break;
00800 case FACE_Y1|FACE_Z0: r = (x1-x0)*0.5f; y1 = y0-r; z0 = z1+r; break;
00801 case FACE_Y1|FACE_Z1: r = (x1-x0)*0.5f; y1 = y0-r; z1 = z0-r; break;
00802
00803
00804 case FACE_X0|FACE_Y0|FACE_Z0: x0 = x1; y0 = y1; z0 = z1; break;
00805 case FACE_X1|FACE_Y0|FACE_Z0: x1 = x0; y0 = y1; z0 = z1; break;
00806 case FACE_X0|FACE_Y1|FACE_Z0: x0 = x1; y1 = y0; z0 = z1; break;
00807 case FACE_X1|FACE_Y1|FACE_Z0: x1 = x0; y1 = y0; z0 = z1; break;
00808 case FACE_X0|FACE_Y0|FACE_Z1: x0 = x1; y0 = y1; z1 = z0; break;
00809 case FACE_X1|FACE_Y0|FACE_Z1: x1 = x0; y0 = y1; z1 = z0; break;
00810 case FACE_X0|FACE_Y1|FACE_Z1: x0 = x1; y1 = y0; z1 = z0; break;
00811 case FACE_X1|FACE_Y1|FACE_Z1: x1 = x0; y1 = y0; z1 = z0; break;
00812
00813 case FACE_X0|FACE_Y0|FACE_Y1: x0 = x1 +y1-y0+z1-z0; break;
00814 case FACE_X0|FACE_Z0|FACE_Z1: x0 = x1 +y1-y0+z1-z0; break;
00815 case FACE_X1|FACE_Y0|FACE_Y1: x1 = x0 +y0-y1+z0-z1; break;
00816 case FACE_X1|FACE_Z0|FACE_Z1: x1 = x0 +y0-y1+z0-z1; break;
00817 case FACE_Y0|FACE_X0|FACE_X1: y0 = x1-x0+y1 +z1-z0; break;
00818 case FACE_Y0|FACE_Z0|FACE_Z1: y0 = x1-x0+y1 +z1-z0; break;
00819 case FACE_Y1|FACE_X0|FACE_X1: y1 = x0-x1+y0 +z0-z1; break;
00820 case FACE_Y1|FACE_Z0|FACE_Z1: y1 = x0-x1+y0 +z0-z1; break;
00821 case FACE_Z0|FACE_Y0|FACE_Y1: z0 = x1-x0+y1-y0+z1 ; break;
00822 case FACE_Z0|FACE_X0|FACE_X1: z0 = x1-x0+y1-y0+z1 ; break;
00823 case FACE_Z1|FACE_Y0|FACE_Y1: z1 = x0-x1+y0-y1+z0 ; break;
00824 case FACE_Z1|FACE_X0|FACE_X1: z1 = x0-x1+y0-y1+z0 ; break;
00825
00826
00827 case FACE_X0|FACE_X1|FACE_Y0|FACE_Y1: r = ( z1-z0)*0.25f; x0 = r; x1 = -r; y0 = r; y1 = -r; break;
00828 case FACE_X0|FACE_X1|FACE_Z0|FACE_Z1: r = ( z1-z0)*0.25f; x0 = r; x1 = -r; z0 = r; z1 = -r; break;
00829 case FACE_Y0|FACE_Y1|FACE_Z0|FACE_Z1: r = ( z1-z0)*0.25f; y0 = r; y1 = -r; y0 = r; y1 = -r; break;
00830
00831 case FACE_X0|FACE_X1|FACE_Y0|FACE_Z0: y0 = y1; z0 = z1; r = ( y1+z1)*0.5f; x0 = r; x1 = r; break;
00832 case FACE_X0|FACE_X1|FACE_Y1|FACE_Z0: y1 = y0; z0 = z1; r = (-y0+z1)*0.5f; x0 = r; x1 = r; break;
00833 case FACE_X0|FACE_X1|FACE_Y0|FACE_Z1: y0 = y1; z1 = z0; r = ( y1-z0)*0.5f; x0 = r; x1 = r; break;
00834 case FACE_X0|FACE_X1|FACE_Y1|FACE_Z1: y1 = y0; z1 = z0; r = (-y0-z0)*0.5f; x0 = r; x1 = r; break;
00835 case FACE_Y0|FACE_Y1|FACE_X0|FACE_Z0: x0 = x1; z0 = z1; r = ( x1+z1)*0.5f; y0 = r; y1 = r; break;
00836 case FACE_Y0|FACE_Y1|FACE_X1|FACE_Z0: x1 = x0; z0 = z1; r = (-x0+z1)*0.5f; y0 = r; y1 = r; break;
00837 case FACE_Y0|FACE_Y1|FACE_X0|FACE_Z1: x0 = x1; z1 = z0; r = ( x1-z0)*0.5f; y0 = r; y1 = r; break;
00838 case FACE_Y0|FACE_Y1|FACE_X1|FACE_Z1: x1 = x0; z1 = z0; r = (-x0-z0)*0.5f; y0 = r; y1 = r; break;
00839 case FACE_Z0|FACE_Z1|FACE_Y0|FACE_X0: y0 = y1; x0 = x1; r = ( y1+x1)*0.5f; z0 = r; z1 = r; break;
00840 case FACE_Z0|FACE_Z1|FACE_Y1|FACE_X0: y1 = y0; x0 = x1; r = (-y0+x1)*0.5f; z0 = r; z1 = r; break;
00841 case FACE_Z0|FACE_Z1|FACE_Y0|FACE_X1: y0 = y1; x1 = x0; r = ( y1-x0)*0.5f; z0 = r; z1 = r; break;
00842 case FACE_Z0|FACE_Z1|FACE_Y1|FACE_X1: y1 = y0; x1 = x0; r = (-y0-x0)*0.5f; z0 = r; z1 = r; break;
00843
00844
00845 case FACE_X1|FACE_Y0|FACE_Y1|FACE_Z0|FACE_Z1: x0 = x1 +y1-y0+z1-z0; break;
00846 case FACE_X0| FACE_Y0|FACE_Y1|FACE_Z0|FACE_Z1: x1 = x0 +y0-y1+z0-z1; break;
00847 case FACE_X0|FACE_X1| FACE_Y1|FACE_Z0|FACE_Z1: y0 = x1-x0+y1 +z1-z0; break;
00848 case FACE_X0|FACE_X1|FACE_Y0| FACE_Z0|FACE_Z1: y1 = x0-x1+y0 +z0-z1; break;
00849 case FACE_X0|FACE_X1|FACE_Y0|FACE_Y1| FACE_Z1: z0 = x1-x0+y1-y0+z1 ; break;
00850 case FACE_X0|FACE_X1|FACE_Y0|FACE_Y1|FACE_Z0 : z1 = x0-x1+y0-y1+z0 ; break;
00851
00852
00853 case FACE_X0|FACE_X1|FACE_Y0|FACE_Y1|FACE_Z0|FACE_Z1: break;
00854
00855
00856 }
00857 }
00858 }
00859 });
00860 }
00861
00864
00865
00866
00867 void Grid3D::step_advect(const Grid3D* , Grid3D* temp, real dt, real )
00868 {
00869
00870
00871
00872
00873
00874
00875
00876 memset(temp->fdata,0,temp->ncell*sizeof(Cell));
00877
00878 FOR_INNER_CELLS(temp->fdata,
00879 {
00880
00881 vec3 px( x-0.5f - dt*(fdata[ind].u[0]),
00882 y - dt*0.25f*(fdata[ind].u[1]+fdata[ind+index(-1,0,0)].u[1]+fdata[ind+index(0,1,0)].u[1]+fdata[ind+index(-1,1,0)].u[1]),
00883 z - dt*(fdata[ind].u[2]+fdata[ind+index(-1,0,0)].u[2]+fdata[ind+index(0,0,1)].u[2]+fdata[ind+index(-1,0,1)].u[2]));
00884 temp->fdata[ind].u[0] = interp<0>(px);
00885
00886 vec3 py( x - dt*0.25f*(fdata[ind].u[0]+fdata[ind+index(0,-1,0)].u[0]+fdata[ind+index(1,0,0)].u[0]+fdata[ind+index(1,-1,0)].u[0]),
00887 y-0.5f - dt*(fdata[ind].u[1]),
00888 z - dt*(fdata[ind].u[2]+fdata[ind+index(0,-1,0)].u[2]+fdata[ind+index(0,0,1)].u[2]+fdata[ind+index(0,-1,1)].u[2]));
00889 temp->fdata[ind].u[1] = interp<1>(py);
00890
00891 vec3 pz( x - dt*(fdata[ind].u[0]+fdata[ind+index(0,0,-1)].u[0]+fdata[ind+index(1,0,0)].u[0]+fdata[ind+index(1,0,-1)].u[0]),
00892 y - dt*0.25f*(fdata[ind].u[1]+fdata[ind+index(0,0,-1)].u[1]+fdata[ind+index(0,1,0)].u[1]+fdata[ind+index(0,1,-1)].u[1]),
00893 z-0.5f - dt*(fdata[ind].u[2]));
00894 temp->fdata[ind].u[2] = interp<2>(pz);
00895 });
00896
00897 }
00898
00899
00900 void Grid3D::step_diffuse(const Grid3D* , Grid3D* temp, real , real diff)
00901 {
00902
00903
00904
00905
00906 if (diff==0.0f)
00907 {
00908 for (int ind=0;ind<ncell;ind++)
00909 fdata[ind].u = temp->fdata[ind].u;
00910 return;
00911 }
00912
00913 real a = diff;
00914 real inv_c = 1.0f / (1.0001f + 6*a);
00915
00916 FOR_INNER_CELLS(fdata,
00917 {
00918 fdata[ind].u = (temp->fdata[ind].u +
00919 (temp->fdata[ind+index(-1,0,0)].u+temp->fdata[ind+index(1,0,0)].u+
00920 temp->fdata[ind+index(0,-1,0)].u+temp->fdata[ind+index(0,1,0)].u+
00921 temp->fdata[ind+index(0,0,-1)].u+temp->fdata[ind+index(0,0,1)].u
00922 )*a)*inv_c;
00923 });
00924 }
00925
00926
00927 void Grid3D::step_project(const Grid3D* prev, Grid3D* temp, real dt, real )
00928 {
00929
00930
00931
00932
00933
00934
00935
00936
00937
00938
00939 memset(temp->fdata,0,temp->ncell*sizeof(Cell));
00940 memset(temp->pressure,0,temp->ncell*sizeof(real));
00941
00942 real* diag = (real*)temp->fdata;
00943 real* b = diag+ncell;
00944 real* r = b+ncell;
00945 real* g = r+ncell;
00946 real* q = temp->pressure;
00947
00948 real a = -1.0f/dt;
00949
00950 double b_norm2 = 0.0;
00951
00952
00953
00954 FOR_INNER_CELLS(diag,
00955 {
00956 if (fdata[ind].type>0)
00957 {
00958 real d = 6;
00959 d -= ((unsigned int)fdata[ind+index(-1,0,0)].type)>>31;
00960 d -= ((unsigned int)fdata[ind+index(0,-1,0)].type)>>31;
00961 d -= ((unsigned int)fdata[ind+index(0,0,-1)].type)>>31;
00962 d -= ((unsigned int)fdata[ind+index( 1,0,0)].type)>>31;
00963 d -= ((unsigned int)fdata[ind+index(0, 1,0)].type)>>31;
00964 d -= ((unsigned int)fdata[ind+index(0,0, 1)].type)>>31;
00965
00966 diag[ind] = d;
00967 }
00968 });
00969
00970 FOR_INNER_CELLS(b,
00971 {
00972 if (fdata[ind].type>0)
00973 {
00974 real bi = a*(fdata[ind+index(1,0,0)].u[0]-fdata[ind].u[0] + fdata[ind+index(0,1,0)].u[1]-fdata[ind].u[1] + fdata[ind+index(0,0,1)].u[2]-fdata[ind].u[2]);
00975 b[ind] = bi;
00976 b_norm2 += bi*bi;
00977 }
00978 });
00979
00980
00981
00982
00983
00984 FOR_ALL_CELLS(pressure,
00985 {
00986 if (fdata[ind].type>0)
00987 pressure[ind] = prev->pressure[ind];
00988 else pressure[ind] = 0;
00989 });
00990
00991
00992
00993
00994
00995 double err = 0.0;
00996
00997
00998 FOR_INNER_CELLS(r,
00999 {
01000 if (diag[ind] != 0)
01001 {
01002 r[ind] = b[ind] - (diag[ind]*pressure[ind]
01003 -pressure[ind+index(-1,0,0)]-pressure[ind+index(0,-1,0)]-pressure[ind+index(0,0,-1)]
01004 -pressure[ind+index( 1,0,0)]-pressure[ind+index(0, 1,0)]-pressure[ind+index(0,0, 1)]);
01005 }
01006 });
01007
01008 FOR_ALL_CELLS(g,
01009 {
01010 g[ind] = r[ind];
01011 });
01012
01013 double min_err = 0.000001f*b_norm2;
01014
01015 int step;
01016 for (step=0;step<100;step++)
01017 {
01018 double err_old = err;
01019 err = 0.0;
01020 FOR_READ_INNER_CELLS(
01021 {
01022 err += r[ind]*r[ind];
01023 });
01024
01025 if (err<=min_err) break;
01026 if (step>0)
01027 {
01028 real beta = (real)(err/err_old);
01029
01030 FOR_ALL_CELLS(g,
01031 {
01032 g[ind] = g[ind]*beta + r[ind];
01033 });
01034 }
01035 double g_q = 0.0;
01036
01037 FOR_INNER_CELLS(q,
01038 {
01039 if (diag[ind] != 0)
01040 {
01041 real Ag = (diag[ind]*g[ind]
01042 -g[ind+index(-1,0,0)]-g[ind+index(0,-1,0)]-g[ind+index(0,0,-1)]
01043 -g[ind+index( 1,0,0)]-g[ind+index(0, 1,0)]-g[ind+index(0,0, 1)]);
01044 q[ind] = Ag;
01045 g_q += g[ind]*Ag;
01046 }
01047 });
01048
01049 real alpha = (real)(err/g_q);
01050
01051 FOR_ALL_CELLS(pressure,
01052 {
01053 pressure[ind] += alpha*g[ind];
01054 r[ind] -= alpha*q[ind];
01055 });
01056 }
01057
01058 std::cout << "STEP: CG iteration "<<step<<" error(d) "<<sqrt(err/b_norm2)<<"\n";
01059
01060
01061 a = dt;
01062
01063 real max_speed = 0.5f/dt;
01064
01065
01066 max_pressure = prev->max_pressure;
01067
01068 FOR_INNER_CELLS(fdata,
01069 {
01070 if (fdata[ind].type>=PART_EMPTY)
01071 {
01072 if (fdata[ind+index(-1,0,0)].type>=PART_EMPTY)
01073 {
01074 fdata[ind].u[0] -= a*(pressure[ind] - pressure[ind+index(-1,0,0)]);
01075
01076 if (fdata[ind].u[0] > max_speed) fdata[ind].u[0] = max_speed;
01077 else if (fdata[ind].u[0] < -max_speed) fdata[ind].u[0] = -max_speed;
01078 }
01079 if (fdata[ind+index(0,-1,0)].type>=PART_EMPTY)
01080 {
01081 fdata[ind].u[1] -= a*(pressure[ind] - pressure[ind+index(0,-1,0)]);
01082 if (fdata[ind].u[1] > max_speed) fdata[ind].u[1] = max_speed;
01083 else if (fdata[ind].u[1] < -max_speed) fdata[ind].u[1] = -max_speed;
01084 }
01085 if (fdata[ind+index(0,0,-1)].type>=PART_EMPTY)
01086 {
01087 fdata[ind].u[2] -= a*(pressure[ind] - pressure[ind+index(0,0,-1)]);
01088 if (fdata[ind].u[2] > max_speed) fdata[ind].u[2] = max_speed;
01089 else if (fdata[ind].u[2] < -max_speed) fdata[ind].u[2] = -max_speed;
01090 }
01091 }
01092 });
01093
01094
01095 }
01096
01097 }
01098
01099 }
01100
01101 }
01102
01103 }
01104