ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/group/trunk/OOPSE/libmdtools/SimSetup.cpp
Revision: 1032
Committed: Fri Feb 6 19:05:07 2004 UTC (20 years, 5 months ago) by tim
File size: 48320 byte(s)
Log Message:
Add one more file into Makefile.in

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 tim 1031 #include "ConjugateMinimizer.hpp"
13 mmeineke 377
14     #ifdef IS_MPI
15     #include "mpiBASS.h"
16     #include "mpiSimulation.hpp"
17     #endif
18    
19 mmeineke 557 // some defines for ensemble and Forcefield cases
20    
21 tim 660 #define NVE_ENS 0
22     #define NVT_ENS 1
23     #define NPTi_ENS 2
24     #define NPTf_ENS 3
25 mmeineke 812 #define NPTxyz_ENS 4
26 mmeineke 557
27 mmeineke 812
28 chrisfen 999 #define FF_DUFF 0
29     #define FF_LJ 1
30     #define FF_EAM 2
31     #define FF_H2O 3
32 mmeineke 557
33 tim 658 using namespace std;
34    
35 tim 962 /**
36     * Check whether dividend is divisble by divisor or not
37     */
38     bool isDivisible(double dividend, double divisor){
39     double tolerance = 0.000001;
40     double quotient;
41     double diff;
42     int intQuotient;
43    
44     quotient = dividend / divisor;
45    
46     if (quotient < 0)
47     quotient = -quotient;
48    
49     intQuotient = int (quotient + tolerance);
50    
51     diff = fabs(fabs(dividend) - intQuotient * fabs(divisor));
52    
53     if (diff <= tolerance)
54     return true;
55     else
56     return false;
57     }
58    
59 mmeineke 377 SimSetup::SimSetup(){
60 mmeineke 823
61     initSuspend = false;
62 mmeineke 656 isInfoArray = 0;
63     nInfo = 1;
64 tim 722
65 mmeineke 377 stamps = new MakeStamps();
66     globals = new Globals();
67 tim 722
68    
69 mmeineke 377 #ifdef IS_MPI
70 tim 722 strcpy(checkPointMsg, "SimSetup creation successful");
71 mmeineke 377 MPIcheckPoint();
72     #endif // IS_MPI
73     }
74    
75     SimSetup::~SimSetup(){
76     delete stamps;
77     delete globals;
78     }
79    
80 tim 722 void SimSetup::setSimInfo(SimInfo* the_info, int theNinfo){
81     info = the_info;
82     nInfo = theNinfo;
83     isInfoArray = 1;
84 mmeineke 823 initSuspend = true;
85 mmeineke 670 }
86 mmeineke 656
87    
88 tim 722 void SimSetup::parseFile(char* fileName){
89 mmeineke 377 #ifdef IS_MPI
90 tim 722 if (worldRank == 0){
91 mmeineke 377 #endif // is_mpi
92 tim 722
93 mmeineke 377 inFileName = fileName;
94 tim 722 set_interface_stamps(stamps, globals);
95    
96 mmeineke 377 #ifdef IS_MPI
97     mpiEventInit();
98     #endif
99    
100 tim 722 yacc_BASS(fileName);
101 mmeineke 377
102     #ifdef IS_MPI
103     throwMPIEvent(NULL);
104     }
105 tim 722 else{
106     receiveParse();
107     }
108 mmeineke 377 #endif
109    
110     }
111    
112     #ifdef IS_MPI
113     void SimSetup::receiveParse(void){
114 tim 722 set_interface_stamps(stamps, globals);
115     mpiEventInit();
116     MPIcheckPoint();
117     mpiEventLoop();
118 mmeineke 377 }
119    
120     #endif // is_mpi
121    
122 mmeineke 670 void SimSetup::createSim(void){
123 mmeineke 377
124 mmeineke 614 // gather all of the information from the Bass file
125 tim 689
126 mmeineke 614 gatherInfo();
127 mmeineke 377
128 mmeineke 614 // creation of complex system objects
129 mmeineke 377
130 mmeineke 614 sysObjectsCreation();
131 mmeineke 377
132 mmeineke 859 // check on the post processing info
133    
134     finalInfoCheck();
135    
136 mmeineke 614 // initialize the system coordinates
137 mmeineke 377
138 mmeineke 823 if ( !initSuspend ){
139 tim 722 initSystemCoords();
140 mmeineke 811
141     if( !(globals->getUseInitTime()) )
142     info[0].currentTime = 0.0;
143 tim 722 }
144 mmeineke 377
145 mmeineke 614 // make the output filenames
146 mmeineke 377
147 mmeineke 614 makeOutNames();
148 tim 722
149 tim 1031 if (globals->haveMinimizer())
150     // make minimizer
151     makeMinimizer();
152     else
153     // make the integrator
154     makeIntegrator();
155    
156 chuckv 432 #ifdef IS_MPI
157     mpiSim->mpiRefresh();
158     #endif
159 mmeineke 377
160 chuckv 432 // initialize the Fortran
161 mmeineke 377
162 mmeineke 616 initFortran();
163 mmeineke 377 }
164    
165 mmeineke 407
166 tim 722 void SimSetup::makeMolecules(void){
167 mmeineke 787 int k;
168 mmeineke 412 int i, j, exI, exJ, tempEx, stampID, atomOffset, excludeOffset;
169 mmeineke 616 molInit molInfo;
170 mmeineke 407 DirectionalAtom* dAtom;
171 mmeineke 412 LinkedAssign* extras;
172     LinkedAssign* current_extra;
173 mmeineke 407 AtomStamp* currentAtom;
174     BondStamp* currentBond;
175     BendStamp* currentBend;
176     TorsionStamp* currentTorsion;
177 mmeineke 427
178     bond_pair* theBonds;
179     bend_set* theBends;
180     torsion_set* theTorsions;
181    
182 mmeineke 407 //init the forceField paramters
183    
184     the_ff->readParams();
185    
186 tim 722
187 mmeineke 427 // init the atoms
188 mmeineke 407
189 gezelter 983 double phi, theta, psi;
190     double sux, suy, suz;
191     double Axx, Axy, Axz, Ayx, Ayy, Ayz, Azx, Azy, Azz;
192 mmeineke 427 double ux, uy, uz, u, uSqr;
193 mmeineke 407
194 tim 722 for (k = 0; k < nInfo; k++){
195     the_ff->setSimInfo(&(info[k]));
196    
197 mmeineke 670 atomOffset = 0;
198     excludeOffset = 0;
199 tim 722 for (i = 0; i < info[k].n_mol; i++){
200 mmeineke 670 stampID = info[k].molecules[i].getStampID();
201 mmeineke 412
202 tim 722 molInfo.nAtoms = comp_stamps[stampID]->getNAtoms();
203     molInfo.nBonds = comp_stamps[stampID]->getNBonds();
204     molInfo.nBends = comp_stamps[stampID]->getNBends();
205 mmeineke 670 molInfo.nTorsions = comp_stamps[stampID]->getNTorsions();
206     molInfo.nExcludes = molInfo.nBonds + molInfo.nBends + molInfo.nTorsions;
207 tim 722
208 mmeineke 670 molInfo.myAtoms = &(info[k].atoms[atomOffset]);
209     molInfo.myExcludes = &(info[k].excludes[excludeOffset]);
210 tim 722 molInfo.myBonds = new Bond * [molInfo.nBonds];
211     molInfo.myBends = new Bend * [molInfo.nBends];
212     molInfo.myTorsions = new Torsion * [molInfo.nTorsions];
213 mmeineke 407
214 mmeineke 670 theBonds = new bond_pair[molInfo.nBonds];
215     theBends = new bend_set[molInfo.nBends];
216     theTorsions = new torsion_set[molInfo.nTorsions];
217 tim 722
218 mmeineke 670 // make the Atoms
219 tim 722
220     for (j = 0; j < molInfo.nAtoms; j++){
221     currentAtom = comp_stamps[stampID]->getAtom(j);
222     if (currentAtom->haveOrientation()){
223     dAtom = new DirectionalAtom((j + atomOffset),
224     info[k].getConfiguration());
225     info[k].n_oriented++;
226     molInfo.myAtoms[j] = dAtom;
227    
228 gezelter 983 // Directional Atoms have standard unit vectors which are oriented
229     // in space using the three Euler angles. We assume the standard
230     // unit vector was originally along the z axis below.
231 tim 722
232 gezelter 984 phi = currentAtom->getEulerPhi() * M_PI / 180.0;
233     theta = currentAtom->getEulerTheta() * M_PI / 180.0;
234     psi = currentAtom->getEulerPsi()* M_PI / 180.0;
235 gezelter 983
236     Axx = (cos(phi) * cos(psi)) - (sin(phi) * cos(theta) * sin(psi));
237     Axy = (sin(phi) * cos(psi)) + (cos(phi) * cos(theta) * sin(psi));
238     Axz = sin(theta) * sin(psi);
239    
240     Ayx = -(cos(phi) * sin(psi)) - (sin(phi) * cos(theta) * cos(psi));
241     Ayy = -(sin(phi) * sin(psi)) + (cos(phi) * cos(theta) * cos(psi));
242     Ayz = sin(theta) * cos(psi);
243    
244     Azx = sin(phi) * sin(theta);
245     Azy = -cos(phi) * sin(theta);
246     Azz = cos(theta);
247    
248     sux = 0.0;
249     suy = 0.0;
250     suz = 1.0;
251    
252     ux = (Axx * sux) + (Ayx * suy) + (Azx * suz);
253     uy = (Axy * sux) + (Ayy * suy) + (Azy * suz);
254     uz = (Axz * sux) + (Ayz * suy) + (Azz * suz);
255    
256 tim 722 uSqr = (ux * ux) + (uy * uy) + (uz * uz);
257    
258     u = sqrt(uSqr);
259     ux = ux / u;
260     uy = uy / u;
261     uz = uz / u;
262    
263     dAtom->setSUx(ux);
264     dAtom->setSUy(uy);
265     dAtom->setSUz(uz);
266     }
267     else{
268     molInfo.myAtoms[j] = new GeneralAtom((j + atomOffset),
269     info[k].getConfiguration());
270     }
271     molInfo.myAtoms[j]->setType(currentAtom->getType());
272    
273 mmeineke 407 #ifdef IS_MPI
274 tim 722
275     molInfo.myAtoms[j]->setGlobalIndex(globalIndex[j + atomOffset]);
276    
277 mmeineke 407 #endif // is_mpi
278 mmeineke 670 }
279 tim 722
280     // make the bonds
281     for (j = 0; j < molInfo.nBonds; j++){
282     currentBond = comp_stamps[stampID]->getBond(j);
283     theBonds[j].a = currentBond->getA() + atomOffset;
284     theBonds[j].b = currentBond->getB() + atomOffset;
285    
286     exI = theBonds[j].a;
287     exJ = theBonds[j].b;
288    
289     // exclude_I must always be the smaller of the pair
290     if (exI > exJ){
291     tempEx = exI;
292     exI = exJ;
293     exJ = tempEx;
294     }
295 mmeineke 670 #ifdef IS_MPI
296 tim 722 tempEx = exI;
297     exI = info[k].atoms[tempEx]->getGlobalIndex() + 1;
298     tempEx = exJ;
299     exJ = info[k].atoms[tempEx]->getGlobalIndex() + 1;
300    
301     info[k].excludes[j + excludeOffset]->setPair(exI, exJ);
302 mmeineke 412 #else // isn't MPI
303 tim 722
304     info[k].excludes[j + excludeOffset]->setPair((exI + 1), (exJ + 1));
305 mmeineke 412 #endif //is_mpi
306 mmeineke 670 }
307     excludeOffset += molInfo.nBonds;
308 tim 722
309 mmeineke 670 //make the bends
310 tim 722 for (j = 0; j < molInfo.nBends; j++){
311     currentBend = comp_stamps[stampID]->getBend(j);
312     theBends[j].a = currentBend->getA() + atomOffset;
313     theBends[j].b = currentBend->getB() + atomOffset;
314     theBends[j].c = currentBend->getC() + atomOffset;
315    
316     if (currentBend->haveExtras()){
317     extras = currentBend->getExtras();
318     current_extra = extras;
319    
320     while (current_extra != NULL){
321     if (!strcmp(current_extra->getlhs(), "ghostVectorSource")){
322     switch (current_extra->getType()){
323     case 0:
324     theBends[j].ghost = current_extra->getInt() + atomOffset;
325     theBends[j].isGhost = 1;
326     break;
327    
328     case 1:
329     theBends[j].ghost = (int) current_extra->getDouble() +
330     atomOffset;
331     theBends[j].isGhost = 1;
332     break;
333    
334     default:
335     sprintf(painCave.errMsg,
336     "SimSetup Error: ghostVectorSource was neither a "
337     "double nor an int.\n"
338     "-->Bend[%d] in %s\n",
339     j, comp_stamps[stampID]->getID());
340     painCave.isFatal = 1;
341     simError();
342     }
343     }
344     else{
345     sprintf(painCave.errMsg,
346     "SimSetup Error: unhandled bend assignment:\n"
347     " -->%s in Bend[%d] in %s\n",
348     current_extra->getlhs(), j, comp_stamps[stampID]->getID());
349     painCave.isFatal = 1;
350     simError();
351     }
352    
353     current_extra = current_extra->getNext();
354     }
355 tim 701 }
356 tim 722
357     if (!theBends[j].isGhost){
358     exI = theBends[j].a;
359     exJ = theBends[j].c;
360     }
361     else{
362     exI = theBends[j].a;
363     exJ = theBends[j].b;
364     }
365    
366     // exclude_I must always be the smaller of the pair
367     if (exI > exJ){
368     tempEx = exI;
369     exI = exJ;
370     exJ = tempEx;
371     }
372 mmeineke 670 #ifdef IS_MPI
373 tim 722 tempEx = exI;
374     exI = info[k].atoms[tempEx]->getGlobalIndex() + 1;
375     tempEx = exJ;
376     exJ = info[k].atoms[tempEx]->getGlobalIndex() + 1;
377    
378     info[k].excludes[j + excludeOffset]->setPair(exI, exJ);
379 mmeineke 670 #else // isn't MPI
380 tim 722 info[k].excludes[j + excludeOffset]->setPair((exI + 1), (exJ + 1));
381 mmeineke 670 #endif //is_mpi
382 mmeineke 412 }
383 mmeineke 670 excludeOffset += molInfo.nBends;
384 tim 722
385     for (j = 0; j < molInfo.nTorsions; j++){
386     currentTorsion = comp_stamps[stampID]->getTorsion(j);
387     theTorsions[j].a = currentTorsion->getA() + atomOffset;
388     theTorsions[j].b = currentTorsion->getB() + atomOffset;
389     theTorsions[j].c = currentTorsion->getC() + atomOffset;
390     theTorsions[j].d = currentTorsion->getD() + atomOffset;
391    
392     exI = theTorsions[j].a;
393     exJ = theTorsions[j].d;
394    
395     // exclude_I must always be the smaller of the pair
396     if (exI > exJ){
397     tempEx = exI;
398     exI = exJ;
399     exJ = tempEx;
400     }
401 mmeineke 670 #ifdef IS_MPI
402 tim 722 tempEx = exI;
403     exI = info[k].atoms[tempEx]->getGlobalIndex() + 1;
404     tempEx = exJ;
405     exJ = info[k].atoms[tempEx]->getGlobalIndex() + 1;
406    
407     info[k].excludes[j + excludeOffset]->setPair(exI, exJ);
408 mmeineke 407 #else // isn't MPI
409 tim 722 info[k].excludes[j + excludeOffset]->setPair((exI + 1), (exJ + 1));
410 mmeineke 412 #endif //is_mpi
411 mmeineke 670 }
412     excludeOffset += molInfo.nTorsions;
413 tim 722
414    
415 mmeineke 670 // send the arrays off to the forceField for init.
416 mmeineke 407
417 tim 722 the_ff->initializeAtoms(molInfo.nAtoms, molInfo.myAtoms);
418     the_ff->initializeBonds(molInfo.nBonds, molInfo.myBonds, theBonds);
419     the_ff->initializeBends(molInfo.nBends, molInfo.myBends, theBends);
420     the_ff->initializeTorsions(molInfo.nTorsions, molInfo.myTorsions,
421     theTorsions);
422    
423    
424     info[k].molecules[i].initialize(molInfo);
425    
426    
427 mmeineke 670 atomOffset += molInfo.nAtoms;
428     delete[] theBonds;
429     delete[] theBends;
430     delete[] theTorsions;
431 mmeineke 412 }
432 mmeineke 414 }
433 tim 722
434 chuckv 434 #ifdef IS_MPI
435 tim 722 sprintf(checkPointMsg, "all molecules initialized succesfully");
436 chuckv 434 MPIcheckPoint();
437     #endif // is_mpi
438 tim 722
439 mmeineke 670 // clean up the forcefield
440 chuckv 434
441 mmeineke 420 the_ff->calcRcut();
442 mmeineke 414 the_ff->cleanMe();
443     }
444 mmeineke 407
445 tim 722 void SimSetup::initFromBass(void){
446 mmeineke 377 int i, j, k;
447     int n_cells;
448     double cellx, celly, cellz;
449     double temp1, temp2, temp3;
450     int n_per_extra;
451     int n_extra;
452     int have_extra, done;
453    
454 mmeineke 670 double vel[3];
455     vel[0] = 0.0;
456     vel[1] = 0.0;
457     vel[2] = 0.0;
458    
459 tim 722 temp1 = (double) tot_nmol / 4.0;
460     temp2 = pow(temp1, (1.0 / 3.0));
461     temp3 = ceil(temp2);
462 mmeineke 377
463 tim 722 have_extra = 0;
464     if (temp2 < temp3){
465     // we have a non-complete lattice
466     have_extra = 1;
467 mmeineke 377
468 tim 722 n_cells = (int) temp3 - 1;
469 mmeineke 670 cellx = info[0].boxL[0] / temp3;
470     celly = info[0].boxL[1] / temp3;
471     cellz = info[0].boxL[2] / temp3;
472 tim 722 n_extra = tot_nmol - (4 * n_cells * n_cells * n_cells);
473     temp1 = ((double) n_extra) / (pow(temp3, 3.0) - pow(n_cells, 3.0));
474     n_per_extra = (int) ceil(temp1);
475 mmeineke 377
476 tim 722 if (n_per_extra > 4){
477     sprintf(painCave.errMsg,
478     "SimSetup error. There has been an error in constructing"
479     " the non-complete lattice.\n");
480 mmeineke 377 painCave.isFatal = 1;
481     simError();
482     }
483     }
484     else{
485 tim 722 n_cells = (int) temp3;
486 mmeineke 670 cellx = info[0].boxL[0] / temp3;
487     celly = info[0].boxL[1] / temp3;
488     cellz = info[0].boxL[2] / temp3;
489 mmeineke 377 }
490    
491     current_mol = 0;
492     current_comp_mol = 0;
493     current_comp = 0;
494     current_atom_ndx = 0;
495    
496 tim 722 for (i = 0; i < n_cells ; i++){
497     for (j = 0; j < n_cells; j++){
498     for (k = 0; k < n_cells; k++){
499     makeElement(i * cellx, j * celly, k * cellz);
500 mmeineke 377
501 tim 722 makeElement(i * cellx + 0.5 * cellx, j * celly + 0.5 * celly, k * cellz);
502 mmeineke 377
503 tim 722 makeElement(i * cellx, j * celly + 0.5 * celly, k * cellz + 0.5 * cellz);
504 mmeineke 377
505 tim 722 makeElement(i * cellx + 0.5 * cellx, j * celly, k * cellz + 0.5 * cellz);
506 mmeineke 377 }
507     }
508     }
509    
510 tim 722 if (have_extra){
511 mmeineke 377 done = 0;
512    
513     int start_ndx;
514 tim 722 for (i = 0; i < (n_cells + 1) && !done; i++){
515     for (j = 0; j < (n_cells + 1) && !done; j++){
516     if (i < n_cells){
517     if (j < n_cells){
518     start_ndx = n_cells;
519     }
520     else
521     start_ndx = 0;
522     }
523     else
524     start_ndx = 0;
525 mmeineke 377
526 tim 722 for (k = start_ndx; k < (n_cells + 1) && !done; k++){
527     makeElement(i * cellx, j * celly, k * cellz);
528     done = (current_mol >= tot_nmol);
529 mmeineke 377
530 tim 722 if (!done && n_per_extra > 1){
531     makeElement(i * cellx + 0.5 * cellx, j * celly + 0.5 * celly,
532     k * cellz);
533     done = (current_mol >= tot_nmol);
534     }
535 mmeineke 377
536 tim 722 if (!done && n_per_extra > 2){
537     makeElement(i * cellx, j * celly + 0.5 * celly,
538     k * cellz + 0.5 * cellz);
539     done = (current_mol >= tot_nmol);
540     }
541 mmeineke 377
542 tim 722 if (!done && n_per_extra > 3){
543     makeElement(i * cellx + 0.5 * cellx, j * celly,
544     k * cellz + 0.5 * cellz);
545     done = (current_mol >= tot_nmol);
546     }
547     }
548 mmeineke 377 }
549     }
550     }
551    
552 tim 722 for (i = 0; i < info[0].n_atoms; i++){
553     info[0].atoms[i]->setVel(vel);
554 mmeineke 377 }
555     }
556    
557 tim 722 void SimSetup::makeElement(double x, double y, double z){
558 mmeineke 377 int k;
559     AtomStamp* current_atom;
560     DirectionalAtom* dAtom;
561     double rotMat[3][3];
562 mmeineke 670 double pos[3];
563 mmeineke 377
564 tim 722 for (k = 0; k < comp_stamps[current_comp]->getNAtoms(); k++){
565     current_atom = comp_stamps[current_comp]->getAtom(k);
566     if (!current_atom->havePosition()){
567     sprintf(painCave.errMsg,
568     "SimSetup:initFromBass error.\n"
569     "\tComponent %s, atom %s does not have a position specified.\n"
570     "\tThe initialization routine is unable to give a start"
571     " position.\n",
572     comp_stamps[current_comp]->getID(), current_atom->getType());
573 mmeineke 377 painCave.isFatal = 1;
574     simError();
575     }
576 tim 722
577 mmeineke 670 pos[0] = x + current_atom->getPosX();
578     pos[1] = y + current_atom->getPosY();
579     pos[2] = z + current_atom->getPosZ();
580 mmeineke 377
581 tim 722 info[0].atoms[current_atom_ndx]->setPos(pos);
582 mmeineke 377
583 tim 722 if (info[0].atoms[current_atom_ndx]->isDirectional()){
584     dAtom = (DirectionalAtom *) info[0].atoms[current_atom_ndx];
585 mmeineke 377
586     rotMat[0][0] = 1.0;
587     rotMat[0][1] = 0.0;
588     rotMat[0][2] = 0.0;
589    
590     rotMat[1][0] = 0.0;
591     rotMat[1][1] = 1.0;
592     rotMat[1][2] = 0.0;
593    
594     rotMat[2][0] = 0.0;
595     rotMat[2][1] = 0.0;
596     rotMat[2][2] = 1.0;
597    
598 tim 722 dAtom->setA(rotMat);
599 mmeineke 377 }
600    
601     current_atom_ndx++;
602     }
603    
604     current_mol++;
605     current_comp_mol++;
606    
607 tim 722 if (current_comp_mol >= components_nmol[current_comp]){
608 mmeineke 377 current_comp_mol = 0;
609     current_comp++;
610     }
611     }
612 mmeineke 614
613    
614 tim 722 void SimSetup::gatherInfo(void){
615 mmeineke 787 int i;
616 mmeineke 614
617     ensembleCase = -1;
618     ffCase = -1;
619    
620 mmeineke 670 // set the easy ones first
621 mmeineke 614
622 tim 722 for (i = 0; i < nInfo; i++){
623 mmeineke 670 info[i].target_temp = globals->getTargetTemp();
624     info[i].dt = globals->getDt();
625     info[i].run_time = globals->getRunTime();
626     }
627 mmeineke 616 n_components = globals->getNComponents();
628 mmeineke 614
629    
630     // get the forceField
631    
632 tim 722 strcpy(force_field, globals->getForceField());
633 mmeineke 614
634 tim 722 if (!strcasecmp(force_field, "DUFF")){
635     ffCase = FF_DUFF;
636     }
637     else if (!strcasecmp(force_field, "LJ")){
638     ffCase = FF_LJ;
639     }
640     else if (!strcasecmp(force_field, "EAM")){
641     ffCase = FF_EAM;
642     }
643 chrisfen 999 else if (!strcasecmp(force_field, "WATER")){
644     ffCase = FF_H2O;
645     }
646 mmeineke 614 else{
647 tim 722 sprintf(painCave.errMsg, "SimSetup Error. Unrecognized force field -> %s\n",
648     force_field);
649     painCave.isFatal = 1;
650     simError();
651 mmeineke 614 }
652    
653 tim 722 // get the ensemble
654 mmeineke 614
655 tim 722 strcpy(ensemble, globals->getEnsemble());
656 mmeineke 614
657 tim 722 if (!strcasecmp(ensemble, "NVE")){
658     ensembleCase = NVE_ENS;
659     }
660     else if (!strcasecmp(ensemble, "NVT")){
661     ensembleCase = NVT_ENS;
662     }
663     else if (!strcasecmp(ensemble, "NPTi") || !strcasecmp(ensemble, "NPT")){
664 mmeineke 614 ensembleCase = NPTi_ENS;
665 tim 722 }
666     else if (!strcasecmp(ensemble, "NPTf")){
667     ensembleCase = NPTf_ENS;
668     }
669 mmeineke 812 else if (!strcasecmp(ensemble, "NPTxyz")){
670     ensembleCase = NPTxyz_ENS;
671     }
672 mmeineke 614 else{
673 tim 722 sprintf(painCave.errMsg,
674 gezelter 965 "SimSetup Warning. Unrecognized Ensemble -> %s \n"
675     "\treverting to NVE for this simulation.\n",
676 tim 722 ensemble);
677     painCave.isFatal = 0;
678     simError();
679     strcpy(ensemble, "NVE");
680     ensembleCase = NVE_ENS;
681 mmeineke 614 }
682    
683 tim 722 for (i = 0; i < nInfo; i++){
684     strcpy(info[i].ensemble, ensemble);
685    
686 mmeineke 670 // get the mixing rule
687 mmeineke 614
688 tim 722 strcpy(info[i].mixingRule, globals->getMixingRule());
689 mmeineke 670 info[i].usePBC = globals->getPBC();
690     }
691 tim 722
692 mmeineke 614 // get the components and calculate the tot_nMol and indvidual n_mol
693 tim 722
694 mmeineke 616 the_components = globals->getComponents();
695 mmeineke 614 components_nmol = new int[n_components];
696    
697    
698 tim 722 if (!globals->haveNMol()){
699 mmeineke 614 // we don't have the total number of molecules, so we assume it is
700     // given in each component
701    
702     tot_nmol = 0;
703 tim 722 for (i = 0; i < n_components; i++){
704     if (!the_components[i]->haveNMol()){
705     // we have a problem
706     sprintf(painCave.errMsg,
707 gezelter 965 "SimSetup Error. No global NMol or component NMol given.\n"
708     "\tCannot calculate the number of atoms.\n");
709 tim 722 painCave.isFatal = 1;
710     simError();
711 mmeineke 614 }
712    
713     tot_nmol += the_components[i]->getNMol();
714     components_nmol[i] = the_components[i]->getNMol();
715     }
716     }
717     else{
718 tim 722 sprintf(painCave.errMsg,
719     "SimSetup error.\n"
720     "\tSorry, the ability to specify total"
721     " nMols and then give molfractions in the components\n"
722     "\tis not currently supported."
723     " Please give nMol in the components.\n");
724 mmeineke 614 painCave.isFatal = 1;
725     simError();
726     }
727    
728 tim 962 //check whether sample time, status time, thermal time and reset time are divisble by dt
729     if (!isDivisible(globals->getSampleTime(), globals->getDt())){
730     sprintf(painCave.errMsg,
731 gezelter 965 "Sample time is not divisible by dt.\n"
732     "\tThis will result in samples that are not uniformly\n"
733     "\tdistributed in time. If this is a problem, change\n"
734     "\tyour sampleTime variable.\n");
735 tim 962 painCave.isFatal = 0;
736     simError();
737     }
738    
739     if (globals->haveStatusTime() && !isDivisible(globals->getSampleTime(), globals->getDt())){
740     sprintf(painCave.errMsg,
741 gezelter 965 "Status time is not divisible by dt.\n"
742     "\tThis will result in status reports that are not uniformly\n"
743     "\tdistributed in time. If this is a problem, change \n"
744     "\tyour statusTime variable.\n");
745 tim 962 painCave.isFatal = 0;
746     simError();
747     }
748    
749     if (globals->haveThermalTime() && !isDivisible(globals->getThermalTime(), globals->getDt())){
750     sprintf(painCave.errMsg,
751 gezelter 965 "Thermal time is not divisible by dt.\n"
752     "\tThis will result in thermalizations that are not uniformly\n"
753     "\tdistributed in time. If this is a problem, change \n"
754     "\tyour thermalTime variable.\n");
755 tim 962 painCave.isFatal = 0;
756     simError();
757     }
758    
759     if (globals->haveResetTime() && !isDivisible(globals->getResetTime(), globals->getDt())){
760     sprintf(painCave.errMsg,
761 gezelter 965 "Reset time is not divisible by dt.\n"
762     "\tThis will result in integrator resets that are not uniformly\n"
763     "\tdistributed in time. If this is a problem, change\n"
764     "\tyour resetTime variable.\n");
765 tim 962 painCave.isFatal = 0;
766     simError();
767     }
768    
769 mmeineke 614 // set the status, sample, and thermal kick times
770    
771 tim 722 for (i = 0; i < nInfo; i++){
772     if (globals->haveSampleTime()){
773 mmeineke 670 info[i].sampleTime = globals->getSampleTime();
774     info[i].statusTime = info[i].sampleTime;
775     info[i].thermalTime = info[i].sampleTime;
776     }
777     else{
778     info[i].sampleTime = globals->getRunTime();
779     info[i].statusTime = info[i].sampleTime;
780     info[i].thermalTime = info[i].sampleTime;
781     }
782 tim 722
783     if (globals->haveStatusTime()){
784 mmeineke 670 info[i].statusTime = globals->getStatusTime();
785     }
786 tim 722
787     if (globals->haveThermalTime()){
788 mmeineke 670 info[i].thermalTime = globals->getThermalTime();
789     }
790 mmeineke 614
791 mmeineke 746 info[i].resetIntegrator = 0;
792     if( globals->haveResetTime() ){
793     info[i].resetTime = globals->getResetTime();
794     info[i].resetIntegrator = 1;
795     }
796    
797 mmeineke 670 // check for the temperature set flag
798 mmeineke 841
799 tim 722 if (globals->haveTempSet())
800     info[i].setTemp = globals->getTempSet();
801 mmeineke 855
802     // check for the extended State init
803    
804     info[i].useInitXSstate = globals->getUseInitXSstate();
805     info[i].orthoTolerance = globals->getOrthoBoxTolerance();
806 mmeineke 841
807 tim 708 }
808 mmeineke 841
809 tim 722 //setup seed for random number generator
810 tim 708 int seedValue;
811    
812 tim 722 if (globals->haveSeed()){
813 tim 708 seedValue = globals->getSeed();
814 tim 722
815     if(seedValue / 1E9 == 0){
816     sprintf(painCave.errMsg,
817     "Seed for sprng library should contain at least 9 digits\n"
818     "OOPSE will generate a seed for user\n");
819     painCave.isFatal = 0;
820     simError();
821    
822     //using seed generated by system instead of invalid seed set by user
823     #ifndef IS_MPI
824     seedValue = make_sprng_seed();
825     #else
826     if (worldRank == 0){
827     seedValue = make_sprng_seed();
828     }
829     MPI_Bcast(&seedValue, 1, MPI_INT, 0, MPI_COMM_WORLD);
830     #endif
831     }
832     }//end of if branch of globals->haveSeed()
833 tim 708 else{
834 tim 722
835 tim 708 #ifndef IS_MPI
836 tim 722 seedValue = make_sprng_seed();
837 tim 708 #else
838 tim 722 if (worldRank == 0){
839     seedValue = make_sprng_seed();
840 tim 708 }
841 tim 722 MPI_Bcast(&seedValue, 1, MPI_INT, 0, MPI_COMM_WORLD);
842 tim 708 #endif
843 tim 722 }//end of globals->haveSeed()
844 tim 708
845 tim 722 for (int i = 0; i < nInfo; i++){
846 tim 708 info[i].setSeed(seedValue);
847     }
848 tim 1031
849 mmeineke 614 #ifdef IS_MPI
850 chrisfen 999 strcpy(checkPointMsg, "Successfully gathered all information from Bass\n");
851 mmeineke 614 MPIcheckPoint();
852     #endif // is_mpi
853     }
854    
855    
856 tim 722 void SimSetup::finalInfoCheck(void){
857 mmeineke 614 int index;
858     int usesDipoles;
859 mmeineke 670 int i;
860 mmeineke 614
861 tim 722 for (i = 0; i < nInfo; i++){
862 mmeineke 670 // check electrostatic parameters
863 tim 722
864 mmeineke 670 index = 0;
865     usesDipoles = 0;
866 tim 722 while ((index < info[i].n_atoms) && !usesDipoles){
867 mmeineke 670 usesDipoles = (info[i].atoms[index])->hasDipole();
868     index++;
869     }
870 tim 722
871 mmeineke 614 #ifdef IS_MPI
872 mmeineke 670 int myUse = usesDipoles;
873 tim 722 MPI_Allreduce(&myUse, &usesDipoles, 1, MPI_INT, MPI_LOR, MPI_COMM_WORLD);
874 mmeineke 614 #endif //is_mpi
875 tim 722
876 mmeineke 670 double theEcr, theEst;
877 tim 722
878     if (globals->getUseRF()){
879 mmeineke 670 info[i].useReactionField = 1;
880 tim 722
881     if (!globals->haveECR()){
882     sprintf(painCave.errMsg,
883 gezelter 965 "SimSetup Warning: No value was set for electrostaticCutoffRadius.\n"
884     "\tOOPSE will use a default value of 15.0 angstroms"
885     "\tfor the electrostaticCutoffRadius.\n");
886 tim 722 painCave.isFatal = 0;
887     simError();
888 mmeineke 859 theEcr = 15.0;
889 mmeineke 614 }
890 tim 722 else{
891     theEcr = globals->getECR();
892 mmeineke 614 }
893 tim 722
894     if (!globals->haveEST()){
895     sprintf(painCave.errMsg,
896 gezelter 965 "SimSetup Warning: No value was set for electrostaticSkinThickness.\n"
897     "\tOOPSE will use a default value of\n"
898     "\t0.05 * electrostaticCutoffRadius\n"
899     "\tfor the electrostaticSkinThickness\n");
900 tim 722 painCave.isFatal = 0;
901     simError();
902     theEst = 0.05 * theEcr;
903 mmeineke 670 }
904 tim 722 else{
905     theEst = globals->getEST();
906 mmeineke 670 }
907 tim 722
908 mmeineke 841 info[i].setDefaultEcr(theEcr, theEst);
909 tim 722
910     if (!globals->haveDielectric()){
911     sprintf(painCave.errMsg,
912 gezelter 965 "SimSetup Error: No Dielectric constant was set.\n"
913     "\tYou are trying to use Reaction Field without"
914     "\tsetting a dielectric constant!\n");
915 tim 722 painCave.isFatal = 1;
916     simError();
917     }
918     info[i].dielectric = globals->getDielectric();
919     }
920     else{
921     if (usesDipoles){
922     if (!globals->haveECR()){
923     sprintf(painCave.errMsg,
924 gezelter 965 "SimSetup Warning: No value was set for electrostaticCutoffRadius.\n"
925     "\tOOPSE will use a default value of 15.0 angstroms"
926     "\tfor the electrostaticCutoffRadius.\n");
927 mmeineke 859 painCave.isFatal = 0;
928     simError();
929     theEcr = 15.0;
930 tim 722 }
931     else{
932     theEcr = globals->getECR();
933     }
934 mmeineke 859
935 tim 722 if (!globals->haveEST()){
936     sprintf(painCave.errMsg,
937 gezelter 965 "SimSetup Warning: No value was set for electrostaticSkinThickness.\n"
938     "\tOOPSE will use a default value of\n"
939     "\t0.05 * electrostaticCutoffRadius\n"
940     "\tfor the electrostaticSkinThickness\n");
941 tim 722 painCave.isFatal = 0;
942     simError();
943     theEst = 0.05 * theEcr;
944     }
945     else{
946     theEst = globals->getEST();
947     }
948 mmeineke 859
949 mmeineke 841 info[i].setDefaultEcr(theEcr, theEst);
950 tim 722 }
951     }
952 mmeineke 670 }
953 mmeineke 614 #ifdef IS_MPI
954 tim 722 strcpy(checkPointMsg, "post processing checks out");
955 mmeineke 614 MPIcheckPoint();
956     #endif // is_mpi
957     }
958 mmeineke 859
959 tim 722 void SimSetup::initSystemCoords(void){
960 mmeineke 670 int i;
961 tim 722
962 tim 689 char* inName;
963    
964 tim 722 (info[0].getConfiguration())->createArrays(info[0].n_atoms);
965 mmeineke 614
966 tim 722 for (i = 0; i < info[0].n_atoms; i++)
967     info[0].atoms[i]->setCoords();
968    
969     if (globals->haveInitialConfig()){
970 mmeineke 670 InitializeFromFile* fileInit;
971 mmeineke 614 #ifdef IS_MPI // is_mpi
972 tim 722 if (worldRank == 0){
973 mmeineke 614 #endif //is_mpi
974 tim 689 inName = globals->getInitialConfig();
975 tim 722 fileInit = new InitializeFromFile(inName);
976 mmeineke 614 #ifdef IS_MPI
977 tim 722 }
978     else
979     fileInit = new InitializeFromFile(NULL);
980 mmeineke 614 #endif
981 tim 722 fileInit->readInit(info); // default velocities on
982    
983 mmeineke 670 delete fileInit;
984     }
985     else{
986 mmeineke 859
987 mmeineke 670 // no init from bass
988 mmeineke 859
989 tim 722 sprintf(painCave.errMsg,
990 mmeineke 859 "Cannot intialize a simulation without an initial configuration file.\n");
991 mmeineke 787 painCave.isFatal = 1;;
992 mmeineke 670 simError();
993 mmeineke 859
994 mmeineke 670 }
995 tim 722
996 mmeineke 614 #ifdef IS_MPI
997 tim 722 strcpy(checkPointMsg, "Successfully read in the initial configuration");
998 mmeineke 614 MPIcheckPoint();
999     #endif // is_mpi
1000     }
1001    
1002    
1003 tim 722 void SimSetup::makeOutNames(void){
1004 mmeineke 670 int k;
1005 mmeineke 614
1006 mmeineke 670
1007 tim 722 for (k = 0; k < nInfo; k++){
1008 mmeineke 614 #ifdef IS_MPI
1009 tim 722 if (worldRank == 0){
1010 mmeineke 614 #endif // is_mpi
1011 tim 722
1012     if (globals->haveFinalConfig()){
1013     strcpy(info[k].finalName, globals->getFinalConfig());
1014 mmeineke 614 }
1015     else{
1016 tim 722 strcpy(info[k].finalName, inFileName);
1017     char* endTest;
1018     int nameLength = strlen(info[k].finalName);
1019     endTest = &(info[k].finalName[nameLength - 5]);
1020     if (!strcmp(endTest, ".bass")){
1021     strcpy(endTest, ".eor");
1022     }
1023     else if (!strcmp(endTest, ".BASS")){
1024     strcpy(endTest, ".eor");
1025     }
1026     else{
1027     endTest = &(info[k].finalName[nameLength - 4]);
1028     if (!strcmp(endTest, ".bss")){
1029     strcpy(endTest, ".eor");
1030     }
1031     else if (!strcmp(endTest, ".mdl")){
1032     strcpy(endTest, ".eor");
1033     }
1034     else{
1035     strcat(info[k].finalName, ".eor");
1036     }
1037     }
1038 mmeineke 614 }
1039 tim 722
1040 mmeineke 670 // make the sample and status out names
1041 tim 722
1042     strcpy(info[k].sampleName, inFileName);
1043 mmeineke 670 char* endTest;
1044 tim 722 int nameLength = strlen(info[k].sampleName);
1045 mmeineke 670 endTest = &(info[k].sampleName[nameLength - 5]);
1046 tim 722 if (!strcmp(endTest, ".bass")){
1047     strcpy(endTest, ".dump");
1048 mmeineke 614 }
1049 tim 722 else if (!strcmp(endTest, ".BASS")){
1050     strcpy(endTest, ".dump");
1051 mmeineke 614 }
1052     else{
1053 tim 722 endTest = &(info[k].sampleName[nameLength - 4]);
1054     if (!strcmp(endTest, ".bss")){
1055     strcpy(endTest, ".dump");
1056     }
1057     else if (!strcmp(endTest, ".mdl")){
1058     strcpy(endTest, ".dump");
1059     }
1060     else{
1061     strcat(info[k].sampleName, ".dump");
1062     }
1063 mmeineke 614 }
1064 tim 722
1065     strcpy(info[k].statusName, inFileName);
1066     nameLength = strlen(info[k].statusName);
1067 mmeineke 670 endTest = &(info[k].statusName[nameLength - 5]);
1068 tim 722 if (!strcmp(endTest, ".bass")){
1069     strcpy(endTest, ".stat");
1070 mmeineke 614 }
1071 tim 722 else if (!strcmp(endTest, ".BASS")){
1072     strcpy(endTest, ".stat");
1073 mmeineke 614 }
1074     else{
1075 tim 722 endTest = &(info[k].statusName[nameLength - 4]);
1076     if (!strcmp(endTest, ".bss")){
1077     strcpy(endTest, ".stat");
1078     }
1079     else if (!strcmp(endTest, ".mdl")){
1080     strcpy(endTest, ".stat");
1081     }
1082     else{
1083     strcat(info[k].statusName, ".stat");
1084     }
1085 mmeineke 614 }
1086 tim 722
1087 mmeineke 670 #ifdef IS_MPI
1088 tim 722
1089 mmeineke 614 }
1090 mmeineke 670 #endif // is_mpi
1091 mmeineke 614 }
1092     }
1093    
1094    
1095 tim 722 void SimSetup::sysObjectsCreation(void){
1096     int i, k;
1097    
1098 mmeineke 614 // create the forceField
1099 tim 689
1100 mmeineke 614 createFF();
1101    
1102     // extract componentList
1103    
1104     compList();
1105    
1106     // calc the number of atoms, bond, bends, and torsions
1107    
1108     calcSysValues();
1109    
1110     #ifdef IS_MPI
1111     // divide the molecules among the processors
1112 tim 722
1113 mmeineke 614 mpiMolDivide();
1114     #endif //is_mpi
1115 tim 722
1116 mmeineke 614 // create the atom and SRI arrays. Also initialize Molecule Stamp ID's
1117 tim 722
1118 mmeineke 614 makeSysArrays();
1119    
1120 mmeineke 616 // make and initialize the molecules (all but atomic coordinates)
1121 tim 722
1122 mmeineke 616 makeMolecules();
1123 tim 722
1124     for (k = 0; k < nInfo; k++){
1125 mmeineke 670 info[k].identArray = new int[info[k].n_atoms];
1126 tim 722 for (i = 0; i < info[k].n_atoms; i++){
1127 mmeineke 670 info[k].identArray[i] = info[k].atoms[i]->getIdent();
1128     }
1129 mmeineke 616 }
1130 mmeineke 614 }
1131    
1132    
1133 tim 722 void SimSetup::createFF(void){
1134     switch (ffCase){
1135     case FF_DUFF:
1136     the_ff = new DUFF();
1137     break;
1138 mmeineke 614
1139 tim 722 case FF_LJ:
1140     the_ff = new LJFF();
1141     break;
1142 mmeineke 614
1143 tim 722 case FF_EAM:
1144     the_ff = new EAM_FF();
1145     break;
1146 mmeineke 614
1147 chrisfen 999 case FF_H2O:
1148     the_ff = new WATER();
1149     break;
1150    
1151 tim 722 default:
1152     sprintf(painCave.errMsg,
1153     "SimSetup Error. Unrecognized force field in case statement.\n");
1154     painCave.isFatal = 1;
1155     simError();
1156 mmeineke 614 }
1157    
1158     #ifdef IS_MPI
1159 tim 722 strcpy(checkPointMsg, "ForceField creation successful");
1160 mmeineke 614 MPIcheckPoint();
1161     #endif // is_mpi
1162     }
1163    
1164    
1165 tim 722 void SimSetup::compList(void){
1166 mmeineke 616 int i;
1167 mmeineke 670 char* id;
1168     LinkedMolStamp* headStamp = new LinkedMolStamp();
1169     LinkedMolStamp* currentStamp = NULL;
1170 tim 722 comp_stamps = new MoleculeStamp * [n_components];
1171    
1172 mmeineke 614 // make an array of molecule stamps that match the components used.
1173     // also extract the used stamps out into a separate linked list
1174 tim 722
1175     for (i = 0; i < nInfo; i++){
1176 mmeineke 670 info[i].nComponents = n_components;
1177     info[i].componentsNmol = components_nmol;
1178     info[i].compStamps = comp_stamps;
1179     info[i].headStamp = headStamp;
1180     }
1181 mmeineke 614
1182    
1183 tim 722 for (i = 0; i < n_components; i++){
1184 mmeineke 614 id = the_components[i]->getType();
1185     comp_stamps[i] = NULL;
1186 tim 722
1187 mmeineke 614 // check to make sure the component isn't already in the list
1188    
1189 tim 722 comp_stamps[i] = headStamp->match(id);
1190     if (comp_stamps[i] == NULL){
1191 mmeineke 614 // extract the component from the list;
1192 tim 722
1193     currentStamp = stamps->extractMolStamp(id);
1194     if (currentStamp == NULL){
1195     sprintf(painCave.errMsg,
1196     "SimSetup error: Component \"%s\" was not found in the "
1197     "list of declared molecules\n",
1198     id);
1199     painCave.isFatal = 1;
1200     simError();
1201 mmeineke 614 }
1202 tim 722
1203     headStamp->add(currentStamp);
1204     comp_stamps[i] = headStamp->match(id);
1205 mmeineke 614 }
1206     }
1207    
1208     #ifdef IS_MPI
1209 tim 722 strcpy(checkPointMsg, "Component stamps successfully extracted\n");
1210 mmeineke 614 MPIcheckPoint();
1211     #endif // is_mpi
1212 tim 722 }
1213 mmeineke 614
1214 tim 722 void SimSetup::calcSysValues(void){
1215 mmeineke 787 int i;
1216 mmeineke 614
1217 tim 722 int* molMembershipArray;
1218 mmeineke 614
1219     tot_atoms = 0;
1220     tot_bonds = 0;
1221     tot_bends = 0;
1222     tot_torsions = 0;
1223 tim 722 for (i = 0; i < n_components; i++){
1224     tot_atoms += components_nmol[i] * comp_stamps[i]->getNAtoms();
1225     tot_bonds += components_nmol[i] * comp_stamps[i]->getNBonds();
1226     tot_bends += components_nmol[i] * comp_stamps[i]->getNBends();
1227 mmeineke 614 tot_torsions += components_nmol[i] * comp_stamps[i]->getNTorsions();
1228     }
1229 tim 722
1230 mmeineke 614 tot_SRI = tot_bonds + tot_bends + tot_torsions;
1231 mmeineke 670 molMembershipArray = new int[tot_atoms];
1232 tim 722
1233     for (i = 0; i < nInfo; i++){
1234 mmeineke 670 info[i].n_atoms = tot_atoms;
1235     info[i].n_bonds = tot_bonds;
1236     info[i].n_bends = tot_bends;
1237     info[i].n_torsions = tot_torsions;
1238     info[i].n_SRI = tot_SRI;
1239     info[i].n_mol = tot_nmol;
1240 tim 722
1241 mmeineke 670 info[i].molMembershipArray = molMembershipArray;
1242 tim 722 }
1243 mmeineke 614 }
1244    
1245     #ifdef IS_MPI
1246    
1247 tim 722 void SimSetup::mpiMolDivide(void){
1248 mmeineke 616 int i, j, k;
1249 mmeineke 614 int localMol, allMol;
1250     int local_atoms, local_bonds, local_bends, local_torsions, local_SRI;
1251    
1252 tim 722 mpiSim = new mpiSimulation(info);
1253    
1254 mmeineke 614 globalIndex = mpiSim->divideLabor();
1255    
1256     // set up the local variables
1257 tim 722
1258 mmeineke 614 mol2proc = mpiSim->getMolToProcMap();
1259     molCompType = mpiSim->getMolComponentType();
1260 tim 722
1261 mmeineke 614 allMol = 0;
1262     localMol = 0;
1263     local_atoms = 0;
1264     local_bonds = 0;
1265     local_bends = 0;
1266     local_torsions = 0;
1267     globalAtomIndex = 0;
1268    
1269    
1270 tim 722 for (i = 0; i < n_components; i++){
1271     for (j = 0; j < components_nmol[i]; j++){
1272     if (mol2proc[allMol] == worldRank){
1273     local_atoms += comp_stamps[i]->getNAtoms();
1274     local_bonds += comp_stamps[i]->getNBonds();
1275     local_bends += comp_stamps[i]->getNBends();
1276     local_torsions += comp_stamps[i]->getNTorsions();
1277     localMol++;
1278 mmeineke 614 }
1279 tim 722 for (k = 0; k < comp_stamps[i]->getNAtoms(); k++){
1280 mmeineke 670 info[0].molMembershipArray[globalAtomIndex] = allMol;
1281 mmeineke 614 globalAtomIndex++;
1282     }
1283    
1284 tim 722 allMol++;
1285 mmeineke 614 }
1286     }
1287     local_SRI = local_bonds + local_bends + local_torsions;
1288 tim 722
1289 mmeineke 670 info[0].n_atoms = mpiSim->getMyNlocal();
1290 tim 722
1291     if (local_atoms != info[0].n_atoms){
1292     sprintf(painCave.errMsg,
1293 gezelter 965 "SimSetup error: mpiSim's localAtom (%d) and SimSetup's\n"
1294     "\tlocalAtom (%d) are not equal.\n",
1295 tim 722 info[0].n_atoms, local_atoms);
1296 mmeineke 614 painCave.isFatal = 1;
1297     simError();
1298     }
1299    
1300 mmeineke 670 info[0].n_bonds = local_bonds;
1301     info[0].n_bends = local_bends;
1302     info[0].n_torsions = local_torsions;
1303     info[0].n_SRI = local_SRI;
1304     info[0].n_mol = localMol;
1305 mmeineke 614
1306 tim 722 strcpy(checkPointMsg, "Passed nlocal consistency check.");
1307 mmeineke 614 MPIcheckPoint();
1308     }
1309 tim 722
1310 mmeineke 614 #endif // is_mpi
1311    
1312    
1313 tim 722 void SimSetup::makeSysArrays(void){
1314 mmeineke 787
1315     #ifndef IS_MPI
1316     int k, j;
1317     #endif // is_mpi
1318     int i, l;
1319 mmeineke 614
1320 mmeineke 670 Atom** the_atoms;
1321     Molecule* the_molecules;
1322     Exclude** the_excludes;
1323 mmeineke 616
1324 tim 722
1325     for (l = 0; l < nInfo; l++){
1326 mmeineke 670 // create the atom and short range interaction arrays
1327 tim 722
1328     the_atoms = new Atom * [info[l].n_atoms];
1329 mmeineke 670 the_molecules = new Molecule[info[l].n_mol];
1330     int molIndex;
1331 mmeineke 614
1332 mmeineke 670 // initialize the molecule's stampID's
1333 tim 722
1334 mmeineke 670 #ifdef IS_MPI
1335 tim 722
1336    
1337 mmeineke 670 molIndex = 0;
1338 tim 722 for (i = 0; i < mpiSim->getTotNmol(); i++){
1339     if (mol2proc[i] == worldRank){
1340     the_molecules[molIndex].setStampID(molCompType[i]);
1341     the_molecules[molIndex].setMyIndex(molIndex);
1342     the_molecules[molIndex].setGlobalIndex(i);
1343     molIndex++;
1344 mmeineke 670 }
1345 mmeineke 614 }
1346 tim 722
1347 mmeineke 614 #else // is_mpi
1348 tim 722
1349 mmeineke 670 molIndex = 0;
1350     globalAtomIndex = 0;
1351 tim 722 for (i = 0; i < n_components; i++){
1352     for (j = 0; j < components_nmol[i]; j++){
1353     the_molecules[molIndex].setStampID(i);
1354     the_molecules[molIndex].setMyIndex(molIndex);
1355     the_molecules[molIndex].setGlobalIndex(molIndex);
1356     for (k = 0; k < comp_stamps[i]->getNAtoms(); k++){
1357     info[l].molMembershipArray[globalAtomIndex] = molIndex;
1358     globalAtomIndex++;
1359     }
1360     molIndex++;
1361 mmeineke 614 }
1362     }
1363 tim 722
1364    
1365 mmeineke 614 #endif // is_mpi
1366    
1367    
1368 tim 722 if (info[l].n_SRI){
1369 mmeineke 670 Exclude::createArray(info[l].n_SRI);
1370 tim 722 the_excludes = new Exclude * [info[l].n_SRI];
1371     for (int ex = 0; ex < info[l].n_SRI; ex++){
1372     the_excludes[ex] = new Exclude(ex);
1373 mmeineke 670 }
1374     info[l].globalExcludes = new int;
1375     info[l].n_exclude = info[l].n_SRI;
1376     }
1377     else{
1378 tim 722 Exclude::createArray(1);
1379     the_excludes = new Exclude * ;
1380 mmeineke 670 the_excludes[0] = new Exclude(0);
1381 tim 722 the_excludes[0]->setPair(0, 0);
1382 mmeineke 670 info[l].globalExcludes = new int;
1383     info[l].globalExcludes[0] = 0;
1384     info[l].n_exclude = 0;
1385     }
1386 mmeineke 614
1387 mmeineke 670 // set the arrays into the SimInfo object
1388 mmeineke 614
1389 mmeineke 670 info[l].atoms = the_atoms;
1390     info[l].molecules = the_molecules;
1391     info[l].nGlobalExcludes = 0;
1392     info[l].excludes = the_excludes;
1393 mmeineke 614
1394 tim 722 the_ff->setSimInfo(info);
1395 mmeineke 670 }
1396 mmeineke 614 }
1397 mmeineke 616
1398 tim 722 void SimSetup::makeIntegrator(void){
1399 mmeineke 670 int k;
1400    
1401 mmeineke 782 NVE<RealIntegrator>* myNVE = NULL;
1402 tim 722 NVT<RealIntegrator>* myNVT = NULL;
1403 mmeineke 778 NPTi<NPT<RealIntegrator> >* myNPTi = NULL;
1404 mmeineke 780 NPTf<NPT<RealIntegrator> >* myNPTf = NULL;
1405 mmeineke 812 NPTxyz<NPT<RealIntegrator> >* myNPTxyz = NULL;
1406 tim 733
1407 tim 722 for (k = 0; k < nInfo; k++){
1408     switch (ensembleCase){
1409     case NVE_ENS:
1410     if (globals->haveZconstraints()){
1411     setupZConstraint(info[k]);
1412 mmeineke 782 myNVE = new ZConstraint<NVE<RealIntegrator> >(&(info[k]), the_ff);
1413 tim 722 }
1414 mmeineke 782 else{
1415     myNVE = new NVE<RealIntegrator>(&(info[k]), the_ff);
1416     }
1417    
1418     info->the_integrator = myNVE;
1419 tim 722 break;
1420 tim 676
1421 tim 722 case NVT_ENS:
1422     if (globals->haveZconstraints()){
1423     setupZConstraint(info[k]);
1424     myNVT = new ZConstraint<NVT<RealIntegrator> >(&(info[k]), the_ff);
1425     }
1426     else
1427     myNVT = new NVT<RealIntegrator>(&(info[k]), the_ff);
1428    
1429 tim 701 myNVT->setTargetTemp(globals->getTargetTemp());
1430 tim 722
1431     if (globals->haveTauThermostat())
1432 tim 701 myNVT->setTauThermostat(globals->getTauThermostat());
1433 tim 722 else{
1434     sprintf(painCave.errMsg,
1435     "SimSetup error: If you use the NVT\n"
1436 gezelter 965 "\tensemble, you must set tauThermostat.\n");
1437 tim 701 painCave.isFatal = 1;
1438     simError();
1439     }
1440 mmeineke 782
1441     info->the_integrator = myNVT;
1442 tim 701 break;
1443 tim 676
1444 tim 722 case NPTi_ENS:
1445     if (globals->haveZconstraints()){
1446     setupZConstraint(info[k]);
1447 mmeineke 778 myNPTi = new ZConstraint<NPTi<NPT <RealIntegrator> > >(&(info[k]), the_ff);
1448 tim 722 }
1449     else
1450 mmeineke 778 myNPTi = new NPTi<NPT<RealIntegrator> >(&(info[k]), the_ff);
1451 tim 722
1452     myNPTi->setTargetTemp(globals->getTargetTemp());
1453    
1454     if (globals->haveTargetPressure())
1455     myNPTi->setTargetPressure(globals->getTargetPressure());
1456     else{
1457     sprintf(painCave.errMsg,
1458     "SimSetup error: If you use a constant pressure\n"
1459 gezelter 965 "\tensemble, you must set targetPressure in the BASS file.\n");
1460 tim 722 painCave.isFatal = 1;
1461     simError();
1462     }
1463    
1464     if (globals->haveTauThermostat())
1465     myNPTi->setTauThermostat(globals->getTauThermostat());
1466     else{
1467     sprintf(painCave.errMsg,
1468     "SimSetup error: If you use an NPT\n"
1469 gezelter 965 "\tensemble, you must set tauThermostat.\n");
1470 tim 722 painCave.isFatal = 1;
1471     simError();
1472     }
1473    
1474     if (globals->haveTauBarostat())
1475     myNPTi->setTauBarostat(globals->getTauBarostat());
1476     else{
1477     sprintf(painCave.errMsg,
1478 tim 701 "SimSetup error: If you use an NPT\n"
1479 gezelter 965 "\tensemble, you must set tauBarostat.\n");
1480 tim 722 painCave.isFatal = 1;
1481     simError();
1482     }
1483 mmeineke 782
1484     info->the_integrator = myNPTi;
1485 tim 722 break;
1486 tim 676
1487 tim 722 case NPTf_ENS:
1488     if (globals->haveZconstraints()){
1489     setupZConstraint(info[k]);
1490 mmeineke 780 myNPTf = new ZConstraint<NPTf<NPT <RealIntegrator> > >(&(info[k]), the_ff);
1491 tim 722 }
1492     else
1493 mmeineke 780 myNPTf = new NPTf<NPT <RealIntegrator> >(&(info[k]), the_ff);
1494 tim 722
1495     myNPTf->setTargetTemp(globals->getTargetTemp());
1496    
1497     if (globals->haveTargetPressure())
1498     myNPTf->setTargetPressure(globals->getTargetPressure());
1499     else{
1500     sprintf(painCave.errMsg,
1501 tim 701 "SimSetup error: If you use a constant pressure\n"
1502 gezelter 965 "\tensemble, you must set targetPressure in the BASS file.\n");
1503 tim 722 painCave.isFatal = 1;
1504     simError();
1505     }
1506    
1507     if (globals->haveTauThermostat())
1508     myNPTf->setTauThermostat(globals->getTauThermostat());
1509 mmeineke 843
1510 tim 722 else{
1511     sprintf(painCave.errMsg,
1512 tim 701 "SimSetup error: If you use an NPT\n"
1513 gezelter 965 "\tensemble, you must set tauThermostat.\n");
1514 tim 722 painCave.isFatal = 1;
1515     simError();
1516     }
1517    
1518     if (globals->haveTauBarostat())
1519     myNPTf->setTauBarostat(globals->getTauBarostat());
1520 mmeineke 843
1521 tim 722 else{
1522     sprintf(painCave.errMsg,
1523     "SimSetup error: If you use an NPT\n"
1524 gezelter 965 "\tensemble, you must set tauBarostat.\n");
1525 tim 722 painCave.isFatal = 1;
1526     simError();
1527     }
1528 mmeineke 782
1529     info->the_integrator = myNPTf;
1530 tim 722 break;
1531 tim 676
1532 mmeineke 812 case NPTxyz_ENS:
1533     if (globals->haveZconstraints()){
1534     setupZConstraint(info[k]);
1535     myNPTxyz = new ZConstraint<NPTxyz<NPT <RealIntegrator> > >(&(info[k]), the_ff);
1536     }
1537     else
1538     myNPTxyz = new NPTxyz<NPT <RealIntegrator> >(&(info[k]), the_ff);
1539    
1540     myNPTxyz->setTargetTemp(globals->getTargetTemp());
1541    
1542     if (globals->haveTargetPressure())
1543     myNPTxyz->setTargetPressure(globals->getTargetPressure());
1544     else{
1545     sprintf(painCave.errMsg,
1546     "SimSetup error: If you use a constant pressure\n"
1547 gezelter 965 "\tensemble, you must set targetPressure in the BASS file.\n");
1548 mmeineke 812 painCave.isFatal = 1;
1549     simError();
1550     }
1551    
1552     if (globals->haveTauThermostat())
1553     myNPTxyz->setTauThermostat(globals->getTauThermostat());
1554     else{
1555     sprintf(painCave.errMsg,
1556     "SimSetup error: If you use an NPT\n"
1557 gezelter 965 "\tensemble, you must set tauThermostat.\n");
1558 mmeineke 812 painCave.isFatal = 1;
1559     simError();
1560     }
1561    
1562     if (globals->haveTauBarostat())
1563     myNPTxyz->setTauBarostat(globals->getTauBarostat());
1564     else{
1565     sprintf(painCave.errMsg,
1566     "SimSetup error: If you use an NPT\n"
1567 gezelter 965 "\tensemble, you must set tauBarostat.\n");
1568 mmeineke 812 painCave.isFatal = 1;
1569     simError();
1570     }
1571    
1572     info->the_integrator = myNPTxyz;
1573     break;
1574    
1575 tim 722 default:
1576     sprintf(painCave.errMsg,
1577     "SimSetup Error. Unrecognized ensemble in case statement.\n");
1578 tim 701 painCave.isFatal = 1;
1579     simError();
1580 tim 660 }
1581 mmeineke 616 }
1582     }
1583    
1584 tim 722 void SimSetup::initFortran(void){
1585     info[0].refreshSim();
1586 mmeineke 616
1587 tim 722 if (!strcmp(info[0].mixingRule, "standard")){
1588     the_ff->initForceField(LB_MIXING_RULE);
1589 mmeineke 616 }
1590 tim 722 else if (!strcmp(info[0].mixingRule, "explicit")){
1591     the_ff->initForceField(EXPLICIT_MIXING_RULE);
1592 mmeineke 616 }
1593     else{
1594 tim 722 sprintf(painCave.errMsg, "SimSetup Error: unknown mixing rule -> \"%s\"\n",
1595     info[0].mixingRule);
1596 mmeineke 616 painCave.isFatal = 1;
1597     simError();
1598     }
1599    
1600    
1601     #ifdef IS_MPI
1602 tim 722 strcpy(checkPointMsg, "Successfully intialized the mixingRule for Fortran.");
1603 mmeineke 616 MPIcheckPoint();
1604     #endif // is_mpi
1605     }
1606 tim 660
1607 tim 722 void SimSetup::setupZConstraint(SimInfo& theInfo){
1608 tim 701 int nZConstraints;
1609     ZconStamp** zconStamp;
1610 tim 682
1611 tim 722 if (globals->haveZconstraintTime()){
1612 tim 701 //add sample time of z-constraint into SimInfo's property list
1613     DoubleData* zconsTimeProp = new DoubleData();
1614     zconsTimeProp->setID(ZCONSTIME_ID);
1615     zconsTimeProp->setData(globals->getZconsTime());
1616     theInfo.addProperty(zconsTimeProp);
1617     }
1618     else{
1619 tim 722 sprintf(painCave.errMsg,
1620 gezelter 965 "ZConstraint error: If you use a ZConstraint,\n"
1621     "\tyou must set zconsTime.\n");
1622 tim 701 painCave.isFatal = 1;
1623 tim 722 simError();
1624 tim 701 }
1625 tim 682
1626 tim 701 //push zconsTol into siminfo, if user does not specify
1627     //value for zconsTol, a default value will be used
1628     DoubleData* zconsTol = new DoubleData();
1629     zconsTol->setID(ZCONSTOL_ID);
1630 tim 722 if (globals->haveZconsTol()){
1631 tim 701 zconsTol->setData(globals->getZconsTol());
1632     }
1633     else{
1634 tim 722 double defaultZConsTol = 0.01;
1635     sprintf(painCave.errMsg,
1636 gezelter 965 "ZConstraint Warning: Tolerance for z-constraint method is not specified.\n"
1637     "\tOOPSE will use a default value of %f.\n"
1638     "\tTo set the tolerance, use the zconsTol variable.\n",
1639 tim 722 defaultZConsTol);
1640 tim 701 painCave.isFatal = 0;
1641     simError();
1642 tim 699
1643 tim 701 zconsTol->setData(defaultZConsTol);
1644     }
1645     theInfo.addProperty(zconsTol);
1646 tim 699
1647 tim 738 //set Force Subtraction Policy
1648 tim 722 StringData* zconsForcePolicy = new StringData();
1649 tim 701 zconsForcePolicy->setID(ZCONSFORCEPOLICY_ID);
1650 tim 722
1651     if (globals->haveZconsForcePolicy()){
1652 tim 701 zconsForcePolicy->setData(globals->getZconsForcePolicy());
1653 tim 722 }
1654 tim 701 else{
1655 tim 722 sprintf(painCave.errMsg,
1656 gezelter 965 "ZConstraint Warning: No force subtraction policy was set.\n"
1657     "\tOOPSE will use PolicyByMass.\n"
1658     "\tTo set the policy, use the zconsForcePolicy variable.\n");
1659 tim 722 painCave.isFatal = 0;
1660     simError();
1661 tim 736 zconsForcePolicy->setData("BYMASS");
1662 tim 701 }
1663 tim 722
1664     theInfo.addProperty(zconsForcePolicy);
1665    
1666 tim 701 //Determine the name of ouput file and add it into SimInfo's property list
1667     //Be careful, do not use inFileName, since it is a pointer which
1668     //point to a string at master node, and slave nodes do not contain that string
1669 tim 722
1670 tim 701 string zconsOutput(theInfo.finalName);
1671 tim 722
1672 tim 701 zconsOutput = zconsOutput.substr(0, zconsOutput.rfind(".")) + ".fz";
1673 tim 722
1674 tim 701 StringData* zconsFilename = new StringData();
1675     zconsFilename->setID(ZCONSFILENAME_ID);
1676     zconsFilename->setData(zconsOutput);
1677 tim 722
1678 tim 701 theInfo.addProperty(zconsFilename);
1679 tim 722
1680 tim 701 //setup index, pos and other parameters of z-constraint molecules
1681     nZConstraints = globals->getNzConstraints();
1682     theInfo.nZconstraints = nZConstraints;
1683    
1684     zconStamp = globals->getZconStamp();
1685     ZConsParaItem tempParaItem;
1686    
1687     ZConsParaData* zconsParaData = new ZConsParaData();
1688     zconsParaData->setID(ZCONSPARADATA_ID);
1689 tim 722
1690     for (int i = 0; i < nZConstraints; i++){
1691 tim 699 tempParaItem.havingZPos = zconStamp[i]->haveZpos();
1692     tempParaItem.zPos = zconStamp[i]->getZpos();
1693     tempParaItem.zconsIndex = zconStamp[i]->getMolIndex();
1694     tempParaItem.kRatio = zconStamp[i]->getKratio();
1695    
1696     zconsParaData->addItem(tempParaItem);
1697 tim 701 }
1698 tim 699
1699 tim 736 //check the uniqueness of index
1700     if(!zconsParaData->isIndexUnique()){
1701     sprintf(painCave.errMsg,
1702 gezelter 965 "ZConstraint Error: molIndex is not unique!\n");
1703 tim 736 painCave.isFatal = 1;
1704     simError();
1705     }
1706    
1707 tim 701 //sort the parameters by index of molecules
1708     zconsParaData->sortByIndex();
1709 tim 736
1710 tim 701 //push data into siminfo, therefore, we can retrieve later
1711     theInfo.addProperty(zconsParaData);
1712 tim 660 }
1713 tim 1031
1714     void SimSetup::makeMinimizer(){
1715 tim 1032
1716 tim 1031 OOPSEMinimizerBase* myOOPSEMinimizerBase;
1717     ObjFunctor1 * objFunc;
1718     OutputFunctor* outputFunc;
1719     ConcreteNLModel1* nlp;
1720     MinimizerParameterSet* param;
1721     ConjugateMinimizerBase* minimizer;
1722     int dim;
1723    
1724     for (int i = 0; i < nInfo; i++){
1725     //creat
1726     myOOPSEMinimizerBase = new OOPSEMinimizerBase(&(info[i]), the_ff);
1727    
1728     //creat the object functor;
1729     objFunc = (ObjFunctor1*) new ClassMemObjFunctor1<OOPSEMinimizerBase>
1730     (myOOPSEMinimizerBase, &OOPSEMinimizerBase::calcGradient);
1731    
1732     //creat output functor;
1733     outputFunc = new ClassMemOutputFunctor<OOPSEMinimizerBase>
1734     (myOOPSEMinimizerBase, &OOPSEMinimizerBase::output);
1735    
1736     //creat nonlinear model
1737     dim = myOOPSEMinimizerBase->getDim();
1738     nlp = new ConcreteNLModel1(dim, objFunc);
1739    
1740     //prepare parameter set for minimizer
1741     param = new MinimizerParameterSet();
1742     param->setDefaultParameter();
1743    
1744     if (globals->haveMinimizer()){
1745     param->setFTol(globals->getMinFTol());
1746     }
1747    
1748     if (globals->haveMinGTol()){
1749     param->setGTol(globals->getMinGTol());
1750     }
1751    
1752     if (globals->haveMinMaxIter()){
1753     param->setMaxIteration(globals->getMinMaxIter());
1754     }
1755    
1756     if (globals->haveMinWriteFrq()){
1757     param->setMaxIteration(globals->getMinMaxIter());
1758     }
1759    
1760     if (globals->haveMinWriteFrq()){
1761     param->setWriteFrq(globals->getMinWriteFrq());
1762     }
1763    
1764     if (globals->haveMinResetFrq()){
1765     param->setResetFrq(globals->getMinResetFrq());
1766     }
1767    
1768     if (globals->haveMinLSMaxIter()){
1769     param->setLineSearchMaxIteration(globals->getMinLSMaxIter());
1770     }
1771    
1772     if (globals->haveMinLSTol()){
1773     param->setLineSearchTol(globals->getMinLSTol());
1774     }
1775    
1776     //creat the minimizer
1777     minimizer = new PRCGMinimizer(nlp, param);
1778     minimizer->setLineSearchStrategy(nlp, GoldenSection);
1779     minimizer->setOutputFunctor(outputFunc);
1780    
1781     //store the minimizer into simInfo
1782     info[i].the_minimizer = minimizer;
1783     info[i].has_minimizer = true;
1784     }
1785 tim 1032
1786 tim 1031 }