ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/group/trunk/OOPSE/libmdtools/SimSetup.cpp
Revision: 1129
Committed: Thu Apr 22 03:29:30 2004 UTC (21 years ago) by tim
File size: 51593 byte(s)
Log Message:
fixed two bugs in MPI version of InitfromFile and one unmatch MPI command in DumpWriter

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