Changeset 2933


Ignore:
Timestamp:
01/29/10 11:33:45 (15 years ago)
Author:
Mathieu Morlighem
Message:

Added some useful comments to Simultaneous reduction

Location:
issm/trunk/src/c/Bamgx
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • issm/trunk/src/c/Bamgx/Metric.h

    r2932 r2933  
    3939                Real8 operator()(R2 x) const { return sqrt((x,x))/h;};
    4040                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;}
    4242                MetricIso operator*(Real8 c) const {return  MetricIso(h/c);}
    4343                MetricIso operator/(Real8 c) const {return  MetricIso(h*c);}
     
    122122        }
    123123
    124         void  SimultaneousMatrixReduction( MetricAnIso M1,  MetricAnIso M2,double & l1,double & l2, D2xD2 & V);
     124        void  SimultaneousMatrixReduction( MetricAnIso M1,  MetricAnIso M2,D2xD2 &V);
    125125
    126126        inline MetricAnIso::MetricAnIso(const MatVVP2x2 M) {
  • issm/trunk/src/c/Bamgx/objects/MetricAnIso.cpp

    r2932 r2933  
    7373                /*Get a new metric from an existing metric (M1=this)
    7474                 * 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;
    102120        }
    103121        /*}}}1*/
     
    171189        /*}}}1*/
    172190        /*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
    174207                double a11=M1.a11,a21=M1.a21,a22=M1.a22;
    175208                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
    189229                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
    195231                        V= D2xD2(1,0,0,1);
    196232                }
     233
     234                //general case: two distinct roots: lambda1 and lambda2
    197235                else {
     236
     237                        /*Compute eigen values*/
    198238                        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                }
    222291        }
    223292        /*}}}1*/
Note: See TracChangeset for help on using the changeset viewer.