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

# Content
1 /*
2 * 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 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 *
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * 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 *
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 * [4] Kuang & Gezelter, J. Chem. Phys. 133, 164101 (2010).
40 * [5] Vardeman, Stocker & Gezelter, J. Chem. Theory Comput. 7, 834 (2011).
41 */
42
43 /**
44 * @file SimInfo.cpp
45 * @author tlin
46 * @date 11/02/2004
47 * @version 1.0
48 */
49
50 #include <algorithm>
51 #include <set>
52 #include <map>
53
54 #include "brains/SimInfo.hpp"
55 #include "math/Vector3.hpp"
56 #include "primitives/Molecule.hpp"
57 #include "primitives/StuntDouble.hpp"
58 #include "utils/MemoryUtils.hpp"
59 #include "utils/simError.h"
60 #include "selection/SelectionManager.hpp"
61 #include "io/ForceFieldOptions.hpp"
62 #include "brains/ForceField.hpp"
63 #include "nonbonded/SwitchingFunction.hpp"
64 #ifdef IS_MPI
65 #include <mpi.h>
66 #endif
67
68 using namespace std;
69 namespace OpenMD {
70
71 SimInfo::SimInfo(ForceField* ff, Globals* simParams) :
72 forceField_(ff), simParams_(simParams),
73 ndf_(0), fdf_local(0), ndfRaw_(0), ndfTrans_(0), nZconstraint_(0),
74 nGlobalMols_(0), nGlobalAtoms_(0), nGlobalCutoffGroups_(0),
75 nGlobalIntegrableObjects_(0), nGlobalRigidBodies_(0), nGlobalFluctuatingCharges_(0),
76 nAtoms_(0), nBonds_(0), nBends_(0), nTorsions_(0), nInversions_(0),
77 nRigidBodies_(0), nIntegrableObjects_(0), nCutoffGroups_(0),
78 nConstraints_(0), nFluctuatingCharges_(0), sman_(NULL), topologyDone_(false),
79 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
95 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 }
108
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
133 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
147 SimInfo::~SimInfo() {
148 map<int, Molecule*>::iterator i;
149 for (i = molecules_.begin(); i != molecules_.end(); ++i) {
150 delete i->second;
151 }
152 molecules_.clear();
153
154 delete sman_;
155 delete simParams_;
156 delete forceField_;
157 }
158
159
160 bool SimInfo::addMolecule(Molecule* mol) {
161 MoleculeIterator i;
162
163 i = molecules_.find(mol->getGlobalIndex());
164 if (i == molecules_.end() ) {
165
166 molecules_.insert(make_pair(mol->getGlobalIndex(), mol));
167
168 nAtoms_ += mol->getNAtoms();
169 nBonds_ += mol->getNBonds();
170 nBends_ += mol->getNBends();
171 nTorsions_ += mol->getNTorsions();
172 nInversions_ += mol->getNInversions();
173 nRigidBodies_ += mol->getNRigidBodies();
174 nIntegrableObjects_ += mol->getNIntegrableObjects();
175 nCutoffGroups_ += mol->getNCutoffGroups();
176 nConstraints_ += mol->getNConstraintPairs();
177
178 addInteractionPairs(mol);
179
180 return true;
181 } else {
182 return false;
183 }
184 }
185
186 bool SimInfo::removeMolecule(Molecule* mol) {
187 MoleculeIterator i;
188 i = molecules_.find(mol->getGlobalIndex());
189
190 if (i != molecules_.end() ) {
191
192 assert(mol == i->second);
193
194 nAtoms_ -= mol->getNAtoms();
195 nBonds_ -= mol->getNBonds();
196 nBends_ -= mol->getNBends();
197 nTorsions_ -= mol->getNTorsions();
198 nInversions_ -= mol->getNInversions();
199 nRigidBodies_ -= mol->getNRigidBodies();
200 nIntegrableObjects_ -= mol->getNIntegrableObjects();
201 nCutoffGroups_ -= mol->getNCutoffGroups();
202 nConstraints_ -= mol->getNConstraintPairs();
203
204 removeInteractionPairs(mol);
205 molecules_.erase(mol->getGlobalIndex());
206
207 delete mol;
208
209 return true;
210 } else {
211 return false;
212 }
213 }
214
215
216 Molecule* SimInfo::beginMolecule(MoleculeIterator& i) {
217 i = molecules_.begin();
218 return i == molecules_.end() ? NULL : i->second;
219 }
220
221 Molecule* SimInfo::nextMolecule(MoleculeIterator& i) {
222 ++i;
223 return i == molecules_.end() ? NULL : i->second;
224 }
225
226
227 void SimInfo::calcNdf() {
228 int ndf_local, nfq_local;
229 MoleculeIterator i;
230 vector<StuntDouble*>::iterator j;
231 vector<Atom*>::iterator k;
232
233 Molecule* mol;
234 StuntDouble* integrableObject;
235 Atom* atom;
236
237 ndf_local = 0;
238 nfq_local = 0;
239
240 for (mol = beginMolecule(i); mol != NULL; mol = nextMolecule(i)) {
241 for (integrableObject = mol->beginIntegrableObject(j); integrableObject != NULL;
242 integrableObject = mol->nextIntegrableObject(j)) {
243
244 ndf_local += 3;
245
246 if (integrableObject->isDirectional()) {
247 if (integrableObject->isLinear()) {
248 ndf_local += 2;
249 } else {
250 ndf_local += 3;
251 }
252 }
253 }
254 for (atom = mol->beginFluctuatingCharge(k); atom != NULL;
255 atom = mol->nextFluctuatingCharge(k)) {
256 if (atom->isFluctuatingCharge()) {
257 nfq_local++;
258 }
259 }
260 }
261
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 MPI_Allreduce(&nfq_local,&nGlobalFluctuatingCharges_,1, MPI_INT, MPI_SUM, MPI_COMM_WORLD);
268 #else
269 ndf_ = ndf_local;
270 nGlobalFluctuatingCharges_ = nfq_local;
271 #endif
272
273 // nZconstraints_ is global, as are the 3 COM translations for the
274 // entire system:
275 ndf_ = ndf_ - 3 - nZconstraint_;
276
277 }
278
279 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
288 unsigned int SimInfo::getNLocalCutoffGroups(){
289 int nLocalCutoffAtoms = 0;
290 Molecule* mol;
291 MoleculeIterator mi;
292 CutoffGroup* cg;
293 Molecule::CutoffGroupIterator ci;
294
295 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 void SimInfo::calcNdfRaw() {
308 int ndfRaw_local;
309
310 MoleculeIterator i;
311 vector<StuntDouble*>::iterator j;
312 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 for (integrableObject = mol->beginIntegrableObject(j); integrableObject != NULL;
320 integrableObject = mol->nextIntegrableObject(j)) {
321
322 ndfRaw_local += 3;
323
324 if (integrableObject->isDirectional()) {
325 if (integrableObject->isLinear()) {
326 ndfRaw_local += 2;
327 } else {
328 ndfRaw_local += 3;
329 }
330 }
331
332 }
333 }
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 }
341
342 void SimInfo::calcNdfTrans() {
343 int ndfTrans_local;
344
345 ndfTrans_local = 3 * nIntegrableObjects_ - nConstraints_;
346
347
348 #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
354 ndfTrans_ = ndfTrans_ - 3 - nZconstraint_;
355
356 }
357
358 void SimInfo::addInteractionPairs(Molecule* mol) {
359 ForceFieldOptions& options_ = forceField_->getForceFieldOptions();
360 vector<Bond*>::iterator bondIter;
361 vector<Bend*>::iterator bendIter;
362 vector<Torsion*>::iterator torsionIter;
363 vector<Inversion*>::iterator inversionIter;
364 Bond* bond;
365 Bend* bend;
366 Torsion* torsion;
367 Inversion* inversion;
368 int a;
369 int b;
370 int c;
371 int d;
372
373 // 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 map<int, set<int> > atomGroups;
382 Molecule::RigidBodyIterator rbIter;
383 RigidBody* rb;
384 Molecule::IntegrableObjectIterator ii;
385 StuntDouble* integrableObject;
386
387 for (integrableObject = mol->beginIntegrableObject(ii);
388 integrableObject != NULL;
389 integrableObject = mol->nextIntegrableObject(ii)) {
390
391 if (integrableObject->isRigidBody()) {
392 rb = static_cast<RigidBody*>(integrableObject);
393 vector<Atom*> atoms = rb->getAtoms();
394 set<int> rigidAtoms;
395 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 atomGroups.insert(map<int, set<int> >::value_type(atoms[i]->getGlobalIndex(), rigidAtoms));
400 }
401 } else {
402 set<int> oneAtomSet;
403 oneAtomSet.insert(integrableObject->getGlobalIndex());
404 atomGroups.insert(map<int, set<int> >::value_type(integrableObject->getGlobalIndex(), oneAtomSet));
405 }
406 }
407
408 for (bond= mol->beginBond(bondIter); bond != NULL;
409 bond = mol->nextBond(bondIter)) {
410
411 a = bond->getAtomA()->getGlobalIndex();
412 b = bond->getAtomB()->getGlobalIndex();
413
414 if (options_.havevdw12scale() || options_.haveelectrostatic12scale()) {
415 oneTwoInteractions_.addPair(a, b);
416 } else {
417 excludedInteractions_.addPair(a, b);
418 }
419 }
420
421 for (bend= mol->beginBend(bendIter); bend != NULL;
422 bend = mol->nextBend(bendIter)) {
423
424 a = bend->getAtomA()->getGlobalIndex();
425 b = bend->getAtomB()->getGlobalIndex();
426 c = bend->getAtomC()->getGlobalIndex();
427
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
436 if (options_.havevdw13scale() || options_.haveelectrostatic13scale()) {
437 oneThreeInteractions_.addPair(a, c);
438 } else {
439 excludedInteractions_.addPair(a, c);
440 }
441 }
442
443 for (torsion= mol->beginTorsion(torsionIter); torsion != NULL;
444 torsion = mol->nextTorsion(torsionIter)) {
445
446 a = torsion->getAtomA()->getGlobalIndex();
447 b = torsion->getAtomB()->getGlobalIndex();
448 c = torsion->getAtomC()->getGlobalIndex();
449 d = torsion->getAtomD()->getGlobalIndex();
450
451 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
461 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
469 if (options_.havevdw14scale() || options_.haveelectrostatic14scale()) {
470 oneFourInteractions_.addPair(a, d);
471 } else {
472 excludedInteractions_.addPair(a, d);
473 }
474 }
475
476 for (inversion= mol->beginInversion(inversionIter); inversion != NULL;
477 inversion = mol->nextInversion(inversionIter)) {
478
479 a = inversion->getAtomA()->getGlobalIndex();
480 b = inversion->getAtomB()->getGlobalIndex();
481 c = inversion->getAtomC()->getGlobalIndex();
482 d = inversion->getAtomD()->getGlobalIndex();
483
484 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
494 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 }
504
505 for (rb = mol->beginRigidBody(rbIter); rb != NULL;
506 rb = mol->nextRigidBody(rbIter)) {
507 vector<Atom*> atoms = rb->getAtoms();
508 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 a = atoms[i]->getGlobalIndex();
511 b = atoms[j]->getGlobalIndex();
512 excludedInteractions_.addPair(a, b);
513 }
514 }
515 }
516
517 }
518
519 void SimInfo::removeInteractionPairs(Molecule* mol) {
520 ForceFieldOptions& options_ = forceField_->getForceFieldOptions();
521 vector<Bond*>::iterator bondIter;
522 vector<Bend*>::iterator bendIter;
523 vector<Torsion*>::iterator torsionIter;
524 vector<Inversion*>::iterator inversionIter;
525 Bond* bond;
526 Bend* bend;
527 Torsion* torsion;
528 Inversion* inversion;
529 int a;
530 int b;
531 int c;
532 int d;
533
534 map<int, set<int> > atomGroups;
535 Molecule::RigidBodyIterator rbIter;
536 RigidBody* rb;
537 Molecule::IntegrableObjectIterator ii;
538 StuntDouble* integrableObject;
539
540 for (integrableObject = mol->beginIntegrableObject(ii);
541 integrableObject != NULL;
542 integrableObject = mol->nextIntegrableObject(ii)) {
543
544 if (integrableObject->isRigidBody()) {
545 rb = static_cast<RigidBody*>(integrableObject);
546 vector<Atom*> atoms = rb->getAtoms();
547 set<int> rigidAtoms;
548 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 atomGroups.insert(map<int, set<int> >::value_type(atoms[i]->getGlobalIndex(), rigidAtoms));
553 }
554 } else {
555 set<int> oneAtomSet;
556 oneAtomSet.insert(integrableObject->getGlobalIndex());
557 atomGroups.insert(map<int, set<int> >::value_type(integrableObject->getGlobalIndex(), oneAtomSet));
558 }
559 }
560
561 for (bond= mol->beginBond(bondIter); bond != NULL;
562 bond = mol->nextBond(bondIter)) {
563
564 a = bond->getAtomA()->getGlobalIndex();
565 b = bond->getAtomB()->getGlobalIndex();
566
567 if (options_.havevdw12scale() || options_.haveelectrostatic12scale()) {
568 oneTwoInteractions_.removePair(a, b);
569 } else {
570 excludedInteractions_.removePair(a, b);
571 }
572 }
573
574 for (bend= mol->beginBend(bendIter); bend != NULL;
575 bend = mol->nextBend(bendIter)) {
576
577 a = bend->getAtomA()->getGlobalIndex();
578 b = bend->getAtomB()->getGlobalIndex();
579 c = bend->getAtomC()->getGlobalIndex();
580
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
589 if (options_.havevdw13scale() || options_.haveelectrostatic13scale()) {
590 oneThreeInteractions_.removePair(a, c);
591 } else {
592 excludedInteractions_.removePair(a, c);
593 }
594 }
595
596 for (torsion= mol->beginTorsion(torsionIter); torsion != NULL;
597 torsion = mol->nextTorsion(torsionIter)) {
598
599 a = torsion->getAtomA()->getGlobalIndex();
600 b = torsion->getAtomB()->getGlobalIndex();
601 c = torsion->getAtomC()->getGlobalIndex();
602 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
614 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
622 if (options_.havevdw14scale() || options_.haveelectrostatic14scale()) {
623 oneFourInteractions_.removePair(a, d);
624 } else {
625 excludedInteractions_.removePair(a, d);
626 }
627 }
628
629 for (inversion= mol->beginInversion(inversionIter); inversion != NULL;
630 inversion = mol->nextInversion(inversionIter)) {
631
632 a = inversion->getAtomA()->getGlobalIndex();
633 b = inversion->getAtomB()->getGlobalIndex();
634 c = inversion->getAtomC()->getGlobalIndex();
635 d = inversion->getAtomD()->getGlobalIndex();
636
637 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
647 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 }
657
658 for (rb = mol->beginRigidBody(rbIter); rb != NULL;
659 rb = mol->nextRigidBody(rbIter)) {
660 vector<Atom*> atoms = rb->getAtoms();
661 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 a = atoms[i]->getGlobalIndex();
664 b = atoms[j]->getGlobalIndex();
665 excludedInteractions_.removePair(a, b);
666 }
667 }
668 }
669
670 }
671
672
673 void SimInfo::addMoleculeStamp(MoleculeStamp* molStamp, int nmol) {
674 int curStampId;
675
676 //index from 0
677 curStampId = moleculeStamps_.size();
678
679 moleculeStamps_.push_back(molStamp);
680 molStampIds_.insert(molStampIds_.end(), nmol, curStampId);
681 }
682
683
684 /**
685 * update
686 *
687 * Performs the global checks and variable settings after the
688 * objects have been created.
689 *
690 */
691 void SimInfo::update() {
692 setupSimVariables();
693 calcNdf();
694 calcNdfRaw();
695 calcNdfTrans();
696 }
697
698 /**
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 set<AtomType*> SimInfo::getSimulatedAtomTypes() {
706 SimInfo::MoleculeIterator mi;
707 Molecule* mol;
708 Molecule::AtomIterator ai;
709 Atom* atom;
710 set<AtomType*> atomTypes;
711
712 for(mol = beginMolecule(mi); mol != NULL; mol = nextMolecule(mi)) {
713 for(atom = mol->beginAtom(ai); atom != NULL;
714 atom = mol->nextAtom(ai)) {
715 atomTypes.insert(atom->getAtomType());
716 }
717 }
718
719 #ifdef IS_MPI
720
721 // loop over the found atom types on this processor, and add their
722 // numerical idents to a vector:
723
724 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 int nproc = MPI::COMM_WORLD.Get_size();
733
734 // 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
739 // 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
751 // we need a (possibly redundant) set of all found types:
752 vector<int> ftGlobal(totalCount);
753
754 // now spray out the foundTypes to all the other processors:
755 MPI::COMM_WORLD.Allgatherv(&foundTypes[0], count_local, MPI::INT,
756 &ftGlobal[0], &counts[0], &disps[0],
757 MPI::INT);
758
759 vector<int>::iterator j;
760
761 // foundIdents is a stl set, so inserting an already found ident
762 // will have no effect.
763 set<int> foundIdents;
764
765 for (j = ftGlobal.begin(); j != ftGlobal.end(); ++j)
766 foundIdents.insert((*j));
767
768 // now iterate over the foundIdents and get the actual atom types
769 // that correspond to these:
770 set<int>::iterator it;
771 for (it = foundIdents.begin(); it != foundIdents.end(); ++it)
772 atomTypes.insert( forceField_->getAtomType((*it)) );
773
774 #endif
775
776 return atomTypes;
777 }
778
779 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
788 set<AtomType*>::iterator i;
789 set<AtomType*> atomTypes;
790 atomTypes = getSimulatedAtomTypes();
791 int usesElectrostatic = 0;
792 int usesMetallic = 0;
793 int usesDirectional = 0;
794 int usesFluctuatingCharges = 0;
795 //loop over all of the atom types
796 for (i = atomTypes.begin(); i != atomTypes.end(); ++i) {
797 usesElectrostatic |= (*i)->isElectrostatic();
798 usesMetallic |= (*i)->isMetal();
799 usesDirectional |= (*i)->isDirectional();
800 usesFluctuatingCharges |= (*i)->isFluctuatingCharge();
801 }
802
803 #ifdef IS_MPI
804 int temp;
805 temp = usesDirectional;
806 MPI_Allreduce(&temp, &usesDirectionalAtoms_, 1, MPI_INT, MPI_LOR, MPI_COMM_WORLD);
807
808 temp = usesMetallic;
809 MPI_Allreduce(&temp, &usesMetallicAtoms_, 1, MPI_INT, MPI_LOR, MPI_COMM_WORLD);
810
811 temp = usesElectrostatic;
812 MPI_Allreduce(&temp, &usesElectrostaticAtoms_, 1, MPI_INT, MPI_LOR, MPI_COMM_WORLD);
813
814 temp = usesFluctuatingCharges;
815 MPI_Allreduce(&temp, &usesFluctuatingCharges_, 1, MPI_INT, MPI_LOR, MPI_COMM_WORLD);
816 #else
817
818 usesDirectionalAtoms_ = usesDirectional;
819 usesMetallicAtoms_ = usesMetallic;
820 usesElectrostaticAtoms_ = usesElectrostatic;
821 usesFluctuatingCharges_ = usesFluctuatingCharges;
822
823 #endif
824
825 requiresPrepair_ = usesMetallicAtoms_ ? true : false;
826 requiresSkipCorrection_ = usesElectrostaticAtoms_ ? true : false;
827 requiresSelfCorrection_ = usesElectrostaticAtoms_ ? true : false;
828 }
829
830
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 void SimInfo::prepareTopology() {
871 int nExclude, nOneTwo, nOneThree, nOneFour;
872
873 //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 RealType totalMass;
881
882 /**
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 massFactors_.clear();
891 massFactors_.resize(getNAtoms(), 1.0);
892
893 for(mol = beginMolecule(mi); mol != NULL; mol = nextMolecule(mi)) {
894 for (cg = mol->beginCutoffGroup(ci); cg != NULL;
895 cg = mol->nextCutoffGroup(ci)) {
896
897 totalMass = cg->getMass();
898 for(atom = cg->beginAtom(ai); atom != NULL; atom = cg->nextAtom(ai)) {
899 // Check for massless groups - set mfact to 1 if true
900 if (totalMass != 0)
901 massFactors_[atom->getLocalIndex()] = atom->getMass()/totalMass;
902 else
903 massFactors_[atom->getLocalIndex()] = 1.0;
904 }
905 }
906 }
907
908 // Build the identArray_
909
910 identArray_.clear();
911 identArray_.reserve(getNAtoms());
912 for(mol = beginMolecule(mi); mol != NULL; mol = nextMolecule(mi)) {
913 for(atom = mol->beginAtom(ai); atom != NULL; atom = mol->nextAtom(ai)) {
914 identArray_.push_back(atom->getIdent());
915 }
916 }
917
918 //scan topology
919
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 topologyDone_ = true;
931 }
932
933 void SimInfo::addProperty(GenericData* genData) {
934 properties_.addProperty(genData);
935 }
936
937 void SimInfo::removeProperty(const string& propName) {
938 properties_.removeProperty(propName);
939 }
940
941 void SimInfo::clearProperties() {
942 properties_.clearProperties();
943 }
944
945 vector<string> SimInfo::getPropertyNames() {
946 return properties_.getPropertyNames();
947 }
948
949 vector<GenericData*> SimInfo::getProperties() {
950 return properties_.getProperties();
951 }
952
953 GenericData* SimInfo::getPropertyByName(const string& propName) {
954 return properties_.getPropertyByName(propName);
955 }
956
957 void SimInfo::setSnapshotManager(SnapshotManager* sman) {
958 if (sman_ == sman) {
959 return;
960 }
961 delete sman_;
962 sman_ = sman;
963
964 Molecule* mol;
965 RigidBody* rb;
966 Atom* atom;
967 CutoffGroup* cg;
968 SimInfo::MoleculeIterator mi;
969 Molecule::RigidBodyIterator rbIter;
970 Molecule::AtomIterator atomIter;
971 Molecule::CutoffGroupIterator cgIter;
972
973 for (mol = beginMolecule(mi); mol != NULL; mol = nextMolecule(mi)) {
974
975 for (atom = mol->beginAtom(atomIter); atom != NULL; atom = mol->nextAtom(atomIter)) {
976 atom->setSnapshotManager(sman_);
977 }
978
979 for (rb = mol->beginRigidBody(rbIter); rb != NULL; rb = mol->nextRigidBody(rbIter)) {
980 rb->setSnapshotManager(sman_);
981 }
982
983 for (cg = mol->beginCutoffGroup(cgIter); cg != NULL; cg = mol->nextCutoffGroup(cgIter)) {
984 cg->setSnapshotManager(sman_);
985 }
986 }
987
988 }
989
990 Vector3d SimInfo::getComVel(){
991 SimInfo::MoleculeIterator i;
992 Molecule* mol;
993
994 Vector3d comVel(0.0);
995 RealType totalMass = 0.0;
996
997
998 for (mol = beginMolecule(i); mol != NULL; mol = nextMolecule(i)) {
999 RealType mass = mol->getMass();
1000 totalMass += mass;
1001 comVel += mass * mol->getComVel();
1002 }
1003
1004 #ifdef IS_MPI
1005 RealType tmpMass = totalMass;
1006 Vector3d tmpComVel(comVel);
1007 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 #endif
1010
1011 comVel /= totalMass;
1012
1013 return comVel;
1014 }
1015
1016 Vector3d SimInfo::getCom(){
1017 SimInfo::MoleculeIterator i;
1018 Molecule* mol;
1019
1020 Vector3d com(0.0);
1021 RealType totalMass = 0.0;
1022
1023 for (mol = beginMolecule(i); mol != NULL; mol = nextMolecule(i)) {
1024 RealType mass = mol->getMass();
1025 totalMass += mass;
1026 com += mass * mol->getCom();
1027 }
1028
1029 #ifdef IS_MPI
1030 RealType tmpMass = totalMass;
1031 Vector3d tmpCom(com);
1032 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 #endif
1035
1036 com /= totalMass;
1037
1038 return com;
1039
1040 }
1041
1042 ostream& operator <<(ostream& o, SimInfo& info) {
1043
1044 return o;
1045 }
1046
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 RealType totalMass = 0.0;
1058
1059
1060 for (mol = beginMolecule(i); mol != NULL; mol = nextMolecule(i)) {
1061 RealType mass = mol->getMass();
1062 totalMass += mass;
1063 com += mass * mol->getCom();
1064 comVel += mass * mol->getComVel();
1065 }
1066
1067 #ifdef IS_MPI
1068 RealType tmpMass = totalMass;
1069 Vector3d tmpCom(com);
1070 Vector3d tmpComVel(comVel);
1071 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 #endif
1075
1076 com /= totalMass;
1077 comVel /= totalMass;
1078 }
1079
1080 /*
1081 Return intertia tensor for entire system and angular momentum Vector.
1082
1083
1084 [ Ixx -Ixy -Ixz ]
1085 J =| -Iyx Iyy -Iyz |
1086 [ -Izx -Iyz Izz ]
1087 */
1088
1089 void SimInfo::getInertiaTensor(Mat3x3d &inertiaTensor, Vector3d &angularMomentum){
1090
1091
1092 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 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 RealType thisMass = 0.0;
1110
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 inertiaTensor(1,1) = xx + zz;
1139 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 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 #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 Vector3d thisr(0.0);
1167 Vector3d thisp(0.0);
1168
1169 RealType thisMass;
1170
1171 for (mol = beginMolecule(i); mol != NULL; mol = nextMolecule(i)) {
1172 thisMass = mol->getMass();
1173 thisr = mol->getCom()-com;
1174 thisp = (mol->getComVel()-comVel)*thisMass;
1175
1176 angularMomentum += cross( thisr, thisp );
1177
1178 }
1179
1180 #ifdef IS_MPI
1181 Vector3d tmpAngMom;
1182 MPI_Allreduce(tmpAngMom.getArrayPointer(), angularMomentum.getArrayPointer(),3,MPI_REALTYPE,MPI_SUM, MPI_COMM_WORLD);
1183 #endif
1184
1185 return angularMomentum;
1186 }
1187
1188 StuntDouble* SimInfo::getIOIndexToIntegrableObject(int index) {
1189 return IOIndexToIntegrableObject.at(index);
1190 }
1191
1192 void SimInfo::setIOIndexToIntegrableObject(const vector<StuntDouble*>& v) {
1193 IOIndexToIntegrableObject= v;
1194 }
1195
1196 /* 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 volume = 4.0/3.0*NumericConstant::PI*pow(sysconstants,geomCnst)*sqrt(det);
1215 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 volume = 4.0/3.0*NumericConstant::PI*pow(sysconstants,geomCnst)*sqrt(detI);
1231 return;
1232 }
1233 /*
1234 void SimInfo::setStuntDoubleFromGlobalIndex(vector<StuntDouble*> v) {
1235 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 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 }//end namespace OpenMD
1256

Properties

Name Value
svn:keywords Author Id Revision Date