MechSys  1.0
Computing library for simulations in continuum and discrete mechanics
/home/dorival/mechsys/lib/fem/flowelem.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_FEM_FLOWELEM_H
00021 #define MECHSYS_FEM_FLOWELEM_H
00022 
00023 // Std Lib
00024 #include <map>
00025 
00026 // MechSys
00027 #include <mechsys/fem/element.h>
00028 #include <mechsys/models/flowstate.h>
00029 #include <mechsys/models/flowupdate.h>
00030 
00031 namespace FEM
00032 {
00033 
00034 class FlowElem : public Element
00035 {
00036 public:
00037     // Constructor
00038     FlowElem (int                  NDim,   
00039               Mesh::Cell   const & Cell,   
00040               Model        const * Mdl,    
00041               Model        const * XMdl,   
00042               SDPair       const & Prp,    
00043               SDPair       const & Ini,    
00044               Array<Node*> const & Nodes); 
00045 
00046     // Methods
00047     void SetBCs      (size_t IdxEdgeOrFace, SDPair const & BCs, BCFuncs * BCF); 
00048     void ClrBCs      ();                                                        
00049     void GetLoc      (Array<size_t> & Loc)                               const; 
00050     void CalcK       (Mat_t & K)                                         const; 
00051     void CalcM       (Mat_t & M)                                         const; 
00052     void UpdateState (Vec_t const & dU, Vec_t * F_int=NULL)              const; 
00053     void StateKeys   (Array<String> & Keys)                              const; 
00054     void StateAtIP   (SDPair & KeysVals, int IdxIP)                      const; 
00055 
00056     // Internal methods
00057     void Interp (Mat_t const & C, IntegPoint const & IP, Mat_t & B, Mat_t & N, double & detJ, double & Coef) const; 
00058 
00059     // Data
00060     bool                 HasConv; // Has convection ?
00061     bool                 HasPer;  // Hsa convection along perimeter ? (line elements only)
00062     std::map<int,double> Bry2h;   // Map: boundary (edge/face) ID ==> to convection coefficient (h)
00063     double               rho;     // Coefficient for mass matrix
00064     double               hPer;    // h*Perimeter (if HasPer==true) (line elements only)
00065     double               A;       // cross-sectional area (line elements only)
00066 };
00067 
00068 
00070 
00071 
00072 inline FlowElem::FlowElem (int NDim, Mesh::Cell const & Cell, Model const * Mdl, Model const * XMdl, SDPair const & Prp, SDPair const & Ini, Array<Node*> const & Nodes)
00073     : Element(NDim,Cell,Mdl,XMdl,Prp,Ini,Nodes), HasConv(false), HasPer(false), rho(1.0), hPer(0.0), A(1.0)
00074 {
00075     // check
00076     if (GE==NULL)  throw new Fatal("FlowElem::FlowElem: GE (geometry element) must be defined");
00077     if (Mdl==NULL) throw new Fatal("FlowElem::FlowElem: Model must be defined");
00078 
00079     // check GTy
00080          if (NDim==2 && GTy==d2d_t) { /*OK*/ }
00081     else if (NDim==3 && GTy==d3d_t) { /*OK*/ }
00082     else throw new Fatal("FlowElem::FlowElem: For NDim=%d, geometry type (GTy) must be equal to 'd%dd'. GTy=%s is invalid",NDim,NDim,GTypeToStr(GTy).CStr());
00083 
00084     // properties
00085     if (Prp.HasKey("rho")) rho = Prp("rho");
00086     if (Prp.HasKey("A"))   A   = Prp("A");
00087 
00088     // allocate and initialize state at each IP
00089     for (size_t i=0; i<GE->NIP; ++i)
00090     {
00091         Sta.Push (new FlowState(NDim));
00092         Mdl->InitIvs (Ini, Sta[i]);
00093     }
00094 }
00095 
00096 inline void FlowElem::SetBCs (size_t IdxEdgeOrFace, SDPair const & BCs, BCFuncs * BCF)
00097 {
00098     bool has_s    = BCs.HasKey("s");    // source term
00099     bool has_H    = BCs.HasKey("hh");   // potential
00100     bool has_flux = BCs.HasKey("flux"); // flux
00101     bool has_conv = BCs.HasKey("conv"); // convection
00102     bool has_per  = BCs.HasKey("per");  // perimeter (length) in which convection is applied (line element only)
00103 
00104     if (has_s || has_flux || has_conv)
00105     {
00106         // source term
00107         if (has_s)
00108         {
00109             double detJ, coef;
00110             double s = BCs("s");
00111             Mat_t C;
00112             CoordMatrix (C);
00113             for (size_t i=0; i<GE->NIP; ++i)
00114             {
00115                 CalcShape (C, GE->IPs[i], detJ, coef);
00116                 for (size_t j=0; j<GE->NN; ++j)
00117                 {
00118                     Con[j]->AddToPF("qq", s*coef*GE->N(j), BCF);
00119                 }
00120             }
00121         }
00122 
00123         // flux
00124         if (has_flux)
00125         {
00126             double qn = BCs("flux");
00127             double detJ, coef;
00128             Mat_t FC;
00129             FCoordMatrix (IdxEdgeOrFace, FC);
00130             for (size_t i=0; i<GE->NFIP; ++i)
00131             {
00132                 CalcFaceShape (FC, GE->FIPs[i], detJ, coef);
00133                 for (size_t j=0; j<GE->NFN; ++j)
00134                 {
00135                     size_t k = GE->FNode(IdxEdgeOrFace,j);
00136                     Con[k]->AddToPF("qq", coef*GE->FN(j)*qn, BCF);
00137                 }
00138             }
00139         }
00140 
00141         // convection
00142         else if (has_conv)
00143         {
00144             // data
00145             double h    = BCs("h");    // convection coefficient
00146             double Tinf = BCs("Tinf"); // temperature of surrounding environment
00147 
00148             // convection along perimeter
00149             if (has_per)
00150             {
00151                 hPer   = h * BCs("per");
00152                 HasPer = true;
00153                 if (GE->NN==2)
00154                 {
00155                     Vec3_t dl(Con[1]->Vert.C - Con[0]->Vert.C);
00156                     double l = norm(dl);
00157                     Con[0]->AddToPF("qq", hPer*l*Tinf/2.0, BCF);
00158                     Con[1]->AddToPF("qq", hPer*l*Tinf/2.0, BCF);
00159                 }
00160                 else throw new Fatal("FlowElem::SetBCs: per (perimiter) must be used for convection in Line elments only");
00161             }
00162 
00163             // convection at boundaries
00164             else
00165             {
00166                 Bry2h[IdxEdgeOrFace] = h;    // Map: bry => h
00167                 HasConv              = true; // has convection
00168             }
00169 
00170             // add to pF
00171             double detJ, coef;
00172             Mat_t FC;
00173             FCoordMatrix (IdxEdgeOrFace, FC);
00174             for (size_t i=0; i<GE->NFIP; ++i)
00175             {
00176                 CalcFaceShape (FC, GE->FIPs[i], detJ, coef);
00177                 for (size_t j=0; j<GE->NFN; ++j)
00178                 {
00179                     size_t k = GE->FNode(IdxEdgeOrFace,j);
00180                     Con[k]->AddToPF("qq", coef*GE->FN(j)*h*Tinf, BCF);
00181                 }
00182             }
00183         }
00184     }
00185 
00186     // potential
00187     else if (has_H)
00188     {
00189         double H = BCs("hh");
00190         for (size_t j=0; j<GE->NFN; ++j)
00191         {
00192             size_t k = GE->FNode(IdxEdgeOrFace,j);
00193             Con[k]->SetPU("hh", H, BCF);
00194         }
00195     }
00196 }
00197 
00198 inline void FlowElem::ClrBCs ()
00199 {
00200     HasConv = false;
00201     Bry2h.clear();
00202 }
00203 
00204 inline void FlowElem::GetLoc (Array<size_t> & Loc) const
00205 {
00206     Loc.Resize (GE->NN);
00207     for (size_t i=0; i<GE->NN; ++i) Loc[i] = Con[i]->Eq("hh");
00208 }
00209 
00210 inline void FlowElem::CalcK (Mat_t & K) const
00211 {
00212     double detJ, coef;
00213     Mat_t C, D, B, N;
00214     int nrows = Con.Size(); // number of rows in local K matrix
00215     K.change_dim (nrows,nrows);
00216     set_to_zero  (K);
00217     CoordMatrix  (C);
00218     for (size_t i=0; i<GE->NIP; ++i)
00219     {
00220         Mdl->Stiffness (Sta[i], D);
00221         Interp (C, GE->IPs[i], B, N, detJ, coef);
00222         Mat_t BtDB(trans(B)*D*B);
00223         K += (A*coef) * BtDB;
00224 
00225         // convection along perimeter (line elements)
00226         if (HasPer)
00227         {
00228             CalcShape (C, GE->IPs[i], detJ, coef);
00229             Mat_t NtN(trans(N)*N);
00230             K += (hPer*coef) * NtN;
00231         }
00232     }
00233 
00234     // convection at boundaries
00235     if (HasConv)
00236     {
00237         for (std::map<int,double>::const_iterator p=Bry2h.begin(); p!=Bry2h.end(); ++p)
00238         {
00239             int    idx_bry = p->first;
00240             double h       = p->second;
00241 
00242             // add to K
00243             Mat_t FC;
00244             FCoordMatrix (idx_bry, FC);
00245             for (size_t i=0; i<GE->NFIP; ++i)
00246             {
00247                 CalcFaceShape (FC, GE->FIPs[i], detJ, coef);
00248                 for (size_t j=0; j<GE->NFN; ++j)
00249                 {
00250                     int row = GE->FNode(idx_bry,j);
00251                     for (size_t k=0; k<GE->NFN; ++k)
00252                     {
00253                         int col = GE->FNode(idx_bry,k);
00254                         K(row,col) += h*coef * GE->FN(j)*GE->FN(k);
00255                     }
00256                 }
00257             }
00258         }
00259     }
00260 }
00261 
00262 inline void FlowElem::CalcM (Mat_t & M) const
00263 {
00264     double detJ, coef;
00265     Mat_t C;
00266     int nrows = Con.Size(); // number of rows in local K matrix
00267     M.change_dim (nrows,nrows);
00268     set_to_zero  (M);
00269     CoordMatrix  (C);
00270     for (size_t i=0; i<GE->NIP; ++i)
00271     {
00272         CalcShape (C, GE->IPs[i], detJ, coef);
00273         for (size_t j=0; j<GE->NN; ++j)
00274         {
00275             for (size_t k=0; k<GE->NN; ++k)
00276             {
00277                 M(j,k) += (A*rho*coef)*GE->N(j)*GE->N(k);
00278             }
00279         }
00280     }
00281 }
00282 
00283 inline void FlowElem::Interp (Mat_t const & C, IntegPoint const & IP, Mat_t & B, Mat_t & N, double & detJ, double & Coef) const
00284 {
00285     // deriv of shape func w.r.t natural coordinates
00286     GE->Shape  (IP.r, IP.s, IP.t);
00287     GE->Derivs (IP.r, IP.s, IP.t);
00288 
00289     // Jacobian and its determinant
00290     Mat_t J(GE->dNdR * C); // J = dNdR * C
00291     detJ = Det(J);
00292 
00293     // deriv of shape func w.r.t real coordinates
00294     Mat_t Ji;
00295     Inv (J, Ji);
00296 
00297     // coefficient used during integration
00298     Coef = detJ*IP.w;
00299 
00300     // B matrix
00301     int nrows = Con.Size(); // number of rows in local K matrix
00302     B.change_dim (NDim,nrows);
00303     B = Ji * GE->dNdR; // B = dNdX = Inv(J) * dNdR
00304 
00305     // N matrix
00306     N.change_dim (1,nrows);
00307     for (size_t j=0; j<GE->NN; ++j) N(0,j) = GE->N(j);
00308 }
00309 
00310 inline void FlowElem::UpdateState (Vec_t const & dU, Vec_t * F_int) const
00311 {
00312     // get location array
00313     Array<size_t> loc;
00314     GetLoc (loc);
00315 
00316     // element nodal potential
00317     int nrows = Con.Size(); // number of rows in local K matrix
00318     Vec_t dUe(nrows);
00319     for (size_t i=0; i<loc.Size(); ++i) dUe(i) = dU(loc[i]);
00320 
00321     // update state at each IP
00322     FlowUpdate fu(Mdl);
00323     double detJ, coef;
00324     Mat_t  C, B, N;
00325     Vec_t  dFe(nrows), dvel(NDim), dgra(NDim);
00326     set_to_zero (dFe);
00327     CoordMatrix (C);
00328     for (size_t i=0; i<GE->NIP; ++i)
00329     {
00330         // B matrix
00331         Interp (C, GE->IPs[i], B, N, detJ, coef);
00332 
00333         // velocity and gradient increments
00334         dgra = B * dUe;
00335         fu.Update (dgra, Sta[i], dvel);
00336 
00337         // element nodal forces
00338         Vec_t Btdvel(trans(B)*dvel);
00339         dFe -= (A*coef) * (Btdvel); // '-=' because dvel is -k*dgra
00340 
00341         // convection along perimeter (line elements)
00342         if (HasPer)
00343         {
00344             Mat_t NtN(trans(N)*N);
00345             dFe += (hPer*coef) * NtN * dUe;
00346         }
00347     }
00348 
00349     // add contribution to dFe due to convection term
00350     if (HasConv)
00351     {
00352         for (std::map<int,double>::const_iterator p=Bry2h.begin(); p!=Bry2h.end(); ++p)
00353         {
00354             int    idx_bry = p->first;
00355             double h       = p->second;
00356 
00357             // add to dFe
00358             Mat_t FC;
00359             FCoordMatrix (idx_bry, FC);
00360             for (size_t i=0; i<GE->NFIP; ++i)
00361             {
00362                 CalcFaceShape (FC, GE->FIPs[i], detJ, coef);
00363                 for (size_t j=0; j<GE->NFN; ++j)
00364                 {
00365                     int row = GE->FNode(idx_bry,j);
00366                     for (size_t k=0; k<GE->NFN; ++k)
00367                     {
00368                         int col = GE->FNode(idx_bry,k);
00369                         dFe(row) += h*coef * GE->FN(j)*GE->FN(k) * dUe(col);
00370                     }
00371                 }
00372             }
00373         }
00374     }
00375 
00376     // add results to Fint (internal forces)
00377     if (F_int!=NULL) for (size_t i=0; i<loc.Size(); ++i) (*F_int)(loc[i]) += dFe(i);
00378 }
00379 
00380 inline void FlowElem::StateKeys (Array<String> & Keys) const
00381 {
00382     Keys.Resize (2*NDim + Mdl->NIvs);
00383     size_t k=0;
00384     Keys[k++] = "vx";
00385     Keys[k++] = "vy";
00386     if (NDim==3)
00387     {
00388         Keys[k++] = "vz";
00389     }
00390     Keys[k++] = "gx";
00391     Keys[k++] = "gy";
00392     if (NDim==3)
00393     {
00394         Keys[k++] = "gz";
00395     }
00396     for (size_t i=0; i<Mdl->NIvs; ++i) Keys[k++] = Mdl->IvNames[i];
00397 }
00398 
00399 inline void FlowElem::StateAtIP (SDPair & KeysVals, int IdxIP) const
00400 {
00401     Vec_t const & vel = static_cast<FlowState const *>(Sta[IdxIP])->Vel;
00402     Vec_t const & gra = static_cast<FlowState const *>(Sta[IdxIP])->Gra;
00403 
00404     if (NDim==2)
00405     {
00406         KeysVals.Set("vx vy  gx gy",
00407                      vel(0), vel(1),
00408                      gra(0), gra(1));
00409     }
00410     else
00411     {
00412         KeysVals.Set("vx vy vz  gx gy gz",
00413                      vel(0), vel(1), vel(2),
00414                      gra(0), gra(1), gra(2));
00415     }
00416 }
00417 
00418 
00420 
00421 
00422 // Allocate a new element
00423 Element * FlowElemMaker(int NDim, Mesh::Cell const & Cell, Model const * Mdl, Model const * XMdl, SDPair const & Prp, SDPair const & Ini, Array<Node*> const & Nodes) { return new FlowElem(NDim,Cell,Mdl,XMdl,Prp,Ini,Nodes); }
00424 
00425 // Register element
00426 int FlowElemRegister()
00427 {
00428     ElementFactory  ["Flow"]   = FlowElemMaker;
00429     ElementVarKeys  ["Flow2D"] = std::make_pair ("hh", "qq");
00430     ElementVarKeys  ["Flow3D"] = std::make_pair ("hh", "qq");
00431     ElementExtraKeys["Flow2D"] = Array<String>  ("flux", "conv");
00432     ElementExtraKeys["Flow3D"] = Array<String>  ("flux", "conv");
00433     PROB.Set ("Flow", (double)PROB.Keys.Size());
00434     return 0;
00435 }
00436 
00437 // Call register
00438 int __FlowElem_dummy_int  = FlowElemRegister();
00439 
00440 }; // namespace FEM
00441 
00442 #endif // MECHSYS_FEM_FLOWELEM
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines