ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/group/trunk/OOPSE/libmdtools/SimSetup.cpp
Revision: 708
Committed: Wed Aug 20 22:23:34 2003 UTC (20 years, 10 months ago) by tim
File size: 42901 byte(s)
Log Message:
user can setup seed in bass file now, if he does not specify any value for
seed, oopse will take the value of seconds of system time as seed

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