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

Comparing trunk/OOPSE-3.0/src/brains/SimInfo.cpp (file contents):
Revision 1490 by gezelter, Fri Sep 24 04:16:43 2004 UTC vs.
Revision 2204 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 "SimInfo.hpp"
53 < #define __C
54 < #include "fSimulation.h"
55 < #include "simError.h"
52 > #include "brains/SimInfo.hpp"
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  
61 < #include "fortranWrappers.hpp"
61 > #ifdef IS_MPI
62 > #include "UseTheForce/mpiComponentPlan.h"
63 > #include "UseTheForce/DarkSide/simParallel_interface.h"
64 > #endif
65  
66 < #include "MatVec3.h"
66 > namespace oopse {
67  
68 < #ifdef IS_MPI
69 < #include "mpiSimulation.hpp"
70 < #endif
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 < inline double roundMe( double x ){
79 <  return ( x >= 0 ) ? floor( x + 0.5 ) : ceil( x - 0.5 );
80 < }
81 <          
82 < inline double min( double a, double b ){
83 <  return (a < b ) ? a : b;
84 < }
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 < SimInfo* currentInfo;
94 >        //calculate atoms in molecules
95 >        nGlobalAtoms_ += molStamp->getNAtoms() *nMolWithSameStamp;  
96  
31 SimInfo::SimInfo(){
97  
98 <  n_constraints = 0;
99 <  nZconstraints = 0;
100 <  n_oriented = 0;
101 <  n_dipoles = 0;
102 <  ndf = 0;
103 <  ndfRaw = 0;
104 <  nZconstraints = 0;
105 <  the_integrator = NULL;
41 <  setTemp = 0;
42 <  thermalTime = 0.0;
43 <  currentTime = 0.0;
44 <  rCut = 0.0;
45 <  rSw = 0.0;
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 <  haveRcut = 0;
108 <  haveRsw = 0;
49 <  boxIsInit = 0;
50 <  
51 <  resetTime = 1e99;
107 >        nGroups += nCutoffGroupsInStamp * nMolWithSameStamp;
108 >        nCutoffAtoms += nAtomsInGroups * nMolWithSameStamp;            
109  
110 <  orthoRhombic = 0;
111 <  orthoTolerance = 1E-6;
112 <  useInitXSstate = true;
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 <  usePBC = 0;
120 <  useLJ = 0;
121 <  useSticky = 0;
122 <  useCharges = 0;
61 <  useDipoles = 0;
62 <  useReactionField = 0;
63 <  useGB = 0;
64 <  useEAM = 0;
65 <  useSolidThermInt = 0;
66 <  useLiquidThermInt = 0;
119 >        nGlobalRigidBodies_ += nRigidBodiesInStamp * nMolWithSameStamp;
120 >        nRigidAtoms += nAtomsInRigidBodies * nMolWithSameStamp;            
121 >        
122 >      }
123  
124 <  haveCutoffGroups = false;
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 <  excludes = Exclude::Instance();
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 <  myConfiguration = new SimState();
136 >      nGlobalMols_ = molStampIds_.size();
137  
138 <  has_minimizer = false;
139 <  the_minimizer =NULL;
138 > #ifdef IS_MPI    
139 >      molToProcMap_.resize(nGlobalMols_);
140 > #endif
141  
142 <  ngroup = 0;
142 >    }
143  
144 <  wrapMeSimInfo( this );
145 < }
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 +  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 < SimInfo::~SimInfo(){
168 >  bool SimInfo::addMolecule(Molecule* mol) {
169 >    MoleculeIterator i;
170  
171 <  delete myConfiguration;
171 >    i = molecules_.find(mol->getGlobalIndex());
172 >    if (i == molecules_.end() ) {
173  
174 <  map<string, GenericData*>::iterator i;
175 <  
176 <  for(i = properties.begin(); i != properties.end(); i++)
177 <    delete (*i).second;
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 < }
185 >      addExcludePairs(mol);
186 >        
187 >      return true;
188 >    } else {
189 >      return false;
190 >    }
191 >  }
192  
193 < void SimInfo::setBox(double newBox[3]) {
194 <  
195 <  int i, j;
97 <  double tempMat[3][3];
193 >  bool SimInfo::removeMolecule(Molecule* mol) {
194 >    MoleculeIterator i;
195 >    i = molecules_.find(mol->getGlobalIndex());
196  
197 <  for(i=0; i<3; i++)
100 <    for (j=0; j<3; j++) tempMat[i][j] = 0.0;;
197 >    if (i != molecules_.end() ) {
198  
199 <  tempMat[0][0] = newBox[0];
200 <  tempMat[1][1] = newBox[1];
201 <  tempMat[2][2] = newBox[2];
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 <  setBoxM( tempMat );
210 >      removeExcludePairs(mol);
211 >      molecules_.erase(mol->getGlobalIndex());
212  
213 < }
213 >      delete mol;
214 >        
215 >      return true;
216 >    } else {
217 >      return false;
218 >    }
219  
110 void SimInfo::setBoxM( double theBox[3][3] ){
111  
112  int i, j;
113  double FortranHmat[9]; // to preserve compatibility with Fortran the
114                         // ordering in the array is as follows:
115                         // [ 0 3 6 ]
116                         // [ 1 4 7 ]
117                         // [ 2 5 8 ]
118  double FortranHmatInv[9]; // the inverted Hmat (for Fortran);
220  
221 <  if( !boxIsInit ) boxIsInit = 1;
221 >  }    
222  
223 <  for(i=0; i < 3; i++)
224 <    for (j=0; j < 3; j++) Hmat[i][j] = theBox[i][j];
225 <  
226 <  calcBoxL();
227 <  calcHmatInv();
223 >        
224 >  Molecule* SimInfo::beginMolecule(MoleculeIterator& i) {
225 >    i = molecules_.begin();
226 >    return i == molecules_.end() ? NULL : i->second;
227 >  }    
228  
229 <  for(i=0; i < 3; i++) {
230 <    for (j=0; j < 3; j++) {
231 <      FortranHmat[3*j + i] = Hmat[i][j];
131 <      FortranHmatInv[3*j + i] = HmatInv[i][j];
132 <    }
229 >  Molecule* SimInfo::nextMolecule(MoleculeIterator& i) {
230 >    ++i;
231 >    return i == molecules_.end() ? NULL : i->second;    
232    }
233  
135  setFortranBoxSize(FortranHmat, FortranHmatInv, &orthoRhombic);
136
137 }
138
234  
235 < void SimInfo::getBoxM (double theBox[3][3]) {
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 <  int i, j;
243 <  for(i=0; i<3; i++)
244 <    for (j=0; j<3; j++) theBox[i][j] = Hmat[i][j];
245 < }
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 +        ndf_local += 3;
249  
250 < void SimInfo::scaleBox(double scale) {
251 <  double theBox[3][3];
252 <  int i, j;
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 <  // cerr << "Scaling box by " << scale << "\n";
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 <  for(i=0; i<3; i++)
271 <    for (j=0; j<3; j++) theBox[i][j] = Hmat[i][j]*scale;
270 >    // nZconstraints_ is global, as are the 3 COM translations for the
271 >    // entire system:
272 >    ndf_ = ndf_ - 3 - nZconstraint_;
273  
274 <  setBoxM(theBox);
274 >  }
275  
276 < }
276 >  void SimInfo::calcNdfRaw() {
277 >    int ndfRaw_local;
278  
279 < void SimInfo::calcHmatInv( void ) {
280 <  
281 <  int oldOrtho;
282 <  int i,j;
165 <  double smallDiag;
166 <  double tol;
167 <  double sanity[3][3];
279 >    MoleculeIterator i;
280 >    std::vector<StuntDouble*>::iterator j;
281 >    Molecule* mol;
282 >    StuntDouble* integrableObject;
283  
284 <  invertMat3( Hmat, HmatInv );
285 <
286 <  // check to see if Hmat is orthorhombic
287 <  
288 <  oldOrtho = orthoRhombic;
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 <  smallDiag = fabs(Hmat[0][0]);
176 <  if(smallDiag > fabs(Hmat[1][1])) smallDiag = fabs(Hmat[1][1]);
177 <  if(smallDiag > fabs(Hmat[2][2])) smallDiag = fabs(Hmat[2][2]);
178 <  tol = smallDiag * orthoTolerance;
291 >        ndfRaw_local += 3;
292  
293 <  orthoRhombic = 1;
294 <  
295 <  for (i = 0; i < 3; i++ ) {
296 <    for (j = 0 ; j < 3; j++) {
297 <      if (i != j) {
298 <        if (orthoRhombic) {
299 <          if ( fabs(Hmat[i][j]) >= tol) orthoRhombic = 0;
300 <        }        
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"
198 <               "\tThis is usually a good thing, but if you wan't the\n"
199 <               "\tNon-Orthorhombic computations, make the orthoBoxTolerance\n"
200 <               "\tvariable ( currently set to %G ) smaller.\n",
201 <               orthoTolerance);
202 <      painCave.severity = OOPSE_INFO;
203 <      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      }
205    else {
206      sprintf( painCave.errMsg,
207               "OOPSE is switching from the faster Orthorhombic to the more\n"
208               "\tflexible Non-Orthorhombic periodic boundary computations.\n"
209               "\tThis is usually because the box has deformed under\n"
210               "\tNPTf integration. If you wan't to live on the edge with\n"
211               "\tthe Orthorhombic computations, make the orthoBoxTolerance\n"
212               "\tvariable ( currently set to %G ) larger.\n",
213               orthoTolerance);
214      painCave.severity = OOPSE_WARNING;
215      simError();
216    }
217  }
218 }
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
236 <  
237 <  dx = Hmat[0][1]; dy = Hmat[1][1]; dz = Hmat[2][1];
238 <  dsq = dx*dx + dy*dy + dz*dz;
239 <  boxL[1] = sqrt( dsq );
240 <  //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;
247 <  boxL[2] = sqrt( dsq );
248 <  //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];
261 <  double rij[3], rjk[3], rki[3];
262 <  double minDist;
439 >  }
440  
264  ri[0] = Hmat[0][0];
265  ri[1] = Hmat[1][0];
266  ri[2] = Hmat[2][0];
441  
442 <  rj[0] = Hmat[0][1];
443 <  rj[1] = Hmat[1][1];
270 <  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];
274 <  rk[2] = Hmat[2][2];
275 <    
276 <  crossProduct3(ri, rj, rij);
277 <  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);
283 <  distZX = dotProduct3(rj,rki) / norm3(rki);
452 >  void SimInfo::update() {
453  
454 <  minDist = min(min(distXY, distYZ), distZX);
286 <  return minDist/2;
287 <  
288 < }
454 >    setupSimType();
455  
456 < void SimInfo::wrapVector( double thePos[3] ){
456 > #ifdef IS_MPI
457 >    setupFortranParallel();
458 > #endif
459  
460 <  int i;
293 <  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    
298
299    matVecMul3(HmatInv, thePos, scaled);
473      
474 <    for(i=0; i<3; i++)
302 <      scaled[i] -= roundMe(scaled[i]);
303 <    
304 <    // calc the wrapped real coordinates from the wrapped scaled coordinates
305 <    
306 <    matVecMul3(Hmat, scaled, thePos);
474 >    setupCutoff();
475  
476 +    calcNdf();
477 +    calcNdfRaw();
478 +    calcNdfTrans();
479 +
480 +    fortranInitialized_ = true;
481    }
309  else{
310    // calc the scaled coordinates.
311    
312    for(i=0; i<3; i++)
313      scaled[i] = thePos[i]*HmatInv[i][i];
314    
315    // wrap the scaled coordinates
316    
317    for(i=0; i<3; i++)
318      scaled[i] -= roundMe(scaled[i]);
319    
320    // calc the wrapped real coordinates from the wrapped scaled coordinates
321    
322    for(i=0; i<3; i++)
323      thePos[i] = scaled[i]*Hmat[i][i];
324  }
325    
326 }
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(){
330 <  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;
336 <    if (integrableObjects[i]->isDirectional()) {
337 <      if (integrableObjects[i]->isLinear())
338 <        ndf_local += 2;
339 <      else
340 <        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;
370 <    if (integrableObjects[i]->isDirectional()) {
371 <       if (integrableObjects[i]->isLinear())
372 <        ndfRaw_local += 2;
373 <      else
374 <        ndfRaw_local += 3;
375 <    }
376 <  }
377 <    
378 < #ifdef IS_MPI
379 <  MPI_Allreduce(&ndfRaw_local,&ndfRaw,1,MPI_INT,MPI_SUM, MPI_COMM_WORLD);
380 < #else
381 <  ndfRaw = ndfRaw_local;
382 < #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);
395 < #else
396 <  ndfTrans = ndfTrans_local;
397 < #endif
567 >    temp = useGayBerne;
568 >    MPI_Allreduce(&temp, &useGayBerne, 1, MPI_INT, MPI_LOR, MPI_COMM_WORLD);    
569  
570 <  ndfTrans = ndfTrans - 3 - nZconstraints;
570 >    temp = useEAM;
571 >    MPI_Allreduce(&temp, &useEAM, 1, MPI_INT, MPI_LOR, MPI_COMM_WORLD);    
572  
573 <  return ndfTrans;
574 < }
573 >    temp = useShape;
574 >    MPI_Allreduce(&temp, &useShape, 1, MPI_INT, MPI_LOR, MPI_COMM_WORLD);  
575  
576 < int SimInfo::getTotIntegrableObjects() {
577 <  int nObjs_local;
406 <  int nObjs;
576 >    temp = useFLARB;
577 >    MPI_Allreduce(&temp, &useFLARB, 1, MPI_INT, MPI_LOR, MPI_COMM_WORLD);    
578  
579 <  nObjs_local =  integrableObjects.size();
580 <
581 <
411 < #ifdef IS_MPI
412 <  MPI_Allreduce(&nObjs_local,&nObjs,1,MPI_INT,MPI_SUM, MPI_COMM_WORLD);
413 < #else
414 <  nObjs = nObjs_local;
579 >    temp = useRF;
580 >    MPI_Allreduce(&temp, &useRF, 1, MPI_INT, MPI_LOR, MPI_COMM_WORLD);    
581 >    
582   #endif
583  
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 nObjs;
419 < }
597 >    if( fInfo_.SIM_uses_Dipoles && fInfo_.SIM_uses_RF) {
598  
599 < void SimInfo::refreshSim(){
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  
423  simtype fInfo;
424  int isError;
425  int n_global;
426  int* excl;
427
428  fInfo.dielect = 0.0;
429
430  if( useDipoles ){
431    if( useReactionField )fInfo.dielect = dielectric;
614    }
615  
616 <  fInfo.SIM_uses_PBC = usePBC;
617 <  //fInfo.SIM_uses_LJ = 0;
618 <  fInfo.SIM_uses_LJ = useLJ;
619 <  fInfo.SIM_uses_sticky = useSticky;
620 <  //fInfo.SIM_uses_sticky = 0;
621 <  fInfo.SIM_uses_charges = useCharges;
622 <  fInfo.SIM_uses_dipoles = useDipoles;
441 <  //fInfo.SIM_uses_dipoles = 0;
442 <  fInfo.SIM_uses_RF = useReactionField;
443 <  //fInfo.SIM_uses_RF = 0;
444 <  fInfo.SIM_uses_GB = useGB;
445 <  fInfo.SIM_uses_EAM = useEAM;
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 <  n_exclude = excludes->getSize();
625 <  excl = excludes->getFortranArray();
626 <  
627 < #ifdef IS_MPI
451 <  n_global = mpiSim->getNAtomsGlobal();
452 < #else
453 <  n_global = n_atoms;
454 < #endif
455 <  
456 <  isError = 0;
457 <  
458 <  getFortranGroupArrays(this, FglobalGroupMembership, mfact);
459 <  //it may not be a good idea to pass the address of first element in vector
460 <  //since c++ standard does not require vector to be stored continuously in meomory
461 <  //Most of the compilers will organize the memory of vector continuously
462 <  setFsimulation( &fInfo, &n_global, &n_atoms, identArray, &n_exclude, excl,
463 <                  &nGlobalExcludes, globalExcludes, molMembershipArray,
464 <                  &mfact[0], &ngroup, &FglobalGroupMembership[0], &isError);
624 >    //globalGroupMembership_ is filled by SimCreator    
625 >    for (int i = 0; i < nGlobalAtoms_; i++) {
626 >      fortranGlobalGroupMembership.push_back(globalGroupMembership_[i] + 1);
627 >    }
628  
629 <  if( isError ){
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 >    //to avoid memory reallocation, reserve enough space for mfact
640 >    mfact.reserve(getNCutoffGroups());
641      
642 <    sprintf( painCave.errMsg,
643 <             "There was an error setting the simulation information in fortran.\n" );
470 <    painCave.isFatal = 1;
471 <    painCave.severity = OOPSE_ERROR;
472 <    simError();
473 <  }
474 <  
475 < #ifdef IS_MPI
476 <  sprintf( checkPointMsg,
477 <           "succesfully sent the simulation information to fortran.\n");
478 <  MPIcheckPoint();
479 < #endif // is_mpi
480 <  
481 <  this->ndf = this->getNDF();
482 <  this->ndfRaw = this->getNDFraw();
483 <  this->ndfTrans = this->getNDFtranslational();
484 < }
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::setDefaultRcut( double theRcut ){
646 <  
647 <  haveRcut = 1;
648 <  rCut = theRcut;
490 <  rList = rCut + 1.0;
491 <  
492 <  notifyFortranCutOffs( &rCut, &rSw, &rList );
493 < }
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 < void SimInfo::setDefaultRcut( double theRcut, double theRsw ){
650 >      }      
651 >    }
652  
653 <  rSw = theRsw;
654 <  setDefaultRcut( theRcut );
499 < }
653 >    //fill ident array of local atoms (it is actually ident of AtomType, it is so confusing !!!)
654 >    std::vector<int> identArray;
655  
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 < void SimInfo::checkCutOffs( void ){
666 <  
667 <  if( boxIsInit ){
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 <    //we need to check cutOffs against the box
673 <    
674 <    if( rCut > maxCutoff ){
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( isError ){
681 >
682        sprintf( painCave.errMsg,
683 <               "cutoffRadius is too large for the current periodic box.\n"
511 <               "\tCurrent Value of cutoffRadius = %G at time %G\n "
512 <               "\tThis is larger than half of at least one of the\n"
513 <               "\tperiodic box vectors.  Right now, the Box matrix is:\n"
514 <               "\n"
515 <               "\t[ %G %G %G ]\n"
516 <               "\t[ %G %G %G ]\n"
517 <               "\t[ %G %G %G ]\n",
518 <               rCut, currentTime,
519 <               Hmat[0][0], Hmat[0][1], Hmat[0][2],
520 <               Hmat[1][0], Hmat[1][1], Hmat[1][2],
521 <               Hmat[2][0], Hmat[2][1], Hmat[2][2]);
522 <      painCave.severity = OOPSE_ERROR;
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 <  } else {
689 <    // initialize this stuff before using it, OK?
690 <    sprintf( painCave.errMsg,
691 <             "Trying to check cutoffs without a box.\n"
692 <             "\tOOPSE should have better programmers than that.\n" );
693 <    painCave.severity = OOPSE_ERROR;
532 <    painCave.isFatal = 1;
533 <    simError();      
687 >    }
688 >
689 > #ifdef IS_MPI
690 >    sprintf( checkPointMsg,
691 >             "succesfully sent the simulation information to fortran.\n");
692 >    MPIcheckPoint();
693 > #endif // is_mpi
694    }
535  
536 }
695  
538 void SimInfo::addProperty(GenericData* prop){
696  
697 <  map<string, GenericData*>::iterator result;
698 <  result = properties.find(prop->getID());
542 <  
543 <  //we can't simply use  properties[prop->getID()] = prop,
544 <  //it will cause memory leak if we already contain a propery which has the same name of prop
545 <  
546 <  if(result != properties.end()){
697 > #ifdef IS_MPI
698 >  void SimInfo::setupFortranParallel() {
699      
700 <    delete (*result).second;
701 <    (*result).second = prop;
702 <      
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 >    for (mol = beginMolecule(mi); mol != NULL; mol  = nextMolecule(mi)) {
713 >
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 >      //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 >    //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 >
748 >    sprintf(checkPointMsg, " mpiRefresh successful.\n");
749 >    MPIcheckPoint();
750 >
751 >
752    }
552  else{
753  
754 <    properties[prop->getID()] = prop;
754 > #endif
755  
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 < }
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 < GenericData* SimInfo::getProperty(const string& propName){
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 >  }
826 >
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 <  map<string, GenericData*>::iterator result;
874 <  
875 <  //string lowerCaseName = ();
876 <  
877 <  result = properties.find(propName);
878 <  
879 <  if(result != properties.end())
880 <    return (*result).second;  
881 <  else  
882 <    return NULL;  
883 < }
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 >  }
885  
886 +  Vector3d SimInfo::getComVel(){
887 +    SimInfo::MoleculeIterator i;
888 +    Molecule* mol;
889  
890 < void SimInfo::getFortranGroupArrays(SimInfo* info,
891 <                                    vector<int>& FglobalGroupMembership,
892 <                                    vector<double>& mfact){
893 <  
894 <  Molecule* myMols;
895 <  Atom** myAtoms;
896 <  int numAtom;
897 <  double mtot;
898 <  int numMol;
584 <  int numCutoffGroups;
585 <  CutoffGroup* myCutoffGroup;
586 <  vector<CutoffGroup*>::iterator iterCutoff;
587 <  Atom* cutoffAtom;
588 <  vector<Atom*>::iterator iterAtom;
589 <  int atomIndex;
590 <  double totalMass;
591 <  
592 <  mfact.clear();
593 <  FglobalGroupMembership.clear();
594 <  
890 >    Vector3d comVel(0.0);
891 >    double totalMass = 0.0;
892 >    
893 >
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  
596  // Fix the silly fortran indexing problem
900   #ifdef IS_MPI
901 <  numAtom = mpiSim->getNAtomsGlobal();
902 < #else
903 <  numAtom = n_atoms;
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
602  for (int i = 0; i < numAtom; i++)
603    FglobalGroupMembership.push_back(globalGroupMembership[i] + 1);
604  
906  
907 <  myMols = info->molecules;
607 <  numMol = info->n_mol;
608 <  for(int i  = 0; i < numMol; i++){
609 <    numCutoffGroups = myMols[i].getNCutoffGroups();
610 <    for(myCutoffGroup =myMols[i].beginCutoffGroup(iterCutoff);
611 <        myCutoffGroup != NULL;
612 <        myCutoffGroup =myMols[i].nextCutoffGroup(iterCutoff)){
907 >    comVel /= totalMass;
908  
909 <      totalMass = myCutoffGroup->getMass();
615 <      
616 <      for(cutoffAtom = myCutoffGroup->beginAtom(iterAtom);
617 <          cutoffAtom != NULL;
618 <          cutoffAtom = myCutoffGroup->nextAtom(iterAtom)){
619 <        mfact.push_back(cutoffAtom->getMass()/totalMass);
620 <      }  
621 <    }
909 >    return comVel;
910    }
911  
912 < }
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 >    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
931 >
932 >    com /= totalMass;
933 >
934 >    return com;
935 >
936 >  }        
937 >
938 >  std::ostream& operator <<(std::ostream& o, SimInfo& info) {
939 >
940 >    return o;
941 >  }
942 >
943 > }//end namespace oopse
944 >

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines