ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/group/trunk/OOPSE/libmdtools/SimSetup.cpp
Revision: 1234
Committed: Fri Jun 4 03:15:31 2004 UTC (20 years, 3 months ago) by tim
File size: 62950 byte(s)
Log Message:
new rattle algorithm is working

File Contents

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