ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/group/trunk/OOPSE/libmdtools/SimSetup.cpp
Revision: 689
Committed: Tue Aug 12 19:56:49 2003 UTC (20 years, 11 months ago) by tim
File size: 40516 byte(s)
Log Message:
debugging globals

File Contents

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