MechSys  1.0
Computing library for simulations in continuum and discrete mechanics
/home/dorival/mechsys/lib/fem/uwpelem.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_UWPELEM_H
00021 #define MECHSYS_UWPELEM_H
00022 
00023 // MechSys
00024 #include <mechsys/fem/equilibelem.h>
00025 #include <mechsys/models/unsatflow.h>
00026 
00027 namespace FEM
00028 {
00029 
00030 class UWPElem : public Element
00031 {
00032 public:
00033     // typedefs
00034     typedef std::map<size_t,SDPair  > IdxToBcs_t;
00035     typedef std::map<size_t,BCFuncs*> IdxToBcf_t;
00036 
00037     // Static
00038     static size_t        NCo;     
00039     static size_t        NDu;     
00040     static size_t        NDp;     
00041     static Array<size_t> LocU;    
00042     static Array<size_t> LocWw;   
00043     static Array<size_t> LocPw;   
00044     static Mat_t         M;       
00045     static Mat_t         Mw;      
00046     static Mat_t         Hw;      
00047     static Vec_t         f;       
00048     static Vec_t         fw;      
00049     static Vec_t         hw;      
00050     static Vec_t         cw;      
00051     static Vec_t         ew;      
00052     static Mat_t         dNdX;    
00053     static Mat_t         B;       
00054     static Mat_t         Bp;      
00055     static Mat_t         N;       
00056     static Mat_t         Np;      
00057     static Vec_t         Npv;     
00058     static Mat_t         J;       
00059     static Mat_t         Ji;      
00060     static Mat_t         Jf;      
00061     static double        DetJ;    
00062     static double        Coef;    
00063     static Vec_t         V;       
00064     static Vec_t         Ww;      
00065     static Vec_t         Pw;      
00066     static Vec_t         dPwdt;   
00067     static Mat_t         Co;      
00068     static Mat_t         Cf;      
00069     static Mat_t         lw;      
00070     static Vec_t         ww;      
00071     static Vec_t         d;       
00072     static Vec_t         fwd;     
00073     static Array<String> StaKeys; 
00074 
00075     // Constructor
00076     UWPElem (int                  NDim,   
00077              Mesh::Cell   const & Cell,   
00078              Model        const * Mdl,    
00079              Model        const * XMdl,   
00080              SDPair       const & Prp,    
00081              SDPair       const & Ini,    
00082              Array<Node*> const & Nodes); 
00083 
00084     // Destructor
00085     ~UWPElem () { for (size_t i=0; i<GE->NIP; ++i) delete FSta[i]; }
00086 
00087     // Methods
00088     void SetBCs        (size_t IdxEdgeOrFace, SDPair const & BCs, BCFuncs * BCF);                      
00089     void CalcSurfLoads (double Time, Vec_t & Sl, Vec_t & Sq)  const;                                   
00090     void GetLoc        ()                                     const;                                   
00091     void ElemEqs       (double Time, Vec_t const & V_g, Vec_t const & Ww_g, Vec_t const & Pw_g) const; 
00092     void StateKeys     (Array<String> & Keys)                 const { Keys = StaKeys; }                
00093     void StateAtIP     (SDPair & KeysVals, int IdxIP)         const;                                   
00094 
00095     // Internal Methods
00096     void Interp (Mat_t const & C, IntegPoint const & IP, double h=1.0) const; 
00097 
00098     // Methods for Runge-Kutta
00099     double Update  (size_t Idx, Vec_t const & V_g, Vec_t const & dPwdt_g, double dt); 
00100     void   Restore ();                                                                
00101 
00102     // Data
00103     Array<UnsatFlowState*>         FSta;    
00104     UnsatFlow              const * FMdl;    
00105     IdxToBcs_t                     LBCs;    
00106     IdxToBcf_t                     LBCf;    
00107     bool                           HasGrav; 
00108     Vec_t                          g;       
00109 };
00110 
00111 size_t        UWPElem::NCo = 0;
00112 size_t        UWPElem::NDu = 0;
00113 size_t        UWPElem::NDp = 0;
00114 Array<size_t> UWPElem::LocU;
00115 Array<size_t> UWPElem::LocWw;
00116 Array<size_t> UWPElem::LocPw;
00117 Mat_t         UWPElem::M;
00118 Mat_t         UWPElem::Mw;
00119 Mat_t         UWPElem::Hw;
00120 Vec_t         UWPElem::f;
00121 Vec_t         UWPElem::fw;
00122 Vec_t         UWPElem::hw;
00123 Vec_t         UWPElem::cw;
00124 Vec_t         UWPElem::ew;
00125 Mat_t         UWPElem::dNdX;
00126 Mat_t         UWPElem::B;
00127 Mat_t         UWPElem::Bp;
00128 Mat_t         UWPElem::N;
00129 Mat_t         UWPElem::Np;
00130 Vec_t         UWPElem::Npv;
00131 Mat_t         UWPElem::J;
00132 Mat_t         UWPElem::Ji;
00133 Mat_t         UWPElem::Jf;
00134 double        UWPElem::DetJ;
00135 double        UWPElem::Coef;
00136 Vec_t         UWPElem::V;
00137 Vec_t         UWPElem::Ww;
00138 Vec_t         UWPElem::Pw;
00139 Vec_t         UWPElem::dPwdt;
00140 Mat_t         UWPElem::Co;
00141 Mat_t         UWPElem::Cf;
00142 Mat_t         UWPElem::lw;
00143 Vec_t         UWPElem::ww;
00144 Vec_t         UWPElem::d;
00145 Vec_t         UWPElem::fwd;
00146 Array<String> UWPElem::StaKeys;
00147 
00148 
00150 
00151 
00152 inline UWPElem::UWPElem (int NDim, Mesh::Cell const & Cell, Model const * Mdl, Model const * XMdl, SDPair const & Prp, SDPair const & Ini, Array<Node*> const & Nodes)
00153     : Element(NDim,Cell,Mdl,XMdl,Prp,Ini,Nodes),
00154       FMdl(static_cast<UnsatFlow const*>(XMdl)), HasGrav(false)
00155 {
00156     // set u-w-p element
00157     Element::IsUWP = true;
00158 
00159     // check
00160     if (GE  ==NULL) throw new Fatal("UWPElem::UWPElem: GE (geometry element) must be defined");
00161     if (Mdl ==NULL) throw new Fatal("UWPElem::UWPElem: Model must be defined");
00162     if (XMdl==NULL) throw new Fatal("UWPElem::UWPElem: E(x)tra Model (flow model) must be defined by means of 'xname' key");
00163 
00164     // gravity vector
00165     g.change_dim(NDim);
00166     set_to_zero(g);
00167 
00168     // allocate and initialize state at each IP
00169     for (size_t i=0; i<GE->NIP; ++i)
00170     {
00171         // mechanical state
00172         Sta.Push     (new EquilibState(NDim));
00173         Mdl->InitIvs (Ini, Sta[i]);
00174 
00175         // hydraulic state
00176         FSta.Push     (new UnsatFlowState(NDim));
00177         FMdl->InitIvs (Ini, FSta[i]);
00178     }
00179 
00180     // set constants of this class (just once)
00181     if (NDp==0)
00182     {
00183         NCo = 2*NDim;
00184         NDu = NDim*GE->NN;
00185         NDp = GE->NN;
00186 
00187         M .change_dim (NDu,NDu);
00188         Mw.change_dim (NDu,NDu);
00189         Hw.change_dim (NDp,NDp);
00190         f .change_dim (NDu);
00191         fw.change_dim (NDu);
00192         hw.change_dim (NDu);
00193         cw.change_dim (NDu);
00194         ew.change_dim (NDp);
00195 
00196         dNdX.change_dim (NDim, GE->NN);
00197         B   .change_dim (NCo,  NDu);
00198         Bp  .change_dim (NDim, GE->NN);
00199         N   .change_dim (NDim, NDu);
00200         Np  .change_dim (1,    NDp);
00201         Npv .change_dim (NDp);
00202 
00203         J .change_dim (NDim,   NDim);
00204         Ji.change_dim (NDim,   NDim);
00205         Jf.change_dim (NDim-1, NDim);
00206 
00207         V    .change_dim (NDu);
00208         Ww   .change_dim (NDu);
00209         Pw   .change_dim (NDp);
00210         dPwdt.change_dim (NDp);
00211 
00212         Co.change_dim (GE->NN,  NDim);
00213         Cf.change_dim (GE->NFN, NDim);
00214 
00215         lw .change_dim (NDim, NDim);
00216         ww .change_dim (NDim);
00217         d  .change_dim (NCo);
00218         fwd.change_dim (NDim);
00219 
00220         StaKeys = EquilibState::Keys;
00221         for (size_t i=0; i<Mdl->NIvs; ++i)                   StaKeys.Push (Mdl->IvNames[i]);
00222         for (size_t i=0; i<UnsatFlowState::Keys.Size(); ++i) StaKeys.Push (UnsatFlowState::Keys[i]);
00223         StaKeys.Push ("rw");
00224         StaKeys.Push ("H");
00225         StaKeys.Push ("gpwx");
00226         StaKeys.Push ("gpwy"); if (NDim==3)
00227         StaKeys.Push ("gpwz");
00228     }
00229 
00230     // set pore-water pressure at nodes (extrapolated) -- TODO: should average between shared nodes
00231     Array<SDPair> res;
00232     StateAtNodes (res);
00233     for (size_t i=0; i<GE->NN; ++i)
00234     {
00235         double pw = -res[i]("pc");
00236         Con[i]->U("pw") = pw;
00237     }
00238 }
00239 
00240 inline void UWPElem::SetBCs (size_t IdxEdgeOrFace, SDPair const & BCs, BCFuncs * BCF)
00241 {
00242     // has gravity?
00243     HasGrav = BCs.HasKey("gravity");
00244     if (HasGrav)
00245     {
00246         if (NDim==2) g = 0.0,      -BCs("gravity");
00247         else         g = 0.0, 0.0, -BCs("gravity");
00248     }
00249 
00250     // set essential BCs (do not depend on geometry shape)
00251     if (BCs.HasKey("ux"))     { for (size_t j=0; j<GE->NFN; ++j) Con[GE->FNode(IdxEdgeOrFace,j)]->SetPU("ux",  BCs("ux"),  BCF); }
00252     if (BCs.HasKey("uy"))     { for (size_t j=0; j<GE->NFN; ++j) Con[GE->FNode(IdxEdgeOrFace,j)]->SetPU("uy",  BCs("uy"),  BCF); }
00253     if (BCs.HasKey("uz"))     { for (size_t j=0; j<GE->NFN; ++j) Con[GE->FNode(IdxEdgeOrFace,j)]->SetPU("uz",  BCs("uz"),  BCF); }
00254     if (BCs.HasKey("wwx"))    { for (size_t j=0; j<GE->NFN; ++j) Con[GE->FNode(IdxEdgeOrFace,j)]->SetPU("wwx", BCs("wwx"), BCF); }
00255     if (BCs.HasKey("wwy"))    { for (size_t j=0; j<GE->NFN; ++j) Con[GE->FNode(IdxEdgeOrFace,j)]->SetPU("wwy", BCs("wwy"), BCF); }
00256     if (BCs.HasKey("wwz"))    { for (size_t j=0; j<GE->NFN; ++j) Con[GE->FNode(IdxEdgeOrFace,j)]->SetPU("wwz", BCs("wwz"), BCF); }
00257     if (BCs.HasKey("pw"))     { for (size_t j=0; j<GE->NFN; ++j) Con[GE->FNode(IdxEdgeOrFace,j)]->SetPU("pw",  BCs("pw"),  BCF); }
00258     if (BCs.HasKey("incsup")) { for (size_t j=0; j<GE->NFN; ++j) Con[GE->FNode(IdxEdgeOrFace,j)]->SetIncSup(BCs("alpha"));       }
00259 
00260     // set maps for prescribed loads
00261     bool has_qx = BCs.HasKey("qx");  // x component of distributed loading
00262     bool has_qy = BCs.HasKey("qy");  // y component of distributed loading
00263     bool has_qz = BCs.HasKey("qz");  // z component of distributed loading
00264     bool has_qn = BCs.HasKey("qn");  // normal distributed loading
00265     bool has_qt = BCs.HasKey("qt");  // tangential distributed loading (2D only)
00266     bool has_qw = BCs.HasKey("qw");  // water flux
00267     if (has_qx || has_qy || has_qz || has_qn || has_qt || has_qw)
00268     {
00269         LBCs[IdxEdgeOrFace] = BCs;
00270         LBCf[IdxEdgeOrFace] = BCF;
00271     }
00272 }
00273 
00274 inline void UWPElem::CalcSurfLoads (double Time, Vec_t & Sl, Vec_t & Sq) const
00275 {
00276     // surface load
00277     //Sl.change_dim(NDu);
00278     set_to_zero(Sl);
00279 
00280     // surface flux
00281     //Sq.change_dim(NDp);
00282     set_to_zero(Sq);
00283 
00284     for (IdxToBcs_t::const_iterator it=LBCs.begin(); it!=LBCs.end(); ++it)
00285     {
00286         // local index of edge of face
00287         size_t ief = it->first; // IdxEdgeOrFace
00288 
00289         // load multiplier
00290         IdxToBcf_t::const_iterator itt = LBCf.find(ief);
00291         double lm = (itt->second==NULL ? 1.0 : itt->second->fm(Time));
00292 
00293         // prescribed quantities
00294         bool has_qx = it->second.HasKey("qx");  // x component of distributed loading
00295         bool has_qy = it->second.HasKey("qy");  // y component of distributed loading
00296         bool has_qz = it->second.HasKey("qz");  // z component of distributed loading
00297         bool has_qn = it->second.HasKey("qn");  // normal distributed loading
00298         bool has_qt = it->second.HasKey("qt");  // tangential distributed loading (2D only)
00299         bool has_qw = it->second.HasKey("qw");  // water flux
00300 
00301         // matrix of coordinates of edge/face
00302         for (size_t i=0; i<GE->NFN; ++i)
00303         for (int    j=0; j<NDim;    ++j)
00304             Cf(i,j) = Con[GE->FNode(ief,i)]->Vert.C[j];
00305 
00306         // surface loading
00307         if (has_qx || has_qy || has_qz || has_qn || has_qt)
00308         {
00309             // loading
00310             double qx = (has_qx ? (it->second)("qx") : 0.0);
00311             double qy = (has_qy ? (it->second)("qy") : 0.0);
00312             double qz = (has_qz ? (it->second)("qz") : 0.0);
00313             double qn = (has_qn ? (it->second)("qn") : 0.0);
00314             double qt = (has_qt ? (it->second)("qt") : 0.0);
00315 
00316             // set
00317             double detJ, coef;
00318             for (size_t i=0; i<GE->NFIP; ++i)
00319             {
00320                 CalcFaceShape (Cf, GE->FIPs[i], Jf, detJ, coef);
00321                 coef /= detJ; // *detJ is not necessary since qx,qy,qz are already multiplied by detJ (due to normal)
00322 
00323                 // calculate qx, qy and qz from qn and qt
00324                 if (has_qn || has_qt)
00325                 {
00326                     // normal to edge/face
00327                     Vec_t n(NDim); // normal multiplied by detJ
00328                     if (NDim==2) n = Jf(0,1), -Jf(0,0);
00329                     else
00330                     {
00331                         // vectorial product
00332                         Vec_t a(3);  a = Jf(0,0), Jf(0,1), Jf(0,2);
00333                         Vec_t b(3);  b = Jf(1,0), Jf(1,1), Jf(1,2);
00334                         n = a(1)*b(2) - a(2)*b(1),
00335                             a(2)*b(0) - a(0)*b(2),
00336                             a(0)*b(1) - a(1)*b(0);
00337                     }
00338 
00339                     // loading
00340                     if (NDim==2)
00341                     {
00342                         qx = n(0)*qn - n(1)*qt;
00343                         qy = n(1)*qn + n(0)*qt;
00344                     }
00345                     else
00346                     {
00347                         qx = n(0)*qn;
00348                         qy = n(1)*qn;
00349                         qz = n(2)*qn;
00350                     }
00351                 }
00352 
00353                 // set boundary conditions
00354                 for (size_t j=0; j<GE->NFN; ++j)
00355                 {
00356                     size_t k = GE->FNode(ief,j);
00357                     Sl(k*NDim+0) += coef*GE->FN(j)*qx*lm;
00358                     Sl(k*NDim+1) += coef*GE->FN(j)*qy*lm;  if (NDim==3)
00359                     Sl(k*NDim+2) += coef*GE->FN(j)*qz*lm;
00360                 }
00361             }
00362         }
00363 
00364         // water flux
00365         if (has_qw)
00366         {
00367             double qw = (it->second)("qw");
00368             double detJ, coef;
00369             for (size_t i=0; i<GE->NFIP; ++i)
00370             {
00371                 CalcFaceShape (Cf, GE->FIPs[i], detJ, coef);
00372                 for (size_t j=0; j<GE->NFN; ++j)
00373                 {
00374                     size_t k = GE->FNode(ief,j);
00375                     Sq(k) += coef*GE->FN(j)*(-qw)*lm;
00376                 }
00377             }
00378         }
00379     }
00380 }
00381 
00382 inline void UWPElem::GetLoc () const
00383 {
00384     LocU .Resize (NDu);
00385     LocWw.Resize (NDu);
00386     LocPw.Resize (NDp);
00387     for (size_t i=0; i<GE->NN; ++i)
00388     {
00389         LocU [i*NDim+0] = Con[i]->Eq("ux");
00390         LocU [i*NDim+1] = Con[i]->Eq("uy");  if (NDim==3)
00391         LocU [i*NDim+2] = Con[i]->Eq("uz");
00392         LocWw[i*NDim+0] = Con[i]->Eq("wwx");
00393         LocWw[i*NDim+1] = Con[i]->Eq("wwy");  if (NDim==3)
00394         LocWw[i*NDim+2] = Con[i]->Eq("wwz");
00395         LocPw[i]        = Con[i]->Eq("pw");
00396     }
00397 }
00398 
00399 inline void UWPElem::ElemEqs (double Time, Vec_t const & V_g, Vec_t const & Ww_g, Vec_t const & Pw_g) const
00400 {
00401     // element vectors
00402     for (size_t i=0; i<GE->NN; ++i)
00403     {
00404         V (i*NDim+0) = V_g (Con[i]->Eq("ux"));
00405         V (i*NDim+1) = V_g (Con[i]->Eq("uy"));  if (NDim==3)
00406         V (i*NDim+2) = V_g (Con[i]->Eq("uz"));
00407         Ww(i*NDim+0) = Ww_g(Con[i]->Eq("wwx"));
00408         Ww(i*NDim+1) = Ww_g(Con[i]->Eq("wwy"));  if (NDim==3)
00409         Ww(i*NDim+2) = Ww_g(Con[i]->Eq("wwz"));
00410         Pw(i)        = Pw_g(Con[i]->Eq("pw"));
00411     }
00412 
00413     // clear output matrices and vectors
00414     set_to_zero (M);
00415     set_to_zero (Mw);
00416     set_to_zero (Hw);
00417     set_to_zero (fw);
00418     set_to_zero (hw);
00419     set_to_zero (cw);
00420 
00421     // surface loads
00422     CalcSurfLoads (Time, f, ew); // f=Sl  ew=Sq
00423 
00424     // coordinates matrix
00425     for (size_t i=0; i<GE->NN; ++i)
00426     for (int    j=0; j<NDim;   ++j)
00427         Co(i,j) = Con[i]->Vert.C[j];
00428 
00429     // integrate
00430     double Cpw, Cvs, trd;
00431     for (size_t i=0; i<GE->NIP; ++i)
00432     {
00433         // interpolation
00434         Interp (Co, GE->IPs[i]);
00435 
00436         // water relative velocity at IP
00437         ww = N * Ww;
00438 
00439         // calc Cpw, Cvs and fwd
00440         FMdl->TgVars (FSta[i], ww,  Cpw, Cvs, fwd);
00441 
00442         //printf("Cpw=%20.10e  Cvs=%20.10e\n", Cpw, Cvs);
00443 
00444         // values at IP
00445         double n    = FSta[i]->n;          // porosity
00446         double Sw   = FSta[i]->Sw;         // water saturation
00447         double nw   = n*Sw;                // water volume fraction
00448         double RhoW = FSta[i]->RhoW;       // real water density
00449         double RhoS = FSta[i]->RhoS;       // real solids density
00450         double rhow = nw*RhoW;             // water partial density
00451         double rho  = (1.0-n)*RhoS + rhow; // mixture density
00452 
00453         // calc lw
00454         set_to_zero (lw);
00455         for (size_t j=0; j<GE->NN; ++j)
00456         {
00457             for (int r=0; r<NDim; ++r)
00458             for (int s=0; s<NDim; ++s)
00459                 lw(r,s) += (V(j*NDim+r)+Ww(j*NDim+r)) * dNdX(s,j);
00460         }
00461 
00462         // solids rate of deformation
00463         d   = B * V;
00464         trd = Tra(d);
00465 
00466         // vectors
00467         f  += (Coef * rho)     * trans(N)  * g;
00468         f  -= (Coef)           * trans(B)  * static_cast<EquilibState*>(Sta[i])->Sig;
00469         cw += (Coef * rhow)    * trans(N)  * lw * ww;
00470         hw += (Coef * nw)      * trans(N)  * Bp * Pw;
00471         fw += (Coef)           * trans(N)  * fwd;
00472         fw += (Coef * rhow)    * trans(N)  * g;
00473         ew += (Coef * rhow)    * trans(Bp) * ww;
00474         ew -= (Coef * Cvs*trd) * Npv;
00475 
00476         // matrices
00477         M  += (Coef * rho)  * trans(N)  * N;
00478         Mw += (Coef * rhow) * trans(N)  * N;
00479         Hw += (Coef * Cpw)  * trans(Np) * Np;
00480     }
00481 
00482     printf("t = %5.3e\n", Time);
00483     std::cout << "Hw =\n" << PrintMatrix(Hw, "%20.10e");
00484 }
00485 
00486 inline void UWPElem::StateAtIP (SDPair & KeysVals, int IdxIP) const
00487 {
00488     // check
00489     if (FSta[IdxIP]->Sw<0.0) throw new Fatal("UWPElem::StateAtIP: Sw<0");
00490 
00491     // equilib state
00492     Sta[IdxIP]->Output (KeysVals);
00493     for (size_t k=0; k<Mdl->NIvs; ++k) KeysVals.Set (Mdl->IvNames[k].CStr(), static_cast<EquilibState const *>(Sta[IdxIP])->Ivs(k));
00494 
00495     // hydraulic state
00496     FSta[IdxIP]->Output (KeysVals);
00497     double rw = FMdl->rw(FSta[IdxIP]->Sw);
00498     KeysVals.Set ("rw", rw);
00499 
00500     // elevation of point
00501     Vec_t X;
00502     CoordsOfIP (IdxIP, X);
00503     double z = (NDim==2 ? X(1) : X(2)); // the Datum will be z=0 always
00504 
00505     // total water head
00506     double pw = -FSta[IdxIP]->pc;
00507     KeysVals.Set ("H", z + pw/FMdl->GamW);
00508 
00509     // vector of current pw at nodes of element
00510     Vec_t Pw(NDp);
00511     for (size_t i=0; i<GE->NN; ++i) Pw(i) = Con[i]->U("pw");
00512 
00513     // coordinates matrix
00514     for (size_t i=0; i<GE->NN; ++i)
00515     for (int    j=0; j<NDim;   ++j)
00516         Co(i,j) = Con[i]->Vert.C[j];
00517 
00518     // interpolation
00519     Interp (Co, GE->IPs[IdxIP]);
00520 
00521     // pore-water pressure gradient at IP
00522     Vec_t grad_pw(Bp * Pw);
00523 
00524     // seepage velocity vector
00525     KeysVals.Set ("gpwx gpwy", grad_pw(0), grad_pw(1)); if (NDim==3)
00526     KeysVals.Set ("gpwz",      grad_pw(2));
00527 }
00528 
00529 inline void UWPElem::Interp (Mat_t const & C, IntegPoint const & IP, double h) const
00530 {
00531     // deriv of shape func w.r.t natural coordinates
00532     GE->Shape  (IP.r, IP.s, IP.t);
00533     GE->Derivs (IP.r, IP.s, IP.t);
00534 
00535     // Jacobian and its determinant
00536     J    = GE->dNdR * C;
00537     DetJ = Det(J);
00538 
00539     // deriv of shape func w.r.t real coordinates
00540     Inv (J, Ji);
00541     dNdX = Ji * GE->dNdR; // dNdX = Inv(J) * dNdR
00542 
00543     // coefficient used during integration
00544     Coef = h*DetJ*IP.w;
00545 
00546     // B matrix
00547     set_to_zero (B);
00548     if (NDim==2)
00549     {
00550         if (GTy==axs_t)
00551         {
00552             // correct Coef
00553             double radius = 0.0; // radius=x at this IP
00554             for (size_t j=0; j<GE->NN; ++j) radius += GE->N(j)*Con[j]->Vert.C[0];
00555             Coef *= radius;
00556 
00557             // B matrix
00558             for (size_t i=0; i<GE->NN; ++i)
00559             {
00560                 B(0,0+i*NDim) = dNdX(0,i);
00561                 B(1,1+i*NDim) = dNdX(1,i);
00562                 B(2,0+i*NDim) = GE->N(i)/radius;
00563                 B(3,0+i*NDim) = dNdX(1,i)/sqrt(2.0);
00564                 B(3,1+i*NDim) = dNdX(0,i)/sqrt(2.0);
00565             }
00566         }
00567         else // pse_t, psa_t
00568         {
00569             for (size_t i=0; i<GE->NN; ++i)
00570             {
00571                 B(0,0+i*NDim) = dNdX(0,i);
00572                 B(1,1+i*NDim) = dNdX(1,i);
00573                 B(3,0+i*NDim) = dNdX(1,i)/sqrt(2.0);
00574                 B(3,1+i*NDim) = dNdX(0,i)/sqrt(2.0);
00575             }
00576         }
00577     }
00578     else // 3D
00579     {
00580         for (size_t i=0; i<GE->NN; ++i)
00581         {
00582             B(0,0+i*NDim) = dNdX(0,i);
00583             B(1,1+i*NDim) = dNdX(1,i);
00584             B(2,2+i*NDim) = dNdX(2,i);
00585             B(3,0+i*NDim) = dNdX(1,i)/sqrt(2.0);   B(3,1+i*NDim) = dNdX(0,i)/sqrt(2.0);
00586             B(4,1+i*NDim) = dNdX(2,i)/sqrt(2.0);   B(4,2+i*NDim) = dNdX(1,i)/sqrt(2.0);
00587             B(5,2+i*NDim) = dNdX(0,i)/sqrt(2.0);   B(5,0+i*NDim) = dNdX(2,i)/sqrt(2.0);
00588         }
00589     }
00590 
00591     // Bp matrix
00592     Bp = dNdX;
00593 
00594     // N matrix
00595     set_to_zero (N);
00596     for (int    i=0; i<NDim;   ++i)
00597     for (size_t j=0; j<GE->NN; ++j)
00598         N(i,i+j*NDim) = GE->N(j);
00599 
00600     // Np matrix
00601     for (size_t j=0; j<GE->NN; ++j)
00602     {
00603         Np (0,j) = GE->N(j);
00604         Npv(j)   = GE->N(j);
00605     }
00606 }
00607 
00608 inline double UWPElem::Update (size_t Idx, Vec_t const & V_g, Vec_t const & dPwdt_g, double dt)
00609 {
00610     // element vectors
00611     for (size_t i=0; i<GE->NN; ++i)
00612     {
00613         V (i*NDim+0) = V_g    (Con[i]->Eq("ux"));
00614         V (i*NDim+1) = V_g    (Con[i]->Eq("uy"));  if (NDim==3)
00615         V (i*NDim+2) = V_g    (Con[i]->Eq("uz"));
00616         dPwdt(i)     = dPwdt_g(Con[i]->Eq("pw"));
00617     }
00618 
00619     // coordinates matrix
00620     for (size_t i=0; i<GE->NN; ++i)
00621     for (int    j=0; j<NDim;   ++j)
00622         Co(i,j) = Con[i]->Vert.C[j];
00623 
00624     // update
00625     double dpwdt;
00626     for (size_t i=0; i<GE->NIP; ++i)
00627     {
00628         // interpolation
00629         Interp (Co, GE->IPs[i]);
00630 
00631         // solids rate of deformation at IP
00632         d = B * V;
00633 
00634         // pore-water pressure rate at IP
00635         dpwdt = dot (Npv, dPwdt);
00636 
00637         // backup
00638         if (Idx==0) // FE
00639         {
00640             Sta [i]->Backup ();
00641             FSta[i]->Backup ();
00642         }
00643         else // ME
00644         {
00645             Sta [i]->Restore ();
00646             FSta[i]->Restore ();
00647         }
00648 
00649         // rate and update
00650         FMdl->RateAndUpdate (Idx, d, dpwdt, dt, FSta[i], static_cast<EquilibState*>(Sta[i]));
00651     }
00652     return 0.0;
00653 }
00654 
00655 inline void UWPElem::Restore ()
00656 {
00657     for (size_t i=0; i<GE->NIP; ++i)
00658     {
00659         Sta [i]->Restore ();
00660         FSta[i]->Restore ();
00661     }
00662 }
00663 
00664 
00666 
00667 
00668 // Allocate a new element
00669 Element * UWPElemMaker(int NDim, Mesh::Cell const & Cell, Model const * Mdl, Model const * XMdl, SDPair const & Prp, SDPair const & Ini, Array<Node*> const & Nodes) { return new UWPElem(NDim,Cell,Mdl,XMdl,Prp,Ini,Nodes); }
00670 
00671 // Register element
00672 int UWPElemRegister()
00673 {
00674     ElementFactory  ["UWP"]   = UWPElemMaker;
00675     ElementVarKeys  ["UWP2D"] = std::make_pair ("ux uy wwx wwy pw",        "fx fy fwx fwy qw");
00676     ElementVarKeys  ["UWP3D"] = std::make_pair ("ux uy uz wwx wwy wwz pw", "fx fy fz fwx fwy fwz qw");
00677     ElementExtraKeys["UWP2D"] = Array<String>  ("qw", "qx", "qy", "qn", "qt");
00678     ElementExtraKeys["UWP3D"] = Array<String>  ("qw", "qx", "qy", "qz", "qn");
00679     PROB.Set ("UWP", (double)PROB.Keys.Size());
00680     return 0;
00681 }
00682 
00683 // Call register
00684 int __UWPElem_dummy_int  = UWPElemRegister();
00685 
00686 }; // namespace FEM
00687 
00688 #endif // MECHSYS_UWPELEM_H
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines