ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/group/trunk/OOPSE/libmdtools/SimInfo.cpp
Revision: 1158
Committed: Tue May 11 21:14:26 2004 UTC (20 years, 2 months ago) by tim
File size: 14158 byte(s)
Log Message:
fix two bugs in siminfo which cause infinite loop; fix anoter one in CutoffGroup which causes seg fault

File Contents

# Content
1 #include <stdlib.h>
2 #include <string.h>
3 #include <math.h>
4
5 #include <iostream>
6 using namespace std;
7
8 #include "SimInfo.hpp"
9 #define __C
10 #include "fSimulation.h"
11 #include "simError.h"
12
13 #include "fortranWrappers.hpp"
14
15 #include "MatVec3.h"
16
17 #ifdef IS_MPI
18 #include "mpiSimulation.hpp"
19 #endif
20
21 inline double roundMe( double x ){
22 return ( x >= 0 ) ? floor( x + 0.5 ) : ceil( x - 0.5 );
23 }
24
25 inline double min( double a, double b ){
26 return (a < b ) ? a : b;
27 }
28
29 SimInfo* currentInfo;
30
31 SimInfo::SimInfo(){
32
33 n_constraints = 0;
34 nZconstraints = 0;
35 n_oriented = 0;
36 n_dipoles = 0;
37 ndf = 0;
38 ndfRaw = 0;
39 nZconstraints = 0;
40 the_integrator = NULL;
41 setTemp = 0;
42 thermalTime = 0.0;
43 currentTime = 0.0;
44 rCut = 0.0;
45 rSw = 0.0;
46
47 haveRcut = 0;
48 haveRsw = 0;
49 boxIsInit = 0;
50
51 resetTime = 1e99;
52
53 orthoRhombic = 0;
54 orthoTolerance = 1E-6;
55 useInitXSstate = true;
56
57 usePBC = 0;
58 useLJ = 0;
59 useSticky = 0;
60 useCharges = 0;
61 useDipoles = 0;
62 useReactionField = 0;
63 useGB = 0;
64 useEAM = 0;
65
66 haveCutoffGroups = false;
67
68 excludes = Exclude::Instance();
69
70 myConfiguration = new SimState();
71
72 has_minimizer = false;
73 the_minimizer =NULL;
74
75 ngroup = 0;
76
77 wrapMeSimInfo( this );
78 }
79
80
81 SimInfo::~SimInfo(){
82
83 delete myConfiguration;
84
85 map<string, GenericData*>::iterator i;
86
87 for(i = properties.begin(); i != properties.end(); i++)
88 delete (*i).second;
89
90 }
91
92 void SimInfo::setBox(double newBox[3]) {
93
94 int i, j;
95 double tempMat[3][3];
96
97 for(i=0; i<3; i++)
98 for (j=0; j<3; j++) tempMat[i][j] = 0.0;;
99
100 tempMat[0][0] = newBox[0];
101 tempMat[1][1] = newBox[1];
102 tempMat[2][2] = newBox[2];
103
104 setBoxM( tempMat );
105
106 }
107
108 void SimInfo::setBoxM( double theBox[3][3] ){
109
110 int i, j;
111 double FortranHmat[9]; // to preserve compatibility with Fortran the
112 // ordering in the array is as follows:
113 // [ 0 3 6 ]
114 // [ 1 4 7 ]
115 // [ 2 5 8 ]
116 double FortranHmatInv[9]; // the inverted Hmat (for Fortran);
117
118 if( !boxIsInit ) boxIsInit = 1;
119
120 for(i=0; i < 3; i++)
121 for (j=0; j < 3; j++) Hmat[i][j] = theBox[i][j];
122
123 calcBoxL();
124 calcHmatInv();
125
126 for(i=0; i < 3; i++) {
127 for (j=0; j < 3; j++) {
128 FortranHmat[3*j + i] = Hmat[i][j];
129 FortranHmatInv[3*j + i] = HmatInv[i][j];
130 }
131 }
132
133 setFortranBoxSize(FortranHmat, FortranHmatInv, &orthoRhombic);
134
135 }
136
137
138 void SimInfo::getBoxM (double theBox[3][3]) {
139
140 int i, j;
141 for(i=0; i<3; i++)
142 for (j=0; j<3; j++) theBox[i][j] = Hmat[i][j];
143 }
144
145
146 void SimInfo::scaleBox(double scale) {
147 double theBox[3][3];
148 int i, j;
149
150 // cerr << "Scaling box by " << scale << "\n";
151
152 for(i=0; i<3; i++)
153 for (j=0; j<3; j++) theBox[i][j] = Hmat[i][j]*scale;
154
155 setBoxM(theBox);
156
157 }
158
159 void SimInfo::calcHmatInv( void ) {
160
161 int oldOrtho;
162 int i,j;
163 double smallDiag;
164 double tol;
165 double sanity[3][3];
166
167 invertMat3( Hmat, HmatInv );
168
169 // check to see if Hmat is orthorhombic
170
171 oldOrtho = orthoRhombic;
172
173 smallDiag = fabs(Hmat[0][0]);
174 if(smallDiag > fabs(Hmat[1][1])) smallDiag = fabs(Hmat[1][1]);
175 if(smallDiag > fabs(Hmat[2][2])) smallDiag = fabs(Hmat[2][2]);
176 tol = smallDiag * orthoTolerance;
177
178 orthoRhombic = 1;
179
180 for (i = 0; i < 3; i++ ) {
181 for (j = 0 ; j < 3; j++) {
182 if (i != j) {
183 if (orthoRhombic) {
184 if ( fabs(Hmat[i][j]) >= tol) orthoRhombic = 0;
185 }
186 }
187 }
188 }
189
190 if( oldOrtho != orthoRhombic ){
191
192 if( orthoRhombic ){
193 sprintf( painCave.errMsg,
194 "OOPSE is switching from the default Non-Orthorhombic\n"
195 "\tto the faster Orthorhombic periodic boundary computations.\n"
196 "\tThis is usually a good thing, but if you wan't the\n"
197 "\tNon-Orthorhombic computations, make the orthoBoxTolerance\n"
198 "\tvariable ( currently set to %G ) smaller.\n",
199 orthoTolerance);
200 simError();
201 }
202 else {
203 sprintf( painCave.errMsg,
204 "OOPSE is switching from the faster Orthorhombic to the more\n"
205 "\tflexible Non-Orthorhombic periodic boundary computations.\n"
206 "\tThis is usually because the box has deformed under\n"
207 "\tNPTf integration. If you wan't to live on the edge with\n"
208 "\tthe Orthorhombic computations, make the orthoBoxTolerance\n"
209 "\tvariable ( currently set to %G ) larger.\n",
210 orthoTolerance);
211 simError();
212 }
213 }
214 }
215
216 void SimInfo::calcBoxL( void ){
217
218 double dx, dy, dz, dsq;
219
220 // boxVol = Determinant of Hmat
221
222 boxVol = matDet3( Hmat );
223
224 // boxLx
225
226 dx = Hmat[0][0]; dy = Hmat[1][0]; dz = Hmat[2][0];
227 dsq = dx*dx + dy*dy + dz*dz;
228 boxL[0] = sqrt( dsq );
229 //maxCutoff = 0.5 * boxL[0];
230
231 // boxLy
232
233 dx = Hmat[0][1]; dy = Hmat[1][1]; dz = Hmat[2][1];
234 dsq = dx*dx + dy*dy + dz*dz;
235 boxL[1] = sqrt( dsq );
236 //if( (0.5 * boxL[1]) < maxCutoff ) maxCutoff = 0.5 * boxL[1];
237
238
239 // boxLz
240
241 dx = Hmat[0][2]; dy = Hmat[1][2]; dz = Hmat[2][2];
242 dsq = dx*dx + dy*dy + dz*dz;
243 boxL[2] = sqrt( dsq );
244 //if( (0.5 * boxL[2]) < maxCutoff ) maxCutoff = 0.5 * boxL[2];
245
246 //calculate the max cutoff
247 maxCutoff = calcMaxCutOff();
248
249 checkCutOffs();
250
251 }
252
253
254 double SimInfo::calcMaxCutOff(){
255
256 double ri[3], rj[3], rk[3];
257 double rij[3], rjk[3], rki[3];
258 double minDist;
259
260 ri[0] = Hmat[0][0];
261 ri[1] = Hmat[1][0];
262 ri[2] = Hmat[2][0];
263
264 rj[0] = Hmat[0][1];
265 rj[1] = Hmat[1][1];
266 rj[2] = Hmat[2][1];
267
268 rk[0] = Hmat[0][2];
269 rk[1] = Hmat[1][2];
270 rk[2] = Hmat[2][2];
271
272 crossProduct3(ri, rj, rij);
273 distXY = dotProduct3(rk,rij) / norm3(rij);
274
275 crossProduct3(rj,rk, rjk);
276 distYZ = dotProduct3(ri,rjk) / norm3(rjk);
277
278 crossProduct3(rk,ri, rki);
279 distZX = dotProduct3(rj,rki) / norm3(rki);
280
281 minDist = min(min(distXY, distYZ), distZX);
282 return minDist/2;
283
284 }
285
286 void SimInfo::wrapVector( double thePos[3] ){
287
288 int i;
289 double scaled[3];
290
291 if( !orthoRhombic ){
292 // calc the scaled coordinates.
293
294
295 matVecMul3(HmatInv, thePos, scaled);
296
297 for(i=0; i<3; i++)
298 scaled[i] -= roundMe(scaled[i]);
299
300 // calc the wrapped real coordinates from the wrapped scaled coordinates
301
302 matVecMul3(Hmat, scaled, thePos);
303
304 }
305 else{
306 // calc the scaled coordinates.
307
308 for(i=0; i<3; i++)
309 scaled[i] = thePos[i]*HmatInv[i][i];
310
311 // wrap the scaled coordinates
312
313 for(i=0; i<3; i++)
314 scaled[i] -= roundMe(scaled[i]);
315
316 // calc the wrapped real coordinates from the wrapped scaled coordinates
317
318 for(i=0; i<3; i++)
319 thePos[i] = scaled[i]*Hmat[i][i];
320 }
321
322 }
323
324
325 int SimInfo::getNDF(){
326 int ndf_local;
327
328 ndf_local = 0;
329
330 for(int i = 0; i < integrableObjects.size(); i++){
331 ndf_local += 3;
332 if (integrableObjects[i]->isDirectional()) {
333 if (integrableObjects[i]->isLinear())
334 ndf_local += 2;
335 else
336 ndf_local += 3;
337 }
338 }
339
340 // n_constraints is local, so subtract them on each processor:
341
342 ndf_local -= n_constraints;
343
344 #ifdef IS_MPI
345 MPI_Allreduce(&ndf_local,&ndf,1,MPI_INT,MPI_SUM, MPI_COMM_WORLD);
346 #else
347 ndf = ndf_local;
348 #endif
349
350 // nZconstraints is global, as are the 3 COM translations for the
351 // entire system:
352
353 ndf = ndf - 3 - nZconstraints;
354
355 return ndf;
356 }
357
358 int SimInfo::getNDFraw() {
359 int ndfRaw_local;
360
361 // Raw degrees of freedom that we have to set
362 ndfRaw_local = 0;
363
364 for(int i = 0; i < integrableObjects.size(); i++){
365 ndfRaw_local += 3;
366 if (integrableObjects[i]->isDirectional()) {
367 if (integrableObjects[i]->isLinear())
368 ndfRaw_local += 2;
369 else
370 ndfRaw_local += 3;
371 }
372 }
373
374 #ifdef IS_MPI
375 MPI_Allreduce(&ndfRaw_local,&ndfRaw,1,MPI_INT,MPI_SUM, MPI_COMM_WORLD);
376 #else
377 ndfRaw = ndfRaw_local;
378 #endif
379
380 return ndfRaw;
381 }
382
383 int SimInfo::getNDFtranslational() {
384 int ndfTrans_local;
385
386 ndfTrans_local = 3 * integrableObjects.size() - n_constraints;
387
388
389 #ifdef IS_MPI
390 MPI_Allreduce(&ndfTrans_local,&ndfTrans,1,MPI_INT,MPI_SUM, MPI_COMM_WORLD);
391 #else
392 ndfTrans = ndfTrans_local;
393 #endif
394
395 ndfTrans = ndfTrans - 3 - nZconstraints;
396
397 return ndfTrans;
398 }
399
400 int SimInfo::getTotIntegrableObjects() {
401 int nObjs_local;
402 int nObjs;
403
404 nObjs_local = integrableObjects.size();
405
406
407 #ifdef IS_MPI
408 MPI_Allreduce(&nObjs_local,&nObjs,1,MPI_INT,MPI_SUM, MPI_COMM_WORLD);
409 #else
410 nObjs = nObjs_local;
411 #endif
412
413
414 return nObjs;
415 }
416
417 void SimInfo::refreshSim(){
418
419 simtype fInfo;
420 int isError;
421 int n_global;
422 int* excl;
423
424 fInfo.dielect = 0.0;
425
426 if( useDipoles ){
427 if( useReactionField )fInfo.dielect = dielectric;
428 }
429
430 fInfo.SIM_uses_PBC = usePBC;
431 //fInfo.SIM_uses_LJ = 0;
432 fInfo.SIM_uses_LJ = useLJ;
433 fInfo.SIM_uses_sticky = useSticky;
434 //fInfo.SIM_uses_sticky = 0;
435 fInfo.SIM_uses_charges = useCharges;
436 fInfo.SIM_uses_dipoles = useDipoles;
437 //fInfo.SIM_uses_dipoles = 0;
438 fInfo.SIM_uses_RF = useReactionField;
439 //fInfo.SIM_uses_RF = 0;
440 fInfo.SIM_uses_GB = useGB;
441 fInfo.SIM_uses_EAM = useEAM;
442
443 n_exclude = excludes->getSize();
444 excl = excludes->getFortranArray();
445
446 #ifdef IS_MPI
447 n_global = mpiSim->getTotAtoms();
448 #else
449 n_global = n_atoms;
450 #endif
451
452 isError = 0;
453
454 getFortranGroupArray(this, mfact, ngroup, groupList, groupStart);
455 //it may not be a good idea to pass the address of first element in vector
456 //since c++ standard does not require vector to be stored continously in meomory
457 //Most of the compilers will organize the memory of vector continously
458 setFsimulation( &fInfo, &n_global, &n_atoms, identArray, &n_exclude, excl,
459 &nGlobalExcludes, globalExcludes, molMembershipArray,
460 &mfact[0], &ngroup, &groupList[0], &groupStart[0], &isError);
461
462 if( isError ){
463
464 sprintf( painCave.errMsg,
465 "There was an error setting the simulation information in fortran.\n" );
466 painCave.isFatal = 1;
467 simError();
468 }
469
470 #ifdef IS_MPI
471 sprintf( checkPointMsg,
472 "succesfully sent the simulation information to fortran.\n");
473 MPIcheckPoint();
474 #endif // is_mpi
475
476 this->ndf = this->getNDF();
477 this->ndfRaw = this->getNDFraw();
478 this->ndfTrans = this->getNDFtranslational();
479 }
480
481 void SimInfo::setDefaultRcut( double theRcut ){
482
483 haveRcut = 1;
484 rCut = theRcut;
485 rList = rCut + 1.0;
486
487 notifyFortranCutOffs( &rCut, &rSw, &rList );
488 }
489
490 void SimInfo::setDefaultRcut( double theRcut, double theRsw ){
491
492 rSw = theRsw;
493 setDefaultRcut( theRcut );
494 }
495
496
497 void SimInfo::checkCutOffs( void ){
498
499 if( boxIsInit ){
500
501 //we need to check cutOffs against the box
502
503 if( rCut > maxCutoff ){
504 sprintf( painCave.errMsg,
505 "cutoffRadius is too large for the current periodic box.\n"
506 "\tCurrent Value of cutoffRadius = %G at time %G\n "
507 "\tThis is larger than half of at least one of the\n"
508 "\tperiodic box vectors. Right now, the Box matrix is:\n"
509 "\n"
510 "\t[ %G %G %G ]\n"
511 "\t[ %G %G %G ]\n"
512 "\t[ %G %G %G ]\n",
513 rCut, currentTime,
514 Hmat[0][0], Hmat[0][1], Hmat[0][2],
515 Hmat[1][0], Hmat[1][1], Hmat[1][2],
516 Hmat[2][0], Hmat[2][1], Hmat[2][2]);
517 painCave.isFatal = 1;
518 simError();
519 }
520 } else {
521 // initialize this stuff before using it, OK?
522 sprintf( painCave.errMsg,
523 "Trying to check cutoffs without a box.\n"
524 "\tOOPSE should have better programmers than that.\n" );
525 painCave.isFatal = 1;
526 simError();
527 }
528
529 }
530
531 void SimInfo::addProperty(GenericData* prop){
532
533 map<string, GenericData*>::iterator result;
534 result = properties.find(prop->getID());
535
536 //we can't simply use properties[prop->getID()] = prop,
537 //it will cause memory leak if we already contain a propery which has the same name of prop
538
539 if(result != properties.end()){
540
541 delete (*result).second;
542 (*result).second = prop;
543
544 }
545 else{
546
547 properties[prop->getID()] = prop;
548
549 }
550
551 }
552
553 GenericData* SimInfo::getProperty(const string& propName){
554
555 map<string, GenericData*>::iterator result;
556
557 //string lowerCaseName = ();
558
559 result = properties.find(propName);
560
561 if(result != properties.end())
562 return (*result).second;
563 else
564 return NULL;
565 }
566
567
568 void getFortranGroupArray(SimInfo* info, vector<double>& mfact, int& ngroup,
569 vector<int>& groupList, vector<int>& groupStart){
570 Molecule* myMols;
571 Atom** myAtoms;
572 int numAtom;
573 int curIndex;
574 double mtot;
575 int numMol;
576 int numCutoffGroups;
577 CutoffGroup* myCutoffGroup;
578 vector<CutoffGroup*>::iterator iterCutoff;
579 Atom* cutoffAtom;
580 vector<Atom*>::iterator iterAtom;
581 int atomIndex;
582 double totalMass;
583
584 mfact.clear();
585 groupList.clear();
586 groupStart.clear();
587
588 //Be careful, fortran array begin at 1
589 curIndex = 1;
590
591 myMols = info->molecules;
592 numMol = info->n_mol;
593 for(int i = 0; i < numMol; i++){
594 numAtom = myMols[i].getNAtoms();
595 myAtoms = myMols[i].getMyAtoms();
596
597
598 for(int j = 0; j < numAtom; j++){
599
600
601 #ifdef IS_MPI
602 atomIndex = myAtoms[j]->getGlobalIndex();
603 #else
604 atomIndex = myAtoms[j]->getIndex();
605 #endif
606
607 if(myMols[i].belongToCutoffGroup(atomIndex))
608 continue;
609 else{
610 mfact.push_back(myAtoms[j]->getMass());
611 groupList.push_back(myAtoms[j]->getIndex() + 1);
612 groupStart.push_back(curIndex++);
613 }
614 }
615
616 numCutoffGroups = myMols[i].getNCutoffGroups();
617 for(myCutoffGroup =myMols[i].beginCutoffGroup(iterCutoff); myCutoffGroup != NULL;
618 myCutoffGroup =myMols[i].nextCutoffGroup(iterCutoff)){
619
620 totalMass = myCutoffGroup->getMass();
621
622 for(cutoffAtom = myCutoffGroup->beginAtom(iterAtom); cutoffAtom != NULL;
623 cutoffAtom = myCutoffGroup->nextAtom(iterAtom)){
624 mfact.push_back(cutoffAtom->getMass()/totalMass);
625 groupList.push_back(cutoffAtom->getIndex() + 1);
626 }
627
628 groupStart.push_back(curIndex);
629 curIndex += myCutoffGroup->getNumAtom();
630
631 }//end for(myCutoffGroup =myMols[i].beginCutoffGroup(iterCutoff))
632
633 }//end for(int i = 0; i < numMol; i++)
634
635 ngroup = groupStart.size();
636 }