Changeset 2933
- Timestamp:
- 01/29/10 11:33:45 (15 years ago)
- Location:
- issm/trunk/src/c/Bamgx
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
issm/trunk/src/c/Bamgx/Metric.h
r2932 r2933 39 39 Real8 operator()(R2 x) const { return sqrt((x,x))/h;}; 40 40 Real8 operator()(R2 x,R2 y) const { return ((x,y))/(h*h);}; 41 int IntersectWith(MetricIso M) {int r=0;if (M.h<h) r=1,h=M.h;return r;}41 int IntersectWith(MetricIso M) {int change=0;if (M.h<h) change=1,h=M.h;return change;} 42 42 MetricIso operator*(Real8 c) const {return MetricIso(h/c);} 43 43 MetricIso operator/(Real8 c) const {return MetricIso(h*c);} … … 122 122 } 123 123 124 void SimultaneousMatrixReduction( MetricAnIso M1, MetricAnIso M2, double & l1,double & l2, D2xD2 &V);124 void SimultaneousMatrixReduction( MetricAnIso M1, MetricAnIso M2,D2xD2 &V); 125 125 126 126 inline MetricAnIso::MetricAnIso(const MatVVP2x2 M) { -
issm/trunk/src/c/Bamgx/objects/MetricAnIso.cpp
r2932 r2933 73 73 /*Get a new metric from an existing metric (M1=this) 74 74 * and a new metric given in input M2 using a 75 * Simultaneous Matrix Reduction 76 * */ 77 78 int r=0; 79 MetricAnIso & M1 = *this; 80 D2xD2 M; 81 double l1,l2; 82 83 SimultaneousMatrixReduction(*this,M2,l1,l2,M); 84 85 R2 v1(M.x.x,M.y.x); 86 R2 v2(M.x.y,M.y.y); 87 double l11=M1(v1,v1); 88 double l12=M1(v2,v2); 89 double l21=M2(v1,v1); 90 double l22=M2(v2,v2); 91 if ( l11 < l21 ) r=1,l11=l21; 92 if ( l12 < l22 ) r=1,l12=l22; 93 if (r) { // change 94 D2xD2 M_1(M.inv()); 95 D2xD2 D(l11,0,0,l12); 96 D2xD2 Mi(M_1.t()*D*M_1); 97 a11=Mi.x.x; 98 a21=0.5*(Mi.x.y+Mi.y.x); 99 a22=Mi.y.y; 100 } 101 return r; 75 * Simultaneous Matrix Reduction: 76 * If M1 and M2 are 2 metrics, we must build N=M1^-1 M2 (Alauzet2003 p16) 77 * the eigen vectors of N form a matrix P 78 * The new metric M = M1 inter M2 is then given by: 79 * 80 * -T [ max(lambda1, mu1) 0 ] -1 81 * M = P [ ] P 82 * [ 0 max(lambda2, mu2)] 83 * 84 * where lambdai and mui can be computed using Rayleigh formula: 85 * lambdai = vi' M1 vi 86 * with vi eigen vectors of N (columns of P) 87 */ 88 89 int change=0; 90 MetricAnIso &M1=*this; 91 D2xD2 P; 92 93 //Get P, eigen vectors of N=inv(M1) M2 94 SimultaneousMatrixReduction(*this,M2,P); 95 96 //extract the eigen vectors of P (columns) 97 R2 v1(P.x.x,P.y.x); 98 R2 v2(P.x.y,P.y.y); 99 100 //compute lambdai mui 101 double lambda1=M1(v1,v1); 102 double lambda2=M1(v2,v2); 103 double mu1=M2(v1,v1); 104 double mu2=M2(v2,v2); 105 106 //check where any change needs to be done on M1 107 if ( lambda1 < mu1 ) change=1,lambda1=mu1; 108 if ( lambda2 < mu2 ) change=1,lambda2=mu2; 109 110 //update M1 if necessary 111 if (change) { 112 D2xD2 invP(P.inv()); 113 D2xD2 D(lambda1,0,0,lambda2); 114 D2xD2 M(invP.t()*D*invP); 115 a11=M.x.x; 116 a21=0.5*(M.x.y+M.y.x); 117 a22=M.y.y; 118 } 119 return change; 102 120 } 103 121 /*}}}1*/ … … 171 189 /*}}}1*/ 172 190 /*FUNCTION SimultaneousMatrixReduction{{{1*/ 173 void SimultaneousMatrixReduction( MetricAnIso M1, MetricAnIso M2,double & l1,double & l2, D2xD2 & V) { 191 void SimultaneousMatrixReduction( MetricAnIso M1, MetricAnIso M2, D2xD2 &V) { 192 /*In this routine we must return a matrix V that is composed of the 193 * eigen vectors of N=inv(M1) M2. 194 * Instead of looking at N directly, we are going to use the fact that 195 * M1 and M2 are symmetrical, positive definite. 196 * The eigen values of N are given by solving 197 * inv(M1) M2 V = lambda V 198 * which is equivalent to 199 * M2 V = lambda M1 V 200 * and we will hence solve 201 * (M2 - lambda M1) V = 0 202 */ 203 204 int i; 205 206 //M1 and M2 components 174 207 double a11=M1.a11,a21=M1.a21,a22=M1.a22; 175 208 double b11=M2.a11,b21=M2.a21,b22=M2.a22; 176 // M1 v = l M2 v 177 // (M1 - l M2) v =0 178 // det (M1 - l M2) =0 179 // det (M1 - l M2) = a l^2 + b l + c; 180 // = (a11 - l * b11) * (a22 - l * b22) - (a21 - l * b21 ) ^2 181 const double /*c11 = a11*a11,*/ c21= a21*a21; 182 const double /*d11 = b11*b11,*/ d21= b21*b21; 183 const double a=b11*b22 - d21; 184 const double b=-a11*b22-a22*b11+2*a21*b21; 185 const double c=-c21+a11*a22; 186 const double bb = b*b,ac= a*c; 187 const double b2a = b/(2*a); 188 const double delta = bb - 4 * ac; 209 210 /*To get the eigen values, we solve the following problem: 211 * det(M2-lambda M1) = 0 212 * (b11 - lambda a11)(b22-lambda a22) - (b21-lambda a21)^2 213 * and we have the following trinome: 214 * a lambda^2 + b lambda + c =0 215 * with: 216 * a = a11 a22 - a21 a21 (=det(M1)) 217 * b = -a11 b22 -b11 a22 + 2 b21 a21 218 * c = b11 b22 - b21 b21 (=det(M2)) 219 * */ 220 const double a= a11*a22 - a21*a21; 221 const double b=-a11*b22 - b11*a22+2*b21*a21; 222 const double c=-b21*b21 + b11*b22; 223 const double bb=b*b,ac=a*c; 224 const double delta= bb-4*ac; 225 226 // first, case of a double root if: 227 // - all the terms are very small (a??) 228 // - or : delta is very small 189 229 if ( (bb + Abs(ac) < 1.0e-34 ) || (delta < 1.0e-6*bb) ){ 190 // racine double; 191 if (Abs(a) < 1.e-30 ) 192 l1 = l2 = 0; 193 else 194 l1=l2=-b/(2*a); 230 //all vectors are eigen vectors -> choose 1,0 and 0,1 195 231 V= D2xD2(1,0,0,1); 196 232 } 233 234 //general case: two distinct roots: lambda1 and lambda2 197 235 else { 236 237 /*Compute eigen values*/ 198 238 const double delta2 = sqrt(delta); 199 l1= (-b - delta2)/(2*a); 200 l2= (-b + delta2)/(2*a); 201 // M1 v = l M2 v 202 // ( (M1 - I M2) x,y) = (x,(M1 - I M2) y) \forall y 203 // so Ker((M1 - I M2)) = Im((M1 - I M2))^\perp 204 double v0 = a11-l1*b11, v1 = a21-l1*b21,v2 = a22 - l1*b22; 205 double s0 = v0*v0 + v1*v1, s1 = v1*v1 +v2*v2; 206 double vp1x,vp1y,vp2x,vp2y; 207 208 if(s1 < s0) 209 s0=sqrt(s0),vp1x=v1/s0,vp1y=-v0/s0; 210 else 211 s1=sqrt(s1),vp1x=v2/s1,vp1y=-v1/s1; 212 213 v0 = a11-l2*b11, v1 = a21-l2*b21,v2 = a22 - l2*b22; 214 s0 = v0*v0 + v1*v1, s1 = v1*v1 +v2*v2; 215 if(s1 < s0) 216 s0=sqrt(s0),vp2x=v1/s0,vp2y=-v0/s0; 217 else 218 s1=sqrt(s1),vp2x=v2/s1,vp2y=-v1/s1; 219 V=D2xD2(vp1x,vp2x,vp1y,vp2y); 220 } 221 return; 239 double lambda[2]; 240 lambda[0]= (-b - delta2)/(2*a); 241 lambda[1]= (-b + delta2)/(2*a); 242 243 /*compute eigen vectors*/ 244 double vp[2][2]; 245 double v0,v1,v2; 246 double s0,s1; 247 248 for(i=0;i<2;i++){ 249 /*Now, one must find the eigen vectors. For that we use the 250 * following property of the scalare product 251 * (Ax,b) = transp(b) Ax = transp(x) transp(A) b 252 * = (transp(A) b ,x) 253 * Here we are dealing with A= M2 - lambda M1 which is symmetrical: 254 * for all (x,y) in R2 255 * ((M2 - lambda M1)x,y)=((M2 - lambda M1)y,x) 256 * If y is in Ker(M2 - lambda M1): 257 * for all x in R2 258 * ((M2 - lambda M1)y,x)=0 259 * This shows that: 260 * Ker(M2 - lambda M1) is orthogonal to Im(M2 - lambda M1) 261 * To find the eigen vectors, we only have to find two vectors 262 * of the image and take their perpendicular as long as they are 263 * not 0. 264 * To do that, we take (1,0) and (0,1) and take the larger norm*/ 265 266 //compute V = M2 - lambdai M1 267 v0 = b11 - lambda[i]*a11; 268 v1 = b21 - lambda[i]*a21; 269 v2 = b22 - lambda[i]*a22; 270 271 // compute s1=norm(V(1,0)) and s0=norm(V(0,1)) 272 s0 = v0*v0 + v1*v1; 273 s1 = v1*v1 + v2*v2; 274 275 //compute vp1 = (vp1x,vp1y) 276 if(s1 < s0){ 277 s0=sqrt(s0); 278 vp[0][i]= v1/s0; 279 vp[1][i]= - v0/s0; 280 } 281 else{ 282 s1=sqrt(s1); 283 vp[0][i]= v2/s0; 284 vp[1][i]= - v1/s0; 285 } 286 } 287 288 //compute V from vp 289 V=D2xD2(vp[0][0],vp[0][1],vp[1][0],vp[1][1]); 290 } 222 291 } 223 292 /*}}}1*/
Note:
See TracChangeset
for help on using the changeset viewer.