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: 1927
Committed: Wed Jan 12 17:14:35 2005 UTC (20 years, 4 months ago) by tim
File size: 28347 byte(s)
Log Message:
change license

File Contents

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