diff --git a/src/comm.cpp b/src/comm.cpp index 1bb82bd8c4..bf5213af53 100644 --- a/src/comm.cpp +++ b/src/comm.cpp @@ -1518,6 +1518,61 @@ void Comm::forward_comm_array(int n, double **array) } } +/* ---------------------------------------------------------------------- + exchange info provided with all 6 stencil neighbors +------------------------------------------------------------------------- */ + +int Comm::exchange_variable(int n, double *inbuf, double *&outbuf) +{ + int nsend,nrecv,nrecv1,nrecv2; + MPI_Request request; + MPI_Status status; + + nrecv = n; + if (nrecv > maxrecv) grow_recv(nrecv); + memcpy(buf_recv,inbuf,nrecv*sizeof(double)); + + // loop over dimensions + + for (int dim = 0; dim < 3; dim++) { + + // no exchange if only one proc in a dimension + + if (procgrid[dim] == 1) continue; + + // send/recv info in both directions using same buf_recv + // if 2 procs in dimension, single send/recv + // if more than 2 procs in dimension, send/recv to both neighbors + + nsend = nrecv; + MPI_Sendrecv(&nsend,1,MPI_INT,procneigh[dim][0],0, + &nrecv1,1,MPI_INT,procneigh[dim][1],0,world,&status); + nrecv += nrecv1; + if (procgrid[dim] > 2) { + MPI_Sendrecv(&nsend,1,MPI_INT,procneigh[dim][1],0, + &nrecv2,1,MPI_INT,procneigh[dim][0],0,world,&status); + nrecv += nrecv2; + } else nrecv2 = 0; + + if (nrecv > maxrecv) grow_recv(nrecv); + + MPI_Irecv(&buf_recv[nsend],nrecv1,MPI_DOUBLE,procneigh[dim][1],0, + world,&request); + MPI_Send(buf_recv,nsend,MPI_DOUBLE,procneigh[dim][0],0,world); + MPI_Wait(&request,&status); + + if (procgrid[dim] > 2) { + MPI_Irecv(&buf_recv[nsend+nrecv1],nrecv2,MPI_DOUBLE,procneigh[dim][0],0, + world,&request); + MPI_Send(buf_recv,nsend,MPI_DOUBLE,procneigh[dim][1],0,world); + MPI_Wait(&request,&status); + } + } + + outbuf = buf_recv; + return nrecv; +} + /* ---------------------------------------------------------------------- communicate inbuf around full ring of processors with messtag nbytes = size of inbuf = n datums * nper bytes diff --git a/src/comm.h b/src/comm.h index e667ba2c32..2c72359552 100644 --- a/src/comm.h +++ b/src/comm.h @@ -63,6 +63,8 @@ class Comm : protected Pointers { virtual void reverse_comm_dump(class Dump *); // reverse comm from a Dump void forward_comm_array(int, double **); // forward comm of array + int exchange_variable(int, double *, // exchange of info on neigh stencil + double *&); void ring(int, int, void *, int, void (*)(int, char *), // ring comm void *, int self = 1); int read_lines_from_file(FILE *, int, int, char *); // read/bcast file lines diff --git a/src/force.cpp b/src/force.cpp index 04dea56633..7e8e189e84 100644 --- a/src/force.cpp +++ b/src/force.cpp @@ -485,6 +485,21 @@ Improper *Force::new_improper(const char *style, const char *suffix, int &sflag) return NULL; } +/* ---------------------------------------------------------------------- + return ptr to current improper class or hybrid sub-class if matches style +------------------------------------------------------------------------- */ + +Improper *Force::improper_match(const char *style) +{ + if (strcmp(improper_style,style) == 0) return improper; + else if (strcmp(improper_style,"hybrid") == 0) { + ImproperHybrid *hybrid = (ImproperHybrid *) bond; + for (int i = 0; i < hybrid->nstyles; i++) + if (strcmp(hybrid->keywords[i],style) == 0) return hybrid->styles[i]; + } + return NULL; +} + /* ---------------------------------------------------------------------- new kspace style ------------------------------------------------------------------------- */ diff --git a/src/force.h b/src/force.h index bd72567812..a9efb08fbf 100644 --- a/src/force.h +++ b/src/force.h @@ -93,6 +93,7 @@ class Force : protected Pointers { void create_improper(const char *, const char *suffix = NULL); class Improper *new_improper(const char *, const char *, int &); + class Improper *improper_match(const char *); void create_kspace(int, char **, const char *suffix = NULL); class KSpace *new_kspace(int, char **, const char *, int &); diff --git a/src/neighbor.cpp b/src/neighbor.cpp index c38d8db7aa..37305effca 100644 --- a/src/neighbor.cpp +++ b/src/neighbor.cpp @@ -565,11 +565,16 @@ void Neighbor::init() if (processed) continue; - // pair and half: if there is a full non-occasional non-skip list + // pair and half and newton != 2: + // if there is a full non-occasional non-skip list // change this list to half_from_full and point at the full list // parent could be copy list or pair or fix + // could remove newton != 2 check if added half_from_full_no_newton_ghost + // option in neigh_derive.cpp and below in choose_build() + // this would require full list had ghost info + // would be useful when reax/c used in hybrid mode, e.g. with airebo - if (requests[i]->pair && requests[i]->half) { + if (requests[i]->pair && requests[i]->half && requests[i]->newton != 2) { for (j = 0; j < nrequest; j++) { if (!lists[j]) continue; if (requests[j]->full && requests[j]->occasional == 0 && @@ -924,8 +929,14 @@ void Neighbor::choose_build(int index, NeighRequest *rq) else pb = &Neighbor::skip_from; } else if (rq->half_from_full) { - if (newton_pair == 0) pb = &Neighbor::half_from_full_no_newton; - else if (newton_pair == 1) pb = &Neighbor::half_from_full_newton; + if (rq->newton == 0) { + if (newton_pair == 0) pb = &Neighbor::half_from_full_no_newton; + else if (newton_pair == 1) pb = &Neighbor::half_from_full_newton; + } else if (rq->newton == 1) { + pb = &Neighbor::half_from_full_newton; + } else if (rq->newton == 2) { + pb = &Neighbor::half_from_full_no_newton; + } } else if (rq->half) { if (style == NSQ) {