MechSys  1.0
Computing library for simulations in continuum and discrete mechanics
/home/dorival/mechsys/lib/fem/usigcondelem.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 // This is the mixed u-sig element (usigelem) with the condensation of the local DOFs
00021 
00022 #ifndef MECHSYS_FEM_USIGCONDELEM_H
00023 #define MECHSYS_FEM_USIGCONDELEM_H
00024 
00025 // MechSys
00026 #include <mechsys/fem/element.h>
00027 #include <mechsys/models/equilibstate.h>
00028 #include <mechsys/models/stressupdate.h>
00029 
00030 namespace FEM
00031 {
00032 
00033 class USigCondElem : public Element
00034 {
00035 public:
00036     // static
00037     static size_t NCo; 
00038     static size_t NDs; 
00039     static size_t NDu; 
00040 
00041     // Constructor
00042     USigCondElem (int                  NDim,   
00043                   Mesh::Cell   const & Cell,   
00044                   Model        const * Mdl,    
00045                   Model        const * XMdl,   
00046                   SDPair       const & Prp,    
00047                   SDPair       const & Ini,    
00048                   Array<Node*> const & Nodes); 
00049 
00050     // Destructor
00051     ~USigCondElem () { if (GEs!=NULL) delete GEs; }
00052 
00053     // Methods
00054     void GetLoc      (Array<size_t> & Loc)                               const; 
00055     void SetBCs      (size_t IdxEdgeOrFace, SDPair const & BCs, BCFuncs * BCF); 
00056     void CalcK       (Mat_t & K)                                         const; 
00057     void CalcFint    (Vec_t * F_int=NULL)                                const; 
00058     void UpdateState (Vec_t const & dU, Vec_t * F_int=NULL)              const; 
00059     void StateKeys   (Array<String> & Keys)                              const; 
00060     void StateAtIP   (SDPair & KeysVals, int IdxIP)                      const; 
00061 
00062     // Internal methods
00063     void Matrices (Mat_t & Ai, Mat_t & Q) const;
00064     void Interp   (Mat_t const & C, IntegPoint const & IP, Mat_t & B, Mat_t & N, Mat_t & Nsig, double & detJ, double & Coef) const; 
00065 
00066     // Constants
00067     GeomElem   * GEs;        
00068     mutable long FirstEQsig; 
00069 };
00070 
00071 size_t USigCondElem::NCo = 0;
00072 size_t USigCondElem::NDs = 0;
00073 size_t USigCondElem::NDu = 0;
00074 
00075 
00077 
00078 
00079 inline USigCondElem::USigCondElem (int NDim, Mesh::Cell const & Cell, Model const * Mdl, Model const * XMdl, SDPair const & Prp, SDPair const & Ini, Array<Node*> const & Nodes)
00080     : Element(NDim,Cell,Mdl,XMdl,Prp,Ini,Nodes)
00081 {
00082     // check GE
00083     if (GE==NULL)   throw new Fatal("USigCondElem::USigCondElem: GE (geometry element) must be defined");
00084     if (GTy==pse_t) throw new Fatal("USigCondElem::USigCondElem: This element does not work for plane-stress (pse)");
00085     if (Mdl==NULL)  throw new Fatal("USigCondElem::USigCondElem: Model must be defined");
00086 
00087     // local nodes
00088     if (strcmp(GE->Name.CStr(),"Quad8")==0) GEs = AllocGeomElem ("Quad4", NDim);
00089     else throw new Fatal("USigCondElem::USigCondElem: GE must be Quad8 for the time being");
00090 
00091     // set constants of this class (once)
00092     if (NDs==0)
00093     {
00094         NCo = 2*NDim;
00095         NDs = NCo*GEs->NN;
00096         NDu = NDim*GE->NN;
00097     }
00098 
00099     // allocate and initialize state at each local node
00100     for (size_t i=0; i<GEs->NN; ++i)
00101     {
00102         Sta.Push (new EquilibState(NDim));
00103         Mdl->InitIvs (Ini, Sta[i]); // initialize with effective stresses
00104     }
00105 
00106     // set F in nodes due to initial stresses
00107     double detJ, coef;
00108     Mat_t C, B, N, Ns;
00109     Vec_t Fe(NDu);
00110     CoordMatrix (C);
00111     set_to_zero (Fe);
00112     for (size_t i=0; i<GE->NIP; ++i)
00113     {
00114         Interp (C, GE->IPs[i], B, N, Ns, detJ, coef);
00115         Vec_t const & sig = static_cast<EquilibState const *>(Sta[i])->Sig;
00116         Fe += (coef) * trans(B)*sig;
00117     }
00118     for (size_t i=0; i<GE->NN; ++i)
00119     {
00120         Con[i]->F("fx") += Fe(0+i*NDim);
00121         Con[i]->F("fy") += Fe(1+i*NDim);  if (NDim==3)
00122         Con[i]->F("fz") += Fe(2+i*NDim);
00123     }
00124 }
00125 
00126 inline void USigCondElem::SetBCs (size_t IdxEdgeOrFace, SDPair const & BCs, BCFuncs * BCF)
00127 {
00128     // deactivate/activate commands
00129     if (BCs.HasKey("deactivate")) throw new Fatal("USigCondElem::SetBCs: 'deactivate' command failed: method not implemented yet");
00130     if (BCs.HasKey("activate"))   throw new Fatal("USigCondElem::SetBCs: 'activate' command failed: method not implemented yet");
00131 
00132     // check
00133     if (!Active) throw new Fatal("USigCondElem::SetBCs: Element %d is inactive",Cell.ID);
00134 
00135     bool has_bx  = BCs.HasKey("bx");  // x component of body force
00136     bool has_by  = BCs.HasKey("by");  // y component of body force
00137     bool has_bz  = BCs.HasKey("bz");  // z component of body force
00138     bool has_cbx = BCs.HasKey("cbx"); // centrifugal body force along x (in axisymmetric problems)
00139     bool has_qx  = BCs.HasKey("qx");  // x component of distributed loading
00140     bool has_qy  = BCs.HasKey("qy");  // y component of distributed loading
00141     bool has_qz  = BCs.HasKey("qz");  // z component of distributed loading
00142     bool has_qn  = BCs.HasKey("qn");  // normal distributed loading
00143     bool has_qt  = BCs.HasKey("qt");  // tangential distributed loading (2D only)
00144     bool has_ux  = BCs.HasKey("ux");  // x displacement
00145     bool has_uy  = BCs.HasKey("uy");  // y displacement
00146     bool has_uz  = BCs.HasKey("uz");  // z displacement
00147     bool has_sup = BCs.HasKey("incsup");  // inclined support
00148 
00149     // force components specified
00150     if (has_bx || has_by || has_bz || has_cbx || 
00151         has_qx || has_qy || has_qz || has_qn  || has_qt)
00152     {
00153         // body forces
00154         if (has_bx || has_by || has_bz || has_cbx) // prescribed body forces
00155         {
00156             // matrix of coordinates of nodes
00157             Mat_t C;
00158             CoordMatrix (C);
00159             
00160             // loading
00161             double bx = (has_bx  ? BCs("bx")  : 0.0);
00162             double by = (has_by  ? BCs("by")  : 0.0);
00163             double bz = (has_bz  ? BCs("bz")  : 0.0);
00164                    bx = (has_cbx ? BCs("cbx") : bx );
00165 
00166             // set
00167             for (size_t i=0; i<GE->NIP; ++i)
00168             {
00169                 // geometric data
00170                 GE->Shape  (GE->IPs[i].r, GE->IPs[i].s, GE->IPs[i].t);
00171                 GE->Derivs (GE->IPs[i].r, GE->IPs[i].s, GE->IPs[i].t);
00172 
00173                 // Jacobian and its determinant
00174                 Mat_t J(GE->dNdR * C); // J = dNdR * C
00175                 double detJ = Det(J);
00176 
00177                 // coefficient used during integration
00178                 double coef = detJ*GE->IPs[i].w;
00179                 if (GTy==axs_t)
00180                 {
00181                     // calculate radius=x at this IP
00182                     double radius = 0.0;
00183                     for (size_t j=0; j<GE->NN; ++j) radius += GE->N(j)*Con[j]->Vert.C[0];
00184 
00185                     // correct coef
00186                     if (has_cbx) coef *= radius*radius;
00187                     else         coef *= radius;
00188                 }
00189 
00190                 // set boundary conditions
00191                 for (size_t j=0; j<GE->NN; ++j)
00192                 {
00193                     Con[j]->AddToPF("fx", coef*GE->N(j)*bx, BCF);
00194                     Con[j]->AddToPF("fy", coef*GE->N(j)*by, BCF);  if (NDim==3)
00195                     Con[j]->AddToPF("fz", coef*GE->N(j)*bz, BCF);
00196                 }
00197             }
00198         }
00199 
00200         // surface loading
00201         if (has_qx || has_qy || has_qz || has_qn  || has_qt)
00202         {
00203             // matrix of coordinates of edge/face
00204             Mat_t Cf;
00205             FCoordMatrix (IdxEdgeOrFace, Cf);
00206 
00207             // loading
00208             double qx = (has_qx ? BCs("qx") : 0.0);
00209             double qy = (has_qy ? BCs("qy") : 0.0);
00210             double qz = (has_qz ? BCs("qz") : 0.0);
00211             double qn = (has_qn ? BCs("qn") : 0.0);
00212             double qt = (has_qt ? BCs("qt") : 0.0);
00213 
00214             // set
00215             for (size_t i=0; i<GE->NFIP; ++i)
00216             {
00217                 // geometric data
00218                 GE->FaceShape  (GE->FIPs[i].r, GE->FIPs[i].s);
00219                 GE->FaceDerivs (GE->FIPs[i].r, GE->FIPs[i].s);
00220 
00221                 // face/edge Jacobian and its determinant
00222                 Mat_t J(GE->FdNdR * Cf);
00223 
00224                 // coefficient used during integration
00225                 double coef = GE->FIPs[i].w; // *detJ is not necessary since qx,qy,qz are already multiplied by detJ (due to normal)
00226 
00227                 if (GTy==axs_t)
00228                 {
00229                     // calculate radius=x at this FIP
00230                     double radius = 0.0;
00231                     for (size_t j=0; j<GE->NFN; ++j) radius += GE->FN(j)*Con[GE->FNode(IdxEdgeOrFace,j)]->Vert.C[0];
00232                     coef *= radius; // correct coef
00233                 }
00234 
00235                 // calculate qx, qy and qz from qn and qt
00236                 if (has_qn || has_qt)
00237                 {
00238                     // normal to edge/face
00239                     Vec_t n(NDim); // normal multiplied by detJ
00240                     if (NDim==2) n = J(0,1), -J(0,0);
00241                     else
00242                     {
00243                         // vectorial product
00244                         Vec_t a(3);  a = J(0,0), J(0,1), J(0,2);
00245                         Vec_t b(3);  b = J(1,0), J(1,1), J(1,2);
00246                         n = a(1)*b(2) - a(2)*b(1),
00247                             a(2)*b(0) - a(0)*b(2),
00248                             a(0)*b(1) - a(1)*b(0);
00249                     }
00250 
00251                     // loading
00252                     if (NDim==2)
00253                     {
00254                         qx = n(0)*qn - n(1)*qt;
00255                         qy = n(1)*qn + n(0)*qt;
00256                     }
00257                     else
00258                     {
00259                         qx = n(0)*qn;
00260                         qy = n(1)*qn;
00261                         qz = n(2)*qn;
00262                     }
00263                 }
00264 
00265                 // set boundary conditions
00266                 for (size_t j=0; j<GE->NFN; ++j)
00267                 {
00268                     size_t k = GE->FNode(IdxEdgeOrFace,j);
00269                     Con[k]->AddToPF("fx", coef*GE->FN(j)*qx, BCF);
00270                     Con[k]->AddToPF("fy", coef*GE->FN(j)*qy, BCF);  if (NDim==3)
00271                     Con[k]->AddToPF("fz", coef*GE->FN(j)*qz, BCF);
00272                 }
00273             }
00274         }
00275     }
00276 
00277     // prescribed displacements
00278     else if (has_ux || has_uy || has_uz || has_sup)
00279     {
00280         double ux = (has_ux ? BCs("ux") : 0.0);
00281         double uy = (has_uy ? BCs("uy") : 0.0);
00282         double uz = (has_uz ? BCs("uz") : 0.0);
00283         double alpha = (has_sup ? BCs("alpha") : 0.0);
00284         for (size_t j=0; j<GE->NFN; ++j)
00285         {
00286             size_t k = GE->FNode(IdxEdgeOrFace,j);
00287             if (has_ux) Con[k]->SetPU("ux", ux, BCF);
00288             if (has_uy) Con[k]->SetPU("uy", uy, BCF);
00289             if (has_uz) Con[k]->SetPU("uz", uz, BCF);
00290             if (has_sup) Con[k]->SetIncSup (alpha);
00291         }
00292     }
00293 }
00294 
00295 inline void USigCondElem::GetLoc (Array<size_t> & Loc) const
00296 {
00297     Loc.Resize (NDu);
00298     for (size_t i=0; i<GE->NN; ++i)
00299     {
00300         Loc[i*NDim+0] = Con[i]->Eq("ux");
00301         Loc[i*NDim+1] = Con[i]->Eq("uy");  if (NDim==3)
00302         Loc[i*NDim+2] = Con[i]->Eq("uz");
00303     }
00304 }
00305 
00306 inline void USigCondElem::Matrices (Mat_t & Ai, Mat_t & Q) const
00307 {
00308     // submatrices
00309     Q.change_dim (NDs,NDu);
00310     set_to_zero  (Q);
00311 
00312     // auxiliar matrices
00313     double detJ, coef;
00314     Mat_t NtDiN  (NDs,NDs);
00315     Mat_t NtB    (NDs,NDu);
00316     Mat_t N, Nsig, A(NDs,NDs), B, C, D(NCo,NCo), Di;
00317     CoordMatrix  (C);
00318     set_to_zero  (A);
00319 
00320     double E  = 1000.0;
00321     double nu = 0.2;
00322     double c  = E/((1.0+nu)*(1.0-2.0*nu));
00323     D = c*(1.0-nu),       c*nu ,      c*nu ,            0.0,
00324              c*nu ,  c*(1.0-nu),      c*nu ,            0.0,
00325              c*nu ,       c*nu , c*(1.0-nu),            0.0,
00326               0.0 ,        0.0 ,       0.0 , c*(1.0-2.0*nu);
00327 
00328     for (size_t i=0; i<GE->NIP; ++i)
00329     {
00330         Interp (C, GE->IPs[i], B, N, Nsig, detJ, coef);
00331 
00332         Inv (D, Di);
00333 
00334         NtDiN = trans(Nsig)*Di*Nsig;
00335         NtB   = trans(Nsig)*B;
00336         A    -= (coef)     * NtDiN;
00337         Q    += (coef)     * NtB;
00338     }
00339     
00340     Inv (A, Ai);
00341 }
00342 
00343 inline void USigCondElem::CalcK (Mat_t & K) const
00344 {
00345   Mat_t Ai, Q;
00346   Matrices (Ai, Q);
00347   K.change_dim (NDu,NDu);
00348   
00349   K = (-1.)*trans(Q)*Ai*Q;
00350 }
00351 
00352 inline void USigCondElem::Interp (Mat_t const & C, IntegPoint const & IP, Mat_t & B, Mat_t & N, Mat_t & Nsig, double & detJ, double & Coef) const
00353 {
00354     // deriv of shape func w.r.t natural coordinates
00355     GE ->Shape  (IP.r, IP.s, IP.t);
00356     GE ->Derivs (IP.r, IP.s, IP.t);
00357     GEs->Shape  (IP.r, IP.s, IP.t);
00358 
00359     // Jacobian and its determinant
00360     Mat_t J(GE->dNdR * C); // J = dNdR * C
00361     detJ = Det(J);
00362 
00363     // deriv of shape func w.r.t real coordinates
00364     Mat_t Ji;
00365     Inv (J, Ji);
00366     Mat_t dNdX(Ji * GE->dNdR); // dNdX = Inv(J) * dNdR
00367 
00368     // coefficient used during integration
00369     Coef = detJ*IP.w;
00370 
00371     // B matrix
00372     B.change_dim (NCo,NDu);
00373     set_to_zero  (B);
00374     if (NDim==2)
00375     {
00376         if (GTy==axs_t)
00377         {
00378             // correct Coef
00379             double radius = 0.0; // radius=x at this IP
00380             for (size_t j=0; j<GE->NN; ++j) radius += GE->N(j)*Con[j]->Vert.C[0];
00381             Coef *= radius;
00382 
00383             // B matrix
00384             for (size_t i=0; i<GE->NN; ++i)
00385             {
00386                 B(0,0+i*NDim) = dNdX(0,i);
00387                 B(1,1+i*NDim) = dNdX(1,i);
00388                 B(2,0+i*NDim) = GE->N(i)/radius;
00389                 B(3,0+i*NDim) = dNdX(1,i)/sqrt(2.0);
00390                 B(3,1+i*NDim) = dNdX(0,i)/sqrt(2.0);
00391             }
00392         }
00393         else // pse_t, psa_t
00394         {
00395             for (size_t i=0; i<GE->NN; ++i)
00396             {
00397                 B(0,0+i*NDim) = dNdX(0,i);
00398                 B(1,1+i*NDim) = dNdX(1,i);
00399                 B(3,0+i*NDim) = dNdX(1,i)/sqrt(2.0);
00400                 B(3,1+i*NDim) = dNdX(0,i)/sqrt(2.0);
00401             }
00402         }
00403     }
00404     else // 3D
00405     {
00406         for (size_t i=0; i<GE->NN; ++i)
00407         {
00408             B(0,0+i*NDim) = dNdX(0,i);
00409             B(1,1+i*NDim) = dNdX(1,i);
00410             B(2,2+i*NDim) = dNdX(2,i);
00411             B(3,0+i*NDim) = dNdX(1,i)/sqrt(2.0);   B(3,1+i*NDim) = dNdX(0,i)/sqrt(2.0);
00412             B(4,1+i*NDim) = dNdX(2,i)/sqrt(2.0);   B(4,2+i*NDim) = dNdX(1,i)/sqrt(2.0);
00413             B(5,2+i*NDim) = dNdX(0,i)/sqrt(2.0);   B(5,0+i*NDim) = dNdX(2,i)/sqrt(2.0);
00414         }
00415     }
00416 
00417     // N matrix
00418     N.change_dim (NDim,NDu);
00419     set_to_zero  (N);
00420     for (int    i=0; i<NDim;   ++i)
00421     for (size_t j=0; j<GE->NN; ++j)
00422         N(i,i+j*NDim) = GE->N(j);
00423 
00424     // Nsig matrix
00425     Nsig.change_dim (NCo,NDs);
00426     set_to_zero     (Nsig);
00427     for (size_t i=0; i<NCo;     ++i)
00428     for (size_t j=0; j<GEs->NN; ++j)
00429         Nsig(i,i+j*NCo) = GEs->N(j);
00430 }
00431 
00432 inline void USigCondElem::UpdateState (Vec_t const & dU, Vec_t * F_int) const
00433 {
00434 }
00435 
00436 inline void USigCondElem::StateKeys (Array<String> & Keys) const
00437 {
00438 }
00439 
00440 inline void USigCondElem::StateAtIP (SDPair & KeysVals, int IdxIP) const
00441 {
00442 }
00443 
00444 
00446 
00447 
00448 // Allocate a new element
00449 Element * USigCondMaker(int NDim, Mesh::Cell const & Cell, Model const * Mdl, Model const * XMdl, SDPair const & Prp, SDPair const & Ini, Array<Node*> const & Nodes) { return new USigCondElem(NDim,Cell,Mdl,XMdl,Prp,Ini,Nodes); }
00450 
00451 // Register element
00452 int USigCondRegister()
00453 {
00454     ElementFactory["USigCond"]   = USigCondMaker;
00455     ElementVarKeys["USigCond2D"] = std::make_pair ("ux uy",    "fx fy");
00456     ElementVarKeys["USigCond3D"] = std::make_pair ("ux uy uz", "fx fy fz");
00457     PROB.Set ("USigCond", (double)PROB.Keys.Size());
00458     return 0;
00459 }    
00460  
00461 // Call register
00462 int __USigCond_dummy_int  = USigCondRegister();
00463  
00464 }; // namespace FEM
00465 
00466 #endif // MECHSYS_FEM_USIGCONDELEM_H
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines