ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/group/trunk/OOPSE-3.0/src/brains/SimInfo.cpp
Revision: 1930
Committed: Wed Jan 12 22:41:40 2005 UTC (19 years, 6 months ago) by gezelter
File size: 28347 byte(s)
Log Message:
merging new_design branch into OOPSE-2.0

File Contents

# User Rev Content
1 gezelter 1930 /*
2     * Copyright (c) 2005 The University of Notre Dame. All Rights Reserved.
3     *
4     * 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     */
41    
42     /**
43     * @file SimInfo.cpp
44     * @author tlin
45     * @date 11/02/2004
46     * @version 1.0
47     */
48 gezelter 1490
49 gezelter 1930 #include <algorithm>
50     #include <set>
51 gezelter 1490
52 tim 1492 #include "brains/SimInfo.hpp"
53 gezelter 1930 #include "math/Vector3.hpp"
54     #include "primitives/Molecule.hpp"
55     #include "UseTheForce/doForces_interface.h"
56     #include "UseTheForce/notifyCutoffs_interface.h"
57     #include "utils/MemoryUtils.hpp"
58 tim 1492 #include "utils/simError.h"
59 gezelter 1490
60 gezelter 1930 #ifdef IS_MPI
61     #include "UseTheForce/mpiComponentPlan.h"
62     #include "UseTheForce/DarkSide/simParallel_interface.h"
63     #endif
64 gezelter 1490
65 gezelter 1930 namespace oopse {
66 gezelter 1490
67 gezelter 1930 SimInfo::SimInfo(std::vector<std::pair<MoleculeStamp*, int> >& molStampPairs,
68     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 gezelter 1930
78     std::vector<std::pair<MoleculeStamp*, int> >::iterator i;
79     MoleculeStamp* molStamp;
80     int nMolWithSameStamp;
81     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     RigidBodyStamp* rbStamp;
85     int nRigidAtoms = 0;
86    
87     for (i = molStampPairs.begin(); i !=molStampPairs.end(); ++i) {
88     molStamp = i->first;
89     nMolWithSameStamp = i->second;
90    
91     addMoleculeStamp(molStamp, nMolWithSameStamp);
92 gezelter 1490
93 gezelter 1930 //calculate atoms in molecules
94     nGlobalAtoms_ += molStamp->getNAtoms() *nMolWithSameStamp;
95 gezelter 1490
96    
97 gezelter 1930 //calculate atoms in cutoff groups
98     int nAtomsInGroups = 0;
99     int nCutoffGroupsInStamp = molStamp->getNCutoffGroups();
100    
101     for (int j=0; j < nCutoffGroupsInStamp; j++) {
102     cgStamp = molStamp->getCutoffGroup(j);
103     nAtomsInGroups += cgStamp->getNMembers();
104     }
105 gezelter 1490
106 gezelter 1930 nGroups += nCutoffGroupsInStamp * nMolWithSameStamp;
107     nCutoffAtoms += nAtomsInGroups * nMolWithSameStamp;
108 gezelter 1490
109 gezelter 1930 //calculate atoms in rigid bodies
110     int nAtomsInRigidBodies = 0;
111     int nRigidBodiesInStamp = molStamp->getNCutoffGroups();
112    
113     for (int j=0; j < nRigidBodiesInStamp; j++) {
114     rbStamp = molStamp->getRigidBody(j);
115     nAtomsInRigidBodies += rbStamp->getNMembers();
116     }
117 gezelter 1490
118 gezelter 1930 nGlobalRigidBodies_ += nRigidBodiesInStamp * nMolWithSameStamp;
119     nRigidAtoms += nAtomsInRigidBodies * nMolWithSameStamp;
120    
121     }
122 chrisfen 1636
123 gezelter 1930 //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     nGlobalCutoffGroups_ = nGlobalAtoms_ - nCutoffAtoms + nGroups;
128 gezelter 1490
129 gezelter 1930 //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     //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     nGlobalIntegrableObjects_ = nGlobalAtoms_ - nRigidAtoms + nGlobalRigidBodies_;
134 gezelter 1490
135 gezelter 1930 nGlobalMols_ = molStampIds_.size();
136 gezelter 1490
137 gezelter 1930 #ifdef IS_MPI
138     molToProcMap_.resize(nGlobalMols_);
139     #endif
140    
141     }
142 gezelter 1490
143 gezelter 1930 SimInfo::~SimInfo() {
144     //MemoryUtils::deleteVectorOfPointer(molecules_);
145 gezelter 1490
146 gezelter 1930 MemoryUtils::deleteVectorOfPointer(moleculeStamps_);
147    
148     delete sman_;
149     delete simParams_;
150     delete forceField_;
151 gezelter 1490
152     }
153    
154 gezelter 1930 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 gezelter 1930 bool SimInfo::addMolecule(Molecule* mol) {
166     MoleculeIterator i;
167 gezelter 1490
168 gezelter 1930 i = molecules_.find(mol->getGlobalIndex());
169     if (i == molecules_.end() ) {
170 gezelter 1490
171 gezelter 1930 molecules_.insert(std::make_pair(mol->getGlobalIndex(), mol));
172    
173     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->getNConstraintPairs();
181 gezelter 1490
182 gezelter 1930 addExcludePairs(mol);
183    
184     return true;
185     } else {
186     return false;
187     }
188 gezelter 1490 }
189    
190 gezelter 1930 bool SimInfo::removeMolecule(Molecule* mol) {
191     MoleculeIterator i;
192     i = molecules_.find(mol->getGlobalIndex());
193 gezelter 1490
194 gezelter 1930 if (i != molecules_.end() ) {
195 gezelter 1490
196 gezelter 1930 assert(mol == i->second);
197    
198     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     nConstraints_ -= mol->getNConstraintPairs();
206 gezelter 1490
207 gezelter 1930 removeExcludePairs(mol);
208     molecules_.erase(mol->getGlobalIndex());
209 gezelter 1490
210 gezelter 1930 delete mol;
211    
212     return true;
213     } else {
214     return false;
215     }
216    
217    
218     }
219    
220    
221     Molecule* SimInfo::beginMolecule(MoleculeIterator& i) {
222     i = molecules_.begin();
223     return i == molecules_.end() ? NULL : i->second;
224     }
225    
226     Molecule* SimInfo::nextMolecule(MoleculeIterator& i) {
227     ++i;
228     return i == molecules_.end() ? NULL : i->second;
229 gezelter 1490 }
230    
231    
232 gezelter 1930 void SimInfo::calcNdf() {
233     int ndf_local;
234     MoleculeIterator i;
235     std::vector<StuntDouble*>::iterator j;
236     Molecule* mol;
237     StuntDouble* integrableObject;
238 gezelter 1490
239 gezelter 1930 ndf_local = 0;
240    
241     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 gezelter 1930 ndf_local += 3;
246 gezelter 1490
247 gezelter 1930 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    
258     // n_constraints is local, so subtract them on each processor
259     ndf_local -= nConstraints_;
260    
261     #ifdef IS_MPI
262     MPI_Allreduce(&ndf_local,&ndf_,1,MPI_INT,MPI_SUM, MPI_COMM_WORLD);
263     #else
264     ndf_ = ndf_local;
265     #endif
266    
267     // nZconstraints_ is global, as are the 3 COM translations for the
268     // entire system:
269     ndf_ = ndf_ - 3 - nZconstraint_;
270    
271 gezelter 1490 }
272    
273 gezelter 1930 void SimInfo::calcNdfRaw() {
274     int ndfRaw_local;
275 gezelter 1490
276 gezelter 1930 MoleculeIterator i;
277     std::vector<StuntDouble*>::iterator j;
278     Molecule* mol;
279     StuntDouble* integrableObject;
280    
281     // Raw degrees of freedom that we have to set
282     ndfRaw_local = 0;
283    
284     for (mol = beginMolecule(i); mol != NULL; mol = nextMolecule(i)) {
285     for (integrableObject = mol->beginIntegrableObject(j); integrableObject != NULL;
286     integrableObject = mol->nextIntegrableObject(j)) {
287    
288     ndfRaw_local += 3;
289    
290     if (integrableObject->isDirectional()) {
291     if (integrableObject->isLinear()) {
292     ndfRaw_local += 2;
293     } else {
294     ndfRaw_local += 3;
295     }
296     }
297    
298     }
299     }
300    
301     #ifdef IS_MPI
302     MPI_Allreduce(&ndfRaw_local,&ndfRaw_,1,MPI_INT,MPI_SUM, MPI_COMM_WORLD);
303     #else
304     ndfRaw_ = ndfRaw_local;
305     #endif
306 gezelter 1490 }
307    
308 gezelter 1930 void SimInfo::calcNdfTrans() {
309     int ndfTrans_local;
310 gezelter 1490
311 gezelter 1930 ndfTrans_local = 3 * nIntegrableObjects_ - nConstraints_;
312 gezelter 1490
313    
314 gezelter 1930 #ifdef IS_MPI
315     MPI_Allreduce(&ndfTrans_local,&ndfTrans_,1,MPI_INT,MPI_SUM, MPI_COMM_WORLD);
316     #else
317     ndfTrans_ = ndfTrans_local;
318     #endif
319 gezelter 1490
320 gezelter 1930 ndfTrans_ = ndfTrans_ - 3 - nZconstraint_;
321    
322 gezelter 1490 }
323    
324 gezelter 1930 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 gezelter 1930 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 gezelter 1490
347 gezelter 1930 exclude_.addPair(a, b);
348     exclude_.addPair(a, c);
349     exclude_.addPair(b, c);
350     }
351 gezelter 1490
352 gezelter 1930 for (torsion= mol->beginTorsion(torsionIter); torsion != NULL; torsion = mol->nextTorsion(torsionIter)) {
353     a = torsion->getAtomA()->getGlobalIndex();
354     b = torsion->getAtomB()->getGlobalIndex();
355     c = torsion->getAtomC()->getGlobalIndex();
356     d = torsion->getAtomD()->getGlobalIndex();
357 gezelter 1490
358 gezelter 1930 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 gezelter 1490 }
365    
366    
367 gezelter 1930 }
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 gezelter 1490 }
386 gezelter 1930
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 gezelter 1490 }
396 gezelter 1930
397     for (torsion= mol->beginTorsion(torsionIter); torsion != NULL; torsion = mol->nextTorsion(torsionIter)) {
398     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 gezelter 1490 }
412    
413    
414 gezelter 1930 void SimInfo::addMoleculeStamp(MoleculeStamp* molStamp, int nmol) {
415     int curStampId;
416 gezelter 1490
417 gezelter 1930 //index from 0
418     curStampId = moleculeStamps_.size();
419 gezelter 1490
420 gezelter 1930 moleculeStamps_.push_back(molStamp);
421     molStampIds_.insert(molStampIds_.end(), nmol, curStampId);
422     }
423 gezelter 1490
424 gezelter 1930 void SimInfo::update() {
425 gezelter 1490
426 gezelter 1930 setupSimType();
427 gezelter 1490
428 gezelter 1930 #ifdef IS_MPI
429     setupFortranParallel();
430     #endif
431 gezelter 1490
432 gezelter 1930 setupFortranSim();
433 gezelter 1490
434 gezelter 1930 //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 gezelter 1490
445 gezelter 1930
446     setupCutoff();
447 gezelter 1490
448 gezelter 1930 calcNdf();
449     calcNdfRaw();
450     calcNdfTrans();
451    
452     fortranInitialized_ = true;
453 gezelter 1490 }
454    
455 gezelter 1930 std::set<AtomType*> SimInfo::getUniqueAtomTypes() {
456     SimInfo::MoleculeIterator mi;
457     Molecule* mol;
458     Molecule::AtomIterator ai;
459     Atom* atom;
460     std::set<AtomType*> atomTypes;
461 gezelter 1490
462 gezelter 1930 for(mol = beginMolecule(mi); mol != NULL; mol = nextMolecule(mi)) {
463 gezelter 1490
464 gezelter 1930 for(atom = mol->beginAtom(ai); atom != NULL; atom = mol->nextAtom(ai)) {
465     atomTypes.insert(atom->getAtomType());
466     }
467    
468     }
469 gezelter 1490
470 gezelter 1930 return atomTypes;
471     }
472 gezelter 1490
473 gezelter 1930 void SimInfo::setupSimType() {
474     std::set<AtomType*>::iterator i;
475     std::set<AtomType*> atomTypes;
476     atomTypes = getUniqueAtomTypes();
477 gezelter 1490
478 gezelter 1930 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     //usePBC and useRF are from simParams
491     int usePBC = simParams_->getPBC();
492     int useRF = simParams_->getUseRF();
493 gezelter 1490
494 gezelter 1930 //loop over all of the atom types
495     for (i = atomTypes.begin(); i != atomTypes.end(); ++i) {
496     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     }
506 gezelter 1490
507 gezelter 1930 if (useSticky || useDipole || useGayBerne || useShape) {
508     useDirectionalAtom = 1;
509     }
510 gezelter 1490
511 gezelter 1930 if (useCharge || useDipole) {
512     useElectrostatics = 1;
513     }
514 gezelter 1490
515 gezelter 1930 #ifdef IS_MPI
516     int temp;
517 gezelter 1490
518 gezelter 1930 temp = usePBC;
519     MPI_Allreduce(&temp, &usePBC, 1, MPI_INT, MPI_LOR, MPI_COMM_WORLD);
520 gezelter 1490
521 gezelter 1930 temp = useDirectionalAtom;
522     MPI_Allreduce(&temp, &useDirectionalAtom, 1, MPI_INT, MPI_LOR, MPI_COMM_WORLD);
523 gezelter 1490
524 gezelter 1930 temp = useLennardJones;
525     MPI_Allreduce(&temp, &useLennardJones, 1, MPI_INT, MPI_LOR, MPI_COMM_WORLD);
526 gezelter 1490
527 gezelter 1930 temp = useElectrostatics;
528     MPI_Allreduce(&temp, &useElectrostatics, 1, MPI_INT, MPI_LOR, MPI_COMM_WORLD);
529 gezelter 1490
530 gezelter 1930 temp = useCharge;
531     MPI_Allreduce(&temp, &useCharge, 1, MPI_INT, MPI_LOR, MPI_COMM_WORLD);
532 gezelter 1490
533 gezelter 1930 temp = useDipole;
534     MPI_Allreduce(&temp, &useDipole, 1, MPI_INT, MPI_LOR, MPI_COMM_WORLD);
535 gezelter 1490
536 gezelter 1930 temp = useSticky;
537     MPI_Allreduce(&temp, &useSticky, 1, MPI_INT, MPI_LOR, MPI_COMM_WORLD);
538 gezelter 1490
539 gezelter 1930 temp = useGayBerne;
540     MPI_Allreduce(&temp, &useGayBerne, 1, MPI_INT, MPI_LOR, MPI_COMM_WORLD);
541 gezelter 1490
542 gezelter 1930 temp = useEAM;
543     MPI_Allreduce(&temp, &useEAM, 1, MPI_INT, MPI_LOR, MPI_COMM_WORLD);
544 gezelter 1490
545 gezelter 1930 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 gezelter 1490 #endif
555    
556 gezelter 1930 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 gezelter 1490
569 gezelter 1930 if( fInfo_.SIM_uses_Dipoles && fInfo_.SIM_uses_RF) {
570 gezelter 1490
571 gezelter 1930 if (simParams_->haveDielectric()) {
572     fInfo_.dielect = simParams_->getDielectric();
573     } 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     } else {
583     fInfo_.dielect = 0.0;
584     }
585    
586 gezelter 1490 }
587    
588 gezelter 1930 void SimInfo::setupFortranSim() {
589     int isError;
590     int nExclude;
591     std::vector<int> fortranGlobalGroupMembership;
592    
593     nExclude = exclude_.getSize();
594     isError = 0;
595 gezelter 1490
596 gezelter 1930 //globalGroupMembership_ is filled by SimCreator
597     for (int i = 0; i < nGlobalAtoms_; i++) {
598     fortranGlobalGroupMembership.push_back(globalGroupMembership_[i] + 1);
599     }
600 gezelter 1490
601 gezelter 1930 //calculate mass ratio of cutoff group
602     std::vector<double> mfact;
603     SimInfo::MoleculeIterator mi;
604     Molecule* mol;
605     Molecule::CutoffGroupIterator ci;
606     CutoffGroup* cg;
607     Molecule::AtomIterator ai;
608     Atom* atom;
609     double totalMass;
610    
611     //to avoid memory reallocation, reserve enough space for mfact
612     mfact.reserve(getNCutoffGroups());
613 gezelter 1490
614 gezelter 1930 for(mol = beginMolecule(mi); mol != NULL; mol = nextMolecule(mi)) {
615     for (cg = mol->beginCutoffGroup(ci); cg != NULL; cg = mol->nextCutoffGroup(ci)) {
616 gezelter 1490
617 gezelter 1930 totalMass = cg->getMass();
618     for(atom = cg->beginAtom(ai); atom != NULL; atom = cg->nextAtom(ai)) {
619     mfact.push_back(atom->getMass()/totalMass);
620     }
621 gezelter 1490
622 gezelter 1930 }
623     }
624 gezelter 1490
625 gezelter 1930 //fill ident array of local atoms (it is actually ident of AtomType, it is so confusing !!!)
626     std::vector<int> identArray;
627 gezelter 1490
628 gezelter 1930 //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 gezelter 1490
637 gezelter 1930 //fill molMembershipArray
638     //molMembershipArray is filled by SimCreator
639     std::vector<int> molMembershipArray(nGlobalAtoms_);
640     for (int i = 0; i < nGlobalAtoms_; i++) {
641     molMembershipArray[i] = globalMolMembership_[i] + 1;
642     }
643    
644     //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     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     &mfact[0], &nCutoffGroups_, &fortranGlobalGroupMembership[0], &isError);
654 gezelter 1490
655 gezelter 1930 if( isError ){
656 gezelter 1490
657 gezelter 1930 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 gezelter 1490 }
670    
671    
672 gezelter 1930 #ifdef IS_MPI
673     void SimInfo::setupFortranParallel() {
674    
675     //SimInfo is responsible for creating localToGlobalAtomIndex and localToGlobalGroupIndex
676     std::vector<int> localToGlobalAtomIndex(getNAtoms(), 0);
677     std::vector<int> localToGlobalCutoffGroupIndex;
678     SimInfo::MoleculeIterator mi;
679     Molecule::AtomIterator ai;
680     Molecule::CutoffGroupIterator ci;
681     Molecule* mol;
682     Atom* atom;
683     CutoffGroup* cg;
684     mpiSimData parallelData;
685     int isError;
686 gezelter 1490
687 gezelter 1930 for (mol = beginMolecule(mi); mol != NULL; mol = nextMolecule(mi)) {
688 gezelter 1490
689 gezelter 1930 //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 gezelter 1490
694 gezelter 1930 //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 gezelter 1490
701 gezelter 1930 //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     parallelData.myNode = worldRank;
709     MPI_Comm_size(MPI_COMM_WORLD, &(parallelData.nProcessors));
710 gezelter 1490
711 gezelter 1930 //pass mpiSimData struct and index arrays to fortran
712     setFsimParallel(&parallelData, &(parallelData.nAtomsLocal),
713     &localToGlobalAtomIndex[0], &(parallelData.nGroupsLocal),
714     &localToGlobalCutoffGroupIndex[0], &isError);
715 gezelter 1490
716 gezelter 1930 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 gezelter 1490
723 gezelter 1930 sprintf(checkPointMsg, " mpiRefresh successful.\n");
724     MPIcheckPoint();
725 gezelter 1490
726    
727 gezelter 1930 }
728 chrisfen 1636
729 gezelter 1930 #endif
730 chrisfen 1636
731 gezelter 1930 double SimInfo::calcMaxCutoffRadius() {
732 chrisfen 1636
733    
734 gezelter 1930 std::set<AtomType*> atomTypes;
735     std::set<AtomType*>::iterator i;
736     std::vector<double> cutoffRadius;
737 gezelter 1490
738 gezelter 1930 //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     double maxCutoffRadius = *(std::max_element(cutoffRadius.begin(), cutoffRadius.end()));
747 gezelter 1490 #ifdef IS_MPI
748 gezelter 1930 //pick the max cutoff radius among the processors
749 gezelter 1490 #endif
750    
751 gezelter 1930 return maxCutoffRadius;
752     }
753    
754     void SimInfo::setupCutoff() {
755     double rcut_; //cutoff radius
756     double rsw_; //switching radius
757 gezelter 1490
758 gezelter 1930 if (fInfo_.SIM_uses_Charges | fInfo_.SIM_uses_Dipoles | fInfo_.SIM_uses_RF) {
759    
760     if (!simParams_->haveRcut()){
761     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     rcut_ = simParams_->getRcut();
770     }
771    
772     if (!simParams_->haveRsw()){
773     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     rsw_ = simParams_->getRsw();
782     }
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     if (simParams_->haveRcut()) {
789     rcut_ = simParams_->getRcut();
790     } else {
791     //set cutoff radius to the maximum cutoff radius based on atom types in the whole system
792     rcut_ = calcMaxCutoffRadius();
793     }
794    
795     if (simParams_->haveRsw()) {
796     rsw_ = simParams_->getRsw();
797     } 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 gezelter 1490 }
808    
809 gezelter 1930 void SimInfo::addProperty(GenericData* genData) {
810     properties_.addProperty(genData);
811 gezelter 1490 }
812    
813 gezelter 1930 void SimInfo::removeProperty(const std::string& propName) {
814     properties_.removeProperty(propName);
815     }
816 gezelter 1490
817 gezelter 1930 void SimInfo::clearProperties() {
818     properties_.clearProperties();
819 gezelter 1490 }
820    
821 gezelter 1930 std::vector<std::string> SimInfo::getPropertyNames() {
822     return properties_.getPropertyNames();
823     }
824    
825     std::vector<GenericData*> SimInfo::getProperties() {
826     return properties_.getProperties();
827     }
828 gezelter 1490
829 gezelter 1930 GenericData* SimInfo::getPropertyByName(const std::string& propName) {
830     return properties_.getPropertyByName(propName);
831 gezelter 1490 }
832    
833 gezelter 1930 void SimInfo::setSnapshotManager(SnapshotManager* sman) {
834     sman_ = sman;
835 gezelter 1490
836 gezelter 1930 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 gezelter 1490
854 gezelter 1930 }
855 gezelter 1490
856 gezelter 1930 Vector3d SimInfo::getComVel(){
857     SimInfo::MoleculeIterator i;
858     Molecule* mol;
859 gezelter 1490
860 gezelter 1930 Vector3d comVel(0.0);
861     double totalMass = 0.0;
862 gezelter 1490
863 gezelter 1930
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 gezelter 1490
870 gezelter 1930 #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     comVel /= totalMass;
878    
879     return comVel;
880 gezelter 1490 }
881    
882 gezelter 1930 Vector3d SimInfo::getCom(){
883     SimInfo::MoleculeIterator i;
884     Molecule* mol;
885 gezelter 1490
886 gezelter 1930 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 gezelter 1490
895     #ifdef IS_MPI
896 gezelter 1930 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 gezelter 1490 #endif
901    
902 gezelter 1930 com /= totalMass;
903 gezelter 1490
904 gezelter 1930 return com;
905 gezelter 1490
906 gezelter 1930 }
907    
908     std::ostream& operator <<(std::ostream& o, SimInfo& info) {
909    
910     return o;
911 gezelter 1490 }
912 gezelter 1930
913     }//end namespace oopse
914