Point start_point(scalar f,double xs, double ys){ double dist = sq(L0*pow(2.,0.5)); foreach(reduction(min:dist)){ if (f[]>0. && f[]<1.&&fabs(x-X0)>Delta&&fabs(x-(X0+L0))>Delta&&fabs(y-(Y0+L0))>Delta&&fabs(y-Y0)>Delta){ double dis = (sq(x-xs)+sq(y-ys)); if (dis0 && f[]<1.){ // Only true on a single PID. xp=x; yp=y; } } return locate(xp,yp); } void find_facets(Point point,scalar f,double xy[4]){ coord n; n = mycs (point, f); double alpha = plane_alpha (f[], n); coord segment[2]; if (facets (n, alpha, segment) == 2){ xy[0] = x + segment[0].x*Delta; xy[1] = y + segment[0].y*Delta; xy[2] = x + segment[1].x*Delta; xy[3] = y + segment[1].y*Delta; }else{ fprintf(stdout,"Warning:\nCould not find facets; expect unexpected behaviour.\n"); } } void next_point(Point point,scalar f,double xp,double yp,int dir[2],int * iter,double * xu,double * yu){ int nb=0; foreach_dimension() nb+=((f[-1]>0.)*(f[-1]<1.))+((f[1]>0.)*(f[1]<1.)); if (nb==2&&(fabs(dir[0])+fabs(dir[1])==1)){ // Only two neighbouring interfacial cells could be easy... for(int ii = -1;ii<=1;ii++){ for(int jj = -1;jj<=1;jj++){ if ((abs(ii)+(abs(jj))==1) && (dir[0]!=-ii || dir[1]!=-jj) && f[ii,jj]>0. && f[ii,jj]<1.){// Simple neighbour dir[0]=ii; dir[1]=jj; if (!is_refined(neighbor(ii,jj))){//Special care for refined next cells *xu=(5*xp+x)/6.+((double)ii*Delta/3.); *yu=(5*yp+y)/6.+((double)jj*Delta/3.); return; }else if(fine(f,(xp>x)+ii,(yp>y)+jj)>0 && fine(f,(xp>x)+ii,(yp>y)+jj)<1){//still OK *xu=(5*xp+x)/6.+((double)ii*Delta/3.); *yu=(5*yp+y)/6.+((double)jj*Delta/3.); return; }else if(ii==0){//y-dir if(fine(f,(xpy))+jj)>0 && fine(f,(xpy)+jj)<1){ //poorly reconstructed, do not follow facet *xu=x+(0.5*Delta*((xpx)+ii,(yp0 && fine(f,(xp>x)+ii,(yp0.)||(!is_leaf(neighbor(1,0))&&coarse(f,1,0)<1&&coarse(f,1,0)>0))){ dir[0]=1.; dir[1]=0; *xu=xp+Delta/10.; *yu=yp; return; } else if (xp==x-Delta/2.&&((f[-1]<1.&&f[-1]>0.)||(!is_leaf(neighbor(-1,0))&&coarse(f,-1,0)<1&&coarse(f,-1,0)>0))){ dir[0]=-1; dir[1]=0; *xu=xp-Delta/10.; *yu=yp; return; } else if (yp==y+Delta/2.&&((f[0,1]<1.&&f[0,1]>0.)||(!is_leaf(neighbor(0,1))&&coarse(f,0,1)<1&&coarse(f,0,1)>0))){ dir[0]=0; dir[1]=1; *xu=xp; *yu=yp+Delta/10.; return; } else if (yp==y-Delta/2.&&((f[0,-1]<1.&&f[0,-1]>0.)||(!is_leaf(neighbor(0,-1))&&coarse(f,0,-1)<1&&coarse(f,0,-1)>0))) { dir[0]=0; dir[1]=-1; *xu=xp; *yu=yp-Delta/10; return; } //As a last resort, try a diagnonal neighbour, blindly. If this does not go well, we are in in trouble double fac[4]; find_facets(point,f,fac); double meanx = (fac[0]+fac[2])/2.; double meany = (fac[1]+fac[3])/2.; double dx,dy; if (yp>meany){ dy= 0.3; }else dy = -0.3; if (xp>meanx){ dx= 0.3; }else dx = -0.3; dir[0]=0; dir[1]=0; *xu=xp+Delta*dx; *yu=yp+Delta*dy; return; } void update_new_facet(Point point, double xyn[2],double xyf[4],int dir[2]){ if ((fabs(dir[0])+fabs(dir[1])==1)){ // Try to make use of the direction. for (int g=-1;g<=1;g+=2){ if (dir[0]==g){ //x-dir double dg = (double)g; if(dg*xyf[0]==min(dg*xyf[0],dg*xyf[2])){ xyn[0]=xyf[2];xyn[1]=xyf[3]; return; }else if(dg*xyf[2]==min(dg*xyf[0],dg*xyf[2])){ xyn[0]=xyf[0];xyn[1]=xyf[1]; return; } }else if(dir[1]==g){ //y-dir double dg = (double)g; if(dg*xyf[1]==min(dg*xyf[1],dg*xyf[3])){ xyn[0]=xyf[2];xyn[1]=xyf[3]; return; }else if(dg*xyf[3]==min(dg*xyf[1],dg*xyf[3])){ xyn[0]=xyf[0];xyn[1]=xyf[1]; return; } } } } // Else choose the one farest away from the previous. This is not very robust and is the main cause of 'bounce backs'. if ((sq(xyf[0]-xyn[0])+sq(xyf[1]-xyn[1])) <= (sq(xyf[2]-xyn[0])+sq(xyf[3]-xyn[1]))){ xyn[0]=xyf[2]; xyn[1]=xyf[3]; }else{ xyn[0]=xyf[0]; xyn[1]=xyf[1]; } } void loop_interfacial_cells(FILE * fp, scalar f,scalar tag,double xynn[2]){ if (dimension!=2){ fprintf(stdout,"2D only!\n"); if (pid()==0) fprintf(fp,"# 2D only!\n"); return; } boundary({f});//neighbors on trees etc. double xyn[2]; xyn[0]=xynn[0]; xyn[1]=xynn[1]; int ifc= 0; foreach(reduction(+:ifc)){ if ( f[]>0. && f[]<1.) ifc++; } double xu,yu; Point point; point = start_point(f,xyn[0],xyn[1]); // int i = 1; //static FILE * fpp = popen ("gfsview2D tag.gfv -s","w"); //For trouble shooting int igg=0; double l =0,cur; double xyf[4]; int dir[2]={0,0}; while (igg <= ifc){ xu=X0-L0; yu=Y0-L0; if (point.level>0){ // Local pid() find_facets(point,f,xyf); l+=pow(sq(xyf[0]-xyf[2])+sq(xyf[1]-xyf[3]),0.5); cur = tag[]; //tag[]+=100.; // For trouble shooting update_new_facet(point,xyn,xyf,dir); // For tracing the interface in the correct direction next_point(point,f,xyn[0],xyn[1],dir,&igg,&xu,&yu); // Aims to Update xu and yu to be in next leaf cell along the interface }else{ // Set small values for the tracing variables on the other threads cur=-HUGE; xyf[0]=xu; xyf[1]=yu; xyf[2]=xu; xyf[3]=yu; xyn[0]=xu;xyn[1]=yu; dir[0]=-2;dir[1]=-2; } @ if _MPI // Set send buffers, so reduced variables can be recieved in the original ones. double oldx=xu;double oldy=yu;double oldl = l; double xyfold[4]; xyfold[0]=xyf[0];xyfold[1]=xyf[1];xyfold[2]=xyf[2];xyfold[3]=xyf[3]; double oldcur=cur; double oldxyn[2]; oldxyn[0]=xyn[0];oldxyn[1]=xyn[1]; int olddir[2]; olddir[1]=dir[1];olddir[0]=dir[0]; int oldi=igg; // Update all workers, just in case one has to take over, this should be improved for better performance. MPI_Allreduce(&oldx, &xu, 1, MPI_DOUBLE, MPI_MAX,MPI_COMM_WORLD); MPI_Allreduce(&oldy, &yu, 1, MPI_DOUBLE, MPI_MAX,MPI_COMM_WORLD); MPI_Allreduce(&xyfold, &xyf, 4, MPI_DOUBLE, MPI_MAX,MPI_COMM_WORLD); MPI_Allreduce(&oldxyn, &xyn, 2, MPI_DOUBLE, MPI_MAX,MPI_COMM_WORLD); MPI_Allreduce(&oldl, &l, 1, MPI_DOUBLE, MPI_MAX,MPI_COMM_WORLD); MPI_Allreduce(&oldcur, &cur, 1, MPI_DOUBLE, MPI_MAX,MPI_COMM_WORLD); MPI_Allreduce(&olddir, &dir, 2, MPI_INT, MPI_MAX,MPI_COMM_WORLD); MPI_Allreduce(&oldi, &igg, 1, MPI_INT, MPI_MAX,MPI_COMM_WORLD); @ endif if (pid()==0&&igg