ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/group/trunk/OOPSE/libmdtools/SimSetup.cpp
Revision: 693
Committed: Wed Aug 13 19:21:53 2003 UTC (20 years, 10 months ago) by tim
File size: 40394 byte(s)
Log Message:
harmonic potential & z-contraint method

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 tim 693 double* tempDouble = new double[1000000];
907 tim 689 fileInit = new InitializeFromFile( inName );
908 mmeineke 614 #ifdef IS_MPI
909 mmeineke 670 }else fileInit = new InitializeFromFile( NULL );
910 mmeineke 614 #endif
911 mmeineke 670 fileInit->readInit( info ); // default velocities on
912    
913     delete fileInit;
914     }
915     else{
916    
917 mmeineke 614 #ifdef IS_MPI
918 mmeineke 670
919     // no init from bass
920    
921     sprintf( painCave.errMsg,
922     "Cannot intialize a parallel simulation without an initial configuration file.\n" );
923     painCave.isFatal;
924     simError();
925    
926 mmeineke 614 #else
927 mmeineke 670
928     initFromBass();
929    
930    
931 mmeineke 614 #endif
932 mmeineke 670 }
933    
934 mmeineke 614 #ifdef IS_MPI
935     strcpy( checkPointMsg, "Successfully read in the initial configuration" );
936     MPIcheckPoint();
937     #endif // is_mpi
938 mmeineke 670
939 mmeineke 614 }
940    
941    
942     void SimSetup::makeOutNames( void ){
943 mmeineke 670
944     int k;
945 mmeineke 614
946 mmeineke 670
947     for(k=0; k<nInfo; k++){
948    
949 mmeineke 614 #ifdef IS_MPI
950 mmeineke 670 if( worldRank == 0 ){
951 mmeineke 614 #endif // is_mpi
952 mmeineke 670
953     if( globals->haveFinalConfig() ){
954     strcpy( info[k].finalName, globals->getFinalConfig() );
955 mmeineke 614 }
956     else{
957 mmeineke 670 strcpy( info[k].finalName, inFileName );
958     char* endTest;
959     int nameLength = strlen( info[k].finalName );
960     endTest = &(info[k].finalName[nameLength - 5]);
961     if( !strcmp( endTest, ".bass" ) ){
962 mmeineke 614 strcpy( endTest, ".eor" );
963     }
964 mmeineke 670 else if( !strcmp( endTest, ".BASS" ) ){
965 mmeineke 614 strcpy( endTest, ".eor" );
966     }
967     else{
968 mmeineke 670 endTest = &(info[k].finalName[nameLength - 4]);
969     if( !strcmp( endTest, ".bss" ) ){
970     strcpy( endTest, ".eor" );
971     }
972     else if( !strcmp( endTest, ".mdl" ) ){
973     strcpy( endTest, ".eor" );
974     }
975     else{
976     strcat( info[k].finalName, ".eor" );
977     }
978 mmeineke 614 }
979     }
980 mmeineke 670
981     // make the sample and status out names
982    
983     strcpy( info[k].sampleName, inFileName );
984     char* endTest;
985     int nameLength = strlen( info[k].sampleName );
986     endTest = &(info[k].sampleName[nameLength - 5]);
987     if( !strcmp( endTest, ".bass" ) ){
988 mmeineke 614 strcpy( endTest, ".dump" );
989     }
990 mmeineke 670 else if( !strcmp( endTest, ".BASS" ) ){
991 mmeineke 614 strcpy( endTest, ".dump" );
992     }
993     else{
994 mmeineke 670 endTest = &(info[k].sampleName[nameLength - 4]);
995     if( !strcmp( endTest, ".bss" ) ){
996     strcpy( endTest, ".dump" );
997     }
998     else if( !strcmp( endTest, ".mdl" ) ){
999     strcpy( endTest, ".dump" );
1000     }
1001     else{
1002     strcat( info[k].sampleName, ".dump" );
1003     }
1004 mmeineke 614 }
1005 mmeineke 670
1006     strcpy( info[k].statusName, inFileName );
1007     nameLength = strlen( info[k].statusName );
1008     endTest = &(info[k].statusName[nameLength - 5]);
1009     if( !strcmp( endTest, ".bass" ) ){
1010 mmeineke 614 strcpy( endTest, ".stat" );
1011     }
1012 mmeineke 670 else if( !strcmp( endTest, ".BASS" ) ){
1013 mmeineke 614 strcpy( endTest, ".stat" );
1014     }
1015     else{
1016 mmeineke 670 endTest = &(info[k].statusName[nameLength - 4]);
1017     if( !strcmp( endTest, ".bss" ) ){
1018     strcpy( endTest, ".stat" );
1019     }
1020     else if( !strcmp( endTest, ".mdl" ) ){
1021     strcpy( endTest, ".stat" );
1022     }
1023     else{
1024     strcat( info[k].statusName, ".stat" );
1025     }
1026 mmeineke 614 }
1027 mmeineke 670
1028     #ifdef IS_MPI
1029 mmeineke 614 }
1030 mmeineke 670 #endif // is_mpi
1031 mmeineke 614 }
1032     }
1033    
1034    
1035     void SimSetup::sysObjectsCreation( void ){
1036 mmeineke 670
1037     int i,k;
1038    
1039 mmeineke 614 // create the forceField
1040 tim 689
1041 mmeineke 614 createFF();
1042    
1043     // extract componentList
1044    
1045     compList();
1046    
1047     // calc the number of atoms, bond, bends, and torsions
1048    
1049     calcSysValues();
1050    
1051     #ifdef IS_MPI
1052     // divide the molecules among the processors
1053    
1054     mpiMolDivide();
1055     #endif //is_mpi
1056    
1057     // create the atom and SRI arrays. Also initialize Molecule Stamp ID's
1058 tim 689
1059 mmeineke 614 makeSysArrays();
1060    
1061 mmeineke 616 // make and initialize the molecules (all but atomic coordinates)
1062 tim 689
1063 mmeineke 616 makeMolecules();
1064 mmeineke 670
1065     for(k=0; k<nInfo; k++){
1066     info[k].identArray = new int[info[k].n_atoms];
1067     for(i=0; i<info[k].n_atoms; i++){
1068     info[k].identArray[i] = info[k].atoms[i]->getIdent();
1069     }
1070 mmeineke 616 }
1071 mmeineke 614 }
1072    
1073    
1074     void SimSetup::createFF( void ){
1075    
1076     switch( ffCase ){
1077    
1078     case FF_DUFF:
1079     the_ff = new DUFF();
1080     break;
1081    
1082     case FF_LJ:
1083     the_ff = new LJFF();
1084     break;
1085    
1086 chuckv 653 case FF_EAM:
1087     the_ff = new EAM_FF();
1088     break;
1089    
1090 mmeineke 614 default:
1091     sprintf( painCave.errMsg,
1092     "SimSetup Error. Unrecognized force field in case statement.\n");
1093     painCave.isFatal = 1;
1094     simError();
1095     }
1096    
1097     #ifdef IS_MPI
1098     strcpy( checkPointMsg, "ForceField creation successful" );
1099     MPIcheckPoint();
1100     #endif // is_mpi
1101    
1102     }
1103    
1104    
1105     void SimSetup::compList( void ){
1106    
1107 mmeineke 616 int i;
1108 mmeineke 670 char* id;
1109     LinkedMolStamp* headStamp = new LinkedMolStamp();
1110     LinkedMolStamp* currentStamp = NULL;
1111 mmeineke 614 comp_stamps = new MoleculeStamp*[n_components];
1112 mmeineke 670
1113 mmeineke 614 // make an array of molecule stamps that match the components used.
1114     // also extract the used stamps out into a separate linked list
1115 mmeineke 670
1116     for(i=0; i<nInfo; i++){
1117     info[i].nComponents = n_components;
1118     info[i].componentsNmol = components_nmol;
1119     info[i].compStamps = comp_stamps;
1120     info[i].headStamp = headStamp;
1121     }
1122    
1123 mmeineke 614
1124     for( i=0; i<n_components; i++ ){
1125    
1126     id = the_components[i]->getType();
1127     comp_stamps[i] = NULL;
1128    
1129     // check to make sure the component isn't already in the list
1130    
1131     comp_stamps[i] = headStamp->match( id );
1132     if( comp_stamps[i] == NULL ){
1133    
1134     // extract the component from the list;
1135    
1136 mmeineke 616 currentStamp = stamps->extractMolStamp( id );
1137 mmeineke 614 if( currentStamp == NULL ){
1138     sprintf( painCave.errMsg,
1139     "SimSetup error: Component \"%s\" was not found in the "
1140     "list of declared molecules\n",
1141     id );
1142     painCave.isFatal = 1;
1143     simError();
1144     }
1145    
1146     headStamp->add( currentStamp );
1147     comp_stamps[i] = headStamp->match( id );
1148     }
1149     }
1150    
1151     #ifdef IS_MPI
1152     strcpy( checkPointMsg, "Component stamps successfully extracted\n" );
1153     MPIcheckPoint();
1154     #endif // is_mpi
1155    
1156    
1157     }
1158    
1159     void SimSetup::calcSysValues( void ){
1160 mmeineke 616 int i, j, k;
1161 mmeineke 670
1162     int *molMembershipArray;
1163    
1164 mmeineke 614 tot_atoms = 0;
1165     tot_bonds = 0;
1166     tot_bends = 0;
1167     tot_torsions = 0;
1168     for( i=0; i<n_components; i++ ){
1169    
1170     tot_atoms += components_nmol[i] * comp_stamps[i]->getNAtoms();
1171     tot_bonds += components_nmol[i] * comp_stamps[i]->getNBonds();
1172     tot_bends += components_nmol[i] * comp_stamps[i]->getNBends();
1173     tot_torsions += components_nmol[i] * comp_stamps[i]->getNTorsions();
1174     }
1175 mmeineke 670
1176 mmeineke 614 tot_SRI = tot_bonds + tot_bends + tot_torsions;
1177 mmeineke 670 molMembershipArray = new int[tot_atoms];
1178 mmeineke 614
1179 mmeineke 670 for(i=0; i<nInfo; i++){
1180     info[i].n_atoms = tot_atoms;
1181     info[i].n_bonds = tot_bonds;
1182     info[i].n_bends = tot_bends;
1183     info[i].n_torsions = tot_torsions;
1184     info[i].n_SRI = tot_SRI;
1185     info[i].n_mol = tot_nmol;
1186    
1187     info[i].molMembershipArray = molMembershipArray;
1188     }
1189 mmeineke 614 }
1190    
1191     #ifdef IS_MPI
1192    
1193     void SimSetup::mpiMolDivide( void ){
1194    
1195 mmeineke 616 int i, j, k;
1196 mmeineke 614 int localMol, allMol;
1197     int local_atoms, local_bonds, local_bends, local_torsions, local_SRI;
1198    
1199     mpiSim = new mpiSimulation( info );
1200    
1201     globalIndex = mpiSim->divideLabor();
1202    
1203     // set up the local variables
1204    
1205     mol2proc = mpiSim->getMolToProcMap();
1206     molCompType = mpiSim->getMolComponentType();
1207    
1208     allMol = 0;
1209     localMol = 0;
1210     local_atoms = 0;
1211     local_bonds = 0;
1212     local_bends = 0;
1213     local_torsions = 0;
1214     globalAtomIndex = 0;
1215    
1216    
1217     for( i=0; i<n_components; i++ ){
1218    
1219     for( j=0; j<components_nmol[i]; j++ ){
1220    
1221     if( mol2proc[allMol] == worldRank ){
1222    
1223     local_atoms += comp_stamps[i]->getNAtoms();
1224     local_bonds += comp_stamps[i]->getNBonds();
1225     local_bends += comp_stamps[i]->getNBends();
1226     local_torsions += comp_stamps[i]->getNTorsions();
1227     localMol++;
1228     }
1229     for (k = 0; k < comp_stamps[i]->getNAtoms(); k++) {
1230 mmeineke 670 info[0].molMembershipArray[globalAtomIndex] = allMol;
1231 mmeineke 614 globalAtomIndex++;
1232     }
1233    
1234     allMol++;
1235     }
1236     }
1237     local_SRI = local_bonds + local_bends + local_torsions;
1238    
1239 mmeineke 670 info[0].n_atoms = mpiSim->getMyNlocal();
1240 mmeineke 614
1241 mmeineke 670 if( local_atoms != info[0].n_atoms ){
1242 mmeineke 614 sprintf( painCave.errMsg,
1243     "SimSetup error: mpiSim's localAtom (%d) and SimSetup's"
1244     " localAtom (%d) are not equal.\n",
1245 mmeineke 670 info[0].n_atoms,
1246 mmeineke 614 local_atoms );
1247     painCave.isFatal = 1;
1248     simError();
1249     }
1250    
1251 mmeineke 670 info[0].n_bonds = local_bonds;
1252     info[0].n_bends = local_bends;
1253     info[0].n_torsions = local_torsions;
1254     info[0].n_SRI = local_SRI;
1255     info[0].n_mol = localMol;
1256 mmeineke 614
1257     strcpy( checkPointMsg, "Passed nlocal consistency check." );
1258     MPIcheckPoint();
1259     }
1260 mmeineke 670
1261 mmeineke 614 #endif // is_mpi
1262    
1263    
1264     void SimSetup::makeSysArrays( void ){
1265 mmeineke 670 int i, j, k, l;
1266 mmeineke 614
1267 mmeineke 670 Atom** the_atoms;
1268     Molecule* the_molecules;
1269     Exclude** the_excludes;
1270 mmeineke 616
1271 mmeineke 614
1272 mmeineke 670 for(l=0; l<nInfo; l++){
1273    
1274     // create the atom and short range interaction arrays
1275    
1276     the_atoms = new Atom*[info[l].n_atoms];
1277     the_molecules = new Molecule[info[l].n_mol];
1278     int molIndex;
1279 mmeineke 614
1280 mmeineke 670 // initialize the molecule's stampID's
1281 mmeineke 614
1282 mmeineke 670 #ifdef IS_MPI
1283    
1284    
1285     molIndex = 0;
1286     for(i=0; i<mpiSim->getTotNmol(); i++){
1287    
1288     if(mol2proc[i] == worldRank ){
1289     the_molecules[molIndex].setStampID( molCompType[i] );
1290     the_molecules[molIndex].setMyIndex( molIndex );
1291     the_molecules[molIndex].setGlobalIndex( i );
1292     molIndex++;
1293     }
1294 mmeineke 614 }
1295 mmeineke 670
1296 mmeineke 614 #else // is_mpi
1297 mmeineke 670
1298     molIndex = 0;
1299     globalAtomIndex = 0;
1300     for(i=0; i<n_components; i++){
1301     for(j=0; j<components_nmol[i]; j++ ){
1302     the_molecules[molIndex].setStampID( i );
1303     the_molecules[molIndex].setMyIndex( molIndex );
1304     the_molecules[molIndex].setGlobalIndex( molIndex );
1305     for (k = 0; k < comp_stamps[i]->getNAtoms(); k++) {
1306     info[l].molMembershipArray[globalAtomIndex] = molIndex;
1307     globalAtomIndex++;
1308     }
1309     molIndex++;
1310 mmeineke 614 }
1311     }
1312    
1313 mmeineke 670
1314 mmeineke 614 #endif // is_mpi
1315    
1316    
1317 mmeineke 670 if( info[l].n_SRI ){
1318 mmeineke 614
1319 mmeineke 670 Exclude::createArray(info[l].n_SRI);
1320     the_excludes = new Exclude*[info[l].n_SRI];
1321     for( int ex=0; ex<info[l].n_SRI; ex++){
1322     the_excludes[ex] = new Exclude(ex);
1323     }
1324     info[l].globalExcludes = new int;
1325     info[l].n_exclude = info[l].n_SRI;
1326     }
1327     else{
1328 mmeineke 614
1329 mmeineke 670 Exclude::createArray( 1 );
1330     the_excludes = new Exclude*;
1331     the_excludes[0] = new Exclude(0);
1332     the_excludes[0]->setPair( 0,0 );
1333     info[l].globalExcludes = new int;
1334     info[l].globalExcludes[0] = 0;
1335     info[l].n_exclude = 0;
1336     }
1337 mmeineke 614
1338 mmeineke 670 // set the arrays into the SimInfo object
1339 mmeineke 614
1340 mmeineke 670 info[l].atoms = the_atoms;
1341     info[l].molecules = the_molecules;
1342     info[l].nGlobalExcludes = 0;
1343     info[l].excludes = the_excludes;
1344 mmeineke 614
1345 mmeineke 670 the_ff->setSimInfo( info );
1346    
1347     }
1348 mmeineke 614 }
1349 mmeineke 616
1350     void SimSetup::makeIntegrator( void ){
1351    
1352 mmeineke 670 int k;
1353    
1354 tim 645 NVT<RealIntegrator>* myNVT = NULL;
1355     NPTi<RealIntegrator>* myNPTi = NULL;
1356     NPTf<RealIntegrator>* myNPTf = NULL;
1357     NPTim<RealIntegrator>* myNPTim = NULL;
1358     NPTfm<RealIntegrator>* myNPTfm = NULL;
1359 tim 661
1360 mmeineke 670 for(k=0; k<nInfo; k++){
1361 mmeineke 616
1362 mmeineke 670 switch( ensembleCase ){
1363    
1364     case NVE_ENS:
1365 tim 682 if (globals->haveZconstraints()){
1366     setupZConstraint(info[k]);
1367 tim 676 new ZConstraint<NVE<RealIntegrator> >( &(info[k]), the_ff );
1368     }
1369    
1370     else
1371     new NVE<RealIntegrator>( &(info[k]), the_ff );
1372 mmeineke 670 break;
1373    
1374     case NVT_ENS:
1375 tim 682 if (globals->haveZconstraints()){
1376     setupZConstraint(info[k]);
1377 tim 676 myNVT = new ZConstraint<NVT<RealIntegrator> >( &(info[k]), the_ff );
1378     }
1379     else
1380     myNVT = new NVT<RealIntegrator>( &(info[k]), the_ff );
1381    
1382 mmeineke 670 myNVT->setTargetTemp(globals->getTargetTemp());
1383    
1384     if (globals->haveTauThermostat())
1385     myNVT->setTauThermostat(globals->getTauThermostat());
1386    
1387     else {
1388     sprintf( painCave.errMsg,
1389     "SimSetup error: If you use the NVT\n"
1390     " ensemble, you must set tauThermostat.\n");
1391     painCave.isFatal = 1;
1392     simError();
1393     }
1394     break;
1395    
1396     case NPTi_ENS:
1397 tim 682 if (globals->haveZconstraints()){
1398     setupZConstraint(info[k]);
1399 tim 676 myNPTi = new ZConstraint<NPTi<RealIntegrator> >( &(info[k]), the_ff );
1400     }
1401     else
1402     myNPTi = new NPTi<RealIntegrator>( &(info[k]), the_ff );
1403    
1404     myNPTi->setTargetTemp( globals->getTargetTemp() );
1405 mmeineke 670
1406     if (globals->haveTargetPressure())
1407     myNPTi->setTargetPressure(globals->getTargetPressure());
1408     else {
1409     sprintf( painCave.errMsg,
1410     "SimSetup error: If you use a constant pressure\n"
1411     " ensemble, you must set targetPressure in the BASS file.\n");
1412     painCave.isFatal = 1;
1413     simError();
1414     }
1415    
1416     if( globals->haveTauThermostat() )
1417     myNPTi->setTauThermostat( globals->getTauThermostat() );
1418     else{
1419     sprintf( painCave.errMsg,
1420     "SimSetup error: If you use an NPT\n"
1421     " ensemble, you must set tauThermostat.\n");
1422     painCave.isFatal = 1;
1423     simError();
1424     }
1425    
1426     if( globals->haveTauBarostat() )
1427     myNPTi->setTauBarostat( globals->getTauBarostat() );
1428     else{
1429     sprintf( painCave.errMsg,
1430     "SimSetup error: If you use an NPT\n"
1431     " ensemble, you must set tauBarostat.\n");
1432     painCave.isFatal = 1;
1433     simError();
1434     }
1435     break;
1436    
1437     case NPTf_ENS:
1438 tim 682 if (globals->haveZconstraints()){
1439     setupZConstraint(info[k]);
1440 tim 676 myNPTf = new ZConstraint<NPTf<RealIntegrator> >( &(info[k]), the_ff );
1441     }
1442     else
1443     myNPTf = new NPTf<RealIntegrator>( &(info[k]), the_ff );
1444    
1445 mmeineke 670 myNPTf->setTargetTemp( globals->getTargetTemp());
1446    
1447     if (globals->haveTargetPressure())
1448     myNPTf->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     myNPTf->setTauThermostat( globals->getTauThermostat() );
1459     else{
1460     sprintf( painCave.errMsg,
1461     "SimSetup error: If you use an NPT\n"
1462 mmeineke 616 " ensemble, you must set tauThermostat.\n");
1463 mmeineke 670 painCave.isFatal = 1;
1464     simError();
1465     }
1466 tim 658
1467 mmeineke 670 if( globals->haveTauBarostat() )
1468     myNPTf->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 NPTim_ENS:
1479 tim 682 if (globals->haveZconstraints()){
1480     setupZConstraint(info[k]);
1481 tim 676 myNPTim = new ZConstraint<NPTim<RealIntegrator> >( &(info[k]), the_ff );
1482     }
1483     else
1484     myNPTim = new NPTim<RealIntegrator>( &(info[k]), the_ff );
1485    
1486     myNPTim->setTargetTemp( globals->getTargetTemp());
1487 mmeineke 670
1488     if (globals->haveTargetPressure())
1489     myNPTim->setTargetPressure(globals->getTargetPressure());
1490     else {
1491     sprintf( painCave.errMsg,
1492     "SimSetup error: If you use a constant pressure\n"
1493     " ensemble, you must set targetPressure in the BASS file.\n");
1494     painCave.isFatal = 1;
1495     simError();
1496     }
1497    
1498     if( globals->haveTauThermostat() )
1499     myNPTim->setTauThermostat( globals->getTauThermostat() );
1500     else{
1501     sprintf( painCave.errMsg,
1502     "SimSetup error: If you use an NPT\n"
1503     " ensemble, you must set tauThermostat.\n");
1504     painCave.isFatal = 1;
1505     simError();
1506     }
1507    
1508     if( globals->haveTauBarostat() )
1509     myNPTim->setTauBarostat( globals->getTauBarostat() );
1510     else{
1511 tim 660 sprintf( painCave.errMsg,
1512     "SimSetup error: If you use an NPT\n"
1513     " ensemble, you must set tauBarostat.\n");
1514     painCave.isFatal = 1;
1515     simError();
1516 mmeineke 670 }
1517     break;
1518 tim 658
1519 mmeineke 670 case NPTfm_ENS:
1520 tim 682 if (globals->haveZconstraints()){
1521     setupZConstraint(info[k]);
1522 tim 676 myNPTfm = new ZConstraint<NPTfm<RealIntegrator> >( &(info[k]), the_ff );
1523     }
1524     else
1525     myNPTfm = new NPTfm<RealIntegrator>( &(info[k]), the_ff );
1526    
1527     myNPTfm->setTargetTemp( globals->getTargetTemp());
1528 mmeineke 670
1529     if (globals->haveTargetPressure())
1530     myNPTfm->setTargetPressure(globals->getTargetPressure());
1531     else {
1532     sprintf( painCave.errMsg,
1533     "SimSetup error: If you use a constant pressure\n"
1534     " ensemble, you must set targetPressure in the BASS file.\n");
1535     painCave.isFatal = 1;
1536     simError();
1537     }
1538    
1539     if( globals->haveTauThermostat() )
1540     myNPTfm->setTauThermostat( globals->getTauThermostat() );
1541     else{
1542     sprintf( painCave.errMsg,
1543     "SimSetup error: If you use an NPT\n"
1544     " ensemble, you must set tauThermostat.\n");
1545     painCave.isFatal = 1;
1546     simError();
1547     }
1548    
1549     if( globals->haveTauBarostat() )
1550     myNPTfm->setTauBarostat( globals->getTauBarostat() );
1551     else{
1552     sprintf( painCave.errMsg,
1553     "SimSetup error: If you use an NPT\n"
1554     " ensemble, you must set tauBarostat.\n");
1555     painCave.isFatal = 1;
1556     simError();
1557     }
1558     break;
1559    
1560     default:
1561 tim 660 sprintf( painCave.errMsg,
1562 mmeineke 670 "SimSetup Error. Unrecognized ensemble in case statement.\n");
1563 tim 660 painCave.isFatal = 1;
1564     simError();
1565     }
1566 mmeineke 616 }
1567     }
1568    
1569     void SimSetup::initFortran( void ){
1570    
1571 mmeineke 670 info[0].refreshSim();
1572 mmeineke 616
1573 mmeineke 670 if( !strcmp( info[0].mixingRule, "standard") ){
1574 mmeineke 616 the_ff->initForceField( LB_MIXING_RULE );
1575     }
1576 mmeineke 670 else if( !strcmp( info[0].mixingRule, "explicit") ){
1577 mmeineke 616 the_ff->initForceField( EXPLICIT_MIXING_RULE );
1578     }
1579     else{
1580     sprintf( painCave.errMsg,
1581     "SimSetup Error: unknown mixing rule -> \"%s\"\n",
1582 mmeineke 670 info[0].mixingRule );
1583 mmeineke 616 painCave.isFatal = 1;
1584     simError();
1585     }
1586    
1587    
1588     #ifdef IS_MPI
1589     strcpy( checkPointMsg,
1590     "Successfully intialized the mixingRule for Fortran." );
1591     MPIcheckPoint();
1592     #endif // is_mpi
1593    
1594     }
1595 tim 660
1596 tim 682 void SimSetup::setupZConstraint(SimInfo& theInfo)
1597 tim 660 {
1598 tim 682 int nZConstraints;
1599     ZconStamp** zconStamp;
1600    
1601     if(globals->haveZconstraintTime()){
1602 tim 660
1603 mmeineke 670 //add sample time of z-constraint into SimInfo's property list
1604     DoubleData* zconsTimeProp = new DoubleData();
1605 tim 682 zconsTimeProp->setID(ZCONSTIME_ID);
1606     zconsTimeProp->setData(globals->getZconsTime());
1607     theInfo.addProperty(zconsTimeProp);
1608 mmeineke 670 }
1609     else{
1610     sprintf( painCave.errMsg,
1611     "ZConstraint error: If you use an ZConstraint\n"
1612     " , you must set sample time.\n");
1613     painCave.isFatal = 1;
1614     simError();
1615     }
1616 tim 682
1617     //
1618     nZConstraints = globals->getNzConstraints();
1619 tim 693 theInfo.nZconstraints = nZConstraints;
1620    
1621 tim 682 zconStamp = globals->getZconStamp();
1622     ZConsParaItem tempParaItem;
1623    
1624     ZConsParaData* zconsParaData = new ZConsParaData();
1625     zconsParaData->setID(ZCONSPARADATA_ID);
1626    
1627     for(int i = 0; i < nZConstraints; i++){
1628     tempParaItem.havingZPos = zconStamp[i]->haveZpos();
1629     tempParaItem.zPos = zconStamp[i]->getZpos();
1630     tempParaItem.zconsIndex = zconStamp[i]->getMolIndex();
1631     tempParaItem.kRatio = zconStamp[i]->getKratio();
1632    
1633     zconsParaData->addItem(tempParaItem);
1634 mmeineke 670 }
1635 tim 682
1636     //sort the parameters by index of molecules
1637     zconsParaData->sortByIndex();
1638    
1639     //push data into siminfo, therefore, we can retrieve later
1640     theInfo.addProperty(zconsParaData);
1641    
1642     //push zconsTol into siminfo, if user does not specify
1643     //value for zconsTol, a default value will be used
1644     DoubleData* zconsTol = new DoubleData();
1645     zconsTol->setID(ZCONSTOL_ID);
1646     if(globals->haveZconsTol()){
1647     zconsTol->setData(globals->getZconsTol());
1648     }
1649     else{
1650     double defaultZConsTol = 1E-6;
1651 mmeineke 670 sprintf( painCave.errMsg,
1652 tim 682 "ZConstraint Waring: Tolerance for z-constraint methodl is not specified\n"
1653     " , default value %f is used.\n", defaultZConsTol);
1654     painCave.isFatal = 0;
1655     simError();
1656    
1657     zconsTol->setData(defaultZConsTol);
1658     }
1659     theInfo.addProperty(zconsTol);
1660    
1661 mmeineke 670 //Determine the name of ouput file and add it into SimInfo's property list
1662     //Be careful, do not use inFileName, since it is a pointer which
1663     //point to a string at master node, and slave nodes do not contain that string
1664    
1665 tim 682 string zconsOutput(theInfo.finalName);
1666 mmeineke 670
1667     zconsOutput = zconsOutput.substr(0, zconsOutput.rfind(".")) + ".fz";
1668    
1669     StringData* zconsFilename = new StringData();
1670 tim 682 zconsFilename->setID(ZCONSFILENAME_ID);
1671 mmeineke 670 zconsFilename->setData(zconsOutput);
1672    
1673 tim 682 theInfo.addProperty(zconsFilename);
1674 tim 660 }