ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/group/branches/new_design/OOPSE-3.0/src/brains/SimInfo.cpp
Revision: 1907
Committed: Thu Jan 6 22:31:07 2005 UTC (19 years, 8 months ago) by tim
File size: 27417 byte(s)
Log Message:
constraint is almost working

File Contents

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