ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/group/trunk/OOPSE/libmdtools/SimSetup.cpp
Revision: 1167
Committed: Wed May 12 16:38:45 2004 UTC (20 years, 11 months ago) by tim
File size: 53659 byte(s)
Log Message:
get rid of rc and massratio from simState, creat cutoff group forevery atom
which does not belong to
cutoff group defined at mdl file

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