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

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 1715 by gezelter, Tue May 22 21:55:31 2012 UTC

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

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines