Simpatico  v1.10
tools/chemistry/Species.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 "Species.h"
9 #include "Atom.h"
10 
11 namespace Tools
12 {
13 
14  using namespace Util;
15 
16  /*
17  * Constructor.
18  */
20  : atomPtrs_(),
21  molecules_(),
22  id_(-1),
23  nAtom_(0),
24  capacity_(0)
25  {}
26 
27  /*
28  * Destructor.
29  */
31  {}
32 
33  void Species::setId(int id)
34  { id_ = id; }
35 
36  void Species::initialize(int nAtom, int capacity)
37  {
38  if (capacity_ != 0) {
39  UTIL_THROW("Species already initialized: capacity_ != 0");
40  }
41  if (nAtom_ != 0) {
42  UTIL_THROW("Species already initialized: nAtom_ != 0");
43  }
44  nAtom_ = nAtom;
45  capacity_ = capacity;
46  initialize();
47  }
48 
49  void Species::initialize()
50  {
51  // Preconditions
52  if (molecules_.capacity() != 0) {
53  UTIL_THROW("Species::molecules_ already allocated");
54  }
55  if (atomPtrs_.capacity() != 0) {
56  UTIL_THROW("Species::atomPtrs_ already allocated");
57  }
58  if (capacity_ <= 0) {
59  UTIL_THROW("Species::capacity_ <= 0: Value not set");
60  }
61  if (nAtom_ <= 0) {
62  UTIL_THROW("Species::nAtom_ <= 0: Value not set");
63  }
64 
65  // Allocate and initialize atomPtrs_ array
66  atomPtrs_.allocate(capacity_*nAtom_);
67  for (int i=0; i < atomPtrs_.capacity(); ++i) {
68  atomPtrs_[i] = 0;
69  }
70 
71  // Allocate and initialize molecules_ array
72  molecules_.allocate(capacity_);
73 
74  // Initialize molecules_ array
75  molecules_.resize(capacity_); // temporarily resize
76  Atom** atomPtr = &atomPtrs_[0];
77  for (int i = 0; i < capacity_; ++i) {
78  molecules_[i].atoms_ = atomPtr;
79  molecules_[i].id_ = i;
80  molecules_[i].nAtom_ = 0;
81  molecules_[i].speciesPtr_ = this;
82  atomPtr += nAtom_;
83  }
84  molecules_.resize(0); // reset size to zero
85 
86  }
87 
88  /*
89  * Reset to empty state.
90  */
91  void Species::clear()
92  {
93  for (int i = 0; i < atomPtrs_.capacity(); ++i) {
94  atomPtrs_[i] = 0;
95  }
96  for (int i = 0; i < molecules_.size(); ++i) {
97  molecules_[i].nAtom_ = 0;
98  }
99  molecules_.resize(0);
100  }
101 
102  /*
103  * Add an atom to this Species.
104  */
105  void Species::addAtom(Atom& atom)
106  {
107  if (atom.speciesId != id_) {
108  UTIL_THROW("Inconsistent speciesId");
109  }
110  int mId = atom.moleculeId;
111  int aId = atom.atomId;
112  if (mId < 0) {
113  UTIL_THROW("atom.moleculeId < 0");
114  }
115  if (mId >= capacity_) {
116  UTIL_THROW("atom.moleculeId >= capacity_");
117  }
118  if (aId < 0) {
119  UTIL_THROW("atom.atomId < 0");
120  }
121  if (aId >= nAtom_) {
122  UTIL_THROW("atom.atomId >= nAtom_");
123  }
124  int gid = mId*nAtom_ + aId; // "global" atom id, within species
125  if (atomPtrs_[gid] != 0) {
126  UTIL_THROW("Atom already present");
127  }
128  atomPtrs_[gid] = &atom;
129  if (mId >= molecules_.size()) {
130  molecules_.resize(mId+1);
131  }
132  ++molecules_[mId].nAtom_;
133  }
134 
135  /*
136  * Initialized an iterator over molecules in species.
137  */
138  void Species::begin(Iterator& iterator)
139  { molecules_.begin(iterator); }
140 
141  /*
142  * Return true if valid, throw Exception otherwise.
143  */
144  bool Species::isValid() const
145  {
146  // Check allocation and initialization
147  if (molecules_.capacity() != capacity_) {
148  UTIL_THROW("molecules_ is not allocated");
149  }
150  if (atomPtrs_.capacity() != capacity_*nAtom_) {
151  UTIL_THROW("atomPtrs_ is not allocated");
152  }
153 
154  // Check molecules and atoms
155  if (molecules_.size() > 0) {
156  const Molecule* mPtr;
157  const Atom* aPtr;
158  int im, ia;
159  for (im = 0; im < molecules_.size(); ++im) {
160  mPtr = &(molecules_[im]);
161  if (mPtr->atoms_ != &atomPtrs_[0] + im*nAtom_) {
162  UTIL_THROW("Incorrect assignment of atoms_ in molecule");
163  }
164  if (mPtr->id() != im) {
165  UTIL_THROW("Incorrect molecule id");
166  }
167  if (mPtr->speciesPtr_ != this) {
168  UTIL_THROW("Incorrect species pointer in molecule");
169  }
170  #if 1
171  if (mPtr->nAtom_ == nAtom_) {
172  for (ia = 0; ia < nAtom_; ++ia) {
173  aPtr = mPtr->atoms_[ia];
174  if (aPtr == 0) {
175  UTIL_THROW("Null atom ptr in molecule");
176  }
177  if (aPtr->atomId != ia) {
178  UTIL_THROW("Inconsistent atom index");
179  }
180  if (aPtr->moleculeId != im) {
181  UTIL_THROW("Inconsistent molecule index");
182  }
183  if (aPtr->speciesId != id_) {
184  UTIL_THROW("Inconsistent species index");
185  }
186  }
187  } else
188  if (mPtr->nAtom_ == 0) {
189  for (ia = 0; ia < nAtom_; ++ia) {
190  if (mPtr->atoms_[ia] != 0) {
191  UTIL_THROW("Nonnull atom ptr in empty molecule");
192  }
193  }
194  } else {
195  UTIL_THROW("0 != molecule nAtom != species nAtom");
196  }
197  #endif
198  }
199  }
200  return true;
201  }
202 
203  /*
204  * istream extractor (>>) for a Species.
205  */
206  std::istream& operator >> (std::istream& in, Species &species)
207  {
208  in >> species.nAtom_;
209  in >> species.capacity_;
210  species.initialize();
211  return in;
212  }
213 
214  /*
215  * ostream inserter (<<) for a Species.
216  */
217  std::ostream& operator << (std::ostream& out, const Species &species)
218  {
219  out.width(10);
220  out << species.nAtom_;
221  out.width(10);
222  out << species.capacity_;
223  return out;
224  }
225 
226 }
int speciesId
Index for species of parent molecule.
int id() const
Return id of this Molecule within its species.
int nAtom() const
Get number of atoms per molecule for this Species.
virtual ~Species()
Destructor.
std::istream & operator>>(std::istream &in, MonoclinicBoundary &boundary)
istream extractor for a MonoclinicBoundary.
int nAtom_
Number of atoms per molecule.
#define UTIL_THROW(msg)
Macro for throwing an Exception, reporting function, file and line number.
Definition: global.h:51
Species()
Constructor.
Utility classes for scientific computation.
Definition: accumulators.mod:1
std::ostream & operator<<(std::ostream &out, const MonoclinicBoundary &boundary)
ostream inserter for an MonoclinicBoundary.
An Molecule has a sequence of atoms, and belongs to an Species.
Forward iterator for an Array or a C array.
Definition: ArrayIterator.h:39
Single-processor classes for pre- and post-processing MD trajectories.
int atomId
Index of atom within its molecule.
bool isValid() const
Return true if Species is valid, or throw an Exception.
void setId(int id)
Set integer id for this Species.
A point particle in an MD simulation.
int id_
Integer index for this Species.
int id() const
Get integer id of this Species.
int capacity() const
Maximum allowed number of molecules for this Species.
A Species represents a set of chemically similar molecules.
int moleculeId
Index of molecule with its species.