int main(int argc, char** argv) { int x, y; //set paramet param_t p; int ncycle = 0; p.L = 128; p.m = 0.01; p.scale = 1/(4.0 + p.m*p.m); p.niter = 10; p.dt = 0.1; // Initialize MPI MPI_Init(&argc, &argv); // Get the number of processes MPI_Comm_size(MPI_COMM_WORLD, &p.world_size); // Get the rank MPI_Comm_rank(MPI_COMM_WORLD, &p.my_rank); // How tall am I in the y direction? p.y = p.L/p.world_size; // intentionally do integer divide... if (p.my_rank == (p.world_size-1)) // ...because the last rank... { p.y += p.L % p.world_size; // ... gets the leftover! } // phi is slightly bigger, it needs a buffer! double *phi = (double*)malloc(sizeof(double)*p.L*(p.y+2)); double *tmp = (double*)malloc(sizeof(double)*p.L*p.y); // for Jacobi double *b = (double*)malloc(sizeof(double)*p.L*p.y); //initilize for(x = 0; x < p.L; x++) { for(y = 0; y < p.y; y++) { phi[x + y*p.L] =0.0; tmp[x + y*p.L] = 0.0; b[x + y*p.L] = 0.0; } // including the extra space for phi. phi[x + p.y*p.L] = 0.0; phi[x + (p.y+1)*p.L] = 0.0; } //b[p.L/4 + (p.L/4)*p.L] = 10.0; //b[3*p.L/4 + (3*p.L/4)*p.L] = -10.0; // We need to set sources on the right place on the right rank! int source_rank = (p.L/4)/(p.L/p.world_size); if (p.my_rank == source_rank) { b[p.L/4 + (p.L/4 - source_rank*(p.L/p.world_size))*p.L] = 10.0; } source_rank = (3*p.L/4)/(p.L/p.world_size); if (p.my_rank == source_rank) { b[3*p.L/4 + (3*p.L/4 - source_rank*(p.L/p.world_size))*p.L] = -10.0; } // iterate to solve_____________________________________ double resmag = 1.0; // not rescaled. resmag = GetResRoot(phi,b,p); if (p.my_rank == 0) { printf("At the %d cycle the mag residue is %.8e \n",0,resmag); } // while(resmag > 0.00001 && ncycle < 10000) while(resmag > 0.00001) { ncycle++; relax(phi,b,tmp,p); resmag = GetResRoot(phi,b,p); if (p.my_rank == 0) { printf("At the %d cycle the mag residue is %.8e \n",ncycle,resmag); } } free(phi); free(tmp); free(b); return 0; }
int multigrid(int Lmax, double (*boundary_func)(int)) { double *phi[20], *res[20]; param_t p; int nlev; int i,j,lev; //set parameters________________________________________ p.Lmax = Lmax; // max number of levels p.N = 2*(int)pow(2,p.Lmax); // MUST BE POWER OF 2 //p.N = 64; // p.m = 0.01; nlev = 2; // NUMBER OF LEVELS: nlev = 0 give top level alone if(nlev > p.Lmax){ printf(" ERROR: More levels than available in lattice! \n"); return 1; } double resmag = 1.0; // not rescaled. int ncycle = 0; int n_per_lev = 10; printf(" V cycle for %d by %d lattice with nlev = %d out of max %d \n", p.N, p.N, nlev, p.Lmax); // initialize arrays__________________________________ p.size[0] = p.N; p.a[0] = 1.0; p.alpha = 1.0; for(lev = 1;lev< p.Lmax+1; lev++) { p.size[lev] = (p.size[lev-1])/2; p.a[lev] = 2.0 * p.a[lev-1]; // p.scale[lev] = 1.0/(4.0 + p.m*p.m*p.a[lev]*p.a[lev]); } for(lev = 0;lev< p.Lmax+1; lev++) { phi[lev] = (double *) malloc(p.size[lev]*p.size[lev] * sizeof(double)); res[lev] = (double *) malloc(p.size[lev]*p.size[lev] * sizeof(double)); for(i = 0; i < p.size[lev]*p.size[lev]; i++) { phi[lev][i] = 0.0; res[lev][i] = 0.0; } } // set up the boundary conditions for (i=0; i<p.N; i++) { double tmp = (*boundary_func)(i); phi[0][i] = tmp; // top edge, left to right // res[p.N * p.N - (p.N * (i+1))] = boundary_func(i); phi[0][p.N * (p.N - i - 1)] = tmp; // left edge, bottom to top phi[0][(p.N * (i+1)) - 1] = tmp; // right edge, top to bottom phi[0][(p.N * p.N) - i - 1] = tmp; // bottom edge, right to left } FILE *nfile = fopen("res_data.dat", "w+"); for (i=0; i<p.N; i++) { for (j=0; j<p.N; j++) { fprintf(nfile, "%i %i %f\n", i, j, res[0][i + j*p.N]); } } // set up the heat source res[0][(1*(p.N/4)) + ((1*(p.N/4)))*p.N] = p.alpha; res[0][(1*(p.N/4)) + ((3*(p.N/4)))*p.N] = p.alpha; res[0][(3*(p.N/4)) + ((1*(p.N/4)))*p.N] = p.alpha; res[0][(3*(p.N/4)) + ((3*(p.N/4)))*p.N] = p.alpha; // iterate to solve_____________________________________ resmag = 1.0; // not rescaled. ncycle = 0; n_per_lev = 10; resmag = GetResRoot(phi[0],res[0],0,p); printf(" At the %d cycle the mag residue is %g \n", ncycle, resmag); // while(resmag > 0.00001 && ncycle < 10000) while(resmag > 0.00001) { ncycle +=1; for(lev = 0;lev<nlev; lev++) { //go down relax(phi[lev],res[lev],lev, n_per_lev,p); // lev = 1, ..., nlev-1 proj_res(res[lev + 1], res[lev], phi[lev], lev,p); // res[lev+1] += P^dag res[lev] } for(lev = nlev;lev >= 0; lev--) { //come up relax(phi[lev],res[lev],lev, n_per_lev,p); // lev = nlev -1, ... 0; if(lev > 0) inter_add(phi[lev-1], phi[lev], lev, p); // phi[lev-1] += error = P phi[lev] and set phi[lev] = 0; } resmag = GetResRoot(phi[0],res[0],0,p); if (ncycle % 100 == 0) printf(" At the %d cycle the mag residue is %g \n", ncycle, resmag); } FILE *file = fopen("serial.dat", "w+"); for (i=0; i<p.N; i++) { for (j=0; j<p.N; j++) { fprintf(file, "%i %i %f\n", i, j, phi[0][getIndex(i, j, p.N)]); } } return 0; }
int main(int argc, char **argv) { struct timespec time1, time2, total; double *phi[20], *res[20]; param_t p; int nlev; int i,lev; //set parameters________________________________________ p.Lmax = 6; // max number of levels p.N = 2*(int)pow(2,p.Lmax); // MUST BE POWER OF 2 p.m = 0.01; nlev = 0; // NUMBER OF LEVELS: nlev = 0 give top level alone if(nlev > p.Lmax){ printf("ERROR More levels than available in lattice! \n"); return 0; } // PARALLEL clock_gettime(CLOCK_MONOTONIC, &time1); printf("\n V cycle for %d by %d lattice with nlev = %d out of max %d \n", p.N, p.N, nlev, p.Lmax); // initialize arrays__________________________________ p.size[0] = p.N; p.a[0] = 1.0; p.scale[0] = 1.0/(4.0 + p.m*p.m); for(lev = 1;lev< p.Lmax+1; lev++) { p.size[lev] = p.size[lev-1]/2; p.a[lev] = 2.0 * p.a[lev-1]; // p.scale[lev] = 1.0/(4.0 + p.m*p.m*p.a[lev]*p.a[lev]); p.scale[lev] = 1.0/(4.0 + p.m*p.m); } for(lev = 0;lev< p.Lmax+1; lev++) { phi[lev] = (double *) malloc(p.size[lev]*p.size[lev] * sizeof(double)); res[lev] = (double *) malloc(p.size[lev]*p.size[lev] * sizeof(double)); for(i = 0;i< p.size[lev]*p.size[lev];i++) { phi[lev][i] = 0.0; res[lev][i] = 0.0; } } res[0][p.N/2 + (p.N/2)*p.N] = 1.0*p.scale[0]; //unit point source in middle of N by N lattice // iterate to solve_____________________________________ double resmag = 1.0; // not rescaled. int ncycle = 0; int n_per_lev = 10; resmag = GetResRoot_parallel(phi[0],res[0],0,p); printf("At the %d cycle the mag residue is %g \n",ncycle,resmag); // while(resmag > 0.00001 && ncycle < 10000) while(resmag > 0.00001) { ncycle +=1; for(lev = 0;lev<nlev; lev++) { //go down relax_parallel(phi[lev],res[lev],lev, n_per_lev,p); // lev = 1, ..., nlev-1 proj_res_parallel(res[lev + 1], res[lev], phi[lev], lev,p); // res[lev+1] += P^dag res[lev] } for(lev = nlev;lev >= 0; lev--) { //come up relax_parallel(phi[lev],res[lev],lev, n_per_lev,p); // lev = nlev -1, ... 0; if(lev > 0) inter_add_parallel(phi[lev-1], phi[lev], lev, p); // phi[lev-1] += error = P phi[lev] and set phi[lev] = 0; } resmag = GetResRoot_parallel(phi[0],res[0],0,p); if (ncycle % 1000 == 0) printf("At the %d cycle the mag residue is %g \n", ncycle, resmag); } clock_gettime(CLOCK_MONOTONIC, &time2); total = diff(time1, time2); printf("Total time: %ld.%ld seconds\n", total.tv_sec, total.tv_nsec); // NON-PARALLEL clock_gettime(CLOCK_MONOTONIC, &time1); printf("\n V cycle for %d by %d lattice with nlev = %d out of max %d \n", p.N, p.N, nlev, p.Lmax); // initialize arrays__________________________________ p.size[0] = p.N; p.a[0] = 1.0; p.scale[0] = 1.0/(4.0 + p.m*p.m); for(lev = 1;lev< p.Lmax+1; lev++) { p.size[lev] = p.size[lev-1]/2; p.a[lev] = 2.0 * p.a[lev-1]; // p.scale[lev] = 1.0/(4.0 + p.m*p.m*p.a[lev]*p.a[lev]); p.scale[lev] = 1.0/(4.0 + p.m*p.m); } for(lev = 0;lev< p.Lmax+1; lev++) { phi[lev] = (double *) malloc(p.size[lev]*p.size[lev] * sizeof(double)); res[lev] = (double *) malloc(p.size[lev]*p.size[lev] * sizeof(double)); for(i = 0;i< p.size[lev]*p.size[lev];i++) { phi[lev][i] = 0.0; res[lev][i] = 0.0; } } res[0][p.N/2 + (p.N/2)*p.N] = 1.0*p.scale[0]; //unit point source in middle of N by N lattice // iterate to solve_____________________________________ resmag = 1.0; // not rescaled. ncycle = 0; n_per_lev = 10; resmag = GetResRoot(phi[0],res[0],0,p); printf("At the %d cycle the mag residue is %g \n",ncycle,resmag); // while(resmag > 0.00001 && ncycle < 10000) while(resmag > 0.00001) { ncycle +=1; for(lev = 0;lev<nlev; lev++) { //go down relax(phi[lev],res[lev],lev, n_per_lev,p); // lev = 1, ..., nlev-1 proj_res(res[lev + 1], res[lev], phi[lev], lev,p); // res[lev+1] += P^dag res[lev] } for(lev = nlev;lev >= 0; lev--) { //come up relax(phi[lev],res[lev],lev, n_per_lev,p); // lev = nlev -1, ... 0; if(lev > 0) inter_add(phi[lev-1], phi[lev], lev, p); // phi[lev-1] += error = P phi[lev] and set phi[lev] = 0; } resmag = GetResRoot(phi[0],res[0],0,p); if (ncycle % 1000 == 0) printf("At the %d cycle the mag residue is %g \n", ncycle, resmag); } clock_gettime(CLOCK_MONOTONIC, &time2); total = diff(time1, time2); printf("Total time: %ld.%ld seconds\n", total.tv_sec, total.tv_nsec); return 0; }