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

Comparing:
trunk/src/brains/SimInfo.cpp (property svn:keywords), Revision 2 by gezelter, Fri Sep 24 04:16:43 2004 UTC vs.
branches/development/src/brains/SimInfo.cpp (property svn:keywords), Revision 1532 by gezelter, Wed Dec 29 19:59:21 2010 UTC

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

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines