ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/group/trunk/OOPSE/libmdtools/SimSetup.cpp
Revision: 1035
Committed: Fri Feb 6 21:37:59 2004 UTC (20 years, 5 months ago) by tim
File size: 48421 byte(s)
Log Message:
Single version of energy minimization for argon is working, need to add constraint

File Contents

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