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 1627 by gezelter, Tue Sep 13 22:05:04 2011 UTC

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

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 1627 by gezelter, Tue Sep 13 22:05:04 2011 UTC

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

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines