sandbox/fintzin/Rising-Suspenion/algebra.h

    /** # This file include mathematical operator for coord struct */
    typedef struct ten{
      coord x;
      coord y;
      #if dimension == 3
      coord z;
      #endif
    }ten;
    /** declaration of the null coord*/
    
    const coord Coord_nul = {0};
    const tens tens_nul = {{0}};
    #define Identity\
              {{1,0,0},\
              {0,1,0},\
              {0,0,1}}
    const tens I = Identity;
    
    /** and operator on coord */
    coord and_coord(coord a,coord b){
      coord c = {(int)a.x && (int)b.x,(int)a.y &&(int) b.y,(int)a.z &&(int) b.z};
      return c;
    }
    coord add_coord(coord a,coord b){
      #if dimension == 2
      coord c = {a.x+b.x, a.y+b.y};
      #elif dimension == 3
      coord c = {a.x+b.x, a.y+b.y, a.z+b.z};
      #endif
      return c;
    }
    coord diff_coord(coord a,coord b){
      #if dimension == 2
      coord c = {a.x-b.x,a.y-b.y};
      #elif dimension == 3
      coord c = {a.x-b.x, a.y-b.y, a.z-b.z};
      #endif
      return c;
    }
    coord mult_coord(coord a,double b){
      #if dimension == 2
      coord c = {a.x*b,  a.y*b};
      #elif dimension == 3
      coord c = {a.x*b,  a.y*b,  a.z*b};
      #endif
      return c;
    } 
    coord div_coord(coord a,double b){
      #if dimension == 2
      coord c = {a.x/b,  a.y/b};
      #elif dimension == 3
      coord c = {a.x/b,  a.y/b,  a.z/b};
      #endif
      return c;
    }
    tens div_tens(tens a,double b){
      einstein_sum(i,j){
         a.i.j /= b;
      }
      return a;
    }
    tens mult_tens(tens a,double b){
      einstein_sum(i,j){
         a.i.j *= b;
      }
      return a;
    }
    tens add_tens(tens A,tens B){
      einstein_sum(i,j){
         A.i.j += B.i.j;
      }
      return A;
    }
    double tens_norm(tens A){
      double norm = 0;
      einstein_sum(k,l){
         norm = A.k.l * A.k.l;
      }
      norm = sqrt(norm);
      return norm;
    }
    double normL2_coord(coord a){
      #if dimension == 2
      double c = sqrt(pow(a.x,2)+pow(a.y,2));
      #elif dimension == 3
      double c = sqrt(pow(a.x,2)+pow(a.y,2)+pow(a.z,2));
      #endif
      return c;
    }
    double normL2_coord_sq(coord a){
      #if dimension == 2
      double c = sq(a.x)+sq(a.y);
      #elif dimension == 3
      double c = sq(a.x)+sq(a.y)+sq(a.z);
      #endif
      return c;
    }
    double normL2_ten(ten a){
      #if dimension == 2
      double c = sqrt(pow(a.x.x,2)+pow(a.y.y,2)+pow(a.x.y,2)+pow(a.y.x,2));
      #elif dimension == 3
      double c = sqrt(pow(a.x.x,2)+pow(a.y.y,2)+pow(a.z.z,2)+pow(a.x.y,2)+pow(a.y.x,2)+pow(a.x.z,2)+pow(a.z.x,2)+pow(a.z.y,2)+pow(a.y.z,2));
      #endif
      return c;
    }
    //only in 3D for the cross product 
    #if dimension == 3
    coord cross_coord(coord a,coord b){
      coord c = {a.y*b.z-a.z*b.y, 
                a.z*b.x-a.x*b.z, 
                a.x*b.y-a.y*b.x};
    #elif dimension == 2
    double cross_coord(coord a,coord b){
      double c = a.x*b.y-a.y*b.x;
    #endif
      return c;
    }
    
    coord EigenValue(ten A){
      double Delta = pow(A.x.x,2.) - 2.*A.x.x*A.y.y+pow(A.y.y,2.) +4.*A.x.y*A.y.x;
      coord Eig = {0.,0.};
      if(Delta > 0){
        Eig.x = 1./2.*(  A.x.x + A.y.y - sqrt( Delta ));
        Eig.y = 1./2.*(  A.x.x + A.y.y + sqrt( Delta ));
      }
      return Eig;
    }
    
    ten EigenVectors(ten A){
      ten V;
      if(A.y.x != 0){
        V.x.x = -1./(2.*A.y.x)*( - A.x.x + A.y.y + sqrt( pow(A.x.x,2.) - 2.*A.x.x*A.y.y+pow(A.y.y,2.) +4.*A.x.y*A.y.x ) ); 
        V.x.y = 1.;
        V.y.x = -1./(2.*A.y.x)*( - A.x.x + A.y.y - sqrt( pow(A.x.x,2.) - 2*A.x.x*A.y.y+pow(A.y.y,2.) +4.*A.x.y*A.y.x ) );
        V.y.y = 1.;
      }else if((A.x.x-A.y.y)!=0){
        V.x.x = 1.;
        V.x.y = 0.;
        V.y.x = -A.x.y/(A.x.x-A.y.y);
        V.y.y = 1.;
      }else{
        V.x.x = 1.;
        V.x.y = 0.;
        V.y.x = 0.;
        V.y.y = 1.;
      }
      V.x = div_coord(V.x,normL2_coord(V.x));
      V.y = div_coord(V.y,normL2_coord(V.y));
      return V;
    }
    
    /** Set the coordinate of a coord at the positive side of the domain */
    coord POS_perio(coord pos,coord per){
      foreach_dimension(){
        if(per.x) pos.x = pos.x>0?pos.x:pos.x+Ls;
      }
      return pos;
    }
    /** compute the periodic distance between two coord */
    coord dist_perio_coord(coord a,coord b){
      foreach_dimension(){
        if(a.x>0) b.x = (b.x<a.x-Ls/2)*Ls+b.x;
        else b.x = (b.x>a.x+Ls/2)*(-Ls)+b.x;
      }
      return diff_coord(a,b);
    }
    
    
    double dist_perio(coord a,coord b){
      foreach_dimension(){
        if(a.x>0) b.x = (b.x<a.x-Ls/2)*Ls+b.x;
        else b.x = (b.x>a.x+Ls/2)*(-Ls)+b.x;
      }
      return normL2_coord(diff_coord(a,b));
    }
    /** compute the tranpsoe of a tensor */ 
    tens transpsoe(tens A){
      tens B;
      einstein_sum(i,j){
         B.i.j = A.j.i;
      }
      return B;
    }
    tens sym(tens A){
      tens B;
      einstein_sum(i,j){
      B. i.j = 0.5*(A.i.j + A.j.i);
      }
      return B;
    }
    tens coord_prod(coord A,coord B){
      tens C;
      einstein_sum(i,j){
         C.i.j = A.i*B.j;
      }
      return C;
    }
    /** compute the symetric part of a tensor */