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 (dis<dist)
dist = dis;
}
}
double xp=(2*L0)+X0;// These coordinates cannot be located.
double yp=(2*L0)+Y0;
foreach(){
if (sq(x-xs)+sq(y-ys)==dist && f[]>0 && 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,(xp<x),((yp>y))+jj)>0 && fine(f,(xp<x),(yp>y)+jj)<1){ //poorly reconstructed, do not follow facet
*xu=x+(0.5*Delta*((xp<x)-0.5));
*yu=y+(0.75*Delta*jj) ;
return;
}
}else if(fine(f,(xp>x)+ii,(yp<y))>0 && fine(f,(xp>x)+ii,(yp<y))<1){ //x-dir, poorly reconstructed, do not follow facet
*yu=y+(0.5*Delta*((yp<y)-0.5));
*xu=x+(0.75*Delta*ii);
return;
}
}
}
}
}
if (fabs(xp-X0)<Delta||fabs(xp-(X0+L0))<=Delta||fabs(yp-Y0)<Delta||fabs(yp-(Y0+L0))<Delta){//domain boundary cell: stop tracing
*iter += (1<<25);// add large number
*xu=X0+L0/2.;
*yu=Y0+L0/2.;
return;
}
// If previous efforts have not worked, tryo to follow the interface
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 (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<ifc){ // Our favorite worker writes in the file
fprintf(fp,"%d\t%g\t%g\t%g\t%g\n",igg,(xyf[0]+xyf[2])/2,(xyf[1]+xyf[3])/2,l,cur);
fflush(fp);
}
// All threads try to find the new location.
point = locate(xu,yu);
igg++;
// i = igg;
//output_gfs(fpp); //For trouble shooting purposes:
}
}