ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/group/trunk/OOPSE/libmdtools/SimSetup.cpp
Revision: 1212
Committed: Tue Jun 1 17:15:43 2004 UTC (20 years, 3 months ago) by chrisfen
File size: 61015 byte(s)
Log Message:
Implemented a separate solid and liquid thermodynamic integration routines

File Contents

# User Rev Content
1 tim 658 #include <algorithm>
2 gezelter 829 #include <stdlib.h>
3 mmeineke 377 #include <iostream>
4 gezelter 829 #include <math.h>
5 tim 658 #include <string>
6 tim 722 #include <sprng.h>
7 mmeineke 377 #include "SimSetup.hpp"
8 tim 689 #include "ReadWrite.hpp"
9 mmeineke 377 #include "parse_me.h"
10     #include "Integrator.hpp"
11     #include "simError.h"
12 gezelter 1097 #include "RigidBody.hpp"
13 tim 1064 #include "OOPSEMinimizer.hpp"
14 tim 1211 //#include "ConstraintElement.hpp"
15     //#include "ConstraintPair.hpp"
16 mmeineke 377
17     #ifdef IS_MPI
18     #include "mpiBASS.h"
19     #include "mpiSimulation.hpp"
20     #endif
21    
22 mmeineke 557 // some defines for ensemble and Forcefield cases
23    
24 tim 660 #define NVE_ENS 0
25     #define NVT_ENS 1
26     #define NPTi_ENS 2
27     #define NPTf_ENS 3
28 mmeineke 812 #define NPTxyz_ENS 4
29 mmeineke 557
30 mmeineke 812
31 chrisfen 999 #define FF_DUFF 0
32     #define FF_LJ 1
33     #define FF_EAM 2
34 chrisfen 1041 #define FF_H2O 3
35 mmeineke 557
36 tim 658 using namespace std;
37    
38 tim 962 /**
39     * Check whether dividend is divisble by divisor or not
40     */
41     bool isDivisible(double dividend, double divisor){
42     double tolerance = 0.000001;
43     double quotient;
44     double diff;
45     int intQuotient;
46    
47     quotient = dividend / divisor;
48    
49     if (quotient < 0)
50     quotient = -quotient;
51    
52     intQuotient = int (quotient + tolerance);
53    
54     diff = fabs(fabs(dividend) - intQuotient * fabs(divisor));
55    
56     if (diff <= tolerance)
57     return true;
58     else
59     return false;
60     }
61    
62 mmeineke 377 SimSetup::SimSetup(){
63 mmeineke 823
64     initSuspend = false;
65 mmeineke 656 isInfoArray = 0;
66     nInfo = 1;
67 tim 722
68 mmeineke 377 stamps = new MakeStamps();
69     globals = new Globals();
70 tim 722
71    
72 mmeineke 377 #ifdef IS_MPI
73 tim 722 strcpy(checkPointMsg, "SimSetup creation successful");
74 mmeineke 377 MPIcheckPoint();
75     #endif // IS_MPI
76     }
77    
78     SimSetup::~SimSetup(){
79     delete stamps;
80     delete globals;
81     }
82    
83 tim 722 void SimSetup::setSimInfo(SimInfo* the_info, int theNinfo){
84     info = the_info;
85     nInfo = theNinfo;
86     isInfoArray = 1;
87 mmeineke 823 initSuspend = true;
88 mmeineke 670 }
89 mmeineke 656
90    
91 tim 722 void SimSetup::parseFile(char* fileName){
92 mmeineke 377 #ifdef IS_MPI
93 tim 722 if (worldRank == 0){
94 mmeineke 377 #endif // is_mpi
95 tim 722
96 mmeineke 377 inFileName = fileName;
97 tim 722 set_interface_stamps(stamps, globals);
98    
99 mmeineke 377 #ifdef IS_MPI
100     mpiEventInit();
101     #endif
102    
103 tim 722 yacc_BASS(fileName);
104 mmeineke 377
105     #ifdef IS_MPI
106     throwMPIEvent(NULL);
107     }
108 tim 722 else{
109     receiveParse();
110     }
111 mmeineke 377 #endif
112    
113     }
114    
115     #ifdef IS_MPI
116     void SimSetup::receiveParse(void){
117 tim 722 set_interface_stamps(stamps, globals);
118     mpiEventInit();
119     MPIcheckPoint();
120     mpiEventLoop();
121 mmeineke 377 }
122    
123     #endif // is_mpi
124    
125 mmeineke 670 void SimSetup::createSim(void){
126 mmeineke 377
127 mmeineke 614 // gather all of the information from the Bass file
128 tim 689
129 mmeineke 614 gatherInfo();
130 mmeineke 377
131 mmeineke 614 // creation of complex system objects
132 mmeineke 377
133 mmeineke 614 sysObjectsCreation();
134 mmeineke 377
135 mmeineke 859 // check on the post processing info
136    
137     finalInfoCheck();
138    
139 mmeineke 614 // initialize the system coordinates
140 mmeineke 377
141 mmeineke 823 if ( !initSuspend ){
142 tim 722 initSystemCoords();
143 mmeineke 811
144     if( !(globals->getUseInitTime()) )
145     info[0].currentTime = 0.0;
146 tim 722 }
147 mmeineke 377
148 mmeineke 614 // make the output filenames
149 mmeineke 377
150 mmeineke 614 makeOutNames();
151 tim 1113
152     #ifdef IS_MPI
153     mpiSim->mpiRefresh();
154     #endif
155 tim 722
156 tim 1113 // initialize the Fortran
157    
158     initFortran();
159    
160 tim 1031 if (globals->haveMinimizer())
161     // make minimizer
162     makeMinimizer();
163     else
164     // make the integrator
165     makeIntegrator();
166 mmeineke 377
167     }
168    
169 mmeineke 407
170 tim 722 void SimSetup::makeMolecules(void){
171 gezelter 1097 int i, j, k;
172 gezelter 1104 int exI, exJ, exK, exL, slI, slJ;
173 gezelter 1097 int tempI, tempJ, tempK, tempL;
174     int molI;
175     int stampID, atomOffset, rbOffset;
176 mmeineke 616 molInit molInfo;
177 mmeineke 407 DirectionalAtom* dAtom;
178 gezelter 1097 RigidBody* myRB;
179     StuntDouble* mySD;
180 mmeineke 412 LinkedAssign* extras;
181     LinkedAssign* current_extra;
182 mmeineke 407 AtomStamp* currentAtom;
183     BondStamp* currentBond;
184     BendStamp* currentBend;
185     TorsionStamp* currentTorsion;
186 gezelter 1097 RigidBodyStamp* currentRigidBody;
187 tim 1157 CutoffGroupStamp* currentCutoffGroup;
188     CutoffGroup* myCutoffGroup;
189 tim 1167 int nCutoffGroups;// number of cutoff group of a molecule defined in mdl file
190     set<int> cutoffAtomSet; //atoms belong to cutoffgroup defined at mdl file
191    
192 mmeineke 427 bond_pair* theBonds;
193     bend_set* theBends;
194     torsion_set* theTorsions;
195    
196 gezelter 1097 set<int> skipList;
197    
198     double phi, theta, psi;
199 tim 1108 char* molName;
200     char rbName[100];
201 gezelter 1097
202 tim 1211 //ConstraintPair* consPair; //constraint pair
203     //ConstraintElement* consElement1; //first element of constraint pair
204     //ConstraintElement* consElement2; //second element of constraint pair
205     //int whichRigidBody;
206     //int consAtomIndex; //index of constraint atom in rigid body's atom array
207     //vector<pair<int, int> > jointAtoms;
208 mmeineke 407 //init the forceField paramters
209    
210     the_ff->readParams();
211    
212 mmeineke 427 // init the atoms
213 mmeineke 407
214 gezelter 1097 int nMembers, nNew, rb1, rb2;
215 mmeineke 407
216 tim 722 for (k = 0; k < nInfo; k++){
217     the_ff->setSimInfo(&(info[k]));
218    
219 mmeineke 670 atomOffset = 0;
220 tim 1211 groupOffset = 0;
221 gezelter 1097
222 tim 722 for (i = 0; i < info[k].n_mol; i++){
223 mmeineke 670 stampID = info[k].molecules[i].getStampID();
224 tim 1108 molName = comp_stamps[stampID]->getID();
225 mmeineke 412
226 tim 722 molInfo.nAtoms = comp_stamps[stampID]->getNAtoms();
227     molInfo.nBonds = comp_stamps[stampID]->getNBonds();
228     molInfo.nBends = comp_stamps[stampID]->getNBends();
229 mmeineke 670 molInfo.nTorsions = comp_stamps[stampID]->getNTorsions();
230 gezelter 1097 molInfo.nRigidBodies = comp_stamps[stampID]->getNRigidBodies();
231 tim 1167
232     nCutoffGroups = comp_stamps[stampID]->getNCutoffGroups();
233 gezelter 1097
234 mmeineke 670 molInfo.myAtoms = &(info[k].atoms[atomOffset]);
235 mmeineke 407
236 gezelter 1097 if (molInfo.nBonds > 0)
237 gezelter 1174 molInfo.myBonds = new Bond*[molInfo.nBonds];
238 gezelter 1097 else
239     molInfo.myBonds = NULL;
240    
241     if (molInfo.nBends > 0)
242 gezelter 1174 molInfo.myBends = new Bend*[molInfo.nBends];
243 gezelter 1097 else
244     molInfo.myBends = NULL;
245    
246     if (molInfo.nTorsions > 0)
247 gezelter 1174 molInfo.myTorsions = new Torsion *[molInfo.nTorsions];
248 gezelter 1097 else
249     molInfo.myTorsions = NULL;
250    
251 mmeineke 670 theBonds = new bond_pair[molInfo.nBonds];
252     theBends = new bend_set[molInfo.nBends];
253     theTorsions = new torsion_set[molInfo.nTorsions];
254 gezelter 1097
255 mmeineke 670 // make the Atoms
256 tim 722
257     for (j = 0; j < molInfo.nAtoms; j++){
258     currentAtom = comp_stamps[stampID]->getAtom(j);
259 gezelter 1097
260 tim 722 if (currentAtom->haveOrientation()){
261     dAtom = new DirectionalAtom((j + atomOffset),
262     info[k].getConfiguration());
263     info[k].n_oriented++;
264     molInfo.myAtoms[j] = dAtom;
265    
266 gezelter 983 // Directional Atoms have standard unit vectors which are oriented
267     // in space using the three Euler angles. We assume the standard
268     // unit vector was originally along the z axis below.
269 tim 722
270 gezelter 984 phi = currentAtom->getEulerPhi() * M_PI / 180.0;
271     theta = currentAtom->getEulerTheta() * M_PI / 180.0;
272     psi = currentAtom->getEulerPsi()* M_PI / 180.0;
273 gezelter 1097
274     dAtom->setUnitFrameFromEuler(phi, theta, psi);
275 gezelter 983
276 tim 722 }
277     else{
278 gezelter 1097
279     molInfo.myAtoms[j] = new Atom((j + atomOffset), info[k].getConfiguration());
280 tim 1113
281 tim 722 }
282 gezelter 1097
283 tim 722 molInfo.myAtoms[j]->setType(currentAtom->getType());
284 mmeineke 407 #ifdef IS_MPI
285 tim 722
286 tim 1108 molInfo.myAtoms[j]->setGlobalIndex(globalAtomIndex[j + atomOffset]);
287 tim 722
288 mmeineke 407 #endif // is_mpi
289 mmeineke 670 }
290 tim 722
291     // make the bonds
292     for (j = 0; j < molInfo.nBonds; j++){
293     currentBond = comp_stamps[stampID]->getBond(j);
294     theBonds[j].a = currentBond->getA() + atomOffset;
295     theBonds[j].b = currentBond->getB() + atomOffset;
296    
297 gezelter 1097 tempI = theBonds[j].a;
298     tempJ = theBonds[j].b;
299 tim 722
300 mmeineke 670 #ifdef IS_MPI
301 gezelter 1097 exI = info[k].atoms[tempI]->getGlobalIndex() + 1;
302     exJ = info[k].atoms[tempJ]->getGlobalIndex() + 1;
303     #else
304     exI = tempI + 1;
305     exJ = tempJ + 1;
306     #endif
307 tim 722
308 gezelter 1097 info[k].excludes->addPair(exI, exJ);
309 mmeineke 670 }
310 tim 722
311 mmeineke 670 //make the bends
312 tim 722 for (j = 0; j < molInfo.nBends; j++){
313     currentBend = comp_stamps[stampID]->getBend(j);
314     theBends[j].a = currentBend->getA() + atomOffset;
315     theBends[j].b = currentBend->getB() + atomOffset;
316     theBends[j].c = currentBend->getC() + atomOffset;
317    
318     if (currentBend->haveExtras()){
319     extras = currentBend->getExtras();
320     current_extra = extras;
321    
322     while (current_extra != NULL){
323     if (!strcmp(current_extra->getlhs(), "ghostVectorSource")){
324     switch (current_extra->getType()){
325     case 0:
326     theBends[j].ghost = current_extra->getInt() + atomOffset;
327     theBends[j].isGhost = 1;
328     break;
329    
330     case 1:
331     theBends[j].ghost = (int) current_extra->getDouble() +
332     atomOffset;
333     theBends[j].isGhost = 1;
334     break;
335    
336     default:
337     sprintf(painCave.errMsg,
338     "SimSetup Error: ghostVectorSource was neither a "
339     "double nor an int.\n"
340     "-->Bend[%d] in %s\n",
341     j, comp_stamps[stampID]->getID());
342     painCave.isFatal = 1;
343     simError();
344     }
345     }
346     else{
347     sprintf(painCave.errMsg,
348     "SimSetup Error: unhandled bend assignment:\n"
349     " -->%s in Bend[%d] in %s\n",
350     current_extra->getlhs(), j, comp_stamps[stampID]->getID());
351     painCave.isFatal = 1;
352     simError();
353     }
354    
355     current_extra = current_extra->getNext();
356     }
357 tim 701 }
358 tim 722
359 gezelter 1097 if (theBends[j].isGhost) {
360    
361     tempI = theBends[j].a;
362     tempJ = theBends[j].b;
363    
364     #ifdef IS_MPI
365     exI = info[k].atoms[tempI]->getGlobalIndex() + 1;
366     exJ = info[k].atoms[tempJ]->getGlobalIndex() + 1;
367     #else
368     exI = tempI + 1;
369     exJ = tempJ + 1;
370     #endif
371     info[k].excludes->addPair(exI, exJ);
372 tim 722
373 gezelter 1097 } else {
374    
375     tempI = theBends[j].a;
376     tempJ = theBends[j].b;
377     tempK = theBends[j].c;
378    
379     #ifdef IS_MPI
380     exI = info[k].atoms[tempI]->getGlobalIndex() + 1;
381     exJ = info[k].atoms[tempJ]->getGlobalIndex() + 1;
382     exK = info[k].atoms[tempK]->getGlobalIndex() + 1;
383     #else
384     exI = tempI + 1;
385     exJ = tempJ + 1;
386     exK = tempK + 1;
387     #endif
388    
389     info[k].excludes->addPair(exI, exK);
390     info[k].excludes->addPair(exI, exJ);
391     info[k].excludes->addPair(exJ, exK);
392 tim 722 }
393 mmeineke 412 }
394 tim 722
395     for (j = 0; j < molInfo.nTorsions; j++){
396     currentTorsion = comp_stamps[stampID]->getTorsion(j);
397     theTorsions[j].a = currentTorsion->getA() + atomOffset;
398     theTorsions[j].b = currentTorsion->getB() + atomOffset;
399     theTorsions[j].c = currentTorsion->getC() + atomOffset;
400     theTorsions[j].d = currentTorsion->getD() + atomOffset;
401    
402 gezelter 1097 tempI = theTorsions[j].a;
403     tempJ = theTorsions[j].b;
404     tempK = theTorsions[j].c;
405     tempL = theTorsions[j].d;
406 tim 722
407 mmeineke 670 #ifdef IS_MPI
408 gezelter 1097 exI = info[k].atoms[tempI]->getGlobalIndex() + 1;
409     exJ = info[k].atoms[tempJ]->getGlobalIndex() + 1;
410     exK = info[k].atoms[tempK]->getGlobalIndex() + 1;
411     exL = info[k].atoms[tempL]->getGlobalIndex() + 1;
412     #else
413     exI = tempI + 1;
414     exJ = tempJ + 1;
415     exK = tempK + 1;
416     exL = tempL + 1;
417     #endif
418 tim 722
419 gezelter 1097 info[k].excludes->addPair(exI, exJ);
420     info[k].excludes->addPair(exI, exK);
421     info[k].excludes->addPair(exI, exL);
422     info[k].excludes->addPair(exJ, exK);
423     info[k].excludes->addPair(exJ, exL);
424     info[k].excludes->addPair(exK, exL);
425 mmeineke 670 }
426 tim 722
427 tim 1113
428     molInfo.myRigidBodies.clear();
429    
430 gezelter 1097 for (j = 0; j < molInfo.nRigidBodies; j++){
431 tim 722
432 gezelter 1097 currentRigidBody = comp_stamps[stampID]->getRigidBody(j);
433     nMembers = currentRigidBody->getNMembers();
434    
435     // Create the Rigid Body:
436    
437     myRB = new RigidBody();
438 tim 1108
439 tim 1113 sprintf(rbName,"%s_RB_%d", molName, j);
440 tim 1108 myRB->setType(rbName);
441 gezelter 1097
442     for (rb1 = 0; rb1 < nMembers; rb1++) {
443    
444     // molI is atom numbering inside this molecule
445     molI = currentRigidBody->getMember(rb1);
446    
447     // tempI is atom numbering on local processor
448     tempI = molI + atomOffset;
449    
450     // currentAtom is the AtomStamp (which we need for
451     // rigid body reference positions)
452     currentAtom = comp_stamps[stampID]->getAtom(molI);
453    
454     // When we add to the rigid body, add the atom itself and
455     // the stamp info:
456    
457     myRB->addAtom(info[k].atoms[tempI], currentAtom);
458    
459     // Add this atom to the Skip List for the integrators
460     #ifdef IS_MPI
461     slI = info[k].atoms[tempI]->getGlobalIndex();
462     #else
463     slI = tempI;
464     #endif
465     skipList.insert(slI);
466    
467     }
468    
469     for(rb1 = 0; rb1 < nMembers - 1; rb1++) {
470     for(rb2 = rb1+1; rb2 < nMembers; rb2++) {
471    
472     tempI = currentRigidBody->getMember(rb1);
473     tempJ = currentRigidBody->getMember(rb2);
474    
475     // Some explanation is required here.
476     // Fortran indexing starts at 1, while c indexing starts at 0
477     // Also, in parallel computations, the GlobalIndex is
478     // used for the exclude list:
479    
480     #ifdef IS_MPI
481 tim 1116 exI = molInfo.myAtoms[tempI]->getGlobalIndex() + 1;
482     exJ = molInfo.myAtoms[tempJ]->getGlobalIndex() + 1;
483 gezelter 1097 #else
484 tim 1116 exI = molInfo.myAtoms[tempI]->getIndex() + 1;
485     exJ = molInfo.myAtoms[tempJ]->getIndex() + 1;
486 gezelter 1097 #endif
487    
488     info[k].excludes->addPair(exI, exJ);
489    
490     }
491     }
492 gezelter 1104
493     molInfo.myRigidBodies.push_back(myRB);
494     info[k].rigidBodies.push_back(myRB);
495 gezelter 1097 }
496    
497 gezelter 1104
498 gezelter 1163 //create cutoff group for molecule
499 tim 1167
500     cutoffAtomSet.clear();
501 tim 1157 molInfo.myCutoffGroups.clear();
502 tim 1167
503     for (j = 0; j < nCutoffGroups; j++){
504 tim 1157
505     currentCutoffGroup = comp_stamps[stampID]->getCutoffGroup(j);
506     nMembers = currentCutoffGroup->getNMembers();
507    
508     myCutoffGroup = new CutoffGroup();
509 tim 1211 myCutoffGroup->setGlobalIndex(globalGroupIndex[j + groupOffset]);
510 tim 1157
511     for (int cg = 0; cg < nMembers; cg++) {
512    
513     // molI is atom numbering inside this molecule
514     molI = currentCutoffGroup->getMember(cg);
515    
516     // tempI is atom numbering on local processor
517     tempI = molI + atomOffset;
518 tim 1211
519     #ifdef IS_MPI
520     globalID = info[k].atoms[tempI]->getGlobalIndex()
521     #else
522     globalID = info[k].atoms[tempI]->getIndex();
523     #endif
524    
525     globalGroupMembership[globalID] = globalGroupIndex[j+groupOffset];
526    
527 tim 1167 myCutoffGroup->addAtom(info[k].atoms[tempI]);
528 tim 1157
529 tim 1167 cutoffAtomSet.insert(tempI);
530 tim 1157 }
531 tim 1211
532     molInfo.myCutoffGroups.push_back(myCutoffGroup);
533     groupOffset++;
534 tim 1157
535     }//end for (j = 0; j < molInfo.nCutoffGroups; j++)
536    
537 tim 1167 //creat a cutoff group for every atom in current molecule which does not belong to cutoffgroup defined at mdl file
538 tim 1157
539 tim 1167 for(j = 0; j < molInfo.nAtoms; j++){
540    
541     if(cutoffAtomSet.find(molInfo.myAtoms[j]->getIndex()) == cutoffAtomSet.end()){
542     myCutoffGroup = new CutoffGroup();
543     myCutoffGroup->addAtom(molInfo.myAtoms[j]);
544 tim 1211 myCutoffGroup->setGlobalIndex(globalGroupIndex[j + groupOffset]);
545     #ifdef IS_MPI
546     globalID = info[k].atoms[atomOffset + j]->getGlobalIndex()
547     #else
548     globalID = info[k].atoms[atomOffset + j]->getIndex();
549     #endif
550     globalGroupMembership[globalID] = globalGroupIndex[j+groupOffset];
551 tim 1167 molInfo.myCutoffGroups.push_back(myCutoffGroup);
552 tim 1211 groupOffset++;
553 tim 1167 }
554    
555     }
556    
557 gezelter 1104 // After this is all set up, scan through the atoms to
558     // see if they can be added to the integrableObjects:
559    
560 tim 1113 molInfo.myIntegrableObjects.clear();
561    
562    
563 gezelter 1104 for (j = 0; j < molInfo.nAtoms; j++){
564    
565     #ifdef IS_MPI
566     slJ = molInfo.myAtoms[j]->getGlobalIndex();
567     #else
568     slJ = j+atomOffset;
569     #endif
570    
571     // if they aren't on the skip list, then they can be integrated
572    
573     if (skipList.find(slJ) == skipList.end()) {
574     mySD = (StuntDouble *) molInfo.myAtoms[j];
575     info[k].integrableObjects.push_back(mySD);
576     molInfo.myIntegrableObjects.push_back(mySD);
577     }
578     }
579    
580     // all rigid bodies are integrated:
581    
582     for (j = 0; j < molInfo.nRigidBodies; j++) {
583     mySD = (StuntDouble *) molInfo.myRigidBodies[j];
584     info[k].integrableObjects.push_back(mySD);
585     molInfo.myIntegrableObjects.push_back(mySD);
586     }
587 tim 1211
588    
589     /*
590    
591     //creat ConstraintPair.
592     molInfo.myConstraintPair.clear();
593 gezelter 1104
594 tim 1211 for (j = 0; j < molInfo.nBonds; j++){
595    
596     //if both atoms are in the same rigid body, just skip it
597     currentBond = comp_stamps[stampID]->getBond(j);
598     if(!comp_stamps[stampID]->isBondInSameRigidBody(currentBond)){
599    
600     tempI = currentBond->getA() + atomOffset;
601     if( comp_stamps[stampID]->isAtomInRigidBody(currentBond->getA(), whichRigidBody, consAtomIndex))
602     consElement1 = new ConstraintRigidBody(molInfo.myRigidBodies[whichRigidBody], consAtomIndex);
603     else
604     consElement1 = new ConstraintAtom(info[k].atoms[tempI]);
605    
606     tempJ = currentBond->getB() + atomOffset;
607     if(comp_stamps[stampID]->isAtomInRigidBody(currentBond->getB(), whichRigidBody, consAtomIndex))
608     consElement2 = new ConstraintRigidBody(molInfo.myRigidBodies[whichRigidBody], consAtomIndex);
609     else
610     consElement2 = new ConstraintAtom(info[k].atoms[tempJ]);
611    
612     consPair = new DistanceConstraintPair(consElement1, consElement2);
613     molInfo.myConstraintPairs.push_back(consPair);
614     }
615     }
616    
617     //loop over rigid bodies, if two rigid bodies share same joint, creat a HingeConstraintPair
618     for (int rb1 = 0; rb1 < molInfo.nRigidBodies -1 ; rb1++){
619     for (int rb2 = rb1 + 1; rb2 < molInfo.nRigidBodies ; rb2++){
620    
621     jointAtoms = comp_stamps[stampID]->getJointAtoms(rb1, rb2);
622    
623     for(size_t m = 0; m < jointAtoms.size(); m++){
624     consElement1 = new ConstraintRigidBody(molInfo.myRigidBodies[rb1], jointAtoms[m].first);
625     consElement2 = new ConstraintRigidBody(molInfo.myRigidBodies[rb2], jointAtoms[m].second);
626    
627     consPair = new JointConstraintPair(consElement1, consElement2);
628     molInfo.myConstraintPairs.push_back(consPair);
629     }
630    
631     }
632     }
633    
634     */
635 mmeineke 670 // send the arrays off to the forceField for init.
636 gezelter 1097
637 tim 722 the_ff->initializeAtoms(molInfo.nAtoms, molInfo.myAtoms);
638     the_ff->initializeBonds(molInfo.nBonds, molInfo.myBonds, theBonds);
639     the_ff->initializeBends(molInfo.nBends, molInfo.myBends, theBends);
640     the_ff->initializeTorsions(molInfo.nTorsions, molInfo.myTorsions,
641     theTorsions);
642    
643     info[k].molecules[i].initialize(molInfo);
644    
645    
646 mmeineke 670 atomOffset += molInfo.nAtoms;
647     delete[] theBonds;
648     delete[] theBends;
649     delete[] theTorsions;
650 gezelter 1104 }
651 mmeineke 414 }
652 tim 722
653 chuckv 434 #ifdef IS_MPI
654 tim 722 sprintf(checkPointMsg, "all molecules initialized succesfully");
655 chuckv 434 MPIcheckPoint();
656     #endif // is_mpi
657 tim 722
658 mmeineke 414 }
659 mmeineke 407
660 tim 722 void SimSetup::initFromBass(void){
661 mmeineke 377 int i, j, k;
662     int n_cells;
663     double cellx, celly, cellz;
664     double temp1, temp2, temp3;
665     int n_per_extra;
666     int n_extra;
667     int have_extra, done;
668    
669 mmeineke 670 double vel[3];
670     vel[0] = 0.0;
671     vel[1] = 0.0;
672     vel[2] = 0.0;
673    
674 tim 722 temp1 = (double) tot_nmol / 4.0;
675     temp2 = pow(temp1, (1.0 / 3.0));
676     temp3 = ceil(temp2);
677 mmeineke 377
678 tim 722 have_extra = 0;
679     if (temp2 < temp3){
680     // we have a non-complete lattice
681     have_extra = 1;
682 mmeineke 377
683 tim 722 n_cells = (int) temp3 - 1;
684 mmeineke 670 cellx = info[0].boxL[0] / temp3;
685     celly = info[0].boxL[1] / temp3;
686     cellz = info[0].boxL[2] / temp3;
687 tim 722 n_extra = tot_nmol - (4 * n_cells * n_cells * n_cells);
688     temp1 = ((double) n_extra) / (pow(temp3, 3.0) - pow(n_cells, 3.0));
689     n_per_extra = (int) ceil(temp1);
690 mmeineke 377
691 tim 722 if (n_per_extra > 4){
692     sprintf(painCave.errMsg,
693     "SimSetup error. There has been an error in constructing"
694     " the non-complete lattice.\n");
695 mmeineke 377 painCave.isFatal = 1;
696     simError();
697     }
698     }
699     else{
700 tim 722 n_cells = (int) temp3;
701 mmeineke 670 cellx = info[0].boxL[0] / temp3;
702     celly = info[0].boxL[1] / temp3;
703     cellz = info[0].boxL[2] / temp3;
704 mmeineke 377 }
705    
706     current_mol = 0;
707     current_comp_mol = 0;
708     current_comp = 0;
709     current_atom_ndx = 0;
710    
711 tim 722 for (i = 0; i < n_cells ; i++){
712     for (j = 0; j < n_cells; j++){
713     for (k = 0; k < n_cells; k++){
714     makeElement(i * cellx, j * celly, k * cellz);
715 mmeineke 377
716 tim 722 makeElement(i * cellx + 0.5 * cellx, j * celly + 0.5 * celly, k * cellz);
717 mmeineke 377
718 tim 722 makeElement(i * cellx, j * celly + 0.5 * celly, k * cellz + 0.5 * cellz);
719 mmeineke 377
720 tim 722 makeElement(i * cellx + 0.5 * cellx, j * celly, k * cellz + 0.5 * cellz);
721 mmeineke 377 }
722     }
723     }
724    
725 tim 722 if (have_extra){
726 mmeineke 377 done = 0;
727    
728     int start_ndx;
729 tim 722 for (i = 0; i < (n_cells + 1) && !done; i++){
730     for (j = 0; j < (n_cells + 1) && !done; j++){
731     if (i < n_cells){
732     if (j < n_cells){
733     start_ndx = n_cells;
734     }
735     else
736     start_ndx = 0;
737     }
738     else
739     start_ndx = 0;
740 mmeineke 377
741 tim 722 for (k = start_ndx; k < (n_cells + 1) && !done; k++){
742     makeElement(i * cellx, j * celly, k * cellz);
743     done = (current_mol >= tot_nmol);
744 mmeineke 377
745 tim 722 if (!done && n_per_extra > 1){
746     makeElement(i * cellx + 0.5 * cellx, j * celly + 0.5 * celly,
747     k * cellz);
748     done = (current_mol >= tot_nmol);
749     }
750 mmeineke 377
751 tim 722 if (!done && n_per_extra > 2){
752     makeElement(i * cellx, j * celly + 0.5 * celly,
753     k * cellz + 0.5 * cellz);
754     done = (current_mol >= tot_nmol);
755     }
756 mmeineke 377
757 tim 722 if (!done && n_per_extra > 3){
758     makeElement(i * cellx + 0.5 * cellx, j * celly,
759     k * cellz + 0.5 * cellz);
760     done = (current_mol >= tot_nmol);
761     }
762     }
763 mmeineke 377 }
764     }
765     }
766    
767 tim 722 for (i = 0; i < info[0].n_atoms; i++){
768     info[0].atoms[i]->setVel(vel);
769 mmeineke 377 }
770     }
771    
772 tim 722 void SimSetup::makeElement(double x, double y, double z){
773 mmeineke 377 int k;
774     AtomStamp* current_atom;
775     DirectionalAtom* dAtom;
776     double rotMat[3][3];
777 mmeineke 670 double pos[3];
778 mmeineke 377
779 tim 722 for (k = 0; k < comp_stamps[current_comp]->getNAtoms(); k++){
780     current_atom = comp_stamps[current_comp]->getAtom(k);
781     if (!current_atom->havePosition()){
782     sprintf(painCave.errMsg,
783     "SimSetup:initFromBass error.\n"
784     "\tComponent %s, atom %s does not have a position specified.\n"
785     "\tThe initialization routine is unable to give a start"
786     " position.\n",
787     comp_stamps[current_comp]->getID(), current_atom->getType());
788 mmeineke 377 painCave.isFatal = 1;
789     simError();
790     }
791 tim 722
792 mmeineke 670 pos[0] = x + current_atom->getPosX();
793     pos[1] = y + current_atom->getPosY();
794     pos[2] = z + current_atom->getPosZ();
795 mmeineke 377
796 tim 722 info[0].atoms[current_atom_ndx]->setPos(pos);
797 mmeineke 377
798 tim 722 if (info[0].atoms[current_atom_ndx]->isDirectional()){
799     dAtom = (DirectionalAtom *) info[0].atoms[current_atom_ndx];
800 mmeineke 377
801     rotMat[0][0] = 1.0;
802     rotMat[0][1] = 0.0;
803     rotMat[0][2] = 0.0;
804    
805     rotMat[1][0] = 0.0;
806     rotMat[1][1] = 1.0;
807     rotMat[1][2] = 0.0;
808    
809     rotMat[2][0] = 0.0;
810     rotMat[2][1] = 0.0;
811     rotMat[2][2] = 1.0;
812    
813 tim 722 dAtom->setA(rotMat);
814 mmeineke 377 }
815    
816     current_atom_ndx++;
817     }
818    
819     current_mol++;
820     current_comp_mol++;
821    
822 tim 722 if (current_comp_mol >= components_nmol[current_comp]){
823 mmeineke 377 current_comp_mol = 0;
824     current_comp++;
825     }
826     }
827 mmeineke 614
828    
829 tim 722 void SimSetup::gatherInfo(void){
830 mmeineke 787 int i;
831 mmeineke 614
832     ensembleCase = -1;
833     ffCase = -1;
834    
835 mmeineke 670 // set the easy ones first
836 mmeineke 614
837 tim 722 for (i = 0; i < nInfo; i++){
838 mmeineke 670 info[i].target_temp = globals->getTargetTemp();
839     info[i].dt = globals->getDt();
840     info[i].run_time = globals->getRunTime();
841     }
842 mmeineke 616 n_components = globals->getNComponents();
843 mmeineke 614
844    
845     // get the forceField
846    
847 tim 722 strcpy(force_field, globals->getForceField());
848 mmeineke 614
849 tim 722 if (!strcasecmp(force_field, "DUFF")){
850     ffCase = FF_DUFF;
851     }
852     else if (!strcasecmp(force_field, "LJ")){
853     ffCase = FF_LJ;
854     }
855     else if (!strcasecmp(force_field, "EAM")){
856     ffCase = FF_EAM;
857     }
858 chrisfen 999 else if (!strcasecmp(force_field, "WATER")){
859     ffCase = FF_H2O;
860     }
861 mmeineke 614 else{
862 tim 722 sprintf(painCave.errMsg, "SimSetup Error. Unrecognized force field -> %s\n",
863     force_field);
864     painCave.isFatal = 1;
865     simError();
866 mmeineke 614 }
867    
868 tim 722 // get the ensemble
869 mmeineke 614
870 tim 722 strcpy(ensemble, globals->getEnsemble());
871 mmeineke 614
872 tim 722 if (!strcasecmp(ensemble, "NVE")){
873     ensembleCase = NVE_ENS;
874     }
875     else if (!strcasecmp(ensemble, "NVT")){
876     ensembleCase = NVT_ENS;
877     }
878     else if (!strcasecmp(ensemble, "NPTi") || !strcasecmp(ensemble, "NPT")){
879 mmeineke 614 ensembleCase = NPTi_ENS;
880 tim 722 }
881     else if (!strcasecmp(ensemble, "NPTf")){
882     ensembleCase = NPTf_ENS;
883     }
884 mmeineke 812 else if (!strcasecmp(ensemble, "NPTxyz")){
885     ensembleCase = NPTxyz_ENS;
886     }
887 mmeineke 614 else{
888 tim 722 sprintf(painCave.errMsg,
889 gezelter 965 "SimSetup Warning. Unrecognized Ensemble -> %s \n"
890     "\treverting to NVE for this simulation.\n",
891 tim 722 ensemble);
892     painCave.isFatal = 0;
893     simError();
894     strcpy(ensemble, "NVE");
895     ensembleCase = NVE_ENS;
896 mmeineke 614 }
897    
898 tim 722 for (i = 0; i < nInfo; i++){
899     strcpy(info[i].ensemble, ensemble);
900    
901 mmeineke 670 // get the mixing rule
902 mmeineke 614
903 tim 722 strcpy(info[i].mixingRule, globals->getMixingRule());
904 mmeineke 670 info[i].usePBC = globals->getPBC();
905     }
906 tim 722
907 mmeineke 614 // get the components and calculate the tot_nMol and indvidual n_mol
908 tim 722
909 mmeineke 616 the_components = globals->getComponents();
910 mmeineke 614 components_nmol = new int[n_components];
911    
912    
913 tim 722 if (!globals->haveNMol()){
914 mmeineke 614 // we don't have the total number of molecules, so we assume it is
915     // given in each component
916    
917     tot_nmol = 0;
918 tim 722 for (i = 0; i < n_components; i++){
919     if (!the_components[i]->haveNMol()){
920     // we have a problem
921     sprintf(painCave.errMsg,
922 gezelter 965 "SimSetup Error. No global NMol or component NMol given.\n"
923     "\tCannot calculate the number of atoms.\n");
924 tim 722 painCave.isFatal = 1;
925     simError();
926 mmeineke 614 }
927    
928     tot_nmol += the_components[i]->getNMol();
929     components_nmol[i] = the_components[i]->getNMol();
930     }
931     }
932     else{
933 tim 722 sprintf(painCave.errMsg,
934     "SimSetup error.\n"
935     "\tSorry, the ability to specify total"
936     " nMols and then give molfractions in the components\n"
937     "\tis not currently supported."
938     " Please give nMol in the components.\n");
939 mmeineke 614 painCave.isFatal = 1;
940     simError();
941     }
942    
943 tim 962 //check whether sample time, status time, thermal time and reset time are divisble by dt
944 tim 1129 if (globals->haveSampleTime() && !isDivisible(globals->getSampleTime(), globals->getDt())){
945 tim 962 sprintf(painCave.errMsg,
946 gezelter 965 "Sample time is not divisible by dt.\n"
947     "\tThis will result in samples that are not uniformly\n"
948     "\tdistributed in time. If this is a problem, change\n"
949     "\tyour sampleTime variable.\n");
950 tim 962 painCave.isFatal = 0;
951     simError();
952     }
953    
954 tim 1129 if (globals->haveStatusTime() && !isDivisible(globals->getStatusTime(), globals->getDt())){
955 tim 962 sprintf(painCave.errMsg,
956 gezelter 965 "Status time is not divisible by dt.\n"
957     "\tThis will result in status reports that are not uniformly\n"
958     "\tdistributed in time. If this is a problem, change \n"
959     "\tyour statusTime variable.\n");
960 tim 962 painCave.isFatal = 0;
961     simError();
962     }
963    
964     if (globals->haveThermalTime() && !isDivisible(globals->getThermalTime(), globals->getDt())){
965     sprintf(painCave.errMsg,
966 gezelter 965 "Thermal time is not divisible by dt.\n"
967     "\tThis will result in thermalizations that are not uniformly\n"
968     "\tdistributed in time. If this is a problem, change \n"
969     "\tyour thermalTime variable.\n");
970 tim 962 painCave.isFatal = 0;
971     simError();
972     }
973    
974     if (globals->haveResetTime() && !isDivisible(globals->getResetTime(), globals->getDt())){
975     sprintf(painCave.errMsg,
976 gezelter 965 "Reset time is not divisible by dt.\n"
977     "\tThis will result in integrator resets that are not uniformly\n"
978     "\tdistributed in time. If this is a problem, change\n"
979     "\tyour resetTime variable.\n");
980 tim 962 painCave.isFatal = 0;
981     simError();
982     }
983    
984 mmeineke 614 // set the status, sample, and thermal kick times
985    
986 tim 722 for (i = 0; i < nInfo; i++){
987     if (globals->haveSampleTime()){
988 mmeineke 670 info[i].sampleTime = globals->getSampleTime();
989     info[i].statusTime = info[i].sampleTime;
990     }
991     else{
992     info[i].sampleTime = globals->getRunTime();
993     info[i].statusTime = info[i].sampleTime;
994     }
995 tim 722
996     if (globals->haveStatusTime()){
997 mmeineke 670 info[i].statusTime = globals->getStatusTime();
998     }
999 tim 722
1000     if (globals->haveThermalTime()){
1001 mmeineke 670 info[i].thermalTime = globals->getThermalTime();
1002 tim 1129 } else {
1003     info[i].thermalTime = globals->getRunTime();
1004 mmeineke 670 }
1005 mmeineke 614
1006 mmeineke 746 info[i].resetIntegrator = 0;
1007     if( globals->haveResetTime() ){
1008     info[i].resetTime = globals->getResetTime();
1009     info[i].resetIntegrator = 1;
1010     }
1011    
1012 mmeineke 670 // check for the temperature set flag
1013 mmeineke 841
1014 tim 722 if (globals->haveTempSet())
1015     info[i].setTemp = globals->getTempSet();
1016 mmeineke 855
1017     // check for the extended State init
1018    
1019     info[i].useInitXSstate = globals->getUseInitXSstate();
1020     info[i].orthoTolerance = globals->getOrthoBoxTolerance();
1021 chrisfen 1180
1022     // check for thermodynamic integration
1023 chrisfen 1212 if (globals->getUseSolidThermInt() && !globals->getUseLiquidThermInt()) {
1024 chrisfen 1187 if (globals->haveThermIntLambda() && globals->haveThermIntK()) {
1025 chrisfen 1212 info[i].useSolidThermInt = globals->getUseSolidThermInt();
1026 chrisfen 1187 info[i].thermIntLambda = globals->getThermIntLambda();
1027     info[i].thermIntK = globals->getThermIntK();
1028    
1029     Restraints *myRestraint = new Restraints(tot_nmol, info[i].thermIntLambda, info[i].thermIntK);
1030     info[i].restraint = myRestraint;
1031     }
1032     else {
1033     sprintf(painCave.errMsg,
1034     "SimSetup Error:\n"
1035 chrisfen 1212 "\tKeyword useSolidThermInt was set to 'true' but\n"
1036 chrisfen 1187 "\tthermodynamicIntegrationLambda (and/or\n"
1037     "\tthermodynamicIntegrationK) was not specified.\n"
1038     "\tPlease provide a lambda value and k value in your .bass file.\n");
1039     painCave.isFatal = 1;
1040     simError();
1041     }
1042 chrisfen 1180 }
1043 chrisfen 1212 else if(globals->getUseLiquidThermInt()) {
1044     if (globals->getUseSolidThermInt()) {
1045     sprintf( painCave.errMsg,
1046     "SimSetup Warning: It appears that you have both solid and\n"
1047     "\tliquid thermodynamic integration activated in your .bass\n"
1048     "\tfile. To avoid confusion, specify only one technique in\n"
1049     "\tyour .bass file. Liquid-state thermodynamic integration\n"
1050     "\twill be assumed for the current simulation. If this is not\n"
1051     "\twhat you desire, set useSolidThermInt to 'true' and\n"
1052     "\tuseLiquidThermInt to 'false' in your .bass file.\n");
1053     painCave.isFatal = 0;
1054     simError();
1055     }
1056     if (globals->haveThermIntLambda() && globals->haveThermIntK()) {
1057     info[i].useLiquidThermInt = globals->getUseLiquidThermInt();
1058     info[i].thermIntLambda = globals->getThermIntLambda();
1059     info[i].thermIntK = globals->getThermIntK();
1060     }
1061     else {
1062     sprintf(painCave.errMsg,
1063     "SimSetup Error:\n"
1064     "\tKeyword useLiquidThermInt was set to 'true' but\n"
1065     "\tthermodynamicIntegrationLambda (and/or\n"
1066     "\tthermodynamicIntegrationK) was not specified.\n"
1067     "\tPlease provide a lambda value and k value in your .bass file.\n");
1068     painCave.isFatal = 1;
1069     simError();
1070     }
1071     }
1072 chrisfen 1187 else if(globals->haveThermIntLambda() || globals->haveThermIntK()){
1073     sprintf(painCave.errMsg,
1074     "SimSetup Warning: If you want to use Thermodynamic\n"
1075 chrisfen 1212 "\tIntegration, set useSolidThermInt or useLiquidThermInt to\n"
1076     "\t'true' in your .bass file. These keywords are set to\n"
1077     "\t'false' by default, so your lambda and/or k values are\n"
1078     "\tbeing ignored.\n");
1079 chrisfen 1187 painCave.isFatal = 0;
1080     simError();
1081     }
1082 tim 708 }
1083 mmeineke 841
1084 tim 722 //setup seed for random number generator
1085 tim 708 int seedValue;
1086    
1087 tim 722 if (globals->haveSeed()){
1088 tim 708 seedValue = globals->getSeed();
1089 tim 722
1090     if(seedValue / 1E9 == 0){
1091     sprintf(painCave.errMsg,
1092     "Seed for sprng library should contain at least 9 digits\n"
1093     "OOPSE will generate a seed for user\n");
1094     painCave.isFatal = 0;
1095     simError();
1096    
1097     //using seed generated by system instead of invalid seed set by user
1098     #ifndef IS_MPI
1099     seedValue = make_sprng_seed();
1100     #else
1101     if (worldRank == 0){
1102     seedValue = make_sprng_seed();
1103     }
1104     MPI_Bcast(&seedValue, 1, MPI_INT, 0, MPI_COMM_WORLD);
1105     #endif
1106     }
1107     }//end of if branch of globals->haveSeed()
1108 tim 708 else{
1109 tim 722
1110 tim 708 #ifndef IS_MPI
1111 tim 722 seedValue = make_sprng_seed();
1112 tim 708 #else
1113 tim 722 if (worldRank == 0){
1114     seedValue = make_sprng_seed();
1115 tim 708 }
1116 tim 722 MPI_Bcast(&seedValue, 1, MPI_INT, 0, MPI_COMM_WORLD);
1117 tim 708 #endif
1118 tim 722 }//end of globals->haveSeed()
1119 tim 708
1120 tim 722 for (int i = 0; i < nInfo; i++){
1121 tim 708 info[i].setSeed(seedValue);
1122     }
1123 tim 1031
1124 mmeineke 614 #ifdef IS_MPI
1125 chrisfen 999 strcpy(checkPointMsg, "Successfully gathered all information from Bass\n");
1126 mmeineke 614 MPIcheckPoint();
1127     #endif // is_mpi
1128     }
1129    
1130    
1131 tim 722 void SimSetup::finalInfoCheck(void){
1132 mmeineke 614 int index;
1133     int usesDipoles;
1134 tim 1113 int usesCharges;
1135 mmeineke 670 int i;
1136 mmeineke 614
1137 tim 722 for (i = 0; i < nInfo; i++){
1138 mmeineke 670 // check electrostatic parameters
1139 tim 722
1140 mmeineke 670 index = 0;
1141     usesDipoles = 0;
1142 tim 722 while ((index < info[i].n_atoms) && !usesDipoles){
1143 mmeineke 670 usesDipoles = (info[i].atoms[index])->hasDipole();
1144     index++;
1145     }
1146 tim 1113 index = 0;
1147     usesCharges = 0;
1148     while ((index < info[i].n_atoms) && !usesCharges){
1149     usesCharges= (info[i].atoms[index])->hasCharge();
1150     index++;
1151     }
1152 mmeineke 614 #ifdef IS_MPI
1153 mmeineke 670 int myUse = usesDipoles;
1154 tim 722 MPI_Allreduce(&myUse, &usesDipoles, 1, MPI_INT, MPI_LOR, MPI_COMM_WORLD);
1155 mmeineke 614 #endif //is_mpi
1156 tim 722
1157 gezelter 1154 double theRcut, theRsw;
1158 tim 722
1159 gezelter 1163 if (globals->haveRcut()) {
1160     theRcut = globals->getRcut();
1161    
1162     if (globals->haveRsw())
1163     theRsw = globals->getRsw();
1164     else
1165     theRsw = theRcut;
1166    
1167     info[i].setDefaultRcut(theRcut, theRsw);
1168    
1169     } else {
1170    
1171     the_ff->calcRcut();
1172     theRcut = info[i].getRcut();
1173    
1174     if (globals->haveRsw())
1175     theRsw = globals->getRsw();
1176     else
1177     theRsw = theRcut;
1178    
1179     info[i].setDefaultRcut(theRcut, theRsw);
1180     }
1181    
1182 tim 722 if (globals->getUseRF()){
1183 mmeineke 670 info[i].useReactionField = 1;
1184 gezelter 1163
1185 gezelter 1154 if (!globals->haveRcut()){
1186 tim 722 sprintf(painCave.errMsg,
1187 gezelter 1154 "SimSetup Warning: No value was set for the cutoffRadius.\n"
1188 gezelter 965 "\tOOPSE will use a default value of 15.0 angstroms"
1189 gezelter 1154 "\tfor the cutoffRadius.\n");
1190 tim 722 painCave.isFatal = 0;
1191     simError();
1192 gezelter 1154 theRcut = 15.0;
1193 mmeineke 614 }
1194 tim 722 else{
1195 gezelter 1154 theRcut = globals->getRcut();
1196 mmeineke 614 }
1197 tim 722
1198 gezelter 1154 if (!globals->haveRsw()){
1199 tim 722 sprintf(painCave.errMsg,
1200 gezelter 1154 "SimSetup Warning: No value was set for switchingRadius.\n"
1201 gezelter 965 "\tOOPSE will use a default value of\n"
1202 gezelter 1154 "\t0.95 * cutoffRadius for the switchingRadius\n");
1203 tim 722 painCave.isFatal = 0;
1204     simError();
1205 gezelter 1154 theRsw = 0.95 * theRcut;
1206 mmeineke 670 }
1207 tim 722 else{
1208 gezelter 1154 theRsw = globals->getRsw();
1209 mmeineke 670 }
1210 tim 722
1211 gezelter 1154 info[i].setDefaultRcut(theRcut, theRsw);
1212 tim 722
1213     if (!globals->haveDielectric()){
1214     sprintf(painCave.errMsg,
1215 gezelter 965 "SimSetup Error: No Dielectric constant was set.\n"
1216     "\tYou are trying to use Reaction Field without"
1217     "\tsetting a dielectric constant!\n");
1218 tim 722 painCave.isFatal = 1;
1219     simError();
1220     }
1221     info[i].dielectric = globals->getDielectric();
1222     }
1223     else{
1224 tim 1113 if (usesDipoles || usesCharges){
1225 gezelter 1154
1226     if (!globals->haveRcut()){
1227 tim 722 sprintf(painCave.errMsg,
1228 gezelter 1154 "SimSetup Warning: No value was set for the cutoffRadius.\n"
1229 gezelter 965 "\tOOPSE will use a default value of 15.0 angstroms"
1230 gezelter 1154 "\tfor the cutoffRadius.\n");
1231     painCave.isFatal = 0;
1232     simError();
1233     theRcut = 15.0;
1234     }
1235 tim 722 else{
1236 gezelter 1154 theRcut = globals->getRcut();
1237 tim 722 }
1238 gezelter 1154
1239     if (!globals->haveRsw()){
1240 tim 722 sprintf(painCave.errMsg,
1241 gezelter 1154 "SimSetup Warning: No value was set for switchingRadius.\n"
1242 gezelter 965 "\tOOPSE will use a default value of\n"
1243 gezelter 1154 "\t0.95 * cutoffRadius for the switchingRadius\n");
1244 tim 722 painCave.isFatal = 0;
1245     simError();
1246 gezelter 1154 theRsw = 0.95 * theRcut;
1247 tim 722 }
1248     else{
1249 gezelter 1154 theRsw = globals->getRsw();
1250 tim 722 }
1251 gezelter 1154
1252     info[i].setDefaultRcut(theRcut, theRsw);
1253 mmeineke 859
1254 tim 722 }
1255     }
1256 mmeineke 670 }
1257 mmeineke 614 #ifdef IS_MPI
1258 tim 722 strcpy(checkPointMsg, "post processing checks out");
1259 mmeineke 614 MPIcheckPoint();
1260     #endif // is_mpi
1261 gezelter 1163
1262     // clean up the forcefield
1263     the_ff->cleanMe();
1264 mmeineke 614 }
1265 mmeineke 859
1266 tim 722 void SimSetup::initSystemCoords(void){
1267 mmeineke 670 int i;
1268 tim 722
1269 tim 689 char* inName;
1270    
1271 tim 722 (info[0].getConfiguration())->createArrays(info[0].n_atoms);
1272 mmeineke 614
1273 tim 722 for (i = 0; i < info[0].n_atoms; i++)
1274     info[0].atoms[i]->setCoords();
1275    
1276     if (globals->haveInitialConfig()){
1277 mmeineke 670 InitializeFromFile* fileInit;
1278 mmeineke 614 #ifdef IS_MPI // is_mpi
1279 tim 722 if (worldRank == 0){
1280 mmeineke 614 #endif //is_mpi
1281 tim 689 inName = globals->getInitialConfig();
1282 tim 722 fileInit = new InitializeFromFile(inName);
1283 mmeineke 614 #ifdef IS_MPI
1284 tim 722 }
1285     else
1286     fileInit = new InitializeFromFile(NULL);
1287 mmeineke 614 #endif
1288 tim 722 fileInit->readInit(info); // default velocities on
1289    
1290 mmeineke 670 delete fileInit;
1291     }
1292     else{
1293 mmeineke 859
1294 mmeineke 670 // no init from bass
1295 mmeineke 859
1296 tim 722 sprintf(painCave.errMsg,
1297 mmeineke 859 "Cannot intialize a simulation without an initial configuration file.\n");
1298 mmeineke 787 painCave.isFatal = 1;;
1299 mmeineke 670 simError();
1300 mmeineke 859
1301 mmeineke 670 }
1302 tim 722
1303 mmeineke 614 #ifdef IS_MPI
1304 tim 722 strcpy(checkPointMsg, "Successfully read in the initial configuration");
1305 mmeineke 614 MPIcheckPoint();
1306     #endif // is_mpi
1307     }
1308    
1309    
1310 tim 722 void SimSetup::makeOutNames(void){
1311 mmeineke 670 int k;
1312 mmeineke 614
1313 mmeineke 670
1314 tim 722 for (k = 0; k < nInfo; k++){
1315 mmeineke 614 #ifdef IS_MPI
1316 tim 722 if (worldRank == 0){
1317 mmeineke 614 #endif // is_mpi
1318 tim 722
1319     if (globals->haveFinalConfig()){
1320     strcpy(info[k].finalName, globals->getFinalConfig());
1321 mmeineke 614 }
1322     else{
1323 tim 722 strcpy(info[k].finalName, inFileName);
1324     char* endTest;
1325     int nameLength = strlen(info[k].finalName);
1326     endTest = &(info[k].finalName[nameLength - 5]);
1327     if (!strcmp(endTest, ".bass")){
1328     strcpy(endTest, ".eor");
1329     }
1330     else if (!strcmp(endTest, ".BASS")){
1331     strcpy(endTest, ".eor");
1332     }
1333     else{
1334     endTest = &(info[k].finalName[nameLength - 4]);
1335     if (!strcmp(endTest, ".bss")){
1336     strcpy(endTest, ".eor");
1337     }
1338     else if (!strcmp(endTest, ".mdl")){
1339     strcpy(endTest, ".eor");
1340     }
1341     else{
1342     strcat(info[k].finalName, ".eor");
1343     }
1344     }
1345 mmeineke 614 }
1346 tim 722
1347 mmeineke 670 // make the sample and status out names
1348 tim 722
1349     strcpy(info[k].sampleName, inFileName);
1350 mmeineke 670 char* endTest;
1351 tim 722 int nameLength = strlen(info[k].sampleName);
1352 mmeineke 670 endTest = &(info[k].sampleName[nameLength - 5]);
1353 tim 722 if (!strcmp(endTest, ".bass")){
1354     strcpy(endTest, ".dump");
1355 mmeineke 614 }
1356 tim 722 else if (!strcmp(endTest, ".BASS")){
1357     strcpy(endTest, ".dump");
1358 mmeineke 614 }
1359     else{
1360 tim 722 endTest = &(info[k].sampleName[nameLength - 4]);
1361     if (!strcmp(endTest, ".bss")){
1362     strcpy(endTest, ".dump");
1363     }
1364     else if (!strcmp(endTest, ".mdl")){
1365     strcpy(endTest, ".dump");
1366     }
1367     else{
1368     strcat(info[k].sampleName, ".dump");
1369     }
1370 mmeineke 614 }
1371 tim 722
1372     strcpy(info[k].statusName, inFileName);
1373     nameLength = strlen(info[k].statusName);
1374 mmeineke 670 endTest = &(info[k].statusName[nameLength - 5]);
1375 tim 722 if (!strcmp(endTest, ".bass")){
1376     strcpy(endTest, ".stat");
1377 mmeineke 614 }
1378 tim 722 else if (!strcmp(endTest, ".BASS")){
1379     strcpy(endTest, ".stat");
1380 mmeineke 614 }
1381     else{
1382 tim 722 endTest = &(info[k].statusName[nameLength - 4]);
1383     if (!strcmp(endTest, ".bss")){
1384     strcpy(endTest, ".stat");
1385     }
1386     else if (!strcmp(endTest, ".mdl")){
1387     strcpy(endTest, ".stat");
1388     }
1389     else{
1390     strcat(info[k].statusName, ".stat");
1391     }
1392 mmeineke 614 }
1393 tim 722
1394 chrisfen 1180 strcpy(info[k].rawPotName, inFileName);
1395     nameLength = strlen(info[k].rawPotName);
1396     endTest = &(info[k].rawPotName[nameLength - 5]);
1397     if (!strcmp(endTest, ".bass")){
1398     strcpy(endTest, ".raw");
1399     }
1400     else if (!strcmp(endTest, ".BASS")){
1401     strcpy(endTest, ".raw");
1402     }
1403     else{
1404     endTest = &(info[k].rawPotName[nameLength - 4]);
1405     if (!strcmp(endTest, ".bss")){
1406     strcpy(endTest, ".raw");
1407     }
1408     else if (!strcmp(endTest, ".mdl")){
1409     strcpy(endTest, ".raw");
1410     }
1411     else{
1412     strcat(info[k].rawPotName, ".raw");
1413     }
1414     }
1415    
1416 mmeineke 670 #ifdef IS_MPI
1417 tim 722
1418 mmeineke 614 }
1419 mmeineke 670 #endif // is_mpi
1420 mmeineke 614 }
1421     }
1422    
1423    
1424 tim 722 void SimSetup::sysObjectsCreation(void){
1425     int i, k;
1426    
1427 mmeineke 614 // create the forceField
1428 tim 689
1429 mmeineke 614 createFF();
1430    
1431     // extract componentList
1432    
1433     compList();
1434    
1435     // calc the number of atoms, bond, bends, and torsions
1436    
1437     calcSysValues();
1438    
1439     #ifdef IS_MPI
1440     // divide the molecules among the processors
1441 tim 722
1442 mmeineke 614 mpiMolDivide();
1443     #endif //is_mpi
1444 tim 722
1445 mmeineke 614 // create the atom and SRI arrays. Also initialize Molecule Stamp ID's
1446 tim 722
1447 mmeineke 614 makeSysArrays();
1448    
1449 mmeineke 616 // make and initialize the molecules (all but atomic coordinates)
1450 tim 722
1451 mmeineke 616 makeMolecules();
1452 tim 722
1453     for (k = 0; k < nInfo; k++){
1454 mmeineke 670 info[k].identArray = new int[info[k].n_atoms];
1455 tim 722 for (i = 0; i < info[k].n_atoms; i++){
1456 mmeineke 670 info[k].identArray[i] = info[k].atoms[i]->getIdent();
1457     }
1458 mmeineke 616 }
1459 mmeineke 614 }
1460    
1461    
1462 tim 722 void SimSetup::createFF(void){
1463     switch (ffCase){
1464     case FF_DUFF:
1465     the_ff = new DUFF();
1466     break;
1467 mmeineke 614
1468 tim 722 case FF_LJ:
1469     the_ff = new LJFF();
1470     break;
1471 mmeineke 614
1472 tim 722 case FF_EAM:
1473     the_ff = new EAM_FF();
1474     break;
1475 mmeineke 614
1476 chrisfen 999 case FF_H2O:
1477     the_ff = new WATER();
1478     break;
1479    
1480 tim 722 default:
1481     sprintf(painCave.errMsg,
1482     "SimSetup Error. Unrecognized force field in case statement.\n");
1483     painCave.isFatal = 1;
1484     simError();
1485 mmeineke 614 }
1486    
1487     #ifdef IS_MPI
1488 tim 722 strcpy(checkPointMsg, "ForceField creation successful");
1489 mmeineke 614 MPIcheckPoint();
1490     #endif // is_mpi
1491     }
1492    
1493    
1494 tim 722 void SimSetup::compList(void){
1495 mmeineke 616 int i;
1496 mmeineke 670 char* id;
1497     LinkedMolStamp* headStamp = new LinkedMolStamp();
1498     LinkedMolStamp* currentStamp = NULL;
1499 tim 722 comp_stamps = new MoleculeStamp * [n_components];
1500 tim 1157 bool haveCutoffGroups;
1501 tim 722
1502 tim 1157 haveCutoffGroups = false;
1503    
1504 mmeineke 614 // make an array of molecule stamps that match the components used.
1505     // also extract the used stamps out into a separate linked list
1506 tim 722
1507     for (i = 0; i < nInfo; i++){
1508 mmeineke 670 info[i].nComponents = n_components;
1509     info[i].componentsNmol = components_nmol;
1510     info[i].compStamps = comp_stamps;
1511     info[i].headStamp = headStamp;
1512     }
1513 mmeineke 614
1514    
1515 tim 722 for (i = 0; i < n_components; i++){
1516 mmeineke 614 id = the_components[i]->getType();
1517     comp_stamps[i] = NULL;
1518 tim 722
1519 mmeineke 614 // check to make sure the component isn't already in the list
1520    
1521 tim 722 comp_stamps[i] = headStamp->match(id);
1522     if (comp_stamps[i] == NULL){
1523 mmeineke 614 // extract the component from the list;
1524 tim 722
1525     currentStamp = stamps->extractMolStamp(id);
1526     if (currentStamp == NULL){
1527     sprintf(painCave.errMsg,
1528     "SimSetup error: Component \"%s\" was not found in the "
1529     "list of declared molecules\n",
1530     id);
1531     painCave.isFatal = 1;
1532     simError();
1533 mmeineke 614 }
1534 tim 722
1535     headStamp->add(currentStamp);
1536     comp_stamps[i] = headStamp->match(id);
1537 mmeineke 614 }
1538 tim 1157
1539     if(comp_stamps[i]->getNCutoffGroups() > 0)
1540     haveCutoffGroups = true;
1541 mmeineke 614 }
1542 tim 1157
1543     for (i = 0; i < nInfo; i++)
1544     info[i].haveCutoffGroups = haveCutoffGroups;
1545 mmeineke 614
1546     #ifdef IS_MPI
1547 tim 722 strcpy(checkPointMsg, "Component stamps successfully extracted\n");
1548 mmeineke 614 MPIcheckPoint();
1549     #endif // is_mpi
1550 tim 722 }
1551 mmeineke 614
1552 tim 722 void SimSetup::calcSysValues(void){
1553 gezelter 1203 int i, j;
1554     int ncutgroups, atomsingroups, ngroupsinstamp;
1555 mmeineke 614
1556 tim 722 int* molMembershipArray;
1557 gezelter 1203 CutoffGroupStamp* cg;
1558 mmeineke 614
1559     tot_atoms = 0;
1560     tot_bonds = 0;
1561     tot_bends = 0;
1562     tot_torsions = 0;
1563 gezelter 1097 tot_rigid = 0;
1564 gezelter 1203 tot_groups = 0;
1565 tim 722 for (i = 0; i < n_components; i++){
1566     tot_atoms += components_nmol[i] * comp_stamps[i]->getNAtoms();
1567     tot_bonds += components_nmol[i] * comp_stamps[i]->getNBonds();
1568     tot_bends += components_nmol[i] * comp_stamps[i]->getNBends();
1569 mmeineke 614 tot_torsions += components_nmol[i] * comp_stamps[i]->getNTorsions();
1570 gezelter 1097 tot_rigid += components_nmol[i] * comp_stamps[i]->getNRigidBodies();
1571 gezelter 1203
1572     ncutgroups = comp_stamps[i]->getNCutoffGroups();
1573     atomsingroups = 0;
1574     for (j=0; j < ncutgroups; j++) {
1575     cg = comp_stamps[i]->getCutoffGroup(j);
1576     atomsingroups += cg->getNMembers();
1577     }
1578     ngroupsinstamp = comp_stamps[i]->getNAtoms() - atomsingroups + ncutgroups;
1579     tot_groups += components_nmol[i] * ngroupsinstamp;
1580 mmeineke 614 }
1581 gezelter 1097
1582 mmeineke 614 tot_SRI = tot_bonds + tot_bends + tot_torsions;
1583 mmeineke 670 molMembershipArray = new int[tot_atoms];
1584 tim 722
1585     for (i = 0; i < nInfo; i++){
1586 mmeineke 670 info[i].n_atoms = tot_atoms;
1587     info[i].n_bonds = tot_bonds;
1588     info[i].n_bends = tot_bends;
1589     info[i].n_torsions = tot_torsions;
1590     info[i].n_SRI = tot_SRI;
1591     info[i].n_mol = tot_nmol;
1592 gezelter 1203 info[i].ngroup = tot_groups;
1593 mmeineke 670 info[i].molMembershipArray = molMembershipArray;
1594 tim 722 }
1595 mmeineke 614 }
1596    
1597     #ifdef IS_MPI
1598    
1599 tim 722 void SimSetup::mpiMolDivide(void){
1600 mmeineke 616 int i, j, k;
1601 mmeineke 614 int localMol, allMol;
1602     int local_atoms, local_bonds, local_bends, local_torsions, local_SRI;
1603 gezelter 1204 int local_rigid, local_groups;
1604 tim 1108 vector<int> globalMolIndex;
1605 gezelter 1204 int ncutgroups, atomsingroups, ngroupsinstamp;
1606     CutoffGroupStamp* cg;
1607 mmeineke 614
1608 tim 722 mpiSim = new mpiSimulation(info);
1609    
1610 tim 1108 mpiSim->divideLabor();
1611     globalAtomIndex = mpiSim->getGlobalAtomIndex();
1612 tim 1129 //globalMolIndex = mpiSim->getGlobalMolIndex();
1613 mmeineke 614
1614     // set up the local variables
1615 tim 722
1616 mmeineke 614 mol2proc = mpiSim->getMolToProcMap();
1617     molCompType = mpiSim->getMolComponentType();
1618 tim 722
1619 mmeineke 614 allMol = 0;
1620     localMol = 0;
1621     local_atoms = 0;
1622     local_bonds = 0;
1623     local_bends = 0;
1624     local_torsions = 0;
1625 gezelter 1097 local_rigid = 0;
1626 gezelter 1204 local_groups = 0;
1627 tim 1108 globalAtomCounter = 0;
1628 mmeineke 614
1629 tim 722 for (i = 0; i < n_components; i++){
1630     for (j = 0; j < components_nmol[i]; j++){
1631     if (mol2proc[allMol] == worldRank){
1632     local_atoms += comp_stamps[i]->getNAtoms();
1633     local_bonds += comp_stamps[i]->getNBonds();
1634     local_bends += comp_stamps[i]->getNBends();
1635     local_torsions += comp_stamps[i]->getNTorsions();
1636 gezelter 1097 local_rigid += comp_stamps[i]->getNRigidBodies();
1637 gezelter 1204
1638     ncutgroups = comp_stamps[i]->getNCutoffGroups();
1639     atomsingroups = 0;
1640     for (k=0; k < ncutgroups; k++) {
1641     cg = comp_stamps[i]->getCutoffGroup(k);
1642     atomsingroups += cg->getNMembers();
1643     }
1644     ngroupsinstamp = comp_stamps[i]->getNAtoms() - atomsingroups +
1645     ncutgroups;
1646     local_groups += ngroupsinstamp;
1647    
1648 tim 722 localMol++;
1649 mmeineke 614 }
1650 tim 722 for (k = 0; k < comp_stamps[i]->getNAtoms(); k++){
1651 tim 1108 info[0].molMembershipArray[globalAtomCounter] = allMol;
1652     globalAtomCounter++;
1653 mmeineke 614 }
1654    
1655 tim 722 allMol++;
1656 mmeineke 614 }
1657     }
1658     local_SRI = local_bonds + local_bends + local_torsions;
1659 tim 722
1660 gezelter 1203 info[0].n_atoms = mpiSim->getNAtomsLocal();
1661 gezelter 1097
1662 tim 722 if (local_atoms != info[0].n_atoms){
1663     sprintf(painCave.errMsg,
1664 gezelter 965 "SimSetup error: mpiSim's localAtom (%d) and SimSetup's\n"
1665     "\tlocalAtom (%d) are not equal.\n",
1666 tim 722 info[0].n_atoms, local_atoms);
1667 mmeineke 614 painCave.isFatal = 1;
1668     simError();
1669     }
1670    
1671 gezelter 1204 info[0].ngroup = mpiSim->getNGroupsLocal();
1672     if (local_groups != info[0].ngroup){
1673     sprintf(painCave.errMsg,
1674     "SimSetup error: mpiSim's localGroups (%d) and SimSetup's\n"
1675     "\tlocalGroups (%d) are not equal.\n",
1676     info[0].ngroup, local_groups);
1677     painCave.isFatal = 1;
1678     simError();
1679     }
1680    
1681 mmeineke 670 info[0].n_bonds = local_bonds;
1682     info[0].n_bends = local_bends;
1683     info[0].n_torsions = local_torsions;
1684     info[0].n_SRI = local_SRI;
1685     info[0].n_mol = localMol;
1686 mmeineke 614
1687 tim 722 strcpy(checkPointMsg, "Passed nlocal consistency check.");
1688 mmeineke 614 MPIcheckPoint();
1689     }
1690 tim 722
1691 mmeineke 614 #endif // is_mpi
1692    
1693    
1694 tim 722 void SimSetup::makeSysArrays(void){
1695 mmeineke 787
1696     #ifndef IS_MPI
1697     int k, j;
1698     #endif // is_mpi
1699     int i, l;
1700 mmeineke 614
1701 mmeineke 670 Atom** the_atoms;
1702     Molecule* the_molecules;
1703 mmeineke 616
1704 tim 722 for (l = 0; l < nInfo; l++){
1705 mmeineke 670 // create the atom and short range interaction arrays
1706 tim 722
1707     the_atoms = new Atom * [info[l].n_atoms];
1708 mmeineke 670 the_molecules = new Molecule[info[l].n_mol];
1709     int molIndex;
1710 mmeineke 614
1711 mmeineke 670 // initialize the molecule's stampID's
1712 tim 722
1713 mmeineke 670 #ifdef IS_MPI
1714 tim 722
1715    
1716 mmeineke 670 molIndex = 0;
1717 gezelter 1203 for (i = 0; i < mpiSim->getNMolGlobal(); i++){
1718 tim 722 if (mol2proc[i] == worldRank){
1719     the_molecules[molIndex].setStampID(molCompType[i]);
1720     the_molecules[molIndex].setMyIndex(molIndex);
1721     the_molecules[molIndex].setGlobalIndex(i);
1722     molIndex++;
1723 mmeineke 670 }
1724 mmeineke 614 }
1725 tim 722
1726 mmeineke 614 #else // is_mpi
1727 tim 722
1728 mmeineke 670 molIndex = 0;
1729 tim 1108 globalAtomCounter = 0;
1730 tim 722 for (i = 0; i < n_components; i++){
1731     for (j = 0; j < components_nmol[i]; j++){
1732     the_molecules[molIndex].setStampID(i);
1733     the_molecules[molIndex].setMyIndex(molIndex);
1734     the_molecules[molIndex].setGlobalIndex(molIndex);
1735     for (k = 0; k < comp_stamps[i]->getNAtoms(); k++){
1736 tim 1108 info[l].molMembershipArray[globalAtomCounter] = molIndex;
1737     globalAtomCounter++;
1738 tim 722 }
1739     molIndex++;
1740 mmeineke 614 }
1741     }
1742 tim 722
1743    
1744 mmeineke 614 #endif // is_mpi
1745    
1746 gezelter 1097 info[l].globalExcludes = new int;
1747     info[l].globalExcludes[0] = 0;
1748    
1749 mmeineke 670 // set the arrays into the SimInfo object
1750 mmeineke 614
1751 mmeineke 670 info[l].atoms = the_atoms;
1752     info[l].molecules = the_molecules;
1753     info[l].nGlobalExcludes = 0;
1754 tim 1157
1755 tim 722 the_ff->setSimInfo(info);
1756 mmeineke 670 }
1757 mmeineke 614 }
1758 mmeineke 616
1759 tim 722 void SimSetup::makeIntegrator(void){
1760 mmeineke 670 int k;
1761    
1762 mmeineke 782 NVE<RealIntegrator>* myNVE = NULL;
1763 tim 722 NVT<RealIntegrator>* myNVT = NULL;
1764 mmeineke 778 NPTi<NPT<RealIntegrator> >* myNPTi = NULL;
1765 mmeineke 780 NPTf<NPT<RealIntegrator> >* myNPTf = NULL;
1766 mmeineke 812 NPTxyz<NPT<RealIntegrator> >* myNPTxyz = NULL;
1767 tim 733
1768 tim 722 for (k = 0; k < nInfo; k++){
1769     switch (ensembleCase){
1770     case NVE_ENS:
1771     if (globals->haveZconstraints()){
1772     setupZConstraint(info[k]);
1773 mmeineke 782 myNVE = new ZConstraint<NVE<RealIntegrator> >(&(info[k]), the_ff);
1774 tim 722 }
1775 mmeineke 782 else{
1776     myNVE = new NVE<RealIntegrator>(&(info[k]), the_ff);
1777     }
1778    
1779     info->the_integrator = myNVE;
1780 tim 722 break;
1781 tim 676
1782 tim 722 case NVT_ENS:
1783     if (globals->haveZconstraints()){
1784     setupZConstraint(info[k]);
1785     myNVT = new ZConstraint<NVT<RealIntegrator> >(&(info[k]), the_ff);
1786     }
1787     else
1788     myNVT = new NVT<RealIntegrator>(&(info[k]), the_ff);
1789    
1790 tim 701 myNVT->setTargetTemp(globals->getTargetTemp());
1791 tim 722
1792     if (globals->haveTauThermostat())
1793 tim 701 myNVT->setTauThermostat(globals->getTauThermostat());
1794 tim 722 else{
1795     sprintf(painCave.errMsg,
1796     "SimSetup error: If you use the NVT\n"
1797 gezelter 965 "\tensemble, you must set tauThermostat.\n");
1798 tim 701 painCave.isFatal = 1;
1799     simError();
1800     }
1801 mmeineke 782
1802     info->the_integrator = myNVT;
1803 tim 701 break;
1804 tim 676
1805 tim 722 case NPTi_ENS:
1806     if (globals->haveZconstraints()){
1807     setupZConstraint(info[k]);
1808 mmeineke 778 myNPTi = new ZConstraint<NPTi<NPT <RealIntegrator> > >(&(info[k]), the_ff);
1809 tim 722 }
1810     else
1811 mmeineke 778 myNPTi = new NPTi<NPT<RealIntegrator> >(&(info[k]), the_ff);
1812 tim 722
1813     myNPTi->setTargetTemp(globals->getTargetTemp());
1814    
1815     if (globals->haveTargetPressure())
1816     myNPTi->setTargetPressure(globals->getTargetPressure());
1817     else{
1818     sprintf(painCave.errMsg,
1819     "SimSetup error: If you use a constant pressure\n"
1820 gezelter 965 "\tensemble, you must set targetPressure in the BASS file.\n");
1821 tim 722 painCave.isFatal = 1;
1822     simError();
1823     }
1824    
1825     if (globals->haveTauThermostat())
1826     myNPTi->setTauThermostat(globals->getTauThermostat());
1827     else{
1828     sprintf(painCave.errMsg,
1829     "SimSetup error: If you use an NPT\n"
1830 gezelter 965 "\tensemble, you must set tauThermostat.\n");
1831 tim 722 painCave.isFatal = 1;
1832     simError();
1833     }
1834    
1835     if (globals->haveTauBarostat())
1836     myNPTi->setTauBarostat(globals->getTauBarostat());
1837     else{
1838     sprintf(painCave.errMsg,
1839 tim 701 "SimSetup error: If you use an NPT\n"
1840 gezelter 965 "\tensemble, you must set tauBarostat.\n");
1841 tim 722 painCave.isFatal = 1;
1842     simError();
1843     }
1844 mmeineke 782
1845     info->the_integrator = myNPTi;
1846 tim 722 break;
1847 tim 676
1848 tim 722 case NPTf_ENS:
1849     if (globals->haveZconstraints()){
1850     setupZConstraint(info[k]);
1851 mmeineke 780 myNPTf = new ZConstraint<NPTf<NPT <RealIntegrator> > >(&(info[k]), the_ff);
1852 tim 722 }
1853     else
1854 mmeineke 780 myNPTf = new NPTf<NPT <RealIntegrator> >(&(info[k]), the_ff);
1855 tim 722
1856     myNPTf->setTargetTemp(globals->getTargetTemp());
1857    
1858     if (globals->haveTargetPressure())
1859     myNPTf->setTargetPressure(globals->getTargetPressure());
1860     else{
1861     sprintf(painCave.errMsg,
1862 tim 701 "SimSetup error: If you use a constant pressure\n"
1863 gezelter 965 "\tensemble, you must set targetPressure in the BASS file.\n");
1864 tim 722 painCave.isFatal = 1;
1865     simError();
1866     }
1867    
1868     if (globals->haveTauThermostat())
1869     myNPTf->setTauThermostat(globals->getTauThermostat());
1870 mmeineke 843
1871 tim 722 else{
1872     sprintf(painCave.errMsg,
1873 tim 701 "SimSetup error: If you use an NPT\n"
1874 gezelter 965 "\tensemble, you must set tauThermostat.\n");
1875 tim 722 painCave.isFatal = 1;
1876     simError();
1877     }
1878    
1879     if (globals->haveTauBarostat())
1880     myNPTf->setTauBarostat(globals->getTauBarostat());
1881 mmeineke 843
1882 tim 722 else{
1883     sprintf(painCave.errMsg,
1884     "SimSetup error: If you use an NPT\n"
1885 gezelter 965 "\tensemble, you must set tauBarostat.\n");
1886 tim 722 painCave.isFatal = 1;
1887     simError();
1888     }
1889 mmeineke 782
1890     info->the_integrator = myNPTf;
1891 tim 722 break;
1892 tim 676
1893 mmeineke 812 case NPTxyz_ENS:
1894     if (globals->haveZconstraints()){
1895     setupZConstraint(info[k]);
1896     myNPTxyz = new ZConstraint<NPTxyz<NPT <RealIntegrator> > >(&(info[k]), the_ff);
1897     }
1898     else
1899     myNPTxyz = new NPTxyz<NPT <RealIntegrator> >(&(info[k]), the_ff);
1900    
1901     myNPTxyz->setTargetTemp(globals->getTargetTemp());
1902    
1903     if (globals->haveTargetPressure())
1904     myNPTxyz->setTargetPressure(globals->getTargetPressure());
1905     else{
1906     sprintf(painCave.errMsg,
1907     "SimSetup error: If you use a constant pressure\n"
1908 gezelter 965 "\tensemble, you must set targetPressure in the BASS file.\n");
1909 mmeineke 812 painCave.isFatal = 1;
1910     simError();
1911     }
1912    
1913     if (globals->haveTauThermostat())
1914     myNPTxyz->setTauThermostat(globals->getTauThermostat());
1915     else{
1916     sprintf(painCave.errMsg,
1917     "SimSetup error: If you use an NPT\n"
1918 gezelter 965 "\tensemble, you must set tauThermostat.\n");
1919 mmeineke 812 painCave.isFatal = 1;
1920     simError();
1921     }
1922    
1923     if (globals->haveTauBarostat())
1924     myNPTxyz->setTauBarostat(globals->getTauBarostat());
1925     else{
1926     sprintf(painCave.errMsg,
1927     "SimSetup error: If you use an NPT\n"
1928 gezelter 965 "\tensemble, you must set tauBarostat.\n");
1929 mmeineke 812 painCave.isFatal = 1;
1930     simError();
1931     }
1932    
1933     info->the_integrator = myNPTxyz;
1934     break;
1935    
1936 tim 722 default:
1937     sprintf(painCave.errMsg,
1938     "SimSetup Error. Unrecognized ensemble in case statement.\n");
1939 tim 701 painCave.isFatal = 1;
1940     simError();
1941 tim 660 }
1942 mmeineke 616 }
1943     }
1944    
1945 tim 722 void SimSetup::initFortran(void){
1946     info[0].refreshSim();
1947 mmeineke 616
1948 tim 722 if (!strcmp(info[0].mixingRule, "standard")){
1949     the_ff->initForceField(LB_MIXING_RULE);
1950 mmeineke 616 }
1951 tim 722 else if (!strcmp(info[0].mixingRule, "explicit")){
1952     the_ff->initForceField(EXPLICIT_MIXING_RULE);
1953 mmeineke 616 }
1954     else{
1955 tim 722 sprintf(painCave.errMsg, "SimSetup Error: unknown mixing rule -> \"%s\"\n",
1956     info[0].mixingRule);
1957 mmeineke 616 painCave.isFatal = 1;
1958     simError();
1959     }
1960    
1961    
1962     #ifdef IS_MPI
1963 tim 722 strcpy(checkPointMsg, "Successfully intialized the mixingRule for Fortran.");
1964 mmeineke 616 MPIcheckPoint();
1965     #endif // is_mpi
1966     }
1967 tim 660
1968 tim 722 void SimSetup::setupZConstraint(SimInfo& theInfo){
1969 tim 701 int nZConstraints;
1970     ZconStamp** zconStamp;
1971 tim 682
1972 tim 722 if (globals->haveZconstraintTime()){
1973 tim 701 //add sample time of z-constraint into SimInfo's property list
1974     DoubleData* zconsTimeProp = new DoubleData();
1975     zconsTimeProp->setID(ZCONSTIME_ID);
1976     zconsTimeProp->setData(globals->getZconsTime());
1977     theInfo.addProperty(zconsTimeProp);
1978     }
1979     else{
1980 tim 722 sprintf(painCave.errMsg,
1981 gezelter 965 "ZConstraint error: If you use a ZConstraint,\n"
1982     "\tyou must set zconsTime.\n");
1983 tim 701 painCave.isFatal = 1;
1984 tim 722 simError();
1985 tim 701 }
1986 tim 682
1987 tim 701 //push zconsTol into siminfo, if user does not specify
1988     //value for zconsTol, a default value will be used
1989     DoubleData* zconsTol = new DoubleData();
1990     zconsTol->setID(ZCONSTOL_ID);
1991 tim 722 if (globals->haveZconsTol()){
1992 tim 701 zconsTol->setData(globals->getZconsTol());
1993     }
1994     else{
1995 tim 722 double defaultZConsTol = 0.01;
1996     sprintf(painCave.errMsg,
1997 gezelter 965 "ZConstraint Warning: Tolerance for z-constraint method is not specified.\n"
1998     "\tOOPSE will use a default value of %f.\n"
1999     "\tTo set the tolerance, use the zconsTol variable.\n",
2000 tim 722 defaultZConsTol);
2001 tim 701 painCave.isFatal = 0;
2002     simError();
2003 tim 699
2004 tim 701 zconsTol->setData(defaultZConsTol);
2005     }
2006     theInfo.addProperty(zconsTol);
2007 tim 699
2008 tim 738 //set Force Subtraction Policy
2009 tim 722 StringData* zconsForcePolicy = new StringData();
2010 tim 701 zconsForcePolicy->setID(ZCONSFORCEPOLICY_ID);
2011 tim 722
2012     if (globals->haveZconsForcePolicy()){
2013 tim 701 zconsForcePolicy->setData(globals->getZconsForcePolicy());
2014 tim 722 }
2015 tim 701 else{
2016 tim 722 sprintf(painCave.errMsg,
2017 gezelter 965 "ZConstraint Warning: No force subtraction policy was set.\n"
2018     "\tOOPSE will use PolicyByMass.\n"
2019     "\tTo set the policy, use the zconsForcePolicy variable.\n");
2020 tim 722 painCave.isFatal = 0;
2021     simError();
2022 tim 736 zconsForcePolicy->setData("BYMASS");
2023 tim 701 }
2024 tim 722
2025     theInfo.addProperty(zconsForcePolicy);
2026    
2027 tim 1091 //set zcons gap
2028     DoubleData* zconsGap = new DoubleData();
2029     zconsGap->setID(ZCONSGAP_ID);
2030    
2031     if (globals->haveZConsGap()){
2032     zconsGap->setData(globals->getZconsGap());
2033     theInfo.addProperty(zconsGap);
2034     }
2035    
2036     //set zcons fixtime
2037     DoubleData* zconsFixtime = new DoubleData();
2038     zconsFixtime->setID(ZCONSFIXTIME_ID);
2039    
2040     if (globals->haveZConsFixTime()){
2041     zconsFixtime->setData(globals->getZconsFixtime());
2042     theInfo.addProperty(zconsFixtime);
2043     }
2044    
2045 tim 1093 //set zconsUsingSMD
2046     IntData* zconsUsingSMD = new IntData();
2047     zconsUsingSMD->setID(ZCONSUSINGSMD_ID);
2048 tim 1091
2049 tim 1093 if (globals->haveZConsUsingSMD()){
2050     zconsUsingSMD->setData(globals->getZconsUsingSMD());
2051     theInfo.addProperty(zconsUsingSMD);
2052     }
2053    
2054 tim 701 //Determine the name of ouput file and add it into SimInfo's property list
2055     //Be careful, do not use inFileName, since it is a pointer which
2056     //point to a string at master node, and slave nodes do not contain that string
2057 tim 722
2058 tim 701 string zconsOutput(theInfo.finalName);
2059 tim 722
2060 tim 701 zconsOutput = zconsOutput.substr(0, zconsOutput.rfind(".")) + ".fz";
2061 tim 722
2062 tim 701 StringData* zconsFilename = new StringData();
2063     zconsFilename->setID(ZCONSFILENAME_ID);
2064     zconsFilename->setData(zconsOutput);
2065 tim 722
2066 tim 701 theInfo.addProperty(zconsFilename);
2067 tim 722
2068 tim 701 //setup index, pos and other parameters of z-constraint molecules
2069     nZConstraints = globals->getNzConstraints();
2070     theInfo.nZconstraints = nZConstraints;
2071    
2072     zconStamp = globals->getZconStamp();
2073     ZConsParaItem tempParaItem;
2074    
2075     ZConsParaData* zconsParaData = new ZConsParaData();
2076     zconsParaData->setID(ZCONSPARADATA_ID);
2077 tim 722
2078     for (int i = 0; i < nZConstraints; i++){
2079 tim 699 tempParaItem.havingZPos = zconStamp[i]->haveZpos();
2080     tempParaItem.zPos = zconStamp[i]->getZpos();
2081     tempParaItem.zconsIndex = zconStamp[i]->getMolIndex();
2082     tempParaItem.kRatio = zconStamp[i]->getKratio();
2083 tim 1093 tempParaItem.havingCantVel = zconStamp[i]->haveCantVel();
2084     tempParaItem.cantVel = zconStamp[i]->getCantVel();
2085 tim 699 zconsParaData->addItem(tempParaItem);
2086 tim 701 }
2087 tim 699
2088 tim 736 //check the uniqueness of index
2089     if(!zconsParaData->isIndexUnique()){
2090     sprintf(painCave.errMsg,
2091 gezelter 965 "ZConstraint Error: molIndex is not unique!\n");
2092 tim 736 painCave.isFatal = 1;
2093     simError();
2094     }
2095    
2096 tim 701 //sort the parameters by index of molecules
2097     zconsParaData->sortByIndex();
2098 tim 736
2099 tim 701 //push data into siminfo, therefore, we can retrieve later
2100     theInfo.addProperty(zconsParaData);
2101 tim 660 }
2102 tim 1031
2103     void SimSetup::makeMinimizer(){
2104 tim 1032
2105 tim 1064 OOPSEMinimizer* myOOPSEMinimizer;
2106 tim 1031 MinimizerParameterSet* param;
2107 tim 1064 char minimizerName[100];
2108 tim 1031
2109     for (int i = 0; i < nInfo; i++){
2110 tim 1064
2111 tim 1031 //prepare parameter set for minimizer
2112     param = new MinimizerParameterSet();
2113     param->setDefaultParameter();
2114    
2115     if (globals->haveMinimizer()){
2116     param->setFTol(globals->getMinFTol());
2117     }
2118    
2119     if (globals->haveMinGTol()){
2120     param->setGTol(globals->getMinGTol());
2121     }
2122    
2123     if (globals->haveMinMaxIter()){
2124     param->setMaxIteration(globals->getMinMaxIter());
2125     }
2126    
2127     if (globals->haveMinWriteFrq()){
2128     param->setMaxIteration(globals->getMinMaxIter());
2129     }
2130    
2131     if (globals->haveMinWriteFrq()){
2132     param->setWriteFrq(globals->getMinWriteFrq());
2133     }
2134    
2135 tim 1064 if (globals->haveMinStepSize()){
2136     param->setStepSize(globals->getMinStepSize());
2137 tim 1031 }
2138    
2139     if (globals->haveMinLSMaxIter()){
2140     param->setLineSearchMaxIteration(globals->getMinLSMaxIter());
2141     }
2142    
2143     if (globals->haveMinLSTol()){
2144     param->setLineSearchTol(globals->getMinLSTol());
2145     }
2146    
2147 tim 1066 strcpy(minimizerName, globals->getMinimizer());
2148 tim 1064
2149     if (!strcasecmp(minimizerName, "CG")){
2150     myOOPSEMinimizer = new PRCGMinimizer(&(info[i]), the_ff, param);
2151     }
2152     else if (!strcasecmp(minimizerName, "SD")){
2153     //myOOPSEMinimizer = MinimizerFactory.creatMinimizer("", &(info[i]), the_ff, param);
2154     myOOPSEMinimizer = new SDMinimizer(&(info[i]), the_ff, param);
2155     }
2156     else{
2157 tim 1066 sprintf(painCave.errMsg,
2158     "SimSetup error: Unrecognized Minimizer, use Conjugate Gradient \n");
2159     painCave.isFatal = 0;
2160     simError();
2161    
2162     myOOPSEMinimizer = new PRCGMinimizer(&(info[i]), the_ff, param);
2163     }
2164 tim 1064 info[i].the_integrator = myOOPSEMinimizer;
2165    
2166 tim 1031 //store the minimizer into simInfo
2167 tim 1064 info[i].the_minimizer = myOOPSEMinimizer;
2168 tim 1031 info[i].has_minimizer = true;
2169     }
2170 tim 1032
2171 tim 1031 }