ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/group/trunk/OOPSE/libmdtools/SimSetup.cpp
Revision: 466
Committed: Mon Apr 7 14:30:36 2003 UTC (21 years, 2 months ago) by gezelter
File size: 29095 byte(s)
Log Message:
Added ExtendedSystem infrastructure for NPT and NVT calculations

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