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

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