ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/group/trunk/OOPSE-2.0/src/brains/SimInfo.cpp
Revision: 1976
Committed: Fri Feb 4 22:44:15 2005 UTC (19 years, 5 months ago) by tim
File size: 28487 byte(s)
Log Message:
adding SelectionManager into SimInfo

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