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: 1854
Committed: Sun Dec 5 22:02:42 2004 UTC (19 years, 7 months ago) by tim
File size: 26361 byte(s)
Log Message:
fix a bug in filling MolMembership

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