ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/group/trunk/OOPSE/libmdtools/SimInfo.cpp
Revision: 781
Committed: Mon Sep 22 23:07:57 2003 UTC (20 years, 9 months ago) by tim
File size: 14402 byte(s)
Log Message:
fix bug in calculating maxCutoff

File Contents

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