ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/group/trunk/OOPSE/libmdtools/SimSetup.cpp
Revision: 580
Committed: Wed Jul 9 13:56:36 2003 UTC (20 years, 11 months ago) by gezelter
File size: 32896 byte(s)
Log Message:
Fixes and merging NPTf

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