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

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 1549 by gezelter, Wed Apr 27 18:38:15 2011 UTC

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

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines