ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/group/trunk/OOPSE/libmdtools/SimSetup.cpp
Revision: 469
Committed: Mon Apr 7 20:06:31 2003 UTC (21 years, 2 months ago) by mmeineke
File size: 29248 byte(s)
Log Message:
bug fixes

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