1 #ifndef DDMD_GROUP_STORAGE_TPP 2 #define DDMD_GROUP_STORAGE_TPP 11 #include "GroupStorage.h" 12 #include "AtomStorage.h" 13 #include <util/format/Int.h> 14 #include <util/mpi/MpiLoader.h> 15 #include <ddMd/communicate/GroupDistributor.tpp> 16 #include <ddMd/communicate/GroupCollector.tpp> 39 { emptyGroups_.reserve(128); }
55 distributor_.associate(domain, atomStorage, *
this, buffer);
56 collector_.associate(domain, *
this, buffer);
76 read<int>(in,
"capacity", capacity_);
77 read<int>(in,
"totalCapacity", totalCapacity_);
87 loadParameter<int>(ar,
"capacity", capacity_);
88 loadParameter<int>(ar,
"totalCapacity", totalCapacity_);
92 loader.
load(maxNGroupLocal_);
93 maxNGroup_.
set(maxNGroupLocal_);
104 int max = maxNGroup_.
value();
114 groups_.allocate(capacity_);
115 reservoir_.allocate(capacity_);
116 groupSet_.allocate(groups_);
117 groupPtrs_.allocate(totalCapacity_);
120 for (
int i = capacity_ - 1; i >=0; --i) {
121 reservoir_.push(groups_[i]);
125 for (
int i = 0; i < totalCapacity_; ++i) {
141 UTIL_THROW(
"Unregistered newPtr_ still active");
142 newPtr_ = &reservoir_.pop();
157 reservoir_.push(*newPtr_);
172 int groupId = newPtr_->id();
173 if (groupId < 0 || groupId >= totalCapacity_) {
174 Log::file() <<
"groupId = " << groupId << std::endl;
177 if (groupPtrs_[groupId] != 0) {
178 UTIL_THROW(
"Group with specified id is already present");
182 groupSet_.append(*newPtr_);
183 groupPtrs_[groupId] = newPtr_;
189 if (groupSet_.size() > maxNGroupLocal_) {
190 maxNGroupLocal_ = groupSet_.size();
212 int groupId = groupPtr->
id();
213 if (groupId < 0 || groupId >= totalCapacity_) {
214 Log::file() <<
"Group id = " << groupId << std::endl;
216 }
else if (groupPtrs_[groupId] == 0) {
217 UTIL_THROW(
"Group does not exist on this processor");
219 reservoir_.push(*groupPtr);
220 groupSet_.remove(*groupPtr);
221 groupPtrs_[groupId] = 0;
233 while (groupSet_.size() > 0) {
234 groupPtr = &groupSet_.pop();
235 groupId = groupPtr->
id();
236 groupPtrs_[groupId] = 0;
238 reservoir_.push(*groupPtr);
241 if (groupSet_.size() != 0) {
242 UTIL_THROW(
"Nonzero ghostSet size at end of clearGhosts");
257 if (
size() + reservoir_.size() != capacity_)
258 UTIL_THROW(
"nGroup + reservoir size != local capacity");
264 for (i = 0; i < totalCapacity_ ; ++i) {
268 if (ptr->
id() != i) {
279 ptr =
find(iter->id());
281 UTIL_THROW(
"Unable to find local group returned by iterator");
282 if (ptr != iter.
get())
302 if (nTotal_.
isSet())
return;
310 for ( ; iterator.
notEnd(); ++iterator) {
311 atomPtr = iterator->atomPtr(0);
322 communicator.Reduce(&nLocal, &nTot, 1,
323 MPI::INT, MPI::SUM, 0);
324 if (communicator.Get_rank() !=0) {
345 communicator.Allreduce(&maxNGroupLocal_, &maxNGroupGlobal, 1,
347 maxNGroup_.
set(maxNGroupGlobal);
348 maxNGroupLocal_ = maxNGroupGlobal;
350 maxNGroup_.
set(maxNGroupLocal_);
372 out <<
"GroupStorage<" << N <<
">" << std::endl;
373 out <<
"NGroup: max, capacity " 375 <<
Int(capacity_, 10)
385 MPI::Intracomm& communicator,
404 for (
begin(groupIter); groupIter.
notEnd(); ++groupIter) {
407 for (i = 0; i < N; ++i) {
408 atomId = groupIter->atomId(i);
412 atomPtr = groupIter->atomPtr(i);
414 if (atomPtr != atomMap.
find(atomId)) {
415 UTIL_THROW(
"Inconsistent non-null atom pointer in Group");
423 atomPtr = atomMap.
find(atomId);
438 if (hasGhosts && (nAtom + nGhost) < N) {
453 const int source = 0;
454 communicator.Reduce(&nAtomGroup, &nAtomGroupTotal, 1,
455 MPI::INT, MPI::SUM, source);
456 if (communicator.Get_rank() == source) {
457 if (!nTotal_.
isSet()) {
460 if (nAtomGroupTotal != N*
nTotal()) {
461 Log::file() <<
"nAtomGroupTotal = " << nAtomGroupTotal << std::endl;
463 UTIL_THROW(
"Discrepancy in number of local atoms in Group objects");
500 template <
int N>
void 509 int nIn, nOut, i, j, k;
515 for ( ; groupIter.
notEnd(); ++groupIter) {
516 groupIter->plan().clearFlags();
518 isComplete = (groupIter->nPtr() == N);
524 for (j = 0; j < 2; ++j) {
531 for (k = 0; k < N; ++k) {
532 atomPtr = groupIter->atomPtr(k);
534 coordinate = atomPtr->
position()[i];
537 assert(inner(i, j) > bound(i, j));
538 if (coordinate < inner(i, j)) {
541 if (coordinate > outer(i, j)) {
545 assert(inner(i, j) < bound(i, j));
546 if (coordinate > inner(i, j)) {
549 if (coordinate < outer(i, j)) {
561 if (nOut > 0 && nIn > 0) {
565 groupIter->plan().setGhost(i, j);
567 groupIter->plan().clearGhost(i, j);
573 if (groupIter->plan().ghost(i, 0) && groupIter->plan().ghost(i, 1)) {
574 Log::file() <<
"Direction " << i << std::endl;
575 Log::file() <<
"Inner / outer (j=0) = " << inner(i,0)
576 <<
" " << outer(i, 0) << std::endl;
577 Log::file() <<
"Inner / outer (j=1) = " << inner(i,1)
578 <<
" " << outer(i, 1) << std::endl;
579 for (k = 0; k < N; ++k) {
580 atomPtr = groupIter->atomPtr(k);
582 coordinate = atomPtr->
position()[i];
594 UTIL_THROW(
"Group spans both upper and lower boundaries");
606 for (j = 0; j < 2; ++j) {
607 groupIter->plan().setGhost(i, j);
615 for (k = 0; k < N; ++k) {
616 atomPtr = groupIter->atomPtr(k);
619 groupIter->clearAtomPtr(k);
646 emptyGroups_.clear();
651 for ( ; groupIter.
notEnd(); ++groupIter) {
654 for (k = 0; k < N; ++k) {
655 atomPtr = groupIter->atomPtr(k);
659 groupIter->clearAtomPtr(k);
666 emptyGroups_.append(*groupIter);
669 groupIter->pack(buffer);
675 int nEmpty = emptyGroups_.size();
676 for (
int k = 0; k < nEmpty; ++k) {
677 remove(&(emptyGroups_[k]));
695 newGroupPtr->
unpack(buffer);
696 groupId = newGroupPtr->
id();
697 oldGroupPtr =
find(groupId);
709 #endif // endif ifdef UTIL_MPI 731 template <
int N>
void 743 for ( ; groupIter.
notEnd(); ++groupIter) {
746 #ifdef DDMD_GROUP_STORAGE_DEBUG 751 for (k = 0; k < N; ++k) {
752 atomPtr = groupIter->atomPtr(k);
753 atomId = groupIter->atomId(k);
755 if (atomPtr != atomMap.
find(atomId)) {
764 atomPtr = atomMap.
find(atomId);
767 UTIL_THROW(
"Missing pointer to local atom in group");
772 assert(nAtom == groupIter->nPtr());
776 #endif // ifdef DDMD_GROUP_STORAGE_DEBUG 777 #endif // ifdef UTIL_DEBUG 780 nAtom = groupIter->nPtr();
784 for (j = 0; j < 2; ++j) {
785 if (groupIter->plan().ghost(i, j)) {
786 for (k = 0; k < N; ++k) {
787 atomPtr = groupIter->atomPtr(k);
790 planPtr = &atomPtr->
plan();
791 if (!planPtr->ghost(i, j)) {
793 sendArray(i, j).append(*atomPtr);
815 for (
begin(groupIter); groupIter.
notEnd(); ++groupIter) {
816 nAtom = groupIter->nPtr();
820 UTIL_THROW(
"Incomplete group after search for ghosts");
void setGhost(int i, int j)
Set ghost flag for direction i, j (set true).
void computeNTotal(MPI::Intracomm &communicator)
Compute and store the number of distinct groups on all processors.
bool beginRecvBlock()
Begin to receive a block from the recv buffer.
Group< N > * newPtr()
Returns an address available for addition of a new Group.
const int Dimension
Dimensionality of space.
void initialize(int capacity, int totalCapacity)
Set parameters, allocate memory and initialize.
virtual void findGhosts(AtomStorage &atomStorage)
Find all ghost members of groups.
GroupStorage()
Default constructor.
void set(const T &value)
Set the value and mark as set.
virtual void markGhosts(AtomStorage &atomStorage, FMatrix< GPArray< Atom >, Dimension, 2 > &sendArray, IntVector &gridFlags)
Set ghost communication flags for all atoms in incomplete groups.
void unpack(Buffer &buffer)
Unpack a Group from the recv buffer.
bool isSet() const
Is this object set (is the value known)?
bool exchange(int i, int j) const
Get bool exchange flag for direction i, j.
Vector & position()
Get position Vector by reference.
void add()
Complete addition of a new Group.
void beginSendBlock(int sendType)
Initialize a data block.
virtual void save(Serializable::OArchive &ar)
Save internal state to an archive.
Associative container for finding atoms identified by integer id.
bool isValid()
Return true if the container is valid, or throw an Exception.
virtual void readParameters(std::istream &in)
Read parameters, allocate memory and initialize.
A point particle in an MD simulation.
Parallel domain decomposition (DD) MD simulation.
void associate(Domain &domain, AtomStorage &atomStorage, Buffer &buffer)
Create associations for distributor and collector members.
void unsetNTotal()
Mark nTotal as unknown.
void clearStatistics()
Clear statistical accumulators (call on all processors).
int capacity() const
Return capacity for groups on this processor.
Saving / output archive for binary ostream.
int findGroupGhostAtoms(Group< N > &group) const
Set handles to ghost atoms in a Group<N> object.
const T & value() const
Return value (if set).
virtual void computeStatistics(MPI::Intracomm &communicator)
Compute statistics (reduce from all processors).
#define UTIL_THROW(msg)
Macro for throwing an Exception, reporting function, file and line number.
void clearGroups()
Remove all groups.
bool isGhost() const
Is this atom a ghost?
~GroupStorage()
Destructor.
void outputStatistics(std::ostream &out)
Output statistics.
virtual void markSpanningGroups(FMatrix< double, Dimension, 2 > &bound, FMatrix< double, Dimension, 2 > &inner, FMatrix< double, Dimension, 2 > &outer, IntVector &gridFlags)
Find and mark groups that span boundaries.
Iterator for all Group < N > objects owned by a GroupStorage< N >.
void remove(Group< N > *groupPtr)
Remove a specific Group.
bool notEnd() const
Is the current pointer not at the end of the PArray?
Group< N > * get() const
Return a pointer to the current data.
Utility classes for scientific computation.
void load(Data &value)
Load and broadcast a single Data value.
const AtomMap & map() const
Return the AtomMap by const reference.
Const iterator for all Group < N > objects owned by a GroupStorage < N >.
Wrapper for an int, for formatted ostream output.
A container for all the Group<N> objects on this processor.
int recvSize() const
Number of unread items left in current recv block.
Atom * find(int atomId) const
Return pointer to Atom with specified id.
void unset()
Unset the value (mark as unknown).
virtual void pack(int i, int j, Buffer &buffer)
Pack groups for exchange.
A container for all the atoms and ghost atoms on this processor.
void begin(GroupIterator< N > &iterator)
Set iterator to beginning of the set of groups.
int findGroupLocalAtoms(Group< N > &group) const
Set handles to local atoms in a Group<N> object.
int totalCapacity() const
Return maximum allowed number of groups on all processors.
int totalAtomCapacity() const
Return maximum number of atoms on all processors.
virtual void unpack(Buffer &buffer, AtomStorage &atomStorage)
Unpack groups from buffer and locate available atoms.
Buffer for interprocessor communication.
Decomposition of the system into domains associated with processors.
static std::ostream & file()
Get log ostream by reference.
int nTotal() const
Return total number of distinct groups on all processors.
bool notEnd() const
Is the current pointer not at the end of the array?
Saving archive for binary istream.
Provides methods for MPI-aware loading of data from input archive.
void endSendBlock(bool isComplete=true)
Finalize a block in the send buffer.
An IntVector is an integer Cartesian vector.
A group of covalently interacting atoms.
virtual void loadParameters(Serializable::IArchive &ar)
Load internal state from an archive.
An automatically growable PArray.
int id() const
Get the global id for this group.
Plan & plan()
Get communication plan by reference.
void endRecvBlock()
Finish processing a block in the recv buffer.
void returnPtr()
Reverts a transaction begun by the newPtr() function.
int size() const
Return current number of groups on this processor.
void setId(int id)
Set the global id for this group.
Group< N > * find(int id) const
Find local Group<N> indexed by global id.