ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/group/branches/new_design/OOPSE-2.0/src/brains/SimInfo.cpp
(Generate patch)

Comparing branches/new_design/OOPSE-2.0/src/brains/SimInfo.cpp (file contents):
Revision 1683, Thu Oct 28 22:34:02 2004 UTC vs.
Revision 1738 by tim, Sat Nov 13 05:08:12 2004 UTC

# Line 1 | Line 1
1 < #include <stdlib.h>
2 < #include <string.h>
3 < #include <math.h>
1 > /*
2 > * Copyright (C) 2000-2004  Object Oriented Parallel Simulation Engine (OOPSE) project
3 > *
4 > * Contact: oopse@oopse.org
5 > *
6 > * This program is free software; you can redistribute it and/or
7 > * modify it under the terms of the GNU Lesser General Public License
8 > * as published by the Free Software Foundation; either version 2.1
9 > * of the License, or (at your option) any later version.
10 > * All we ask is that proper credit is given for our work, which includes
11 > * - but is not limited to - adding the above copyright notice to the beginning
12 > * of your source code files, and to any copyright notice that you may distribute
13 > * with programs based on this work.
14 > *
15 > * This program is distributed in the hope that it will be useful,
16 > * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 > * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18 > * GNU Lesser General Public License for more details.
19 > *
20 > * You should have received a copy of the GNU Lesser General Public License
21 > * along with this program; if not, write to the Free Software
22 > * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
23 > *
24 > */
25  
26 < #include <iostream>
27 < using namespace std;
26 > /**
27 > * @file SimInfo.cpp
28 > * @author    tlin
29 > * @date  11/02/2004
30 > * @version 1.0
31 > */
32  
33 + #include <algorithm>
34 +
35   #include "brains/SimInfo.hpp"
36 < #define __C
10 < #include "brains/fSimulation.h"
11 < #include "utils/simError.h"
12 < #include "UseTheForce/DarkSide/simulation_interface.h"
13 < #include "UseTheForce/notifyCutoffs_interface.h"
36 > #include "utils/MemoryUtils.hpp"
37  
38 < //#include "UseTheForce/fortranWrappers.hpp"
38 > namespace oopse {
39  
40 < #include "math/MatVec3.h"
40 > SimInfo::SimInfo(const std::vector<std::pair<MoleculeStamp*, int> >& molStampPairs,
41 >                                ForceField* ff, Globals* globals) :
42 >                                forceField_(ff), globals_(globals), nAtoms_(0), nBonds_(0),
43 >                                nBends_(0), nTorsions_(0), nRigidBodies_(0), nIntegrableObjects_(0),
44 >                                nCutoffGroups_(0), nConstraints_(0), nZConstraint_(0), sman_(NULL),
45 >                                fortranInitialized_(false) {
46  
47 < #ifdef IS_MPI
48 < #include "brains/mpiSimulation.hpp"
49 < #endif
47 >    std::vector<std::pair<MoleculeStamp*, int> >::iterator i;
48 >    int nCutoffAtoms; // number of atoms belong to cutoff groups
49 >    int ngroups;          //total cutoff groups defined in meta-data file
50 >    MoleculeStamp* molStamp;
51 >    int nMolWithSameStamp;
52 >    CutoffGroupStamp* cgStamp;
53 >    int nAtomsIngroups;
54 >    int nCutoffGroupsInStamp;    
55  
56 < inline double roundMe( double x ){
57 <  return ( x >= 0 ) ? floor( x + 0.5 ) : ceil( x - 0.5 );
58 < }
59 <          
60 < inline double min( double a, double b ){
61 <  return (a < b ) ? a : b;
62 < }
56 >    nGlobalAtoms_ =  0;
57 >    ngroups = 0;
58 >    
59 >    for (i = molStampPairs.begin(); i !=molStampPairs.end(); ++i) {
60 >        molStamp = i->first;
61 >        nMolWithSameStamp = i->second;
62 >        
63 >        addMoleculeStamp(molStamp, nMolWithSameStamp);
64 >        
65 >        nGlobalAtoms_ += molStamp->getNAtoms() *nMolWithSameStamp;  
66 >        
67 >        nAtomsIngroups = 0;
68 >        nCutoffGroupsInStamp = molStamp->getNCutoffGroups();
69 >        
70 >        for (int j=0; j < nCutoffGroupsInStamp; j++) {
71 >            cgStamp = molStamp->getCutoffGroup(j);
72 >            nAtomsIngroups += cgStamp->getNMembers();
73 >        }
74  
75 < SimInfo* currentInfo;
75 >        ngroups += *nMolWithSameStamp;
76 >        nCutoffAtoms += nAtomsIngroups * nMolWithSameStamp;                
77 >    }
78  
79 < SimInfo::SimInfo(){
79 >    //every free atom (atom does not belong to cutoff groups) is a cutoff group
80 >    //therefore the total number of cutoff groups in the system is equal to
81 >    //the total number of atoms minus number of atoms belong to cutoff group defined in meta-data
82 >    //file plus the number of cutoff groups defined in meta-data file
83 >    nGlobalCutoffGroups_ = nGlobalAtoms_ - nCutoffAtoms + ngroups;
84  
85 <  n_constraints = 0;
86 <  nZconstraints = 0;
37 <  n_oriented = 0;
38 <  n_dipoles = 0;
39 <  ndf = 0;
40 <  ndfRaw = 0;
41 <  nZconstraints = 0;
42 <  the_integrator = NULL;
43 <  setTemp = 0;
44 <  thermalTime = 0.0;
45 <  currentTime = 0.0;
46 <  rCut = 0.0;
47 <  rSw = 0.0;
85 >    //initialize globalGroupMembership_, every element of this array will be 0
86 >    globalGroupMembership_.insert(globalGroupMembership_.end(), nGlobalAtoms_, 0);
87  
88 <  haveRcut = 0;
50 <  haveRsw = 0;
51 <  boxIsInit = 0;
52 <  
53 <  resetTime = 1e99;
88 >    nGlobalMols_ = molStampIds_.size();
89  
90 <  orthoRhombic = 0;
91 <  orthoTolerance = 1E-6;
92 <  useInitXSstate = true;
90 > #ifdef IS_MPI    
91 >    molToProcMap_.resize(nGlobalMols_);
92 > #endif
93 >    
94 > }
95  
96 <  usePBC = 0;
97 <  useDirectionalAtoms = 0;
61 <  useLennardJones = 0;
62 <  useElectrostatics = 0;
63 <  useCharges = 0;
64 <  useDipoles = 0;
65 <  useSticky = 0;
66 <  useGayBerne = 0;
67 <  useEAM = 0;
68 <  useShapes = 0;
69 <  useFLARB = 0;
96 > SimInfo::~SimInfo() {
97 >    //MemoryUtils::deleteVectorOfPointer(molecules_);
98  
99 <  useSolidThermInt = 0;
100 <  useLiquidThermInt = 0;
99 >    MemoryUtils::deleteVectorOfPointer(moleculeStamps_);
100 >    
101 >    delete sman_;
102 >    delete globals_;
103 >    delete forceField_;
104  
105 <  haveCutoffGroups = false;
105 > }
106  
76  excludes = Exclude::Instance();
107  
108 <  myConfiguration = new SimState();
108 > bool SimInfo::addMolecule(Molecule* mol) {
109 >    MoleculeIterator i;
110  
111 <  has_minimizer = false;
112 <  the_minimizer =NULL;
111 >    i = molecules_.find(mol->getGlobalIndex());
112 >    if (i != molecules_.end() ) {
113  
114 <  ngroup = 0;
114 >        molecules_.insert(make_pair(mol->getGlobalIndex(), mol));
115 >        
116 >        nAtoms_ += mol->getNAtoms();
117 >        nBonds_ += mol->getNBonds();
118 >        nBends_ += mol->getNBends();
119 >        nTorsions_ += mol->getNTorsions();
120 >        nRigidBodies_ += mol->getNRigidBodies();
121 >        nIntegrableObjects_ += mol->getNIntegrableObjects();
122 >        nCutoffGroups_ += mol->getNCutoffGroups();
123 >        nConstraints_ += mol->getNConstraints();
124  
125 +        return true;
126 +    } else {
127 +        return false;
128 +    }
129   }
130  
131 + bool SimInfo::removeMolecule(Molecule* mol) {
132 +    MoleculeIterator i;
133 +    i = molecules_.find(mol->getGlobalIndex());
134  
135 < SimInfo::~SimInfo(){
135 >    if (i != molecules_.end() ) {
136  
137 <  delete myConfiguration;
137 >        assert(mol == i->second);
138 >        
139 >        nAtoms_ -= mol->getNAtoms();
140 >        nBonds_ -= mol->getNBonds();
141 >        nBends_ -= mol->getNBends();
142 >        nTorsions_ -= mol->getNTorsions();
143 >        nRigidBodies_ -= mol->getNRigidBodies();
144 >        nIntegrableObjects_ -= mol->getNIntegrableObjects();
145 >        nCutoffGroups_ -= mol->getNCutoffGroups();
146 >        nConstraints_ -= mol->getNConstraints();
147  
148 <  map<string, GenericData*>::iterator i;
93 <  
94 <  for(i = properties.begin(); i != properties.end(); i++)
95 <    delete (*i).second;
148 >        molecules_.erase(mol->getGlobalIndex());
149  
150 < }
150 >        delete mol;
151 >        
152 >        return true;
153 >    } else {
154 >        return false;
155 >    }
156  
99 void SimInfo::setBox(double newBox[3]) {
100  
101  int i, j;
102  double tempMat[3][3];
157  
158 <  for(i=0; i<3; i++)
105 <    for (j=0; j<3; j++) tempMat[i][j] = 0.0;;
158 > }    
159  
160 <  tempMat[0][0] = newBox[0];
161 <  tempMat[1][1] = newBox[1];
162 <  tempMat[2][2] = newBox[2];
160 >        
161 > Molecule* SimInfo::beginMolecule(MoleculeIterator& i) {
162 >    i = molecules_.begin();
163 >    return i == molecules_.end() ? NULL : i->second;
164 > }    
165  
166 <  setBoxM( tempMat );
167 <
166 > Molecule* SimInfo::nextMolecule(MoleculeIterator& i) {
167 >    ++i;
168 >    return i == molecules_.end() ? NULL : i->second;    
169   }
170  
115 void SimInfo::setBoxM( double theBox[3][3] ){
116  
117  int i, j;
118  double FortranHmat[9]; // to preserve compatibility with Fortran the
119                         // ordering in the array is as follows:
120                         // [ 0 3 6 ]
121                         // [ 1 4 7 ]
122                         // [ 2 5 8 ]
123  double FortranHmatInv[9]; // the inverted Hmat (for Fortran);
171  
172 <  if( !boxIsInit ) boxIsInit = 1;
172 > void SimInfo::calcNdf() {
173 >    int ndf_local;
174 >    MoleculeIterator i;
175 >    std::vector<StuntDouble*>::iterator j;
176 >    Molecule* mol;
177 >    StuntDouble* integrableObject;
178  
179 <  for(i=0; i < 3; i++)
180 <    for (j=0; j < 3; j++) Hmat[i][j] = theBox[i][j];
181 <  
182 <  calcBoxL();
183 <  calcHmatInv();
179 >    ndf_local = 0;
180 >    
181 >    for (mol = beginMolecule(i); mol != NULL; mol = nextMolecule(i)) {
182 >        for (integrableObject = mol->beginIntegrableObject(j); integrableObject != NULL;
183 >               integrableObject = mol->nextIntegrableObject(j)) {
184  
185 <  for(i=0; i < 3; i++) {
134 <    for (j=0; j < 3; j++) {
135 <      FortranHmat[3*j + i] = Hmat[i][j];
136 <      FortranHmatInv[3*j + i] = HmatInv[i][j];
137 <    }
138 <  }
185 >            ndf_local += 3;
186  
187 <  setFortranBox(FortranHmat, FortranHmatInv, &orthoRhombic);
188 <
189 < }
190 <
187 >            if (integrableObject->isDirectional()) {
188 >                if (integrableObject->isLinear()) {
189 >                    ndf_local += 2;
190 >                } else {
191 >                    ndf_local += 3;
192 >                }
193 >            }
194 >            
195 >        }//end for (integrableObject)
196 >    }// end for (mol)
197 >    
198 >    // n_constraints is local, so subtract them on each processor
199 >    ndf_local -= nConstraints_;
200  
201 < void SimInfo::getBoxM (double theBox[3][3]) {
201 > #ifdef IS_MPI
202 >    MPI_Allreduce(&ndf_local,&ndf_,1,MPI_INT,MPI_SUM, MPI_COMM_WORLD);
203 > #else
204 >    ndf_ = ndf_local;
205 > #endif
206  
207 <  int i, j;
208 <  for(i=0; i<3; i++)
209 <    for (j=0; j<3; j++) theBox[i][j] = Hmat[i][j];
207 >    // nZconstraints_ is global, as are the 3 COM translations for the
208 >    // entire system:
209 >    ndf_ = ndf_ - 3 - nZconstraints_;
210 >
211   }
212  
213 + void SimInfo::calcNdfRaw() {
214 +    int ndfRaw_local;
215  
216 < void SimInfo::scaleBox(double scale) {
217 <  double theBox[3][3];
218 <  int i, j;
216 >    MoleculeIterator i;
217 >    std::vector<StuntDouble*>::iterator j;
218 >    Molecule* mol;
219 >    StuntDouble* integrableObject;
220  
221 <  // cerr << "Scaling box by " << scale << "\n";
221 >    // Raw degrees of freedom that we have to set
222 >    ndfRaw_local = 0;
223 >    
224 >    for (mol = beginMolecule(i); mol != NULL; mol = nextMolecule(i)) {
225 >        for (integrableObject = mol->beginIntegrableObject(j); integrableObject != NULL;
226 >               integrableObject = mol->nextIntegrableObject(j)) {
227  
228 <  for(i=0; i<3; i++)
160 <    for (j=0; j<3; j++) theBox[i][j] = Hmat[i][j]*scale;
228 >            ndfRaw_local += 3;
229  
230 <  setBoxM(theBox);
231 <
230 >            if (integrableObject->isDirectional()) {
231 >                if (integrableObject->isLinear()) {
232 >                    ndfRaw_local += 2;
233 >                } else {
234 >                    ndfRaw_local += 3;
235 >                }
236 >            }
237 >            
238 >        }
239 >    }
240 >    
241 > #ifdef IS_MPI
242 >    MPI_Allreduce(&ndfRaw_local,&ndfRaw_,1,MPI_INT,MPI_SUM, MPI_COMM_WORLD);
243 > #else
244 >    ndfRaw_ = ndfRaw_local;
245 > #endif
246   }
247  
248 < void SimInfo::calcHmatInv( void ) {
249 <  
168 <  int oldOrtho;
169 <  int i,j;
170 <  double smallDiag;
171 <  double tol;
172 <  double sanity[3][3];
248 > void SimInfo::calcNdfTrans() {
249 >    int ndfTrans_local;
250  
251 <  invertMat3( Hmat, HmatInv );
251 >    ndfTrans_local = 3 * nIntegrableObjects_ - nConstraints_;
252  
253 <  // check to see if Hmat is orthorhombic
254 <  
255 <  oldOrtho = orthoRhombic;
253 >
254 > #ifdef IS_MPI
255 >    MPI_Allreduce(&ndfTrans_local,&ndfTrans_,1,MPI_INT,MPI_SUM, MPI_COMM_WORLD);
256 > #else
257 >    ndfTrans_ = ndfTrans_local;
258 > #endif
259  
260 <  smallDiag = fabs(Hmat[0][0]);
261 <  if(smallDiag > fabs(Hmat[1][1])) smallDiag = fabs(Hmat[1][1]);
262 <  if(smallDiag > fabs(Hmat[2][2])) smallDiag = fabs(Hmat[2][2]);
183 <  tol = smallDiag * orthoTolerance;
260 >    ndfTrans_ = ndfTrans_ - 3 - nZconstraints_;
261 >
262 > }
263  
264 <  orthoRhombic = 1;
265 <  
266 <  for (i = 0; i < 3; i++ ) {
267 <    for (j = 0 ; j < 3; j++) {
268 <      if (i != j) {
269 <        if (orthoRhombic) {
270 <          if ( fabs(Hmat[i][j]) >= tol) orthoRhombic = 0;
271 <        }        
272 <      }
273 <    }
274 <  }
196 <
197 <  if( oldOrtho != orthoRhombic ){
264 > void SimInfo::addExcludePairs(Molecule* mol) {
265 >    std::vector<Bond*>::iterator bondIter;
266 >    std::vector<Bend*>::iterator bendIter;
267 >    std::vector<Torsion*>::iterator torsionIter;
268 >    Bond* bond;
269 >    Bend* bend;
270 >    Torsion* torsion;
271 >    int a;
272 >    int b;
273 >    int c;
274 >    int d;
275      
276 <    if( orthoRhombic ) {
277 <      sprintf( painCave.errMsg,
278 <               "OOPSE is switching from the default Non-Orthorhombic\n"
279 <               "\tto the faster Orthorhombic periodic boundary computations.\n"
203 <               "\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();
276 >    for (bond= mol->beginBond(bondIter); bond != NULL; bond = mol->nextBond(bondIter)) {
277 >        a = bond->getAtomA()->getGlobalIndex();
278 >        b = bond->getAtomB()->getGlobalIndex();        
279 >        exclude_.addPair(a, b);
280      }
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 }
281  
282 < void SimInfo::calcBoxL( void ){
282 >    for (bend= mol->beginBend(bendIter); bend != NULL; bend = mol->nextBend(bendIter)) {
283 >        a = bend->getAtomA()->getGlobalIndex();
284 >        b = bend->getAtomB()->getGlobalIndex();        
285 >        c = bend->getAtomC()->getGlobalIndex();
286  
287 <  double dx, dy, dz, dsq;
287 >        exclude_.addPair(a, b);
288 >        exclude_.addPair(a, c);
289 >        exclude_.addPair(b, c);        
290 >    }
291  
292 <  // boxVol = Determinant of Hmat
292 >    for (torsion= mol->beginTorsion(torsionIter); torsion != NULL; torsion = mol->nextBond(torsionIter)) {
293 >        a = torsion->getAtomA()->getGlobalIndex();
294 >        b = torsion->getAtomB()->getGlobalIndex();        
295 >        c = torsion->getAtomC()->getGlobalIndex();        
296 >        d = torsion->getAtomD()->getGlobalIndex();        
297  
298 <  boxVol = matDet3( Hmat );
298 >        exclude_.addPair(a, b);
299 >        exclude_.addPair(a, c);
300 >        exclude_.addPair(a, d);
301 >        exclude_.addPair(b, c);
302 >        exclude_.addPair(b, d);
303 >        exclude_.addPair(c, d);        
304 >    }
305  
306 <  // boxLx
307 <  
235 <  dx = Hmat[0][0]; dy = Hmat[1][0]; dz = Hmat[2][0];
236 <  dsq = dx*dx + dy*dy + dz*dz;
237 <  boxL[0] = sqrt( dsq );
238 <  //maxCutoff = 0.5 * boxL[0];
306 >    
307 > }
308  
309 <  // boxLy
310 <  
311 <  dx = Hmat[0][1]; dy = Hmat[1][1]; dz = Hmat[2][1];
312 <  dsq = dx*dx + dy*dy + dz*dz;
313 <  boxL[1] = sqrt( dsq );
314 <  //if( (0.5 * boxL[1]) < maxCutoff ) maxCutoff = 0.5 * boxL[1];
309 > void SimInfo::removeExcludePairs(Molecule* mol) {
310 >    std::vector<Bond*>::iterator bondIter;
311 >    std::vector<Bend*>::iterator bendIter;
312 >    std::vector<Torsion*>::iterator torsionIter;
313 >    Bond* bond;
314 >    Bend* bend;
315 >    Torsion* torsion;
316 >    int a;
317 >    int b;
318 >    int c;
319 >    int d;
320 >    
321 >    for (bond= mol->beginBond(bondIter); bond != NULL; bond = mol->nextBond(bondIter)) {
322 >        a = bond->getAtomA()->getGlobalIndex();
323 >        b = bond->getAtomB()->getGlobalIndex();        
324 >        exclude_.removePair(a, b);
325 >    }
326  
327 +    for (bend= mol->beginBend(bendIter); bend != NULL; bend = mol->nextBend(bendIter)) {
328 +        a = bend->getAtomA()->getGlobalIndex();
329 +        b = bend->getAtomB()->getGlobalIndex();        
330 +        c = bend->getAtomC()->getGlobalIndex();
331  
332 <  // boxLz
333 <  
334 <  dx = Hmat[0][2]; dy = Hmat[1][2]; dz = Hmat[2][2];
335 <  dsq = dx*dx + dy*dy + dz*dz;
252 <  boxL[2] = sqrt( dsq );
253 <  //if( (0.5 * boxL[2]) < maxCutoff ) maxCutoff = 0.5 * boxL[2];
332 >        exclude_.removePair(a, b);
333 >        exclude_.removePair(a, c);
334 >        exclude_.removePair(b, c);        
335 >    }
336  
337 <  //calculate the max cutoff
338 <  maxCutoff =  calcMaxCutOff();
339 <  
340 <  checkCutOffs();
337 >    for (torsion= mol->beginTorsion(torsionIter); torsion != NULL; torsion = mol->nextBond(torsionIter)) {
338 >        a = torsion->getAtomA()->getGlobalIndex();
339 >        b = torsion->getAtomB()->getGlobalIndex();        
340 >        c = torsion->getAtomC()->getGlobalIndex();        
341 >        d = torsion->getAtomD()->getGlobalIndex();        
342  
343 +        exclude_.removePair(a, b);
344 +        exclude_.removePair(a, c);
345 +        exclude_.removePair(a, d);
346 +        exclude_.removePair(b, c);
347 +        exclude_.removePair(b, d);
348 +        exclude_.removePair(c, d);        
349 +    }
350 +
351   }
352  
353  
354 < double SimInfo::calcMaxCutOff(){
354 > void SimInfo::addMoleculeStamp(MoleculeStamp* molStamp, int nmol) {
355 >    int curStampId;
356  
357 <  double ri[3], rj[3], rk[3];
358 <  double rij[3], rjk[3], rki[3];
267 <  double minDist;
357 >    //index from 0
358 >    curStampId = molStampIds_.size();
359  
360 <  ri[0] = Hmat[0][0];
361 <  ri[1] = Hmat[1][0];
362 <  ri[2] = Hmat[2][0];
360 >    moleculeStamps_.push_back(molStamp);
361 >    molStampIds_.insert(molStampIds_.end(), nmol, curStampId)
362 > }
363  
364 <  rj[0] = Hmat[0][1];
274 <  rj[1] = Hmat[1][1];
275 <  rj[2] = Hmat[2][1];
364 > void SimInfo::update() {
365  
366 <  rk[0] = Hmat[0][2];
278 <  rk[1] = Hmat[1][2];
279 <  rk[2] = Hmat[2][2];
280 <    
281 <  crossProduct3(ri, rj, rij);
282 <  distXY = dotProduct3(rk,rij) / norm3(rij);
366 >    setupSimType();
367  
368 <  crossProduct3(rj,rk, rjk);
369 <  distYZ = dotProduct3(ri,rjk) / norm3(rjk);
368 > #ifdef IS_MPI
369 >    setupFortranParallel();
370 > #endif
371  
372 <  crossProduct3(rk,ri, rki);
288 <  distZX = dotProduct3(rj,rki) / norm3(rki);
372 >    setupFortranSim();
373  
374 <  minDist = min(min(distXY, distYZ), distZX);
291 <  return minDist/2;
292 <  
293 < }
374 >    setupCutoff();
375  
376 < void SimInfo::wrapVector( double thePos[3] ){
376 >    //notify fortran whether reaction field is used or not. It is deprecated now
377 >    //int isError = 0;
378 >    //initFortranFF( &useReactionField, &isError );
379  
380 <  int i;
381 <  double scaled[3];
382 <
383 <  if( !orthoRhombic ){
384 <    // calc the scaled coordinates.
385 <  
303 <
304 <    matVecMul3(HmatInv, thePos, scaled);
380 >    //if(isError){
381 >    //    sprintf( painCave.errMsg,
382 >    //    "SimCreator::initFortran() error: There was an error initializing the forceField in fortran.\n" );
383 >    //    painCave.isFatal = 1;
384 >    //    simError();
385 >    //}
386      
387 <    for(i=0; i<3; i++)
388 <      scaled[i] -= roundMe(scaled[i]);
389 <    
309 <    // calc the wrapped real coordinates from the wrapped scaled coordinates
310 <    
311 <    matVecMul3(Hmat, scaled, thePos);
387 >    calcNdf();
388 >    calcNdfRaw();
389 >    calcNdfTrans();
390  
391 <  }
314 <  else{
315 <    // calc the scaled coordinates.
316 <    
317 <    for(i=0; i<3; i++)
318 <      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 <    
391 >    fortranInitialized_ = true;
392   }
393  
394 + std::set<AtomType*> SimInfo::getUniqueAtomTypes() {
395 +    typename SimInfo::MoleculeIterator mi;
396 +    Molecule* mol;
397 +    typename Molecule::AtomIterator ai;
398 +    Atom* atom;
399 +    std::set<AtomType*> atomTypes;
400  
401 < int SimInfo::getNDF(){
335 <  int ndf_local;
401 >    for(mol = beginMolecule(mi); mol != NULL; mol = nextMolecule(mi)) {
402  
403 <  ndf_local = 0;
404 <  
405 <  for(int i = 0; i < integrableObjects.size(); i++){
406 <    ndf_local += 3;
341 <    if (integrableObjects[i]->isDirectional()) {
342 <      if (integrableObjects[i]->isLinear())
343 <        ndf_local += 2;
344 <      else
345 <        ndf_local += 3;
403 >        for(atom = mol->beginAtom(ai); atom != NULL; atom = mol->nextAtom(ai)) {
404 >            atomTypes.insert(atom->getAtomType());
405 >        }
406 >        
407      }
347  }
408  
409 <  // n_constraints is local, so subtract them on each processor:
409 >    return atomTypes;        
410 > }
411  
412 <  ndf_local -= n_constraints;
412 > void SimInfo::setupSimType() {
413 >    std::set<AtomType*>::iterator i;
414 >    std::set<AtomType*> atomTypes;
415 >    atomTypes = getUniqueAtomTypes();
416 >    
417 >    int useLennardJones = 0;
418 >    int useElectrostatic = 0;
419 >    int useEAM = 0;
420 >    int useCharge = 0;
421 >    int useDirectional = 0;
422 >    int useDipole = 0;
423 >    int useGayBerne = 0;
424 >    int useSticky = 0;
425 >    int useShape = 0;
426 >    int useFLARB = 0; //it is not in AtomType yet
427 >    int useDirectionalAtom = 0;    
428 >    int useElectrostatics = 0;
429 >    //usePBC and useRF are from globals
430 >    bool usePBC = globals_->getPBC();
431 >    bool useRF = globals_->getUseRF();
432  
433 < #ifdef IS_MPI
434 <  MPI_Allreduce(&ndf_local,&ndf,1,MPI_INT,MPI_SUM, MPI_COMM_WORLD);
435 < #else
436 <  ndf = ndf_local;
437 < #endif
433 >    //loop over all of the atom types
434 >    for (i = atomTypes.begin(); i != atomTypes.end(); ++i) {
435 >        useLennardJones |= i->isLennardJones();
436 >        useElectrostatic |= i->isElectrostatic();
437 >        useEAM |= i->isEAM();
438 >        useCharge |= i->isCharge();
439 >        useDirectional |= i->isDirectional();
440 >        useDipole |= i->isDipole();
441 >        useGayBerne |= i->isGayBerne();
442 >        useSticky |= i->isSticky();
443 >        useShape |= i->isShape();
444 >    }
445  
446 <  // nZconstraints is global, as are the 3 COM translations for the
447 <  // entire system:
446 >    if (useSticky || useDipole || useGayBerne || useShape) {
447 >        useDirectionalAtom = 1;
448 >    }
449  
450 <  ndf = ndf - 3 - nZconstraints;
450 >    if (useCharge || useDipole) {
451 >        useElectrostatics = 1;
452 >    }
453  
454 <  return ndf;
455 < }
454 > #ifdef IS_MPI    
455 >    int temp;
456  
457 < int SimInfo::getNDFraw() {
458 <  int ndfRaw_local;
457 >    temp = usePBC;
458 >    MPI_Allreduce(&temp, &usePBC, 1, MPI_INT, MPI_LOR, MPI_COMM_WORLD);    
459  
460 <  // Raw degrees of freedom that we have to set
461 <  ndfRaw_local = 0;
460 >    temp = useDirectionalAtom;
461 >    MPI_Allreduce(&temp, &useDirectionalAtom, 1, MPI_INT, MPI_LOR, MPI_COMM_WORLD);    
462  
463 <  for(int i = 0; i < integrableObjects.size(); i++){
464 <    ndfRaw_local += 3;
375 <    if (integrableObjects[i]->isDirectional()) {
376 <       if (integrableObjects[i]->isLinear())
377 <        ndfRaw_local += 2;
378 <      else
379 <        ndfRaw_local += 3;
380 <    }
381 <  }
382 <    
383 < #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
463 >    temp = useLennardJones;
464 >    MPI_Allreduce(&temp, &useLennardJones, 1, MPI_INT, MPI_LOR, MPI_COMM_WORLD);    
465  
466 <  return ndfRaw;
467 < }
466 >    temp = useElectrostatics;
467 >    MPI_Allreduce(&temp, &useElectrostatics, 1, MPI_INT, MPI_LOR, MPI_COMM_WORLD);    
468  
469 < int SimInfo::getNDFtranslational() {
470 <  int ndfTrans_local;
469 >    temp = useCharge;
470 >    MPI_Allreduce(&temp, &useCharge, 1, MPI_INT, MPI_LOR, MPI_COMM_WORLD);    
471  
472 <  ndfTrans_local = 3 * integrableObjects.size() - n_constraints;
472 >    temp = useDipole;
473 >    MPI_Allreduce(&temp, &useDipole, 1, MPI_INT, MPI_LOR, MPI_COMM_WORLD);    
474  
475 +    temp = useSticky;
476 +    MPI_Allreduce(&temp, &useSticky, 1, MPI_INT, MPI_LOR, MPI_COMM_WORLD);    
477  
478 < #ifdef IS_MPI
479 <  MPI_Allreduce(&ndfTrans_local,&ndfTrans,1,MPI_INT,MPI_SUM, MPI_COMM_WORLD);
400 < #else
401 <  ndfTrans = ndfTrans_local;
402 < #endif
478 >    temp = useGayBerne;
479 >    MPI_Allreduce(&temp, &useGayBerne, 1, MPI_INT, MPI_LOR, MPI_COMM_WORLD);    
480  
481 <  ndfTrans = ndfTrans - 3 - nZconstraints;
481 >    temp = useEAM;
482 >    MPI_Allreduce(&temp, &useEAM, 1, MPI_INT, MPI_LOR, MPI_COMM_WORLD);    
483  
484 <  return ndfTrans;
485 < }
484 >    temp = useShape;
485 >    MPI_Allreduce(&temp, &useShape, 1, MPI_INT, MPI_LOR, MPI_COMM_WORLD);  
486  
487 < int SimInfo::getTotIntegrableObjects() {
488 <  int nObjs_local;
411 <  int nObjs;
487 >    temp = useFLARB;
488 >    MPI_Allreduce(&temp, &useFLARB, 1, MPI_INT, MPI_LOR, MPI_COMM_WORLD);    
489  
490 <  nObjs_local =  integrableObjects.size();
491 <
492 <
416 < #ifdef IS_MPI
417 <  MPI_Allreduce(&nObjs_local,&nObjs,1,MPI_INT,MPI_SUM, MPI_COMM_WORLD);
418 < #else
419 <  nObjs = nObjs_local;
490 >    temp = useRF;
491 >    MPI_Allreduce(&temp, &useRF, 1, MPI_INT, MPI_LOR, MPI_COMM_WORLD);    
492 >    
493   #endif
494  
495 +    fInfo_.SIM_uses_PBC = usePBC;    
496 +    fInfo_.SIM_uses_DirectionalAtoms = useDirectionalAtom;
497 +    fInfo_.SIM_uses_LennardJones = useLennardJones;
498 +    fInfo_.SIM_uses_Electrostatics = useElectrostatics;    
499 +    fInfo_.SIM_uses_Charges = useCharge;
500 +    fInfo_.SIM_uses_Dipoles = useDipole;
501 +    fInfo_.SIM_uses_Sticky = useSticky;
502 +    fInfo_.SIM_uses_GayBerne = useGayBerne;
503 +    fInfo_.SIM_uses_EAM = useEAM;
504 +    fInfo_.SIM_uses_Shapes = useShape;
505 +    fInfo_.SIM_uses_FLARB = useFLARB;
506 +    fInfo_.SIM_uses_RF = useRF;
507  
508 <  return nObjs;
508 >    if( fInfo_.SIM_uses_Dipoles && fInfo_.SIM_uses_RF) {
509 >        fInfo_.dielect = dielectric;
510 >    } else {
511 >        fInfo_.dielect = 0.0;
512 >    }
513 >
514   }
515  
516 < void SimInfo::refreshSim(){
516 > void SimInfo::setupFortranSim() {
517 >    int isError;
518 >    int nExclude;
519 >    std::vector<int> fortranGlobalGroupMembership;
520 >    
521 >    nExclude = exclude_.getSize();
522 >    isError = 0;
523  
524 <  simtype fInfo;
525 <  int isError;
526 <  int n_global;
527 <  int* excl;
524 >    //globalGroupMembership_ is filled by SimCreator    
525 >    for (int i = 0; i < nGlobalAtoms_; i++) {
526 >        fortranGlobalGroupMembership.push_back(globalGroupMembership_[i] + 1);
527 >    }
528  
529 <  fInfo.dielect = 0.0;
529 >    //calculate mass ratio of cutoff group
530 >    std::vector<double> mfact;
531 >    typename SimInfo::MoleculeIterator mi;
532 >    Molecule* mol;
533 >    typename Molecule::CutoffGroupIterator ci;
534 >    CutoffGroup* cg;
535 >    typename Molecule::AtomIterator ai;
536 >    Atom* atom;
537 >    double totalMass;
538  
539 <  if( useDipoles ){
540 <    if( useReactionField )fInfo.dielect = dielectric;
541 <  }
539 >    //to avoid memory reallocation, reserve enough space for mfact
540 >    mfact.reserve(getNCutoffGroups());
541 >    
542 >    for(mol = beginMolecule(mi); mol != NULL; mol = nextMolecule(mi)) {        
543 >        for (cg = mol->beginCutoffGroup(ci); cg != NULL; cg = mol->nextCutoffGroup(ci)) {
544  
545 <  fInfo.SIM_uses_PBC = usePBC;
545 >            totalMass = cg->getMass();
546 >            for(atom = cg->beginAtom(ai); atom != NULL; atom = cg->nextAtom(ai)) {
547 >                        mfact.push_back(atom->getMass()/totalMass);
548 >            }
549  
550 <  if (useSticky || useDipoles || useGayBerne || useShapes) {
551 <    useDirectionalAtoms = 1;
443 <    fInfo.SIM_uses_DirectionalAtoms = useDirectionalAtoms;
444 <  }
550 >        }      
551 >    }
552  
553 <  fInfo.SIM_uses_LennardJones = useLennardJones;
553 >    //fill ident array of local atoms (it is actually ident of AtomType, it is so confusing !!!)
554 >    std::vector<int> identArray;
555  
556 <  if (useCharges || useDipoles) {
557 <    useElectrostatics = 1;
558 <    fInfo.SIM_uses_Electrostatics = useElectrostatics;
559 <  }
556 >    //to avoid memory reallocation, reserve enough space identArray
557 >    identArray.reserve(getNAtoms());
558 >    
559 >    for(mol = beginMolecule(mi); mol != NULL; mol = nextMolecule(mi)) {        
560 >        for(atom = mol->beginAtom(ai); atom != NULL; atom = mol->nextAtom(ai)) {
561 >            identArray.push_back(atom->getIdent());
562 >        }
563 >    }    
564  
565 <  fInfo.SIM_uses_Charges = useCharges;
566 <  fInfo.SIM_uses_Dipoles = useDipoles;
567 <  fInfo.SIM_uses_Sticky = useSticky;
568 <  fInfo.SIM_uses_GayBerne = useGayBerne;
569 <  fInfo.SIM_uses_EAM = useEAM;
570 <  fInfo.SIM_uses_Shapes = useShapes;
571 <  fInfo.SIM_uses_FLARB = useFLARB;
572 <  fInfo.SIM_uses_RF = useReactionField;
573 <
574 <  n_exclude = excludes->getSize();
575 <  excl = excludes->getFortranArray();
576 <  
577 < #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,
565 >    //fill molMembershipArray
566 >    //molMembershipArray is filled by SimCreator    
567 >    std::vector<int> molMembershipArray(nGlobalAtoms_);
568 >    for (int i = 0; i < nGlobalAtoms_; i++) {
569 >        molMembershipArray.push_back(globalMolMembership_[i] + 1);
570 >    }
571 >    
572 >    //setup fortran simulation
573 >    //gloalExcludes and molMembershipArray should go away (They are never used)
574 >    //why the hell fortran need to know molecule?
575 >    //OOPSE = Object-Obfuscated Parallel Simulation Engine
576 >    
577 >    setFortranSim( &fInfo_, &nGlobalAtoms_, &nAtoms_, &identArray[0], &nExclude, exclude_->getExcludeList(),
578                    &nGlobalExcludes, globalExcludes, molMembershipArray,
579 <                  &mfact[0], &ngroup, &FglobalGroupMembership[0], &isError);
579 >                  &mfact[0], &nCutoffGroups_, &fortranGlobalGroupMembership[0], &isError);
580  
581 <  if( isError ){
582 <    
583 <    sprintf( painCave.errMsg,
584 <             "There was an error setting the simulation information in fortran.\n" );
585 <    painCave.isFatal = 1;
586 <    painCave.severity = OOPSE_ERROR;
587 <    simError();
588 <  }
589 <  
581 >    if( isError ){
582 >
583 >        sprintf( painCave.errMsg,
584 >                 "There was an error setting the simulation information in fortran.\n" );
585 >        painCave.isFatal = 1;
586 >        painCave.severity = OOPSE_ERROR;
587 >        simError();
588 >    }
589 >
590   #ifdef IS_MPI
591 <  sprintf( checkPointMsg,
592 <           "succesfully sent the simulation information to fortran.\n");
593 <  MPIcheckPoint();
591 >    sprintf( checkPointMsg,
592 >       "succesfully sent the simulation information to fortran.\n");
593 >    MPIcheckPoint();
594   #endif // is_mpi
495  
496  this->ndf = this->getNDF();
497  this->ndfRaw = this->getNDFraw();
498  this->ndfTrans = this->getNDFtranslational();
595   }
596  
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 }
597  
598 < void SimInfo::setDefaultRcut( double theRcut, double theRsw ){
599 <
600 <  rSw = theRsw;
601 <  setDefaultRcut( theRcut );
602 < }
598 > #ifdef IS_MPI
599 > void SimInfo::setupFortranParallel() {
600 >    
601 >    //SimInfo is responsible for creating localToGlobalAtomIndex and localToGlobalGroupIndex
602 >    std::vector<int> localToGlobalAtomIndex(getNAtoms(), 0);
603 >    std::vector<int> localToGlobalCutoffGroupIndex;
604 >    typename SimInfo::MoleculeIterator mi;
605 >    typename Molecule::AtomIterator ai;
606 >    typename Molecule::CutoffGroupIterator ci;
607 >    Molecule* mol;
608 >    Atom* atom;
609 >    CutoffGroup* cg;
610 >    mpiSimData parallelData;
611 >    int isError;
612  
613 +    for (mol = beginMolecule(mi); mol != NULL; mol  = nextMolecule(mi)) {
614  
615 < void SimInfo::checkCutOffs( void ){
616 <  
617 <  if( boxIsInit ){
618 <    
619 <    //we need to check cutOffs against the box
620 <    
621 <    if( rCut > maxCutoff ){
622 <      sprintf( painCave.errMsg,
623 <               "cutoffRadius is too large for the current periodic box.\n"
624 <               "\tCurrent Value of cutoffRadius = %G at time %G\n "
625 <               "\tThis is larger than half of at least one of the\n"
626 <               "\tperiodic box vectors.  Right now, the Box matrix is:\n"
627 <               "\n"
628 <               "\t[ %G %G %G ]\n"
629 <               "\t[ %G %G %G ]\n"
630 <               "\t[ %G %G %G ]\n",
631 <               rCut, currentTime,
632 <               Hmat[0][0], Hmat[0][1], Hmat[0][2],
633 <               Hmat[1][0], Hmat[1][1], Hmat[1][2],
634 <               Hmat[2][0], Hmat[2][1], Hmat[2][2]);
635 <      painCave.severity = OOPSE_ERROR;
636 <      painCave.isFatal = 1;
637 <      simError();
638 <    }    
639 <  } else {
640 <    // initialize this stuff before using it, OK?
641 <    sprintf( painCave.errMsg,
642 <             "Trying to check cutoffs without a box.\n"
643 <             "\tOOPSE should have better programmers than that.\n" );
644 <    painCave.severity = OOPSE_ERROR;
645 <    painCave.isFatal = 1;
646 <    simError();      
647 <  }
648 <  
615 >        //local index(index in DataStorge) of atom is important
616 >        for (atom = mol->beginAtom(ai); atom != NULL; atom = mol->nextAtom(ai)) {
617 >            localToGlobalAtomIndex[atom->getLocalIndex()] = atom->getGlobalIndex() + 1;
618 >        }
619 >
620 >        //local index of cutoff group is trivial, it only depends on the order of travesing
621 >        for (cg = mol->beginCutoffGroup(ci); cg != NULL; cg = mol->nextCutoffGroup(ci)) {
622 >            localToGlobalCutoffGroupIndex.push_back(cg->getGlobalIndex() + 1);
623 >        }        
624 >        
625 >    }
626 >
627 >    //fill up mpiSimData struct
628 >    parallelData.nMolGlobal = getNGlobalMolecules();
629 >    parallelData.nMolLocal = getNMolecules();
630 >    parallelData.nAtomsGlobal = getNGlobalAtoms();
631 >    parallelData.nAtomsLocal = getNAtoms();
632 >    parallelData.nGroupsGlobal = getNGlobalCutoffGroups();
633 >    parallelData.nGroupsLocal = getNCutoffGroups();
634 >    parallelData.myNode = worldRank;
635 >    MPI_Comm_size(MPI_COMM_WORLD, &(parallelData->nProcessors));
636 >
637 >    //pass mpiSimData struct and index arrays to fortran
638 >    setFsimParallel(parallelData, &(parallelData->nAtomsLocal),
639 >                    &localToGlobalAtomIndex[0],  &(parallelData->nGroupsLocal),
640 >                    &localToGlobalCutoffGroupIndex[0], &isError);
641 >
642 >    if (isError) {
643 >        sprintf(painCave.errMsg,
644 >                "mpiRefresh errror: fortran didn't like something we gave it.\n");
645 >        painCave.isFatal = 1;
646 >        simError();
647 >    }
648 >
649 >    sprintf(checkPointMsg, " mpiRefresh successful.\n");
650 >    MPIcheckPoint();
651 >
652 >
653   }
654  
655 < void SimInfo::addProperty(GenericData* prop){
655 > #endif
656  
657 <  map<string, GenericData*>::iterator result;
658 <  result = properties.find(prop->getID());
659 <  
660 <  //we can't simply use  properties[prop->getID()] = prop,
661 <  //it will cause memory leak if we already contain a propery which has the same name of prop
662 <  
663 <  if(result != properties.end()){
657 > double SimInfo::calcMaxCutoffRadius() {
658 >
659 >
660 >    std::vector<AtomType*> atomTypes;
661 >    std::vector<AtomType*>::iterator i;
662 >    std::vector<double> cutoffRadius;
663 >
664 >    //get the unique atom types
665 >    atomTypes = getUniqueAtomTypes();
666 >
667 >    //query the max cutoff radius among these atom types
668 >    for (i = atomTypes.begin(); i != atomTypes.end(); ++i) {
669 >        cutoffRadius.push_back(forceField_->getRcutFromAtomType(*i));
670 >    }
671 >
672 >    double maxCutoffRadius = std::max_element(cutoffRadius.begin(), cutoffRadius.end());
673 > #ifdef IS_MPI
674 >    //pick the max cutoff radius among the processors
675 > #endif
676 >
677 >    return maxCutoffRadius;
678 > }
679 >
680 > void SimInfo::setupCutoff() {
681 >    double rcut_;  //cutoff radius
682 >    double rsw_; //switching radius
683      
684 <    delete (*result).second;
685 <    (*result).second = prop;
686 <      
687 <  }
688 <  else{
684 >    if (fInfo_.SIM_uses_Charges | fInfo_.SIM_uses_Dipoles | fInfo_.SIM_uses_RF) {
685 >        
686 >        if (!globals_->haveRcut()){
687 >            sprintf(painCave.errMsg,
688 >                "SimCreator Warning: No value was set for the cutoffRadius.\n"
689 >                "\tOOPSE will use a default value of 15.0 angstroms"
690 >                "\tfor the cutoffRadius.\n");
691 >            painCave.isFatal = 0;
692 >            simError();
693 >            rcut_ = 15.0;
694 >        } else{
695 >            rcut_ = globals_->getRcut();
696 >        }
697  
698 <    properties[prop->getID()] = prop;
698 >        if (!globals_->haveRsw()){
699 >            sprintf(painCave.errMsg,
700 >                "SimCreator Warning: No value was set for switchingRadius.\n"
701 >                "\tOOPSE will use a default value of\n"
702 >                "\t0.95 * cutoffRadius for the switchingRadius\n");
703 >            painCave.isFatal = 0;
704 >            simError();
705 >            rsw_ = 0.95 * rcut_;
706 >        } else{
707 >            rsw_ = globals_->getRsw();
708 >        }
709  
710 <  }
710 >    } else {
711 >        // if charge, dipole or reaction field is not used and the cutofff radius is not specified in
712 >        //meta-data file, the maximum cutoff radius calculated from forcefiled will be used
713 >        
714 >        if (globals_->haveRcut()) {
715 >            rcut_ = globals_->getRcut();
716 >        } else {
717 >            //set cutoff radius to the maximum cutoff radius based on atom types in the whole system
718 >            rcut_ = calcMaxCutoffRadius();
719 >        }
720 >
721 >        if (globals_->haveRsw()) {
722 >            rsw_  = globals_->getRsw()
723 >        } else {
724 >            rsw_ = rcut_;
725 >        }
726      
727 +    }
728 +        
729 +    double rnblist = rcut_ + 1; // skin of neighbor list
730 +
731 +    //Pass these cutoff radius etc. to fortran. This function should be called once and only once
732 +    notifyFortranCutoffs(&rcut_, &rsw_, &rnblist);
733   }
734  
735 < GenericData* SimInfo::getProperty(const string& propName){
736 <
577 <  map<string, GenericData*>::iterator result;
578 <  
579 <  //string lowerCaseName = ();
580 <  
581 <  result = properties.find(propName);
582 <  
583 <  if(result != properties.end())
584 <    return (*result).second;  
585 <  else  
586 <    return NULL;  
735 > void SimInfo::addProperty(GenericData* genData) {
736 >    properties_.addProperty(genData);  
737   }
738  
739 + void SimInfo::removeProperty(const std::string& propName) {
740 +    properties_.removeProperty(propName);  
741 + }
742  
743 < void SimInfo::getFortranGroupArrays(SimInfo* info,
744 <                                    vector<int>& FglobalGroupMembership,
745 <                                    vector<double>& mfact){
593 <  
594 <  Molecule* myMols;
595 <  Atom** myAtoms;
596 <  int numAtom;
597 <  double mtot;
598 <  int numMol;
599 <  int numCutoffGroups;
600 <  CutoffGroup* myCutoffGroup;
601 <  vector<CutoffGroup*>::iterator iterCutoff;
602 <  Atom* cutoffAtom;
603 <  vector<Atom*>::iterator iterAtom;
604 <  int atomIndex;
605 <  double totalMass;
606 <  
607 <  mfact.clear();
608 <  FglobalGroupMembership.clear();
609 <  
743 > void SimInfo::clearProperties() {
744 >    properties_.clearProperties();
745 > }
746  
747 <  // Fix the silly fortran indexing problem
748 < #ifdef IS_MPI
749 <  numAtom = mpiSim->getNAtomsGlobal();
750 < #else
751 <  numAtom = n_atoms;
752 < #endif
753 <  for (int i = 0; i < numAtom; i++)
618 <    FglobalGroupMembership.push_back(globalGroupMembership[i] + 1);
619 <  
747 > std::vector<std::string> SimInfo::getPropertyNames() {
748 >    return properties_.getPropertyNames();  
749 > }
750 >      
751 > std::vector<GenericData*> SimInfo::getProperties() {
752 >    return properties_.getProperties();
753 > }
754  
755 <  myMols = info->molecules;
756 <  numMol = info->n_mol;
757 <  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)){
755 > GenericData* SimInfo::getPropertyByName(const std::string& propName) {
756 >    return properties_.getPropertyByName(propName);
757 > }
758  
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    }
637  }
759  
760 + std::ostream& operator <<(ostream& o, SimInfo& info) {
761 +
762 +    return o;
763   }
764 +
765 + }//end namespace oopse

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines