ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/group/trunk/OOPSE-2.0/src/brains/SimInfo.cpp
(Generate patch)

Comparing trunk/OOPSE-2.0/src/brains/SimInfo.cpp (file contents):
Revision 1617 by chuckv, Wed Oct 20 20:46:20 2004 UTC vs.
Revision 2220 by chrisfen, Thu May 5 14:47:35 2005 UTC

# Line 1 | Line 1
1 < #include <stdlib.h>
2 < #include <string.h>
3 < #include <math.h>
1 > /*
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  
49 < #include <iostream>
50 < using namespace std;
49 > #include <algorithm>
50 > #include <set>
51  
52   #include "brains/SimInfo.hpp"
53 < #define __C
54 < #include "brains/fSimulation.h"
55 < #include "utils/simError.h"
12 < #include "UseTheForce/DarkSide/simulation_interface.h"
53 > #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 + #include "utils/simError.h"
59 + #include "selection/SelectionManager.hpp"
60  
15 //#include "UseTheForce/fortranWrappers.hpp"
16
17 #include "math/MatVec3.h"
18
61   #ifdef IS_MPI
62 < #include "brains/mpiSimulation.hpp"
63 < #endif
62 > #include "UseTheForce/mpiComponentPlan.h"
63 > #include "UseTheForce/DarkSide/simParallel_interface.h"
64 > #endif
65  
66 < inline double roundMe( double x ){
24 <  return ( x >= 0 ) ? floor( x + 0.5 ) : ceil( x - 0.5 );
25 < }
26 <          
27 < inline double min( double a, double b ){
28 <  return (a < b ) ? a : b;
29 < }
66 > namespace oopse {
67  
68 < SimInfo* currentInfo;
68 >  SimInfo::SimInfo(MakeStamps* stamps, std::vector<std::pair<MoleculeStamp*, int> >& molStampPairs,
69 >                   ForceField* ff, Globals* simParams) :
70 >    stamps_(stamps), forceField_(ff), simParams_(simParams),
71 >    ndf_(0), ndfRaw_(0), ndfTrans_(0), nZconstraint_(0),
72 >    nGlobalMols_(0), nGlobalAtoms_(0), nGlobalCutoffGroups_(0),
73 >    nGlobalIntegrableObjects_(0), nGlobalRigidBodies_(0),
74 >    nAtoms_(0), nBonds_(0),  nBends_(0), nTorsions_(0), nRigidBodies_(0),
75 >    nIntegrableObjects_(0),  nCutoffGroups_(0), nConstraints_(0),
76 >    sman_(NULL), fortranInitialized_(false) {
77  
78 < SimInfo::SimInfo(){
78 >            
79 >      std::vector<std::pair<MoleculeStamp*, int> >::iterator i;
80 >      MoleculeStamp* molStamp;
81 >      int nMolWithSameStamp;
82 >      int nCutoffAtoms = 0; // number of atoms belong to cutoff groups
83 >      int nGroups = 0;          //total cutoff groups defined in meta-data file
84 >      CutoffGroupStamp* cgStamp;    
85 >      RigidBodyStamp* rbStamp;
86 >      int nRigidAtoms = 0;
87 >    
88 >      for (i = molStampPairs.begin(); i !=molStampPairs.end(); ++i) {
89 >        molStamp = i->first;
90 >        nMolWithSameStamp = i->second;
91 >        
92 >        addMoleculeStamp(molStamp, nMolWithSameStamp);
93  
94 <  n_constraints = 0;
95 <  nZconstraints = 0;
37 <  n_oriented = 0;
38 <  n_dipoles = 0;
39 <  ndf = 0;
40 <  ndfRaw = 0;
41 <  nZconstraints = 0;
42 <  the_integrator = NULL;
43 <  setTemp = 0;
44 <  thermalTime = 0.0;
45 <  currentTime = 0.0;
46 <  rCut = 0.0;
47 <  rSw = 0.0;
94 >        //calculate atoms in molecules
95 >        nGlobalAtoms_ += molStamp->getNAtoms() *nMolWithSameStamp;  
96  
49  haveRcut = 0;
50  haveRsw = 0;
51  boxIsInit = 0;
52  
53  resetTime = 1e99;
97  
98 <  orthoRhombic = 0;
99 <  orthoTolerance = 1E-6;
100 <  useInitXSstate = true;
98 >        //calculate atoms in cutoff groups
99 >        int nAtomsInGroups = 0;
100 >        int nCutoffGroupsInStamp = molStamp->getNCutoffGroups();
101 >        
102 >        for (int j=0; j < nCutoffGroupsInStamp; j++) {
103 >          cgStamp = molStamp->getCutoffGroup(j);
104 >          nAtomsInGroups += cgStamp->getNMembers();
105 >        }
106  
107 <  usePBC = 0;
108 <  useLJ = 0;
61 <  useSticky = 0;
62 <  useCharges = 0;
63 <  useDipoles = 0;
64 <  useReactionField = 0;
65 <  useGB = 0;
66 <  useEAM = 0;
67 <  useSolidThermInt = 0;
68 <  useLiquidThermInt = 0;
107 >        nGroups += nCutoffGroupsInStamp * nMolWithSameStamp;
108 >        nCutoffAtoms += nAtomsInGroups * nMolWithSameStamp;            
109  
110 <  haveCutoffGroups = false;
110 >        //calculate atoms in rigid bodies
111 >        int nAtomsInRigidBodies = 0;
112 >        int nRigidBodiesInStamp = molStamp->getNRigidBodies();
113 >        
114 >        for (int j=0; j < nRigidBodiesInStamp; j++) {
115 >          rbStamp = molStamp->getRigidBody(j);
116 >          nAtomsInRigidBodies += rbStamp->getNMembers();
117 >        }
118  
119 <  excludes = Exclude::Instance();
119 >        nGlobalRigidBodies_ += nRigidBodiesInStamp * nMolWithSameStamp;
120 >        nRigidAtoms += nAtomsInRigidBodies * nMolWithSameStamp;            
121 >        
122 >      }
123  
124 <  myConfiguration = new SimState();
124 >      //every free atom (atom does not belong to cutoff groups) is a cutoff group
125 >      //therefore the total number of cutoff groups in the system is equal to
126 >      //the total number of atoms minus number of atoms belong to cutoff group defined in meta-data
127 >      //file plus the number of cutoff groups defined in meta-data file
128 >      nGlobalCutoffGroups_ = nGlobalAtoms_ - nCutoffAtoms + nGroups;
129  
130 <  has_minimizer = false;
131 <  the_minimizer =NULL;
130 >      //every free atom (atom does not belong to rigid bodies) is an integrable object
131 >      //therefore the total number of  integrable objects in the system is equal to
132 >      //the total number of atoms minus number of atoms belong to  rigid body defined in meta-data
133 >      //file plus the number of  rigid bodies defined in meta-data file
134 >      nGlobalIntegrableObjects_ = nGlobalAtoms_ - nRigidAtoms + nGlobalRigidBodies_;
135  
136 <  ngroup = 0;
136 >      nGlobalMols_ = molStampIds_.size();
137  
138 < }
138 > #ifdef IS_MPI    
139 >      molToProcMap_.resize(nGlobalMols_);
140 > #endif
141  
142 +    }
143  
144 < SimInfo::~SimInfo(){
144 >  SimInfo::~SimInfo() {
145 >    std::map<int, Molecule*>::iterator i;
146 >    for (i = molecules_.begin(); i != molecules_.end(); ++i) {
147 >      delete i->second;
148 >    }
149 >    molecules_.clear();
150 >      
151 >    delete stamps_;
152 >    delete sman_;
153 >    delete simParams_;
154 >    delete forceField_;
155 >  }
156  
157 <  delete myConfiguration;
157 >  int SimInfo::getNGlobalConstraints() {
158 >    int nGlobalConstraints;
159 > #ifdef IS_MPI
160 >    MPI_Allreduce(&nConstraints_, &nGlobalConstraints, 1, MPI_INT, MPI_SUM,
161 >                  MPI_COMM_WORLD);    
162 > #else
163 >    nGlobalConstraints =  nConstraints_;
164 > #endif
165 >    return nGlobalConstraints;
166 >  }
167  
168 <  map<string, GenericData*>::iterator i;
169 <  
90 <  for(i = properties.begin(); i != properties.end(); i++)
91 <    delete (*i).second;
168 >  bool SimInfo::addMolecule(Molecule* mol) {
169 >    MoleculeIterator i;
170  
171 < }
171 >    i = molecules_.find(mol->getGlobalIndex());
172 >    if (i == molecules_.end() ) {
173  
174 < void SimInfo::setBox(double newBox[3]) {
175 <  
176 <  int i, j;
177 <  double tempMat[3][3];
174 >      molecules_.insert(std::make_pair(mol->getGlobalIndex(), mol));
175 >        
176 >      nAtoms_ += mol->getNAtoms();
177 >      nBonds_ += mol->getNBonds();
178 >      nBends_ += mol->getNBends();
179 >      nTorsions_ += mol->getNTorsions();
180 >      nRigidBodies_ += mol->getNRigidBodies();
181 >      nIntegrableObjects_ += mol->getNIntegrableObjects();
182 >      nCutoffGroups_ += mol->getNCutoffGroups();
183 >      nConstraints_ += mol->getNConstraintPairs();
184  
185 <  for(i=0; i<3; i++)
186 <    for (j=0; j<3; j++) tempMat[i][j] = 0.0;;
185 >      addExcludePairs(mol);
186 >        
187 >      return true;
188 >    } else {
189 >      return false;
190 >    }
191 >  }
192  
193 <  tempMat[0][0] = newBox[0];
194 <  tempMat[1][1] = newBox[1];
195 <  tempMat[2][2] = newBox[2];
193 >  bool SimInfo::removeMolecule(Molecule* mol) {
194 >    MoleculeIterator i;
195 >    i = molecules_.find(mol->getGlobalIndex());
196  
197 <  setBoxM( tempMat );
197 >    if (i != molecules_.end() ) {
198  
199 < }
199 >      assert(mol == i->second);
200 >        
201 >      nAtoms_ -= mol->getNAtoms();
202 >      nBonds_ -= mol->getNBonds();
203 >      nBends_ -= mol->getNBends();
204 >      nTorsions_ -= mol->getNTorsions();
205 >      nRigidBodies_ -= mol->getNRigidBodies();
206 >      nIntegrableObjects_ -= mol->getNIntegrableObjects();
207 >      nCutoffGroups_ -= mol->getNCutoffGroups();
208 >      nConstraints_ -= mol->getNConstraintPairs();
209  
210 < void SimInfo::setBoxM( double theBox[3][3] ){
211 <  
113 <  int i, j;
114 <  double FortranHmat[9]; // to preserve compatibility with Fortran the
115 <                         // ordering in the array is as follows:
116 <                         // [ 0 3 6 ]
117 <                         // [ 1 4 7 ]
118 <                         // [ 2 5 8 ]
119 <  double FortranHmatInv[9]; // the inverted Hmat (for Fortran);
210 >      removeExcludePairs(mol);
211 >      molecules_.erase(mol->getGlobalIndex());
212  
213 <  if( !boxIsInit ) boxIsInit = 1;
214 <
215 <  for(i=0; i < 3; i++)
216 <    for (j=0; j < 3; j++) Hmat[i][j] = theBox[i][j];
217 <  
126 <  calcBoxL();
127 <  calcHmatInv();
128 <
129 <  for(i=0; i < 3; i++) {
130 <    for (j=0; j < 3; j++) {
131 <      FortranHmat[3*j + i] = Hmat[i][j];
132 <      FortranHmatInv[3*j + i] = HmatInv[i][j];
213 >      delete mol;
214 >        
215 >      return true;
216 >    } else {
217 >      return false;
218      }
134  }
219  
136  setFortranBox(FortranHmat, FortranHmatInv, &orthoRhombic);
137
138 }
139
220  
221 < void SimInfo::getBoxM (double theBox[3][3]) {
221 >  }    
222  
223 <  int i, j;
224 <  for(i=0; i<3; i++)
225 <    for (j=0; j<3; j++) theBox[i][j] = Hmat[i][j];
226 < }
223 >        
224 >  Molecule* SimInfo::beginMolecule(MoleculeIterator& i) {
225 >    i = molecules_.begin();
226 >    return i == molecules_.end() ? NULL : i->second;
227 >  }    
228  
229 +  Molecule* SimInfo::nextMolecule(MoleculeIterator& i) {
230 +    ++i;
231 +    return i == molecules_.end() ? NULL : i->second;    
232 +  }
233  
149 void SimInfo::scaleBox(double scale) {
150  double theBox[3][3];
151  int i, j;
234  
235 <  // cerr << "Scaling box by " << scale << "\n";
235 >  void SimInfo::calcNdf() {
236 >    int ndf_local;
237 >    MoleculeIterator i;
238 >    std::vector<StuntDouble*>::iterator j;
239 >    Molecule* mol;
240 >    StuntDouble* integrableObject;
241  
242 <  for(i=0; i<3; i++)
243 <    for (j=0; j<3; j++) theBox[i][j] = Hmat[i][j]*scale;
242 >    ndf_local = 0;
243 >    
244 >    for (mol = beginMolecule(i); mol != NULL; mol = nextMolecule(i)) {
245 >      for (integrableObject = mol->beginIntegrableObject(j); integrableObject != NULL;
246 >           integrableObject = mol->nextIntegrableObject(j)) {
247  
248 <  setBoxM(theBox);
248 >        ndf_local += 3;
249  
250 < }
250 >        if (integrableObject->isDirectional()) {
251 >          if (integrableObject->isLinear()) {
252 >            ndf_local += 2;
253 >          } else {
254 >            ndf_local += 3;
255 >          }
256 >        }
257 >            
258 >      }//end for (integrableObject)
259 >    }// end for (mol)
260 >    
261 >    // n_constraints is local, so subtract them on each processor
262 >    ndf_local -= nConstraints_;
263  
264 < void SimInfo::calcHmatInv( void ) {
265 <  
266 <  int oldOrtho;
267 <  int i,j;
268 <  double smallDiag;
167 <  double tol;
168 <  double sanity[3][3];
264 > #ifdef IS_MPI
265 >    MPI_Allreduce(&ndf_local,&ndf_,1,MPI_INT,MPI_SUM, MPI_COMM_WORLD);
266 > #else
267 >    ndf_ = ndf_local;
268 > #endif
269  
270 <  invertMat3( Hmat, HmatInv );
270 >    // nZconstraints_ is global, as are the 3 COM translations for the
271 >    // entire system:
272 >    ndf_ = ndf_ - 3 - nZconstraint_;
273  
274 <  // check to see if Hmat is orthorhombic
173 <  
174 <  oldOrtho = orthoRhombic;
274 >  }
275  
276 <  smallDiag = fabs(Hmat[0][0]);
277 <  if(smallDiag > fabs(Hmat[1][1])) smallDiag = fabs(Hmat[1][1]);
178 <  if(smallDiag > fabs(Hmat[2][2])) smallDiag = fabs(Hmat[2][2]);
179 <  tol = smallDiag * orthoTolerance;
276 >  void SimInfo::calcNdfRaw() {
277 >    int ndfRaw_local;
278  
279 <  orthoRhombic = 1;
280 <  
281 <  for (i = 0; i < 3; i++ ) {
282 <    for (j = 0 ; j < 3; j++) {
283 <      if (i != j) {
284 <        if (orthoRhombic) {
285 <          if ( fabs(Hmat[i][j]) >= tol) orthoRhombic = 0;
286 <        }        
279 >    MoleculeIterator i;
280 >    std::vector<StuntDouble*>::iterator j;
281 >    Molecule* mol;
282 >    StuntDouble* integrableObject;
283 >
284 >    // Raw degrees of freedom that we have to set
285 >    ndfRaw_local = 0;
286 >    
287 >    for (mol = beginMolecule(i); mol != NULL; mol = nextMolecule(i)) {
288 >      for (integrableObject = mol->beginIntegrableObject(j); integrableObject != NULL;
289 >           integrableObject = mol->nextIntegrableObject(j)) {
290 >
291 >        ndfRaw_local += 3;
292 >
293 >        if (integrableObject->isDirectional()) {
294 >          if (integrableObject->isLinear()) {
295 >            ndfRaw_local += 2;
296 >          } else {
297 >            ndfRaw_local += 3;
298 >          }
299 >        }
300 >            
301        }
302      }
303 +    
304 + #ifdef IS_MPI
305 +    MPI_Allreduce(&ndfRaw_local,&ndfRaw_,1,MPI_INT,MPI_SUM, MPI_COMM_WORLD);
306 + #else
307 +    ndfRaw_ = ndfRaw_local;
308 + #endif
309    }
310  
311 <  if( oldOrtho != orthoRhombic ){
311 >  void SimInfo::calcNdfTrans() {
312 >    int ndfTrans_local;
313 >
314 >    ndfTrans_local = 3 * nIntegrableObjects_ - nConstraints_;
315 >
316 >
317 > #ifdef IS_MPI
318 >    MPI_Allreduce(&ndfTrans_local,&ndfTrans_,1,MPI_INT,MPI_SUM, MPI_COMM_WORLD);
319 > #else
320 >    ndfTrans_ = ndfTrans_local;
321 > #endif
322 >
323 >    ndfTrans_ = ndfTrans_ - 3 - nZconstraint_;
324 >
325 >  }
326 >
327 >  void SimInfo::addExcludePairs(Molecule* mol) {
328 >    std::vector<Bond*>::iterator bondIter;
329 >    std::vector<Bend*>::iterator bendIter;
330 >    std::vector<Torsion*>::iterator torsionIter;
331 >    Bond* bond;
332 >    Bend* bend;
333 >    Torsion* torsion;
334 >    int a;
335 >    int b;
336 >    int c;
337 >    int d;
338      
339 <    if( orthoRhombic ) {
340 <      sprintf( painCave.errMsg,
341 <               "OOPSE is switching from the default Non-Orthorhombic\n"
342 <               "\tto the faster Orthorhombic periodic boundary computations.\n"
199 <               "\tThis is usually a good thing, but if you wan't the\n"
200 <               "\tNon-Orthorhombic computations, make the orthoBoxTolerance\n"
201 <               "\tvariable ( currently set to %G ) smaller.\n",
202 <               orthoTolerance);
203 <      painCave.severity = OOPSE_INFO;
204 <      simError();
339 >    for (bond= mol->beginBond(bondIter); bond != NULL; bond = mol->nextBond(bondIter)) {
340 >      a = bond->getAtomA()->getGlobalIndex();
341 >      b = bond->getAtomB()->getGlobalIndex();        
342 >      exclude_.addPair(a, b);
343      }
206    else {
207      sprintf( painCave.errMsg,
208               "OOPSE is switching from the faster Orthorhombic to the more\n"
209               "\tflexible Non-Orthorhombic periodic boundary computations.\n"
210               "\tThis is usually because the box has deformed under\n"
211               "\tNPTf integration. If you wan't to live on the edge with\n"
212               "\tthe Orthorhombic computations, make the orthoBoxTolerance\n"
213               "\tvariable ( currently set to %G ) larger.\n",
214               orthoTolerance);
215      painCave.severity = OOPSE_WARNING;
216      simError();
217    }
218  }
219 }
344  
345 < void SimInfo::calcBoxL( void ){
345 >    for (bend= mol->beginBend(bendIter); bend != NULL; bend = mol->nextBend(bendIter)) {
346 >      a = bend->getAtomA()->getGlobalIndex();
347 >      b = bend->getAtomB()->getGlobalIndex();        
348 >      c = bend->getAtomC()->getGlobalIndex();
349  
350 <  double dx, dy, dz, dsq;
350 >      exclude_.addPair(a, b);
351 >      exclude_.addPair(a, c);
352 >      exclude_.addPair(b, c);        
353 >    }
354  
355 <  // boxVol = Determinant of Hmat
355 >    for (torsion= mol->beginTorsion(torsionIter); torsion != NULL; torsion = mol->nextTorsion(torsionIter)) {
356 >      a = torsion->getAtomA()->getGlobalIndex();
357 >      b = torsion->getAtomB()->getGlobalIndex();        
358 >      c = torsion->getAtomC()->getGlobalIndex();        
359 >      d = torsion->getAtomD()->getGlobalIndex();        
360  
361 <  boxVol = matDet3( Hmat );
361 >      exclude_.addPair(a, b);
362 >      exclude_.addPair(a, c);
363 >      exclude_.addPair(a, d);
364 >      exclude_.addPair(b, c);
365 >      exclude_.addPair(b, d);
366 >      exclude_.addPair(c, d);        
367 >    }
368  
369 <  // boxLx
370 <  
371 <  dx = Hmat[0][0]; dy = Hmat[1][0]; dz = Hmat[2][0];
372 <  dsq = dx*dx + dy*dy + dz*dz;
373 <  boxL[0] = sqrt( dsq );
374 <  //maxCutoff = 0.5 * boxL[0];
369 >    Molecule::RigidBodyIterator rbIter;
370 >    RigidBody* rb;
371 >    for (rb = mol->beginRigidBody(rbIter); rb != NULL; rb = mol->nextRigidBody(rbIter)) {
372 >      std::vector<Atom*> atoms = rb->getAtoms();
373 >      for (int i = 0; i < atoms.size() -1 ; ++i) {
374 >        for (int j = i + 1; j < atoms.size(); ++j) {
375 >          a = atoms[i]->getGlobalIndex();
376 >          b = atoms[j]->getGlobalIndex();
377 >          exclude_.addPair(a, b);
378 >        }
379 >      }
380 >    }        
381  
382 <  // boxLy
237 <  
238 <  dx = Hmat[0][1]; dy = Hmat[1][1]; dz = Hmat[2][1];
239 <  dsq = dx*dx + dy*dy + dz*dz;
240 <  boxL[1] = sqrt( dsq );
241 <  //if( (0.5 * boxL[1]) < maxCutoff ) maxCutoff = 0.5 * boxL[1];
382 >  }
383  
384 +  void SimInfo::removeExcludePairs(Molecule* mol) {
385 +    std::vector<Bond*>::iterator bondIter;
386 +    std::vector<Bend*>::iterator bendIter;
387 +    std::vector<Torsion*>::iterator torsionIter;
388 +    Bond* bond;
389 +    Bend* bend;
390 +    Torsion* torsion;
391 +    int a;
392 +    int b;
393 +    int c;
394 +    int d;
395 +    
396 +    for (bond= mol->beginBond(bondIter); bond != NULL; bond = mol->nextBond(bondIter)) {
397 +      a = bond->getAtomA()->getGlobalIndex();
398 +      b = bond->getAtomB()->getGlobalIndex();        
399 +      exclude_.removePair(a, b);
400 +    }
401  
402 <  // boxLz
403 <  
404 <  dx = Hmat[0][2]; dy = Hmat[1][2]; dz = Hmat[2][2];
405 <  dsq = dx*dx + dy*dy + dz*dz;
248 <  boxL[2] = sqrt( dsq );
249 <  //if( (0.5 * boxL[2]) < maxCutoff ) maxCutoff = 0.5 * boxL[2];
402 >    for (bend= mol->beginBend(bendIter); bend != NULL; bend = mol->nextBend(bendIter)) {
403 >      a = bend->getAtomA()->getGlobalIndex();
404 >      b = bend->getAtomB()->getGlobalIndex();        
405 >      c = bend->getAtomC()->getGlobalIndex();
406  
407 <  //calculate the max cutoff
408 <  maxCutoff =  calcMaxCutOff();
409 <  
410 <  checkCutOffs();
407 >      exclude_.removePair(a, b);
408 >      exclude_.removePair(a, c);
409 >      exclude_.removePair(b, c);        
410 >    }
411  
412 < }
412 >    for (torsion= mol->beginTorsion(torsionIter); torsion != NULL; torsion = mol->nextTorsion(torsionIter)) {
413 >      a = torsion->getAtomA()->getGlobalIndex();
414 >      b = torsion->getAtomB()->getGlobalIndex();        
415 >      c = torsion->getAtomC()->getGlobalIndex();        
416 >      d = torsion->getAtomD()->getGlobalIndex();        
417  
418 +      exclude_.removePair(a, b);
419 +      exclude_.removePair(a, c);
420 +      exclude_.removePair(a, d);
421 +      exclude_.removePair(b, c);
422 +      exclude_.removePair(b, d);
423 +      exclude_.removePair(c, d);        
424 +    }
425  
426 < double SimInfo::calcMaxCutOff(){
426 >    Molecule::RigidBodyIterator rbIter;
427 >    RigidBody* rb;
428 >    for (rb = mol->beginRigidBody(rbIter); rb != NULL; rb = mol->nextRigidBody(rbIter)) {
429 >      std::vector<Atom*> atoms = rb->getAtoms();
430 >      for (int i = 0; i < atoms.size() -1 ; ++i) {
431 >        for (int j = i + 1; j < atoms.size(); ++j) {
432 >          a = atoms[i]->getGlobalIndex();
433 >          b = atoms[j]->getGlobalIndex();
434 >          exclude_.removePair(a, b);
435 >        }
436 >      }
437 >    }        
438  
439 <  double ri[3], rj[3], rk[3];
262 <  double rij[3], rjk[3], rki[3];
263 <  double minDist;
439 >  }
440  
265  ri[0] = Hmat[0][0];
266  ri[1] = Hmat[1][0];
267  ri[2] = Hmat[2][0];
441  
442 <  rj[0] = Hmat[0][1];
443 <  rj[1] = Hmat[1][1];
271 <  rj[2] = Hmat[2][1];
442 >  void SimInfo::addMoleculeStamp(MoleculeStamp* molStamp, int nmol) {
443 >    int curStampId;
444  
445 <  rk[0] = Hmat[0][2];
446 <  rk[1] = Hmat[1][2];
275 <  rk[2] = Hmat[2][2];
276 <    
277 <  crossProduct3(ri, rj, rij);
278 <  distXY = dotProduct3(rk,rij) / norm3(rij);
445 >    //index from 0
446 >    curStampId = moleculeStamps_.size();
447  
448 <  crossProduct3(rj,rk, rjk);
449 <  distYZ = dotProduct3(ri,rjk) / norm3(rjk);
448 >    moleculeStamps_.push_back(molStamp);
449 >    molStampIds_.insert(molStampIds_.end(), nmol, curStampId);
450 >  }
451  
452 <  crossProduct3(rk,ri, rki);
284 <  distZX = dotProduct3(rj,rki) / norm3(rki);
452 >  void SimInfo::update() {
453  
454 <  minDist = min(min(distXY, distYZ), distZX);
287 <  return minDist/2;
288 <  
289 < }
454 >    setupSimType();
455  
456 < void SimInfo::wrapVector( double thePos[3] ){
456 > #ifdef IS_MPI
457 >    setupFortranParallel();
458 > #endif
459  
460 <  int i;
294 <  double scaled[3];
460 >    setupFortranSim();
461  
462 <  if( !orthoRhombic ){
463 <    // calc the scaled coordinates.
462 >    //setup fortran force field
463 >    /** @deprecate */    
464 >    int isError = 0;
465 >    initFortranFF( &fInfo_.SIM_uses_RF , &isError );
466 >    if(isError){
467 >      sprintf( painCave.errMsg,
468 >               "ForceField error: There was an error initializing the forceField in fortran.\n" );
469 >      painCave.isFatal = 1;
470 >      simError();
471 >    }
472    
299
300    matVecMul3(HmatInv, thePos, scaled);
473      
474 <    for(i=0; i<3; i++)
303 <      scaled[i] -= roundMe(scaled[i]);
304 <    
305 <    // calc the wrapped real coordinates from the wrapped scaled coordinates
306 <    
307 <    matVecMul3(Hmat, scaled, thePos);
474 >    setupCutoff();
475  
476 +    calcNdf();
477 +    calcNdfRaw();
478 +    calcNdfTrans();
479 +
480 +    fortranInitialized_ = true;
481    }
310  else{
311    // calc the scaled coordinates.
312    
313    for(i=0; i<3; i++)
314      scaled[i] = thePos[i]*HmatInv[i][i];
315    
316    // wrap the scaled coordinates
317    
318    for(i=0; i<3; i++)
319      scaled[i] -= roundMe(scaled[i]);
320    
321    // calc the wrapped real coordinates from the wrapped scaled coordinates
322    
323    for(i=0; i<3; i++)
324      thePos[i] = scaled[i]*Hmat[i][i];
325  }
326    
327 }
482  
483 +  std::set<AtomType*> SimInfo::getUniqueAtomTypes() {
484 +    SimInfo::MoleculeIterator mi;
485 +    Molecule* mol;
486 +    Molecule::AtomIterator ai;
487 +    Atom* atom;
488 +    std::set<AtomType*> atomTypes;
489  
490 < int SimInfo::getNDF(){
331 <  int ndf_local;
490 >    for(mol = beginMolecule(mi); mol != NULL; mol = nextMolecule(mi)) {
491  
492 <  ndf_local = 0;
493 <  
494 <  for(int i = 0; i < integrableObjects.size(); i++){
495 <    ndf_local += 3;
337 <    if (integrableObjects[i]->isDirectional()) {
338 <      if (integrableObjects[i]->isLinear())
339 <        ndf_local += 2;
340 <      else
341 <        ndf_local += 3;
492 >      for(atom = mol->beginAtom(ai); atom != NULL; atom = mol->nextAtom(ai)) {
493 >        atomTypes.insert(atom->getAtomType());
494 >      }
495 >        
496      }
497 +
498 +    return atomTypes;        
499    }
500  
501 <  // n_constraints is local, so subtract them on each processor:
502 <
503 <  ndf_local -= n_constraints;
501 >  void SimInfo::setupSimType() {
502 >    std::set<AtomType*>::iterator i;
503 >    std::set<AtomType*> atomTypes;
504 >    atomTypes = getUniqueAtomTypes();
505 >    
506 >    int useLennardJones = 0;
507 >    int useElectrostatic = 0;
508 >    int useEAM = 0;
509 >    int useCharge = 0;
510 >    int useDirectional = 0;
511 >    int useDipole = 0;
512 >    int useGayBerne = 0;
513 >    int useSticky = 0;
514 >    int useStickyPower = 0;
515 >    int useShape = 0;
516 >    int useFLARB = 0; //it is not in AtomType yet
517 >    int useDirectionalAtom = 0;    
518 >    int useElectrostatics = 0;
519 >    //usePBC and useRF are from simParams
520 >    int usePBC = simParams_->getPBC();
521 >    int useRF = simParams_->getUseRF();
522  
523 < #ifdef IS_MPI
524 <  MPI_Allreduce(&ndf_local,&ndf,1,MPI_INT,MPI_SUM, MPI_COMM_WORLD);
525 < #else
526 <  ndf = ndf_local;
527 < #endif
523 >    //loop over all of the atom types
524 >    for (i = atomTypes.begin(); i != atomTypes.end(); ++i) {
525 >      useLennardJones |= (*i)->isLennardJones();
526 >      useElectrostatic |= (*i)->isElectrostatic();
527 >      useEAM |= (*i)->isEAM();
528 >      useCharge |= (*i)->isCharge();
529 >      useDirectional |= (*i)->isDirectional();
530 >      useDipole |= (*i)->isDipole();
531 >      useGayBerne |= (*i)->isGayBerne();
532 >      useSticky |= (*i)->isSticky();
533 >      useStickyPower |= (*i)->isStickyPower();
534 >      useShape |= (*i)->isShape();
535 >    }
536  
537 <  // nZconstraints is global, as are the 3 COM translations for the
538 <  // entire system:
537 >    if (useSticky || useStickyPower || useDipole || useGayBerne || useShape) {
538 >      useDirectionalAtom = 1;
539 >    }
540  
541 <  ndf = ndf - 3 - nZconstraints;
541 >    if (useCharge || useDipole) {
542 >      useElectrostatics = 1;
543 >    }
544  
545 <  return ndf;
546 < }
545 > #ifdef IS_MPI    
546 >    int temp;
547  
548 < int SimInfo::getNDFraw() {
549 <  int ndfRaw_local;
548 >    temp = usePBC;
549 >    MPI_Allreduce(&temp, &usePBC, 1, MPI_INT, MPI_LOR, MPI_COMM_WORLD);    
550  
551 <  // Raw degrees of freedom that we have to set
552 <  ndfRaw_local = 0;
551 >    temp = useDirectionalAtom;
552 >    MPI_Allreduce(&temp, &useDirectionalAtom, 1, MPI_INT, MPI_LOR, MPI_COMM_WORLD);    
553  
554 <  for(int i = 0; i < integrableObjects.size(); i++){
555 <    ndfRaw_local += 3;
371 <    if (integrableObjects[i]->isDirectional()) {
372 <       if (integrableObjects[i]->isLinear())
373 <        ndfRaw_local += 2;
374 <      else
375 <        ndfRaw_local += 3;
376 <    }
377 <  }
378 <    
379 < #ifdef IS_MPI
380 <  MPI_Allreduce(&ndfRaw_local,&ndfRaw,1,MPI_INT,MPI_SUM, MPI_COMM_WORLD);
381 < #else
382 <  ndfRaw = ndfRaw_local;
383 < #endif
554 >    temp = useLennardJones;
555 >    MPI_Allreduce(&temp, &useLennardJones, 1, MPI_INT, MPI_LOR, MPI_COMM_WORLD);    
556  
557 <  return ndfRaw;
558 < }
557 >    temp = useElectrostatics;
558 >    MPI_Allreduce(&temp, &useElectrostatics, 1, MPI_INT, MPI_LOR, MPI_COMM_WORLD);    
559  
560 < int SimInfo::getNDFtranslational() {
561 <  int ndfTrans_local;
560 >    temp = useCharge;
561 >    MPI_Allreduce(&temp, &useCharge, 1, MPI_INT, MPI_LOR, MPI_COMM_WORLD);    
562  
563 <  ndfTrans_local = 3 * integrableObjects.size() - n_constraints;
563 >    temp = useDipole;
564 >    MPI_Allreduce(&temp, &useDipole, 1, MPI_INT, MPI_LOR, MPI_COMM_WORLD);    
565  
566 +    temp = useSticky;
567 +    MPI_Allreduce(&temp, &useSticky, 1, MPI_INT, MPI_LOR, MPI_COMM_WORLD);    
568  
569 < #ifdef IS_MPI
570 <  MPI_Allreduce(&ndfTrans_local,&ndfTrans,1,MPI_INT,MPI_SUM, MPI_COMM_WORLD);
571 < #else
572 <  ndfTrans = ndfTrans_local;
573 < #endif
569 >    temp = useStickyPower;
570 >    MPI_Allreduce(&temp, &useStickyPower, 1, MPI_INT, MPI_LOR, MPI_COMM_WORLD);    
571 >    
572 >    temp = useGayBerne;
573 >    MPI_Allreduce(&temp, &useGayBerne, 1, MPI_INT, MPI_LOR, MPI_COMM_WORLD);    
574  
575 <  ndfTrans = ndfTrans - 3 - nZconstraints;
575 >    temp = useEAM;
576 >    MPI_Allreduce(&temp, &useEAM, 1, MPI_INT, MPI_LOR, MPI_COMM_WORLD);    
577  
578 <  return ndfTrans;
579 < }
578 >    temp = useShape;
579 >    MPI_Allreduce(&temp, &useShape, 1, MPI_INT, MPI_LOR, MPI_COMM_WORLD);  
580  
581 < int SimInfo::getTotIntegrableObjects() {
582 <  int nObjs_local;
407 <  int nObjs;
581 >    temp = useFLARB;
582 >    MPI_Allreduce(&temp, &useFLARB, 1, MPI_INT, MPI_LOR, MPI_COMM_WORLD);    
583  
584 <  nObjs_local =  integrableObjects.size();
585 <
586 <
412 < #ifdef IS_MPI
413 <  MPI_Allreduce(&nObjs_local,&nObjs,1,MPI_INT,MPI_SUM, MPI_COMM_WORLD);
414 < #else
415 <  nObjs = nObjs_local;
584 >    temp = useRF;
585 >    MPI_Allreduce(&temp, &useRF, 1, MPI_INT, MPI_LOR, MPI_COMM_WORLD);    
586 >    
587   #endif
588  
589 +    fInfo_.SIM_uses_PBC = usePBC;    
590 +    fInfo_.SIM_uses_DirectionalAtoms = useDirectionalAtom;
591 +    fInfo_.SIM_uses_LennardJones = useLennardJones;
592 +    fInfo_.SIM_uses_Electrostatics = useElectrostatics;    
593 +    fInfo_.SIM_uses_Charges = useCharge;
594 +    fInfo_.SIM_uses_Dipoles = useDipole;
595 +    fInfo_.SIM_uses_Sticky = useSticky;
596 +    fInfo_.SIM_uses_StickyPower = useStickyPower;
597 +    fInfo_.SIM_uses_GayBerne = useGayBerne;
598 +    fInfo_.SIM_uses_EAM = useEAM;
599 +    fInfo_.SIM_uses_Shapes = useShape;
600 +    fInfo_.SIM_uses_FLARB = useFLARB;
601 +    fInfo_.SIM_uses_RF = useRF;
602  
603 <  return nObjs;
420 < }
603 >    if( fInfo_.SIM_uses_Dipoles && fInfo_.SIM_uses_RF) {
604  
605 < void SimInfo::refreshSim(){
605 >      if (simParams_->haveDielectric()) {
606 >        fInfo_.dielect = simParams_->getDielectric();
607 >      } else {
608 >        sprintf(painCave.errMsg,
609 >                "SimSetup Error: No Dielectric constant was set.\n"
610 >                "\tYou are trying to use Reaction Field without"
611 >                "\tsetting a dielectric constant!\n");
612 >        painCave.isFatal = 1;
613 >        simError();
614 >      }
615 >        
616 >    } else {
617 >      fInfo_.dielect = 0.0;
618 >    }
619  
424  simtype fInfo;
425  int isError;
426  int n_global;
427  int* excl;
428
429  fInfo.dielect = 0.0;
430
431  if( useDipoles ){
432    if( useReactionField )fInfo.dielect = dielectric;
620    }
621  
622 <  fInfo.SIM_uses_PBC = usePBC;
623 <  //fInfo.SIM_uses_LJ = 0;
624 <  fInfo.SIM_uses_LJ = useLJ;
625 <  fInfo.SIM_uses_sticky = useSticky;
626 <  //fInfo.SIM_uses_sticky = 0;
627 <  fInfo.SIM_uses_charges = useCharges;
628 <  fInfo.SIM_uses_dipoles = useDipoles;
442 <  //fInfo.SIM_uses_dipoles = 0;
443 <  fInfo.SIM_uses_RF = useReactionField;
444 <  //fInfo.SIM_uses_RF = 0;
445 <  fInfo.SIM_uses_GB = useGB;
446 <  fInfo.SIM_uses_EAM = useEAM;
622 >  void SimInfo::setupFortranSim() {
623 >    int isError;
624 >    int nExclude;
625 >    std::vector<int> fortranGlobalGroupMembership;
626 >    
627 >    nExclude = exclude_.getSize();
628 >    isError = 0;
629  
630 <  n_exclude = excludes->getSize();
631 <  excl = excludes->getFortranArray();
632 <  
633 < #ifdef IS_MPI
452 <  n_global = mpiSim->getNAtomsGlobal();
453 < #else
454 <  n_global = n_atoms;
455 < #endif
456 <  
457 <  isError = 0;
458 <  
459 <  getFortranGroupArrays(this, FglobalGroupMembership, mfact);
460 <  //it may not be a good idea to pass the address of first element in vector
461 <  //since c++ standard does not require vector to be stored continuously in meomory
462 <  //Most of the compilers will organize the memory of vector continuously
463 <  setFortranSim( &fInfo, &n_global, &n_atoms, identArray, &n_exclude, excl,
464 <                  &nGlobalExcludes, globalExcludes, molMembershipArray,
465 <                  &mfact[0], &ngroup, &FglobalGroupMembership[0], &isError);
630 >    //globalGroupMembership_ is filled by SimCreator    
631 >    for (int i = 0; i < nGlobalAtoms_; i++) {
632 >      fortranGlobalGroupMembership.push_back(globalGroupMembership_[i] + 1);
633 >    }
634  
635 <  if( isError ){
635 >    //calculate mass ratio of cutoff group
636 >    std::vector<double> mfact;
637 >    SimInfo::MoleculeIterator mi;
638 >    Molecule* mol;
639 >    Molecule::CutoffGroupIterator ci;
640 >    CutoffGroup* cg;
641 >    Molecule::AtomIterator ai;
642 >    Atom* atom;
643 >    double totalMass;
644 >
645 >    //to avoid memory reallocation, reserve enough space for mfact
646 >    mfact.reserve(getNCutoffGroups());
647      
648 <    sprintf( painCave.errMsg,
649 <             "There was an error setting the simulation information in fortran.\n" );
471 <    painCave.isFatal = 1;
472 <    painCave.severity = OOPSE_ERROR;
473 <    simError();
474 <  }
475 <  
476 < #ifdef IS_MPI
477 <  sprintf( checkPointMsg,
478 <           "succesfully sent the simulation information to fortran.\n");
479 <  MPIcheckPoint();
480 < #endif // is_mpi
481 <  
482 <  this->ndf = this->getNDF();
483 <  this->ndfRaw = this->getNDFraw();
484 <  this->ndfTrans = this->getNDFtranslational();
485 < }
648 >    for(mol = beginMolecule(mi); mol != NULL; mol = nextMolecule(mi)) {        
649 >      for (cg = mol->beginCutoffGroup(ci); cg != NULL; cg = mol->nextCutoffGroup(ci)) {
650  
651 < void SimInfo::setDefaultRcut( double theRcut ){
652 <  
653 <  haveRcut = 1;
654 <  rCut = theRcut;
491 <  rList = rCut + 1.0;
492 <  
493 <  notifyFortranCutoffs( &rCut, &rSw, &rList );
494 < }
651 >        totalMass = cg->getMass();
652 >        for(atom = cg->beginAtom(ai); atom != NULL; atom = cg->nextAtom(ai)) {
653 >          mfact.push_back(atom->getMass()/totalMass);
654 >        }
655  
656 < void SimInfo::setDefaultRcut( double theRcut, double theRsw ){
656 >      }      
657 >    }
658  
659 <  rSw = theRsw;
660 <  setDefaultRcut( theRcut );
500 < }
659 >    //fill ident array of local atoms (it is actually ident of AtomType, it is so confusing !!!)
660 >    std::vector<int> identArray;
661  
662 +    //to avoid memory reallocation, reserve enough space identArray
663 +    identArray.reserve(getNAtoms());
664 +    
665 +    for(mol = beginMolecule(mi); mol != NULL; mol = nextMolecule(mi)) {        
666 +      for(atom = mol->beginAtom(ai); atom != NULL; atom = mol->nextAtom(ai)) {
667 +        identArray.push_back(atom->getIdent());
668 +      }
669 +    }    
670  
671 < void SimInfo::checkCutOffs( void ){
672 <  
673 <  if( boxIsInit ){
671 >    //fill molMembershipArray
672 >    //molMembershipArray is filled by SimCreator    
673 >    std::vector<int> molMembershipArray(nGlobalAtoms_);
674 >    for (int i = 0; i < nGlobalAtoms_; i++) {
675 >      molMembershipArray[i] = globalMolMembership_[i] + 1;
676 >    }
677      
678 <    //we need to check cutOffs against the box
679 <    
680 <    if( rCut > maxCutoff ){
678 >    //setup fortran simulation
679 >    int nGlobalExcludes = 0;
680 >    int* globalExcludes = NULL;
681 >    int* excludeList = exclude_.getExcludeList();
682 >    setFortranSim( &fInfo_, &nGlobalAtoms_, &nAtoms_, &identArray[0], &nExclude, excludeList ,
683 >                   &nGlobalExcludes, globalExcludes, &molMembershipArray[0],
684 >                   &mfact[0], &nCutoffGroups_, &fortranGlobalGroupMembership[0], &isError);
685 >
686 >    if( isError ){
687 >
688        sprintf( painCave.errMsg,
689 <               "cutoffRadius is too large for the current periodic box.\n"
512 <               "\tCurrent Value of cutoffRadius = %G at time %G\n "
513 <               "\tThis is larger than half of at least one of the\n"
514 <               "\tperiodic box vectors.  Right now, the Box matrix is:\n"
515 <               "\n"
516 <               "\t[ %G %G %G ]\n"
517 <               "\t[ %G %G %G ]\n"
518 <               "\t[ %G %G %G ]\n",
519 <               rCut, currentTime,
520 <               Hmat[0][0], Hmat[0][1], Hmat[0][2],
521 <               Hmat[1][0], Hmat[1][1], Hmat[1][2],
522 <               Hmat[2][0], Hmat[2][1], Hmat[2][2]);
523 <      painCave.severity = OOPSE_ERROR;
689 >               "There was an error setting the simulation information in fortran.\n" );
690        painCave.isFatal = 1;
691 +      painCave.severity = OOPSE_ERROR;
692        simError();
693 <    }    
694 <  } else {
695 <    // initialize this stuff before using it, OK?
696 <    sprintf( painCave.errMsg,
697 <             "Trying to check cutoffs without a box.\n"
698 <             "\tOOPSE should have better programmers than that.\n" );
699 <    painCave.severity = OOPSE_ERROR;
533 <    painCave.isFatal = 1;
534 <    simError();      
693 >    }
694 >
695 > #ifdef IS_MPI
696 >    sprintf( checkPointMsg,
697 >             "succesfully sent the simulation information to fortran.\n");
698 >    MPIcheckPoint();
699 > #endif // is_mpi
700    }
536  
537 }
701  
539 void SimInfo::addProperty(GenericData* prop){
702  
703 <  map<string, GenericData*>::iterator result;
704 <  result = properties.find(prop->getID());
543 <  
544 <  //we can't simply use  properties[prop->getID()] = prop,
545 <  //it will cause memory leak if we already contain a propery which has the same name of prop
546 <  
547 <  if(result != properties.end()){
703 > #ifdef IS_MPI
704 >  void SimInfo::setupFortranParallel() {
705      
706 <    delete (*result).second;
707 <    (*result).second = prop;
708 <      
706 >    //SimInfo is responsible for creating localToGlobalAtomIndex and localToGlobalGroupIndex
707 >    std::vector<int> localToGlobalAtomIndex(getNAtoms(), 0);
708 >    std::vector<int> localToGlobalCutoffGroupIndex;
709 >    SimInfo::MoleculeIterator mi;
710 >    Molecule::AtomIterator ai;
711 >    Molecule::CutoffGroupIterator ci;
712 >    Molecule* mol;
713 >    Atom* atom;
714 >    CutoffGroup* cg;
715 >    mpiSimData parallelData;
716 >    int isError;
717 >
718 >    for (mol = beginMolecule(mi); mol != NULL; mol  = nextMolecule(mi)) {
719 >
720 >      //local index(index in DataStorge) of atom is important
721 >      for (atom = mol->beginAtom(ai); atom != NULL; atom = mol->nextAtom(ai)) {
722 >        localToGlobalAtomIndex[atom->getLocalIndex()] = atom->getGlobalIndex() + 1;
723 >      }
724 >
725 >      //local index of cutoff group is trivial, it only depends on the order of travesing
726 >      for (cg = mol->beginCutoffGroup(ci); cg != NULL; cg = mol->nextCutoffGroup(ci)) {
727 >        localToGlobalCutoffGroupIndex.push_back(cg->getGlobalIndex() + 1);
728 >      }        
729 >        
730 >    }
731 >
732 >    //fill up mpiSimData struct
733 >    parallelData.nMolGlobal = getNGlobalMolecules();
734 >    parallelData.nMolLocal = getNMolecules();
735 >    parallelData.nAtomsGlobal = getNGlobalAtoms();
736 >    parallelData.nAtomsLocal = getNAtoms();
737 >    parallelData.nGroupsGlobal = getNGlobalCutoffGroups();
738 >    parallelData.nGroupsLocal = getNCutoffGroups();
739 >    parallelData.myNode = worldRank;
740 >    MPI_Comm_size(MPI_COMM_WORLD, &(parallelData.nProcessors));
741 >
742 >    //pass mpiSimData struct and index arrays to fortran
743 >    setFsimParallel(&parallelData, &(parallelData.nAtomsLocal),
744 >                    &localToGlobalAtomIndex[0],  &(parallelData.nGroupsLocal),
745 >                    &localToGlobalCutoffGroupIndex[0], &isError);
746 >
747 >    if (isError) {
748 >      sprintf(painCave.errMsg,
749 >              "mpiRefresh errror: fortran didn't like something we gave it.\n");
750 >      painCave.isFatal = 1;
751 >      simError();
752 >    }
753 >
754 >    sprintf(checkPointMsg, " mpiRefresh successful.\n");
755 >    MPIcheckPoint();
756 >
757 >
758    }
553  else{
759  
760 <    properties[prop->getID()] = prop;
760 > #endif
761  
762 +  double SimInfo::calcMaxCutoffRadius() {
763 +
764 +
765 +    std::set<AtomType*> atomTypes;
766 +    std::set<AtomType*>::iterator i;
767 +    std::vector<double> cutoffRadius;
768 +
769 +    //get the unique atom types
770 +    atomTypes = getUniqueAtomTypes();
771 +
772 +    //query the max cutoff radius among these atom types
773 +    for (i = atomTypes.begin(); i != atomTypes.end(); ++i) {
774 +      cutoffRadius.push_back(forceField_->getRcutFromAtomType(*i));
775 +    }
776 +
777 +    double maxCutoffRadius = *(std::max_element(cutoffRadius.begin(), cutoffRadius.end()));
778 + #ifdef IS_MPI
779 +    //pick the max cutoff radius among the processors
780 + #endif
781 +
782 +    return maxCutoffRadius;
783    }
784 +
785 +  void SimInfo::getCutoff(double& rcut, double& rsw) {
786      
787 < }
787 >    if (fInfo_.SIM_uses_Charges | fInfo_.SIM_uses_Dipoles | fInfo_.SIM_uses_RF) {
788 >        
789 >      if (!simParams_->haveRcut()){
790 >        sprintf(painCave.errMsg,
791 >                "SimCreator Warning: No value was set for the cutoffRadius.\n"
792 >                "\tOOPSE will use a default value of 15.0 angstroms"
793 >                "\tfor the cutoffRadius.\n");
794 >        painCave.isFatal = 0;
795 >        simError();
796 >        rcut = 15.0;
797 >      } else{
798 >        rcut = simParams_->getRcut();
799 >      }
800  
801 < GenericData* SimInfo::getProperty(const string& propName){
801 >      if (!simParams_->haveRsw()){
802 >        sprintf(painCave.errMsg,
803 >                "SimCreator Warning: No value was set for switchingRadius.\n"
804 >                "\tOOPSE will use a default value of\n"
805 >                "\t0.95 * cutoffRadius for the switchingRadius\n");
806 >        painCave.isFatal = 0;
807 >        simError();
808 >        rsw = 0.95 * rcut;
809 >      } else{
810 >        rsw = simParams_->getRsw();
811 >      }
812 >
813 >    } else {
814 >      // if charge, dipole or reaction field is not used and the cutofff radius is not specified in
815 >      //meta-data file, the maximum cutoff radius calculated from forcefiled will be used
816 >        
817 >      if (simParams_->haveRcut()) {
818 >        rcut = simParams_->getRcut();
819 >      } else {
820 >        //set cutoff radius to the maximum cutoff radius based on atom types in the whole system
821 >        rcut = calcMaxCutoffRadius();
822 >      }
823 >
824 >      if (simParams_->haveRsw()) {
825 >        rsw  = simParams_->getRsw();
826 >      } else {
827 >        rsw = rcut;
828 >      }
829 >    
830 >    }
831 >  }
832 >
833 >  void SimInfo::setupCutoff() {
834 >    getCutoff(rcut_, rsw_);    
835 >    double rnblist = rcut_ + 1; // skin of neighbor list
836 >
837 >    //Pass these cutoff radius etc. to fortran. This function should be called once and only once
838 >    notifyFortranCutoffs(&rcut_, &rsw_, &rnblist);
839 >  }
840 >
841 >  void SimInfo::addProperty(GenericData* genData) {
842 >    properties_.addProperty(genData);  
843 >  }
844 >
845 >  void SimInfo::removeProperty(const std::string& propName) {
846 >    properties_.removeProperty(propName);  
847 >  }
848 >
849 >  void SimInfo::clearProperties() {
850 >    properties_.clearProperties();
851 >  }
852 >
853 >  std::vector<std::string> SimInfo::getPropertyNames() {
854 >    return properties_.getPropertyNames();  
855 >  }
856 >      
857 >  std::vector<GenericData*> SimInfo::getProperties() {
858 >    return properties_.getProperties();
859 >  }
860 >
861 >  GenericData* SimInfo::getPropertyByName(const std::string& propName) {
862 >    return properties_.getPropertyByName(propName);
863 >  }
864 >
865 >  void SimInfo::setSnapshotManager(SnapshotManager* sman) {
866 >    if (sman_ == sman) {
867 >      return;
868 >    }    
869 >    delete sman_;
870 >    sman_ = sman;
871 >
872 >    Molecule* mol;
873 >    RigidBody* rb;
874 >    Atom* atom;
875 >    SimInfo::MoleculeIterator mi;
876 >    Molecule::RigidBodyIterator rbIter;
877 >    Molecule::AtomIterator atomIter;;
878  
879 <  map<string, GenericData*>::iterator result;
880 <  
881 <  //string lowerCaseName = ();
882 <  
883 <  result = properties.find(propName);
884 <  
885 <  if(result != properties.end())
886 <    return (*result).second;  
887 <  else  
888 <    return NULL;  
889 < }
879 >    for (mol = beginMolecule(mi); mol != NULL; mol = nextMolecule(mi)) {
880 >        
881 >      for (atom = mol->beginAtom(atomIter); atom != NULL; atom = mol->nextAtom(atomIter)) {
882 >        atom->setSnapshotManager(sman_);
883 >      }
884 >        
885 >      for (rb = mol->beginRigidBody(rbIter); rb != NULL; rb = mol->nextRigidBody(rbIter)) {
886 >        rb->setSnapshotManager(sman_);
887 >      }
888 >    }    
889 >    
890 >  }
891  
892 +  Vector3d SimInfo::getComVel(){
893 +    SimInfo::MoleculeIterator i;
894 +    Molecule* mol;
895  
896 < void SimInfo::getFortranGroupArrays(SimInfo* info,
897 <                                    vector<int>& FglobalGroupMembership,
898 <                                    vector<double>& mfact){
899 <  
900 <  Molecule* myMols;
901 <  Atom** myAtoms;
902 <  int numAtom;
903 <  double mtot;
904 <  int numMol;
585 <  int numCutoffGroups;
586 <  CutoffGroup* myCutoffGroup;
587 <  vector<CutoffGroup*>::iterator iterCutoff;
588 <  Atom* cutoffAtom;
589 <  vector<Atom*>::iterator iterAtom;
590 <  int atomIndex;
591 <  double totalMass;
592 <  
593 <  mfact.clear();
594 <  FglobalGroupMembership.clear();
595 <  
896 >    Vector3d comVel(0.0);
897 >    double totalMass = 0.0;
898 >    
899 >
900 >    for (mol = beginMolecule(i); mol != NULL; mol = nextMolecule(i)) {
901 >      double mass = mol->getMass();
902 >      totalMass += mass;
903 >      comVel += mass * mol->getComVel();
904 >    }  
905  
597  // Fix the silly fortran indexing problem
906   #ifdef IS_MPI
907 <  numAtom = mpiSim->getNAtomsGlobal();
908 < #else
909 <  numAtom = n_atoms;
907 >    double tmpMass = totalMass;
908 >    Vector3d tmpComVel(comVel);    
909 >    MPI_Allreduce(&tmpMass,&totalMass,1,MPI_DOUBLE,MPI_SUM, MPI_COMM_WORLD);
910 >    MPI_Allreduce(tmpComVel.getArrayPointer(), comVel.getArrayPointer(),3,MPI_DOUBLE,MPI_SUM, MPI_COMM_WORLD);
911   #endif
603  for (int i = 0; i < numAtom; i++)
604    FglobalGroupMembership.push_back(globalGroupMembership[i] + 1);
605  
912  
913 <  myMols = info->molecules;
608 <  numMol = info->n_mol;
609 <  for(int i  = 0; i < numMol; i++){
610 <    numCutoffGroups = myMols[i].getNCutoffGroups();
611 <    for(myCutoffGroup =myMols[i].beginCutoffGroup(iterCutoff);
612 <        myCutoffGroup != NULL;
613 <        myCutoffGroup =myMols[i].nextCutoffGroup(iterCutoff)){
913 >    comVel /= totalMass;
914  
915 <      totalMass = myCutoffGroup->getMass();
616 <      
617 <      for(cutoffAtom = myCutoffGroup->beginAtom(iterAtom);
618 <          cutoffAtom != NULL;
619 <          cutoffAtom = myCutoffGroup->nextAtom(iterAtom)){
620 <        mfact.push_back(cutoffAtom->getMass()/totalMass);
621 <      }  
622 <    }
915 >    return comVel;
916    }
917  
918 < }
918 >  Vector3d SimInfo::getCom(){
919 >    SimInfo::MoleculeIterator i;
920 >    Molecule* mol;
921 >
922 >    Vector3d com(0.0);
923 >    double totalMass = 0.0;
924 >    
925 >    for (mol = beginMolecule(i); mol != NULL; mol = nextMolecule(i)) {
926 >      double mass = mol->getMass();
927 >      totalMass += mass;
928 >      com += mass * mol->getCom();
929 >    }  
930 >
931 > #ifdef IS_MPI
932 >    double tmpMass = totalMass;
933 >    Vector3d tmpCom(com);    
934 >    MPI_Allreduce(&tmpMass,&totalMass,1,MPI_DOUBLE,MPI_SUM, MPI_COMM_WORLD);
935 >    MPI_Allreduce(tmpCom.getArrayPointer(), com.getArrayPointer(),3,MPI_DOUBLE,MPI_SUM, MPI_COMM_WORLD);
936 > #endif
937 >
938 >    com /= totalMass;
939 >
940 >    return com;
941 >
942 >  }        
943 >
944 >  std::ostream& operator <<(std::ostream& o, SimInfo& info) {
945 >
946 >    return o;
947 >  }
948 >
949 > }//end namespace oopse
950 >

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines