ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/OpenMD/branches/development/src/brains/SimInfo.cpp
Revision: 1798
Committed: Thu Sep 13 14:10:11 2012 UTC (12 years, 7 months ago) by gezelter
File size: 32843 byte(s)
Log Message:
Merged trunk changes into the development branch

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();
92 i !=components.end(); ++i) {
93 molStamp = (*i)->getMoleculeStamp();
94 nMolWithSameStamp = (*i)->getNMol();
95
96 addMoleculeStamp(molStamp, nMolWithSameStamp);
97
98 //calculate atoms in molecules
99 nGlobalAtoms_ += molStamp->getNAtoms() *nMolWithSameStamp;
100
101 //calculate atoms in cutoff groups
102 int nAtomsInGroups = 0;
103 int nCutoffGroupsInStamp = molStamp->getNCutoffGroups();
104
105 for (int j=0; j < nCutoffGroupsInStamp; j++) {
106 cgStamp = molStamp->getCutoffGroupStamp(j);
107 nAtomsInGroups += cgStamp->getNMembers();
108 }
109
110 nGroups += nCutoffGroupsInStamp * nMolWithSameStamp;
111
112 nCutoffAtoms += nAtomsInGroups * nMolWithSameStamp;
113
114 //calculate atoms in rigid bodies
115 int nAtomsInRigidBodies = 0;
116 int nRigidBodiesInStamp = molStamp->getNRigidBodies();
117
118 for (int j=0; j < nRigidBodiesInStamp; j++) {
119 rbStamp = molStamp->getRigidBodyStamp(j);
120 nAtomsInRigidBodies += rbStamp->getNMembers();
121 }
122
123 nGlobalRigidBodies_ += nRigidBodiesInStamp * nMolWithSameStamp;
124 nRigidAtoms += nAtomsInRigidBodies * nMolWithSameStamp;
125
126 }
127
128 //every free atom (atom does not belong to cutoff groups) is a cutoff
129 //group therefore the total number of cutoff groups in the system is
130 //equal to the total number of atoms minus number of atoms belong to
131 //cutoff group defined in meta-data file plus the number of cutoff
132 //groups defined in meta-data file
133
134 nGlobalCutoffGroups_ = nGlobalAtoms_ - nCutoffAtoms + nGroups;
135
136 //every free atom (atom does not belong to rigid bodies) is an
137 //integrable object therefore the total number of integrable objects
138 //in the system is equal to the total number of atoms minus number of
139 //atoms belong to rigid body defined in meta-data file plus the number
140 //of rigid bodies defined in meta-data file
141 nGlobalIntegrableObjects_ = nGlobalAtoms_ - nRigidAtoms
142 + nGlobalRigidBodies_;
143
144 nGlobalMols_ = molStampIds_.size();
145 molToProcMap_.resize(nGlobalMols_);
146 }
147
148 SimInfo::~SimInfo() {
149 map<int, Molecule*>::iterator i;
150 for (i = molecules_.begin(); i != molecules_.end(); ++i) {
151 delete i->second;
152 }
153 molecules_.clear();
154
155 delete sman_;
156 delete simParams_;
157 delete forceField_;
158 }
159
160
161 bool SimInfo::addMolecule(Molecule* mol) {
162 MoleculeIterator i;
163
164 i = molecules_.find(mol->getGlobalIndex());
165 if (i == molecules_.end() ) {
166
167 molecules_.insert(make_pair(mol->getGlobalIndex(), mol));
168
169 nAtoms_ += mol->getNAtoms();
170 nBonds_ += mol->getNBonds();
171 nBends_ += mol->getNBends();
172 nTorsions_ += mol->getNTorsions();
173 nInversions_ += mol->getNInversions();
174 nRigidBodies_ += mol->getNRigidBodies();
175 nIntegrableObjects_ += mol->getNIntegrableObjects();
176 nCutoffGroups_ += mol->getNCutoffGroups();
177 nConstraints_ += mol->getNConstraintPairs();
178
179 addInteractionPairs(mol);
180
181 return true;
182 } else {
183 return false;
184 }
185 }
186
187 bool SimInfo::removeMolecule(Molecule* mol) {
188 MoleculeIterator i;
189 i = molecules_.find(mol->getGlobalIndex());
190
191 if (i != molecules_.end() ) {
192
193 assert(mol == i->second);
194
195 nAtoms_ -= mol->getNAtoms();
196 nBonds_ -= mol->getNBonds();
197 nBends_ -= mol->getNBends();
198 nTorsions_ -= mol->getNTorsions();
199 nInversions_ -= mol->getNInversions();
200 nRigidBodies_ -= mol->getNRigidBodies();
201 nIntegrableObjects_ -= mol->getNIntegrableObjects();
202 nCutoffGroups_ -= mol->getNCutoffGroups();
203 nConstraints_ -= mol->getNConstraintPairs();
204
205 removeInteractionPairs(mol);
206 molecules_.erase(mol->getGlobalIndex());
207
208 delete mol;
209
210 return true;
211 } else {
212 return false;
213 }
214 }
215
216
217 Molecule* SimInfo::beginMolecule(MoleculeIterator& i) {
218 i = molecules_.begin();
219 return i == molecules_.end() ? NULL : i->second;
220 }
221
222 Molecule* SimInfo::nextMolecule(MoleculeIterator& i) {
223 ++i;
224 return i == molecules_.end() ? NULL : i->second;
225 }
226
227
228 void SimInfo::calcNdf() {
229 int ndf_local, nfq_local;
230 MoleculeIterator i;
231 vector<StuntDouble*>::iterator j;
232 vector<Atom*>::iterator k;
233
234 Molecule* mol;
235 StuntDouble* sd;
236 Atom* atom;
237
238 ndf_local = 0;
239 nfq_local = 0;
240
241 for (mol = beginMolecule(i); mol != NULL; mol = nextMolecule(i)) {
242
243 for (sd = mol->beginIntegrableObject(j); sd != NULL;
244 sd = mol->nextIntegrableObject(j)) {
245
246 ndf_local += 3;
247
248 if (sd->isDirectional()) {
249 if (sd->isLinear()) {
250 ndf_local += 2;
251 } else {
252 ndf_local += 3;
253 }
254 }
255 }
256
257 for (atom = mol->beginFluctuatingCharge(k); atom != NULL;
258 atom = mol->nextFluctuatingCharge(k)) {
259 if (atom->isFluctuatingCharge()) {
260 nfq_local++;
261 }
262 }
263 }
264
265 ndfLocal_ = ndf_local;
266
267 // n_constraints is local, so subtract them on each processor
268 ndf_local -= nConstraints_;
269
270 #ifdef IS_MPI
271 MPI::COMM_WORLD.Allreduce(&ndf_local, &ndf_, 1, MPI::INT,MPI::SUM);
272 MPI::COMM_WORLD.Allreduce(&nfq_local, &nGlobalFluctuatingCharges_, 1,
273 MPI::INT, MPI::SUM);
274 #else
275 ndf_ = ndf_local;
276 nGlobalFluctuatingCharges_ = nfq_local;
277 #endif
278
279 // nZconstraints_ is global, as are the 3 COM translations for the
280 // entire system:
281 ndf_ = ndf_ - 3 - nZconstraint_;
282
283 }
284
285 int SimInfo::getFdf() {
286 #ifdef IS_MPI
287 MPI::COMM_WORLD.Allreduce(&fdf_local, &fdf_, 1, MPI::INT, MPI::SUM);
288 #else
289 fdf_ = fdf_local;
290 #endif
291 return fdf_;
292 }
293
294 unsigned int SimInfo::getNLocalCutoffGroups(){
295 int nLocalCutoffAtoms = 0;
296 Molecule* mol;
297 MoleculeIterator mi;
298 CutoffGroup* cg;
299 Molecule::CutoffGroupIterator ci;
300
301 for (mol = beginMolecule(mi); mol != NULL; mol = nextMolecule(mi)) {
302
303 for (cg = mol->beginCutoffGroup(ci); cg != NULL;
304 cg = mol->nextCutoffGroup(ci)) {
305 nLocalCutoffAtoms += cg->getNumAtom();
306
307 }
308 }
309
310 return nAtoms_ - nLocalCutoffAtoms + nCutoffGroups_;
311 }
312
313 void SimInfo::calcNdfRaw() {
314 int ndfRaw_local;
315
316 MoleculeIterator i;
317 vector<StuntDouble*>::iterator j;
318 Molecule* mol;
319 StuntDouble* sd;
320
321 // Raw degrees of freedom that we have to set
322 ndfRaw_local = 0;
323
324 for (mol = beginMolecule(i); mol != NULL; mol = nextMolecule(i)) {
325
326 for (sd = mol->beginIntegrableObject(j); sd != NULL;
327 sd = mol->nextIntegrableObject(j)) {
328
329 ndfRaw_local += 3;
330
331 if (sd->isDirectional()) {
332 if (sd->isLinear()) {
333 ndfRaw_local += 2;
334 } else {
335 ndfRaw_local += 3;
336 }
337 }
338
339 }
340 }
341
342 #ifdef IS_MPI
343 MPI::COMM_WORLD.Allreduce(&ndfRaw_local, &ndfRaw_, 1, MPI::INT, MPI::SUM);
344 #else
345 ndfRaw_ = ndfRaw_local;
346 #endif
347 }
348
349 void SimInfo::calcNdfTrans() {
350 int ndfTrans_local;
351
352 ndfTrans_local = 3 * nIntegrableObjects_ - nConstraints_;
353
354
355 #ifdef IS_MPI
356 MPI::COMM_WORLD.Allreduce(&ndfTrans_local, &ndfTrans_, 1,
357 MPI::INT, MPI::SUM);
358 #else
359 ndfTrans_ = ndfTrans_local;
360 #endif
361
362 ndfTrans_ = ndfTrans_ - 3 - nZconstraint_;
363
364 }
365
366 void SimInfo::addInteractionPairs(Molecule* mol) {
367 ForceFieldOptions& options_ = forceField_->getForceFieldOptions();
368 vector<Bond*>::iterator bondIter;
369 vector<Bend*>::iterator bendIter;
370 vector<Torsion*>::iterator torsionIter;
371 vector<Inversion*>::iterator inversionIter;
372 Bond* bond;
373 Bend* bend;
374 Torsion* torsion;
375 Inversion* inversion;
376 int a;
377 int b;
378 int c;
379 int d;
380
381 // atomGroups can be used to add special interaction maps between
382 // groups of atoms that are in two separate rigid bodies.
383 // However, most site-site interactions between two rigid bodies
384 // are probably not special, just the ones between the physically
385 // bonded atoms. Interactions *within* a single rigid body should
386 // always be excluded. These are done at the bottom of this
387 // function.
388
389 map<int, set<int> > atomGroups;
390 Molecule::RigidBodyIterator rbIter;
391 RigidBody* rb;
392 Molecule::IntegrableObjectIterator ii;
393 StuntDouble* sd;
394
395 for (sd = mol->beginIntegrableObject(ii); sd != NULL;
396 sd = mol->nextIntegrableObject(ii)) {
397
398 if (sd->isRigidBody()) {
399 rb = static_cast<RigidBody*>(sd);
400 vector<Atom*> atoms = rb->getAtoms();
401 set<int> rigidAtoms;
402 for (int i = 0; i < static_cast<int>(atoms.size()); ++i) {
403 rigidAtoms.insert(atoms[i]->getGlobalIndex());
404 }
405 for (int i = 0; i < static_cast<int>(atoms.size()); ++i) {
406 atomGroups.insert(map<int, set<int> >::value_type(atoms[i]->getGlobalIndex(), rigidAtoms));
407 }
408 } else {
409 set<int> oneAtomSet;
410 oneAtomSet.insert(sd->getGlobalIndex());
411 atomGroups.insert(map<int, set<int> >::value_type(sd->getGlobalIndex(), oneAtomSet));
412 }
413 }
414
415 for (bond= mol->beginBond(bondIter); bond != NULL;
416 bond = mol->nextBond(bondIter)) {
417
418 a = bond->getAtomA()->getGlobalIndex();
419 b = bond->getAtomB()->getGlobalIndex();
420
421 if (options_.havevdw12scale() || options_.haveelectrostatic12scale()) {
422 oneTwoInteractions_.addPair(a, b);
423 } else {
424 excludedInteractions_.addPair(a, b);
425 }
426 }
427
428 for (bend= mol->beginBend(bendIter); bend != NULL;
429 bend = mol->nextBend(bendIter)) {
430
431 a = bend->getAtomA()->getGlobalIndex();
432 b = bend->getAtomB()->getGlobalIndex();
433 c = bend->getAtomC()->getGlobalIndex();
434
435 if (options_.havevdw12scale() || options_.haveelectrostatic12scale()) {
436 oneTwoInteractions_.addPair(a, b);
437 oneTwoInteractions_.addPair(b, c);
438 } else {
439 excludedInteractions_.addPair(a, b);
440 excludedInteractions_.addPair(b, c);
441 }
442
443 if (options_.havevdw13scale() || options_.haveelectrostatic13scale()) {
444 oneThreeInteractions_.addPair(a, c);
445 } else {
446 excludedInteractions_.addPair(a, c);
447 }
448 }
449
450 for (torsion= mol->beginTorsion(torsionIter); torsion != NULL;
451 torsion = mol->nextTorsion(torsionIter)) {
452
453 a = torsion->getAtomA()->getGlobalIndex();
454 b = torsion->getAtomB()->getGlobalIndex();
455 c = torsion->getAtomC()->getGlobalIndex();
456 d = torsion->getAtomD()->getGlobalIndex();
457
458 if (options_.havevdw12scale() || options_.haveelectrostatic12scale()) {
459 oneTwoInteractions_.addPair(a, b);
460 oneTwoInteractions_.addPair(b, c);
461 oneTwoInteractions_.addPair(c, d);
462 } else {
463 excludedInteractions_.addPair(a, b);
464 excludedInteractions_.addPair(b, c);
465 excludedInteractions_.addPair(c, d);
466 }
467
468 if (options_.havevdw13scale() || options_.haveelectrostatic13scale()) {
469 oneThreeInteractions_.addPair(a, c);
470 oneThreeInteractions_.addPair(b, d);
471 } else {
472 excludedInteractions_.addPair(a, c);
473 excludedInteractions_.addPair(b, d);
474 }
475
476 if (options_.havevdw14scale() || options_.haveelectrostatic14scale()) {
477 oneFourInteractions_.addPair(a, d);
478 } else {
479 excludedInteractions_.addPair(a, d);
480 }
481 }
482
483 for (inversion= mol->beginInversion(inversionIter); inversion != NULL;
484 inversion = mol->nextInversion(inversionIter)) {
485
486 a = inversion->getAtomA()->getGlobalIndex();
487 b = inversion->getAtomB()->getGlobalIndex();
488 c = inversion->getAtomC()->getGlobalIndex();
489 d = inversion->getAtomD()->getGlobalIndex();
490
491 if (options_.havevdw12scale() || options_.haveelectrostatic12scale()) {
492 oneTwoInteractions_.addPair(a, b);
493 oneTwoInteractions_.addPair(a, c);
494 oneTwoInteractions_.addPair(a, d);
495 } else {
496 excludedInteractions_.addPair(a, b);
497 excludedInteractions_.addPair(a, c);
498 excludedInteractions_.addPair(a, d);
499 }
500
501 if (options_.havevdw13scale() || options_.haveelectrostatic13scale()) {
502 oneThreeInteractions_.addPair(b, c);
503 oneThreeInteractions_.addPair(b, d);
504 oneThreeInteractions_.addPair(c, d);
505 } else {
506 excludedInteractions_.addPair(b, c);
507 excludedInteractions_.addPair(b, d);
508 excludedInteractions_.addPair(c, d);
509 }
510 }
511
512 for (rb = mol->beginRigidBody(rbIter); rb != NULL;
513 rb = mol->nextRigidBody(rbIter)) {
514 vector<Atom*> atoms = rb->getAtoms();
515 for (int i = 0; i < static_cast<int>(atoms.size()) -1 ; ++i) {
516 for (int j = i + 1; j < static_cast<int>(atoms.size()); ++j) {
517 a = atoms[i]->getGlobalIndex();
518 b = atoms[j]->getGlobalIndex();
519 excludedInteractions_.addPair(a, b);
520 }
521 }
522 }
523
524 }
525
526 void SimInfo::removeInteractionPairs(Molecule* mol) {
527 ForceFieldOptions& options_ = forceField_->getForceFieldOptions();
528 vector<Bond*>::iterator bondIter;
529 vector<Bend*>::iterator bendIter;
530 vector<Torsion*>::iterator torsionIter;
531 vector<Inversion*>::iterator inversionIter;
532 Bond* bond;
533 Bend* bend;
534 Torsion* torsion;
535 Inversion* inversion;
536 int a;
537 int b;
538 int c;
539 int d;
540
541 map<int, set<int> > atomGroups;
542 Molecule::RigidBodyIterator rbIter;
543 RigidBody* rb;
544 Molecule::IntegrableObjectIterator ii;
545 StuntDouble* sd;
546
547 for (sd = mol->beginIntegrableObject(ii); sd != NULL;
548 sd = mol->nextIntegrableObject(ii)) {
549
550 if (sd->isRigidBody()) {
551 rb = static_cast<RigidBody*>(sd);
552 vector<Atom*> atoms = rb->getAtoms();
553 set<int> rigidAtoms;
554 for (int i = 0; i < static_cast<int>(atoms.size()); ++i) {
555 rigidAtoms.insert(atoms[i]->getGlobalIndex());
556 }
557 for (int i = 0; i < static_cast<int>(atoms.size()); ++i) {
558 atomGroups.insert(map<int, set<int> >::value_type(atoms[i]->getGlobalIndex(), rigidAtoms));
559 }
560 } else {
561 set<int> oneAtomSet;
562 oneAtomSet.insert(sd->getGlobalIndex());
563 atomGroups.insert(map<int, set<int> >::value_type(sd->getGlobalIndex(), oneAtomSet));
564 }
565 }
566
567 for (bond= mol->beginBond(bondIter); bond != NULL;
568 bond = mol->nextBond(bondIter)) {
569
570 a = bond->getAtomA()->getGlobalIndex();
571 b = bond->getAtomB()->getGlobalIndex();
572
573 if (options_.havevdw12scale() || options_.haveelectrostatic12scale()) {
574 oneTwoInteractions_.removePair(a, b);
575 } else {
576 excludedInteractions_.removePair(a, b);
577 }
578 }
579
580 for (bend= mol->beginBend(bendIter); bend != NULL;
581 bend = mol->nextBend(bendIter)) {
582
583 a = bend->getAtomA()->getGlobalIndex();
584 b = bend->getAtomB()->getGlobalIndex();
585 c = bend->getAtomC()->getGlobalIndex();
586
587 if (options_.havevdw12scale() || options_.haveelectrostatic12scale()) {
588 oneTwoInteractions_.removePair(a, b);
589 oneTwoInteractions_.removePair(b, c);
590 } else {
591 excludedInteractions_.removePair(a, b);
592 excludedInteractions_.removePair(b, c);
593 }
594
595 if (options_.havevdw13scale() || options_.haveelectrostatic13scale()) {
596 oneThreeInteractions_.removePair(a, c);
597 } else {
598 excludedInteractions_.removePair(a, c);
599 }
600 }
601
602 for (torsion= mol->beginTorsion(torsionIter); torsion != NULL;
603 torsion = mol->nextTorsion(torsionIter)) {
604
605 a = torsion->getAtomA()->getGlobalIndex();
606 b = torsion->getAtomB()->getGlobalIndex();
607 c = torsion->getAtomC()->getGlobalIndex();
608 d = torsion->getAtomD()->getGlobalIndex();
609
610 if (options_.havevdw12scale() || options_.haveelectrostatic12scale()) {
611 oneTwoInteractions_.removePair(a, b);
612 oneTwoInteractions_.removePair(b, c);
613 oneTwoInteractions_.removePair(c, d);
614 } else {
615 excludedInteractions_.removePair(a, b);
616 excludedInteractions_.removePair(b, c);
617 excludedInteractions_.removePair(c, d);
618 }
619
620 if (options_.havevdw13scale() || options_.haveelectrostatic13scale()) {
621 oneThreeInteractions_.removePair(a, c);
622 oneThreeInteractions_.removePair(b, d);
623 } else {
624 excludedInteractions_.removePair(a, c);
625 excludedInteractions_.removePair(b, d);
626 }
627
628 if (options_.havevdw14scale() || options_.haveelectrostatic14scale()) {
629 oneFourInteractions_.removePair(a, d);
630 } else {
631 excludedInteractions_.removePair(a, d);
632 }
633 }
634
635 for (inversion= mol->beginInversion(inversionIter); inversion != NULL;
636 inversion = mol->nextInversion(inversionIter)) {
637
638 a = inversion->getAtomA()->getGlobalIndex();
639 b = inversion->getAtomB()->getGlobalIndex();
640 c = inversion->getAtomC()->getGlobalIndex();
641 d = inversion->getAtomD()->getGlobalIndex();
642
643 if (options_.havevdw12scale() || options_.haveelectrostatic12scale()) {
644 oneTwoInteractions_.removePair(a, b);
645 oneTwoInteractions_.removePair(a, c);
646 oneTwoInteractions_.removePair(a, d);
647 } else {
648 excludedInteractions_.removePair(a, b);
649 excludedInteractions_.removePair(a, c);
650 excludedInteractions_.removePair(a, d);
651 }
652
653 if (options_.havevdw13scale() || options_.haveelectrostatic13scale()) {
654 oneThreeInteractions_.removePair(b, c);
655 oneThreeInteractions_.removePair(b, d);
656 oneThreeInteractions_.removePair(c, d);
657 } else {
658 excludedInteractions_.removePair(b, c);
659 excludedInteractions_.removePair(b, d);
660 excludedInteractions_.removePair(c, d);
661 }
662 }
663
664 for (rb = mol->beginRigidBody(rbIter); rb != NULL;
665 rb = mol->nextRigidBody(rbIter)) {
666 vector<Atom*> atoms = rb->getAtoms();
667 for (int i = 0; i < static_cast<int>(atoms.size()) -1 ; ++i) {
668 for (int j = i + 1; j < static_cast<int>(atoms.size()); ++j) {
669 a = atoms[i]->getGlobalIndex();
670 b = atoms[j]->getGlobalIndex();
671 excludedInteractions_.removePair(a, b);
672 }
673 }
674 }
675
676 }
677
678
679 void SimInfo::addMoleculeStamp(MoleculeStamp* molStamp, int nmol) {
680 int curStampId;
681
682 //index from 0
683 curStampId = moleculeStamps_.size();
684
685 moleculeStamps_.push_back(molStamp);
686 molStampIds_.insert(molStampIds_.end(), nmol, curStampId);
687 }
688
689
690 /**
691 * update
692 *
693 * Performs the global checks and variable settings after the
694 * objects have been created.
695 *
696 */
697 void SimInfo::update() {
698 setupSimVariables();
699 calcNdf();
700 calcNdfRaw();
701 calcNdfTrans();
702 }
703
704 /**
705 * getSimulatedAtomTypes
706 *
707 * Returns an STL set of AtomType* that are actually present in this
708 * simulation. Must query all processors to assemble this information.
709 *
710 */
711 set<AtomType*> SimInfo::getSimulatedAtomTypes() {
712 SimInfo::MoleculeIterator mi;
713 Molecule* mol;
714 Molecule::AtomIterator ai;
715 Atom* atom;
716 set<AtomType*> atomTypes;
717
718 for(mol = beginMolecule(mi); mol != NULL; mol = nextMolecule(mi)) {
719 for(atom = mol->beginAtom(ai); atom != NULL;
720 atom = mol->nextAtom(ai)) {
721 atomTypes.insert(atom->getAtomType());
722 }
723 }
724
725 #ifdef IS_MPI
726
727 // loop over the found atom types on this processor, and add their
728 // numerical idents to a vector:
729
730 vector<int> foundTypes;
731 set<AtomType*>::iterator i;
732 for (i = atomTypes.begin(); i != atomTypes.end(); ++i)
733 foundTypes.push_back( (*i)->getIdent() );
734
735 // count_local holds the number of found types on this processor
736 int count_local = foundTypes.size();
737
738 int nproc = MPI::COMM_WORLD.Get_size();
739
740 // we need arrays to hold the counts and displacement vectors for
741 // all processors
742 vector<int> counts(nproc, 0);
743 vector<int> disps(nproc, 0);
744
745 // fill the counts array
746 MPI::COMM_WORLD.Allgather(&count_local, 1, MPI::INT, &counts[0],
747 1, MPI::INT);
748
749 // use the processor counts to compute the displacement array
750 disps[0] = 0;
751 int totalCount = counts[0];
752 for (int iproc = 1; iproc < nproc; iproc++) {
753 disps[iproc] = disps[iproc-1] + counts[iproc-1];
754 totalCount += counts[iproc];
755 }
756
757 // we need a (possibly redundant) set of all found types:
758 vector<int> ftGlobal(totalCount);
759
760 // now spray out the foundTypes to all the other processors:
761 MPI::COMM_WORLD.Allgatherv(&foundTypes[0], count_local, MPI::INT,
762 &ftGlobal[0], &counts[0], &disps[0],
763 MPI::INT);
764
765 vector<int>::iterator j;
766
767 // foundIdents is a stl set, so inserting an already found ident
768 // will have no effect.
769 set<int> foundIdents;
770
771 for (j = ftGlobal.begin(); j != ftGlobal.end(); ++j)
772 foundIdents.insert((*j));
773
774 // now iterate over the foundIdents and get the actual atom types
775 // that correspond to these:
776 set<int>::iterator it;
777 for (it = foundIdents.begin(); it != foundIdents.end(); ++it)
778 atomTypes.insert( forceField_->getAtomType((*it)) );
779
780 #endif
781
782 return atomTypes;
783 }
784
785 void SimInfo::setupSimVariables() {
786 useAtomicVirial_ = simParams_->getUseAtomicVirial();
787 // we only call setAccumulateBoxDipole if the accumulateBoxDipole
788 // parameter is true
789 calcBoxDipole_ = false;
790 if ( simParams_->haveAccumulateBoxDipole() )
791 if ( simParams_->getAccumulateBoxDipole() ) {
792 calcBoxDipole_ = true;
793 }
794
795 set<AtomType*>::iterator i;
796 set<AtomType*> atomTypes;
797 atomTypes = getSimulatedAtomTypes();
798 bool usesElectrostatic = false;
799 bool usesMetallic = false;
800 bool usesDirectional = false;
801 bool usesFluctuatingCharges = false;
802 //loop over all of the atom types
803 for (i = atomTypes.begin(); i != atomTypes.end(); ++i) {
804 usesElectrostatic |= (*i)->isElectrostatic();
805 usesMetallic |= (*i)->isMetal();
806 usesDirectional |= (*i)->isDirectional();
807 usesFluctuatingCharges |= (*i)->isFluctuatingCharge();
808 }
809
810 #ifdef IS_MPI
811 bool temp;
812 temp = usesDirectional;
813 MPI::COMM_WORLD.Allreduce(&temp, &usesDirectionalAtoms_, 1, MPI::BOOL,
814 MPI::LOR);
815
816 temp = usesMetallic;
817 MPI::COMM_WORLD.Allreduce(&temp, &usesMetallicAtoms_, 1, MPI::BOOL,
818 MPI::LOR);
819
820 temp = usesElectrostatic;
821 MPI::COMM_WORLD.Allreduce(&temp, &usesElectrostaticAtoms_, 1, MPI::BOOL,
822 MPI::LOR);
823
824 temp = usesFluctuatingCharges;
825 MPI::COMM_WORLD.Allreduce(&temp, &usesFluctuatingCharges_, 1, MPI::BOOL,
826 MPI::LOR);
827 #else
828
829 usesDirectionalAtoms_ = usesDirectional;
830 usesMetallicAtoms_ = usesMetallic;
831 usesElectrostaticAtoms_ = usesElectrostatic;
832 usesFluctuatingCharges_ = usesFluctuatingCharges;
833
834 #endif
835
836 requiresPrepair_ = usesMetallicAtoms_ ? true : false;
837 requiresSkipCorrection_ = usesElectrostaticAtoms_ ? true : false;
838 requiresSelfCorrection_ = usesElectrostaticAtoms_ ? true : false;
839 }
840
841
842 vector<int> SimInfo::getGlobalAtomIndices() {
843 SimInfo::MoleculeIterator mi;
844 Molecule* mol;
845 Molecule::AtomIterator ai;
846 Atom* atom;
847
848 vector<int> GlobalAtomIndices(getNAtoms(), 0);
849
850 for (mol = beginMolecule(mi); mol != NULL; mol = nextMolecule(mi)) {
851
852 for (atom = mol->beginAtom(ai); atom != NULL; atom = mol->nextAtom(ai)) {
853 GlobalAtomIndices[atom->getLocalIndex()] = atom->getGlobalIndex();
854 }
855 }
856 return GlobalAtomIndices;
857 }
858
859
860 vector<int> SimInfo::getGlobalGroupIndices() {
861 SimInfo::MoleculeIterator mi;
862 Molecule* mol;
863 Molecule::CutoffGroupIterator ci;
864 CutoffGroup* cg;
865
866 vector<int> GlobalGroupIndices;
867
868 for (mol = beginMolecule(mi); mol != NULL; mol = nextMolecule(mi)) {
869
870 //local index of cutoff group is trivial, it only depends on the
871 //order of travesing
872 for (cg = mol->beginCutoffGroup(ci); cg != NULL;
873 cg = mol->nextCutoffGroup(ci)) {
874 GlobalGroupIndices.push_back(cg->getGlobalIndex());
875 }
876 }
877 return GlobalGroupIndices;
878 }
879
880
881 void SimInfo::prepareTopology() {
882 int nExclude, nOneTwo, nOneThree, nOneFour;
883
884 //calculate mass ratio of cutoff group
885 SimInfo::MoleculeIterator mi;
886 Molecule* mol;
887 Molecule::CutoffGroupIterator ci;
888 CutoffGroup* cg;
889 Molecule::AtomIterator ai;
890 Atom* atom;
891 RealType totalMass;
892
893 /**
894 * The mass factor is the relative mass of an atom to the total
895 * mass of the cutoff group it belongs to. By default, all atoms
896 * are their own cutoff groups, and therefore have mass factors of
897 * 1. We need some special handling for massless atoms, which
898 * will be treated as carrying the entire mass of the cutoff
899 * group.
900 */
901 massFactors_.clear();
902 massFactors_.resize(getNAtoms(), 1.0);
903
904 for(mol = beginMolecule(mi); mol != NULL; mol = nextMolecule(mi)) {
905 for (cg = mol->beginCutoffGroup(ci); cg != NULL;
906 cg = mol->nextCutoffGroup(ci)) {
907
908 totalMass = cg->getMass();
909 for(atom = cg->beginAtom(ai); atom != NULL; atom = cg->nextAtom(ai)) {
910 // Check for massless groups - set mfact to 1 if true
911 if (totalMass != 0)
912 massFactors_[atom->getLocalIndex()] = atom->getMass()/totalMass;
913 else
914 massFactors_[atom->getLocalIndex()] = 1.0;
915 }
916 }
917 }
918
919 // Build the identArray_
920
921 identArray_.clear();
922 identArray_.reserve(getNAtoms());
923 for(mol = beginMolecule(mi); mol != NULL; mol = nextMolecule(mi)) {
924 for(atom = mol->beginAtom(ai); atom != NULL; atom = mol->nextAtom(ai)) {
925 identArray_.push_back(atom->getIdent());
926 }
927 }
928
929 //scan topology
930
931 nExclude = excludedInteractions_.getSize();
932 nOneTwo = oneTwoInteractions_.getSize();
933 nOneThree = oneThreeInteractions_.getSize();
934 nOneFour = oneFourInteractions_.getSize();
935
936 int* excludeList = excludedInteractions_.getPairList();
937 int* oneTwoList = oneTwoInteractions_.getPairList();
938 int* oneThreeList = oneThreeInteractions_.getPairList();
939 int* oneFourList = oneFourInteractions_.getPairList();
940
941 topologyDone_ = true;
942 }
943
944 void SimInfo::addProperty(GenericData* genData) {
945 properties_.addProperty(genData);
946 }
947
948 void SimInfo::removeProperty(const string& propName) {
949 properties_.removeProperty(propName);
950 }
951
952 void SimInfo::clearProperties() {
953 properties_.clearProperties();
954 }
955
956 vector<string> SimInfo::getPropertyNames() {
957 return properties_.getPropertyNames();
958 }
959
960 vector<GenericData*> SimInfo::getProperties() {
961 return properties_.getProperties();
962 }
963
964 GenericData* SimInfo::getPropertyByName(const string& propName) {
965 return properties_.getPropertyByName(propName);
966 }
967
968 void SimInfo::setSnapshotManager(SnapshotManager* sman) {
969 if (sman_ == sman) {
970 return;
971 }
972 delete sman_;
973 sman_ = sman;
974
975 Molecule* mol;
976 RigidBody* rb;
977 Atom* atom;
978 CutoffGroup* cg;
979 SimInfo::MoleculeIterator mi;
980 Molecule::RigidBodyIterator rbIter;
981 Molecule::AtomIterator atomIter;
982 Molecule::CutoffGroupIterator cgIter;
983
984 for (mol = beginMolecule(mi); mol != NULL; mol = nextMolecule(mi)) {
985
986 for (atom = mol->beginAtom(atomIter); atom != NULL;
987 atom = mol->nextAtom(atomIter)) {
988 atom->setSnapshotManager(sman_);
989 }
990
991 for (rb = mol->beginRigidBody(rbIter); rb != NULL;
992 rb = mol->nextRigidBody(rbIter)) {
993 rb->setSnapshotManager(sman_);
994 }
995
996 for (cg = mol->beginCutoffGroup(cgIter); cg != NULL;
997 cg = mol->nextCutoffGroup(cgIter)) {
998 cg->setSnapshotManager(sman_);
999 }
1000 }
1001
1002 }
1003
1004
1005 ostream& operator <<(ostream& o, SimInfo& info) {
1006
1007 return o;
1008 }
1009
1010
1011 StuntDouble* SimInfo::getIOIndexToIntegrableObject(int index) {
1012 if (index >= IOIndexToIntegrableObject.size()) {
1013 sprintf(painCave.errMsg,
1014 "SimInfo::getIOIndexToIntegrableObject Error: Integrable Object\n"
1015 "\tindex exceeds number of known objects!\n");
1016 painCave.isFatal = 1;
1017 simError();
1018 return NULL;
1019 } else
1020 return IOIndexToIntegrableObject.at(index);
1021 }
1022
1023 void SimInfo::setIOIndexToIntegrableObject(const vector<StuntDouble*>& v) {
1024 IOIndexToIntegrableObject= v;
1025 }
1026
1027 int SimInfo::getNGlobalConstraints() {
1028 int nGlobalConstraints;
1029 #ifdef IS_MPI
1030 MPI::COMM_WORLD.Allreduce(&nConstraints_, &nGlobalConstraints, 1,
1031 MPI::INT, MPI::SUM);
1032 #else
1033 nGlobalConstraints = nConstraints_;
1034 #endif
1035 return nGlobalConstraints;
1036 }
1037
1038 }//end namespace OpenMD
1039

Properties

Name Value
svn:keywords Author Id Revision Date