[3913] | 1 | #include <cstdio>
|
---|
| 2 | #include <cstring>
|
---|
| 3 | #include <cmath>
|
---|
| 4 | #include <ctime>
|
---|
| 5 |
|
---|
| 6 | #include "Metric.h"
|
---|
[15067] | 7 | #include "../shared/shared.h"
|
---|
[3913] | 8 |
|
---|
| 9 | namespace bamg {
|
---|
| 10 |
|
---|
| 11 | /*Constructor*/
|
---|
[18064] | 12 | EigenMetric::EigenMetric(const Metric& M){/*{{{*/
|
---|
[5397] | 13 | /*From a metric (a11,a21,a22), get eigen values lambda1 and lambda2 and one eigen vector v*/
|
---|
[3913] | 14 |
|
---|
[5397] | 15 | /*Intermediaries*/
|
---|
[3913] | 16 | double a11=M.a11,a21=M.a21,a22=M.a22;
|
---|
[9320] | 17 | double normM;
|
---|
[5397] | 18 | double delta,b;
|
---|
[3913] | 19 |
|
---|
[5397] | 20 | /*To get the eigen values, we must solve the following equation:
|
---|
| 21 | * | a11 - lambda a21 |
|
---|
| 22 | * det | | = 0
|
---|
| 23 | * | a21 a22-lambda |
|
---|
| 24 | *
|
---|
| 25 | * We have to solve the following polynom:
|
---|
| 26 | * lamda^2 + ( -a11 -a22)*lambda + (a11*a22-a21*a21) = 0*/
|
---|
[3913] | 27 |
|
---|
[5397] | 28 | /*Compute polynom determinant*/
|
---|
| 29 | b=-a11-a22;
|
---|
| 30 | delta=b*b - 4*(a11*a22-a21*a21);
|
---|
| 31 |
|
---|
| 32 | /*Compute norm of M to avoid round off errors*/
|
---|
| 33 | normM=a11*a11 + a22*a22 + a21*a21;
|
---|
| 34 |
|
---|
| 35 | /*1: normM too small: eigen values = 0*/
|
---|
| 36 | if(normM<1.e-30){
|
---|
| 37 | lambda1=0;
|
---|
| 38 | lambda2=0;
|
---|
[21759] | 39 | vx=1;
|
---|
| 40 | vy=0;
|
---|
[3913] | 41 | }
|
---|
[5397] | 42 | /*2: delta is small -> double root*/
|
---|
| 43 | else if (delta < 1.e-5*normM){
|
---|
| 44 | lambda1=-b/2;
|
---|
| 45 | lambda2=-b/2;
|
---|
[21759] | 46 | vx=1;
|
---|
| 47 | vy=0;
|
---|
[5397] | 48 | }
|
---|
| 49 | /*3: general case -> two roots*/
|
---|
| 50 | else{
|
---|
| 51 | delta = sqrt(delta);
|
---|
| 52 | lambda1 = (-b-delta)/2.0;
|
---|
| 53 | lambda2 = (-b+delta)/2.0;
|
---|
[3913] | 54 |
|
---|
[5397] | 55 | /*Now, one must find the eigen vectors. For that we use the following property of the inner product
|
---|
| 56 | * <Ax,y> = <x,tAy>
|
---|
| 57 | * Here, M'(M-lambda*Id) is symmetrical, which gives:
|
---|
| 58 | * ∀(x,y)∈R²xR² <M'x,y> = <M'y,x>
|
---|
| 59 | * And we have the following:
|
---|
| 60 | * if y∈Ker(M'), ∀x∈R² <M'x,y> = <x,M'y> = 0
|
---|
| 61 | * We have shown that
|
---|
| 62 | * Im(M') ⊥ Ker(M')
|
---|
| 63 | *
|
---|
| 64 | * To find the eigen vectors of M, we only have to find two vectors
|
---|
| 65 | * of the image of M' and take their perpendicular as long as they are
|
---|
| 66 | * not 0.
|
---|
| 67 | * To do that, we take the images (1,0) and (0,1):
|
---|
| 68 | * x1 = (a11 - lambda) x2 = a21
|
---|
| 69 | * y1 = a21 y2 = (a22-lambda)
|
---|
| 70 | *
|
---|
| 71 | * We take the vector that has the larger norm and take its perpendicular.*/
|
---|
| 72 |
|
---|
| 73 | double norm1 = (a11-lambda1)*(a11-lambda1) + a21*a21;
|
---|
| 74 | double norm2 = a21*a21 + (a22-lambda1)*(a22-lambda1);
|
---|
| 75 |
|
---|
| 76 | if (norm2<norm1){
|
---|
| 77 | norm1=sqrt(norm1);
|
---|
[21759] | 78 | vx = - a21/norm1;
|
---|
| 79 | vy = (a11-lambda1)/norm1;
|
---|
[5397] | 80 | }
|
---|
| 81 | else{
|
---|
| 82 | norm2=sqrt(norm2);
|
---|
[21759] | 83 | vx = - (a22-lambda1)/norm2;
|
---|
| 84 | vy = a21/norm2;
|
---|
[5397] | 85 | }
|
---|
| 86 | }
|
---|
| 87 |
|
---|
[3913] | 88 | }
|
---|
[12365] | 89 | /*}}}*/
|
---|
[21759] | 90 | EigenMetric::EigenMetric(double r1,double r2,const D2& vp1){/*{{{*/
|
---|
| 91 | this->lambda1 = r1;
|
---|
| 92 | this->lambda2 = r2;
|
---|
| 93 | this->vx = vp1.x;
|
---|
| 94 | this->vy = vp1.y;
|
---|
[5151] | 95 | }/*}}}*/
|
---|
| 96 |
|
---|
[3913] | 97 | /*Methods*/
|
---|
[18064] | 98 | void EigenMetric::Abs(){/*{{{*/
|
---|
[5151] | 99 | lambda1=bamg::Abs(lambda1),lambda2=bamg::Abs(lambda2);
|
---|
| 100 | }/*}}}*/
|
---|
[18064] | 101 | double EigenMetric::Aniso2() const { /*{{{*/
|
---|
[5151] | 102 | return lmax()/lmin();
|
---|
| 103 | }/*}}}*/
|
---|
[18064] | 104 | void EigenMetric::Echo(void){/*{{{*/
|
---|
[3913] | 105 |
|
---|
[15104] | 106 | _printf_("EigenMetric:\n");
|
---|
[15100] | 107 | _printf_(" lambda1: " << lambda1 << "\n");
|
---|
| 108 | _printf_(" lambda2: " << lambda2 << "\n");
|
---|
[21759] | 109 | _printf_(" vx: " << vx << "\n");
|
---|
| 110 | _printf_(" vy: " << vy << "\n");
|
---|
[3913] | 111 |
|
---|
| 112 | return;
|
---|
| 113 | }
|
---|
| 114 | /*}}}*/
|
---|
[18064] | 115 | double EigenMetric::hmin() const {/*{{{*/
|
---|
[5151] | 116 | return sqrt(1/bamg::Max3(lambda1,lambda2,1e-30));
|
---|
| 117 | }/*}}}*/
|
---|
[18064] | 118 | double EigenMetric::hmax() const {/*{{{*/
|
---|
[5151] | 119 | return sqrt(1/bamg::Max(bamg::Min(lambda1,lambda2),1e-30));
|
---|
| 120 | }/*}}}*/
|
---|
[18064] | 121 | double EigenMetric::lmax() const {/*{{{*/
|
---|
[5151] | 122 | return bamg::Max3(lambda1,lambda2,1e-30);
|
---|
| 123 | }/*}}}*/
|
---|
[18064] | 124 | double EigenMetric::lmin() const {/*{{{*/
|
---|
[5151] | 125 | return bamg::Max(bamg::Min(lambda1,lambda2),1e-30);
|
---|
| 126 | }/*}}}*/
|
---|
[18064] | 127 | void EigenMetric::Min(double a) { /*{{{*/
|
---|
[5151] | 128 | lambda1=bamg::Min(a,lambda1); lambda2=bamg::Min(a,lambda2) ;
|
---|
| 129 | }/*}}}*/
|
---|
[18064] | 130 | void EigenMetric::Max(double a) { /*{{{*/
|
---|
[5447] | 131 | //change eigen values
|
---|
[5151] | 132 | lambda1=bamg::Max(a,lambda1); lambda2=bamg::Max(a,lambda2) ;
|
---|
| 133 | }/*}}}*/
|
---|
[18064] | 134 | void EigenMetric::Minh(double h) {/*{{{*/
|
---|
[5151] | 135 | Min(1.0/(h*h));
|
---|
| 136 | }/*}}}*/
|
---|
[18064] | 137 | void EigenMetric::Maxh(double h) {/*{{{*/
|
---|
[5447] | 138 | //Call Max function
|
---|
[5151] | 139 | Max(1.0/(h*h));
|
---|
| 140 | }/*}}}*/
|
---|
[18064] | 141 | void EigenMetric::pow(double p){/*{{{*/
|
---|
[5151] | 142 | lambda1=::pow(lambda1,p);lambda2=::pow(lambda2,p);
|
---|
| 143 | }/*}}}*/
|
---|
[3913] | 144 |
|
---|
| 145 | }
|
---|