ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/group/trunk/OOPSE/libmdtools/SimSetup.cpp
Revision: 466
Committed: Mon Apr 7 14:30:36 2003 UTC (21 years, 3 months ago) by gezelter
File size: 29095 byte(s)
Log Message:
Added ExtendedSystem infrastructure for NPT and NVT calculations

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