ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/group/trunk/OOPSE_old/src/mdtools/libmdCode/SimSetup.cpp
Revision: 362
Committed: Tue Mar 18 21:25:45 2003 UTC (21 years, 5 months ago) by mmeineke
File size: 26719 byte(s)
Log Message:
shed implementation of the Fortran interfaces.

File Contents

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