ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/group/trunk/OOPSE/libmdtools/SimSetup.cpp
Revision: 582
Committed: Wed Jul 9 15:33:46 2003 UTC (21 years ago) by mmeineke
File size: 32900 byte(s)
Log Message:
adding in dan's NPT stuff

File Contents

# User Rev Content
1 mmeineke 377 #include <cstdlib>
2     #include <iostream>
3     #include <cmath>
4    
5     #include "SimSetup.hpp"
6     #include "parse_me.h"
7     #include "Integrator.hpp"
8     #include "simError.h"
9    
10     #ifdef IS_MPI
11     #include "mpiBASS.h"
12     #include "mpiSimulation.hpp"
13     #endif
14    
15 mmeineke 557 // some defines for ensemble and Forcefield cases
16    
17 mmeineke 582 #define NVE_ENS 0
18     #define NVT_ENS 1
19 gezelter 580 #define NPTi_ENS 2
20     #define NPTf_ENS 3
21 mmeineke 557
22 mmeineke 582
23 mmeineke 557 #define FF_DUFF 0
24     #define FF_LJ 1
25    
26    
27 mmeineke 377 SimSetup::SimSetup(){
28     stamps = new MakeStamps();
29     globals = new Globals();
30    
31     #ifdef IS_MPI
32     strcpy( checkPointMsg, "SimSetup creation successful" );
33     MPIcheckPoint();
34     #endif // IS_MPI
35     }
36    
37     SimSetup::~SimSetup(){
38     delete stamps;
39     delete globals;
40     }
41    
42     void SimSetup::parseFile( char* fileName ){
43    
44     #ifdef IS_MPI
45     if( worldRank == 0 ){
46     #endif // is_mpi
47    
48     inFileName = fileName;
49     set_interface_stamps( stamps, globals );
50    
51     #ifdef IS_MPI
52     mpiEventInit();
53     #endif
54    
55     yacc_BASS( fileName );
56    
57     #ifdef IS_MPI
58     throwMPIEvent(NULL);
59     }
60     else receiveParse();
61     #endif
62    
63     }
64    
65     #ifdef IS_MPI
66     void SimSetup::receiveParse(void){
67    
68     set_interface_stamps( stamps, globals );
69     mpiEventInit();
70     MPIcheckPoint();
71     mpiEventLoop();
72    
73     }
74    
75     #endif // is_mpi
76    
77     void SimSetup::createSim( void ){
78    
79     MakeStamps *the_stamps;
80     Globals* the_globals;
81 gezelter 490 int i, j, k, globalAtomIndex;
82 mmeineke 557
83     int ensembleCase;
84     int ffCase;
85    
86     ensembleCase = -1;
87     ffCase = -1;
88 mmeineke 377
89     // get the stamps and globals;
90     the_stamps = stamps;
91     the_globals = globals;
92    
93     // set the easy ones first
94     simnfo->target_temp = the_globals->getTargetTemp();
95     simnfo->dt = the_globals->getDt();
96     simnfo->run_time = the_globals->getRunTime();
97    
98     // get the ones we know are there, yet still may need some work.
99     n_components = the_globals->getNComponents();
100     strcpy( force_field, the_globals->getForceField() );
101 gezelter 466
102 mmeineke 561 if( !strcasecmp( force_field, "DUFF" )) ffCase = FF_DUFF;
103 mmeineke 557 else if( !strcasecmp( force_field, "LJ" )) ffCase = FF_LJ;
104     else{
105     sprintf( painCave.errMsg,
106     "SimSetup Error. Unrecognized force field -> %s\n",
107     force_field );
108     painCave.isFatal = 1;
109     simError();
110     }
111    
112     // get the ensemble:
113 mmeineke 377 strcpy( ensemble, the_globals->getEnsemble() );
114 gezelter 481
115 mmeineke 561 if( !strcasecmp( ensemble, "NVE" )) ensembleCase = NVE_ENS;
116     else if( !strcasecmp( ensemble, "NVT" )) ensembleCase = NVT_ENS;
117 gezelter 580 else if( !strcasecmp( ensemble, "NPTi" ) || !strcasecmp( ensemble, "NPT") )
118     ensembleCase = NPTi_ENS;
119     else if( !strcasecmp( ensemble, "NPTf" )) ensembleCase = NPTf_ENS;
120 mmeineke 557 else{
121 gezelter 466 sprintf( painCave.errMsg,
122     "SimSetup Warning. Unrecognized Ensemble -> %s, "
123     "reverting to NVE for this simulation.\n",
124     ensemble );
125     painCave.isFatal = 0;
126     simError();
127     strcpy( ensemble, "NVE" );
128 mmeineke 557 ensembleCase = NVE_ENS;
129 gezelter 466 }
130 mmeineke 377 strcpy( simnfo->ensemble, ensemble );
131    
132 mmeineke 557
133     // if( !strcasecmp( ensemble, "NPT" ) ) {
134     // the_extendedsystem = new ExtendedSystem( simnfo );
135     // the_extendedsystem->setTargetTemp(the_globals->getTargetTemp());
136     // if (the_globals->haveTargetPressure())
137     // the_extendedsystem->setTargetPressure(the_globals->getTargetPressure());
138     // else {
139     // sprintf( painCave.errMsg,
140     // "SimSetup error: If you use the constant pressure\n"
141     // " ensemble, you must set targetPressure.\n"
142     // " This was found in the BASS file.\n");
143     // painCave.isFatal = 1;
144     // simError();
145     // }
146    
147     // if (the_globals->haveTauThermostat())
148     // the_extendedsystem->setTauThermostat(the_globals->getTauThermostat());
149     // else if (the_globals->haveQmass())
150     // the_extendedsystem->setQmass(the_globals->getQmass());
151     // else {
152     // sprintf( painCave.errMsg,
153     // "SimSetup error: If you use one of the constant temperature\n"
154     // " ensembles, you must set either tauThermostat or qMass.\n"
155     // " Neither of these was found in the BASS file.\n");
156     // painCave.isFatal = 1;
157     // simError();
158     // }
159    
160     // if (the_globals->haveTauBarostat())
161     // the_extendedsystem->setTauBarostat(the_globals->getTauBarostat());
162     // else {
163     // sprintf( painCave.errMsg,
164     // "SimSetup error: If you use the constant pressure\n"
165     // " ensemble, you must set tauBarostat.\n"
166     // " This was found in the BASS file.\n");
167     // painCave.isFatal = 1;
168     // simError();
169     // }
170    
171     // } else if ( !strcasecmp( ensemble, "NVT") ) {
172     // the_extendedsystem = new ExtendedSystem( simnfo );
173     // the_extendedsystem->setTargetTemp(the_globals->getTargetTemp());
174    
175     // if (the_globals->haveTauThermostat())
176     // the_extendedsystem->setTauThermostat(the_globals->getTauThermostat());
177     // else if (the_globals->haveQmass())
178     // the_extendedsystem->setQmass(the_globals->getQmass());
179     // else {
180     // sprintf( painCave.errMsg,
181     // "SimSetup error: If you use one of the constant temperature\n"
182     // " ensembles, you must set either tauThermostat or qMass.\n"
183     // " Neither of these was found in the BASS file.\n");
184     // painCave.isFatal = 1;
185     // simError();
186     // }
187    
188 mmeineke 377 strcpy( simnfo->mixingRule, the_globals->getMixingRule() );
189     simnfo->usePBC = the_globals->getPBC();
190    
191 mmeineke 469 int usesDipoles = 0;
192 mmeineke 557 switch( ffCase ){
193    
194     case FF_DUFF:
195     the_ff = new DUFF();
196 mmeineke 469 usesDipoles = 1;
197 mmeineke 557 break;
198    
199     case FF_LJ:
200 mmeineke 561 the_ff = new LJFF();
201 mmeineke 557 break;
202    
203     default:
204 mmeineke 377 sprintf( painCave.errMsg,
205 mmeineke 557 "SimSetup Error. Unrecognized force field in case statement.\n");
206 mmeineke 377 painCave.isFatal = 1;
207     simError();
208     }
209    
210     #ifdef IS_MPI
211     strcpy( checkPointMsg, "ForceField creation successful" );
212     MPIcheckPoint();
213     #endif // is_mpi
214    
215     // get the components and calculate the tot_nMol and indvidual n_mol
216     the_components = the_globals->getComponents();
217     components_nmol = new int[n_components];
218     comp_stamps = new MoleculeStamp*[n_components];
219    
220     if( !the_globals->haveNMol() ){
221     // we don't have the total number of molecules, so we assume it is
222     // given in each component
223    
224     tot_nmol = 0;
225     for( i=0; i<n_components; i++ ){
226    
227     if( !the_components[i]->haveNMol() ){
228     // we have a problem
229     sprintf( painCave.errMsg,
230     "SimSetup Error. No global NMol or component NMol"
231     " given. Cannot calculate the number of atoms.\n" );
232     painCave.isFatal = 1;
233     simError();
234     }
235    
236     tot_nmol += the_components[i]->getNMol();
237     components_nmol[i] = the_components[i]->getNMol();
238     }
239     }
240     else{
241     sprintf( painCave.errMsg,
242     "SimSetup error.\n"
243     "\tSorry, the ability to specify total"
244     " nMols and then give molfractions in the components\n"
245     "\tis not currently supported."
246     " Please give nMol in the components.\n" );
247     painCave.isFatal = 1;
248     simError();
249    
250    
251     // tot_nmol = the_globals->getNMol();
252    
253     // //we have the total number of molecules, now we check for molfractions
254     // for( i=0; i<n_components; i++ ){
255    
256     // if( !the_components[i]->haveMolFraction() ){
257    
258     // if( !the_components[i]->haveNMol() ){
259     // //we have a problem
260     // std::cerr << "SimSetup error. Neither molFraction nor "
261     // << " nMol was given in component
262    
263     }
264    
265     #ifdef IS_MPI
266     strcpy( checkPointMsg, "Have the number of components" );
267     MPIcheckPoint();
268     #endif // is_mpi
269    
270     // make an array of molecule stamps that match the components used.
271     // also extract the used stamps out into a separate linked list
272    
273     simnfo->nComponents = n_components;
274     simnfo->componentsNmol = components_nmol;
275     simnfo->compStamps = comp_stamps;
276     simnfo->headStamp = new LinkedMolStamp();
277    
278     char* id;
279     LinkedMolStamp* headStamp = simnfo->headStamp;
280     LinkedMolStamp* currentStamp = NULL;
281     for( i=0; i<n_components; i++ ){
282    
283     id = the_components[i]->getType();
284     comp_stamps[i] = NULL;
285    
286     // check to make sure the component isn't already in the list
287    
288     comp_stamps[i] = headStamp->match( id );
289     if( comp_stamps[i] == NULL ){
290    
291     // extract the component from the list;
292    
293     currentStamp = the_stamps->extractMolStamp( id );
294     if( currentStamp == NULL ){
295     sprintf( painCave.errMsg,
296     "SimSetup error: Component \"%s\" was not found in the "
297     "list of declared molecules\n",
298     id );
299     painCave.isFatal = 1;
300     simError();
301     }
302    
303     headStamp->add( currentStamp );
304     comp_stamps[i] = headStamp->match( id );
305     }
306     }
307    
308     #ifdef IS_MPI
309     strcpy( checkPointMsg, "Component stamps successfully extracted\n" );
310     MPIcheckPoint();
311     #endif // is_mpi
312    
313    
314    
315    
316     // caclulate the number of atoms, bonds, bends and torsions
317    
318     tot_atoms = 0;
319     tot_bonds = 0;
320     tot_bends = 0;
321     tot_torsions = 0;
322     for( i=0; i<n_components; i++ ){
323    
324     tot_atoms += components_nmol[i] * comp_stamps[i]->getNAtoms();
325     tot_bonds += components_nmol[i] * comp_stamps[i]->getNBonds();
326     tot_bends += components_nmol[i] * comp_stamps[i]->getNBends();
327     tot_torsions += components_nmol[i] * comp_stamps[i]->getNTorsions();
328     }
329    
330     tot_SRI = tot_bonds + tot_bends + tot_torsions;
331    
332     simnfo->n_atoms = tot_atoms;
333     simnfo->n_bonds = tot_bonds;
334     simnfo->n_bends = tot_bends;
335     simnfo->n_torsions = tot_torsions;
336     simnfo->n_SRI = tot_SRI;
337     simnfo->n_mol = tot_nmol;
338 mmeineke 491
339 gezelter 490 simnfo->molMembershipArray = new int[tot_atoms];
340 mmeineke 377
341     #ifdef IS_MPI
342    
343     // divide the molecules among processors here.
344    
345     mpiSim = new mpiSimulation( simnfo );
346    
347     globalIndex = mpiSim->divideLabor();
348    
349     // set up the local variables
350    
351     int localMol, allMol;
352     int local_atoms, local_bonds, local_bends, local_torsions, local_SRI;
353 mmeineke 422
354     int* mol2proc = mpiSim->getMolToProcMap();
355     int* molCompType = mpiSim->getMolComponentType();
356 mmeineke 377
357     allMol = 0;
358     localMol = 0;
359     local_atoms = 0;
360     local_bonds = 0;
361     local_bends = 0;
362     local_torsions = 0;
363 gezelter 490 globalAtomIndex = 0;
364    
365    
366 mmeineke 377 for( i=0; i<n_components; i++ ){
367    
368     for( j=0; j<components_nmol[i]; j++ ){
369    
370 mmeineke 487 if( mol2proc[allMol] == worldRank ){
371 mmeineke 377
372     local_atoms += comp_stamps[i]->getNAtoms();
373     local_bonds += comp_stamps[i]->getNBonds();
374     local_bends += comp_stamps[i]->getNBends();
375     local_torsions += comp_stamps[i]->getNTorsions();
376     localMol++;
377     }
378 gezelter 490 for (k = 0; k < comp_stamps[i]->getNAtoms(); k++) {
379     simnfo->molMembershipArray[globalAtomIndex] = allMol;
380     globalAtomIndex++;
381     }
382    
383     allMol++;
384 mmeineke 377 }
385     }
386     local_SRI = local_bonds + local_bends + local_torsions;
387    
388     simnfo->n_atoms = mpiSim->getMyNlocal();
389    
390     if( local_atoms != simnfo->n_atoms ){
391     sprintf( painCave.errMsg,
392     "SimSetup error: mpiSim's localAtom (%d) and SimSetup's"
393 mmeineke 422 " localAtom (%d) are not equal.\n",
394 mmeineke 377 simnfo->n_atoms,
395     local_atoms );
396     painCave.isFatal = 1;
397     simError();
398     }
399    
400     simnfo->n_bonds = local_bonds;
401     simnfo->n_bends = local_bends;
402     simnfo->n_torsions = local_torsions;
403     simnfo->n_SRI = local_SRI;
404     simnfo->n_mol = localMol;
405    
406     strcpy( checkPointMsg, "Passed nlocal consistency check." );
407     MPIcheckPoint();
408    
409    
410     #endif // is_mpi
411    
412    
413     // create the atom and short range interaction arrays
414    
415     Atom::createArrays(simnfo->n_atoms);
416     the_atoms = new Atom*[simnfo->n_atoms];
417     the_molecules = new Molecule[simnfo->n_mol];
418 mmeineke 422 int molIndex;
419 mmeineke 377
420 mmeineke 422 // initialize the molecule's stampID's
421 mmeineke 377
422 mmeineke 422 #ifdef IS_MPI
423    
424    
425     molIndex = 0;
426     for(i=0; i<mpiSim->getTotNmol(); i++){
427    
428     if(mol2proc[i] == worldRank ){
429     the_molecules[molIndex].setStampID( molCompType[i] );
430 chuckv 438 the_molecules[molIndex].setMyIndex( molIndex );
431 mmeineke 489 the_molecules[molIndex].setGlobalIndex( i );
432 mmeineke 422 molIndex++;
433     }
434     }
435    
436     #else // is_mpi
437    
438     molIndex = 0;
439 gezelter 490 globalAtomIndex = 0;
440 mmeineke 422 for(i=0; i<n_components; i++){
441     for(j=0; j<components_nmol[i]; j++ ){
442     the_molecules[molIndex].setStampID( i );
443 chuckv 438 the_molecules[molIndex].setMyIndex( molIndex );
444 mmeineke 489 the_molecules[molIndex].setGlobalIndex( molIndex );
445 gezelter 490 for (k = 0; k < comp_stamps[i]->getNAtoms(); k++) {
446     simnfo->molMembershipArray[globalAtomIndex] = molIndex;
447     globalAtomIndex++;
448     }
449 mmeineke 422 molIndex++;
450     }
451     }
452    
453    
454     #endif // is_mpi
455    
456    
457 mmeineke 377 if( simnfo->n_SRI ){
458 mmeineke 431
459 mmeineke 412 Exclude::createArray(simnfo->n_SRI);
460     the_excludes = new Exclude*[simnfo->n_SRI];
461 mmeineke 431 for( int ex=0; ex<simnfo->n_SRI; ex++) the_excludes[ex] = new Exclude(ex);
462 mmeineke 377 simnfo->globalExcludes = new int;
463 chuckv 438 simnfo->n_exclude = simnfo->n_SRI;
464 mmeineke 377 }
465     else{
466    
467 mmeineke 412 Exclude::createArray( 1 );
468     the_excludes = new Exclude*;
469     the_excludes[0] = new Exclude(0);
470     the_excludes[0]->setPair( 0,0 );
471 mmeineke 377 simnfo->globalExcludes = new int;
472     simnfo->globalExcludes[0] = 0;
473 mmeineke 412 simnfo->n_exclude = 0;
474 mmeineke 377 }
475    
476     // set the arrays into the SimInfo object
477    
478     simnfo->atoms = the_atoms;
479 mmeineke 429 simnfo->molecules = the_molecules;
480 mmeineke 377 simnfo->nGlobalExcludes = 0;
481     simnfo->excludes = the_excludes;
482    
483    
484     // get some of the tricky things that may still be in the globals
485    
486 mmeineke 572 double boxVector[3];
487 mmeineke 377 if( the_globals->haveBox() ){
488 mmeineke 572 boxVector[0] = the_globals->getBox();
489     boxVector[1] = the_globals->getBox();
490     boxVector[2] = the_globals->getBox();
491    
492     simnfo->setBox( boxVector );
493 mmeineke 377 }
494     else if( the_globals->haveDensity() ){
495    
496     double vol;
497     vol = (double)tot_nmol / the_globals->getDensity();
498 mmeineke 572 boxVector[0] = pow( vol, ( 1.0 / 3.0 ) );
499     boxVector[1] = boxVector[0];
500     boxVector[2] = boxVector[0];
501    
502     simnfo->setBox( boxVector );
503 mmeineke 377 }
504     else{
505     if( !the_globals->haveBoxX() ){
506     sprintf( painCave.errMsg,
507     "SimSetup error, no periodic BoxX size given.\n" );
508     painCave.isFatal = 1;
509     simError();
510     }
511 mmeineke 572 boxVector[0] = the_globals->getBoxX();
512 mmeineke 377
513     if( !the_globals->haveBoxY() ){
514     sprintf( painCave.errMsg,
515     "SimSetup error, no periodic BoxY size given.\n" );
516     painCave.isFatal = 1;
517     simError();
518     }
519 mmeineke 572 boxVector[1] = the_globals->getBoxY();
520 mmeineke 377
521     if( !the_globals->haveBoxZ() ){
522     sprintf( painCave.errMsg,
523     "SimSetup error, no periodic BoxZ size given.\n" );
524     painCave.isFatal = 1;
525     simError();
526     }
527 mmeineke 572 boxVector[2] = the_globals->getBoxZ();
528    
529     simnfo->setBox( boxVector );
530 mmeineke 377 }
531    
532     #ifdef IS_MPI
533     strcpy( checkPointMsg, "Box size set up" );
534     MPIcheckPoint();
535     #endif // is_mpi
536    
537    
538     // initialize the arrays
539    
540     the_ff->setSimInfo( simnfo );
541    
542 mmeineke 422 makeMolecules();
543 mmeineke 377 simnfo->identArray = new int[simnfo->n_atoms];
544     for(i=0; i<simnfo->n_atoms; i++){
545     simnfo->identArray[i] = the_atoms[i]->getIdent();
546     }
547    
548 gezelter 394 if (the_globals->getUseRF() ) {
549     simnfo->useReactionField = 1;
550    
551     if( !the_globals->haveECR() ){
552     sprintf( painCave.errMsg,
553     "SimSetup Warning: using default value of 1/2 the smallest "
554     "box length for the electrostaticCutoffRadius.\n"
555     "I hope you have a very fast processor!\n");
556     painCave.isFatal = 0;
557     simError();
558     double smallest;
559 mmeineke 572 smallest = simnfo->boxLx;
560     if (simnfo->boxLy <= smallest) smallest = simnfo->boxLy;
561     if (simnfo->boxLz <= smallest) smallest = simnfo->boxLz;
562 gezelter 394 simnfo->ecr = 0.5 * smallest;
563     } else {
564     simnfo->ecr = the_globals->getECR();
565     }
566 mmeineke 377
567 gezelter 394 if( !the_globals->haveEST() ){
568     sprintf( painCave.errMsg,
569     "SimSetup Warning: using default value of 0.05 * the "
570     "electrostaticCutoffRadius for the electrostaticSkinThickness\n"
571     );
572     painCave.isFatal = 0;
573     simError();
574     simnfo->est = 0.05 * simnfo->ecr;
575     } else {
576     simnfo->est = the_globals->getEST();
577     }
578    
579     if(!the_globals->haveDielectric() ){
580     sprintf( painCave.errMsg,
581     "SimSetup Error: You are trying to use Reaction Field without"
582     "setting a dielectric constant!\n"
583     );
584     painCave.isFatal = 1;
585     simError();
586     }
587     simnfo->dielectric = the_globals->getDielectric();
588     } else {
589 mmeineke 469 if (usesDipoles) {
590 gezelter 394
591     if( !the_globals->haveECR() ){
592     sprintf( painCave.errMsg,
593 mmeineke 469 "SimSetup Warning: using default value of 1/2 the smallest "
594 gezelter 394 "box length for the electrostaticCutoffRadius.\n"
595     "I hope you have a very fast processor!\n");
596     painCave.isFatal = 0;
597     simError();
598     double smallest;
599 mmeineke 572 smallest = simnfo->boxLx;
600     if (simnfo->boxLy <= smallest) smallest = simnfo->boxLy;
601     if (simnfo->boxLz <= smallest) smallest = simnfo->boxLz;
602 gezelter 394 simnfo->ecr = 0.5 * smallest;
603     } else {
604     simnfo->ecr = the_globals->getECR();
605     }
606    
607     if( !the_globals->haveEST() ){
608     sprintf( painCave.errMsg,
609 mmeineke 469 "SimSetup Warning: using default value of 5%% of the "
610 gezelter 394 "electrostaticCutoffRadius for the "
611     "electrostaticSkinThickness\n"
612     );
613     painCave.isFatal = 0;
614     simError();
615     simnfo->est = 0.05 * simnfo->ecr;
616     } else {
617     simnfo->est = the_globals->getEST();
618     }
619     }
620     }
621 mmeineke 377
622 gezelter 394 #ifdef IS_MPI
623     strcpy( checkPointMsg, "electrostatic parameters check out" );
624     MPIcheckPoint();
625     #endif // is_mpi
626 mmeineke 377
627     if( the_globals->haveInitialConfig() ){
628    
629     InitializeFromFile* fileInit;
630     #ifdef IS_MPI // is_mpi
631     if( worldRank == 0 ){
632     #endif //is_mpi
633     fileInit = new InitializeFromFile( the_globals->getInitialConfig() );
634     #ifdef IS_MPI
635     }else fileInit = new InitializeFromFile( NULL );
636     #endif
637     fileInit->read_xyz( simnfo ); // default velocities on
638    
639     delete fileInit;
640     }
641     else{
642    
643     #ifdef IS_MPI
644    
645     // no init from bass
646    
647     sprintf( painCave.errMsg,
648     "Cannot intialize a parallel simulation without an initial configuration file.\n" );
649     painCave.isFatal;
650     simError();
651    
652     #else
653    
654     initFromBass();
655    
656    
657     #endif
658     }
659    
660     #ifdef IS_MPI
661     strcpy( checkPointMsg, "Successfully read in the initial configuration" );
662     MPIcheckPoint();
663     #endif // is_mpi
664    
665    
666    
667    
668    
669    
670    
671     #ifdef IS_MPI
672     if( worldRank == 0 ){
673     #endif // is_mpi
674    
675     if( the_globals->haveFinalConfig() ){
676     strcpy( simnfo->finalName, the_globals->getFinalConfig() );
677     }
678     else{
679     strcpy( simnfo->finalName, inFileName );
680     char* endTest;
681     int nameLength = strlen( simnfo->finalName );
682     endTest = &(simnfo->finalName[nameLength - 5]);
683     if( !strcmp( endTest, ".bass" ) ){
684     strcpy( endTest, ".eor" );
685     }
686     else if( !strcmp( endTest, ".BASS" ) ){
687     strcpy( endTest, ".eor" );
688     }
689     else{
690     endTest = &(simnfo->finalName[nameLength - 4]);
691     if( !strcmp( endTest, ".bss" ) ){
692     strcpy( endTest, ".eor" );
693     }
694     else if( !strcmp( endTest, ".mdl" ) ){
695     strcpy( endTest, ".eor" );
696     }
697     else{
698     strcat( simnfo->finalName, ".eor" );
699     }
700     }
701     }
702    
703     // make the sample and status out names
704    
705     strcpy( simnfo->sampleName, inFileName );
706     char* endTest;
707     int nameLength = strlen( simnfo->sampleName );
708     endTest = &(simnfo->sampleName[nameLength - 5]);
709     if( !strcmp( endTest, ".bass" ) ){
710     strcpy( endTest, ".dump" );
711     }
712     else if( !strcmp( endTest, ".BASS" ) ){
713     strcpy( endTest, ".dump" );
714     }
715     else{
716     endTest = &(simnfo->sampleName[nameLength - 4]);
717     if( !strcmp( endTest, ".bss" ) ){
718     strcpy( endTest, ".dump" );
719     }
720     else if( !strcmp( endTest, ".mdl" ) ){
721     strcpy( endTest, ".dump" );
722     }
723     else{
724     strcat( simnfo->sampleName, ".dump" );
725     }
726     }
727    
728     strcpy( simnfo->statusName, inFileName );
729     nameLength = strlen( simnfo->statusName );
730     endTest = &(simnfo->statusName[nameLength - 5]);
731     if( !strcmp( endTest, ".bass" ) ){
732     strcpy( endTest, ".stat" );
733     }
734     else if( !strcmp( endTest, ".BASS" ) ){
735     strcpy( endTest, ".stat" );
736     }
737     else{
738     endTest = &(simnfo->statusName[nameLength - 4]);
739     if( !strcmp( endTest, ".bss" ) ){
740     strcpy( endTest, ".stat" );
741     }
742     else if( !strcmp( endTest, ".mdl" ) ){
743     strcpy( endTest, ".stat" );
744     }
745     else{
746     strcat( simnfo->statusName, ".stat" );
747     }
748     }
749    
750     #ifdef IS_MPI
751     }
752     #endif // is_mpi
753    
754     // set the status, sample, and themal kick times
755    
756     if( the_globals->haveSampleTime() ){
757     simnfo->sampleTime = the_globals->getSampleTime();
758     simnfo->statusTime = simnfo->sampleTime;
759     simnfo->thermalTime = simnfo->sampleTime;
760     }
761     else{
762     simnfo->sampleTime = the_globals->getRunTime();
763     simnfo->statusTime = simnfo->sampleTime;
764     simnfo->thermalTime = simnfo->sampleTime;
765     }
766    
767     if( the_globals->haveStatusTime() ){
768     simnfo->statusTime = the_globals->getStatusTime();
769     }
770    
771     if( the_globals->haveThermalTime() ){
772     simnfo->thermalTime = the_globals->getThermalTime();
773     }
774    
775     // check for the temperature set flag
776    
777     if( the_globals->haveTempSet() ) simnfo->setTemp = the_globals->getTempSet();
778    
779    
780 mmeineke 555 // make the integrator
781 mmeineke 561
782    
783     NVT* myNVT = NULL;
784 mmeineke 558 switch( ensembleCase ){
785 mmeineke 377
786 mmeineke 558 case NVE_ENS:
787     new NVE( simnfo, the_ff );
788     break;
789    
790 mmeineke 561 case NVT_ENS:
791     myNVT = new NVT( simnfo, the_ff );
792     myNVT->setTargetTemp(the_globals->getTargetTemp());
793    
794     if (the_globals->haveTauThermostat())
795     myNVT->setTauThermostat(the_globals->getTauThermostat());
796 mmeineke 567 // else if (the_globals->haveQmass())
797     // myNVT->setQmass(the_globals->getQmass());
798 mmeineke 561 else {
799     sprintf( painCave.errMsg,
800     "SimSetup error: If you use the NVT\n"
801     " ensemble, you must set either tauThermostat or qMass.\n"
802     " Neither of these was found in the BASS file.\n");
803     painCave.isFatal = 1;
804     simError();
805     }
806     break;
807    
808 mmeineke 558 default:
809     sprintf( painCave.errMsg,
810     "SimSetup Error. Unrecognized ensemble in case statement.\n");
811     painCave.isFatal = 1;
812     simError();
813 mmeineke 469 }
814 mmeineke 504
815 mmeineke 558
816 chuckv 432 #ifdef IS_MPI
817     mpiSim->mpiRefresh();
818     #endif
819 mmeineke 377
820 chuckv 432 // initialize the Fortran
821 mmeineke 377
822 chuckv 432
823 mmeineke 377 simnfo->refreshSim();
824    
825     if( !strcmp( simnfo->mixingRule, "standard") ){
826     the_ff->initForceField( LB_MIXING_RULE );
827     }
828     else if( !strcmp( simnfo->mixingRule, "explicit") ){
829     the_ff->initForceField( EXPLICIT_MIXING_RULE );
830     }
831     else{
832     sprintf( painCave.errMsg,
833     "SimSetup Error: unknown mixing rule -> \"%s\"\n",
834     simnfo->mixingRule );
835     painCave.isFatal = 1;
836     simError();
837     }
838    
839    
840     #ifdef IS_MPI
841     strcpy( checkPointMsg,
842     "Successfully intialized the mixingRule for Fortran." );
843     MPIcheckPoint();
844     #endif // is_mpi
845     }
846    
847 mmeineke 407
848     void SimSetup::makeMolecules( void ){
849    
850 mmeineke 412 int i, j, exI, exJ, tempEx, stampID, atomOffset, excludeOffset;
851 mmeineke 407 molInit info;
852     DirectionalAtom* dAtom;
853 mmeineke 412 LinkedAssign* extras;
854     LinkedAssign* current_extra;
855 mmeineke 407 AtomStamp* currentAtom;
856     BondStamp* currentBond;
857     BendStamp* currentBend;
858     TorsionStamp* currentTorsion;
859 mmeineke 427
860     bond_pair* theBonds;
861     bend_set* theBends;
862     torsion_set* theTorsions;
863    
864 mmeineke 407
865     //init the forceField paramters
866    
867     the_ff->readParams();
868    
869    
870 mmeineke 427 // init the atoms
871 mmeineke 407
872 mmeineke 427 double ux, uy, uz, u, uSqr;
873    
874 mmeineke 407 atomOffset = 0;
875 mmeineke 412 excludeOffset = 0;
876 mmeineke 407 for(i=0; i<simnfo->n_mol; i++){
877    
878     stampID = the_molecules[i].getStampID();
879    
880     info.nAtoms = comp_stamps[stampID]->getNAtoms();
881     info.nBonds = comp_stamps[stampID]->getNBonds();
882     info.nBends = comp_stamps[stampID]->getNBends();
883     info.nTorsions = comp_stamps[stampID]->getNTorsions();
884 mmeineke 412 info.nExcludes = info.nBonds + info.nBends + info.nTorsions;
885    
886 mmeineke 407 info.myAtoms = &the_atoms[atomOffset];
887 mmeineke 412 info.myExcludes = &the_excludes[excludeOffset];
888 mmeineke 407 info.myBonds = new Bond*[info.nBonds];
889     info.myBends = new Bend*[info.nBends];
890 mmeineke 427 info.myTorsions = new Torsion*[info.nTorsions];
891 mmeineke 407
892     theBonds = new bond_pair[info.nBonds];
893     theBends = new bend_set[info.nBends];
894     theTorsions = new torsion_set[info.nTorsions];
895    
896     // make the Atoms
897    
898     for(j=0; j<info.nAtoms; j++){
899    
900 mmeineke 427 currentAtom = comp_stamps[stampID]->getAtom( j );
901 mmeineke 407 if( currentAtom->haveOrientation() ){
902    
903     dAtom = new DirectionalAtom(j + atomOffset);
904     simnfo->n_oriented++;
905     info.myAtoms[j] = dAtom;
906    
907     ux = currentAtom->getOrntX();
908     uy = currentAtom->getOrntY();
909     uz = currentAtom->getOrntZ();
910    
911     uSqr = (ux * ux) + (uy * uy) + (uz * uz);
912    
913     u = sqrt( uSqr );
914     ux = ux / u;
915     uy = uy / u;
916     uz = uz / u;
917    
918     dAtom->setSUx( ux );
919     dAtom->setSUy( uy );
920     dAtom->setSUz( uz );
921     }
922     else{
923     info.myAtoms[j] = new GeneralAtom(j + atomOffset);
924     }
925     info.myAtoms[j]->setType( currentAtom->getType() );
926    
927     #ifdef IS_MPI
928    
929     info.myAtoms[j]->setGlobalIndex( globalIndex[j+atomOffset] );
930    
931     #endif // is_mpi
932     }
933    
934     // make the bonds
935 mmeineke 412 for(j=0; j<info.nBonds; j++){
936 mmeineke 407
937     currentBond = comp_stamps[stampID]->getBond( j );
938     theBonds[j].a = currentBond->getA() + atomOffset;
939     theBonds[j].b = currentBond->getB() + atomOffset;
940    
941 mmeineke 435 exI = theBonds[j].a;
942     exJ = theBonds[j].b;
943 mmeineke 407
944     // exclude_I must always be the smaller of the pair
945     if( exI > exJ ){
946     tempEx = exI;
947     exI = exJ;
948     exJ = tempEx;
949     }
950     #ifdef IS_MPI
951 mmeineke 412 tempEx = exI;
952     exI = the_atoms[tempEx]->getGlobalIndex() + 1;
953     tempEx = exJ;
954     exJ = the_atoms[tempEx]->getGlobalIndex() + 1;
955 mmeineke 407
956 mmeineke 412 the_excludes[j+excludeOffset]->setPair( exI, exJ );
957     #else // isn't MPI
958 mmeineke 435
959 mmeineke 412 the_excludes[j+excludeOffset]->setPair( (exI+1), (exJ+1) );
960     #endif //is_mpi
961     }
962     excludeOffset += info.nBonds;
963    
964     //make the bends
965     for(j=0; j<info.nBends; j++){
966 mmeineke 407
967 mmeineke 412 currentBend = comp_stamps[stampID]->getBend( j );
968     theBends[j].a = currentBend->getA() + atomOffset;
969     theBends[j].b = currentBend->getB() + atomOffset;
970     theBends[j].c = currentBend->getC() + atomOffset;
971    
972     if( currentBend->haveExtras() ){
973    
974 mmeineke 427 extras = currentBend->getExtras();
975 mmeineke 412 current_extra = extras;
976    
977     while( current_extra != NULL ){
978     if( !strcmp( current_extra->getlhs(), "ghostVectorSource" )){
979    
980     switch( current_extra->getType() ){
981    
982     case 0:
983     theBends[j].ghost =
984     current_extra->getInt() + atomOffset;
985     theBends[j].isGhost = 1;
986     break;
987    
988     case 1:
989     theBends[j].ghost =
990     (int)current_extra->getDouble() + atomOffset;
991     theBends[j].isGhost = 1;
992     break;
993    
994     default:
995     sprintf( painCave.errMsg,
996 chuckv 434 "SimSetup Error: ghostVectorSource was neither a "
997 mmeineke 412 "double nor an int.\n"
998     "-->Bend[%d] in %s\n",
999     j, comp_stamps[stampID]->getID() );
1000     painCave.isFatal = 1;
1001     simError();
1002     }
1003     }
1004    
1005     else{
1006    
1007     sprintf( painCave.errMsg,
1008     "SimSetup Error: unhandled bend assignment:\n"
1009     " -->%s in Bend[%d] in %s\n",
1010     current_extra->getlhs(),
1011     j, comp_stamps[stampID]->getID() );
1012     painCave.isFatal = 1;
1013     simError();
1014     }
1015    
1016     current_extra = current_extra->getNext();
1017     }
1018     }
1019    
1020     if( !theBends[j].isGhost ){
1021    
1022     exI = theBends[j].a;
1023     exJ = theBends[j].c;
1024     }
1025     else{
1026    
1027     exI = theBends[j].a;
1028     exJ = theBends[j].b;
1029     }
1030    
1031     // exclude_I must always be the smaller of the pair
1032     if( exI > exJ ){
1033     tempEx = exI;
1034     exI = exJ;
1035     exJ = tempEx;
1036     }
1037     #ifdef IS_MPI
1038     tempEx = exI;
1039     exI = the_atoms[tempEx]->getGlobalIndex() + 1;
1040     tempEx = exJ;
1041     exJ = the_atoms[tempEx]->getGlobalIndex() + 1;
1042    
1043     the_excludes[j+excludeOffset]->setPair( exI, exJ );
1044 mmeineke 407 #else // isn't MPI
1045 mmeineke 412 the_excludes[j+excludeOffset]->setPair( (exI+1), (exJ+1) );
1046     #endif //is_mpi
1047     }
1048     excludeOffset += info.nBends;
1049    
1050     for(j=0; j<info.nTorsions; j++){
1051 mmeineke 407
1052 mmeineke 412 currentTorsion = comp_stamps[stampID]->getTorsion( j );
1053     theTorsions[j].a = currentTorsion->getA() + atomOffset;
1054     theTorsions[j].b = currentTorsion->getB() + atomOffset;
1055     theTorsions[j].c = currentTorsion->getC() + atomOffset;
1056     theTorsions[j].d = currentTorsion->getD() + atomOffset;
1057    
1058     exI = theTorsions[j].a;
1059     exJ = theTorsions[j].d;
1060 mmeineke 407
1061 mmeineke 412 // exclude_I must always be the smaller of the pair
1062     if( exI > exJ ){
1063     tempEx = exI;
1064     exI = exJ;
1065     exJ = tempEx;
1066     }
1067     #ifdef IS_MPI
1068     tempEx = exI;
1069     exI = the_atoms[tempEx]->getGlobalIndex() + 1;
1070     tempEx = exJ;
1071     exJ = the_atoms[tempEx]->getGlobalIndex() + 1;
1072    
1073     the_excludes[j+excludeOffset]->setPair( exI, exJ );
1074     #else // isn't MPI
1075     the_excludes[j+excludeOffset]->setPair( (exI+1), (exJ+1) );
1076 mmeineke 407 #endif //is_mpi
1077 mmeineke 412 }
1078     excludeOffset += info.nTorsions;
1079    
1080 mmeineke 407
1081 mmeineke 414 // send the arrays off to the forceField for init.
1082 mmeineke 407
1083 mmeineke 414 the_ff->initializeAtoms( info.nAtoms, info.myAtoms );
1084     the_ff->initializeBonds( info.nBonds, info.myBonds, theBonds );
1085     the_ff->initializeBends( info.nBends, info.myBends, theBends );
1086     the_ff->initializeTorsions( info.nTorsions, info.myTorsions, theTorsions );
1087 mmeineke 407
1088    
1089 mmeineke 414 the_molecules[i].initialize( info );
1090 chuckv 438
1091    
1092 mmeineke 414 atomOffset += info.nAtoms;
1093 mmeineke 427 delete[] theBonds;
1094     delete[] theBends;
1095     delete[] theTorsions;
1096 mmeineke 414 }
1097 mmeineke 407
1098 chuckv 434 #ifdef IS_MPI
1099     sprintf( checkPointMsg, "all molecules initialized succesfully" );
1100     MPIcheckPoint();
1101     #endif // is_mpi
1102    
1103 mmeineke 414 // clean up the forcefield
1104 mmeineke 420 the_ff->calcRcut();
1105 mmeineke 414 the_ff->cleanMe();
1106 chuckv 434
1107 mmeineke 414 }
1108 mmeineke 407
1109 mmeineke 377 void SimSetup::initFromBass( void ){
1110    
1111     int i, j, k;
1112     int n_cells;
1113     double cellx, celly, cellz;
1114     double temp1, temp2, temp3;
1115     int n_per_extra;
1116     int n_extra;
1117     int have_extra, done;
1118    
1119     temp1 = (double)tot_nmol / 4.0;
1120     temp2 = pow( temp1, ( 1.0 / 3.0 ) );
1121     temp3 = ceil( temp2 );
1122    
1123     have_extra =0;
1124     if( temp2 < temp3 ){ // we have a non-complete lattice
1125     have_extra =1;
1126    
1127     n_cells = (int)temp3 - 1;
1128 mmeineke 572 cellx = simnfo->boxLx / temp3;
1129     celly = simnfo->boxLy / temp3;
1130     cellz = simnfo->boxLz / temp3;
1131 mmeineke 377 n_extra = tot_nmol - ( 4 * n_cells * n_cells * n_cells );
1132     temp1 = ((double)n_extra) / ( pow( temp3, 3.0 ) - pow( n_cells, 3.0 ) );
1133     n_per_extra = (int)ceil( temp1 );
1134    
1135     if( n_per_extra > 4){
1136     sprintf( painCave.errMsg,
1137     "SimSetup error. There has been an error in constructing"
1138     " the non-complete lattice.\n" );
1139     painCave.isFatal = 1;
1140     simError();
1141     }
1142     }
1143     else{
1144     n_cells = (int)temp3;
1145 mmeineke 572 cellx = simnfo->boxLx / temp3;
1146     celly = simnfo->boxLy / temp3;
1147     cellz = simnfo->boxLz / temp3;
1148 mmeineke 377 }
1149    
1150     current_mol = 0;
1151     current_comp_mol = 0;
1152     current_comp = 0;
1153     current_atom_ndx = 0;
1154    
1155     for( i=0; i < n_cells ; i++ ){
1156     for( j=0; j < n_cells; j++ ){
1157     for( k=0; k < n_cells; k++ ){
1158    
1159     makeElement( i * cellx,
1160     j * celly,
1161     k * cellz );
1162    
1163     makeElement( i * cellx + 0.5 * cellx,
1164     j * celly + 0.5 * celly,
1165     k * cellz );
1166    
1167     makeElement( i * cellx,
1168     j * celly + 0.5 * celly,
1169     k * cellz + 0.5 * cellz );
1170    
1171     makeElement( i * cellx + 0.5 * cellx,
1172     j * celly,
1173     k * cellz + 0.5 * cellz );
1174     }
1175     }
1176     }
1177    
1178     if( have_extra ){
1179     done = 0;
1180    
1181     int start_ndx;
1182     for( i=0; i < (n_cells+1) && !done; i++ ){
1183     for( j=0; j < (n_cells+1) && !done; j++ ){
1184    
1185     if( i < n_cells ){
1186    
1187     if( j < n_cells ){
1188     start_ndx = n_cells;
1189     }
1190     else start_ndx = 0;
1191     }
1192     else start_ndx = 0;
1193    
1194     for( k=start_ndx; k < (n_cells+1) && !done; k++ ){
1195    
1196     makeElement( i * cellx,
1197     j * celly,
1198     k * cellz );
1199     done = ( current_mol >= tot_nmol );
1200    
1201     if( !done && n_per_extra > 1 ){
1202     makeElement( i * cellx + 0.5 * cellx,
1203     j * celly + 0.5 * celly,
1204     k * cellz );
1205     done = ( current_mol >= tot_nmol );
1206     }
1207    
1208     if( !done && n_per_extra > 2){
1209     makeElement( i * cellx,
1210     j * celly + 0.5 * celly,
1211     k * cellz + 0.5 * cellz );
1212     done = ( current_mol >= tot_nmol );
1213     }
1214    
1215     if( !done && n_per_extra > 3){
1216     makeElement( i * cellx + 0.5 * cellx,
1217     j * celly,
1218     k * cellz + 0.5 * cellz );
1219     done = ( current_mol >= tot_nmol );
1220     }
1221     }
1222     }
1223     }
1224     }
1225    
1226    
1227     for( i=0; i<simnfo->n_atoms; i++ ){
1228     simnfo->atoms[i]->set_vx( 0.0 );
1229     simnfo->atoms[i]->set_vy( 0.0 );
1230     simnfo->atoms[i]->set_vz( 0.0 );
1231     }
1232     }
1233    
1234     void SimSetup::makeElement( double x, double y, double z ){
1235    
1236     int k;
1237     AtomStamp* current_atom;
1238     DirectionalAtom* dAtom;
1239     double rotMat[3][3];
1240    
1241     for( k=0; k<comp_stamps[current_comp]->getNAtoms(); k++ ){
1242    
1243     current_atom = comp_stamps[current_comp]->getAtom( k );
1244     if( !current_atom->havePosition() ){
1245     sprintf( painCave.errMsg,
1246     "SimSetup:initFromBass error.\n"
1247     "\tComponent %s, atom %s does not have a position specified.\n"
1248     "\tThe initialization routine is unable to give a start"
1249     " position.\n",
1250     comp_stamps[current_comp]->getID(),
1251     current_atom->getType() );
1252     painCave.isFatal = 1;
1253     simError();
1254     }
1255    
1256     the_atoms[current_atom_ndx]->setX( x + current_atom->getPosX() );
1257     the_atoms[current_atom_ndx]->setY( y + current_atom->getPosY() );
1258     the_atoms[current_atom_ndx]->setZ( z + current_atom->getPosZ() );
1259    
1260     if( the_atoms[current_atom_ndx]->isDirectional() ){
1261    
1262     dAtom = (DirectionalAtom *)the_atoms[current_atom_ndx];
1263    
1264     rotMat[0][0] = 1.0;
1265     rotMat[0][1] = 0.0;
1266     rotMat[0][2] = 0.0;
1267    
1268     rotMat[1][0] = 0.0;
1269     rotMat[1][1] = 1.0;
1270     rotMat[1][2] = 0.0;
1271    
1272     rotMat[2][0] = 0.0;
1273     rotMat[2][1] = 0.0;
1274     rotMat[2][2] = 1.0;
1275    
1276     dAtom->setA( rotMat );
1277     }
1278    
1279     current_atom_ndx++;
1280     }
1281    
1282     current_mol++;
1283     current_comp_mol++;
1284    
1285     if( current_comp_mol >= components_nmol[current_comp] ){
1286    
1287     current_comp_mol = 0;
1288     current_comp++;
1289     }
1290     }