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

Comparing trunk/src/brains/SimInfo.cpp (file contents):
Revision 143 by chrisfen, Fri Oct 22 22:54:01 2004 UTC vs.
Revision 507 by gezelter, Fri Apr 15 22:04:00 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 <  useDirectionalAtoms = 0;
61 <  useLennardJones = 0;
62 <  useElectrostatics = 0;
63 <  useCharges = 0;
64 <  useDipoles = 0;
65 <  useSticky = 0;
66 <  useGayBerne = 0;
67 <  useEAM = 0;
68 <  useShapes = 0;
69 <  useFLARB = 0;
107 >        nGroups += nCutoffGroupsInStamp * nMolWithSameStamp;
108 >        nCutoffAtoms += nAtomsInGroups * nMolWithSameStamp;            
109  
110 <  useSolidThermInt = 0;
111 <  useLiquidThermInt = 0;
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 <  haveCutoffGroups = false;
119 >        nGlobalRigidBodies_ += nRigidBodiesInStamp * nMolWithSameStamp;
120 >        nRigidAtoms += nAtomsInRigidBodies * nMolWithSameStamp;            
121 >        
122 >      }
123  
124 <  excludes = Exclude::Instance();
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 <  myConfiguration = new SimState();
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 <  has_minimizer = false;
81 <  the_minimizer =NULL;
136 >      nGlobalMols_ = molStampIds_.size();
137  
138 <  ngroup = 0;
138 > #ifdef IS_MPI    
139 >      molToProcMap_.resize(nGlobalMols_);
140 > #endif
141  
142 < }
142 >    }
143  
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 < SimInfo::~SimInfo(){
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 <  delete myConfiguration;
168 >  bool SimInfo::addMolecule(Molecule* mol) {
169 >    MoleculeIterator i;
170  
171 <  map<string, GenericData*>::iterator i;
172 <  
94 <  for(i = properties.begin(); i != properties.end(); i++)
95 <    delete (*i).second;
171 >    i = molecules_.find(mol->getGlobalIndex());
172 >    if (i == molecules_.end() ) {
173  
174 < }
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 < void SimInfo::setBox(double newBox[3]) {
186 <  
187 <  int i, j;
188 <  double tempMat[3][3];
185 >      addExcludePairs(mol);
186 >        
187 >      return true;
188 >    } else {
189 >      return false;
190 >    }
191 >  }
192  
193 <  for(i=0; i<3; i++)
194 <    for (j=0; j<3; j++) tempMat[i][j] = 0.0;;
193 >  bool SimInfo::removeMolecule(Molecule* mol) {
194 >    MoleculeIterator i;
195 >    i = molecules_.find(mol->getGlobalIndex());
196  
197 <  tempMat[0][0] = newBox[0];
108 <  tempMat[1][1] = newBox[1];
109 <  tempMat[2][2] = newBox[2];
197 >    if (i != molecules_.end() ) {
198  
199 <  setBoxM( tempMat );
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 < }
210 >      removeExcludePairs(mol);
211 >      molecules_.erase(mol->getGlobalIndex());
212  
213 < void SimInfo::setBoxM( double theBox[3][3] ){
214 <  
215 <  int i, j;
216 <  double FortranHmat[9]; // to preserve compatibility with Fortran the
217 <                         // ordering in the array is as follows:
120 <                         // [ 0 3 6 ]
121 <                         // [ 1 4 7 ]
122 <                         // [ 2 5 8 ]
123 <  double FortranHmatInv[9]; // the inverted Hmat (for Fortran);
124 <
125 <  if( !boxIsInit ) boxIsInit = 1;
126 <
127 <  for(i=0; i < 3; i++)
128 <    for (j=0; j < 3; j++) Hmat[i][j] = theBox[i][j];
129 <  
130 <  calcBoxL();
131 <  calcHmatInv();
132 <
133 <  for(i=0; i < 3; i++) {
134 <    for (j=0; j < 3; j++) {
135 <      FortranHmat[3*j + i] = Hmat[i][j];
136 <      FortranHmatInv[3*j + i] = HmatInv[i][j];
213 >      delete mol;
214 >        
215 >      return true;
216 >    } else {
217 >      return false;
218      }
138  }
219  
140  setFortranBox(FortranHmat, FortranHmatInv, &orthoRhombic);
141
142 }
143
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  
153 void SimInfo::scaleBox(double scale) {
154  double theBox[3][3];
155  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;
171 <  double tol;
172 <  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
177 <  
178 <  oldOrtho = orthoRhombic;
274 >  }
275  
276 <  smallDiag = fabs(Hmat[0][0]);
277 <  if(smallDiag > fabs(Hmat[1][1])) smallDiag = fabs(Hmat[1][1]);
182 <  if(smallDiag > fabs(Hmat[2][2])) smallDiag = fabs(Hmat[2][2]);
183 <  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"
203 <               "\tThis is usually a good thing, but if you wan't the\n"
204 <               "\tNon-Orthorhombic computations, make the orthoBoxTolerance\n"
205 <               "\tvariable ( currently set to %G ) smaller.\n",
206 <               orthoTolerance);
207 <      painCave.severity = OOPSE_INFO;
208 <      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      }
210    else {
211      sprintf( painCave.errMsg,
212               "OOPSE is switching from the faster Orthorhombic to the more\n"
213               "\tflexible Non-Orthorhombic periodic boundary computations.\n"
214               "\tThis is usually because the box has deformed under\n"
215               "\tNPTf integration. If you wan't to live on the edge with\n"
216               "\tthe Orthorhombic computations, make the orthoBoxTolerance\n"
217               "\tvariable ( currently set to %G ) larger.\n",
218               orthoTolerance);
219      painCave.severity = OOPSE_WARNING;
220      simError();
221    }
222  }
223 }
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
241 <  
242 <  dx = Hmat[0][1]; dy = Hmat[1][1]; dz = Hmat[2][1];
243 <  dsq = dx*dx + dy*dy + dz*dz;
244 <  boxL[1] = sqrt( dsq );
245 <  //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;
252 <  boxL[2] = sqrt( dsq );
253 <  //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];
266 <  double rij[3], rjk[3], rki[3];
267 <  double minDist;
439 >  }
440  
269  ri[0] = Hmat[0][0];
270  ri[1] = Hmat[1][0];
271  ri[2] = Hmat[2][0];
441  
442 <  rj[0] = Hmat[0][1];
443 <  rj[1] = Hmat[1][1];
275 <  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];
279 <  rk[2] = Hmat[2][2];
280 <    
281 <  crossProduct3(ri, rj, rij);
282 <  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);
288 <  distZX = dotProduct3(rj,rki) / norm3(rki);
452 >  void SimInfo::update() {
453  
454 <  minDist = min(min(distXY, distYZ), distZX);
291 <  return minDist/2;
292 <  
293 < }
454 >    setupSimType();
455  
456 < void SimInfo::wrapVector( double thePos[3] ){
456 > #ifdef IS_MPI
457 >    setupFortranParallel();
458 > #endif
459  
460 <  int i;
298 <  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    
303
304    matVecMul3(HmatInv, thePos, scaled);
473      
474 <    for(i=0; i<3; i++)
307 <      scaled[i] -= roundMe(scaled[i]);
308 <    
309 <    // calc the wrapped real coordinates from the wrapped scaled coordinates
310 <    
311 <    matVecMul3(Hmat, scaled, thePos);
474 >    setupCutoff();
475  
476 +    calcNdf();
477 +    calcNdfRaw();
478 +    calcNdfTrans();
479 +
480 +    fortranInitialized_ = true;
481    }
314  else{
315    // calc the scaled coordinates.
316    
317    for(i=0; i<3; i++)
318      scaled[i] = thePos[i]*HmatInv[i][i];
319    
320    // wrap the scaled coordinates
321    
322    for(i=0; i<3; i++)
323      scaled[i] -= roundMe(scaled[i]);
324    
325    // calc the wrapped real coordinates from the wrapped scaled coordinates
326    
327    for(i=0; i<3; i++)
328      thePos[i] = scaled[i]*Hmat[i][i];
329  }
330    
331 }
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(){
335 <  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;
341 <    if (integrableObjects[i]->isDirectional()) {
342 <      if (integrableObjects[i]->isLinear())
343 <        ndf_local += 2;
344 <      else
345 <        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 useShape = 0;
515 >    int useFLARB = 0; //it is not in AtomType yet
516 >    int useDirectionalAtom = 0;    
517 >    int useElectrostatics = 0;
518 >    //usePBC and useRF are from simParams
519 >    int usePBC = simParams_->getPBC();
520 >    int useRF = simParams_->getUseRF();
521  
522 < #ifdef IS_MPI
523 <  MPI_Allreduce(&ndf_local,&ndf,1,MPI_INT,MPI_SUM, MPI_COMM_WORLD);
524 < #else
525 <  ndf = ndf_local;
526 < #endif
522 >    //loop over all of the atom types
523 >    for (i = atomTypes.begin(); i != atomTypes.end(); ++i) {
524 >      useLennardJones |= (*i)->isLennardJones();
525 >      useElectrostatic |= (*i)->isElectrostatic();
526 >      useEAM |= (*i)->isEAM();
527 >      useCharge |= (*i)->isCharge();
528 >      useDirectional |= (*i)->isDirectional();
529 >      useDipole |= (*i)->isDipole();
530 >      useGayBerne |= (*i)->isGayBerne();
531 >      useSticky |= (*i)->isSticky();
532 >      useShape |= (*i)->isShape();
533 >    }
534  
535 <  // nZconstraints is global, as are the 3 COM translations for the
536 <  // entire system:
535 >    if (useSticky || useDipole || useGayBerne || useShape) {
536 >      useDirectionalAtom = 1;
537 >    }
538  
539 <  ndf = ndf - 3 - nZconstraints;
539 >    if (useCharge || useDipole) {
540 >      useElectrostatics = 1;
541 >    }
542  
543 <  return ndf;
544 < }
543 > #ifdef IS_MPI    
544 >    int temp;
545  
546 < int SimInfo::getNDFraw() {
547 <  int ndfRaw_local;
546 >    temp = usePBC;
547 >    MPI_Allreduce(&temp, &usePBC, 1, MPI_INT, MPI_LOR, MPI_COMM_WORLD);    
548  
549 <  // Raw degrees of freedom that we have to set
550 <  ndfRaw_local = 0;
549 >    temp = useDirectionalAtom;
550 >    MPI_Allreduce(&temp, &useDirectionalAtom, 1, MPI_INT, MPI_LOR, MPI_COMM_WORLD);    
551  
552 <  for(int i = 0; i < integrableObjects.size(); i++){
553 <    ndfRaw_local += 3;
375 <    if (integrableObjects[i]->isDirectional()) {
376 <       if (integrableObjects[i]->isLinear())
377 <        ndfRaw_local += 2;
378 <      else
379 <        ndfRaw_local += 3;
380 <    }
381 <  }
382 <    
383 < #ifdef IS_MPI
384 <  MPI_Allreduce(&ndfRaw_local,&ndfRaw,1,MPI_INT,MPI_SUM, MPI_COMM_WORLD);
385 < #else
386 <  ndfRaw = ndfRaw_local;
387 < #endif
552 >    temp = useLennardJones;
553 >    MPI_Allreduce(&temp, &useLennardJones, 1, MPI_INT, MPI_LOR, MPI_COMM_WORLD);    
554  
555 <  return ndfRaw;
556 < }
555 >    temp = useElectrostatics;
556 >    MPI_Allreduce(&temp, &useElectrostatics, 1, MPI_INT, MPI_LOR, MPI_COMM_WORLD);    
557  
558 < int SimInfo::getNDFtranslational() {
559 <  int ndfTrans_local;
558 >    temp = useCharge;
559 >    MPI_Allreduce(&temp, &useCharge, 1, MPI_INT, MPI_LOR, MPI_COMM_WORLD);    
560  
561 <  ndfTrans_local = 3 * integrableObjects.size() - n_constraints;
561 >    temp = useDipole;
562 >    MPI_Allreduce(&temp, &useDipole, 1, MPI_INT, MPI_LOR, MPI_COMM_WORLD);    
563  
564 +    temp = useSticky;
565 +    MPI_Allreduce(&temp, &useSticky, 1, MPI_INT, MPI_LOR, MPI_COMM_WORLD);    
566  
567 < #ifdef IS_MPI
568 <  MPI_Allreduce(&ndfTrans_local,&ndfTrans,1,MPI_INT,MPI_SUM, MPI_COMM_WORLD);
569 < #else
570 <  ndfTrans = ndfTrans_local;
567 >    temp = useGayBerne;
568 >    MPI_Allreduce(&temp, &useGayBerne, 1, MPI_INT, MPI_LOR, MPI_COMM_WORLD);    
569 >
570 >    temp = useEAM;
571 >    MPI_Allreduce(&temp, &useEAM, 1, MPI_INT, MPI_LOR, MPI_COMM_WORLD);    
572 >
573 >    temp = useShape;
574 >    MPI_Allreduce(&temp, &useShape, 1, MPI_INT, MPI_LOR, MPI_COMM_WORLD);  
575 >
576 >    temp = useFLARB;
577 >    MPI_Allreduce(&temp, &useFLARB, 1, MPI_INT, MPI_LOR, MPI_COMM_WORLD);    
578 >
579 >    temp = useRF;
580 >    MPI_Allreduce(&temp, &useRF, 1, MPI_INT, MPI_LOR, MPI_COMM_WORLD);    
581 >    
582   #endif
583  
584 <  ndfTrans = ndfTrans - 3 - nZconstraints;
584 >    fInfo_.SIM_uses_PBC = usePBC;    
585 >    fInfo_.SIM_uses_DirectionalAtoms = useDirectionalAtom;
586 >    fInfo_.SIM_uses_LennardJones = useLennardJones;
587 >    fInfo_.SIM_uses_Electrostatics = useElectrostatics;    
588 >    fInfo_.SIM_uses_Charges = useCharge;
589 >    fInfo_.SIM_uses_Dipoles = useDipole;
590 >    fInfo_.SIM_uses_Sticky = useSticky;
591 >    fInfo_.SIM_uses_GayBerne = useGayBerne;
592 >    fInfo_.SIM_uses_EAM = useEAM;
593 >    fInfo_.SIM_uses_Shapes = useShape;
594 >    fInfo_.SIM_uses_FLARB = useFLARB;
595 >    fInfo_.SIM_uses_RF = useRF;
596  
597 <  return ndfTrans;
407 < }
597 >    if( fInfo_.SIM_uses_Dipoles && fInfo_.SIM_uses_RF) {
598  
599 < int SimInfo::getTotIntegrableObjects() {
600 <  int nObjs_local;
601 <  int nObjs;
599 >      if (simParams_->haveDielectric()) {
600 >        fInfo_.dielect = simParams_->getDielectric();
601 >      } else {
602 >        sprintf(painCave.errMsg,
603 >                "SimSetup Error: No Dielectric constant was set.\n"
604 >                "\tYou are trying to use Reaction Field without"
605 >                "\tsetting a dielectric constant!\n");
606 >        painCave.isFatal = 1;
607 >        simError();
608 >      }
609 >        
610 >    } else {
611 >      fInfo_.dielect = 0.0;
612 >    }
613  
614 <  nObjs_local =  integrableObjects.size();
614 >  }
615  
616 +  void SimInfo::setupFortranSim() {
617 +    int isError;
618 +    int nExclude;
619 +    std::vector<int> fortranGlobalGroupMembership;
620 +    
621 +    nExclude = exclude_.getSize();
622 +    isError = 0;
623  
624 < #ifdef IS_MPI
625 <  MPI_Allreduce(&nObjs_local,&nObjs,1,MPI_INT,MPI_SUM, MPI_COMM_WORLD);
626 < #else
627 <  nObjs = nObjs_local;
420 < #endif
624 >    //globalGroupMembership_ is filled by SimCreator    
625 >    for (int i = 0; i < nGlobalAtoms_; i++) {
626 >      fortranGlobalGroupMembership.push_back(globalGroupMembership_[i] + 1);
627 >    }
628  
629 +    //calculate mass ratio of cutoff group
630 +    std::vector<double> mfact;
631 +    SimInfo::MoleculeIterator mi;
632 +    Molecule* mol;
633 +    Molecule::CutoffGroupIterator ci;
634 +    CutoffGroup* cg;
635 +    Molecule::AtomIterator ai;
636 +    Atom* atom;
637 +    double totalMass;
638  
639 <  return nObjs;
640 < }
639 >    //to avoid memory reallocation, reserve enough space for mfact
640 >    mfact.reserve(getNCutoffGroups());
641 >    
642 >    for(mol = beginMolecule(mi); mol != NULL; mol = nextMolecule(mi)) {        
643 >      for (cg = mol->beginCutoffGroup(ci); cg != NULL; cg = mol->nextCutoffGroup(ci)) {
644  
645 < void SimInfo::refreshSim(){
645 >        totalMass = cg->getMass();
646 >        for(atom = cg->beginAtom(ai); atom != NULL; atom = cg->nextAtom(ai)) {
647 >          mfact.push_back(atom->getMass()/totalMass);
648 >        }
649  
650 <  simtype fInfo;
651 <  int isError;
430 <  int n_global;
431 <  int* excl;
650 >      }      
651 >    }
652  
653 <  fInfo.dielect = 0.0;
653 >    //fill ident array of local atoms (it is actually ident of AtomType, it is so confusing !!!)
654 >    std::vector<int> identArray;
655  
656 <  if( useDipoles ){
657 <    if( useReactionField )fInfo.dielect = dielectric;
658 <  }
656 >    //to avoid memory reallocation, reserve enough space identArray
657 >    identArray.reserve(getNAtoms());
658 >    
659 >    for(mol = beginMolecule(mi); mol != NULL; mol = nextMolecule(mi)) {        
660 >      for(atom = mol->beginAtom(ai); atom != NULL; atom = mol->nextAtom(ai)) {
661 >        identArray.push_back(atom->getIdent());
662 >      }
663 >    }    
664  
665 <  fInfo.SIM_uses_PBC = usePBC;
665 >    //fill molMembershipArray
666 >    //molMembershipArray is filled by SimCreator    
667 >    std::vector<int> molMembershipArray(nGlobalAtoms_);
668 >    for (int i = 0; i < nGlobalAtoms_; i++) {
669 >      molMembershipArray[i] = globalMolMembership_[i] + 1;
670 >    }
671 >    
672 >    //setup fortran simulation
673 >    int nGlobalExcludes = 0;
674 >    int* globalExcludes = NULL;
675 >    int* excludeList = exclude_.getExcludeList();
676 >    setFortranSim( &fInfo_, &nGlobalAtoms_, &nAtoms_, &identArray[0], &nExclude, excludeList ,
677 >                   &nGlobalExcludes, globalExcludes, &molMembershipArray[0],
678 >                   &mfact[0], &nCutoffGroups_, &fortranGlobalGroupMembership[0], &isError);
679  
680 <  if (useSticky || useDipoles || useGayBerne || useShapes) {
442 <    useDirectionalAtoms = 1;
443 <    fInfo.SIM_uses_DirectionalAtoms = useDirectionalAtoms;
444 <  }
680 >    if( isError ){
681  
682 <  fInfo.SIM_uses_LennardJones = useLennardJones;
682 >      sprintf( painCave.errMsg,
683 >               "There was an error setting the simulation information in fortran.\n" );
684 >      painCave.isFatal = 1;
685 >      painCave.severity = OOPSE_ERROR;
686 >      simError();
687 >    }
688  
689 <  if (useCharges || useDipoles) {
690 <    useElectrostatics = 1;
691 <    fInfo.SIM_uses_Electrostatics = useElectrostatics;
689 > #ifdef IS_MPI
690 >    sprintf( checkPointMsg,
691 >             "succesfully sent the simulation information to fortran.\n");
692 >    MPIcheckPoint();
693 > #endif // is_mpi
694    }
695  
453  fInfo.SIM_uses_Charges = useCharges;
454  fInfo.SIM_uses_Dipoles = useDipoles;
455  fInfo.SIM_uses_Sticky = useSticky;
456  fInfo.SIM_uses_GayBerne = useGayBerne;
457  fInfo.SIM_uses_EAM = useEAM;
458  fInfo.SIM_uses_Shapes = useShapes;
459  fInfo.SIM_uses_FLARB = useFLARB;
460  fInfo.SIM_uses_RF = useReactionField;
696  
462  n_exclude = excludes->getSize();
463  excl = excludes->getFortranArray();
464  
697   #ifdef IS_MPI
698 <  n_global = mpiSim->getNAtomsGlobal();
467 < #else
468 <  n_global = n_atoms;
469 < #endif
470 <  
471 <  isError = 0;
472 <  
473 <  getFortranGroupArrays(this, FglobalGroupMembership, mfact);
474 <  //it may not be a good idea to pass the address of first element in vector
475 <  //since c++ standard does not require vector to be stored continuously in meomory
476 <  //Most of the compilers will organize the memory of vector continuously
477 <  setFortranSim( &fInfo, &n_global, &n_atoms, identArray, &n_exclude, excl,
478 <                  &nGlobalExcludes, globalExcludes, molMembershipArray,
479 <                  &mfact[0], &ngroup, &FglobalGroupMembership[0], &isError);
480 <
481 <  if( isError ){
698 >  void SimInfo::setupFortranParallel() {
699      
700 <    sprintf( painCave.errMsg,
701 <             "There was an error setting the simulation information in fortran.\n" );
702 <    painCave.isFatal = 1;
703 <    painCave.severity = OOPSE_ERROR;
704 <    simError();
705 <  }
706 <  
707 < #ifdef IS_MPI
708 <  sprintf( checkPointMsg,
709 <           "succesfully sent the simulation information to fortran.\n");
710 <  MPIcheckPoint();
494 < #endif // is_mpi
495 <  
496 <  this->ndf = this->getNDF();
497 <  this->ndfRaw = this->getNDFraw();
498 <  this->ndfTrans = this->getNDFtranslational();
499 < }
700 >    //SimInfo is responsible for creating localToGlobalAtomIndex and localToGlobalGroupIndex
701 >    std::vector<int> localToGlobalAtomIndex(getNAtoms(), 0);
702 >    std::vector<int> localToGlobalCutoffGroupIndex;
703 >    SimInfo::MoleculeIterator mi;
704 >    Molecule::AtomIterator ai;
705 >    Molecule::CutoffGroupIterator ci;
706 >    Molecule* mol;
707 >    Atom* atom;
708 >    CutoffGroup* cg;
709 >    mpiSimData parallelData;
710 >    int isError;
711  
712 < void SimInfo::setDefaultRcut( double theRcut ){
502 <  
503 <  haveRcut = 1;
504 <  rCut = theRcut;
505 <  rList = rCut + 1.0;
506 <  
507 <  notifyFortranCutoffs( &rCut, &rSw, &rList );
508 < }
712 >    for (mol = beginMolecule(mi); mol != NULL; mol  = nextMolecule(mi)) {
713  
714 < void SimInfo::setDefaultRcut( double theRcut, double theRsw ){
714 >      //local index(index in DataStorge) of atom is important
715 >      for (atom = mol->beginAtom(ai); atom != NULL; atom = mol->nextAtom(ai)) {
716 >        localToGlobalAtomIndex[atom->getLocalIndex()] = atom->getGlobalIndex() + 1;
717 >      }
718  
719 <  rSw = theRsw;
720 <  setDefaultRcut( theRcut );
721 < }
719 >      //local index of cutoff group is trivial, it only depends on the order of travesing
720 >      for (cg = mol->beginCutoffGroup(ci); cg != NULL; cg = mol->nextCutoffGroup(ci)) {
721 >        localToGlobalCutoffGroupIndex.push_back(cg->getGlobalIndex() + 1);
722 >      }        
723 >        
724 >    }
725  
726 +    //fill up mpiSimData struct
727 +    parallelData.nMolGlobal = getNGlobalMolecules();
728 +    parallelData.nMolLocal = getNMolecules();
729 +    parallelData.nAtomsGlobal = getNGlobalAtoms();
730 +    parallelData.nAtomsLocal = getNAtoms();
731 +    parallelData.nGroupsGlobal = getNGlobalCutoffGroups();
732 +    parallelData.nGroupsLocal = getNCutoffGroups();
733 +    parallelData.myNode = worldRank;
734 +    MPI_Comm_size(MPI_COMM_WORLD, &(parallelData.nProcessors));
735  
736 < void SimInfo::checkCutOffs( void ){
737 <  
738 <  if( boxIsInit ){
739 <    
740 <    //we need to check cutOffs against the box
741 <    
742 <    if( rCut > maxCutoff ){
743 <      sprintf( painCave.errMsg,
525 <               "cutoffRadius is too large for the current periodic box.\n"
526 <               "\tCurrent Value of cutoffRadius = %G at time %G\n "
527 <               "\tThis is larger than half of at least one of the\n"
528 <               "\tperiodic box vectors.  Right now, the Box matrix is:\n"
529 <               "\n"
530 <               "\t[ %G %G %G ]\n"
531 <               "\t[ %G %G %G ]\n"
532 <               "\t[ %G %G %G ]\n",
533 <               rCut, currentTime,
534 <               Hmat[0][0], Hmat[0][1], Hmat[0][2],
535 <               Hmat[1][0], Hmat[1][1], Hmat[1][2],
536 <               Hmat[2][0], Hmat[2][1], Hmat[2][2]);
537 <      painCave.severity = OOPSE_ERROR;
736 >    //pass mpiSimData struct and index arrays to fortran
737 >    setFsimParallel(&parallelData, &(parallelData.nAtomsLocal),
738 >                    &localToGlobalAtomIndex[0],  &(parallelData.nGroupsLocal),
739 >                    &localToGlobalCutoffGroupIndex[0], &isError);
740 >
741 >    if (isError) {
742 >      sprintf(painCave.errMsg,
743 >              "mpiRefresh errror: fortran didn't like something we gave it.\n");
744        painCave.isFatal = 1;
745        simError();
746 <    }    
747 <  } else {
748 <    // initialize this stuff before using it, OK?
749 <    sprintf( painCave.errMsg,
750 <             "Trying to check cutoffs without a box.\n"
751 <             "\tOOPSE should have better programmers than that.\n" );
546 <    painCave.severity = OOPSE_ERROR;
547 <    painCave.isFatal = 1;
548 <    simError();      
746 >    }
747 >
748 >    sprintf(checkPointMsg, " mpiRefresh successful.\n");
749 >    MPIcheckPoint();
750 >
751 >
752    }
550  
551 }
753  
754 < void SimInfo::addProperty(GenericData* prop){
754 > #endif
755  
756 <  map<string, GenericData*>::iterator result;
757 <  result = properties.find(prop->getID());
758 <  
759 <  //we can't simply use  properties[prop->getID()] = prop,
760 <  //it will cause memory leak if we already contain a propery which has the same name of prop
761 <  
762 <  if(result != properties.end()){
756 >  double SimInfo::calcMaxCutoffRadius() {
757 >
758 >
759 >    std::set<AtomType*> atomTypes;
760 >    std::set<AtomType*>::iterator i;
761 >    std::vector<double> cutoffRadius;
762 >
763 >    //get the unique atom types
764 >    atomTypes = getUniqueAtomTypes();
765 >
766 >    //query the max cutoff radius among these atom types
767 >    for (i = atomTypes.begin(); i != atomTypes.end(); ++i) {
768 >      cutoffRadius.push_back(forceField_->getRcutFromAtomType(*i));
769 >    }
770 >
771 >    double maxCutoffRadius = *(std::max_element(cutoffRadius.begin(), cutoffRadius.end()));
772 > #ifdef IS_MPI
773 >    //pick the max cutoff radius among the processors
774 > #endif
775 >
776 >    return maxCutoffRadius;
777 >  }
778 >
779 >  void SimInfo::getCutoff(double& rcut, double& rsw) {
780      
781 <    delete (*result).second;
782 <    (*result).second = prop;
783 <      
781 >    if (fInfo_.SIM_uses_Charges | fInfo_.SIM_uses_Dipoles | fInfo_.SIM_uses_RF) {
782 >        
783 >      if (!simParams_->haveRcut()){
784 >        sprintf(painCave.errMsg,
785 >                "SimCreator Warning: No value was set for the cutoffRadius.\n"
786 >                "\tOOPSE will use a default value of 15.0 angstroms"
787 >                "\tfor the cutoffRadius.\n");
788 >        painCave.isFatal = 0;
789 >        simError();
790 >        rcut = 15.0;
791 >      } else{
792 >        rcut = simParams_->getRcut();
793 >      }
794 >
795 >      if (!simParams_->haveRsw()){
796 >        sprintf(painCave.errMsg,
797 >                "SimCreator Warning: No value was set for switchingRadius.\n"
798 >                "\tOOPSE will use a default value of\n"
799 >                "\t0.95 * cutoffRadius for the switchingRadius\n");
800 >        painCave.isFatal = 0;
801 >        simError();
802 >        rsw = 0.95 * rcut;
803 >      } else{
804 >        rsw = simParams_->getRsw();
805 >      }
806 >
807 >    } else {
808 >      // if charge, dipole or reaction field is not used and the cutofff radius is not specified in
809 >      //meta-data file, the maximum cutoff radius calculated from forcefiled will be used
810 >        
811 >      if (simParams_->haveRcut()) {
812 >        rcut = simParams_->getRcut();
813 >      } else {
814 >        //set cutoff radius to the maximum cutoff radius based on atom types in the whole system
815 >        rcut = calcMaxCutoffRadius();
816 >      }
817 >
818 >      if (simParams_->haveRsw()) {
819 >        rsw  = simParams_->getRsw();
820 >      } else {
821 >        rsw = rcut;
822 >      }
823 >    
824 >    }
825    }
567  else{
826  
827 <    properties[prop->getID()] = prop;
827 >  void SimInfo::setupCutoff() {
828 >    getCutoff(rcut_, rsw_);    
829 >    double rnblist = rcut_ + 1; // skin of neighbor list
830  
831 +    //Pass these cutoff radius etc. to fortran. This function should be called once and only once
832 +    notifyFortranCutoffs(&rcut_, &rsw_, &rnblist);
833    }
834 +
835 +  void SimInfo::addProperty(GenericData* genData) {
836 +    properties_.addProperty(genData);  
837 +  }
838 +
839 +  void SimInfo::removeProperty(const std::string& propName) {
840 +    properties_.removeProperty(propName);  
841 +  }
842 +
843 +  void SimInfo::clearProperties() {
844 +    properties_.clearProperties();
845 +  }
846 +
847 +  std::vector<std::string> SimInfo::getPropertyNames() {
848 +    return properties_.getPropertyNames();  
849 +  }
850 +      
851 +  std::vector<GenericData*> SimInfo::getProperties() {
852 +    return properties_.getProperties();
853 +  }
854 +
855 +  GenericData* SimInfo::getPropertyByName(const std::string& propName) {
856 +    return properties_.getPropertyByName(propName);
857 +  }
858 +
859 +  void SimInfo::setSnapshotManager(SnapshotManager* sman) {
860 +    if (sman_ == sman) {
861 +      return;
862 +    }    
863 +    delete sman_;
864 +    sman_ = sman;
865 +
866 +    Molecule* mol;
867 +    RigidBody* rb;
868 +    Atom* atom;
869 +    SimInfo::MoleculeIterator mi;
870 +    Molecule::RigidBodyIterator rbIter;
871 +    Molecule::AtomIterator atomIter;;
872 +
873 +    for (mol = beginMolecule(mi); mol != NULL; mol = nextMolecule(mi)) {
874 +        
875 +      for (atom = mol->beginAtom(atomIter); atom != NULL; atom = mol->nextAtom(atomIter)) {
876 +        atom->setSnapshotManager(sman_);
877 +      }
878 +        
879 +      for (rb = mol->beginRigidBody(rbIter); rb != NULL; rb = mol->nextRigidBody(rbIter)) {
880 +        rb->setSnapshotManager(sman_);
881 +      }
882 +    }    
883      
884 < }
884 >  }
885  
886 < GenericData* SimInfo::getProperty(const string& propName){
886 >  Vector3d SimInfo::getComVel(){
887 >    SimInfo::MoleculeIterator i;
888 >    Molecule* mol;
889 >
890 >    Vector3d comVel(0.0);
891 >    double totalMass = 0.0;
892 >    
893  
894 <  map<string, GenericData*>::iterator result;
895 <  
896 <  //string lowerCaseName = ();
897 <  
898 <  result = properties.find(propName);
582 <  
583 <  if(result != properties.end())
584 <    return (*result).second;  
585 <  else  
586 <    return NULL;  
587 < }
894 >    for (mol = beginMolecule(i); mol != NULL; mol = nextMolecule(i)) {
895 >      double mass = mol->getMass();
896 >      totalMass += mass;
897 >      comVel += mass * mol->getComVel();
898 >    }  
899  
900 + #ifdef IS_MPI
901 +    double tmpMass = totalMass;
902 +    Vector3d tmpComVel(comVel);    
903 +    MPI_Allreduce(&tmpMass,&totalMass,1,MPI_DOUBLE,MPI_SUM, MPI_COMM_WORLD);
904 +    MPI_Allreduce(tmpComVel.getArrayPointer(), comVel.getArrayPointer(),3,MPI_DOUBLE,MPI_SUM, MPI_COMM_WORLD);
905 + #endif
906  
907 < void SimInfo::getFortranGroupArrays(SimInfo* info,
591 <                                    vector<int>& FglobalGroupMembership,
592 <                                    vector<double>& mfact){
593 <  
594 <  Molecule* myMols;
595 <  Atom** myAtoms;
596 <  int numAtom;
597 <  double mtot;
598 <  int numMol;
599 <  int numCutoffGroups;
600 <  CutoffGroup* myCutoffGroup;
601 <  vector<CutoffGroup*>::iterator iterCutoff;
602 <  Atom* cutoffAtom;
603 <  vector<Atom*>::iterator iterAtom;
604 <  int atomIndex;
605 <  double totalMass;
606 <  
607 <  mfact.clear();
608 <  FglobalGroupMembership.clear();
609 <  
907 >    comVel /= totalMass;
908  
909 <  // Fix the silly fortran indexing problem
909 >    return comVel;
910 >  }
911 >
912 >  Vector3d SimInfo::getCom(){
913 >    SimInfo::MoleculeIterator i;
914 >    Molecule* mol;
915 >
916 >    Vector3d com(0.0);
917 >    double totalMass = 0.0;
918 >    
919 >    for (mol = beginMolecule(i); mol != NULL; mol = nextMolecule(i)) {
920 >      double mass = mol->getMass();
921 >      totalMass += mass;
922 >      com += mass * mol->getCom();
923 >    }  
924 >
925   #ifdef IS_MPI
926 <  numAtom = mpiSim->getNAtomsGlobal();
927 < #else
928 <  numAtom = n_atoms;
926 >    double tmpMass = totalMass;
927 >    Vector3d tmpCom(com);    
928 >    MPI_Allreduce(&tmpMass,&totalMass,1,MPI_DOUBLE,MPI_SUM, MPI_COMM_WORLD);
929 >    MPI_Allreduce(tmpCom.getArrayPointer(), com.getArrayPointer(),3,MPI_DOUBLE,MPI_SUM, MPI_COMM_WORLD);
930   #endif
617  for (int i = 0; i < numAtom; i++)
618    FglobalGroupMembership.push_back(globalGroupMembership[i] + 1);
619  
931  
932 <  myMols = info->molecules;
622 <  numMol = info->n_mol;
623 <  for(int i  = 0; i < numMol; i++){
624 <    numCutoffGroups = myMols[i].getNCutoffGroups();
625 <    for(myCutoffGroup =myMols[i].beginCutoffGroup(iterCutoff);
626 <        myCutoffGroup != NULL;
627 <        myCutoffGroup =myMols[i].nextCutoffGroup(iterCutoff)){
932 >    com /= totalMass;
933  
934 <      totalMass = myCutoffGroup->getMass();
935 <      
936 <      for(cutoffAtom = myCutoffGroup->beginAtom(iterAtom);
937 <          cutoffAtom != NULL;
938 <          cutoffAtom = myCutoffGroup->nextAtom(iterAtom)){
939 <        mfact.push_back(cutoffAtom->getMass()/totalMass);
940 <      }  
636 <    }
934 >    return com;
935 >
936 >  }        
937 >
938 >  std::ostream& operator <<(std::ostream& o, SimInfo& info) {
939 >
940 >    return o;
941    }
942  
943 < }
943 > }//end namespace oopse
944 >

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines