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

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 1569 by gezelter, Thu May 26 13:55:04 2011 UTC

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

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines