_s< 1;_s++) for(scalar sb=s;sb.i< s.i+s.block;sb.i++, b++) memcpy(b, &sb[], sizeof(real));MPI_Isend(buf, size, MPI_BYTE, dst, tag, MPI_COMM_WORLD, req);return buf;}for(int _d=0;_d< 2;_d++) static void rcv_x(int i, int src, int tag, int level, scalar *list){ if(src==MPI_PROC_NULL) return;size_t size=0;for(int _s=0;_s< 1;_s++) size+=s.block;size *=pow((1<< level)+2 *GHOSTS, 2 - 1) *GHOSTS *sizeof(real);double *buf=(double *) malloc(size), *b=buf;MPI_Status s;MPI_Recv(buf, size, MPI_BYTE, src, tag, MPI_COMM_WORLD, &s);foreach_slice_x(i, i+GHOSTS, level) for(int _s=0;_s< 1;_s++) for(scalar sb=s;sb.i< s.i+s.block;sb.i++, b++) memcpy(&sb[], b, sizeof(real));free(buf);}tracestatic void mpi_boundary_level(const Boundary *b, scalar *list, int level){ scalar *list1=NULL;for(int _s=0;_s< 1;_s++) if(!is_constant(s) &&s.block > 0) list1=list_add(list1, s);if(!list1) return;prof_start("mpi_boundary_level");if(level< 0) level=depth();MpiBoundary *mpi=(MpiBoundary *) b;struct { int x, y, z;} dir={0, 1, 2};for(int _d=0;_d< 2;_d++) { int left, right;MPI_Cart_shift(mpi->cartcomm, dir.x, 1, &left, &right);MPI_Request reqs[2];void *buf[2];int npl=(1<< level)+2 *GHOSTS, nr=0;if((buf[0]=snd_x(npl - 2 *GHOSTS, right, 0, level, list1, &reqs[nr]))) nr++;if((buf[1]=snd_x(2, left, 1, level, list1, &reqs[nr]))) nr++;rcv_x(0, left, 0, level, list1);rcv_x(npl - GHOSTS, right, 1, level, list1);MPI_Status stats[nr];MPI_Waitall(nr, reqs, stats);free(buf[0]);free(buf[1]);} free(list1);prof_stop();}static void mpi_boundary_destroy(Boundary *b){ MpiBoundary *m=(MpiBoundary *) b;MPI_Comm_free(&m->cartcomm);free(m);}static void mpi_dimensions_error(int n){ fprintf(stderr, "%s:%d: error: the number of MPI processes must be equal to ", __FILE__, LINENO);if(n > 1) fprintf(stderr, "%dx", n);fprintf(stderr, "%d^i\n", 1<< 2);exit(1);}Boundary *mpi_boundary_new(){ MpiBoundary *m=qcalloc(1, MpiBoundary);int n=1;for(int _d=0;_d< 2;_d++) n *=Dimensions.x;if(npe() % n) mpi_dimensions_error(n);int j=npe()/n, i=0;while(j > 1) { if(j %(1<< 2)) mpi_dimensions_error(n);j/=1<< 2;i++;} for(int _d=0;_d< 2;_d++) Dimensions.x *=1<< i;MPI_Dims_create(npe(), 2, &Dimensions.x);MPI_Cart_create(MPI_COMM_WORLD, 2, &Dimensions.x, &Period.x, 0, &m->cartcomm);MPI_Cart_coords(m->cartcomm, pid(), 2, mpi_coords);struct { int x, y, z;} dir={0, 1, 2};for(int _d=0;_d< 2;_d++) { int l, r;MPI_Cart_shift(m->cartcomm, dir.x, 1, &l, &r);if(l !=MPI_PROC_NULL) periodic_boundary(left);if(r !=MPI_PROC_NULL) periodic_boundary(right);} Dimensions_scale=Dimensions.x;N/=Dimensions.x;int r=0;while(N > 1) N/=2, r++;grid-> depth