Simpatico  v1.10
ddMd/storage/AtomStorage.cpp
1 /*
2 * Simpatico - Simulation Package for Polymeric and Molecular Liquids
3 *
4 * Copyright 2010 - 2017, The Regents of the University of Minnesota
5 * Distributed under the terms of the GNU General Public License.
6 */
7 
8 #include "AtomStorage.h"
9 #include "AtomIterator.h"
10 #include "ConstAtomIterator.h"
11 #include "GhostIterator.h"
12 #include "ConstGhostIterator.h"
13 #include <ddMd/chemistry/Group.h>
14 #include <util/format/Int.h>
15 #include <util/mpi/MpiLoader.h>
16 #include <util/global.h>
17 
18 namespace DdMd
19 {
20 
21  using namespace Util;
22 
23  /*
24  * Default constructor.
25  */
27  : atoms_(),
28  atomSet_(),
29  atomReservoir_(),
30  ghosts_(),
31  ghostSet_(),
32  ghostReservoir_(),
33  map_(),
34  newAtomPtr_(0),
35  newGhostPtr_(0),
36  atomCapacity_(0),
37  ghostCapacity_(0),
38  totalAtomCapacity_(0),
39  maxNAtomLocal_(0),
40  maxNGhostLocal_(0),
41  #ifdef UTIL_MPI
42  nAtomTotal_(),
43  maxNAtom_(),
44  maxNGhost_(),
45  #endif
46  locked_(false),
47  isInitialized_(false),
48  isCartesian_(false)
49  { setClassName("AtomStorage"); }
50 
51  /*
52  * Destructor.
53  */
55  {}
56 
57  /*
58  * Create associations for distributor and collector.
59  */
60  void AtomStorage::associate(Domain& domain, Boundary& boundary,
61  Buffer& buffer)
62  {
63  distributor_.associate(domain, boundary, *this, buffer);
64  collector_.associate(domain, *this, buffer);
65  }
66 
67  /*
68  * Set parameters and allocate memory.
69  */
72  {
73  atomCapacity_ = atomCapacity;
74  ghostCapacity_ = ghostCapacity;
75  totalAtomCapacity_ = totalAtomCapacity;
76  allocate();
77  }
78 
79  /*
80  * Read parameters and allocate memory.
81  */
82  void AtomStorage::readParameters(std::istream& in)
83  {
84  read<int>(in, "atomCapacity", atomCapacity_);
85  read<int>(in, "ghostCapacity", ghostCapacity_);
86  read<int>(in, "totalAtomCapacity", totalAtomCapacity_);
87  allocate();
88  }
89 
90  /*
91  * Load parameters and allocate memory (call on all processors)
92  */
94  {
95  loadParameter<int>(ar, "atomCapacity", atomCapacity_);
96  loadParameter<int>(ar, "ghostCapacity", ghostCapacity_);
97  loadParameter<int>(ar, "totalAtomCapacity", totalAtomCapacity_);
98  MpiLoader<Serializable::IArchive> loader(*this, ar);
99  loader.load(maxNAtomLocal_);
100  loader.load(maxNGhostLocal_);
101  allocate();
102  }
103 
104  /*
105  * Save parameters (call only on ioProcessor).
106  */
108  {
109  ar << atomCapacity_;
110  ar << ghostCapacity_;
111  ar << totalAtomCapacity_;
112  ar << maxNAtomLocal_;
113  ar << maxNGhostLocal_;
114  }
115 
116  /*
117  * Allocate and initialize all containers (private).
118  */
119  void AtomStorage::allocate()
120  {
121  // Precondition
122  if (isInitialized_) {
123  UTIL_THROW("AtomStorage can only be initialized once");
124  }
125 
126  atoms_.allocate(atomCapacity_);
127  atomReservoir_.allocate(atomCapacity_);
128  atomSet_.allocate(atoms_);
129  int i;
130  for (i = atomCapacity_ - 1; i >=0; --i) {
131  atomReservoir_.push(atoms_[i]);
132  }
133 
134  ghosts_.allocate(ghostCapacity_);
135  ghostReservoir_.allocate(ghostCapacity_);
136  ghostSet_.allocate(ghosts_);
137  for (i = ghostCapacity_ - 1; i >=0; --i) {
138  ghostReservoir_.push(ghosts_[i]);
139  }
140 
141  map_.allocate(totalAtomCapacity_);
142  snapshot_.allocate(atomCapacity_);
143 
144  isInitialized_ = true;
145  }
146 
147  /*
148  * Zero forces on all local atoms and optionally on ghosts.
149  */
150  void AtomStorage::zeroForces(bool zeroGhosts)
151  {
152  int factor = 2;
153 
154  // Zero forces for all local atoms
155  if (nAtom() > atomCapacity_/factor) {
156  atoms_.zeroForces();
157  // Optimization to allow sequential access
158  } else {
159  AtomIterator atomIter;
160  begin(atomIter);
161  for( ; atomIter.notEnd(); ++atomIter){
162  atomIter->force().zero();
163  }
164  }
165 
166  // If using reverse communication, zero ghost atoms
167  if (zeroGhosts && nGhost()) {
168  if (nGhost() > ghostCapacity_/factor) {
169  ghosts_.zeroForces();
170  // Optimization to allow sequential access
171  } else {
172  GhostIterator ghostIter;
173  begin(ghostIter);
174  for( ; ghostIter.notEnd(); ++ghostIter){
175  ghostIter->force().zero();
176  }
177  }
178  }
179 
180  }
181 
182  // Local atom mutators
183 
184  /*
185  * Returns address for a new local Atom.
186  */
188  {
189  // Preconditions
190  if (newAtomPtr_ != 0) {
191  UTIL_THROW("Unregistered newAtomPtr_ still active");
192  }
193  if (locked_ ) {
194  UTIL_THROW("AtomStorage is locked");
195  }
196  if (atomReservoir_.size() == 0) {
197  UTIL_THROW("Cannot pop from empty atomReservoir");
198  }
199 
200  newAtomPtr_ = &atomReservoir_.pop();
201  newAtomPtr_->clear();
202  return newAtomPtr_;
203  }
204 
205  /*
206  * Register new local Atom in internal data structures.
207  */
209  {
210  if (newAtomPtr_ == 0)
211  UTIL_THROW("No active newAtomPtr_");
212  if (locked_)
213  UTIL_THROW("AtomStorage is locked");
214 
215  // Add to containers.
216  map_.addLocal(newAtomPtr_);
217  atomSet_.append(*newAtomPtr_);
218  newAtomPtr_->setIsGhost(false);
219 
220  // De-activate new atom pointer
221  newAtomPtr_ = 0;
222 
223  // Update statistics
224  if (atomSet_.size() > maxNAtomLocal_) {
225  maxNAtomLocal_ = atomSet_.size();
226  }
227  }
228 
230  {
231  Atom* ptr = newAtomPtr();
232  ptr->setId(id);
233  addNewAtom();
234  return ptr;
235  }
236 
237  /*
238  * Remove a specific local Atom.
239  */
241  {
242  map_.removeLocal(atomPtr);
243  atomSet_.remove(*atomPtr);
244  atomReservoir_.push(*atomPtr);
245  }
246 
247  /*
248  * Remove all local atoms.
249  */
251  {
252  // Precondition
253  if (locked_) {
254  UTIL_THROW("AtomStorage is locked");
255  }
256 
257  Atom* atomPtr;
258  while (atomSet_.size() > 0) {
259  atomPtr = &atomSet_.pop();
260  map_.removeLocal(atomPtr);
261  atomReservoir_.push(*atomPtr);
262  }
263 
264  // Sanity checks
265  if (atomSet_.size() != 0) {
266  UTIL_THROW("Nonzero atomSet size at end of clearAtoms");
267  }
268  if (map_.nLocal() != 0) {
269  UTIL_THROW("Nonzero nLocal in atom map at end of clearAtoms");
270  }
271  }
272 
273  // Ghost atom mutators
274 
275  /*
276  * Return address for a new ghost Atom.
277  */
279  {
280  // Preconditions
281  if (newGhostPtr_ != 0)
282  UTIL_THROW("Unregistered newGhostPtr_ still active");
283  if (locked_ )
284  UTIL_THROW("AtomStorage is locked");
285  if (ghostReservoir_.size() == 0)
286  UTIL_THROW("Atom to pop from empty atomReservoir");
287 
288  newGhostPtr_ = &ghostReservoir_.pop();
289  newGhostPtr_->clear();
290  newGhostPtr_->setIsGhost(true);
291  return newGhostPtr_;
292  }
293 
294  /*
295  * Register new ghost Atom to internal data structures.
296  */
298  {
299  if (newGhostPtr_ == 0) {
300  UTIL_THROW("No active newGhostPtr_");
301  }
302  if (locked_) {
303  UTIL_THROW("AtomStorage is locked");
304  }
305 
306  // Add to containers
307  map_.addGhost(newGhostPtr_);
308  ghostSet_.append(*newGhostPtr_);
309  newGhostPtr_->setIsGhost(true);
310 
311  // De-activate new ghost pointer
312  newGhostPtr_ = 0;
313 
314  // Update statistics
315  if (ghostSet_.size() > maxNGhostLocal_) {
316  maxNGhostLocal_ = ghostSet_.size();
317  }
318  }
319 
321  {
322  Atom* ptr = newGhostPtr();
323  ptr->setId(id);
324  addNewGhost();
325  return ptr;
326  }
327 
328  /*
329  * Remove a specific ghost Atom.
330  */
332  {
333  // Precondition
334  if (locked_) UTIL_THROW("AtomStorage is locked");
335 
336  map_.removeGhost(atomPtr);
337  ghostSet_.remove(*atomPtr);
338  ghostReservoir_.push(*atomPtr);
339  }
340 
341  /*
342  * Remove all ghosts.
343  */
345  {
346  // Precondition
347  if (locked_)
348  UTIL_THROW("AtomStorage is locked");
349 
350  // Clear ghosts from the map
351  map_.clearGhosts(ghostSet_);
352 
353  // Transfer ghosts from the set to the reservoir
354  Atom* atomPtr;
355  while (ghostSet_.size() > 0) {
356  atomPtr = &ghostSet_.pop();
357  ghostReservoir_.push(*atomPtr);
358  }
359 
360  if (ghostSet_.size() != 0) {
361  UTIL_THROW("Nonzero ghostSet size at end of clearGhosts");
362  }
363  if (map_.nGhost() != 0) {
364  UTIL_THROW("Nonzero nGhost in map at end of clearGhosts");
365  }
366  if (map_.nGhostDistinct() != 0) {
367  UTIL_THROW("Nonzero nGhostDistinct at end of clearGhosts");
368  }
369  }
370 
371  // Snapshot functions
372 
373  /*
374  * Record current positions of all local atoms and lock storage.
375  */
377  {
378  // Precondition
379  if (!isCartesian()) {
380  UTIL_THROW("Error: Coordinates not Cartesian in makeSnapshot");
381  }
382 
383  AtomIterator iter;
384  int i = 0;
385  for (begin(iter); iter.notEnd(); ++iter) {
386  snapshot_[i] = iter->position();
387  ++i;
388  }
389  locked_ = true;
390  }
391 
392  /*
393  * Clear snapshot of local atom positions.
394  */
396  {
397  locked_ = false;
398  }
399 
400  /*
401  * Return max. sq. displacement of local atoms on this node since snapshot.
402  */
404  {
405  if (!isCartesian()) {
406  UTIL_THROW("Error: Coordinates not Cartesian in maxSqDisplacement");
407  }
408  if (!locked_) {
409  UTIL_THROW("Error: AtomStorage not locked in maxSqDisplacement");
410  }
411  Vector dr;
412  double norm;
413  double max = 0.0;
414  AtomIterator iter;
415  int i = 0;
416  for (begin(iter); iter.notEnd(); ++iter) {
417  dr.subtract(iter->position(), snapshot_[i]);
418  norm = dr.square();
419  if (norm > max) {
420  max = norm;
421  }
422  ++i;
423  }
424  return max;
425  }
426 
427  // Accessors
428 
429  /*
430  * Set iterator to beginning of the set of local atoms.
431  */
433  { atomSet_.begin(iterator); }
434 
435  /*
436  * Set const iterator to beginning of the set of local atoms.
437  */
438  void AtomStorage::begin(ConstAtomIterator& iterator) const
439  { atomSet_.begin(iterator); }
440 
441  /*
442  * Set iterator to beginning of the set of ghost atoms.
443  */
445  { ghostSet_.begin(iterator); }
446 
447  /*
448  * Set iterator to beginning of the set of ghost atoms.
449  */
451  { ghostSet_.begin(iterator); }
452 
453  /*
454  * Transform all atomic coordinates from Cartesian to generalized.
455  */
457  {
458  if (!isCartesian()) {
459  UTIL_THROW("Error: Coordinates not Cartesian on entry");
460  }
461  Vector r;
462  if (nAtom()) {
463  AtomIterator atomIter;
464  for (begin(atomIter); atomIter.notEnd(); ++atomIter) {
465  r = atomIter->position();
466  boundary.transformCartToGen(r, atomIter->position());
467  }
468  }
469  if (nGhost()) {
470  GhostIterator ghostIter;
471  for (begin(ghostIter); ghostIter.notEnd(); ++ghostIter) {
472  r = ghostIter->position();
473  boundary.transformCartToGen(r, ghostIter->position());
474  }
475  }
476  isCartesian_ = false;
477  }
478 
479  /*
480  * Transform all atomic coordinates from generalized to Cartesian.
481  */
483  {
484  if (isCartesian()) {
485  UTIL_THROW("Error: Coordinates are Cartesian on entry");
486  }
487  Vector r;
488  if (nAtom()) {
489  AtomIterator atomIter;
490  for (begin(atomIter); atomIter.notEnd(); ++atomIter) {
491  r = atomIter->position();
492  boundary.transformGenToCart(r, atomIter->position());
493  }
494  }
495  if (nGhost()) {
496  GhostIterator ghostIter;
497  for (begin(ghostIter); ghostIter.notEnd(); ++ghostIter) {
498  r = ghostIter->position();
499  boundary.transformGenToCart(r, ghostIter->position());
500  }
501  }
502  isCartesian_ = true;
503  }
504 
505  #ifdef UTIL_MPI
506  /*
507  * Compute, store and return total number of atoms on all processors.
508  */
509  void AtomStorage::computeNAtomTotal(MPI::Intracomm& communicator)
510  {
511  // If nAtomTotal is already set, do nothing and return.
512  // if (nAtomTotal_.isSet()) return;
513 
514  int nAtomLocal = nAtom();
515  int nAtomTotal = 0;
516  communicator.Reduce(&nAtomLocal, &nAtomTotal, 1,
517  MPI::INT, MPI::SUM, 0);
518  if (communicator.Get_rank() !=0) {
519  nAtomTotal = 0;
520  }
521  nAtomTotal_.set(nAtomTotal);
522  }
523 
525  { nAtomTotal_.unset(); }
526  #endif
527 
528  /*
529  * Compute memory usage statistics (call on all processors).
530  */
531  #ifdef UTIL_MPI
532  void AtomStorage::computeStatistics(MPI::Intracomm& communicator)
533  #else
535  #endif
536  {
537  #ifdef UTIL_MPI
538  int maxNAtomGlobal;
539  communicator.Allreduce(&maxNAtomLocal_, &maxNAtomGlobal, 1,
540  MPI::INT, MPI::MAX);
541  maxNAtom_.set(maxNAtomGlobal);
542  maxNAtomLocal_ = maxNAtomGlobal;
543  #else
544  maxNAtom_.set(maxNAtomLocal_);
545  #endif
546 
547  #ifdef UTIL_MPI
548  int maxNGhostGlobal;
549  communicator.Allreduce(&maxNGhostLocal_, &maxNGhostGlobal, 1,
550  MPI::INT, MPI::MAX);
551  maxNGhost_.set(maxNGhostGlobal);
552  maxNGhostLocal_ = maxNGhostGlobal;
553  #else
554  maxNGhost_.set(maxNGhostLocal_);
555  #endif
556  }
557 
558  /*
559  * Clear all statistics.
560  */
562  {
563  maxNAtomLocal_ = 0;
564  maxNAtom_.unset();
565  maxNGhostLocal_ = 0;
566  maxNGhost_.unset();
567  }
568 
569  /*
570  * Output statistics.
571  */
572  void AtomStorage::outputStatistics(std::ostream& out)
573  {
574 
575  out << std::endl;
576  out << "AtomStorage" << std::endl;
577  out << "NAtom: max, capacity "
578  << Int(maxNAtom_.value(), 10)
579  << Int(atomCapacity_, 10)
580  << std::endl;
581  out << "NGhost: max, capacity "
582  << Int(maxNGhost_.value(), 10)
583  << Int(ghostCapacity_, 10)
584  << std::endl;
585  }
586 
587  /*
588  * Check validity of this AtomStorage.
589  *
590  * Returns true if all is ok, or throws an Exception.
591  */
592  bool AtomStorage::isValid() const
593  {
594  if (nAtom() + atomReservoir_.size() != atomCapacity_) {
595  UTIL_THROW("nAtom + reservoir size != local capacity");
596  }
597  if (nGhost() + ghostReservoir_.size() != ghostCapacity_) {
598  UTIL_THROW("nGhost + reservoir size != ghost capacity");
599  }
600  if (nGhost() != map_.nGhost()) {
601  UTIL_THROW("Inconsistent values of nGhost");
602  }
603 
604  // Test validity of AtomMap.
605  map_.isValid();
606 
607  // Iterate over, count and find local atoms on this processor.
608  ConstAtomIterator localIter;
609  Atom* ptr;
610  int j = 0;
611  for (begin(localIter); localIter.notEnd(); ++localIter) {
612  ++j;
613  if (localIter->isGhost()) {
614  UTIL_THROW("Atom in atomSet is marked isGhost");
615  }
616  ptr = map_.find(localIter->id());
617  if (ptr == 0) {
618  UTIL_THROW("Unable to find local atom returned by iterator");
619  }
620  if (ptr != localIter.get()) {
621  UTIL_THROW("Inconsistent find(localIter->id()");
622  }
623  }
624  if (j != nAtom()) {
625  UTIL_THROW("Number counted by localIterator != nAtom()");
626  }
627 
628  // Iterate over, count and find ghost atoms
629  ConstGhostIterator ghostIter;
630  j = 0;
631  for (begin(ghostIter); ghostIter.notEnd(); ++ghostIter) {
632  ++j;
633  if (!ghostIter->isGhost()) {
634  UTIL_THROW("Atom in ghostSet is not marked isGhost");
635  }
636  ptr = map_.find(ghostIter->id());
637  if (ptr == 0) {
638  UTIL_THROW("find(ghostIter->id()) == 0");
639  }
640  // We do NOT test if ptr == ghostIter.get(), because it is possible
641  // to have multiple atoms with the same id on one processor. One to
642  // one correspondence of ids and pointers is guaranteed only for
643  // local atoms.
644  }
645  #if 0
646  if (j != nGhost()) {
647  UTIL_THROW("Number counted by ghostIterator != nGhost()");
648  }
649  #endif
650 
651  return true;
652  }
653 
654  #ifdef UTIL_MPI
655 
660  bool AtomStorage::isValid(MPI::Intracomm& communicator) const
661  {
662  isValid();
663  nAtomTotal_.isValid(communicator);
664  return true;
665  }
666  #endif
667 
668 }
void addNewGhost()
Register the most recent new ghost atom.
void makeSnapshot()
Record current positions of all local atoms and lock storage.
Atom * newAtomPtr()
Returns pointer an address available for a new Atom.
void associate(Domain &domain, AtomStorage &storage, Buffer &buffer)
Initialize pointers to associated objects.
void removeGhost(Atom *atomPtr)
Remove a specific ghost Atom.
A Vector is a Cartesian vector.
Definition: Vector.h:75
void transformGenToCart(const Boundary &boundary)
Transform positions from generalized to Cartesian coordinates.
void clearAtoms()
Clear all local atoms.
void allocate(int capacity)
Allocate memory on the heap.
Definition: AtomArray.cpp:56
void clearStatistics()
Clear statistical accumulators (call on all processors).
void clear()
Reset integer members to initial null values.
virtual void loadParameters(Serializable::IArchive &ar)
Load internal state from an archive.
int nAtomTotal() const
Get total number of atoms on all processors.
const Data * get() const
Return a pointer to const current data.
void outputStatistics(std::ostream &out)
Output statistics.
void setId(int Id)
Set unique global id for this Atom.
void set(const T &value)
Set the value and mark as set.
Definition: Setable.h:107
An orthorhombic periodic unit cell.
int nGhostDistinct() const
Return the number of ghosts with distinct ids.
Definition: AtomMap.h:242
bool isValid() const
Check validity of this AtomMap.
Definition: AtomMap.cpp:215
void addLocal(Atom *ptr)
Add local atom.
Definition: AtomMap.cpp:57
void allocate(int totalAtomCapacity)
Set parameters, allocate memory and initialize.
Definition: AtomMap.cpp:40
File containing preprocessor macros for error handling.
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 removeLocal(Atom *ptr)
Remove a specific Atom.
Definition: AtomMap.cpp:83
Atom * addAtom(int id)
Add atom with specified global id.
void addNewAtom()
Finalize addition of the most recent new atom.
int nAtom() const
Return number of local atoms on this procesor (excluding ghosts)
Saving / output archive for binary ostream.
const T & value() const
Return value (if set).
Definition: Setable.h:132
#define UTIL_THROW(msg)
Macro for throwing an Exception, reporting function, file and line number.
Definition: global.h:51
int nLocal() const
Return the number of local atoms.
Definition: AtomMap.h:236
virtual void computeStatistics(MPI::Intracomm &communicator)
Compute statistics (reduce from all processors).
void associate(Domain &domain, Boundary &boundary, AtomStorage &storage, Buffer &buffer)
Set pointers to associated objects.
bool isValid(MPI::Intracomm &communicator) const
Test consistency of states on different processors.
Definition: Setable.h:163
int nGhost() const
Return current number of ghost atoms on this processor.
Const iterator for all atoms owned by an AtomStorage.
int nGhost() const
Return the number of ghosts, including images.
Definition: AtomMap.h:248
bool notEnd() const
Is the current pointer not at the end of the PArray?
Utility classes for scientific computation.
Definition: accumulators.mod:1
void initialize(int atomCapacity, int ghostCapacity, int totalAtomCapacity)
Set parameters, allocate memory and initialize.
Wrapper for an int, for formatted ostream output.
Definition: Int.h:36
void setIsGhost(bool isGhost)
Mark as ghost or local atom for this processor.
void associate(Domain &domain, Boundary &boundary, Buffer &buffer)
Create associations for distributor and collector.
Atom * find(int atomId) const
Return pointer to Atom with specified id.
Definition: AtomMap.h:230
void unset()
Unset the value (mark as unknown).
Definition: Setable.h:116
void transformGenToCart(const Vector &Rg, Vector &Rc) const
Transform Vector of generalized coordinates to Cartesian Vector.
void clearSnapshot()
Clear previous snapshot.
Atom * newGhostPtr()
Returns pointer an address available for a new ghost Atom.
int atomCapacity() const
Return capacity for local atoms on this processor (excluding ghosts).
void computeNAtomTotal(MPI::Intracomm &communicator)
Compute the total number of local atoms on all processors.
int totalAtomCapacity() const
Return maximum number of atoms on all processors.
bool isValid() const
Return true if the container is valid, or throw an Exception.
Buffer for interprocessor communication.
Definition: Buffer.h:217
Decomposition of the system into domains associated with processors.
Definition: Domain.h:31
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.
Definition: MpiLoader.h:43
int ghostCapacity() const
Return capacity for ghost atoms on this processor.
bool isCartesian() const
Are atom coordinates Cartesian (true) or generalized (false)?
Iterator for all ghost atoms owned by an AtomStorage.
Definition: GhostIterator.h:24
Atom * addGhost(int id)
Add ghost atom with specified global id.
virtual void save(Serializable::OArchive &ar)
Save internal state to an archive.
Vector & subtract(const Vector &v1, const Vector &v2)
Subtract vector v2 from v1.
Definition: Vector.h:672
void setClassName(const char *className)
Set class name string.
void clearGhosts()
Clear all ghost atoms.
Iterator for all atoms owned by an AtomStorage.
Definition: AtomIterator.h:24
double maxSqDisplacement()
Return max-squared displacement since the last snapshot.
Iterator for all ghost atoms owned by an AtomStorage.
void removeGhost(Atom *ptr)
Remove a ghost Atom.
Definition: AtomMap.cpp:139
void zeroForces()
Set force vector to zero for all atoms in this array.
Definition: AtomArray.cpp:101
double square() const
Return square magnitude of this vector.
Definition: Vector.h:616
void begin(AtomIterator &iterator)
Set iterator to beginning of the set of atoms.
void removeAtom(Atom *atomPtr)
Remove a specific Atom.
void addGhost(Atom *ptr)
Add ghost atom.
Definition: AtomMap.cpp:120
void transformCartToGen(const Boundary &boundary)
Transform positions from Cartesian to generalized coordinates.
void zeroForces(bool zeroGhosts)
Set all forces to zero.
void clearGhosts(const ArraySet< Atom > &ghostSet)
Clear all ghosts from this map.
Definition: AtomMap.cpp:185
void unsetNAtomTotal()
Unset value of NAtomTotal (mark as unknown).
void transformCartToGen(const Vector &Rc, Vector &Rg) const
Transform Cartesian Vector to scaled / generalized coordinates.