ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/group/trunk/OOPSE-2.0/src/brains/SimInfo.cpp
Revision: 2307
Committed: Fri Sep 16 21:07:45 2005 UTC (18 years, 9 months ago) by chrisfen
File size: 34538 byte(s)
Log Message:
xlf found a bug that ifc missed...

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
52 #include "brains/SimInfo.hpp"
53 #include "math/Vector3.hpp"
54 #include "primitives/Molecule.hpp"
55 #include "UseTheForce/fCutoffPolicy.h"
56 #include "UseTheForce/DarkSide/fElectrostaticSummationMethod.h"
57 #include "UseTheForce/doForces_interface.h"
58 #include "UseTheForce/notifyCutoffs_interface.h"
59 #include "utils/MemoryUtils.hpp"
60 #include "utils/simError.h"
61 #include "selection/SelectionManager.hpp"
62
63 #ifdef IS_MPI
64 #include "UseTheForce/mpiComponentPlan.h"
65 #include "UseTheForce/DarkSide/simParallel_interface.h"
66 #endif
67
68 namespace oopse {
69
70 SimInfo::SimInfo(MakeStamps* stamps, std::vector<std::pair<MoleculeStamp*, int> >& molStampPairs,
71 ForceField* ff, Globals* simParams) :
72 stamps_(stamps), forceField_(ff), simParams_(simParams),
73 ndf_(0), ndfRaw_(0), ndfTrans_(0), nZconstraint_(0),
74 nGlobalMols_(0), nGlobalAtoms_(0), nGlobalCutoffGroups_(0),
75 nGlobalIntegrableObjects_(0), nGlobalRigidBodies_(0),
76 nAtoms_(0), nBonds_(0), nBends_(0), nTorsions_(0), nRigidBodies_(0),
77 nIntegrableObjects_(0), nCutoffGroups_(0), nConstraints_(0),
78 sman_(NULL), fortranInitialized_(false) {
79
80
81 std::vector<std::pair<MoleculeStamp*, int> >::iterator i;
82 MoleculeStamp* molStamp;
83 int nMolWithSameStamp;
84 int nCutoffAtoms = 0; // number of atoms belong to cutoff groups
85 int nGroups = 0; //total cutoff groups defined in meta-data file
86 CutoffGroupStamp* cgStamp;
87 RigidBodyStamp* rbStamp;
88 int nRigidAtoms = 0;
89
90 for (i = molStampPairs.begin(); i !=molStampPairs.end(); ++i) {
91 molStamp = i->first;
92 nMolWithSameStamp = i->second;
93
94 addMoleculeStamp(molStamp, nMolWithSameStamp);
95
96 //calculate atoms in molecules
97 nGlobalAtoms_ += molStamp->getNAtoms() *nMolWithSameStamp;
98
99
100 //calculate atoms in cutoff groups
101 int nAtomsInGroups = 0;
102 int nCutoffGroupsInStamp = molStamp->getNCutoffGroups();
103
104 for (int j=0; j < nCutoffGroupsInStamp; j++) {
105 cgStamp = molStamp->getCutoffGroup(j);
106 nAtomsInGroups += cgStamp->getNMembers();
107 }
108
109 nGroups += nCutoffGroupsInStamp * nMolWithSameStamp;
110 nCutoffAtoms += nAtomsInGroups * nMolWithSameStamp;
111
112 //calculate atoms in rigid bodies
113 int nAtomsInRigidBodies = 0;
114 int nRigidBodiesInStamp = molStamp->getNRigidBodies();
115
116 for (int j=0; j < nRigidBodiesInStamp; j++) {
117 rbStamp = molStamp->getRigidBody(j);
118 nAtomsInRigidBodies += rbStamp->getNMembers();
119 }
120
121 nGlobalRigidBodies_ += nRigidBodiesInStamp * nMolWithSameStamp;
122 nRigidAtoms += nAtomsInRigidBodies * nMolWithSameStamp;
123
124 }
125
126 //every free atom (atom does not belong to cutoff groups) is a cutoff group
127 //therefore the total number of cutoff groups in the system is equal to
128 //the total number of atoms minus number of atoms belong to cutoff group defined in meta-data
129 //file plus the number of cutoff groups defined in meta-data file
130 nGlobalCutoffGroups_ = nGlobalAtoms_ - nCutoffAtoms + nGroups;
131
132 //every free atom (atom does not belong to rigid bodies) is an integrable object
133 //therefore the total number of integrable objects in the system is equal to
134 //the total number of atoms minus number of atoms belong to rigid body defined in meta-data
135 //file plus the number of rigid bodies defined in meta-data file
136 nGlobalIntegrableObjects_ = nGlobalAtoms_ - nRigidAtoms + nGlobalRigidBodies_;
137
138 nGlobalMols_ = molStampIds_.size();
139
140 #ifdef IS_MPI
141 molToProcMap_.resize(nGlobalMols_);
142 #endif
143
144 }
145
146 SimInfo::~SimInfo() {
147 std::map<int, Molecule*>::iterator i;
148 for (i = molecules_.begin(); i != molecules_.end(); ++i) {
149 delete i->second;
150 }
151 molecules_.clear();
152
153 delete stamps_;
154 delete sman_;
155 delete simParams_;
156 delete forceField_;
157 }
158
159 int SimInfo::getNGlobalConstraints() {
160 int nGlobalConstraints;
161 #ifdef IS_MPI
162 MPI_Allreduce(&nConstraints_, &nGlobalConstraints, 1, MPI_INT, MPI_SUM,
163 MPI_COMM_WORLD);
164 #else
165 nGlobalConstraints = nConstraints_;
166 #endif
167 return nGlobalConstraints;
168 }
169
170 bool SimInfo::addMolecule(Molecule* mol) {
171 MoleculeIterator i;
172
173 i = molecules_.find(mol->getGlobalIndex());
174 if (i == molecules_.end() ) {
175
176 molecules_.insert(std::make_pair(mol->getGlobalIndex(), mol));
177
178 nAtoms_ += mol->getNAtoms();
179 nBonds_ += mol->getNBonds();
180 nBends_ += mol->getNBends();
181 nTorsions_ += mol->getNTorsions();
182 nRigidBodies_ += mol->getNRigidBodies();
183 nIntegrableObjects_ += mol->getNIntegrableObjects();
184 nCutoffGroups_ += mol->getNCutoffGroups();
185 nConstraints_ += mol->getNConstraintPairs();
186
187 addExcludePairs(mol);
188
189 return true;
190 } else {
191 return false;
192 }
193 }
194
195 bool SimInfo::removeMolecule(Molecule* mol) {
196 MoleculeIterator i;
197 i = molecules_.find(mol->getGlobalIndex());
198
199 if (i != molecules_.end() ) {
200
201 assert(mol == i->second);
202
203 nAtoms_ -= mol->getNAtoms();
204 nBonds_ -= mol->getNBonds();
205 nBends_ -= mol->getNBends();
206 nTorsions_ -= mol->getNTorsions();
207 nRigidBodies_ -= mol->getNRigidBodies();
208 nIntegrableObjects_ -= mol->getNIntegrableObjects();
209 nCutoffGroups_ -= mol->getNCutoffGroups();
210 nConstraints_ -= mol->getNConstraintPairs();
211
212 removeExcludePairs(mol);
213 molecules_.erase(mol->getGlobalIndex());
214
215 delete mol;
216
217 return true;
218 } else {
219 return false;
220 }
221
222
223 }
224
225
226 Molecule* SimInfo::beginMolecule(MoleculeIterator& i) {
227 i = molecules_.begin();
228 return i == molecules_.end() ? NULL : i->second;
229 }
230
231 Molecule* SimInfo::nextMolecule(MoleculeIterator& i) {
232 ++i;
233 return i == molecules_.end() ? NULL : i->second;
234 }
235
236
237 void SimInfo::calcNdf() {
238 int ndf_local;
239 MoleculeIterator i;
240 std::vector<StuntDouble*>::iterator j;
241 Molecule* mol;
242 StuntDouble* integrableObject;
243
244 ndf_local = 0;
245
246 for (mol = beginMolecule(i); mol != NULL; mol = nextMolecule(i)) {
247 for (integrableObject = mol->beginIntegrableObject(j); integrableObject != NULL;
248 integrableObject = mol->nextIntegrableObject(j)) {
249
250 ndf_local += 3;
251
252 if (integrableObject->isDirectional()) {
253 if (integrableObject->isLinear()) {
254 ndf_local += 2;
255 } else {
256 ndf_local += 3;
257 }
258 }
259
260 }//end for (integrableObject)
261 }// end for (mol)
262
263 // n_constraints is local, so subtract them on each processor
264 ndf_local -= nConstraints_;
265
266 #ifdef IS_MPI
267 MPI_Allreduce(&ndf_local,&ndf_,1,MPI_INT,MPI_SUM, MPI_COMM_WORLD);
268 #else
269 ndf_ = ndf_local;
270 #endif
271
272 // nZconstraints_ is global, as are the 3 COM translations for the
273 // entire system:
274 ndf_ = ndf_ - 3 - nZconstraint_;
275
276 }
277
278 void SimInfo::calcNdfRaw() {
279 int ndfRaw_local;
280
281 MoleculeIterator i;
282 std::vector<StuntDouble*>::iterator j;
283 Molecule* mol;
284 StuntDouble* integrableObject;
285
286 // Raw degrees of freedom that we have to set
287 ndfRaw_local = 0;
288
289 for (mol = beginMolecule(i); mol != NULL; mol = nextMolecule(i)) {
290 for (integrableObject = mol->beginIntegrableObject(j); integrableObject != NULL;
291 integrableObject = mol->nextIntegrableObject(j)) {
292
293 ndfRaw_local += 3;
294
295 if (integrableObject->isDirectional()) {
296 if (integrableObject->isLinear()) {
297 ndfRaw_local += 2;
298 } else {
299 ndfRaw_local += 3;
300 }
301 }
302
303 }
304 }
305
306 #ifdef IS_MPI
307 MPI_Allreduce(&ndfRaw_local,&ndfRaw_,1,MPI_INT,MPI_SUM, MPI_COMM_WORLD);
308 #else
309 ndfRaw_ = ndfRaw_local;
310 #endif
311 }
312
313 void SimInfo::calcNdfTrans() {
314 int ndfTrans_local;
315
316 ndfTrans_local = 3 * nIntegrableObjects_ - nConstraints_;
317
318
319 #ifdef IS_MPI
320 MPI_Allreduce(&ndfTrans_local,&ndfTrans_,1,MPI_INT,MPI_SUM, MPI_COMM_WORLD);
321 #else
322 ndfTrans_ = ndfTrans_local;
323 #endif
324
325 ndfTrans_ = ndfTrans_ - 3 - nZconstraint_;
326
327 }
328
329 void SimInfo::addExcludePairs(Molecule* mol) {
330 std::vector<Bond*>::iterator bondIter;
331 std::vector<Bend*>::iterator bendIter;
332 std::vector<Torsion*>::iterator torsionIter;
333 Bond* bond;
334 Bend* bend;
335 Torsion* torsion;
336 int a;
337 int b;
338 int c;
339 int d;
340
341 for (bond= mol->beginBond(bondIter); bond != NULL; bond = mol->nextBond(bondIter)) {
342 a = bond->getAtomA()->getGlobalIndex();
343 b = bond->getAtomB()->getGlobalIndex();
344 exclude_.addPair(a, b);
345 }
346
347 for (bend= mol->beginBend(bendIter); bend != NULL; bend = mol->nextBend(bendIter)) {
348 a = bend->getAtomA()->getGlobalIndex();
349 b = bend->getAtomB()->getGlobalIndex();
350 c = bend->getAtomC()->getGlobalIndex();
351
352 exclude_.addPair(a, b);
353 exclude_.addPair(a, c);
354 exclude_.addPair(b, c);
355 }
356
357 for (torsion= mol->beginTorsion(torsionIter); torsion != NULL; torsion = mol->nextTorsion(torsionIter)) {
358 a = torsion->getAtomA()->getGlobalIndex();
359 b = torsion->getAtomB()->getGlobalIndex();
360 c = torsion->getAtomC()->getGlobalIndex();
361 d = torsion->getAtomD()->getGlobalIndex();
362
363 exclude_.addPair(a, b);
364 exclude_.addPair(a, c);
365 exclude_.addPair(a, d);
366 exclude_.addPair(b, c);
367 exclude_.addPair(b, d);
368 exclude_.addPair(c, d);
369 }
370
371 Molecule::RigidBodyIterator rbIter;
372 RigidBody* rb;
373 for (rb = mol->beginRigidBody(rbIter); rb != NULL; rb = mol->nextRigidBody(rbIter)) {
374 std::vector<Atom*> atoms = rb->getAtoms();
375 for (int i = 0; i < atoms.size() -1 ; ++i) {
376 for (int j = i + 1; j < atoms.size(); ++j) {
377 a = atoms[i]->getGlobalIndex();
378 b = atoms[j]->getGlobalIndex();
379 exclude_.addPair(a, b);
380 }
381 }
382 }
383
384 }
385
386 void SimInfo::removeExcludePairs(Molecule* mol) {
387 std::vector<Bond*>::iterator bondIter;
388 std::vector<Bend*>::iterator bendIter;
389 std::vector<Torsion*>::iterator torsionIter;
390 Bond* bond;
391 Bend* bend;
392 Torsion* torsion;
393 int a;
394 int b;
395 int c;
396 int d;
397
398 for (bond= mol->beginBond(bondIter); bond != NULL; bond = mol->nextBond(bondIter)) {
399 a = bond->getAtomA()->getGlobalIndex();
400 b = bond->getAtomB()->getGlobalIndex();
401 exclude_.removePair(a, b);
402 }
403
404 for (bend= mol->beginBend(bendIter); bend != NULL; bend = mol->nextBend(bendIter)) {
405 a = bend->getAtomA()->getGlobalIndex();
406 b = bend->getAtomB()->getGlobalIndex();
407 c = bend->getAtomC()->getGlobalIndex();
408
409 exclude_.removePair(a, b);
410 exclude_.removePair(a, c);
411 exclude_.removePair(b, c);
412 }
413
414 for (torsion= mol->beginTorsion(torsionIter); torsion != NULL; torsion = mol->nextTorsion(torsionIter)) {
415 a = torsion->getAtomA()->getGlobalIndex();
416 b = torsion->getAtomB()->getGlobalIndex();
417 c = torsion->getAtomC()->getGlobalIndex();
418 d = torsion->getAtomD()->getGlobalIndex();
419
420 exclude_.removePair(a, b);
421 exclude_.removePair(a, c);
422 exclude_.removePair(a, d);
423 exclude_.removePair(b, c);
424 exclude_.removePair(b, d);
425 exclude_.removePair(c, d);
426 }
427
428 Molecule::RigidBodyIterator rbIter;
429 RigidBody* rb;
430 for (rb = mol->beginRigidBody(rbIter); rb != NULL; rb = mol->nextRigidBody(rbIter)) {
431 std::vector<Atom*> atoms = rb->getAtoms();
432 for (int i = 0; i < atoms.size() -1 ; ++i) {
433 for (int j = i + 1; j < atoms.size(); ++j) {
434 a = atoms[i]->getGlobalIndex();
435 b = atoms[j]->getGlobalIndex();
436 exclude_.removePair(a, b);
437 }
438 }
439 }
440
441 }
442
443
444 void SimInfo::addMoleculeStamp(MoleculeStamp* molStamp, int nmol) {
445 int curStampId;
446
447 //index from 0
448 curStampId = moleculeStamps_.size();
449
450 moleculeStamps_.push_back(molStamp);
451 molStampIds_.insert(molStampIds_.end(), nmol, curStampId);
452 }
453
454 void SimInfo::update() {
455
456 setupSimType();
457
458 #ifdef IS_MPI
459 setupFortranParallel();
460 #endif
461
462 setupFortranSim();
463
464 //setup fortran force field
465 /** @deprecate */
466 int isError = 0;
467
468 setupElectrostaticSummationMethod( isError );
469
470 if(isError){
471 sprintf( painCave.errMsg,
472 "ForceField error: There was an error initializing the forceField in fortran.\n" );
473 painCave.isFatal = 1;
474 simError();
475 }
476
477
478 setupCutoff();
479
480 calcNdf();
481 calcNdfRaw();
482 calcNdfTrans();
483
484 fortranInitialized_ = true;
485 }
486
487 std::set<AtomType*> SimInfo::getUniqueAtomTypes() {
488 SimInfo::MoleculeIterator mi;
489 Molecule* mol;
490 Molecule::AtomIterator ai;
491 Atom* atom;
492 std::set<AtomType*> atomTypes;
493
494 for(mol = beginMolecule(mi); mol != NULL; mol = nextMolecule(mi)) {
495
496 for(atom = mol->beginAtom(ai); atom != NULL; atom = mol->nextAtom(ai)) {
497 atomTypes.insert(atom->getAtomType());
498 }
499
500 }
501
502 return atomTypes;
503 }
504
505 void SimInfo::setupSimType() {
506 std::set<AtomType*>::iterator i;
507 std::set<AtomType*> atomTypes;
508 atomTypes = getUniqueAtomTypes();
509
510 int useLennardJones = 0;
511 int useElectrostatic = 0;
512 int useEAM = 0;
513 int useCharge = 0;
514 int useDirectional = 0;
515 int useDipole = 0;
516 int useGayBerne = 0;
517 int useSticky = 0;
518 int useStickyPower = 0;
519 int useShape = 0;
520 int useFLARB = 0; //it is not in AtomType yet
521 int useDirectionalAtom = 0;
522 int useElectrostatics = 0;
523 //usePBC and useRF are from simParams
524 int usePBC = simParams_->getPBC();
525
526 //loop over all of the atom types
527 for (i = atomTypes.begin(); i != atomTypes.end(); ++i) {
528 useLennardJones |= (*i)->isLennardJones();
529 useElectrostatic |= (*i)->isElectrostatic();
530 useEAM |= (*i)->isEAM();
531 useCharge |= (*i)->isCharge();
532 useDirectional |= (*i)->isDirectional();
533 useDipole |= (*i)->isDipole();
534 useGayBerne |= (*i)->isGayBerne();
535 useSticky |= (*i)->isSticky();
536 useStickyPower |= (*i)->isStickyPower();
537 useShape |= (*i)->isShape();
538 }
539
540 if (useSticky || useStickyPower || useDipole || useGayBerne || useShape) {
541 useDirectionalAtom = 1;
542 }
543
544 if (useCharge || useDipole) {
545 useElectrostatics = 1;
546 }
547
548 #ifdef IS_MPI
549 int temp;
550
551 temp = usePBC;
552 MPI_Allreduce(&temp, &usePBC, 1, MPI_INT, MPI_LOR, MPI_COMM_WORLD);
553
554 temp = useDirectionalAtom;
555 MPI_Allreduce(&temp, &useDirectionalAtom, 1, MPI_INT, MPI_LOR, MPI_COMM_WORLD);
556
557 temp = useLennardJones;
558 MPI_Allreduce(&temp, &useLennardJones, 1, MPI_INT, MPI_LOR, MPI_COMM_WORLD);
559
560 temp = useElectrostatics;
561 MPI_Allreduce(&temp, &useElectrostatics, 1, MPI_INT, MPI_LOR, MPI_COMM_WORLD);
562
563 temp = useCharge;
564 MPI_Allreduce(&temp, &useCharge, 1, MPI_INT, MPI_LOR, MPI_COMM_WORLD);
565
566 temp = useDipole;
567 MPI_Allreduce(&temp, &useDipole, 1, MPI_INT, MPI_LOR, MPI_COMM_WORLD);
568
569 temp = useSticky;
570 MPI_Allreduce(&temp, &useSticky, 1, MPI_INT, MPI_LOR, MPI_COMM_WORLD);
571
572 temp = useStickyPower;
573 MPI_Allreduce(&temp, &useStickyPower, 1, MPI_INT, MPI_LOR, MPI_COMM_WORLD);
574
575 temp = useGayBerne;
576 MPI_Allreduce(&temp, &useGayBerne, 1, MPI_INT, MPI_LOR, MPI_COMM_WORLD);
577
578 temp = useEAM;
579 MPI_Allreduce(&temp, &useEAM, 1, MPI_INT, MPI_LOR, MPI_COMM_WORLD);
580
581 temp = useShape;
582 MPI_Allreduce(&temp, &useShape, 1, MPI_INT, MPI_LOR, MPI_COMM_WORLD);
583
584 temp = useFLARB;
585 MPI_Allreduce(&temp, &useFLARB, 1, MPI_INT, MPI_LOR, MPI_COMM_WORLD);
586
587 #endif
588
589 fInfo_.SIM_uses_PBC = usePBC;
590 fInfo_.SIM_uses_DirectionalAtoms = useDirectionalAtom;
591 fInfo_.SIM_uses_LennardJones = useLennardJones;
592 fInfo_.SIM_uses_Electrostatics = useElectrostatics;
593 fInfo_.SIM_uses_Charges = useCharge;
594 fInfo_.SIM_uses_Dipoles = useDipole;
595 fInfo_.SIM_uses_Sticky = useSticky;
596 fInfo_.SIM_uses_StickyPower = useStickyPower;
597 fInfo_.SIM_uses_GayBerne = useGayBerne;
598 fInfo_.SIM_uses_EAM = useEAM;
599 fInfo_.SIM_uses_Shapes = useShape;
600 fInfo_.SIM_uses_FLARB = useFLARB;
601
602 if( fInfo_.SIM_uses_Dipoles && fInfo_.SIM_uses_RF) {
603
604 if (simParams_->haveDielectric()) {
605 fInfo_.dielect = simParams_->getDielectric();
606 } else {
607 sprintf(painCave.errMsg,
608 "SimSetup Error: No Dielectric constant was set.\n"
609 "\tYou are trying to use Reaction Field without"
610 "\tsetting a dielectric constant!\n");
611 painCave.isFatal = 1;
612 simError();
613 }
614
615 } else {
616 fInfo_.dielect = 0.0;
617 }
618
619 }
620
621 void SimInfo::setupFortranSim() {
622 int isError;
623 int nExclude;
624 std::vector<int> fortranGlobalGroupMembership;
625
626 nExclude = exclude_.getSize();
627 isError = 0;
628
629 //globalGroupMembership_ is filled by SimCreator
630 for (int i = 0; i < nGlobalAtoms_; i++) {
631 fortranGlobalGroupMembership.push_back(globalGroupMembership_[i] + 1);
632 }
633
634 //calculate mass ratio of cutoff group
635 std::vector<double> mfact;
636 SimInfo::MoleculeIterator mi;
637 Molecule* mol;
638 Molecule::CutoffGroupIterator ci;
639 CutoffGroup* cg;
640 Molecule::AtomIterator ai;
641 Atom* atom;
642 double totalMass;
643
644 //to avoid memory reallocation, reserve enough space for mfact
645 mfact.reserve(getNCutoffGroups());
646
647 for(mol = beginMolecule(mi); mol != NULL; mol = nextMolecule(mi)) {
648 for (cg = mol->beginCutoffGroup(ci); cg != NULL; cg = mol->nextCutoffGroup(ci)) {
649
650 totalMass = cg->getMass();
651 for(atom = cg->beginAtom(ai); atom != NULL; atom = cg->nextAtom(ai)) {
652 mfact.push_back(atom->getMass()/totalMass);
653 }
654
655 }
656 }
657
658 //fill ident array of local atoms (it is actually ident of AtomType, it is so confusing !!!)
659 std::vector<int> identArray;
660
661 //to avoid memory reallocation, reserve enough space identArray
662 identArray.reserve(getNAtoms());
663
664 for(mol = beginMolecule(mi); mol != NULL; mol = nextMolecule(mi)) {
665 for(atom = mol->beginAtom(ai); atom != NULL; atom = mol->nextAtom(ai)) {
666 identArray.push_back(atom->getIdent());
667 }
668 }
669
670 //fill molMembershipArray
671 //molMembershipArray is filled by SimCreator
672 std::vector<int> molMembershipArray(nGlobalAtoms_);
673 for (int i = 0; i < nGlobalAtoms_; i++) {
674 molMembershipArray[i] = globalMolMembership_[i] + 1;
675 }
676
677 //setup fortran simulation
678 int nGlobalExcludes = 0;
679 int* globalExcludes = NULL;
680 int* excludeList = exclude_.getExcludeList();
681 setFortranSim( &fInfo_, &nGlobalAtoms_, &nAtoms_, &identArray[0], &nExclude, excludeList ,
682 &nGlobalExcludes, globalExcludes, &molMembershipArray[0],
683 &mfact[0], &nCutoffGroups_, &fortranGlobalGroupMembership[0], &isError);
684
685 if( isError ){
686
687 sprintf( painCave.errMsg,
688 "There was an error setting the simulation information in fortran.\n" );
689 painCave.isFatal = 1;
690 painCave.severity = OOPSE_ERROR;
691 simError();
692 }
693
694 #ifdef IS_MPI
695 sprintf( checkPointMsg,
696 "succesfully sent the simulation information to fortran.\n");
697 MPIcheckPoint();
698 #endif // is_mpi
699 }
700
701
702 #ifdef IS_MPI
703 void SimInfo::setupFortranParallel() {
704
705 //SimInfo is responsible for creating localToGlobalAtomIndex and localToGlobalGroupIndex
706 std::vector<int> localToGlobalAtomIndex(getNAtoms(), 0);
707 std::vector<int> localToGlobalCutoffGroupIndex;
708 SimInfo::MoleculeIterator mi;
709 Molecule::AtomIterator ai;
710 Molecule::CutoffGroupIterator ci;
711 Molecule* mol;
712 Atom* atom;
713 CutoffGroup* cg;
714 mpiSimData parallelData;
715 int isError;
716
717 for (mol = beginMolecule(mi); mol != NULL; mol = nextMolecule(mi)) {
718
719 //local index(index in DataStorge) of atom is important
720 for (atom = mol->beginAtom(ai); atom != NULL; atom = mol->nextAtom(ai)) {
721 localToGlobalAtomIndex[atom->getLocalIndex()] = atom->getGlobalIndex() + 1;
722 }
723
724 //local index of cutoff group is trivial, it only depends on the order of travesing
725 for (cg = mol->beginCutoffGroup(ci); cg != NULL; cg = mol->nextCutoffGroup(ci)) {
726 localToGlobalCutoffGroupIndex.push_back(cg->getGlobalIndex() + 1);
727 }
728
729 }
730
731 //fill up mpiSimData struct
732 parallelData.nMolGlobal = getNGlobalMolecules();
733 parallelData.nMolLocal = getNMolecules();
734 parallelData.nAtomsGlobal = getNGlobalAtoms();
735 parallelData.nAtomsLocal = getNAtoms();
736 parallelData.nGroupsGlobal = getNGlobalCutoffGroups();
737 parallelData.nGroupsLocal = getNCutoffGroups();
738 parallelData.myNode = worldRank;
739 MPI_Comm_size(MPI_COMM_WORLD, &(parallelData.nProcessors));
740
741 //pass mpiSimData struct and index arrays to fortran
742 setFsimParallel(&parallelData, &(parallelData.nAtomsLocal),
743 &localToGlobalAtomIndex[0], &(parallelData.nGroupsLocal),
744 &localToGlobalCutoffGroupIndex[0], &isError);
745
746 if (isError) {
747 sprintf(painCave.errMsg,
748 "mpiRefresh errror: fortran didn't like something we gave it.\n");
749 painCave.isFatal = 1;
750 simError();
751 }
752
753 sprintf(checkPointMsg, " mpiRefresh successful.\n");
754 MPIcheckPoint();
755
756
757 }
758
759 #endif
760
761 double SimInfo::calcMaxCutoffRadius() {
762
763
764 std::set<AtomType*> atomTypes;
765 std::set<AtomType*>::iterator i;
766 std::vector<double> cutoffRadius;
767
768 //get the unique atom types
769 atomTypes = getUniqueAtomTypes();
770
771 //query the max cutoff radius among these atom types
772 for (i = atomTypes.begin(); i != atomTypes.end(); ++i) {
773 cutoffRadius.push_back(forceField_->getRcutFromAtomType(*i));
774 }
775
776 double maxCutoffRadius = *(std::max_element(cutoffRadius.begin(), cutoffRadius.end()));
777 #ifdef IS_MPI
778 //pick the max cutoff radius among the processors
779 #endif
780
781 return maxCutoffRadius;
782 }
783
784 void SimInfo::getCutoff(double& rcut, double& rsw) {
785
786 if (fInfo_.SIM_uses_Charges | fInfo_.SIM_uses_Dipoles | fInfo_.SIM_uses_RF) {
787
788 if (!simParams_->haveRcut()){
789 sprintf(painCave.errMsg,
790 "SimCreator Warning: No value was set for the cutoffRadius.\n"
791 "\tOOPSE will use a default value of 15.0 angstroms"
792 "\tfor the cutoffRadius.\n");
793 painCave.isFatal = 0;
794 simError();
795 rcut = 15.0;
796 } else{
797 rcut = simParams_->getRcut();
798 }
799
800 if (!simParams_->haveRsw()){
801 sprintf(painCave.errMsg,
802 "SimCreator Warning: No value was set for switchingRadius.\n"
803 "\tOOPSE will use a default value of\n"
804 "\t0.95 * cutoffRadius for the switchingRadius\n");
805 painCave.isFatal = 0;
806 simError();
807 rsw = 0.95 * rcut;
808 } else{
809 rsw = simParams_->getRsw();
810 }
811
812 } else {
813 // if charge, dipole or reaction field is not used and the cutofff radius is not specified in
814 //meta-data file, the maximum cutoff radius calculated from forcefiled will be used
815
816 if (simParams_->haveRcut()) {
817 rcut = simParams_->getRcut();
818 } else {
819 //set cutoff radius to the maximum cutoff radius based on atom types in the whole system
820 rcut = calcMaxCutoffRadius();
821 }
822
823 if (simParams_->haveRsw()) {
824 rsw = simParams_->getRsw();
825 } else {
826 rsw = rcut;
827 }
828
829 }
830 }
831
832 void SimInfo::setupCutoff() {
833 getCutoff(rcut_, rsw_);
834 double rnblist = rcut_ + 1; // skin of neighbor list
835
836 //Pass these cutoff radius etc. to fortran. This function should be called once and only once
837
838 int cp = TRADITIONAL_CUTOFF_POLICY;
839 if (simParams_->haveCutoffPolicy()) {
840 std::string myPolicy = simParams_->getCutoffPolicy();
841 if (myPolicy == "MIX") {
842 cp = MIX_CUTOFF_POLICY;
843 } else {
844 if (myPolicy == "MAX") {
845 cp = MAX_CUTOFF_POLICY;
846 } else {
847 if (myPolicy == "TRADITIONAL") {
848 cp = TRADITIONAL_CUTOFF_POLICY;
849 } else {
850 // throw error
851 sprintf( painCave.errMsg,
852 "SimInfo error: Unknown cutoffPolicy. (Input file specified %s .)\n\tcutoffPolicy must be one of: \"Mix\", \"Max\", or \"Traditional\".", myPolicy.c_str() );
853 painCave.isFatal = 1;
854 simError();
855 }
856 }
857 }
858 }
859 notifyFortranCutoffs(&rcut_, &rsw_, &rnblist, &cp);
860 }
861
862 void SimInfo::setupElectrostaticSummationMethod( int isError ) {
863
864 int errorOut;
865 int esm = NONE;
866 double alphaVal;
867
868 errorOut = isError;
869
870 if (simParams_->haveElectrostaticSummationMethod()) {
871 std::string myMethod = simParams_->getElectrostaticSummationMethod();
872 if (myMethod == "NONE") {
873 esm = NONE;
874 } else {
875 if (myMethod == "UNDAMPED_WOLF") {
876 esm = UNDAMPED_WOLF;
877 } else {
878 if (myMethod == "DAMPED_WOLF") {
879 esm = DAMPED_WOLF;
880 if (!simParams_->haveDampingAlpha()) {
881 //throw error
882 sprintf( painCave.errMsg,
883 "SimInfo warning: dampingAlpha was not specified in the input file. A default value of %f (1/ang) will be used for the Damped Wolf Method.", simParams_->getDampingAlpha());
884 painCave.isFatal = 0;
885 simError();
886 }
887 alphaVal = simParams_->getDampingAlpha();
888 } else {
889 if (myMethod == "REACTION_FIELD") {
890 esm = REACTION_FIELD;
891 } else {
892 // throw error
893 sprintf( painCave.errMsg,
894 "SimInfo error: Unknown electrostaticSummationMethod. (Input file specified %s .)\n\telectrostaticSummationMethod must be one of: \"none\", \"undamped_wolf\", \"damped_wolf\", or \"reaction_field\".", myMethod.c_str() );
895 painCave.isFatal = 1;
896 simError();
897 }
898 }
899 }
900 }
901 }
902 initFortranFF( &esm, &alphaVal, &errorOut );
903 }
904
905 void SimInfo::addProperty(GenericData* genData) {
906 properties_.addProperty(genData);
907 }
908
909 void SimInfo::removeProperty(const std::string& propName) {
910 properties_.removeProperty(propName);
911 }
912
913 void SimInfo::clearProperties() {
914 properties_.clearProperties();
915 }
916
917 std::vector<std::string> SimInfo::getPropertyNames() {
918 return properties_.getPropertyNames();
919 }
920
921 std::vector<GenericData*> SimInfo::getProperties() {
922 return properties_.getProperties();
923 }
924
925 GenericData* SimInfo::getPropertyByName(const std::string& propName) {
926 return properties_.getPropertyByName(propName);
927 }
928
929 void SimInfo::setSnapshotManager(SnapshotManager* sman) {
930 if (sman_ == sman) {
931 return;
932 }
933 delete sman_;
934 sman_ = sman;
935
936 Molecule* mol;
937 RigidBody* rb;
938 Atom* atom;
939 SimInfo::MoleculeIterator mi;
940 Molecule::RigidBodyIterator rbIter;
941 Molecule::AtomIterator atomIter;;
942
943 for (mol = beginMolecule(mi); mol != NULL; mol = nextMolecule(mi)) {
944
945 for (atom = mol->beginAtom(atomIter); atom != NULL; atom = mol->nextAtom(atomIter)) {
946 atom->setSnapshotManager(sman_);
947 }
948
949 for (rb = mol->beginRigidBody(rbIter); rb != NULL; rb = mol->nextRigidBody(rbIter)) {
950 rb->setSnapshotManager(sman_);
951 }
952 }
953
954 }
955
956 Vector3d SimInfo::getComVel(){
957 SimInfo::MoleculeIterator i;
958 Molecule* mol;
959
960 Vector3d comVel(0.0);
961 double totalMass = 0.0;
962
963
964 for (mol = beginMolecule(i); mol != NULL; mol = nextMolecule(i)) {
965 double mass = mol->getMass();
966 totalMass += mass;
967 comVel += mass * mol->getComVel();
968 }
969
970 #ifdef IS_MPI
971 double tmpMass = totalMass;
972 Vector3d tmpComVel(comVel);
973 MPI_Allreduce(&tmpMass,&totalMass,1,MPI_DOUBLE,MPI_SUM, MPI_COMM_WORLD);
974 MPI_Allreduce(tmpComVel.getArrayPointer(), comVel.getArrayPointer(),3,MPI_DOUBLE,MPI_SUM, MPI_COMM_WORLD);
975 #endif
976
977 comVel /= totalMass;
978
979 return comVel;
980 }
981
982 Vector3d SimInfo::getCom(){
983 SimInfo::MoleculeIterator i;
984 Molecule* mol;
985
986 Vector3d com(0.0);
987 double totalMass = 0.0;
988
989 for (mol = beginMolecule(i); mol != NULL; mol = nextMolecule(i)) {
990 double mass = mol->getMass();
991 totalMass += mass;
992 com += mass * mol->getCom();
993 }
994
995 #ifdef IS_MPI
996 double tmpMass = totalMass;
997 Vector3d tmpCom(com);
998 MPI_Allreduce(&tmpMass,&totalMass,1,MPI_DOUBLE,MPI_SUM, MPI_COMM_WORLD);
999 MPI_Allreduce(tmpCom.getArrayPointer(), com.getArrayPointer(),3,MPI_DOUBLE,MPI_SUM, MPI_COMM_WORLD);
1000 #endif
1001
1002 com /= totalMass;
1003
1004 return com;
1005
1006 }
1007
1008 std::ostream& operator <<(std::ostream& o, SimInfo& info) {
1009
1010 return o;
1011 }
1012
1013
1014 /*
1015 Returns center of mass and center of mass velocity in one function call.
1016 */
1017
1018 void SimInfo::getComAll(Vector3d &com, Vector3d &comVel){
1019 SimInfo::MoleculeIterator i;
1020 Molecule* mol;
1021
1022
1023 double totalMass = 0.0;
1024
1025
1026 for (mol = beginMolecule(i); mol != NULL; mol = nextMolecule(i)) {
1027 double mass = mol->getMass();
1028 totalMass += mass;
1029 com += mass * mol->getCom();
1030 comVel += mass * mol->getComVel();
1031 }
1032
1033 #ifdef IS_MPI
1034 double tmpMass = totalMass;
1035 Vector3d tmpCom(com);
1036 Vector3d tmpComVel(comVel);
1037 MPI_Allreduce(&tmpMass,&totalMass,1,MPI_DOUBLE,MPI_SUM, MPI_COMM_WORLD);
1038 MPI_Allreduce(tmpCom.getArrayPointer(), com.getArrayPointer(),3,MPI_DOUBLE,MPI_SUM, MPI_COMM_WORLD);
1039 MPI_Allreduce(tmpComVel.getArrayPointer(), comVel.getArrayPointer(),3,MPI_DOUBLE,MPI_SUM, MPI_COMM_WORLD);
1040 #endif
1041
1042 com /= totalMass;
1043 comVel /= totalMass;
1044 }
1045
1046 /*
1047 Return intertia tensor for entire system and angular momentum Vector.
1048
1049
1050 [ Ixx -Ixy -Ixz ]
1051 J =| -Iyx Iyy -Iyz |
1052 [ -Izx -Iyz Izz ]
1053 */
1054
1055 void SimInfo::getInertiaTensor(Mat3x3d &inertiaTensor, Vector3d &angularMomentum){
1056
1057
1058 double xx = 0.0;
1059 double yy = 0.0;
1060 double zz = 0.0;
1061 double xy = 0.0;
1062 double xz = 0.0;
1063 double yz = 0.0;
1064 Vector3d com(0.0);
1065 Vector3d comVel(0.0);
1066
1067 getComAll(com, comVel);
1068
1069 SimInfo::MoleculeIterator i;
1070 Molecule* mol;
1071
1072 Vector3d thisq(0.0);
1073 Vector3d thisv(0.0);
1074
1075 double thisMass = 0.0;
1076
1077
1078
1079
1080 for (mol = beginMolecule(i); mol != NULL; mol = nextMolecule(i)) {
1081
1082 thisq = mol->getCom()-com;
1083 thisv = mol->getComVel()-comVel;
1084 thisMass = mol->getMass();
1085 // Compute moment of intertia coefficients.
1086 xx += thisq[0]*thisq[0]*thisMass;
1087 yy += thisq[1]*thisq[1]*thisMass;
1088 zz += thisq[2]*thisq[2]*thisMass;
1089
1090 // compute products of intertia
1091 xy += thisq[0]*thisq[1]*thisMass;
1092 xz += thisq[0]*thisq[2]*thisMass;
1093 yz += thisq[1]*thisq[2]*thisMass;
1094
1095 angularMomentum += cross( thisq, thisv ) * thisMass;
1096
1097 }
1098
1099
1100 inertiaTensor(0,0) = yy + zz;
1101 inertiaTensor(0,1) = -xy;
1102 inertiaTensor(0,2) = -xz;
1103 inertiaTensor(1,0) = -xy;
1104 inertiaTensor(1,1) = xx + zz;
1105 inertiaTensor(1,2) = -yz;
1106 inertiaTensor(2,0) = -xz;
1107 inertiaTensor(2,1) = -yz;
1108 inertiaTensor(2,2) = xx + yy;
1109
1110 #ifdef IS_MPI
1111 Mat3x3d tmpI(inertiaTensor);
1112 Vector3d tmpAngMom;
1113 MPI_Allreduce(tmpI.getArrayPointer(), inertiaTensor.getArrayPointer(),9,MPI_DOUBLE,MPI_SUM, MPI_COMM_WORLD);
1114 MPI_Allreduce(tmpAngMom.getArrayPointer(), angularMomentum.getArrayPointer(),3,MPI_DOUBLE,MPI_SUM, MPI_COMM_WORLD);
1115 #endif
1116
1117 return;
1118 }
1119
1120 //Returns the angular momentum of the system
1121 Vector3d SimInfo::getAngularMomentum(){
1122
1123 Vector3d com(0.0);
1124 Vector3d comVel(0.0);
1125 Vector3d angularMomentum(0.0);
1126
1127 getComAll(com,comVel);
1128
1129 SimInfo::MoleculeIterator i;
1130 Molecule* mol;
1131
1132 Vector3d thisr(0.0);
1133 Vector3d thisp(0.0);
1134
1135 double thisMass;
1136
1137 for (mol = beginMolecule(i); mol != NULL; mol = nextMolecule(i)) {
1138 thisMass = mol->getMass();
1139 thisr = mol->getCom()-com;
1140 thisp = (mol->getComVel()-comVel)*thisMass;
1141
1142 angularMomentum += cross( thisr, thisp );
1143
1144 }
1145
1146 #ifdef IS_MPI
1147 Vector3d tmpAngMom;
1148 MPI_Allreduce(tmpAngMom.getArrayPointer(), angularMomentum.getArrayPointer(),3,MPI_DOUBLE,MPI_SUM, MPI_COMM_WORLD);
1149 #endif
1150
1151 return angularMomentum;
1152 }
1153
1154
1155 }//end namespace oopse
1156