ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/group/trunk/OOPSE/libmdtools/SimSetup.cpp
Revision: 780
Committed: Mon Sep 22 21:23:25 2003 UTC (20 years, 9 months ago) by mmeineke
File size: 41983 byte(s)
Log Message:
Converted NPTf to work with the NPT base class.

Removed NPTfm and NPTim from cvs

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