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

# Content
1 #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 // some defines for ensemble and Forcefield cases
16
17 #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
24
25 #define FF_DUFF 0
26 #define FF_LJ 1
27
28
29 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 int i, j, k, globalAtomIndex;
84
85 // gather all of the information from the Bass file
86
87 gatherInfo();
88
89 // creation of complex system objects
90
91 sysObjectsCreation();
92
93
94
95 // initialize the arrays
96
97
98
99 makeMolecules();
100 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 }
104
105
106 // check on the post processing info
107
108 finalInfoCheck();
109
110
111
112
113 // initialize the system coordinates
114
115 initSystemCoords();
116
117
118 // make the output filenames
119
120 makeOutNames();
121
122
123
124
125
126
127
128
129
130 // make the integrator
131
132
133 NVT* myNVT = NULL;
134 NPTi* myNPTi = NULL;
135 NPTf* myNPTf = NULL;
136 NPTim* myNPTim = NULL;
137 NPTfm* myNPTfm = NULL;
138
139 switch( ensembleCase ){
140
141 case NVE_ENS:
142 new NVE( info, the_ff );
143 break;
144
145 case NVT_ENS:
146 myNVT = new NVT( info, the_ff );
147 myNVT->setTargetTemp(the_globals->getTargetTemp());
148
149 if (the_globals->haveTauThermostat())
150 myNVT->setTauThermostat(the_globals->getTauThermostat());
151
152 else {
153 sprintf( painCave.errMsg,
154 "SimSetup error: If you use the NVT\n"
155 " ensemble, you must set tauThermostat.\n");
156 painCave.isFatal = 1;
157 simError();
158 }
159 break;
160
161 case NPTi_ENS:
162 myNPTi = new NPTi( info, the_ff );
163 myNPTi->setTargetTemp( the_globals->getTargetTemp() );
164
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 myNPTf = new NPTf( info, the_ff );
198 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 case NPTim_ENS:
232 myNPTim = new NPTim( info, the_ff );
233 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
245 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
255 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 case NPTfm_ENS:
267 myNPTfm = new NPTfm( info, the_ff );
268 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
280 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
290 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 default:
302 sprintf( painCave.errMsg,
303 "SimSetup Error. Unrecognized ensemble in case statement.\n");
304 painCave.isFatal = 1;
305 simError();
306 }
307
308
309 #ifdef IS_MPI
310 mpiSim->mpiRefresh();
311 #endif
312
313 // initialize the Fortran
314
315
316 info->refreshSim();
317
318 if( !strcmp( info->mixingRule, "standard") ){
319 the_ff->initForceField( LB_MIXING_RULE );
320 }
321 else if( !strcmp( info->mixingRule, "explicit") ){
322 the_ff->initForceField( EXPLICIT_MIXING_RULE );
323 }
324 else{
325 sprintf( painCave.errMsg,
326 "SimSetup Error: unknown mixing rule -> \"%s\"\n",
327 info->mixingRule );
328 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
341 void SimSetup::makeMolecules( void ){
342
343 int i, j, exI, exJ, tempEx, stampID, atomOffset, excludeOffset;
344 molInit info;
345 DirectionalAtom* dAtom;
346 LinkedAssign* extras;
347 LinkedAssign* current_extra;
348 AtomStamp* currentAtom;
349 BondStamp* currentBond;
350 BendStamp* currentBend;
351 TorsionStamp* currentTorsion;
352
353 bond_pair* theBonds;
354 bend_set* theBends;
355 torsion_set* theTorsions;
356
357
358 //init the forceField paramters
359
360 the_ff->readParams();
361
362
363 // init the atoms
364
365 double ux, uy, uz, u, uSqr;
366
367 atomOffset = 0;
368 excludeOffset = 0;
369 for(i=0; i<info->n_mol; i++){
370
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 info.nExcludes = info.nBonds + info.nBends + info.nTorsions;
378
379 info.myAtoms = &the_atoms[atomOffset];
380 info.myExcludes = &the_excludes[excludeOffset];
381 info.myBonds = new Bond*[info.nBonds];
382 info.myBends = new Bend*[info.nBends];
383 info.myTorsions = new Torsion*[info.nTorsions];
384
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 currentAtom = comp_stamps[stampID]->getAtom( j );
394 if( currentAtom->haveOrientation() ){
395
396 dAtom = new DirectionalAtom(j + atomOffset);
397 info->n_oriented++;
398 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 for(j=0; j<info.nBonds; j++){
429
430 currentBond = comp_stamps[stampID]->getBond( j );
431 theBonds[j].a = currentBond->getA() + atomOffset;
432 theBonds[j].b = currentBond->getB() + atomOffset;
433
434 exI = theBonds[j].a;
435 exJ = theBonds[j].b;
436
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 tempEx = exI;
445 exI = the_atoms[tempEx]->getGlobalIndex() + 1;
446 tempEx = exJ;
447 exJ = the_atoms[tempEx]->getGlobalIndex() + 1;
448
449 the_excludes[j+excludeOffset]->setPair( exI, exJ );
450 #else // isn't MPI
451
452 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
460 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 extras = currentBend->getExtras();
468 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 "SimSetup Error: ghostVectorSource was neither a "
490 "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 #else // isn't MPI
538 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
545 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
554 // 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 #endif //is_mpi
570 }
571 excludeOffset += info.nTorsions;
572
573
574 // send the arrays off to the forceField for init.
575
576 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
581
582 the_molecules[i].initialize( info );
583
584
585 atomOffset += info.nAtoms;
586 delete[] theBonds;
587 delete[] theBends;
588 delete[] theTorsions;
589 }
590
591 #ifdef IS_MPI
592 sprintf( checkPointMsg, "all molecules initialized succesfully" );
593 MPIcheckPoint();
594 #endif // is_mpi
595
596 // clean up the forcefield
597 the_ff->calcRcut();
598 the_ff->cleanMe();
599
600 }
601
602 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 cellx = info->boxLx / temp3;
622 celly = info->boxLy / temp3;
623 cellz = info->boxLz / temp3;
624 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 cellx = info->boxLx / temp3;
639 celly = info->boxLy / temp3;
640 cellz = info->boxLz / temp3;
641 }
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 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 }
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
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 }