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: 1739
Committed: Mon Nov 15 18:02:15 2004 UTC (19 years, 7 months ago) by tim
File size: 24455 byte(s)
Log Message:
finish DumpReader, DumpWriter.Next Step is LJFF and integrators

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    
35 tim 1492 #include "brains/SimInfo.hpp"
36 tim 1710 #include "utils/MemoryUtils.hpp"
37 gezelter 1490
38 tim 1710 namespace oopse {
39 gezelter 1490
40 tim 1733 SimInfo::SimInfo(const std::vector<std::pair<MoleculeStamp*, int> >& molStampPairs,
41     ForceField* ff, Globals* globals) :
42     forceField_(ff), globals_(globals), nAtoms_(0), nBonds_(0),
43     nBends_(0), nTorsions_(0), nRigidBodies_(0), nIntegrableObjects_(0),
44 tim 1738 nCutoffGroups_(0), nConstraints_(0), nZConstraint_(0), sman_(NULL),
45     fortranInitialized_(false) {
46 gezelter 1490
47 tim 1733 std::vector<std::pair<MoleculeStamp*, int> >::iterator i;
48     MoleculeStamp* molStamp;
49     int nMolWithSameStamp;
50 tim 1739 int nCutoffAtoms; // number of atoms belong to cutoff groups
51     int nGroups; //total cutoff groups defined in meta-data file
52 tim 1733 CutoffGroupStamp* cgStamp;
53 tim 1739 int nAtomsInGroups;
54     int nCutoffGroupsInStamp;
55    
56     RigidBodyStamp* rbStamp;
57     int nAtomsInRigidBodies;
58     int nRigidBodiesInStamp;
59     int nRigidAtoms;
60     int nRigidBodies;
61    
62 tim 1733 nGlobalAtoms_ = 0;
63    
64 tim 1739 nGroups = 0;
65     nCutoffAtoms = 0;
66    
67     nRigidBodies
68     nRigidBodies = 0;
69    
70 tim 1733 for (i = molStampPairs.begin(); i !=molStampPairs.end(); ++i) {
71     molStamp = i->first;
72     nMolWithSameStamp = i->second;
73    
74     addMoleculeStamp(molStamp, nMolWithSameStamp);
75 tim 1739
76     //calculate atoms in molecules
77 tim 1733 nGlobalAtoms_ += molStamp->getNAtoms() *nMolWithSameStamp;
78 tim 1739
79    
80     //calculate atoms in cutoff groups
81     nAtomsInGroups = 0;
82 tim 1733 nCutoffGroupsInStamp = molStamp->getNCutoffGroups();
83    
84     for (int j=0; j < nCutoffGroupsInStamp; j++) {
85     cgStamp = molStamp->getCutoffGroup(j);
86 tim 1739 nAtomsInGroups += cgStamp->getNMembers();
87 tim 1733 }
88    
89 tim 1739 nGroups += nCutoffGroupsInStamp * nMolWithSameStamp;
90     nCutoffAtoms += nAtomsInGroups * nMolWithSameStamp;
91    
92     //calculate atoms in rigid bodies
93     nAtomsInRigidBodies = 0;
94     nRigidBodiesInStamp = molStamp->getNCutoffGroups();
95    
96     for (int j=0; j < nRigidBodiesInStamp; j++) {
97     rbStamp = molStamp->getRigidBody(j);
98     nRigidBodiesInStamp += rbStamp->getNMembers();
99     }
100    
101     nRigidBodies += nRigidBodiesInStamp * nMolWithSameStamp;
102     nRigidAtoms += nAtomsInRigidBodies * nMolWithSameStamp;
103    
104 tim 1733 }
105    
106     //every free atom (atom does not belong to cutoff groups) is a cutoff group
107     //therefore the total number of cutoff groups in the system is equal to
108     //the total number of atoms minus number of atoms belong to cutoff group defined in meta-data
109     //file plus the number of cutoff groups defined in meta-data file
110 tim 1739 nGlobalCutoffGroups_ = nGlobalAtoms_ - nCutoffAtoms + nGroups;
111 tim 1733
112 tim 1739 //every free atom (atom does not belong to rigid bodies) is a rigid body
113     //therefore the total number of cutoff groups in the system is equal to
114     //the total number of atoms minus number of atoms belong to rigid body defined in meta-data
115     //file plus the number of rigid bodies defined in meta-data file
116     nGlobalIntegrableObjects_ = nGlobalAtoms_ - nRigidAtoms + nRigidBodies;
117    
118 tim 1733 //initialize globalGroupMembership_, every element of this array will be 0
119     globalGroupMembership_.insert(globalGroupMembership_.end(), nGlobalAtoms_, 0);
120    
121     nGlobalMols_ = molStampIds_.size();
122    
123     #ifdef IS_MPI
124     molToProcMap_.resize(nGlobalMols_);
125     #endif
126    
127 gezelter 1490 }
128    
129 tim 1710 SimInfo::~SimInfo() {
130 tim 1726 //MemoryUtils::deleteVectorOfPointer(molecules_);
131 tim 1733
132     MemoryUtils::deleteVectorOfPointer(moleculeStamps_);
133    
134 tim 1710 delete sman_;
135 tim 1733 delete globals_;
136     delete forceField_;
137 gezelter 1490
138     }
139    
140    
141 tim 1710 bool SimInfo::addMolecule(Molecule* mol) {
142 tim 1726 MoleculeIterator i;
143 tim 1733
144     i = molecules_.find(mol->getGlobalIndex());
145 tim 1710 if (i != molecules_.end() ) {
146 gezelter 1490
147 tim 1726 molecules_.insert(make_pair(mol->getGlobalIndex(), mol));
148    
149 tim 1710 nAtoms_ += mol->getNAtoms();
150     nBonds_ += mol->getNBonds();
151     nBends_ += mol->getNBends();
152     nTorsions_ += mol->getNTorsions();
153     nRigidBodies_ += mol->getNRigidBodies();
154     nIntegrableObjects_ += mol->getNIntegrableObjects();
155     nCutoffGroups_ += mol->getNCutoffGroups();
156     nConstraints_ += mol->getNConstraints();
157 gezelter 1490
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 1726 molecules_.erase(mol->getGlobalIndex());
182    
183     delete mol;
184    
185 tim 1710 return true;
186     } else {
187     return false;
188 gezelter 1490 }
189    
190    
191 tim 1710 }
192 gezelter 1490
193 tim 1710
194 tim 1726 Molecule* SimInfo::beginMolecule(MoleculeIterator& i) {
195 tim 1710 i = molecules_.begin();
196 tim 1738 return i == molecules_.end() ? NULL : i->second;
197 tim 1710 }
198 gezelter 1490
199 tim 1726 Molecule* SimInfo::nextMolecule(MoleculeIterator& i) {
200 tim 1710 ++i;
201 tim 1738 return i == molecules_.end() ? NULL : i->second;
202 gezelter 1490 }
203    
204    
205 tim 1722 void SimInfo::calcNdf() {
206 tim 1710 int ndf_local;
207 tim 1726 MoleculeIterator i;
208 tim 1710 std::vector<StuntDouble*>::iterator j;
209     Molecule* mol;
210     StuntDouble* integrableObject;
211 gezelter 1490
212 tim 1710 ndf_local = 0;
213 gezelter 1490
214 tim 1710 for (mol = beginMolecule(i); mol != NULL; mol = nextMolecule(i)) {
215     for (integrableObject = mol->beginIntegrableObject(j); integrableObject != NULL;
216     integrableObject = mol->nextIntegrableObject(j)) {
217 gezelter 1490
218 tim 1710 ndf_local += 3;
219 gezelter 1490
220 tim 1710 if (integrableObject->isDirectional()) {
221     if (integrableObject->isLinear()) {
222     ndf_local += 2;
223     } else {
224     ndf_local += 3;
225     }
226     }
227    
228     }//end for (integrableObject)
229     }// end for (mol)
230 gezelter 1490
231 tim 1710 // n_constraints is local, so subtract them on each processor
232     ndf_local -= nConstraints_;
233 gezelter 1490
234     #ifdef IS_MPI
235 tim 1710 MPI_Allreduce(&ndf_local,&ndf_,1,MPI_INT,MPI_SUM, MPI_COMM_WORLD);
236 gezelter 1490 #else
237 tim 1710 ndf_ = ndf_local;
238 gezelter 1490 #endif
239    
240 tim 1733 // nZconstraints_ is global, as are the 3 COM translations for the
241 tim 1710 // entire system:
242 tim 1733 ndf_ = ndf_ - 3 - nZconstraints_;
243 gezelter 1490
244     }
245    
246 tim 1722 void SimInfo::calcNdfRaw() {
247 tim 1710 int ndfRaw_local;
248 gezelter 1490
249 tim 1726 MoleculeIterator i;
250 tim 1710 std::vector<StuntDouble*>::iterator j;
251     Molecule* mol;
252     StuntDouble* integrableObject;
253 gezelter 1490
254 tim 1710 // Raw degrees of freedom that we have to set
255     ndfRaw_local = 0;
256 gezelter 1490
257 tim 1710 for (mol = beginMolecule(i); mol != NULL; mol = nextMolecule(i)) {
258     for (integrableObject = mol->beginIntegrableObject(j); integrableObject != NULL;
259     integrableObject = mol->nextIntegrableObject(j)) {
260 gezelter 1490
261 tim 1710 ndfRaw_local += 3;
262 gezelter 1490
263 tim 1710 if (integrableObject->isDirectional()) {
264     if (integrableObject->isLinear()) {
265     ndfRaw_local += 2;
266     } else {
267     ndfRaw_local += 3;
268     }
269     }
270    
271     }
272     }
273    
274 gezelter 1490 #ifdef IS_MPI
275 tim 1710 MPI_Allreduce(&ndfRaw_local,&ndfRaw_,1,MPI_INT,MPI_SUM, MPI_COMM_WORLD);
276 gezelter 1490 #else
277 tim 1710 ndfRaw_ = ndfRaw_local;
278 gezelter 1490 #endif
279     }
280    
281 tim 1722 void SimInfo::calcNdfTrans() {
282 tim 1710 int ndfTrans_local;
283 gezelter 1490
284 tim 1710 ndfTrans_local = 3 * nIntegrableObjects_ - nConstraints_;
285 gezelter 1490
286    
287     #ifdef IS_MPI
288 tim 1710 MPI_Allreduce(&ndfTrans_local,&ndfTrans_,1,MPI_INT,MPI_SUM, MPI_COMM_WORLD);
289 gezelter 1490 #else
290 tim 1710 ndfTrans_ = ndfTrans_local;
291 gezelter 1490 #endif
292    
293 tim 1733 ndfTrans_ = ndfTrans_ - 3 - nZconstraints_;
294 gezelter 1490
295     }
296    
297 tim 1719 void SimInfo::addExcludePairs(Molecule* mol) {
298     std::vector<Bond*>::iterator bondIter;
299     std::vector<Bend*>::iterator bendIter;
300     std::vector<Torsion*>::iterator torsionIter;
301     Bond* bond;
302     Bend* bend;
303     Torsion* torsion;
304     int a;
305     int b;
306     int c;
307     int d;
308    
309     for (bond= mol->beginBond(bondIter); bond != NULL; bond = mol->nextBond(bondIter)) {
310     a = bond->getAtomA()->getGlobalIndex();
311     b = bond->getAtomB()->getGlobalIndex();
312     exclude_.addPair(a, b);
313     }
314 gezelter 1490
315 tim 1719 for (bend= mol->beginBend(bendIter); bend != NULL; bend = mol->nextBend(bendIter)) {
316     a = bend->getAtomA()->getGlobalIndex();
317     b = bend->getAtomB()->getGlobalIndex();
318     c = bend->getAtomC()->getGlobalIndex();
319    
320     exclude_.addPair(a, b);
321     exclude_.addPair(a, c);
322     exclude_.addPair(b, c);
323     }
324    
325     for (torsion= mol->beginTorsion(torsionIter); torsion != NULL; torsion = mol->nextBond(torsionIter)) {
326     a = torsion->getAtomA()->getGlobalIndex();
327     b = torsion->getAtomB()->getGlobalIndex();
328     c = torsion->getAtomC()->getGlobalIndex();
329     d = torsion->getAtomD()->getGlobalIndex();
330    
331     exclude_.addPair(a, b);
332     exclude_.addPair(a, c);
333     exclude_.addPair(a, d);
334     exclude_.addPair(b, c);
335     exclude_.addPair(b, d);
336     exclude_.addPair(c, d);
337     }
338    
339    
340     }
341    
342     void SimInfo::removeExcludePairs(Molecule* mol) {
343     std::vector<Bond*>::iterator bondIter;
344     std::vector<Bend*>::iterator bendIter;
345     std::vector<Torsion*>::iterator torsionIter;
346     Bond* bond;
347     Bend* bend;
348     Torsion* torsion;
349     int a;
350     int b;
351     int c;
352     int d;
353    
354     for (bond= mol->beginBond(bondIter); bond != NULL; bond = mol->nextBond(bondIter)) {
355     a = bond->getAtomA()->getGlobalIndex();
356     b = bond->getAtomB()->getGlobalIndex();
357     exclude_.removePair(a, b);
358     }
359    
360     for (bend= mol->beginBend(bendIter); bend != NULL; bend = mol->nextBend(bendIter)) {
361     a = bend->getAtomA()->getGlobalIndex();
362     b = bend->getAtomB()->getGlobalIndex();
363     c = bend->getAtomC()->getGlobalIndex();
364    
365     exclude_.removePair(a, b);
366     exclude_.removePair(a, c);
367     exclude_.removePair(b, c);
368     }
369    
370     for (torsion= mol->beginTorsion(torsionIter); torsion != NULL; torsion = mol->nextBond(torsionIter)) {
371     a = torsion->getAtomA()->getGlobalIndex();
372     b = torsion->getAtomB()->getGlobalIndex();
373     c = torsion->getAtomC()->getGlobalIndex();
374     d = torsion->getAtomD()->getGlobalIndex();
375    
376     exclude_.removePair(a, b);
377     exclude_.removePair(a, c);
378     exclude_.removePair(a, d);
379     exclude_.removePair(b, c);
380     exclude_.removePair(b, d);
381     exclude_.removePair(c, d);
382     }
383    
384     }
385    
386    
387 tim 1725 void SimInfo::addMoleculeStamp(MoleculeStamp* molStamp, int nmol) {
388     int curStampId;
389    
390     //index from 0
391     curStampId = molStampIds_.size();
392    
393     moleculeStamps_.push_back(molStamp);
394     molStampIds_.insert(molStampIds_.end(), nmol, curStampId)
395     }
396    
397 tim 1727 void SimInfo::update() {
398    
399 tim 1738 setupSimType();
400    
401 tim 1733 #ifdef IS_MPI
402     setupFortranParallel();
403     #endif
404 tim 1727
405 tim 1733 setupFortranSim();
406    
407 tim 1738 setupCutoff();
408    
409     //notify fortran whether reaction field is used or not. It is deprecated now
410     //int isError = 0;
411     //initFortranFF( &useReactionField, &isError );
412    
413     //if(isError){
414     // sprintf( painCave.errMsg,
415     // "SimCreator::initFortran() error: There was an error initializing the forceField in fortran.\n" );
416     // painCave.isFatal = 1;
417     // simError();
418     //}
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     typename SimInfo::MoleculeIterator mi;
429     Molecule* mol;
430     typename Molecule::AtomIterator ai;
431     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     //usePBC and useRF are from globals
463     bool usePBC = globals_->getPBC();
464     bool useRF = globals_->getUseRF();
465    
466     //loop over all of the atom types
467     for (i = atomTypes.begin(); i != atomTypes.end(); ++i) {
468     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     }
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     fInfo_.dielect = dielectric;
543     } else {
544     fInfo_.dielect = 0.0;
545     }
546    
547     }
548    
549     void SimInfo::setupFortranSim() {
550     int isError;
551     int nExclude;
552     std::vector<int> fortranGlobalGroupMembership;
553    
554     nExclude = exclude_.getSize();
555     isError = 0;
556    
557     //globalGroupMembership_ is filled by SimCreator
558     for (int i = 0; i < nGlobalAtoms_; i++) {
559     fortranGlobalGroupMembership.push_back(globalGroupMembership_[i] + 1);
560     }
561    
562     //calculate mass ratio of cutoff group
563     std::vector<double> mfact;
564     typename SimInfo::MoleculeIterator mi;
565     Molecule* mol;
566     typename Molecule::CutoffGroupIterator ci;
567     CutoffGroup* cg;
568     typename Molecule::AtomIterator ai;
569     Atom* atom;
570     double totalMass;
571    
572     //to avoid memory reallocation, reserve enough space for mfact
573     mfact.reserve(getNCutoffGroups());
574    
575     for(mol = beginMolecule(mi); mol != NULL; mol = nextMolecule(mi)) {
576     for (cg = mol->beginCutoffGroup(ci); cg != NULL; cg = mol->nextCutoffGroup(ci)) {
577    
578     totalMass = cg->getMass();
579     for(atom = cg->beginAtom(ai); atom != NULL; atom = cg->nextAtom(ai)) {
580     mfact.push_back(atom->getMass()/totalMass);
581     }
582    
583     }
584     }
585    
586     //fill ident array of local atoms (it is actually ident of AtomType, it is so confusing !!!)
587     std::vector<int> identArray;
588    
589     //to avoid memory reallocation, reserve enough space identArray
590     identArray.reserve(getNAtoms());
591    
592     for(mol = beginMolecule(mi); mol != NULL; mol = nextMolecule(mi)) {
593     for(atom = mol->beginAtom(ai); atom != NULL; atom = mol->nextAtom(ai)) {
594     identArray.push_back(atom->getIdent());
595     }
596     }
597    
598 tim 1735 //fill molMembershipArray
599     //molMembershipArray is filled by SimCreator
600     std::vector<int> molMembershipArray(nGlobalAtoms_);
601     for (int i = 0; i < nGlobalAtoms_; i++) {
602     molMembershipArray.push_back(globalMolMembership_[i] + 1);
603     }
604    
605 tim 1733 //setup fortran simulation
606     //gloalExcludes and molMembershipArray should go away (They are never used)
607     //why the hell fortran need to know molecule?
608     //OOPSE = Object-Obfuscated Parallel Simulation Engine
609    
610     setFortranSim( &fInfo_, &nGlobalAtoms_, &nAtoms_, &identArray[0], &nExclude, exclude_->getExcludeList(),
611     &nGlobalExcludes, globalExcludes, molMembershipArray,
612     &mfact[0], &nCutoffGroups_, &fortranGlobalGroupMembership[0], &isError);
613    
614     if( isError ){
615    
616     sprintf( painCave.errMsg,
617     "There was an error setting the simulation information in fortran.\n" );
618     painCave.isFatal = 1;
619     painCave.severity = OOPSE_ERROR;
620     simError();
621     }
622    
623     #ifdef IS_MPI
624     sprintf( checkPointMsg,
625     "succesfully sent the simulation information to fortran.\n");
626     MPIcheckPoint();
627     #endif // is_mpi
628     }
629    
630    
631     #ifdef IS_MPI
632     void SimInfo::setupFortranParallel() {
633    
634 tim 1727 //SimInfo is responsible for creating localToGlobalAtomIndex and localToGlobalGroupIndex
635     std::vector<int> localToGlobalAtomIndex(getNAtoms(), 0);
636     std::vector<int> localToGlobalCutoffGroupIndex;
637     typename SimInfo::MoleculeIterator mi;
638     typename Molecule::AtomIterator ai;
639     typename Molecule::CutoffGroupIterator ci;
640     Molecule* mol;
641     Atom* atom;
642     CutoffGroup* cg;
643     mpiSimData parallelData;
644     int isError;
645    
646     for (mol = beginMolecule(mi); mol != NULL; mol = nextMolecule(mi)) {
647    
648     //local index(index in DataStorge) of atom is important
649     for (atom = mol->beginAtom(ai); atom != NULL; atom = mol->nextAtom(ai)) {
650     localToGlobalAtomIndex[atom->getLocalIndex()] = atom->getGlobalIndex() + 1;
651     }
652    
653     //local index of cutoff group is trivial, it only depends on the order of travesing
654     for (cg = mol->beginCutoffGroup(ci); cg != NULL; cg = mol->nextCutoffGroup(ci)) {
655     localToGlobalCutoffGroupIndex.push_back(cg->getGlobalIndex() + 1);
656     }
657    
658     }
659    
660 tim 1733 //fill up mpiSimData struct
661     parallelData.nMolGlobal = getNGlobalMolecules();
662     parallelData.nMolLocal = getNMolecules();
663     parallelData.nAtomsGlobal = getNGlobalAtoms();
664     parallelData.nAtomsLocal = getNAtoms();
665     parallelData.nGroupsGlobal = getNGlobalCutoffGroups();
666     parallelData.nGroupsLocal = getNCutoffGroups();
667 tim 1727 parallelData.myNode = worldRank;
668     MPI_Comm_size(MPI_COMM_WORLD, &(parallelData->nProcessors));
669 tim 1733
670     //pass mpiSimData struct and index arrays to fortran
671     setFsimParallel(parallelData, &(parallelData->nAtomsLocal),
672 tim 1727 &localToGlobalAtomIndex[0], &(parallelData->nGroupsLocal),
673     &localToGlobalCutoffGroupIndex[0], &isError);
674    
675     if (isError) {
676     sprintf(painCave.errMsg,
677     "mpiRefresh errror: fortran didn't like something we gave it.\n");
678     painCave.isFatal = 1;
679     simError();
680     }
681    
682     sprintf(checkPointMsg, " mpiRefresh successful.\n");
683     MPIcheckPoint();
684    
685    
686     }
687    
688 tim 1733 #endif
689    
690 tim 1735 double SimInfo::calcMaxCutoffRadius() {
691    
692    
693     std::vector<AtomType*> atomTypes;
694     std::vector<AtomType*>::iterator i;
695     std::vector<double> cutoffRadius;
696    
697     //get the unique atom types
698     atomTypes = getUniqueAtomTypes();
699    
700     //query the max cutoff radius among these atom types
701     for (i = atomTypes.begin(); i != atomTypes.end(); ++i) {
702     cutoffRadius.push_back(forceField_->getRcutFromAtomType(*i));
703     }
704    
705     double maxCutoffRadius = std::max_element(cutoffRadius.begin(), cutoffRadius.end());
706     #ifdef IS_MPI
707     //pick the max cutoff radius among the processors
708     #endif
709    
710     return maxCutoffRadius;
711     }
712    
713 tim 1738 void SimInfo::setupCutoff() {
714     double rcut_; //cutoff radius
715     double rsw_; //switching radius
716    
717     if (fInfo_.SIM_uses_Charges | fInfo_.SIM_uses_Dipoles | fInfo_.SIM_uses_RF) {
718    
719     if (!globals_->haveRcut()){
720     sprintf(painCave.errMsg,
721     "SimCreator Warning: No value was set for the cutoffRadius.\n"
722     "\tOOPSE will use a default value of 15.0 angstroms"
723     "\tfor the cutoffRadius.\n");
724     painCave.isFatal = 0;
725     simError();
726     rcut_ = 15.0;
727     } else{
728     rcut_ = globals_->getRcut();
729     }
730    
731     if (!globals_->haveRsw()){
732     sprintf(painCave.errMsg,
733     "SimCreator Warning: No value was set for switchingRadius.\n"
734     "\tOOPSE will use a default value of\n"
735     "\t0.95 * cutoffRadius for the switchingRadius\n");
736     painCave.isFatal = 0;
737     simError();
738     rsw_ = 0.95 * rcut_;
739     } else{
740     rsw_ = globals_->getRsw();
741     }
742    
743     } else {
744     // if charge, dipole or reaction field is not used and the cutofff radius is not specified in
745     //meta-data file, the maximum cutoff radius calculated from forcefiled will be used
746    
747     if (globals_->haveRcut()) {
748     rcut_ = globals_->getRcut();
749     } else {
750     //set cutoff radius to the maximum cutoff radius based on atom types in the whole system
751     rcut_ = calcMaxCutoffRadius();
752     }
753    
754     if (globals_->haveRsw()) {
755     rsw_ = globals_->getRsw()
756     } else {
757     rsw_ = rcut_;
758     }
759    
760     }
761    
762     double rnblist = rcut_ + 1; // skin of neighbor list
763    
764     //Pass these cutoff radius etc. to fortran. This function should be called once and only once
765     notifyFortranCutoffs(&rcut_, &rsw_, &rnblist);
766     }
767    
768 tim 1733 void SimInfo::addProperty(GenericData* genData) {
769     properties_.addProperty(genData);
770     }
771    
772     void SimInfo::removeProperty(const std::string& propName) {
773     properties_.removeProperty(propName);
774     }
775    
776     void SimInfo::clearProperties() {
777     properties_.clearProperties();
778     }
779    
780     std::vector<std::string> SimInfo::getPropertyNames() {
781     return properties_.getPropertyNames();
782     }
783    
784     std::vector<GenericData*> SimInfo::getProperties() {
785     return properties_.getProperties();
786     }
787    
788     GenericData* SimInfo::getPropertyByName(const std::string& propName) {
789     return properties_.getPropertyByName(propName);
790     }
791    
792    
793 tim 1725 std::ostream& operator <<(ostream& o, SimInfo& info) {
794    
795     return o;
796     }
797    
798 tim 1710 }//end namespace oopse