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

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 1764 by gezelter, Tue Jul 3 18:32:27 2012 UTC

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

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines