ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/group/branches/new_design/OOPSE-2.0/src/brains/SimInfo.cpp
Revision: 1886
Committed: Wed Dec 15 16:13:35 2004 UTC (19 years, 6 months ago) by tim
File size: 26550 byte(s)
Log Message:
MPI in NVE is working

File Contents

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