ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/group/trunk/OOPSE/libmdtools/SimSetup.cpp
Revision: 469
Committed: Mon Apr 7 20:06:31 2003 UTC (21 years, 3 months ago) by mmeineke
File size: 29248 byte(s)
Log Message:
bug fixes

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