ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/group/trunk/OOPSE/libmdtools/SimSetup.cpp
Revision: 1157
Committed: Tue May 11 20:33:41 2004 UTC (20 years, 11 months ago) by tim
File size: 52617 byte(s)
Log Message:
adding cutoffGroup into OOPSE

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