ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/group/trunk/OOPSE/libmdtools/SimSetup.cpp
Revision: 605
Committed: Tue Jul 15 03:27:24 2003 UTC (20 years, 11 months ago) by gezelter
File size: 37502 byte(s)
Log Message:
Bugfix in NPTim, fixes for NPTfm

File Contents

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