Changeset 19030
- Timestamp:
- 01/21/15 10:23:41 (10 years ago)
- Location:
- issm/trunk-jpl/src/c/shared/Matrix
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
issm/trunk-jpl/src/c/shared/Matrix/MatrixUtils.cpp
r18161 r19030 333 333 334 334 }/*}}}*/ 335 void Matrix2x2Eigen(IssmDouble* plambda1,IssmDouble* plambda2,IssmDouble* pvx, IssmDouble* pvy,IssmDouble a11, IssmDouble a21,IssmDouble a22){/*{{{*/ 336 /*From symetric matrix (a11,a21;a21,a22), get eigen values lambda1 and lambda2 and one eigen vector v*/ 337 338 /*Output*/ 339 IssmDouble lambda1,lambda2; 340 IssmDouble vx,vy; 341 342 /*To get the eigen values, we must solve the following equation: 343 * | a11 - lambda a21 | 344 * det | | = 0 345 * | a21 a22-lambda | 346 * 347 * We have to solve the following polynom: 348 * lamda^2 + ( -a11 -a22)*lambda + (a11*a22-a21*a21) = 0*/ 349 350 /*Compute polynom determinant*/ 351 IssmDouble b=-a11-a22; 352 IssmDouble delta=b*b - 4*(a11*a22-a21*a21); 353 354 /*Compute norm of M to avoid round off errors*/ 355 IssmDouble normM=a11*a11 + a22*a22 + a21*a21; 356 357 /*1: normM too small: eigen values = 0*/ 358 if(normM<1.e-30){ 359 lambda1=0.; 360 lambda2=0.; 361 vx=1.; 362 vy=0.; 363 } 364 /*2: delta is small -> double root*/ 365 else if (delta < 1.e-5*normM){ 366 lambda1=-b/2.; 367 lambda2=-b/2.; 368 vx=1.; 369 vy=0.; 370 } 371 /*3: general case -> two roots*/ 372 else{ 373 delta = sqrt(delta); 374 lambda1 = (-b-delta)/2.; 375 lambda2 = (-b+delta)/2.; 376 377 /*Now, one must find the eigen vectors. For that we use the following property of the inner product 378 * <Ax,y> = <x,tAy> 379 * Here, M'(M-lambda*Id) is symmetrical, which gives: 380 * ∀(x,y)∈R²xR² <M'x,y> = <M'y,x> 381 * And we have the following: 382 * if y∈Ker(M'), ∀x∈R² <M'x,y> = <x,M'y> = 0 383 * We have shown that 384 * Im(M') ⊥ Ker(M') 385 * 386 * To find the eigen vectors of M, we only have to find two vectors 387 * of the image of M' and take their perpendicular as long as they are 388 * not 0. 389 * To do that, we take the images (1,0) and (0,1): 390 * x1 = (a11 - lambda) x2 = a21 391 * y1 = a21 y2 = (a22-lambda) 392 * 393 * We take the vector that has the larger norm and take its perpendicular.*/ 394 395 IssmDouble norm1 = (a11-lambda1)*(a11-lambda1) + a21*a21; 396 IssmDouble norm2 = a21*a21 + (a22-lambda1)*(a22-lambda1); 397 398 if(norm2<norm1){ 399 norm1=sqrt(norm1); 400 vx = - a21/norm1; 401 vy = (a11-lambda1)/norm1; 402 } 403 else{ 404 norm2=sqrt(norm2); 405 vx = - (a22-lambda1)/norm2; 406 vy = a21/norm2; 407 } 408 } 409 410 /*Assign output*/ 411 *plambda1 = lambda1; 412 *plambda2 = lambda2; 413 *pvx = vx; 414 *pvy = vy; 415 416 417 }/*}}}*/ 335 418 336 419 void Matrix3x3Determinant(IssmDouble* Adet,IssmDouble* A){/*{{{*/ -
issm/trunk-jpl/src/c/shared/Matrix/matrix.h
r18148 r19030 14 14 void Matrix2x2Invert(IssmDouble* Ainv, IssmDouble* A); 15 15 void Matrix2x2Determinant(IssmDouble* Adet,IssmDouble* A); 16 void Matrix2x2Eigen(IssmDouble* plambda1,IssmDouble* plambda2,IssmDouble* pvx, IssmDouble* pvy,IssmDouble a11, IssmDouble a21,IssmDouble a22); 16 17 17 18 void Matrix3x3Invert(IssmDouble* Ainv, IssmDouble* A);
Note:
See TracChangeset
for help on using the changeset viewer.