source: issm/branches/trunk-larour-NatGeoScience2016/src/c/bamg/EigenMetric.cpp@ 21759

Last change on this file since 21759 was 21759, checked in by Eric.Larour, 8 years ago

CHG: merged branch back to trunk-jpl 21754.

File size: 3.8 KB
Line 
1#include <cstdio>
2#include <cstring>
3#include <cmath>
4#include <ctime>
5
6#include "Metric.h"
7#include "../shared/shared.h"
8
9namespace bamg {
10
11 /*Constructor*/
12 EigenMetric::EigenMetric(const Metric& M){/*{{{*/
13 /*From a metric (a11,a21,a22), get eigen values lambda1 and lambda2 and one eigen vector v*/
14
15 /*Intermediaries*/
16 double a11=M.a11,a21=M.a21,a22=M.a22;
17 double normM;
18 double delta,b;
19
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*/
27
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;
39 vx=1;
40 vy=0;
41 }
42 /*2: delta is small -> double root*/
43 else if (delta < 1.e-5*normM){
44 lambda1=-b/2;
45 lambda2=-b/2;
46 vx=1;
47 vy=0;
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;
54
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);
78 vx = - a21/norm1;
79 vy = (a11-lambda1)/norm1;
80 }
81 else{
82 norm2=sqrt(norm2);
83 vx = - (a22-lambda1)/norm2;
84 vy = a21/norm2;
85 }
86 }
87
88 }
89 /*}}}*/
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;
95 }/*}}}*/
96
97 /*Methods*/
98 void EigenMetric::Abs(){/*{{{*/
99 lambda1=bamg::Abs(lambda1),lambda2=bamg::Abs(lambda2);
100 }/*}}}*/
101 double EigenMetric::Aniso2() const { /*{{{*/
102 return lmax()/lmin();
103 }/*}}}*/
104 void EigenMetric::Echo(void){/*{{{*/
105
106 _printf_("EigenMetric:\n");
107 _printf_(" lambda1: " << lambda1 << "\n");
108 _printf_(" lambda2: " << lambda2 << "\n");
109 _printf_(" vx: " << vx << "\n");
110 _printf_(" vy: " << vy << "\n");
111
112 return;
113 }
114 /*}}}*/
115 double EigenMetric::hmin() const {/*{{{*/
116 return sqrt(1/bamg::Max3(lambda1,lambda2,1e-30));
117 }/*}}}*/
118 double EigenMetric::hmax() const {/*{{{*/
119 return sqrt(1/bamg::Max(bamg::Min(lambda1,lambda2),1e-30));
120 }/*}}}*/
121 double EigenMetric::lmax() const {/*{{{*/
122 return bamg::Max3(lambda1,lambda2,1e-30);
123 }/*}}}*/
124 double EigenMetric::lmin() const {/*{{{*/
125 return bamg::Max(bamg::Min(lambda1,lambda2),1e-30);
126 }/*}}}*/
127 void EigenMetric::Min(double a) { /*{{{*/
128 lambda1=bamg::Min(a,lambda1); lambda2=bamg::Min(a,lambda2) ;
129 }/*}}}*/
130 void EigenMetric::Max(double a) { /*{{{*/
131 //change eigen values
132 lambda1=bamg::Max(a,lambda1); lambda2=bamg::Max(a,lambda2) ;
133 }/*}}}*/
134 void EigenMetric::Minh(double h) {/*{{{*/
135 Min(1.0/(h*h));
136 }/*}}}*/
137 void EigenMetric::Maxh(double h) {/*{{{*/
138 //Call Max function
139 Max(1.0/(h*h));
140 }/*}}}*/
141 void EigenMetric::pow(double p){/*{{{*/
142 lambda1=::pow(lambda1,p);lambda2=::pow(lambda2,p);
143 }/*}}}*/
144
145}
Note: See TracBrowser for help on using the repository browser.