Commit 3a1b88c5 authored by Steve Plimpton's avatar Steve Plimpton
Browse files

enable MSM to work withe new GridComm class

parent e00544c8
Loading
Loading
Loading
Loading
+138 −115
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@
#include "kspace.h"
#include "irregular.h"
#include "memory.h"
#include "error.h"

using namespace LAMMPS_NS;

@@ -24,12 +25,17 @@ enum{REGULAR,TILED};

#define SWAPDELTA 8

// NOTE: gridcomm needs to be world for TILED, will it work with MSM?
// NOTE: Tiled implementation here only works for RCB, not general tiled
/* ----------------------------------------------------------------------
   NOTES
   tiled implementation only currently works for RCB, not general tiled
   if o indices for ghosts are < 0 or hi indices are >= N,
     then grid is treated as periodic in that dimension,
     communication is done across the periodic boundaries
------------------------------------------------------------------------- */

/* ----------------------------------------------------------------------
   gcomm = MPI communicator that shares this grid
           does not have to be world, see MSM
   constructor called by all classes except MSM
   gcomm = world communicator
   gn xyz = size of global grid
   i xyz lohi = portion of global grid this proc owns, 0 <= index < N
   o xyz lohi = owned grid portion + ghost grid cells needed in all directions
@@ -44,75 +50,122 @@ GridComm::GridComm(LAMMPS *lmp, MPI_Comm gcomm,
		   int oxlo, int oxhi, int oylo, int oyhi, int ozlo, int ozhi)
  : Pointers(lmp)
{
  gridcomm = gcomm;
  MPI_Comm_rank(gridcomm,&me);
  MPI_Comm_size(gridcomm,&nprocs);

  nx = gnx;
  ny = gny;
  nz = gnz;
  
  inxlo = ixlo;
  inxhi = ixhi;
  inylo = iylo;
  inyhi = iyhi;
  inzlo = izlo;
  inzhi = izhi;
  if (comm->layout == Comm::LAYOUT_TILED) layout = TILED;
  else layout = REGULAR;

  outxlo = oxlo;
  outxhi = oxhi;
  outylo = oylo;
  outyhi = oyhi;
  outzlo = ozlo;
  outzhi = ozhi;
  if (layout == REGULAR) {
    int (*procneigh)[2] = comm->procneigh;
    initialize(gcomm,gnx,gny,gnz,
	       ixlo,ixhi,iylo,iyhi,izlo,izhi,
	       oxlo,oxhi,oylo,oyhi,ozlo,ozhi,
	       oxlo,oxhi,oylo,oyhi,ozlo,ozhi,
	       procneigh[0][0],procneigh[0][1],
	       procneigh[1][0],procneigh[1][1],
	       procneigh[2][0],procneigh[2][1]);
  } else {
    initialize(gcomm,gnx,gny,gnz,
	       ixlo,ixhi,iylo,iyhi,izlo,izhi,
	       oxlo,oxhi,oylo,oyhi,ozlo,ozhi,
	       oxlo,oxhi,oylo,oyhi,ozlo,ozhi,
	       0,0,0,0,0,0);
  }
}

  // layout == REGULAR or TILED
  // for REGULAR, proc xyz lohi = my 6 neighbor procs
/* ----------------------------------------------------------------------
   constructor called by MSM
   gcomm = world communicator or sub-communicator for a hierarchical grid
   flag = 1 if e xyz lohi values = larger grid stored by caller in gcomm = world
   flag = 2 if e xyz lohi values = 6 neighbor procs in gcomm
   gn xyz = size of global grid
   i xyz lohi = portion of global grid this proc owns, 0 <= index < N
   o xyz lohi = owned grid portion + ghost grid cells needed in all directions
   e xyz lohi for flag = 1: extent of larger grid stored by caller
   e xyz lohi for flag = 2: 6 neighbor procs
------------------------------------------------------------------------- */

  layout = REGULAR;
GridComm::GridComm(LAMMPS *lmp, MPI_Comm gcomm, int flag,
		   int gnx, int gny, int gnz,
		   int ixlo, int ixhi, int iylo, int iyhi, int izlo, int izhi,
		   int oxlo, int oxhi, int oylo, int oyhi, int ozlo, int ozhi,
		   int exlo, int exhi, int eylo, int eyhi, int ezlo, int ezhi)
  : Pointers(lmp)
{
  if (comm->layout == Comm::LAYOUT_TILED) layout = TILED;
  else layout = REGULAR;

  outxlo_max = oxlo;
  outxhi_max = oxhi;
  outylo_max = oylo;
  outyhi_max = oyhi;
  outzlo_max = ozlo;
  outzhi_max = ozhi;

  if (flag == 1) {
    if (layout == REGULAR) {
      // this assumes gcomm = world
      int (*procneigh)[2] = comm->procneigh;
      initialize(gcomm,gnx,gny,gnz,
		 ixlo,ixhi,iylo,iyhi,izlo,izhi,
		 oxlo,oxhi,oylo,oyhi,ozlo,ozhi,
		 exlo,exhi,eylo,eyhi,ezlo,ezhi,
		 procneigh[0][0],procneigh[0][1],
		 procneigh[1][0],procneigh[1][1],
		 procneigh[2][0],procneigh[2][1]);
    } else {
      initialize(gcomm,gnx,gny,gnz,
		 ixlo,ixhi,iylo,iyhi,izlo,izhi,
		 oxlo,oxhi,oylo,oyhi,ozlo,ozhi,
		 exlo,exhi,eylo,eyhi,ezlo,ezhi,
		 0,0,0,0,0,0);
    }
    
    procxlo = procneigh[0][0];
    procxhi = procneigh[0][1];
    procylo = procneigh[1][0];
    procyhi = procneigh[1][1];
    proczlo = procneigh[2][0];
    proczhi = procneigh[2][1];
  } else if (flag == 2) {
    if (layout == REGULAR) {
      initialize(gcomm,gnx,gny,gnz,
		 ixlo,ixhi,iylo,iyhi,izlo,izhi,
		 oxlo,oxhi,oylo,oyhi,ozlo,ozhi,
		 oxlo,oxhi,oylo,oyhi,ozlo,ozhi,
		 exlo,exhi,eylo,eyhi,ezlo,ezhi);
    } else {
      error->all(FLERR,"GridComm does not support tiled layout with neighbor procs");
    }
  }
}

  nswap = maxswap = 0;
  swap = NULL;
/* ---------------------------------------------------------------------- */

  nsend = nrecv = ncopy = 0;
  send = NULL;
  recv = NULL;
  copy = NULL;
  requests = NULL;
GridComm::~GridComm()
{
  // regular comm data struct
  
  for (int i = 0; i < nswap; i++) {
    memory->destroy(swap[i].packlist);
    memory->destroy(swap[i].unpacklist);
  }
  memory->sfree(swap);

  // tiled comm data structs
  
  for (int i = 0; i < nsend; i++)
    memory->destroy(send[i].packlist);
  memory->sfree(send);

  for (int i = 0; i < nrecv; i++)
    memory->destroy(recv[i].unpacklist);
  memory->sfree(recv);

  for (int i = 0; i < ncopy; i++) {
    memory->destroy(copy[i].packlist);
    memory->destroy(copy[i].unpacklist);
  }
  memory->sfree(copy);

  delete [] requests;
}

/* ----------------------------------------------------------------------
   same as first constructor except o xyz lohi max are added arguments
   this is for case when caller stores grid in a larger array than o xyz lohi
   only affects indices() method which generates indices into the caller's array
   store constructor args in local variables
------------------------------------------------------------------------- */

GridComm::GridComm(LAMMPS *lmp, MPI_Comm gcomm,
void GridComm::initialize(MPI_Comm gcomm,
			  int gnx, int gny, int gnz,
			  int ixlo, int ixhi, int iylo, int iyhi, int izlo, int izhi,
			  int oxlo, int oxhi, int oylo, int oyhi, int ozlo, int ozhi,
		   int oxlo_max, int oxhi_max, int oylo_max, int oyhi_max,
		   int ozlo_max, int ozhi_max)
  : Pointers(lmp)
			  int fxlo, int fxhi, int fylo, int fyhi, int fzlo, int fzhi,
			  int pxlo, int pxhi, int pylo, int pyhi, int pzlo, int pzhi)
{
  gridcomm = gcomm;
  MPI_Comm_rank(gridcomm,&me);
@@ -136,30 +189,26 @@ GridComm::GridComm(LAMMPS *lmp, MPI_Comm gcomm,
  outzlo = ozlo;
  outzhi = ozhi;

  outxlo_max = oxlo_max;
  outxhi_max = oxhi_max;
  outylo_max = oylo_max;
  outyhi_max = oyhi_max;
  outzlo_max = ozlo_max;
  outzhi_max = ozhi_max;

  // layout == REGULAR or TILED
  // for REGULAR, proc xyz lohi = my 6 neighbor procs
  fullxlo = fxlo;
  fullxhi = fxhi;
  fullylo = fylo;
  fullyhi = fyhi;
  fullzlo = fzlo;
  fullzhi = fzhi;

  layout = REGULAR;
  if (comm->layout == Comm::LAYOUT_TILED) layout = TILED;
  // for REGULAR layout, proc xyz lohi = my 6 neighbor procs in this MPI_Comm

  if (layout == REGULAR) {
    int (*procneigh)[2] = comm->procneigh;

    procxlo = procneigh[0][0];
    procxhi = procneigh[0][1];
    procylo = procneigh[1][0];
    procyhi = procneigh[1][1];
    proczlo = procneigh[2][0];
    proczhi = procneigh[2][1];
    procxlo = pxlo;
    procxhi = pxhi;
    procylo = pylo;
    procyhi = pyhi;
    proczlo = pzlo;
    proczhi = pzhi;
  }

  // internal data initializations
  
  nswap = maxswap = 0;
  swap = NULL;

@@ -172,37 +221,6 @@ GridComm::GridComm(LAMMPS *lmp, MPI_Comm gcomm,

/* ---------------------------------------------------------------------- */

GridComm::~GridComm()
{
  // regular comm data struct
  
  for (int i = 0; i < nswap; i++) {
    memory->destroy(swap[i].packlist);
    memory->destroy(swap[i].unpacklist);
  }
  memory->sfree(swap);

  // tiled comm data structs
  
  for (int i = 0; i < nsend; i++)
    memory->destroy(send[i].packlist);
  memory->sfree(send);

  for (int i = 0; i < nrecv; i++)
    memory->destroy(recv[i].unpacklist);
  memory->sfree(recv);

  for (int i = 0; i < ncopy; i++) {
    memory->destroy(copy[i].packlist);
    memory->destroy(copy[i].unpacklist);
  }
  memory->sfree(copy);

  delete [] requests;
}

/* ---------------------------------------------------------------------- */

void GridComm::setup(int &nbuf1, int &nbuf2)
{
  if (layout == REGULAR) setup_regular(nbuf1,nbuf2);
@@ -504,6 +522,7 @@ void GridComm::setup_regular(int &nbuf1, int &nbuf2)
}

/* ----------------------------------------------------------------------
   NOTE: need to doc this header
------------------------------------------------------------------------- */

void GridComm::setup_tiled(int &nbuf1, int &nbuf2)
@@ -725,6 +744,8 @@ void GridComm::setup_tiled(int &nbuf1, int &nbuf2)
}

/* ----------------------------------------------------------------------
   NOTE: need to doc this header
   recursive ...
------------------------------------------------------------------------- */

void GridComm::ghost_box_drop(int *box, int *pbc)
@@ -803,6 +824,8 @@ void GridComm::ghost_box_drop(int *box, int *pbc)
}

/* ----------------------------------------------------------------------
   NOTE: need to doc this header
   recursive ...
------------------------------------------------------------------------- */

void GridComm::box_drop_grid(int *box, int proclower, int procupper,
@@ -1083,15 +1106,15 @@ int GridComm::indices(int *&list,
  memory->create(list,nmax,"CommGrid:indices");
  if (nmax == 0) return 0;

  int nx = (outxhi_max-outxlo_max+1);
  int ny = (outyhi_max-outylo_max+1);
  int nx = (fullxhi-fullxlo+1);
  int ny = (fullyhi-fullylo+1);

  int n = 0;
  int ix,iy,iz;
  for (iz = zlo; iz <= zhi; iz++)
    for (iy = ylo; iy <= yhi; iy++)
      for (ix = xlo; ix <= xhi; ix++)
        list[n++] = (iz-outzlo_max)*ny*nx + (iy-outylo_max)*nx + (ix-outxlo_max);
        list[n++] = (iz-fullzlo)*ny*nx + (iy-fullylo)*nx + (ix-fullxlo);

  return nmax;
}
+17 −11
Original line number Diff line number Diff line
@@ -23,7 +23,7 @@ class GridComm : protected Pointers {
  GridComm(class LAMMPS *, MPI_Comm, int, int, int,
	   int, int, int, int, int, int,
	   int, int, int, int, int, int);
  GridComm(class LAMMPS *, MPI_Comm, int, int, int,
  GridComm(class LAMMPS *, MPI_Comm, int, int, int, int,
	   int, int, int, int, int, int,
	   int, int, int, int, int, int,
	   int, int, int, int, int, int);
@@ -38,7 +38,8 @@ class GridComm : protected Pointers {
 private:
  int me,nprocs;
  int layout;                 // REGULAR or TILED
  MPI_Comm gridcomm;
  MPI_Comm gridcomm;          // communicator for this class
                              // usually world, but MSM calls with subset

  // inputs from caller via constructor

@@ -49,9 +50,9 @@ class GridComm : protected Pointers {
  int outxlo,outxhi;          // inclusive extent of my grid chunk plus
  int outylo,outyhi;          //   ghost cells in all 6 directions
  int outzlo,outzhi;          //   lo indices can be < 0, hi indices can be >= N
  int outxlo_max,outxhi_max;  // ??
  int outylo_max,outyhi_max;
  int outzlo_max,outzhi_max;
  int fullxlo,fullxhi;        // extent of grid chunk that caller stores
  int fullylo,fullyhi;        //   can be same as out indices or larger
  int fullzlo,fullzhi;

  // -------------------------------------------
  // internal variables for REGULAR layout
@@ -83,8 +84,8 @@ class GridComm : protected Pointers {
  // internal variables for TILED layout
  // -------------------------------------------

  int *overlap_procs;
  MPI_Request *requests;
  int *overlap_procs;          // length of Nprocs in communicator
  MPI_Request *requests;       // length of max messages this proc receives

  // RCB tree of cut info
  // each proc contributes one value, except proc 0
@@ -175,6 +176,11 @@ class GridComm : protected Pointers {
  // internal methods
  // -------------------------------------------

  void initialize(MPI_Comm, int, int, int,
		  int, int, int, int, int, int,
		  int, int, int, int, int, int,
		  int, int, int, int, int, int,
		  int, int, int, int, int, int);
  void setup_regular(int &, int &);
  void setup_tiled(int &, int &);
  void ghost_box_drop(int *, int *);
+168 −142

File changed.

Preview size limit exceeded, changes collapsed.

+15 −12
Original line number Diff line number Diff line
@@ -32,6 +32,7 @@ class MSM : public KSpace {
  void setup();
  virtual void settings(int, char **);
  virtual void compute(int, int);
  virtual double memory_usage();

 protected:
  int me,nprocs;
@@ -79,16 +80,21 @@ class MSM : public KSpace {
  int procgrid[3];                  // procs assigned in each dim of 3d grid
  int myloc[3];                     // which proc I am in each dim
  int ***procneigh_levels;          // my 6 neighboring procs, 0/1 = left/right
  class GridComm **cg;
  class GridComm **cg_peratom;
  class GridComm *cg_all;
  class GridComm *cg_peratom_all;
  
  class GridComm *gcall;       // GridComm class for finest level grid
  class GridComm **gc;         // GridComm classes for each hierarchical level

  double *gcall_buf1,*gcall_buf2;
  double **gc_buf1,**gc_buf2;
  int ngcall_buf1,ngcall_buf2,npergrid;
  int *ngc_buf1,*ngc_buf2;

  int current_level;

  int **part2grid;             // storage for particle -> grid mapping
  int nmax;

  int triclinic;
  double *boxlo;

  void set_grid_global();
@@ -126,15 +132,12 @@ class MSM : public KSpace {
  void get_g_direct_top(int);
  void get_virial_direct_top(int);

  // triclinic

  int triclinic;

  // grid communication
  void pack_forward(int, double *, int, int *);
  void unpack_forward(int, double *, int, int *);
  void pack_reverse(int, double *, int, int *);
  void unpack_reverse(int, double *, int, int *);
  
  void pack_forward_grid(int, void *, int, int *);
  void unpack_forward_grid(int, void *, int, int *);
  void pack_reverse_grid(int, void *, int, int *);
  void unpack_reverse_grid(int, void *, int, int *);
};

}
+29 −23
Original line number Diff line number Diff line
@@ -91,17 +91,7 @@ void MSMCG::compute(int eflag, int vflag)

  // invoke allocate_peratom() if needed for first time

  if (vflag_atom && !peratom_allocate_flag) {
    allocate_peratom();
    cg_peratom_all->ghost_notify();
    cg_peratom_all->setup();
    for (int n=0; n<levels; n++) {
      if (!active_flag[n]) continue;
      cg_peratom[n]->ghost_notify();
      cg_peratom[n]->setup();
    }
    peratom_allocate_flag = 1;
  }
  if (vflag_atom && !peratom_allocate_flag) allocate_peratom();

  // extend size of per-atom arrays if necessary

@@ -171,7 +161,8 @@ void MSMCG::compute(int eflag, int vflag)
  //   to fully sum contribution in their 3d grid

  current_level = 0;
  cg_all->reverse_comm(this,REVERSE_RHO);
  gcall->reverse_comm_kspace(this,1,sizeof(double),REVERSE_RHO,
			     gcall_buf1,gcall_buf2,MPI_DOUBLE);

  // forward communicate charge density values to fill ghost grid points
  // compute direct sum interaction and then restrict to coarser grid
@@ -179,24 +170,30 @@ void MSMCG::compute(int eflag, int vflag)
  for (int n=0; n<=levels-2; n++) {
    if (!active_flag[n]) continue;
    current_level = n;
    cg[n]->forward_comm(this,FORWARD_RHO);

    gc[n]->forward_comm_kspace(this,1,sizeof(double),FORWARD_RHO,
			       gc_buf1[n],gc_buf2[n],MPI_DOUBLE);
    direct(n);
    restriction(n);
  }


  // compute direct interaction for top grid level for non-periodic
  //   and for second from top grid level for periodic

  if (active_flag[levels-1]) {
    if (domain->nonperiodic) {
      current_level = levels-1;
      cg[levels-1]->forward_comm(this,FORWARD_RHO);
      gc[levels-1]->
	forward_comm_kspace(this,1,sizeof(double),FORWARD_RHO,
			    gc_buf1[levels-1],gc_buf2[levels-1],MPI_DOUBLE);
      direct_top(levels-1);
      cg[levels-1]->reverse_comm(this,REVERSE_AD);
      gc[levels-1]->
	reverse_comm_kspace(this,1,sizeof(double),REVERSE_AD,
			    gc_buf1[levels-1],gc_buf2[levels-1],MPI_DOUBLE);
      if (vflag_atom)
        cg_peratom[levels-1]->reverse_comm(this,REVERSE_AD_PERATOM);
	gc[levels-1]->
	  reverse_comm_kspace(this,6,sizeof(double),REVERSE_AD_PERATOM,
			      gc_buf1[levels-1],gc_buf2[levels-1],MPI_DOUBLE);

    } else {
      // Here using MPI_Allreduce is cheaper than using commgrid
      grid_swap_forward(levels-1,qgrid[levels-1]);
@@ -204,7 +201,9 @@ void MSMCG::compute(int eflag, int vflag)
      grid_swap_reverse(levels-1,egrid[levels-1]);
      current_level = levels-1;
      if (vflag_atom)
        cg_peratom[levels-1]->reverse_comm(this,REVERSE_AD_PERATOM);
	gc[levels-1]->
	  reverse_comm_kspace(this,6,sizeof(double),REVERSE_AD_PERATOM,
			      gc_buf1[levels-1],gc_buf2[levels-1],MPI_DOUBLE);
    }
  }

@@ -216,24 +215,28 @@ void MSMCG::compute(int eflag, int vflag)
    prolongation(n);

    current_level = n;
    cg[n]->reverse_comm(this,REVERSE_AD);
    gc[n]->reverse_comm_kspace(this,1,sizeof(double),REVERSE_AD,
			       gc_buf1[n],gc_buf2[n],MPI_DOUBLE);

    // extra per-atom virial communication

    if (vflag_atom)
      cg_peratom[n]->reverse_comm(this,REVERSE_AD_PERATOM);
      gc[n]->reverse_comm_kspace(this,6,sizeof(double),REVERSE_AD_PERATOM,
				 gc_buf1[n],gc_buf2[n],MPI_DOUBLE);
  }

  // all procs communicate E-field values
  // to fill ghost cells surrounding their 3d bricks

  current_level = 0;
  cg_all->forward_comm(this,FORWARD_AD);
  gcall->forward_comm_kspace(this,1,sizeof(double),FORWARD_AD,
			     gcall_buf1,gcall_buf2,MPI_DOUBLE);

  // extra per-atom energy/virial communication

  if (vflag_atom)
    cg_peratom_all->forward_comm(this,FORWARD_AD_PERATOM);
    gcall->forward_comm_kspace(this,6,sizeof(double),FORWARD_AD_PERATOM,
			       gcall_buf1,gcall_buf2,MPI_DOUBLE);

  // calculate the force on my particles (interpolation)

@@ -536,6 +539,9 @@ void MSMCG::fieldforce_peratom()
  }
}

/* ----------------------------------------------------------------------
   memory usage of local arrays
------------------------------------------------------------------------- */

double MSMCG::memory_usage()
{
Loading