ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/group/trunk/OOPSE/libmdtools/SimSetup.cpp
Revision: 572
Committed: Wed Jul 2 21:26:55 2003 UTC (21 years ago) by mmeineke
File size: 32766 byte(s)
Log Message:
fixed the bugs introduced by switching the periodic box to a matrix

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