ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/OpenMD/branches/development/src/brains/SimInfo.cpp
Revision: 1715
Committed: Tue May 22 21:55:31 2012 UTC (12 years, 11 months ago) by gezelter
File size: 39587 byte(s)
Log Message:
Adding more support structure for Fluctuating Charges.

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     #include "UseTheForce/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