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 780 by mmeineke, Mon Sep 22 21:23:25 2003 UTC vs.
Revision 1163 by gezelter, Wed May 12 14:30:12 2004 UTC

# Line 1 | Line 1
1   #include <algorithm>
2 < #include <cstdlib>
2 > #include <stdlib.h>
3   #include <iostream>
4 < #include <cmath>
4 > #include <math.h>
5   #include <string>
6   #include <sprng.h>
7
7   #include "SimSetup.hpp"
8   #include "ReadWrite.hpp"
9   #include "parse_me.h"
10   #include "Integrator.hpp"
11   #include "simError.h"
12 + #include "RigidBody.hpp"
13 + //#include "ConjugateMinimizer.hpp"
14 + #include "OOPSEMinimizer.hpp"
15  
16   #ifdef IS_MPI
17   #include "mpiBASS.h"
# Line 22 | Line 24
24   #define NVT_ENS        1
25   #define NPTi_ENS       2
26   #define NPTf_ENS       3
27 + #define NPTxyz_ENS     4
28  
26 #define FF_DUFF 0
27 #define FF_LJ   1
28 #define FF_EAM  2
29  
30 + #define FF_DUFF  0
31 + #define FF_LJ    1
32 + #define FF_EAM   2
33 + #define FF_H2O   3
34 +
35   using namespace std;
36  
37 + /**
38 + * Check whether dividend is divisble by divisor or not
39 + */
40 + bool isDivisible(double dividend, double divisor){
41 +  double tolerance = 0.000001;
42 +  double quotient;
43 +  double diff;
44 +  int intQuotient;
45 +  
46 +  quotient = dividend / divisor;
47 +
48 +  if (quotient < 0)
49 +    quotient = -quotient;
50 +
51 +  intQuotient = int (quotient + tolerance);
52 +
53 +  diff = fabs(fabs(dividend) - intQuotient  * fabs(divisor));
54 +
55 +  if (diff <= tolerance)
56 +    return true;
57 +  else
58 +    return false;  
59 + }
60 +
61   SimSetup::SimSetup(){
62 +  
63 +  initSuspend = false;
64    isInfoArray = 0;
65    nInfo = 1;
66  
# Line 52 | Line 83 | void SimSetup::setSimInfo(SimInfo* the_info, int theNi
83    info = the_info;
84    nInfo = theNinfo;
85    isInfoArray = 1;
86 +  initSuspend = true;
87   }
88  
89  
# Line 90 | Line 122 | void SimSetup::createSim(void){
122   #endif // is_mpi
123  
124   void SimSetup::createSim(void){
93  int i, j, k, globalAtomIndex;
125  
126    // gather all of the information from the Bass file
127  
# Line 106 | Line 137 | void SimSetup::createSim(void){
137  
138    // initialize the system coordinates
139  
140 <  if (!isInfoArray){
140 >  if ( !initSuspend ){
141      initSystemCoords();
142 +
143 +    if( !(globals->getUseInitTime()) )
144 +      info[0].currentTime = 0.0;
145    }  
146  
147    // make the output filenames
148  
149    makeOutNames();
150 <
117 <  // make the integrator
118 <
119 <  makeIntegrator();
120 <
150 >  
151   #ifdef IS_MPI
152    mpiSim->mpiRefresh();
153   #endif
# Line 125 | Line 155 | void SimSetup::createSim(void){
155    // initialize the Fortran
156  
157    initFortran();
158 +
159 +  if (globals->haveMinimizer())
160 +    // make minimizer
161 +    makeMinimizer();
162 +  else
163 +    // make the integrator
164 +    makeIntegrator();
165 +
166   }
167  
168  
169   void SimSetup::makeMolecules(void){
170 <  int k, l;
171 <  int i, j, exI, exJ, tempEx, stampID, atomOffset, excludeOffset;
170 >  int i, j, k;
171 >  int exI, exJ, exK, exL, slI, slJ;
172 >  int tempI, tempJ, tempK, tempL;
173 >  int molI;
174 >  int stampID, atomOffset, rbOffset;
175    molInit molInfo;
176    DirectionalAtom* dAtom;
177 +  RigidBody* myRB;
178 +  StuntDouble* mySD;
179    LinkedAssign* extras;
180    LinkedAssign* current_extra;
181    AtomStamp* currentAtom;
182    BondStamp* currentBond;
183    BendStamp* currentBend;
184    TorsionStamp* currentTorsion;
185 <
185 >  RigidBodyStamp* currentRigidBody;
186 >  CutoffGroupStamp* currentCutoffGroup;
187 >  CutoffGroup* myCutoffGroup;
188 >  
189    bond_pair* theBonds;
190    bend_set* theBends;
191    torsion_set* theTorsions;
192  
193 +  set<int> skipList;
194  
195 +  double phi, theta, psi;
196 +  char* molName;
197 +  char rbName[100];
198 +
199    //init the forceField paramters
200  
201    the_ff->readParams();
202  
152
203    // init the atoms
204  
205 <  double ux, uy, uz, u, uSqr;
205 >  int nMembers, nNew, rb1, rb2;
206  
207    for (k = 0; k < nInfo; k++){
208      the_ff->setSimInfo(&(info[k]));
209  
210      atomOffset = 0;
211 <    excludeOffset = 0;
211 >
212      for (i = 0; i < info[k].n_mol; i++){
213        stampID = info[k].molecules[i].getStampID();
214 +      molName = comp_stamps[stampID]->getID();
215  
216        molInfo.nAtoms = comp_stamps[stampID]->getNAtoms();
217        molInfo.nBonds = comp_stamps[stampID]->getNBonds();
218        molInfo.nBends = comp_stamps[stampID]->getNBends();
219        molInfo.nTorsions = comp_stamps[stampID]->getNTorsions();
220 <      molInfo.nExcludes = molInfo.nBonds + molInfo.nBends + molInfo.nTorsions;
221 <
220 >      molInfo.nRigidBodies = comp_stamps[stampID]->getNRigidBodies();
221 >      molInfo.nCutoffGroups = comp_stamps[stampID]->getNCutoffGroups();
222 >      
223        molInfo.myAtoms = &(info[k].atoms[atomOffset]);
172      molInfo.myExcludes = &(info[k].excludes[excludeOffset]);
173      molInfo.myBonds = new Bond * [molInfo.nBonds];
174      molInfo.myBends = new Bend * [molInfo.nBends];
175      molInfo.myTorsions = new Torsion * [molInfo.nTorsions];
224  
225 +      if (molInfo.nBonds > 0)
226 +        molInfo.myBonds = new (Bond *) [molInfo.nBonds];
227 +      else
228 +        molInfo.myBonds = NULL;
229 +
230 +      if (molInfo.nBends > 0)
231 +        molInfo.myBends = new (Bend *) [molInfo.nBends];
232 +      else
233 +        molInfo.myBends = NULL;
234 +
235 +      if (molInfo.nTorsions > 0)
236 +        molInfo.myTorsions = new (Torsion *) [molInfo.nTorsions];
237 +      else
238 +        molInfo.myTorsions = NULL;
239 +
240        theBonds = new bond_pair[molInfo.nBonds];
241        theBends = new bend_set[molInfo.nBends];
242        theTorsions = new torsion_set[molInfo.nTorsions];
243 <
243 >      
244        // make the Atoms
245  
246        for (j = 0; j < molInfo.nAtoms; j++){
247          currentAtom = comp_stamps[stampID]->getAtom(j);
248 +
249          if (currentAtom->haveOrientation()){
250            dAtom = new DirectionalAtom((j + atomOffset),
251                                        info[k].getConfiguration());
252            info[k].n_oriented++;
253            molInfo.myAtoms[j] = dAtom;
254  
255 <          ux = currentAtom->getOrntX();
256 <          uy = currentAtom->getOrntY();
257 <          uz = currentAtom->getOrntZ();
255 >          // Directional Atoms have standard unit vectors which are oriented
256 >          // in space using the three Euler angles.  We assume the standard
257 >          // unit vector was originally along the z axis below.
258  
259 <          uSqr = (ux * ux) + (uy * uy) + (uz * uz);
259 >          phi = currentAtom->getEulerPhi() * M_PI / 180.0;
260 >          theta = currentAtom->getEulerTheta() * M_PI / 180.0;
261 >          psi = currentAtom->getEulerPsi()* M_PI / 180.0;
262  
263 <          u = sqrt(uSqr);
264 <          ux = ux / u;
199 <          uy = uy / u;
200 <          uz = uz / u;
201 <
202 <          dAtom->setSUx(ux);
203 <          dAtom->setSUy(uy);
204 <          dAtom->setSUz(uz);
263 >          dAtom->setUnitFrameFromEuler(phi, theta, psi);
264 >            
265          }
266          else{
267 <          molInfo.myAtoms[j] = new GeneralAtom((j + atomOffset),
268 <                                               info[k].getConfiguration());
267 >
268 >          molInfo.myAtoms[j] = new Atom((j + atomOffset), info[k].getConfiguration());
269 >
270          }
210        molInfo.myAtoms[j]->setType(currentAtom->getType());
271  
272 +        molInfo.myAtoms[j]->setType(currentAtom->getType());
273   #ifdef IS_MPI
274  
275 <        molInfo.myAtoms[j]->setGlobalIndex(globalIndex[j + atomOffset]);
275 >        molInfo.myAtoms[j]->setGlobalIndex(globalAtomIndex[j + atomOffset]);
276  
277   #endif // is_mpi
278        }
# Line 222 | Line 283 | void SimSetup::makeMolecules(void){
283          theBonds[j].a = currentBond->getA() + atomOffset;
284          theBonds[j].b = currentBond->getB() + atomOffset;
285  
286 <        exI = theBonds[j].a;
287 <        exJ = theBonds[j].b;
286 >        tempI = theBonds[j].a;
287 >        tempJ = theBonds[j].b;
288  
228        // exclude_I must always be the smaller of the pair
229        if (exI > exJ){
230          tempEx = exI;
231          exI = exJ;
232          exJ = tempEx;
233        }
289   #ifdef IS_MPI
290 <        tempEx = exI;
291 <        exI = info[k].atoms[tempEx]->getGlobalIndex() + 1;
292 <        tempEx = exJ;
293 <        exJ = info[k].atoms[tempEx]->getGlobalIndex() + 1;
290 >        exI = info[k].atoms[tempI]->getGlobalIndex() + 1;
291 >        exJ = info[k].atoms[tempJ]->getGlobalIndex() + 1;
292 > #else
293 >        exI = tempI + 1;
294 >        exJ = tempJ + 1;
295 > #endif
296  
297 <        info[k].excludes[j + excludeOffset]->setPair(exI, exJ);
241 < #else  // isn't MPI
242 <
243 <        info[k].excludes[j + excludeOffset]->setPair((exI + 1), (exJ + 1));
244 < #endif  //is_mpi
297 >        info[k].excludes->addPair(exI, exJ);
298        }
246      excludeOffset += molInfo.nBonds;
299  
300        //make the bends
301        for (j = 0; j < molInfo.nBends; j++){
# Line 293 | Line 345 | void SimSetup::makeMolecules(void){
345            }
346          }
347  
348 <        if (!theBends[j].isGhost){
349 <          exI = theBends[j].a;
350 <          exJ = theBends[j].c;
351 <        }
352 <        else{
301 <          exI = theBends[j].a;
302 <          exJ = theBends[j].b;
303 <        }
304 <
305 <        // exclude_I must always be the smaller of the pair
306 <        if (exI > exJ){
307 <          tempEx = exI;
308 <          exI = exJ;
309 <          exJ = tempEx;
310 <        }
348 >        if (theBends[j].isGhost) {
349 >          
350 >          tempI = theBends[j].a;
351 >          tempJ = theBends[j].b;
352 >          
353   #ifdef IS_MPI
354 <        tempEx = exI;
355 <        exI = info[k].atoms[tempEx]->getGlobalIndex() + 1;
356 <        tempEx = exJ;
357 <        exJ = info[k].atoms[tempEx]->getGlobalIndex() + 1;
354 >          exI = info[k].atoms[tempI]->getGlobalIndex() + 1;
355 >          exJ = info[k].atoms[tempJ]->getGlobalIndex() + 1;
356 > #else
357 >          exI = tempI + 1;
358 >          exJ = tempJ + 1;
359 > #endif          
360 >          info[k].excludes->addPair(exI, exJ);
361  
362 <        info[k].excludes[j + excludeOffset]->setPair(exI, exJ);
363 < #else  // isn't MPI
364 <        info[k].excludes[j + excludeOffset]->setPair((exI + 1), (exJ + 1));
365 < #endif  //is_mpi
362 >        } else {
363 >
364 >          tempI = theBends[j].a;
365 >          tempJ = theBends[j].b;
366 >          tempK = theBends[j].c;
367 >          
368 > #ifdef IS_MPI
369 >          exI = info[k].atoms[tempI]->getGlobalIndex() + 1;
370 >          exJ = info[k].atoms[tempJ]->getGlobalIndex() + 1;
371 >          exK = info[k].atoms[tempK]->getGlobalIndex() + 1;
372 > #else
373 >          exI = tempI + 1;
374 >          exJ = tempJ + 1;
375 >          exK = tempK + 1;
376 > #endif
377 >          
378 >          info[k].excludes->addPair(exI, exK);
379 >          info[k].excludes->addPair(exI, exJ);
380 >          info[k].excludes->addPair(exJ, exK);
381 >        }
382        }
322      excludeOffset += molInfo.nBends;
383  
384        for (j = 0; j < molInfo.nTorsions; j++){
385          currentTorsion = comp_stamps[stampID]->getTorsion(j);
# Line 328 | Line 388 | void SimSetup::makeMolecules(void){
388          theTorsions[j].c = currentTorsion->getC() + atomOffset;
389          theTorsions[j].d = currentTorsion->getD() + atomOffset;
390  
391 <        exI = theTorsions[j].a;
392 <        exJ = theTorsions[j].d;
391 >        tempI = theTorsions[j].a;      
392 >        tempJ = theTorsions[j].b;
393 >        tempK = theTorsions[j].c;
394 >        tempL = theTorsions[j].d;
395  
334        // exclude_I must always be the smaller of the pair
335        if (exI > exJ){
336          tempEx = exI;
337          exI = exJ;
338          exJ = tempEx;
339        }
396   #ifdef IS_MPI
397 <        tempEx = exI;
398 <        exI = info[k].atoms[tempEx]->getGlobalIndex() + 1;
399 <        tempEx = exJ;
400 <        exJ = info[k].atoms[tempEx]->getGlobalIndex() + 1;
397 >        exI = info[k].atoms[tempI]->getGlobalIndex() + 1;
398 >        exJ = info[k].atoms[tempJ]->getGlobalIndex() + 1;
399 >        exK = info[k].atoms[tempK]->getGlobalIndex() + 1;
400 >        exL = info[k].atoms[tempL]->getGlobalIndex() + 1;
401 > #else
402 >        exI = tempI + 1;
403 >        exJ = tempJ + 1;
404 >        exK = tempK + 1;
405 >        exL = tempL + 1;
406 > #endif
407  
408 <        info[k].excludes[j + excludeOffset]->setPair(exI, exJ);
409 < #else  // isn't MPI
410 <        info[k].excludes[j + excludeOffset]->setPair((exI + 1), (exJ + 1));
411 < #endif  //is_mpi
408 >        info[k].excludes->addPair(exI, exJ);
409 >        info[k].excludes->addPair(exI, exK);
410 >        info[k].excludes->addPair(exI, exL);        
411 >        info[k].excludes->addPair(exJ, exK);
412 >        info[k].excludes->addPair(exJ, exL);
413 >        info[k].excludes->addPair(exK, exL);
414        }
351      excludeOffset += molInfo.nTorsions;
415  
416 +      
417 +      molInfo.myRigidBodies.clear();
418 +      
419 +      for (j = 0; j < molInfo.nRigidBodies; j++){
420  
421 <      // send the arrays off to the forceField for init.
421 >        currentRigidBody = comp_stamps[stampID]->getRigidBody(j);
422 >        nMembers = currentRigidBody->getNMembers();
423  
424 +        // Create the Rigid Body:
425 +
426 +        myRB = new RigidBody();
427 +
428 +        sprintf(rbName,"%s_RB_%d", molName, j);
429 +        myRB->setType(rbName);
430 +        
431 +        for (rb1 = 0; rb1 < nMembers; rb1++) {
432 +
433 +          // molI is atom numbering inside this molecule
434 +          molI = currentRigidBody->getMember(rb1);    
435 +
436 +          // tempI is atom numbering on local processor
437 +          tempI = molI + atomOffset;
438 +
439 +          // currentAtom is the AtomStamp (which we need for
440 +          // rigid body reference positions)
441 +          currentAtom = comp_stamps[stampID]->getAtom(molI);
442 +
443 +          // When we add to the rigid body, add the atom itself and
444 +          // the stamp info:
445 +
446 +          myRB->addAtom(info[k].atoms[tempI], currentAtom);
447 +          
448 +          // Add this atom to the Skip List for the integrators
449 + #ifdef IS_MPI
450 +          slI = info[k].atoms[tempI]->getGlobalIndex();
451 + #else
452 +          slI = tempI;
453 + #endif
454 +          skipList.insert(slI);
455 +          
456 +        }
457 +        
458 +        for(rb1 = 0; rb1 < nMembers - 1; rb1++) {
459 +          for(rb2 = rb1+1; rb2 < nMembers; rb2++) {
460 +            
461 +            tempI = currentRigidBody->getMember(rb1);
462 +            tempJ = currentRigidBody->getMember(rb2);
463 +            
464 +            // Some explanation is required here.
465 +            // Fortran indexing starts at 1, while c indexing starts at 0
466 +            // Also, in parallel computations, the GlobalIndex is
467 +            // used for the exclude list:
468 +            
469 + #ifdef IS_MPI
470 +            exI = molInfo.myAtoms[tempI]->getGlobalIndex() + 1;
471 +            exJ = molInfo.myAtoms[tempJ]->getGlobalIndex() + 1;
472 + #else
473 +            exI = molInfo.myAtoms[tempI]->getIndex() + 1;
474 +            exJ = molInfo.myAtoms[tempJ]->getIndex() + 1;
475 + #endif
476 +            
477 +            info[k].excludes->addPair(exI, exJ);
478 +            
479 +          }
480 +        }
481 +
482 +        molInfo.myRigidBodies.push_back(myRB);
483 +        info[k].rigidBodies.push_back(myRB);
484 +      }
485 +      
486 +
487 +      //create cutoff group for molecule
488 +      molInfo.myCutoffGroups.clear();
489 +      for (j = 0; j < molInfo.nCutoffGroups; j++){
490 +
491 +        currentCutoffGroup = comp_stamps[stampID]->getCutoffGroup(j);
492 +        nMembers = currentCutoffGroup->getNMembers();
493 +
494 +        myCutoffGroup = new CutoffGroup();
495 +        
496 +        for (int cg = 0; cg < nMembers; cg++) {
497 +
498 +          // molI is atom numbering inside this molecule
499 +          molI = currentCutoffGroup->getMember(cg);    
500 +
501 +          // tempI is atom numbering on local processor
502 +          tempI = molI + atomOffset;
503 +
504 +          myCutoffGroup->addAtom(info[k].atoms[tempI]);          
505 +        }
506 +
507 +        molInfo.myCutoffGroups.push_back(myCutoffGroup);
508 +      }//end for (j = 0; j < molInfo.nCutoffGroups; j++)
509 +      
510 +
511 +
512 +      // After this is all set up, scan through the atoms to
513 +      // see if they can be added to the integrableObjects:
514 +
515 +      molInfo.myIntegrableObjects.clear();
516 +      
517 +
518 +      for (j = 0; j < molInfo.nAtoms; j++){
519 +
520 + #ifdef IS_MPI
521 +        slJ = molInfo.myAtoms[j]->getGlobalIndex();
522 + #else
523 +        slJ = j+atomOffset;
524 + #endif
525 +
526 +        // if they aren't on the skip list, then they can be integrated
527 +
528 +        if (skipList.find(slJ) == skipList.end()) {
529 +          mySD = (StuntDouble *) molInfo.myAtoms[j];
530 +          info[k].integrableObjects.push_back(mySD);
531 +          molInfo.myIntegrableObjects.push_back(mySD);
532 +        }
533 +      }
534 +
535 +      // all rigid bodies are integrated:
536 +
537 +      for (j = 0; j < molInfo.nRigidBodies; j++) {
538 +        mySD = (StuntDouble *) molInfo.myRigidBodies[j];
539 +        info[k].integrableObjects.push_back(mySD);      
540 +        molInfo.myIntegrableObjects.push_back(mySD);
541 +      }
542 +    
543 +      
544 +      // send the arrays off to the forceField for init.
545 +      
546        the_ff->initializeAtoms(molInfo.nAtoms, molInfo.myAtoms);
547        the_ff->initializeBonds(molInfo.nBonds, molInfo.myBonds, theBonds);
548        the_ff->initializeBends(molInfo.nBends, molInfo.myBends, theBends);
549        the_ff->initializeTorsions(molInfo.nTorsions, molInfo.myTorsions,
550                                   theTorsions);
551  
362
552        info[k].molecules[i].initialize(molInfo);
553  
554  
# Line 367 | Line 556 | void SimSetup::makeMolecules(void){
556        delete[] theBonds;
557        delete[] theBends;
558        delete[] theTorsions;
559 <    }
559 >    }    
560    }
561  
562   #ifdef IS_MPI
# Line 375 | Line 564 | void SimSetup::makeMolecules(void){
564    MPIcheckPoint();
565   #endif // is_mpi
566  
378  // clean up the forcefield
379
380  the_ff->calcRcut();
381  the_ff->cleanMe();
567   }
568  
569   void SimSetup::initFromBass(void){
# Line 551 | Line 736 | void SimSetup::gatherInfo(void){
736  
737  
738   void SimSetup::gatherInfo(void){
739 <  int i, j, k;
739 >  int i;
740  
741    ensembleCase = -1;
742    ffCase = -1;
# Line 579 | Line 764 | void SimSetup::gatherInfo(void){
764    else if (!strcasecmp(force_field, "EAM")){
765      ffCase = FF_EAM;
766    }
767 +  else if (!strcasecmp(force_field, "WATER")){
768 +    ffCase = FF_H2O;
769 +  }
770    else{
771      sprintf(painCave.errMsg, "SimSetup Error. Unrecognized force field -> %s\n",
772              force_field);
# Line 602 | Line 790 | void SimSetup::gatherInfo(void){
790    else if (!strcasecmp(ensemble, "NPTf")){
791      ensembleCase = NPTf_ENS;
792    }
793 +  else if (!strcasecmp(ensemble, "NPTxyz")){
794 +    ensembleCase = NPTxyz_ENS;
795 +  }
796    else{
797      sprintf(painCave.errMsg,
798 <            "SimSetup Warning. Unrecognized Ensemble -> %s, "
799 <            "reverting to NVE for this simulation.\n",
798 >            "SimSetup Warning. Unrecognized Ensemble -> %s \n"
799 >            "\treverting to NVE for this simulation.\n",
800              ensemble);
801           painCave.isFatal = 0;
802           simError();
# Line 637 | Line 828 | void SimSetup::gatherInfo(void){
828        if (!the_components[i]->haveNMol()){
829          // we have a problem
830          sprintf(painCave.errMsg,
831 <                "SimSetup Error. No global NMol or component NMol"
832 <                " given. Cannot calculate the number of atoms.\n");
831 >                "SimSetup Error. No global NMol or component NMol given.\n"
832 >                "\tCannot calculate the number of atoms.\n");
833          painCave.isFatal = 1;
834          simError();
835        }
# Line 656 | Line 847 | void SimSetup::gatherInfo(void){
847              " Please give nMol in the components.\n");
848      painCave.isFatal = 1;
849      simError();
850 +  }
851 +
852 +  //check whether sample time, status time, thermal time and reset time are divisble by dt
853 +  if (globals->haveSampleTime() && !isDivisible(globals->getSampleTime(), globals->getDt())){
854 +    sprintf(painCave.errMsg,
855 +            "Sample time is not divisible by dt.\n"
856 +            "\tThis will result in samples that are not uniformly\n"
857 +            "\tdistributed in time.  If this is a problem, change\n"
858 +            "\tyour sampleTime variable.\n");
859 +    painCave.isFatal = 0;
860 +    simError();    
861    }
862  
863 +  if (globals->haveStatusTime() && !isDivisible(globals->getStatusTime(), globals->getDt())){
864 +    sprintf(painCave.errMsg,
865 +            "Status time is not divisible by dt.\n"
866 +            "\tThis will result in status reports that are not uniformly\n"
867 +            "\tdistributed in time.  If this is a problem, change \n"
868 +            "\tyour statusTime variable.\n");
869 +    painCave.isFatal = 0;
870 +    simError();    
871 +  }
872 +
873 +  if (globals->haveThermalTime() && !isDivisible(globals->getThermalTime(), globals->getDt())){
874 +    sprintf(painCave.errMsg,
875 +            "Thermal time is not divisible by dt.\n"
876 +            "\tThis will result in thermalizations that are not uniformly\n"
877 +            "\tdistributed in time.  If this is a problem, change \n"
878 +            "\tyour thermalTime variable.\n");
879 +    painCave.isFatal = 0;
880 +    simError();    
881 +  }  
882 +
883 +  if (globals->haveResetTime() && !isDivisible(globals->getResetTime(), globals->getDt())){
884 +    sprintf(painCave.errMsg,
885 +            "Reset time is not divisible by dt.\n"
886 +            "\tThis will result in integrator resets that are not uniformly\n"
887 +            "\tdistributed in time.  If this is a problem, change\n"
888 +            "\tyour resetTime variable.\n");
889 +    painCave.isFatal = 0;
890 +    simError();    
891 +  }
892 +
893    // set the status, sample, and thermal kick times
894  
895    for (i = 0; i < nInfo; i++){
896      if (globals->haveSampleTime()){
897        info[i].sampleTime = globals->getSampleTime();
898        info[i].statusTime = info[i].sampleTime;
667      info[i].thermalTime = info[i].sampleTime;
899      }
900      else{
901        info[i].sampleTime = globals->getRunTime();
902        info[i].statusTime = info[i].sampleTime;
672      info[i].thermalTime = info[i].sampleTime;
903      }
904  
905      if (globals->haveStatusTime()){
# Line 678 | Line 908 | void SimSetup::gatherInfo(void){
908  
909      if (globals->haveThermalTime()){
910        info[i].thermalTime = globals->getThermalTime();
911 +    } else {
912 +      info[i].thermalTime = globals->getRunTime();
913      }
914  
915      info[i].resetIntegrator = 0;
# Line 687 | Line 919 | void SimSetup::gatherInfo(void){
919      }
920  
921      // check for the temperature set flag
922 <
922 >    
923      if (globals->haveTempSet())
924        info[i].setTemp = globals->getTempSet();
925  
926 <    // get some of the tricky things that may still be in the globals
926 >    // check for the extended State init
927  
928 <    double boxVector[3];
929 <    if (globals->haveBox()){
930 <      boxVector[0] = globals->getBox();
699 <      boxVector[1] = globals->getBox();
700 <      boxVector[2] = globals->getBox();
701 <
702 <      info[i].setBox(boxVector);
703 <    }
704 <    else if (globals->haveDensity()){
705 <      double vol;
706 <      vol = (double) tot_nmol / globals->getDensity();
707 <      boxVector[0] = pow(vol, (1.0 / 3.0));
708 <      boxVector[1] = boxVector[0];
709 <      boxVector[2] = boxVector[0];
710 <
711 <      info[i].setBox(boxVector);
712 <    }
713 <    else{
714 <      if (!globals->haveBoxX()){
715 <        sprintf(painCave.errMsg,
716 <                "SimSetup error, no periodic BoxX size given.\n");
717 <        painCave.isFatal = 1;
718 <        simError();
719 <      }
720 <      boxVector[0] = globals->getBoxX();
721 <
722 <      if (!globals->haveBoxY()){
723 <        sprintf(painCave.errMsg,
724 <                "SimSetup error, no periodic BoxY size given.\n");
725 <        painCave.isFatal = 1;
726 <        simError();
727 <      }
728 <      boxVector[1] = globals->getBoxY();
729 <
730 <      if (!globals->haveBoxZ()){
731 <        sprintf(painCave.errMsg,
732 <                "SimSetup error, no periodic BoxZ size given.\n");
733 <        painCave.isFatal = 1;
734 <        simError();
735 <      }
736 <      boxVector[2] = globals->getBoxZ();
737 <
738 <      info[i].setBox(boxVector);
739 <    }
928 >    info[i].useInitXSstate = globals->getUseInitXSstate();
929 >    info[i].orthoTolerance = globals->getOrthoBoxTolerance();
930 >    
931    }
932 <
932 >  
933    //setup seed for random number generator
934    int seedValue;
935  
# Line 778 | Line 969 | void SimSetup::gatherInfo(void){
969    for (int i = 0; i < nInfo; i++){
970      info[i].setSeed(seedValue);
971    }
972 <
972 >  
973   #ifdef IS_MPI
974 <  strcpy(checkPointMsg, "Succesfully gathered all information from Bass\n");
974 >  strcpy(checkPointMsg, "Successfully gathered all information from Bass\n");
975    MPIcheckPoint();
976   #endif // is_mpi
977   }
# Line 789 | Line 980 | void SimSetup::finalInfoCheck(void){
980   void SimSetup::finalInfoCheck(void){
981    int index;
982    int usesDipoles;
983 +  int usesCharges;
984    int i;
985  
986    for (i = 0; i < nInfo; i++){
# Line 800 | Line 992 | void SimSetup::finalInfoCheck(void){
992        usesDipoles = (info[i].atoms[index])->hasDipole();
993        index++;
994      }
995 <
995 >    index = 0;
996 >    usesCharges = 0;
997 >    while ((index < info[i].n_atoms) && !usesCharges){
998 >      usesCharges= (info[i].atoms[index])->hasCharge();
999 >      index++;
1000 >    }
1001   #ifdef IS_MPI
1002      int myUse = usesDipoles;
1003      MPI_Allreduce(&myUse, &usesDipoles, 1, MPI_INT, MPI_LOR, MPI_COMM_WORLD);
1004   #endif //is_mpi
1005  
1006 <    double theEcr, theEst;
1006 >    double theRcut, theRsw;
1007  
1008 +    if (globals->haveRcut()) {
1009 +      theRcut = globals->getRcut();
1010 +
1011 +      if (globals->haveRsw())
1012 +        theRsw = globals->getRsw();
1013 +      else
1014 +        theRsw = theRcut;
1015 +      
1016 +      info[i].setDefaultRcut(theRcut, theRsw);
1017 +
1018 +    } else {
1019 +      
1020 +      the_ff->calcRcut();
1021 +      theRcut = info[i].getRcut();
1022 +
1023 +      if (globals->haveRsw())
1024 +        theRsw = globals->getRsw();
1025 +      else
1026 +        theRsw = theRcut;
1027 +      
1028 +      info[i].setDefaultRcut(theRcut, theRsw);
1029 +    }
1030 +
1031      if (globals->getUseRF()){
1032        info[i].useReactionField = 1;
1033 <
1034 <      if (!globals->haveECR()){
1033 >      
1034 >      if (!globals->haveRcut()){
1035          sprintf(painCave.errMsg,
1036 <                "SimSetup Warning: using default value of 1/2 the smallest "
1037 <                "box length for the electrostaticCutoffRadius.\n"
1038 <                "I hope you have a very fast processor!\n");
1036 >                "SimSetup Warning: No value was set for the cutoffRadius.\n"
1037 >                "\tOOPSE will use a default value of 15.0 angstroms"
1038 >                "\tfor the cutoffRadius.\n");
1039          painCave.isFatal = 0;
1040          simError();
1041 <        double smallest;
822 <        smallest = info[i].boxL[0];
823 <        if (info[i].boxL[1] <= smallest)
824 <          smallest = info[i].boxL[1];
825 <        if (info[i].boxL[2] <= smallest)
826 <          smallest = info[i].boxL[2];
827 <        theEcr = 0.5 * smallest;
1041 >        theRcut = 15.0;
1042        }
1043        else{
1044 <        theEcr = globals->getECR();
1044 >        theRcut = globals->getRcut();
1045        }
1046  
1047 <      if (!globals->haveEST()){
1047 >      if (!globals->haveRsw()){
1048          sprintf(painCave.errMsg,
1049 <                "SimSetup Warning: using default value of 0.05 * the "
1050 <                "electrostaticCutoffRadius for the electrostaticSkinThickness\n");
1049 >                "SimSetup Warning: No value was set for switchingRadius.\n"
1050 >                "\tOOPSE will use a default value of\n"
1051 >                "\t0.95 * cutoffRadius for the switchingRadius\n");
1052          painCave.isFatal = 0;
1053          simError();
1054 <        theEst = 0.05 * theEcr;
1054 >        theRsw = 0.95 * theRcut;
1055        }
1056        else{
1057 <        theEst = globals->getEST();
1057 >        theRsw = globals->getRsw();
1058        }
1059  
1060 <      info[i].setEcr(theEcr, theEst);
1060 >      info[i].setDefaultRcut(theRcut, theRsw);
1061  
1062        if (!globals->haveDielectric()){
1063          sprintf(painCave.errMsg,
1064 <                "SimSetup Error: You are trying to use Reaction Field without"
1065 <                "setting a dielectric constant!\n");
1064 >                "SimSetup Error: No Dielectric constant was set.\n"
1065 >                "\tYou are trying to use Reaction Field without"
1066 >                "\tsetting a dielectric constant!\n");
1067          painCave.isFatal = 1;
1068          simError();
1069        }
1070        info[i].dielectric = globals->getDielectric();
1071      }
1072      else{
1073 <      if (usesDipoles){
858 <        if (!globals->haveECR()){
859 <          sprintf(painCave.errMsg,
860 <                  "SimSetup Warning: using default value of 1/2 the smallest "
861 <                  "box length for the electrostaticCutoffRadius.\n"
862 <                  "I hope you have a very fast processor!\n");
863 <          painCave.isFatal = 0;
864 <          simError();
865 <          double smallest;
866 <          smallest = info[i].boxL[0];
867 <          if (info[i].boxL[1] <= smallest)
868 <            smallest = info[i].boxL[1];
869 <          if (info[i].boxL[2] <= smallest)
870 <            smallest = info[i].boxL[2];
871 <          theEcr = 0.5 * smallest;
872 <        }
873 <        else{
874 <          theEcr = globals->getECR();
875 <        }
1073 >      if (usesDipoles || usesCharges){
1074  
1075 <        if (!globals->haveEST()){
1075 >        if (!globals->haveRcut()){
1076            sprintf(painCave.errMsg,
1077 <                  "SimSetup Warning: using default value of 0.05 * the "
1078 <                  "electrostaticCutoffRadius for the "
1079 <                  "electrostaticSkinThickness\n");
1077 >                  "SimSetup Warning: No value was set for the cutoffRadius.\n"
1078 >                  "\tOOPSE will use a default value of 15.0 angstroms"
1079 >                  "\tfor the cutoffRadius.\n");
1080            painCave.isFatal = 0;
1081            simError();
1082 <          theEst = 0.05 * theEcr;
1082 >          theRcut = 15.0;
1083 >      }
1084 >        else{
1085 >          theRcut = globals->getRcut();
1086          }
1087 +        
1088 +        if (!globals->haveRsw()){
1089 +          sprintf(painCave.errMsg,
1090 +                  "SimSetup Warning: No value was set for switchingRadius.\n"
1091 +                  "\tOOPSE will use a default value of\n"
1092 +                  "\t0.95 * cutoffRadius for the switchingRadius\n");
1093 +          painCave.isFatal = 0;
1094 +          simError();
1095 +          theRsw = 0.95 * theRcut;
1096 +        }
1097          else{
1098 <          theEst = globals->getEST();
1098 >          theRsw = globals->getRsw();
1099          }
1100 <
1101 <        info[i].setEcr(theEcr, theEst);
1100 >        
1101 >        info[i].setDefaultRcut(theRcut, theRsw);
1102 >        
1103        }
1104      }
1105    }
894
1106   #ifdef IS_MPI
1107    strcpy(checkPointMsg, "post processing checks out");
1108    MPIcheckPoint();
1109   #endif // is_mpi
899 }
1110  
1111 +  // clean up the forcefield
1112 +  the_ff->cleanMe();
1113 + }
1114 +  
1115   void SimSetup::initSystemCoords(void){
1116    int i;
1117  
# Line 914 | Line 1128 | void SimSetup::initSystemCoords(void){
1128      if (worldRank == 0){
1129   #endif //is_mpi
1130        inName = globals->getInitialConfig();
917      double* tempDouble = new double[1000000];
1131        fileInit = new InitializeFromFile(inName);
1132   #ifdef IS_MPI
1133      }
# Line 926 | Line 1139 | void SimSetup::initSystemCoords(void){
1139      delete fileInit;
1140    }
1141    else{
1142 < #ifdef IS_MPI
930 <
1142 >    
1143      // no init from bass
1144 <
1144 >    
1145      sprintf(painCave.errMsg,
1146 <            "Cannot intialize a parallel simulation without an initial configuration file.\n");
1147 <    painCave.isFatal;
1146 >            "Cannot intialize a simulation without an initial configuration file.\n");
1147 >    painCave.isFatal = 1;;
1148      simError();
1149 <
938 < #else
939 <
940 <    initFromBass();
941 <
942 <
943 < #endif
1149 >    
1150    }
1151  
1152   #ifdef IS_MPI
# Line 1094 | Line 1300 | void SimSetup::createFF(void){
1300        the_ff = new EAM_FF();
1301        break;
1302  
1303 +    case FF_H2O:
1304 +      the_ff = new WATER();
1305 +      break;
1306 +
1307      default:
1308        sprintf(painCave.errMsg,
1309                "SimSetup Error. Unrecognized force field in case statement.\n");
# Line 1114 | Line 1324 | void SimSetup::compList(void){
1324    LinkedMolStamp* headStamp = new LinkedMolStamp();
1325    LinkedMolStamp* currentStamp = NULL;
1326    comp_stamps = new MoleculeStamp * [n_components];
1327 +  bool haveCutoffGroups;
1328  
1329 +  haveCutoffGroups = false;
1330 +  
1331    // make an array of molecule stamps that match the components used.
1332    // also extract the used stamps out into a separate linked list
1333  
# Line 1149 | Line 1362 | void SimSetup::compList(void){
1362        headStamp->add(currentStamp);
1363        comp_stamps[i] = headStamp->match(id);
1364      }
1365 +
1366 +    if(comp_stamps[i]->getNCutoffGroups() > 0)
1367 +      haveCutoffGroups = true;    
1368    }
1369 +    
1370 +  for (i = 0; i < nInfo; i++)
1371 +    info[i].haveCutoffGroups = haveCutoffGroups;
1372  
1373   #ifdef IS_MPI
1374    strcpy(checkPointMsg, "Component stamps successfully extracted\n");
# Line 1158 | Line 1377 | void SimSetup::calcSysValues(void){
1377   }
1378  
1379   void SimSetup::calcSysValues(void){
1380 <  int i, j, k;
1380 >  int i;
1381  
1382    int* molMembershipArray;
1383  
# Line 1166 | Line 1385 | void SimSetup::calcSysValues(void){
1385    tot_bonds = 0;
1386    tot_bends = 0;
1387    tot_torsions = 0;
1388 +  tot_rigid = 0;
1389    for (i = 0; i < n_components; i++){
1390      tot_atoms += components_nmol[i] * comp_stamps[i]->getNAtoms();
1391      tot_bonds += components_nmol[i] * comp_stamps[i]->getNBonds();
1392      tot_bends += components_nmol[i] * comp_stamps[i]->getNBends();
1393      tot_torsions += components_nmol[i] * comp_stamps[i]->getNTorsions();
1394 +    tot_rigid += components_nmol[i] * comp_stamps[i]->getNRigidBodies();
1395    }
1396 <
1396 >  
1397    tot_SRI = tot_bonds + tot_bends + tot_torsions;
1398    molMembershipArray = new int[tot_atoms];
1399  
# Line 1194 | Line 1415 | void SimSetup::mpiMolDivide(void){
1415    int i, j, k;
1416    int localMol, allMol;
1417    int local_atoms, local_bonds, local_bends, local_torsions, local_SRI;
1418 +  int local_rigid;
1419 +  vector<int> globalMolIndex;
1420  
1421    mpiSim = new mpiSimulation(info);
1422  
1423 <  globalIndex = mpiSim->divideLabor();
1423 >  mpiSim->divideLabor();
1424 >  globalAtomIndex = mpiSim->getGlobalAtomIndex();
1425 >  //globalMolIndex = mpiSim->getGlobalMolIndex();
1426  
1427    // set up the local variables
1428  
# Line 1210 | Line 1435 | void SimSetup::mpiMolDivide(void){
1435    local_bonds = 0;
1436    local_bends = 0;
1437    local_torsions = 0;
1438 <  globalAtomIndex = 0;
1438 >  local_rigid = 0;
1439 >  globalAtomCounter = 0;
1440  
1215
1441    for (i = 0; i < n_components; i++){
1442      for (j = 0; j < components_nmol[i]; j++){
1443        if (mol2proc[allMol] == worldRank){
# Line 1220 | Line 1445 | void SimSetup::mpiMolDivide(void){
1445          local_bonds += comp_stamps[i]->getNBonds();
1446          local_bends += comp_stamps[i]->getNBends();
1447          local_torsions += comp_stamps[i]->getNTorsions();
1448 +        local_rigid += comp_stamps[i]->getNRigidBodies();
1449          localMol++;
1450        }      
1451        for (k = 0; k < comp_stamps[i]->getNAtoms(); k++){
1452 <        info[0].molMembershipArray[globalAtomIndex] = allMol;
1453 <        globalAtomIndex++;
1452 >        info[0].molMembershipArray[globalAtomCounter] = allMol;
1453 >        globalAtomCounter++;
1454        }
1455  
1456        allMol++;
# Line 1233 | Line 1459 | void SimSetup::mpiMolDivide(void){
1459    local_SRI = local_bonds + local_bends + local_torsions;
1460  
1461    info[0].n_atoms = mpiSim->getMyNlocal();  
1462 +  
1463  
1464    if (local_atoms != info[0].n_atoms){
1465      sprintf(painCave.errMsg,
1466 <            "SimSetup error: mpiSim's localAtom (%d) and SimSetup's"
1467 <            " localAtom (%d) are not equal.\n",
1466 >            "SimSetup error: mpiSim's localAtom (%d) and SimSetup's\n"
1467 >            "\tlocalAtom (%d) are not equal.\n",
1468              info[0].n_atoms, local_atoms);
1469      painCave.isFatal = 1;
1470      simError();
# Line 1257 | Line 1484 | void SimSetup::makeSysArrays(void){
1484  
1485  
1486   void SimSetup::makeSysArrays(void){
1487 <  int i, j, k, l;
1487 >
1488 > #ifndef IS_MPI
1489 >  int k, j;
1490 > #endif // is_mpi
1491 >  int i, l;
1492  
1493    Atom** the_atoms;
1494    Molecule* the_molecules;
1264  Exclude** the_excludes;
1495  
1266
1496    for (l = 0; l < nInfo; l++){
1497      // create the atom and short range interaction arrays
1498  
# Line 1289 | Line 1518 | void SimSetup::makeSysArrays(void){
1518   #else // is_mpi
1519  
1520      molIndex = 0;
1521 <    globalAtomIndex = 0;
1521 >    globalAtomCounter = 0;
1522      for (i = 0; i < n_components; i++){
1523        for (j = 0; j < components_nmol[i]; j++){
1524          the_molecules[molIndex].setStampID(i);
1525          the_molecules[molIndex].setMyIndex(molIndex);
1526          the_molecules[molIndex].setGlobalIndex(molIndex);
1527          for (k = 0; k < comp_stamps[i]->getNAtoms(); k++){
1528 <          info[l].molMembershipArray[globalAtomIndex] = molIndex;
1529 <          globalAtomIndex++;
1528 >          info[l].molMembershipArray[globalAtomCounter] = molIndex;
1529 >          globalAtomCounter++;
1530          }
1531          molIndex++;
1532        }
# Line 1306 | Line 1535 | void SimSetup::makeSysArrays(void){
1535  
1536   #endif // is_mpi
1537  
1538 <
1539 <    if (info[l].n_SRI){
1540 <      Exclude::createArray(info[l].n_SRI);
1312 <      the_excludes = new Exclude * [info[l].n_SRI];
1313 <      for (int ex = 0; ex < info[l].n_SRI; ex++){
1314 <        the_excludes[ex] = new Exclude(ex);
1315 <      }
1316 <      info[l].globalExcludes = new int;
1317 <      info[l].n_exclude = info[l].n_SRI;
1318 <    }
1319 <    else{
1320 <      Exclude::createArray(1);
1321 <      the_excludes = new Exclude * ;
1322 <      the_excludes[0] = new Exclude(0);
1323 <      the_excludes[0]->setPair(0, 0);
1324 <      info[l].globalExcludes = new int;
1325 <      info[l].globalExcludes[0] = 0;
1326 <      info[l].n_exclude = 0;
1327 <    }
1328 <
1538 >    info[l].globalExcludes = new int;
1539 >    info[l].globalExcludes[0] = 0;
1540 >    
1541      // set the arrays into the SimInfo object
1542  
1543      info[l].atoms = the_atoms;
1544      info[l].molecules = the_molecules;
1545      info[l].nGlobalExcludes = 0;
1546 <    info[l].excludes = the_excludes;
1335 <
1546 >    
1547      the_ff->setSimInfo(info);
1548    }
1549   }
# Line 1340 | Line 1551 | void SimSetup::makeIntegrator(void){
1551   void SimSetup::makeIntegrator(void){
1552    int k;
1553  
1554 +  NVE<RealIntegrator>* myNVE = NULL;
1555    NVT<RealIntegrator>* myNVT = NULL;
1556    NPTi<NPT<RealIntegrator> >* myNPTi = NULL;
1557    NPTf<NPT<RealIntegrator> >* myNPTf = NULL;
1558 +  NPTxyz<NPT<RealIntegrator> >* myNPTxyz = NULL;
1559    
1560    for (k = 0; k < nInfo; k++){
1561      switch (ensembleCase){
1562        case NVE_ENS:
1563          if (globals->haveZconstraints()){
1564            setupZConstraint(info[k]);
1565 <          new ZConstraint<NVE<RealIntegrator> >(&(info[k]), the_ff);
1565 >          myNVE = new ZConstraint<NVE<RealIntegrator> >(&(info[k]), the_ff);
1566          }
1567 <        else
1568 <          new NVE<RealIntegrator>(&(info[k]), the_ff);
1567 >        else{
1568 >          myNVE = new NVE<RealIntegrator>(&(info[k]), the_ff);
1569 >        }
1570 >        
1571 >        info->the_integrator = myNVE;
1572          break;
1573  
1574        case NVT_ENS:
# Line 1370 | Line 1586 | void SimSetup::makeIntegrator(void){
1586          else{
1587            sprintf(painCave.errMsg,
1588                    "SimSetup error: If you use the NVT\n"
1589 <                  "    ensemble, you must set tauThermostat.\n");
1589 >                  "\tensemble, you must set tauThermostat.\n");
1590            painCave.isFatal = 1;
1591            simError();
1592          }
1593 +
1594 +        info->the_integrator = myNVT;
1595          break;
1596  
1597        case NPTi_ENS:
# Line 1391 | Line 1609 | void SimSetup::makeIntegrator(void){
1609          else{
1610            sprintf(painCave.errMsg,
1611                    "SimSetup error: If you use a constant pressure\n"
1612 <                  "    ensemble, you must set targetPressure in the BASS file.\n");
1612 >                  "\tensemble, you must set targetPressure in the BASS file.\n");
1613            painCave.isFatal = 1;
1614            simError();
1615          }
# Line 1401 | Line 1619 | void SimSetup::makeIntegrator(void){
1619          else{
1620            sprintf(painCave.errMsg,
1621                    "SimSetup error: If you use an NPT\n"
1622 <                  "    ensemble, you must set tauThermostat.\n");
1622 >                  "\tensemble, you must set tauThermostat.\n");
1623            painCave.isFatal = 1;
1624            simError();
1625          }
# Line 1411 | Line 1629 | void SimSetup::makeIntegrator(void){
1629          else{
1630            sprintf(painCave.errMsg,
1631                    "SimSetup error: If you use an NPT\n"
1632 <                  "    ensemble, you must set tauBarostat.\n");
1632 >                  "\tensemble, you must set tauBarostat.\n");
1633            painCave.isFatal = 1;
1634            simError();
1635          }
1636 +
1637 +        info->the_integrator = myNPTi;
1638          break;
1639  
1640        case NPTf_ENS:
# Line 1432 | Line 1652 | void SimSetup::makeIntegrator(void){
1652          else{
1653            sprintf(painCave.errMsg,
1654                    "SimSetup error: If you use a constant pressure\n"
1655 <                  "    ensemble, you must set targetPressure in the BASS file.\n");
1655 >                  "\tensemble, you must set targetPressure in the BASS file.\n");
1656            painCave.isFatal = 1;
1657            simError();
1658          }    
1659  
1660          if (globals->haveTauThermostat())
1661            myNPTf->setTauThermostat(globals->getTauThermostat());
1662 +
1663          else{
1664            sprintf(painCave.errMsg,
1665                    "SimSetup error: If you use an NPT\n"
1666 <                  "    ensemble, you must set tauThermostat.\n");
1666 >                  "\tensemble, you must set tauThermostat.\n");
1667            painCave.isFatal = 1;
1668            simError();
1669          }
1670  
1671          if (globals->haveTauBarostat())
1672            myNPTf->setTauBarostat(globals->getTauBarostat());
1673 +
1674          else{
1675            sprintf(painCave.errMsg,
1676                    "SimSetup error: If you use an NPT\n"
1677 <                  "    ensemble, you must set tauBarostat.\n");
1677 >                  "\tensemble, you must set tauBarostat.\n");
1678            painCave.isFatal = 1;
1679            simError();
1680          }
1681 +
1682 +        info->the_integrator = myNPTf;
1683          break;
1684  
1685 +      case NPTxyz_ENS:
1686 +        if (globals->haveZconstraints()){
1687 +          setupZConstraint(info[k]);
1688 +          myNPTxyz = new ZConstraint<NPTxyz<NPT <RealIntegrator> > >(&(info[k]), the_ff);
1689 +        }
1690 +        else
1691 +          myNPTxyz = new NPTxyz<NPT <RealIntegrator> >(&(info[k]), the_ff);
1692 +
1693 +        myNPTxyz->setTargetTemp(globals->getTargetTemp());
1694 +
1695 +        if (globals->haveTargetPressure())
1696 +          myNPTxyz->setTargetPressure(globals->getTargetPressure());
1697 +        else{
1698 +          sprintf(painCave.errMsg,
1699 +                  "SimSetup error: If you use a constant pressure\n"
1700 +                  "\tensemble, you must set targetPressure in the BASS file.\n");
1701 +          painCave.isFatal = 1;
1702 +          simError();
1703 +        }    
1704 +
1705 +        if (globals->haveTauThermostat())
1706 +          myNPTxyz->setTauThermostat(globals->getTauThermostat());
1707 +        else{
1708 +          sprintf(painCave.errMsg,
1709 +                  "SimSetup error: If you use an NPT\n"
1710 +                  "\tensemble, you must set tauThermostat.\n");
1711 +          painCave.isFatal = 1;
1712 +          simError();
1713 +        }
1714 +
1715 +        if (globals->haveTauBarostat())
1716 +          myNPTxyz->setTauBarostat(globals->getTauBarostat());
1717 +        else{
1718 +          sprintf(painCave.errMsg,
1719 +                  "SimSetup error: If you use an NPT\n"
1720 +                  "\tensemble, you must set tauBarostat.\n");
1721 +          painCave.isFatal = 1;
1722 +          simError();
1723 +        }
1724 +
1725 +        info->the_integrator = myNPTxyz;
1726 +        break;
1727 +
1728        default:
1729          sprintf(painCave.errMsg,
1730                  "SimSetup Error. Unrecognized ensemble in case statement.\n");
# Line 1503 | Line 1770 | void SimSetup::setupZConstraint(SimInfo& theInfo){
1770    }
1771    else{
1772      sprintf(painCave.errMsg,
1773 <            "ZConstraint error: If you use an ZConstraint\n"
1774 <            " , you must set sample time.\n");
1773 >            "ZConstraint error: If you use a ZConstraint,\n"
1774 >            "\tyou must set zconsTime.\n");
1775      painCave.isFatal = 1;
1776      simError();
1777    }
# Line 1519 | Line 1786 | void SimSetup::setupZConstraint(SimInfo& theInfo){
1786    else{
1787      double defaultZConsTol = 0.01;
1788      sprintf(painCave.errMsg,
1789 <            "ZConstraint Waring: Tolerance for z-constraint methodl is not specified\n"
1790 <            " , default value %f is used.\n",
1789 >            "ZConstraint Warning: Tolerance for z-constraint method is not specified.\n"
1790 >            "\tOOPSE will use a default value of %f.\n"
1791 >            "\tTo set the tolerance, use the zconsTol variable.\n",
1792              defaultZConsTol);
1793      painCave.isFatal = 0;
1794      simError();      
# Line 1538 | Line 1806 | void SimSetup::setupZConstraint(SimInfo& theInfo){
1806    }
1807    else{
1808      sprintf(painCave.errMsg,
1809 <            "ZConstraint Warning: User does not set force Subtraction policy, "
1810 <            "PolicyByMass is used\n");
1809 >            "ZConstraint Warning: No force subtraction policy was set.\n"
1810 >            "\tOOPSE will use PolicyByMass.\n"
1811 >            "\tTo set the policy, use the zconsForcePolicy variable.\n");
1812      painCave.isFatal = 0;
1813      simError();
1814      zconsForcePolicy->setData("BYMASS");
# Line 1547 | Line 1816 | void SimSetup::setupZConstraint(SimInfo& theInfo){
1816  
1817    theInfo.addProperty(zconsForcePolicy);
1818  
1819 +  //set zcons gap
1820 +  DoubleData* zconsGap = new DoubleData();
1821 +  zconsGap->setID(ZCONSGAP_ID);
1822 +
1823 +  if (globals->haveZConsGap()){
1824 +    zconsGap->setData(globals->getZconsGap());
1825 +    theInfo.addProperty(zconsGap);  
1826 +  }
1827 +
1828 +  //set zcons fixtime
1829 +  DoubleData* zconsFixtime = new DoubleData();
1830 +  zconsFixtime->setID(ZCONSFIXTIME_ID);
1831 +
1832 +  if (globals->haveZConsFixTime()){
1833 +    zconsFixtime->setData(globals->getZconsFixtime());
1834 +    theInfo.addProperty(zconsFixtime);  
1835 +  }
1836 +
1837 +  //set zconsUsingSMD
1838 +  IntData* zconsUsingSMD = new IntData();
1839 +  zconsUsingSMD->setID(ZCONSUSINGSMD_ID);
1840 +
1841 +  if (globals->haveZConsUsingSMD()){
1842 +    zconsUsingSMD->setData(globals->getZconsUsingSMD());
1843 +    theInfo.addProperty(zconsUsingSMD);  
1844 +  }
1845 +
1846    //Determine the name of ouput file and add it into SimInfo's property list
1847    //Be careful, do not use inFileName, since it is a pointer which
1848    //point to a string at master node, and slave nodes do not contain that string
# Line 1576 | Line 1872 | void SimSetup::setupZConstraint(SimInfo& theInfo){
1872      tempParaItem.zPos = zconStamp[i]->getZpos();
1873      tempParaItem.zconsIndex = zconStamp[i]->getMolIndex();
1874      tempParaItem.kRatio = zconStamp[i]->getKratio();
1875 <
1875 >    tempParaItem.havingCantVel = zconStamp[i]->haveCantVel();
1876 >    tempParaItem.cantVel = zconStamp[i]->getCantVel();    
1877      zconsParaData->addItem(tempParaItem);
1878    }
1879  
1880    //check the uniqueness of index  
1881    if(!zconsParaData->isIndexUnique()){
1882      sprintf(painCave.errMsg,
1883 <            "ZConstraint Error: molIndex is not unique\n");
1883 >            "ZConstraint Error: molIndex is not unique!\n");
1884      painCave.isFatal = 1;
1885      simError();
1886    }
# Line 1594 | Line 1891 | void SimSetup::setupZConstraint(SimInfo& theInfo){
1891    //push data into siminfo, therefore, we can retrieve later
1892    theInfo.addProperty(zconsParaData);
1893   }
1894 +
1895 + void SimSetup::makeMinimizer(){
1896 +
1897 +  OOPSEMinimizer* myOOPSEMinimizer;
1898 +  MinimizerParameterSet* param;
1899 +  char minimizerName[100];
1900 +  
1901 +  for (int i = 0; i < nInfo; i++){
1902 +    
1903 +    //prepare parameter set for minimizer
1904 +    param = new MinimizerParameterSet();
1905 +    param->setDefaultParameter();
1906 +
1907 +    if (globals->haveMinimizer()){
1908 +      param->setFTol(globals->getMinFTol());
1909 +    }
1910 +
1911 +    if (globals->haveMinGTol()){
1912 +      param->setGTol(globals->getMinGTol());
1913 +    }
1914 +
1915 +    if (globals->haveMinMaxIter()){
1916 +      param->setMaxIteration(globals->getMinMaxIter());
1917 +    }
1918 +
1919 +    if (globals->haveMinWriteFrq()){
1920 +      param->setMaxIteration(globals->getMinMaxIter());
1921 +    }
1922 +
1923 +    if (globals->haveMinWriteFrq()){
1924 +      param->setWriteFrq(globals->getMinWriteFrq());
1925 +    }
1926 +    
1927 +    if (globals->haveMinStepSize()){
1928 +      param->setStepSize(globals->getMinStepSize());
1929 +    }
1930 +
1931 +    if (globals->haveMinLSMaxIter()){
1932 +      param->setLineSearchMaxIteration(globals->getMinLSMaxIter());
1933 +    }    
1934 +
1935 +    if (globals->haveMinLSTol()){
1936 +      param->setLineSearchTol(globals->getMinLSTol());
1937 +    }    
1938 +
1939 +    strcpy(minimizerName, globals->getMinimizer());
1940 +
1941 +    if (!strcasecmp(minimizerName, "CG")){
1942 +      myOOPSEMinimizer = new PRCGMinimizer(&(info[i]), the_ff, param);
1943 +    }
1944 +    else if (!strcasecmp(minimizerName, "SD")){
1945 +    //myOOPSEMinimizer = MinimizerFactory.creatMinimizer("", &(info[i]), the_ff, param);
1946 +      myOOPSEMinimizer = new SDMinimizer(&(info[i]), the_ff, param);
1947 +    }
1948 +    else{
1949 +          sprintf(painCave.errMsg,
1950 +                  "SimSetup error: Unrecognized Minimizer, use Conjugate Gradient \n");
1951 +          painCave.isFatal = 0;
1952 +          simError();
1953 +
1954 +      myOOPSEMinimizer = new PRCGMinimizer(&(info[i]), the_ff, param);          
1955 +    }
1956 +     info[i].the_integrator = myOOPSEMinimizer;
1957 +
1958 +     //store the minimizer into simInfo
1959 +     info[i].the_minimizer = myOOPSEMinimizer;
1960 +     info[i].has_minimizer = true;
1961 +  }
1962 +
1963 + }

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines