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

Comparing:
trunk/src/brains/SimInfo.cpp (file contents), Revision 3 by tim, Fri Sep 24 16:27:58 2004 UTC vs.
branches/development/src/brains/SimInfo.cpp (file contents), Revision 1530 by gezelter, Tue Dec 28 21:47:55 2010 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. Redistributions of source code must retain the above copyright
10 > *    notice, this list of conditions and the following disclaimer.
11 > *
12 > * 2. Redistributions in binary form must reproduce the above copyright
13 > *    notice, this list of conditions and the following disclaimer in the
14 > *    documentation and/or other materials provided with the
15 > *    distribution.
16 > *
17 > * This software is provided "AS IS," without a warranty of any
18 > * kind. All express or implied conditions, representations and
19 > * warranties, including any implied warranty of merchantability,
20 > * fitness for a particular purpose or non-infringement, are hereby
21 > * excluded.  The University of Notre Dame and its licensors shall not
22 > * be liable for any damages suffered by licensee as a result of
23 > * using, modifying or distributing the software or its
24 > * derivatives. In no event will the University of Notre Dame or its
25 > * licensors be liable for any lost revenue, profit or data, or for
26 > * direct, indirect, special, consequential, incidental or punitive
27 > * damages, however caused and regardless of the theory of liability,
28 > * arising out of the use of or inability to use software, even if the
29 > * University of Notre Dame has been advised of the possibility of
30 > * such damages.
31 > *
32 > * SUPPORT OPEN SCIENCE!  If you use OpenMD or its source code in your
33 > * research, please cite the appropriate papers when you publish your
34 > * work.  Good starting points are:
35 > *                                                                      
36 > * [1]  Meineke, et al., J. Comp. Chem. 26, 252-271 (2005).            
37 > * [2]  Fennell & Gezelter, J. Chem. Phys. 124, 234104 (2006).          
38 > * [3]  Sun, Lin & Gezelter, J. Chem. Phys. 128, 24107 (2008).          
39 > * [4]  Vardeman & Gezelter, in progress (2009).                        
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 > #include <map>
52  
53   #include "brains/SimInfo.hpp"
54 < #define __C
55 < #include "brains/fSimulation.h"
54 > #include "math/Vector3.hpp"
55 > #include "primitives/Molecule.hpp"
56 > #include "primitives/StuntDouble.hpp"
57 > #include "UseTheForce/fCutoffPolicy.h"
58 > #include "UseTheForce/doForces_interface.h"
59 > #include "UseTheForce/DarkSide/neighborLists_interface.h"
60 > #include "utils/MemoryUtils.hpp"
61   #include "utils/simError.h"
62 + #include "selection/SelectionManager.hpp"
63 + #include "io/ForceFieldOptions.hpp"
64 + #include "UseTheForce/ForceField.hpp"
65 + #include "nonbonded/SwitchingFunction.hpp"
66  
13 #include "UseTheForce/fortranWrappers.hpp"
67  
15 #include "math/MatVec3.h"
16
68   #ifdef IS_MPI
69 < #include "brains/mpiSimulation.hpp"
70 < #endif
69 > #include "UseTheForce/mpiComponentPlan.h"
70 > #include "UseTheForce/DarkSide/simParallel_interface.h"
71 > #endif
72  
73 < inline double roundMe( double x ){
74 <  return ( x >= 0 ) ? floor( x + 0.5 ) : ceil( x - 0.5 );
75 < }
76 <          
77 < inline double min( double a, double b ){
78 <  return (a < b ) ? a : b;
79 < }
73 > using namespace std;
74 > namespace OpenMD {
75 >  
76 >  SimInfo::SimInfo(ForceField* ff, Globals* simParams) :
77 >    forceField_(ff), simParams_(simParams),
78 >    ndf_(0), fdf_local(0), ndfRaw_(0), ndfTrans_(0), nZconstraint_(0),
79 >    nGlobalMols_(0), nGlobalAtoms_(0), nGlobalCutoffGroups_(0),
80 >    nGlobalIntegrableObjects_(0), nGlobalRigidBodies_(0),
81 >    nAtoms_(0), nBonds_(0),  nBends_(0), nTorsions_(0), nInversions_(0),
82 >    nRigidBodies_(0), nIntegrableObjects_(0), nCutoffGroups_(0),
83 >    nConstraints_(0), sman_(NULL), fortranInitialized_(false),
84 >    calcBoxDipole_(false), useAtomicVirial_(true) {    
85 >    
86 >    MoleculeStamp* molStamp;
87 >    int nMolWithSameStamp;
88 >    int nCutoffAtoms = 0; // number of atoms belong to cutoff groups
89 >    int nGroups = 0;       //total cutoff groups defined in meta-data file
90 >    CutoffGroupStamp* cgStamp;    
91 >    RigidBodyStamp* rbStamp;
92 >    int nRigidAtoms = 0;
93 >    
94 >    vector<Component*> components = simParams->getComponents();
95 >    
96 >    for (vector<Component*>::iterator i = components.begin(); i !=components.end(); ++i) {
97 >      molStamp = (*i)->getMoleculeStamp();
98 >      nMolWithSameStamp = (*i)->getNMol();
99 >      
100 >      addMoleculeStamp(molStamp, nMolWithSameStamp);
101 >      
102 >      //calculate atoms in molecules
103 >      nGlobalAtoms_ += molStamp->getNAtoms() *nMolWithSameStamp;  
104 >      
105 >      //calculate atoms in cutoff groups
106 >      int nAtomsInGroups = 0;
107 >      int nCutoffGroupsInStamp = molStamp->getNCutoffGroups();
108 >      
109 >      for (int j=0; j < nCutoffGroupsInStamp; j++) {
110 >        cgStamp = molStamp->getCutoffGroupStamp(j);
111 >        nAtomsInGroups += cgStamp->getNMembers();
112 >      }
113 >      
114 >      nGroups += nCutoffGroupsInStamp * nMolWithSameStamp;
115 >      
116 >      nCutoffAtoms += nAtomsInGroups * nMolWithSameStamp;            
117 >      
118 >      //calculate atoms in rigid bodies
119 >      int nAtomsInRigidBodies = 0;
120 >      int nRigidBodiesInStamp = molStamp->getNRigidBodies();
121 >      
122 >      for (int j=0; j < nRigidBodiesInStamp; j++) {
123 >        rbStamp = molStamp->getRigidBodyStamp(j);
124 >        nAtomsInRigidBodies += rbStamp->getNMembers();
125 >      }
126 >      
127 >      nGlobalRigidBodies_ += nRigidBodiesInStamp * nMolWithSameStamp;
128 >      nRigidAtoms += nAtomsInRigidBodies * nMolWithSameStamp;            
129 >      
130 >    }
131 >    
132 >    //every free atom (atom does not belong to cutoff groups) is a cutoff
133 >    //group therefore the total number of cutoff groups in the system is
134 >    //equal to the total number of atoms minus number of atoms belong to
135 >    //cutoff group defined in meta-data file plus the number of cutoff
136 >    //groups defined in meta-data file
137 >    nGlobalCutoffGroups_ = nGlobalAtoms_ - nCutoffAtoms + nGroups;
138 >    
139 >    //every free atom (atom does not belong to rigid bodies) is an
140 >    //integrable object therefore the total number of integrable objects
141 >    //in the system is equal to the total number of atoms minus number of
142 >    //atoms belong to rigid body defined in meta-data file plus the number
143 >    //of rigid bodies defined in meta-data file
144 >    nGlobalIntegrableObjects_ = nGlobalAtoms_ - nRigidAtoms
145 >      + nGlobalRigidBodies_;
146 >    
147 >    nGlobalMols_ = molStampIds_.size();
148 >    molToProcMap_.resize(nGlobalMols_);
149 >  }
150 >  
151 >  SimInfo::~SimInfo() {
152 >    map<int, Molecule*>::iterator i;
153 >    for (i = molecules_.begin(); i != molecules_.end(); ++i) {
154 >      delete i->second;
155 >    }
156 >    molecules_.clear();
157 >      
158 >    delete sman_;
159 >    delete simParams_;
160 >    delete forceField_;
161 >  }
162  
29 SimInfo* currentInfo;
163  
164 < SimInfo::SimInfo(){
165 <
166 <  n_constraints = 0;
167 <  nZconstraints = 0;
168 <  n_oriented = 0;
169 <  n_dipoles = 0;
170 <  ndf = 0;
171 <  ndfRaw = 0;
172 <  nZconstraints = 0;
173 <  the_integrator = NULL;
174 <  setTemp = 0;
175 <  thermalTime = 0.0;
176 <  currentTime = 0.0;
177 <  rCut = 0.0;
178 <  rSw = 0.0;
179 <
180 <  haveRcut = 0;
181 <  haveRsw = 0;
182 <  boxIsInit = 0;
164 >  bool SimInfo::addMolecule(Molecule* mol) {
165 >    MoleculeIterator i;
166 >    
167 >    i = molecules_.find(mol->getGlobalIndex());
168 >    if (i == molecules_.end() ) {
169 >      
170 >      molecules_.insert(make_pair(mol->getGlobalIndex(), mol));
171 >      
172 >      nAtoms_ += mol->getNAtoms();
173 >      nBonds_ += mol->getNBonds();
174 >      nBends_ += mol->getNBends();
175 >      nTorsions_ += mol->getNTorsions();
176 >      nInversions_ += mol->getNInversions();
177 >      nRigidBodies_ += mol->getNRigidBodies();
178 >      nIntegrableObjects_ += mol->getNIntegrableObjects();
179 >      nCutoffGroups_ += mol->getNCutoffGroups();
180 >      nConstraints_ += mol->getNConstraintPairs();
181 >      
182 >      addInteractionPairs(mol);
183 >      
184 >      return true;
185 >    } else {
186 >      return false;
187 >    }
188 >  }
189    
190 <  resetTime = 1e99;
190 >  bool SimInfo::removeMolecule(Molecule* mol) {
191 >    MoleculeIterator i;
192 >    i = molecules_.find(mol->getGlobalIndex());
193  
194 <  orthoRhombic = 0;
54 <  orthoTolerance = 1E-6;
55 <  useInitXSstate = true;
194 >    if (i != molecules_.end() ) {
195  
196 <  usePBC = 0;
197 <  useLJ = 0;
198 <  useSticky = 0;
199 <  useCharges = 0;
200 <  useDipoles = 0;
201 <  useReactionField = 0;
202 <  useGB = 0;
203 <  useEAM = 0;
204 <  useSolidThermInt = 0;
205 <  useLiquidThermInt = 0;
196 >      assert(mol == i->second);
197 >        
198 >      nAtoms_ -= mol->getNAtoms();
199 >      nBonds_ -= mol->getNBonds();
200 >      nBends_ -= mol->getNBends();
201 >      nTorsions_ -= mol->getNTorsions();
202 >      nInversions_ -= mol->getNInversions();
203 >      nRigidBodies_ -= mol->getNRigidBodies();
204 >      nIntegrableObjects_ -= mol->getNIntegrableObjects();
205 >      nCutoffGroups_ -= mol->getNCutoffGroups();
206 >      nConstraints_ -= mol->getNConstraintPairs();
207  
208 <  haveCutoffGroups = false;
208 >      removeInteractionPairs(mol);
209 >      molecules_.erase(mol->getGlobalIndex());
210  
211 <  excludes = Exclude::Instance();
212 <
213 <  myConfiguration = new SimState();
214 <
215 <  has_minimizer = false;
216 <  the_minimizer =NULL;
217 <
77 <  ngroup = 0;
78 <
79 <  wrapMeSimInfo( this );
80 < }
211 >      delete mol;
212 >        
213 >      return true;
214 >    } else {
215 >      return false;
216 >    }
217 >  }    
218  
219 +        
220 +  Molecule* SimInfo::beginMolecule(MoleculeIterator& i) {
221 +    i = molecules_.begin();
222 +    return i == molecules_.end() ? NULL : i->second;
223 +  }    
224  
225 < SimInfo::~SimInfo(){
225 >  Molecule* SimInfo::nextMolecule(MoleculeIterator& i) {
226 >    ++i;
227 >    return i == molecules_.end() ? NULL : i->second;    
228 >  }
229  
85  delete myConfiguration;
230  
231 <  map<string, GenericData*>::iterator i;
232 <  
233 <  for(i = properties.begin(); i != properties.end(); i++)
234 <    delete (*i).second;
231 >  void SimInfo::calcNdf() {
232 >    int ndf_local;
233 >    MoleculeIterator i;
234 >    vector<StuntDouble*>::iterator j;
235 >    Molecule* mol;
236 >    StuntDouble* integrableObject;
237  
238 < }
238 >    ndf_local = 0;
239 >    
240 >    for (mol = beginMolecule(i); mol != NULL; mol = nextMolecule(i)) {
241 >      for (integrableObject = mol->beginIntegrableObject(j); integrableObject != NULL;
242 >           integrableObject = mol->nextIntegrableObject(j)) {
243  
244 < void SimInfo::setBox(double newBox[3]) {
95 <  
96 <  int i, j;
97 <  double tempMat[3][3];
244 >        ndf_local += 3;
245  
246 <  for(i=0; i<3; i++)
247 <    for (j=0; j<3; j++) tempMat[i][j] = 0.0;;
246 >        if (integrableObject->isDirectional()) {
247 >          if (integrableObject->isLinear()) {
248 >            ndf_local += 2;
249 >          } else {
250 >            ndf_local += 3;
251 >          }
252 >        }
253 >            
254 >      }
255 >    }
256 >    
257 >    // n_constraints is local, so subtract them on each processor
258 >    ndf_local -= nConstraints_;
259  
260 <  tempMat[0][0] = newBox[0];
261 <  tempMat[1][1] = newBox[1];
262 <  tempMat[2][2] = newBox[2];
260 > #ifdef IS_MPI
261 >    MPI_Allreduce(&ndf_local,&ndf_,1,MPI_INT,MPI_SUM, MPI_COMM_WORLD);
262 > #else
263 >    ndf_ = ndf_local;
264 > #endif
265  
266 <  setBoxM( tempMat );
266 >    // nZconstraints_ is global, as are the 3 COM translations for the
267 >    // entire system:
268 >    ndf_ = ndf_ - 3 - nZconstraint_;
269  
270 < }
270 >  }
271  
272 < void SimInfo::setBoxM( double theBox[3][3] ){
273 <  
274 <  int i, j;
275 <  double FortranHmat[9]; // to preserve compatibility with Fortran the
276 <                         // ordering in the array is as follows:
277 <                         // [ 0 3 6 ]
278 <                         // [ 1 4 7 ]
117 <                         // [ 2 5 8 ]
118 <  double FortranHmatInv[9]; // the inverted Hmat (for Fortran);
119 <
120 <  if( !boxIsInit ) boxIsInit = 1;
121 <
122 <  for(i=0; i < 3; i++)
123 <    for (j=0; j < 3; j++) Hmat[i][j] = theBox[i][j];
124 <  
125 <  calcBoxL();
126 <  calcHmatInv();
127 <
128 <  for(i=0; i < 3; i++) {
129 <    for (j=0; j < 3; j++) {
130 <      FortranHmat[3*j + i] = Hmat[i][j];
131 <      FortranHmatInv[3*j + i] = HmatInv[i][j];
132 <    }
272 >  int SimInfo::getFdf() {
273 > #ifdef IS_MPI
274 >    MPI_Allreduce(&fdf_local,&fdf_,1,MPI_INT,MPI_SUM, MPI_COMM_WORLD);
275 > #else
276 >    fdf_ = fdf_local;
277 > #endif
278 >    return fdf_;
279    }
280 +    
281 +  void SimInfo::calcNdfRaw() {
282 +    int ndfRaw_local;
283  
284 <  setFortranBoxSize(FortranHmat, FortranHmatInv, &orthoRhombic);
285 <
286 < }
287 <
284 >    MoleculeIterator i;
285 >    vector<StuntDouble*>::iterator j;
286 >    Molecule* mol;
287 >    StuntDouble* integrableObject;
288  
289 < void SimInfo::getBoxM (double theBox[3][3]) {
289 >    // Raw degrees of freedom that we have to set
290 >    ndfRaw_local = 0;
291 >    
292 >    for (mol = beginMolecule(i); mol != NULL; mol = nextMolecule(i)) {
293 >      for (integrableObject = mol->beginIntegrableObject(j); integrableObject != NULL;
294 >           integrableObject = mol->nextIntegrableObject(j)) {
295  
296 <  int i, j;
143 <  for(i=0; i<3; i++)
144 <    for (j=0; j<3; j++) theBox[i][j] = Hmat[i][j];
145 < }
296 >        ndfRaw_local += 3;
297  
298 <
299 < void SimInfo::scaleBox(double scale) {
300 <  double theBox[3][3];
301 <  int i, j;
302 <
303 <  // cerr << "Scaling box by " << scale << "\n";
304 <
305 <  for(i=0; i<3; i++)
155 <    for (j=0; j<3; j++) theBox[i][j] = Hmat[i][j]*scale;
156 <
157 <  setBoxM(theBox);
158 <
159 < }
160 <
161 < void SimInfo::calcHmatInv( void ) {
162 <  
163 <  int oldOrtho;
164 <  int i,j;
165 <  double smallDiag;
166 <  double tol;
167 <  double sanity[3][3];
168 <
169 <  invertMat3( Hmat, HmatInv );
170 <
171 <  // check to see if Hmat is orthorhombic
172 <  
173 <  oldOrtho = orthoRhombic;
174 <
175 <  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;
179 <
180 <  orthoRhombic = 1;
181 <  
182 <  for (i = 0; i < 3; i++ ) {
183 <    for (j = 0 ; j < 3; j++) {
184 <      if (i != j) {
185 <        if (orthoRhombic) {
186 <          if ( fabs(Hmat[i][j]) >= tol) orthoRhombic = 0;
187 <        }        
298 >        if (integrableObject->isDirectional()) {
299 >          if (integrableObject->isLinear()) {
300 >            ndfRaw_local += 2;
301 >          } else {
302 >            ndfRaw_local += 3;
303 >          }
304 >        }
305 >            
306        }
307      }
190  }
191
192  if( oldOrtho != orthoRhombic ){
308      
309 <    if( orthoRhombic ) {
310 <      sprintf( painCave.errMsg,
311 <               "OOPSE is switching from the default Non-Orthorhombic\n"
312 <               "\tto the faster Orthorhombic periodic boundary computations.\n"
313 <               "\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();
204 <    }
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 <    }
309 > #ifdef IS_MPI
310 >    MPI_Allreduce(&ndfRaw_local,&ndfRaw_,1,MPI_INT,MPI_SUM, MPI_COMM_WORLD);
311 > #else
312 >    ndfRaw_ = ndfRaw_local;
313 > #endif
314    }
218 }
315  
316 < void SimInfo::calcBoxL( void ){
316 >  void SimInfo::calcNdfTrans() {
317 >    int ndfTrans_local;
318  
319 <  double dx, dy, dz, dsq;
319 >    ndfTrans_local = 3 * nIntegrableObjects_ - nConstraints_;
320  
224  // boxVol = Determinant of Hmat
321  
322 <  boxVol = matDet3( Hmat );
322 > #ifdef IS_MPI
323 >    MPI_Allreduce(&ndfTrans_local,&ndfTrans_,1,MPI_INT,MPI_SUM, MPI_COMM_WORLD);
324 > #else
325 >    ndfTrans_ = ndfTrans_local;
326 > #endif
327  
328 <  // boxLx
329 <  
330 <  dx = Hmat[0][0]; dy = Hmat[1][0]; dz = Hmat[2][0];
231 <  dsq = dx*dx + dy*dy + dz*dz;
232 <  boxL[0] = sqrt( dsq );
233 <  //maxCutoff = 0.5 * boxL[0];
234 <
235 <  // 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];
328 >    ndfTrans_ = ndfTrans_ - 3 - nZconstraint_;
329 >
330 >  }
331  
332 +  void SimInfo::addInteractionPairs(Molecule* mol) {
333 +    ForceFieldOptions& options_ = forceField_->getForceFieldOptions();
334 +    vector<Bond*>::iterator bondIter;
335 +    vector<Bend*>::iterator bendIter;
336 +    vector<Torsion*>::iterator torsionIter;
337 +    vector<Inversion*>::iterator inversionIter;
338 +    Bond* bond;
339 +    Bend* bend;
340 +    Torsion* torsion;
341 +    Inversion* inversion;
342 +    int a;
343 +    int b;
344 +    int c;
345 +    int d;
346  
347 <  // boxLz
348 <  
349 <  dx = Hmat[0][2]; dy = Hmat[1][2]; dz = Hmat[2][2];
350 <  dsq = dx*dx + dy*dy + dz*dz;
351 <  boxL[2] = sqrt( dsq );
352 <  //if( (0.5 * boxL[2]) < maxCutoff ) maxCutoff = 0.5 * boxL[2];
347 >    // atomGroups can be used to add special interaction maps between
348 >    // groups of atoms that are in two separate rigid bodies.
349 >    // However, most site-site interactions between two rigid bodies
350 >    // are probably not special, just the ones between the physically
351 >    // bonded atoms.  Interactions *within* a single rigid body should
352 >    // always be excluded.  These are done at the bottom of this
353 >    // function.
354  
355 <  //calculate the max cutoff
356 <  maxCutoff =  calcMaxCutOff();
357 <  
358 <  checkCutOffs();
355 >    map<int, set<int> > atomGroups;
356 >    Molecule::RigidBodyIterator rbIter;
357 >    RigidBody* rb;
358 >    Molecule::IntegrableObjectIterator ii;
359 >    StuntDouble* integrableObject;
360 >    
361 >    for (integrableObject = mol->beginIntegrableObject(ii);
362 >         integrableObject != NULL;
363 >         integrableObject = mol->nextIntegrableObject(ii)) {
364 >      
365 >      if (integrableObject->isRigidBody()) {
366 >        rb = static_cast<RigidBody*>(integrableObject);
367 >        vector<Atom*> atoms = rb->getAtoms();
368 >        set<int> rigidAtoms;
369 >        for (int i = 0; i < static_cast<int>(atoms.size()); ++i) {
370 >          rigidAtoms.insert(atoms[i]->getGlobalIndex());
371 >        }
372 >        for (int i = 0; i < static_cast<int>(atoms.size()); ++i) {
373 >          atomGroups.insert(map<int, set<int> >::value_type(atoms[i]->getGlobalIndex(), rigidAtoms));
374 >        }      
375 >      } else {
376 >        set<int> oneAtomSet;
377 >        oneAtomSet.insert(integrableObject->getGlobalIndex());
378 >        atomGroups.insert(map<int, set<int> >::value_type(integrableObject->getGlobalIndex(), oneAtomSet));        
379 >      }
380 >    }  
381 >          
382 >    for (bond= mol->beginBond(bondIter); bond != NULL;
383 >         bond = mol->nextBond(bondIter)) {
384  
385 < }
385 >      a = bond->getAtomA()->getGlobalIndex();
386 >      b = bond->getAtomB()->getGlobalIndex();  
387 >    
388 >      if (options_.havevdw12scale() || options_.haveelectrostatic12scale()) {
389 >        oneTwoInteractions_.addPair(a, b);
390 >      } else {
391 >        excludedInteractions_.addPair(a, b);
392 >      }
393 >    }
394  
395 +    for (bend= mol->beginBend(bendIter); bend != NULL;
396 +         bend = mol->nextBend(bendIter)) {
397  
398 < double SimInfo::calcMaxCutOff(){
398 >      a = bend->getAtomA()->getGlobalIndex();
399 >      b = bend->getAtomB()->getGlobalIndex();        
400 >      c = bend->getAtomC()->getGlobalIndex();
401 >      
402 >      if (options_.havevdw12scale() || options_.haveelectrostatic12scale()) {
403 >        oneTwoInteractions_.addPair(a, b);      
404 >        oneTwoInteractions_.addPair(b, c);
405 >      } else {
406 >        excludedInteractions_.addPair(a, b);
407 >        excludedInteractions_.addPair(b, c);
408 >      }
409  
410 <  double ri[3], rj[3], rk[3];
411 <  double rij[3], rjk[3], rki[3];
412 <  double minDist;
410 >      if (options_.havevdw13scale() || options_.haveelectrostatic13scale()) {
411 >        oneThreeInteractions_.addPair(a, c);      
412 >      } else {
413 >        excludedInteractions_.addPair(a, c);
414 >      }
415 >    }
416  
417 <  ri[0] = Hmat[0][0];
418 <  ri[1] = Hmat[1][0];
266 <  ri[2] = Hmat[2][0];
417 >    for (torsion= mol->beginTorsion(torsionIter); torsion != NULL;
418 >         torsion = mol->nextTorsion(torsionIter)) {
419  
420 <  rj[0] = Hmat[0][1];
421 <  rj[1] = Hmat[1][1];
422 <  rj[2] = Hmat[2][1];
420 >      a = torsion->getAtomA()->getGlobalIndex();
421 >      b = torsion->getAtomB()->getGlobalIndex();        
422 >      c = torsion->getAtomC()->getGlobalIndex();        
423 >      d = torsion->getAtomD()->getGlobalIndex();      
424  
425 <  rk[0] = Hmat[0][2];
426 <  rk[1] = Hmat[1][2];
427 <  rk[2] = Hmat[2][2];
428 <    
429 <  crossProduct3(ri, rj, rij);
430 <  distXY = dotProduct3(rk,rij) / norm3(rij);
425 >      if (options_.havevdw12scale() || options_.haveelectrostatic12scale()) {
426 >        oneTwoInteractions_.addPair(a, b);      
427 >        oneTwoInteractions_.addPair(b, c);
428 >        oneTwoInteractions_.addPair(c, d);
429 >      } else {
430 >        excludedInteractions_.addPair(a, b);
431 >        excludedInteractions_.addPair(b, c);
432 >        excludedInteractions_.addPair(c, d);
433 >      }
434  
435 <  crossProduct3(rj,rk, rjk);
436 <  distYZ = dotProduct3(ri,rjk) / norm3(rjk);
435 >      if (options_.havevdw13scale() || options_.haveelectrostatic13scale()) {
436 >        oneThreeInteractions_.addPair(a, c);      
437 >        oneThreeInteractions_.addPair(b, d);      
438 >      } else {
439 >        excludedInteractions_.addPair(a, c);
440 >        excludedInteractions_.addPair(b, d);
441 >      }
442  
443 <  crossProduct3(rk,ri, rki);
444 <  distZX = dotProduct3(rj,rki) / norm3(rki);
443 >      if (options_.havevdw14scale() || options_.haveelectrostatic14scale()) {
444 >        oneFourInteractions_.addPair(a, d);      
445 >      } else {
446 >        excludedInteractions_.addPair(a, d);
447 >      }
448 >    }
449  
450 <  minDist = min(min(distXY, distYZ), distZX);
451 <  return minDist/2;
287 <  
288 < }
450 >    for (inversion= mol->beginInversion(inversionIter); inversion != NULL;
451 >         inversion = mol->nextInversion(inversionIter)) {
452  
453 < void SimInfo::wrapVector( double thePos[3] ){
453 >      a = inversion->getAtomA()->getGlobalIndex();
454 >      b = inversion->getAtomB()->getGlobalIndex();        
455 >      c = inversion->getAtomC()->getGlobalIndex();        
456 >      d = inversion->getAtomD()->getGlobalIndex();        
457  
458 <  int i;
459 <  double scaled[3];
458 >      if (options_.havevdw12scale() || options_.haveelectrostatic12scale()) {
459 >        oneTwoInteractions_.addPair(a, b);      
460 >        oneTwoInteractions_.addPair(a, c);
461 >        oneTwoInteractions_.addPair(a, d);
462 >      } else {
463 >        excludedInteractions_.addPair(a, b);
464 >        excludedInteractions_.addPair(a, c);
465 >        excludedInteractions_.addPair(a, d);
466 >      }
467  
468 <  if( !orthoRhombic ){
469 <    // calc the scaled coordinates.
470 <  
468 >      if (options_.havevdw13scale() || options_.haveelectrostatic13scale()) {
469 >        oneThreeInteractions_.addPair(b, c);    
470 >        oneThreeInteractions_.addPair(b, d);    
471 >        oneThreeInteractions_.addPair(c, d);      
472 >      } else {
473 >        excludedInteractions_.addPair(b, c);
474 >        excludedInteractions_.addPair(b, d);
475 >        excludedInteractions_.addPair(c, d);
476 >      }
477 >    }
478  
479 <    matVecMul3(HmatInv, thePos, scaled);
480 <    
481 <    for(i=0; i<3; i++)
482 <      scaled[i] -= roundMe(scaled[i]);
483 <    
484 <    // calc the wrapped real coordinates from the wrapped scaled coordinates
485 <    
486 <    matVecMul3(Hmat, scaled, thePos);
479 >    for (rb = mol->beginRigidBody(rbIter); rb != NULL;
480 >         rb = mol->nextRigidBody(rbIter)) {
481 >      vector<Atom*> atoms = rb->getAtoms();
482 >      for (int i = 0; i < static_cast<int>(atoms.size()) -1 ; ++i) {
483 >        for (int j = i + 1; j < static_cast<int>(atoms.size()); ++j) {
484 >          a = atoms[i]->getGlobalIndex();
485 >          b = atoms[j]->getGlobalIndex();
486 >          excludedInteractions_.addPair(a, b);
487 >        }
488 >      }
489 >    }        
490  
491    }
492 <  else{
493 <    // calc the scaled coordinates.
492 >
493 >  void SimInfo::removeInteractionPairs(Molecule* mol) {
494 >    ForceFieldOptions& options_ = forceField_->getForceFieldOptions();
495 >    vector<Bond*>::iterator bondIter;
496 >    vector<Bend*>::iterator bendIter;
497 >    vector<Torsion*>::iterator torsionIter;
498 >    vector<Inversion*>::iterator inversionIter;
499 >    Bond* bond;
500 >    Bend* bend;
501 >    Torsion* torsion;
502 >    Inversion* inversion;
503 >    int a;
504 >    int b;
505 >    int c;
506 >    int d;
507 >
508 >    map<int, set<int> > atomGroups;
509 >    Molecule::RigidBodyIterator rbIter;
510 >    RigidBody* rb;
511 >    Molecule::IntegrableObjectIterator ii;
512 >    StuntDouble* integrableObject;
513      
514 <    for(i=0; i<3; i++)
515 <      scaled[i] = thePos[i]*HmatInv[i][i];
514 >    for (integrableObject = mol->beginIntegrableObject(ii);
515 >         integrableObject != NULL;
516 >         integrableObject = mol->nextIntegrableObject(ii)) {
517 >      
518 >      if (integrableObject->isRigidBody()) {
519 >        rb = static_cast<RigidBody*>(integrableObject);
520 >        vector<Atom*> atoms = rb->getAtoms();
521 >        set<int> rigidAtoms;
522 >        for (int i = 0; i < static_cast<int>(atoms.size()); ++i) {
523 >          rigidAtoms.insert(atoms[i]->getGlobalIndex());
524 >        }
525 >        for (int i = 0; i < static_cast<int>(atoms.size()); ++i) {
526 >          atomGroups.insert(map<int, set<int> >::value_type(atoms[i]->getGlobalIndex(), rigidAtoms));
527 >        }      
528 >      } else {
529 >        set<int> oneAtomSet;
530 >        oneAtomSet.insert(integrableObject->getGlobalIndex());
531 >        atomGroups.insert(map<int, set<int> >::value_type(integrableObject->getGlobalIndex(), oneAtomSet));        
532 >      }
533 >    }  
534 >
535 >    for (bond= mol->beginBond(bondIter); bond != NULL;
536 >         bond = mol->nextBond(bondIter)) {
537 >      
538 >      a = bond->getAtomA()->getGlobalIndex();
539 >      b = bond->getAtomB()->getGlobalIndex();  
540      
541 <    // wrap the scaled coordinates
542 <    
543 <    for(i=0; i<3; i++)
544 <      scaled[i] -= roundMe(scaled[i]);
545 <    
546 <    // 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 < }
541 >      if (options_.havevdw12scale() || options_.haveelectrostatic12scale()) {
542 >        oneTwoInteractions_.removePair(a, b);
543 >      } else {
544 >        excludedInteractions_.removePair(a, b);
545 >      }
546 >    }
547  
548 +    for (bend= mol->beginBend(bendIter); bend != NULL;
549 +         bend = mol->nextBend(bendIter)) {
550  
551 < int SimInfo::getNDF(){
552 <  int ndf_local;
551 >      a = bend->getAtomA()->getGlobalIndex();
552 >      b = bend->getAtomB()->getGlobalIndex();        
553 >      c = bend->getAtomC()->getGlobalIndex();
554 >      
555 >      if (options_.havevdw12scale() || options_.haveelectrostatic12scale()) {
556 >        oneTwoInteractions_.removePair(a, b);      
557 >        oneTwoInteractions_.removePair(b, c);
558 >      } else {
559 >        excludedInteractions_.removePair(a, b);
560 >        excludedInteractions_.removePair(b, c);
561 >      }
562  
563 <  ndf_local = 0;
563 >      if (options_.havevdw13scale() || options_.haveelectrostatic13scale()) {
564 >        oneThreeInteractions_.removePair(a, c);      
565 >      } else {
566 >        excludedInteractions_.removePair(a, c);
567 >      }
568 >    }
569 >
570 >    for (torsion= mol->beginTorsion(torsionIter); torsion != NULL;
571 >         torsion = mol->nextTorsion(torsionIter)) {
572 >
573 >      a = torsion->getAtomA()->getGlobalIndex();
574 >      b = torsion->getAtomB()->getGlobalIndex();        
575 >      c = torsion->getAtomC()->getGlobalIndex();        
576 >      d = torsion->getAtomD()->getGlobalIndex();      
577    
578 <  for(int i = 0; i < integrableObjects.size(); i++){
579 <    ndf_local += 3;
580 <    if (integrableObjects[i]->isDirectional()) {
581 <      if (integrableObjects[i]->isLinear())
582 <        ndf_local += 2;
583 <      else
584 <        ndf_local += 3;
578 >      if (options_.havevdw12scale() || options_.haveelectrostatic12scale()) {
579 >        oneTwoInteractions_.removePair(a, b);      
580 >        oneTwoInteractions_.removePair(b, c);
581 >        oneTwoInteractions_.removePair(c, d);
582 >      } else {
583 >        excludedInteractions_.removePair(a, b);
584 >        excludedInteractions_.removePair(b, c);
585 >        excludedInteractions_.removePair(c, d);
586 >      }
587 >
588 >      if (options_.havevdw13scale() || options_.haveelectrostatic13scale()) {
589 >        oneThreeInteractions_.removePair(a, c);      
590 >        oneThreeInteractions_.removePair(b, d);      
591 >      } else {
592 >        excludedInteractions_.removePair(a, c);
593 >        excludedInteractions_.removePair(b, d);
594 >      }
595 >
596 >      if (options_.havevdw14scale() || options_.haveelectrostatic14scale()) {
597 >        oneFourInteractions_.removePair(a, d);      
598 >      } else {
599 >        excludedInteractions_.removePair(a, d);
600 >      }
601      }
342  }
602  
603 <  // n_constraints is local, so subtract them on each processor:
603 >    for (inversion= mol->beginInversion(inversionIter); inversion != NULL;
604 >         inversion = mol->nextInversion(inversionIter)) {
605  
606 <  ndf_local -= n_constraints;
606 >      a = inversion->getAtomA()->getGlobalIndex();
607 >      b = inversion->getAtomB()->getGlobalIndex();        
608 >      c = inversion->getAtomC()->getGlobalIndex();        
609 >      d = inversion->getAtomD()->getGlobalIndex();        
610  
611 < #ifdef IS_MPI
612 <  MPI_Allreduce(&ndf_local,&ndf,1,MPI_INT,MPI_SUM, MPI_COMM_WORLD);
613 < #else
614 <  ndf = ndf_local;
615 < #endif
611 >      if (options_.havevdw12scale() || options_.haveelectrostatic12scale()) {
612 >        oneTwoInteractions_.removePair(a, b);      
613 >        oneTwoInteractions_.removePair(a, c);
614 >        oneTwoInteractions_.removePair(a, d);
615 >      } else {
616 >        excludedInteractions_.removePair(a, b);
617 >        excludedInteractions_.removePair(a, c);
618 >        excludedInteractions_.removePair(a, d);
619 >      }
620  
621 <  // nZconstraints is global, as are the 3 COM translations for the
622 <  // entire system:
621 >      if (options_.havevdw13scale() || options_.haveelectrostatic13scale()) {
622 >        oneThreeInteractions_.removePair(b, c);    
623 >        oneThreeInteractions_.removePair(b, d);    
624 >        oneThreeInteractions_.removePair(c, d);      
625 >      } else {
626 >        excludedInteractions_.removePair(b, c);
627 >        excludedInteractions_.removePair(b, d);
628 >        excludedInteractions_.removePair(c, d);
629 >      }
630 >    }
631  
632 <  ndf = ndf - 3 - nZconstraints;
632 >    for (rb = mol->beginRigidBody(rbIter); rb != NULL;
633 >         rb = mol->nextRigidBody(rbIter)) {
634 >      vector<Atom*> atoms = rb->getAtoms();
635 >      for (int i = 0; i < static_cast<int>(atoms.size()) -1 ; ++i) {
636 >        for (int j = i + 1; j < static_cast<int>(atoms.size()); ++j) {
637 >          a = atoms[i]->getGlobalIndex();
638 >          b = atoms[j]->getGlobalIndex();
639 >          excludedInteractions_.removePair(a, b);
640 >        }
641 >      }
642 >    }        
643 >    
644 >  }
645 >  
646 >  
647 >  void SimInfo::addMoleculeStamp(MoleculeStamp* molStamp, int nmol) {
648 >    int curStampId;
649 >    
650 >    //index from 0
651 >    curStampId = moleculeStamps_.size();
652  
653 <  return ndf;
654 < }
653 >    moleculeStamps_.push_back(molStamp);
654 >    molStampIds_.insert(molStampIds_.end(), nmol, curStampId);
655 >  }
656  
362 int SimInfo::getNDFraw() {
363  int ndfRaw_local;
657  
658 <  // Raw degrees of freedom that we have to set
659 <  ndfRaw_local = 0;
658 >  /**
659 >   * update
660 >   *
661 >   *  Performs the global checks and variable settings after the objects have been
662 >   *  created.
663 >   *
664 >   */
665 >  void SimInfo::update() {
666 >    
667 >    setupSimVariables();
668 >    setupCutoffs();
669 >    setupSwitching();
670 >    setupElectrostatics();
671 >    setupNeighborlists();
672  
673 <  for(int i = 0; i < integrableObjects.size(); i++){
674 <    ndfRaw_local += 3;
675 <    if (integrableObjects[i]->isDirectional()) {
676 <       if (integrableObjects[i]->isLinear())
677 <        ndfRaw_local += 2;
678 <      else
679 <        ndfRaw_local += 3;
680 <    }
681 <  }
673 > #ifdef IS_MPI
674 >    setupFortranParallel();
675 > #endif
676 >    setupFortranSim();
677 >    fortranInitialized_ = true;
678 >
679 >    calcNdf();
680 >    calcNdfRaw();
681 >    calcNdfTrans();
682 >  }
683 >  
684 >  set<AtomType*> SimInfo::getSimulatedAtomTypes() {
685 >    SimInfo::MoleculeIterator mi;
686 >    Molecule* mol;
687 >    Molecule::AtomIterator ai;
688 >    Atom* atom;
689 >    set<AtomType*> atomTypes;
690 >    
691 >    for(mol = beginMolecule(mi); mol != NULL; mol = nextMolecule(mi)) {      
692 >      for(atom = mol->beginAtom(ai); atom != NULL; atom = mol->nextAtom(ai)) {
693 >        atomTypes.insert(atom->getAtomType());
694 >      }      
695 >    }    
696 >    return atomTypes;        
697 >  }
698 >
699 >  /**
700 >   * setupCutoffs
701 >   *
702 >   * Sets the values of cutoffRadius and cutoffMethod
703 >   *
704 >   * cutoffRadius : realType
705 >   *  If the cutoffRadius was explicitly set, use that value.
706 >   *  If the cutoffRadius was not explicitly set:
707 >   *      Are there electrostatic atoms?  Use 12.0 Angstroms.
708 >   *      No electrostatic atoms?  Poll the atom types present in the
709 >   *      simulation for suggested cutoff values (e.g. 2.5 * sigma).
710 >   *      Use the maximum suggested value that was found.
711 >   *
712 >   * cutoffMethod : (one of HARD, SWITCHED, SHIFTED_FORCE, SHIFTED_POTENTIAL)
713 >   *      If cutoffMethod was explicitly set, use that choice.
714 >   *      If cutoffMethod was not explicitly set, use SHIFTED_FORCE
715 >   */
716 >  void SimInfo::setupCutoffs() {
717      
718 < #ifdef IS_MPI
719 <  MPI_Allreduce(&ndfRaw_local,&ndfRaw,1,MPI_INT,MPI_SUM, MPI_COMM_WORLD);
720 < #else
721 <  ndfRaw = ndfRaw_local;
722 < #endif
718 >    if (simParams_->haveCutoffRadius()) {
719 >      cutoffRadius_ = simParams_->getCutoffRadius();
720 >    } else {      
721 >      if (usesElectrostaticAtoms_) {
722 >        sprintf(painCave.errMsg,
723 >                "SimInfo: No value was set for the cutoffRadius.\n"
724 >                "\tOpenMD will use a default value of 12.0 angstroms"
725 >                "\tfor the cutoffRadius.\n");
726 >        painCave.isFatal = 0;
727 >        painCave.severity = OPENMD_INFO;
728 >        simError();
729 >        cutoffRadius_ = 12.0;
730 >      } else {
731 >        RealType thisCut;
732 >        set<AtomType*>::iterator i;
733 >        set<AtomType*> atomTypes;
734 >        atomTypes = getSimulatedAtomTypes();        
735 >        for (i = atomTypes.begin(); i != atomTypes.end(); ++i) {
736 >          thisCut = InteractionManager::Instance()->getSuggestedCutoffRadius((*i));
737 >          cutoffRadius_ = max(thisCut, cutoffRadius_);
738 >        }
739 >        sprintf(painCave.errMsg,
740 >                "SimInfo: No value was set for the cutoffRadius.\n"
741 >                "\tOpenMD will use %lf angstroms.\n",
742 >                cutoffRadius_);
743 >        painCave.isFatal = 0;
744 >        painCave.severity = OPENMD_INFO;
745 >        simError();
746 >      }            
747 >    }
748  
749 <  return ndfRaw;
385 < }
749 >    InteractionManager::Instance()->setCutoffRadius(cutoffRadius_);
750  
751 < int SimInfo::getNDFtranslational() {
752 <  int ndfTrans_local;
751 >    map<string, CutoffMethod> stringToCutoffMethod;
752 >    stringToCutoffMethod["HARD"] = HARD;
753 >    stringToCutoffMethod["SWITCHING_FUNCTION"] = SWITCHING_FUNCTION;
754 >    stringToCutoffMethod["SHIFTED_POTENTIAL"] = SHIFTED_POTENTIAL;    
755 >    stringToCutoffMethod["SHIFTED_FORCE"] = SHIFTED_FORCE;
756 >  
757 >    if (simParams_->haveCutoffMethod()) {
758 >      string cutMeth = toUpperCopy(simParams_->getCutoffMethod());
759 >      map<string, CutoffMethod>::iterator i;
760 >      i = stringToCutoffMethod.find(cutMeth);
761 >      if (i == stringToCutoffMethod.end()) {
762 >        sprintf(painCave.errMsg,
763 >                "SimInfo: Could not find chosen cutoffMethod %s\n"
764 >                "\tShould be one of: "
765 >                "HARD, SWITCHING_FUNCTION, SHIFTED_POTENTIAL, or SHIFTED_FORCE\n",
766 >                cutMeth.c_str());
767 >        painCave.isFatal = 1;
768 >        painCave.severity = OPENMD_ERROR;
769 >        simError();
770 >      } else {
771 >        cutoffMethod_ = i->second;
772 >      }
773 >    } else {
774 >      sprintf(painCave.errMsg,
775 >              "SimInfo: No value was set for the cutoffMethod.\n"
776 >              "\tOpenMD will use SHIFTED_FORCE.\n");
777 >        painCave.isFatal = 0;
778 >        painCave.severity = OPENMD_INFO;
779 >        simError();
780 >        cutoffMethod_ = SHIFTED_FORCE;        
781 >    }
782  
783 <  ndfTrans_local = 3 * integrableObjects.size() - n_constraints;
783 >    InteractionManager::Instance()->setCutoffMethod(cutoffMethod_);
784 >  }
785 >  
786 >  /**
787 >   * setupSwitching
788 >   *
789 >   * Sets the values of switchingRadius and
790 >   *  If the switchingRadius was explicitly set, use that value (but check it)
791 >   *  If the switchingRadius was not explicitly set: use 0.85 * cutoffRadius_
792 >   */
793 >  void SimInfo::setupSwitching() {
794 >    
795 >    if (simParams_->haveSwitchingRadius()) {
796 >      switchingRadius_ = simParams_->getSwitchingRadius();
797 >      if (switchingRadius_ > cutoffRadius_) {        
798 >        sprintf(painCave.errMsg,
799 >                "SimInfo: switchingRadius (%f) is larger than cutoffRadius(%f)\n",
800 >                switchingRadius_, cutoffRadius_);
801 >        painCave.isFatal = 1;
802 >        painCave.severity = OPENMD_ERROR;
803 >        simError();
804 >      }
805 >    } else {      
806 >      switchingRadius_ = 0.85 * cutoffRadius_;
807 >      sprintf(painCave.errMsg,
808 >              "SimInfo: No value was set for the switchingRadius.\n"
809 >              "\tOpenMD will use a default value of 85 percent of the cutoffRadius.\n"
810 >              "\tswitchingRadius = %f. for this simulation\n", switchingRadius_);
811 >      painCave.isFatal = 0;
812 >      painCave.severity = OPENMD_WARNING;
813 >      simError();
814 >    }          
815 >  
816 >    InteractionManager::Instance()->setSwitchingRadius(switchingRadius_);
817  
818 +    SwitchingFunctionType ft;
819 +    
820 +    if (simParams_->haveSwitchingFunctionType()) {
821 +      string funcType = simParams_->getSwitchingFunctionType();
822 +      toUpper(funcType);
823 +      if (funcType == "CUBIC") {
824 +        ft = cubic;
825 +      } else {
826 +        if (funcType == "FIFTH_ORDER_POLYNOMIAL") {
827 +          ft = fifth_order_poly;
828 +        } else {
829 +          // throw error        
830 +          sprintf( painCave.errMsg,
831 +                   "SimInfo : Unknown switchingFunctionType. (Input file specified %s .)\n"
832 +                   "\tswitchingFunctionType must be one of: "
833 +                   "\"cubic\" or \"fifth_order_polynomial\".",
834 +                   funcType.c_str() );
835 +          painCave.isFatal = 1;
836 +          painCave.severity = OPENMD_ERROR;
837 +          simError();
838 +        }          
839 +      }
840 +    }
841  
842 < #ifdef IS_MPI
843 <  MPI_Allreduce(&ndfTrans_local,&ndfTrans,1,MPI_INT,MPI_SUM, MPI_COMM_WORLD);
395 < #else
396 <  ndfTrans = ndfTrans_local;
397 < #endif
842 >    InteractionManager::Instance()->setSwitchingFunctionType(ft);
843 >  }
844  
845 <  ndfTrans = ndfTrans - 3 - nZconstraints;
845 >  /**
846 >   * setupSkinThickness
847 >   *
848 >   *  If the skinThickness was explicitly set, use that value (but check it)
849 >   *  If the skinThickness was not explicitly set: use 1.0 angstroms
850 >   */
851 >  void SimInfo::setupSkinThickness() {    
852 >    if (simParams_->haveSkinThickness()) {
853 >      skinThickness_ = simParams_->getSkinThickness();
854 >    } else {      
855 >      skinThickness_ = 1.0;
856 >      sprintf(painCave.errMsg,
857 >              "SimInfo Warning: No value was set for the skinThickness.\n"
858 >              "\tOpenMD will use a default value of %f Angstroms\n"
859 >              "\tfor this simulation\n", skinThickness_);
860 >      painCave.isFatal = 0;
861 >      simError();
862 >    }            
863 >  }
864  
865 <  return ndfTrans;
866 < }
865 >  void SimInfo::setupSimType() {
866 >    set<AtomType*>::iterator i;
867 >    set<AtomType*> atomTypes;
868 >    atomTypes = getSimulatedAtomTypes();
869  
870 < int SimInfo::getTotIntegrableObjects() {
405 <  int nObjs_local;
406 <  int nObjs;
870 >    useAtomicVirial_ = simParams_->getUseAtomicVirial();
871  
872 <  nObjs_local =  integrableObjects.size();
872 >    int usesElectrostatic = 0;
873 >    int usesMetallic = 0;
874 >    int usesDirectional = 0;
875 >    //loop over all of the atom types
876 >    for (i = atomTypes.begin(); i != atomTypes.end(); ++i) {
877 >      usesElectrostatic |= (*i)->isElectrostatic();
878 >      usesMetallic |= (*i)->isMetal();
879 >      usesDirectional |= (*i)->isDirectional();
880 >    }
881  
882 + #ifdef IS_MPI    
883 +    int temp;
884 +    temp = usesDirectional;
885 +    MPI_Allreduce(&temp, &usesDirectionalAtoms_, 1, MPI_INT, MPI_LOR, MPI_COMM_WORLD);    
886  
887 < #ifdef IS_MPI
888 <  MPI_Allreduce(&nObjs_local,&nObjs,1,MPI_INT,MPI_SUM, MPI_COMM_WORLD);
889 < #else
890 <  nObjs = nObjs_local;
887 >    temp = usesMetallic;
888 >    MPI_Allreduce(&temp, &usesMetallicAtoms_, 1, MPI_INT, MPI_LOR, MPI_COMM_WORLD);    
889 >
890 >    temp = usesElectrostatic;
891 >    MPI_Allreduce(&temp, &usesElectrostaticAtoms_, 1, MPI_INT, MPI_LOR, MPI_COMM_WORLD);
892   #endif
893 +    fInfo_.SIM_uses_PBC = usesPeriodicBoundaries_;    
894 +    fInfo_.SIM_uses_DirectionalAtoms = usesDirectionalAtoms_;
895 +    fInfo_.SIM_uses_MetallicAtoms = usesMetallicAtoms_;
896 +    fInfo_.SIM_requires_SkipCorrection = usesElectrostaticAtoms_;
897 +    fInfo_.SIM_requires_SelfCorrection = usesElectrostaticAtoms_;
898 +    fInfo_.SIM_uses_AtomicVirial = usesAtomicVirial_;
899 +  }
900  
901 +  void SimInfo::setupFortranSim() {
902 +    int isError;
903 +    int nExclude, nOneTwo, nOneThree, nOneFour;
904 +    vector<int> fortranGlobalGroupMembership;
905 +    
906 +    notifyFortranSkinThickness(&skinThickness_);
907  
908 <  return nObjs;
909 < }
908 >    int ljsp = cutoffMethod_ == SHIFTED_POTENTIAL ? 1 : 0;
909 >    int ljsf = cutoffMethod_ == SHIFTED_FORCE ? 1 : 0;
910 >    notifyFortranCutoffs(&cutoffRadius_, &switchingRadius_, &ljsp, &ljsf);
911  
912 < void SimInfo::refreshSim(){
912 >    isError = 0;
913  
914 <  simtype fInfo;
915 <  int isError;
916 <  int n_global;
917 <  int* excl;
914 >    //globalGroupMembership_ is filled by SimCreator    
915 >    for (int i = 0; i < nGlobalAtoms_; i++) {
916 >      fortranGlobalGroupMembership.push_back(globalGroupMembership_[i] + 1);
917 >    }
918  
919 <  fInfo.dielect = 0.0;
919 >    //calculate mass ratio of cutoff group
920 >    vector<RealType> mfact;
921 >    SimInfo::MoleculeIterator mi;
922 >    Molecule* mol;
923 >    Molecule::CutoffGroupIterator ci;
924 >    CutoffGroup* cg;
925 >    Molecule::AtomIterator ai;
926 >    Atom* atom;
927 >    RealType totalMass;
928  
929 <  if( useDipoles ){
930 <    if( useReactionField )fInfo.dielect = dielectric;
931 <  }
929 >    //to avoid memory reallocation, reserve enough space for mfact
930 >    mfact.reserve(getNCutoffGroups());
931 >    
932 >    for(mol = beginMolecule(mi); mol != NULL; mol = nextMolecule(mi)) {        
933 >      for (cg = mol->beginCutoffGroup(ci); cg != NULL; cg = mol->nextCutoffGroup(ci)) {
934  
935 <  fInfo.SIM_uses_PBC = usePBC;
936 <  //fInfo.SIM_uses_LJ = 0;
937 <  fInfo.SIM_uses_LJ = useLJ;
938 <  fInfo.SIM_uses_sticky = useSticky;
939 <  //fInfo.SIM_uses_sticky = 0;
940 <  fInfo.SIM_uses_charges = useCharges;
941 <  fInfo.SIM_uses_dipoles = useDipoles;
942 <  //fInfo.SIM_uses_dipoles = 0;
943 <  fInfo.SIM_uses_RF = useReactionField;
944 <  //fInfo.SIM_uses_RF = 0;
444 <  fInfo.SIM_uses_GB = useGB;
445 <  fInfo.SIM_uses_EAM = useEAM;
935 >        totalMass = cg->getMass();
936 >        for(atom = cg->beginAtom(ai); atom != NULL; atom = cg->nextAtom(ai)) {
937 >          // Check for massless groups - set mfact to 1 if true
938 >          if (totalMass != 0)
939 >            mfact.push_back(atom->getMass()/totalMass);
940 >          else
941 >            mfact.push_back( 1.0 );
942 >        }
943 >      }      
944 >    }
945  
946 <  n_exclude = excludes->getSize();
947 <  excl = excludes->getFortranArray();
449 <  
450 < #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);
946 >    //fill ident array of local atoms (it is actually ident of AtomType, it is so confusing !!!)
947 >    vector<int> identArray;
948  
949 <  if( isError ){
949 >    //to avoid memory reallocation, reserve enough space identArray
950 >    identArray.reserve(getNAtoms());
951      
952 <    sprintf( painCave.errMsg,
953 <             "There was an error setting the simulation information in fortran.\n" );
954 <    painCave.isFatal = 1;
955 <    painCave.severity = OOPSE_ERROR;
956 <    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 < }
952 >    for(mol = beginMolecule(mi); mol != NULL; mol = nextMolecule(mi)) {        
953 >      for(atom = mol->beginAtom(ai); atom != NULL; atom = mol->nextAtom(ai)) {
954 >        identArray.push_back(atom->getIdent());
955 >      }
956 >    }    
957  
958 < void SimInfo::setDefaultRcut( double theRcut ){
959 <  
960 <  haveRcut = 1;
961 <  rCut = theRcut;
962 <  rList = rCut + 1.0;
963 <  
964 <  notifyFortranCutOffs( &rCut, &rSw, &rList );
965 < }
958 >    //fill molMembershipArray
959 >    //molMembershipArray is filled by SimCreator    
960 >    vector<int> molMembershipArray(nGlobalAtoms_);
961 >    for (int i = 0; i < nGlobalAtoms_; i++) {
962 >      molMembershipArray[i] = globalMolMembership_[i] + 1;
963 >    }
964 >    
965 >    //setup fortran simulation
966  
967 < void SimInfo::setDefaultRcut( double theRcut, double theRsw ){
967 >    nExclude = excludedInteractions_.getSize();
968 >    nOneTwo = oneTwoInteractions_.getSize();
969 >    nOneThree = oneThreeInteractions_.getSize();
970 >    nOneFour = oneFourInteractions_.getSize();
971  
972 <  rSw = theRsw;
973 <  setDefaultRcut( theRcut );
974 < }
972 >    int* excludeList = excludedInteractions_.getPairList();
973 >    int* oneTwoList = oneTwoInteractions_.getPairList();
974 >    int* oneThreeList = oneThreeInteractions_.getPairList();
975 >    int* oneFourList = oneFourInteractions_.getPairList();
976  
977 <
978 < void SimInfo::checkCutOffs( void ){
979 <  
980 <  if( boxIsInit ){
977 >    setFortranSim( &fInfo_, &nGlobalAtoms_, &nAtoms_, &identArray[0],
978 >                   &nExclude, excludeList,
979 >                   &nOneTwo, oneTwoList,
980 >                   &nOneThree, oneThreeList,
981 >                   &nOneFour, oneFourList,
982 >                   &molMembershipArray[0], &mfact[0], &nCutoffGroups_,
983 >                   &fortranGlobalGroupMembership[0], &isError);
984      
985 <    //we need to check cutOffs against the box
986 <    
508 <    if( rCut > maxCutoff ){
985 >    if( isError ){
986 >      
987        sprintf( painCave.errMsg,
988 <               "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;
988 >               "There was an error setting the simulation information in fortran.\n" );
989        painCave.isFatal = 1;
990 +      painCave.severity = OPENMD_ERROR;
991        simError();
992 <    }    
526 <  } else {
527 <    // initialize this stuff before using it, OK?
528 <    sprintf( painCave.errMsg,
529 <             "Trying to check cutoffs without a box.\n"
530 <             "\tOOPSE should have better programmers than that.\n" );
531 <    painCave.severity = OOPSE_ERROR;
532 <    painCave.isFatal = 1;
533 <    simError();      
534 <  }
535 <  
536 < }
537 <
538 < void SimInfo::addProperty(GenericData* prop){
539 <
540 <  map<string, GenericData*>::iterator result;
541 <  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()){
992 >    }
993      
548    delete (*result).second;
549    (*result).second = prop;
550      
551  }
552  else{
553
554    properties[prop->getID()] = prop;
555
556  }
994      
995 < }
995 >    sprintf( checkPointMsg,
996 >             "succesfully sent the simulation information to fortran.\n");
997 >    
998 >    errorCheckPoint();
999 >    
1000 >    // Setup number of neighbors in neighbor list if present
1001 >    if (simParams_->haveNeighborListNeighbors()) {
1002 >      int nlistNeighbors = simParams_->getNeighborListNeighbors();
1003 >      setNeighbors(&nlistNeighbors);
1004 >    }
1005 >  
1006  
1007 < GenericData* SimInfo::getProperty(const string& propName){
561 <
562 <  map<string, GenericData*>::iterator result;
563 <  
564 <  //string lowerCaseName = ();
565 <  
566 <  result = properties.find(propName);
567 <  
568 <  if(result != properties.end())
569 <    return (*result).second;  
570 <  else  
571 <    return NULL;  
572 < }
1007 >  }
1008  
1009  
1010 < void SimInfo::getFortranGroupArrays(SimInfo* info,
1011 <                                    vector<int>& FglobalGroupMembership,
1012 <                                    vector<double>& mfact){
1013 <  
1014 <  Molecule* myMols;
1015 <  Atom** myAtoms;
1016 <  int numAtom;
1017 <  double mtot;
1018 <  int numMol;
1019 <  int numCutoffGroups;
1020 <  CutoffGroup* myCutoffGroup;
1021 <  vector<CutoffGroup*>::iterator iterCutoff;
1022 <  Atom* cutoffAtom;
588 <  vector<Atom*>::iterator iterAtom;
589 <  int atomIndex;
590 <  double totalMass;
591 <  
592 <  mfact.clear();
593 <  FglobalGroupMembership.clear();
594 <  
1010 >  void SimInfo::setupFortranParallel() {
1011 > #ifdef IS_MPI    
1012 >    //SimInfo is responsible for creating localToGlobalAtomIndex and localToGlobalGroupIndex
1013 >    vector<int> localToGlobalAtomIndex(getNAtoms(), 0);
1014 >    vector<int> localToGlobalCutoffGroupIndex;
1015 >    SimInfo::MoleculeIterator mi;
1016 >    Molecule::AtomIterator ai;
1017 >    Molecule::CutoffGroupIterator ci;
1018 >    Molecule* mol;
1019 >    Atom* atom;
1020 >    CutoffGroup* cg;
1021 >    mpiSimData parallelData;
1022 >    int isError;
1023  
1024 <  // Fix the silly fortran indexing problem
1024 >    for (mol = beginMolecule(mi); mol != NULL; mol  = nextMolecule(mi)) {
1025 >
1026 >      //local index(index in DataStorge) of atom is important
1027 >      for (atom = mol->beginAtom(ai); atom != NULL; atom = mol->nextAtom(ai)) {
1028 >        localToGlobalAtomIndex[atom->getLocalIndex()] = atom->getGlobalIndex() + 1;
1029 >      }
1030 >
1031 >      //local index of cutoff group is trivial, it only depends on the order of travesing
1032 >      for (cg = mol->beginCutoffGroup(ci); cg != NULL; cg = mol->nextCutoffGroup(ci)) {
1033 >        localToGlobalCutoffGroupIndex.push_back(cg->getGlobalIndex() + 1);
1034 >      }        
1035 >        
1036 >    }
1037 >
1038 >    //fill up mpiSimData struct
1039 >    parallelData.nMolGlobal = getNGlobalMolecules();
1040 >    parallelData.nMolLocal = getNMolecules();
1041 >    parallelData.nAtomsGlobal = getNGlobalAtoms();
1042 >    parallelData.nAtomsLocal = getNAtoms();
1043 >    parallelData.nGroupsGlobal = getNGlobalCutoffGroups();
1044 >    parallelData.nGroupsLocal = getNCutoffGroups();
1045 >    parallelData.myNode = worldRank;
1046 >    MPI_Comm_size(MPI_COMM_WORLD, &(parallelData.nProcessors));
1047 >
1048 >    //pass mpiSimData struct and index arrays to fortran
1049 >    setFsimParallel(&parallelData, &(parallelData.nAtomsLocal),
1050 >                    &localToGlobalAtomIndex[0],  &(parallelData.nGroupsLocal),
1051 >                    &localToGlobalCutoffGroupIndex[0], &isError);
1052 >
1053 >    if (isError) {
1054 >      sprintf(painCave.errMsg,
1055 >              "mpiRefresh errror: fortran didn't like something we gave it.\n");
1056 >      painCave.isFatal = 1;
1057 >      simError();
1058 >    }
1059 >
1060 >    sprintf(checkPointMsg, " mpiRefresh successful.\n");
1061 >    errorCheckPoint();
1062 >
1063 > #endif
1064 >  }
1065 >
1066 >
1067 >  void SimInfo::setupSwitchingFunction() {    
1068 >
1069 >  }
1070 >
1071 >  void SimInfo::setupAccumulateBoxDipole() {    
1072 >
1073 >    // we only call setAccumulateBoxDipole if the accumulateBoxDipole parameter is true
1074 >    if ( simParams_->haveAccumulateBoxDipole() )
1075 >      if ( simParams_->getAccumulateBoxDipole() ) {
1076 >        calcBoxDipole_ = true;
1077 >      }
1078 >
1079 >  }
1080 >
1081 >  void SimInfo::addProperty(GenericData* genData) {
1082 >    properties_.addProperty(genData);  
1083 >  }
1084 >
1085 >  void SimInfo::removeProperty(const string& propName) {
1086 >    properties_.removeProperty(propName);  
1087 >  }
1088 >
1089 >  void SimInfo::clearProperties() {
1090 >    properties_.clearProperties();
1091 >  }
1092 >
1093 >  vector<string> SimInfo::getPropertyNames() {
1094 >    return properties_.getPropertyNames();  
1095 >  }
1096 >      
1097 >  vector<GenericData*> SimInfo::getProperties() {
1098 >    return properties_.getProperties();
1099 >  }
1100 >
1101 >  GenericData* SimInfo::getPropertyByName(const string& propName) {
1102 >    return properties_.getPropertyByName(propName);
1103 >  }
1104 >
1105 >  void SimInfo::setSnapshotManager(SnapshotManager* sman) {
1106 >    if (sman_ == sman) {
1107 >      return;
1108 >    }    
1109 >    delete sman_;
1110 >    sman_ = sman;
1111 >
1112 >    Molecule* mol;
1113 >    RigidBody* rb;
1114 >    Atom* atom;
1115 >    SimInfo::MoleculeIterator mi;
1116 >    Molecule::RigidBodyIterator rbIter;
1117 >    Molecule::AtomIterator atomIter;;
1118 >
1119 >    for (mol = beginMolecule(mi); mol != NULL; mol = nextMolecule(mi)) {
1120 >        
1121 >      for (atom = mol->beginAtom(atomIter); atom != NULL; atom = mol->nextAtom(atomIter)) {
1122 >        atom->setSnapshotManager(sman_);
1123 >      }
1124 >        
1125 >      for (rb = mol->beginRigidBody(rbIter); rb != NULL; rb = mol->nextRigidBody(rbIter)) {
1126 >        rb->setSnapshotManager(sman_);
1127 >      }
1128 >    }    
1129 >    
1130 >  }
1131 >
1132 >  Vector3d SimInfo::getComVel(){
1133 >    SimInfo::MoleculeIterator i;
1134 >    Molecule* mol;
1135 >
1136 >    Vector3d comVel(0.0);
1137 >    RealType totalMass = 0.0;
1138 >    
1139 >
1140 >    for (mol = beginMolecule(i); mol != NULL; mol = nextMolecule(i)) {
1141 >      RealType mass = mol->getMass();
1142 >      totalMass += mass;
1143 >      comVel += mass * mol->getComVel();
1144 >    }  
1145 >
1146   #ifdef IS_MPI
1147 <  numAtom = mpiSim->getNAtomsGlobal();
1148 < #else
1149 <  numAtom = n_atoms;
1147 >    RealType tmpMass = totalMass;
1148 >    Vector3d tmpComVel(comVel);    
1149 >    MPI_Allreduce(&tmpMass,&totalMass,1,MPI_REALTYPE,MPI_SUM, MPI_COMM_WORLD);
1150 >    MPI_Allreduce(tmpComVel.getArrayPointer(), comVel.getArrayPointer(),3,MPI_REALTYPE,MPI_SUM, MPI_COMM_WORLD);
1151   #endif
602  for (int i = 0; i < numAtom; i++)
603    FglobalGroupMembership.push_back(globalGroupMembership[i] + 1);
604  
1152  
1153 <  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)){
1153 >    comVel /= totalMass;
1154  
1155 <      totalMass = myCutoffGroup->getMass();
1155 >    return comVel;
1156 >  }
1157 >
1158 >  Vector3d SimInfo::getCom(){
1159 >    SimInfo::MoleculeIterator i;
1160 >    Molecule* mol;
1161 >
1162 >    Vector3d com(0.0);
1163 >    RealType totalMass = 0.0;
1164 >    
1165 >    for (mol = beginMolecule(i); mol != NULL; mol = nextMolecule(i)) {
1166 >      RealType mass = mol->getMass();
1167 >      totalMass += mass;
1168 >      com += mass * mol->getCom();
1169 >    }  
1170 >
1171 > #ifdef IS_MPI
1172 >    RealType tmpMass = totalMass;
1173 >    Vector3d tmpCom(com);    
1174 >    MPI_Allreduce(&tmpMass,&totalMass,1,MPI_REALTYPE,MPI_SUM, MPI_COMM_WORLD);
1175 >    MPI_Allreduce(tmpCom.getArrayPointer(), com.getArrayPointer(),3,MPI_REALTYPE,MPI_SUM, MPI_COMM_WORLD);
1176 > #endif
1177 >
1178 >    com /= totalMass;
1179 >
1180 >    return com;
1181 >
1182 >  }        
1183 >
1184 >  ostream& operator <<(ostream& o, SimInfo& info) {
1185 >
1186 >    return o;
1187 >  }
1188 >  
1189 >  
1190 >   /*
1191 >   Returns center of mass and center of mass velocity in one function call.
1192 >   */
1193 >  
1194 >   void SimInfo::getComAll(Vector3d &com, Vector3d &comVel){
1195 >      SimInfo::MoleculeIterator i;
1196 >      Molecule* mol;
1197        
1198 <      for(cutoffAtom = myCutoffGroup->beginAtom(iterAtom);
1199 <          cutoffAtom != NULL;
1200 <          cutoffAtom = myCutoffGroup->nextAtom(iterAtom)){
1201 <        mfact.push_back(cutoffAtom->getMass()/totalMass);
1198 >    
1199 >      RealType totalMass = 0.0;
1200 >    
1201 >
1202 >      for (mol = beginMolecule(i); mol != NULL; mol = nextMolecule(i)) {
1203 >         RealType mass = mol->getMass();
1204 >         totalMass += mass;
1205 >         com += mass * mol->getCom();
1206 >         comVel += mass * mol->getComVel();          
1207        }  
1208 +      
1209 + #ifdef IS_MPI
1210 +      RealType tmpMass = totalMass;
1211 +      Vector3d tmpCom(com);  
1212 +      Vector3d tmpComVel(comVel);
1213 +      MPI_Allreduce(&tmpMass,&totalMass,1,MPI_REALTYPE,MPI_SUM, MPI_COMM_WORLD);
1214 +      MPI_Allreduce(tmpCom.getArrayPointer(), com.getArrayPointer(),3,MPI_REALTYPE,MPI_SUM, MPI_COMM_WORLD);
1215 +      MPI_Allreduce(tmpComVel.getArrayPointer(), comVel.getArrayPointer(),3,MPI_REALTYPE,MPI_SUM, MPI_COMM_WORLD);
1216 + #endif
1217 +      
1218 +      com /= totalMass;
1219 +      comVel /= totalMass;
1220 +   }        
1221 +  
1222 +   /*
1223 +   Return intertia tensor for entire system and angular momentum Vector.
1224 +
1225 +
1226 +       [  Ixx -Ixy  -Ixz ]
1227 +    J =| -Iyx  Iyy  -Iyz |
1228 +       [ -Izx -Iyz   Izz ]
1229 +    */
1230 +
1231 +   void SimInfo::getInertiaTensor(Mat3x3d &inertiaTensor, Vector3d &angularMomentum){
1232 +      
1233 +
1234 +      RealType xx = 0.0;
1235 +      RealType yy = 0.0;
1236 +      RealType zz = 0.0;
1237 +      RealType xy = 0.0;
1238 +      RealType xz = 0.0;
1239 +      RealType yz = 0.0;
1240 +      Vector3d com(0.0);
1241 +      Vector3d comVel(0.0);
1242 +      
1243 +      getComAll(com, comVel);
1244 +      
1245 +      SimInfo::MoleculeIterator i;
1246 +      Molecule* mol;
1247 +      
1248 +      Vector3d thisq(0.0);
1249 +      Vector3d thisv(0.0);
1250 +
1251 +      RealType thisMass = 0.0;
1252 +    
1253 +      
1254 +      
1255 +  
1256 +      for (mol = beginMolecule(i); mol != NULL; mol = nextMolecule(i)) {
1257 +        
1258 +         thisq = mol->getCom()-com;
1259 +         thisv = mol->getComVel()-comVel;
1260 +         thisMass = mol->getMass();
1261 +         // Compute moment of intertia coefficients.
1262 +         xx += thisq[0]*thisq[0]*thisMass;
1263 +         yy += thisq[1]*thisq[1]*thisMass;
1264 +         zz += thisq[2]*thisq[2]*thisMass;
1265 +        
1266 +         // compute products of intertia
1267 +         xy += thisq[0]*thisq[1]*thisMass;
1268 +         xz += thisq[0]*thisq[2]*thisMass;
1269 +         yz += thisq[1]*thisq[2]*thisMass;
1270 +            
1271 +         angularMomentum += cross( thisq, thisv ) * thisMass;
1272 +            
1273 +      }  
1274 +      
1275 +      
1276 +      inertiaTensor(0,0) = yy + zz;
1277 +      inertiaTensor(0,1) = -xy;
1278 +      inertiaTensor(0,2) = -xz;
1279 +      inertiaTensor(1,0) = -xy;
1280 +      inertiaTensor(1,1) = xx + zz;
1281 +      inertiaTensor(1,2) = -yz;
1282 +      inertiaTensor(2,0) = -xz;
1283 +      inertiaTensor(2,1) = -yz;
1284 +      inertiaTensor(2,2) = xx + yy;
1285 +      
1286 + #ifdef IS_MPI
1287 +      Mat3x3d tmpI(inertiaTensor);
1288 +      Vector3d tmpAngMom;
1289 +      MPI_Allreduce(tmpI.getArrayPointer(), inertiaTensor.getArrayPointer(),9,MPI_REALTYPE,MPI_SUM, MPI_COMM_WORLD);
1290 +      MPI_Allreduce(tmpAngMom.getArrayPointer(), angularMomentum.getArrayPointer(),3,MPI_REALTYPE,MPI_SUM, MPI_COMM_WORLD);
1291 + #endif
1292 +              
1293 +      return;
1294 +   }
1295 +
1296 +   //Returns the angular momentum of the system
1297 +   Vector3d SimInfo::getAngularMomentum(){
1298 +      
1299 +      Vector3d com(0.0);
1300 +      Vector3d comVel(0.0);
1301 +      Vector3d angularMomentum(0.0);
1302 +      
1303 +      getComAll(com,comVel);
1304 +      
1305 +      SimInfo::MoleculeIterator i;
1306 +      Molecule* mol;
1307 +      
1308 +      Vector3d thisr(0.0);
1309 +      Vector3d thisp(0.0);
1310 +      
1311 +      RealType thisMass;
1312 +      
1313 +      for (mol = beginMolecule(i); mol != NULL; mol = nextMolecule(i)) {        
1314 +        thisMass = mol->getMass();
1315 +        thisr = mol->getCom()-com;
1316 +        thisp = (mol->getComVel()-comVel)*thisMass;
1317 +        
1318 +        angularMomentum += cross( thisr, thisp );
1319 +        
1320 +      }  
1321 +      
1322 + #ifdef IS_MPI
1323 +      Vector3d tmpAngMom;
1324 +      MPI_Allreduce(tmpAngMom.getArrayPointer(), angularMomentum.getArrayPointer(),3,MPI_REALTYPE,MPI_SUM, MPI_COMM_WORLD);
1325 + #endif
1326 +      
1327 +      return angularMomentum;
1328 +   }
1329 +  
1330 +  StuntDouble* SimInfo::getIOIndexToIntegrableObject(int index) {
1331 +    return IOIndexToIntegrableObject.at(index);
1332 +  }
1333 +  
1334 +  void SimInfo::setIOIndexToIntegrableObject(const vector<StuntDouble*>& v) {
1335 +    IOIndexToIntegrableObject= v;
1336 +  }
1337 +
1338 +  /* Returns the Volume of the simulation based on a ellipsoid with semi-axes
1339 +     based on the radius of gyration V=4/3*Pi*R_1*R_2*R_3
1340 +     where R_i are related to the principle inertia moments R_i = sqrt(C*I_i/N), this reduces to
1341 +     V = 4/3*Pi*(C/N)^3/2*sqrt(det(I)). See S.E. Baltazar et. al. Comp. Mat. Sci. 37 (2006) 526-536.
1342 +  */
1343 +  void SimInfo::getGyrationalVolume(RealType &volume){
1344 +    Mat3x3d intTensor;
1345 +    RealType det;
1346 +    Vector3d dummyAngMom;
1347 +    RealType sysconstants;
1348 +    RealType geomCnst;
1349 +
1350 +    geomCnst = 3.0/2.0;
1351 +    /* Get the inertial tensor and angular momentum for free*/
1352 +    getInertiaTensor(intTensor,dummyAngMom);
1353 +    
1354 +    det = intTensor.determinant();
1355 +    sysconstants = geomCnst/(RealType)nGlobalIntegrableObjects_;
1356 +    volume = 4.0/3.0*NumericConstant::PI*pow(sysconstants,3.0/2.0)*sqrt(det);
1357 +    return;
1358 +  }
1359 +
1360 +  void SimInfo::getGyrationalVolume(RealType &volume, RealType &detI){
1361 +    Mat3x3d intTensor;
1362 +    Vector3d dummyAngMom;
1363 +    RealType sysconstants;
1364 +    RealType geomCnst;
1365 +
1366 +    geomCnst = 3.0/2.0;
1367 +    /* Get the inertial tensor and angular momentum for free*/
1368 +    getInertiaTensor(intTensor,dummyAngMom);
1369 +    
1370 +    detI = intTensor.determinant();
1371 +    sysconstants = geomCnst/(RealType)nGlobalIntegrableObjects_;
1372 +    volume = 4.0/3.0*NumericConstant::PI*pow(sysconstants,3.0/2.0)*sqrt(detI);
1373 +    return;
1374 +  }
1375 + /*
1376 +   void SimInfo::setStuntDoubleFromGlobalIndex(vector<StuntDouble*> v) {
1377 +      assert( v.size() == nAtoms_ + nRigidBodies_);
1378 +      sdByGlobalIndex_ = v;
1379      }
1380 +
1381 +    StuntDouble* SimInfo::getStuntDoubleFromGlobalIndex(int index) {
1382 +      //assert(index < nAtoms_ + nRigidBodies_);
1383 +      return sdByGlobalIndex_.at(index);
1384 +    }  
1385 + */  
1386 +  int SimInfo::getNGlobalConstraints() {
1387 +    int nGlobalConstraints;
1388 + #ifdef IS_MPI
1389 +    MPI_Allreduce(&nConstraints_, &nGlobalConstraints, 1, MPI_INT, MPI_SUM,
1390 +                  MPI_COMM_WORLD);    
1391 + #else
1392 +    nGlobalConstraints =  nConstraints_;
1393 + #endif
1394 +    return nGlobalConstraints;
1395    }
1396  
1397 < }
1397 > }//end namespace OpenMD
1398 >

Comparing:
trunk/src/brains/SimInfo.cpp (property svn:keywords), Revision 3 by tim, Fri Sep 24 16:27:58 2004 UTC vs.
branches/development/src/brains/SimInfo.cpp (property svn:keywords), Revision 1530 by gezelter, Tue Dec 28 21:47:55 2010 UTC

# Line 0 | Line 1
1 + Author Id Revision Date

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines