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: 1804
Committed: Tue Nov 30 19:58:25 2004 UTC (19 years, 7 months ago) by tim
File size: 24991 byte(s)
Log Message:
fix Thermo

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 1804 #include "primitives/Molecule.hpp"
37     #include "UseTheForce/notifyCutoffs_interface.h"
38 tim 1710 #include "utils/MemoryUtils.hpp"
39 tim 1804 #include "utils/simError.h"
40 gezelter 1490
41 tim 1710 namespace oopse {
42 gezelter 1490
43 tim 1804 SimInfo::SimInfo(std::vector<std::pair<MoleculeStamp*, int> >& molStampPairs,
44 tim 1733 ForceField* ff, Globals* globals) :
45     forceField_(ff), globals_(globals), nAtoms_(0), nBonds_(0),
46     nBends_(0), nTorsions_(0), nRigidBodies_(0), nIntegrableObjects_(0),
47 tim 1804 nCutoffGroups_(0), nConstraints_(0), nZconstraint_(0), sman_(NULL),
48 tim 1738 fortranInitialized_(false) {
49 gezelter 1490
50 tim 1733 std::vector<std::pair<MoleculeStamp*, int> >::iterator i;
51     MoleculeStamp* molStamp;
52     int nMolWithSameStamp;
53 tim 1739 int nCutoffAtoms; // number of atoms belong to cutoff groups
54     int nGroups; //total cutoff groups defined in meta-data file
55 tim 1733 CutoffGroupStamp* cgStamp;
56 tim 1739 int nAtomsInGroups;
57     int nCutoffGroupsInStamp;
58    
59     RigidBodyStamp* rbStamp;
60     int nAtomsInRigidBodies;
61     int nRigidBodiesInStamp;
62     int nRigidAtoms;
63     int nRigidBodies;
64    
65 tim 1733 nGlobalAtoms_ = 0;
66    
67 tim 1739 nGroups = 0;
68     nCutoffAtoms = 0;
69     nRigidBodies = 0;
70    
71 tim 1733 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     nAtomsInGroups = 0;
83 tim 1733 nCutoffGroupsInStamp = molStamp->getNCutoffGroups();
84    
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     nAtomsInRigidBodies = 0;
95     nRigidBodiesInStamp = molStamp->getNCutoffGroups();
96    
97     for (int j=0; j < nRigidBodiesInStamp; j++) {
98     rbStamp = molStamp->getRigidBody(j);
99     nRigidBodiesInStamp += rbStamp->getNMembers();
100     }
101    
102     nRigidBodies += nRigidBodiesInStamp * nMolWithSameStamp;
103     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 1739 //every free atom (atom does not belong to rigid bodies) is a rigid body
114     //therefore the total number of cutoff groups in the system is equal to
115     //the total number of atoms minus number of atoms belong to rigid body defined in meta-data
116     //file plus the number of rigid bodies defined in meta-data file
117     nGlobalIntegrableObjects_ = nGlobalAtoms_ - nRigidAtoms + nRigidBodies;
118    
119 tim 1733 //initialize globalGroupMembership_, every element of this array will be 0
120     globalGroupMembership_.insert(globalGroupMembership_.end(), nGlobalAtoms_, 0);
121    
122     nGlobalMols_ = molStampIds_.size();
123    
124     #ifdef IS_MPI
125     molToProcMap_.resize(nGlobalMols_);
126     #endif
127    
128 gezelter 1490 }
129    
130 tim 1710 SimInfo::~SimInfo() {
131 tim 1726 //MemoryUtils::deleteVectorOfPointer(molecules_);
132 tim 1733
133     MemoryUtils::deleteVectorOfPointer(moleculeStamps_);
134    
135 tim 1710 delete sman_;
136 tim 1733 delete globals_;
137     delete forceField_;
138 gezelter 1490
139     }
140    
141    
142 tim 1710 bool SimInfo::addMolecule(Molecule* mol) {
143 tim 1726 MoleculeIterator i;
144 tim 1733
145     i = molecules_.find(mol->getGlobalIndex());
146 tim 1710 if (i != molecules_.end() ) {
147 gezelter 1490
148 tim 1726 molecules_.insert(make_pair(mol->getGlobalIndex(), mol));
149    
150 tim 1710 nAtoms_ += mol->getNAtoms();
151     nBonds_ += mol->getNBonds();
152     nBends_ += mol->getNBends();
153     nTorsions_ += mol->getNTorsions();
154     nRigidBodies_ += mol->getNRigidBodies();
155     nIntegrableObjects_ += mol->getNIntegrableObjects();
156     nCutoffGroups_ += mol->getNCutoffGroups();
157     nConstraints_ += mol->getNConstraints();
158 gezelter 1490
159 tim 1710 return true;
160     } else {
161     return false;
162 gezelter 1490 }
163     }
164    
165 tim 1710 bool SimInfo::removeMolecule(Molecule* mol) {
166 tim 1726 MoleculeIterator i;
167 tim 1733 i = molecules_.find(mol->getGlobalIndex());
168 gezelter 1490
169 tim 1710 if (i != molecules_.end() ) {
170 tim 1726
171 tim 1733 assert(mol == i->second);
172    
173 tim 1710 nAtoms_ -= mol->getNAtoms();
174     nBonds_ -= mol->getNBonds();
175     nBends_ -= mol->getNBends();
176     nTorsions_ -= mol->getNTorsions();
177     nRigidBodies_ -= mol->getNRigidBodies();
178     nIntegrableObjects_ -= mol->getNIntegrableObjects();
179     nCutoffGroups_ -= mol->getNCutoffGroups();
180     nConstraints_ -= mol->getNConstraints();
181 gezelter 1490
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     curStampId = molStampIds_.size();
393    
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 1738 setupCutoff();
409    
410     //notify fortran whether reaction field is used or not. It is deprecated now
411     //int isError = 0;
412     //initFortranFF( &useReactionField, &isError );
413    
414     //if(isError){
415     // sprintf( painCave.errMsg,
416     // "SimCreator::initFortran() error: There was an error initializing the forceField in fortran.\n" );
417     // painCave.isFatal = 1;
418     // simError();
419     //}
420    
421 tim 1733 calcNdf();
422     calcNdfRaw();
423     calcNdfTrans();
424 tim 1738
425     fortranInitialized_ = true;
426 tim 1733 }
427    
428     std::set<AtomType*> SimInfo::getUniqueAtomTypes() {
429 tim 1804 SimInfo::MoleculeIterator mi;
430 tim 1733 Molecule* mol;
431 tim 1804 Molecule::AtomIterator ai;
432 tim 1733 Atom* atom;
433     std::set<AtomType*> atomTypes;
434    
435     for(mol = beginMolecule(mi); mol != NULL; mol = nextMolecule(mi)) {
436    
437     for(atom = mol->beginAtom(ai); atom != NULL; atom = mol->nextAtom(ai)) {
438     atomTypes.insert(atom->getAtomType());
439     }
440    
441     }
442    
443     return atomTypes;
444     }
445    
446     void SimInfo::setupSimType() {
447     std::set<AtomType*>::iterator i;
448     std::set<AtomType*> atomTypes;
449     atomTypes = getUniqueAtomTypes();
450 tim 1727
451 tim 1733 int useLennardJones = 0;
452     int useElectrostatic = 0;
453     int useEAM = 0;
454     int useCharge = 0;
455     int useDirectional = 0;
456     int useDipole = 0;
457     int useGayBerne = 0;
458     int useSticky = 0;
459     int useShape = 0;
460     int useFLARB = 0; //it is not in AtomType yet
461     int useDirectionalAtom = 0;
462     int useElectrostatics = 0;
463     //usePBC and useRF are from globals
464     bool usePBC = globals_->getPBC();
465     bool useRF = globals_->getUseRF();
466    
467     //loop over all of the atom types
468     for (i = atomTypes.begin(); i != atomTypes.end(); ++i) {
469 tim 1804 useLennardJones |= (*i)->isLennardJones();
470     useElectrostatic |= (*i)->isElectrostatic();
471     useEAM |= (*i)->isEAM();
472     useCharge |= (*i)->isCharge();
473     useDirectional |= (*i)->isDirectional();
474     useDipole |= (*i)->isDipole();
475     useGayBerne |= (*i)->isGayBerne();
476     useSticky |= (*i)->isSticky();
477     useShape |= (*i)->isShape();
478 tim 1733 }
479    
480     if (useSticky || useDipole || useGayBerne || useShape) {
481     useDirectionalAtom = 1;
482     }
483    
484     if (useCharge || useDipole) {
485     useElectrostatics = 1;
486     }
487    
488     #ifdef IS_MPI
489     int temp;
490    
491     temp = usePBC;
492     MPI_Allreduce(&temp, &usePBC, 1, MPI_INT, MPI_LOR, MPI_COMM_WORLD);
493    
494     temp = useDirectionalAtom;
495     MPI_Allreduce(&temp, &useDirectionalAtom, 1, MPI_INT, MPI_LOR, MPI_COMM_WORLD);
496    
497     temp = useLennardJones;
498     MPI_Allreduce(&temp, &useLennardJones, 1, MPI_INT, MPI_LOR, MPI_COMM_WORLD);
499    
500     temp = useElectrostatics;
501     MPI_Allreduce(&temp, &useElectrostatics, 1, MPI_INT, MPI_LOR, MPI_COMM_WORLD);
502    
503     temp = useCharge;
504     MPI_Allreduce(&temp, &useCharge, 1, MPI_INT, MPI_LOR, MPI_COMM_WORLD);
505    
506     temp = useDipole;
507     MPI_Allreduce(&temp, &useDipole, 1, MPI_INT, MPI_LOR, MPI_COMM_WORLD);
508    
509     temp = useSticky;
510     MPI_Allreduce(&temp, &useSticky, 1, MPI_INT, MPI_LOR, MPI_COMM_WORLD);
511    
512     temp = useGayBerne;
513     MPI_Allreduce(&temp, &useGayBerne, 1, MPI_INT, MPI_LOR, MPI_COMM_WORLD);
514    
515     temp = useEAM;
516     MPI_Allreduce(&temp, &useEAM, 1, MPI_INT, MPI_LOR, MPI_COMM_WORLD);
517    
518     temp = useShape;
519     MPI_Allreduce(&temp, &useShape, 1, MPI_INT, MPI_LOR, MPI_COMM_WORLD);
520    
521     temp = useFLARB;
522     MPI_Allreduce(&temp, &useFLARB, 1, MPI_INT, MPI_LOR, MPI_COMM_WORLD);
523    
524     temp = useRF;
525     MPI_Allreduce(&temp, &useRF, 1, MPI_INT, MPI_LOR, MPI_COMM_WORLD);
526    
527     #endif
528    
529     fInfo_.SIM_uses_PBC = usePBC;
530     fInfo_.SIM_uses_DirectionalAtoms = useDirectionalAtom;
531     fInfo_.SIM_uses_LennardJones = useLennardJones;
532     fInfo_.SIM_uses_Electrostatics = useElectrostatics;
533     fInfo_.SIM_uses_Charges = useCharge;
534     fInfo_.SIM_uses_Dipoles = useDipole;
535     fInfo_.SIM_uses_Sticky = useSticky;
536     fInfo_.SIM_uses_GayBerne = useGayBerne;
537     fInfo_.SIM_uses_EAM = useEAM;
538     fInfo_.SIM_uses_Shapes = useShape;
539     fInfo_.SIM_uses_FLARB = useFLARB;
540     fInfo_.SIM_uses_RF = useRF;
541    
542     if( fInfo_.SIM_uses_Dipoles && fInfo_.SIM_uses_RF) {
543 tim 1804
544     if (globals_->haveDielectric()) {
545     fInfo_.dielect = globals_->getDielectric();
546     } else {
547     sprintf(painCave.errMsg,
548     "SimSetup Error: No Dielectric constant was set.\n"
549     "\tYou are trying to use Reaction Field without"
550     "\tsetting a dielectric constant!\n");
551     painCave.isFatal = 1;
552     simError();
553     }
554    
555 tim 1733 } else {
556     fInfo_.dielect = 0.0;
557     }
558    
559     }
560    
561     void SimInfo::setupFortranSim() {
562     int isError;
563     int nExclude;
564     std::vector<int> fortranGlobalGroupMembership;
565    
566     nExclude = exclude_.getSize();
567     isError = 0;
568    
569     //globalGroupMembership_ is filled by SimCreator
570     for (int i = 0; i < nGlobalAtoms_; i++) {
571     fortranGlobalGroupMembership.push_back(globalGroupMembership_[i] + 1);
572     }
573    
574     //calculate mass ratio of cutoff group
575     std::vector<double> mfact;
576 tim 1804 SimInfo::MoleculeIterator mi;
577 tim 1733 Molecule* mol;
578 tim 1804 Molecule::CutoffGroupIterator ci;
579 tim 1733 CutoffGroup* cg;
580 tim 1804 Molecule::AtomIterator ai;
581 tim 1733 Atom* atom;
582     double totalMass;
583    
584     //to avoid memory reallocation, reserve enough space for mfact
585     mfact.reserve(getNCutoffGroups());
586    
587     for(mol = beginMolecule(mi); mol != NULL; mol = nextMolecule(mi)) {
588     for (cg = mol->beginCutoffGroup(ci); cg != NULL; cg = mol->nextCutoffGroup(ci)) {
589    
590     totalMass = cg->getMass();
591     for(atom = cg->beginAtom(ai); atom != NULL; atom = cg->nextAtom(ai)) {
592     mfact.push_back(atom->getMass()/totalMass);
593     }
594    
595     }
596     }
597    
598     //fill ident array of local atoms (it is actually ident of AtomType, it is so confusing !!!)
599     std::vector<int> identArray;
600    
601     //to avoid memory reallocation, reserve enough space identArray
602     identArray.reserve(getNAtoms());
603    
604     for(mol = beginMolecule(mi); mol != NULL; mol = nextMolecule(mi)) {
605     for(atom = mol->beginAtom(ai); atom != NULL; atom = mol->nextAtom(ai)) {
606     identArray.push_back(atom->getIdent());
607     }
608     }
609    
610 tim 1735 //fill molMembershipArray
611     //molMembershipArray is filled by SimCreator
612     std::vector<int> molMembershipArray(nGlobalAtoms_);
613     for (int i = 0; i < nGlobalAtoms_; i++) {
614     molMembershipArray.push_back(globalMolMembership_[i] + 1);
615     }
616    
617 tim 1733 //setup fortran simulation
618     //gloalExcludes and molMembershipArray should go away (They are never used)
619     //why the hell fortran need to know molecule?
620     //OOPSE = Object-Obfuscated Parallel Simulation Engine
621 tim 1804 int nGlobalExcludes = 0;
622     int* globalExcludes = NULL;
623     int* excludeList = exclude_.getExcludeList();
624     setFortranSim( &fInfo_, &nGlobalAtoms_, &nAtoms_, &identArray[0], &nExclude, excludeList ,
625     &nGlobalExcludes, globalExcludes, &molMembershipArray[0],
626 tim 1733 &mfact[0], &nCutoffGroups_, &fortranGlobalGroupMembership[0], &isError);
627    
628     if( isError ){
629    
630     sprintf( painCave.errMsg,
631     "There was an error setting the simulation information in fortran.\n" );
632     painCave.isFatal = 1;
633     painCave.severity = OOPSE_ERROR;
634     simError();
635     }
636    
637     #ifdef IS_MPI
638     sprintf( checkPointMsg,
639     "succesfully sent the simulation information to fortran.\n");
640     MPIcheckPoint();
641     #endif // is_mpi
642     }
643    
644    
645     #ifdef IS_MPI
646     void SimInfo::setupFortranParallel() {
647    
648 tim 1727 //SimInfo is responsible for creating localToGlobalAtomIndex and localToGlobalGroupIndex
649     std::vector<int> localToGlobalAtomIndex(getNAtoms(), 0);
650     std::vector<int> localToGlobalCutoffGroupIndex;
651 tim 1804 SimInfo::MoleculeIterator mi;
652     Molecule::AtomIterator ai;
653     Molecule::CutoffGroupIterator ci;
654 tim 1727 Molecule* mol;
655     Atom* atom;
656     CutoffGroup* cg;
657     mpiSimData parallelData;
658     int isError;
659    
660     for (mol = beginMolecule(mi); mol != NULL; mol = nextMolecule(mi)) {
661    
662     //local index(index in DataStorge) of atom is important
663     for (atom = mol->beginAtom(ai); atom != NULL; atom = mol->nextAtom(ai)) {
664     localToGlobalAtomIndex[atom->getLocalIndex()] = atom->getGlobalIndex() + 1;
665     }
666    
667     //local index of cutoff group is trivial, it only depends on the order of travesing
668     for (cg = mol->beginCutoffGroup(ci); cg != NULL; cg = mol->nextCutoffGroup(ci)) {
669     localToGlobalCutoffGroupIndex.push_back(cg->getGlobalIndex() + 1);
670     }
671    
672     }
673    
674 tim 1733 //fill up mpiSimData struct
675     parallelData.nMolGlobal = getNGlobalMolecules();
676     parallelData.nMolLocal = getNMolecules();
677     parallelData.nAtomsGlobal = getNGlobalAtoms();
678     parallelData.nAtomsLocal = getNAtoms();
679     parallelData.nGroupsGlobal = getNGlobalCutoffGroups();
680     parallelData.nGroupsLocal = getNCutoffGroups();
681 tim 1727 parallelData.myNode = worldRank;
682     MPI_Comm_size(MPI_COMM_WORLD, &(parallelData->nProcessors));
683 tim 1733
684     //pass mpiSimData struct and index arrays to fortran
685     setFsimParallel(parallelData, &(parallelData->nAtomsLocal),
686 tim 1727 &localToGlobalAtomIndex[0], &(parallelData->nGroupsLocal),
687     &localToGlobalCutoffGroupIndex[0], &isError);
688    
689     if (isError) {
690     sprintf(painCave.errMsg,
691     "mpiRefresh errror: fortran didn't like something we gave it.\n");
692     painCave.isFatal = 1;
693     simError();
694     }
695    
696     sprintf(checkPointMsg, " mpiRefresh successful.\n");
697     MPIcheckPoint();
698    
699    
700     }
701    
702 tim 1733 #endif
703    
704 tim 1735 double SimInfo::calcMaxCutoffRadius() {
705    
706    
707 tim 1804 std::set<AtomType*> atomTypes;
708     std::set<AtomType*>::iterator i;
709 tim 1735 std::vector<double> cutoffRadius;
710    
711     //get the unique atom types
712     atomTypes = getUniqueAtomTypes();
713    
714     //query the max cutoff radius among these atom types
715     for (i = atomTypes.begin(); i != atomTypes.end(); ++i) {
716     cutoffRadius.push_back(forceField_->getRcutFromAtomType(*i));
717     }
718    
719 tim 1804 double maxCutoffRadius = *(std::max_element(cutoffRadius.begin(), cutoffRadius.end()));
720 tim 1735 #ifdef IS_MPI
721     //pick the max cutoff radius among the processors
722     #endif
723    
724     return maxCutoffRadius;
725     }
726    
727 tim 1738 void SimInfo::setupCutoff() {
728     double rcut_; //cutoff radius
729     double rsw_; //switching radius
730    
731     if (fInfo_.SIM_uses_Charges | fInfo_.SIM_uses_Dipoles | fInfo_.SIM_uses_RF) {
732    
733     if (!globals_->haveRcut()){
734     sprintf(painCave.errMsg,
735     "SimCreator Warning: No value was set for the cutoffRadius.\n"
736     "\tOOPSE will use a default value of 15.0 angstroms"
737     "\tfor the cutoffRadius.\n");
738     painCave.isFatal = 0;
739     simError();
740     rcut_ = 15.0;
741     } else{
742     rcut_ = globals_->getRcut();
743     }
744    
745     if (!globals_->haveRsw()){
746     sprintf(painCave.errMsg,
747     "SimCreator Warning: No value was set for switchingRadius.\n"
748     "\tOOPSE will use a default value of\n"
749     "\t0.95 * cutoffRadius for the switchingRadius\n");
750     painCave.isFatal = 0;
751     simError();
752     rsw_ = 0.95 * rcut_;
753     } else{
754     rsw_ = globals_->getRsw();
755     }
756    
757     } else {
758     // if charge, dipole or reaction field is not used and the cutofff radius is not specified in
759     //meta-data file, the maximum cutoff radius calculated from forcefiled will be used
760    
761     if (globals_->haveRcut()) {
762     rcut_ = globals_->getRcut();
763     } else {
764     //set cutoff radius to the maximum cutoff radius based on atom types in the whole system
765     rcut_ = calcMaxCutoffRadius();
766     }
767    
768     if (globals_->haveRsw()) {
769 tim 1804 rsw_ = globals_->getRsw();
770 tim 1738 } else {
771     rsw_ = rcut_;
772     }
773    
774     }
775    
776     double rnblist = rcut_ + 1; // skin of neighbor list
777    
778     //Pass these cutoff radius etc. to fortran. This function should be called once and only once
779     notifyFortranCutoffs(&rcut_, &rsw_, &rnblist);
780     }
781    
782 tim 1733 void SimInfo::addProperty(GenericData* genData) {
783     properties_.addProperty(genData);
784     }
785    
786     void SimInfo::removeProperty(const std::string& propName) {
787     properties_.removeProperty(propName);
788     }
789    
790     void SimInfo::clearProperties() {
791     properties_.clearProperties();
792     }
793    
794     std::vector<std::string> SimInfo::getPropertyNames() {
795     return properties_.getPropertyNames();
796     }
797    
798     std::vector<GenericData*> SimInfo::getProperties() {
799     return properties_.getProperties();
800     }
801    
802     GenericData* SimInfo::getPropertyByName(const std::string& propName) {
803     return properties_.getPropertyByName(propName);
804     }
805    
806    
807 tim 1725 std::ostream& operator <<(ostream& o, SimInfo& info) {
808    
809     return o;
810     }
811    
812 tim 1710 }//end namespace oopse