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 1779 by gezelter, Mon Aug 20 17:51:39 2012 UTC

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

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 1779 by gezelter, Mon Aug 20 17:51:39 2012 UTC

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

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines