ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/group/trunk/OOPSE/libmdtools/SimSetup.cpp
(Generate patch)

Comparing trunk/OOPSE/libmdtools/SimSetup.cpp (file contents):
Revision 407 by mmeineke, Wed Mar 26 20:22:02 2003 UTC vs.
Revision 656 by mmeineke, Tue Jul 29 16:32:37 2003 UTC

# Line 12 | Line 12 | SimSetup::SimSetup(){
12   #include "mpiSimulation.hpp"
13   #endif
14  
15 + // some defines for ensemble and Forcefield  cases
16 +
17 + #define NVE_ENS   0
18 + #define NVT_ENS   1
19 + #define NPTi_ENS  2
20 + #define NPTf_ENS  3
21 + #define NPTim_ENS 4
22 + #define NPTfm_ENS 5
23 +
24 +
25 + #define FF_DUFF 0
26 + #define FF_LJ   1
27 + #define FF_EAM  2
28 +
29   SimSetup::SimSetup(){
30 +  
31 +  isInfoArray = 0;
32 +  nInfo = 1;
33 +  
34    stamps = new MakeStamps();
35    globals = new Globals();
36    
37 +  
38   #ifdef IS_MPI
39    strcpy( checkPointMsg, "SimSetup creation successful" );
40    MPIcheckPoint();
# Line 27 | Line 46 | void SimSetup::parseFile( char* fileName ){
46    delete globals;
47   }
48  
49 + void SimSetup::setSimInfo( SimInfo* the_info, int theNinfo ) {
50 +    info = the_info;
51 +    nInfo = theNinfo;
52 +    isInfoArray = 1;
53 +  }
54 +
55 +
56   void SimSetup::parseFile( char* fileName ){
57  
58   #ifdef IS_MPI
# Line 64 | Line 90 | void SimSetup::createSim( void ){
90  
91   void SimSetup::createSim( void ){
92  
93 <  MakeStamps *the_stamps;
94 <  Globals* the_globals;
95 <  int i, j;
93 >  int i, j, k, globalAtomIndex;
94 >  
95 >  // gather all of the information from the Bass file
96 >  
97 >  gatherInfo();
98  
99 <  // get the stamps and globals;
72 <  the_stamps = stamps;
73 <  the_globals = globals;
99 >  // creation of complex system objects
100  
101 <  // set the easy ones first
76 <  simnfo->target_temp = the_globals->getTargetTemp();
77 <  simnfo->dt = the_globals->getDt();
78 <  simnfo->run_time = the_globals->getRunTime();
101 >  sysObjectsCreation();
102  
103 <  // get the ones we know are there, yet still may need some work.
104 <  n_components = the_globals->getNComponents();
105 <  strcpy( force_field, the_globals->getForceField() );
83 <  strcpy( ensemble, the_globals->getEnsemble() );
84 <  strcpy( simnfo->ensemble, ensemble );
103 >  // check on the post processing info
104 >  
105 >  finalInfoCheck();
106  
107 <  strcpy( simnfo->mixingRule, the_globals->getMixingRule() );
87 <  simnfo->usePBC = the_globals->getPBC();
88 <          
107 >  // initialize the system coordinates
108  
109 +  initSystemCoords();
110 +  
111  
112 <  if( !strcmp( force_field, "TraPPE" ) ) the_ff = new TraPPEFF();
92 <  else if( !strcmp( force_field, "DipoleTest" ) ) the_ff = new DipoleTestFF();
93 <  else if( !strcmp( force_field, "TraPPE_Ex" ) ) the_ff = new TraPPE_ExFF();
94 <  else if( !strcmp( force_field, "LJ" ) ) the_ff = new LJ_FF();
95 <  else{
96 <    sprintf( painCave.errMsg,
97 <             "SimSetup Error. Unrecognized force field -> %s\n",
98 <             force_field );
99 <    painCave.isFatal = 1;
100 <    simError();
101 <  }
112 >  // make the output filenames
113  
114 +  makeOutNames();
115 +  
116 +  // make the integrator
117 +  
118 +  makeIntegrator();
119 +  
120   #ifdef IS_MPI
121 <  strcpy( checkPointMsg, "ForceField creation successful" );
122 <  MPIcheckPoint();
106 < #endif // is_mpi
121 >  mpiSim->mpiRefresh();
122 > #endif
123  
124 <  
124 >  // initialize the Fortran
125  
126 <  // get the components and calculate the tot_nMol and indvidual n_mol
111 <  the_components = the_globals->getComponents();
112 <  components_nmol = new int[n_components];
113 <  comp_stamps = new MoleculeStamp*[n_components];
126 >  initFortran();
127  
115  if( !the_globals->haveNMol() ){
116    // we don't have the total number of molecules, so we assume it is
117    // given in each component
128  
119    tot_nmol = 0;
120    for( i=0; i<n_components; i++ ){
129  
130 <      if( !the_components[i]->haveNMol() ){
123 <        // we have a problem
124 <        sprintf( painCave.errMsg,
125 <                 "SimSetup Error. No global NMol or component NMol"
126 <                 " given. Cannot calculate the number of atoms.\n" );
127 <        painCave.isFatal = 1;
128 <        simError();
129 <      }
130 > }
131  
131      tot_nmol += the_components[i]->getNMol();
132      components_nmol[i] = the_components[i]->getNMol();
133    }
134  }
135  else{
136    sprintf( painCave.errMsg,
137             "SimSetup error.\n"
138             "\tSorry, the ability to specify total"
139             " nMols and then give molfractions in the components\n"
140             "\tis not currently supported."
141             " Please give nMol in the components.\n" );
142    painCave.isFatal = 1;
143    simError();
144    
145    
146    //     tot_nmol = the_globals->getNMol();
147    
148    //   //we have the total number of molecules, now we check for molfractions
149    //     for( i=0; i<n_components; i++ ){
150    
151    //       if( !the_components[i]->haveMolFraction() ){
152    
153    //  if( !the_components[i]->haveNMol() ){
154    //    //we have a problem
155    //    std::cerr << "SimSetup error. Neither molFraction nor "
156    //              << " nMol was given in component
157    
158  }
132  
133 < #ifdef IS_MPI
161 <  strcpy( checkPointMsg, "Have the number of components" );
162 <  MPIcheckPoint();
163 < #endif // is_mpi
133 > void SimSetup::makeMolecules( void ){
134  
135 <  // make an array of molecule stamps that match the components used.
136 <  // also extract the used stamps out into a separate linked list
135 >  int i, j, exI, exJ, tempEx, stampID, atomOffset, excludeOffset;
136 >  molInit molInfo;
137 >  DirectionalAtom* dAtom;
138 >  LinkedAssign* extras;
139 >  LinkedAssign* current_extra;
140 >  AtomStamp* currentAtom;
141 >  BondStamp* currentBond;
142 >  BendStamp* currentBend;
143 >  TorsionStamp* currentTorsion;
144  
145 <  simnfo->nComponents = n_components;
146 <  simnfo->componentsNmol = components_nmol;
147 <  simnfo->compStamps = comp_stamps;
148 <  simnfo->headStamp = new LinkedMolStamp();
145 >  bond_pair* theBonds;
146 >  bend_set* theBends;
147 >  torsion_set* theTorsions;
148 >
149    
150 <  char* id;
174 <  LinkedMolStamp* headStamp = simnfo->headStamp;
175 <  LinkedMolStamp* currentStamp = NULL;
176 <  for( i=0; i<n_components; i++ ){
150 >  //init the forceField paramters
151  
152 <    id = the_components[i]->getType();
179 <    comp_stamps[i] = NULL;
180 <    
181 <    // check to make sure the component isn't already in the list
152 >  the_ff->readParams();
153  
154 <    comp_stamps[i] = headStamp->match( id );
155 <    if( comp_stamps[i] == NULL ){
185 <      
186 <      // extract the component from the list;
187 <      
188 <      currentStamp = the_stamps->extractMolStamp( id );
189 <      if( currentStamp == NULL ){
190 <        sprintf( painCave.errMsg,
191 <                 "SimSetup error: Component \"%s\" was not found in the "
192 <                 "list of declared molecules\n",
193 <                 id );
194 <        painCave.isFatal = 1;
195 <        simError();
196 <      }
197 <      
198 <      headStamp->add( currentStamp );
199 <      comp_stamps[i] = headStamp->match( id );
200 <    }
201 <  }
154 >  
155 >  // init the atoms
156  
157 < #ifdef IS_MPI
204 <  strcpy( checkPointMsg, "Component stamps successfully extracted\n" );
205 <  MPIcheckPoint();
206 < #endif // is_mpi
157 >  double ux, uy, uz, u, uSqr;
158    
159 +  atomOffset = 0;
160 +  excludeOffset = 0;
161 +  for(i=0; i<info->n_mol; i++){
162 +    
163 +    stampID = the_molecules[i].getStampID();
164  
165 +    molInfo.nAtoms    = comp_stamps[stampID]->getNAtoms();
166 +    molInfo.nBonds    = comp_stamps[stampID]->getNBonds();
167 +    molInfo.nBends    = comp_stamps[stampID]->getNBends();
168 +    molInfo.nTorsions = comp_stamps[stampID]->getNTorsions();
169 +    molInfo.nExcludes = molInfo.nBonds + molInfo.nBends + molInfo.nTorsions;
170  
171 +    molInfo.myAtoms = &the_atoms[atomOffset];
172 +    molInfo.myExcludes = &the_excludes[excludeOffset];
173 +    molInfo.myBonds = new Bond*[molInfo.nBonds];
174 +    molInfo.myBends = new Bend*[molInfo.nBends];
175 +    molInfo.myTorsions = new Torsion*[molInfo.nTorsions];
176  
177 <  // caclulate the number of atoms, bonds, bends and torsions
178 <
179 <  tot_atoms = 0;
214 <  tot_bonds = 0;
215 <  tot_bends = 0;
216 <  tot_torsions = 0;
217 <  for( i=0; i<n_components; i++ ){
177 >    theBonds = new bond_pair[molInfo.nBonds];
178 >    theBends = new bend_set[molInfo.nBends];
179 >    theTorsions = new torsion_set[molInfo.nTorsions];
180      
181 <    tot_atoms +=    components_nmol[i] * comp_stamps[i]->getNAtoms();
182 <    tot_bonds +=    components_nmol[i] * comp_stamps[i]->getNBonds();
183 <    tot_bends +=    components_nmol[i] * comp_stamps[i]->getNBends();
184 <    tot_torsions += components_nmol[i] * comp_stamps[i]->getNTorsions();
185 <  }
181 >    // make the Atoms
182 >    
183 >    for(j=0; j<molInfo.nAtoms; j++){
184 >      
185 >      currentAtom = comp_stamps[stampID]->getAtom( j );
186 >      if( currentAtom->haveOrientation() ){
187 >        
188 >        dAtom = new DirectionalAtom(j + atomOffset);
189 >        info->n_oriented++;
190 >        molInfo.myAtoms[j] = dAtom;
191 >        
192 >        ux = currentAtom->getOrntX();
193 >        uy = currentAtom->getOrntY();
194 >        uz = currentAtom->getOrntZ();
195 >        
196 >        uSqr = (ux * ux) + (uy * uy) + (uz * uz);
197 >        
198 >        u = sqrt( uSqr );
199 >        ux = ux / u;
200 >        uy = uy / u;
201 >        uz = uz / u;
202 >        
203 >        dAtom->setSUx( ux );
204 >        dAtom->setSUy( uy );
205 >        dAtom->setSUz( uz );
206 >      }
207 >      else{
208 >        molInfo.myAtoms[j] = new GeneralAtom(j + atomOffset);
209 >      }
210 >      molInfo.myAtoms[j]->setType( currentAtom->getType() );
211 >    
212 > #ifdef IS_MPI
213 >      
214 >      molInfo.myAtoms[j]->setGlobalIndex( globalIndex[j+atomOffset] );
215 >      
216 > #endif // is_mpi
217 >    }
218 >    
219 >    // make the bonds
220 >    for(j=0; j<molInfo.nBonds; j++){
221 >      
222 >      currentBond = comp_stamps[stampID]->getBond( j );
223 >      theBonds[j].a = currentBond->getA() + atomOffset;
224 >      theBonds[j].b = currentBond->getB() + atomOffset;
225  
226 <  tot_SRI = tot_bonds + tot_bends + tot_torsions;
226 >      exI = theBonds[j].a;
227 >      exJ = theBonds[j].b;
228  
229 <  simnfo->n_atoms = tot_atoms;
230 <  simnfo->n_bonds = tot_bonds;
231 <  simnfo->n_bends = tot_bends;
232 <  simnfo->n_torsions = tot_torsions;
233 <  simnfo->n_SRI = tot_SRI;
234 <  simnfo->n_mol = tot_nmol;
233 <
234 <  
229 >      // exclude_I must always be the smaller of the pair
230 >      if( exI > exJ ){
231 >        tempEx = exI;
232 >        exI = exJ;
233 >        exJ = tempEx;
234 >      }
235   #ifdef IS_MPI
236 +      tempEx = exI;
237 +      exI = the_atoms[tempEx]->getGlobalIndex() + 1;
238 +      tempEx = exJ;
239 +      exJ = the_atoms[tempEx]->getGlobalIndex() + 1;
240 +      
241 +      the_excludes[j+excludeOffset]->setPair( exI, exJ );
242 + #else  // isn't MPI
243  
244 <  // divide the molecules among processors here.
245 <  
246 <  mpiSim = new mpiSimulation( simnfo );
247 <  
241 <  
244 >      the_excludes[j+excludeOffset]->setPair( (exI+1), (exJ+1) );
245 > #endif  //is_mpi
246 >    }
247 >    excludeOffset += molInfo.nBonds;
248  
249 <  globalIndex = mpiSim->divideLabor();
249 >    //make the bends
250 >    for(j=0; j<molInfo.nBends; j++){
251 >      
252 >      currentBend = comp_stamps[stampID]->getBend( j );
253 >      theBends[j].a = currentBend->getA() + atomOffset;
254 >      theBends[j].b = currentBend->getB() + atomOffset;
255 >      theBends[j].c = currentBend->getC() + atomOffset;
256 >          
257 >      if( currentBend->haveExtras() ){
258 >            
259 >        extras = currentBend->getExtras();
260 >        current_extra = extras;
261 >            
262 >        while( current_extra != NULL ){
263 >          if( !strcmp( current_extra->getlhs(), "ghostVectorSource" )){
264 >                
265 >            switch( current_extra->getType() ){
266 >              
267 >            case 0:
268 >              theBends[j].ghost =
269 >                current_extra->getInt() + atomOffset;
270 >              theBends[j].isGhost = 1;
271 >              break;
272 >                  
273 >            case 1:
274 >              theBends[j].ghost =
275 >                (int)current_extra->getDouble() + atomOffset;
276 >              theBends[j].isGhost = 1;
277 >              break;
278 >              
279 >            default:
280 >              sprintf( painCave.errMsg,
281 >                       "SimSetup Error: ghostVectorSource was neither a "
282 >                       "double nor an int.\n"
283 >                       "-->Bend[%d] in %s\n",
284 >                       j, comp_stamps[stampID]->getID() );
285 >              painCave.isFatal = 1;
286 >              simError();
287 >            }
288 >          }
289 >          
290 >          else{
291 >            
292 >            sprintf( painCave.errMsg,
293 >                     "SimSetup Error: unhandled bend assignment:\n"
294 >                     "    -->%s in Bend[%d] in %s\n",
295 >                     current_extra->getlhs(),
296 >                     j, comp_stamps[stampID]->getID() );
297 >            painCave.isFatal = 1;
298 >            simError();
299 >          }
300 >          
301 >          current_extra = current_extra->getNext();
302 >        }
303 >      }
304 >          
305 >      if( !theBends[j].isGhost ){
306 >            
307 >        exI = theBends[j].a;
308 >        exJ = theBends[j].c;
309 >      }
310 >      else{
311 >        
312 >        exI = theBends[j].a;
313 >        exJ = theBends[j].b;
314 >      }
315 >      
316 >      // exclude_I must always be the smaller of the pair
317 >      if( exI > exJ ){
318 >        tempEx = exI;
319 >        exI = exJ;
320 >        exJ = tempEx;
321 >      }
322 > #ifdef IS_MPI
323 >      tempEx = exI;
324 >      exI = the_atoms[tempEx]->getGlobalIndex() + 1;
325 >      tempEx = exJ;
326 >      exJ = the_atoms[tempEx]->getGlobalIndex() + 1;
327 >      
328 >      the_excludes[j+excludeOffset]->setPair( exI, exJ );
329 > #else  // isn't MPI
330 >      the_excludes[j+excludeOffset]->setPair( (exI+1), (exJ+1) );
331 > #endif  //is_mpi
332 >    }
333 >    excludeOffset += molInfo.nBends;
334  
335 +    for(j=0; j<molInfo.nTorsions; j++){
336 +      
337 +      currentTorsion = comp_stamps[stampID]->getTorsion( j );
338 +      theTorsions[j].a = currentTorsion->getA() + atomOffset;
339 +      theTorsions[j].b = currentTorsion->getB() + atomOffset;
340 +      theTorsions[j].c = currentTorsion->getC() + atomOffset;
341 +      theTorsions[j].d = currentTorsion->getD() + atomOffset;
342 +      
343 +      exI = theTorsions[j].a;
344 +      exJ = theTorsions[j].d;
345  
346 <
347 <  // set up the local variables
348 <  
349 <  int localMol, allMol;
350 <  int local_atoms, local_bonds, local_bends, local_torsions, local_SRI;
351 <  
352 <  allMol = 0;
353 <  localMol = 0;
354 <  local_atoms = 0;
355 <  local_bonds = 0;
356 <  local_bends = 0;
257 <  local_torsions = 0;
258 <  for( i=0; i<n_components; i++ ){
259 <
260 <    for( j=0; j<components_nmol[i]; j++ ){
346 >      // exclude_I must always be the smaller of the pair
347 >      if( exI > exJ ){
348 >        tempEx = exI;
349 >        exI = exJ;
350 >        exJ = tempEx;
351 >      }
352 > #ifdef IS_MPI
353 >      tempEx = exI;
354 >      exI = the_atoms[tempEx]->getGlobalIndex() + 1;
355 >      tempEx = exJ;
356 >      exJ = the_atoms[tempEx]->getGlobalIndex() + 1;
357        
358 <      if( mpiSim->getMyMolStart() <= allMol &&
359 <          allMol <= mpiSim->getMyMolEnd() ){
360 <        
361 <        local_atoms +=    comp_stamps[i]->getNAtoms();
266 <        local_bonds +=    comp_stamps[i]->getNBonds();
267 <        local_bends +=    comp_stamps[i]->getNBends();
268 <        local_torsions += comp_stamps[i]->getNTorsions();
269 <        localMol++;
270 <      }      
271 <      allMol++;
358 >      the_excludes[j+excludeOffset]->setPair( exI, exJ );
359 > #else  // isn't MPI
360 >      the_excludes[j+excludeOffset]->setPair( (exI+1), (exJ+1) );
361 > #endif  //is_mpi
362      }
363 <  }
274 <  local_SRI = local_bonds + local_bends + local_torsions;
275 <  
363 >    excludeOffset += molInfo.nTorsions;
364  
365 <  simnfo->n_atoms = mpiSim->getMyNlocal();  
366 <  
279 <  if( local_atoms != simnfo->n_atoms ){
280 <    sprintf( painCave.errMsg,
281 <             "SimSetup error: mpiSim's localAtom (%d) and SimSetup's"
282 <             " localAtom (%d) are note equal.\n",
283 <             simnfo->n_atoms,
284 <             local_atoms );
285 <    painCave.isFatal = 1;
286 <    simError();
287 <  }
365 >    
366 >    // send the arrays off to the forceField for init.
367  
368 <  simnfo->n_bonds = local_bonds;
369 <  simnfo->n_bends = local_bends;
370 <  simnfo->n_torsions = local_torsions;
371 <  simnfo->n_SRI = local_SRI;
293 <  simnfo->n_mol = localMol;
368 >    the_ff->initializeAtoms( molInfo.nAtoms, molInfo.myAtoms );
369 >    the_ff->initializeBonds( molInfo.nBonds, molInfo.myBonds, theBonds );
370 >    the_ff->initializeBends( molInfo.nBends, molInfo.myBends, theBends );
371 >    the_ff->initializeTorsions( molInfo.nTorsions, molInfo.myTorsions, theTorsions );
372  
373 <  strcpy( checkPointMsg, "Passed nlocal consistency check." );
373 >
374 >    the_molecules[i].initialize( molInfo );
375 >
376 >
377 >    atomOffset += molInfo.nAtoms;
378 >    delete[] theBonds;
379 >    delete[] theBends;
380 >    delete[] theTorsions;
381 >  }
382 >
383 > #ifdef IS_MPI
384 >  sprintf( checkPointMsg, "all molecules initialized succesfully" );
385    MPIcheckPoint();
297  
298  
386   #endif // is_mpi
300  
387  
388 <  // create the atom and short range interaction arrays
388 >  // clean up the forcefield
389 >  the_ff->calcRcut();
390 >  the_ff->cleanMe();
391  
392 <  Atom::createArrays(simnfo->n_atoms);
305 <  the_atoms = new Atom*[simnfo->n_atoms];
306 <  the_molecules = new Molecule[simnfo->n_mol];
392 > }
393  
394 + void SimSetup::initFromBass( void ){
395  
396 <  if( simnfo->n_SRI ){
397 <    the_sris = new SRI*[simnfo->n_SRI];
398 <    the_excludes = new int[2 * simnfo->n_SRI];
399 <    simnfo->globalExcludes = new int;
400 <    simnfo->n_exclude = tot_SRI;
396 >  int i, j, k;
397 >  int n_cells;
398 >  double cellx, celly, cellz;
399 >  double temp1, temp2, temp3;
400 >  int n_per_extra;
401 >  int n_extra;
402 >  int have_extra, done;
403 >
404 >  temp1 = (double)tot_nmol / 4.0;
405 >  temp2 = pow( temp1, ( 1.0 / 3.0 ) );
406 >  temp3 = ceil( temp2 );
407 >
408 >  have_extra =0;
409 >  if( temp2 < temp3 ){ // we have a non-complete lattice
410 >    have_extra =1;
411 >
412 >    n_cells = (int)temp3 - 1;
413 >    cellx = info->boxL[0] / temp3;
414 >    celly = info->boxL[1] / temp3;
415 >    cellz = info->boxL[2] / temp3;
416 >    n_extra = tot_nmol - ( 4 * n_cells * n_cells * n_cells );
417 >    temp1 = ((double)n_extra) / ( pow( temp3, 3.0 ) - pow( n_cells, 3.0 ) );
418 >    n_per_extra = (int)ceil( temp1 );
419 >
420 >    if( n_per_extra > 4){
421 >      sprintf( painCave.errMsg,
422 >               "SimSetup error. There has been an error in constructing"
423 >               " the non-complete lattice.\n" );
424 >      painCave.isFatal = 1;
425 >      simError();
426 >    }
427    }
428    else{
429 <    
430 <    the_excludes = new int[2];
431 <    the_excludes[0] = 0;
432 <    the_excludes[1] = 0;
433 <    simnfo->globalExcludes = new int;
321 <    simnfo->globalExcludes[0] = 0;
429 >    n_cells = (int)temp3;
430 >    cellx = info->boxL[0] / temp3;
431 >    celly = info->boxL[1] / temp3;
432 >    cellz = info->boxL[2] / temp3;
433 >  }
434  
435 <    simnfo->n_exclude = 1;
435 >  current_mol = 0;
436 >  current_comp_mol = 0;
437 >  current_comp = 0;
438 >  current_atom_ndx = 0;
439 >
440 >  for( i=0; i < n_cells ; i++ ){
441 >    for( j=0; j < n_cells; j++ ){
442 >      for( k=0; k < n_cells; k++ ){
443 >
444 >        makeElement( i * cellx,
445 >                     j * celly,
446 >                     k * cellz );
447 >
448 >        makeElement( i * cellx + 0.5 * cellx,
449 >                     j * celly + 0.5 * celly,
450 >                     k * cellz );
451 >
452 >        makeElement( i * cellx,
453 >                     j * celly + 0.5 * celly,
454 >                     k * cellz + 0.5 * cellz );
455 >
456 >        makeElement( i * cellx + 0.5 * cellx,
457 >                     j * celly,
458 >                     k * cellz + 0.5 * cellz );
459 >      }
460 >    }
461    }
462  
463 <  // set the arrays into the SimInfo object
463 >  if( have_extra ){
464 >    done = 0;
465  
466 <  simnfo->atoms = the_atoms;
467 <  simnfo->sr_interactions = the_sris;
468 <  simnfo->nGlobalExcludes = 0;
469 <  simnfo->excludes = the_excludes;
466 >    int start_ndx;
467 >    for( i=0; i < (n_cells+1) && !done; i++ ){
468 >      for( j=0; j < (n_cells+1) && !done; j++ ){
469 >
470 >        if( i < n_cells ){
471  
472 +          if( j < n_cells ){
473 +            start_ndx = n_cells;
474 +          }
475 +          else start_ndx = 0;
476 +        }
477 +        else start_ndx = 0;
478  
479 <  // get some of the tricky things that may still be in the globals
479 >        for( k=start_ndx; k < (n_cells+1) && !done; k++ ){
480  
481 +          makeElement( i * cellx,
482 +                       j * celly,
483 +                       k * cellz );
484 +          done = ( current_mol >= tot_nmol );
485 +
486 +          if( !done && n_per_extra > 1 ){
487 +            makeElement( i * cellx + 0.5 * cellx,
488 +                         j * celly + 0.5 * celly,
489 +                         k * cellz );
490 +            done = ( current_mol >= tot_nmol );
491 +          }
492 +
493 +          if( !done && n_per_extra > 2){
494 +            makeElement( i * cellx,
495 +                         j * celly + 0.5 * celly,
496 +                         k * cellz + 0.5 * cellz );
497 +            done = ( current_mol >= tot_nmol );
498 +          }
499 +
500 +          if( !done && n_per_extra > 3){
501 +            makeElement( i * cellx + 0.5 * cellx,
502 +                         j * celly,
503 +                         k * cellz + 0.5 * cellz );
504 +            done = ( current_mol >= tot_nmol );
505 +          }
506 +        }
507 +      }
508 +    }
509 +  }
510 +
511 +
512 +  for( i=0; i<info->n_atoms; i++ ){
513 +    info->atoms[i]->set_vx( 0.0 );
514 +    info->atoms[i]->set_vy( 0.0 );
515 +    info->atoms[i]->set_vz( 0.0 );
516 +  }
517 + }
518 +
519 + void SimSetup::makeElement( double x, double y, double z ){
520 +
521 +  int k;
522 +  AtomStamp* current_atom;
523 +  DirectionalAtom* dAtom;
524 +  double rotMat[3][3];
525 +
526 +  for( k=0; k<comp_stamps[current_comp]->getNAtoms(); k++ ){
527 +
528 +    current_atom = comp_stamps[current_comp]->getAtom( k );
529 +    if( !current_atom->havePosition() ){
530 +      sprintf( painCave.errMsg,
531 +               "SimSetup:initFromBass error.\n"
532 +               "\tComponent %s, atom %s does not have a position specified.\n"
533 +               "\tThe initialization routine is unable to give a start"
534 +               " position.\n",
535 +               comp_stamps[current_comp]->getID(),
536 +               current_atom->getType() );
537 +      painCave.isFatal = 1;
538 +      simError();
539 +    }
540 +
541 +    the_atoms[current_atom_ndx]->setX( x + current_atom->getPosX() );
542 +    the_atoms[current_atom_ndx]->setY( y + current_atom->getPosY() );
543 +    the_atoms[current_atom_ndx]->setZ( z + current_atom->getPosZ() );
544 +
545 +    if( the_atoms[current_atom_ndx]->isDirectional() ){
546 +
547 +      dAtom = (DirectionalAtom *)the_atoms[current_atom_ndx];
548 +
549 +      rotMat[0][0] = 1.0;
550 +      rotMat[0][1] = 0.0;
551 +      rotMat[0][2] = 0.0;
552 +
553 +      rotMat[1][0] = 0.0;
554 +      rotMat[1][1] = 1.0;
555 +      rotMat[1][2] = 0.0;
556 +
557 +      rotMat[2][0] = 0.0;
558 +      rotMat[2][1] = 0.0;
559 +      rotMat[2][2] = 1.0;
560 +
561 +      dAtom->setA( rotMat );
562 +    }
563 +
564 +    current_atom_ndx++;
565 +  }
566 +
567 +  current_mol++;
568 +  current_comp_mol++;
569 +
570 +  if( current_comp_mol >= components_nmol[current_comp] ){
571 +
572 +    current_comp_mol = 0;
573 +    current_comp++;
574 +  }
575 + }
576 +
577 +
578 + void SimSetup::gatherInfo( void ){
579 +  int i,j,k;
580 +
581 +  ensembleCase = -1;
582 +  ffCase = -1;
583 +
584 +  // get the stamps and globals;
585 +  stamps = stamps;
586 +  globals = globals;
587 +
588 +  // set the easy ones first
589 +  info->target_temp = globals->getTargetTemp();
590 +  info->dt = globals->getDt();
591 +  info->run_time = globals->getRunTime();
592 +  n_components = globals->getNComponents();
593 +
594 +
595 +  // get the forceField
596 +
597 +  strcpy( force_field, globals->getForceField() );
598 +
599 +  if( !strcasecmp( force_field, "DUFF" )) ffCase = FF_DUFF;
600 +  else if( !strcasecmp( force_field, "LJ" )) ffCase = FF_LJ;
601 +  else if( !strcasecmp( force_field, "EAM" )) ffCase = FF_EAM;
602 +  else{
603 +    sprintf( painCave.errMsg,
604 +             "SimSetup Error. Unrecognized force field -> %s\n",
605 +             force_field );
606 +    painCave.isFatal = 1;
607 +    simError();
608 +  }
609 +
610 +  // get the ensemble
611 +
612 +  strcpy( ensemble, globals->getEnsemble() );
613 +
614 +  if( !strcasecmp( ensemble, "NVE" ))      ensembleCase = NVE_ENS;
615 +  else if( !strcasecmp( ensemble, "NVT" )) ensembleCase = NVT_ENS;
616 +  else if( !strcasecmp( ensemble, "NPTi" ) || !strcasecmp( ensemble, "NPT") )
617 +    ensembleCase = NPTi_ENS;
618 +  else if( !strcasecmp( ensemble, "NPTf" )) ensembleCase = NPTf_ENS;
619 +  else if( !strcasecmp( ensemble, "NPTim" )) ensembleCase = NPTim_ENS;
620 +  else if( !strcasecmp( ensemble, "NPTfm" )) ensembleCase = NPTfm_ENS;
621 +  else{
622 +    sprintf( painCave.errMsg,
623 +             "SimSetup Warning. Unrecognized Ensemble -> %s, "
624 +             "reverting to NVE for this simulation.\n",
625 +             ensemble );
626 +    painCave.isFatal = 0;
627 +    simError();
628 +    strcpy( ensemble, "NVE" );
629 +    ensembleCase = NVE_ENS;
630 +  }  
631 +  strcpy( info->ensemble, ensemble );
632 +
633 +  // get the mixing rule
634 +
635 +  strcpy( info->mixingRule, globals->getMixingRule() );
636 +  info->usePBC = globals->getPBC();
637 +        
638    
639 <  if( the_globals->haveBox() ){
640 <    simnfo->box_x = the_globals->getBox();
641 <    simnfo->box_y = the_globals->getBox();
642 <    simnfo->box_z = the_globals->getBox();
639 >  // get the components and calculate the tot_nMol and indvidual n_mol
640 >
641 >  the_components = globals->getComponents();
642 >  components_nmol = new int[n_components];
643 >
644 >
645 >  if( !globals->haveNMol() ){
646 >    // we don't have the total number of molecules, so we assume it is
647 >    // given in each component
648 >
649 >    tot_nmol = 0;
650 >    for( i=0; i<n_components; i++ ){
651 >
652 >      if( !the_components[i]->haveNMol() ){
653 >        // we have a problem
654 >        sprintf( painCave.errMsg,
655 >                 "SimSetup Error. No global NMol or component NMol"
656 >                 " given. Cannot calculate the number of atoms.\n" );
657 >        painCave.isFatal = 1;
658 >        simError();
659 >      }
660 >
661 >      tot_nmol += the_components[i]->getNMol();
662 >      components_nmol[i] = the_components[i]->getNMol();
663 >    }
664    }
665 <  else if( the_globals->haveDensity() ){
665 >  else{
666 >    sprintf( painCave.errMsg,
667 >             "SimSetup error.\n"
668 >             "\tSorry, the ability to specify total"
669 >             " nMols and then give molfractions in the components\n"
670 >             "\tis not currently supported."
671 >             " Please give nMol in the components.\n" );
672 >    painCave.isFatal = 1;
673 >    simError();
674 >  }
675  
676 +  // set the status, sample, and thermal kick times
677 +  
678 +  if( globals->haveSampleTime() ){
679 +    info->sampleTime = globals->getSampleTime();
680 +    info->statusTime = info->sampleTime;
681 +    info->thermalTime = info->sampleTime;
682 +  }
683 +  else{
684 +    info->sampleTime = globals->getRunTime();
685 +    info->statusTime = info->sampleTime;
686 +    info->thermalTime = info->sampleTime;
687 +  }
688 +
689 +  if( globals->haveStatusTime() ){
690 +    info->statusTime = globals->getStatusTime();
691 +  }
692 +
693 +  if( globals->haveThermalTime() ){
694 +    info->thermalTime = globals->getThermalTime();
695 +  }
696 +
697 +  // check for the temperature set flag
698 +
699 +  if( globals->haveTempSet() ) info->setTemp = globals->getTempSet();
700 +
701 +  // get some of the tricky things that may still be in the globals
702 +
703 +  double boxVector[3];
704 +  if( globals->haveBox() ){
705 +    boxVector[0] = globals->getBox();
706 +    boxVector[1] = globals->getBox();
707 +    boxVector[2] = globals->getBox();
708 +    
709 +    info->setBox( boxVector );
710 +  }
711 +  else if( globals->haveDensity() ){
712 +
713      double vol;
714 <    vol = (double)tot_nmol / the_globals->getDensity();
715 <    simnfo->box_x = pow( vol, ( 1.0 / 3.0 ) );
716 <    simnfo->box_y = simnfo->box_x;
717 <    simnfo->box_z = simnfo->box_x;
714 >    vol = (double)tot_nmol / globals->getDensity();
715 >     boxVector[0] = pow( vol, ( 1.0 / 3.0 ) );
716 >     boxVector[1] = boxVector[0];
717 >     boxVector[2] = boxVector[0];
718 >
719 >    info->setBox( boxVector );
720    }
721    else{
722 <    if( !the_globals->haveBoxX() ){
722 >    if( !globals->haveBoxX() ){
723        sprintf( painCave.errMsg,
724                 "SimSetup error, no periodic BoxX size given.\n" );
725        painCave.isFatal = 1;
726        simError();
727      }
728 <    simnfo->box_x = the_globals->getBoxX();
728 >    boxVector[0] = globals->getBoxX();
729  
730 <    if( !the_globals->haveBoxY() ){
730 >    if( !globals->haveBoxY() ){
731        sprintf( painCave.errMsg,
732                 "SimSetup error, no periodic BoxY size given.\n" );
733        painCave.isFatal = 1;
734        simError();
735      }
736 <    simnfo->box_y = the_globals->getBoxY();
736 >    boxVector[1] = globals->getBoxY();
737  
738 <    if( !the_globals->haveBoxZ() ){
738 >    if( !globals->haveBoxZ() ){
739        sprintf( painCave.errMsg,
740                 "SimSetup error, no periodic BoxZ size given.\n" );
741        painCave.isFatal = 1;
742        simError();
743      }
744 <    simnfo->box_z = the_globals->getBoxZ();
744 >    boxVector[2] = globals->getBoxZ();
745 >
746 >    info->setBox( boxVector );
747    }
748  
749 +
750 +    
751   #ifdef IS_MPI
752 <  strcpy( checkPointMsg, "Box size set up" );
752 >  strcpy( checkPointMsg, "Succesfully gathered all information from Bass\n" );
753    MPIcheckPoint();
754   #endif // is_mpi
755  
756 + }
757  
382  // initialize the arrays
758  
759 <  the_ff->setSimInfo( simnfo );
759 > void SimSetup::finalInfoCheck( void ){
760 >  int index;
761 >  int usesDipoles;
762 >  
763  
764 <  makeAtoms();
387 <  simnfo->identArray = new int[simnfo->n_atoms];
388 <  for(i=0; i<simnfo->n_atoms; i++){
389 <    simnfo->identArray[i] = the_atoms[i]->getIdent();
390 <  }
764 >  // check electrostatic parameters
765    
766 <  if( tot_bonds ){
767 <    makeBonds();
766 >  index = 0;
767 >  usesDipoles = 0;
768 >  while( (index < info->n_atoms) && !usesDipoles ){
769 >    usesDipoles = ((info->atoms)[index])->hasDipole();
770 >    index++;
771    }
772 +  
773 + #ifdef IS_MPI
774 +  int myUse = usesDipoles;
775 +  MPI_Allreduce( &myUse, &usesDipoles, 1, MPI_INT, MPI_LOR, MPI_COMM_WORLD );
776 + #endif //is_mpi
777  
778 <  if( tot_bends ){
397 <    makeBends();
398 <  }
778 >  double theEcr, theEst;
779  
780 <  if( tot_torsions ){
781 <    makeTorsions();
782 <  }
783 <
404 <
405 <  if (the_globals->getUseRF() ) {
406 <    simnfo->useReactionField = 1;
407 <  
408 <    if( !the_globals->haveECR() ){
780 >  if (globals->getUseRF() ) {
781 >    info->useReactionField = 1;
782 >    
783 >    if( !globals->haveECR() ){
784        sprintf( painCave.errMsg,
785                 "SimSetup Warning: using default value of 1/2 the smallest "
786                 "box length for the electrostaticCutoffRadius.\n"
# Line 413 | Line 788 | void SimSetup::createSim( void ){
788        painCave.isFatal = 0;
789        simError();
790        double smallest;
791 <      smallest = simnfo->box_x;
792 <      if (simnfo->box_y <= smallest) smallest = simnfo->box_y;
793 <      if (simnfo->box_z <= smallest) smallest = simnfo->box_z;
794 <      simnfo->ecr = 0.5 * smallest;
791 >      smallest = info->boxL[0];
792 >      if (info->boxL[1] <= smallest) smallest = info->boxL[1];
793 >      if (info->boxL[2] <= smallest) smallest = info->boxL[2];
794 >      theEcr = 0.5 * smallest;
795      } else {
796 <      simnfo->ecr        = the_globals->getECR();
796 >      theEcr = globals->getECR();
797      }
798  
799 <    if( !the_globals->haveEST() ){
799 >    if( !globals->haveEST() ){
800        sprintf( painCave.errMsg,
801                 "SimSetup Warning: using default value of 0.05 * the "
802                 "electrostaticCutoffRadius for the electrostaticSkinThickness\n"
803                 );
804        painCave.isFatal = 0;
805        simError();
806 <      simnfo->est = 0.05 * simnfo->ecr;
806 >      theEst = 0.05 * theEcr;
807      } else {
808 <      simnfo->est        = the_globals->getEST();
808 >      theEst= globals->getEST();
809      }
810 +
811 +    info->setEcr( theEcr, theEst );
812      
813 <    if(!the_globals->haveDielectric() ){
813 >    if(!globals->haveDielectric() ){
814        sprintf( painCave.errMsg,
815                 "SimSetup Error: You are trying to use Reaction Field without"
816                 "setting a dielectric constant!\n"
# Line 441 | Line 818 | void SimSetup::createSim( void ){
818        painCave.isFatal = 1;
819        simError();
820      }
821 <    simnfo->dielectric = the_globals->getDielectric();  
822 <  } else {
823 <    if (simnfo->n_dipoles) {
821 >    info->dielectric = globals->getDielectric();  
822 >  }
823 >  else {
824 >    if (usesDipoles) {
825        
826 <      if( !the_globals->haveECR() ){
827 <        sprintf( painCave.errMsg,
828 <                 "SimSetup Warning: using default value of 1/2 the smallest"
829 <                 "box length for the electrostaticCutoffRadius.\n"
830 <                 "I hope you have a very fast processor!\n");
831 <        painCave.isFatal = 0;
832 <        simError();
833 <        double smallest;
834 <        smallest = simnfo->box_x;
835 <        if (simnfo->box_y <= smallest) smallest = simnfo->box_y;
836 <        if (simnfo->box_z <= smallest) smallest = simnfo->box_z;
837 <        simnfo->ecr = 0.5 * smallest;
826 >      if( !globals->haveECR() ){
827 >        sprintf( painCave.errMsg,
828 >                 "SimSetup Warning: using default value of 1/2 the smallest "
829 >                 "box length for the electrostaticCutoffRadius.\n"
830 >                 "I hope you have a very fast processor!\n");
831 >        painCave.isFatal = 0;
832 >        simError();
833 >        double smallest;
834 >        smallest = info->boxL[0];
835 >        if (info->boxL[1] <= smallest) smallest = info->boxL[1];
836 >        if (info->boxL[2] <= smallest) smallest = info->boxL[2];
837 >        theEcr = 0.5 * smallest;
838        } else {
839 <        simnfo->ecr        = the_globals->getECR();
839 >        theEcr = globals->getECR();
840        }
841        
842 <      if( !the_globals->haveEST() ){
843 <        sprintf( painCave.errMsg,
844 <                 "SimSetup Warning: using default value of 5% of the"
845 <                 "electrostaticCutoffRadius for the "
846 <                 "electrostaticSkinThickness\n"
847 <                 );
848 <        painCave.isFatal = 0;
849 <        simError();
850 <        simnfo->est = 0.05 * simnfo->ecr;
842 >      if( !globals->haveEST() ){
843 >        sprintf( painCave.errMsg,
844 >                 "SimSetup Warning: using default value of 0.05 * the "
845 >                 "electrostaticCutoffRadius for the "
846 >                 "electrostaticSkinThickness\n"
847 >                 );
848 >        painCave.isFatal = 0;
849 >        simError();
850 >        theEst = 0.05 * theEcr;
851        } else {
852 <        simnfo->est        = the_globals->getEST();
852 >        theEst= globals->getEST();
853        }
854 +
855 +      info->setEcr( theEcr, theEst );
856      }
857    }  
858  
859   #ifdef IS_MPI
860 <  strcpy( checkPointMsg, "electrostatic parameters check out" );
860 >  strcpy( checkPointMsg, "post processing checks out" );
861    MPIcheckPoint();
862   #endif // is_mpi
863  
864 < if( the_globals->haveInitialConfig() ){
864 > }
865 >
866 > void SimSetup::initSystemCoords( void ){
867 >
868 > if( globals->haveInitialConfig() ){
869  
870       InitializeFromFile* fileInit;
871   #ifdef IS_MPI // is_mpi
872       if( worldRank == 0 ){
873   #endif //is_mpi
874 <   fileInit = new InitializeFromFile( the_globals->getInitialConfig() );
874 >   fileInit = new InitializeFromFile( globals->getInitialConfig() );
875   #ifdef IS_MPI
876       }else fileInit = new InitializeFromFile( NULL );
877   #endif
878 <   fileInit->read_xyz( simnfo ); // default velocities on
878 >   fileInit->readInit( info ); // default velocities on
879  
880     delete fileInit;
881   }
# Line 519 | Line 903 | void SimSetup::createSim( void ){
903    MPIcheckPoint();
904   #endif // is_mpi
905  
906 + }
907  
523  
524
525  
908  
909 <  
909 > void SimSetup::makeOutNames( void ){
910 >
911   #ifdef IS_MPI
912    if( worldRank == 0 ){
913   #endif // is_mpi
914      
915 <    if( the_globals->haveFinalConfig() ){
916 <      strcpy( simnfo->finalName, the_globals->getFinalConfig() );
915 >    if( globals->haveFinalConfig() ){
916 >      strcpy( info->finalName, globals->getFinalConfig() );
917      }
918      else{
919 <      strcpy( simnfo->finalName, inFileName );
919 >      strcpy( info->finalName, inFileName );
920        char* endTest;
921 <      int nameLength = strlen( simnfo->finalName );
922 <      endTest = &(simnfo->finalName[nameLength - 5]);
921 >      int nameLength = strlen( info->finalName );
922 >      endTest = &(info->finalName[nameLength - 5]);
923        if( !strcmp( endTest, ".bass" ) ){
924          strcpy( endTest, ".eor" );
925        }
# Line 544 | Line 927 | void SimSetup::createSim( void ){
927          strcpy( endTest, ".eor" );
928        }
929        else{
930 <        endTest = &(simnfo->finalName[nameLength - 4]);
930 >        endTest = &(info->finalName[nameLength - 4]);
931          if( !strcmp( endTest, ".bss" ) ){
932            strcpy( endTest, ".eor" );
933          }
# Line 552 | Line 935 | void SimSetup::createSim( void ){
935            strcpy( endTest, ".eor" );
936          }
937          else{
938 <          strcat( simnfo->finalName, ".eor" );
938 >          strcat( info->finalName, ".eor" );
939          }
940        }
941      }
942      
943      // make the sample and status out names
944      
945 <    strcpy( simnfo->sampleName, inFileName );
945 >    strcpy( info->sampleName, inFileName );
946      char* endTest;
947 <    int nameLength = strlen( simnfo->sampleName );
948 <    endTest = &(simnfo->sampleName[nameLength - 5]);
947 >    int nameLength = strlen( info->sampleName );
948 >    endTest = &(info->sampleName[nameLength - 5]);
949      if( !strcmp( endTest, ".bass" ) ){
950        strcpy( endTest, ".dump" );
951      }
# Line 570 | Line 953 | void SimSetup::createSim( void ){
953        strcpy( endTest, ".dump" );
954      }
955      else{
956 <      endTest = &(simnfo->sampleName[nameLength - 4]);
956 >      endTest = &(info->sampleName[nameLength - 4]);
957        if( !strcmp( endTest, ".bss" ) ){
958          strcpy( endTest, ".dump" );
959        }
# Line 578 | Line 961 | void SimSetup::createSim( void ){
961          strcpy( endTest, ".dump" );
962        }
963        else{
964 <        strcat( simnfo->sampleName, ".dump" );
964 >        strcat( info->sampleName, ".dump" );
965        }
966      }
967      
968 <    strcpy( simnfo->statusName, inFileName );
969 <    nameLength = strlen( simnfo->statusName );
970 <    endTest = &(simnfo->statusName[nameLength - 5]);
968 >    strcpy( info->statusName, inFileName );
969 >    nameLength = strlen( info->statusName );
970 >    endTest = &(info->statusName[nameLength - 5]);
971      if( !strcmp( endTest, ".bass" ) ){
972        strcpy( endTest, ".stat" );
973      }
# Line 592 | Line 975 | void SimSetup::createSim( void ){
975        strcpy( endTest, ".stat" );
976      }
977      else{
978 <      endTest = &(simnfo->statusName[nameLength - 4]);
978 >      endTest = &(info->statusName[nameLength - 4]);
979        if( !strcmp( endTest, ".bss" ) ){
980          strcpy( endTest, ".stat" );
981        }
# Line 600 | Line 983 | void SimSetup::createSim( void ){
983          strcpy( endTest, ".stat" );
984        }
985        else{
986 <        strcat( simnfo->statusName, ".stat" );
986 >        strcat( info->statusName, ".stat" );
987        }
988      }
989      
990   #ifdef IS_MPI
991    }
992   #endif // is_mpi
610  
611  // set the status, sample, and themal kick times
612  
613  if( the_globals->haveSampleTime() ){
614    simnfo->sampleTime = the_globals->getSampleTime();
615    simnfo->statusTime = simnfo->sampleTime;
616    simnfo->thermalTime = simnfo->sampleTime;
617  }
618  else{
619    simnfo->sampleTime = the_globals->getRunTime();
620    simnfo->statusTime = simnfo->sampleTime;
621    simnfo->thermalTime = simnfo->sampleTime;
622  }
993  
994 <  if( the_globals->haveStatusTime() ){
625 <    simnfo->statusTime = the_globals->getStatusTime();
626 <  }
994 > }
995  
628  if( the_globals->haveThermalTime() ){
629    simnfo->thermalTime = the_globals->getThermalTime();
630  }
996  
997 <  // check for the temperature set flag
997 > void SimSetup::sysObjectsCreation( void ){
998  
999 <  if( the_globals->haveTempSet() ) simnfo->setTemp = the_globals->getTempSet();
999 >  int i;
1000  
1001 +  // create the forceField
1002  
1003 < //   // make the longe range forces and the integrator
1003 >  createFF();
1004  
1005 < //   new AllLong( simnfo );
1005 >  // extract componentList
1006  
1007 <  if( !strcmp( force_field, "TraPPE" ) ) new Verlet( *simnfo, the_ff );
642 <  if( !strcmp( force_field, "DipoleTest" ) ) new Symplectic( simnfo, the_ff );
643 <  if( !strcmp( force_field, "TraPPE_Ex" ) ) new Symplectic( simnfo, the_ff );
644 <  if( !strcmp( force_field, "LJ" ) ) new Verlet( *simnfo, the_ff );
1007 >  compList();
1008  
1009 +  // calc the number of atoms, bond, bends, and torsions
1010  
1011 +  calcSysValues();
1012  
1013 <  // initialize the Fortran
1013 > #ifdef IS_MPI
1014 >  // divide the molecules among the processors
1015    
1016 <  simnfo->refreshSim();
1016 >  mpiMolDivide();
1017 > #endif //is_mpi
1018    
1019 <  if( !strcmp( simnfo->mixingRule, "standard") ){
1020 <    the_ff->initForceField( LB_MIXING_RULE );
1021 <  }
1022 <  else if( !strcmp( simnfo->mixingRule, "explicit") ){
1023 <    the_ff->initForceField( EXPLICIT_MIXING_RULE );
1024 <  }
1025 <  else{
1026 <    sprintf( painCave.errMsg,
1027 <             "SimSetup Error: unknown mixing rule -> \"%s\"\n",
1028 <             simnfo->mixingRule );
1019 >  // create the atom and SRI arrays. Also initialize Molecule Stamp ID's
1020 >  
1021 >  makeSysArrays();
1022 >
1023 >  // make and initialize the molecules (all but atomic coordinates)
1024 >  
1025 >  makeMolecules();
1026 >  info->identArray = new int[info->n_atoms];
1027 >  for(i=0; i<info->n_atoms; i++){
1028 >    info->identArray[i] = the_atoms[i]->getIdent();
1029 >  }
1030 >  
1031 >
1032 >
1033 > }
1034 >
1035 >
1036 > void SimSetup::createFF( void ){
1037 >
1038 >  switch( ffCase ){
1039 >
1040 >  case FF_DUFF:
1041 >    the_ff = new DUFF();
1042 >    break;
1043 >
1044 >  case FF_LJ:
1045 >    the_ff = new LJFF();
1046 >    break;
1047 >
1048 >  case FF_EAM:
1049 >    the_ff = new EAM_FF();
1050 >    break;
1051 >
1052 >  default:
1053 >    sprintf( painCave.errMsg,
1054 >             "SimSetup Error. Unrecognized force field in case statement.\n");
1055      painCave.isFatal = 1;
1056      simError();
1057    }
1058  
666
1059   #ifdef IS_MPI
1060 <  strcpy( checkPointMsg,
669 <          "Successfully intialized the mixingRule for Fortran." );
1060 >  strcpy( checkPointMsg, "ForceField creation successful" );
1061    MPIcheckPoint();
1062   #endif // is_mpi
1063 +
1064   }
1065  
1066  
1067 < void SimSetup::makeMolecules( void ){
1067 > void SimSetup::compList( void ){
1068  
1069 <  int i, j, exI, exJ, tempEx, stampID, atomOffset;
678 <  molInit info;
679 <  DirectionalAtom* dAtom;
680 <  AtomStamp* currentAtom;
681 <  BondStamp* currentBond;
682 <  BendStamp* currentBend;
683 <  TorsionStamp* currentTorsion;
684 <  
685 <  //init the forceField paramters
1069 >  int i;
1070  
1071 <  the_ff->readParams();
1071 >  comp_stamps = new MoleculeStamp*[n_components];
1072  
1073 +  // make an array of molecule stamps that match the components used.
1074 +  // also extract the used stamps out into a separate linked list
1075 +
1076 +  info->nComponents = n_components;
1077 +  info->componentsNmol = components_nmol;
1078 +  info->compStamps = comp_stamps;
1079 +  info->headStamp = new LinkedMolStamp();
1080    
1081 <  // init the molecules
1081 >  char* id;
1082 >  LinkedMolStamp* headStamp = info->headStamp;
1083 >  LinkedMolStamp* currentStamp = NULL;
1084 >  for( i=0; i<n_components; i++ ){
1085  
1086 <  atomOffset = 0;
1087 <  for(i=0; i<simnfo->n_mol; i++){
1086 >    id = the_components[i]->getType();
1087 >    comp_stamps[i] = NULL;
1088      
1089 <    stampID = the_molecules[i].getStampID();
1089 >    // check to make sure the component isn't already in the list
1090  
1091 <    info.nAtoms    = comp_stamps[stampID]->getNAtoms();
1092 <    info.nBonds    = comp_stamps[stampID]->getNBonds();
699 <    info.nBends    = comp_stamps[stampID]->getNBends();
700 <    info.nTorsions = comp_stamps[stampID]->getNTorsions();
701 <    
702 <    info.myAtoms = &the_atoms[atomOffset];
703 <    info.myBonds = new Bond*[info.nBonds];
704 <    info.myBends = new Bend*[info.nBends];
705 <    info.myTorsions = new Torsions*[info.nTorsions];
706 <
707 <    theBonds = new bond_pair[info.nBonds];
708 <    theBends = new bend_set[info.nBends];
709 <    theTorsions = new torsion_set[info.nTorsions];
710 <    
711 <    // make the Atoms
712 <    
713 <    for(j=0; j<info.nAtoms; j++){
1091 >    comp_stamps[i] = headStamp->match( id );
1092 >    if( comp_stamps[i] == NULL ){
1093        
1094 <      currentAtom = theComponents[stampID]->getAtom( j );
1095 <      if( currentAtom->haveOrientation() ){
1096 <        
1097 <        dAtom = new DirectionalAtom(j + atomOffset);
1098 <        simnfo->n_oriented++;
1099 <        info.myAtoms[j] = dAtom;
1100 <        
1101 <        ux = currentAtom->getOrntX();
1102 <        uy = currentAtom->getOrntY();
1103 <        uz = currentAtom->getOrntZ();
725 <        
726 <        uSqr = (ux * ux) + (uy * uy) + (uz * uz);
727 <        
728 <        u = sqrt( uSqr );
729 <        ux = ux / u;
730 <        uy = uy / u;
731 <        uz = uz / u;
732 <        
733 <        dAtom->setSUx( ux );
734 <        dAtom->setSUy( uy );
735 <        dAtom->setSUz( uz );
1094 >      // extract the component from the list;
1095 >      
1096 >      currentStamp = stamps->extractMolStamp( id );
1097 >      if( currentStamp == NULL ){
1098 >        sprintf( painCave.errMsg,
1099 >                 "SimSetup error: Component \"%s\" was not found in the "
1100 >                 "list of declared molecules\n",
1101 >                 id );
1102 >        painCave.isFatal = 1;
1103 >        simError();
1104        }
737      else{
738        info.myAtoms[j] = new GeneralAtom(j + atomOffset);
739      }
740      info.myAtoms[j]->setType( currentAtom->getType() );
741    
742 #ifdef IS_MPI
1105        
1106 <      info.myAtoms[j]->setGlobalIndex( globalIndex[j+atomOffset] );
1107 <      
1106 >      headStamp->add( currentStamp );
1107 >      comp_stamps[i] = headStamp->match( id );
1108 >    }
1109 >  }
1110 >
1111 > #ifdef IS_MPI
1112 >  strcpy( checkPointMsg, "Component stamps successfully extracted\n" );
1113 >  MPIcheckPoint();
1114   #endif // is_mpi
747    }
748    
749    // make the bonds
750    for(j=0; j<nBonds; j++){
751      
752      currentBond = comp_stamps[stampID]->getBond( j );
753      theBonds[j].a = currentBond->getA() + atomOffset;
754      theBonds[j].b = currentBond->getB() + atomOffset;
1115  
756      exI = theBonds[i].a;
757      exJ = theBonds[i].b;
1116  
1117 <      // exclude_I must always be the smaller of the pair
760 <      if( exI > exJ ){
761 <        tempEx = exI;
762 <        exI = exJ;
763 <        exJ = tempEx;
764 <      }
765 < #ifdef IS_MPI
766 <      
767 <      the_excludes[index*2] =    
768 <        the_atoms[exI]->getGlobalIndex() + 1;
769 <      the_excludes[index*2 + 1] =
770 <        the_atoms[exJ]->getGlobalIndex() + 1;
771 <      
772 < #else  // isn't MPI
773 <      
774 <      the_excludes[index*2] =     exI + 1;
775 <      the_excludes[index*2 + 1] = exJ + 1;
776 <      // fortran index from 1 (hence the +1 in the indexing)
1117 > }
1118  
1119 < #endif  //is_mpi
1119 > void SimSetup::calcSysValues( void ){
1120 >  int i, j, k;
1121 >
1122 >
1123 >  tot_atoms = 0;
1124 >  tot_bonds = 0;
1125 >  tot_bends = 0;
1126 >  tot_torsions = 0;
1127 >  for( i=0; i<n_components; i++ ){
1128      
1129 +    tot_atoms +=    components_nmol[i] * comp_stamps[i]->getNAtoms();
1130 +    tot_bonds +=    components_nmol[i] * comp_stamps[i]->getNBonds();
1131 +    tot_bends +=    components_nmol[i] * comp_stamps[i]->getNBends();
1132 +    tot_torsions += components_nmol[i] * comp_stamps[i]->getNTorsions();
1133    }
1134  
1135 +  tot_SRI = tot_bonds + tot_bends + tot_torsions;
1136  
1137 +  info->n_atoms = tot_atoms;
1138 +  info->n_bonds = tot_bonds;
1139 +  info->n_bends = tot_bends;
1140 +  info->n_torsions = tot_torsions;
1141 +  info->n_SRI = tot_SRI;
1142 +  info->n_mol = tot_nmol;
1143 +  
1144 +  info->molMembershipArray = new int[tot_atoms];
1145 + }
1146  
1147  
1148 + #ifdef IS_MPI
1149  
1150 + void SimSetup::mpiMolDivide( void ){
1151 +  
1152 +  int i, j, k;
1153 +  int localMol, allMol;
1154 +  int local_atoms, local_bonds, local_bends, local_torsions, local_SRI;
1155  
1156 +  mpiSim = new mpiSimulation( info );
1157 +  
1158 +  globalIndex = mpiSim->divideLabor();
1159  
1160 +  // set up the local variables
1161 +  
1162 +  mol2proc = mpiSim->getMolToProcMap();
1163 +  molCompType = mpiSim->getMolComponentType();
1164 +  
1165 +  allMol = 0;
1166 +  localMol = 0;
1167 +  local_atoms = 0;
1168 +  local_bonds = 0;
1169 +  local_bends = 0;
1170 +  local_torsions = 0;
1171 +  globalAtomIndex = 0;
1172  
1173  
1174 +  for( i=0; i<n_components; i++ ){
1175  
1176 +    for( j=0; j<components_nmol[i]; j++ ){
1177 +      
1178 +      if( mol2proc[allMol] == worldRank ){
1179 +        
1180 +        local_atoms +=    comp_stamps[i]->getNAtoms();
1181 +        local_bonds +=    comp_stamps[i]->getNBonds();
1182 +        local_bends +=    comp_stamps[i]->getNBends();
1183 +        local_torsions += comp_stamps[i]->getNTorsions();
1184 +        localMol++;
1185 +      }      
1186 +      for (k = 0; k < comp_stamps[i]->getNAtoms(); k++) {
1187 +        info->molMembershipArray[globalAtomIndex] = allMol;
1188 +        globalAtomIndex++;
1189 +      }
1190  
1191 +      allMol++;      
1192 +    }
1193 +  }
1194 +  local_SRI = local_bonds + local_bends + local_torsions;
1195 +  
1196 +  info->n_atoms = mpiSim->getMyNlocal();  
1197 +  
1198 +  if( local_atoms != info->n_atoms ){
1199 +    sprintf( painCave.errMsg,
1200 +             "SimSetup error: mpiSim's localAtom (%d) and SimSetup's"
1201 +             " localAtom (%d) are not equal.\n",
1202 +             info->n_atoms,
1203 +             local_atoms );
1204 +    painCave.isFatal = 1;
1205 +    simError();
1206 +  }
1207  
1208 +  info->n_bonds = local_bonds;
1209 +  info->n_bends = local_bends;
1210 +  info->n_torsions = local_torsions;
1211 +  info->n_SRI = local_SRI;
1212 +  info->n_mol = localMol;
1213  
1214 +  strcpy( checkPointMsg, "Passed nlocal consistency check." );
1215 +  MPIcheckPoint();
1216 + }
1217 +  
1218 + #endif // is_mpi
1219  
1220  
1221 < void SimSetup::makeAtoms( void ){
1221 > void SimSetup::makeSysArrays( void ){
1222 >  int i, j, k;
1223  
798  int i, j, k, index;
799  double ux, uy, uz, uSqr, u;
800  AtomStamp* current_atom;
1224  
1225 <  DirectionalAtom* dAtom;
803 <  int molIndex, molStart, molEnd, nMemb, lMolIndex;
1225 >  // create the atom and short range interaction arrays
1226  
1227 <  lMolIndex = 0;
1228 <  molIndex = 0;
1229 <  index = 0;
1230 <  for( i=0; i<n_components; i++ ){
1227 >  Atom::createArrays(info->n_atoms);
1228 >  the_atoms = new Atom*[info->n_atoms];
1229 >  the_molecules = new Molecule[info->n_mol];
1230 >  int molIndex;
1231  
1232 <    for( j=0; j<components_nmol[i]; j++ ){
1232 >  // initialize the molecule's stampID's
1233  
1234   #ifdef IS_MPI
1235 <      if( mpiSim->getMyMolStart() <= molIndex &&
814 <          molIndex <= mpiSim->getMyMolEnd() ){
815 < #endif // is_mpi        
1235 >  
1236  
1237 <        molStart = index;
1238 <        nMemb = comp_stamps[i]->getNAtoms();
1239 <        for( k=0; k<comp_stamps[i]->getNAtoms(); k++ ){
1240 <          
1241 <          current_atom = comp_stamps[i]->getAtom( k );
1242 <          if( current_atom->haveOrientation() ){
1243 <            
1244 <            dAtom = new DirectionalAtom(index);
1245 <            simnfo->n_oriented++;
1246 <            the_atoms[index] = dAtom;
827 <            
828 <            ux = current_atom->getOrntX();
829 <            uy = current_atom->getOrntY();
830 <            uz = current_atom->getOrntZ();
831 <            
832 <            uSqr = (ux * ux) + (uy * uy) + (uz * uz);
833 <            
834 <            u = sqrt( uSqr );
835 <            ux = ux / u;
836 <            uy = uy / u;
837 <            uz = uz / u;
838 <            
839 <            dAtom->setSUx( ux );
840 <            dAtom->setSUy( uy );
841 <            dAtom->setSUz( uz );
842 <          }
843 <          else{
844 <            the_atoms[index] = new GeneralAtom(index);
845 <          }
846 <          the_atoms[index]->setType( current_atom->getType() );
847 <          the_atoms[index]->setIndex( index );
848 <          
849 <          // increment the index and repeat;
850 <          index++;
851 <        }
852 <        
853 <        molEnd = index -1;
854 <        the_molecules[lMolIndex].setNMembers( nMemb );
855 <        the_molecules[lMolIndex].setStartAtom( molStart );
856 <        the_molecules[lMolIndex].setEndAtom( molEnd );
857 <        the_molecules[lMolIndex].setStampID( i );
858 <        lMolIndex++;
1237 >  molIndex = 0;
1238 >  for(i=0; i<mpiSim->getTotNmol(); i++){
1239 >    
1240 >    if(mol2proc[i] == worldRank ){
1241 >      the_molecules[molIndex].setStampID( molCompType[i] );
1242 >      the_molecules[molIndex].setMyIndex( molIndex );
1243 >      the_molecules[molIndex].setGlobalIndex( i );
1244 >      molIndex++;
1245 >    }
1246 >  }
1247  
1248 < #ifdef IS_MPI
1248 > #else // is_mpi
1249 >  
1250 >  molIndex = 0;
1251 >  globalAtomIndex = 0;
1252 >  for(i=0; i<n_components; i++){
1253 >    for(j=0; j<components_nmol[i]; j++ ){
1254 >      the_molecules[molIndex].setStampID( i );
1255 >      the_molecules[molIndex].setMyIndex( molIndex );
1256 >      the_molecules[molIndex].setGlobalIndex( molIndex );
1257 >      for (k = 0; k < comp_stamps[i]->getNAtoms(); k++) {
1258 >        info->molMembershipArray[globalAtomIndex] = molIndex;
1259 >        globalAtomIndex++;
1260        }
862 #endif //is_mpi
863      
1261        molIndex++;
1262      }
1263    }
867
868 #ifdef IS_MPI
869    for( i=0; i<mpiSim->getMyNlocal(); i++ ) the_atoms[i]->setGlobalIndex( globalIndex[i] );
1264      
871    delete[] globalIndex;
1265  
1266 <    mpiSim->mpiRefresh();
874 < #endif //IS_MPI
875 <          
876 <  the_ff->initializeAtoms();
877 < }
1266 > #endif // is_mpi
1267  
879 void SimSetup::makeBonds( void ){
1268  
1269 <  int i, j, k, index, offset, molIndex, exI, exJ, tempEx;
1270 <  bond_pair* the_bonds;
1271 <  BondStamp* current_bond;
1269 >  if( info->n_SRI ){
1270 >    
1271 >    Exclude::createArray(info->n_SRI);
1272 >    the_excludes = new Exclude*[info->n_SRI];
1273 >    for( int ex=0; ex<info->n_SRI; ex++) the_excludes[ex] = new Exclude(ex);
1274 >    info->globalExcludes = new int;
1275 >    info->n_exclude = info->n_SRI;
1276 >  }
1277 >  else{
1278 >    
1279 >    Exclude::createArray( 1 );
1280 >    the_excludes = new Exclude*;
1281 >    the_excludes[0] = new Exclude(0);
1282 >    the_excludes[0]->setPair( 0,0 );
1283 >    info->globalExcludes = new int;
1284 >    info->globalExcludes[0] = 0;
1285 >    info->n_exclude = 0;
1286 >  }
1287  
1288 <  the_bonds = new bond_pair[tot_bonds];
886 <  index = 0;
887 <  offset = 0;
888 <  molIndex = 0;
1288 >  // set the arrays into the SimInfo object
1289  
1290 <  for( i=0; i<n_components; i++ ){
1290 >  info->atoms = the_atoms;
1291 >  info->molecules = the_molecules;
1292 >  info->nGlobalExcludes = 0;
1293 >  info->excludes = the_excludes;
1294  
1295 <    for( j=0; j<components_nmol[i]; j++ ){
1295 >  the_ff->setSimInfo( info );
1296  
1297 < #ifdef IS_MPI
895 <      if( mpiSim->getMyMolStart() <= molIndex &&
896 <          molIndex <= mpiSim->getMyMolEnd() ){
897 < #endif // is_mpi        
898 <        
899 <        for( k=0; k<comp_stamps[i]->getNBonds(); k++ ){
900 <          
901 <          current_bond = comp_stamps[i]->getBond( k );
902 <          the_bonds[index].a = current_bond->getA() + offset;
903 <          the_bonds[index].b = current_bond->getB() + offset;
1297 > }
1298  
1299 <          exI = the_bonds[index].a;
906 <          exJ = the_bonds[index].b;
1299 > void SimSetup::makeIntegrator( void ){
1300  
1301 <          // exclude_I must always be the smaller of the pair
1302 <          if( exI > exJ ){
1303 <            tempEx = exI;
1304 <            exI = exJ;
1305 <            exJ = tempEx;
913 <          }
1301 >  NVT<RealIntegrator>*  myNVT = NULL;
1302 >  NPTi<RealIntegrator>* myNPTi = NULL;
1303 >  NPTf<RealIntegrator>* myNPTf = NULL;
1304 >  NPTim<RealIntegrator>* myNPTim = NULL;
1305 >  NPTfm<RealIntegrator>* myNPTfm = NULL;
1306  
1307 <          
916 < #ifdef IS_MPI
1307 >  switch( ensembleCase ){
1308  
1309 <          the_excludes[index*2] =    
1310 <            the_atoms[exI]->getGlobalIndex() + 1;
1311 <          the_excludes[index*2 + 1] =
921 <            the_atoms[exJ]->getGlobalIndex() + 1;
1309 >  case NVE_ENS:
1310 >    new NVE<RealIntegrator>( info, the_ff );
1311 >    break;
1312  
1313 < #else  // isn't MPI
1314 <          
1315 <          the_excludes[index*2] =     exI + 1;
926 <          the_excludes[index*2 + 1] = exJ + 1;
927 <          // fortran index from 1 (hence the +1 in the indexing)
928 < #endif  //is_mpi
929 <          
930 <          // increment the index and repeat;
931 <          index++;
932 <        }
933 <        offset += comp_stamps[i]->getNAtoms();
934 <        
935 < #ifdef IS_MPI
936 <      }
937 < #endif //is_mpi
938 <      
939 <      molIndex++;
940 <    }      
941 <  }
1313 >  case NVT_ENS:
1314 >    myNVT = new NVT<RealIntegrator>( info, the_ff );
1315 >    myNVT->setTargetTemp(globals->getTargetTemp());
1316  
1317 <  the_ff->initializeBonds( the_bonds );
1318 < }
1317 >    if (globals->haveTauThermostat())
1318 >      myNVT->setTauThermostat(globals->getTauThermostat());
1319  
1320 < void SimSetup::makeBends( void ){
1320 >    else {
1321 >      sprintf( painCave.errMsg,
1322 >               "SimSetup error: If you use the NVT\n"
1323 >               "    ensemble, you must set tauThermostat.\n");
1324 >      painCave.isFatal = 1;
1325 >      simError();
1326 >    }
1327 >    break;
1328  
1329 <  int i, j, k, index, offset, molIndex, exI, exJ, tempEx;
1330 <  bend_set* the_bends;
1331 <  BendStamp* current_bend;
951 <  LinkedAssign* extras;
952 <  LinkedAssign* current_extra;
953 <  
1329 >  case NPTi_ENS:
1330 >    myNPTi = new NPTi<RealIntegrator>( info, the_ff );
1331 >    myNPTi->setTargetTemp( globals->getTargetTemp() );
1332  
1333 <  the_bends = new bend_set[tot_bends];
1334 <  index = 0;
1335 <  offset = 0;
1336 <  molIndex = 0;
1337 <  for( i=0; i<n_components; i++ ){
1333 >    if (globals->haveTargetPressure())
1334 >      myNPTi->setTargetPressure(globals->getTargetPressure());
1335 >    else {
1336 >      sprintf( painCave.errMsg,
1337 >               "SimSetup error: If you use a constant pressure\n"
1338 >               "    ensemble, you must set targetPressure in the BASS file.\n");
1339 >      painCave.isFatal = 1;
1340 >      simError();
1341 >    }
1342 >    
1343 >    if( globals->haveTauThermostat() )
1344 >      myNPTi->setTauThermostat( globals->getTauThermostat() );
1345 >    else{
1346 >      sprintf( painCave.errMsg,
1347 >               "SimSetup error: If you use an NPT\n"
1348 >               "    ensemble, you must set tauThermostat.\n");
1349 >      painCave.isFatal = 1;
1350 >      simError();
1351 >    }
1352  
1353 <    for( j=0; j<components_nmol[i]; j++ ){
1353 >    if( globals->haveTauBarostat() )
1354 >      myNPTi->setTauBarostat( globals->getTauBarostat() );
1355 >    else{
1356 >      sprintf( painCave.errMsg,
1357 >               "SimSetup error: If you use an NPT\n"
1358 >               "    ensemble, you must set tauBarostat.\n");
1359 >      painCave.isFatal = 1;
1360 >      simError();
1361 >    }
1362 >    break;
1363  
1364 < #ifdef IS_MPI
1365 <      if( mpiSim->getMyMolStart() <= molIndex &&
1366 <          molIndex <= mpiSim->getMyMolEnd() ){
966 < #endif // is_mpi        
1364 >  case NPTf_ENS:
1365 >    myNPTf = new NPTf<RealIntegrator>( info, the_ff );
1366 >    myNPTf->setTargetTemp( globals->getTargetTemp());
1367  
1368 <        for( k=0; k<comp_stamps[i]->getNBends(); k++ ){
1369 <          
1370 <          current_bend = comp_stamps[i]->getBend( k );
1371 <          the_bends[index].a = current_bend->getA() + offset;
1372 <          the_bends[index].b = current_bend->getB() + offset;
1373 <          the_bends[index].c = current_bend->getC() + offset;
1374 <          
1375 <          if( current_bend->haveExtras() ){
1376 <            
977 <            extras = current_bend->getExtras();
978 <            current_extra = extras;
979 <            
980 <            while( current_extra != NULL ){
981 <              if( !strcmp( current_extra->getlhs(), "ghostVectorSource" )){
982 <                
983 <                switch( current_extra->getType() ){
984 <                  
985 <                case 0:
986 <                  the_bends[index].ghost =
987 <                    current_extra->getInt() + offset;
988 <                  the_bends[index].isGhost = 1;
989 <                  break;
990 <                  
991 <                case 1:
992 <                  the_bends[index].ghost =
993 <                    (int)current_extra->getDouble() + offset;
994 <                  the_bends[index].isGhost = 1;
995 <                  break;
996 <                  
997 <                default:
998 <                  sprintf( painCave.errMsg,
999 <                           "SimSetup Error: ghostVectorSource was neiter a "
1000 <                           "double nor an int.\n"
1001 <                           "-->Bend[%d] in %s\n",
1002 <                           k, comp_stamps[i]->getID() );
1003 <                  painCave.isFatal = 1;
1004 <                  simError();
1005 <                }
1006 <              }
1007 <              
1008 <              else{
1009 <                
1010 <                sprintf( painCave.errMsg,
1011 <                         "SimSetup Error: unhandled bend assignment:\n"
1012 <                         "    -->%s in Bend[%d] in %s\n",
1013 <                         current_extra->getlhs(),
1014 <                         k, comp_stamps[i]->getID() );
1015 <                painCave.isFatal = 1;
1016 <                simError();
1017 <              }
1018 <              
1019 <              current_extra = current_extra->getNext();
1020 <            }
1021 <          }
1022 <          
1023 <          if( !the_bends[index].isGhost ){
1024 <            
1025 <            exI = the_bends[index].a;
1026 <            exJ = the_bends[index].c;
1027 <          }
1028 <          else{
1029 <            
1030 <            exI = the_bends[index].a;
1031 <            exJ = the_bends[index].b;
1032 <          }
1033 <          
1034 <          // exclude_I must always be the smaller of the pair
1035 <          if( exI > exJ ){
1036 <            tempEx = exI;
1037 <            exI = exJ;
1038 <            exJ = tempEx;
1039 <          }
1368 >    if (globals->haveTargetPressure())
1369 >      myNPTf->setTargetPressure(globals->getTargetPressure());
1370 >    else {
1371 >      sprintf( painCave.errMsg,
1372 >               "SimSetup error: If you use a constant pressure\n"
1373 >               "    ensemble, you must set targetPressure in the BASS file.\n");
1374 >      painCave.isFatal = 1;
1375 >      simError();
1376 >    }    
1377  
1378 +    if( globals->haveTauThermostat() )
1379 +      myNPTf->setTauThermostat( globals->getTauThermostat() );
1380 +    else{
1381 +      sprintf( painCave.errMsg,
1382 +               "SimSetup error: If you use an NPT\n"
1383 +               "    ensemble, you must set tauThermostat.\n");
1384 +      painCave.isFatal = 1;
1385 +      simError();
1386 +    }
1387  
1388 < #ifdef IS_MPI
1388 >    if( globals->haveTauBarostat() )
1389 >      myNPTf->setTauBarostat( globals->getTauBarostat() );
1390 >    else{
1391 >      sprintf( painCave.errMsg,
1392 >               "SimSetup error: If you use an NPT\n"
1393 >               "    ensemble, you must set tauBarostat.\n");
1394 >      painCave.isFatal = 1;
1395 >      simError();
1396 >    }
1397 >    break;
1398 >    
1399 >  case NPTim_ENS:
1400 >    myNPTim = new NPTim<RealIntegrator>( info, the_ff );
1401 >    myNPTim->setTargetTemp( globals->getTargetTemp());
1402  
1403 <          the_excludes[(index + tot_bonds)*2] =    
1404 <            the_atoms[exI]->getGlobalIndex() + 1;
1405 <          the_excludes[(index + tot_bonds)*2 + 1] =
1406 <            the_atoms[exJ]->getGlobalIndex() + 1;
1407 <          
1408 < #else  // isn't MPI
1409 <          
1410 <          the_excludes[(index + tot_bonds)*2] =     exI + 1;
1411 <          the_excludes[(index + tot_bonds)*2 + 1] = exJ + 1;
1412 <          // fortran index from 1 (hence the +1 in the indexing)
1413 < #endif  //is_mpi
1414 <          
1415 <          
1416 <          // increment the index and repeat;
1417 <          index++;
1418 <        }
1419 <        offset += comp_stamps[i]->getNAtoms();
1420 <        
1421 < #ifdef IS_MPI
1063 <      }
1064 < #endif //is_mpi
1403 >    if (globals->haveTargetPressure())
1404 >      myNPTim->setTargetPressure(globals->getTargetPressure());
1405 >    else {
1406 >      sprintf( painCave.errMsg,
1407 >               "SimSetup error: If you use a constant pressure\n"
1408 >               "    ensemble, you must set targetPressure in the BASS file.\n");
1409 >      painCave.isFatal = 1;
1410 >      simError();
1411 >    }
1412 >    
1413 >    if( globals->haveTauThermostat() )
1414 >      myNPTim->setTauThermostat( globals->getTauThermostat() );
1415 >    else{
1416 >      sprintf( painCave.errMsg,
1417 >               "SimSetup error: If you use an NPT\n"
1418 >               "    ensemble, you must set tauThermostat.\n");
1419 >      painCave.isFatal = 1;
1420 >      simError();
1421 >    }
1422  
1423 <      molIndex++;
1423 >    if( globals->haveTauBarostat() )
1424 >      myNPTim->setTauBarostat( globals->getTauBarostat() );
1425 >    else{
1426 >      sprintf( painCave.errMsg,
1427 >               "SimSetup error: If you use an NPT\n"
1428 >               "    ensemble, you must set tauBarostat.\n");
1429 >      painCave.isFatal = 1;
1430 >      simError();
1431      }
1432 <  }
1432 >    break;
1433  
1434 < #ifdef IS_MPI
1435 <  sprintf( checkPointMsg,
1436 <           "Successfully created the bends list.\n" );
1073 <  MPIcheckPoint();
1074 < #endif // is_mpi
1075 <  
1434 >  case NPTfm_ENS:
1435 >    myNPTfm = new NPTfm<RealIntegrator>( info, the_ff );
1436 >    myNPTfm->setTargetTemp( globals->getTargetTemp());
1437  
1438 <  the_ff->initializeBends( the_bends );
1439 < }
1438 >    if (globals->haveTargetPressure())
1439 >      myNPTfm->setTargetPressure(globals->getTargetPressure());
1440 >    else {
1441 >      sprintf( painCave.errMsg,
1442 >               "SimSetup error: If you use a constant pressure\n"
1443 >               "    ensemble, you must set targetPressure in the BASS file.\n");
1444 >      painCave.isFatal = 1;
1445 >      simError();
1446 >    }
1447 >    
1448 >    if( globals->haveTauThermostat() )
1449 >      myNPTfm->setTauThermostat( globals->getTauThermostat() );
1450 >    else{
1451 >      sprintf( painCave.errMsg,
1452 >               "SimSetup error: If you use an NPT\n"
1453 >               "    ensemble, you must set tauThermostat.\n");
1454 >      painCave.isFatal = 1;
1455 >      simError();
1456 >    }
1457  
1458 < void SimSetup::makeTorsions( void ){
1458 >    if( globals->haveTauBarostat() )
1459 >      myNPTfm->setTauBarostat( globals->getTauBarostat() );
1460 >    else{
1461 >      sprintf( painCave.errMsg,
1462 >               "SimSetup error: If you use an NPT\n"
1463 >               "    ensemble, you must set tauBarostat.\n");
1464 >      painCave.isFatal = 1;
1465 >      simError();
1466 >    }
1467 >    break;
1468  
1469 <  int i, j, k, index, offset, molIndex, exI, exJ, tempEx;
1470 <  torsion_set* the_torsions;
1471 <  TorsionStamp* current_torsion;
1472 <
1473 <  the_torsions = new torsion_set[tot_torsions];
1087 <  index = 0;
1088 <  offset = 0;
1089 <  molIndex = 0;
1090 <  for( i=0; i<n_components; i++ ){
1091 <
1092 <    for( j=0; j<components_nmol[i]; j++ ){
1093 <
1094 < #ifdef IS_MPI
1095 <      if( mpiSim->getMyMolStart() <= molIndex &&
1096 <          molIndex <= mpiSim->getMyMolEnd() ){
1097 < #endif // is_mpi        
1098 <
1099 <      for( k=0; k<comp_stamps[i]->getNTorsions(); k++ ){
1100 <
1101 <        current_torsion = comp_stamps[i]->getTorsion( k );
1102 <        the_torsions[index].a = current_torsion->getA() + offset;
1103 <        the_torsions[index].b = current_torsion->getB() + offset;
1104 <        the_torsions[index].c = current_torsion->getC() + offset;
1105 <        the_torsions[index].d = current_torsion->getD() + offset;
1106 <
1107 <        exI = the_torsions[index].a;
1108 <        exJ = the_torsions[index].d;
1109 <
1110 <        
1111 <        // exclude_I must always be the smaller of the pair
1112 <        if( exI > exJ ){
1113 <          tempEx = exI;
1114 <          exI = exJ;
1115 <          exJ = tempEx;
1116 <        }
1117 <
1118 <
1119 < #ifdef IS_MPI
1120 <        
1121 <        the_excludes[(index + tot_bonds + tot_bends)*2] =    
1122 <          the_atoms[exI]->getGlobalIndex() + 1;
1123 <        the_excludes[(index + tot_bonds + tot_bends)*2 + 1] =
1124 <          the_atoms[exJ]->getGlobalIndex() + 1;
1125 <        
1126 < #else  // isn't MPI
1127 <        
1128 <        the_excludes[(index + tot_bonds + tot_bends)*2] =     exI + 1;
1129 <        the_excludes[(index + tot_bonds + tot_bends)*2 + 1] = exJ + 1;
1130 <        // fortran indexes from 1 (hence the +1 in the indexing)
1131 < #endif  //is_mpi
1132 <        
1133 <
1134 <        // increment the index and repeat;
1135 <        index++;
1136 <      }
1137 <      offset += comp_stamps[i]->getNAtoms();
1138 <
1139 < #ifdef IS_MPI
1140 <      }
1141 < #endif //is_mpi      
1142 <
1143 <      molIndex++;
1144 <    }
1469 >  default:
1470 >    sprintf( painCave.errMsg,
1471 >             "SimSetup Error. Unrecognized ensemble in case statement.\n");
1472 >    painCave.isFatal = 1;
1473 >    simError();
1474    }
1475  
1147  the_ff->initializeTorsions( the_torsions );
1476   }
1477  
1478 < void SimSetup::initFromBass( void ){
1478 > void SimSetup::initFortran( void ){
1479  
1480 <  int i, j, k;
1481 <  int n_cells;
1482 <  double cellx, celly, cellz;
1483 <  double temp1, temp2, temp3;
1156 <  int n_per_extra;
1157 <  int n_extra;
1158 <  int have_extra, done;
1159 <
1160 <  temp1 = (double)tot_nmol / 4.0;
1161 <  temp2 = pow( temp1, ( 1.0 / 3.0 ) );
1162 <  temp3 = ceil( temp2 );
1163 <
1164 <  have_extra =0;
1165 <  if( temp2 < temp3 ){ // we have a non-complete lattice
1166 <    have_extra =1;
1167 <
1168 <    n_cells = (int)temp3 - 1;
1169 <    cellx = simnfo->box_x / temp3;
1170 <    celly = simnfo->box_y / temp3;
1171 <    cellz = simnfo->box_z / temp3;
1172 <    n_extra = tot_nmol - ( 4 * n_cells * n_cells * n_cells );
1173 <    temp1 = ((double)n_extra) / ( pow( temp3, 3.0 ) - pow( n_cells, 3.0 ) );
1174 <    n_per_extra = (int)ceil( temp1 );
1175 <
1176 <    if( n_per_extra > 4){
1177 <      sprintf( painCave.errMsg,
1178 <               "SimSetup error. There has been an error in constructing"
1179 <               " the non-complete lattice.\n" );
1180 <      painCave.isFatal = 1;
1181 <      simError();
1182 <    }
1480 >  info->refreshSim();
1481 >  
1482 >  if( !strcmp( info->mixingRule, "standard") ){
1483 >    the_ff->initForceField( LB_MIXING_RULE );
1484    }
1485 +  else if( !strcmp( info->mixingRule, "explicit") ){
1486 +    the_ff->initForceField( EXPLICIT_MIXING_RULE );
1487 +  }
1488    else{
1489 <    n_cells = (int)temp3;
1490 <    cellx = simnfo->box_x / temp3;
1491 <    celly = simnfo->box_y / temp3;
1492 <    cellz = simnfo->box_z / temp3;
1489 >    sprintf( painCave.errMsg,
1490 >             "SimSetup Error: unknown mixing rule -> \"%s\"\n",
1491 >             info->mixingRule );
1492 >    painCave.isFatal = 1;
1493 >    simError();
1494    }
1495  
1191  current_mol = 0;
1192  current_comp_mol = 0;
1193  current_comp = 0;
1194  current_atom_ndx = 0;
1496  
1497 <  for( i=0; i < n_cells ; i++ ){
1498 <    for( j=0; j < n_cells; j++ ){
1499 <      for( k=0; k < n_cells; k++ ){
1497 > #ifdef IS_MPI
1498 >  strcpy( checkPointMsg,
1499 >          "Successfully intialized the mixingRule for Fortran." );
1500 >  MPIcheckPoint();
1501 > #endif // is_mpi
1502  
1200        makeElement( i * cellx,
1201                     j * celly,
1202                     k * cellz );
1203
1204        makeElement( i * cellx + 0.5 * cellx,
1205                     j * celly + 0.5 * celly,
1206                     k * cellz );
1207
1208        makeElement( i * cellx,
1209                     j * celly + 0.5 * celly,
1210                     k * cellz + 0.5 * cellz );
1211
1212        makeElement( i * cellx + 0.5 * cellx,
1213                     j * celly,
1214                     k * cellz + 0.5 * cellz );
1215      }
1216    }
1217  }
1218
1219  if( have_extra ){
1220    done = 0;
1221
1222    int start_ndx;
1223    for( i=0; i < (n_cells+1) && !done; i++ ){
1224      for( j=0; j < (n_cells+1) && !done; j++ ){
1225
1226        if( i < n_cells ){
1227
1228          if( j < n_cells ){
1229            start_ndx = n_cells;
1230          }
1231          else start_ndx = 0;
1232        }
1233        else start_ndx = 0;
1234
1235        for( k=start_ndx; k < (n_cells+1) && !done; k++ ){
1236
1237          makeElement( i * cellx,
1238                       j * celly,
1239                       k * cellz );
1240          done = ( current_mol >= tot_nmol );
1241
1242          if( !done && n_per_extra > 1 ){
1243            makeElement( i * cellx + 0.5 * cellx,
1244                         j * celly + 0.5 * celly,
1245                         k * cellz );
1246            done = ( current_mol >= tot_nmol );
1247          }
1248
1249          if( !done && n_per_extra > 2){
1250            makeElement( i * cellx,
1251                         j * celly + 0.5 * celly,
1252                         k * cellz + 0.5 * cellz );
1253            done = ( current_mol >= tot_nmol );
1254          }
1255
1256          if( !done && n_per_extra > 3){
1257            makeElement( i * cellx + 0.5 * cellx,
1258                         j * celly,
1259                         k * cellz + 0.5 * cellz );
1260            done = ( current_mol >= tot_nmol );
1261          }
1262        }
1263      }
1264    }
1265  }
1266
1267
1268  for( i=0; i<simnfo->n_atoms; i++ ){
1269    simnfo->atoms[i]->set_vx( 0.0 );
1270    simnfo->atoms[i]->set_vy( 0.0 );
1271    simnfo->atoms[i]->set_vz( 0.0 );
1272  }
1503   }
1274
1275 void SimSetup::makeElement( double x, double y, double z ){
1276
1277  int k;
1278  AtomStamp* current_atom;
1279  DirectionalAtom* dAtom;
1280  double rotMat[3][3];
1281
1282  for( k=0; k<comp_stamps[current_comp]->getNAtoms(); k++ ){
1283
1284    current_atom = comp_stamps[current_comp]->getAtom( k );
1285    if( !current_atom->havePosition() ){
1286      sprintf( painCave.errMsg,
1287               "SimSetup:initFromBass error.\n"
1288               "\tComponent %s, atom %s does not have a position specified.\n"
1289               "\tThe initialization routine is unable to give a start"
1290               " position.\n",
1291               comp_stamps[current_comp]->getID(),
1292               current_atom->getType() );
1293      painCave.isFatal = 1;
1294      simError();
1295    }
1296
1297    the_atoms[current_atom_ndx]->setX( x + current_atom->getPosX() );
1298    the_atoms[current_atom_ndx]->setY( y + current_atom->getPosY() );
1299    the_atoms[current_atom_ndx]->setZ( z + current_atom->getPosZ() );
1300
1301    if( the_atoms[current_atom_ndx]->isDirectional() ){
1302
1303      dAtom = (DirectionalAtom *)the_atoms[current_atom_ndx];
1304
1305      rotMat[0][0] = 1.0;
1306      rotMat[0][1] = 0.0;
1307      rotMat[0][2] = 0.0;
1308
1309      rotMat[1][0] = 0.0;
1310      rotMat[1][1] = 1.0;
1311      rotMat[1][2] = 0.0;
1312
1313      rotMat[2][0] = 0.0;
1314      rotMat[2][1] = 0.0;
1315      rotMat[2][2] = 1.0;
1316
1317      dAtom->setA( rotMat );
1318    }
1319
1320    current_atom_ndx++;
1321  }
1322
1323  current_mol++;
1324  current_comp_mol++;
1325
1326  if( current_comp_mol >= components_nmol[current_comp] ){
1327
1328    current_comp_mol = 0;
1329    current_comp++;
1330  }
1331 }

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines