ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/group/trunk/OOPSE/libmdtools/SimSetup.cpp
Revision: 690
Committed: Tue Aug 12 21:44:06 2003 UTC (20 years, 10 months ago) by mmeineke
File size: 40301 byte(s)
Log Message:
fixed a really annoying bug in Directional Atom, where mu was getting written to pseudorandom memory location.

File Contents

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