// Compute the signed distance from a digitized image // Two phases are present // Phase 1 has value -1 // Phase 2 has value 1 // this code uses the segmented image to generate the signed distance #include #include #include #include #include #include inline void SSO(DoubleArray &Distance, char *ID, int timesteps){ int Q=26; int q,i,j,k,n; int Nx = Distance.m; int Ny = Distance.n; int Nz = Distance.o; const static int D3Q27[26][3]={{1,0,0},{-1,0,0},{0,1,0},{0,-1,0},{0,0,1},{0,0,-1}, {1,1,0},{-1,-1,0},{1,-1,0},{-1,1,0},{1,0,1},{-1,0,-1},{1,0,-1},{-1,0,1}, {0,1,1},{0,-1,-1},{0,1,-1},{0,-1,1},{1,1,1},{-1,-1,-1},{1,1,-1},{-1,-1,1}, {-1,1,-1},{1,-1,1},{1,-1,-1},{-1,1,1}}; double weights[26]; // Compute the weights from the finite differences for (q=0; q 0.0){ for (q=0; q<26; q++){ Cqx = 1.0*D3Q27[q][0]; Cqy = 1.0*D3Q27[q][1]; Cqz = 1.0*D3Q27[q][2]; // get the associated neighbor in = i + D3Q27[q][0]; jn = j + D3Q27[q][1]; kn = k + D3Q27[q][2]; // make sure the neighbor is in the domain (periodic BC) /* if (in < 0 ) in +=Nx; if (jn < 0 ) jn +=Ny; if (kn < 0 ) kn +=Nz; if (!(in < Nx) ) in -=Nx; if (!(jn < Ny) ) jn -=Ny; if (!(kn < Nz) ) kn -=Nz; */ // symmetric boundary if (in < 0 ) in = i; if (jn < 0 ) jn = j; if (kn < 0 ) kn = k; if (!(in < Nx) ) in = i; if (!(jn < Ny) ) jn = k; if (!(kn < Nz) ) kn = k; // 1-D index nn = kn*Nx*Ny + jn*Nx + in; // Compute the gradient using upwind finite differences Dqx = weights[q]*(Distance.data[n] - Distance.data[nn])*Cqx; Dqy = weights[q]*(Distance.data[n] - Distance.data[nn])*Cqy; Dqz = weights[q]*(Distance.data[n] - Distance.data[nn])*Cqz; // Only include upwind derivatives if (sign*(nx*Cqx + ny*Cqy + nz*Cqz) < 0.0 ){ Dx += Dqx; Dy += Dqy; Dz += Dqz; W += weights[q]; } } // Normalize by the weight to get the approximation to the gradient Dx /= W; Dy /= W; Dz /= W; norm = sqrt(Dx*Dx+Dy*Dy+Dz*Dz); } else{ norm = 0.0; } Distance.data[n] += dt*sign*(1.0 - norm); // Disallow any change in phase if (Distance.data[n]*2.0*(ID[n]-1.0) < 0) Distance.data[n] = -Distance.data[n]; } } } count++; } } int main(){ int i,j,k,n,nn; int Nx, Ny, Nz, N; Nx = Ny = Nz = 50; N = Nx*Ny*Nz; double err = 1.0; double err_prev=1.0; double tol = 1e-6; double f_x, f_y, f_z, norm; double f1,f2,f3,f4,f5,f6,f7,f8,f9; double f10,f11,f12,f13,f14,f15,f16,f17,f18; double fxm,fym,fzm,fxp,fyp,fzp; double fxy,fXy,fxY,fXY,fxz,fXz,fxZ,fXZ,fyz,fYz,fyZ,fYZ; double nx,ny,nz; int ip,im,jp,jm,kp,km; int count = 0; double sign; double dt=1.0; printf("Nx=%i, Ny=%i, Nz= %i, \n",Nx,Ny,Nz); char *id; #ifdef READMEDIA Nx = 347; Ny = 347; Nz = 235; Nx = 512; Ny = 512; Nz = 512; N = Nx*Ny*Nz; id = new char [N]; FILE *INPUT = fopen("Solid.dat","rb"); fread(id,1,Nx*Ny*Nz,INPUT); fclose(INPUT); #else id = new char [N]; double BubbleRadius = 5; // Initialize the bubble for (k=0;k 1.0e-6){ err = 0.0; for (k=0;k 0.0) f_x = fxp; else f_x = fxm; if ( ny > 0.0) f_y = fyp; else f_y = fym; if ( nz > 0.0) f_z = fzp; else f_z = fzm; } else{ if ( nx > 0.0) f_x = fxm; else f_x = fxp; if ( ny > 0.0) f_y = fym; else f_y = fyp; if ( nz > 0.0) f_z = fzm; else f_z = fzp; } norm = sqrt(f_x*f_x+f_y*f_y+f_z*f_z); if (err < (1.0 - norm)) err = (1.0 - norm); if (fabs(1.0-norm) > err) err = fabs(1.0-norm); sign =1.0; if (!(id[n] > 0)) sign = -1.0; f_new[n] = f_old[n] + dt*sign*(1.0 - norm); } } } for (int n=0; n err_prev) dt *= 0.2; err_prev = err; count++; } */ FILE *DIST; DIST = fopen("SignDist","wb"); fwrite(Distance.data,8,N,DIST); fclose(DIST); }