ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/group/trunk/OOPSE/libmdtools/SimSetup.cpp
Revision: 481
Committed: Tue Apr 8 21:35:49 2003 UTC (21 years, 2 months ago) by gezelter
File size: 31056 byte(s)
Log Message:
Fixes for NPT / NVT

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