void ImmersedBoundaryMethod::InterpolateFluidVelocity() { const auto nx = lm_.GetNumberOfColumns(); const auto ny = lm_.GetNumberOfRows(); const auto dx = lm_.GetSpaceStep(); const auto dt = lm_.GetTimeStep(); const auto scaling = dx / dt; // pointer always editable, do not need & for (auto particle : particles) { for (auto &node : particle->nodes) { node.u = {0.0, 0.0}; const auto x_particle = node.coord[0]; const auto y_particle = node.coord[1]; // fix for truncation error when double is really close to integer value // http://blog.frama-c.com/index.php?post/2013/05/02/nearbyintf1 // uses "machine epsilon" through std::numeric_limits<double>::epsilon() // http://stackoverflow.com/questions/17333/most-effective-way-for-float- // and-double-comparison const auto x_fluid = static_cast<int>(floor(x_particle + 2 * particle->char_length * std::numeric_limits<double>::epsilon())); const auto y_fluid = static_cast<int>(floor(y_particle + 2 * particle->char_length * std::numeric_limits<double>::epsilon())); for (auto y = y_fluid; y < y_fluid + 2; ++y) { for (auto x = x_fluid; x < x_fluid + 2; ++x) { const auto n = ((y + ny) % ny) * nx + (x + nx) % nx; const auto weight = Dirac(stencil_, x_particle - x, y_particle - y); // node velocity maybe calculated in dimensionless units (check) node.u[0] += lm_.u[n][0] / scaling * weight; node.u[1] += lm_.u[n][1] / scaling * weight; } // x } // y } // node } // particle }
ImageF drlse_edge(ImageF phi_0,ImageF g,float lambda,float mu,float alfa,float epsilon,int timestep, int iter,string sada,char * potentialFunction) { ImageF phi=phi_0; for(int i=0;i<iter;i++) { phi=NeumannBoundCond(phi); ImageF *vx=new ImageF(); ImageF *vy=new ImageF(); (*vy)*(vx); ImageF *phi_x=new ImageF(); ImageF *phi_y=new ImageF(); *vx=gradientx(g); *vy=gradienty(g); *phi_x=gradientx(g); *phi_y=gradienty(g); ImageF *s=new ImageF(); *s=ImageFSqrt( *vx, *vy); float smallNumber=1e-10; ImageF *Nx,*Ny; *Nx=*phi_x/(*s+smallNumber); *Ny=*phi_y/(*s+smallNumber); ImageF * curvature=new ImageF(); *curvature=div(*Nx,*Ny); ImageF distRegTerm; if (strcmp(potentialFunction,"single-well")) /* compute distance regularization term in equation (13) with the single-well potential p1. */ distRegTerm= 4*del2(phi)-*curvature; //printf(""); else if (strcmp(potentialFunction,"double-well")) { distRegTerm=distReg_p2(phi); // compute the distance regularization term in eqaution (13) with the double-well potential p2. printf("asda"); } else printf("EEROR"); //float eplsion=0.1; ImageF diracPhi=Dirac(phi,epsilon); ImageF areaTerm=diracPhi*g; ImageF *edgeTerm=new ImageF(); *edgeTerm=diracPhi*(*vx**Nx+*vy**Ny) + diracPhi*g*(*curvature); //vx*vy; phi=phi + timestep*(mu*distRegTerm + lambda**edgeTerm + alfa*areaTerm); return phi_0; } }
void ImmersedBoundaryMethod::SpreadForce() { // The two-point interpolation stencil (bi-linear interpolation) is used in // the present code. fluid_force.assign(fluid_force.size(), {0.0, 0.0}); const auto nx = lm_.GetNumberOfColumns(); const auto ny = lm_.GetNumberOfRows(); const auto dx = lm_.GetSpaceStep(); const auto dt = lm_.GetTimeStep(); const auto scaling = dx / dt / dt; for (auto particle : particles) { for (auto &node : particle->nodes) { // Identify the lowest fluid lattice node in interpolation range. // The other fluid nodes in range have coordinates // (x_fluid + 1, y_fluid), (x_fluid, y_fluid + 1), and // (x_fluid + 1, y_fluid + 1). const auto x_particle = node.coord[0]; const auto y_particle = node.coord[1]; const auto x_fluid = static_cast<int>(floor(x_particle + 2 * particle->char_length * std::numeric_limits<double>::epsilon())); const auto y_fluid = static_cast<int>(floor(y_particle + 2 * particle->char_length * std::numeric_limits<double>::epsilon())); std::cout << x_particle << " " << x_fluid << std::endl; // Consider unrolling these 2 loops for (auto y = y_fluid; y < y_fluid + 2; ++y) { for (auto x = x_fluid; x < x_fluid + 2; ++x) { const auto n = ((y + ny) % ny) * nx + (x + nx) % nx; // Compute interpolation weights based on distance using interpolation // stencil, still need to implement others const auto weight = Dirac(stencil_, x_particle - x, y_particle - y); // Compute fluid force fluid_force[n][0] += node.force[0] * scaling * weight; fluid_force[n][1] += node.force[1] * scaling * weight; } // x } // y } // node } // particle }
void Evolution(IplImage *u, IplImage *g, double lambda, double mu, double alf, double epsilon, double delt, int numIter) { if (!u||!g) return; CvSize size = cvGetSize(u); IplImage* vx = cvCreateImage(size,IPL_DEPTH_32F,1); IplImage* vy = cvCreateImage(size,IPL_DEPTH_32F,1); IplImage* ux = cvCreateImage(size,IPL_DEPTH_32F,1); IplImage* uy = cvCreateImage(size,IPL_DEPTH_32F,1); IplImage* Nx = cvCreateImage(size,IPL_DEPTH_32F,1); IplImage* Ny = cvCreateImage(size,IPL_DEPTH_32F,1); IplImage* diracU = cvCreateImage(size,IPL_DEPTH_32F,1); IplImage* K = cvCreateImage(size,IPL_DEPTH_32F,1); IplImage* laplace = cvCreateImage(size,IPL_DEPTH_32F,1); Sobel(g, vx, vy); int i,j; CvScalar cur1,cur2,cur11,cur22,cur; CvScalar Cdirac, Cvx, CNx, Cvy, CNy, Cg, CK, Claplace, Cu; for (int k=0;k<numIter;k++) { cout<<k<<"……"<<endl; NeumannBoundCond(u); Sobel(u, ux, uy); for (i=0; i<size.height; i++) { for(j=0; j<size.width; j++) { cur1 = cvGet2D(ux,i,j); cur2 = cvGet2D(uy,i,j); cur11.val[0] = cur1.val[0]/sqrt(cur1.val[0]*cur1.val[0] + cur2.val[0]*cur2.val[0] + 1e-10); cur22.val[0] = cur2.val[0]/sqrt(cur1.val[0]*cur1.val[0] + cur2.val[0]*cur2.val[0] + 1e-10); cvSet2D(Nx,i,j,cur11); cvSet2D(Ny,i,j,cur22); } } Dirac(u,diracU,epsilon); CurvatureCentral2(Nx,Ny,K); cvLaplace(u, laplace, 1); for (i=0; i<size.height; i++) { for(j=0; j<size.width; j++) { Cdirac = cvGet2D(diracU,i,j); Cvx = cvGet2D(vx,i,j); CNx = cvGet2D(Nx,i,j); Cvy = cvGet2D(vy,i,j); CNy = cvGet2D(Ny,i,j); Cg = cvGet2D(g,i,j); CK = cvGet2D(K,i,j); Claplace = cvGet2D(laplace,i,j); Cu = cvGet2D(u,i,j); cur.val[0] = lambda*Cdirac.val[0]*(Cvx.val[0]*CNx.val[0] + Cvy.val[0]*CNy.val[0] + Cg.val[0]*CK.val[0]) + mu*(Claplace.val[0]-CK.val[0]) + alf*Cdirac.val[0]*Cg.val[0]; Cu.val[0] += delt*cur.val[0]; cvSet2D(u,i,j,Cu); } } } cvReleaseImage(&vx); cvReleaseImage(&vy); cvReleaseImage(&ux); cvReleaseImage(&uy); cvReleaseImage(&Nx); cvReleaseImage(&Ny); cvReleaseImage(&diracU); cvReleaseImage(&K); cvReleaseImage(&laplace); }
void Evolution2(IplImage * u, IplImage *g, double lambda, double mu, double alf, double epsilon, double delt, int numIter) { if (!u||!g) return; CvSize size = cvGetSize(u); IplImage* vx = cvCreateImage(size,IPL_DEPTH_32F,1); IplImage* vy = cvCreateImage(size,IPL_DEPTH_32F,1); IplImage* ux = cvCreateImage(size,IPL_DEPTH_32F,1); IplImage* uy = cvCreateImage(size,IPL_DEPTH_32F,1); IplImage* Nx = cvCreateImage(size,IPL_DEPTH_32F,1); IplImage* Ny = cvCreateImage(size,IPL_DEPTH_32F,1); IplImage* diracU = cvCreateImage(size,IPL_DEPTH_32F,1); IplImage* K = cvCreateImage(size,IPL_DEPTH_32F,1); IplImage* Laplace = cvCreateImage(size,IPL_DEPTH_32F,1); Sobel(g,vx,vy); CvScalar s1,s2,s11,s22; CvScalar Cdirac, Cvx, Cvy, CNx, CNy, Cg, CK, CLaplace, Cu; int i,j; for(int k=0;k<numIter;k++) { cout<<k<<"……"<<endl; NeumannBoundCond(u); Sobel(u,ux,uy); for(i=0;i<size.height;i++) { for(j=0;j<size.width;j++) { s1=cvGet2D(ux,i,j); s2=cvGet2D(uy,i,j); double normDu=sqrt(pow(s1.val[0],2)+pow(s2.val[0],2)+1e-10); s11.val[0]=s1.val[0]/normDu; s22.val[0]=s2.val[0]/normDu; cvSet2D(Nx,i,j,s11); cvSet2D(Ny,i,j,s22); } } Dirac(u,diracU,epsilon); CurvatureCentral2(Nx,Ny,K); cvLaplace(u, Laplace, 1); for(i=0;i<size.height;i++) { for(j=0;j<size.width;j++) { Cdirac=cvGet2D(diracU,i,j); Cvx=cvGet2D(vx,i,j); Cvy=cvGet2D(vy,i,j); CNx=cvGet2D(Nx,i,j); CNy=cvGet2D(Ny,i,j); Cg=cvGet2D(g,i,j); CK=cvGet2D(K,i,j); CLaplace=cvGet2D(Laplace,i,j); Cu=cvGet2D(u,i,j); double weightedLengthTerm=lambda*Cdirac.val[0]*(Cvx.val[0]*CNx.val[0]+Cvy.val[0]*CNy.val[0]+Cg.val[0]*CK.val[0]); double weightedAreaTerm=alf*Cdirac.val[0]*Cg.val[0]; double penalizingTerm=mu*(CLaplace.val[0]-CK.val[0]); double total=weightedLengthTerm+weightedAreaTerm+penalizingTerm; Cu.val[0]+=delt*total; cvSet2D(u,i,j,Cu); } } } cvReleaseImage(&vx); cvReleaseImage(&vy); cvReleaseImage(&ux); cvReleaseImage(&uy); cvReleaseImage(&Nx); cvReleaseImage(&Ny); cvReleaseImage(&diracU); cvReleaseImage(&K); cvReleaseImage(&Laplace); }