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;
}
Ejemplo n.º 2
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;
}
Ejemplo n.º 3
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;
}