ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/group/trunk/OOPSE/libmdtools/SimSetup.cpp
Revision: 1139
Committed: Wed Apr 28 22:06:29 2004 UTC (21 years ago) by gezelter
File size: 51663 byte(s)
Log Message:
Adding molecular cutoffs

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 info[i].useMolecularCutoffs = globals->getUseMolecularCutoffs();
915
916
917 }
918
919 //setup seed for random number generator
920 int seedValue;
921
922 if (globals->haveSeed()){
923 seedValue = globals->getSeed();
924
925 if(seedValue / 1E9 == 0){
926 sprintf(painCave.errMsg,
927 "Seed for sprng library should contain at least 9 digits\n"
928 "OOPSE will generate a seed for user\n");
929 painCave.isFatal = 0;
930 simError();
931
932 //using seed generated by system instead of invalid seed set by user
933 #ifndef IS_MPI
934 seedValue = make_sprng_seed();
935 #else
936 if (worldRank == 0){
937 seedValue = make_sprng_seed();
938 }
939 MPI_Bcast(&seedValue, 1, MPI_INT, 0, MPI_COMM_WORLD);
940 #endif
941 }
942 }//end of if branch of globals->haveSeed()
943 else{
944
945 #ifndef IS_MPI
946 seedValue = make_sprng_seed();
947 #else
948 if (worldRank == 0){
949 seedValue = make_sprng_seed();
950 }
951 MPI_Bcast(&seedValue, 1, MPI_INT, 0, MPI_COMM_WORLD);
952 #endif
953 }//end of globals->haveSeed()
954
955 for (int i = 0; i < nInfo; i++){
956 info[i].setSeed(seedValue);
957 }
958
959 #ifdef IS_MPI
960 strcpy(checkPointMsg, "Successfully gathered all information from Bass\n");
961 MPIcheckPoint();
962 #endif // is_mpi
963 }
964
965
966 void SimSetup::finalInfoCheck(void){
967 int index;
968 int usesDipoles;
969 int usesCharges;
970 int i;
971
972 for (i = 0; i < nInfo; i++){
973 // check electrostatic parameters
974
975 index = 0;
976 usesDipoles = 0;
977 while ((index < info[i].n_atoms) && !usesDipoles){
978 usesDipoles = (info[i].atoms[index])->hasDipole();
979 index++;
980 }
981 index = 0;
982 usesCharges = 0;
983 while ((index < info[i].n_atoms) && !usesCharges){
984 usesCharges= (info[i].atoms[index])->hasCharge();
985 index++;
986 }
987 #ifdef IS_MPI
988 int myUse = usesDipoles;
989 MPI_Allreduce(&myUse, &usesDipoles, 1, MPI_INT, MPI_LOR, MPI_COMM_WORLD);
990 #endif //is_mpi
991
992 double theEcr, theEst;
993
994 if (globals->getUseRF()){
995 info[i].useReactionField = 1;
996
997 if (!globals->haveECR()){
998 sprintf(painCave.errMsg,
999 "SimSetup Warning: No value was set for electrostaticCutoffRadius.\n"
1000 "\tOOPSE will use a default value of 15.0 angstroms"
1001 "\tfor the electrostaticCutoffRadius.\n");
1002 painCave.isFatal = 0;
1003 simError();
1004 theEcr = 15.0;
1005 }
1006 else{
1007 theEcr = globals->getECR();
1008 }
1009
1010 if (!globals->haveEST()){
1011 sprintf(painCave.errMsg,
1012 "SimSetup Warning: No value was set for electrostaticSkinThickness.\n"
1013 "\tOOPSE will use a default value of\n"
1014 "\t0.05 * electrostaticCutoffRadius\n"
1015 "\tfor the electrostaticSkinThickness\n");
1016 painCave.isFatal = 0;
1017 simError();
1018 theEst = 0.05 * theEcr;
1019 }
1020 else{
1021 theEst = globals->getEST();
1022 }
1023
1024 info[i].setDefaultEcr(theEcr, theEst);
1025
1026 if (!globals->haveDielectric()){
1027 sprintf(painCave.errMsg,
1028 "SimSetup Error: No Dielectric constant was set.\n"
1029 "\tYou are trying to use Reaction Field without"
1030 "\tsetting a dielectric constant!\n");
1031 painCave.isFatal = 1;
1032 simError();
1033 }
1034 info[i].dielectric = globals->getDielectric();
1035 }
1036 else{
1037 if (usesDipoles || usesCharges){
1038 if (!globals->haveECR()){
1039 sprintf(painCave.errMsg,
1040 "SimSetup Warning: No value was set for electrostaticCutoffRadius.\n"
1041 "\tOOPSE will use a default value of 15.0 angstroms"
1042 "\tfor the electrostaticCutoffRadius.\n");
1043 painCave.isFatal = 0;
1044 simError();
1045 theEcr = 15.0;
1046 }
1047 else{
1048 theEcr = globals->getECR();
1049 }
1050
1051 if (!globals->haveEST()){
1052 sprintf(painCave.errMsg,
1053 "SimSetup Warning: No value was set for electrostaticSkinThickness.\n"
1054 "\tOOPSE will use a default value of\n"
1055 "\t0.05 * electrostaticCutoffRadius\n"
1056 "\tfor the electrostaticSkinThickness\n");
1057 painCave.isFatal = 0;
1058 simError();
1059 theEst = 0.05 * theEcr;
1060 }
1061 else{
1062 theEst = globals->getEST();
1063 }
1064
1065 info[i].setDefaultEcr(theEcr, theEst);
1066 }
1067 }
1068 }
1069 #ifdef IS_MPI
1070 strcpy(checkPointMsg, "post processing checks out");
1071 MPIcheckPoint();
1072 #endif // is_mpi
1073 }
1074
1075 void SimSetup::initSystemCoords(void){
1076 int i;
1077
1078 char* inName;
1079
1080 (info[0].getConfiguration())->createArrays(info[0].n_atoms);
1081
1082 for (i = 0; i < info[0].n_atoms; i++)
1083 info[0].atoms[i]->setCoords();
1084
1085 if (globals->haveInitialConfig()){
1086 InitializeFromFile* fileInit;
1087 #ifdef IS_MPI // is_mpi
1088 if (worldRank == 0){
1089 #endif //is_mpi
1090 inName = globals->getInitialConfig();
1091 fileInit = new InitializeFromFile(inName);
1092 #ifdef IS_MPI
1093 }
1094 else
1095 fileInit = new InitializeFromFile(NULL);
1096 #endif
1097 fileInit->readInit(info); // default velocities on
1098
1099 delete fileInit;
1100 }
1101 else{
1102
1103 // no init from bass
1104
1105 sprintf(painCave.errMsg,
1106 "Cannot intialize a simulation without an initial configuration file.\n");
1107 painCave.isFatal = 1;;
1108 simError();
1109
1110 }
1111
1112 #ifdef IS_MPI
1113 strcpy(checkPointMsg, "Successfully read in the initial configuration");
1114 MPIcheckPoint();
1115 #endif // is_mpi
1116 }
1117
1118
1119 void SimSetup::makeOutNames(void){
1120 int k;
1121
1122
1123 for (k = 0; k < nInfo; k++){
1124 #ifdef IS_MPI
1125 if (worldRank == 0){
1126 #endif // is_mpi
1127
1128 if (globals->haveFinalConfig()){
1129 strcpy(info[k].finalName, globals->getFinalConfig());
1130 }
1131 else{
1132 strcpy(info[k].finalName, inFileName);
1133 char* endTest;
1134 int nameLength = strlen(info[k].finalName);
1135 endTest = &(info[k].finalName[nameLength - 5]);
1136 if (!strcmp(endTest, ".bass")){
1137 strcpy(endTest, ".eor");
1138 }
1139 else if (!strcmp(endTest, ".BASS")){
1140 strcpy(endTest, ".eor");
1141 }
1142 else{
1143 endTest = &(info[k].finalName[nameLength - 4]);
1144 if (!strcmp(endTest, ".bss")){
1145 strcpy(endTest, ".eor");
1146 }
1147 else if (!strcmp(endTest, ".mdl")){
1148 strcpy(endTest, ".eor");
1149 }
1150 else{
1151 strcat(info[k].finalName, ".eor");
1152 }
1153 }
1154 }
1155
1156 // make the sample and status out names
1157
1158 strcpy(info[k].sampleName, inFileName);
1159 char* endTest;
1160 int nameLength = strlen(info[k].sampleName);
1161 endTest = &(info[k].sampleName[nameLength - 5]);
1162 if (!strcmp(endTest, ".bass")){
1163 strcpy(endTest, ".dump");
1164 }
1165 else if (!strcmp(endTest, ".BASS")){
1166 strcpy(endTest, ".dump");
1167 }
1168 else{
1169 endTest = &(info[k].sampleName[nameLength - 4]);
1170 if (!strcmp(endTest, ".bss")){
1171 strcpy(endTest, ".dump");
1172 }
1173 else if (!strcmp(endTest, ".mdl")){
1174 strcpy(endTest, ".dump");
1175 }
1176 else{
1177 strcat(info[k].sampleName, ".dump");
1178 }
1179 }
1180
1181 strcpy(info[k].statusName, inFileName);
1182 nameLength = strlen(info[k].statusName);
1183 endTest = &(info[k].statusName[nameLength - 5]);
1184 if (!strcmp(endTest, ".bass")){
1185 strcpy(endTest, ".stat");
1186 }
1187 else if (!strcmp(endTest, ".BASS")){
1188 strcpy(endTest, ".stat");
1189 }
1190 else{
1191 endTest = &(info[k].statusName[nameLength - 4]);
1192 if (!strcmp(endTest, ".bss")){
1193 strcpy(endTest, ".stat");
1194 }
1195 else if (!strcmp(endTest, ".mdl")){
1196 strcpy(endTest, ".stat");
1197 }
1198 else{
1199 strcat(info[k].statusName, ".stat");
1200 }
1201 }
1202
1203 #ifdef IS_MPI
1204
1205 }
1206 #endif // is_mpi
1207 }
1208 }
1209
1210
1211 void SimSetup::sysObjectsCreation(void){
1212 int i, k;
1213
1214 // create the forceField
1215
1216 createFF();
1217
1218 // extract componentList
1219
1220 compList();
1221
1222 // calc the number of atoms, bond, bends, and torsions
1223
1224 calcSysValues();
1225
1226 #ifdef IS_MPI
1227 // divide the molecules among the processors
1228
1229 mpiMolDivide();
1230 #endif //is_mpi
1231
1232 // create the atom and SRI arrays. Also initialize Molecule Stamp ID's
1233
1234 makeSysArrays();
1235
1236 // make and initialize the molecules (all but atomic coordinates)
1237
1238 makeMolecules();
1239
1240 for (k = 0; k < nInfo; k++){
1241 info[k].identArray = new int[info[k].n_atoms];
1242 for (i = 0; i < info[k].n_atoms; i++){
1243 info[k].identArray[i] = info[k].atoms[i]->getIdent();
1244 }
1245 }
1246 }
1247
1248
1249 void SimSetup::createFF(void){
1250 switch (ffCase){
1251 case FF_DUFF:
1252 the_ff = new DUFF();
1253 break;
1254
1255 case FF_LJ:
1256 the_ff = new LJFF();
1257 break;
1258
1259 case FF_EAM:
1260 the_ff = new EAM_FF();
1261 break;
1262
1263 case FF_H2O:
1264 the_ff = new WATER();
1265 break;
1266
1267 default:
1268 sprintf(painCave.errMsg,
1269 "SimSetup Error. Unrecognized force field in case statement.\n");
1270 painCave.isFatal = 1;
1271 simError();
1272 }
1273
1274 #ifdef IS_MPI
1275 strcpy(checkPointMsg, "ForceField creation successful");
1276 MPIcheckPoint();
1277 #endif // is_mpi
1278 }
1279
1280
1281 void SimSetup::compList(void){
1282 int i;
1283 char* id;
1284 LinkedMolStamp* headStamp = new LinkedMolStamp();
1285 LinkedMolStamp* currentStamp = NULL;
1286 comp_stamps = new MoleculeStamp * [n_components];
1287
1288 // make an array of molecule stamps that match the components used.
1289 // also extract the used stamps out into a separate linked list
1290
1291 for (i = 0; i < nInfo; i++){
1292 info[i].nComponents = n_components;
1293 info[i].componentsNmol = components_nmol;
1294 info[i].compStamps = comp_stamps;
1295 info[i].headStamp = headStamp;
1296 }
1297
1298
1299 for (i = 0; i < n_components; i++){
1300 id = the_components[i]->getType();
1301 comp_stamps[i] = NULL;
1302
1303 // check to make sure the component isn't already in the list
1304
1305 comp_stamps[i] = headStamp->match(id);
1306 if (comp_stamps[i] == NULL){
1307 // extract the component from the list;
1308
1309 currentStamp = stamps->extractMolStamp(id);
1310 if (currentStamp == NULL){
1311 sprintf(painCave.errMsg,
1312 "SimSetup error: Component \"%s\" was not found in the "
1313 "list of declared molecules\n",
1314 id);
1315 painCave.isFatal = 1;
1316 simError();
1317 }
1318
1319 headStamp->add(currentStamp);
1320 comp_stamps[i] = headStamp->match(id);
1321 }
1322 }
1323
1324 #ifdef IS_MPI
1325 strcpy(checkPointMsg, "Component stamps successfully extracted\n");
1326 MPIcheckPoint();
1327 #endif // is_mpi
1328 }
1329
1330 void SimSetup::calcSysValues(void){
1331 int i;
1332
1333 int* molMembershipArray;
1334
1335 tot_atoms = 0;
1336 tot_bonds = 0;
1337 tot_bends = 0;
1338 tot_torsions = 0;
1339 tot_rigid = 0;
1340 for (i = 0; i < n_components; i++){
1341 tot_atoms += components_nmol[i] * comp_stamps[i]->getNAtoms();
1342 tot_bonds += components_nmol[i] * comp_stamps[i]->getNBonds();
1343 tot_bends += components_nmol[i] * comp_stamps[i]->getNBends();
1344 tot_torsions += components_nmol[i] * comp_stamps[i]->getNTorsions();
1345 tot_rigid += components_nmol[i] * comp_stamps[i]->getNRigidBodies();
1346 }
1347
1348 tot_SRI = tot_bonds + tot_bends + tot_torsions;
1349 molMembershipArray = new int[tot_atoms];
1350
1351 for (i = 0; i < nInfo; i++){
1352 info[i].n_atoms = tot_atoms;
1353 info[i].n_bonds = tot_bonds;
1354 info[i].n_bends = tot_bends;
1355 info[i].n_torsions = tot_torsions;
1356 info[i].n_SRI = tot_SRI;
1357 info[i].n_mol = tot_nmol;
1358
1359 info[i].molMembershipArray = molMembershipArray;
1360 }
1361 }
1362
1363 #ifdef IS_MPI
1364
1365 void SimSetup::mpiMolDivide(void){
1366 int i, j, k;
1367 int localMol, allMol;
1368 int local_atoms, local_bonds, local_bends, local_torsions, local_SRI;
1369 int local_rigid;
1370 vector<int> globalMolIndex;
1371
1372 mpiSim = new mpiSimulation(info);
1373
1374 mpiSim->divideLabor();
1375 globalAtomIndex = mpiSim->getGlobalAtomIndex();
1376 //globalMolIndex = mpiSim->getGlobalMolIndex();
1377
1378 // set up the local variables
1379
1380 mol2proc = mpiSim->getMolToProcMap();
1381 molCompType = mpiSim->getMolComponentType();
1382
1383 allMol = 0;
1384 localMol = 0;
1385 local_atoms = 0;
1386 local_bonds = 0;
1387 local_bends = 0;
1388 local_torsions = 0;
1389 local_rigid = 0;
1390 globalAtomCounter = 0;
1391
1392 for (i = 0; i < n_components; i++){
1393 for (j = 0; j < components_nmol[i]; j++){
1394 if (mol2proc[allMol] == worldRank){
1395 local_atoms += comp_stamps[i]->getNAtoms();
1396 local_bonds += comp_stamps[i]->getNBonds();
1397 local_bends += comp_stamps[i]->getNBends();
1398 local_torsions += comp_stamps[i]->getNTorsions();
1399 local_rigid += comp_stamps[i]->getNRigidBodies();
1400 localMol++;
1401 }
1402 for (k = 0; k < comp_stamps[i]->getNAtoms(); k++){
1403 info[0].molMembershipArray[globalAtomCounter] = allMol;
1404 globalAtomCounter++;
1405 }
1406
1407 allMol++;
1408 }
1409 }
1410 local_SRI = local_bonds + local_bends + local_torsions;
1411
1412 info[0].n_atoms = mpiSim->getMyNlocal();
1413
1414
1415 if (local_atoms != info[0].n_atoms){
1416 sprintf(painCave.errMsg,
1417 "SimSetup error: mpiSim's localAtom (%d) and SimSetup's\n"
1418 "\tlocalAtom (%d) are not equal.\n",
1419 info[0].n_atoms, local_atoms);
1420 painCave.isFatal = 1;
1421 simError();
1422 }
1423
1424 info[0].n_bonds = local_bonds;
1425 info[0].n_bends = local_bends;
1426 info[0].n_torsions = local_torsions;
1427 info[0].n_SRI = local_SRI;
1428 info[0].n_mol = localMol;
1429
1430 strcpy(checkPointMsg, "Passed nlocal consistency check.");
1431 MPIcheckPoint();
1432 }
1433
1434 #endif // is_mpi
1435
1436
1437 void SimSetup::makeSysArrays(void){
1438
1439 #ifndef IS_MPI
1440 int k, j;
1441 #endif // is_mpi
1442 int i, l;
1443
1444 Atom** the_atoms;
1445 Molecule* the_molecules;
1446
1447 for (l = 0; l < nInfo; l++){
1448 // create the atom and short range interaction arrays
1449
1450 the_atoms = new Atom * [info[l].n_atoms];
1451 the_molecules = new Molecule[info[l].n_mol];
1452 int molIndex;
1453
1454 // initialize the molecule's stampID's
1455
1456 #ifdef IS_MPI
1457
1458
1459 molIndex = 0;
1460 for (i = 0; i < mpiSim->getTotNmol(); i++){
1461 if (mol2proc[i] == worldRank){
1462 the_molecules[molIndex].setStampID(molCompType[i]);
1463 the_molecules[molIndex].setMyIndex(molIndex);
1464 the_molecules[molIndex].setGlobalIndex(i);
1465 molIndex++;
1466 }
1467 }
1468
1469 #else // is_mpi
1470
1471 molIndex = 0;
1472 globalAtomCounter = 0;
1473 for (i = 0; i < n_components; i++){
1474 for (j = 0; j < components_nmol[i]; j++){
1475 the_molecules[molIndex].setStampID(i);
1476 the_molecules[molIndex].setMyIndex(molIndex);
1477 the_molecules[molIndex].setGlobalIndex(molIndex);
1478 for (k = 0; k < comp_stamps[i]->getNAtoms(); k++){
1479 info[l].molMembershipArray[globalAtomCounter] = molIndex;
1480 globalAtomCounter++;
1481 }
1482 molIndex++;
1483 }
1484 }
1485
1486
1487 #endif // is_mpi
1488
1489 info[l].globalExcludes = new int;
1490 info[l].globalExcludes[0] = 0;
1491
1492 // set the arrays into the SimInfo object
1493
1494 info[l].atoms = the_atoms;
1495 info[l].molecules = the_molecules;
1496 info[l].nGlobalExcludes = 0;
1497
1498 the_ff->setSimInfo(info);
1499 }
1500 }
1501
1502 void SimSetup::makeIntegrator(void){
1503 int k;
1504
1505 NVE<RealIntegrator>* myNVE = NULL;
1506 NVT<RealIntegrator>* myNVT = NULL;
1507 NPTi<NPT<RealIntegrator> >* myNPTi = NULL;
1508 NPTf<NPT<RealIntegrator> >* myNPTf = NULL;
1509 NPTxyz<NPT<RealIntegrator> >* myNPTxyz = NULL;
1510
1511 for (k = 0; k < nInfo; k++){
1512 switch (ensembleCase){
1513 case NVE_ENS:
1514 if (globals->haveZconstraints()){
1515 setupZConstraint(info[k]);
1516 myNVE = new ZConstraint<NVE<RealIntegrator> >(&(info[k]), the_ff);
1517 }
1518 else{
1519 myNVE = new NVE<RealIntegrator>(&(info[k]), the_ff);
1520 }
1521
1522 info->the_integrator = myNVE;
1523 break;
1524
1525 case NVT_ENS:
1526 if (globals->haveZconstraints()){
1527 setupZConstraint(info[k]);
1528 myNVT = new ZConstraint<NVT<RealIntegrator> >(&(info[k]), the_ff);
1529 }
1530 else
1531 myNVT = new NVT<RealIntegrator>(&(info[k]), the_ff);
1532
1533 myNVT->setTargetTemp(globals->getTargetTemp());
1534
1535 if (globals->haveTauThermostat())
1536 myNVT->setTauThermostat(globals->getTauThermostat());
1537 else{
1538 sprintf(painCave.errMsg,
1539 "SimSetup error: If you use the NVT\n"
1540 "\tensemble, you must set tauThermostat.\n");
1541 painCave.isFatal = 1;
1542 simError();
1543 }
1544
1545 info->the_integrator = myNVT;
1546 break;
1547
1548 case NPTi_ENS:
1549 if (globals->haveZconstraints()){
1550 setupZConstraint(info[k]);
1551 myNPTi = new ZConstraint<NPTi<NPT <RealIntegrator> > >(&(info[k]), the_ff);
1552 }
1553 else
1554 myNPTi = new NPTi<NPT<RealIntegrator> >(&(info[k]), the_ff);
1555
1556 myNPTi->setTargetTemp(globals->getTargetTemp());
1557
1558 if (globals->haveTargetPressure())
1559 myNPTi->setTargetPressure(globals->getTargetPressure());
1560 else{
1561 sprintf(painCave.errMsg,
1562 "SimSetup error: If you use a constant pressure\n"
1563 "\tensemble, you must set targetPressure in the BASS file.\n");
1564 painCave.isFatal = 1;
1565 simError();
1566 }
1567
1568 if (globals->haveTauThermostat())
1569 myNPTi->setTauThermostat(globals->getTauThermostat());
1570 else{
1571 sprintf(painCave.errMsg,
1572 "SimSetup error: If you use an NPT\n"
1573 "\tensemble, you must set tauThermostat.\n");
1574 painCave.isFatal = 1;
1575 simError();
1576 }
1577
1578 if (globals->haveTauBarostat())
1579 myNPTi->setTauBarostat(globals->getTauBarostat());
1580 else{
1581 sprintf(painCave.errMsg,
1582 "SimSetup error: If you use an NPT\n"
1583 "\tensemble, you must set tauBarostat.\n");
1584 painCave.isFatal = 1;
1585 simError();
1586 }
1587
1588 info->the_integrator = myNPTi;
1589 break;
1590
1591 case NPTf_ENS:
1592 if (globals->haveZconstraints()){
1593 setupZConstraint(info[k]);
1594 myNPTf = new ZConstraint<NPTf<NPT <RealIntegrator> > >(&(info[k]), the_ff);
1595 }
1596 else
1597 myNPTf = new NPTf<NPT <RealIntegrator> >(&(info[k]), the_ff);
1598
1599 myNPTf->setTargetTemp(globals->getTargetTemp());
1600
1601 if (globals->haveTargetPressure())
1602 myNPTf->setTargetPressure(globals->getTargetPressure());
1603 else{
1604 sprintf(painCave.errMsg,
1605 "SimSetup error: If you use a constant pressure\n"
1606 "\tensemble, you must set targetPressure in the BASS file.\n");
1607 painCave.isFatal = 1;
1608 simError();
1609 }
1610
1611 if (globals->haveTauThermostat())
1612 myNPTf->setTauThermostat(globals->getTauThermostat());
1613
1614 else{
1615 sprintf(painCave.errMsg,
1616 "SimSetup error: If you use an NPT\n"
1617 "\tensemble, you must set tauThermostat.\n");
1618 painCave.isFatal = 1;
1619 simError();
1620 }
1621
1622 if (globals->haveTauBarostat())
1623 myNPTf->setTauBarostat(globals->getTauBarostat());
1624
1625 else{
1626 sprintf(painCave.errMsg,
1627 "SimSetup error: If you use an NPT\n"
1628 "\tensemble, you must set tauBarostat.\n");
1629 painCave.isFatal = 1;
1630 simError();
1631 }
1632
1633 info->the_integrator = myNPTf;
1634 break;
1635
1636 case NPTxyz_ENS:
1637 if (globals->haveZconstraints()){
1638 setupZConstraint(info[k]);
1639 myNPTxyz = new ZConstraint<NPTxyz<NPT <RealIntegrator> > >(&(info[k]), the_ff);
1640 }
1641 else
1642 myNPTxyz = new NPTxyz<NPT <RealIntegrator> >(&(info[k]), the_ff);
1643
1644 myNPTxyz->setTargetTemp(globals->getTargetTemp());
1645
1646 if (globals->haveTargetPressure())
1647 myNPTxyz->setTargetPressure(globals->getTargetPressure());
1648 else{
1649 sprintf(painCave.errMsg,
1650 "SimSetup error: If you use a constant pressure\n"
1651 "\tensemble, you must set targetPressure in the BASS file.\n");
1652 painCave.isFatal = 1;
1653 simError();
1654 }
1655
1656 if (globals->haveTauThermostat())
1657 myNPTxyz->setTauThermostat(globals->getTauThermostat());
1658 else{
1659 sprintf(painCave.errMsg,
1660 "SimSetup error: If you use an NPT\n"
1661 "\tensemble, you must set tauThermostat.\n");
1662 painCave.isFatal = 1;
1663 simError();
1664 }
1665
1666 if (globals->haveTauBarostat())
1667 myNPTxyz->setTauBarostat(globals->getTauBarostat());
1668 else{
1669 sprintf(painCave.errMsg,
1670 "SimSetup error: If you use an NPT\n"
1671 "\tensemble, you must set tauBarostat.\n");
1672 painCave.isFatal = 1;
1673 simError();
1674 }
1675
1676 info->the_integrator = myNPTxyz;
1677 break;
1678
1679 default:
1680 sprintf(painCave.errMsg,
1681 "SimSetup Error. Unrecognized ensemble in case statement.\n");
1682 painCave.isFatal = 1;
1683 simError();
1684 }
1685 }
1686 }
1687
1688 void SimSetup::initFortran(void){
1689 info[0].refreshSim();
1690
1691 if (!strcmp(info[0].mixingRule, "standard")){
1692 the_ff->initForceField(LB_MIXING_RULE);
1693 }
1694 else if (!strcmp(info[0].mixingRule, "explicit")){
1695 the_ff->initForceField(EXPLICIT_MIXING_RULE);
1696 }
1697 else{
1698 sprintf(painCave.errMsg, "SimSetup Error: unknown mixing rule -> \"%s\"\n",
1699 info[0].mixingRule);
1700 painCave.isFatal = 1;
1701 simError();
1702 }
1703
1704
1705 #ifdef IS_MPI
1706 strcpy(checkPointMsg, "Successfully intialized the mixingRule for Fortran.");
1707 MPIcheckPoint();
1708 #endif // is_mpi
1709 }
1710
1711 void SimSetup::setupZConstraint(SimInfo& theInfo){
1712 int nZConstraints;
1713 ZconStamp** zconStamp;
1714
1715 if (globals->haveZconstraintTime()){
1716 //add sample time of z-constraint into SimInfo's property list
1717 DoubleData* zconsTimeProp = new DoubleData();
1718 zconsTimeProp->setID(ZCONSTIME_ID);
1719 zconsTimeProp->setData(globals->getZconsTime());
1720 theInfo.addProperty(zconsTimeProp);
1721 }
1722 else{
1723 sprintf(painCave.errMsg,
1724 "ZConstraint error: If you use a ZConstraint,\n"
1725 "\tyou must set zconsTime.\n");
1726 painCave.isFatal = 1;
1727 simError();
1728 }
1729
1730 //push zconsTol into siminfo, if user does not specify
1731 //value for zconsTol, a default value will be used
1732 DoubleData* zconsTol = new DoubleData();
1733 zconsTol->setID(ZCONSTOL_ID);
1734 if (globals->haveZconsTol()){
1735 zconsTol->setData(globals->getZconsTol());
1736 }
1737 else{
1738 double defaultZConsTol = 0.01;
1739 sprintf(painCave.errMsg,
1740 "ZConstraint Warning: Tolerance for z-constraint method is not specified.\n"
1741 "\tOOPSE will use a default value of %f.\n"
1742 "\tTo set the tolerance, use the zconsTol variable.\n",
1743 defaultZConsTol);
1744 painCave.isFatal = 0;
1745 simError();
1746
1747 zconsTol->setData(defaultZConsTol);
1748 }
1749 theInfo.addProperty(zconsTol);
1750
1751 //set Force Subtraction Policy
1752 StringData* zconsForcePolicy = new StringData();
1753 zconsForcePolicy->setID(ZCONSFORCEPOLICY_ID);
1754
1755 if (globals->haveZconsForcePolicy()){
1756 zconsForcePolicy->setData(globals->getZconsForcePolicy());
1757 }
1758 else{
1759 sprintf(painCave.errMsg,
1760 "ZConstraint Warning: No force subtraction policy was set.\n"
1761 "\tOOPSE will use PolicyByMass.\n"
1762 "\tTo set the policy, use the zconsForcePolicy variable.\n");
1763 painCave.isFatal = 0;
1764 simError();
1765 zconsForcePolicy->setData("BYMASS");
1766 }
1767
1768 theInfo.addProperty(zconsForcePolicy);
1769
1770 //set zcons gap
1771 DoubleData* zconsGap = new DoubleData();
1772 zconsGap->setID(ZCONSGAP_ID);
1773
1774 if (globals->haveZConsGap()){
1775 zconsGap->setData(globals->getZconsGap());
1776 theInfo.addProperty(zconsGap);
1777 }
1778
1779 //set zcons fixtime
1780 DoubleData* zconsFixtime = new DoubleData();
1781 zconsFixtime->setID(ZCONSFIXTIME_ID);
1782
1783 if (globals->haveZConsFixTime()){
1784 zconsFixtime->setData(globals->getZconsFixtime());
1785 theInfo.addProperty(zconsFixtime);
1786 }
1787
1788 //set zconsUsingSMD
1789 IntData* zconsUsingSMD = new IntData();
1790 zconsUsingSMD->setID(ZCONSUSINGSMD_ID);
1791
1792 if (globals->haveZConsUsingSMD()){
1793 zconsUsingSMD->setData(globals->getZconsUsingSMD());
1794 theInfo.addProperty(zconsUsingSMD);
1795 }
1796
1797 //Determine the name of ouput file and add it into SimInfo's property list
1798 //Be careful, do not use inFileName, since it is a pointer which
1799 //point to a string at master node, and slave nodes do not contain that string
1800
1801 string zconsOutput(theInfo.finalName);
1802
1803 zconsOutput = zconsOutput.substr(0, zconsOutput.rfind(".")) + ".fz";
1804
1805 StringData* zconsFilename = new StringData();
1806 zconsFilename->setID(ZCONSFILENAME_ID);
1807 zconsFilename->setData(zconsOutput);
1808
1809 theInfo.addProperty(zconsFilename);
1810
1811 //setup index, pos and other parameters of z-constraint molecules
1812 nZConstraints = globals->getNzConstraints();
1813 theInfo.nZconstraints = nZConstraints;
1814
1815 zconStamp = globals->getZconStamp();
1816 ZConsParaItem tempParaItem;
1817
1818 ZConsParaData* zconsParaData = new ZConsParaData();
1819 zconsParaData->setID(ZCONSPARADATA_ID);
1820
1821 for (int i = 0; i < nZConstraints; i++){
1822 tempParaItem.havingZPos = zconStamp[i]->haveZpos();
1823 tempParaItem.zPos = zconStamp[i]->getZpos();
1824 tempParaItem.zconsIndex = zconStamp[i]->getMolIndex();
1825 tempParaItem.kRatio = zconStamp[i]->getKratio();
1826 tempParaItem.havingCantVel = zconStamp[i]->haveCantVel();
1827 tempParaItem.cantVel = zconStamp[i]->getCantVel();
1828 zconsParaData->addItem(tempParaItem);
1829 }
1830
1831 //check the uniqueness of index
1832 if(!zconsParaData->isIndexUnique()){
1833 sprintf(painCave.errMsg,
1834 "ZConstraint Error: molIndex is not unique!\n");
1835 painCave.isFatal = 1;
1836 simError();
1837 }
1838
1839 //sort the parameters by index of molecules
1840 zconsParaData->sortByIndex();
1841
1842 //push data into siminfo, therefore, we can retrieve later
1843 theInfo.addProperty(zconsParaData);
1844 }
1845
1846 void SimSetup::makeMinimizer(){
1847
1848 OOPSEMinimizer* myOOPSEMinimizer;
1849 MinimizerParameterSet* param;
1850 char minimizerName[100];
1851
1852 for (int i = 0; i < nInfo; i++){
1853
1854 //prepare parameter set for minimizer
1855 param = new MinimizerParameterSet();
1856 param->setDefaultParameter();
1857
1858 if (globals->haveMinimizer()){
1859 param->setFTol(globals->getMinFTol());
1860 }
1861
1862 if (globals->haveMinGTol()){
1863 param->setGTol(globals->getMinGTol());
1864 }
1865
1866 if (globals->haveMinMaxIter()){
1867 param->setMaxIteration(globals->getMinMaxIter());
1868 }
1869
1870 if (globals->haveMinWriteFrq()){
1871 param->setMaxIteration(globals->getMinMaxIter());
1872 }
1873
1874 if (globals->haveMinWriteFrq()){
1875 param->setWriteFrq(globals->getMinWriteFrq());
1876 }
1877
1878 if (globals->haveMinStepSize()){
1879 param->setStepSize(globals->getMinStepSize());
1880 }
1881
1882 if (globals->haveMinLSMaxIter()){
1883 param->setLineSearchMaxIteration(globals->getMinLSMaxIter());
1884 }
1885
1886 if (globals->haveMinLSTol()){
1887 param->setLineSearchTol(globals->getMinLSTol());
1888 }
1889
1890 strcpy(minimizerName, globals->getMinimizer());
1891
1892 if (!strcasecmp(minimizerName, "CG")){
1893 myOOPSEMinimizer = new PRCGMinimizer(&(info[i]), the_ff, param);
1894 }
1895 else if (!strcasecmp(minimizerName, "SD")){
1896 //myOOPSEMinimizer = MinimizerFactory.creatMinimizer("", &(info[i]), the_ff, param);
1897 myOOPSEMinimizer = new SDMinimizer(&(info[i]), the_ff, param);
1898 }
1899 else{
1900 sprintf(painCave.errMsg,
1901 "SimSetup error: Unrecognized Minimizer, use Conjugate Gradient \n");
1902 painCave.isFatal = 0;
1903 simError();
1904
1905 myOOPSEMinimizer = new PRCGMinimizer(&(info[i]), the_ff, param);
1906 }
1907 info[i].the_integrator = myOOPSEMinimizer;
1908
1909 //store the minimizer into simInfo
1910 info[i].the_minimizer = myOOPSEMinimizer;
1911 info[i].has_minimizer = true;
1912 }
1913
1914 }