ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/group/trunk/OOPSE-3.0/src/brains/SimSetup.cpp
Revision: 1772
Committed: Tue Nov 23 22:48:31 2004 UTC (19 years, 7 months ago) by chrisfen
File size: 56483 byte(s)
Log Message:
Improvements to restraints

File Contents

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