ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/group/trunk/OOPSE-4/src/brains/SimInfo.cpp
Revision: 1930
Committed: Wed Jan 12 22:41:40 2005 UTC (19 years, 5 months ago) by gezelter
File size: 28347 byte(s)
Log Message:
merging new_design branch into OOPSE-2.0

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/doForces_interface.h"
56 #include "UseTheForce/notifyCutoffs_interface.h"
57 #include "utils/MemoryUtils.hpp"
58 #include "utils/simError.h"
59
60 #ifdef IS_MPI
61 #include "UseTheForce/mpiComponentPlan.h"
62 #include "UseTheForce/DarkSide/simParallel_interface.h"
63 #endif
64
65 namespace oopse {
66
67 SimInfo::SimInfo(std::vector<std::pair<MoleculeStamp*, int> >& molStampPairs,
68 ForceField* ff, Globals* simParams) :
69 forceField_(ff), simParams_(simParams),
70 ndf_(0), ndfRaw_(0), ndfTrans_(0), nZconstraint_(0),
71 nGlobalMols_(0), nGlobalAtoms_(0), nGlobalCutoffGroups_(0),
72 nGlobalIntegrableObjects_(0), nGlobalRigidBodies_(0),
73 nAtoms_(0), nBonds_(0), nBends_(0), nTorsions_(0), nRigidBodies_(0),
74 nIntegrableObjects_(0), nCutoffGroups_(0), nConstraints_(0),
75 sman_(NULL), fortranInitialized_(false) {
76
77
78 std::vector<std::pair<MoleculeStamp*, int> >::iterator i;
79 MoleculeStamp* molStamp;
80 int nMolWithSameStamp;
81 int nCutoffAtoms = 0; // number of atoms belong to cutoff groups
82 int nGroups = 0; //total cutoff groups defined in meta-data file
83 CutoffGroupStamp* cgStamp;
84 RigidBodyStamp* rbStamp;
85 int nRigidAtoms = 0;
86
87 for (i = molStampPairs.begin(); i !=molStampPairs.end(); ++i) {
88 molStamp = i->first;
89 nMolWithSameStamp = i->second;
90
91 addMoleculeStamp(molStamp, nMolWithSameStamp);
92
93 //calculate atoms in molecules
94 nGlobalAtoms_ += molStamp->getNAtoms() *nMolWithSameStamp;
95
96
97 //calculate atoms in cutoff groups
98 int nAtomsInGroups = 0;
99 int nCutoffGroupsInStamp = molStamp->getNCutoffGroups();
100
101 for (int j=0; j < nCutoffGroupsInStamp; j++) {
102 cgStamp = molStamp->getCutoffGroup(j);
103 nAtomsInGroups += cgStamp->getNMembers();
104 }
105
106 nGroups += nCutoffGroupsInStamp * nMolWithSameStamp;
107 nCutoffAtoms += nAtomsInGroups * nMolWithSameStamp;
108
109 //calculate atoms in rigid bodies
110 int nAtomsInRigidBodies = 0;
111 int nRigidBodiesInStamp = molStamp->getNCutoffGroups();
112
113 for (int j=0; j < nRigidBodiesInStamp; j++) {
114 rbStamp = molStamp->getRigidBody(j);
115 nAtomsInRigidBodies += rbStamp->getNMembers();
116 }
117
118 nGlobalRigidBodies_ += nRigidBodiesInStamp * nMolWithSameStamp;
119 nRigidAtoms += nAtomsInRigidBodies * nMolWithSameStamp;
120
121 }
122
123 //every free atom (atom does not belong to cutoff groups) is a cutoff group
124 //therefore the total number of cutoff groups in the system is equal to
125 //the total number of atoms minus number of atoms belong to cutoff group defined in meta-data
126 //file plus the number of cutoff groups defined in meta-data file
127 nGlobalCutoffGroups_ = nGlobalAtoms_ - nCutoffAtoms + nGroups;
128
129 //every free atom (atom does not belong to rigid bodies) is an integrable object
130 //therefore the total number of integrable objects in the system is equal to
131 //the total number of atoms minus number of atoms belong to rigid body defined in meta-data
132 //file plus the number of rigid bodies defined in meta-data file
133 nGlobalIntegrableObjects_ = nGlobalAtoms_ - nRigidAtoms + nGlobalRigidBodies_;
134
135 nGlobalMols_ = molStampIds_.size();
136
137 #ifdef IS_MPI
138 molToProcMap_.resize(nGlobalMols_);
139 #endif
140
141 }
142
143 SimInfo::~SimInfo() {
144 //MemoryUtils::deleteVectorOfPointer(molecules_);
145
146 MemoryUtils::deleteVectorOfPointer(moleculeStamps_);
147
148 delete sman_;
149 delete simParams_;
150 delete forceField_;
151
152 }
153
154 int SimInfo::getNGlobalConstraints() {
155 int nGlobalConstraints;
156 #ifdef IS_MPI
157 MPI_Allreduce(&nConstraints_, &nGlobalConstraints, 1, MPI_INT, MPI_SUM,
158 MPI_COMM_WORLD);
159 #else
160 nGlobalConstraints = nConstraints_;
161 #endif
162 return nGlobalConstraints;
163 }
164
165 bool SimInfo::addMolecule(Molecule* mol) {
166 MoleculeIterator i;
167
168 i = molecules_.find(mol->getGlobalIndex());
169 if (i == molecules_.end() ) {
170
171 molecules_.insert(std::make_pair(mol->getGlobalIndex(), mol));
172
173 nAtoms_ += mol->getNAtoms();
174 nBonds_ += mol->getNBonds();
175 nBends_ += mol->getNBends();
176 nTorsions_ += mol->getNTorsions();
177 nRigidBodies_ += mol->getNRigidBodies();
178 nIntegrableObjects_ += mol->getNIntegrableObjects();
179 nCutoffGroups_ += mol->getNCutoffGroups();
180 nConstraints_ += mol->getNConstraintPairs();
181
182 addExcludePairs(mol);
183
184 return true;
185 } else {
186 return false;
187 }
188 }
189
190 bool SimInfo::removeMolecule(Molecule* mol) {
191 MoleculeIterator i;
192 i = molecules_.find(mol->getGlobalIndex());
193
194 if (i != molecules_.end() ) {
195
196 assert(mol == i->second);
197
198 nAtoms_ -= mol->getNAtoms();
199 nBonds_ -= mol->getNBonds();
200 nBends_ -= mol->getNBends();
201 nTorsions_ -= mol->getNTorsions();
202 nRigidBodies_ -= mol->getNRigidBodies();
203 nIntegrableObjects_ -= mol->getNIntegrableObjects();
204 nCutoffGroups_ -= mol->getNCutoffGroups();
205 nConstraints_ -= mol->getNConstraintPairs();
206
207 removeExcludePairs(mol);
208 molecules_.erase(mol->getGlobalIndex());
209
210 delete mol;
211
212 return true;
213 } else {
214 return false;
215 }
216
217
218 }
219
220
221 Molecule* SimInfo::beginMolecule(MoleculeIterator& i) {
222 i = molecules_.begin();
223 return i == molecules_.end() ? NULL : i->second;
224 }
225
226 Molecule* SimInfo::nextMolecule(MoleculeIterator& i) {
227 ++i;
228 return i == molecules_.end() ? NULL : i->second;
229 }
230
231
232 void SimInfo::calcNdf() {
233 int ndf_local;
234 MoleculeIterator i;
235 std::vector<StuntDouble*>::iterator j;
236 Molecule* mol;
237 StuntDouble* integrableObject;
238
239 ndf_local = 0;
240
241 for (mol = beginMolecule(i); mol != NULL; mol = nextMolecule(i)) {
242 for (integrableObject = mol->beginIntegrableObject(j); integrableObject != NULL;
243 integrableObject = mol->nextIntegrableObject(j)) {
244
245 ndf_local += 3;
246
247 if (integrableObject->isDirectional()) {
248 if (integrableObject->isLinear()) {
249 ndf_local += 2;
250 } else {
251 ndf_local += 3;
252 }
253 }
254
255 }//end for (integrableObject)
256 }// end for (mol)
257
258 // n_constraints is local, so subtract them on each processor
259 ndf_local -= nConstraints_;
260
261 #ifdef IS_MPI
262 MPI_Allreduce(&ndf_local,&ndf_,1,MPI_INT,MPI_SUM, MPI_COMM_WORLD);
263 #else
264 ndf_ = ndf_local;
265 #endif
266
267 // nZconstraints_ is global, as are the 3 COM translations for the
268 // entire system:
269 ndf_ = ndf_ - 3 - nZconstraint_;
270
271 }
272
273 void SimInfo::calcNdfRaw() {
274 int ndfRaw_local;
275
276 MoleculeIterator i;
277 std::vector<StuntDouble*>::iterator j;
278 Molecule* mol;
279 StuntDouble* integrableObject;
280
281 // Raw degrees of freedom that we have to set
282 ndfRaw_local = 0;
283
284 for (mol = beginMolecule(i); mol != NULL; mol = nextMolecule(i)) {
285 for (integrableObject = mol->beginIntegrableObject(j); integrableObject != NULL;
286 integrableObject = mol->nextIntegrableObject(j)) {
287
288 ndfRaw_local += 3;
289
290 if (integrableObject->isDirectional()) {
291 if (integrableObject->isLinear()) {
292 ndfRaw_local += 2;
293 } else {
294 ndfRaw_local += 3;
295 }
296 }
297
298 }
299 }
300
301 #ifdef IS_MPI
302 MPI_Allreduce(&ndfRaw_local,&ndfRaw_,1,MPI_INT,MPI_SUM, MPI_COMM_WORLD);
303 #else
304 ndfRaw_ = ndfRaw_local;
305 #endif
306 }
307
308 void SimInfo::calcNdfTrans() {
309 int ndfTrans_local;
310
311 ndfTrans_local = 3 * nIntegrableObjects_ - nConstraints_;
312
313
314 #ifdef IS_MPI
315 MPI_Allreduce(&ndfTrans_local,&ndfTrans_,1,MPI_INT,MPI_SUM, MPI_COMM_WORLD);
316 #else
317 ndfTrans_ = ndfTrans_local;
318 #endif
319
320 ndfTrans_ = ndfTrans_ - 3 - nZconstraint_;
321
322 }
323
324 void SimInfo::addExcludePairs(Molecule* mol) {
325 std::vector<Bond*>::iterator bondIter;
326 std::vector<Bend*>::iterator bendIter;
327 std::vector<Torsion*>::iterator torsionIter;
328 Bond* bond;
329 Bend* bend;
330 Torsion* torsion;
331 int a;
332 int b;
333 int c;
334 int d;
335
336 for (bond= mol->beginBond(bondIter); bond != NULL; bond = mol->nextBond(bondIter)) {
337 a = bond->getAtomA()->getGlobalIndex();
338 b = bond->getAtomB()->getGlobalIndex();
339 exclude_.addPair(a, b);
340 }
341
342 for (bend= mol->beginBend(bendIter); bend != NULL; bend = mol->nextBend(bendIter)) {
343 a = bend->getAtomA()->getGlobalIndex();
344 b = bend->getAtomB()->getGlobalIndex();
345 c = bend->getAtomC()->getGlobalIndex();
346
347 exclude_.addPair(a, b);
348 exclude_.addPair(a, c);
349 exclude_.addPair(b, c);
350 }
351
352 for (torsion= mol->beginTorsion(torsionIter); torsion != NULL; torsion = mol->nextTorsion(torsionIter)) {
353 a = torsion->getAtomA()->getGlobalIndex();
354 b = torsion->getAtomB()->getGlobalIndex();
355 c = torsion->getAtomC()->getGlobalIndex();
356 d = torsion->getAtomD()->getGlobalIndex();
357
358 exclude_.addPair(a, b);
359 exclude_.addPair(a, c);
360 exclude_.addPair(a, d);
361 exclude_.addPair(b, c);
362 exclude_.addPair(b, d);
363 exclude_.addPair(c, d);
364 }
365
366
367 }
368
369 void SimInfo::removeExcludePairs(Molecule* mol) {
370 std::vector<Bond*>::iterator bondIter;
371 std::vector<Bend*>::iterator bendIter;
372 std::vector<Torsion*>::iterator torsionIter;
373 Bond* bond;
374 Bend* bend;
375 Torsion* torsion;
376 int a;
377 int b;
378 int c;
379 int d;
380
381 for (bond= mol->beginBond(bondIter); bond != NULL; bond = mol->nextBond(bondIter)) {
382 a = bond->getAtomA()->getGlobalIndex();
383 b = bond->getAtomB()->getGlobalIndex();
384 exclude_.removePair(a, b);
385 }
386
387 for (bend= mol->beginBend(bendIter); bend != NULL; bend = mol->nextBend(bendIter)) {
388 a = bend->getAtomA()->getGlobalIndex();
389 b = bend->getAtomB()->getGlobalIndex();
390 c = bend->getAtomC()->getGlobalIndex();
391
392 exclude_.removePair(a, b);
393 exclude_.removePair(a, c);
394 exclude_.removePair(b, c);
395 }
396
397 for (torsion= mol->beginTorsion(torsionIter); torsion != NULL; torsion = mol->nextTorsion(torsionIter)) {
398 a = torsion->getAtomA()->getGlobalIndex();
399 b = torsion->getAtomB()->getGlobalIndex();
400 c = torsion->getAtomC()->getGlobalIndex();
401 d = torsion->getAtomD()->getGlobalIndex();
402
403 exclude_.removePair(a, b);
404 exclude_.removePair(a, c);
405 exclude_.removePair(a, d);
406 exclude_.removePair(b, c);
407 exclude_.removePair(b, d);
408 exclude_.removePair(c, d);
409 }
410
411 }
412
413
414 void SimInfo::addMoleculeStamp(MoleculeStamp* molStamp, int nmol) {
415 int curStampId;
416
417 //index from 0
418 curStampId = moleculeStamps_.size();
419
420 moleculeStamps_.push_back(molStamp);
421 molStampIds_.insert(molStampIds_.end(), nmol, curStampId);
422 }
423
424 void SimInfo::update() {
425
426 setupSimType();
427
428 #ifdef IS_MPI
429 setupFortranParallel();
430 #endif
431
432 setupFortranSim();
433
434 //setup fortran force field
435 /** @deprecate */
436 int isError = 0;
437 initFortranFF( &fInfo_.SIM_uses_RF , &isError );
438 if(isError){
439 sprintf( painCave.errMsg,
440 "ForceField error: There was an error initializing the forceField in fortran.\n" );
441 painCave.isFatal = 1;
442 simError();
443 }
444
445
446 setupCutoff();
447
448 calcNdf();
449 calcNdfRaw();
450 calcNdfTrans();
451
452 fortranInitialized_ = true;
453 }
454
455 std::set<AtomType*> SimInfo::getUniqueAtomTypes() {
456 SimInfo::MoleculeIterator mi;
457 Molecule* mol;
458 Molecule::AtomIterator ai;
459 Atom* atom;
460 std::set<AtomType*> atomTypes;
461
462 for(mol = beginMolecule(mi); mol != NULL; mol = nextMolecule(mi)) {
463
464 for(atom = mol->beginAtom(ai); atom != NULL; atom = mol->nextAtom(ai)) {
465 atomTypes.insert(atom->getAtomType());
466 }
467
468 }
469
470 return atomTypes;
471 }
472
473 void SimInfo::setupSimType() {
474 std::set<AtomType*>::iterator i;
475 std::set<AtomType*> atomTypes;
476 atomTypes = getUniqueAtomTypes();
477
478 int useLennardJones = 0;
479 int useElectrostatic = 0;
480 int useEAM = 0;
481 int useCharge = 0;
482 int useDirectional = 0;
483 int useDipole = 0;
484 int useGayBerne = 0;
485 int useSticky = 0;
486 int useShape = 0;
487 int useFLARB = 0; //it is not in AtomType yet
488 int useDirectionalAtom = 0;
489 int useElectrostatics = 0;
490 //usePBC and useRF are from simParams
491 int usePBC = simParams_->getPBC();
492 int useRF = simParams_->getUseRF();
493
494 //loop over all of the atom types
495 for (i = atomTypes.begin(); i != atomTypes.end(); ++i) {
496 useLennardJones |= (*i)->isLennardJones();
497 useElectrostatic |= (*i)->isElectrostatic();
498 useEAM |= (*i)->isEAM();
499 useCharge |= (*i)->isCharge();
500 useDirectional |= (*i)->isDirectional();
501 useDipole |= (*i)->isDipole();
502 useGayBerne |= (*i)->isGayBerne();
503 useSticky |= (*i)->isSticky();
504 useShape |= (*i)->isShape();
505 }
506
507 if (useSticky || useDipole || useGayBerne || useShape) {
508 useDirectionalAtom = 1;
509 }
510
511 if (useCharge || useDipole) {
512 useElectrostatics = 1;
513 }
514
515 #ifdef IS_MPI
516 int temp;
517
518 temp = usePBC;
519 MPI_Allreduce(&temp, &usePBC, 1, MPI_INT, MPI_LOR, MPI_COMM_WORLD);
520
521 temp = useDirectionalAtom;
522 MPI_Allreduce(&temp, &useDirectionalAtom, 1, MPI_INT, MPI_LOR, MPI_COMM_WORLD);
523
524 temp = useLennardJones;
525 MPI_Allreduce(&temp, &useLennardJones, 1, MPI_INT, MPI_LOR, MPI_COMM_WORLD);
526
527 temp = useElectrostatics;
528 MPI_Allreduce(&temp, &useElectrostatics, 1, MPI_INT, MPI_LOR, MPI_COMM_WORLD);
529
530 temp = useCharge;
531 MPI_Allreduce(&temp, &useCharge, 1, MPI_INT, MPI_LOR, MPI_COMM_WORLD);
532
533 temp = useDipole;
534 MPI_Allreduce(&temp, &useDipole, 1, MPI_INT, MPI_LOR, MPI_COMM_WORLD);
535
536 temp = useSticky;
537 MPI_Allreduce(&temp, &useSticky, 1, MPI_INT, MPI_LOR, MPI_COMM_WORLD);
538
539 temp = useGayBerne;
540 MPI_Allreduce(&temp, &useGayBerne, 1, MPI_INT, MPI_LOR, MPI_COMM_WORLD);
541
542 temp = useEAM;
543 MPI_Allreduce(&temp, &useEAM, 1, MPI_INT, MPI_LOR, MPI_COMM_WORLD);
544
545 temp = useShape;
546 MPI_Allreduce(&temp, &useShape, 1, MPI_INT, MPI_LOR, MPI_COMM_WORLD);
547
548 temp = useFLARB;
549 MPI_Allreduce(&temp, &useFLARB, 1, MPI_INT, MPI_LOR, MPI_COMM_WORLD);
550
551 temp = useRF;
552 MPI_Allreduce(&temp, &useRF, 1, MPI_INT, MPI_LOR, MPI_COMM_WORLD);
553
554 #endif
555
556 fInfo_.SIM_uses_PBC = usePBC;
557 fInfo_.SIM_uses_DirectionalAtoms = useDirectionalAtom;
558 fInfo_.SIM_uses_LennardJones = useLennardJones;
559 fInfo_.SIM_uses_Electrostatics = useElectrostatics;
560 fInfo_.SIM_uses_Charges = useCharge;
561 fInfo_.SIM_uses_Dipoles = useDipole;
562 fInfo_.SIM_uses_Sticky = useSticky;
563 fInfo_.SIM_uses_GayBerne = useGayBerne;
564 fInfo_.SIM_uses_EAM = useEAM;
565 fInfo_.SIM_uses_Shapes = useShape;
566 fInfo_.SIM_uses_FLARB = useFLARB;
567 fInfo_.SIM_uses_RF = useRF;
568
569 if( fInfo_.SIM_uses_Dipoles && fInfo_.SIM_uses_RF) {
570
571 if (simParams_->haveDielectric()) {
572 fInfo_.dielect = simParams_->getDielectric();
573 } else {
574 sprintf(painCave.errMsg,
575 "SimSetup Error: No Dielectric constant was set.\n"
576 "\tYou are trying to use Reaction Field without"
577 "\tsetting a dielectric constant!\n");
578 painCave.isFatal = 1;
579 simError();
580 }
581
582 } else {
583 fInfo_.dielect = 0.0;
584 }
585
586 }
587
588 void SimInfo::setupFortranSim() {
589 int isError;
590 int nExclude;
591 std::vector<int> fortranGlobalGroupMembership;
592
593 nExclude = exclude_.getSize();
594 isError = 0;
595
596 //globalGroupMembership_ is filled by SimCreator
597 for (int i = 0; i < nGlobalAtoms_; i++) {
598 fortranGlobalGroupMembership.push_back(globalGroupMembership_[i] + 1);
599 }
600
601 //calculate mass ratio of cutoff group
602 std::vector<double> mfact;
603 SimInfo::MoleculeIterator mi;
604 Molecule* mol;
605 Molecule::CutoffGroupIterator ci;
606 CutoffGroup* cg;
607 Molecule::AtomIterator ai;
608 Atom* atom;
609 double totalMass;
610
611 //to avoid memory reallocation, reserve enough space for mfact
612 mfact.reserve(getNCutoffGroups());
613
614 for(mol = beginMolecule(mi); mol != NULL; mol = nextMolecule(mi)) {
615 for (cg = mol->beginCutoffGroup(ci); cg != NULL; cg = mol->nextCutoffGroup(ci)) {
616
617 totalMass = cg->getMass();
618 for(atom = cg->beginAtom(ai); atom != NULL; atom = cg->nextAtom(ai)) {
619 mfact.push_back(atom->getMass()/totalMass);
620 }
621
622 }
623 }
624
625 //fill ident array of local atoms (it is actually ident of AtomType, it is so confusing !!!)
626 std::vector<int> identArray;
627
628 //to avoid memory reallocation, reserve enough space identArray
629 identArray.reserve(getNAtoms());
630
631 for(mol = beginMolecule(mi); mol != NULL; mol = nextMolecule(mi)) {
632 for(atom = mol->beginAtom(ai); atom != NULL; atom = mol->nextAtom(ai)) {
633 identArray.push_back(atom->getIdent());
634 }
635 }
636
637 //fill molMembershipArray
638 //molMembershipArray is filled by SimCreator
639 std::vector<int> molMembershipArray(nGlobalAtoms_);
640 for (int i = 0; i < nGlobalAtoms_; i++) {
641 molMembershipArray[i] = globalMolMembership_[i] + 1;
642 }
643
644 //setup fortran simulation
645 //gloalExcludes and molMembershipArray should go away (They are never used)
646 //why the hell fortran need to know molecule?
647 //OOPSE = Object-Obfuscated Parallel Simulation Engine
648 int nGlobalExcludes = 0;
649 int* globalExcludes = NULL;
650 int* excludeList = exclude_.getExcludeList();
651 setFortranSim( &fInfo_, &nGlobalAtoms_, &nAtoms_, &identArray[0], &nExclude, excludeList ,
652 &nGlobalExcludes, globalExcludes, &molMembershipArray[0],
653 &mfact[0], &nCutoffGroups_, &fortranGlobalGroupMembership[0], &isError);
654
655 if( isError ){
656
657 sprintf( painCave.errMsg,
658 "There was an error setting the simulation information in fortran.\n" );
659 painCave.isFatal = 1;
660 painCave.severity = OOPSE_ERROR;
661 simError();
662 }
663
664 #ifdef IS_MPI
665 sprintf( checkPointMsg,
666 "succesfully sent the simulation information to fortran.\n");
667 MPIcheckPoint();
668 #endif // is_mpi
669 }
670
671
672 #ifdef IS_MPI
673 void SimInfo::setupFortranParallel() {
674
675 //SimInfo is responsible for creating localToGlobalAtomIndex and localToGlobalGroupIndex
676 std::vector<int> localToGlobalAtomIndex(getNAtoms(), 0);
677 std::vector<int> localToGlobalCutoffGroupIndex;
678 SimInfo::MoleculeIterator mi;
679 Molecule::AtomIterator ai;
680 Molecule::CutoffGroupIterator ci;
681 Molecule* mol;
682 Atom* atom;
683 CutoffGroup* cg;
684 mpiSimData parallelData;
685 int isError;
686
687 for (mol = beginMolecule(mi); mol != NULL; mol = nextMolecule(mi)) {
688
689 //local index(index in DataStorge) of atom is important
690 for (atom = mol->beginAtom(ai); atom != NULL; atom = mol->nextAtom(ai)) {
691 localToGlobalAtomIndex[atom->getLocalIndex()] = atom->getGlobalIndex() + 1;
692 }
693
694 //local index of cutoff group is trivial, it only depends on the order of travesing
695 for (cg = mol->beginCutoffGroup(ci); cg != NULL; cg = mol->nextCutoffGroup(ci)) {
696 localToGlobalCutoffGroupIndex.push_back(cg->getGlobalIndex() + 1);
697 }
698
699 }
700
701 //fill up mpiSimData struct
702 parallelData.nMolGlobal = getNGlobalMolecules();
703 parallelData.nMolLocal = getNMolecules();
704 parallelData.nAtomsGlobal = getNGlobalAtoms();
705 parallelData.nAtomsLocal = getNAtoms();
706 parallelData.nGroupsGlobal = getNGlobalCutoffGroups();
707 parallelData.nGroupsLocal = getNCutoffGroups();
708 parallelData.myNode = worldRank;
709 MPI_Comm_size(MPI_COMM_WORLD, &(parallelData.nProcessors));
710
711 //pass mpiSimData struct and index arrays to fortran
712 setFsimParallel(&parallelData, &(parallelData.nAtomsLocal),
713 &localToGlobalAtomIndex[0], &(parallelData.nGroupsLocal),
714 &localToGlobalCutoffGroupIndex[0], &isError);
715
716 if (isError) {
717 sprintf(painCave.errMsg,
718 "mpiRefresh errror: fortran didn't like something we gave it.\n");
719 painCave.isFatal = 1;
720 simError();
721 }
722
723 sprintf(checkPointMsg, " mpiRefresh successful.\n");
724 MPIcheckPoint();
725
726
727 }
728
729 #endif
730
731 double SimInfo::calcMaxCutoffRadius() {
732
733
734 std::set<AtomType*> atomTypes;
735 std::set<AtomType*>::iterator i;
736 std::vector<double> cutoffRadius;
737
738 //get the unique atom types
739 atomTypes = getUniqueAtomTypes();
740
741 //query the max cutoff radius among these atom types
742 for (i = atomTypes.begin(); i != atomTypes.end(); ++i) {
743 cutoffRadius.push_back(forceField_->getRcutFromAtomType(*i));
744 }
745
746 double maxCutoffRadius = *(std::max_element(cutoffRadius.begin(), cutoffRadius.end()));
747 #ifdef IS_MPI
748 //pick the max cutoff radius among the processors
749 #endif
750
751 return maxCutoffRadius;
752 }
753
754 void SimInfo::setupCutoff() {
755 double rcut_; //cutoff radius
756 double rsw_; //switching radius
757
758 if (fInfo_.SIM_uses_Charges | fInfo_.SIM_uses_Dipoles | fInfo_.SIM_uses_RF) {
759
760 if (!simParams_->haveRcut()){
761 sprintf(painCave.errMsg,
762 "SimCreator Warning: No value was set for the cutoffRadius.\n"
763 "\tOOPSE will use a default value of 15.0 angstroms"
764 "\tfor the cutoffRadius.\n");
765 painCave.isFatal = 0;
766 simError();
767 rcut_ = 15.0;
768 } else{
769 rcut_ = simParams_->getRcut();
770 }
771
772 if (!simParams_->haveRsw()){
773 sprintf(painCave.errMsg,
774 "SimCreator Warning: No value was set for switchingRadius.\n"
775 "\tOOPSE will use a default value of\n"
776 "\t0.95 * cutoffRadius for the switchingRadius\n");
777 painCave.isFatal = 0;
778 simError();
779 rsw_ = 0.95 * rcut_;
780 } else{
781 rsw_ = simParams_->getRsw();
782 }
783
784 } else {
785 // if charge, dipole or reaction field is not used and the cutofff radius is not specified in
786 //meta-data file, the maximum cutoff radius calculated from forcefiled will be used
787
788 if (simParams_->haveRcut()) {
789 rcut_ = simParams_->getRcut();
790 } else {
791 //set cutoff radius to the maximum cutoff radius based on atom types in the whole system
792 rcut_ = calcMaxCutoffRadius();
793 }
794
795 if (simParams_->haveRsw()) {
796 rsw_ = simParams_->getRsw();
797 } else {
798 rsw_ = rcut_;
799 }
800
801 }
802
803 double rnblist = rcut_ + 1; // skin of neighbor list
804
805 //Pass these cutoff radius etc. to fortran. This function should be called once and only once
806 notifyFortranCutoffs(&rcut_, &rsw_, &rnblist);
807 }
808
809 void SimInfo::addProperty(GenericData* genData) {
810 properties_.addProperty(genData);
811 }
812
813 void SimInfo::removeProperty(const std::string& propName) {
814 properties_.removeProperty(propName);
815 }
816
817 void SimInfo::clearProperties() {
818 properties_.clearProperties();
819 }
820
821 std::vector<std::string> SimInfo::getPropertyNames() {
822 return properties_.getPropertyNames();
823 }
824
825 std::vector<GenericData*> SimInfo::getProperties() {
826 return properties_.getProperties();
827 }
828
829 GenericData* SimInfo::getPropertyByName(const std::string& propName) {
830 return properties_.getPropertyByName(propName);
831 }
832
833 void SimInfo::setSnapshotManager(SnapshotManager* sman) {
834 sman_ = sman;
835
836 Molecule* mol;
837 RigidBody* rb;
838 Atom* atom;
839 SimInfo::MoleculeIterator mi;
840 Molecule::RigidBodyIterator rbIter;
841 Molecule::AtomIterator atomIter;;
842
843 for (mol = beginMolecule(mi); mol != NULL; mol = nextMolecule(mi)) {
844
845 for (atom = mol->beginAtom(atomIter); atom != NULL; atom = mol->nextAtom(atomIter)) {
846 atom->setSnapshotManager(sman_);
847 }
848
849 for (rb = mol->beginRigidBody(rbIter); rb != NULL; rb = mol->nextRigidBody(rbIter)) {
850 rb->setSnapshotManager(sman_);
851 }
852 }
853
854 }
855
856 Vector3d SimInfo::getComVel(){
857 SimInfo::MoleculeIterator i;
858 Molecule* mol;
859
860 Vector3d comVel(0.0);
861 double totalMass = 0.0;
862
863
864 for (mol = beginMolecule(i); mol != NULL; mol = nextMolecule(i)) {
865 double mass = mol->getMass();
866 totalMass += mass;
867 comVel += mass * mol->getComVel();
868 }
869
870 #ifdef IS_MPI
871 double tmpMass = totalMass;
872 Vector3d tmpComVel(comVel);
873 MPI_Allreduce(&tmpMass,&totalMass,1,MPI_DOUBLE,MPI_SUM, MPI_COMM_WORLD);
874 MPI_Allreduce(tmpComVel.getArrayPointer(), comVel.getArrayPointer(),3,MPI_DOUBLE,MPI_SUM, MPI_COMM_WORLD);
875 #endif
876
877 comVel /= totalMass;
878
879 return comVel;
880 }
881
882 Vector3d SimInfo::getCom(){
883 SimInfo::MoleculeIterator i;
884 Molecule* mol;
885
886 Vector3d com(0.0);
887 double totalMass = 0.0;
888
889 for (mol = beginMolecule(i); mol != NULL; mol = nextMolecule(i)) {
890 double mass = mol->getMass();
891 totalMass += mass;
892 com += mass * mol->getCom();
893 }
894
895 #ifdef IS_MPI
896 double tmpMass = totalMass;
897 Vector3d tmpCom(com);
898 MPI_Allreduce(&tmpMass,&totalMass,1,MPI_DOUBLE,MPI_SUM, MPI_COMM_WORLD);
899 MPI_Allreduce(tmpCom.getArrayPointer(), com.getArrayPointer(),3,MPI_DOUBLE,MPI_SUM, MPI_COMM_WORLD);
900 #endif
901
902 com /= totalMass;
903
904 return com;
905
906 }
907
908 std::ostream& operator <<(std::ostream& o, SimInfo& info) {
909
910 return o;
911 }
912
913 }//end namespace oopse
914