/* This program uses PAMR to setup the subdomain * division of certain region, and then uses * standard mpi calls to evolve a set of particles * by Ben, 555 spring 2006 assigment 4. * */ #include #include #include #include #include #include #define DIM 2 // dimensionality of the problem #define XMIN -1.0//0.0 #define XMAX 1.0 #define YMIN -1.0//0.0 #define YMAX 1.0 #define RHO 2 // refinment ratio #define NGLEV 1 // number of grid levels #define NX 25 // total number of grid points in x-direction #define NY 25 // total number of grid points in y-direction #define NTLEV 1 // number of timet levels #define NMAXGRIDS 3 // maximum number of grids (1 for unigrid) #define NMAXGF 1 // maximum number of grid functions #define OUTMODULO 1 // save every OUTMODULO steps ///#define NSTEPS 120// number of evolution steps #define REGRIDSTEP 5 // regriding period #define NGHOSTS 1 // number of ghost zones #define HFRAC 0.25 // defines the size of the grids in hierarchy #define NUMP 5000 //number of particles #define GF_F 0 // symbolic name of index for grid function "f" #define max(a, b) (((a) > (b)) ? (a) : (b)) #define min(a, b) (((a) < (b)) ? (a) : (b)) #define PI 3.14159265358979323846 // declare the fortran functions - note the trailing underscore void initialize_(int *Nx,int *Ny,real *x,real *y,real *f); void calc_center(real *timet,real *arm,real *x0,real *y0,real *xc); void newposition(int *Nx,int *Ny,int *pn,real *timet,real *pposx,real *pposy,real *x,real *y); void save_particles_(real *timet, double *savex, double *savey,int *Np,int *rank); void make_step_(real *dt, real *timet, double *px, double *py,int *vtype,int *Nx, int *Ny, real *x, real*y, real *vmx, real *vmy); // define global variables real *f[NTLEV]; int f_gfn[NTLEV]; real *x,*y; real xmin,xmax,ymin,ymax; int ghost_width[2*DIM],Nx,Ny,phys_bdy[2*DIM],size; int Lf,rank; real base_bbox[2*DIM],bbox[2*DIM],dx,dy,lambda,na,ne; int base_shape[DIM]; real *pposx[NUMP],*pposy[NUMP]; //*mx[NUMP], *my[NUMP]; // set the gfn's for all the variables void set_gfns(void) { int lev; for(lev=1;lev<=NTLEV;lev++) { if ((f_gfn[lev-1]=PAMR_get_gfn("f",PAMR_AMRH,lev))<0) perror("set_gnfs error"); } } // load pointers void ldptr(void) { int dim,ngfs,lev,shape[DIM]; real t,*x0[DIM],*gfs[NMAXGF*NTLEV],dx0[DIM]; static int first=1; if (first) // call only once { first=0; set_gfns(); } if (!(PAMR_get_g_attribs(&rank,&dim,shape,bbox,ghost_width,&t,&ngfs,x0,gfs))) perror("ldptr: PAMR_get_g_attribs failed"); // for(lev=0;lev bbox[0] && newcx[i] < bbox[1] && newcy[i] > bbox[2] && newcy[i] < bbox[3]) { filtered=filtered+1; } }//end for // if newcomers belong to our domain if (filtered!=0){ tsx=creaArreglo(filtered); tsy=creaArreglo(filtered); tss=0; for(i=0;i bbox[0] && newcx[i] < bbox[1] && newcy[i] > bbox[2] && newcy[i] < bbox[3]) { insertaArreglo(tsx,tss,newcx[i]); insertaArreglo(tsy,tss,newcy[i]); tss=tss+1; } }//end for // put newcomers belonging to us in array nuevasx //// printf("here filtered=%i\n",filtered); nuevasx=creaArreglo(filtered+Np); nuevasy=creaArreglo(filtered+Np); for(i=0;i<=(filtered-1);i++){ insertaArreglo(nuevasx,i,gete(tsx,i)); insertaArreglo(nuevasy,i,gete(tsy,i)); }//end for for(i=(filtered);i<=(Np+filtered-1);i++){ insertaArreglo(nuevasx,i,gete(posx,(i-filtered))); insertaArreglo(nuevasy,i,gete(posy,(i-filtered))); }//end for ////printf("here posx,nuevasx,posy,nuevasy,filtered=%i,Np=%i\n",filtered,Np); ////MuestraArreglo(posx); ////MuestraArreglo(nuevasx); ////MuestraArreglo(posy); ////MuestraArreglo(nuevasy); borraArreglo(posx); borraArreglo(posy); borraArreglo(tsx); borraArreglo(tsy); posx=creaArreglo(filtered+Np); posy=creaArreglo(filtered+Np); for(i=0;i<=(Np+filtered-1);i++){ insertaArreglo(posx,i,gete(nuevasx,i)); insertaArreglo(posy,i,gete(nuevasy,i)); }//end for Np=filtered+Np; borraArreglo(nuevasx); borraArreglo(nuevasy); }//end if filtered !=0 free(newcx); free(newcy); }///////////////////////////////////////////////////////////////////end filter out if timet!=0 //subdomain partition by PAMR //// printf("----------------------\n"); //// printf("rank=%i,timet=%g\n\n",rank,timet); /* printf("box_0xmin=%f\n",bbox[0]); printf("box_1xmax=%f\n",bbox[1]); printf("box_2ymin=%f\n",bbox[2]); printf("box_3ymax=%f\n",bbox[3]); */ ////printf("checkrank=%i,Np=%i,time=%g\n",rank,Np,timet); /////////////////////////////////////////////////////////////////////save particles savex=(real *)calloc(Np, sizeof(real)); savey=(real *)calloc(Np, sizeof(real)); for(i=0;i<=(Np-1);i++){ savex[i]=gete(posx,i); savey[i]=gete(posy,i); ////printf("hola %f %f %g holarank=%i\n",savex[i],savey[i],timet,rank); }//end for save_particles_(&timet, savex, savey,&Np, &rank); free(savex); free(savey); //////////////////////////////////////////////////// for(i=0;i<=(Np-1);i++){ /////////////////////////////////////////begin first cycle thru particles ////////////////////////////////update px=gete(posx,i); py=gete(posy,i); //printf("make %i %i %g %f %f\n",rank,i,timet,gete(posx,i),gete(posy,i)); make_step_(&dt,&timet, &px, &py,&vtype, &Nx, &Ny, x, y, vmx, vmy); insertaArreglo(posx,i,px); insertaArreglo(posy,i,py); //printf("make %i %i %g %f %f\n",rank,i,timet,gete(posx,i),gete(posy,i)); //////////////////////////////////////////////////// // insertaArreglo(posx,i,gete(posx,i)+0.01); // printf("%i %i %g %f %f\n",rank,i,timet,gete(posx,i),gete(posy,i)); //printf("after update rank=%i,particle=%i,timet=%g,pposx=%f,pposy=%f,\n\n\n",rank,i,timet,gete(posx,i),gete(posy,i)); //check if the particles migrate and count their number if(gete(posx,i) < bbox[0] || gete(posx,i) > bbox[1] || gete(posy,i) < bbox[2] || gete(posy,i) > bbox[3]) { mig=mig+1; } }////////////////////////////////////////////////////////////////////////////end first cycle thru particles ////printf("mig= %i\n",mig); mx=creaArreglo(1); my=creaArreglo(1); insertaArreglo(mx,0,XMAX+1); insertaArreglo(my,0,YMAX+1); dim=1; // if there are migrants we create an array to store the entries // of posx and posy that will migrate and the resize those if(mig!=0){ borraArreglo(mx); borraArreglo(my); temp=creaArreglo(mig); mx=creaArreglo(mig); my=creaArreglo(mig); l=0.0; for(i=0;i<=(Np-1);i++){//2nd circle thru updated particles to fetch migrants if(gete(posx,i) < bbox[0] || gete(posx,i) > bbox[1] || gete(posy,i) < bbox[2] || gete(posy,i) > bbox[3]) { insertaArreglo(temp,l,i); l=l+1; } }//end 2nd cycle particles //printf("Muestra arreglo temp,mig=%i,l=%i\n\n",mig,l); //MuestraArreglo(temp); for(j=0;j<=(mig-1);j++){ addy=gete(temp,j); // printf("gete=%f\n",addy); insertaArreglo(mx,j,gete(posx,addy)); insertaArreglo(my,j,gete(posy,addy)); }//end j loop ////MuestraArreglo(mx); ////MuestraArreglo(my); ////printf("Np=%i,mig=%i\n",Np,mig); //now i adjust the posx and posy arrays to their new size excluding migrants ////////////////////////////////////////////////////////////////////////////////resize bax=creaArreglo(Np-mig); p=0; k=0; for(i=0;i<=(Np-1);i++) { //printf("i=%i\n",i); for(u=0;u<=(mig-1);u++) { //printf("i=%i,u=%i, muestra=%f\n",i,u,gete(temp,u)); if (i==gete(temp,u)) { p=1; } }//end u loop if (p==1)//means if there isa match and this entry will migrate and be excluded from posx { ////printf("do nothing\n"); } else//we keep this entry for the new array be which will become the new posx { elem=gete(posx,i); insertaArreglo(bax,k,elem); //ba[k]==posx[u]; k=k+1; //Debug// printf("elem %f, k=%i\n",elem,k); } p=0; }//end i loop //////////////////////////////////////////////////////////////////////////////end resize ////////////////////////////////////////////////////////////////////////////////resize bay=creaArreglo(Np-mig); p=0; k=0; for(i=0;i<=(Np-1);i++) { //printf("i=%i\n",i); for(u=0;u<=(mig-1);u++) { //printf("i=%i,u=%i, muestra=%f\n",i,u,gete(temp,u)); if (i==gete(temp,u)) { p=1; } }//end u loop if (p==1)//means if there is a match and this entry will migrate and be excluded from posx { ////printf("do nothing\n"); } else//we keep this entry for the new array be which will become the new posx { elem=gete(posy,i); insertaArreglo(bay,k,elem); //ba[k]==posy[u]; k=k+1; //Debug//printf("elem %f, k=%i\n",elem,k); } p=0; }//end i loop //////////////////////////////////////////////////////////////////////////////end resize ////MuestraArreglo(bax); ////MuestraArreglo(bay); Np=Np-mig;//We redefine the number of particles in the domain, Np-mig borraArreglo(posx);//erasing posx posx=creaArreglo(Np);//we create it again (reallocate memory) for(i=0;i<=(Np-1);i++) {//refill it with bax insertaArreglo(posx,i,gete(bax,i)); } //same for posy borraArreglo(posy);//erasing posy posy=creaArreglo(Np);//we create it again (reallocate memory) for(i=0;i<=(Np-1);i++) {//refill it with bay insertaArreglo(posy,i,gete(bay,i)); } ////printf("new posx and posy\n"); ////MuestraArreglo(posx); ////MuestraArreglo(posy); // printf("arreglo mx"); // MuestraArreglo(mx); dim=mig; }//end if there are migrants... (mig)///////////////////////////////////////////////// nRecv=(int *)calloc(processors, sizeof(int)); migsrecv=(int *)calloc(processors, sizeof(int)); displ=(int *)calloc(processors, sizeof(int)); ////printf("newrank=%i,mig=%i,dim=%i,time=%g\n",rank,mig,dim,timet); MPI_Gather(&dim, 1, MPI_INT, nRecv, 1, MPI_INT, 0,MPI_COMM_WORLD); MPI_Gather(&mig, 1, MPI_INT, migsrecv, 1, MPI_INT, 0,MPI_COMM_WORLD); // calculate the displacement if (rank==0){ displ[0] = 0; for (i=1;i