46#define MG_EIGENV_EPS27 1.e-27
47#define MG_EIGENV_EPS13 1.e-13
48#define MG_EIGENV_EPS10 1.e-10
49#define MG_EIGENV_EPS5e6 5.e-06
50#define MG_EIGENV_EPS6 1.e-06
51#define MG_EIGENV_EPS2e6 2.e-06
52#define MG_EIGENV_EPS5 1.e-05
60 ( ((x) == 0.0f) ? (fabs(y) < MG_EIGENV_EPS6) : \
61 ( ((y) == 0.0f) ? (fabs(x) < MG_EIGENV_EPS6) : \
62 (fabs((x)-(y)) / (fabs(x) + fabs(y)) < MG_EIGENV_EPS2e6) ) ) )
67static double Id[3][3] = {
86static int newton3(
double p[4],
double x[3]) {
87 double b,c,d,da,db,dc,epsd;
88 double delta,fx,dfx,dxx;
89 double fdx0,fdx1,dx0,dx1,x1,x2,
tmp,epsA,epsB;
91 static int8_t mmgWarn=0;
96 fprintf(stderr,
"\n ## Warning: %s: bad use of newton3 function, polynomial"
97 " must be of type P(x) = x^3+bx^2+cx+d.\n",
113 delta = db*db - 4.0*da*c;
120 if ( delta > epsd ) {
122 dx0 = (-db + delta) / 6.0;
123 dx1 = (-db - delta) / 6.0;
125 fdx0 = d + dx0*(c+dx0*(b+dx0));
126 fdx1 = d + dx1*(c+dx1*(b+dx1));
138 fx = d + x[2]*(c+x[2]*(b+x[2]));
141 fprintf(stderr,
"\n ## Error: %s: ERR 9100, newton3: fx= %E.\n",
156 fx = d + x[2]*(c+x[2]*(b+x[2]));
159 fprintf(stderr,
"\n ## Error: %s: ERR 9100, newton3: fx= %E.\n",
168 else if ( fabs(delta) < db*db * 1.e-20 ||
169 ( fabs(delta) < epsd && x1 > 0. ) ) {
176 fx = d + x[0]*(c+x[0]*(b+x[0]));
179 fprintf(stderr,
"\n ## Error: %s: ERR 9100, newton3: fx= %E.\n",
189 fprintf(stderr,
"\n ## Error: %s: ERR 9101, newton3: no real roots.\n",
199 fx = d + x1*(c -2.0*x1*x1);
210 fx = d + x2*(c+x2*(b+x2));
211 if ( fabs(fx) < epsA && x2 > 0. ) {
215 dfx = c + x2*(db + da*x2);
218 dxx = fabs((x2-x1) / x2);
219 if ( dxx < epsB && x2 > 0. ) {
225 fprintf(stderr,
"\n ## Error: %s: ERR 9102, newton3, no root found"
239 fx = d + x1*(c+(x1*(b+x1)));
243 fprintf(stderr,
"\n ## Error: %s: ERR 9102, newton3, no root found"
254 delta = db*db - 4.0*dc;
256 if ( delta <= 0.0 ) {
257 fprintf(stderr,
"\n ## Error: %s: ERR 9103, newton3, det = 0.\n",__func__);
262 x[1] = 0.5 * (-db+delta);
263 x[2] = 0.5 * (-db-delta);
265 while ( ++it2 < 5 && ( ( x[0] <= 0 && fabs(x[0]) <=
MG_EIGENV_EPS5 ) ||
276 fx = d + x[1]*(c+x[1]*(b+x[1]));
278 fprintf(stderr,
"\n ## Error: %s: ERR 9104, newton3: fx= %E x= %E.\n",
282 fx = d + x[2]*(c+x[2]*(b+x[2]));
284 fprintf(stderr,
"\n ## Error: %s: ERR 9104, newton3: fx= %E x= %E.\n",
312 double w1[3],
double w2[3],
double w3[3],
313 double maxm,
int order,
int symmat) {
314 double err,tmpx,tmpy,tmpz;
318 if ( !symmat )
return 1;
321 for (i=0; i<3; i++) {
322 for (j=i; j<3; j++) {
323 m[k++] = lambda[0]*v[0][i]*v[0][j]
324 + lambda[1]*v[1][i]*v[1][j]
325 + lambda[2]*v[2][i]*v[2][j];
328 err = fabs(mat[0]-m[0]);
330 if ( fabs(m[i]-mat[i]) > err ) err = fabs(m[i]-mat[i]);
332 if ( err > 1.e03*maxm ) {
333 fprintf(stderr,
"\n ## Error: %s:\nProbleme eigenv3: err= %f\n",__func__,err*maxm);
334 fprintf(stderr,
"\n ## Error: %s:mat depart :\n",__func__);
335 fprintf(stderr,
"\n ## Error: %s:%13.6f %13.6f %13.6f\n",__func__,mat[0],mat[1],mat[2]);
336 fprintf(stderr,
"\n ## Error: %s:%13.6f %13.6f %13.6f\n",__func__,mat[1],mat[3],mat[4]);
337 fprintf(stderr,
"\n ## Error: %s:%13.6f %13.6f %13.6f\n",__func__,mat[2],mat[4],mat[5]);
338 fprintf(stderr,
"\n ## Error: %s:mat finale :\n",__func__);
339 fprintf(stderr,
"\n ## Error: %s:%13.6f %13.6f %13.6f\n",__func__,m[0],m[1],m[2]);
340 fprintf(stderr,
"\n ## Error: %s:%13.6f %13.6f %13.6f\n",__func__,m[1],m[3],m[4]);
341 fprintf(stderr,
"\n ## Error: %s:%13.6f %13.6f %13.6f\n",__func__,m[2],m[4],m[5]);
342 fprintf(stderr,
"\n ## Error: %s:lambda : %f %f %f\n",__func__,lambda[0],lambda[1],lambda[2]);
343 fprintf(stderr,
"\n ## Error: %s: ordre %d\n",__func__,order);
344 fprintf(stderr,
"\n ## Error: %s:\nOrtho:\n",__func__);
345 fprintf(stderr,
"\n ## Error: %s:v1.v2 = %.14f\n",__func__,
346 v[0][0]*v[1][0]+v[0][1]*v[1][1]+ v[0][2]*v[1][2]);
347 fprintf(stderr,
"\n ## Error: %s:v1.v3 = %.14f\n",__func__,
348 v[0][0]*v[2][0]+v[0][1]*v[2][1]+ v[0][2]*v[2][2]);
349 fprintf(stderr,
"\n ## Error: %s:v2.v3 = %.14f\n",__func__,
350 v[1][0]*v[2][0]+v[1][1]*v[2][1]+ v[1][2]*v[2][2]);
352 fprintf(stderr,
"\n ## Error: %s:Consistency\n",__func__);
353 for (i=0; i<3; i++) {
354 tmpx = v[0][i]*m[0] + v[1][i]*m[1]
355 + v[2][i]*m[2] - lambda[i]*v[0][i];
356 tmpy = v[0][i]*m[1] + v[1][i]*m[3]
357 + v[2][i]*m[4] - lambda[i]*v[1][i];
358 tmpz = v[0][i]*m[2] + v[1][i]*m[4]
359 + v[2][i]*m[5] - lambda[i]*v[2][i];
360 fprintf(stderr,
"\n ## Error: %s: Av %d - lambda %d *v %d = %f %f %f\n",
361 __func__,i,i,i,tmpx,tmpy,tmpz);
363 fprintf(stderr,
"\n ## Error: %s:w1 %f %f %f\n",__func__,w1[0],w1[1],w1[2]);
364 fprintf(stderr,
"\n ## Error: %s:w2 %f %f %f\n",__func__,w2[0],w2[1],w2[2]);
365 fprintf(stderr,
"\n ## Error: %s:w3 %f %f %f\n",__func__,w3[0],w3[1],w3[2]);
386 double a11,a12,a13,a21,a22,a23,a31,a32,a33;
387 double aa,bb,cc,dd,ee,ii,vx1[3],vx2[3],vx3[3],dd1,dd2,dd3;
388 double maxd,maxm,valm,p[4],w1[3],w2[3],w3[3],epsd;
393 w1[0] = w1[1] = w1[2] = 0;
394 w2[0] = w2[1] = w2[2] = 0;
395 w3[0] = w3[1] = w3[2] = 0;
397 memcpy(v,
Id,9*
sizeof(
double));
399 lambda[0] = (double)mat[0];
400 lambda[1] = (double)mat[3];
401 lambda[2] = (double)mat[5];
404 for (k=1; k<6; k++) {
406 if ( valm > maxm ) maxm = valm;
410 if ( lambda[0]>0. && lambda[1] > 0. && lambda[2] > 0. ) {
431 if ( valm > maxd ) maxd = valm;
433 if ( valm > maxd ) maxd = valm;
434 if ( maxd < epsd )
return 1;
446 p[0] = a11*bb + a33*(cc-aa) + a22*dd -2.0*a12*a13*a23;
447 p[1] = a11*(a22 + a33) + a22*a33 - bb - cc - dd;
448 p[2] = -a11 - a22 - a33;
452 lambda[0] = (double)mat[0];
453 lambda[1] = (double)mat[4];
454 lambda[2] = (double)mat[8];
457 for (k=1; k<9; k++) {
459 if ( valm > maxm ) maxm = valm;
464 if ( lambda[0]>0. && lambda[1] > 0. && lambda[2] > 0. ) {
488 if ( valm > maxd ) maxd = valm;
490 if ( valm > maxd ) maxd = valm;
492 if ( valm > maxd ) maxd = valm;
494 if ( valm > maxd ) maxd = valm;
496 if ( valm > maxd ) maxd = valm;
497 if ( maxd < epsd )
return 1;
501 aa = a22*a33 - a23*a32;
502 bb = a23*a31 - a21*a33;
503 cc = a21*a32 - a31*a22;
504 ee = a11*a33 - a13*a31;
505 ii = a11*a22 - a12*a21;
507 p[0] = -a11*aa - a12*bb - a13*cc;
509 p[2] = -a11 - a22 - a33;
515 if ( n <= 0 )
return 0;
519 v[0][0] = 1.0; v[0][1] = v[0][2] = 0.0;
520 v[1][1] = 1.0; v[1][0] = v[1][2] = 0.0;
521 v[2][2] = 1.0; v[2][0] = v[2][1] = 0.0;
523 w1[1] = a12; w1[2] = a13;
524 w2[0] = a21; w2[2] = a23;
525 w3[0] = a31; w3[1] = a32;
529 for (k=0; k<3; k++) {
530 w1[0] = a11 - lambda[k];
531 w2[1] = a22 - lambda[k];
532 w3[2] = a33 - lambda[k];
547 dd1 = 1.0 / sqrt(dd1);
548 v[k][0] = vx1[0] * dd1;
549 v[k][1] = vx1[1] * dd1;
550 v[k][2] = vx1[2] * dd1;
553 dd3 = 1.0 / sqrt(dd3);
554 v[k][0] = vx3[0] * dd3;
555 v[k][1] = vx3[1] * dd3;
556 v[k][2] = vx3[2] * dd3;
561 dd2 = 1.0 / sqrt(dd2);
562 v[k][0] = vx2[0] * dd2;
563 v[k][1] = vx2[1] * dd2;
564 v[k][2] = vx2[2] * dd2;
567 dd3 = 1.0 / sqrt(dd3);
568 v[k][0] = vx3[0] * dd3;
569 v[k][1] = vx3[1] * dd3;
570 v[k][2] = vx3[2] * dd3;
582 w1[0] = a11 - lambda[2];
583 w2[1] = a22 - lambda[2];
584 w3[2] = a33 - lambda[2];
606 dd1 = 1.0 / sqrt(dd1);
607 v[2][0] = vx1[0] * dd1;
608 v[2][1] = vx1[1] * dd1;
609 v[2][2] = vx1[2] * dd1;
610 memcpy(z1,w1,3*
sizeof(
double));
611 memcpy(z2,w3,3*
sizeof(
double));
614 dd3 = 1.0 / sqrt(dd3);
615 v[2][0] = vx3[0] * dd3;
616 v[2][1] = vx3[1] * dd3;
617 v[2][2] = vx3[2] * dd3;
618 memcpy(z1,w2,3*
sizeof(
double));
619 memcpy(z2,w3,3*
sizeof(
double));
624 dd2 = 1.0 / sqrt(dd2);
625 v[2][0] = vx2[0] * dd2;
626 v[2][1] = vx2[1] * dd2;
627 v[2][2] = vx2[2] * dd2;
628 memcpy(z1,w1,3*
sizeof(
double));
629 memcpy(z2,w2,3*
sizeof(
double));
632 dd3 = 1.0 / sqrt(dd3);
633 v[2][0] = vx3[0] * dd3;
634 v[2][1] = vx3[1] * dd3;
635 v[2][2] = vx3[2] * dd3;
636 memcpy(z1,w2,3*
sizeof(
double));
637 memcpy(z2,w3,3*
sizeof(
double));
643 dd1 = 1.0 / sqrt(dd1);
648 dd2 = 1.0 / sqrt(dd2);
655 w1[0] = a11 - lambda[0];
656 w2[1] = a22 - lambda[0];
657 w3[2] = a33 - lambda[0];
691 dd1 = 1.0 / sqrt(dd1);
697 dd3 = 1.0 / sqrt(dd3);
705 dd2 = 1.0 / sqrt(dd2);
711 dd3 = 1.0 / sqrt(dd3);
722 dd1 = 1.0 / sqrt(dd1);
732 dd2 = 1.0 / sqrt(dd2);
742 v[1][0] -= dd1*v[0][0];
743 v[1][1] -= dd1*v[0][1];
744 v[1][2] -= dd1*v[0][2];
748 dd2 = 1.0 / sqrt(dd2);
760 if ( getenv(
"MMG_EIGENV_DDEBUG") && symmat ) {
781 double dd,sqDelta,trmat,vnorm;
782 static int8_t mmgWarn0=0;
789 dd = mat[0] - mat[3];
790 sqDelta = sqrt(fabs(dd*dd + 4.0*mat[1]*mat[2]));
791 trmat = mat[0] + mat[3];
793 lambda[0] = 0.5 * (trmat - sqDelta);
794 if ( lambda[0] < 0.0 ) {
797 fprintf(stderr,
"\n ## Warning: %s: at least 1 metric with a "
798 "negative eigenvalue: %f \n",__func__,lambda[0]);
813 lambda[1] = 0.5 * (trmat + sqDelta);
814 assert(lambda[1] >= 0.0);
817 vp[0][1] = (lambda[0] - mat[0]);
818 vnorm = sqrt(vp[0][0]*vp[0][0] + vp[0][1]*vp[0][1]);
821 vp[0][0] = (lambda[0] - mat[3]);
823 vnorm = sqrt(vp[0][0]*vp[0][0] + vp[0][1]*vp[0][1]);
831 vp[1][1] = (lambda[1] - mat[0]);
832 vnorm = sqrt(vp[1][0]*vp[1][0] + vp[1][1]*vp[1][1]);
835 vp[1][0] = (lambda[1] - mat[3]);
837 vnorm = sqrt(vp[1][0]*vp[1][0] + vp[1][1]*vp[1][1]);
859 double m[3],dd,a1,xn,ddeltb,rr1,rr2,ux,uy;
862 memcpy(m,mm,3*
sizeof(
double));
864 if ( fabs(m[1]) > xn ) xn = fabs(m[1]);
865 if ( fabs(m[2]) > xn ) xn = fabs(m[2]);
867 lambda[0] = lambda[1] = 0.0;
879 if (
egal(m[1],0.0) ) {
887 ddeltb = a1*a1 - 4.0 * (m[0]*m[2] - m[1]*m[1]);
889 if ( ddeltb < 0.0 ) {
890 fprintf(stderr,
"\n ## Error: %s: Delta: %f\n",__func__,ddeltb);
893 ddeltb = sqrt(ddeltb);
896 rr1 = 0.5 * sqrt(ddeltb);
899 else if ( a1 < 0.0 ) {
900 rr1 = 0.5 * (-a1 + ddeltb);
901 rr2 = (-m[1]*m[1] + m[0]*m[2]) / rr1;
903 else if ( a1 > 0.0 ) {
904 rr1 = 0.5 * (-a1 - ddeltb);
905 rr2 = (-m[1]*m[1] + m[0]*m[2]) / rr1;
914 lambda[0] = rr1 * xn;
915 lambda[1] = rr2 * xn;
920 if (fabs(lambda[1]) < fabs(lambda[0]) ) {
929 else if ( fabs(a1) < fabs(m[1]) ) {
933 else if ( fabs(a1) > fabs(m[1]) ) {
937 else if ( fabs(lambda[1]) > fabs(lambda[0]) ) {
946 dd = sqrt(ux*ux + uy*uy);
948 if ( fabs(lambda[0]) > fabs(lambda[1]) ) {
958 vp[1][0] = -vp[0][1];
974 double sqDelta,dd,trm,vnorm,maxm,a11,a12,a22;
975 static int ddebug = 0;
977 lambda[0] = lambda[1] = 0.;
978 vp[0][0] = vp[0][1] = vp[1][0] = vp[1][1] = 0.;
981 maxm = fabs( m[1] ) > maxm ? fabs ( m[1] ) : maxm;
982 maxm = fabs( m[2] ) > maxm ? fabs ( m[2] ) : maxm;
985 if ( ddebug ) printf(
" ## Warning:%s: Quasi-null matrix.",__func__);
997 sqDelta = sqrt(dd*dd + 4.0*a12*a12);
998 lambda[0] = 0.5*(trm - sqDelta);
1003 lambda[1] = lambda[0];
1014 vp[0][1] = (lambda[0] - a11);
1015 vnorm = sqrt(vp[0][0]*vp[0][0] + vp[0][1]*vp[0][1]);
1018 vp[0][0] = (lambda[0] - a22);
1020 vnorm = sqrt(vp[0][0]*vp[0][0] + vp[0][1]*vp[0][1]);
1028 vp[1][0] = -vp[0][1];
1029 vp[1][1] = vp[0][0];
1031 lambda[1] = a11*vp[1][0]*vp[1][0] + 2.0*a12*vp[1][0]*vp[1][1]
1032 + a22*vp[1][1]*vp[1][1];
1039 assert ( fabs(vp[0][0]*vp[1][0] + vp[0][1]*vp[1][1]) <=
MG_EIGENV_EPS6 );
int MMG5_eigensym(double m[3], double lambda[2], double vp[2][2])
int MMG5_eigen2(double *mm, double *lambda, double vp[2][2])
Find eigenvalues and vectors of a 2x2 matrix.
int MMG5_eigenv3d(int symmat, double *mat, double lambda[3], double v[3][3])
Find eigenvalues and vectors of a 3x3 matrix.
int MMG5_eigenv2d(int symmat, double *mat, double lambda[2], double vp[2][2])
Find eigenvalues and vectors of a 2x2 matrix.
static double Id[3][3]
Identity matrix.
static int newton3(double p[4], double x[3])
Find root(s) of a polynomial of degree 3.
static int MMG5_check_accuracy(double mat[6], double lambda[3], double v[3][3], double w1[3], double w2[3], double w3[3], double maxm, int order, int symmat)
void MMG5_dotprod(int8_t dim, double *a, double *b, double *result)
void MMG5_crossprod3d(double *a, double *b, double *result)