ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/group/trunk/OOPSE/libmdtools/SimSetup.cpp
Revision: 707
Committed: Wed Aug 20 19:42:31 2003 UTC (20 years, 10 months ago) by mmeineke
File size: 42238 byte(s)
Log Message:
updated the Changelog.

added some bug fixes for setting the random number generator seed value.

fixed a bug where ghostbend atom b was not being set. ( recent bug from SimState conversion)

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