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 1830 by gezelter, Wed Jan 9 22:02:30 2013 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::COMM_WORLD.Allreduce(&ndf_local, &ndf_, 1, MPI::INT,MPI::SUM);
272 >    MPI::COMM_WORLD.Allreduce(&nfq_local, &nGlobalFluctuatingCharges_, 1,
273 >                              MPI::INT, MPI::SUM);
274 > #else
275 >    ndf_ = ndf_local;
276 >    nGlobalFluctuatingCharges_ = nfq_local;
277 > #endif
278  
279 <  tempMat[0][0] = newBox[0];
280 <  tempMat[1][1] = newBox[1];
281 <  tempMat[2][2] = newBox[2];
279 >    // nZconstraints_ is global, as are the 3 COM translations for the
280 >    // entire system:
281 >    ndf_ = ndf_ - 3 - nZconstraint_;
282  
283 <  setBoxM( tempMat );
283 >  }
284  
285 < }
286 <
287 < void SimInfo::setBoxM( double theBox[3][3] ){
285 >  int SimInfo::getFdf() {
286 > #ifdef IS_MPI
287 >    MPI::COMM_WORLD.Allreduce(&fdf_local, &fdf_, 1, MPI::INT, MPI::SUM);
288 > #else
289 >    fdf_ = fdf_local;
290 > #endif
291 >    return fdf_;
292 >  }
293    
294 <  int i, j;
295 <  double FortranHmat[9]; // to preserve compatibility with Fortran the
296 <                         // ordering in the array is as follows:
297 <                         // [ 0 3 6 ]
298 <                         // [ 1 4 7 ]
299 <                         // [ 2 5 8 ]
300 <  double FortranHmatInv[9]; // the inverted Hmat (for Fortran);
294 >  unsigned int SimInfo::getNLocalCutoffGroups(){
295 >    int nLocalCutoffAtoms = 0;
296 >    Molecule* mol;
297 >    MoleculeIterator mi;
298 >    CutoffGroup* cg;
299 >    Molecule::CutoffGroupIterator ci;
300 >    
301 >    for (mol = beginMolecule(mi); mol != NULL; mol  = nextMolecule(mi)) {
302 >      
303 >      for (cg = mol->beginCutoffGroup(ci); cg != NULL;
304 >           cg = mol->nextCutoffGroup(ci)) {
305 >        nLocalCutoffAtoms += cg->getNumAtom();
306 >        
307 >      }        
308 >    }
309 >    
310 >    return nAtoms_ - nLocalCutoffAtoms + nCutoffGroups_;
311 >  }
312 >    
313 >  void SimInfo::calcNdfRaw() {
314 >    int ndfRaw_local;
315  
316 <  if( !boxIsInit ) boxIsInit = 1;
316 >    MoleculeIterator i;
317 >    vector<StuntDouble*>::iterator j;
318 >    Molecule* mol;
319 >    StuntDouble* sd;
320  
321 <  for(i=0; i < 3; i++)
322 <    for (j=0; j < 3; j++) Hmat[i][j] = theBox[i][j];
323 <  
324 <  calcBoxL();
131 <  calcHmatInv();
321 >    // Raw degrees of freedom that we have to set
322 >    ndfRaw_local = 0;
323 >    
324 >    for (mol = beginMolecule(i); mol != NULL; mol = nextMolecule(i)) {
325  
326 <  for(i=0; i < 3; i++) {
327 <    for (j=0; j < 3; j++) {
328 <      FortranHmat[3*j + i] = Hmat[i][j];
329 <      FortranHmatInv[3*j + i] = HmatInv[i][j];
326 >      for (sd = mol->beginIntegrableObject(j); sd != NULL;
327 >           sd = mol->nextIntegrableObject(j)) {
328 >
329 >        ndfRaw_local += 3;
330 >
331 >        if (sd->isDirectional()) {
332 >          if (sd->isLinear()) {
333 >            ndfRaw_local += 2;
334 >          } else {
335 >            ndfRaw_local += 3;
336 >          }
337 >        }
338 >            
339 >      }
340      }
341 +    
342 + #ifdef IS_MPI
343 +    MPI::COMM_WORLD.Allreduce(&ndfRaw_local, &ndfRaw_, 1, MPI::INT, MPI::SUM);
344 + #else
345 +    ndfRaw_ = ndfRaw_local;
346 + #endif
347    }
348  
349 <  setFortranBox(FortranHmat, FortranHmatInv, &orthoRhombic);
350 <
142 < }
143 <
349 >  void SimInfo::calcNdfTrans() {
350 >    int ndfTrans_local;
351  
352 < void SimInfo::getBoxM (double theBox[3][3]) {
352 >    ndfTrans_local = 3 * nIntegrableObjects_ - nConstraints_;
353  
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 }
354  
355 + #ifdef IS_MPI
356 +    MPI::COMM_WORLD.Allreduce(&ndfTrans_local, &ndfTrans_, 1,
357 +                              MPI::INT, MPI::SUM);
358 + #else
359 +    ndfTrans_ = ndfTrans_local;
360 + #endif
361  
362 < void SimInfo::scaleBox(double scale) {
363 <  double theBox[3][3];
364 <  int i, j;
362 >    ndfTrans_ = ndfTrans_ - 3 - nZconstraint_;
363 >
364 >  }
365  
366 <  // cerr << "Scaling box by " << scale << "\n";
366 >  void SimInfo::addInteractionPairs(Molecule* mol) {
367 >    ForceFieldOptions& options_ = forceField_->getForceFieldOptions();
368 >    vector<Bond*>::iterator bondIter;
369 >    vector<Bend*>::iterator bendIter;
370 >    vector<Torsion*>::iterator torsionIter;
371 >    vector<Inversion*>::iterator inversionIter;
372 >    Bond* bond;
373 >    Bend* bend;
374 >    Torsion* torsion;
375 >    Inversion* inversion;
376 >    int a;
377 >    int b;
378 >    int c;
379 >    int d;
380  
381 <  for(i=0; i<3; i++)
382 <    for (j=0; j<3; j++) theBox[i][j] = Hmat[i][j]*scale;
381 >    // atomGroups can be used to add special interaction maps between
382 >    // groups of atoms that are in two separate rigid bodies.
383 >    // However, most site-site interactions between two rigid bodies
384 >    // are probably not special, just the ones between the physically
385 >    // bonded atoms.  Interactions *within* a single rigid body should
386 >    // always be excluded.  These are done at the bottom of this
387 >    // function.
388  
389 <  setBoxM(theBox);
390 <
391 < }
392 <
393 < void SimInfo::calcHmatInv( void ) {
394 <  
395 <  int oldOrtho;
396 <  int i,j;
397 <  double smallDiag;
398 <  double tol;
399 <  double sanity[3][3];
400 <
401 <  invertMat3( Hmat, HmatInv );
402 <
403 <  // check to see if Hmat is orthorhombic
404 <  
405 <  oldOrtho = orthoRhombic;
406 <
407 <  smallDiag = fabs(Hmat[0][0]);
408 <  if(smallDiag > fabs(Hmat[1][1])) smallDiag = fabs(Hmat[1][1]);
409 <  if(smallDiag > fabs(Hmat[2][2])) smallDiag = fabs(Hmat[2][2]);
410 <  tol = smallDiag * orthoTolerance;
411 <
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 <        }        
389 >    map<int, set<int> > atomGroups;
390 >    Molecule::RigidBodyIterator rbIter;
391 >    RigidBody* rb;
392 >    Molecule::IntegrableObjectIterator ii;
393 >    StuntDouble* sd;
394 >    
395 >    for (sd = mol->beginIntegrableObject(ii); sd != NULL;
396 >         sd = mol->nextIntegrableObject(ii)) {
397 >      
398 >      if (sd->isRigidBody()) {
399 >        rb = static_cast<RigidBody*>(sd);
400 >        vector<Atom*> atoms = rb->getAtoms();
401 >        set<int> rigidAtoms;
402 >        for (int i = 0; i < static_cast<int>(atoms.size()); ++i) {
403 >          rigidAtoms.insert(atoms[i]->getGlobalIndex());
404 >        }
405 >        for (int i = 0; i < static_cast<int>(atoms.size()); ++i) {
406 >          atomGroups.insert(map<int, set<int> >::value_type(atoms[i]->getGlobalIndex(), rigidAtoms));
407 >        }      
408 >      } else {
409 >        set<int> oneAtomSet;
410 >        oneAtomSet.insert(sd->getGlobalIndex());
411 >        atomGroups.insert(map<int, set<int> >::value_type(sd->getGlobalIndex(), oneAtomSet));        
412        }
413 <    }
414 <  }
413 >    }  
414 >          
415 >    for (bond= mol->beginBond(bondIter); bond != NULL;
416 >         bond = mol->nextBond(bondIter)) {
417  
418 <  if( oldOrtho != orthoRhombic ){
418 >      a = bond->getAtomA()->getGlobalIndex();
419 >      b = bond->getAtomB()->getGlobalIndex();  
420      
421 <    if( orthoRhombic ) {
422 <      sprintf( painCave.errMsg,
423 <               "OOPSE is switching from the default Non-Orthorhombic\n"
424 <               "\tto the faster Orthorhombic periodic boundary computations.\n"
425 <               "\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();
421 >      if (options_.havevdw12scale() || options_.haveelectrostatic12scale()) {
422 >        oneTwoInteractions_.addPair(a, b);
423 >      } else {
424 >        excludedInteractions_.addPair(a, b);
425 >      }
426      }
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 }
427  
428 < void SimInfo::calcBoxL( void ){
428 >    for (bend= mol->beginBend(bendIter); bend != NULL;
429 >         bend = mol->nextBend(bendIter)) {
430  
431 <  double dx, dy, dz, dsq;
431 >      a = bend->getAtomA()->getGlobalIndex();
432 >      b = bend->getAtomB()->getGlobalIndex();        
433 >      c = bend->getAtomC()->getGlobalIndex();
434 >      
435 >      if (options_.havevdw12scale() || options_.haveelectrostatic12scale()) {
436 >        oneTwoInteractions_.addPair(a, b);      
437 >        oneTwoInteractions_.addPair(b, c);
438 >      } else {
439 >        excludedInteractions_.addPair(a, b);
440 >        excludedInteractions_.addPair(b, c);
441 >      }
442  
443 <  // boxVol = Determinant of Hmat
443 >      if (options_.havevdw13scale() || options_.haveelectrostatic13scale()) {
444 >        oneThreeInteractions_.addPair(a, c);      
445 >      } else {
446 >        excludedInteractions_.addPair(a, c);
447 >      }
448 >    }
449  
450 <  boxVol = matDet3( Hmat );
450 >    for (torsion= mol->beginTorsion(torsionIter); torsion != NULL;
451 >         torsion = mol->nextTorsion(torsionIter)) {
452  
453 <  // boxLx
454 <  
455 <  dx = Hmat[0][0]; dy = Hmat[1][0]; dz = Hmat[2][0];
456 <  dsq = dx*dx + dy*dy + dz*dz;
237 <  boxL[0] = sqrt( dsq );
238 <  //maxCutoff = 0.5 * boxL[0];
453 >      a = torsion->getAtomA()->getGlobalIndex();
454 >      b = torsion->getAtomB()->getGlobalIndex();        
455 >      c = torsion->getAtomC()->getGlobalIndex();        
456 >      d = torsion->getAtomD()->getGlobalIndex();      
457  
458 <  // boxLy
459 <  
460 <  dx = Hmat[0][1]; dy = Hmat[1][1]; dz = Hmat[2][1];
461 <  dsq = dx*dx + dy*dy + dz*dz;
462 <  boxL[1] = sqrt( dsq );
463 <  //if( (0.5 * boxL[1]) < maxCutoff ) maxCutoff = 0.5 * boxL[1];
458 >      if (options_.havevdw12scale() || options_.haveelectrostatic12scale()) {
459 >        oneTwoInteractions_.addPair(a, b);      
460 >        oneTwoInteractions_.addPair(b, c);
461 >        oneTwoInteractions_.addPair(c, d);
462 >      } else {
463 >        excludedInteractions_.addPair(a, b);
464 >        excludedInteractions_.addPair(b, c);
465 >        excludedInteractions_.addPair(c, d);
466 >      }
467  
468 +      if (options_.havevdw13scale() || options_.haveelectrostatic13scale()) {
469 +        oneThreeInteractions_.addPair(a, c);      
470 +        oneThreeInteractions_.addPair(b, d);      
471 +      } else {
472 +        excludedInteractions_.addPair(a, c);
473 +        excludedInteractions_.addPair(b, d);
474 +      }
475  
476 <  // boxLz
477 <  
478 <  dx = Hmat[0][2]; dy = Hmat[1][2]; dz = Hmat[2][2];
479 <  dsq = dx*dx + dy*dy + dz*dz;
480 <  boxL[2] = sqrt( dsq );
481 <  //if( (0.5 * boxL[2]) < maxCutoff ) maxCutoff = 0.5 * boxL[2];
476 >      if (options_.havevdw14scale() || options_.haveelectrostatic14scale()) {
477 >        oneFourInteractions_.addPair(a, d);      
478 >      } else {
479 >        excludedInteractions_.addPair(a, d);
480 >      }
481 >    }
482  
483 <  //calculate the max cutoff
484 <  maxCutoff =  calcMaxCutOff();
257 <  
258 <  checkCutOffs();
483 >    for (inversion= mol->beginInversion(inversionIter); inversion != NULL;
484 >         inversion = mol->nextInversion(inversionIter)) {
485  
486 < }
486 >      a = inversion->getAtomA()->getGlobalIndex();
487 >      b = inversion->getAtomB()->getGlobalIndex();        
488 >      c = inversion->getAtomC()->getGlobalIndex();        
489 >      d = inversion->getAtomD()->getGlobalIndex();        
490  
491 +      if (options_.havevdw12scale() || options_.haveelectrostatic12scale()) {
492 +        oneTwoInteractions_.addPair(a, b);      
493 +        oneTwoInteractions_.addPair(a, c);
494 +        oneTwoInteractions_.addPair(a, d);
495 +      } else {
496 +        excludedInteractions_.addPair(a, b);
497 +        excludedInteractions_.addPair(a, c);
498 +        excludedInteractions_.addPair(a, d);
499 +      }
500  
501 < double SimInfo::calcMaxCutOff(){
501 >      if (options_.havevdw13scale() || options_.haveelectrostatic13scale()) {
502 >        oneThreeInteractions_.addPair(b, c);    
503 >        oneThreeInteractions_.addPair(b, d);    
504 >        oneThreeInteractions_.addPair(c, d);      
505 >      } else {
506 >        excludedInteractions_.addPair(b, c);
507 >        excludedInteractions_.addPair(b, d);
508 >        excludedInteractions_.addPair(c, d);
509 >      }
510 >    }
511  
512 <  double ri[3], rj[3], rk[3];
513 <  double rij[3], rjk[3], rki[3];
514 <  double minDist;
512 >    for (rb = mol->beginRigidBody(rbIter); rb != NULL;
513 >         rb = mol->nextRigidBody(rbIter)) {
514 >      vector<Atom*> atoms = rb->getAtoms();
515 >      for (int i = 0; i < static_cast<int>(atoms.size()) -1 ; ++i) {
516 >        for (int j = i + 1; j < static_cast<int>(atoms.size()); ++j) {
517 >          a = atoms[i]->getGlobalIndex();
518 >          b = atoms[j]->getGlobalIndex();
519 >          excludedInteractions_.addPair(a, b);
520 >        }
521 >      }
522 >    }        
523  
524 <  ri[0] = Hmat[0][0];
270 <  ri[1] = Hmat[1][0];
271 <  ri[2] = Hmat[2][0];
524 >  }
525  
526 <  rj[0] = Hmat[0][1];
527 <  rj[1] = Hmat[1][1];
528 <  rj[2] = Hmat[2][1];
526 >  void SimInfo::removeInteractionPairs(Molecule* mol) {
527 >    ForceFieldOptions& options_ = forceField_->getForceFieldOptions();
528 >    vector<Bond*>::iterator bondIter;
529 >    vector<Bend*>::iterator bendIter;
530 >    vector<Torsion*>::iterator torsionIter;
531 >    vector<Inversion*>::iterator inversionIter;
532 >    Bond* bond;
533 >    Bend* bend;
534 >    Torsion* torsion;
535 >    Inversion* inversion;
536 >    int a;
537 >    int b;
538 >    int c;
539 >    int d;
540  
541 <  rk[0] = Hmat[0][2];
542 <  rk[1] = Hmat[1][2];
543 <  rk[2] = Hmat[2][2];
541 >    map<int, set<int> > atomGroups;
542 >    Molecule::RigidBodyIterator rbIter;
543 >    RigidBody* rb;
544 >    Molecule::IntegrableObjectIterator ii;
545 >    StuntDouble* sd;
546      
547 <  crossProduct3(ri, rj, rij);
548 <  distXY = dotProduct3(rk,rij) / norm3(rij);
547 >    for (sd = mol->beginIntegrableObject(ii); sd != NULL;
548 >         sd = mol->nextIntegrableObject(ii)) {
549 >      
550 >      if (sd->isRigidBody()) {
551 >        rb = static_cast<RigidBody*>(sd);
552 >        vector<Atom*> atoms = rb->getAtoms();
553 >        set<int> rigidAtoms;
554 >        for (int i = 0; i < static_cast<int>(atoms.size()); ++i) {
555 >          rigidAtoms.insert(atoms[i]->getGlobalIndex());
556 >        }
557 >        for (int i = 0; i < static_cast<int>(atoms.size()); ++i) {
558 >          atomGroups.insert(map<int, set<int> >::value_type(atoms[i]->getGlobalIndex(), rigidAtoms));
559 >        }      
560 >      } else {
561 >        set<int> oneAtomSet;
562 >        oneAtomSet.insert(sd->getGlobalIndex());
563 >        atomGroups.insert(map<int, set<int> >::value_type(sd->getGlobalIndex(), oneAtomSet));        
564 >      }
565 >    }  
566  
567 <  crossProduct3(rj,rk, rjk);
568 <  distYZ = dotProduct3(ri,rjk) / norm3(rjk);
567 >    for (bond= mol->beginBond(bondIter); bond != NULL;
568 >         bond = mol->nextBond(bondIter)) {
569 >      
570 >      a = bond->getAtomA()->getGlobalIndex();
571 >      b = bond->getAtomB()->getGlobalIndex();  
572 >    
573 >      if (options_.havevdw12scale() || options_.haveelectrostatic12scale()) {
574 >        oneTwoInteractions_.removePair(a, b);
575 >      } else {
576 >        excludedInteractions_.removePair(a, b);
577 >      }
578 >    }
579  
580 <  crossProduct3(rk,ri, rki);
581 <  distZX = dotProduct3(rj,rki) / norm3(rki);
580 >    for (bend= mol->beginBend(bendIter); bend != NULL;
581 >         bend = mol->nextBend(bendIter)) {
582  
583 <  minDist = min(min(distXY, distYZ), distZX);
584 <  return minDist/2;
585 <  
586 < }
587 <
588 < void SimInfo::wrapVector( double thePos[3] ){
589 <
590 <  int i;
591 <  double scaled[3];
583 >      a = bend->getAtomA()->getGlobalIndex();
584 >      b = bend->getAtomB()->getGlobalIndex();        
585 >      c = bend->getAtomC()->getGlobalIndex();
586 >      
587 >      if (options_.havevdw12scale() || options_.haveelectrostatic12scale()) {
588 >        oneTwoInteractions_.removePair(a, b);      
589 >        oneTwoInteractions_.removePair(b, c);
590 >      } else {
591 >        excludedInteractions_.removePair(a, b);
592 >        excludedInteractions_.removePair(b, c);
593 >      }
594  
595 <  if( !orthoRhombic ){
596 <    // calc the scaled coordinates.
597 <  
595 >      if (options_.havevdw13scale() || options_.haveelectrostatic13scale()) {
596 >        oneThreeInteractions_.removePair(a, c);      
597 >      } else {
598 >        excludedInteractions_.removePair(a, c);
599 >      }
600 >    }
601  
602 <    matVecMul3(HmatInv, thePos, scaled);
603 <    
306 <    for(i=0; i<3; i++)
307 <      scaled[i] -= roundMe(scaled[i]);
308 <    
309 <    // calc the wrapped real coordinates from the wrapped scaled coordinates
310 <    
311 <    matVecMul3(Hmat, scaled, thePos);
602 >    for (torsion= mol->beginTorsion(torsionIter); torsion != NULL;
603 >         torsion = mol->nextTorsion(torsionIter)) {
604  
605 <  }
606 <  else{
607 <    // calc the scaled coordinates.
608 <    
609 <    for(i=0; i<3; i++)
610 <      scaled[i] = thePos[i]*HmatInv[i][i];
611 <    
612 <    // wrap the scaled coordinates
613 <    
614 <    for(i=0; i<3; i++)
615 <      scaled[i] -= roundMe(scaled[i]);
616 <    
617 <    // calc the wrapped real coordinates from the wrapped scaled coordinates
618 <    
327 <    for(i=0; i<3; i++)
328 <      thePos[i] = scaled[i]*Hmat[i][i];
329 <  }
330 <    
331 < }
605 >      a = torsion->getAtomA()->getGlobalIndex();
606 >      b = torsion->getAtomB()->getGlobalIndex();        
607 >      c = torsion->getAtomC()->getGlobalIndex();        
608 >      d = torsion->getAtomD()->getGlobalIndex();      
609 >  
610 >      if (options_.havevdw12scale() || options_.haveelectrostatic12scale()) {
611 >        oneTwoInteractions_.removePair(a, b);      
612 >        oneTwoInteractions_.removePair(b, c);
613 >        oneTwoInteractions_.removePair(c, d);
614 >      } else {
615 >        excludedInteractions_.removePair(a, b);
616 >        excludedInteractions_.removePair(b, c);
617 >        excludedInteractions_.removePair(c, d);
618 >      }
619  
620 +      if (options_.havevdw13scale() || options_.haveelectrostatic13scale()) {
621 +        oneThreeInteractions_.removePair(a, c);      
622 +        oneThreeInteractions_.removePair(b, d);      
623 +      } else {
624 +        excludedInteractions_.removePair(a, c);
625 +        excludedInteractions_.removePair(b, d);
626 +      }
627  
628 < int SimInfo::getNDF(){
629 <  int ndf_local;
630 <
631 <  ndf_local = 0;
632 <  
339 <  for(int i = 0; i < integrableObjects.size(); i++){
340 <    ndf_local += 3;
341 <    if (integrableObjects[i]->isDirectional()) {
342 <      if (integrableObjects[i]->isLinear())
343 <        ndf_local += 2;
344 <      else
345 <        ndf_local += 3;
628 >      if (options_.havevdw14scale() || options_.haveelectrostatic14scale()) {
629 >        oneFourInteractions_.removePair(a, d);      
630 >      } else {
631 >        excludedInteractions_.removePair(a, d);
632 >      }
633      }
347  }
634  
635 <  // n_constraints is local, so subtract them on each processor:
635 >    for (inversion= mol->beginInversion(inversionIter); inversion != NULL;
636 >         inversion = mol->nextInversion(inversionIter)) {
637  
638 <  ndf_local -= n_constraints;
638 >      a = inversion->getAtomA()->getGlobalIndex();
639 >      b = inversion->getAtomB()->getGlobalIndex();        
640 >      c = inversion->getAtomC()->getGlobalIndex();        
641 >      d = inversion->getAtomD()->getGlobalIndex();        
642  
643 < #ifdef IS_MPI
644 <  MPI_Allreduce(&ndf_local,&ndf,1,MPI_INT,MPI_SUM, MPI_COMM_WORLD);
645 < #else
646 <  ndf = ndf_local;
647 < #endif
643 >      if (options_.havevdw12scale() || options_.haveelectrostatic12scale()) {
644 >        oneTwoInteractions_.removePair(a, b);      
645 >        oneTwoInteractions_.removePair(a, c);
646 >        oneTwoInteractions_.removePair(a, d);
647 >      } else {
648 >        excludedInteractions_.removePair(a, b);
649 >        excludedInteractions_.removePair(a, c);
650 >        excludedInteractions_.removePair(a, d);
651 >      }
652  
653 <  // nZconstraints is global, as are the 3 COM translations for the
654 <  // entire system:
653 >      if (options_.havevdw13scale() || options_.haveelectrostatic13scale()) {
654 >        oneThreeInteractions_.removePair(b, c);    
655 >        oneThreeInteractions_.removePair(b, d);    
656 >        oneThreeInteractions_.removePair(c, d);      
657 >      } else {
658 >        excludedInteractions_.removePair(b, c);
659 >        excludedInteractions_.removePair(b, d);
660 >        excludedInteractions_.removePair(c, d);
661 >      }
662 >    }
663  
664 <  ndf = ndf - 3 - nZconstraints;
664 >    for (rb = mol->beginRigidBody(rbIter); rb != NULL;
665 >         rb = mol->nextRigidBody(rbIter)) {
666 >      vector<Atom*> atoms = rb->getAtoms();
667 >      for (int i = 0; i < static_cast<int>(atoms.size()) -1 ; ++i) {
668 >        for (int j = i + 1; j < static_cast<int>(atoms.size()); ++j) {
669 >          a = atoms[i]->getGlobalIndex();
670 >          b = atoms[j]->getGlobalIndex();
671 >          excludedInteractions_.removePair(a, b);
672 >        }
673 >      }
674 >    }        
675 >    
676 >  }
677 >  
678 >  
679 >  void SimInfo::addMoleculeStamp(MoleculeStamp* molStamp, int nmol) {
680 >    int curStampId;
681 >    
682 >    //index from 0
683 >    curStampId = moleculeStamps_.size();
684  
685 <  return ndf;
686 < }
685 >    moleculeStamps_.push_back(molStamp);
686 >    molStampIds_.insert(molStampIds_.end(), nmol, curStampId);
687 >  }
688  
367 int SimInfo::getNDFraw() {
368  int ndfRaw_local;
689  
690 <  // Raw degrees of freedom that we have to set
691 <  ndfRaw_local = 0;
692 <
693 <  for(int i = 0; i < integrableObjects.size(); i++){
694 <    ndfRaw_local += 3;
695 <    if (integrableObjects[i]->isDirectional()) {
696 <       if (integrableObjects[i]->isLinear())
697 <        ndfRaw_local += 2;
698 <      else
699 <        ndfRaw_local += 3;
700 <    }
690 >  /**
691 >   * update
692 >   *
693 >   *  Performs the global checks and variable settings after the
694 >   *  objects have been created.
695 >   *
696 >   */
697 >  void SimInfo::update() {  
698 >    setupSimVariables();
699 >    calcNdf();
700 >    calcNdfRaw();
701 >    calcNdfTrans();
702    }
703 +  
704 +  /**
705 +   * getSimulatedAtomTypes
706 +   *
707 +   * Returns an STL set of AtomType* that are actually present in this
708 +   * simulation.  Must query all processors to assemble this information.
709 +   *
710 +   */
711 +  set<AtomType*> SimInfo::getSimulatedAtomTypes() {
712 +    SimInfo::MoleculeIterator mi;
713 +    Molecule* mol;
714 +    Molecule::AtomIterator ai;
715 +    Atom* atom;
716 +    set<AtomType*> atomTypes;
717      
718 +    for(mol = beginMolecule(mi); mol != NULL; mol = nextMolecule(mi)) {
719 +      for(atom = mol->beginAtom(ai); atom != NULL;
720 +          atom = mol->nextAtom(ai)) {
721 +        atomTypes.insert(atom->getAtomType());
722 +      }      
723 +    }    
724 +    
725   #ifdef IS_MPI
384  MPI_Allreduce(&ndfRaw_local,&ndfRaw,1,MPI_INT,MPI_SUM, MPI_COMM_WORLD);
385 #else
386  ndfRaw = ndfRaw_local;
387 #endif
726  
727 <  return ndfRaw;
728 < }
727 >    // loop over the found atom types on this processor, and add their
728 >    // numerical idents to a vector:
729 >    
730 >    vector<int> foundTypes;
731 >    set<AtomType*>::iterator i;
732 >    for (i = atomTypes.begin(); i != atomTypes.end(); ++i)
733 >      foundTypes.push_back( (*i)->getIdent() );
734  
735 < int SimInfo::getNDFtranslational() {
736 <  int ndfTrans_local;
735 >    // count_local holds the number of found types on this processor
736 >    int count_local = foundTypes.size();
737  
738 <  ndfTrans_local = 3 * integrableObjects.size() - n_constraints;
738 >    int nproc = MPI::COMM_WORLD.Get_size();
739  
740 +    // we need arrays to hold the counts and displacement vectors for
741 +    // all processors
742 +    vector<int> counts(nproc, 0);
743 +    vector<int> disps(nproc, 0);
744  
745 < #ifdef IS_MPI
746 <  MPI_Allreduce(&ndfTrans_local,&ndfTrans,1,MPI_INT,MPI_SUM, MPI_COMM_WORLD);
747 < #else
748 <  ndfTrans = ndfTrans_local;
749 < #endif
745 >    // fill the counts array
746 >    MPI::COMM_WORLD.Allgather(&count_local, 1, MPI::INT, &counts[0],
747 >                              1, MPI::INT);
748 >  
749 >    // use the processor counts to compute the displacement array
750 >    disps[0] = 0;    
751 >    int totalCount = counts[0];
752 >    for (int iproc = 1; iproc < nproc; iproc++) {
753 >      disps[iproc] = disps[iproc-1] + counts[iproc-1];
754 >      totalCount += counts[iproc];
755 >    }
756  
757 <  ndfTrans = ndfTrans - 3 - nZconstraints;
757 >    // we need a (possibly redundant) set of all found types:
758 >    vector<int> ftGlobal(totalCount);
759 >    
760 >    // now spray out the foundTypes to all the other processors:    
761 >    MPI::COMM_WORLD.Allgatherv(&foundTypes[0], count_local, MPI::INT,
762 >                               &ftGlobal[0], &counts[0], &disps[0],
763 >                               MPI::INT);
764  
765 <  return ndfTrans;
407 < }
765 >    vector<int>::iterator j;
766  
767 < int SimInfo::getTotIntegrableObjects() {
768 <  int nObjs_local;
769 <  int nObjs;
767 >    // foundIdents is a stl set, so inserting an already found ident
768 >    // will have no effect.
769 >    set<int> foundIdents;
770  
771 <  nObjs_local =  integrableObjects.size();
772 <
773 <
774 < #ifdef IS_MPI
775 <  MPI_Allreduce(&nObjs_local,&nObjs,1,MPI_INT,MPI_SUM, MPI_COMM_WORLD);
776 < #else
777 <  nObjs = nObjs_local;
771 >    for (j = ftGlobal.begin(); j != ftGlobal.end(); ++j)
772 >      foundIdents.insert((*j));
773 >    
774 >    // now iterate over the foundIdents and get the actual atom types
775 >    // that correspond to these:
776 >    set<int>::iterator it;
777 >    for (it = foundIdents.begin(); it != foundIdents.end(); ++it)
778 >      atomTypes.insert( forceField_->getAtomType((*it)) );
779 >
780   #endif
781  
782 +    return atomTypes;        
783 +  }
784  
785 <  return nObjs;
786 < }
785 >  void SimInfo::setupSimVariables() {
786 >    useAtomicVirial_ = simParams_->getUseAtomicVirial();
787 >    // we only call setAccumulateBoxDipole if the accumulateBoxDipole
788 >    // parameter is true
789 >    calcBoxDipole_ = false;
790 >    if ( simParams_->haveAccumulateBoxDipole() )
791 >      if ( simParams_->getAccumulateBoxDipole() ) {
792 >        calcBoxDipole_ = true;      
793 >      }
794 >    
795 >    set<AtomType*>::iterator i;
796 >    set<AtomType*> atomTypes;
797 >    atomTypes = getSimulatedAtomTypes();    
798 >    bool usesElectrostatic = false;
799 >    bool usesMetallic = false;
800 >    bool usesDirectional = false;
801 >    bool usesFluctuatingCharges =  false;
802 >    //loop over all of the atom types
803 >    for (i = atomTypes.begin(); i != atomTypes.end(); ++i) {
804 >      usesElectrostatic |= (*i)->isElectrostatic();
805 >      usesMetallic |= (*i)->isMetal();
806 >      usesDirectional |= (*i)->isDirectional();
807 >      usesFluctuatingCharges |= (*i)->isFluctuatingCharge();
808 >    }
809  
810 < void SimInfo::refreshSim(){
810 > #ifdef IS_MPI
811 >    bool temp;
812 >    temp = usesDirectional;
813 >    MPI::COMM_WORLD.Allreduce(&temp, &usesDirectionalAtoms_, 1, MPI::BOOL,
814 >                              MPI::LOR);
815 >        
816 >    temp = usesMetallic;
817 >    MPI::COMM_WORLD.Allreduce(&temp, &usesMetallicAtoms_, 1, MPI::BOOL,
818 >                              MPI::LOR);
819 >    
820 >    temp = usesElectrostatic;
821 >    MPI::COMM_WORLD.Allreduce(&temp, &usesElectrostaticAtoms_, 1, MPI::BOOL,
822 >                              MPI::LOR);
823  
824 <  simtype fInfo;
825 <  int isError;
826 <  int n_global;
827 <  int* excl;
824 >    temp = usesFluctuatingCharges;
825 >    MPI::COMM_WORLD.Allreduce(&temp, &usesFluctuatingCharges_, 1, MPI::BOOL,
826 >                              MPI::LOR);
827 > #else
828  
829 <  fInfo.dielect = 0.0;
829 >    usesDirectionalAtoms_ = usesDirectional;
830 >    usesMetallicAtoms_ = usesMetallic;
831 >    usesElectrostaticAtoms_ = usesElectrostatic;
832 >    usesFluctuatingCharges_ = usesFluctuatingCharges;
833  
834 <  if( useDipoles ){
835 <    if( useReactionField )fInfo.dielect = dielectric;
834 > #endif
835 >    
836 >    requiresPrepair_ = usesMetallicAtoms_ ? true : false;
837 >    requiresSkipCorrection_ = usesElectrostaticAtoms_ ? true : false;
838 >    requiresSelfCorrection_ = usesElectrostaticAtoms_ ? true : false;    
839    }
840  
439  fInfo.SIM_uses_PBC = usePBC;
841  
842 <  if (useSticky || useDipoles || useGayBerne || useShapes) {
843 <    useDirectionalAtoms = 1;
844 <    fInfo.SIM_uses_DirectionalAtoms = useDirectionalAtoms;
842 >  vector<int> SimInfo::getGlobalAtomIndices() {
843 >    SimInfo::MoleculeIterator mi;
844 >    Molecule* mol;
845 >    Molecule::AtomIterator ai;
846 >    Atom* atom;
847 >
848 >    vector<int> GlobalAtomIndices(getNAtoms(), 0);
849 >    
850 >    for (mol = beginMolecule(mi); mol != NULL; mol  = nextMolecule(mi)) {
851 >      
852 >      for (atom = mol->beginAtom(ai); atom != NULL; atom = mol->nextAtom(ai)) {
853 >        GlobalAtomIndices[atom->getLocalIndex()] = atom->getGlobalIndex();
854 >      }
855 >    }
856 >    return GlobalAtomIndices;
857    }
858  
446  fInfo.SIM_uses_LennardJones = useLennardJones;
859  
860 <  if (useCharges || useDipoles) {
861 <    useElectrostatics = 1;
862 <    fInfo.SIM_uses_Electrostatics = useElectrostatics;
860 >  vector<int> SimInfo::getGlobalGroupIndices() {
861 >    SimInfo::MoleculeIterator mi;
862 >    Molecule* mol;
863 >    Molecule::CutoffGroupIterator ci;
864 >    CutoffGroup* cg;
865 >
866 >    vector<int> GlobalGroupIndices;
867 >    
868 >    for (mol = beginMolecule(mi); mol != NULL; mol  = nextMolecule(mi)) {
869 >      
870 >      //local index of cutoff group is trivial, it only depends on the
871 >      //order of travesing
872 >      for (cg = mol->beginCutoffGroup(ci); cg != NULL;
873 >           cg = mol->nextCutoffGroup(ci)) {
874 >        GlobalGroupIndices.push_back(cg->getGlobalIndex());
875 >      }        
876 >    }
877 >    return GlobalGroupIndices;
878    }
879  
453  fInfo.SIM_uses_Charges = useCharges;
454  fInfo.SIM_uses_Dipoles = useDipoles;
455  fInfo.SIM_uses_Sticky = useSticky;
456  fInfo.SIM_uses_GayBerne = useGayBerne;
457  fInfo.SIM_uses_EAM = useEAM;
458  fInfo.SIM_uses_Shapes = useShapes;
459  fInfo.SIM_uses_FLARB = useFLARB;
460  fInfo.SIM_uses_RF = useReactionField;
880  
881 <  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);
881 >  void SimInfo::prepareTopology() {
882  
883 <  if( isError ){
883 >    //calculate mass ratio of cutoff group
884 >    SimInfo::MoleculeIterator mi;
885 >    Molecule* mol;
886 >    Molecule::CutoffGroupIterator ci;
887 >    CutoffGroup* cg;
888 >    Molecule::AtomIterator ai;
889 >    Atom* atom;
890 >    RealType totalMass;
891 >
892 >    /**
893 >     * The mass factor is the relative mass of an atom to the total
894 >     * mass of the cutoff group it belongs to.  By default, all atoms
895 >     * are their own cutoff groups, and therefore have mass factors of
896 >     * 1.  We need some special handling for massless atoms, which
897 >     * will be treated as carrying the entire mass of the cutoff
898 >     * group.
899 >     */
900 >    massFactors_.clear();
901 >    massFactors_.resize(getNAtoms(), 1.0);
902      
903 <    sprintf( painCave.errMsg,
904 <             "There was an error setting the simulation information in fortran.\n" );
905 <    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 < }
903 >    for(mol = beginMolecule(mi); mol != NULL; mol = nextMolecule(mi)) {        
904 >      for (cg = mol->beginCutoffGroup(ci); cg != NULL;
905 >           cg = mol->nextCutoffGroup(ci)) {
906  
907 < void SimInfo::setDefaultRcut( double theRcut ){
908 <  
909 <  haveRcut = 1;
910 <  rCut = theRcut;
911 <  rList = rCut + 1.0;
912 <  
913 <  notifyFortranCutoffs( &rCut, &rSw, &rList );
914 < }
907 >        totalMass = cg->getMass();
908 >        for(atom = cg->beginAtom(ai); atom != NULL; atom = cg->nextAtom(ai)) {
909 >          // Check for massless groups - set mfact to 1 if true
910 >          if (totalMass != 0)
911 >            massFactors_[atom->getLocalIndex()] = atom->getMass()/totalMass;
912 >          else
913 >            massFactors_[atom->getLocalIndex()] = 1.0;
914 >        }
915 >      }      
916 >    }
917  
918 < void SimInfo::setDefaultRcut( double theRcut, double theRsw ){
918 >    // Build the identArray_
919  
920 <  rSw = theRsw;
921 <  setDefaultRcut( theRcut );
922 < }
920 >    identArray_.clear();
921 >    identArray_.reserve(getNAtoms());    
922 >    for(mol = beginMolecule(mi); mol != NULL; mol = nextMolecule(mi)) {        
923 >      for(atom = mol->beginAtom(ai); atom != NULL; atom = mol->nextAtom(ai)) {
924 >        identArray_.push_back(atom->getIdent());
925 >      }
926 >    }    
927 >    
928 >    //scan topology
929  
930 +    int* excludeList = excludedInteractions_.getPairList();
931 +    int* oneTwoList = oneTwoInteractions_.getPairList();
932 +    int* oneThreeList = oneThreeInteractions_.getPairList();
933 +    int* oneFourList = oneFourInteractions_.getPairList();
934  
935 < void SimInfo::checkCutOffs( void ){
518 <  
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();      
935 >    topologyDone_ = true;
936    }
550  
551 }
937  
938 < void SimInfo::addProperty(GenericData* prop){
938 >  void SimInfo::addProperty(GenericData* genData) {
939 >    properties_.addProperty(genData);  
940 >  }
941  
942 <  map<string, GenericData*>::iterator result;
943 <  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()){
562 <    
563 <    delete (*result).second;
564 <    (*result).second = prop;
565 <      
942 >  void SimInfo::removeProperty(const string& propName) {
943 >    properties_.removeProperty(propName);  
944    }
567  else{
945  
946 <    properties[prop->getID()] = prop;
946 >  void SimInfo::clearProperties() {
947 >    properties_.clearProperties();
948 >  }
949  
950 +  vector<string> SimInfo::getPropertyNames() {
951 +    return properties_.getPropertyNames();  
952    }
953 <    
954 < }
953 >      
954 >  vector<GenericData*> SimInfo::getProperties() {
955 >    return properties_.getProperties();
956 >  }
957  
958 < GenericData* SimInfo::getProperty(const string& propName){
958 >  GenericData* SimInfo::getPropertyByName(const string& propName) {
959 >    return properties_.getPropertyByName(propName);
960 >  }
961 >
962 >  void SimInfo::setSnapshotManager(SnapshotManager* sman) {
963 >    if (sman_ == sman) {
964 >      return;
965 >    }    
966 >    delete sman_;
967 >    sman_ = sman;
968 >
969 >    Molecule* mol;
970 >    RigidBody* rb;
971 >    Atom* atom;
972 >    CutoffGroup* cg;
973 >    SimInfo::MoleculeIterator mi;
974 >    Molecule::RigidBodyIterator rbIter;
975 >    Molecule::AtomIterator atomIter;
976 >    Molecule::CutoffGroupIterator cgIter;
977  
978 <  map<string, GenericData*>::iterator result;
979 <  
980 <  //string lowerCaseName = ();
981 <  
982 <  result = properties.find(propName);
983 <  
984 <  if(result != properties.end())
985 <    return (*result).second;  
986 <  else  
987 <    return NULL;  
988 < }
978 >    for (mol = beginMolecule(mi); mol != NULL; mol = nextMolecule(mi)) {
979 >        
980 >      for (atom = mol->beginAtom(atomIter); atom != NULL;
981 >           atom = mol->nextAtom(atomIter)) {
982 >        atom->setSnapshotManager(sman_);
983 >      }
984 >        
985 >      for (rb = mol->beginRigidBody(rbIter); rb != NULL;
986 >           rb = mol->nextRigidBody(rbIter)) {
987 >        rb->setSnapshotManager(sman_);
988 >      }
989  
990 +      for (cg = mol->beginCutoffGroup(cgIter); cg != NULL;
991 +           cg = mol->nextCutoffGroup(cgIter)) {
992 +        cg->setSnapshotManager(sman_);
993 +      }
994 +    }    
995 +    
996 +  }
997  
998 < void SimInfo::getFortranGroupArrays(SimInfo* info,
999 <                                    vector<int>& FglobalGroupMembership,
1000 <                                    vector<double>& mfact){
998 >
999 >  ostream& operator <<(ostream& o, SimInfo& info) {
1000 >
1001 >    return o;
1002 >  }
1003 >  
1004    
1005 <  Molecule* myMols;
1006 <  Atom** myAtoms;
1007 <  int numAtom;
1008 <  double mtot;
1009 <  int numMol;
1010 <  int numCutoffGroups;
1011 <  CutoffGroup* myCutoffGroup;
1012 <  vector<CutoffGroup*>::iterator iterCutoff;
1013 <  Atom* cutoffAtom;
1014 <  vector<Atom*>::iterator iterAtom;
1015 <  int atomIndex;
605 <  double totalMass;
1005 >  StuntDouble* SimInfo::getIOIndexToIntegrableObject(int index) {
1006 >    if (index >= int(IOIndexToIntegrableObject.size())) {
1007 >      sprintf(painCave.errMsg,
1008 >              "SimInfo::getIOIndexToIntegrableObject Error: Integrable Object\n"
1009 >              "\tindex exceeds number of known objects!\n");
1010 >      painCave.isFatal = 1;
1011 >      simError();
1012 >      return NULL;
1013 >    } else
1014 >      return IOIndexToIntegrableObject.at(index);
1015 >  }
1016    
1017 <  mfact.clear();
1018 <  FglobalGroupMembership.clear();
1019 <  
1017 >  void SimInfo::setIOIndexToIntegrableObject(const vector<StuntDouble*>& v) {
1018 >    IOIndexToIntegrableObject= v;
1019 >  }
1020  
1021 <  // Fix the silly fortran indexing problem
1021 >  int SimInfo::getNGlobalConstraints() {
1022 >    int nGlobalConstraints;
1023   #ifdef IS_MPI
1024 <  numAtom = mpiSim->getNAtomsGlobal();
1024 >    MPI::COMM_WORLD.Allreduce(&nConstraints_, &nGlobalConstraints, 1,
1025 >                              MPI::INT, MPI::SUM);
1026   #else
1027 <  numAtom = n_atoms;
1027 >    nGlobalConstraints =  nConstraints_;
1028   #endif
1029 <  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 <    }
1029 >    return nGlobalConstraints;
1030    }
1031  
1032 < }
1032 > }//end namespace OpenMD
1033 >

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 1830 by gezelter, Wed Jan 9 22:02:30 2013 UTC

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

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines