ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/OpenMD/branches/development/src/brains/SimInfo.cpp
Revision: 1277
Committed: Mon Jul 14 12:35:58 2008 UTC (16 years, 9 months ago) by gezelter
Original Path: trunk/src/brains/SimInfo.cpp
File size: 52437 byte(s)
Log Message:
Changes for implementing Amber force field:  Added Inversions and
worked on BaseAtomTypes so that they'd function with the fortran side.

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. Acknowledgement of the program authors must be made in any
10 * publication of scientific results based in part on use of the
11 * program. An acceptable form of acknowledgement is citation of
12 * the article in which the program was described (Matthew
13 * A. Meineke, Charles F. Vardeman II, Teng Lin, Christopher
14 * J. Fennell and J. Daniel Gezelter, "OOPSE: An Object-Oriented
15 * Parallel Simulation Engine for Molecular Dynamics,"
16 * J. Comput. Chem. 26, pp. 252-271 (2005))
17 *
18 * 2. Redistributions of source code must retain the above copyright
19 * notice, this list of conditions and the following disclaimer.
20 *
21 * 3. Redistributions in binary form must reproduce the above copyright
22 * notice, this list of conditions and the following disclaimer in the
23 * documentation and/or other materials provided with the
24 * distribution.
25 *
26 * This software is provided "AS IS," without a warranty of any
27 * kind. All express or implied conditions, representations and
28 * warranties, including any implied warranty of merchantability,
29 * fitness for a particular purpose or non-infringement, are hereby
30 * excluded. The University of Notre Dame and its licensors shall not
31 * be liable for any damages suffered by licensee as a result of
32 * using, modifying or distributing the software or its
33 * derivatives. In no event will the University of Notre Dame or its
34 * licensors be liable for any lost revenue, profit or data, or for
35 * direct, indirect, special, consequential, incidental or punitive
36 * damages, however caused and regardless of the theory of liability,
37 * arising out of the use of or inability to use software, even if the
38 * University of Notre Dame has been advised of the possibility of
39 * such damages.
40 */
41
42 /**
43 * @file SimInfo.cpp
44 * @author tlin
45 * @date 11/02/2004
46 * @version 1.0
47 */
48
49 #include <algorithm>
50 #include <set>
51 #include <map>
52
53 #include "brains/SimInfo.hpp"
54 #include "math/Vector3.hpp"
55 #include "primitives/Molecule.hpp"
56 #include "primitives/StuntDouble.hpp"
57 #include "UseTheForce/fCutoffPolicy.h"
58 #include "UseTheForce/DarkSide/fElectrostaticSummationMethod.h"
59 #include "UseTheForce/DarkSide/fElectrostaticScreeningMethod.h"
60 #include "UseTheForce/DarkSide/fSwitchingFunctionType.h"
61 #include "UseTheForce/doForces_interface.h"
62 #include "UseTheForce/DarkSide/neighborLists_interface.h"
63 #include "UseTheForce/DarkSide/electrostatic_interface.h"
64 #include "UseTheForce/DarkSide/switcheroo_interface.h"
65 #include "utils/MemoryUtils.hpp"
66 #include "utils/simError.h"
67 #include "selection/SelectionManager.hpp"
68 #include "io/ForceFieldOptions.hpp"
69 #include "UseTheForce/ForceField.hpp"
70
71
72 #ifdef IS_MPI
73 #include "UseTheForce/mpiComponentPlan.h"
74 #include "UseTheForce/DarkSide/simParallel_interface.h"
75 #endif
76
77 namespace oopse {
78 std::set<int> getRigidSet(int index, std::map<int, std::set<int> >& container) {
79 std::map<int, std::set<int> >::iterator i = container.find(index);
80 std::set<int> result;
81 if (i != container.end()) {
82 result = i->second;
83 }
84
85 return result;
86 }
87
88 SimInfo::SimInfo(ForceField* ff, Globals* simParams) :
89 forceField_(ff), simParams_(simParams),
90 ndf_(0), fdf_local(0), ndfRaw_(0), ndfTrans_(0), nZconstraint_(0),
91 nGlobalMols_(0), nGlobalAtoms_(0), nGlobalCutoffGroups_(0),
92 nGlobalIntegrableObjects_(0), nGlobalRigidBodies_(0),
93 nAtoms_(0), nBonds_(0), nBends_(0), nTorsions_(0), nInversions_(0),
94 nRigidBodies_(0), nIntegrableObjects_(0), nCutoffGroups_(0),
95 nConstraints_(0), sman_(NULL), fortranInitialized_(false),
96 calcBoxDipole_(false), useAtomicVirial_(true) {
97
98
99 MoleculeStamp* molStamp;
100 int nMolWithSameStamp;
101 int nCutoffAtoms = 0; // number of atoms belong to cutoff groups
102 int nGroups = 0; //total cutoff groups defined in meta-data file
103 CutoffGroupStamp* cgStamp;
104 RigidBodyStamp* rbStamp;
105 int nRigidAtoms = 0;
106
107 std::vector<Component*> components = simParams->getComponents();
108
109 for (std::vector<Component*>::iterator i = components.begin(); i !=components.end(); ++i) {
110 molStamp = (*i)->getMoleculeStamp();
111 nMolWithSameStamp = (*i)->getNMol();
112
113 addMoleculeStamp(molStamp, nMolWithSameStamp);
114
115 //calculate atoms in molecules
116 nGlobalAtoms_ += molStamp->getNAtoms() *nMolWithSameStamp;
117
118 //calculate atoms in cutoff groups
119 int nAtomsInGroups = 0;
120 int nCutoffGroupsInStamp = molStamp->getNCutoffGroups();
121
122 for (int j=0; j < nCutoffGroupsInStamp; j++) {
123 cgStamp = molStamp->getCutoffGroupStamp(j);
124 nAtomsInGroups += cgStamp->getNMembers();
125 }
126
127 nGroups += nCutoffGroupsInStamp * nMolWithSameStamp;
128
129 nCutoffAtoms += nAtomsInGroups * nMolWithSameStamp;
130
131 //calculate atoms in rigid bodies
132 int nAtomsInRigidBodies = 0;
133 int nRigidBodiesInStamp = molStamp->getNRigidBodies();
134
135 for (int j=0; j < nRigidBodiesInStamp; j++) {
136 rbStamp = molStamp->getRigidBodyStamp(j);
137 nAtomsInRigidBodies += rbStamp->getNMembers();
138 }
139
140 nGlobalRigidBodies_ += nRigidBodiesInStamp * nMolWithSameStamp;
141 nRigidAtoms += nAtomsInRigidBodies * nMolWithSameStamp;
142
143 }
144
145 //every free atom (atom does not belong to cutoff groups) is a cutoff
146 //group therefore the total number of cutoff groups in the system is
147 //equal to the total number of atoms minus number of atoms belong to
148 //cutoff group defined in meta-data file plus the number of cutoff
149 //groups defined in meta-data file
150 nGlobalCutoffGroups_ = nGlobalAtoms_ - nCutoffAtoms + nGroups;
151
152 //every free atom (atom does not belong to rigid bodies) is an
153 //integrable object therefore the total number of integrable objects
154 //in the system is equal to the total number of atoms minus number of
155 //atoms belong to rigid body defined in meta-data file plus the number
156 //of rigid bodies defined in meta-data file
157 nGlobalIntegrableObjects_ = nGlobalAtoms_ - nRigidAtoms
158 + nGlobalRigidBodies_;
159
160 nGlobalMols_ = molStampIds_.size();
161 molToProcMap_.resize(nGlobalMols_);
162 }
163
164 SimInfo::~SimInfo() {
165 std::map<int, Molecule*>::iterator i;
166 for (i = molecules_.begin(); i != molecules_.end(); ++i) {
167 delete i->second;
168 }
169 molecules_.clear();
170
171 delete sman_;
172 delete simParams_;
173 delete forceField_;
174 }
175
176 int SimInfo::getNGlobalConstraints() {
177 int nGlobalConstraints;
178 #ifdef IS_MPI
179 MPI_Allreduce(&nConstraints_, &nGlobalConstraints, 1, MPI_INT, MPI_SUM,
180 MPI_COMM_WORLD);
181 #else
182 nGlobalConstraints = nConstraints_;
183 #endif
184 return nGlobalConstraints;
185 }
186
187 bool SimInfo::addMolecule(Molecule* mol) {
188 MoleculeIterator i;
189
190 i = molecules_.find(mol->getGlobalIndex());
191 if (i == molecules_.end() ) {
192
193 molecules_.insert(std::make_pair(mol->getGlobalIndex(), mol));
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 addExcludePairs(mol);
206
207 return true;
208 } else {
209 return false;
210 }
211 }
212
213 bool SimInfo::removeMolecule(Molecule* mol) {
214 MoleculeIterator i;
215 i = molecules_.find(mol->getGlobalIndex());
216
217 if (i != molecules_.end() ) {
218
219 assert(mol == i->second);
220
221 nAtoms_ -= mol->getNAtoms();
222 nBonds_ -= mol->getNBonds();
223 nBends_ -= mol->getNBends();
224 nTorsions_ -= mol->getNTorsions();
225 nInversions_ -= mol->getNInversions();
226 nRigidBodies_ -= mol->getNRigidBodies();
227 nIntegrableObjects_ -= mol->getNIntegrableObjects();
228 nCutoffGroups_ -= mol->getNCutoffGroups();
229 nConstraints_ -= mol->getNConstraintPairs();
230
231 removeExcludePairs(mol);
232 molecules_.erase(mol->getGlobalIndex());
233
234 delete mol;
235
236 return true;
237 } else {
238 return false;
239 }
240
241
242 }
243
244
245 Molecule* SimInfo::beginMolecule(MoleculeIterator& i) {
246 i = molecules_.begin();
247 return i == molecules_.end() ? NULL : i->second;
248 }
249
250 Molecule* SimInfo::nextMolecule(MoleculeIterator& i) {
251 ++i;
252 return i == molecules_.end() ? NULL : i->second;
253 }
254
255
256 void SimInfo::calcNdf() {
257 int ndf_local;
258 MoleculeIterator i;
259 std::vector<StuntDouble*>::iterator j;
260 Molecule* mol;
261 StuntDouble* integrableObject;
262
263 ndf_local = 0;
264
265 for (mol = beginMolecule(i); mol != NULL; mol = nextMolecule(i)) {
266 for (integrableObject = mol->beginIntegrableObject(j); integrableObject != NULL;
267 integrableObject = mol->nextIntegrableObject(j)) {
268
269 ndf_local += 3;
270
271 if (integrableObject->isDirectional()) {
272 if (integrableObject->isLinear()) {
273 ndf_local += 2;
274 } else {
275 ndf_local += 3;
276 }
277 }
278
279 }
280 }
281
282 // n_constraints is local, so subtract them on each processor
283 ndf_local -= nConstraints_;
284
285 #ifdef IS_MPI
286 MPI_Allreduce(&ndf_local,&ndf_,1,MPI_INT,MPI_SUM, MPI_COMM_WORLD);
287 #else
288 ndf_ = ndf_local;
289 #endif
290
291 // nZconstraints_ is global, as are the 3 COM translations for the
292 // entire system:
293 ndf_ = ndf_ - 3 - nZconstraint_;
294
295 }
296
297 int SimInfo::getFdf() {
298 #ifdef IS_MPI
299 MPI_Allreduce(&fdf_local,&fdf_,1,MPI_INT,MPI_SUM, MPI_COMM_WORLD);
300 #else
301 fdf_ = fdf_local;
302 #endif
303 return fdf_;
304 }
305
306 void SimInfo::calcNdfRaw() {
307 int ndfRaw_local;
308
309 MoleculeIterator i;
310 std::vector<StuntDouble*>::iterator j;
311 Molecule* mol;
312 StuntDouble* integrableObject;
313
314 // Raw degrees of freedom that we have to set
315 ndfRaw_local = 0;
316
317 for (mol = beginMolecule(i); mol != NULL; mol = nextMolecule(i)) {
318 for (integrableObject = mol->beginIntegrableObject(j); integrableObject != NULL;
319 integrableObject = mol->nextIntegrableObject(j)) {
320
321 ndfRaw_local += 3;
322
323 if (integrableObject->isDirectional()) {
324 if (integrableObject->isLinear()) {
325 ndfRaw_local += 2;
326 } else {
327 ndfRaw_local += 3;
328 }
329 }
330
331 }
332 }
333
334 #ifdef IS_MPI
335 MPI_Allreduce(&ndfRaw_local,&ndfRaw_,1,MPI_INT,MPI_SUM, MPI_COMM_WORLD);
336 #else
337 ndfRaw_ = ndfRaw_local;
338 #endif
339 }
340
341 void SimInfo::calcNdfTrans() {
342 int ndfTrans_local;
343
344 ndfTrans_local = 3 * nIntegrableObjects_ - nConstraints_;
345
346
347 #ifdef IS_MPI
348 MPI_Allreduce(&ndfTrans_local,&ndfTrans_,1,MPI_INT,MPI_SUM, MPI_COMM_WORLD);
349 #else
350 ndfTrans_ = ndfTrans_local;
351 #endif
352
353 ndfTrans_ = ndfTrans_ - 3 - nZconstraint_;
354
355 }
356
357 void SimInfo::addExcludePairs(Molecule* mol) {
358 std::vector<Bond*>::iterator bondIter;
359 std::vector<Bend*>::iterator bendIter;
360 std::vector<Torsion*>::iterator torsionIter;
361 std::vector<Inversion*>::iterator inversionIter;
362 Bond* bond;
363 Bend* bend;
364 Torsion* torsion;
365 Inversion* inversion;
366 int a;
367 int b;
368 int c;
369 int d;
370
371 std::map<int, std::set<int> > atomGroups;
372
373 Molecule::RigidBodyIterator rbIter;
374 RigidBody* rb;
375 Molecule::IntegrableObjectIterator ii;
376 StuntDouble* integrableObject;
377
378 for (integrableObject = mol->beginIntegrableObject(ii); integrableObject != NULL;
379 integrableObject = mol->nextIntegrableObject(ii)) {
380
381 if (integrableObject->isRigidBody()) {
382 rb = static_cast<RigidBody*>(integrableObject);
383 std::vector<Atom*> atoms = rb->getAtoms();
384 std::set<int> rigidAtoms;
385 for (int i = 0; i < atoms.size(); ++i) {
386 rigidAtoms.insert(atoms[i]->getGlobalIndex());
387 }
388 for (int i = 0; i < atoms.size(); ++i) {
389 atomGroups.insert(std::map<int, std::set<int> >::value_type(atoms[i]->getGlobalIndex(), rigidAtoms));
390 }
391 } else {
392 std::set<int> oneAtomSet;
393 oneAtomSet.insert(integrableObject->getGlobalIndex());
394 atomGroups.insert(std::map<int, std::set<int> >::value_type(integrableObject->getGlobalIndex(), oneAtomSet));
395 }
396 }
397
398
399
400 for (bond= mol->beginBond(bondIter); bond != NULL; bond = mol->nextBond(bondIter)) {
401 a = bond->getAtomA()->getGlobalIndex();
402 b = bond->getAtomB()->getGlobalIndex();
403 exclude_.addPair(a, b);
404 }
405
406 for (bend= mol->beginBend(bendIter); bend != NULL; bend = mol->nextBend(bendIter)) {
407 a = bend->getAtomA()->getGlobalIndex();
408 b = bend->getAtomB()->getGlobalIndex();
409 c = bend->getAtomC()->getGlobalIndex();
410 std::set<int> rigidSetA = getRigidSet(a, atomGroups);
411 std::set<int> rigidSetB = getRigidSet(b, atomGroups);
412 std::set<int> rigidSetC = getRigidSet(c, atomGroups);
413
414 exclude_.addPairs(rigidSetA, rigidSetB);
415 exclude_.addPairs(rigidSetA, rigidSetC);
416 exclude_.addPairs(rigidSetB, rigidSetC);
417
418 //exclude_.addPair(a, b);
419 //exclude_.addPair(a, c);
420 //exclude_.addPair(b, c);
421 }
422
423 for (torsion= mol->beginTorsion(torsionIter); torsion != NULL; torsion = mol->nextTorsion(torsionIter)) {
424 a = torsion->getAtomA()->getGlobalIndex();
425 b = torsion->getAtomB()->getGlobalIndex();
426 c = torsion->getAtomC()->getGlobalIndex();
427 d = torsion->getAtomD()->getGlobalIndex();
428 std::set<int> rigidSetA = getRigidSet(a, atomGroups);
429 std::set<int> rigidSetB = getRigidSet(b, atomGroups);
430 std::set<int> rigidSetC = getRigidSet(c, atomGroups);
431 std::set<int> rigidSetD = getRigidSet(d, atomGroups);
432
433 exclude_.addPairs(rigidSetA, rigidSetB);
434 exclude_.addPairs(rigidSetA, rigidSetC);
435 exclude_.addPairs(rigidSetA, rigidSetD);
436 exclude_.addPairs(rigidSetB, rigidSetC);
437 exclude_.addPairs(rigidSetB, rigidSetD);
438 exclude_.addPairs(rigidSetC, rigidSetD);
439
440 /*
441 exclude_.addPairs(rigidSetA.begin(), rigidSetA.end(), rigidSetB.begin(), rigidSetB.end());
442 exclude_.addPairs(rigidSetA.begin(), rigidSetA.end(), rigidSetC.begin(), rigidSetC.end());
443 exclude_.addPairs(rigidSetA.begin(), rigidSetA.end(), rigidSetD.begin(), rigidSetD.end());
444 exclude_.addPairs(rigidSetB.begin(), rigidSetB.end(), rigidSetC.begin(), rigidSetC.end());
445 exclude_.addPairs(rigidSetB.begin(), rigidSetB.end(), rigidSetD.begin(), rigidSetD.end());
446 exclude_.addPairs(rigidSetC.begin(), rigidSetC.end(), rigidSetD.begin(), rigidSetD.end());
447
448
449 exclude_.addPair(a, b);
450 exclude_.addPair(a, c);
451 exclude_.addPair(a, d);
452 exclude_.addPair(b, c);
453 exclude_.addPair(b, d);
454 exclude_.addPair(c, d);
455 */
456 }
457
458 for (inversion= mol->beginInversion(inversionIter); inversion != NULL;
459 inversion = mol->nextInversion(inversionIter)) {
460 a = inversion->getAtomA()->getGlobalIndex();
461 b = inversion->getAtomB()->getGlobalIndex();
462 c = inversion->getAtomC()->getGlobalIndex();
463 d = inversion->getAtomD()->getGlobalIndex();
464 std::set<int> rigidSetA = getRigidSet(a, atomGroups);
465 std::set<int> rigidSetB = getRigidSet(b, atomGroups);
466 std::set<int> rigidSetC = getRigidSet(c, atomGroups);
467 std::set<int> rigidSetD = getRigidSet(d, atomGroups);
468
469 exclude_.addPairs(rigidSetA, rigidSetB);
470 exclude_.addPairs(rigidSetA, rigidSetC);
471 exclude_.addPairs(rigidSetA, rigidSetD);
472 exclude_.addPairs(rigidSetB, rigidSetC);
473 exclude_.addPairs(rigidSetB, rigidSetD);
474 exclude_.addPairs(rigidSetC, rigidSetD);
475
476 /*
477 exclude_.addPairs(rigidSetA.begin(), rigidSetA.end(), rigidSetB.begin(), rigidSetB.end());
478 exclude_.addPairs(rigidSetA.begin(), rigidSetA.end(), rigidSetC.begin(), rigidSetC.end());
479 exclude_.addPairs(rigidSetA.begin(), rigidSetA.end(), rigidSetD.begin(), rigidSetD.end());
480 exclude_.addPairs(rigidSetB.begin(), rigidSetB.end(), rigidSetC.begin(), rigidSetC.end());
481 exclude_.addPairs(rigidSetB.begin(), rigidSetB.end(), rigidSetD.begin(), rigidSetD.end());
482 exclude_.addPairs(rigidSetC.begin(), rigidSetC.end(), rigidSetD.begin(), rigidSetD.end());
483
484
485 exclude_.addPair(a, b);
486 exclude_.addPair(a, c);
487 exclude_.addPair(a, d);
488 exclude_.addPair(b, c);
489 exclude_.addPair(b, d);
490 exclude_.addPair(c, d);
491 */
492 }
493
494 for (rb = mol->beginRigidBody(rbIter); rb != NULL; rb = mol->nextRigidBody(rbIter)) {
495 std::vector<Atom*> atoms = rb->getAtoms();
496 for (int i = 0; i < atoms.size() -1 ; ++i) {
497 for (int j = i + 1; j < atoms.size(); ++j) {
498 a = atoms[i]->getGlobalIndex();
499 b = atoms[j]->getGlobalIndex();
500 exclude_.addPair(a, b);
501 }
502 }
503 }
504
505 }
506
507 void SimInfo::removeExcludePairs(Molecule* mol) {
508 std::vector<Bond*>::iterator bondIter;
509 std::vector<Bend*>::iterator bendIter;
510 std::vector<Torsion*>::iterator torsionIter;
511 std::vector<Inversion*>::iterator inversionIter;
512 Bond* bond;
513 Bend* bend;
514 Torsion* torsion;
515 Inversion* inversion;
516 int a;
517 int b;
518 int c;
519 int d;
520
521 std::map<int, std::set<int> > atomGroups;
522
523 Molecule::RigidBodyIterator rbIter;
524 RigidBody* rb;
525 Molecule::IntegrableObjectIterator ii;
526 StuntDouble* integrableObject;
527
528 for (integrableObject = mol->beginIntegrableObject(ii); integrableObject != NULL;
529 integrableObject = mol->nextIntegrableObject(ii)) {
530
531 if (integrableObject->isRigidBody()) {
532 rb = static_cast<RigidBody*>(integrableObject);
533 std::vector<Atom*> atoms = rb->getAtoms();
534 std::set<int> rigidAtoms;
535 for (int i = 0; i < atoms.size(); ++i) {
536 rigidAtoms.insert(atoms[i]->getGlobalIndex());
537 }
538 for (int i = 0; i < atoms.size(); ++i) {
539 atomGroups.insert(std::map<int, std::set<int> >::value_type(atoms[i]->getGlobalIndex(), rigidAtoms));
540 }
541 } else {
542 std::set<int> oneAtomSet;
543 oneAtomSet.insert(integrableObject->getGlobalIndex());
544 atomGroups.insert(std::map<int, std::set<int> >::value_type(integrableObject->getGlobalIndex(), oneAtomSet));
545 }
546 }
547
548
549 for (bond= mol->beginBond(bondIter); bond != NULL; bond = mol->nextBond(bondIter)) {
550 a = bond->getAtomA()->getGlobalIndex();
551 b = bond->getAtomB()->getGlobalIndex();
552 exclude_.removePair(a, b);
553 }
554
555 for (bend= mol->beginBend(bendIter); bend != NULL; bend = mol->nextBend(bendIter)) {
556 a = bend->getAtomA()->getGlobalIndex();
557 b = bend->getAtomB()->getGlobalIndex();
558 c = bend->getAtomC()->getGlobalIndex();
559
560 std::set<int> rigidSetA = getRigidSet(a, atomGroups);
561 std::set<int> rigidSetB = getRigidSet(b, atomGroups);
562 std::set<int> rigidSetC = getRigidSet(c, atomGroups);
563
564 exclude_.removePairs(rigidSetA, rigidSetB);
565 exclude_.removePairs(rigidSetA, rigidSetC);
566 exclude_.removePairs(rigidSetB, rigidSetC);
567
568 //exclude_.removePair(a, b);
569 //exclude_.removePair(a, c);
570 //exclude_.removePair(b, c);
571 }
572
573 for (torsion= mol->beginTorsion(torsionIter); torsion != NULL; torsion = mol->nextTorsion(torsionIter)) {
574 a = torsion->getAtomA()->getGlobalIndex();
575 b = torsion->getAtomB()->getGlobalIndex();
576 c = torsion->getAtomC()->getGlobalIndex();
577 d = torsion->getAtomD()->getGlobalIndex();
578
579 std::set<int> rigidSetA = getRigidSet(a, atomGroups);
580 std::set<int> rigidSetB = getRigidSet(b, atomGroups);
581 std::set<int> rigidSetC = getRigidSet(c, atomGroups);
582 std::set<int> rigidSetD = getRigidSet(d, atomGroups);
583
584 exclude_.removePairs(rigidSetA, rigidSetB);
585 exclude_.removePairs(rigidSetA, rigidSetC);
586 exclude_.removePairs(rigidSetA, rigidSetD);
587 exclude_.removePairs(rigidSetB, rigidSetC);
588 exclude_.removePairs(rigidSetB, rigidSetD);
589 exclude_.removePairs(rigidSetC, rigidSetD);
590
591 /*
592 exclude_.removePairs(rigidSetA.begin(), rigidSetA.end(), rigidSetB.begin(), rigidSetB.end());
593 exclude_.removePairs(rigidSetA.begin(), rigidSetA.end(), rigidSetC.begin(), rigidSetC.end());
594 exclude_.removePairs(rigidSetA.begin(), rigidSetA.end(), rigidSetD.begin(), rigidSetD.end());
595 exclude_.removePairs(rigidSetB.begin(), rigidSetB.end(), rigidSetC.begin(), rigidSetC.end());
596 exclude_.removePairs(rigidSetB.begin(), rigidSetB.end(), rigidSetD.begin(), rigidSetD.end());
597 exclude_.removePairs(rigidSetC.begin(), rigidSetC.end(), rigidSetD.begin(), rigidSetD.end());
598
599
600 exclude_.removePair(a, b);
601 exclude_.removePair(a, c);
602 exclude_.removePair(a, d);
603 exclude_.removePair(b, c);
604 exclude_.removePair(b, d);
605 exclude_.removePair(c, d);
606 */
607 }
608
609 for (inversion= mol->beginInversion(inversionIter); inversion != NULL; inversion = mol->nextInversion(inversionIter)) {
610 a = inversion->getAtomA()->getGlobalIndex();
611 b = inversion->getAtomB()->getGlobalIndex();
612 c = inversion->getAtomC()->getGlobalIndex();
613 d = inversion->getAtomD()->getGlobalIndex();
614
615 std::set<int> rigidSetA = getRigidSet(a, atomGroups);
616 std::set<int> rigidSetB = getRigidSet(b, atomGroups);
617 std::set<int> rigidSetC = getRigidSet(c, atomGroups);
618 std::set<int> rigidSetD = getRigidSet(d, atomGroups);
619
620 exclude_.removePairs(rigidSetA, rigidSetB);
621 exclude_.removePairs(rigidSetA, rigidSetC);
622 exclude_.removePairs(rigidSetA, rigidSetD);
623 exclude_.removePairs(rigidSetB, rigidSetC);
624 exclude_.removePairs(rigidSetB, rigidSetD);
625 exclude_.removePairs(rigidSetC, rigidSetD);
626
627 /*
628 exclude_.removePairs(rigidSetA.begin(), rigidSetA.end(), rigidSetB.begin(), rigidSetB.end());
629 exclude_.removePairs(rigidSetA.begin(), rigidSetA.end(), rigidSetC.begin(), rigidSetC.end());
630 exclude_.removePairs(rigidSetA.begin(), rigidSetA.end(), rigidSetD.begin(), rigidSetD.end());
631 exclude_.removePairs(rigidSetB.begin(), rigidSetB.end(), rigidSetC.begin(), rigidSetC.end());
632 exclude_.removePairs(rigidSetB.begin(), rigidSetB.end(), rigidSetD.begin(), rigidSetD.end());
633 exclude_.removePairs(rigidSetC.begin(), rigidSetC.end(), rigidSetD.begin(), rigidSetD.end());
634
635
636 exclude_.removePair(a, b);
637 exclude_.removePair(a, c);
638 exclude_.removePair(a, d);
639 exclude_.removePair(b, c);
640 exclude_.removePair(b, d);
641 exclude_.removePair(c, d);
642 */
643 }
644
645 for (rb = mol->beginRigidBody(rbIter); rb != NULL; rb = mol->nextRigidBody(rbIter)) {
646 std::vector<Atom*> atoms = rb->getAtoms();
647 for (int i = 0; i < atoms.size() -1 ; ++i) {
648 for (int j = i + 1; j < atoms.size(); ++j) {
649 a = atoms[i]->getGlobalIndex();
650 b = atoms[j]->getGlobalIndex();
651 exclude_.removePair(a, b);
652 }
653 }
654 }
655
656 }
657
658
659 void SimInfo::addMoleculeStamp(MoleculeStamp* molStamp, int nmol) {
660 int curStampId;
661
662 //index from 0
663 curStampId = moleculeStamps_.size();
664
665 moleculeStamps_.push_back(molStamp);
666 molStampIds_.insert(molStampIds_.end(), nmol, curStampId);
667 }
668
669 void SimInfo::update() {
670
671 setupSimType();
672
673 #ifdef IS_MPI
674 setupFortranParallel();
675 #endif
676
677 setupFortranSim();
678
679 //setup fortran force field
680 /** @deprecate */
681 int isError = 0;
682
683 setupCutoff();
684
685 setupElectrostaticSummationMethod( isError );
686 setupSwitchingFunction();
687 setupAccumulateBoxDipole();
688
689 if(isError){
690 sprintf( painCave.errMsg,
691 "ForceField error: There was an error initializing the forceField in fortran.\n" );
692 painCave.isFatal = 1;
693 simError();
694 }
695
696 calcNdf();
697 calcNdfRaw();
698 calcNdfTrans();
699
700 fortranInitialized_ = true;
701 }
702
703 std::set<AtomType*> SimInfo::getUniqueAtomTypes() {
704 SimInfo::MoleculeIterator mi;
705 Molecule* mol;
706 Molecule::AtomIterator ai;
707 Atom* atom;
708 std::set<AtomType*> atomTypes;
709
710 for(mol = beginMolecule(mi); mol != NULL; mol = nextMolecule(mi)) {
711
712 for(atom = mol->beginAtom(ai); atom != NULL; atom = mol->nextAtom(ai)) {
713 atomTypes.insert(atom->getAtomType());
714 }
715
716 }
717
718 return atomTypes;
719 }
720
721 void SimInfo::setupSimType() {
722 std::set<AtomType*>::iterator i;
723 std::set<AtomType*> atomTypes;
724 atomTypes = getUniqueAtomTypes();
725
726 int useLennardJones = 0;
727 int useElectrostatic = 0;
728 int useEAM = 0;
729 int useSC = 0;
730 int useCharge = 0;
731 int useDirectional = 0;
732 int useDipole = 0;
733 int useGayBerne = 0;
734 int useSticky = 0;
735 int useStickyPower = 0;
736 int useShape = 0;
737 int useFLARB = 0; //it is not in AtomType yet
738 int useDirectionalAtom = 0;
739 int useElectrostatics = 0;
740 //usePBC and useRF are from simParams
741 int usePBC = simParams_->getUsePeriodicBoundaryConditions();
742 int useRF;
743 int useSF;
744 int useSP;
745 int useBoxDipole;
746
747 std::string myMethod;
748
749 // set the useRF logical
750 useRF = 0;
751 useSF = 0;
752 useSP = 0;
753
754
755 if (simParams_->haveElectrostaticSummationMethod()) {
756 std::string myMethod = simParams_->getElectrostaticSummationMethod();
757 toUpper(myMethod);
758 if (myMethod == "REACTION_FIELD"){
759 useRF = 1;
760 } else if (myMethod == "SHIFTED_FORCE"){
761 useSF = 1;
762 } else if (myMethod == "SHIFTED_POTENTIAL"){
763 useSP = 1;
764 }
765 }
766
767 if (simParams_->haveAccumulateBoxDipole())
768 if (simParams_->getAccumulateBoxDipole())
769 useBoxDipole = 1;
770
771 useAtomicVirial_ = simParams_->getUseAtomicVirial();
772
773 //loop over all of the atom types
774 for (i = atomTypes.begin(); i != atomTypes.end(); ++i) {
775 useLennardJones |= (*i)->isLennardJones();
776 useElectrostatic |= (*i)->isElectrostatic();
777 useEAM |= (*i)->isEAM();
778 useSC |= (*i)->isSC();
779 useCharge |= (*i)->isCharge();
780 useDirectional |= (*i)->isDirectional();
781 useDipole |= (*i)->isDipole();
782 useGayBerne |= (*i)->isGayBerne();
783 useSticky |= (*i)->isSticky();
784 useStickyPower |= (*i)->isStickyPower();
785 useShape |= (*i)->isShape();
786 }
787
788 if (useSticky || useStickyPower || useDipole || useGayBerne || useShape) {
789 useDirectionalAtom = 1;
790 }
791
792 if (useCharge || useDipole) {
793 useElectrostatics = 1;
794 }
795
796 #ifdef IS_MPI
797 int temp;
798
799 temp = usePBC;
800 MPI_Allreduce(&temp, &usePBC, 1, MPI_INT, MPI_LOR, MPI_COMM_WORLD);
801
802 temp = useDirectionalAtom;
803 MPI_Allreduce(&temp, &useDirectionalAtom, 1, MPI_INT, MPI_LOR, MPI_COMM_WORLD);
804
805 temp = useLennardJones;
806 MPI_Allreduce(&temp, &useLennardJones, 1, MPI_INT, MPI_LOR, MPI_COMM_WORLD);
807
808 temp = useElectrostatics;
809 MPI_Allreduce(&temp, &useElectrostatics, 1, MPI_INT, MPI_LOR, MPI_COMM_WORLD);
810
811 temp = useCharge;
812 MPI_Allreduce(&temp, &useCharge, 1, MPI_INT, MPI_LOR, MPI_COMM_WORLD);
813
814 temp = useDipole;
815 MPI_Allreduce(&temp, &useDipole, 1, MPI_INT, MPI_LOR, MPI_COMM_WORLD);
816
817 temp = useSticky;
818 MPI_Allreduce(&temp, &useSticky, 1, MPI_INT, MPI_LOR, MPI_COMM_WORLD);
819
820 temp = useStickyPower;
821 MPI_Allreduce(&temp, &useStickyPower, 1, MPI_INT, MPI_LOR, MPI_COMM_WORLD);
822
823 temp = useGayBerne;
824 MPI_Allreduce(&temp, &useGayBerne, 1, MPI_INT, MPI_LOR, MPI_COMM_WORLD);
825
826 temp = useEAM;
827 MPI_Allreduce(&temp, &useEAM, 1, MPI_INT, MPI_LOR, MPI_COMM_WORLD);
828
829 temp = useSC;
830 MPI_Allreduce(&temp, &useSC, 1, MPI_INT, MPI_LOR, MPI_COMM_WORLD);
831
832 temp = useShape;
833 MPI_Allreduce(&temp, &useShape, 1, MPI_INT, MPI_LOR, MPI_COMM_WORLD);
834
835 temp = useFLARB;
836 MPI_Allreduce(&temp, &useFLARB, 1, MPI_INT, MPI_LOR, MPI_COMM_WORLD);
837
838 temp = useRF;
839 MPI_Allreduce(&temp, &useRF, 1, MPI_INT, MPI_LOR, MPI_COMM_WORLD);
840
841 temp = useSF;
842 MPI_Allreduce(&temp, &useSF, 1, MPI_INT, MPI_LOR, MPI_COMM_WORLD);
843
844 temp = useSP;
845 MPI_Allreduce(&temp, &useSP, 1, MPI_INT, MPI_LOR, MPI_COMM_WORLD);
846
847 temp = useBoxDipole;
848 MPI_Allreduce(&temp, &useBoxDipole, 1, MPI_INT, MPI_LOR, MPI_COMM_WORLD);
849
850 temp = useAtomicVirial_;
851 MPI_Allreduce(&temp, &useAtomicVirial_, 1, MPI_INT, MPI_LOR, MPI_COMM_WORLD);
852
853 #endif
854
855 fInfo_.SIM_uses_PBC = usePBC;
856 fInfo_.SIM_uses_DirectionalAtoms = useDirectionalAtom;
857 fInfo_.SIM_uses_LennardJones = useLennardJones;
858 fInfo_.SIM_uses_Electrostatics = useElectrostatics;
859 fInfo_.SIM_uses_Charges = useCharge;
860 fInfo_.SIM_uses_Dipoles = useDipole;
861 fInfo_.SIM_uses_Sticky = useSticky;
862 fInfo_.SIM_uses_StickyPower = useStickyPower;
863 fInfo_.SIM_uses_GayBerne = useGayBerne;
864 fInfo_.SIM_uses_EAM = useEAM;
865 fInfo_.SIM_uses_SC = useSC;
866 fInfo_.SIM_uses_Shapes = useShape;
867 fInfo_.SIM_uses_FLARB = useFLARB;
868 fInfo_.SIM_uses_RF = useRF;
869 fInfo_.SIM_uses_SF = useSF;
870 fInfo_.SIM_uses_SP = useSP;
871 fInfo_.SIM_uses_BoxDipole = useBoxDipole;
872 fInfo_.SIM_uses_AtomicVirial = useAtomicVirial_;
873 }
874
875 void SimInfo::setupFortranSim() {
876 int isError;
877 int nExclude;
878 std::vector<int> fortranGlobalGroupMembership;
879
880 nExclude = exclude_.getSize();
881 isError = 0;
882
883 //globalGroupMembership_ is filled by SimCreator
884 for (int i = 0; i < nGlobalAtoms_; i++) {
885 fortranGlobalGroupMembership.push_back(globalGroupMembership_[i] + 1);
886 }
887
888 //calculate mass ratio of cutoff group
889 std::vector<RealType> mfact;
890 SimInfo::MoleculeIterator mi;
891 Molecule* mol;
892 Molecule::CutoffGroupIterator ci;
893 CutoffGroup* cg;
894 Molecule::AtomIterator ai;
895 Atom* atom;
896 RealType totalMass;
897
898 //to avoid memory reallocation, reserve enough space for mfact
899 mfact.reserve(getNCutoffGroups());
900
901 for(mol = beginMolecule(mi); mol != NULL; mol = nextMolecule(mi)) {
902 for (cg = mol->beginCutoffGroup(ci); cg != NULL; cg = mol->nextCutoffGroup(ci)) {
903
904 totalMass = cg->getMass();
905 for(atom = cg->beginAtom(ai); atom != NULL; atom = cg->nextAtom(ai)) {
906 // Check for massless groups - set mfact to 1 if true
907 if (totalMass != 0)
908 mfact.push_back(atom->getMass()/totalMass);
909 else
910 mfact.push_back( 1.0 );
911 }
912
913 }
914 }
915
916 //fill ident array of local atoms (it is actually ident of AtomType, it is so confusing !!!)
917 std::vector<int> identArray;
918
919 //to avoid memory reallocation, reserve enough space identArray
920 identArray.reserve(getNAtoms());
921
922 for(mol = beginMolecule(mi); mol != NULL; mol = nextMolecule(mi)) {
923 for(atom = mol->beginAtom(ai); atom != NULL; atom = mol->nextAtom(ai)) {
924 identArray.push_back(atom->getIdent());
925 }
926 }
927
928 //fill molMembershipArray
929 //molMembershipArray is filled by SimCreator
930 std::vector<int> molMembershipArray(nGlobalAtoms_);
931 for (int i = 0; i < nGlobalAtoms_; i++) {
932 molMembershipArray[i] = globalMolMembership_[i] + 1;
933 }
934
935 //setup fortran simulation
936 int nGlobalExcludes = 0;
937 int* globalExcludes = NULL;
938 int* excludeList = exclude_.getExcludeList();
939 setFortranSim( &fInfo_, &nGlobalAtoms_, &nAtoms_, &identArray[0],
940 &nExclude, excludeList , &nGlobalExcludes, globalExcludes,
941 &molMembershipArray[0], &mfact[0], &nCutoffGroups_,
942 &fortranGlobalGroupMembership[0], &isError);
943
944 if( isError ){
945
946 sprintf( painCave.errMsg,
947 "There was an error setting the simulation information in fortran.\n" );
948 painCave.isFatal = 1;
949 painCave.severity = OOPSE_ERROR;
950 simError();
951 }
952
953
954 sprintf( checkPointMsg,
955 "succesfully sent the simulation information to fortran.\n");
956
957 errorCheckPoint();
958
959 // Setup number of neighbors in neighbor list if present
960 if (simParams_->haveNeighborListNeighbors()) {
961 int nlistNeighbors = simParams_->getNeighborListNeighbors();
962 setNeighbors(&nlistNeighbors);
963 }
964
965
966 }
967
968
969 void SimInfo::setupFortranParallel() {
970 #ifdef IS_MPI
971 //SimInfo is responsible for creating localToGlobalAtomIndex and localToGlobalGroupIndex
972 std::vector<int> localToGlobalAtomIndex(getNAtoms(), 0);
973 std::vector<int> localToGlobalCutoffGroupIndex;
974 SimInfo::MoleculeIterator mi;
975 Molecule::AtomIterator ai;
976 Molecule::CutoffGroupIterator ci;
977 Molecule* mol;
978 Atom* atom;
979 CutoffGroup* cg;
980 mpiSimData parallelData;
981 int isError;
982
983 for (mol = beginMolecule(mi); mol != NULL; mol = nextMolecule(mi)) {
984
985 //local index(index in DataStorge) of atom is important
986 for (atom = mol->beginAtom(ai); atom != NULL; atom = mol->nextAtom(ai)) {
987 localToGlobalAtomIndex[atom->getLocalIndex()] = atom->getGlobalIndex() + 1;
988 }
989
990 //local index of cutoff group is trivial, it only depends on the order of travesing
991 for (cg = mol->beginCutoffGroup(ci); cg != NULL; cg = mol->nextCutoffGroup(ci)) {
992 localToGlobalCutoffGroupIndex.push_back(cg->getGlobalIndex() + 1);
993 }
994
995 }
996
997 //fill up mpiSimData struct
998 parallelData.nMolGlobal = getNGlobalMolecules();
999 parallelData.nMolLocal = getNMolecules();
1000 parallelData.nAtomsGlobal = getNGlobalAtoms();
1001 parallelData.nAtomsLocal = getNAtoms();
1002 parallelData.nGroupsGlobal = getNGlobalCutoffGroups();
1003 parallelData.nGroupsLocal = getNCutoffGroups();
1004 parallelData.myNode = worldRank;
1005 MPI_Comm_size(MPI_COMM_WORLD, &(parallelData.nProcessors));
1006
1007 //pass mpiSimData struct and index arrays to fortran
1008 setFsimParallel(&parallelData, &(parallelData.nAtomsLocal),
1009 &localToGlobalAtomIndex[0], &(parallelData.nGroupsLocal),
1010 &localToGlobalCutoffGroupIndex[0], &isError);
1011
1012 if (isError) {
1013 sprintf(painCave.errMsg,
1014 "mpiRefresh errror: fortran didn't like something we gave it.\n");
1015 painCave.isFatal = 1;
1016 simError();
1017 }
1018
1019 sprintf(checkPointMsg, " mpiRefresh successful.\n");
1020 errorCheckPoint();
1021
1022 #endif
1023 }
1024
1025 void SimInfo::setupCutoff() {
1026
1027 ForceFieldOptions& forceFieldOptions_ = forceField_->getForceFieldOptions();
1028
1029 // Check the cutoff policy
1030 int cp = TRADITIONAL_CUTOFF_POLICY; // Set to traditional by default
1031
1032 // Set LJ shifting bools to false
1033 ljsp_ = false;
1034 ljsf_ = false;
1035
1036 std::string myPolicy;
1037 if (forceFieldOptions_.haveCutoffPolicy()){
1038 myPolicy = forceFieldOptions_.getCutoffPolicy();
1039 }else if (simParams_->haveCutoffPolicy()) {
1040 myPolicy = simParams_->getCutoffPolicy();
1041 }
1042
1043 if (!myPolicy.empty()){
1044 toUpper(myPolicy);
1045 if (myPolicy == "MIX") {
1046 cp = MIX_CUTOFF_POLICY;
1047 } else {
1048 if (myPolicy == "MAX") {
1049 cp = MAX_CUTOFF_POLICY;
1050 } else {
1051 if (myPolicy == "TRADITIONAL") {
1052 cp = TRADITIONAL_CUTOFF_POLICY;
1053 } else {
1054 // throw error
1055 sprintf( painCave.errMsg,
1056 "SimInfo error: Unknown cutoffPolicy. (Input file specified %s .)\n\tcutoffPolicy must be one of: \"Mix\", \"Max\", or \"Traditional\".", myPolicy.c_str() );
1057 painCave.isFatal = 1;
1058 simError();
1059 }
1060 }
1061 }
1062 }
1063 notifyFortranCutoffPolicy(&cp);
1064
1065 // Check the Skin Thickness for neighborlists
1066 RealType skin;
1067 if (simParams_->haveSkinThickness()) {
1068 skin = simParams_->getSkinThickness();
1069 notifyFortranSkinThickness(&skin);
1070 }
1071
1072 // Check if the cutoff was set explicitly:
1073 if (simParams_->haveCutoffRadius()) {
1074 rcut_ = simParams_->getCutoffRadius();
1075 if (simParams_->haveSwitchingRadius()) {
1076 rsw_ = simParams_->getSwitchingRadius();
1077 } else {
1078 if (fInfo_.SIM_uses_Charges |
1079 fInfo_.SIM_uses_Dipoles |
1080 fInfo_.SIM_uses_RF) {
1081
1082 rsw_ = 0.85 * rcut_;
1083 sprintf(painCave.errMsg,
1084 "SimCreator Warning: No value was set for the switchingRadius.\n"
1085 "\tOOPSE will use a default value of 85 percent of the cutoffRadius.\n"
1086 "\tswitchingRadius = %f. for this simulation\n", rsw_);
1087 painCave.isFatal = 0;
1088 simError();
1089 } else {
1090 rsw_ = rcut_;
1091 sprintf(painCave.errMsg,
1092 "SimCreator Warning: No value was set for the switchingRadius.\n"
1093 "\tOOPSE will use the same value as the cutoffRadius.\n"
1094 "\tswitchingRadius = %f. for this simulation\n", rsw_);
1095 painCave.isFatal = 0;
1096 simError();
1097 }
1098 }
1099
1100 if (simParams_->haveElectrostaticSummationMethod()) {
1101 std::string myMethod = simParams_->getElectrostaticSummationMethod();
1102 toUpper(myMethod);
1103
1104 if (myMethod == "SHIFTED_POTENTIAL") {
1105 ljsp_ = true;
1106 } else if (myMethod == "SHIFTED_FORCE") {
1107 ljsf_ = true;
1108 }
1109 }
1110 notifyFortranCutoffs(&rcut_, &rsw_, &ljsp_, &ljsf_);
1111
1112 } else {
1113
1114 // For electrostatic atoms, we'll assume a large safe value:
1115 if (fInfo_.SIM_uses_Charges | fInfo_.SIM_uses_Dipoles | fInfo_.SIM_uses_RF) {
1116 sprintf(painCave.errMsg,
1117 "SimCreator Warning: No value was set for the cutoffRadius.\n"
1118 "\tOOPSE will use a default value of 15.0 angstroms"
1119 "\tfor the cutoffRadius.\n");
1120 painCave.isFatal = 0;
1121 simError();
1122 rcut_ = 15.0;
1123
1124 if (simParams_->haveElectrostaticSummationMethod()) {
1125 std::string myMethod = simParams_->getElectrostaticSummationMethod();
1126 toUpper(myMethod);
1127
1128 // For the time being, we're tethering the LJ shifted behavior to the
1129 // electrostaticSummationMethod keyword options
1130 if (myMethod == "SHIFTED_POTENTIAL") {
1131 ljsp_ = true;
1132 } else if (myMethod == "SHIFTED_FORCE") {
1133 ljsf_ = true;
1134 }
1135 if (myMethod == "SHIFTED_POTENTIAL" || myMethod == "SHIFTED_FORCE") {
1136 if (simParams_->haveSwitchingRadius()){
1137 sprintf(painCave.errMsg,
1138 "SimInfo Warning: A value was set for the switchingRadius\n"
1139 "\teven though the electrostaticSummationMethod was\n"
1140 "\tset to %s\n", myMethod.c_str());
1141 painCave.isFatal = 1;
1142 simError();
1143 }
1144 }
1145 }
1146
1147 if (simParams_->haveSwitchingRadius()){
1148 rsw_ = simParams_->getSwitchingRadius();
1149 } else {
1150 sprintf(painCave.errMsg,
1151 "SimCreator Warning: No value was set for switchingRadius.\n"
1152 "\tOOPSE will use a default value of\n"
1153 "\t0.85 * cutoffRadius for the switchingRadius\n");
1154 painCave.isFatal = 0;
1155 simError();
1156 rsw_ = 0.85 * rcut_;
1157 }
1158
1159 notifyFortranCutoffs(&rcut_, &rsw_, &ljsp_, &ljsf_);
1160
1161 } else {
1162 // We didn't set rcut explicitly, and we don't have electrostatic atoms, so
1163 // We'll punt and let fortran figure out the cutoffs later.
1164
1165 notifyFortranYouAreOnYourOwn();
1166
1167 }
1168 }
1169 }
1170
1171 void SimInfo::setupElectrostaticSummationMethod( int isError ) {
1172
1173 int errorOut;
1174 int esm = NONE;
1175 int sm = UNDAMPED;
1176 RealType alphaVal;
1177 RealType dielectric;
1178
1179 errorOut = isError;
1180
1181 if (simParams_->haveElectrostaticSummationMethod()) {
1182 std::string myMethod = simParams_->getElectrostaticSummationMethod();
1183 toUpper(myMethod);
1184 if (myMethod == "NONE") {
1185 esm = NONE;
1186 } else {
1187 if (myMethod == "SWITCHING_FUNCTION") {
1188 esm = SWITCHING_FUNCTION;
1189 } else {
1190 if (myMethod == "SHIFTED_POTENTIAL") {
1191 esm = SHIFTED_POTENTIAL;
1192 } else {
1193 if (myMethod == "SHIFTED_FORCE") {
1194 esm = SHIFTED_FORCE;
1195 } else {
1196 if (myMethod == "REACTION_FIELD") {
1197 esm = REACTION_FIELD;
1198 dielectric = simParams_->getDielectric();
1199 if (!simParams_->haveDielectric()) {
1200 // throw warning
1201 sprintf( painCave.errMsg,
1202 "SimInfo warning: dielectric was not specified in the input file\n\tfor the reaction field correction method.\n"
1203 "\tA default value of %f will be used for the dielectric.\n", dielectric);
1204 painCave.isFatal = 0;
1205 simError();
1206 }
1207 } else {
1208 // throw error
1209 sprintf( painCave.errMsg,
1210 "SimInfo error: Unknown electrostaticSummationMethod.\n"
1211 "\t(Input file specified %s .)\n"
1212 "\telectrostaticSummationMethod must be one of: \"none\",\n"
1213 "\t\"shifted_potential\", \"shifted_force\", or \n"
1214 "\t\"reaction_field\".\n", myMethod.c_str() );
1215 painCave.isFatal = 1;
1216 simError();
1217 }
1218 }
1219 }
1220 }
1221 }
1222 }
1223
1224 if (simParams_->haveElectrostaticScreeningMethod()) {
1225 std::string myScreen = simParams_->getElectrostaticScreeningMethod();
1226 toUpper(myScreen);
1227 if (myScreen == "UNDAMPED") {
1228 sm = UNDAMPED;
1229 } else {
1230 if (myScreen == "DAMPED") {
1231 sm = DAMPED;
1232 if (!simParams_->haveDampingAlpha()) {
1233 // first set a cutoff dependent alpha value
1234 // we assume alpha depends linearly with rcut from 0 to 20.5 ang
1235 alphaVal = 0.5125 - rcut_* 0.025;
1236 // for values rcut > 20.5, alpha is zero
1237 if (alphaVal < 0) alphaVal = 0;
1238
1239 // throw warning
1240 sprintf( painCave.errMsg,
1241 "SimInfo warning: dampingAlpha was not specified in the input file.\n"
1242 "\tA default value of %f (1/ang) will be used for the cutoff of\n\t%f (ang).\n", alphaVal, rcut_);
1243 painCave.isFatal = 0;
1244 simError();
1245 } else {
1246 alphaVal = simParams_->getDampingAlpha();
1247 }
1248
1249 } else {
1250 // throw error
1251 sprintf( painCave.errMsg,
1252 "SimInfo error: Unknown electrostaticScreeningMethod.\n"
1253 "\t(Input file specified %s .)\n"
1254 "\telectrostaticScreeningMethod must be one of: \"undamped\"\n"
1255 "or \"damped\".\n", myScreen.c_str() );
1256 painCave.isFatal = 1;
1257 simError();
1258 }
1259 }
1260 }
1261
1262 // let's pass some summation method variables to fortran
1263 setElectrostaticSummationMethod( &esm );
1264 setFortranElectrostaticMethod( &esm );
1265 setScreeningMethod( &sm );
1266 setDampingAlpha( &alphaVal );
1267 setReactionFieldDielectric( &dielectric );
1268 initFortranFF( &errorOut );
1269 }
1270
1271 void SimInfo::setupSwitchingFunction() {
1272 int ft = CUBIC;
1273
1274 if (simParams_->haveSwitchingFunctionType()) {
1275 std::string funcType = simParams_->getSwitchingFunctionType();
1276 toUpper(funcType);
1277 if (funcType == "CUBIC") {
1278 ft = CUBIC;
1279 } else {
1280 if (funcType == "FIFTH_ORDER_POLYNOMIAL") {
1281 ft = FIFTH_ORDER_POLY;
1282 } else {
1283 // throw error
1284 sprintf( painCave.errMsg,
1285 "SimInfo error: Unknown switchingFunctionType. (Input file specified %s .)\n\tswitchingFunctionType must be one of: \"cubic\" or \"fifth_order_polynomial\".", funcType.c_str() );
1286 painCave.isFatal = 1;
1287 simError();
1288 }
1289 }
1290 }
1291
1292 // send switching function notification to switcheroo
1293 setFunctionType(&ft);
1294
1295 }
1296
1297 void SimInfo::setupAccumulateBoxDipole() {
1298
1299 // we only call setAccumulateBoxDipole if the accumulateBoxDipole parameter is true
1300 if ( simParams_->haveAccumulateBoxDipole() )
1301 if ( simParams_->getAccumulateBoxDipole() ) {
1302 setAccumulateBoxDipole();
1303 calcBoxDipole_ = true;
1304 }
1305
1306 }
1307
1308 void SimInfo::addProperty(GenericData* genData) {
1309 properties_.addProperty(genData);
1310 }
1311
1312 void SimInfo::removeProperty(const std::string& propName) {
1313 properties_.removeProperty(propName);
1314 }
1315
1316 void SimInfo::clearProperties() {
1317 properties_.clearProperties();
1318 }
1319
1320 std::vector<std::string> SimInfo::getPropertyNames() {
1321 return properties_.getPropertyNames();
1322 }
1323
1324 std::vector<GenericData*> SimInfo::getProperties() {
1325 return properties_.getProperties();
1326 }
1327
1328 GenericData* SimInfo::getPropertyByName(const std::string& propName) {
1329 return properties_.getPropertyByName(propName);
1330 }
1331
1332 void SimInfo::setSnapshotManager(SnapshotManager* sman) {
1333 if (sman_ == sman) {
1334 return;
1335 }
1336 delete sman_;
1337 sman_ = sman;
1338
1339 Molecule* mol;
1340 RigidBody* rb;
1341 Atom* atom;
1342 SimInfo::MoleculeIterator mi;
1343 Molecule::RigidBodyIterator rbIter;
1344 Molecule::AtomIterator atomIter;;
1345
1346 for (mol = beginMolecule(mi); mol != NULL; mol = nextMolecule(mi)) {
1347
1348 for (atom = mol->beginAtom(atomIter); atom != NULL; atom = mol->nextAtom(atomIter)) {
1349 atom->setSnapshotManager(sman_);
1350 }
1351
1352 for (rb = mol->beginRigidBody(rbIter); rb != NULL; rb = mol->nextRigidBody(rbIter)) {
1353 rb->setSnapshotManager(sman_);
1354 }
1355 }
1356
1357 }
1358
1359 Vector3d SimInfo::getComVel(){
1360 SimInfo::MoleculeIterator i;
1361 Molecule* mol;
1362
1363 Vector3d comVel(0.0);
1364 RealType totalMass = 0.0;
1365
1366
1367 for (mol = beginMolecule(i); mol != NULL; mol = nextMolecule(i)) {
1368 RealType mass = mol->getMass();
1369 totalMass += mass;
1370 comVel += mass * mol->getComVel();
1371 }
1372
1373 #ifdef IS_MPI
1374 RealType tmpMass = totalMass;
1375 Vector3d tmpComVel(comVel);
1376 MPI_Allreduce(&tmpMass,&totalMass,1,MPI_REALTYPE,MPI_SUM, MPI_COMM_WORLD);
1377 MPI_Allreduce(tmpComVel.getArrayPointer(), comVel.getArrayPointer(),3,MPI_REALTYPE,MPI_SUM, MPI_COMM_WORLD);
1378 #endif
1379
1380 comVel /= totalMass;
1381
1382 return comVel;
1383 }
1384
1385 Vector3d SimInfo::getCom(){
1386 SimInfo::MoleculeIterator i;
1387 Molecule* mol;
1388
1389 Vector3d com(0.0);
1390 RealType totalMass = 0.0;
1391
1392 for (mol = beginMolecule(i); mol != NULL; mol = nextMolecule(i)) {
1393 RealType mass = mol->getMass();
1394 totalMass += mass;
1395 com += mass * mol->getCom();
1396 }
1397
1398 #ifdef IS_MPI
1399 RealType tmpMass = totalMass;
1400 Vector3d tmpCom(com);
1401 MPI_Allreduce(&tmpMass,&totalMass,1,MPI_REALTYPE,MPI_SUM, MPI_COMM_WORLD);
1402 MPI_Allreduce(tmpCom.getArrayPointer(), com.getArrayPointer(),3,MPI_REALTYPE,MPI_SUM, MPI_COMM_WORLD);
1403 #endif
1404
1405 com /= totalMass;
1406
1407 return com;
1408
1409 }
1410
1411 std::ostream& operator <<(std::ostream& o, SimInfo& info) {
1412
1413 return o;
1414 }
1415
1416
1417 /*
1418 Returns center of mass and center of mass velocity in one function call.
1419 */
1420
1421 void SimInfo::getComAll(Vector3d &com, Vector3d &comVel){
1422 SimInfo::MoleculeIterator i;
1423 Molecule* mol;
1424
1425
1426 RealType totalMass = 0.0;
1427
1428
1429 for (mol = beginMolecule(i); mol != NULL; mol = nextMolecule(i)) {
1430 RealType mass = mol->getMass();
1431 totalMass += mass;
1432 com += mass * mol->getCom();
1433 comVel += mass * mol->getComVel();
1434 }
1435
1436 #ifdef IS_MPI
1437 RealType tmpMass = totalMass;
1438 Vector3d tmpCom(com);
1439 Vector3d tmpComVel(comVel);
1440 MPI_Allreduce(&tmpMass,&totalMass,1,MPI_REALTYPE,MPI_SUM, MPI_COMM_WORLD);
1441 MPI_Allreduce(tmpCom.getArrayPointer(), com.getArrayPointer(),3,MPI_REALTYPE,MPI_SUM, MPI_COMM_WORLD);
1442 MPI_Allreduce(tmpComVel.getArrayPointer(), comVel.getArrayPointer(),3,MPI_REALTYPE,MPI_SUM, MPI_COMM_WORLD);
1443 #endif
1444
1445 com /= totalMass;
1446 comVel /= totalMass;
1447 }
1448
1449 /*
1450 Return intertia tensor for entire system and angular momentum Vector.
1451
1452
1453 [ Ixx -Ixy -Ixz ]
1454 J =| -Iyx Iyy -Iyz |
1455 [ -Izx -Iyz Izz ]
1456 */
1457
1458 void SimInfo::getInertiaTensor(Mat3x3d &inertiaTensor, Vector3d &angularMomentum){
1459
1460
1461 RealType xx = 0.0;
1462 RealType yy = 0.0;
1463 RealType zz = 0.0;
1464 RealType xy = 0.0;
1465 RealType xz = 0.0;
1466 RealType yz = 0.0;
1467 Vector3d com(0.0);
1468 Vector3d comVel(0.0);
1469
1470 getComAll(com, comVel);
1471
1472 SimInfo::MoleculeIterator i;
1473 Molecule* mol;
1474
1475 Vector3d thisq(0.0);
1476 Vector3d thisv(0.0);
1477
1478 RealType thisMass = 0.0;
1479
1480
1481
1482
1483 for (mol = beginMolecule(i); mol != NULL; mol = nextMolecule(i)) {
1484
1485 thisq = mol->getCom()-com;
1486 thisv = mol->getComVel()-comVel;
1487 thisMass = mol->getMass();
1488 // Compute moment of intertia coefficients.
1489 xx += thisq[0]*thisq[0]*thisMass;
1490 yy += thisq[1]*thisq[1]*thisMass;
1491 zz += thisq[2]*thisq[2]*thisMass;
1492
1493 // compute products of intertia
1494 xy += thisq[0]*thisq[1]*thisMass;
1495 xz += thisq[0]*thisq[2]*thisMass;
1496 yz += thisq[1]*thisq[2]*thisMass;
1497
1498 angularMomentum += cross( thisq, thisv ) * thisMass;
1499
1500 }
1501
1502
1503 inertiaTensor(0,0) = yy + zz;
1504 inertiaTensor(0,1) = -xy;
1505 inertiaTensor(0,2) = -xz;
1506 inertiaTensor(1,0) = -xy;
1507 inertiaTensor(1,1) = xx + zz;
1508 inertiaTensor(1,2) = -yz;
1509 inertiaTensor(2,0) = -xz;
1510 inertiaTensor(2,1) = -yz;
1511 inertiaTensor(2,2) = xx + yy;
1512
1513 #ifdef IS_MPI
1514 Mat3x3d tmpI(inertiaTensor);
1515 Vector3d tmpAngMom;
1516 MPI_Allreduce(tmpI.getArrayPointer(), inertiaTensor.getArrayPointer(),9,MPI_REALTYPE,MPI_SUM, MPI_COMM_WORLD);
1517 MPI_Allreduce(tmpAngMom.getArrayPointer(), angularMomentum.getArrayPointer(),3,MPI_REALTYPE,MPI_SUM, MPI_COMM_WORLD);
1518 #endif
1519
1520 return;
1521 }
1522
1523 //Returns the angular momentum of the system
1524 Vector3d SimInfo::getAngularMomentum(){
1525
1526 Vector3d com(0.0);
1527 Vector3d comVel(0.0);
1528 Vector3d angularMomentum(0.0);
1529
1530 getComAll(com,comVel);
1531
1532 SimInfo::MoleculeIterator i;
1533 Molecule* mol;
1534
1535 Vector3d thisr(0.0);
1536 Vector3d thisp(0.0);
1537
1538 RealType thisMass;
1539
1540 for (mol = beginMolecule(i); mol != NULL; mol = nextMolecule(i)) {
1541 thisMass = mol->getMass();
1542 thisr = mol->getCom()-com;
1543 thisp = (mol->getComVel()-comVel)*thisMass;
1544
1545 angularMomentum += cross( thisr, thisp );
1546
1547 }
1548
1549 #ifdef IS_MPI
1550 Vector3d tmpAngMom;
1551 MPI_Allreduce(tmpAngMom.getArrayPointer(), angularMomentum.getArrayPointer(),3,MPI_REALTYPE,MPI_SUM, MPI_COMM_WORLD);
1552 #endif
1553
1554 return angularMomentum;
1555 }
1556
1557 StuntDouble* SimInfo::getIOIndexToIntegrableObject(int index) {
1558 return IOIndexToIntegrableObject.at(index);
1559 }
1560
1561 void SimInfo::setIOIndexToIntegrableObject(const std::vector<StuntDouble*>& v) {
1562 IOIndexToIntegrableObject= v;
1563 }
1564
1565 /* Returns the Volume of the simulation based on a ellipsoid with semi-axes
1566 based on the radius of gyration V=4/3*Pi*R_1*R_2*R_3
1567 where R_i are related to the principle inertia moments R_i = sqrt(C*I_i/N), this reduces to
1568 V = 4/3*Pi*(C/N)^3/2*sqrt(det(I)). See S.E. Baltazar et. al. Comp. Mat. Sci. 37 (2006) 526-536.
1569 */
1570 void SimInfo::getGyrationalVolume(RealType &volume){
1571 Mat3x3d intTensor;
1572 RealType det;
1573 Vector3d dummyAngMom;
1574 RealType sysconstants;
1575 RealType geomCnst;
1576
1577 geomCnst = 3.0/2.0;
1578 /* Get the inertial tensor and angular momentum for free*/
1579 getInertiaTensor(intTensor,dummyAngMom);
1580
1581 det = intTensor.determinant();
1582 sysconstants = geomCnst/(RealType)nGlobalIntegrableObjects_;
1583 volume = 4.0/3.0*NumericConstant::PI*pow(sysconstants,3.0/2.0)*sqrt(det);
1584 return;
1585 }
1586
1587 void SimInfo::getGyrationalVolume(RealType &volume, RealType &detI){
1588 Mat3x3d intTensor;
1589 Vector3d dummyAngMom;
1590 RealType sysconstants;
1591 RealType geomCnst;
1592
1593 geomCnst = 3.0/2.0;
1594 /* Get the inertial tensor and angular momentum for free*/
1595 getInertiaTensor(intTensor,dummyAngMom);
1596
1597 detI = intTensor.determinant();
1598 sysconstants = geomCnst/(RealType)nGlobalIntegrableObjects_;
1599 volume = 4.0/3.0*NumericConstant::PI*pow(sysconstants,3.0/2.0)*sqrt(detI);
1600 return;
1601 }
1602 /*
1603 void SimInfo::setStuntDoubleFromGlobalIndex(std::vector<StuntDouble*> v) {
1604 assert( v.size() == nAtoms_ + nRigidBodies_);
1605 sdByGlobalIndex_ = v;
1606 }
1607
1608 StuntDouble* SimInfo::getStuntDoubleFromGlobalIndex(int index) {
1609 //assert(index < nAtoms_ + nRigidBodies_);
1610 return sdByGlobalIndex_.at(index);
1611 }
1612 */
1613 }//end namespace oopse
1614