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

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