ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/group/trunk/OOPSE/libmdtools/SimSetup.cpp
Revision: 1212
Committed: Tue Jun 1 17:15:43 2004 UTC (20 years, 1 month ago) by chrisfen
File size: 61015 byte(s)
Log Message:
Implemented a separate solid and liquid thermodynamic integration routines

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