ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/group/trunk/OOPSE/libmdtools/SimSetup.cpp
Revision: 736
Committed: Thu Aug 28 21:09:47 2003 UTC (20 years, 10 months ago) by tim
File size: 44882 byte(s)
Log Message:
Added: check uniqueness of molIndex

File Contents

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