ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/OpenMD/branches/development/src/brains/SimInfo.cpp
Revision: 1725
Committed: Sat May 26 18:13:43 2012 UTC (12 years, 11 months ago) by gezelter
File size: 39582 byte(s)
Log Message:
Individual ForceField classes have been removed (they were essentially
all duplicates anyway).  

ForceField has moved to brains, and since only one force field is in
play at any time, the ForceFieldFactory and Register methods have been
removed.  


File Contents

# User Rev Content
1 gezelter 507 /*
2 gezelter 246 * Copyright (c) 2005 The University of Notre Dame. All Rights Reserved.
3     *
4     * The University of Notre Dame grants you ("Licensee") a
5     * non-exclusive, royalty free, license to use, modify and
6     * redistribute this software in source and binary code form, provided
7     * that the following conditions are met:
8     *
9 gezelter 1390 * 1. Redistributions of source code must retain the above copyright
10 gezelter 246 * notice, this list of conditions and the following disclaimer.
11     *
12 gezelter 1390 * 2. Redistributions in binary form must reproduce the above copyright
13 gezelter 246 * notice, this list of conditions and the following disclaimer in the
14     * documentation and/or other materials provided with the
15     * distribution.
16     *
17     * This software is provided "AS IS," without a warranty of any
18     * kind. All express or implied conditions, representations and
19     * warranties, including any implied warranty of merchantability,
20     * fitness for a particular purpose or non-infringement, are hereby
21     * excluded. The University of Notre Dame and its licensors shall not
22     * be liable for any damages suffered by licensee as a result of
23     * using, modifying or distributing the software or its
24     * derivatives. In no event will the University of Notre Dame or its
25     * licensors be liable for any lost revenue, profit or data, or for
26     * direct, indirect, special, consequential, incidental or punitive
27     * damages, however caused and regardless of the theory of liability,
28     * arising out of the use of or inability to use software, even if the
29     * University of Notre Dame has been advised of the possibility of
30     * such damages.
31 gezelter 1390 *
32     * SUPPORT OPEN SCIENCE! If you use OpenMD or its source code in your
33     * research, please cite the appropriate papers when you publish your
34     * work. Good starting points are:
35     *
36     * [1] Meineke, et al., J. Comp. Chem. 26, 252-271 (2005).
37     * [2] Fennell & Gezelter, J. Chem. Phys. 124, 234104 (2006).
38     * [3] Sun, Lin & Gezelter, J. Chem. Phys. 128, 24107 (2008).
39 gezelter 1665 * [4] Kuang & Gezelter, J. Chem. Phys. 133, 164101 (2010).
40     * [5] Vardeman, Stocker & Gezelter, J. Chem. Theory Comput. 7, 834 (2011).
41 gezelter 246 */
42    
43     /**
44     * @file SimInfo.cpp
45     * @author tlin
46     * @date 11/02/2004
47     * @version 1.0
48     */
49 gezelter 2
50 gezelter 246 #include <algorithm>
51     #include <set>
52 tim 749 #include <map>
53 gezelter 2
54 tim 3 #include "brains/SimInfo.hpp"
55 gezelter 246 #include "math/Vector3.hpp"
56     #include "primitives/Molecule.hpp"
57 tim 1024 #include "primitives/StuntDouble.hpp"
58 gezelter 246 #include "utils/MemoryUtils.hpp"
59 tim 3 #include "utils/simError.h"
60 tim 316 #include "selection/SelectionManager.hpp"
61 chuckv 834 #include "io/ForceFieldOptions.hpp"
62 gezelter 1725 #include "brains/ForceField.hpp"
63 gezelter 1530 #include "nonbonded/SwitchingFunction.hpp"
64 gezelter 1627 #ifdef IS_MPI
65     #include <mpi.h>
66     #endif
67 gezelter 2
68 gezelter 1528 using namespace std;
69 gezelter 1390 namespace OpenMD {
70 tim 749
71 tim 770 SimInfo::SimInfo(ForceField* ff, Globals* simParams) :
72     forceField_(ff), simParams_(simParams),
73 gezelter 945 ndf_(0), fdf_local(0), ndfRaw_(0), ndfTrans_(0), nZconstraint_(0),
74 gezelter 507 nGlobalMols_(0), nGlobalAtoms_(0), nGlobalCutoffGroups_(0),
75 gezelter 1715 nGlobalIntegrableObjects_(0), nGlobalRigidBodies_(0), nGlobalFluctuatingCharges_(0),
76 gezelter 1277 nAtoms_(0), nBonds_(0), nBends_(0), nTorsions_(0), nInversions_(0),
77     nRigidBodies_(0), nIntegrableObjects_(0), nCutoffGroups_(0),
78 gezelter 1715 nConstraints_(0), nFluctuatingCharges_(0), sman_(NULL), topologyDone_(false),
79 gezelter 1528 calcBoxDipole_(false), useAtomicVirial_(true) {
80    
81     MoleculeStamp* molStamp;
82     int nMolWithSameStamp;
83     int nCutoffAtoms = 0; // number of atoms belong to cutoff groups
84     int nGroups = 0; //total cutoff groups defined in meta-data file
85     CutoffGroupStamp* cgStamp;
86     RigidBodyStamp* rbStamp;
87     int nRigidAtoms = 0;
88    
89     vector<Component*> components = simParams->getComponents();
90    
91     for (vector<Component*>::iterator i = components.begin(); i !=components.end(); ++i) {
92     molStamp = (*i)->getMoleculeStamp();
93     nMolWithSameStamp = (*i)->getNMol();
94 tim 770
95 gezelter 1528 addMoleculeStamp(molStamp, nMolWithSameStamp);
96    
97     //calculate atoms in molecules
98     nGlobalAtoms_ += molStamp->getNAtoms() *nMolWithSameStamp;
99    
100     //calculate atoms in cutoff groups
101     int nAtomsInGroups = 0;
102     int nCutoffGroupsInStamp = molStamp->getNCutoffGroups();
103    
104     for (int j=0; j < nCutoffGroupsInStamp; j++) {
105     cgStamp = molStamp->getCutoffGroupStamp(j);
106     nAtomsInGroups += cgStamp->getNMembers();
107 gezelter 507 }
108 gezelter 1528
109     nGroups += nCutoffGroupsInStamp * nMolWithSameStamp;
110    
111     nCutoffAtoms += nAtomsInGroups * nMolWithSameStamp;
112    
113     //calculate atoms in rigid bodies
114     int nAtomsInRigidBodies = 0;
115     int nRigidBodiesInStamp = molStamp->getNRigidBodies();
116    
117     for (int j=0; j < nRigidBodiesInStamp; j++) {
118     rbStamp = molStamp->getRigidBodyStamp(j);
119     nAtomsInRigidBodies += rbStamp->getNMembers();
120     }
121    
122     nGlobalRigidBodies_ += nRigidBodiesInStamp * nMolWithSameStamp;
123     nRigidAtoms += nAtomsInRigidBodies * nMolWithSameStamp;
124    
125     }
126    
127     //every free atom (atom does not belong to cutoff groups) is a cutoff
128     //group therefore the total number of cutoff groups in the system is
129     //equal to the total number of atoms minus number of atoms belong to
130     //cutoff group defined in meta-data file plus the number of cutoff
131     //groups defined in meta-data file
132 gezelter 1540
133 gezelter 1528 nGlobalCutoffGroups_ = nGlobalAtoms_ - nCutoffAtoms + nGroups;
134    
135     //every free atom (atom does not belong to rigid bodies) is an
136     //integrable object therefore the total number of integrable objects
137     //in the system is equal to the total number of atoms minus number of
138     //atoms belong to rigid body defined in meta-data file plus the number
139     //of rigid bodies defined in meta-data file
140     nGlobalIntegrableObjects_ = nGlobalAtoms_ - nRigidAtoms
141     + nGlobalRigidBodies_;
142    
143     nGlobalMols_ = molStampIds_.size();
144     molToProcMap_.resize(nGlobalMols_);
145     }
146 chrisfen 645
147 gezelter 507 SimInfo::~SimInfo() {
148 gezelter 1528 map<int, Molecule*>::iterator i;
149 tim 398 for (i = molecules_.begin(); i != molecules_.end(); ++i) {
150 gezelter 507 delete i->second;
151 tim 398 }
152     molecules_.clear();
153 tim 490
154 gezelter 246 delete sman_;
155     delete simParams_;
156     delete forceField_;
157 gezelter 507 }
158 gezelter 2
159    
160 gezelter 507 bool SimInfo::addMolecule(Molecule* mol) {
161 gezelter 246 MoleculeIterator i;
162 gezelter 1528
163 gezelter 246 i = molecules_.find(mol->getGlobalIndex());
164     if (i == molecules_.end() ) {
165 gezelter 1528
166     molecules_.insert(make_pair(mol->getGlobalIndex(), mol));
167    
168 gezelter 507 nAtoms_ += mol->getNAtoms();
169     nBonds_ += mol->getNBonds();
170     nBends_ += mol->getNBends();
171     nTorsions_ += mol->getNTorsions();
172 gezelter 1277 nInversions_ += mol->getNInversions();
173 gezelter 507 nRigidBodies_ += mol->getNRigidBodies();
174     nIntegrableObjects_ += mol->getNIntegrableObjects();
175     nCutoffGroups_ += mol->getNCutoffGroups();
176     nConstraints_ += mol->getNConstraintPairs();
177 gezelter 1528
178 gezelter 1287 addInteractionPairs(mol);
179 gezelter 1528
180 gezelter 507 return true;
181 gezelter 246 } else {
182 gezelter 507 return false;
183 gezelter 246 }
184 gezelter 507 }
185 gezelter 1528
186 gezelter 507 bool SimInfo::removeMolecule(Molecule* mol) {
187 gezelter 246 MoleculeIterator i;
188     i = molecules_.find(mol->getGlobalIndex());
189 gezelter 2
190 gezelter 246 if (i != molecules_.end() ) {
191 gezelter 2
192 gezelter 507 assert(mol == i->second);
193 gezelter 246
194 gezelter 507 nAtoms_ -= mol->getNAtoms();
195     nBonds_ -= mol->getNBonds();
196     nBends_ -= mol->getNBends();
197     nTorsions_ -= mol->getNTorsions();
198 gezelter 1277 nInversions_ -= mol->getNInversions();
199 gezelter 507 nRigidBodies_ -= mol->getNRigidBodies();
200     nIntegrableObjects_ -= mol->getNIntegrableObjects();
201     nCutoffGroups_ -= mol->getNCutoffGroups();
202     nConstraints_ -= mol->getNConstraintPairs();
203 gezelter 2
204 gezelter 1287 removeInteractionPairs(mol);
205 gezelter 507 molecules_.erase(mol->getGlobalIndex());
206 gezelter 2
207 gezelter 507 delete mol;
208 gezelter 246
209 gezelter 507 return true;
210 gezelter 246 } else {
211 gezelter 507 return false;
212 gezelter 246 }
213 gezelter 507 }
214 gezelter 246
215    
216 gezelter 507 Molecule* SimInfo::beginMolecule(MoleculeIterator& i) {
217 gezelter 246 i = molecules_.begin();
218     return i == molecules_.end() ? NULL : i->second;
219 gezelter 507 }
220 gezelter 246
221 gezelter 507 Molecule* SimInfo::nextMolecule(MoleculeIterator& i) {
222 gezelter 246 ++i;
223     return i == molecules_.end() ? NULL : i->second;
224 gezelter 507 }
225 gezelter 2
226    
227 gezelter 507 void SimInfo::calcNdf() {
228 gezelter 1715 int ndf_local, nfq_local;
229 gezelter 246 MoleculeIterator i;
230 gezelter 1528 vector<StuntDouble*>::iterator j;
231 gezelter 1715 vector<Atom*>::iterator k;
232    
233 gezelter 246 Molecule* mol;
234     StuntDouble* integrableObject;
235 gezelter 1715 Atom* atom;
236 gezelter 2
237 gezelter 246 ndf_local = 0;
238 gezelter 1715 nfq_local = 0;
239 gezelter 246
240     for (mol = beginMolecule(i); mol != NULL; mol = nextMolecule(i)) {
241 gezelter 507 for (integrableObject = mol->beginIntegrableObject(j); integrableObject != NULL;
242     integrableObject = mol->nextIntegrableObject(j)) {
243 gezelter 2
244 gezelter 507 ndf_local += 3;
245 gezelter 2
246 gezelter 507 if (integrableObject->isDirectional()) {
247     if (integrableObject->isLinear()) {
248     ndf_local += 2;
249     } else {
250     ndf_local += 3;
251     }
252     }
253 tim 770 }
254 gezelter 1715 for (atom = mol->beginFluctuatingCharge(k); atom != NULL;
255     atom = mol->nextFluctuatingCharge(k)) {
256     if (atom->isFluctuatingCharge()) {
257     nfq_local++;
258     }
259     }
260 tim 770 }
261 gezelter 246
262     // n_constraints is local, so subtract them on each processor
263     ndf_local -= nConstraints_;
264    
265     #ifdef IS_MPI
266     MPI_Allreduce(&ndf_local,&ndf_,1,MPI_INT,MPI_SUM, MPI_COMM_WORLD);
267 gezelter 1715 MPI_Allreduce(&nfq_local,&nGlobalFluctuatingCharges_,1, MPI_INT, MPI_SUM, MPI_COMM_WORLD);
268 gezelter 246 #else
269     ndf_ = ndf_local;
270 gezelter 1715 nGlobalFluctuatingCharges_ = nfq_local;
271 gezelter 246 #endif
272    
273     // nZconstraints_ is global, as are the 3 COM translations for the
274     // entire system:
275     ndf_ = ndf_ - 3 - nZconstraint_;
276    
277 gezelter 507 }
278 gezelter 2
279 gezelter 945 int SimInfo::getFdf() {
280     #ifdef IS_MPI
281     MPI_Allreduce(&fdf_local,&fdf_,1,MPI_INT,MPI_SUM, MPI_COMM_WORLD);
282     #else
283     fdf_ = fdf_local;
284     #endif
285     return fdf_;
286     }
287 gezelter 1577
288     unsigned int SimInfo::getNLocalCutoffGroups(){
289     int nLocalCutoffAtoms = 0;
290     Molecule* mol;
291     MoleculeIterator mi;
292     CutoffGroup* cg;
293     Molecule::CutoffGroupIterator ci;
294 gezelter 945
295 gezelter 1577 for (mol = beginMolecule(mi); mol != NULL; mol = nextMolecule(mi)) {
296    
297     for (cg = mol->beginCutoffGroup(ci); cg != NULL;
298     cg = mol->nextCutoffGroup(ci)) {
299     nLocalCutoffAtoms += cg->getNumAtom();
300    
301     }
302     }
303    
304     return nAtoms_ - nLocalCutoffAtoms + nCutoffGroups_;
305     }
306    
307 gezelter 507 void SimInfo::calcNdfRaw() {
308 gezelter 246 int ndfRaw_local;
309 gezelter 2
310 gezelter 246 MoleculeIterator i;
311 gezelter 1528 vector<StuntDouble*>::iterator j;
312 gezelter 246 Molecule* mol;
313     StuntDouble* integrableObject;
314    
315     // Raw degrees of freedom that we have to set
316     ndfRaw_local = 0;
317    
318     for (mol = beginMolecule(i); mol != NULL; mol = nextMolecule(i)) {
319 gezelter 507 for (integrableObject = mol->beginIntegrableObject(j); integrableObject != NULL;
320     integrableObject = mol->nextIntegrableObject(j)) {
321 gezelter 246
322 gezelter 507 ndfRaw_local += 3;
323 gezelter 246
324 gezelter 507 if (integrableObject->isDirectional()) {
325     if (integrableObject->isLinear()) {
326     ndfRaw_local += 2;
327     } else {
328     ndfRaw_local += 3;
329     }
330     }
331 gezelter 246
332 gezelter 507 }
333 gezelter 246 }
334    
335     #ifdef IS_MPI
336     MPI_Allreduce(&ndfRaw_local,&ndfRaw_,1,MPI_INT,MPI_SUM, MPI_COMM_WORLD);
337     #else
338     ndfRaw_ = ndfRaw_local;
339     #endif
340 gezelter 507 }
341 gezelter 2
342 gezelter 507 void SimInfo::calcNdfTrans() {
343 gezelter 246 int ndfTrans_local;
344 gezelter 2
345 gezelter 246 ndfTrans_local = 3 * nIntegrableObjects_ - nConstraints_;
346 gezelter 2
347    
348 gezelter 246 #ifdef IS_MPI
349     MPI_Allreduce(&ndfTrans_local,&ndfTrans_,1,MPI_INT,MPI_SUM, MPI_COMM_WORLD);
350     #else
351     ndfTrans_ = ndfTrans_local;
352     #endif
353 gezelter 2
354 gezelter 246 ndfTrans_ = ndfTrans_ - 3 - nZconstraint_;
355    
356 gezelter 507 }
357 gezelter 2
358 gezelter 1287 void SimInfo::addInteractionPairs(Molecule* mol) {
359     ForceFieldOptions& options_ = forceField_->getForceFieldOptions();
360 gezelter 1528 vector<Bond*>::iterator bondIter;
361     vector<Bend*>::iterator bendIter;
362     vector<Torsion*>::iterator torsionIter;
363     vector<Inversion*>::iterator inversionIter;
364 gezelter 246 Bond* bond;
365     Bend* bend;
366     Torsion* torsion;
367 gezelter 1277 Inversion* inversion;
368 gezelter 246 int a;
369     int b;
370     int c;
371     int d;
372 tim 749
373 gezelter 1287 // atomGroups can be used to add special interaction maps between
374     // groups of atoms that are in two separate rigid bodies.
375     // However, most site-site interactions between two rigid bodies
376     // are probably not special, just the ones between the physically
377     // bonded atoms. Interactions *within* a single rigid body should
378     // always be excluded. These are done at the bottom of this
379     // function.
380    
381 gezelter 1528 map<int, set<int> > atomGroups;
382 tim 749 Molecule::RigidBodyIterator rbIter;
383     RigidBody* rb;
384     Molecule::IntegrableObjectIterator ii;
385     StuntDouble* integrableObject;
386 gezelter 246
387 gezelter 1287 for (integrableObject = mol->beginIntegrableObject(ii);
388     integrableObject != NULL;
389     integrableObject = mol->nextIntegrableObject(ii)) {
390    
391 tim 749 if (integrableObject->isRigidBody()) {
392 gezelter 1287 rb = static_cast<RigidBody*>(integrableObject);
393 gezelter 1528 vector<Atom*> atoms = rb->getAtoms();
394     set<int> rigidAtoms;
395 gezelter 1287 for (int i = 0; i < static_cast<int>(atoms.size()); ++i) {
396     rigidAtoms.insert(atoms[i]->getGlobalIndex());
397     }
398     for (int i = 0; i < static_cast<int>(atoms.size()); ++i) {
399 gezelter 1528 atomGroups.insert(map<int, set<int> >::value_type(atoms[i]->getGlobalIndex(), rigidAtoms));
400 gezelter 1287 }
401 tim 749 } else {
402 gezelter 1528 set<int> oneAtomSet;
403 tim 749 oneAtomSet.insert(integrableObject->getGlobalIndex());
404 gezelter 1528 atomGroups.insert(map<int, set<int> >::value_type(integrableObject->getGlobalIndex(), oneAtomSet));
405 tim 749 }
406     }
407 gezelter 1287
408     for (bond= mol->beginBond(bondIter); bond != NULL;
409     bond = mol->nextBond(bondIter)) {
410 tim 749
411 gezelter 1287 a = bond->getAtomA()->getGlobalIndex();
412     b = bond->getAtomB()->getGlobalIndex();
413 tim 749
414 gezelter 1287 if (options_.havevdw12scale() || options_.haveelectrostatic12scale()) {
415     oneTwoInteractions_.addPair(a, b);
416     } else {
417     excludedInteractions_.addPair(a, b);
418     }
419 gezelter 246 }
420 gezelter 2
421 gezelter 1287 for (bend= mol->beginBend(bendIter); bend != NULL;
422     bend = mol->nextBend(bendIter)) {
423    
424 gezelter 507 a = bend->getAtomA()->getGlobalIndex();
425     b = bend->getAtomB()->getGlobalIndex();
426     c = bend->getAtomC()->getGlobalIndex();
427 gezelter 1287
428     if (options_.havevdw12scale() || options_.haveelectrostatic12scale()) {
429     oneTwoInteractions_.addPair(a, b);
430     oneTwoInteractions_.addPair(b, c);
431     } else {
432     excludedInteractions_.addPair(a, b);
433     excludedInteractions_.addPair(b, c);
434     }
435 gezelter 2
436 gezelter 1287 if (options_.havevdw13scale() || options_.haveelectrostatic13scale()) {
437     oneThreeInteractions_.addPair(a, c);
438     } else {
439     excludedInteractions_.addPair(a, c);
440     }
441 gezelter 246 }
442 gezelter 2
443 gezelter 1287 for (torsion= mol->beginTorsion(torsionIter); torsion != NULL;
444     torsion = mol->nextTorsion(torsionIter)) {
445    
446 gezelter 507 a = torsion->getAtomA()->getGlobalIndex();
447     b = torsion->getAtomB()->getGlobalIndex();
448     c = torsion->getAtomC()->getGlobalIndex();
449 gezelter 1287 d = torsion->getAtomD()->getGlobalIndex();
450 cli2 1290
451 gezelter 1287 if (options_.havevdw12scale() || options_.haveelectrostatic12scale()) {
452     oneTwoInteractions_.addPair(a, b);
453     oneTwoInteractions_.addPair(b, c);
454     oneTwoInteractions_.addPair(c, d);
455     } else {
456     excludedInteractions_.addPair(a, b);
457     excludedInteractions_.addPair(b, c);
458     excludedInteractions_.addPair(c, d);
459     }
460 gezelter 2
461 gezelter 1287 if (options_.havevdw13scale() || options_.haveelectrostatic13scale()) {
462     oneThreeInteractions_.addPair(a, c);
463     oneThreeInteractions_.addPair(b, d);
464     } else {
465     excludedInteractions_.addPair(a, c);
466     excludedInteractions_.addPair(b, d);
467     }
468 tim 749
469 gezelter 1287 if (options_.havevdw14scale() || options_.haveelectrostatic14scale()) {
470     oneFourInteractions_.addPair(a, d);
471     } else {
472     excludedInteractions_.addPair(a, d);
473     }
474 gezelter 2 }
475    
476 gezelter 1277 for (inversion= mol->beginInversion(inversionIter); inversion != NULL;
477     inversion = mol->nextInversion(inversionIter)) {
478 gezelter 1287
479 gezelter 1277 a = inversion->getAtomA()->getGlobalIndex();
480     b = inversion->getAtomB()->getGlobalIndex();
481     c = inversion->getAtomC()->getGlobalIndex();
482     d = inversion->getAtomD()->getGlobalIndex();
483    
484 gezelter 1287 if (options_.havevdw12scale() || options_.haveelectrostatic12scale()) {
485     oneTwoInteractions_.addPair(a, b);
486     oneTwoInteractions_.addPair(a, c);
487     oneTwoInteractions_.addPair(a, d);
488     } else {
489     excludedInteractions_.addPair(a, b);
490     excludedInteractions_.addPair(a, c);
491     excludedInteractions_.addPair(a, d);
492     }
493 gezelter 1277
494 gezelter 1287 if (options_.havevdw13scale() || options_.haveelectrostatic13scale()) {
495     oneThreeInteractions_.addPair(b, c);
496     oneThreeInteractions_.addPair(b, d);
497     oneThreeInteractions_.addPair(c, d);
498     } else {
499     excludedInteractions_.addPair(b, c);
500     excludedInteractions_.addPair(b, d);
501     excludedInteractions_.addPair(c, d);
502     }
503 gezelter 1277 }
504    
505 gezelter 1287 for (rb = mol->beginRigidBody(rbIter); rb != NULL;
506     rb = mol->nextRigidBody(rbIter)) {
507 gezelter 1528 vector<Atom*> atoms = rb->getAtoms();
508 gezelter 1287 for (int i = 0; i < static_cast<int>(atoms.size()) -1 ; ++i) {
509     for (int j = i + 1; j < static_cast<int>(atoms.size()); ++j) {
510 gezelter 507 a = atoms[i]->getGlobalIndex();
511     b = atoms[j]->getGlobalIndex();
512 gezelter 1287 excludedInteractions_.addPair(a, b);
513 gezelter 507 }
514     }
515 tim 430 }
516    
517 gezelter 507 }
518 gezelter 246
519 gezelter 1287 void SimInfo::removeInteractionPairs(Molecule* mol) {
520     ForceFieldOptions& options_ = forceField_->getForceFieldOptions();
521 gezelter 1528 vector<Bond*>::iterator bondIter;
522     vector<Bend*>::iterator bendIter;
523     vector<Torsion*>::iterator torsionIter;
524     vector<Inversion*>::iterator inversionIter;
525 gezelter 246 Bond* bond;
526     Bend* bend;
527     Torsion* torsion;
528 gezelter 1277 Inversion* inversion;
529 gezelter 246 int a;
530     int b;
531     int c;
532     int d;
533 tim 749
534 gezelter 1528 map<int, set<int> > atomGroups;
535 tim 749 Molecule::RigidBodyIterator rbIter;
536     RigidBody* rb;
537     Molecule::IntegrableObjectIterator ii;
538     StuntDouble* integrableObject;
539 gezelter 246
540 gezelter 1287 for (integrableObject = mol->beginIntegrableObject(ii);
541     integrableObject != NULL;
542     integrableObject = mol->nextIntegrableObject(ii)) {
543    
544 tim 749 if (integrableObject->isRigidBody()) {
545 gezelter 1287 rb = static_cast<RigidBody*>(integrableObject);
546 gezelter 1528 vector<Atom*> atoms = rb->getAtoms();
547     set<int> rigidAtoms;
548 gezelter 1287 for (int i = 0; i < static_cast<int>(atoms.size()); ++i) {
549     rigidAtoms.insert(atoms[i]->getGlobalIndex());
550     }
551     for (int i = 0; i < static_cast<int>(atoms.size()); ++i) {
552 gezelter 1528 atomGroups.insert(map<int, set<int> >::value_type(atoms[i]->getGlobalIndex(), rigidAtoms));
553 gezelter 1287 }
554 tim 749 } else {
555 gezelter 1528 set<int> oneAtomSet;
556 tim 749 oneAtomSet.insert(integrableObject->getGlobalIndex());
557 gezelter 1528 atomGroups.insert(map<int, set<int> >::value_type(integrableObject->getGlobalIndex(), oneAtomSet));
558 tim 749 }
559     }
560    
561 gezelter 1287 for (bond= mol->beginBond(bondIter); bond != NULL;
562     bond = mol->nextBond(bondIter)) {
563    
564     a = bond->getAtomA()->getGlobalIndex();
565     b = bond->getAtomB()->getGlobalIndex();
566 tim 749
567 gezelter 1287 if (options_.havevdw12scale() || options_.haveelectrostatic12scale()) {
568     oneTwoInteractions_.removePair(a, b);
569     } else {
570     excludedInteractions_.removePair(a, b);
571     }
572 gezelter 2 }
573 gezelter 246
574 gezelter 1287 for (bend= mol->beginBend(bendIter); bend != NULL;
575     bend = mol->nextBend(bendIter)) {
576    
577 gezelter 507 a = bend->getAtomA()->getGlobalIndex();
578     b = bend->getAtomB()->getGlobalIndex();
579     c = bend->getAtomC()->getGlobalIndex();
580 gezelter 1287
581     if (options_.havevdw12scale() || options_.haveelectrostatic12scale()) {
582     oneTwoInteractions_.removePair(a, b);
583     oneTwoInteractions_.removePair(b, c);
584     } else {
585     excludedInteractions_.removePair(a, b);
586     excludedInteractions_.removePair(b, c);
587     }
588 gezelter 246
589 gezelter 1287 if (options_.havevdw13scale() || options_.haveelectrostatic13scale()) {
590     oneThreeInteractions_.removePair(a, c);
591     } else {
592     excludedInteractions_.removePair(a, c);
593     }
594 gezelter 2 }
595 gezelter 246
596 gezelter 1287 for (torsion= mol->beginTorsion(torsionIter); torsion != NULL;
597     torsion = mol->nextTorsion(torsionIter)) {
598    
599 gezelter 507 a = torsion->getAtomA()->getGlobalIndex();
600     b = torsion->getAtomB()->getGlobalIndex();
601     c = torsion->getAtomC()->getGlobalIndex();
602 gezelter 1287 d = torsion->getAtomD()->getGlobalIndex();
603    
604     if (options_.havevdw12scale() || options_.haveelectrostatic12scale()) {
605     oneTwoInteractions_.removePair(a, b);
606     oneTwoInteractions_.removePair(b, c);
607     oneTwoInteractions_.removePair(c, d);
608     } else {
609     excludedInteractions_.removePair(a, b);
610     excludedInteractions_.removePair(b, c);
611     excludedInteractions_.removePair(c, d);
612     }
613 gezelter 246
614 gezelter 1287 if (options_.havevdw13scale() || options_.haveelectrostatic13scale()) {
615     oneThreeInteractions_.removePair(a, c);
616     oneThreeInteractions_.removePair(b, d);
617     } else {
618     excludedInteractions_.removePair(a, c);
619     excludedInteractions_.removePair(b, d);
620     }
621 tim 749
622 gezelter 1287 if (options_.havevdw14scale() || options_.haveelectrostatic14scale()) {
623     oneFourInteractions_.removePair(a, d);
624     } else {
625     excludedInteractions_.removePair(a, d);
626     }
627     }
628 tim 749
629 gezelter 1287 for (inversion= mol->beginInversion(inversionIter); inversion != NULL;
630     inversion = mol->nextInversion(inversionIter)) {
631 tim 749
632 gezelter 1277 a = inversion->getAtomA()->getGlobalIndex();
633     b = inversion->getAtomB()->getGlobalIndex();
634     c = inversion->getAtomC()->getGlobalIndex();
635     d = inversion->getAtomD()->getGlobalIndex();
636    
637 gezelter 1287 if (options_.havevdw12scale() || options_.haveelectrostatic12scale()) {
638     oneTwoInteractions_.removePair(a, b);
639     oneTwoInteractions_.removePair(a, c);
640     oneTwoInteractions_.removePair(a, d);
641     } else {
642     excludedInteractions_.removePair(a, b);
643     excludedInteractions_.removePair(a, c);
644     excludedInteractions_.removePair(a, d);
645     }
646 gezelter 1277
647 gezelter 1287 if (options_.havevdw13scale() || options_.haveelectrostatic13scale()) {
648     oneThreeInteractions_.removePair(b, c);
649     oneThreeInteractions_.removePair(b, d);
650     oneThreeInteractions_.removePair(c, d);
651     } else {
652     excludedInteractions_.removePair(b, c);
653     excludedInteractions_.removePair(b, d);
654     excludedInteractions_.removePair(c, d);
655     }
656 gezelter 1277 }
657    
658 gezelter 1287 for (rb = mol->beginRigidBody(rbIter); rb != NULL;
659     rb = mol->nextRigidBody(rbIter)) {
660 gezelter 1528 vector<Atom*> atoms = rb->getAtoms();
661 gezelter 1287 for (int i = 0; i < static_cast<int>(atoms.size()) -1 ; ++i) {
662     for (int j = i + 1; j < static_cast<int>(atoms.size()); ++j) {
663 gezelter 507 a = atoms[i]->getGlobalIndex();
664     b = atoms[j]->getGlobalIndex();
665 gezelter 1287 excludedInteractions_.removePair(a, b);
666 gezelter 507 }
667     }
668 tim 430 }
669 gezelter 1287
670 gezelter 507 }
671 gezelter 1287
672    
673 gezelter 507 void SimInfo::addMoleculeStamp(MoleculeStamp* molStamp, int nmol) {
674 gezelter 246 int curStampId;
675 gezelter 1287
676 gezelter 246 //index from 0
677     curStampId = moleculeStamps_.size();
678 gezelter 2
679 gezelter 246 moleculeStamps_.push_back(molStamp);
680     molStampIds_.insert(molStampIds_.end(), nmol, curStampId);
681 gezelter 507 }
682 gezelter 2
683 gezelter 1530
684     /**
685     * update
686     *
687 gezelter 1535 * Performs the global checks and variable settings after the
688     * objects have been created.
689 gezelter 1530 *
690     */
691 gezelter 1535 void SimInfo::update() {
692 gezelter 1530 setupSimVariables();
693 gezelter 246 calcNdf();
694     calcNdfRaw();
695     calcNdfTrans();
696 gezelter 507 }
697 gezelter 1528
698 gezelter 1535 /**
699     * getSimulatedAtomTypes
700     *
701     * Returns an STL set of AtomType* that are actually present in this
702     * simulation. Must query all processors to assemble this information.
703     *
704     */
705 gezelter 1528 set<AtomType*> SimInfo::getSimulatedAtomTypes() {
706 gezelter 246 SimInfo::MoleculeIterator mi;
707     Molecule* mol;
708     Molecule::AtomIterator ai;
709     Atom* atom;
710 gezelter 1528 set<AtomType*> atomTypes;
711    
712 gezelter 1588 for(mol = beginMolecule(mi); mol != NULL; mol = nextMolecule(mi)) {
713     for(atom = mol->beginAtom(ai); atom != NULL;
714     atom = mol->nextAtom(ai)) {
715 gezelter 507 atomTypes.insert(atom->getAtomType());
716 gezelter 1529 }
717     }
718 gezelter 1588
719 gezelter 1535 #ifdef IS_MPI
720    
721     // loop over the found atom types on this processor, and add their
722     // numerical idents to a vector:
723 gezelter 1588
724 gezelter 1535 vector<int> foundTypes;
725     set<AtomType*>::iterator i;
726     for (i = atomTypes.begin(); i != atomTypes.end(); ++i)
727     foundTypes.push_back( (*i)->getIdent() );
728    
729     // count_local holds the number of found types on this processor
730     int count_local = foundTypes.size();
731    
732 gezelter 1588 int nproc = MPI::COMM_WORLD.Get_size();
733 gezelter 1535
734 gezelter 1588 // we need arrays to hold the counts and displacement vectors for
735     // all processors
736     vector<int> counts(nproc, 0);
737     vector<int> disps(nproc, 0);
738 gezelter 1535
739 gezelter 1588 // fill the counts array
740     MPI::COMM_WORLD.Allgather(&count_local, 1, MPI::INT, &counts[0],
741     1, MPI::INT);
742    
743     // use the processor counts to compute the displacement array
744     disps[0] = 0;
745     int totalCount = counts[0];
746     for (int iproc = 1; iproc < nproc; iproc++) {
747     disps[iproc] = disps[iproc-1] + counts[iproc-1];
748     totalCount += counts[iproc];
749     }
750 gezelter 1535
751 gezelter 1588 // we need a (possibly redundant) set of all found types:
752     vector<int> ftGlobal(totalCount);
753 gezelter 2
754 gezelter 1588 // now spray out the foundTypes to all the other processors:
755 gezelter 1535 MPI::COMM_WORLD.Allgatherv(&foundTypes[0], count_local, MPI::INT,
756 gezelter 1588 &ftGlobal[0], &counts[0], &disps[0],
757     MPI::INT);
758 gezelter 1126
759 gezelter 1588 vector<int>::iterator j;
760    
761 gezelter 1535 // foundIdents is a stl set, so inserting an already found ident
762     // will have no effect.
763     set<int> foundIdents;
764 gezelter 1588
765 gezelter 1535 for (j = ftGlobal.begin(); j != ftGlobal.end(); ++j)
766     foundIdents.insert((*j));
767 gezelter 1528
768 gezelter 1535 // now iterate over the foundIdents and get the actual atom types
769     // that correspond to these:
770     set<int>::iterator it;
771 gezelter 1588 for (it = foundIdents.begin(); it != foundIdents.end(); ++it)
772 gezelter 1535 atomTypes.insert( forceField_->getAtomType((*it)) );
773    
774     #endif
775 gezelter 1588
776 gezelter 1535 return atomTypes;
777 gezelter 1528 }
778 chrisfen 611
779 gezelter 1534 void SimInfo::setupSimVariables() {
780     useAtomicVirial_ = simParams_->getUseAtomicVirial();
781     // we only call setAccumulateBoxDipole if the accumulateBoxDipole parameter is true
782     calcBoxDipole_ = false;
783     if ( simParams_->haveAccumulateBoxDipole() )
784     if ( simParams_->getAccumulateBoxDipole() ) {
785     calcBoxDipole_ = true;
786     }
787 gezelter 1583
788 gezelter 1528 set<AtomType*>::iterator i;
789     set<AtomType*> atomTypes;
790 gezelter 1534 atomTypes = getSimulatedAtomTypes();
791 gezelter 1528 int usesElectrostatic = 0;
792     int usesMetallic = 0;
793     int usesDirectional = 0;
794 gezelter 1715 int usesFluctuatingCharges = 0;
795 gezelter 246 //loop over all of the atom types
796     for (i = atomTypes.begin(); i != atomTypes.end(); ++i) {
797 gezelter 1528 usesElectrostatic |= (*i)->isElectrostatic();
798     usesMetallic |= (*i)->isMetal();
799     usesDirectional |= (*i)->isDirectional();
800 gezelter 1715 usesFluctuatingCharges |= (*i)->isFluctuatingCharge();
801 gezelter 246 }
802 gezelter 1583
803 gezelter 246 #ifdef IS_MPI
804     int temp;
805 gezelter 1528 temp = usesDirectional;
806     MPI_Allreduce(&temp, &usesDirectionalAtoms_, 1, MPI_INT, MPI_LOR, MPI_COMM_WORLD);
807 gezelter 1583
808 gezelter 1528 temp = usesMetallic;
809     MPI_Allreduce(&temp, &usesMetallicAtoms_, 1, MPI_INT, MPI_LOR, MPI_COMM_WORLD);
810 gezelter 1583
811 gezelter 1528 temp = usesElectrostatic;
812     MPI_Allreduce(&temp, &usesElectrostaticAtoms_, 1, MPI_INT, MPI_LOR, MPI_COMM_WORLD);
813 gezelter 1715
814     temp = usesFluctuatingCharges;
815     MPI_Allreduce(&temp, &usesFluctuatingCharges_, 1, MPI_INT, MPI_LOR, MPI_COMM_WORLD);
816 gezelter 1583 #else
817    
818     usesDirectionalAtoms_ = usesDirectional;
819     usesMetallicAtoms_ = usesMetallic;
820     usesElectrostaticAtoms_ = usesElectrostatic;
821 gezelter 1715 usesFluctuatingCharges_ = usesFluctuatingCharges;
822 gezelter 1583
823 gezelter 2 #endif
824 gezelter 1583
825     requiresPrepair_ = usesMetallicAtoms_ ? true : false;
826     requiresSkipCorrection_ = usesElectrostaticAtoms_ ? true : false;
827     requiresSelfCorrection_ = usesElectrostaticAtoms_ ? true : false;
828 gezelter 507 }
829 gezelter 2
830 gezelter 1549
831     vector<int> SimInfo::getGlobalAtomIndices() {
832     SimInfo::MoleculeIterator mi;
833     Molecule* mol;
834     Molecule::AtomIterator ai;
835     Atom* atom;
836    
837     vector<int> GlobalAtomIndices(getNAtoms(), 0);
838    
839     for (mol = beginMolecule(mi); mol != NULL; mol = nextMolecule(mi)) {
840    
841     for (atom = mol->beginAtom(ai); atom != NULL; atom = mol->nextAtom(ai)) {
842     GlobalAtomIndices[atom->getLocalIndex()] = atom->getGlobalIndex();
843     }
844     }
845     return GlobalAtomIndices;
846     }
847    
848    
849     vector<int> SimInfo::getGlobalGroupIndices() {
850     SimInfo::MoleculeIterator mi;
851     Molecule* mol;
852     Molecule::CutoffGroupIterator ci;
853     CutoffGroup* cg;
854    
855     vector<int> GlobalGroupIndices;
856    
857     for (mol = beginMolecule(mi); mol != NULL; mol = nextMolecule(mi)) {
858    
859     //local index of cutoff group is trivial, it only depends on the
860     //order of travesing
861     for (cg = mol->beginCutoffGroup(ci); cg != NULL;
862     cg = mol->nextCutoffGroup(ci)) {
863     GlobalGroupIndices.push_back(cg->getGlobalIndex());
864     }
865     }
866     return GlobalGroupIndices;
867     }
868    
869    
870 gezelter 1569 void SimInfo::prepareTopology() {
871 gezelter 1287 int nExclude, nOneTwo, nOneThree, nOneFour;
872 gezelter 2
873 gezelter 246 //calculate mass ratio of cutoff group
874     SimInfo::MoleculeIterator mi;
875     Molecule* mol;
876     Molecule::CutoffGroupIterator ci;
877     CutoffGroup* cg;
878     Molecule::AtomIterator ai;
879     Atom* atom;
880 tim 963 RealType totalMass;
881 gezelter 246
882 gezelter 1581 /**
883     * The mass factor is the relative mass of an atom to the total
884     * mass of the cutoff group it belongs to. By default, all atoms
885     * are their own cutoff groups, and therefore have mass factors of
886     * 1. We need some special handling for massless atoms, which
887     * will be treated as carrying the entire mass of the cutoff
888     * group.
889     */
890 gezelter 1569 massFactors_.clear();
891 gezelter 1581 massFactors_.resize(getNAtoms(), 1.0);
892 gezelter 2
893 gezelter 246 for(mol = beginMolecule(mi); mol != NULL; mol = nextMolecule(mi)) {
894 gezelter 1569 for (cg = mol->beginCutoffGroup(ci); cg != NULL;
895     cg = mol->nextCutoffGroup(ci)) {
896 gezelter 2
897 gezelter 507 totalMass = cg->getMass();
898     for(atom = cg->beginAtom(ai); atom != NULL; atom = cg->nextAtom(ai)) {
899 chrisfen 645 // Check for massless groups - set mfact to 1 if true
900 gezelter 1581 if (totalMass != 0)
901     massFactors_[atom->getLocalIndex()] = atom->getMass()/totalMass;
902 chrisfen 645 else
903 gezelter 1581 massFactors_[atom->getLocalIndex()] = 1.0;
904 gezelter 507 }
905     }
906 gezelter 246 }
907 gezelter 2
908 gezelter 1544 // Build the identArray_
909 gezelter 2
910 gezelter 1544 identArray_.clear();
911     identArray_.reserve(getNAtoms());
912 gezelter 246 for(mol = beginMolecule(mi); mol != NULL; mol = nextMolecule(mi)) {
913 gezelter 507 for(atom = mol->beginAtom(ai); atom != NULL; atom = mol->nextAtom(ai)) {
914 gezelter 1544 identArray_.push_back(atom->getIdent());
915 gezelter 507 }
916 gezelter 246 }
917    
918 gezelter 1569 //scan topology
919 gezelter 1287
920     nExclude = excludedInteractions_.getSize();
921     nOneTwo = oneTwoInteractions_.getSize();
922     nOneThree = oneThreeInteractions_.getSize();
923     nOneFour = oneFourInteractions_.getSize();
924    
925     int* excludeList = excludedInteractions_.getPairList();
926     int* oneTwoList = oneTwoInteractions_.getPairList();
927     int* oneThreeList = oneThreeInteractions_.getPairList();
928     int* oneFourList = oneFourInteractions_.getPairList();
929    
930 gezelter 1569 topologyDone_ = true;
931 gezelter 507 }
932 chrisfen 143
933 gezelter 507 void SimInfo::addProperty(GenericData* genData) {
934 gezelter 246 properties_.addProperty(genData);
935 gezelter 507 }
936 gezelter 2
937 gezelter 1528 void SimInfo::removeProperty(const string& propName) {
938 gezelter 246 properties_.removeProperty(propName);
939 gezelter 507 }
940 gezelter 2
941 gezelter 507 void SimInfo::clearProperties() {
942 gezelter 246 properties_.clearProperties();
943 gezelter 507 }
944 gezelter 2
945 gezelter 1528 vector<string> SimInfo::getPropertyNames() {
946 gezelter 246 return properties_.getPropertyNames();
947 gezelter 507 }
948 gezelter 246
949 gezelter 1528 vector<GenericData*> SimInfo::getProperties() {
950 gezelter 246 return properties_.getProperties();
951 gezelter 507 }
952 gezelter 2
953 gezelter 1528 GenericData* SimInfo::getPropertyByName(const string& propName) {
954 gezelter 246 return properties_.getPropertyByName(propName);
955 gezelter 507 }
956 gezelter 2
957 gezelter 507 void SimInfo::setSnapshotManager(SnapshotManager* sman) {
958 tim 432 if (sman_ == sman) {
959 gezelter 507 return;
960 tim 432 }
961     delete sman_;
962 gezelter 246 sman_ = sman;
963 gezelter 2
964 gezelter 246 Molecule* mol;
965     RigidBody* rb;
966     Atom* atom;
967 gezelter 1540 CutoffGroup* cg;
968 gezelter 246 SimInfo::MoleculeIterator mi;
969     Molecule::RigidBodyIterator rbIter;
970 gezelter 1540 Molecule::AtomIterator atomIter;
971     Molecule::CutoffGroupIterator cgIter;
972 gezelter 246
973     for (mol = beginMolecule(mi); mol != NULL; mol = nextMolecule(mi)) {
974    
975 gezelter 507 for (atom = mol->beginAtom(atomIter); atom != NULL; atom = mol->nextAtom(atomIter)) {
976     atom->setSnapshotManager(sman_);
977     }
978 gezelter 246
979 gezelter 507 for (rb = mol->beginRigidBody(rbIter); rb != NULL; rb = mol->nextRigidBody(rbIter)) {
980     rb->setSnapshotManager(sman_);
981     }
982 gezelter 1540
983     for (cg = mol->beginCutoffGroup(cgIter); cg != NULL; cg = mol->nextCutoffGroup(cgIter)) {
984     cg->setSnapshotManager(sman_);
985     }
986 gezelter 246 }
987 gezelter 2
988 gezelter 507 }
989 gezelter 2
990 gezelter 507 Vector3d SimInfo::getComVel(){
991 gezelter 246 SimInfo::MoleculeIterator i;
992     Molecule* mol;
993 gezelter 2
994 gezelter 246 Vector3d comVel(0.0);
995 tim 963 RealType totalMass = 0.0;
996 gezelter 2
997 gezelter 246
998     for (mol = beginMolecule(i); mol != NULL; mol = nextMolecule(i)) {
999 tim 963 RealType mass = mol->getMass();
1000 gezelter 507 totalMass += mass;
1001     comVel += mass * mol->getComVel();
1002 gezelter 246 }
1003 gezelter 2
1004 gezelter 246 #ifdef IS_MPI
1005 tim 963 RealType tmpMass = totalMass;
1006 gezelter 246 Vector3d tmpComVel(comVel);
1007 tim 963 MPI_Allreduce(&tmpMass,&totalMass,1,MPI_REALTYPE,MPI_SUM, MPI_COMM_WORLD);
1008     MPI_Allreduce(tmpComVel.getArrayPointer(), comVel.getArrayPointer(),3,MPI_REALTYPE,MPI_SUM, MPI_COMM_WORLD);
1009 gezelter 246 #endif
1010    
1011     comVel /= totalMass;
1012    
1013     return comVel;
1014 gezelter 507 }
1015 gezelter 2
1016 gezelter 507 Vector3d SimInfo::getCom(){
1017 gezelter 246 SimInfo::MoleculeIterator i;
1018     Molecule* mol;
1019 gezelter 2
1020 gezelter 246 Vector3d com(0.0);
1021 tim 963 RealType totalMass = 0.0;
1022 gezelter 246
1023     for (mol = beginMolecule(i); mol != NULL; mol = nextMolecule(i)) {
1024 tim 963 RealType mass = mol->getMass();
1025 gezelter 507 totalMass += mass;
1026     com += mass * mol->getCom();
1027 gezelter 246 }
1028 gezelter 2
1029     #ifdef IS_MPI
1030 tim 963 RealType tmpMass = totalMass;
1031 gezelter 246 Vector3d tmpCom(com);
1032 tim 963 MPI_Allreduce(&tmpMass,&totalMass,1,MPI_REALTYPE,MPI_SUM, MPI_COMM_WORLD);
1033     MPI_Allreduce(tmpCom.getArrayPointer(), com.getArrayPointer(),3,MPI_REALTYPE,MPI_SUM, MPI_COMM_WORLD);
1034 gezelter 2 #endif
1035    
1036 gezelter 246 com /= totalMass;
1037 gezelter 2
1038 gezelter 246 return com;
1039 gezelter 2
1040 gezelter 507 }
1041 gezelter 246
1042 gezelter 1528 ostream& operator <<(ostream& o, SimInfo& info) {
1043 gezelter 246
1044     return o;
1045 gezelter 507 }
1046 chuckv 555
1047    
1048     /*
1049     Returns center of mass and center of mass velocity in one function call.
1050     */
1051    
1052     void SimInfo::getComAll(Vector3d &com, Vector3d &comVel){
1053     SimInfo::MoleculeIterator i;
1054     Molecule* mol;
1055    
1056    
1057 tim 963 RealType totalMass = 0.0;
1058 chuckv 555
1059 gezelter 246
1060 chuckv 555 for (mol = beginMolecule(i); mol != NULL; mol = nextMolecule(i)) {
1061 tim 963 RealType mass = mol->getMass();
1062 chuckv 555 totalMass += mass;
1063     com += mass * mol->getCom();
1064     comVel += mass * mol->getComVel();
1065     }
1066    
1067     #ifdef IS_MPI
1068 tim 963 RealType tmpMass = totalMass;
1069 chuckv 555 Vector3d tmpCom(com);
1070     Vector3d tmpComVel(comVel);
1071 tim 963 MPI_Allreduce(&tmpMass,&totalMass,1,MPI_REALTYPE,MPI_SUM, MPI_COMM_WORLD);
1072     MPI_Allreduce(tmpCom.getArrayPointer(), com.getArrayPointer(),3,MPI_REALTYPE,MPI_SUM, MPI_COMM_WORLD);
1073     MPI_Allreduce(tmpComVel.getArrayPointer(), comVel.getArrayPointer(),3,MPI_REALTYPE,MPI_SUM, MPI_COMM_WORLD);
1074 chuckv 555 #endif
1075    
1076     com /= totalMass;
1077     comVel /= totalMass;
1078     }
1079    
1080     /*
1081     Return intertia tensor for entire system and angular momentum Vector.
1082 chuckv 557
1083    
1084     [ Ixx -Ixy -Ixz ]
1085 gezelter 1505 J =| -Iyx Iyy -Iyz |
1086 chuckv 557 [ -Izx -Iyz Izz ]
1087 chuckv 555 */
1088    
1089     void SimInfo::getInertiaTensor(Mat3x3d &inertiaTensor, Vector3d &angularMomentum){
1090    
1091    
1092 tim 963 RealType xx = 0.0;
1093     RealType yy = 0.0;
1094     RealType zz = 0.0;
1095     RealType xy = 0.0;
1096     RealType xz = 0.0;
1097     RealType yz = 0.0;
1098 chuckv 555 Vector3d com(0.0);
1099     Vector3d comVel(0.0);
1100    
1101     getComAll(com, comVel);
1102    
1103     SimInfo::MoleculeIterator i;
1104     Molecule* mol;
1105    
1106     Vector3d thisq(0.0);
1107     Vector3d thisv(0.0);
1108    
1109 tim 963 RealType thisMass = 0.0;
1110 chuckv 555
1111    
1112    
1113    
1114     for (mol = beginMolecule(i); mol != NULL; mol = nextMolecule(i)) {
1115    
1116     thisq = mol->getCom()-com;
1117     thisv = mol->getComVel()-comVel;
1118     thisMass = mol->getMass();
1119     // Compute moment of intertia coefficients.
1120     xx += thisq[0]*thisq[0]*thisMass;
1121     yy += thisq[1]*thisq[1]*thisMass;
1122     zz += thisq[2]*thisq[2]*thisMass;
1123    
1124     // compute products of intertia
1125     xy += thisq[0]*thisq[1]*thisMass;
1126     xz += thisq[0]*thisq[2]*thisMass;
1127     yz += thisq[1]*thisq[2]*thisMass;
1128    
1129     angularMomentum += cross( thisq, thisv ) * thisMass;
1130    
1131     }
1132    
1133    
1134     inertiaTensor(0,0) = yy + zz;
1135     inertiaTensor(0,1) = -xy;
1136     inertiaTensor(0,2) = -xz;
1137     inertiaTensor(1,0) = -xy;
1138 chuckv 557 inertiaTensor(1,1) = xx + zz;
1139 chuckv 555 inertiaTensor(1,2) = -yz;
1140     inertiaTensor(2,0) = -xz;
1141     inertiaTensor(2,1) = -yz;
1142     inertiaTensor(2,2) = xx + yy;
1143    
1144     #ifdef IS_MPI
1145     Mat3x3d tmpI(inertiaTensor);
1146     Vector3d tmpAngMom;
1147 tim 963 MPI_Allreduce(tmpI.getArrayPointer(), inertiaTensor.getArrayPointer(),9,MPI_REALTYPE,MPI_SUM, MPI_COMM_WORLD);
1148     MPI_Allreduce(tmpAngMom.getArrayPointer(), angularMomentum.getArrayPointer(),3,MPI_REALTYPE,MPI_SUM, MPI_COMM_WORLD);
1149 chuckv 555 #endif
1150    
1151     return;
1152     }
1153    
1154     //Returns the angular momentum of the system
1155     Vector3d SimInfo::getAngularMomentum(){
1156    
1157     Vector3d com(0.0);
1158     Vector3d comVel(0.0);
1159     Vector3d angularMomentum(0.0);
1160    
1161     getComAll(com,comVel);
1162    
1163     SimInfo::MoleculeIterator i;
1164     Molecule* mol;
1165    
1166 chuckv 557 Vector3d thisr(0.0);
1167     Vector3d thisp(0.0);
1168 chuckv 555
1169 tim 963 RealType thisMass;
1170 chuckv 555
1171     for (mol = beginMolecule(i); mol != NULL; mol = nextMolecule(i)) {
1172 chuckv 557 thisMass = mol->getMass();
1173     thisr = mol->getCom()-com;
1174     thisp = (mol->getComVel()-comVel)*thisMass;
1175 chuckv 555
1176 chuckv 557 angularMomentum += cross( thisr, thisp );
1177    
1178 chuckv 555 }
1179    
1180     #ifdef IS_MPI
1181     Vector3d tmpAngMom;
1182 tim 963 MPI_Allreduce(tmpAngMom.getArrayPointer(), angularMomentum.getArrayPointer(),3,MPI_REALTYPE,MPI_SUM, MPI_COMM_WORLD);
1183 chuckv 555 #endif
1184    
1185     return angularMomentum;
1186     }
1187    
1188 tim 1024 StuntDouble* SimInfo::getIOIndexToIntegrableObject(int index) {
1189     return IOIndexToIntegrableObject.at(index);
1190     }
1191    
1192 gezelter 1528 void SimInfo::setIOIndexToIntegrableObject(const vector<StuntDouble*>& v) {
1193 tim 1024 IOIndexToIntegrableObject= v;
1194     }
1195    
1196 chuckv 1103 /* Returns the Volume of the simulation based on a ellipsoid with semi-axes
1197     based on the radius of gyration V=4/3*Pi*R_1*R_2*R_3
1198     where R_i are related to the principle inertia moments R_i = sqrt(C*I_i/N), this reduces to
1199     V = 4/3*Pi*(C/N)^3/2*sqrt(det(I)). See S.E. Baltazar et. al. Comp. Mat. Sci. 37 (2006) 526-536.
1200     */
1201     void SimInfo::getGyrationalVolume(RealType &volume){
1202     Mat3x3d intTensor;
1203     RealType det;
1204     Vector3d dummyAngMom;
1205     RealType sysconstants;
1206     RealType geomCnst;
1207    
1208     geomCnst = 3.0/2.0;
1209     /* Get the inertial tensor and angular momentum for free*/
1210     getInertiaTensor(intTensor,dummyAngMom);
1211    
1212     det = intTensor.determinant();
1213     sysconstants = geomCnst/(RealType)nGlobalIntegrableObjects_;
1214 gezelter 1668 volume = 4.0/3.0*NumericConstant::PI*pow(sysconstants,geomCnst)*sqrt(det);
1215 chuckv 1103 return;
1216     }
1217    
1218     void SimInfo::getGyrationalVolume(RealType &volume, RealType &detI){
1219     Mat3x3d intTensor;
1220     Vector3d dummyAngMom;
1221     RealType sysconstants;
1222     RealType geomCnst;
1223    
1224     geomCnst = 3.0/2.0;
1225     /* Get the inertial tensor and angular momentum for free*/
1226     getInertiaTensor(intTensor,dummyAngMom);
1227    
1228     detI = intTensor.determinant();
1229     sysconstants = geomCnst/(RealType)nGlobalIntegrableObjects_;
1230 gezelter 1668 volume = 4.0/3.0*NumericConstant::PI*pow(sysconstants,geomCnst)*sqrt(detI);
1231 chuckv 1103 return;
1232     }
1233 tim 1024 /*
1234 gezelter 1528 void SimInfo::setStuntDoubleFromGlobalIndex(vector<StuntDouble*> v) {
1235 tim 1024 assert( v.size() == nAtoms_ + nRigidBodies_);
1236     sdByGlobalIndex_ = v;
1237     }
1238    
1239     StuntDouble* SimInfo::getStuntDoubleFromGlobalIndex(int index) {
1240     //assert(index < nAtoms_ + nRigidBodies_);
1241     return sdByGlobalIndex_.at(index);
1242     }
1243     */
1244 gezelter 1528 int SimInfo::getNGlobalConstraints() {
1245     int nGlobalConstraints;
1246     #ifdef IS_MPI
1247     MPI_Allreduce(&nConstraints_, &nGlobalConstraints, 1, MPI_INT, MPI_SUM,
1248     MPI_COMM_WORLD);
1249     #else
1250     nGlobalConstraints = nConstraints_;
1251     #endif
1252     return nGlobalConstraints;
1253     }
1254    
1255 gezelter 1390 }//end namespace OpenMD
1256 gezelter 246

Properties

Name Value
svn:keywords Author Id Revision Date