ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/group/trunk/OOPSE/libmdtools/SimInfo.cpp
Revision: 965
Committed: Mon Jan 19 21:17:39 2004 UTC (20 years, 5 months ago) by gezelter
File size: 14251 byte(s)
Log Message:
Made some error messages more user-friendly

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