ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/group/trunk/OOPSE/libmdtools/SimSetup.cpp
Revision: 491
Committed: Fri Apr 11 18:46:37 2003 UTC (21 years, 2 months ago) by mmeineke
File size: 31408 byte(s)
Log Message:
fixed a memory bug in Fortran, where molMembershipArray was declared nLocal instead of nGlobal.

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 gezelter 490 int i, j, k, globalAtomIndex;
71 mmeineke 377
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 mmeineke 491
302 gezelter 490 simnfo->molMembershipArray = new int[tot_atoms];
303 mmeineke 377
304     #ifdef IS_MPI
305    
306     // divide the molecules among processors here.
307    
308     mpiSim = new mpiSimulation( simnfo );
309    
310     globalIndex = mpiSim->divideLabor();
311    
312     // set up the local variables
313    
314     int localMol, allMol;
315     int local_atoms, local_bonds, local_bends, local_torsions, local_SRI;
316 mmeineke 422
317     int* mol2proc = mpiSim->getMolToProcMap();
318     int* molCompType = mpiSim->getMolComponentType();
319 mmeineke 377
320     allMol = 0;
321     localMol = 0;
322     local_atoms = 0;
323     local_bonds = 0;
324     local_bends = 0;
325     local_torsions = 0;
326 gezelter 490 globalAtomIndex = 0;
327    
328    
329 mmeineke 377 for( i=0; i<n_components; i++ ){
330    
331     for( j=0; j<components_nmol[i]; j++ ){
332    
333 mmeineke 487 if( mol2proc[allMol] == worldRank ){
334 mmeineke 377
335     local_atoms += comp_stamps[i]->getNAtoms();
336     local_bonds += comp_stamps[i]->getNBonds();
337     local_bends += comp_stamps[i]->getNBends();
338     local_torsions += comp_stamps[i]->getNTorsions();
339     localMol++;
340     }
341 gezelter 490 for (k = 0; k < comp_stamps[i]->getNAtoms(); k++) {
342     simnfo->molMembershipArray[globalAtomIndex] = allMol;
343     globalAtomIndex++;
344     }
345    
346     allMol++;
347 mmeineke 377 }
348     }
349     local_SRI = local_bonds + local_bends + local_torsions;
350    
351     simnfo->n_atoms = mpiSim->getMyNlocal();
352    
353     if( local_atoms != simnfo->n_atoms ){
354     sprintf( painCave.errMsg,
355     "SimSetup error: mpiSim's localAtom (%d) and SimSetup's"
356 mmeineke 422 " localAtom (%d) are not equal.\n",
357 mmeineke 377 simnfo->n_atoms,
358     local_atoms );
359     painCave.isFatal = 1;
360     simError();
361     }
362    
363     simnfo->n_bonds = local_bonds;
364     simnfo->n_bends = local_bends;
365     simnfo->n_torsions = local_torsions;
366     simnfo->n_SRI = local_SRI;
367     simnfo->n_mol = localMol;
368    
369     strcpy( checkPointMsg, "Passed nlocal consistency check." );
370     MPIcheckPoint();
371    
372    
373     #endif // is_mpi
374    
375    
376     // create the atom and short range interaction arrays
377    
378     Atom::createArrays(simnfo->n_atoms);
379     the_atoms = new Atom*[simnfo->n_atoms];
380     the_molecules = new Molecule[simnfo->n_mol];
381 mmeineke 422 int molIndex;
382 mmeineke 377
383 mmeineke 422 // initialize the molecule's stampID's
384 mmeineke 377
385 mmeineke 422 #ifdef IS_MPI
386    
387    
388     molIndex = 0;
389     for(i=0; i<mpiSim->getTotNmol(); i++){
390    
391     if(mol2proc[i] == worldRank ){
392     the_molecules[molIndex].setStampID( molCompType[i] );
393 chuckv 438 the_molecules[molIndex].setMyIndex( molIndex );
394 mmeineke 489 the_molecules[molIndex].setGlobalIndex( i );
395 mmeineke 422 molIndex++;
396     }
397     }
398    
399     #else // is_mpi
400    
401     molIndex = 0;
402 gezelter 490 globalAtomIndex = 0;
403 mmeineke 422 for(i=0; i<n_components; i++){
404     for(j=0; j<components_nmol[i]; j++ ){
405     the_molecules[molIndex].setStampID( i );
406 chuckv 438 the_molecules[molIndex].setMyIndex( molIndex );
407 mmeineke 489 the_molecules[molIndex].setGlobalIndex( molIndex );
408 gezelter 490 for (k = 0; k < comp_stamps[i]->getNAtoms(); k++) {
409     simnfo->molMembershipArray[globalAtomIndex] = molIndex;
410     globalAtomIndex++;
411     }
412 mmeineke 422 molIndex++;
413     }
414     }
415    
416    
417     #endif // is_mpi
418    
419    
420 mmeineke 377 if( simnfo->n_SRI ){
421 mmeineke 431
422 mmeineke 412 Exclude::createArray(simnfo->n_SRI);
423     the_excludes = new Exclude*[simnfo->n_SRI];
424 mmeineke 431 for( int ex=0; ex<simnfo->n_SRI; ex++) the_excludes[ex] = new Exclude(ex);
425 mmeineke 377 simnfo->globalExcludes = new int;
426 chuckv 438 simnfo->n_exclude = simnfo->n_SRI;
427 mmeineke 377 }
428     else{
429    
430 mmeineke 412 Exclude::createArray( 1 );
431     the_excludes = new Exclude*;
432     the_excludes[0] = new Exclude(0);
433     the_excludes[0]->setPair( 0,0 );
434 mmeineke 377 simnfo->globalExcludes = new int;
435     simnfo->globalExcludes[0] = 0;
436 mmeineke 412 simnfo->n_exclude = 0;
437 mmeineke 377 }
438    
439     // set the arrays into the SimInfo object
440    
441     simnfo->atoms = the_atoms;
442 mmeineke 429 simnfo->molecules = the_molecules;
443 mmeineke 377 simnfo->nGlobalExcludes = 0;
444     simnfo->excludes = the_excludes;
445    
446    
447     // get some of the tricky things that may still be in the globals
448    
449    
450     if( the_globals->haveBox() ){
451     simnfo->box_x = the_globals->getBox();
452     simnfo->box_y = the_globals->getBox();
453     simnfo->box_z = the_globals->getBox();
454     }
455     else if( the_globals->haveDensity() ){
456    
457     double vol;
458     vol = (double)tot_nmol / the_globals->getDensity();
459     simnfo->box_x = pow( vol, ( 1.0 / 3.0 ) );
460     simnfo->box_y = simnfo->box_x;
461     simnfo->box_z = simnfo->box_x;
462     }
463     else{
464     if( !the_globals->haveBoxX() ){
465     sprintf( painCave.errMsg,
466     "SimSetup error, no periodic BoxX size given.\n" );
467     painCave.isFatal = 1;
468     simError();
469     }
470     simnfo->box_x = the_globals->getBoxX();
471    
472     if( !the_globals->haveBoxY() ){
473     sprintf( painCave.errMsg,
474     "SimSetup error, no periodic BoxY size given.\n" );
475     painCave.isFatal = 1;
476     simError();
477     }
478     simnfo->box_y = the_globals->getBoxY();
479    
480     if( !the_globals->haveBoxZ() ){
481     sprintf( painCave.errMsg,
482     "SimSetup error, no periodic BoxZ size given.\n" );
483     painCave.isFatal = 1;
484     simError();
485     }
486     simnfo->box_z = the_globals->getBoxZ();
487     }
488    
489     #ifdef IS_MPI
490     strcpy( checkPointMsg, "Box size set up" );
491     MPIcheckPoint();
492     #endif // is_mpi
493    
494    
495     // initialize the arrays
496    
497     the_ff->setSimInfo( simnfo );
498    
499 mmeineke 422 makeMolecules();
500 mmeineke 377 simnfo->identArray = new int[simnfo->n_atoms];
501     for(i=0; i<simnfo->n_atoms; i++){
502     simnfo->identArray[i] = the_atoms[i]->getIdent();
503     }
504    
505 gezelter 394 if (the_globals->getUseRF() ) {
506     simnfo->useReactionField = 1;
507    
508     if( !the_globals->haveECR() ){
509     sprintf( painCave.errMsg,
510     "SimSetup Warning: using default value of 1/2 the smallest "
511     "box length for the electrostaticCutoffRadius.\n"
512     "I hope you have a very fast processor!\n");
513     painCave.isFatal = 0;
514     simError();
515     double smallest;
516     smallest = simnfo->box_x;
517     if (simnfo->box_y <= smallest) smallest = simnfo->box_y;
518     if (simnfo->box_z <= smallest) smallest = simnfo->box_z;
519     simnfo->ecr = 0.5 * smallest;
520     } else {
521     simnfo->ecr = the_globals->getECR();
522     }
523 mmeineke 377
524 gezelter 394 if( !the_globals->haveEST() ){
525     sprintf( painCave.errMsg,
526     "SimSetup Warning: using default value of 0.05 * the "
527     "electrostaticCutoffRadius for the electrostaticSkinThickness\n"
528     );
529     painCave.isFatal = 0;
530     simError();
531     simnfo->est = 0.05 * simnfo->ecr;
532     } else {
533     simnfo->est = the_globals->getEST();
534     }
535    
536     if(!the_globals->haveDielectric() ){
537     sprintf( painCave.errMsg,
538     "SimSetup Error: You are trying to use Reaction Field without"
539     "setting a dielectric constant!\n"
540     );
541     painCave.isFatal = 1;
542     simError();
543     }
544     simnfo->dielectric = the_globals->getDielectric();
545     } else {
546 mmeineke 469 if (usesDipoles) {
547 gezelter 394
548     if( !the_globals->haveECR() ){
549     sprintf( painCave.errMsg,
550 mmeineke 469 "SimSetup Warning: using default value of 1/2 the smallest "
551 gezelter 394 "box length for the electrostaticCutoffRadius.\n"
552     "I hope you have a very fast processor!\n");
553     painCave.isFatal = 0;
554     simError();
555     double smallest;
556     smallest = simnfo->box_x;
557     if (simnfo->box_y <= smallest) smallest = simnfo->box_y;
558     if (simnfo->box_z <= smallest) smallest = simnfo->box_z;
559     simnfo->ecr = 0.5 * smallest;
560     } else {
561     simnfo->ecr = the_globals->getECR();
562     }
563    
564     if( !the_globals->haveEST() ){
565     sprintf( painCave.errMsg,
566 mmeineke 469 "SimSetup Warning: using default value of 5%% of the "
567 gezelter 394 "electrostaticCutoffRadius for the "
568     "electrostaticSkinThickness\n"
569     );
570     painCave.isFatal = 0;
571     simError();
572     simnfo->est = 0.05 * simnfo->ecr;
573     } else {
574     simnfo->est = the_globals->getEST();
575     }
576     }
577     }
578 mmeineke 377
579 gezelter 394 #ifdef IS_MPI
580     strcpy( checkPointMsg, "electrostatic parameters check out" );
581     MPIcheckPoint();
582     #endif // is_mpi
583 mmeineke 377
584     if( the_globals->haveInitialConfig() ){
585    
586     InitializeFromFile* fileInit;
587     #ifdef IS_MPI // is_mpi
588     if( worldRank == 0 ){
589     #endif //is_mpi
590     fileInit = new InitializeFromFile( the_globals->getInitialConfig() );
591     #ifdef IS_MPI
592     }else fileInit = new InitializeFromFile( NULL );
593     #endif
594     fileInit->read_xyz( simnfo ); // default velocities on
595    
596     delete fileInit;
597     }
598     else{
599    
600     #ifdef IS_MPI
601    
602     // no init from bass
603    
604     sprintf( painCave.errMsg,
605     "Cannot intialize a parallel simulation without an initial configuration file.\n" );
606     painCave.isFatal;
607     simError();
608    
609     #else
610    
611     initFromBass();
612    
613    
614     #endif
615     }
616    
617     #ifdef IS_MPI
618     strcpy( checkPointMsg, "Successfully read in the initial configuration" );
619     MPIcheckPoint();
620     #endif // is_mpi
621    
622    
623    
624    
625    
626    
627    
628     #ifdef IS_MPI
629     if( worldRank == 0 ){
630     #endif // is_mpi
631    
632     if( the_globals->haveFinalConfig() ){
633     strcpy( simnfo->finalName, the_globals->getFinalConfig() );
634     }
635     else{
636     strcpy( simnfo->finalName, inFileName );
637     char* endTest;
638     int nameLength = strlen( simnfo->finalName );
639     endTest = &(simnfo->finalName[nameLength - 5]);
640     if( !strcmp( endTest, ".bass" ) ){
641     strcpy( endTest, ".eor" );
642     }
643     else if( !strcmp( endTest, ".BASS" ) ){
644     strcpy( endTest, ".eor" );
645     }
646     else{
647     endTest = &(simnfo->finalName[nameLength - 4]);
648     if( !strcmp( endTest, ".bss" ) ){
649     strcpy( endTest, ".eor" );
650     }
651     else if( !strcmp( endTest, ".mdl" ) ){
652     strcpy( endTest, ".eor" );
653     }
654     else{
655     strcat( simnfo->finalName, ".eor" );
656     }
657     }
658     }
659    
660     // make the sample and status out names
661    
662     strcpy( simnfo->sampleName, inFileName );
663     char* endTest;
664     int nameLength = strlen( simnfo->sampleName );
665     endTest = &(simnfo->sampleName[nameLength - 5]);
666     if( !strcmp( endTest, ".bass" ) ){
667     strcpy( endTest, ".dump" );
668     }
669     else if( !strcmp( endTest, ".BASS" ) ){
670     strcpy( endTest, ".dump" );
671     }
672     else{
673     endTest = &(simnfo->sampleName[nameLength - 4]);
674     if( !strcmp( endTest, ".bss" ) ){
675     strcpy( endTest, ".dump" );
676     }
677     else if( !strcmp( endTest, ".mdl" ) ){
678     strcpy( endTest, ".dump" );
679     }
680     else{
681     strcat( simnfo->sampleName, ".dump" );
682     }
683     }
684    
685     strcpy( simnfo->statusName, inFileName );
686     nameLength = strlen( simnfo->statusName );
687     endTest = &(simnfo->statusName[nameLength - 5]);
688     if( !strcmp( endTest, ".bass" ) ){
689     strcpy( endTest, ".stat" );
690     }
691     else if( !strcmp( endTest, ".BASS" ) ){
692     strcpy( endTest, ".stat" );
693     }
694     else{
695     endTest = &(simnfo->statusName[nameLength - 4]);
696     if( !strcmp( endTest, ".bss" ) ){
697     strcpy( endTest, ".stat" );
698     }
699     else if( !strcmp( endTest, ".mdl" ) ){
700     strcpy( endTest, ".stat" );
701     }
702     else{
703     strcat( simnfo->statusName, ".stat" );
704     }
705     }
706    
707     #ifdef IS_MPI
708     }
709     #endif // is_mpi
710    
711     // set the status, sample, and themal kick times
712    
713     if( the_globals->haveSampleTime() ){
714     simnfo->sampleTime = the_globals->getSampleTime();
715     simnfo->statusTime = simnfo->sampleTime;
716     simnfo->thermalTime = simnfo->sampleTime;
717     }
718     else{
719     simnfo->sampleTime = the_globals->getRunTime();
720     simnfo->statusTime = simnfo->sampleTime;
721     simnfo->thermalTime = simnfo->sampleTime;
722     }
723    
724     if( the_globals->haveStatusTime() ){
725     simnfo->statusTime = the_globals->getStatusTime();
726     }
727    
728     if( the_globals->haveThermalTime() ){
729     simnfo->thermalTime = the_globals->getThermalTime();
730     }
731    
732     // check for the temperature set flag
733    
734     if( the_globals->haveTempSet() ) simnfo->setTemp = the_globals->getTempSet();
735    
736    
737     // // make the longe range forces and the integrator
738    
739     // new AllLong( simnfo );
740    
741    
742 mmeineke 469 if( !strcmp( force_field, "TraPPE_Ex" ) ){
743     new Symplectic(simnfo, the_ff, the_extendedsystem);
744     }
745     else if( !strcmp( force_field, "LJ" ) ){
746     new Verlet( *simnfo, the_ff, the_extendedsystem );
747     }
748     else {
749     std::cerr << "I'm a bug.\n";
750     fprintf( stderr, "Ima bug. stderr %s\n", force_field);
751     }
752 chuckv 432 #ifdef IS_MPI
753     mpiSim->mpiRefresh();
754     #endif
755 mmeineke 377
756 chuckv 432 // initialize the Fortran
757 mmeineke 377
758 chuckv 432
759 mmeineke 377 simnfo->refreshSim();
760    
761     if( !strcmp( simnfo->mixingRule, "standard") ){
762     the_ff->initForceField( LB_MIXING_RULE );
763     }
764     else if( !strcmp( simnfo->mixingRule, "explicit") ){
765     the_ff->initForceField( EXPLICIT_MIXING_RULE );
766     }
767     else{
768     sprintf( painCave.errMsg,
769     "SimSetup Error: unknown mixing rule -> \"%s\"\n",
770     simnfo->mixingRule );
771     painCave.isFatal = 1;
772     simError();
773     }
774    
775    
776     #ifdef IS_MPI
777     strcpy( checkPointMsg,
778     "Successfully intialized the mixingRule for Fortran." );
779     MPIcheckPoint();
780     #endif // is_mpi
781     }
782    
783 mmeineke 407
784     void SimSetup::makeMolecules( void ){
785    
786 mmeineke 412 int i, j, exI, exJ, tempEx, stampID, atomOffset, excludeOffset;
787 mmeineke 407 molInit info;
788     DirectionalAtom* dAtom;
789 mmeineke 412 LinkedAssign* extras;
790     LinkedAssign* current_extra;
791 mmeineke 407 AtomStamp* currentAtom;
792     BondStamp* currentBond;
793     BendStamp* currentBend;
794     TorsionStamp* currentTorsion;
795 mmeineke 427
796     bond_pair* theBonds;
797     bend_set* theBends;
798     torsion_set* theTorsions;
799    
800 mmeineke 407
801     //init the forceField paramters
802    
803     the_ff->readParams();
804    
805    
806 mmeineke 427 // init the atoms
807 mmeineke 407
808 mmeineke 427 double ux, uy, uz, u, uSqr;
809    
810 mmeineke 407 atomOffset = 0;
811 mmeineke 412 excludeOffset = 0;
812 mmeineke 407 for(i=0; i<simnfo->n_mol; i++){
813    
814     stampID = the_molecules[i].getStampID();
815    
816     info.nAtoms = comp_stamps[stampID]->getNAtoms();
817     info.nBonds = comp_stamps[stampID]->getNBonds();
818     info.nBends = comp_stamps[stampID]->getNBends();
819     info.nTorsions = comp_stamps[stampID]->getNTorsions();
820 mmeineke 412 info.nExcludes = info.nBonds + info.nBends + info.nTorsions;
821    
822 mmeineke 407 info.myAtoms = &the_atoms[atomOffset];
823 mmeineke 412 info.myExcludes = &the_excludes[excludeOffset];
824 mmeineke 407 info.myBonds = new Bond*[info.nBonds];
825     info.myBends = new Bend*[info.nBends];
826 mmeineke 427 info.myTorsions = new Torsion*[info.nTorsions];
827 mmeineke 407
828     theBonds = new bond_pair[info.nBonds];
829     theBends = new bend_set[info.nBends];
830     theTorsions = new torsion_set[info.nTorsions];
831    
832     // make the Atoms
833    
834     for(j=0; j<info.nAtoms; j++){
835    
836 mmeineke 427 currentAtom = comp_stamps[stampID]->getAtom( j );
837 mmeineke 407 if( currentAtom->haveOrientation() ){
838    
839     dAtom = new DirectionalAtom(j + atomOffset);
840     simnfo->n_oriented++;
841     info.myAtoms[j] = dAtom;
842    
843     ux = currentAtom->getOrntX();
844     uy = currentAtom->getOrntY();
845     uz = currentAtom->getOrntZ();
846    
847     uSqr = (ux * ux) + (uy * uy) + (uz * uz);
848    
849     u = sqrt( uSqr );
850     ux = ux / u;
851     uy = uy / u;
852     uz = uz / u;
853    
854     dAtom->setSUx( ux );
855     dAtom->setSUy( uy );
856     dAtom->setSUz( uz );
857     }
858     else{
859     info.myAtoms[j] = new GeneralAtom(j + atomOffset);
860     }
861     info.myAtoms[j]->setType( currentAtom->getType() );
862    
863     #ifdef IS_MPI
864    
865     info.myAtoms[j]->setGlobalIndex( globalIndex[j+atomOffset] );
866    
867     #endif // is_mpi
868     }
869    
870     // make the bonds
871 mmeineke 412 for(j=0; j<info.nBonds; j++){
872 mmeineke 407
873     currentBond = comp_stamps[stampID]->getBond( j );
874     theBonds[j].a = currentBond->getA() + atomOffset;
875     theBonds[j].b = currentBond->getB() + atomOffset;
876    
877 mmeineke 435 exI = theBonds[j].a;
878     exJ = theBonds[j].b;
879 mmeineke 407
880     // exclude_I must always be the smaller of the pair
881     if( exI > exJ ){
882     tempEx = exI;
883     exI = exJ;
884     exJ = tempEx;
885     }
886     #ifdef IS_MPI
887 mmeineke 412 tempEx = exI;
888     exI = the_atoms[tempEx]->getGlobalIndex() + 1;
889     tempEx = exJ;
890     exJ = the_atoms[tempEx]->getGlobalIndex() + 1;
891 mmeineke 407
892 mmeineke 412 the_excludes[j+excludeOffset]->setPair( exI, exJ );
893     #else // isn't MPI
894 mmeineke 435
895 mmeineke 412 the_excludes[j+excludeOffset]->setPair( (exI+1), (exJ+1) );
896     #endif //is_mpi
897     }
898     excludeOffset += info.nBonds;
899    
900     //make the bends
901     for(j=0; j<info.nBends; j++){
902 mmeineke 407
903 mmeineke 412 currentBend = comp_stamps[stampID]->getBend( j );
904     theBends[j].a = currentBend->getA() + atomOffset;
905     theBends[j].b = currentBend->getB() + atomOffset;
906     theBends[j].c = currentBend->getC() + atomOffset;
907    
908     if( currentBend->haveExtras() ){
909    
910 mmeineke 427 extras = currentBend->getExtras();
911 mmeineke 412 current_extra = extras;
912    
913     while( current_extra != NULL ){
914     if( !strcmp( current_extra->getlhs(), "ghostVectorSource" )){
915    
916     switch( current_extra->getType() ){
917    
918     case 0:
919     theBends[j].ghost =
920     current_extra->getInt() + atomOffset;
921     theBends[j].isGhost = 1;
922     break;
923    
924     case 1:
925     theBends[j].ghost =
926     (int)current_extra->getDouble() + atomOffset;
927     theBends[j].isGhost = 1;
928     break;
929    
930     default:
931     sprintf( painCave.errMsg,
932 chuckv 434 "SimSetup Error: ghostVectorSource was neither a "
933 mmeineke 412 "double nor an int.\n"
934     "-->Bend[%d] in %s\n",
935     j, comp_stamps[stampID]->getID() );
936     painCave.isFatal = 1;
937     simError();
938     }
939     }
940    
941     else{
942    
943     sprintf( painCave.errMsg,
944     "SimSetup Error: unhandled bend assignment:\n"
945     " -->%s in Bend[%d] in %s\n",
946     current_extra->getlhs(),
947     j, comp_stamps[stampID]->getID() );
948     painCave.isFatal = 1;
949     simError();
950     }
951    
952     current_extra = current_extra->getNext();
953     }
954     }
955    
956     if( !theBends[j].isGhost ){
957    
958     exI = theBends[j].a;
959     exJ = theBends[j].c;
960     }
961     else{
962    
963     exI = theBends[j].a;
964     exJ = theBends[j].b;
965     }
966    
967     // exclude_I must always be the smaller of the pair
968     if( exI > exJ ){
969     tempEx = exI;
970     exI = exJ;
971     exJ = tempEx;
972     }
973     #ifdef IS_MPI
974     tempEx = exI;
975     exI = the_atoms[tempEx]->getGlobalIndex() + 1;
976     tempEx = exJ;
977     exJ = the_atoms[tempEx]->getGlobalIndex() + 1;
978    
979     the_excludes[j+excludeOffset]->setPair( exI, exJ );
980 mmeineke 407 #else // isn't MPI
981 mmeineke 412 the_excludes[j+excludeOffset]->setPair( (exI+1), (exJ+1) );
982     #endif //is_mpi
983     }
984     excludeOffset += info.nBends;
985    
986     for(j=0; j<info.nTorsions; j++){
987 mmeineke 407
988 mmeineke 412 currentTorsion = comp_stamps[stampID]->getTorsion( j );
989     theTorsions[j].a = currentTorsion->getA() + atomOffset;
990     theTorsions[j].b = currentTorsion->getB() + atomOffset;
991     theTorsions[j].c = currentTorsion->getC() + atomOffset;
992     theTorsions[j].d = currentTorsion->getD() + atomOffset;
993    
994     exI = theTorsions[j].a;
995     exJ = theTorsions[j].d;
996 mmeineke 407
997 mmeineke 412 // exclude_I must always be the smaller of the pair
998     if( exI > exJ ){
999     tempEx = exI;
1000     exI = exJ;
1001     exJ = tempEx;
1002     }
1003     #ifdef IS_MPI
1004     tempEx = exI;
1005     exI = the_atoms[tempEx]->getGlobalIndex() + 1;
1006     tempEx = exJ;
1007     exJ = the_atoms[tempEx]->getGlobalIndex() + 1;
1008    
1009     the_excludes[j+excludeOffset]->setPair( exI, exJ );
1010     #else // isn't MPI
1011     the_excludes[j+excludeOffset]->setPair( (exI+1), (exJ+1) );
1012 mmeineke 407 #endif //is_mpi
1013 mmeineke 412 }
1014     excludeOffset += info.nTorsions;
1015    
1016 mmeineke 407
1017 mmeineke 414 // send the arrays off to the forceField for init.
1018 mmeineke 407
1019 mmeineke 414 the_ff->initializeAtoms( info.nAtoms, info.myAtoms );
1020     the_ff->initializeBonds( info.nBonds, info.myBonds, theBonds );
1021     the_ff->initializeBends( info.nBends, info.myBends, theBends );
1022     the_ff->initializeTorsions( info.nTorsions, info.myTorsions, theTorsions );
1023 mmeineke 407
1024    
1025 mmeineke 414 the_molecules[i].initialize( info );
1026 chuckv 438
1027    
1028 mmeineke 414 atomOffset += info.nAtoms;
1029 mmeineke 427 delete[] theBonds;
1030     delete[] theBends;
1031     delete[] theTorsions;
1032 mmeineke 414 }
1033 mmeineke 407
1034 chuckv 434 #ifdef IS_MPI
1035     sprintf( checkPointMsg, "all molecules initialized succesfully" );
1036     MPIcheckPoint();
1037     #endif // is_mpi
1038    
1039 mmeineke 414 // clean up the forcefield
1040 mmeineke 420 the_ff->calcRcut();
1041 mmeineke 414 the_ff->cleanMe();
1042 chuckv 434
1043 mmeineke 414 }
1044 mmeineke 407
1045 mmeineke 377 void SimSetup::initFromBass( void ){
1046    
1047     int i, j, k;
1048     int n_cells;
1049     double cellx, celly, cellz;
1050     double temp1, temp2, temp3;
1051     int n_per_extra;
1052     int n_extra;
1053     int have_extra, done;
1054    
1055     temp1 = (double)tot_nmol / 4.0;
1056     temp2 = pow( temp1, ( 1.0 / 3.0 ) );
1057     temp3 = ceil( temp2 );
1058    
1059     have_extra =0;
1060     if( temp2 < temp3 ){ // we have a non-complete lattice
1061     have_extra =1;
1062    
1063     n_cells = (int)temp3 - 1;
1064     cellx = simnfo->box_x / temp3;
1065     celly = simnfo->box_y / temp3;
1066     cellz = simnfo->box_z / temp3;
1067     n_extra = tot_nmol - ( 4 * n_cells * n_cells * n_cells );
1068     temp1 = ((double)n_extra) / ( pow( temp3, 3.0 ) - pow( n_cells, 3.0 ) );
1069     n_per_extra = (int)ceil( temp1 );
1070    
1071     if( n_per_extra > 4){
1072     sprintf( painCave.errMsg,
1073     "SimSetup error. There has been an error in constructing"
1074     " the non-complete lattice.\n" );
1075     painCave.isFatal = 1;
1076     simError();
1077     }
1078     }
1079     else{
1080     n_cells = (int)temp3;
1081     cellx = simnfo->box_x / temp3;
1082     celly = simnfo->box_y / temp3;
1083     cellz = simnfo->box_z / temp3;
1084     }
1085    
1086     current_mol = 0;
1087     current_comp_mol = 0;
1088     current_comp = 0;
1089     current_atom_ndx = 0;
1090    
1091     for( i=0; i < n_cells ; i++ ){
1092     for( j=0; j < n_cells; j++ ){
1093     for( k=0; k < n_cells; k++ ){
1094    
1095     makeElement( i * cellx,
1096     j * celly,
1097     k * cellz );
1098    
1099     makeElement( i * cellx + 0.5 * cellx,
1100     j * celly + 0.5 * celly,
1101     k * cellz );
1102    
1103     makeElement( i * cellx,
1104     j * celly + 0.5 * celly,
1105     k * cellz + 0.5 * cellz );
1106    
1107     makeElement( i * cellx + 0.5 * cellx,
1108     j * celly,
1109     k * cellz + 0.5 * cellz );
1110     }
1111     }
1112     }
1113    
1114     if( have_extra ){
1115     done = 0;
1116    
1117     int start_ndx;
1118     for( i=0; i < (n_cells+1) && !done; i++ ){
1119     for( j=0; j < (n_cells+1) && !done; j++ ){
1120    
1121     if( i < n_cells ){
1122    
1123     if( j < n_cells ){
1124     start_ndx = n_cells;
1125     }
1126     else start_ndx = 0;
1127     }
1128     else start_ndx = 0;
1129    
1130     for( k=start_ndx; k < (n_cells+1) && !done; k++ ){
1131    
1132     makeElement( i * cellx,
1133     j * celly,
1134     k * cellz );
1135     done = ( current_mol >= tot_nmol );
1136    
1137     if( !done && n_per_extra > 1 ){
1138     makeElement( i * cellx + 0.5 * cellx,
1139     j * celly + 0.5 * celly,
1140     k * cellz );
1141     done = ( current_mol >= tot_nmol );
1142     }
1143    
1144     if( !done && n_per_extra > 2){
1145     makeElement( i * cellx,
1146     j * celly + 0.5 * celly,
1147     k * cellz + 0.5 * cellz );
1148     done = ( current_mol >= tot_nmol );
1149     }
1150    
1151     if( !done && n_per_extra > 3){
1152     makeElement( i * cellx + 0.5 * cellx,
1153     j * celly,
1154     k * cellz + 0.5 * cellz );
1155     done = ( current_mol >= tot_nmol );
1156     }
1157     }
1158     }
1159     }
1160     }
1161    
1162    
1163     for( i=0; i<simnfo->n_atoms; i++ ){
1164     simnfo->atoms[i]->set_vx( 0.0 );
1165     simnfo->atoms[i]->set_vy( 0.0 );
1166     simnfo->atoms[i]->set_vz( 0.0 );
1167     }
1168     }
1169    
1170     void SimSetup::makeElement( double x, double y, double z ){
1171    
1172     int k;
1173     AtomStamp* current_atom;
1174     DirectionalAtom* dAtom;
1175     double rotMat[3][3];
1176    
1177     for( k=0; k<comp_stamps[current_comp]->getNAtoms(); k++ ){
1178    
1179     current_atom = comp_stamps[current_comp]->getAtom( k );
1180     if( !current_atom->havePosition() ){
1181     sprintf( painCave.errMsg,
1182     "SimSetup:initFromBass error.\n"
1183     "\tComponent %s, atom %s does not have a position specified.\n"
1184     "\tThe initialization routine is unable to give a start"
1185     " position.\n",
1186     comp_stamps[current_comp]->getID(),
1187     current_atom->getType() );
1188     painCave.isFatal = 1;
1189     simError();
1190     }
1191    
1192     the_atoms[current_atom_ndx]->setX( x + current_atom->getPosX() );
1193     the_atoms[current_atom_ndx]->setY( y + current_atom->getPosY() );
1194     the_atoms[current_atom_ndx]->setZ( z + current_atom->getPosZ() );
1195    
1196     if( the_atoms[current_atom_ndx]->isDirectional() ){
1197    
1198     dAtom = (DirectionalAtom *)the_atoms[current_atom_ndx];
1199    
1200     rotMat[0][0] = 1.0;
1201     rotMat[0][1] = 0.0;
1202     rotMat[0][2] = 0.0;
1203    
1204     rotMat[1][0] = 0.0;
1205     rotMat[1][1] = 1.0;
1206     rotMat[1][2] = 0.0;
1207    
1208     rotMat[2][0] = 0.0;
1209     rotMat[2][1] = 0.0;
1210     rotMat[2][2] = 1.0;
1211    
1212     dAtom->setA( rotMat );
1213     }
1214    
1215     current_atom_ndx++;
1216     }
1217    
1218     current_mol++;
1219     current_comp_mol++;
1220    
1221     if( current_comp_mol >= components_nmol[current_comp] ){
1222    
1223     current_comp_mol = 0;
1224     current_comp++;
1225     }
1226     }