ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/group/trunk/OOPSE/libmdtools/SimSetup.cpp
Revision: 614
Committed: Tue Jul 15 17:57:04 2003 UTC (20 years, 11 months ago) by mmeineke
File size: 35613 byte(s)
Log Message:
fixed some bugs, Changed entry_plug to info where appropriate

File Contents

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