MechSys  1.0
Computing library for simulations in continuum and discrete mechanics
/home/dorival/mechsys/lib/models/anisoinvs.h
Go to the documentation of this file.
00001 /************************************************************************
00002  * MechSys - Open Library for Mechanical Systems                        *
00003  * Copyright (C) 2005 Dorival M. Pedroso, Raul Durand                   *
00004  * Copyright (C) 2009 Sergio Galindo                                    *
00005  *                                                                      *
00006  * This program is free software: you can redistribute it and/or modify *
00007  * it under the terms of the GNU General Public License as published by *
00008  * the Free Software Foundation, either version 3 of the License, or    *
00009  * any later version.                                                   *
00010  *                                                                      *
00011  * This program is distributed in the hope that it will be useful,      *
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of       *
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the         *
00014  * GNU General Public License for more details.                         *
00015  *                                                                      *
00016  * You should have received a copy of the GNU General Public License    *
00017  * along with this program. If not, see <http://www.gnu.org/licenses/>  *
00018  ************************************************************************/
00019 
00020 #ifndef MECHSYS_ANISOINVS_H
00021 #define MECHSYS_ANISOINVS_H
00022 
00023 // Std Lib
00024 #include <iostream>
00025 #include <fstream>
00026 
00027 // MechSys
00028 #include <mechsys/util/maps.h>
00029 #include <mechsys/util/fatal.h>
00030 #include <mechsys/linalg/matvec.h>
00031 #include <mechsys/linalg/jacobirot.h>
00032 
00033 class AnisoInvs
00034 {
00035 public:
00036     // Constructor & Destructor
00037      AnisoInvs (double b, double Alpha, Vec3_t const & a, bool Obliq=true, bool Check=true, bool UseJacobi=false);
00038     ~AnisoInvs () {}
00039 
00040     // Methods
00041     void Calc     (Vec_t const & Sig, bool WithDerivs=false);
00042     void CheckSym (char const * Name, Ten2_t const & T) const;
00043     void CheckSym (char const * Name, Ten3_t const & T) const;
00044 
00045     // Constants
00046     double  b, Alpha;
00047     Vec3_t  a;
00048     bool    Obliq;
00049     bool    Check;
00050     bool    UseJacobi;
00051     double  Tol;
00052     double  Zero;
00053     Vec3_t  au;
00054 
00055     // Data
00056     static double  sp, sq;      // invariants
00057     static Vec3_t  N123, N, Nu; // SMP
00058     static Vec3_t  n, nu;       // AMP
00059     static Mat3_t  Q;           // rotation matrix
00060     static Vec3_t  L;           // eigenvalues
00061     static Vec3_t  v0,v1,v2;    // eigenvectors
00062     static Vec3_t  t, p, q;     // traction and projections
00063     static Mat3_t  P;           // projector
00064 
00065     // Derivs
00066 #ifdef HAS_TENSORS
00067     static Ten1_t V0, V1, V2;                // eigenvectors
00068     static Ten2_t E0, E1, E2;                // eigenprojectors
00069     static Ten3_t dv0dSig, dv1dSig, dv2dSig; // eigenvectors
00070     static Ten2_t dN123dL;                   // SMP(123)
00071     static Ten3_t dNdSig, dNudSig;           // SMP
00072     static Ten2_t dNudN;                     // SMP
00073     static Ten3_t dndSig, dnudSig;           // AMP
00074     static Ten2_t dnudn;                     // AMP
00075     static Ten2_t tSig, I;                   // tensor Sig and Identity
00076     static Ten1_t tN, tNu, tn, tnu;          // tensors: normal vectors
00077     static Ten3_t M, dtdSig;                 // auxiliary tensor and traction
00078     static Ten1_t tt, tp, tq;                // tensor: traction and projections
00079     static Ten2_t tP;                        // tensor: projector
00080     static Ten2_t dsdSig;                    // auxiliary tensor for dpdSig
00081     static Ten3_t dpdSig, dqdSig;            // projections
00082     static Ten2_t tdspdSig, tdsqdSig;        // invariants (tensor)
00083     static Vec_t  dspdSig, dsqdSig;          // invariants (Mandel's basis)
00084 #endif
00085 
00086 private:
00087     bool  _allocated;
00088 };
00089 
00090 // Data
00091 double AnisoInvs::sp;       double AnisoInvs::sq;
00092 Vec3_t AnisoInvs::N123;     Vec3_t AnisoInvs::N;       Vec3_t AnisoInvs::Nu;
00093 Vec3_t AnisoInvs::n;        Vec3_t AnisoInvs::nu;
00094 Mat3_t AnisoInvs::Q;
00095 Vec3_t AnisoInvs::L;
00096 Vec3_t AnisoInvs::v0;       Vec3_t AnisoInvs::v1;      Vec3_t AnisoInvs::v2;
00097 Vec3_t AnisoInvs::t;        Vec3_t AnisoInvs::p;       Vec3_t AnisoInvs::q;
00098 Mat3_t AnisoInvs::P;
00099 
00100 // Derivs
00101 #ifdef HAS_TENSORS
00102 Ten1_t AnisoInvs::V0;        Ten1_t AnisoInvs::V1;        Ten1_t AnisoInvs::V2;
00103 Ten3_t AnisoInvs::dv0dSig;   Ten3_t AnisoInvs::dv1dSig;   Ten3_t AnisoInvs::dv2dSig;
00104 Ten2_t AnisoInvs::E0;        Ten2_t AnisoInvs::E1;        Ten2_t AnisoInvs::E2;
00105 Ten2_t AnisoInvs::dN123dL;
00106 Ten3_t AnisoInvs::dNdSig;    Ten3_t AnisoInvs::dNudSig;
00107 Ten2_t AnisoInvs::dNudN;
00108 Ten3_t AnisoInvs::dndSig;    Ten3_t AnisoInvs::dnudSig;
00109 Ten2_t AnisoInvs::dnudn;
00110 Ten2_t AnisoInvs::tSig;      Ten2_t AnisoInvs::I;
00111 Ten1_t AnisoInvs::tN;        Ten1_t AnisoInvs::tNu;       Ten1_t AnisoInvs::tn;    Ten1_t AnisoInvs::tnu;
00112 Ten3_t AnisoInvs::M;         Ten3_t AnisoInvs::dtdSig;
00113 Ten1_t AnisoInvs::tt;        Ten1_t AnisoInvs::tp;        Ten1_t AnisoInvs::tq;
00114 Ten2_t AnisoInvs::tP;
00115 Ten2_t AnisoInvs::dsdSig;
00116 Ten3_t AnisoInvs::dpdSig;    Ten3_t AnisoInvs::dqdSig;
00117 Ten2_t AnisoInvs::tdspdSig;  Ten2_t AnisoInvs::tdsqdSig;
00118 Vec_t  AnisoInvs::dspdSig;   Vec_t  AnisoInvs::dsqdSig;
00119 #endif
00120 
00121 
00123 
00124 
00125 inline AnisoInvs::AnisoInvs (double Theb, double TheAlpha, Vec3_t const & Thea, bool TheObliq, bool TheCheck, bool TheUseJacobi)
00126     : b(Theb), Alpha(TheAlpha), a(Thea), Obliq(TheObliq), Check(TheCheck), UseJacobi(TheUseJacobi), Tol(1.0e-8), Zero(1.0e-14), _allocated(false)
00127 {
00128     if (!_allocated)
00129     {
00130         I.SetDiagonal (1.0);
00131         _allocated = true;
00132     }
00133 
00134     // check
00135     double norm_a = Norm(a);
00136     if (norm_a<Tol) throw new Fatal("AnisoInvs::AnisoInvs 'a' vector must be non zero. a=[%g,%g,%g]. norm(a)=%g",a(0),a(1),a(2),norm_a);
00137     au = a / norm_a;
00138 }
00139 
00140 inline void AnisoInvs::Calc (Vec_t const & Sig, bool WithDerivs)
00141 {
00142     // principal values and eigenvectors
00143     if (UseJacobi)
00144     {
00145         // rotation matrix
00146         JacobiRot (Sig, Q, L);
00147 
00148         // eigenvectors
00149         v0(0) = Q(0,0);   v1(0) = Q(0,1);   v2(0) = Q(0,2);
00150         v0(1) = Q(1,0);   v1(1) = Q(1,1);   v2(1) = Q(1,2);
00151         v0(2) = Q(2,0);   v1(2) = Q(2,1);   v2(2) = Q(2,2);
00152     }
00153     else
00154     {
00155         // eigenvectors
00156         Eig (Sig, L, v0, v1, v2);
00157 
00158         // rotation matrix
00159         Q(0,0) = v0(0);   Q(0,1) = v1(0);   Q(0,2) = v2(0);
00160         Q(1,0) = v0(1);   Q(1,1) = v1(1);   Q(1,2) = v2(1);
00161         Q(2,0) = v0(2);   Q(2,1) = v1(2);   Q(2,2) = v2(2);
00162     }
00163     //if (L(0)>0.0 || L(1)>0.0 || L(2)>0.0) throw new Fatal("AnisoInvs::Calc: This method only works when all principal values are negative (compression octant). L=[%g,%g,%g]",L(0),L(1),L(2));
00164 
00165     // normal vectors
00166     bool zero = (fabs(L(0))<Tol || fabs(L(1))<Tol || fabs(L(2))<Tol);
00167     if (zero) N123 = 1.0, 1.0, 1.0;                                                       // SMP(123)
00168     else      N123 = 1.0/pow(fabs(L(0)),b), 1.0/pow(fabs(L(1)),b), 1.0/pow(fabs(L(2)),b); // SMP(123)
00169 
00170     Mat3_t Qt;
00171     Qt(0,0) = Q(0,0);   Qt(0,1) = Q(1,0);   Qt(0,2) = Q(2,0);
00172     Qt(1,0) = Q(0,1);   Qt(1,1) = Q(1,1);   Qt(1,2) = Q(2,1);
00173     Qt(2,0) = Q(0,2);   Qt(2,1) = Q(1,2);   Qt(2,2) = Q(2,2);
00174 
00175     N  = product (Q, N123); // SMP(xyz)
00176     //N  = product (Qt, N123); // SMP(xyz)
00177     Nu = N / Norm(N);       // SMP
00178     n  = Alpha*au + Nu;     // AMP
00179     nu = n / Norm(n);       // AMP
00180 
00181     // traction
00182     Mult (Sig, nu, t); // t = Sig * nu
00183 
00184     // P projector
00185     double s = 0.0;
00186     if (Obliq)
00187     {
00188         s = 1.0 / dot(N, n);
00189         Dyad (s, N, n, P); // P = s*(N dy n)
00190     }
00191     else Dyad (nu, nu, P);
00192 
00193     // invariants
00194     p  = product (P, t);
00195     q  = t - p;
00196     sp = Norm(p);
00197     sq = Norm(q);
00198 
00199     // derivatives
00200     if (WithDerivs)
00201     {
00202 #ifdef HAS_TENSORS
00203         // normal to SMP in principal system
00204         if (zero) dN123dL.SetDiagonal (1.0);
00205         else dN123dL =            -b/(L(0)*pow(fabs(L(0)),b)), 0.0, 0.0,
00206                         0.0,      -b/(L(1)*pow(fabs(L(1)),b)), 0.0,
00207                         0.0, 0.0, -b/(L(2)*pow(fabs(L(2)),b));
00208 
00209         // eigenvectors and eigenprojectors
00210         Vec2Tensor     (v0,V0);
00211         Vec2Tensor     (v1,V1);
00212         Vec2Tensor     (v2,V2);
00213         EigenVecDerivs (L, V0,V1,V2, dv0dSig,dv1dSig,dv2dSig);
00214         E0 = (V0 & V0);
00215         E1 = (V1 & V1);
00216         E2 = (V2 & V2);
00217 
00218         // normal to SMP in xyz system
00219         dNdSig = ((V0&E0)*dN123dL[0][0]) + ((V1&E1)*dN123dL[1][1]) + ((V2&E2)*dN123dL[2][2]) + (dv0dSig*N123(0)) + (dv1dSig*N123(1)) + (dv2dSig*N123(2));
00220 
00221         // unit normal to SMP in xyz system
00222         UnitVecDeriv (N, Nu, dNudN, Tol);
00223         dNudSig = dNudN * dNdSig;
00224 
00225         // normal to AMP in xyz system
00226         dndSig = dNudSig;
00227 
00228         // unit normal to AMP in xyz system
00229         UnitVecDeriv (n, nu, dnudn, Tol);
00230         dnudSig = dnudn * dndSig;
00231 
00232         // convert to tensors
00233         Mat2Tensor (P,    tP);
00234         Ten2Tensor (Sig,  tSig);
00235         Vec2Tensor (t,    tt);
00236         Vec2Tensor (N,    tN);
00237         Vec2Tensor (Nu,   tNu);
00238         Vec2Tensor (n,    tn);
00239         Vec2Tensor (nu,   tnu);
00240         Vec2Tensor (p,    tp);
00241         Vec2Tensor (q,    tq);
00242 
00243         // traction
00244         for (size_t i=0; i<3; ++i)
00245         for (size_t j=0; j<3; ++j)
00246         for (size_t k=0; k<3; ++k)
00247             M[i][j][k] = 0.5*(I[i][j]*nu[k] + I[i][k]*nu[j]);
00248         dtdSig = M + (tSig * dnudSig);
00249 
00250         // normal projection
00251         if (Obliq)
00252         {
00253             double m = tn * tt;
00254             dsdSig = (tn*dNdSig + tN*dndSig)*(-s*s);
00255             dpdSig = (tN&dsdSig)*m + dNdSig*(s*m) + (tN&(tt*dndSig))*s + tP*dtdSig;
00256         }
00257         else
00258         {
00259             double m = tnu * tt;
00260             dpdSig = dnudSig*m + (tnu&(tt*dnudSig)) + tP*dtdSig;
00261         }
00262 
00263         // on-plane projection
00264         dqdSig = dtdSig - dpdSig;
00265 
00266         // check symmetry
00267         if (Check)
00268         {
00269             CheckSym ("dNdSig",  dNdSig );
00270             CheckSym ("dNudSig", dNudSig);
00271             CheckSym ("dndSig",  dndSig );
00272             CheckSym ("dnudSig", dnudSig);
00273             CheckSym ("dsdSig",  dsdSig );
00274             CheckSym ("dpdSig",  dpdSig );
00275             CheckSym ("M",       M      );
00276             CheckSym ("dtdSig",  dtdSig );
00277             CheckSym ("dqdSig",  dqdSig );
00278         }
00279 
00280         // invariants
00281         if (sp>Tol) tdspdSig = (tp*(1.0/sp)) * dpdSig;   else tdspdSig.SetDiagonal (1.0);
00282         if (sq>Tol) tdsqdSig = (tq*(1.0/sq)) * dqdSig;   else tdsqdSig.SetDiagonal (1.0);
00283         size_t ncp = size(Sig);
00284         Tensor2Ten (tdspdSig, dspdSig, ncp);
00285         Tensor2Ten (tdsqdSig, dsqdSig, ncp);
00286 #else
00287         throw new Fatal("AnisoInvs::Calc: Tensors library is required in order to calculate derivatives");
00288 #endif
00289     }
00290 }
00291 
00292 inline void AnisoInvs::CheckSym (char const * Name, Ten2_t const & T) const
00293 {
00294     for (size_t i=0; i<3; ++i)
00295     for (size_t j=0; j<3; ++j)
00296     {
00297         double error = fabs(T[i][j] - T[i][j]);
00298         if (error>Zero) throw new Fatal("CheckSym: Second order tensor %s is not symmetric. error=%g",Name,error);
00299     }
00300 }
00301 
00302 inline void AnisoInvs::CheckSym (char const * Name, Ten3_t const & T) const
00303 {
00304     for (size_t i=0; i<3; ++i)
00305     for (size_t j=0; j<3; ++j)
00306     for (size_t k=0; k<3; ++k)
00307     {
00308         double error = fabs(T[i][j][k] - T[i][k][j]);
00309         if (error>Zero) throw new Fatal("CheckSym: Third order tensor %s is not minor symmetric. error=%g",Name,error);
00310     }
00311 }
00312 
00313 #endif // MECHSYS_ANISOINVS_H
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines