ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/OpenMD/trunk/src/brains/SimInfo.cpp
Revision: 1908
Committed: Fri Jul 19 21:25:45 2013 UTC (11 years, 9 months ago) by gezelter
File size: 32921 byte(s)
Log Message:
Added infrastructure for region-constrained 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, 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 #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 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 for (bond= mol->beginBond(bondIter); bond != NULL;
423 bond = mol->nextBond(bondIter)) {
424
425 a = bond->getAtomA()->getGlobalIndex();
426 b = bond->getAtomB()->getGlobalIndex();
427
428 if (options_.havevdw12scale() || options_.haveelectrostatic12scale()) {
429 oneTwoInteractions_.addPair(a, b);
430 } else {
431 excludedInteractions_.addPair(a, b);
432 }
433 }
434
435 for (bend= mol->beginBend(bendIter); bend != NULL;
436 bend = mol->nextBend(bendIter)) {
437
438 a = bend->getAtomA()->getGlobalIndex();
439 b = bend->getAtomB()->getGlobalIndex();
440 c = bend->getAtomC()->getGlobalIndex();
441
442 if (options_.havevdw12scale() || options_.haveelectrostatic12scale()) {
443 oneTwoInteractions_.addPair(a, b);
444 oneTwoInteractions_.addPair(b, c);
445 } else {
446 excludedInteractions_.addPair(a, b);
447 excludedInteractions_.addPair(b, c);
448 }
449
450 if (options_.havevdw13scale() || options_.haveelectrostatic13scale()) {
451 oneThreeInteractions_.addPair(a, c);
452 } else {
453 excludedInteractions_.addPair(a, c);
454 }
455 }
456
457 for (torsion= mol->beginTorsion(torsionIter); torsion != NULL;
458 torsion = mol->nextTorsion(torsionIter)) {
459
460 a = torsion->getAtomA()->getGlobalIndex();
461 b = torsion->getAtomB()->getGlobalIndex();
462 c = torsion->getAtomC()->getGlobalIndex();
463 d = torsion->getAtomD()->getGlobalIndex();
464
465 if (options_.havevdw12scale() || options_.haveelectrostatic12scale()) {
466 oneTwoInteractions_.addPair(a, b);
467 oneTwoInteractions_.addPair(b, c);
468 oneTwoInteractions_.addPair(c, d);
469 } else {
470 excludedInteractions_.addPair(a, b);
471 excludedInteractions_.addPair(b, c);
472 excludedInteractions_.addPair(c, d);
473 }
474
475 if (options_.havevdw13scale() || options_.haveelectrostatic13scale()) {
476 oneThreeInteractions_.addPair(a, c);
477 oneThreeInteractions_.addPair(b, d);
478 } else {
479 excludedInteractions_.addPair(a, c);
480 excludedInteractions_.addPair(b, d);
481 }
482
483 if (options_.havevdw14scale() || options_.haveelectrostatic14scale()) {
484 oneFourInteractions_.addPair(a, d);
485 } else {
486 excludedInteractions_.addPair(a, d);
487 }
488 }
489
490 for (inversion= mol->beginInversion(inversionIter); inversion != NULL;
491 inversion = mol->nextInversion(inversionIter)) {
492
493 a = inversion->getAtomA()->getGlobalIndex();
494 b = inversion->getAtomB()->getGlobalIndex();
495 c = inversion->getAtomC()->getGlobalIndex();
496 d = inversion->getAtomD()->getGlobalIndex();
497
498 if (options_.havevdw12scale() || options_.haveelectrostatic12scale()) {
499 oneTwoInteractions_.addPair(a, b);
500 oneTwoInteractions_.addPair(a, c);
501 oneTwoInteractions_.addPair(a, d);
502 } else {
503 excludedInteractions_.addPair(a, b);
504 excludedInteractions_.addPair(a, c);
505 excludedInteractions_.addPair(a, d);
506 }
507
508 if (options_.havevdw13scale() || options_.haveelectrostatic13scale()) {
509 oneThreeInteractions_.addPair(b, c);
510 oneThreeInteractions_.addPair(b, d);
511 oneThreeInteractions_.addPair(c, d);
512 } else {
513 excludedInteractions_.addPair(b, c);
514 excludedInteractions_.addPair(b, d);
515 excludedInteractions_.addPair(c, d);
516 }
517 }
518
519 for (rb = mol->beginRigidBody(rbIter); rb != NULL;
520 rb = mol->nextRigidBody(rbIter)) {
521 vector<Atom*> atoms = rb->getAtoms();
522 for (int i = 0; i < static_cast<int>(atoms.size()) -1 ; ++i) {
523 for (int j = i + 1; j < static_cast<int>(atoms.size()); ++j) {
524 a = atoms[i]->getGlobalIndex();
525 b = atoms[j]->getGlobalIndex();
526 excludedInteractions_.addPair(a, b);
527 }
528 }
529 }
530
531 }
532
533 void SimInfo::removeInteractionPairs(Molecule* mol) {
534 ForceFieldOptions& options_ = forceField_->getForceFieldOptions();
535 vector<Bond*>::iterator bondIter;
536 vector<Bend*>::iterator bendIter;
537 vector<Torsion*>::iterator torsionIter;
538 vector<Inversion*>::iterator inversionIter;
539 Bond* bond;
540 Bend* bend;
541 Torsion* torsion;
542 Inversion* inversion;
543 int a;
544 int b;
545 int c;
546 int d;
547
548 map<int, set<int> > atomGroups;
549 Molecule::RigidBodyIterator rbIter;
550 RigidBody* rb;
551 Molecule::IntegrableObjectIterator ii;
552 StuntDouble* sd;
553
554 for (sd = mol->beginIntegrableObject(ii); sd != NULL;
555 sd = mol->nextIntegrableObject(ii)) {
556
557 if (sd->isRigidBody()) {
558 rb = static_cast<RigidBody*>(sd);
559 vector<Atom*> atoms = rb->getAtoms();
560 set<int> rigidAtoms;
561 for (int i = 0; i < static_cast<int>(atoms.size()); ++i) {
562 rigidAtoms.insert(atoms[i]->getGlobalIndex());
563 }
564 for (int i = 0; i < static_cast<int>(atoms.size()); ++i) {
565 atomGroups.insert(map<int, set<int> >::value_type(atoms[i]->getGlobalIndex(), rigidAtoms));
566 }
567 } else {
568 set<int> oneAtomSet;
569 oneAtomSet.insert(sd->getGlobalIndex());
570 atomGroups.insert(map<int, set<int> >::value_type(sd->getGlobalIndex(), oneAtomSet));
571 }
572 }
573
574 for (bond= mol->beginBond(bondIter); bond != NULL;
575 bond = mol->nextBond(bondIter)) {
576
577 a = bond->getAtomA()->getGlobalIndex();
578 b = bond->getAtomB()->getGlobalIndex();
579
580 if (options_.havevdw12scale() || options_.haveelectrostatic12scale()) {
581 oneTwoInteractions_.removePair(a, b);
582 } else {
583 excludedInteractions_.removePair(a, b);
584 }
585 }
586
587 for (bend= mol->beginBend(bendIter); bend != NULL;
588 bend = mol->nextBend(bendIter)) {
589
590 a = bend->getAtomA()->getGlobalIndex();
591 b = bend->getAtomB()->getGlobalIndex();
592 c = bend->getAtomC()->getGlobalIndex();
593
594 if (options_.havevdw12scale() || options_.haveelectrostatic12scale()) {
595 oneTwoInteractions_.removePair(a, b);
596 oneTwoInteractions_.removePair(b, c);
597 } else {
598 excludedInteractions_.removePair(a, b);
599 excludedInteractions_.removePair(b, c);
600 }
601
602 if (options_.havevdw13scale() || options_.haveelectrostatic13scale()) {
603 oneThreeInteractions_.removePair(a, c);
604 } else {
605 excludedInteractions_.removePair(a, c);
606 }
607 }
608
609 for (torsion= mol->beginTorsion(torsionIter); torsion != NULL;
610 torsion = mol->nextTorsion(torsionIter)) {
611
612 a = torsion->getAtomA()->getGlobalIndex();
613 b = torsion->getAtomB()->getGlobalIndex();
614 c = torsion->getAtomC()->getGlobalIndex();
615 d = torsion->getAtomD()->getGlobalIndex();
616
617 if (options_.havevdw12scale() || options_.haveelectrostatic12scale()) {
618 oneTwoInteractions_.removePair(a, b);
619 oneTwoInteractions_.removePair(b, c);
620 oneTwoInteractions_.removePair(c, d);
621 } else {
622 excludedInteractions_.removePair(a, b);
623 excludedInteractions_.removePair(b, c);
624 excludedInteractions_.removePair(c, d);
625 }
626
627 if (options_.havevdw13scale() || options_.haveelectrostatic13scale()) {
628 oneThreeInteractions_.removePair(a, c);
629 oneThreeInteractions_.removePair(b, d);
630 } else {
631 excludedInteractions_.removePair(a, c);
632 excludedInteractions_.removePair(b, d);
633 }
634
635 if (options_.havevdw14scale() || options_.haveelectrostatic14scale()) {
636 oneFourInteractions_.removePair(a, d);
637 } else {
638 excludedInteractions_.removePair(a, d);
639 }
640 }
641
642 for (inversion= mol->beginInversion(inversionIter); inversion != NULL;
643 inversion = mol->nextInversion(inversionIter)) {
644
645 a = inversion->getAtomA()->getGlobalIndex();
646 b = inversion->getAtomB()->getGlobalIndex();
647 c = inversion->getAtomC()->getGlobalIndex();
648 d = inversion->getAtomD()->getGlobalIndex();
649
650 if (options_.havevdw12scale() || options_.haveelectrostatic12scale()) {
651 oneTwoInteractions_.removePair(a, b);
652 oneTwoInteractions_.removePair(a, c);
653 oneTwoInteractions_.removePair(a, d);
654 } else {
655 excludedInteractions_.removePair(a, b);
656 excludedInteractions_.removePair(a, c);
657 excludedInteractions_.removePair(a, d);
658 }
659
660 if (options_.havevdw13scale() || options_.haveelectrostatic13scale()) {
661 oneThreeInteractions_.removePair(b, c);
662 oneThreeInteractions_.removePair(b, d);
663 oneThreeInteractions_.removePair(c, d);
664 } else {
665 excludedInteractions_.removePair(b, c);
666 excludedInteractions_.removePair(b, d);
667 excludedInteractions_.removePair(c, d);
668 }
669 }
670
671 for (rb = mol->beginRigidBody(rbIter); rb != NULL;
672 rb = mol->nextRigidBody(rbIter)) {
673 vector<Atom*> atoms = rb->getAtoms();
674 for (int i = 0; i < static_cast<int>(atoms.size()) -1 ; ++i) {
675 for (int j = i + 1; j < static_cast<int>(atoms.size()); ++j) {
676 a = atoms[i]->getGlobalIndex();
677 b = atoms[j]->getGlobalIndex();
678 excludedInteractions_.removePair(a, b);
679 }
680 }
681 }
682
683 }
684
685
686 void SimInfo::addMoleculeStamp(MoleculeStamp* molStamp, int nmol) {
687 int curStampId;
688
689 //index from 0
690 curStampId = moleculeStamps_.size();
691
692 moleculeStamps_.push_back(molStamp);
693 molStampIds_.insert(molStampIds_.end(), nmol, curStampId);
694 }
695
696
697 /**
698 * update
699 *
700 * Performs the global checks and variable settings after the
701 * objects have been created.
702 *
703 */
704 void SimInfo::update() {
705 setupSimVariables();
706 calcNdf();
707 calcNdfRaw();
708 calcNdfTrans();
709 }
710
711 /**
712 * getSimulatedAtomTypes
713 *
714 * Returns an STL set of AtomType* that are actually present in this
715 * simulation. Must query all processors to assemble this information.
716 *
717 */
718 set<AtomType*> SimInfo::getSimulatedAtomTypes() {
719 SimInfo::MoleculeIterator mi;
720 Molecule* mol;
721 Molecule::AtomIterator ai;
722 Atom* atom;
723 set<AtomType*> atomTypes;
724
725 for(mol = beginMolecule(mi); mol != NULL; mol = nextMolecule(mi)) {
726 for(atom = mol->beginAtom(ai); atom != NULL;
727 atom = mol->nextAtom(ai)) {
728 atomTypes.insert(atom->getAtomType());
729 }
730 }
731
732 #ifdef IS_MPI
733
734 // loop over the found atom types on this processor, and add their
735 // numerical idents to a vector:
736
737 vector<int> foundTypes;
738 set<AtomType*>::iterator i;
739 for (i = atomTypes.begin(); i != atomTypes.end(); ++i)
740 foundTypes.push_back( (*i)->getIdent() );
741
742 // count_local holds the number of found types on this processor
743 int count_local = foundTypes.size();
744
745 int nproc = MPI::COMM_WORLD.Get_size();
746
747 // we need arrays to hold the counts and displacement vectors for
748 // all processors
749 vector<int> counts(nproc, 0);
750 vector<int> disps(nproc, 0);
751
752 // fill the counts array
753 MPI::COMM_WORLD.Allgather(&count_local, 1, MPI::INT, &counts[0],
754 1, MPI::INT);
755
756 // use the processor counts to compute the displacement array
757 disps[0] = 0;
758 int totalCount = counts[0];
759 for (int iproc = 1; iproc < nproc; iproc++) {
760 disps[iproc] = disps[iproc-1] + counts[iproc-1];
761 totalCount += counts[iproc];
762 }
763
764 // we need a (possibly redundant) set of all found types:
765 vector<int> ftGlobal(totalCount);
766
767 // now spray out the foundTypes to all the other processors:
768 MPI::COMM_WORLD.Allgatherv(&foundTypes[0], count_local, MPI::INT,
769 &ftGlobal[0], &counts[0], &disps[0],
770 MPI::INT);
771
772 vector<int>::iterator j;
773
774 // foundIdents is a stl set, so inserting an already found ident
775 // will have no effect.
776 set<int> foundIdents;
777
778 for (j = ftGlobal.begin(); j != ftGlobal.end(); ++j)
779 foundIdents.insert((*j));
780
781 // now iterate over the foundIdents and get the actual atom types
782 // that correspond to these:
783 set<int>::iterator it;
784 for (it = foundIdents.begin(); it != foundIdents.end(); ++it)
785 atomTypes.insert( forceField_->getAtomType((*it)) );
786
787 #endif
788
789 return atomTypes;
790 }
791
792
793 int getGlobalCountOfType(AtomType* atype) {
794 /*
795 set<AtomType*> atypes = getSimulatedAtomTypes();
796 map<AtomType*, int> counts_;
797
798 for(mol = beginMolecule(mi); mol != NULL; mol = nextMolecule(mi)) {
799 for(atom = mol->beginAtom(ai); atom != NULL;
800 atom = mol->nextAtom(ai)) {
801 atom->getAtomType();
802 }
803 }
804 */
805 return 0;
806 }
807
808 void SimInfo::setupSimVariables() {
809 useAtomicVirial_ = simParams_->getUseAtomicVirial();
810 // we only call setAccumulateBoxDipole if the accumulateBoxDipole
811 // parameter is true
812 calcBoxDipole_ = false;
813 if ( simParams_->haveAccumulateBoxDipole() )
814 if ( simParams_->getAccumulateBoxDipole() ) {
815 calcBoxDipole_ = true;
816 }
817
818 set<AtomType*>::iterator i;
819 set<AtomType*> atomTypes;
820 atomTypes = getSimulatedAtomTypes();
821 bool usesElectrostatic = false;
822 bool usesMetallic = false;
823 bool usesDirectional = false;
824 bool usesFluctuatingCharges = false;
825 //loop over all of the atom types
826 for (i = atomTypes.begin(); i != atomTypes.end(); ++i) {
827 usesElectrostatic |= (*i)->isElectrostatic();
828 usesMetallic |= (*i)->isMetal();
829 usesDirectional |= (*i)->isDirectional();
830 usesFluctuatingCharges |= (*i)->isFluctuatingCharge();
831 }
832
833 #ifdef IS_MPI
834 bool temp;
835 temp = usesDirectional;
836 MPI::COMM_WORLD.Allreduce(&temp, &usesDirectionalAtoms_, 1, MPI::BOOL,
837 MPI::LOR);
838
839 temp = usesMetallic;
840 MPI::COMM_WORLD.Allreduce(&temp, &usesMetallicAtoms_, 1, MPI::BOOL,
841 MPI::LOR);
842
843 temp = usesElectrostatic;
844 MPI::COMM_WORLD.Allreduce(&temp, &usesElectrostaticAtoms_, 1, MPI::BOOL,
845 MPI::LOR);
846
847 temp = usesFluctuatingCharges;
848 MPI::COMM_WORLD.Allreduce(&temp, &usesFluctuatingCharges_, 1, MPI::BOOL,
849 MPI::LOR);
850 #else
851
852 usesDirectionalAtoms_ = usesDirectional;
853 usesMetallicAtoms_ = usesMetallic;
854 usesElectrostaticAtoms_ = usesElectrostatic;
855 usesFluctuatingCharges_ = usesFluctuatingCharges;
856
857 #endif
858
859 requiresPrepair_ = usesMetallicAtoms_ ? true : false;
860 requiresSkipCorrection_ = usesElectrostaticAtoms_ ? true : false;
861 requiresSelfCorrection_ = usesElectrostaticAtoms_ ? true : false;
862 }
863
864
865 vector<int> SimInfo::getGlobalAtomIndices() {
866 SimInfo::MoleculeIterator mi;
867 Molecule* mol;
868 Molecule::AtomIterator ai;
869 Atom* atom;
870
871 vector<int> GlobalAtomIndices(getNAtoms(), 0);
872
873 for (mol = beginMolecule(mi); mol != NULL; mol = nextMolecule(mi)) {
874
875 for (atom = mol->beginAtom(ai); atom != NULL; atom = mol->nextAtom(ai)) {
876 GlobalAtomIndices[atom->getLocalIndex()] = atom->getGlobalIndex();
877 }
878 }
879 return GlobalAtomIndices;
880 }
881
882
883 vector<int> SimInfo::getGlobalGroupIndices() {
884 SimInfo::MoleculeIterator mi;
885 Molecule* mol;
886 Molecule::CutoffGroupIterator ci;
887 CutoffGroup* cg;
888
889 vector<int> GlobalGroupIndices;
890
891 for (mol = beginMolecule(mi); mol != NULL; mol = nextMolecule(mi)) {
892
893 //local index of cutoff group is trivial, it only depends on the
894 //order of travesing
895 for (cg = mol->beginCutoffGroup(ci); cg != NULL;
896 cg = mol->nextCutoffGroup(ci)) {
897 GlobalGroupIndices.push_back(cg->getGlobalIndex());
898 }
899 }
900 return GlobalGroupIndices;
901 }
902
903
904 void SimInfo::prepareTopology() {
905
906 //calculate mass ratio of cutoff group
907 SimInfo::MoleculeIterator mi;
908 Molecule* mol;
909 Molecule::CutoffGroupIterator ci;
910 CutoffGroup* cg;
911 Molecule::AtomIterator ai;
912 Atom* atom;
913 RealType totalMass;
914
915 /**
916 * The mass factor is the relative mass of an atom to the total
917 * mass of the cutoff group it belongs to. By default, all atoms
918 * are their own cutoff groups, and therefore have mass factors of
919 * 1. We need some special handling for massless atoms, which
920 * will be treated as carrying the entire mass of the cutoff
921 * group.
922 */
923 massFactors_.clear();
924 massFactors_.resize(getNAtoms(), 1.0);
925
926 for(mol = beginMolecule(mi); mol != NULL; mol = nextMolecule(mi)) {
927 for (cg = mol->beginCutoffGroup(ci); cg != NULL;
928 cg = mol->nextCutoffGroup(ci)) {
929
930 totalMass = cg->getMass();
931 for(atom = cg->beginAtom(ai); atom != NULL; atom = cg->nextAtom(ai)) {
932 // Check for massless groups - set mfact to 1 if true
933 if (totalMass != 0)
934 massFactors_[atom->getLocalIndex()] = atom->getMass()/totalMass;
935 else
936 massFactors_[atom->getLocalIndex()] = 1.0;
937 }
938 }
939 }
940
941 // Build the identArray_
942
943 identArray_.clear();
944 identArray_.reserve(getNAtoms());
945 for(mol = beginMolecule(mi); mol != NULL; mol = nextMolecule(mi)) {
946 for(atom = mol->beginAtom(ai); atom != NULL; atom = mol->nextAtom(ai)) {
947 identArray_.push_back(atom->getIdent());
948 }
949 }
950
951 topologyDone_ = true;
952 }
953
954 void SimInfo::addProperty(GenericData* genData) {
955 properties_.addProperty(genData);
956 }
957
958 void SimInfo::removeProperty(const string& propName) {
959 properties_.removeProperty(propName);
960 }
961
962 void SimInfo::clearProperties() {
963 properties_.clearProperties();
964 }
965
966 vector<string> SimInfo::getPropertyNames() {
967 return properties_.getPropertyNames();
968 }
969
970 vector<GenericData*> SimInfo::getProperties() {
971 return properties_.getProperties();
972 }
973
974 GenericData* SimInfo::getPropertyByName(const string& propName) {
975 return properties_.getPropertyByName(propName);
976 }
977
978 void SimInfo::setSnapshotManager(SnapshotManager* sman) {
979 if (sman_ == sman) {
980 return;
981 }
982 delete sman_;
983 sman_ = sman;
984
985 Molecule* mol;
986 RigidBody* rb;
987 Atom* atom;
988 CutoffGroup* cg;
989 SimInfo::MoleculeIterator mi;
990 Molecule::RigidBodyIterator rbIter;
991 Molecule::AtomIterator atomIter;
992 Molecule::CutoffGroupIterator cgIter;
993
994 for (mol = beginMolecule(mi); mol != NULL; mol = nextMolecule(mi)) {
995
996 for (atom = mol->beginAtom(atomIter); atom != NULL;
997 atom = mol->nextAtom(atomIter)) {
998 atom->setSnapshotManager(sman_);
999 }
1000
1001 for (rb = mol->beginRigidBody(rbIter); rb != NULL;
1002 rb = mol->nextRigidBody(rbIter)) {
1003 rb->setSnapshotManager(sman_);
1004 }
1005
1006 for (cg = mol->beginCutoffGroup(cgIter); cg != NULL;
1007 cg = mol->nextCutoffGroup(cgIter)) {
1008 cg->setSnapshotManager(sman_);
1009 }
1010 }
1011
1012 }
1013
1014
1015 ostream& operator <<(ostream& o, SimInfo& info) {
1016
1017 return o;
1018 }
1019
1020
1021 StuntDouble* SimInfo::getIOIndexToIntegrableObject(int index) {
1022 if (index >= int(IOIndexToIntegrableObject.size())) {
1023 sprintf(painCave.errMsg,
1024 "SimInfo::getIOIndexToIntegrableObject Error: Integrable Object\n"
1025 "\tindex exceeds number of known objects!\n");
1026 painCave.isFatal = 1;
1027 simError();
1028 return NULL;
1029 } else
1030 return IOIndexToIntegrableObject.at(index);
1031 }
1032
1033 void SimInfo::setIOIndexToIntegrableObject(const vector<StuntDouble*>& v) {
1034 IOIndexToIntegrableObject= v;
1035 }
1036
1037 int SimInfo::getNGlobalConstraints() {
1038 int nGlobalConstraints;
1039 #ifdef IS_MPI
1040 MPI::COMM_WORLD.Allreduce(&nConstraints_, &nGlobalConstraints, 1,
1041 MPI::INT, MPI::SUM);
1042 #else
1043 nGlobalConstraints = nConstraints_;
1044 #endif
1045 return nGlobalConstraints;
1046 }
1047
1048 }//end namespace OpenMD
1049

Properties

Name Value
svn:keywords Author Id Revision Date