ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/group/trunk/OOPSE/libmdtools/SimSetup.cpp
Revision: 474
Committed: Mon Apr 7 21:42:19 2003 UTC (21 years, 2 months ago) by gezelter
File size: 29435 byte(s)
Log Message:
Fixes for NPT and NVT

File Contents

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