ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/group/trunk/OOPSE/libmdtools/SimSetup.cpp
Revision: 443
Committed: Wed Apr 2 22:19:03 2003 UTC (21 years, 3 months ago) by mmeineke
File size: 28017 byte(s)
Log Message:
dipoles mostly work, but there is a memory leak somewhere.

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