ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/group/trunk/OOPSE/libmdtools/SimSetup.cpp
Revision: 999
Committed: Fri Jan 30 15:01:09 2004 UTC (20 years, 5 months ago) by chrisfen
File size: 46117 byte(s)
Log Message:
Substantial changes. OOPSE now has a working WATER.cpp forcefield and parser.
This involved changes to WATER.cpp and ForceFields amoung other files. One important
note: a hardwiring of LJ_rcut was made in calc_LJ_FF.F90. This will be removed on
the next commit...

File Contents

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