Files
lammps/src/comm_tiled.cpp

837 lines
31 KiB
C++

/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "lmptype.h"
#include "comm_tiled.h"
#include "atom.h"
#include "atom_vec.h"
#include "domain.h"
#include "pair.h"
#include "modify.h"
#include "fix.h"
#include "compute.h"
#include "dump.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
#define BUFFACTOR 1.5
enum{SINGLE,MULTI}; // same as in Comm
/* ---------------------------------------------------------------------- */
CommTiled::CommTiled(LAMMPS *lmp) : Comm(lmp)
{
style = 1;
layout = 0;
error->all(FLERR,"Comm_style tiled is not yet supported");
}
/* ---------------------------------------------------------------------- */
CommTiled::~CommTiled()
{
}
/* ---------------------------------------------------------------------- */
void CommTiled::init()
{
triclinic = domain->triclinic;
map_style = atom->map_style;
// comm_only = 1 if only x,f are exchanged in forward/reverse comm
// comm_x_only = 0 if ghost_velocity since velocities are added
comm_x_only = atom->avec->comm_x_only;
comm_f_only = atom->avec->comm_f_only;
if (ghost_velocity) comm_x_only = 0;
// set per-atom sizes for forward/reverse/border comm
// augment by velocity and fix quantities if needed
size_forward = atom->avec->size_forward;
size_reverse = atom->avec->size_reverse;
size_border = atom->avec->size_border;
if (ghost_velocity) size_forward += atom->avec->size_velocity;
if (ghost_velocity) size_border += atom->avec->size_velocity;
for (int i = 0; i < modify->nfix; i++)
size_border += modify->fix[i]->comm_border;
}
/* ----------------------------------------------------------------------
setup spatial-decomposition communication patterns
function of neighbor cutoff(s) & cutghostuser & current box size
single mode sets slab boundaries (slablo,slabhi) based on max cutoff
multi mode sets type-dependent slab boundaries (multilo,multihi)
------------------------------------------------------------------------- */
void CommTiled::setup()
{
// error on triclinic or multi?
// set nswap = 2*dim
// setup neighbor proc info for exchange()
// setup nsendproc and nrecvproc bounts
// setup sendproc and recvproc lists
// setup sendboxes
// reallocate requests and statuses
// check that cutoff is <= 1/2 of periodic box len?
// loop over dims
// left:
// construct ghost boxes
// differnet in x,y,z
// account for ghost borders in y,z
// account for PBC by shifting
// split into multiple boxes if straddles PBC
// drop boxes down RCB tree
// count unique procs they cover
// what about self if crosses PBC
// for each proc they cover:
// compute box I send it to left
// is a message I will recv from right (don't care about box)
// for ghost-extended boxes
// do not count procs that do not overlap my owned box at all
// only touching edge of my owned box does not count
// in this case list I send to and recv from may be different?
// same thing to right
// what need from decomp (RCB):
// dropbox: return list of procs with overlap and overlapping boxes
// return n, proclist, boxlist
// otherbox: bbox of another proc
// dropatom: return what proc owns the atom coord
}
/* ----------------------------------------------------------------------
forward communication of atom coords every timestep
other per-atom attributes may also be sent via pack/unpack routines
------------------------------------------------------------------------- */
void CommTiled::forward_comm(int dummy)
{
int i,irecv,n;
MPI_Status status;
AtomVec *avec = atom->avec;
double **x = atom->x;
// exchange data with another set of procs in each swap
// if first proc in set is self, then is just self across PBC, just copy
// if comm_x_only set, exchange or copy directly to x, don't unpack
for (int iswap = 0; iswap < nswap; iswap++) {
if (sendproc[iswap][0] != me) {
if (comm_x_only) {
for (i = 0; i < nrecvproc[iswap]; i++)
MPI_Irecv(x[firstrecv[iswap][i]],size_forward_recv[iswap][i],
MPI_DOUBLE,recvproc[iswap][i],0,world,&requests[i]);
for (i = 0; i < nsendproc[iswap]; i++) {
n = avec->pack_comm(sendnum[iswap][i],sendlist[iswap][i],
buf_send,pbc_flag[iswap][i],pbc[iswap][i]);
MPI_Send(buf_send,n,MPI_DOUBLE,sendproc[iswap][i],0,world);
}
MPI_Waitall(nrecvproc[iswap],requests,statuses);
} else if (ghost_velocity) {
for (i = 0; i < nrecvproc[iswap]; i++)
MPI_Irecv(&buf_recv[forward_recv_offset[iswap][i]],
size_forward_recv[iswap][i],
MPI_DOUBLE,recvproc[iswap][i],0,world,&requests[i]);
for (i = 0; i < nsendproc[iswap]; i++) {
n = avec->pack_comm_vel(sendnum[iswap][i],sendlist[iswap][i],
buf_send,pbc_flag[iswap][i],pbc[iswap][i]);
MPI_Send(buf_send,n,MPI_DOUBLE,sendproc[iswap][i],0,world);
}
for (i = 0; i < nrecvproc[iswap]; i++) {
MPI_Waitany(nrecvproc[iswap],requests,&irecv,&status);
avec->unpack_comm_vel(recvnum[iswap][i],firstrecv[iswap][irecv],
&buf_recv[forward_recv_offset[iswap][irecv]]);
}
} else {
for (i = 0; i < nrecvproc[iswap]; i++)
MPI_Irecv(&buf_recv[forward_recv_offset[iswap][i]],
size_forward_recv[iswap][i],
MPI_DOUBLE,recvproc[iswap][i],0,world,&requests[i]);
for (i = 0; i < nsendproc[iswap]; i++) {
n = avec->pack_comm(sendnum[iswap][i],sendlist[iswap][i],
buf_send,pbc_flag[iswap][i],pbc[iswap][i]);
MPI_Send(buf_send,n,MPI_DOUBLE,sendproc[iswap][i],0,world);
}
for (i = 0; i < nrecvproc[iswap]; i++) {
MPI_Waitany(nrecvproc[iswap],requests,&irecv,&status);
avec->unpack_comm(recvnum[iswap][i],firstrecv[iswap][irecv],
&buf_recv[forward_recv_offset[iswap][irecv]]);
}
}
} else {
if (comm_x_only) {
if (sendnum[iswap][0])
n = avec->pack_comm(sendnum[iswap][0],sendlist[iswap][0],
x[firstrecv[iswap][0]],pbc_flag[iswap][0],
pbc[iswap][0]);
} else if (ghost_velocity) {
n = avec->pack_comm_vel(sendnum[iswap][0],sendlist[iswap][0],
buf_send,pbc_flag[iswap][0],pbc[iswap][0]);
avec->unpack_comm_vel(recvnum[iswap][0],firstrecv[iswap][0],buf_send);
} else {
n = avec->pack_comm(sendnum[iswap][0],sendlist[iswap][0],
buf_send,pbc_flag[iswap][0],pbc[iswap][0]);
avec->unpack_comm(recvnum[iswap][0],firstrecv[iswap][0],buf_send);
}
}
}
}
/* ----------------------------------------------------------------------
reverse communication of forces on atoms every timestep
other per-atom attributes may also be sent via pack/unpack routines
------------------------------------------------------------------------- */
void CommTiled::reverse_comm()
{
int i,irecv,n;
MPI_Request request;
MPI_Status status;
AtomVec *avec = atom->avec;
double **f = atom->f;
// exchange data with another set of procs in each swap
// if first proc in set is self, then is just self across PBC, just copy
// if comm_f_only set, exchange or copy directly from f, don't pack
for (int iswap = nswap-1; iswap >= 0; iswap--) {
if (sendproc[iswap][0] != me) {
if (comm_f_only) {
for (i = 0; i < nsendproc[iswap]; i++)
MPI_Irecv(&buf_recv[reverse_recv_offset[iswap][i]],
size_reverse_recv[iswap][i],MPI_DOUBLE,
sendproc[iswap][i],0,world,&requests[i]);
for (i = 0; i < nrecvproc[iswap]; i++)
MPI_Send(f[firstrecv[iswap][i]],size_reverse_send[iswap][i],
MPI_DOUBLE,recvproc[iswap][i],0,world);
for (i = 0; i < nsendproc[iswap]; i++) {
MPI_Waitany(nsendproc[iswap],requests,&irecv,&status);
avec->unpack_reverse(sendnum[iswap][irecv],sendlist[iswap][irecv],
&buf_recv[reverse_recv_offset[iswap][irecv]]);
}
} else {
for (i = 0; i < nsendproc[iswap]; i++)
MPI_Irecv(&buf_recv[reverse_recv_offset[iswap][i]],
size_reverse_recv[iswap][i],MPI_DOUBLE,
sendproc[iswap][i],0,world,&requests[i]);
for (i = 0; i < nrecvproc[iswap]; i++) {
n = avec->pack_reverse(recvnum[iswap][i],firstrecv[iswap][i],
buf_send);
MPI_Send(buf_send,n,MPI_DOUBLE,recvproc[iswap][i],0,world);
}
for (i = 0; i < nsendproc[iswap]; i++) {
MPI_Waitany(nsendproc[iswap],requests,&irecv,&status);
avec->unpack_reverse(sendnum[iswap][irecv],sendlist[iswap][irecv],
&buf_recv[reverse_recv_offset[iswap][irecv]]);
}
}
} else {
if (comm_f_only) {
if (sendnum[iswap][0])
avec->unpack_reverse(sendnum[iswap][0],sendlist[iswap][0],
f[firstrecv[iswap][0]]);
} else {
n = avec->pack_reverse(recvnum[iswap][0],firstrecv[iswap][0],buf_send);
avec->unpack_reverse(sendnum[iswap][0],sendlist[iswap][0],buf_send);
}
}
}
}
/* ----------------------------------------------------------------------
exchange: move atoms to correct processors
atoms exchanged with all 6 stencil neighbors
send out atoms that have left my box, receive ones entering my box
atoms will be lost if not inside some proc's box
can happen if atom moves outside of non-periodic bounary
or if atom moves more than one proc away
this routine called before every reneighboring
for triclinic, atoms must be in lamda coords (0-1) before exchange is called
------------------------------------------------------------------------- */
void CommTiled::exchange()
{
// loop over atoms
// if not outside my box, continue
// find which proc it is in
// find which one of my touching procs it is, else lost
// make sure all atoms are "lost" that should be (e.g. outside non-PBC)
// add to list to send to that proc
// loop over touching procs
// send buffer to them
}
/* ----------------------------------------------------------------------
borders: list nearby atoms to send to neighboring procs at every timestep
one list is created per swap/proc that will be made
as list is made, actually do communication
this does equivalent of a forward_comm(), so don't need to explicitly
call forward_comm() on reneighboring timestep
this routine is called before every reneighboring
for triclinic, atoms must be in lamda coords (0-1) before borders is called
------------------------------------------------------------------------- */
void CommTiled::borders()
{
int i,n,irecv,ngroup,nlast,nsend,rmaxswap;
double xlo,xhi,ylo,yhi,zlo,zhi;
double *bbox;
double **x;
MPI_Status status;
AtomVec *avec = atom->avec;
// smax = max size of single send in a swap/proc
// rmax = max size of recvs from all procs for a swap
int smax = 0;
int rmax = 0;
// loop over all swaps in all dimensions
for (int iswap = 0; iswap < nswap; iswap++) {
// find atoms within rectangles using <= and >=
// for x-dim swaps, check owned atoms
// for yz-dim swaps, check owned and ghost atoms
// store sent atom indices in list for use in future timesteps
// NOTE: assume SINGLE mode, add back in logic for MULTI mode later
x = atom->x;
for (i = 0; i < nsendproc[iswap]; i++) {
bbox = sendbox[iswap][i];
xlo = bbox[0]; xhi = bbox[1];
ylo = bbox[2]; yhi = bbox[3];
zlo = bbox[4]; zhi = bbox[5];
ngroup = atom->nfirst;
if (iswap < 2) nlast = atom->nlocal;
else nlast = atom->nlocal + atom->nghost;
nsend = 0;
for (i = 0; i < ngroup; i++)
if (x[i][0] >= xlo && x[i][0] <= xhi &&
x[i][1] >= ylo && x[i][1] <= yhi &&
x[i][2] >= zlo && x[i][2] <= zhi) {
if (nsend == maxsendlist[iswap][i]) grow_list(iswap,i,nsend);
sendlist[iswap][i][nsend++] = i;
}
for (i = atom->nlocal; i < nlast; i++)
if (x[i][0] >= xlo && x[i][0] <= xhi &&
x[i][1] >= ylo && x[i][1] <= yhi &&
x[i][2] >= zlo && x[i][2] <= zhi) {
if (nsend == maxsendlist[iswap][i]) grow_list(iswap,i,nsend);
sendlist[iswap][i][nsend++] = i;
}
sendnum[iswap][i] = nsend;
smax = MAX(smax,nsend);
}
// send sendnum counts to procs who recv from me
if (sendproc[iswap][0] != me) {
for (i = 0; i < nrecvproc[iswap]; i++)
MPI_Irecv(&recvnum[iswap][i],1,MPI_INT,
recvproc[iswap][i],0,world,&requests[i]);
for (i = 0; i < nsendproc[iswap]; i++)
MPI_Send(&sendnum[iswap][i],1,MPI_INT,sendproc[iswap][i],0,world);
MPI_Waitall(nrecvproc[iswap],requests,statuses);
} else recvnum[iswap][0] = sendnum[iswap][0];
// setup other per swap/proc values from sendnum and recvnum
rmaxswap = 0;
for (i = 0; i < nrecvproc[iswap]; i++) {
rmaxswap += recvnum[iswap][i];
size_forward_recv[iswap][i] = recvnum[iswap][i]*size_forward;
size_reverse_send[iswap][i] = recvnum[iswap][i]*size_reverse;
size_reverse_recv[iswap][i] = sendnum[iswap][i]*size_reverse;
if (i == 0) {
firstrecv[iswap][0] = atom->nlocal + atom->nghost;
forward_recv_offset[iswap][0] = 0;
} else {
firstrecv[iswap][i] = firstrecv[iswap][i-1] + recvnum[iswap][i-1];
forward_recv_offset[iswap][i] =
forward_recv_offset[iswap][i-1] + recvnum[iswap][i-1];
}
}
rmax = MAX(rmax,rmaxswap);
// insure send/recv buffers are large enough for border comm
if (smax*size_border > maxsend) grow_send(smax*size_border,0);
if (rmax*size_border > maxrecv) grow_recv(rmax*size_border);
// swap atoms with other procs using pack_border(), unpack_border()
if (sendproc[iswap][0] != me) {
for (i = 0; i < nsendproc[iswap]; i++) {
if (ghost_velocity) {
for (i = 0; i < nrecvproc[iswap]; i++)
MPI_Irecv(&buf_recv[forward_recv_offset[iswap][i]],
recvnum[iswap][i]*size_border,
MPI_DOUBLE,recvproc[iswap][i],0,world,&requests[i]);
for (i = 0; i < nsendproc[iswap]; i++) {
n = avec->pack_border_vel(sendnum[iswap][i],sendlist[iswap][i],
buf_send,pbc_flag[iswap][i],
pbc[iswap][i]);
MPI_Send(buf_send,n*size_border,MPI_DOUBLE,
sendproc[iswap][i],0,world);
}
for (i = 0; i < nrecvproc[iswap]; i++) {
MPI_Waitany(nrecvproc[iswap],requests,&irecv,&status);
avec->unpack_border(recvnum[iswap][i],firstrecv[iswap][irecv],
&buf_recv[forward_recv_offset[iswap][irecv]]);
}
} else {
for (i = 0; i < nrecvproc[iswap]; i++)
MPI_Irecv(&buf_recv[forward_recv_offset[iswap][i]],
recvnum[iswap][i]*size_border,
MPI_DOUBLE,recvproc[iswap][i],0,world,&requests[i]);
for (i = 0; i < nsendproc[iswap]; i++) {
n = avec->pack_border(sendnum[iswap][i],sendlist[iswap][i],
buf_send,pbc_flag[iswap][i],pbc[iswap][i]);
MPI_Send(buf_send,n*size_border,MPI_DOUBLE,
sendproc[iswap][i],0,world);
}
for (i = 0; i < nrecvproc[iswap]; i++) {
MPI_Waitany(nrecvproc[iswap],requests,&irecv,&status);
avec->unpack_border(recvnum[iswap][i],firstrecv[iswap][irecv],
&buf_recv[forward_recv_offset[iswap][irecv]]);
}
}
}
} else {
if (ghost_velocity) {
n = avec->pack_border_vel(sendnum[iswap][0],sendlist[iswap][0],
buf_send,pbc_flag[iswap][0],pbc[iswap][0]);
avec->unpack_border_vel(recvnum[iswap][0],firstrecv[iswap][0],buf_send);
} else {
n = avec->pack_border(sendnum[iswap][0],sendlist[iswap][0],
buf_send,pbc_flag[iswap][0],pbc[iswap][0]);
avec->unpack_border(recvnum[iswap][0],firstrecv[iswap][0],buf_send);
}
}
// increment ghost atoms
n = nrecvproc[iswap];
atom->nghost += forward_recv_offset[iswap][n-1] + recvnum[iswap][n-1];
}
// insure send/recv buffers are long enough for all forward & reverse comm
int max = MAX(maxforward*smax,maxreverse*rmax);
if (max > maxsend) grow_send(max,0);
max = MAX(maxforward*rmax,maxreverse*smax);
if (max > maxrecv) grow_recv(max);
// reset global->local map
if (map_style) atom->map_set();
}
/* ----------------------------------------------------------------------
forward communication invoked by a Pair
n = constant number of datums per atom
------------------------------------------------------------------------- */
void CommTiled::forward_comm_pair(Pair *pair)
{
int i,irecv,n;
MPI_Status status;
for (int iswap = 0; iswap < nswap; iswap++) {
if (sendproc[iswap][0] != me) {
for (i = 0; i < nrecvproc[iswap]; i++)
MPI_Irecv(&buf_recv[forward_recv_offset[iswap][i]],
size_forward_recv[iswap][i],
MPI_DOUBLE,recvproc[iswap][i],0,world,&requests[i]);
for (i = 0; i < nsendproc[iswap]; i++) {
n = pair->pack_comm(sendnum[iswap][i],sendlist[iswap][i],
buf_send,pbc_flag[iswap][i],pbc[iswap][i]);
MPI_Send(buf_send,n*sendnum[iswap][i],MPI_DOUBLE,
sendproc[iswap][i],0,world);
}
for (i = 0; i < nrecvproc[iswap]; i++) {
MPI_Waitany(nrecvproc[iswap],requests,&irecv,&status);
pair->unpack_comm(recvnum[iswap][irecv],firstrecv[iswap][irecv],
&buf_recv[forward_recv_offset[iswap][irecv]]);
}
} else {
n = pair->pack_comm(sendnum[iswap][0],sendlist[iswap][0],
buf_send,pbc_flag[iswap][0],pbc[iswap][0]);
pair->unpack_comm(recvnum[iswap][0],firstrecv[iswap][0],buf_send);
}
}
}
/* ----------------------------------------------------------------------
reverse communication invoked by a Pair
n = constant number of datums per atom
------------------------------------------------------------------------- */
void CommTiled::reverse_comm_pair(Pair *pair)
{
int i,irecv,n;
MPI_Status status;
for (int iswap = nswap-1; iswap >= 0; iswap--) {
if (sendproc[iswap][0] != me) {
for (i = 0; i < nsendproc[iswap]; i++)
MPI_Irecv(&buf_recv[reverse_recv_offset[iswap][i]],
size_reverse_recv[iswap][i],MPI_DOUBLE,
sendproc[iswap][i],0,world,&requests[i]);
for (i = 0; i < nrecvproc[iswap]; i++) {
n = pair->pack_reverse_comm(recvnum[iswap][i],firstrecv[iswap][i],
buf_send);
MPI_Send(buf_send,n*recvnum[iswap][i],MPI_DOUBLE,
recvproc[iswap][i],0,world);
}
for (i = 0; i < nsendproc[iswap]; i++) {
MPI_Waitany(nsendproc[iswap],requests,&irecv,&status);
pair->unpack_reverse_comm(sendnum[iswap][irecv],sendlist[iswap][irecv],
&buf_recv[reverse_recv_offset[iswap][irecv]]);
}
} else {
n = pair->pack_reverse_comm(recvnum[iswap][0],firstrecv[iswap][0],
buf_send);
pair->unpack_reverse_comm(sendnum[iswap][0],sendlist[iswap][0],buf_send);
}
}
}
/* ----------------------------------------------------------------------
forward communication invoked by a Fix
n = constant number of datums per atom
------------------------------------------------------------------------- */
void CommTiled::forward_comm_fix(Fix *fix)
{
int i,irecv,n;
MPI_Status status;
for (int iswap = 0; iswap < nswap; iswap++) {
if (sendproc[iswap][0] != me) {
for (i = 0; i < nrecvproc[iswap]; i++)
MPI_Irecv(&buf_recv[forward_recv_offset[iswap][i]],
size_forward_recv[iswap][i],
MPI_DOUBLE,recvproc[iswap][i],0,world,&requests[i]);
for (i = 0; i < nsendproc[iswap]; i++) {
n = fix->pack_comm(sendnum[iswap][i],sendlist[iswap][i],
buf_send,pbc_flag[iswap][i],pbc[iswap][i]);
MPI_Send(buf_send,n*sendnum[iswap][i],MPI_DOUBLE,
sendproc[iswap][i],0,world);
}
for (i = 0; i < nrecvproc[iswap]; i++) {
MPI_Waitany(nrecvproc[iswap],requests,&irecv,&status);
fix->unpack_comm(recvnum[iswap][irecv],firstrecv[iswap][irecv],
&buf_recv[forward_recv_offset[iswap][irecv]]);
}
} else {
n = fix->pack_comm(sendnum[iswap][0],sendlist[iswap][0],
buf_send,pbc_flag[iswap][0],pbc[iswap][0]);
fix->unpack_comm(recvnum[iswap][0],firstrecv[iswap][0],buf_send);
}
}
}
/* ----------------------------------------------------------------------
reverse communication invoked by a Fix
n = constant number of datums per atom
------------------------------------------------------------------------- */
void CommTiled::reverse_comm_fix(Fix *fix)
{
int i,irecv,n;
MPI_Status status;
for (int iswap = nswap-1; iswap >= 0; iswap--) {
if (sendproc[iswap][0] != me) {
for (i = 0; i < nsendproc[iswap]; i++)
MPI_Irecv(&buf_recv[reverse_recv_offset[iswap][i]],
size_reverse_recv[iswap][i],MPI_DOUBLE,
sendproc[iswap][i],0,world,&requests[i]);
for (i = 0; i < nrecvproc[iswap]; i++) {
n = fix->pack_reverse_comm(recvnum[iswap][i],firstrecv[iswap][i],
buf_send);
MPI_Send(buf_send,n*recvnum[iswap][i],MPI_DOUBLE,
recvproc[iswap][i],0,world);
}
for (i = 0; i < nsendproc[iswap]; i++) {
MPI_Waitany(nsendproc[iswap],requests,&irecv,&status);
fix->unpack_reverse_comm(sendnum[iswap][irecv],sendlist[iswap][irecv],
&buf_recv[reverse_recv_offset[iswap][irecv]]);
}
} else {
n = fix->pack_reverse_comm(recvnum[iswap][0],firstrecv[iswap][0],
buf_send);
fix->unpack_reverse_comm(sendnum[iswap][0],sendlist[iswap][0],buf_send);
}
}
}
/* ----------------------------------------------------------------------
forward communication invoked by a Fix
n = total datums for all atoms, allows for variable number/atom
NOTE: complicated b/c don't know # to recv a priori
------------------------------------------------------------------------- */
void CommTiled::forward_comm_variable_fix(Fix *fix)
{
}
/* ----------------------------------------------------------------------
reverse communication invoked by a Fix
n = total datums for all atoms, allows for variable number/atom
------------------------------------------------------------------------- */
void CommTiled::reverse_comm_variable_fix(Fix *fix)
{
}
/* ----------------------------------------------------------------------
forward communication invoked by a Compute
n = constant number of datums per atom
------------------------------------------------------------------------- */
void CommTiled::forward_comm_compute(Compute *compute)
{
int i,irecv,n;
MPI_Status status;
for (int iswap = 0; iswap < nswap; iswap++) {
if (sendproc[iswap][0] != me) {
for (i = 0; i < nrecvproc[iswap]; i++)
MPI_Irecv(&buf_recv[forward_recv_offset[iswap][i]],
size_forward_recv[iswap][i],
MPI_DOUBLE,recvproc[iswap][i],0,world,&requests[i]);
for (i = 0; i < nsendproc[iswap]; i++) {
n = compute->pack_comm(sendnum[iswap][i],sendlist[iswap][i],
buf_send,pbc_flag[iswap][i],pbc[iswap][i]);
MPI_Send(buf_send,n*sendnum[iswap][i],MPI_DOUBLE,
sendproc[iswap][i],0,world);
}
for (i = 0; i < nrecvproc[iswap]; i++) {
MPI_Waitany(nrecvproc[iswap],requests,&irecv,&status);
compute->unpack_comm(recvnum[iswap][irecv],firstrecv[iswap][irecv],
&buf_recv[forward_recv_offset[iswap][irecv]]);
}
} else {
n = compute->pack_comm(sendnum[iswap][0],sendlist[iswap][0],
buf_send,pbc_flag[iswap][0],pbc[iswap][0]);
compute->unpack_comm(recvnum[iswap][0],firstrecv[iswap][0],buf_send);
}
}
}
/* ----------------------------------------------------------------------
reverse communication invoked by a Compute
n = constant number of datums per atom
------------------------------------------------------------------------- */
void CommTiled::reverse_comm_compute(Compute *compute)
{
int i,irecv,n;
MPI_Status status;
for (int iswap = nswap-1; iswap >= 0; iswap--) {
if (sendproc[iswap][0] != me) {
for (i = 0; i < nsendproc[iswap]; i++)
MPI_Irecv(&buf_recv[reverse_recv_offset[iswap][i]],
size_reverse_recv[iswap][i],MPI_DOUBLE,
sendproc[iswap][i],0,world,&requests[i]);
for (i = 0; i < nrecvproc[iswap]; i++) {
n = compute->pack_reverse_comm(recvnum[iswap][i],firstrecv[iswap][i],
buf_send);
MPI_Send(buf_send,n*recvnum[iswap][i],MPI_DOUBLE,
recvproc[iswap][i],0,world);
}
for (i = 0; i < nsendproc[iswap]; i++) {
MPI_Waitany(nsendproc[iswap],requests,&irecv,&status);
compute->
unpack_reverse_comm(sendnum[iswap][irecv],sendlist[iswap][irecv],
&buf_recv[reverse_recv_offset[iswap][irecv]]);
}
} else {
n = compute->pack_reverse_comm(recvnum[iswap][0],firstrecv[iswap][0],
buf_send);
compute->unpack_reverse_comm(sendnum[iswap][0],sendlist[iswap][0],
buf_send);
}
}
}
/* ----------------------------------------------------------------------
forward communication invoked by a Dump
n = constant number of datums per atom
------------------------------------------------------------------------- */
void CommTiled::forward_comm_dump(Dump *dump)
{
int i,irecv,n;
MPI_Status status;
for (int iswap = 0; iswap < nswap; iswap++) {
if (sendproc[iswap][0] != me) {
for (i = 0; i < nrecvproc[iswap]; i++)
MPI_Irecv(&buf_recv[forward_recv_offset[iswap][i]],
size_forward_recv[iswap][i],
MPI_DOUBLE,recvproc[iswap][i],0,world,&requests[i]);
for (i = 0; i < nsendproc[iswap]; i++) {
n = dump->pack_comm(sendnum[iswap][i],sendlist[iswap][i],
buf_send,pbc_flag[iswap][i],pbc[iswap][i]);
MPI_Send(buf_send,n*sendnum[iswap][i],MPI_DOUBLE,
sendproc[iswap][i],0,world);
}
for (i = 0; i < nrecvproc[iswap]; i++) {
MPI_Waitany(nrecvproc[iswap],requests,&irecv,&status);
dump->unpack_comm(recvnum[iswap][irecv],firstrecv[iswap][irecv],
&buf_recv[forward_recv_offset[iswap][irecv]]);
}
} else {
n = dump->pack_comm(sendnum[iswap][0],sendlist[iswap][0],
buf_send,pbc_flag[iswap][0],pbc[iswap][0]);
dump->unpack_comm(recvnum[iswap][0],firstrecv[iswap][0],buf_send);
}
}
}
/* ----------------------------------------------------------------------
reverse communication invoked by a Dump
n = constant number of datums per atom
------------------------------------------------------------------------- */
void CommTiled::reverse_comm_dump(Dump *dump)
{
int i,irecv,n;
MPI_Status status;
for (int iswap = nswap-1; iswap >= 0; iswap--) {
if (sendproc[iswap][0] != me) {
for (i = 0; i < nsendproc[iswap]; i++)
MPI_Irecv(&buf_recv[reverse_recv_offset[iswap][i]],
size_reverse_recv[iswap][i],MPI_DOUBLE,
sendproc[iswap][i],0,world,&requests[i]);
for (i = 0; i < nrecvproc[iswap]; i++) {
n = dump->pack_reverse_comm(recvnum[iswap][i],firstrecv[iswap][i],
buf_send);
MPI_Send(buf_send,n*recvnum[iswap][i],MPI_DOUBLE,
recvproc[iswap][i],0,world);
}
for (i = 0; i < nsendproc[iswap]; i++) {
MPI_Waitany(nsendproc[iswap],requests,&irecv,&status);
dump->unpack_reverse_comm(sendnum[iswap][irecv],sendlist[iswap][irecv],
&buf_recv[reverse_recv_offset[iswap][irecv]]);
}
} else {
n = dump->pack_reverse_comm(recvnum[iswap][0],firstrecv[iswap][0],
buf_send);
dump->unpack_reverse_comm(sendnum[iswap][0],sendlist[iswap][0],buf_send);
}
}
}
/* ----------------------------------------------------------------------
forward communication of N values in array
------------------------------------------------------------------------- */
void CommTiled::forward_comm_array(int n, double **array)
{
}
/* ----------------------------------------------------------------------
exchange info provided with all 6 stencil neighbors
------------------------------------------------------------------------- */
int CommTiled::exchange_variable(int n, double *inbuf, double *&outbuf)
{
int nrecv = n;
return nrecv;
}
/* ----------------------------------------------------------------------
realloc the size of the send buffer as needed with BUFFACTOR and bufextra
if flag = 1, realloc
if flag = 0, don't need to realloc with copy, just free/malloc
------------------------------------------------------------------------- */
void CommTiled::grow_send(int n, int flag)
{
maxsend = static_cast<int> (BUFFACTOR * n);
if (flag)
memory->grow(buf_send,maxsend+bufextra,"comm:buf_send");
else {
memory->destroy(buf_send);
memory->create(buf_send,maxsend+bufextra,"comm:buf_send");
}
}
/* ----------------------------------------------------------------------
free/malloc the size of the recv buffer as needed with BUFFACTOR
------------------------------------------------------------------------- */
void CommTiled::grow_recv(int n)
{
maxrecv = static_cast<int> (BUFFACTOR * n);
memory->destroy(buf_recv);
memory->create(buf_recv,maxrecv,"comm:buf_recv");
}
/* ----------------------------------------------------------------------
realloc the size of the iswap sendlist as needed with BUFFACTOR
------------------------------------------------------------------------- */
void CommTiled::grow_list(int iswap, int iwhich, int n)
{
maxsendlist[iswap][iwhich] = static_cast<int> (BUFFACTOR * n);
memory->grow(sendlist[iswap][iwhich],maxsendlist[iswap][iwhich],
"comm:sendlist[iswap]");
}
/* ----------------------------------------------------------------------
return # of bytes of allocated memory
------------------------------------------------------------------------- */
bigint CommTiled::memory_usage()
{
bigint bytes = 0;
return bytes;
}