ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/group/trunk/OOPSE/libmdtools/SimSetup.cpp
Revision: 782
Committed: Tue Sep 23 20:34:31 2003 UTC (20 years, 9 months ago) by mmeineke
File size: 42171 byte(s)
Log Message:
Removed NPTfm from Integrator.hpp.

Some small syntax cleaning in NPTfm and SimSetup

File Contents

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