ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/group/branches/new_design/OOPSE-3.0/src/brains/SimInfo.cpp
Revision: 1907
Committed: Thu Jan 6 22:31:07 2005 UTC (19 years, 7 months ago) by tim
File size: 27417 byte(s)
Log Message:
constraint is almost working

File Contents

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