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 143 by chrisfen, Fri Oct 22 22:54:01 2004 UTC vs.
branches/development/src/brains/SimInfo.cpp (file contents), Revision 1744 by gezelter, Tue Jun 5 18:07:08 2012 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]  Kuang & Gezelter,  J. Chem. Phys. 133, 164101 (2010).
40 > * [5]  Vardeman, Stocker & Gezelter, J. Chem. Theory Comput. 7, 834 (2011).
41 > */
42 >
43 > /**
44 > * @file SimInfo.cpp
45 > * @author    tlin
46 > * @date  11/02/2004
47 > * @version 1.0
48 > */
49  
50 < #include <iostream>
51 < using namespace std;
50 > #include <algorithm>
51 > #include <set>
52 > #include <map>
53  
54   #include "brains/SimInfo.hpp"
55 < #define __C
56 < #include "brains/fSimulation.h"
55 > #include "math/Vector3.hpp"
56 > #include "primitives/Molecule.hpp"
57 > #include "primitives/StuntDouble.hpp"
58 > #include "utils/MemoryUtils.hpp"
59   #include "utils/simError.h"
60 < #include "UseTheForce/DarkSide/simulation_interface.h"
61 < #include "UseTheForce/notifyCutoffs_interface.h"
62 <
63 < //#include "UseTheForce/fortranWrappers.hpp"
16 <
17 < #include "math/MatVec3.h"
18 <
60 > #include "selection/SelectionManager.hpp"
61 > #include "io/ForceFieldOptions.hpp"
62 > #include "brains/ForceField.hpp"
63 > #include "nonbonded/SwitchingFunction.hpp"
64   #ifdef IS_MPI
65 < #include "brains/mpiSimulation.hpp"
65 > #include <mpi.h>
66   #endif
67  
68 < inline double roundMe( double x ){
69 <  return ( x >= 0 ) ? floor( x + 0.5 ) : ceil( x - 0.5 );
70 < }
71 <          
72 < inline double min( double a, double b ){
73 <  return (a < b ) ? a : b;
74 < }
68 > using namespace std;
69 > namespace OpenMD {
70 >  
71 >  SimInfo::SimInfo(ForceField* ff, Globals* simParams) :
72 >    forceField_(ff), simParams_(simParams),
73 >    ndf_(0), fdf_local(0), ndfRaw_(0), ndfTrans_(0), nZconstraint_(0),
74 >    nGlobalMols_(0), nGlobalAtoms_(0), nGlobalCutoffGroups_(0),
75 >    nGlobalIntegrableObjects_(0), nGlobalRigidBodies_(0), nGlobalFluctuatingCharges_(0),
76 >    nAtoms_(0), nBonds_(0),  nBends_(0), nTorsions_(0), nInversions_(0),
77 >    nRigidBodies_(0), nIntegrableObjects_(0), nCutoffGroups_(0),
78 >    nConstraints_(0), nFluctuatingCharges_(0), sman_(NULL), topologyDone_(false),
79 >    calcBoxDipole_(false), useAtomicVirial_(true) {    
80 >    
81 >    MoleculeStamp* molStamp;
82 >    int nMolWithSameStamp;
83 >    int nCutoffAtoms = 0; // number of atoms belong to cutoff groups
84 >    int nGroups = 0;       //total cutoff groups defined in meta-data file
85 >    CutoffGroupStamp* cgStamp;    
86 >    RigidBodyStamp* rbStamp;
87 >    int nRigidAtoms = 0;
88 >    
89 >    vector<Component*> components = simParams->getComponents();
90 >    
91 >    for (vector<Component*>::iterator i = components.begin(); i !=components.end(); ++i) {
92 >      molStamp = (*i)->getMoleculeStamp();
93 >      nMolWithSameStamp = (*i)->getNMol();
94 >      
95 >      addMoleculeStamp(molStamp, nMolWithSameStamp);
96 >      
97 >      //calculate atoms in molecules
98 >      nGlobalAtoms_ += molStamp->getNAtoms() *nMolWithSameStamp;  
99 >      
100 >      //calculate atoms in cutoff groups
101 >      int nAtomsInGroups = 0;
102 >      int nCutoffGroupsInStamp = molStamp->getNCutoffGroups();
103 >      
104 >      for (int j=0; j < nCutoffGroupsInStamp; j++) {
105 >        cgStamp = molStamp->getCutoffGroupStamp(j);
106 >        nAtomsInGroups += cgStamp->getNMembers();
107 >      }
108 >      
109 >      nGroups += nCutoffGroupsInStamp * nMolWithSameStamp;
110 >      
111 >      nCutoffAtoms += nAtomsInGroups * nMolWithSameStamp;            
112 >      
113 >      //calculate atoms in rigid bodies
114 >      int nAtomsInRigidBodies = 0;
115 >      int nRigidBodiesInStamp = molStamp->getNRigidBodies();
116 >      
117 >      for (int j=0; j < nRigidBodiesInStamp; j++) {
118 >        rbStamp = molStamp->getRigidBodyStamp(j);
119 >        nAtomsInRigidBodies += rbStamp->getNMembers();
120 >      }
121 >      
122 >      nGlobalRigidBodies_ += nRigidBodiesInStamp * nMolWithSameStamp;
123 >      nRigidAtoms += nAtomsInRigidBodies * nMolWithSameStamp;            
124 >      
125 >    }
126 >    
127 >    //every free atom (atom does not belong to cutoff groups) is a cutoff
128 >    //group therefore the total number of cutoff groups in the system is
129 >    //equal to the total number of atoms minus number of atoms belong to
130 >    //cutoff group defined in meta-data file plus the number of cutoff
131 >    //groups defined in meta-data file
132  
133 < SimInfo* currentInfo;
133 >    nGlobalCutoffGroups_ = nGlobalAtoms_ - nCutoffAtoms + nGroups;
134 >    
135 >    //every free atom (atom does not belong to rigid bodies) is an
136 >    //integrable object therefore the total number of integrable objects
137 >    //in the system is equal to the total number of atoms minus number of
138 >    //atoms belong to rigid body defined in meta-data file plus the number
139 >    //of rigid bodies defined in meta-data file
140 >    nGlobalIntegrableObjects_ = nGlobalAtoms_ - nRigidAtoms
141 >      + nGlobalRigidBodies_;
142 >    
143 >    nGlobalMols_ = molStampIds_.size();
144 >    molToProcMap_.resize(nGlobalMols_);
145 >  }
146 >  
147 >  SimInfo::~SimInfo() {
148 >    map<int, Molecule*>::iterator i;
149 >    for (i = molecules_.begin(); i != molecules_.end(); ++i) {
150 >      delete i->second;
151 >    }
152 >    molecules_.clear();
153 >      
154 >    delete sman_;
155 >    delete simParams_;
156 >    delete forceField_;
157 >  }
158  
33 SimInfo::SimInfo(){
159  
160 <  n_constraints = 0;
161 <  nZconstraints = 0;
162 <  n_oriented = 0;
163 <  n_dipoles = 0;
164 <  ndf = 0;
165 <  ndfRaw = 0;
166 <  nZconstraints = 0;
167 <  the_integrator = NULL;
168 <  setTemp = 0;
169 <  thermalTime = 0.0;
170 <  currentTime = 0.0;
171 <  rCut = 0.0;
172 <  rSw = 0.0;
173 <
174 <  haveRcut = 0;
175 <  haveRsw = 0;
176 <  boxIsInit = 0;
160 >  bool SimInfo::addMolecule(Molecule* mol) {
161 >    MoleculeIterator i;
162 >    
163 >    i = molecules_.find(mol->getGlobalIndex());
164 >    if (i == molecules_.end() ) {
165 >      
166 >      molecules_.insert(make_pair(mol->getGlobalIndex(), mol));
167 >      
168 >      nAtoms_ += mol->getNAtoms();
169 >      nBonds_ += mol->getNBonds();
170 >      nBends_ += mol->getNBends();
171 >      nTorsions_ += mol->getNTorsions();
172 >      nInversions_ += mol->getNInversions();
173 >      nRigidBodies_ += mol->getNRigidBodies();
174 >      nIntegrableObjects_ += mol->getNIntegrableObjects();
175 >      nCutoffGroups_ += mol->getNCutoffGroups();
176 >      nConstraints_ += mol->getNConstraintPairs();
177 >      
178 >      addInteractionPairs(mol);
179 >      
180 >      return true;
181 >    } else {
182 >      return false;
183 >    }
184 >  }
185    
186 <  resetTime = 1e99;
186 >  bool SimInfo::removeMolecule(Molecule* mol) {
187 >    MoleculeIterator i;
188 >    i = molecules_.find(mol->getGlobalIndex());
189  
190 <  orthoRhombic = 0;
56 <  orthoTolerance = 1E-6;
57 <  useInitXSstate = true;
190 >    if (i != molecules_.end() ) {
191  
192 <  usePBC = 0;
193 <  useDirectionalAtoms = 0;
194 <  useLennardJones = 0;
195 <  useElectrostatics = 0;
196 <  useCharges = 0;
197 <  useDipoles = 0;
198 <  useSticky = 0;
199 <  useGayBerne = 0;
200 <  useEAM = 0;
201 <  useShapes = 0;
202 <  useFLARB = 0;
192 >      assert(mol == i->second);
193 >        
194 >      nAtoms_ -= mol->getNAtoms();
195 >      nBonds_ -= mol->getNBonds();
196 >      nBends_ -= mol->getNBends();
197 >      nTorsions_ -= mol->getNTorsions();
198 >      nInversions_ -= mol->getNInversions();
199 >      nRigidBodies_ -= mol->getNRigidBodies();
200 >      nIntegrableObjects_ -= mol->getNIntegrableObjects();
201 >      nCutoffGroups_ -= mol->getNCutoffGroups();
202 >      nConstraints_ -= mol->getNConstraintPairs();
203  
204 <  useSolidThermInt = 0;
205 <  useLiquidThermInt = 0;
204 >      removeInteractionPairs(mol);
205 >      molecules_.erase(mol->getGlobalIndex());
206  
207 <  haveCutoffGroups = false;
208 <
209 <  excludes = Exclude::Instance();
207 >      delete mol;
208 >        
209 >      return true;
210 >    } else {
211 >      return false;
212 >    }
213 >  }    
214  
215 <  myConfiguration = new SimState();
215 >        
216 >  Molecule* SimInfo::beginMolecule(MoleculeIterator& i) {
217 >    i = molecules_.begin();
218 >    return i == molecules_.end() ? NULL : i->second;
219 >  }    
220  
221 <  has_minimizer = false;
222 <  the_minimizer =NULL;
221 >  Molecule* SimInfo::nextMolecule(MoleculeIterator& i) {
222 >    ++i;
223 >    return i == molecules_.end() ? NULL : i->second;    
224 >  }
225  
83  ngroup = 0;
226  
227 < }
227 >  void SimInfo::calcNdf() {
228 >    int ndf_local, nfq_local;
229 >    MoleculeIterator i;
230 >    vector<StuntDouble*>::iterator j;
231 >    vector<Atom*>::iterator k;
232  
233 +    Molecule* mol;
234 +    StuntDouble* integrableObject;
235 +    Atom* atom;
236  
237 < SimInfo::~SimInfo(){
237 >    ndf_local = 0;
238 >    nfq_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 <  delete myConfiguration;
244 >        ndf_local += 3;
245  
246 <  map<string, GenericData*>::iterator i;
247 <  
248 <  for(i = properties.begin(); i != properties.end(); i++)
249 <    delete (*i).second;
246 >        if (integrableObject->isDirectional()) {
247 >          if (integrableObject->isLinear()) {
248 >            ndf_local += 2;
249 >          } else {
250 >            ndf_local += 3;
251 >          }
252 >        }
253 >      }
254 >      for (atom = mol->beginFluctuatingCharge(k); atom != NULL;
255 >           atom = mol->nextFluctuatingCharge(k)) {
256 >        if (atom->isFluctuatingCharge()) {
257 >          nfq_local++;
258 >        }
259 >      }
260 >    }
261 >    
262 >    ndfLocal_ = ndf_local;
263 >    cerr << "ndfLocal_ = " << ndfLocal_ << "\n";
264  
265 < }
265 >    // n_constraints is local, so subtract them on each processor
266 >    ndf_local -= nConstraints_;
267  
268 < void SimInfo::setBox(double newBox[3]) {
269 <  
270 <  int i, j;
271 <  double tempMat[3][3];
268 > #ifdef IS_MPI
269 >    MPI_Allreduce(&ndf_local,&ndf_,1,MPI_INT,MPI_SUM, MPI_COMM_WORLD);
270 >    MPI_Allreduce(&nfq_local,&nGlobalFluctuatingCharges_,1, MPI_INT, MPI_SUM, MPI_COMM_WORLD);
271 > #else
272 >    ndf_ = ndf_local;
273 >    nGlobalFluctuatingCharges_ = nfq_local;
274 > #endif
275  
276 <  for(i=0; i<3; i++)
277 <    for (j=0; j<3; j++) tempMat[i][j] = 0.0;;
276 >    // nZconstraints_ is global, as are the 3 COM translations for the
277 >    // entire system:
278 >    ndf_ = ndf_ - 3 - nZconstraint_;
279  
280 <  tempMat[0][0] = newBox[0];
108 <  tempMat[1][1] = newBox[1];
109 <  tempMat[2][2] = newBox[2];
280 >  }
281  
282 <  setBoxM( tempMat );
283 <
284 < }
285 <
286 < void SimInfo::setBoxM( double theBox[3][3] ){
282 >  int SimInfo::getFdf() {
283 > #ifdef IS_MPI
284 >    MPI_Allreduce(&fdf_local,&fdf_,1,MPI_INT,MPI_SUM, MPI_COMM_WORLD);
285 > #else
286 >    fdf_ = fdf_local;
287 > #endif
288 >    return fdf_;
289 >  }
290    
291 <  int i, j;
292 <  double FortranHmat[9]; // to preserve compatibility with Fortran the
293 <                         // ordering in the array is as follows:
294 <                         // [ 0 3 6 ]
295 <                         // [ 1 4 7 ]
296 <                         // [ 2 5 8 ]
297 <  double FortranHmatInv[9]; // the inverted Hmat (for Fortran);
298 <
299 <  if( !boxIsInit ) boxIsInit = 1;
300 <
301 <  for(i=0; i < 3; i++)
302 <    for (j=0; j < 3; j++) Hmat[i][j] = theBox[i][j];
303 <  
304 <  calcBoxL();
131 <  calcHmatInv();
132 <
133 <  for(i=0; i < 3; i++) {
134 <    for (j=0; j < 3; j++) {
135 <      FortranHmat[3*j + i] = Hmat[i][j];
136 <      FortranHmatInv[3*j + i] = HmatInv[i][j];
291 >  unsigned int SimInfo::getNLocalCutoffGroups(){
292 >    int nLocalCutoffAtoms = 0;
293 >    Molecule* mol;
294 >    MoleculeIterator mi;
295 >    CutoffGroup* cg;
296 >    Molecule::CutoffGroupIterator ci;
297 >    
298 >    for (mol = beginMolecule(mi); mol != NULL; mol  = nextMolecule(mi)) {
299 >      
300 >      for (cg = mol->beginCutoffGroup(ci); cg != NULL;
301 >           cg = mol->nextCutoffGroup(ci)) {
302 >        nLocalCutoffAtoms += cg->getNumAtom();
303 >        
304 >      }        
305      }
306 +    
307 +    return nAtoms_ - nLocalCutoffAtoms + nCutoffGroups_;
308    }
309 +    
310 +  void SimInfo::calcNdfRaw() {
311 +    int ndfRaw_local;
312  
313 <  setFortranBox(FortranHmat, FortranHmatInv, &orthoRhombic);
314 <
315 < }
316 <
313 >    MoleculeIterator i;
314 >    vector<StuntDouble*>::iterator j;
315 >    Molecule* mol;
316 >    StuntDouble* integrableObject;
317  
318 < void SimInfo::getBoxM (double theBox[3][3]) {
318 >    // Raw degrees of freedom that we have to set
319 >    ndfRaw_local = 0;
320 >    
321 >    for (mol = beginMolecule(i); mol != NULL; mol = nextMolecule(i)) {
322 >      for (integrableObject = mol->beginIntegrableObject(j); integrableObject != NULL;
323 >           integrableObject = mol->nextIntegrableObject(j)) {
324  
325 <  int i, j;
148 <  for(i=0; i<3; i++)
149 <    for (j=0; j<3; j++) theBox[i][j] = Hmat[i][j];
150 < }
325 >        ndfRaw_local += 3;
326  
327 +        if (integrableObject->isDirectional()) {
328 +          if (integrableObject->isLinear()) {
329 +            ndfRaw_local += 2;
330 +          } else {
331 +            ndfRaw_local += 3;
332 +          }
333 +        }
334 +            
335 +      }
336 +    }
337 +    
338 + #ifdef IS_MPI
339 +    MPI_Allreduce(&ndfRaw_local,&ndfRaw_,1,MPI_INT,MPI_SUM, MPI_COMM_WORLD);
340 + #else
341 +    ndfRaw_ = ndfRaw_local;
342 + #endif
343 +  }
344  
345 < void SimInfo::scaleBox(double scale) {
346 <  double theBox[3][3];
155 <  int i, j;
345 >  void SimInfo::calcNdfTrans() {
346 >    int ndfTrans_local;
347  
348 <  // cerr << "Scaling box by " << scale << "\n";
348 >    ndfTrans_local = 3 * nIntegrableObjects_ - nConstraints_;
349  
159  for(i=0; i<3; i++)
160    for (j=0; j<3; j++) theBox[i][j] = Hmat[i][j]*scale;
350  
351 <  setBoxM(theBox);
351 > #ifdef IS_MPI
352 >    MPI_Allreduce(&ndfTrans_local,&ndfTrans_,1,MPI_INT,MPI_SUM, MPI_COMM_WORLD);
353 > #else
354 >    ndfTrans_ = ndfTrans_local;
355 > #endif
356  
357 < }
357 >    ndfTrans_ = ndfTrans_ - 3 - nZconstraint_;
358 >
359 >  }
360  
361 < void SimInfo::calcHmatInv( void ) {
362 <  
363 <  int oldOrtho;
364 <  int i,j;
365 <  double smallDiag;
366 <  double tol;
367 <  double sanity[3][3];
368 <
369 <  invertMat3( Hmat, HmatInv );
370 <
371 <  // check to see if Hmat is orthorhombic
372 <  
373 <  oldOrtho = orthoRhombic;
361 >  void SimInfo::addInteractionPairs(Molecule* mol) {
362 >    ForceFieldOptions& options_ = forceField_->getForceFieldOptions();
363 >    vector<Bond*>::iterator bondIter;
364 >    vector<Bend*>::iterator bendIter;
365 >    vector<Torsion*>::iterator torsionIter;
366 >    vector<Inversion*>::iterator inversionIter;
367 >    Bond* bond;
368 >    Bend* bend;
369 >    Torsion* torsion;
370 >    Inversion* inversion;
371 >    int a;
372 >    int b;
373 >    int c;
374 >    int d;
375  
376 <  smallDiag = fabs(Hmat[0][0]);
377 <  if(smallDiag > fabs(Hmat[1][1])) smallDiag = fabs(Hmat[1][1]);
378 <  if(smallDiag > fabs(Hmat[2][2])) smallDiag = fabs(Hmat[2][2]);
379 <  tol = smallDiag * orthoTolerance;
376 >    // atomGroups can be used to add special interaction maps between
377 >    // groups of atoms that are in two separate rigid bodies.
378 >    // However, most site-site interactions between two rigid bodies
379 >    // are probably not special, just the ones between the physically
380 >    // bonded atoms.  Interactions *within* a single rigid body should
381 >    // always be excluded.  These are done at the bottom of this
382 >    // function.
383  
384 <  orthoRhombic = 1;
385 <  
386 <  for (i = 0; i < 3; i++ ) {
387 <    for (j = 0 ; j < 3; j++) {
388 <      if (i != j) {
389 <        if (orthoRhombic) {
390 <          if ( fabs(Hmat[i][j]) >= tol) orthoRhombic = 0;
391 <        }        
384 >    map<int, set<int> > atomGroups;
385 >    Molecule::RigidBodyIterator rbIter;
386 >    RigidBody* rb;
387 >    Molecule::IntegrableObjectIterator ii;
388 >    StuntDouble* integrableObject;
389 >    
390 >    for (integrableObject = mol->beginIntegrableObject(ii);
391 >         integrableObject != NULL;
392 >         integrableObject = mol->nextIntegrableObject(ii)) {
393 >      
394 >      if (integrableObject->isRigidBody()) {
395 >        rb = static_cast<RigidBody*>(integrableObject);
396 >        vector<Atom*> atoms = rb->getAtoms();
397 >        set<int> rigidAtoms;
398 >        for (int i = 0; i < static_cast<int>(atoms.size()); ++i) {
399 >          rigidAtoms.insert(atoms[i]->getGlobalIndex());
400 >        }
401 >        for (int i = 0; i < static_cast<int>(atoms.size()); ++i) {
402 >          atomGroups.insert(map<int, set<int> >::value_type(atoms[i]->getGlobalIndex(), rigidAtoms));
403 >        }      
404 >      } else {
405 >        set<int> oneAtomSet;
406 >        oneAtomSet.insert(integrableObject->getGlobalIndex());
407 >        atomGroups.insert(map<int, set<int> >::value_type(integrableObject->getGlobalIndex(), oneAtomSet));        
408        }
409 <    }
410 <  }
409 >    }  
410 >          
411 >    for (bond= mol->beginBond(bondIter); bond != NULL;
412 >         bond = mol->nextBond(bondIter)) {
413  
414 <  if( oldOrtho != orthoRhombic ){
414 >      a = bond->getAtomA()->getGlobalIndex();
415 >      b = bond->getAtomB()->getGlobalIndex();  
416      
417 <    if( orthoRhombic ) {
418 <      sprintf( painCave.errMsg,
419 <               "OOPSE is switching from the default Non-Orthorhombic\n"
420 <               "\tto the faster Orthorhombic periodic boundary computations.\n"
421 <               "\tThis is usually a good thing, but if you wan't the\n"
204 <               "\tNon-Orthorhombic computations, make the orthoBoxTolerance\n"
205 <               "\tvariable ( currently set to %G ) smaller.\n",
206 <               orthoTolerance);
207 <      painCave.severity = OOPSE_INFO;
208 <      simError();
417 >      if (options_.havevdw12scale() || options_.haveelectrostatic12scale()) {
418 >        oneTwoInteractions_.addPair(a, b);
419 >      } else {
420 >        excludedInteractions_.addPair(a, b);
421 >      }
422      }
210    else {
211      sprintf( painCave.errMsg,
212               "OOPSE is switching from the faster Orthorhombic to the more\n"
213               "\tflexible Non-Orthorhombic periodic boundary computations.\n"
214               "\tThis is usually because the box has deformed under\n"
215               "\tNPTf integration. If you wan't to live on the edge with\n"
216               "\tthe Orthorhombic computations, make the orthoBoxTolerance\n"
217               "\tvariable ( currently set to %G ) larger.\n",
218               orthoTolerance);
219      painCave.severity = OOPSE_WARNING;
220      simError();
221    }
222  }
223 }
423  
424 < void SimInfo::calcBoxL( void ){
424 >    for (bend= mol->beginBend(bendIter); bend != NULL;
425 >         bend = mol->nextBend(bendIter)) {
426  
427 <  double dx, dy, dz, dsq;
427 >      a = bend->getAtomA()->getGlobalIndex();
428 >      b = bend->getAtomB()->getGlobalIndex();        
429 >      c = bend->getAtomC()->getGlobalIndex();
430 >      
431 >      if (options_.havevdw12scale() || options_.haveelectrostatic12scale()) {
432 >        oneTwoInteractions_.addPair(a, b);      
433 >        oneTwoInteractions_.addPair(b, c);
434 >      } else {
435 >        excludedInteractions_.addPair(a, b);
436 >        excludedInteractions_.addPair(b, c);
437 >      }
438  
439 <  // boxVol = Determinant of Hmat
439 >      if (options_.havevdw13scale() || options_.haveelectrostatic13scale()) {
440 >        oneThreeInteractions_.addPair(a, c);      
441 >      } else {
442 >        excludedInteractions_.addPair(a, c);
443 >      }
444 >    }
445  
446 <  boxVol = matDet3( Hmat );
446 >    for (torsion= mol->beginTorsion(torsionIter); torsion != NULL;
447 >         torsion = mol->nextTorsion(torsionIter)) {
448  
449 <  // boxLx
450 <  
451 <  dx = Hmat[0][0]; dy = Hmat[1][0]; dz = Hmat[2][0];
452 <  dsq = dx*dx + dy*dy + dz*dz;
237 <  boxL[0] = sqrt( dsq );
238 <  //maxCutoff = 0.5 * boxL[0];
449 >      a = torsion->getAtomA()->getGlobalIndex();
450 >      b = torsion->getAtomB()->getGlobalIndex();        
451 >      c = torsion->getAtomC()->getGlobalIndex();        
452 >      d = torsion->getAtomD()->getGlobalIndex();      
453  
454 <  // boxLy
455 <  
456 <  dx = Hmat[0][1]; dy = Hmat[1][1]; dz = Hmat[2][1];
457 <  dsq = dx*dx + dy*dy + dz*dz;
458 <  boxL[1] = sqrt( dsq );
459 <  //if( (0.5 * boxL[1]) < maxCutoff ) maxCutoff = 0.5 * boxL[1];
454 >      if (options_.havevdw12scale() || options_.haveelectrostatic12scale()) {
455 >        oneTwoInteractions_.addPair(a, b);      
456 >        oneTwoInteractions_.addPair(b, c);
457 >        oneTwoInteractions_.addPair(c, d);
458 >      } else {
459 >        excludedInteractions_.addPair(a, b);
460 >        excludedInteractions_.addPair(b, c);
461 >        excludedInteractions_.addPair(c, d);
462 >      }
463  
464 +      if (options_.havevdw13scale() || options_.haveelectrostatic13scale()) {
465 +        oneThreeInteractions_.addPair(a, c);      
466 +        oneThreeInteractions_.addPair(b, d);      
467 +      } else {
468 +        excludedInteractions_.addPair(a, c);
469 +        excludedInteractions_.addPair(b, d);
470 +      }
471  
472 <  // boxLz
473 <  
474 <  dx = Hmat[0][2]; dy = Hmat[1][2]; dz = Hmat[2][2];
475 <  dsq = dx*dx + dy*dy + dz*dz;
476 <  boxL[2] = sqrt( dsq );
477 <  //if( (0.5 * boxL[2]) < maxCutoff ) maxCutoff = 0.5 * boxL[2];
472 >      if (options_.havevdw14scale() || options_.haveelectrostatic14scale()) {
473 >        oneFourInteractions_.addPair(a, d);      
474 >      } else {
475 >        excludedInteractions_.addPair(a, d);
476 >      }
477 >    }
478  
479 <  //calculate the max cutoff
480 <  maxCutoff =  calcMaxCutOff();
257 <  
258 <  checkCutOffs();
479 >    for (inversion= mol->beginInversion(inversionIter); inversion != NULL;
480 >         inversion = mol->nextInversion(inversionIter)) {
481  
482 < }
482 >      a = inversion->getAtomA()->getGlobalIndex();
483 >      b = inversion->getAtomB()->getGlobalIndex();        
484 >      c = inversion->getAtomC()->getGlobalIndex();        
485 >      d = inversion->getAtomD()->getGlobalIndex();        
486  
487 +      if (options_.havevdw12scale() || options_.haveelectrostatic12scale()) {
488 +        oneTwoInteractions_.addPair(a, b);      
489 +        oneTwoInteractions_.addPair(a, c);
490 +        oneTwoInteractions_.addPair(a, d);
491 +      } else {
492 +        excludedInteractions_.addPair(a, b);
493 +        excludedInteractions_.addPair(a, c);
494 +        excludedInteractions_.addPair(a, d);
495 +      }
496  
497 < double SimInfo::calcMaxCutOff(){
497 >      if (options_.havevdw13scale() || options_.haveelectrostatic13scale()) {
498 >        oneThreeInteractions_.addPair(b, c);    
499 >        oneThreeInteractions_.addPair(b, d);    
500 >        oneThreeInteractions_.addPair(c, d);      
501 >      } else {
502 >        excludedInteractions_.addPair(b, c);
503 >        excludedInteractions_.addPair(b, d);
504 >        excludedInteractions_.addPair(c, d);
505 >      }
506 >    }
507  
508 <  double ri[3], rj[3], rk[3];
509 <  double rij[3], rjk[3], rki[3];
510 <  double minDist;
508 >    for (rb = mol->beginRigidBody(rbIter); rb != NULL;
509 >         rb = mol->nextRigidBody(rbIter)) {
510 >      vector<Atom*> atoms = rb->getAtoms();
511 >      for (int i = 0; i < static_cast<int>(atoms.size()) -1 ; ++i) {
512 >        for (int j = i + 1; j < static_cast<int>(atoms.size()); ++j) {
513 >          a = atoms[i]->getGlobalIndex();
514 >          b = atoms[j]->getGlobalIndex();
515 >          excludedInteractions_.addPair(a, b);
516 >        }
517 >      }
518 >    }        
519  
520 <  ri[0] = Hmat[0][0];
270 <  ri[1] = Hmat[1][0];
271 <  ri[2] = Hmat[2][0];
520 >  }
521  
522 <  rj[0] = Hmat[0][1];
523 <  rj[1] = Hmat[1][1];
524 <  rj[2] = Hmat[2][1];
522 >  void SimInfo::removeInteractionPairs(Molecule* mol) {
523 >    ForceFieldOptions& options_ = forceField_->getForceFieldOptions();
524 >    vector<Bond*>::iterator bondIter;
525 >    vector<Bend*>::iterator bendIter;
526 >    vector<Torsion*>::iterator torsionIter;
527 >    vector<Inversion*>::iterator inversionIter;
528 >    Bond* bond;
529 >    Bend* bend;
530 >    Torsion* torsion;
531 >    Inversion* inversion;
532 >    int a;
533 >    int b;
534 >    int c;
535 >    int d;
536  
537 <  rk[0] = Hmat[0][2];
538 <  rk[1] = Hmat[1][2];
539 <  rk[2] = Hmat[2][2];
537 >    map<int, set<int> > atomGroups;
538 >    Molecule::RigidBodyIterator rbIter;
539 >    RigidBody* rb;
540 >    Molecule::IntegrableObjectIterator ii;
541 >    StuntDouble* integrableObject;
542      
543 <  crossProduct3(ri, rj, rij);
544 <  distXY = dotProduct3(rk,rij) / norm3(rij);
543 >    for (integrableObject = mol->beginIntegrableObject(ii);
544 >         integrableObject != NULL;
545 >         integrableObject = mol->nextIntegrableObject(ii)) {
546 >      
547 >      if (integrableObject->isRigidBody()) {
548 >        rb = static_cast<RigidBody*>(integrableObject);
549 >        vector<Atom*> atoms = rb->getAtoms();
550 >        set<int> rigidAtoms;
551 >        for (int i = 0; i < static_cast<int>(atoms.size()); ++i) {
552 >          rigidAtoms.insert(atoms[i]->getGlobalIndex());
553 >        }
554 >        for (int i = 0; i < static_cast<int>(atoms.size()); ++i) {
555 >          atomGroups.insert(map<int, set<int> >::value_type(atoms[i]->getGlobalIndex(), rigidAtoms));
556 >        }      
557 >      } else {
558 >        set<int> oneAtomSet;
559 >        oneAtomSet.insert(integrableObject->getGlobalIndex());
560 >        atomGroups.insert(map<int, set<int> >::value_type(integrableObject->getGlobalIndex(), oneAtomSet));        
561 >      }
562 >    }  
563  
564 <  crossProduct3(rj,rk, rjk);
565 <  distYZ = dotProduct3(ri,rjk) / norm3(rjk);
564 >    for (bond= mol->beginBond(bondIter); bond != NULL;
565 >         bond = mol->nextBond(bondIter)) {
566 >      
567 >      a = bond->getAtomA()->getGlobalIndex();
568 >      b = bond->getAtomB()->getGlobalIndex();  
569 >    
570 >      if (options_.havevdw12scale() || options_.haveelectrostatic12scale()) {
571 >        oneTwoInteractions_.removePair(a, b);
572 >      } else {
573 >        excludedInteractions_.removePair(a, b);
574 >      }
575 >    }
576  
577 <  crossProduct3(rk,ri, rki);
578 <  distZX = dotProduct3(rj,rki) / norm3(rki);
577 >    for (bend= mol->beginBend(bendIter); bend != NULL;
578 >         bend = mol->nextBend(bendIter)) {
579  
580 <  minDist = min(min(distXY, distYZ), distZX);
581 <  return minDist/2;
582 <  
583 < }
580 >      a = bend->getAtomA()->getGlobalIndex();
581 >      b = bend->getAtomB()->getGlobalIndex();        
582 >      c = bend->getAtomC()->getGlobalIndex();
583 >      
584 >      if (options_.havevdw12scale() || options_.haveelectrostatic12scale()) {
585 >        oneTwoInteractions_.removePair(a, b);      
586 >        oneTwoInteractions_.removePair(b, c);
587 >      } else {
588 >        excludedInteractions_.removePair(a, b);
589 >        excludedInteractions_.removePair(b, c);
590 >      }
591  
592 < void SimInfo::wrapVector( double thePos[3] ){
592 >      if (options_.havevdw13scale() || options_.haveelectrostatic13scale()) {
593 >        oneThreeInteractions_.removePair(a, c);      
594 >      } else {
595 >        excludedInteractions_.removePair(a, c);
596 >      }
597 >    }
598  
599 <  int i;
600 <  double scaled[3];
599 >    for (torsion= mol->beginTorsion(torsionIter); torsion != NULL;
600 >         torsion = mol->nextTorsion(torsionIter)) {
601  
602 <  if( !orthoRhombic ){
603 <    // calc the scaled coordinates.
602 >      a = torsion->getAtomA()->getGlobalIndex();
603 >      b = torsion->getAtomB()->getGlobalIndex();        
604 >      c = torsion->getAtomC()->getGlobalIndex();        
605 >      d = torsion->getAtomD()->getGlobalIndex();      
606    
607 +      if (options_.havevdw12scale() || options_.haveelectrostatic12scale()) {
608 +        oneTwoInteractions_.removePair(a, b);      
609 +        oneTwoInteractions_.removePair(b, c);
610 +        oneTwoInteractions_.removePair(c, d);
611 +      } else {
612 +        excludedInteractions_.removePair(a, b);
613 +        excludedInteractions_.removePair(b, c);
614 +        excludedInteractions_.removePair(c, d);
615 +      }
616  
617 <    matVecMul3(HmatInv, thePos, scaled);
618 <    
619 <    for(i=0; i<3; i++)
620 <      scaled[i] -= roundMe(scaled[i]);
621 <    
622 <    // calc the wrapped real coordinates from the wrapped scaled coordinates
623 <    
311 <    matVecMul3(Hmat, scaled, thePos);
617 >      if (options_.havevdw13scale() || options_.haveelectrostatic13scale()) {
618 >        oneThreeInteractions_.removePair(a, c);      
619 >        oneThreeInteractions_.removePair(b, d);      
620 >      } else {
621 >        excludedInteractions_.removePair(a, c);
622 >        excludedInteractions_.removePair(b, d);
623 >      }
624  
625 <  }
626 <  else{
627 <    // calc the scaled coordinates.
628 <    
629 <    for(i=0; i<3; i++)
630 <      scaled[i] = thePos[i]*HmatInv[i][i];
319 <    
320 <    // wrap the scaled coordinates
321 <    
322 <    for(i=0; i<3; i++)
323 <      scaled[i] -= roundMe(scaled[i]);
324 <    
325 <    // calc the wrapped real coordinates from the wrapped scaled coordinates
326 <    
327 <    for(i=0; i<3; i++)
328 <      thePos[i] = scaled[i]*Hmat[i][i];
329 <  }
330 <    
331 < }
625 >      if (options_.havevdw14scale() || options_.haveelectrostatic14scale()) {
626 >        oneFourInteractions_.removePair(a, d);      
627 >      } else {
628 >        excludedInteractions_.removePair(a, d);
629 >      }
630 >    }
631  
632 +    for (inversion= mol->beginInversion(inversionIter); inversion != NULL;
633 +         inversion = mol->nextInversion(inversionIter)) {
634  
635 < int SimInfo::getNDF(){
636 <  int ndf_local;
635 >      a = inversion->getAtomA()->getGlobalIndex();
636 >      b = inversion->getAtomB()->getGlobalIndex();        
637 >      c = inversion->getAtomC()->getGlobalIndex();        
638 >      d = inversion->getAtomD()->getGlobalIndex();        
639  
640 <  ndf_local = 0;
641 <  
642 <  for(int i = 0; i < integrableObjects.size(); i++){
643 <    ndf_local += 3;
644 <    if (integrableObjects[i]->isDirectional()) {
645 <      if (integrableObjects[i]->isLinear())
646 <        ndf_local += 2;
647 <      else
648 <        ndf_local += 3;
649 <    }
640 >      if (options_.havevdw12scale() || options_.haveelectrostatic12scale()) {
641 >        oneTwoInteractions_.removePair(a, b);      
642 >        oneTwoInteractions_.removePair(a, c);
643 >        oneTwoInteractions_.removePair(a, d);
644 >      } else {
645 >        excludedInteractions_.removePair(a, b);
646 >        excludedInteractions_.removePair(a, c);
647 >        excludedInteractions_.removePair(a, d);
648 >      }
649 >
650 >      if (options_.havevdw13scale() || options_.haveelectrostatic13scale()) {
651 >        oneThreeInteractions_.removePair(b, c);    
652 >        oneThreeInteractions_.removePair(b, d);    
653 >        oneThreeInteractions_.removePair(c, d);      
654 >      } else {
655 >        excludedInteractions_.removePair(b, c);
656 >        excludedInteractions_.removePair(b, d);
657 >        excludedInteractions_.removePair(c, d);
658 >      }
659 >    }
660 >
661 >    for (rb = mol->beginRigidBody(rbIter); rb != NULL;
662 >         rb = mol->nextRigidBody(rbIter)) {
663 >      vector<Atom*> atoms = rb->getAtoms();
664 >      for (int i = 0; i < static_cast<int>(atoms.size()) -1 ; ++i) {
665 >        for (int j = i + 1; j < static_cast<int>(atoms.size()); ++j) {
666 >          a = atoms[i]->getGlobalIndex();
667 >          b = atoms[j]->getGlobalIndex();
668 >          excludedInteractions_.removePair(a, b);
669 >        }
670 >      }
671 >    }        
672 >    
673    }
674 +  
675 +  
676 +  void SimInfo::addMoleculeStamp(MoleculeStamp* molStamp, int nmol) {
677 +    int curStampId;
678 +    
679 +    //index from 0
680 +    curStampId = moleculeStamps_.size();
681  
682 <  // n_constraints is local, so subtract them on each processor:
682 >    moleculeStamps_.push_back(molStamp);
683 >    molStampIds_.insert(molStampIds_.end(), nmol, curStampId);
684 >  }
685  
351  ndf_local -= n_constraints;
686  
687 +  /**
688 +   * update
689 +   *
690 +   *  Performs the global checks and variable settings after the
691 +   *  objects have been created.
692 +   *
693 +   */
694 +  void SimInfo::update() {  
695 +    setupSimVariables();
696 +    calcNdf();
697 +    calcNdfRaw();
698 +    calcNdfTrans();
699 +  }
700 +  
701 +  /**
702 +   * getSimulatedAtomTypes
703 +   *
704 +   * Returns an STL set of AtomType* that are actually present in this
705 +   * simulation.  Must query all processors to assemble this information.
706 +   *
707 +   */
708 +  set<AtomType*> SimInfo::getSimulatedAtomTypes() {
709 +    SimInfo::MoleculeIterator mi;
710 +    Molecule* mol;
711 +    Molecule::AtomIterator ai;
712 +    Atom* atom;
713 +    set<AtomType*> atomTypes;
714 +    
715 +    for(mol = beginMolecule(mi); mol != NULL; mol = nextMolecule(mi)) {
716 +      for(atom = mol->beginAtom(ai); atom != NULL;
717 +          atom = mol->nextAtom(ai)) {
718 +        atomTypes.insert(atom->getAtomType());
719 +      }      
720 +    }    
721 +    
722   #ifdef IS_MPI
354  MPI_Allreduce(&ndf_local,&ndf,1,MPI_INT,MPI_SUM, MPI_COMM_WORLD);
355 #else
356  ndf = ndf_local;
357 #endif
723  
724 <  // nZconstraints is global, as are the 3 COM translations for the
725 <  // entire system:
724 >    // loop over the found atom types on this processor, and add their
725 >    // numerical idents to a vector:
726 >    
727 >    vector<int> foundTypes;
728 >    set<AtomType*>::iterator i;
729 >    for (i = atomTypes.begin(); i != atomTypes.end(); ++i)
730 >      foundTypes.push_back( (*i)->getIdent() );
731  
732 <  ndf = ndf - 3 - nZconstraints;
732 >    // count_local holds the number of found types on this processor
733 >    int count_local = foundTypes.size();
734  
735 <  return ndf;
365 < }
735 >    int nproc = MPI::COMM_WORLD.Get_size();
736  
737 < int SimInfo::getNDFraw() {
738 <  int ndfRaw_local;
737 >    // we need arrays to hold the counts and displacement vectors for
738 >    // all processors
739 >    vector<int> counts(nproc, 0);
740 >    vector<int> disps(nproc, 0);
741  
742 <  // Raw degrees of freedom that we have to set
743 <  ndfRaw_local = 0;
744 <
745 <  for(int i = 0; i < integrableObjects.size(); i++){
746 <    ndfRaw_local += 3;
747 <    if (integrableObjects[i]->isDirectional()) {
748 <       if (integrableObjects[i]->isLinear())
749 <        ndfRaw_local += 2;
750 <      else
751 <        ndfRaw_local += 3;
742 >    // fill the counts array
743 >    MPI::COMM_WORLD.Allgather(&count_local, 1, MPI::INT, &counts[0],
744 >                              1, MPI::INT);
745 >  
746 >    // use the processor counts to compute the displacement array
747 >    disps[0] = 0;    
748 >    int totalCount = counts[0];
749 >    for (int iproc = 1; iproc < nproc; iproc++) {
750 >      disps[iproc] = disps[iproc-1] + counts[iproc-1];
751 >      totalCount += counts[iproc];
752      }
753 +
754 +    // we need a (possibly redundant) set of all found types:
755 +    vector<int> ftGlobal(totalCount);
756 +    
757 +    // now spray out the foundTypes to all the other processors:    
758 +    MPI::COMM_WORLD.Allgatherv(&foundTypes[0], count_local, MPI::INT,
759 +                               &ftGlobal[0], &counts[0], &disps[0],
760 +                               MPI::INT);
761 +
762 +    vector<int>::iterator j;
763 +
764 +    // foundIdents is a stl set, so inserting an already found ident
765 +    // will have no effect.
766 +    set<int> foundIdents;
767 +
768 +    for (j = ftGlobal.begin(); j != ftGlobal.end(); ++j)
769 +      foundIdents.insert((*j));
770 +    
771 +    // now iterate over the foundIdents and get the actual atom types
772 +    // that correspond to these:
773 +    set<int>::iterator it;
774 +    for (it = foundIdents.begin(); it != foundIdents.end(); ++it)
775 +      atomTypes.insert( forceField_->getAtomType((*it)) );
776 +
777 + #endif
778 +
779 +    return atomTypes;        
780    }
781 +
782 +  void SimInfo::setupSimVariables() {
783 +    useAtomicVirial_ = simParams_->getUseAtomicVirial();
784 +    // we only call setAccumulateBoxDipole if the accumulateBoxDipole parameter is true
785 +    calcBoxDipole_ = false;
786 +    if ( simParams_->haveAccumulateBoxDipole() )
787 +      if ( simParams_->getAccumulateBoxDipole() ) {
788 +        calcBoxDipole_ = true;      
789 +      }
790      
791 < #ifdef IS_MPI
792 <  MPI_Allreduce(&ndfRaw_local,&ndfRaw,1,MPI_INT,MPI_SUM, MPI_COMM_WORLD);
791 >    set<AtomType*>::iterator i;
792 >    set<AtomType*> atomTypes;
793 >    atomTypes = getSimulatedAtomTypes();    
794 >    int usesElectrostatic = 0;
795 >    int usesMetallic = 0;
796 >    int usesDirectional = 0;
797 >    int usesFluctuatingCharges =  0;
798 >    //loop over all of the atom types
799 >    for (i = atomTypes.begin(); i != atomTypes.end(); ++i) {
800 >      usesElectrostatic |= (*i)->isElectrostatic();
801 >      usesMetallic |= (*i)->isMetal();
802 >      usesDirectional |= (*i)->isDirectional();
803 >      usesFluctuatingCharges |= (*i)->isFluctuatingCharge();
804 >    }
805 >    
806 > #ifdef IS_MPI    
807 >    int temp;
808 >    temp = usesDirectional;
809 >    MPI_Allreduce(&temp, &usesDirectionalAtoms_, 1, MPI_INT, MPI_LOR, MPI_COMM_WORLD);    
810 >    
811 >    temp = usesMetallic;
812 >    MPI_Allreduce(&temp, &usesMetallicAtoms_, 1, MPI_INT, MPI_LOR, MPI_COMM_WORLD);    
813 >    
814 >    temp = usesElectrostatic;
815 >    MPI_Allreduce(&temp, &usesElectrostaticAtoms_, 1, MPI_INT, MPI_LOR, MPI_COMM_WORLD);
816 >
817 >    temp = usesFluctuatingCharges;
818 >    MPI_Allreduce(&temp, &usesFluctuatingCharges_, 1, MPI_INT, MPI_LOR, MPI_COMM_WORLD);
819   #else
820 <  ndfRaw = ndfRaw_local;
820 >
821 >    usesDirectionalAtoms_ = usesDirectional;
822 >    usesMetallicAtoms_ = usesMetallic;
823 >    usesElectrostaticAtoms_ = usesElectrostatic;
824 >    usesFluctuatingCharges_ = usesFluctuatingCharges;
825 >
826   #endif
827 +    
828 +    requiresPrepair_ = usesMetallicAtoms_ ? true : false;
829 +    requiresSkipCorrection_ = usesElectrostaticAtoms_ ? true : false;
830 +    requiresSelfCorrection_ = usesElectrostaticAtoms_ ? true : false;    
831 +  }
832  
389  return ndfRaw;
390 }
833  
834 < int SimInfo::getNDFtranslational() {
835 <  int ndfTrans_local;
834 >  vector<int> SimInfo::getGlobalAtomIndices() {
835 >    SimInfo::MoleculeIterator mi;
836 >    Molecule* mol;
837 >    Molecule::AtomIterator ai;
838 >    Atom* atom;
839  
840 <  ndfTrans_local = 3 * integrableObjects.size() - n_constraints;
840 >    vector<int> GlobalAtomIndices(getNAtoms(), 0);
841 >    
842 >    for (mol = beginMolecule(mi); mol != NULL; mol  = nextMolecule(mi)) {
843 >      
844 >      for (atom = mol->beginAtom(ai); atom != NULL; atom = mol->nextAtom(ai)) {
845 >        GlobalAtomIndices[atom->getLocalIndex()] = atom->getGlobalIndex();
846 >      }
847 >    }
848 >    return GlobalAtomIndices;
849 >  }
850  
851  
852 < #ifdef IS_MPI
853 <  MPI_Allreduce(&ndfTrans_local,&ndfTrans,1,MPI_INT,MPI_SUM, MPI_COMM_WORLD);
854 < #else
855 <  ndfTrans = ndfTrans_local;
856 < #endif
852 >  vector<int> SimInfo::getGlobalGroupIndices() {
853 >    SimInfo::MoleculeIterator mi;
854 >    Molecule* mol;
855 >    Molecule::CutoffGroupIterator ci;
856 >    CutoffGroup* cg;
857  
858 <  ndfTrans = ndfTrans - 3 - nZconstraints;
858 >    vector<int> GlobalGroupIndices;
859 >    
860 >    for (mol = beginMolecule(mi); mol != NULL; mol  = nextMolecule(mi)) {
861 >      
862 >      //local index of cutoff group is trivial, it only depends on the
863 >      //order of travesing
864 >      for (cg = mol->beginCutoffGroup(ci); cg != NULL;
865 >           cg = mol->nextCutoffGroup(ci)) {
866 >        GlobalGroupIndices.push_back(cg->getGlobalIndex());
867 >      }        
868 >    }
869 >    return GlobalGroupIndices;
870 >  }
871  
406  return ndfTrans;
407 }
872  
873 < int SimInfo::getTotIntegrableObjects() {
874 <  int nObjs_local;
411 <  int nObjs;
873 >  void SimInfo::prepareTopology() {
874 >    int nExclude, nOneTwo, nOneThree, nOneFour;
875  
876 <  nObjs_local =  integrableObjects.size();
876 >    //calculate mass ratio of cutoff group
877 >    SimInfo::MoleculeIterator mi;
878 >    Molecule* mol;
879 >    Molecule::CutoffGroupIterator ci;
880 >    CutoffGroup* cg;
881 >    Molecule::AtomIterator ai;
882 >    Atom* atom;
883 >    RealType totalMass;
884  
885 +    /**
886 +     * The mass factor is the relative mass of an atom to the total
887 +     * mass of the cutoff group it belongs to.  By default, all atoms
888 +     * are their own cutoff groups, and therefore have mass factors of
889 +     * 1.  We need some special handling for massless atoms, which
890 +     * will be treated as carrying the entire mass of the cutoff
891 +     * group.
892 +     */
893 +    massFactors_.clear();
894 +    massFactors_.resize(getNAtoms(), 1.0);
895 +    
896 +    for(mol = beginMolecule(mi); mol != NULL; mol = nextMolecule(mi)) {        
897 +      for (cg = mol->beginCutoffGroup(ci); cg != NULL;
898 +           cg = mol->nextCutoffGroup(ci)) {
899  
900 < #ifdef IS_MPI
901 <  MPI_Allreduce(&nObjs_local,&nObjs,1,MPI_INT,MPI_SUM, MPI_COMM_WORLD);
902 < #else
903 <  nObjs = nObjs_local;
904 < #endif
900 >        totalMass = cg->getMass();
901 >        for(atom = cg->beginAtom(ai); atom != NULL; atom = cg->nextAtom(ai)) {
902 >          // Check for massless groups - set mfact to 1 if true
903 >          if (totalMass != 0)
904 >            massFactors_[atom->getLocalIndex()] = atom->getMass()/totalMass;
905 >          else
906 >            massFactors_[atom->getLocalIndex()] = 1.0;
907 >        }
908 >      }      
909 >    }
910  
911 +    // Build the identArray_
912  
913 <  return nObjs;
914 < }
913 >    identArray_.clear();
914 >    identArray_.reserve(getNAtoms());    
915 >    for(mol = beginMolecule(mi); mol != NULL; mol = nextMolecule(mi)) {        
916 >      for(atom = mol->beginAtom(ai); atom != NULL; atom = mol->nextAtom(ai)) {
917 >        identArray_.push_back(atom->getIdent());
918 >      }
919 >    }    
920 >    
921 >    //scan topology
922  
923 < void SimInfo::refreshSim(){
923 >    nExclude = excludedInteractions_.getSize();
924 >    nOneTwo = oneTwoInteractions_.getSize();
925 >    nOneThree = oneThreeInteractions_.getSize();
926 >    nOneFour = oneFourInteractions_.getSize();
927  
928 <  simtype fInfo;
929 <  int isError;
930 <  int n_global;
931 <  int* excl;
928 >    int* excludeList = excludedInteractions_.getPairList();
929 >    int* oneTwoList = oneTwoInteractions_.getPairList();
930 >    int* oneThreeList = oneThreeInteractions_.getPairList();
931 >    int* oneFourList = oneFourInteractions_.getPairList();
932  
933 <  fInfo.dielect = 0.0;
933 >    topologyDone_ = true;
934 >  }
935  
936 <  if( useDipoles ){
937 <    if( useReactionField )fInfo.dielect = dielectric;
936 >  void SimInfo::addProperty(GenericData* genData) {
937 >    properties_.addProperty(genData);  
938    }
939  
940 <  fInfo.SIM_uses_PBC = usePBC;
940 >  void SimInfo::removeProperty(const string& propName) {
941 >    properties_.removeProperty(propName);  
942 >  }
943  
944 <  if (useSticky || useDipoles || useGayBerne || useShapes) {
945 <    useDirectionalAtoms = 1;
443 <    fInfo.SIM_uses_DirectionalAtoms = useDirectionalAtoms;
944 >  void SimInfo::clearProperties() {
945 >    properties_.clearProperties();
946    }
947  
948 <  fInfo.SIM_uses_LennardJones = useLennardJones;
948 >  vector<string> SimInfo::getPropertyNames() {
949 >    return properties_.getPropertyNames();  
950 >  }
951 >      
952 >  vector<GenericData*> SimInfo::getProperties() {
953 >    return properties_.getProperties();
954 >  }
955  
956 <  if (useCharges || useDipoles) {
957 <    useElectrostatics = 1;
450 <    fInfo.SIM_uses_Electrostatics = useElectrostatics;
956 >  GenericData* SimInfo::getPropertyByName(const string& propName) {
957 >    return properties_.getPropertyByName(propName);
958    }
959  
960 <  fInfo.SIM_uses_Charges = useCharges;
961 <  fInfo.SIM_uses_Dipoles = useDipoles;
962 <  fInfo.SIM_uses_Sticky = useSticky;
963 <  fInfo.SIM_uses_GayBerne = useGayBerne;
964 <  fInfo.SIM_uses_EAM = useEAM;
965 <  fInfo.SIM_uses_Shapes = useShapes;
459 <  fInfo.SIM_uses_FLARB = useFLARB;
460 <  fInfo.SIM_uses_RF = useReactionField;
960 >  void SimInfo::setSnapshotManager(SnapshotManager* sman) {
961 >    if (sman_ == sman) {
962 >      return;
963 >    }    
964 >    delete sman_;
965 >    sman_ = sman;
966  
967 <  n_exclude = excludes->getSize();
968 <  excl = excludes->getFortranArray();
969 <  
970 < #ifdef IS_MPI
971 <  n_global = mpiSim->getNAtomsGlobal();
972 < #else
973 <  n_global = n_atoms;
974 < #endif
975 <  
976 <  isError = 0;
977 <  
978 <  getFortranGroupArrays(this, FglobalGroupMembership, mfact);
979 <  //it may not be a good idea to pass the address of first element in vector
980 <  //since c++ standard does not require vector to be stored continuously in meomory
981 <  //Most of the compilers will organize the memory of vector continuously
982 <  setFortranSim( &fInfo, &n_global, &n_atoms, identArray, &n_exclude, excl,
983 <                  &nGlobalExcludes, globalExcludes, molMembershipArray,
984 <                  &mfact[0], &ngroup, &FglobalGroupMembership[0], &isError);
967 >    Molecule* mol;
968 >    RigidBody* rb;
969 >    Atom* atom;
970 >    CutoffGroup* cg;
971 >    SimInfo::MoleculeIterator mi;
972 >    Molecule::RigidBodyIterator rbIter;
973 >    Molecule::AtomIterator atomIter;
974 >    Molecule::CutoffGroupIterator cgIter;
975 >
976 >    for (mol = beginMolecule(mi); mol != NULL; mol = nextMolecule(mi)) {
977 >        
978 >      for (atom = mol->beginAtom(atomIter); atom != NULL; atom = mol->nextAtom(atomIter)) {
979 >        atom->setSnapshotManager(sman_);
980 >      }
981 >        
982 >      for (rb = mol->beginRigidBody(rbIter); rb != NULL; rb = mol->nextRigidBody(rbIter)) {
983 >        rb->setSnapshotManager(sman_);
984 >      }
985  
986 <  if( isError ){
986 >      for (cg = mol->beginCutoffGroup(cgIter); cg != NULL; cg = mol->nextCutoffGroup(cgIter)) {
987 >        cg->setSnapshotManager(sman_);
988 >      }
989 >    }    
990      
483    sprintf( painCave.errMsg,
484             "There was an error setting the simulation information in fortran.\n" );
485    painCave.isFatal = 1;
486    painCave.severity = OOPSE_ERROR;
487    simError();
991    }
489  
490 #ifdef IS_MPI
491  sprintf( checkPointMsg,
492           "succesfully sent the simulation information to fortran.\n");
493  MPIcheckPoint();
494 #endif // is_mpi
495  
496  this->ndf = this->getNDF();
497  this->ndfRaw = this->getNDFraw();
498  this->ndfTrans = this->getNDFtranslational();
499 }
992  
993 < void SimInfo::setDefaultRcut( double theRcut ){
994 <  
995 <  haveRcut = 1;
504 <  rCut = theRcut;
505 <  rList = rCut + 1.0;
506 <  
507 <  notifyFortranCutoffs( &rCut, &rSw, &rList );
508 < }
993 >  Vector3d SimInfo::getComVel(){
994 >    SimInfo::MoleculeIterator i;
995 >    Molecule* mol;
996  
997 < void SimInfo::setDefaultRcut( double theRcut, double theRsw ){
997 >    Vector3d comVel(0.0);
998 >    RealType totalMass = 0.0;
999 >    
1000 >
1001 >    for (mol = beginMolecule(i); mol != NULL; mol = nextMolecule(i)) {
1002 >      RealType mass = mol->getMass();
1003 >      totalMass += mass;
1004 >      comVel += mass * mol->getComVel();
1005 >    }  
1006  
1007 <  rSw = theRsw;
1008 <  setDefaultRcut( theRcut );
1009 < }
1007 > #ifdef IS_MPI
1008 >    RealType tmpMass = totalMass;
1009 >    Vector3d tmpComVel(comVel);    
1010 >    MPI_Allreduce(&tmpMass,&totalMass,1,MPI_REALTYPE,MPI_SUM, MPI_COMM_WORLD);
1011 >    MPI_Allreduce(tmpComVel.getArrayPointer(), comVel.getArrayPointer(),3,MPI_REALTYPE,MPI_SUM, MPI_COMM_WORLD);
1012 > #endif
1013  
1014 +    comVel /= totalMass;
1015  
1016 < void SimInfo::checkCutOffs( void ){
518 <  
519 <  if( boxIsInit ){
520 <    
521 <    //we need to check cutOffs against the box
522 <    
523 <    if( rCut > maxCutoff ){
524 <      sprintf( painCave.errMsg,
525 <               "cutoffRadius is too large for the current periodic box.\n"
526 <               "\tCurrent Value of cutoffRadius = %G at time %G\n "
527 <               "\tThis is larger than half of at least one of the\n"
528 <               "\tperiodic box vectors.  Right now, the Box matrix is:\n"
529 <               "\n"
530 <               "\t[ %G %G %G ]\n"
531 <               "\t[ %G %G %G ]\n"
532 <               "\t[ %G %G %G ]\n",
533 <               rCut, currentTime,
534 <               Hmat[0][0], Hmat[0][1], Hmat[0][2],
535 <               Hmat[1][0], Hmat[1][1], Hmat[1][2],
536 <               Hmat[2][0], Hmat[2][1], Hmat[2][2]);
537 <      painCave.severity = OOPSE_ERROR;
538 <      painCave.isFatal = 1;
539 <      simError();
540 <    }    
541 <  } else {
542 <    // initialize this stuff before using it, OK?
543 <    sprintf( painCave.errMsg,
544 <             "Trying to check cutoffs without a box.\n"
545 <             "\tOOPSE should have better programmers than that.\n" );
546 <    painCave.severity = OOPSE_ERROR;
547 <    painCave.isFatal = 1;
548 <    simError();      
1016 >    return comVel;
1017    }
550  
551 }
1018  
1019 < void SimInfo::addProperty(GenericData* prop){
1019 >  Vector3d SimInfo::getCom(){
1020 >    SimInfo::MoleculeIterator i;
1021 >    Molecule* mol;
1022  
1023 <  map<string, GenericData*>::iterator result;
1024 <  result = properties.find(prop->getID());
1025 <  
1026 <  //we can't simply use  properties[prop->getID()] = prop,
1027 <  //it will cause memory leak if we already contain a propery which has the same name of prop
1028 <  
1029 <  if(result != properties.end()){
1030 <    
563 <    delete (*result).second;
564 <    (*result).second = prop;
565 <      
566 <  }
567 <  else{
1023 >    Vector3d com(0.0);
1024 >    RealType totalMass = 0.0;
1025 >    
1026 >    for (mol = beginMolecule(i); mol != NULL; mol = nextMolecule(i)) {
1027 >      RealType mass = mol->getMass();
1028 >      totalMass += mass;
1029 >      com += mass * mol->getCom();
1030 >    }  
1031  
1032 <    properties[prop->getID()] = prop;
1032 > #ifdef IS_MPI
1033 >    RealType tmpMass = totalMass;
1034 >    Vector3d tmpCom(com);    
1035 >    MPI_Allreduce(&tmpMass,&totalMass,1,MPI_REALTYPE,MPI_SUM, MPI_COMM_WORLD);
1036 >    MPI_Allreduce(tmpCom.getArrayPointer(), com.getArrayPointer(),3,MPI_REALTYPE,MPI_SUM, MPI_COMM_WORLD);
1037 > #endif
1038  
1039 +    com /= totalMass;
1040 +
1041 +    return com;
1042 +
1043 +  }        
1044 +
1045 +  ostream& operator <<(ostream& o, SimInfo& info) {
1046 +
1047 +    return o;
1048    }
1049 +  
1050 +  
1051 +   /*
1052 +   Returns center of mass and center of mass velocity in one function call.
1053 +   */
1054 +  
1055 +   void SimInfo::getComAll(Vector3d &com, Vector3d &comVel){
1056 +      SimInfo::MoleculeIterator i;
1057 +      Molecule* mol;
1058 +      
1059      
1060 < }
1060 >      RealType totalMass = 0.0;
1061 >    
1062  
1063 < GenericData* SimInfo::getProperty(const string& propName){
1064 <
1065 <  map<string, GenericData*>::iterator result;
1066 <  
1067 <  //string lowerCaseName = ();
1068 <  
1069 <  result = properties.find(propName);
1070 <  
1071 <  if(result != properties.end())
1072 <    return (*result).second;  
1073 <  else  
1074 <    return NULL;  
1075 < }
1063 >      for (mol = beginMolecule(i); mol != NULL; mol = nextMolecule(i)) {
1064 >         RealType mass = mol->getMass();
1065 >         totalMass += mass;
1066 >         com += mass * mol->getCom();
1067 >         comVel += mass * mol->getComVel();          
1068 >      }  
1069 >      
1070 > #ifdef IS_MPI
1071 >      RealType tmpMass = totalMass;
1072 >      Vector3d tmpCom(com);  
1073 >      Vector3d tmpComVel(comVel);
1074 >      MPI_Allreduce(&tmpMass,&totalMass,1,MPI_REALTYPE,MPI_SUM, MPI_COMM_WORLD);
1075 >      MPI_Allreduce(tmpCom.getArrayPointer(), com.getArrayPointer(),3,MPI_REALTYPE,MPI_SUM, MPI_COMM_WORLD);
1076 >      MPI_Allreduce(tmpComVel.getArrayPointer(), comVel.getArrayPointer(),3,MPI_REALTYPE,MPI_SUM, MPI_COMM_WORLD);
1077 > #endif
1078 >      
1079 >      com /= totalMass;
1080 >      comVel /= totalMass;
1081 >   }        
1082 >  
1083 >   /*
1084 >   Return intertia tensor for entire system and angular momentum Vector.
1085  
1086  
1087 < void SimInfo::getFortranGroupArrays(SimInfo* info,
1088 <                                    vector<int>& FglobalGroupMembership,
1089 <                                    vector<double>& mfact){
1090 <  
594 <  Molecule* myMols;
595 <  Atom** myAtoms;
596 <  int numAtom;
597 <  double mtot;
598 <  int numMol;
599 <  int numCutoffGroups;
600 <  CutoffGroup* myCutoffGroup;
601 <  vector<CutoffGroup*>::iterator iterCutoff;
602 <  Atom* cutoffAtom;
603 <  vector<Atom*>::iterator iterAtom;
604 <  int atomIndex;
605 <  double totalMass;
606 <  
607 <  mfact.clear();
608 <  FglobalGroupMembership.clear();
609 <  
1087 >       [  Ixx -Ixy  -Ixz ]
1088 >    J =| -Iyx  Iyy  -Iyz |
1089 >       [ -Izx -Iyz   Izz ]
1090 >    */
1091  
1092 <  // Fix the silly fortran indexing problem
1092 >   void SimInfo::getInertiaTensor(Mat3x3d &inertiaTensor, Vector3d &angularMomentum){
1093 >      
1094 >
1095 >      RealType xx = 0.0;
1096 >      RealType yy = 0.0;
1097 >      RealType zz = 0.0;
1098 >      RealType xy = 0.0;
1099 >      RealType xz = 0.0;
1100 >      RealType yz = 0.0;
1101 >      Vector3d com(0.0);
1102 >      Vector3d comVel(0.0);
1103 >      
1104 >      getComAll(com, comVel);
1105 >      
1106 >      SimInfo::MoleculeIterator i;
1107 >      Molecule* mol;
1108 >      
1109 >      Vector3d thisq(0.0);
1110 >      Vector3d thisv(0.0);
1111 >
1112 >      RealType thisMass = 0.0;
1113 >    
1114 >      
1115 >      
1116 >  
1117 >      for (mol = beginMolecule(i); mol != NULL; mol = nextMolecule(i)) {
1118 >        
1119 >         thisq = mol->getCom()-com;
1120 >         thisv = mol->getComVel()-comVel;
1121 >         thisMass = mol->getMass();
1122 >         // Compute moment of intertia coefficients.
1123 >         xx += thisq[0]*thisq[0]*thisMass;
1124 >         yy += thisq[1]*thisq[1]*thisMass;
1125 >         zz += thisq[2]*thisq[2]*thisMass;
1126 >        
1127 >         // compute products of intertia
1128 >         xy += thisq[0]*thisq[1]*thisMass;
1129 >         xz += thisq[0]*thisq[2]*thisMass;
1130 >         yz += thisq[1]*thisq[2]*thisMass;
1131 >            
1132 >         angularMomentum += cross( thisq, thisv ) * thisMass;
1133 >            
1134 >      }  
1135 >      
1136 >      
1137 >      inertiaTensor(0,0) = yy + zz;
1138 >      inertiaTensor(0,1) = -xy;
1139 >      inertiaTensor(0,2) = -xz;
1140 >      inertiaTensor(1,0) = -xy;
1141 >      inertiaTensor(1,1) = xx + zz;
1142 >      inertiaTensor(1,2) = -yz;
1143 >      inertiaTensor(2,0) = -xz;
1144 >      inertiaTensor(2,1) = -yz;
1145 >      inertiaTensor(2,2) = xx + yy;
1146 >      
1147   #ifdef IS_MPI
1148 <  numAtom = mpiSim->getNAtomsGlobal();
1149 < #else
1150 <  numAtom = n_atoms;
1148 >      Mat3x3d tmpI(inertiaTensor);
1149 >      Vector3d tmpAngMom;
1150 >      MPI_Allreduce(tmpI.getArrayPointer(), inertiaTensor.getArrayPointer(),9,MPI_REALTYPE,MPI_SUM, MPI_COMM_WORLD);
1151 >      MPI_Allreduce(tmpAngMom.getArrayPointer(), angularMomentum.getArrayPointer(),3,MPI_REALTYPE,MPI_SUM, MPI_COMM_WORLD);
1152   #endif
1153 <  for (int i = 0; i < numAtom; i++)
1154 <    FglobalGroupMembership.push_back(globalGroupMembership[i] + 1);
1155 <  
1153 >              
1154 >      return;
1155 >   }
1156  
1157 <  myMols = info->molecules;
1158 <  numMol = info->n_mol;
623 <  for(int i  = 0; i < numMol; i++){
624 <    numCutoffGroups = myMols[i].getNCutoffGroups();
625 <    for(myCutoffGroup =myMols[i].beginCutoffGroup(iterCutoff);
626 <        myCutoffGroup != NULL;
627 <        myCutoffGroup =myMols[i].nextCutoffGroup(iterCutoff)){
628 <
629 <      totalMass = myCutoffGroup->getMass();
1157 >   //Returns the angular momentum of the system
1158 >   Vector3d SimInfo::getAngularMomentum(){
1159        
1160 <      for(cutoffAtom = myCutoffGroup->beginAtom(iterAtom);
1161 <          cutoffAtom != NULL;
1162 <          cutoffAtom = myCutoffGroup->nextAtom(iterAtom)){
1163 <        mfact.push_back(cutoffAtom->getMass()/totalMass);
1160 >      Vector3d com(0.0);
1161 >      Vector3d comVel(0.0);
1162 >      Vector3d angularMomentum(0.0);
1163 >      
1164 >      getComAll(com,comVel);
1165 >      
1166 >      SimInfo::MoleculeIterator i;
1167 >      Molecule* mol;
1168 >      
1169 >      Vector3d thisr(0.0);
1170 >      Vector3d thisp(0.0);
1171 >      
1172 >      RealType thisMass;
1173 >      
1174 >      for (mol = beginMolecule(i); mol != NULL; mol = nextMolecule(i)) {        
1175 >        thisMass = mol->getMass();
1176 >        thisr = mol->getCom()-com;
1177 >        thisp = (mol->getComVel()-comVel)*thisMass;
1178 >        
1179 >        angularMomentum += cross( thisr, thisp );
1180 >        
1181        }  
1182 +      
1183 + #ifdef IS_MPI
1184 +      Vector3d tmpAngMom;
1185 +      MPI_Allreduce(tmpAngMom.getArrayPointer(), angularMomentum.getArrayPointer(),3,MPI_REALTYPE,MPI_SUM, MPI_COMM_WORLD);
1186 + #endif
1187 +      
1188 +      return angularMomentum;
1189 +   }
1190 +  
1191 +  StuntDouble* SimInfo::getIOIndexToIntegrableObject(int index) {
1192 +    return IOIndexToIntegrableObject.at(index);
1193 +  }
1194 +  
1195 +  void SimInfo::setIOIndexToIntegrableObject(const vector<StuntDouble*>& v) {
1196 +    IOIndexToIntegrableObject= v;
1197 +  }
1198 +
1199 +  /* Returns the Volume of the simulation based on a ellipsoid with semi-axes
1200 +     based on the radius of gyration V=4/3*Pi*R_1*R_2*R_3
1201 +     where R_i are related to the principle inertia moments R_i = sqrt(C*I_i/N), this reduces to
1202 +     V = 4/3*Pi*(C/N)^3/2*sqrt(det(I)). See S.E. Baltazar et. al. Comp. Mat. Sci. 37 (2006) 526-536.
1203 +  */
1204 +  void SimInfo::getGyrationalVolume(RealType &volume){
1205 +    Mat3x3d intTensor;
1206 +    RealType det;
1207 +    Vector3d dummyAngMom;
1208 +    RealType sysconstants;
1209 +    RealType geomCnst;
1210 +
1211 +    geomCnst = 3.0/2.0;
1212 +    /* Get the inertial tensor and angular momentum for free*/
1213 +    getInertiaTensor(intTensor,dummyAngMom);
1214 +    
1215 +    det = intTensor.determinant();
1216 +    sysconstants = geomCnst/(RealType)nGlobalIntegrableObjects_;
1217 +    volume = 4.0/3.0*NumericConstant::PI*pow(sysconstants,geomCnst)*sqrt(det);
1218 +    return;
1219 +  }
1220 +
1221 +  void SimInfo::getGyrationalVolume(RealType &volume, RealType &detI){
1222 +    Mat3x3d intTensor;
1223 +    Vector3d dummyAngMom;
1224 +    RealType sysconstants;
1225 +    RealType geomCnst;
1226 +
1227 +    geomCnst = 3.0/2.0;
1228 +    /* Get the inertial tensor and angular momentum for free*/
1229 +    getInertiaTensor(intTensor,dummyAngMom);
1230 +    
1231 +    detI = intTensor.determinant();
1232 +    sysconstants = geomCnst/(RealType)nGlobalIntegrableObjects_;
1233 +    volume = 4.0/3.0*NumericConstant::PI*pow(sysconstants,geomCnst)*sqrt(detI);
1234 +    return;
1235 +  }
1236 + /*
1237 +   void SimInfo::setStuntDoubleFromGlobalIndex(vector<StuntDouble*> v) {
1238 +      assert( v.size() == nAtoms_ + nRigidBodies_);
1239 +      sdByGlobalIndex_ = v;
1240      }
1241 +
1242 +    StuntDouble* SimInfo::getStuntDoubleFromGlobalIndex(int index) {
1243 +      //assert(index < nAtoms_ + nRigidBodies_);
1244 +      return sdByGlobalIndex_.at(index);
1245 +    }  
1246 + */  
1247 +  int SimInfo::getNGlobalConstraints() {
1248 +    int nGlobalConstraints;
1249 + #ifdef IS_MPI
1250 +    MPI_Allreduce(&nConstraints_, &nGlobalConstraints, 1, MPI_INT, MPI_SUM,
1251 +                  MPI_COMM_WORLD);    
1252 + #else
1253 +    nGlobalConstraints =  nConstraints_;
1254 + #endif
1255 +    return nGlobalConstraints;
1256    }
1257  
1258 < }
1258 > }//end namespace OpenMD
1259 >

Comparing:
trunk/src/brains/SimInfo.cpp (property svn:keywords), Revision 143 by chrisfen, Fri Oct 22 22:54:01 2004 UTC vs.
branches/development/src/brains/SimInfo.cpp (property svn:keywords), Revision 1744 by gezelter, Tue Jun 5 18:07:08 2012 UTC

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

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines