11 #include <ddMd/chemistry/Atom.h> 12 #include <ddMd/chemistry/Group.h> 13 #include <ddMd/storage/AtomStorage.h> 14 #include <ddMd/storage/AtomIterator.h> 15 #include <ddMd/storage/GhostIterator.h> 16 #include <ddMd/storage/GroupExchanger.h> 17 #include <util/format/Dbl.h> 48 { groupExchangers_.reserve(8); }
63 boundaryPtr_ = &boundary;
64 atomStoragePtr_ = &atomStorage;
72 { groupExchangers_.append(groupExchanger); }
81 UTIL_THROW(
"Buffer must be allocated before Exchanger");
89 for (j = 0; j < 2; ++j) {
90 sendArray_(i, j).reserve(sendRecvCapacity);
91 recvArray_(i, j).reserve(sendRecvCapacity);
100 { pairCutoff_ = pairCutoff; }
109 UTIL_THROW(
"Error: Coordinates are Cartesian on entry to exchange");
201 void Exchanger::exchangeAtoms()
205 double bound, slabWidth;
206 double coordinate, rshift;
210 int i, j, jc, ip, jp, k, source, dest, nSend;
217 slabWidth = pairCutoff_/lengths[i];
218 for (j = 0; j < 2; ++j) {
222 bound_(i, j) = bound;
224 inner_(i,j) = bound + slabWidth;
225 outer_(i, j)= bound - slabWidth;
227 inner_(i, j) = bound - slabWidth;
228 outer_(i, j) = bound + slabWidth;
230 sendArray_(i, j).clear();
240 atomStoragePtr_->
begin(atomIter);
241 for ( ; atomIter.
notEnd(); ++atomIter) {
243 planPtr = &atomIter->plan();
251 coordinate = atomIter->position()[i];
254 for (j = 0; j < 2; ++j) {
264 if (coordinate < bound_(i, j)) {
269 if (coordinate > outer_(i, j)) {
274 if (coordinate < inner_(i, j)) {
280 if (coordinate > bound_(i, j)) {
285 if (coordinate < outer_(i, j)) {
290 if (coordinate > inner_(i, j)) {
302 if (isGhost && isHome) {
304 for (j = 0; j < 2; ++j) {
305 if (planPtr->
ghost(i, j)) {
306 sendArray_(i, j).append(*atomIter);
332 for (k = 0; k < groupExchangers_.size(); ++k) {
333 groupExchangers_[k].markSpanningGroups(bound_, inner_, outer_,
336 stamp(INIT_GROUP_PLAN);
343 #ifdef DDMD_EXCHANGER_DEBUG 346 int myRank = domainPtr_->
gridRank();
350 for (k = 0; k < groupExchangers_.size(); ++k) {
351 groupExchangers_[k].isValid(*atomStoragePtr_,
363 for (j = 0; j < 2; ++j) {
372 shift = domainPtr_->
shift(i, j);
373 rshift = double(shift);
384 atomStoragePtr_->
begin(atomIter);
385 for ( ; atomIter.
notEnd(); ++atomIter) {
388 coordinate = atomIter->position()[i];
389 #ifdef DDMD_EXCHANGER_DEBUG 393 choose = (coordinate < bound);
395 choose = (coordinate > bound);
397 assert(choose == atomIter->plan().exchange(i, j));
402 if (atomIter->plan().exchange(i, j)) {
406 sentAtoms_.append(*atomIter);
407 atomIter->packAtom(*bufferPtr_);
413 #ifdef DDMD_EXCHANGER_DEBUG 415 assert(coordinate > -1.0*fabs(rshift));
416 assert(coordinate < 2.0*fabs(rshift));
422 atomIter->position()[i] += rshift;
426 coordinate = atomIter->position()[i];
427 assert(coordinate >= domainPtr_->
domainBound(i, 0));
428 assert(coordinate < domainPtr_->domainBound(i, 1));
433 assert(!atomIter->plan().ghost(i, j));
437 if (j == 0 && atomIter->position()[i] > inner_(i, jc)) {
438 assert(atomIter->plan().ghost(i, 1));
440 if (j == 1 && atomIter->position()[i] < inner_(i, jc)) {
441 assert(atomIter->plan().ghost(i, 0));
472 for (k = 0; k < groupExchangers_.size(); ++k) {
473 groupExchangers_[k].pack(i, j, *bufferPtr_);
478 nSend = sentAtoms_.size();
479 for (k = 0; k < nSend; ++k) {
487 stamp(SEND_RECV_ATOMS);
491 while (bufferPtr_->
recvSize() > 0) {
494 planPtr = &atomPtr->
plan();
504 coordinate = atomPtr->
position()[i];
505 assert(coordinate > domainPtr_->
domainBound(i, 0));
506 assert(coordinate < domainPtr_->domainBound(i, 1));
509 assert(!planPtr->
ghost(i, j));
511 assert(planPtr->
ghost(i, 1)
512 == (coordinate > inner_(i, 1)));
514 assert(planPtr->
ghost(i, 0)
515 == (coordinate < inner_(i, 0)));
521 if (i < Dimension - 1) {
523 if (gridFlags_[ip]) {
524 for (jp = 0; jp < 2; ++jp) {
536 for (jp = 0; jp < 2; ++jp) {
537 if (planPtr->
ghost(ip, jp)) {
538 sendArray_(ip, jp).append(*atomPtr);
546 assert(bufferPtr_->
recvSize() == 0);
550 for (k = 0; k < groupExchangers_.size(); ++k) {
551 groupExchangers_[k].unpack(*bufferPtr_, *atomStoragePtr_);
553 stamp(UNPACK_GROUPS);
556 #endif // ifdef UTIL_MPI 571 #ifdef DDMD_EXCHANGER_DEBUG 575 assert(nAtomTotal = atomStoragePtr_->
nAtomTotal());
578 for (k = 0; k < groupExchangers_.size(); ++k) {
579 groupExchangers_[k].isValid(*atomStoragePtr_,
582 #endif // ifdef DDMD_EXCHANGER_DEBUG 583 #endif // ifdef UTIL_DEBUG 586 for (k = 0; k < groupExchangers_.size(); ++k) {
587 groupExchangers_[k].markGhosts(*atomStoragePtr_, sendArray_,
590 stamp(MARK_GROUP_GHOSTS);
600 void Exchanger::exchangeGhosts()
608 if (atomStoragePtr_->
nGhost() != 0) {
615 int i, j, ip, jp, k, source, dest, shift, size;
619 for (j = 0; j < 2; ++j) {
620 recvArray_(i, j).clear();
626 #ifdef DDMD_EXCHANGER_DEBUG 632 for (j = 0; j < 2; ++j) {
633 sendCounter(i, j) = 0;
638 atomStoragePtr_->
begin(localIter);
639 for ( ; localIter.
notEnd(); ++localIter) {
640 planPtr = &localIter->plan();
642 for (j = 0; j < 2; ++j) {
643 if (planPtr->
ghost(i, j)) {
651 for (j = 0; j < 2; ++j) {
652 if (sendCounter(i, j) != sendArray_(i, j).size()) {
658 #endif // ifdef DDMD_EXCHANGER_DEBUG 659 #endif // ifdef UTIL_DEBUG 660 stamp(INIT_SEND_ARRAYS);
666 for (j = 0; j < 2; ++j) {
672 shift = domainPtr_->
shift(i, j);
683 size = sendArray_(i, j).size();
684 for (k = 0; k < size; ++k) {
686 sendPtr = &sendArray_(i, j)[k];
698 recvArray_(i, j).append(*atomPtr);
713 coordinate = atomPtr->
position()[i];
715 assert(coordinate > bound_(i, 1));
717 assert(coordinate < bound_(i, 0));
722 if (i < Dimension - 1) {
724 for (jp = 0; jp < 2; ++jp) {
726 sendArray_(ip, jp).append(*atomPtr);
746 stamp(SEND_RECV_GHOSTS);
750 while (bufferPtr_->
recvSize() > 0) {
757 recvArray_(i, j).append(*atomPtr);
766 if (i < Dimension - 1) {
768 for (jp = 0; jp < 2; ++jp) {
770 sendArray_(ip, jp).append(*atomPtr);
778 coordinate = atomPtr->
position()[i];
780 assert(coordinate > bound_(i, 1));
782 assert(coordinate < bound_(i, 0));
788 stamp(UNPACK_GHOSTS);
791 #endif // ifdef UTIL_MPI 799 for (k = 0; k < groupExchangers_.size(); ++k) {
800 groupExchangers_[k].findGhosts(*atomStoragePtr_);
804 #ifdef DDMD_EXCHANGER_DEBUG 806 for (k = 0; k < groupExchangers_.size(); ++k) {
807 groupExchangers_[k].isValid(*atomStoragePtr_,
810 #endif // ifdef DDMD_EXCHANGER_DEBUG 811 #endif // ifdef UTIL_DEBUG 813 stamp(FIND_GROUP_GHOSTS);
825 UTIL_THROW(
"Error: Coordinates not Cartesian on entry to update");
829 int i, j, k, source, dest, size, shift;
832 for (j = 0; j < 2; ++j) {
835 shift = domainPtr_->
shift(i, j);
842 size = sendArray_(i, j).size();
843 for (k = 0; k < size; ++k) {
844 atomPtr = &sendArray_(i, j)[k];
854 stamp(SEND_RECV_UPDATE);
858 size = recvArray_(i, j).size();
859 for (k = 0; k < size; ++k) {
860 atomPtr = &recvArray_(i, j)[k];
867 stamp(UNPACK_UPDATE);
874 size = sendArray_(i, j).size();
875 assert(size == recvArray_(i, j).size());
876 for (k = 0; k < size; ++k) {
877 atomPtr = &recvArray_(i, j)[k];
880 atomPtr->
position() = sendArray_(i, j)[k].position();
906 int i, j, k, source, dest, size;
909 for (j = 1; j >= 0; --j) {
916 size = recvArray_(i, j).size();
917 for (k = 0; k < size; ++k) {
918 atomPtr = &recvArray_(i, j)[k];
925 source = domainPtr_->
destRank(i, j);
929 stamp(SEND_RECV_FORCE);
933 size = sendArray_(i, j).size();
934 for (k = 0; k < size; ++k) {
935 atomPtr = &sendArray_(i, j)[k];
946 size = recvArray_(i, j).size();
947 assert(size == sendArray_(i, j).size());
948 for (k = 0; k < size; ++k) {
949 atomPtr = &sendArray_(i, j)[k];
950 atomPtr->
force() += recvArray_(i, j)[k].force();
969 UTIL_THROW(
"May be called only on domain master");
987 double factor1 = 1.0/double(nStep);
988 double factor2 = double(nProc)/(double(nStep)*double(nAtomTot));
989 double factor3 = 100.0/time;
995 <<
" Percent (%)" << std::endl;
997 double atomExchangeT = 0.0;
998 double ghostExchangeT = 0.0;
999 double updateT = 0.0;
1002 double AtomPlanT = timer_.
time(Exchanger::ATOM_PLAN);
1003 atomExchangeT += AtomPlanT;
1005 <<
Dbl(AtomPlanT*factor1, 12, 6) <<
" " 1006 <<
Dbl(AtomPlanT*factor2, 12, 6) <<
" " 1007 <<
Dbl(AtomPlanT*factor3, 12, 6,
true) << std::endl;
1008 double InitGroupPlanT = timer_.
time(Exchanger::INIT_GROUP_PLAN);
1009 atomExchangeT += InitGroupPlanT;
1010 out <<
"InitGroupPlan " 1011 <<
Dbl(InitGroupPlanT*factor1, 12, 6) <<
" " 1012 <<
Dbl(InitGroupPlanT*factor2, 12, 6) <<
" " 1013 <<
Dbl(InitGroupPlanT*factor3, 12, 6,
true) << std::endl;
1014 double ClearGhostsT = timer_.
time(Exchanger::CLEAR_GHOSTS);
1015 atomExchangeT += ClearGhostsT;
1016 out <<
"ClearGhosts " 1017 <<
Dbl(ClearGhostsT*factor1, 12, 6) <<
" " 1018 <<
Dbl(ClearGhostsT*factor2, 12, 6) <<
" " 1019 <<
Dbl(ClearGhostsT*factor3, 12, 6,
true) << std::endl;
1020 double PackAtomsT = timer_.
time(Exchanger::PACK_ATOMS);
1021 atomExchangeT += PackAtomsT;
1023 <<
Dbl(PackAtomsT*factor1, 12, 6) <<
" " 1024 <<
Dbl(PackAtomsT*factor2, 12, 6) <<
" " 1025 <<
Dbl(PackAtomsT*factor3, 12, 6,
true) << std::endl;
1026 double PackGroupsT = timer_.
time(Exchanger::PACK_GROUPS);
1027 atomExchangeT += PackGroupsT;
1028 out <<
"PackGroups " 1029 <<
Dbl(PackGroupsT*factor1, 12, 6) <<
" " 1030 <<
Dbl(PackGroupsT*factor2, 12, 6) <<
" " 1031 <<
Dbl(PackGroupsT*factor3, 12, 6,
true) << std::endl;
1032 double RemoveAtomsT = timer_.
time(Exchanger::REMOVE_ATOMS);
1033 atomExchangeT += RemoveAtomsT;
1034 out <<
"RemoveAtoms " 1035 <<
Dbl(RemoveAtomsT*factor1, 12, 6) <<
" " 1036 <<
Dbl(RemoveAtomsT*factor2, 12, 6) <<
" " 1037 <<
Dbl(RemoveAtomsT*factor3, 12, 6,
true) << std::endl;
1038 double SendRecvAtomsT = timer_.
time(Exchanger::SEND_RECV_ATOMS);
1039 atomExchangeT += SendRecvAtomsT;
1040 out <<
"SendRecvAtoms " 1041 <<
Dbl(SendRecvAtomsT*factor1, 12, 6) <<
" " 1042 <<
Dbl(SendRecvAtomsT*factor2, 12, 6) <<
" " 1043 <<
Dbl(SendRecvAtomsT*factor3, 12, 6,
true) << std::endl;
1044 double UnpackAtomsT = timer_.
time(Exchanger::UNPACK_ATOMS);
1045 atomExchangeT += UnpackAtomsT;
1046 out <<
"UnpackAtoms " 1047 <<
Dbl(UnpackAtomsT*factor1, 12, 6) <<
" " 1048 <<
Dbl(UnpackAtomsT*factor2, 12, 6) <<
" " 1049 <<
Dbl(UnpackAtomsT*factor3, 12, 6,
true) << std::endl;
1050 double UnpackGroupsT = timer_.
time(Exchanger::UNPACK_GROUPS);
1051 atomExchangeT += UnpackGroupsT;
1052 out <<
"UnpackGroups " 1053 <<
Dbl(UnpackGroupsT*factor1, 12, 6) <<
" " 1054 <<
Dbl(UnpackGroupsT*factor2, 12, 6) <<
" " 1055 <<
Dbl(UnpackGroupsT*factor3, 12, 6,
true) << std::endl;
1056 double MarkGroupGhostsT = timer_.
time(Exchanger::MARK_GROUP_GHOSTS);
1057 atomExchangeT += MarkGroupGhostsT;
1058 out <<
"MarkGroupGhosts " 1059 <<
Dbl(MarkGroupGhostsT*factor1, 12, 6) <<
" " 1060 <<
Dbl(MarkGroupGhostsT*factor2, 12, 6) <<
" " 1061 <<
Dbl(MarkGroupGhostsT*factor3, 12, 6,
true) << std::endl;
1062 double SendArraysT = timer_.
time(Exchanger::INIT_SEND_ARRAYS);
1063 atomExchangeT += SendArraysT;
1064 out <<
"SendArrays " 1065 <<
Dbl(SendArraysT*factor1, 12, 6) <<
" " 1066 <<
Dbl(SendArraysT*factor2, 12, 6) <<
" " 1067 <<
Dbl(SendArraysT*factor3, 12, 6,
true) << std::endl;
1068 out <<
"Atom Exchange (Tot) " 1069 <<
Dbl(atomExchangeT*factor1, 12, 6) <<
" " 1070 <<
Dbl(atomExchangeT*factor2, 12, 6) <<
" " 1071 <<
Dbl(atomExchangeT*factor3, 12, 6,
true) << std::endl;
1075 double PackGhostsT = timer_.
time(Exchanger::PACK_GHOSTS);
1076 ghostExchangeT += PackGhostsT;
1077 out <<
"PackGhosts " 1078 <<
Dbl(PackGhostsT*factor1, 12, 6) <<
" " 1079 <<
Dbl(PackGhostsT*factor2, 12, 6) <<
" " 1080 <<
Dbl(PackGhostsT*factor3, 12, 6,
true) << std::endl;
1081 double SendRecvGhostsT = timer_.
time(Exchanger::SEND_RECV_GHOSTS);
1082 ghostExchangeT += SendRecvGhostsT;
1083 out <<
"SendRecvGhosts " 1084 <<
Dbl(SendRecvGhostsT*factor1, 12, 6) <<
" " 1085 <<
Dbl(SendRecvGhostsT*factor2, 12, 6) <<
" " 1086 <<
Dbl(SendRecvGhostsT*factor3, 12, 6,
true) << std::endl;
1087 double UnpackGhostsT = timer_.
time(Exchanger::UNPACK_GHOSTS);
1088 ghostExchangeT += UnpackGhostsT;
1089 out <<
"UnpackGhosts " 1090 <<
Dbl(UnpackGhostsT*factor1, 12, 6) <<
" " 1091 <<
Dbl(UnpackGhostsT*factor2, 12, 6) <<
" " 1092 <<
Dbl(UnpackGhostsT*factor3, 12, 6,
true) << std::endl;
1093 double FindGroupGhostsT = timer_.
time(Exchanger::FIND_GROUP_GHOSTS);
1094 ghostExchangeT += FindGroupGhostsT;
1095 out <<
"FindGroupGhosts " 1096 <<
Dbl(FindGroupGhostsT*factor1, 12, 6) <<
" " 1097 <<
Dbl(FindGroupGhostsT*factor2, 12, 6) <<
" " 1098 <<
Dbl(FindGroupGhostsT*factor3, 12, 6,
true) << std::endl;
1099 out <<
"Ghost Exchange (Tot) " 1100 <<
Dbl(ghostExchangeT*factor1, 12, 6) <<
" " 1101 <<
Dbl(ghostExchangeT*factor2, 12, 6) <<
" " 1102 <<
Dbl(ghostExchangeT*factor3, 12, 6,
true) << std::endl;
1106 double PackUpdateT = timer_.
time(Exchanger::PACK_UPDATE);
1107 updateT += PackUpdateT;
1108 out <<
"PackUpdate " 1109 <<
Dbl(PackUpdateT*factor1, 12, 6) <<
" " 1110 <<
Dbl(PackUpdateT*factor2, 12, 6) <<
" " 1111 <<
Dbl(PackUpdateT*factor3, 12, 6,
true) << std::endl;
1112 double SendRecvUpdateT = timer_.
time(Exchanger::SEND_RECV_UPDATE);
1113 updateT += SendRecvUpdateT;
1114 out <<
"SendRecvUpdate " 1115 <<
Dbl(SendRecvUpdateT*factor1, 12, 6) <<
" " 1116 <<
Dbl(SendRecvUpdateT*factor2, 12, 6) <<
" " 1117 <<
Dbl(SendRecvUpdateT*factor3, 12, 6,
true) << std::endl;
1118 double UnpackUpdateT = timer_.
time(Exchanger::UNPACK_UPDATE);
1119 updateT += UnpackUpdateT;
1120 out <<
"UnpackUpdate " 1121 <<
Dbl(UnpackUpdateT*factor1, 12, 6) <<
" " 1122 <<
Dbl(UnpackUpdateT*factor2, 12, 6) <<
" " 1123 <<
Dbl(UnpackUpdateT*factor3, 12, 6,
true) << std::endl;
1124 double LocalUpdateT = timer_.
time(Exchanger::LOCAL_UPDATE);
1125 updateT += LocalUpdateT;
1126 out <<
"LocalUpdate " 1127 <<
Dbl(LocalUpdateT*factor1, 12, 6) <<
" " 1128 <<
Dbl(LocalUpdateT*factor2, 12, 6) <<
" " 1129 <<
Dbl(LocalUpdateT*factor3, 12, 6,
true) << std::endl;
1130 out <<
"Update (Tot) " 1131 <<
Dbl(updateT*factor1, 12, 6) <<
" " 1132 <<
Dbl(updateT*factor2, 12, 6) <<
" " 1133 <<
Dbl(updateT*factor3, 12, 6,
true) << std::endl;
1137 #endif // ifdef UTIL_MPI void addNewGhost()
Register the most recent new ghost atom.
void setGhost(int i, int j)
Set ghost flag for direction i, j (set true).
bool beginRecvBlock()
Begin to receive a block from the recv buffer.
Atom * newAtomPtr()
Returns pointer an address available for a new Atom.
int typeId() const
Get atom type index.
const int Dimension
Dimensionality of space.
void update()
Update ghost atom coordinates.
A Vector is a Cartesian vector.
void unpackUpdate(Buffer &buffer)
Unpack updated ghost position from recv buffer.
int nAtomTotal() const
Get total number of atoms on all processors.
void sendRecv(MPI::Intracomm &comm, int source, int dest)
Receive from processor send and send to processor recv.
unsigned int flags() const
Return raw flags unsigned int.
int ghostCapacity() const
Maximum number of ghost atoms for which space is available.
bool isInitialized() const
Has this Domain been initialized by calling readParam?
int sourceRank(int i, int j) const
Rank of the processor from which to receive for transfer (i, j).
void setTypeId(int Id)
Set the atom type index.
void setId(int Id)
Set unique global id for this Atom.
const Vector & lengths() const
Get Vector of unit cell lengths by const reference.
An orthorhombic periodic unit cell.
int shift(int i, int j) const
Shift to be applied to sent coordinates in transfer (i, j).
void unpackForce(Buffer &buffer)
Unpack updated position of ghost Atom from recv buffer.
bool exchange(int i, int j) const
Get bool exchange flag for direction i, j.
Vector & position()
Get position Vector by reference.
bool ghost(int i, int j) const
Get ghost flag for direction i, j.
void beginSendBlock(int sendType)
Initialize a data block.
void setFlags(unsigned int flags)
Set all flags (contains all bits).
void allocate()
Allocate all required memory.
Wrapper for a double precision number, for formatted ostream output.
File containing preprocessor macros for error handling.
void clearFlags()
Clear all flags (set all to false, set flags_ = 0).
A point particle in an MD simulation.
Parallel domain decomposition (DD) MD simulation.
void unpackAtom(Buffer &buffer)
Unpack an atom from a recv buffer and receive ownership.
void setExchange(int i, int j)
Set exchange flag for direction i, j (set true).
int id() const
Get unique global index for this atom.
void addGroupExchanger(GroupExchanger &groupExchanger)
Add a GroupExchanger to an internal list.
void addNewAtom()
Finalize addition of the most recent new atom.
void copyLocalUpdate(Atom const &sendAtom)
Copies position of local atom to update this ghost atom.
int dimension(int i) const
Get grid dimension along Cartesian direction i.
MPI::Intracomm & communicator() const
Return Cartesian communicator by reference.
void setPairCutoff(double pairCutoff)
Set width of slab for ghosts.
void packForce(Buffer &buffer)
Pack update of ghost Atom force into send buffer.
void associate(const Domain &domain, const Boundary &boundary, AtomStorage &atomStorage, Buffer &buffer)
Set pointers to associated objects.
int gridRank() const
Get rank of this processor in the processor grid.
#define UTIL_THROW(msg)
Macro for throwing an Exception, reporting function, file and line number.
double time(int id) const
Get accumulated time for interval i, average per processor.
void packGhost(Buffer &buffer)
Pack a ghost Atom into a send buffer.
int nGhost() const
Return current number of ghost atoms on this processor.
bool notEnd() const
Is the current pointer not at the end of the PArray?
Utility classes for scientific computation.
void outputStatistics(std::ostream &out, double time, int nStep)
Output statistics.
int recvSize() const
Number of unread items left in current recv block.
A container for all the atoms and ghost atoms on this processor.
const Grid & grid() const
Return processor Grid by const reference.
Atom * newGhostPtr()
Returns pointer an address available for a new ghost Atom.
void packUpdate(Buffer &buffer)
Pack updated ghost position into send buffer.
void computeNAtomTotal(MPI::Intracomm &communicator)
Compute the total number of local atoms on all processors.
bool isValid() const
Return true if the container is valid, or throw an Exception.
bool isMaster() const
Is this the master processor (gridRank == 0) ?
Buffer for interprocessor communication.
Decomposition of the system into domains associated with processors.
Vector & force()
Get force Vector by reference.
void copyLocalGhost(Atom const &sendAtom)
Copies data from local atom to update this ghost atom.
Class for exchanging Atoms, Ghosts and Groups between processors.
double domainBound(int i, int j) const
Get one boundary of the domain owned by this processor.
void applyShift(Vector &r, int i, int t) const
Shift Cartesian Vector r by multiple t of a Bravais lattice vector.
bool isCartesian() const
Are atom coordinates Cartesian (true) or generalized (false)?
Interface for a GroupStorage<N> for use in Exchanger.
void clearGhost(int i, int j)
Clear ghost flag for direction i, j (set false).
void endSendBlock(bool isComplete=true)
Finalize a block in the send buffer.
bool isInitialized() const
Has this Buffer been initialized?
int destRank(int i, int j) const
Rank of the processor to which to send for transfer (i, j).
void exchange()
Exchange local atoms and ghosts.
void clearGhosts()
Clear all ghost atoms.
void unpackGhost(Buffer &buffer)
Unpack a ghost Atom from a recv buffer.
bool hasBoundary() const
Has an associated Boundary been set?
Iterator for all atoms owned by an AtomStorage.
Plan & plan()
Get communication plan by reference.
void clearSendBuffer()
Clear the send buffer.
void endRecvBlock()
Finish processing a block in the recv buffer.
void reverseUpdate()
Update ghost atom forces.
void begin(AtomIterator &iterator)
Set iterator to beginning of the set of atoms.
void removeAtom(Atom *atomPtr)
Remove a specific Atom.