ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/OpenMD/trunk/src/brains/SimInfo.cpp
Revision: 1940
Committed: Fri Nov 1 19:31:41 2013 UTC (11 years, 5 months ago) by gezelter
File size: 33067 byte(s)
Log Message:
Angular velocity fix in RNEMD

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

Properties

Name Value
svn:keywords Author Id Revision Date