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: 1895
Committed: Thu Dec 16 19:20:49 2004 UTC (19 years, 6 months ago) by tim
File size: 27126 byte(s)
Log Message:
Fix a bug in SimInfo which gives the invalid stamp id

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