ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/group/trunk/OOPSE/libmdtools/SimSetup.cpp
Revision: 658
Committed: Thu Jul 31 15:35:07 2003 UTC (20 years, 11 months ago) by tim
File size: 38158 byte(s)
Log Message:
 Added Z constraint.

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