ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/group/trunk/OOPSE/libmdtools/SimSetup.cpp
Revision: 429
Committed: Thu Mar 27 21:52:21 2003 UTC (21 years, 3 months ago) by mmeineke
File size: 27653 byte(s)
Log Message:
Fixed a single processor segfault bug.

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