Changeset 19030


Ignore:
Timestamp:
01/21/15 10:23:41 (10 years ago)
Author:
Mathieu Morlighem
Message:

NEW: added eigen values and vector calculations for 2x2 symetric matrices

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  
    333333
    334334}/*}}}*/
     335void 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}/*}}}*/
    335418
    336419void Matrix3x3Determinant(IssmDouble* Adet,IssmDouble* A){/*{{{*/
  • issm/trunk-jpl/src/c/shared/Matrix/matrix.h

    r18148 r19030  
    1414void Matrix2x2Invert(IssmDouble* Ainv, IssmDouble* A);
    1515void Matrix2x2Determinant(IssmDouble* Adet,IssmDouble* A);
     16void Matrix2x2Eigen(IssmDouble* plambda1,IssmDouble* plambda2,IssmDouble* pvx, IssmDouble* pvy,IssmDouble a11, IssmDouble a21,IssmDouble a22);
    1617
    1718void Matrix3x3Invert(IssmDouble* Ainv, IssmDouble* A);
Note: See TracChangeset for help on using the changeset viewer.