MechSys  1.0
Computing library for simulations in continuum and discrete mechanics
/home/dorival/mechsys/lib/fem/hydromechelem.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_HYDROMECH_H
00021 #define MECHSYS_HYDROMECH_H
00022 
00023 // MechSys
00024 #include <mechsys/fem/equilibelem.h>
00025 #include <mechsys/models/unsatflow.h>
00026 
00027 namespace FEM
00028 {
00029 
00030 class HydroMechElem : public EquilibElem
00031 {
00032 public:
00033     // Static
00034     static size_t NDp; 
00035     static size_t NDt; 
00036     static Mat_t  Im;  
00037     static Vec_t  Iv;  
00038     static Vec_t  zv;  
00039 
00040     // Constructor
00041     HydroMechElem (int                  NDim,   
00042                    Mesh::Cell   const & Cell,   
00043                    Model        const * Mdl,    
00044                    Model        const * XMdl,   
00045                    SDPair       const & Prp,    
00046                    SDPair       const & Ini,    
00047                    Array<Node*> const & Nodes); 
00048 
00049     // Destructor
00050     ~HydroMechElem () { for (size_t i=0; i<GE->NIP; ++i) delete FSta[i]; }
00051 
00052     // Methods
00053     void SetBCs      (size_t IdxEdgeOrFace, SDPair const & BCs, BCFuncs * BCF);
00054     void CalcKCM     (Mat_t & KK, Mat_t & CC, Mat_t & MM)   const;
00055     void GetLoc      (Array<size_t> & Loc)                  const;
00056     void UpdateState (Vec_t const & dU, Vec_t * F_int=NULL) const;
00057     void StateKeys   (Array<String> & Keys)                 const;
00058     void StateAtIP   (SDPair & KeysVals, int IdxIP)         const;
00059 
00060     // Internal Methods
00061     void Interp (Mat_t const & C, IntegPoint const & IP, Mat_t & B, Mat_t & Bp, Mat_t & N, Mat_t & Np, double & detJ, double & Coef) const; 
00062 
00063     // Methods for the Runge-Kutta method
00064     size_t NIVs       ()                                                            const;
00065     double GetIV      (size_t i)                                                    const;
00066     void   SetIV      (size_t i, double Val);
00067     void   CalcIVRate (double Time, Vec_t const & U, Vec_t const & V, Vec_t & Rate) const;
00068 
00069     // Data
00070     Array<UnsatFlowState*>   FSta; 
00071     UnsatFlow        const * FMdl; 
00072 };
00073 
00074 size_t HydroMechElem::NDp = 0;
00075 size_t HydroMechElem::NDt = 0;
00076 Mat_t  HydroMechElem::Im;
00077 Vec_t  HydroMechElem::Iv;
00078 Vec_t  HydroMechElem::zv;
00079 
00080 
00082 
00083 
00084 inline HydroMechElem::HydroMechElem (int NDim, Mesh::Cell const & Cell, Model const * Mdl, Model const * XMdl, SDPair const & Prp, SDPair const & Ini, Array<Node*> const & Nodes)
00085     : EquilibElem(NDim,Cell,Mdl,XMdl,Prp,Ini,Nodes),
00086       FMdl(static_cast<UnsatFlow const*>(XMdl))
00087 {
00088     // check
00089     if (XMdl==NULL) throw new Fatal("HydroMechElem::HydroMechElem: E(x)tra Model (flow model) must be defined by means of 'xname' key");
00090 
00091     // set constants of this class (just once)
00092     if (NDp==0)
00093     {
00094         NDp = GE->NN;
00095         NDt = NDu + NDp;
00096 
00097         Im.change_dim (NCo,1);
00098         Iv.change_dim (NCo);
00099         set_to_zero (Im);
00100         set_to_zero (Iv);
00101         Im(0,0)=1.0;   Im(1,0)=1.0;   Im(2,0)=1.0;
00102         Iv(0)  =1.0;   Iv(1)  =1.0;   Iv(2)  =1.0;
00103 
00104         zv.change_dim (NDim);
00105         if (NDim==2) zv = 0.0, 1.0;
00106         else         zv = 0.0, 0.0, 1.0;
00107     }
00108 
00109     // initial data
00110     bool   geosta = (Prp.HasKey("geosta") ? Prp("geosta")>0 : false);
00111     bool   pos_pw = (Prp.HasKey("pospw")  ? Prp("pospw")>0  : false);
00112     double gamW   = XMdl->Prms("gamW");
00113 
00114     // allocate and initialize flow state at each IP
00115     SDPair ini(Ini);
00116     for (size_t i=0; i<GE->NIP; ++i)
00117     {
00118         // pw at IP
00119         if (geosta)
00120         {
00121             // elevation of point
00122             Vec_t X;
00123             CoordsOfIP (i, X);
00124             double z = (NDim==2 ? X(1) : X(2));
00125 
00126             // pore-water pressure
00127             double hw = Prp("water")-z; // column of water
00128             double pw = (hw>0.0 ? gamW*hw : (pos_pw ? 0.0 : gamW*hw));
00129             ini.Set ("pw", pw);
00130         }
00131 
00132         // init flow state
00133         FSta.Push     (new UnsatFlowState(NDim));
00134         FMdl->InitIvs (ini, FSta[i]);
00135     }
00136 
00137     // pore-water pressure at nodes (extrapolated)
00138     Vec_t pwe(NDp);
00139     Array<SDPair> res;
00140     StateAtNodes (res);
00141     for (size_t i=0; i<NDp; ++i)
00142     {
00143         double pw = -res[i]("pc");
00144         Con[i]->U("pw") = pw;
00145         pwe(i) = pw;
00146     }
00147 
00148     // set F in nodes due to initial (hydraulic) values
00149     double detJ, coef;
00150     Mat_t  C, B, Bp, N, Np;
00151     CoordMatrix (C);
00152     Vec_t  fe(NDp);
00153     set_to_zero (fe);
00154     for (size_t i=0; i<GE->NIP; ++i)
00155     {
00156         Interp (C, GE->IPs[i], B, Bp, N, Np, detJ, coef);
00157         Mat_t kBp    (FMdl->kwsatb * Bp);
00158         Vec_t kBppwe (kBp * pwe);
00159         fe += (coef) * trans(Bp)*kBppwe;
00160     }
00161     for (size_t i=0; i<GE->NN; ++i) Con[i]->F("qw") += fe(i);
00162 }
00163 
00164 inline void HydroMechElem::SetBCs (size_t IdxEdgeOrFace, SDPair const & BCs, BCFuncs * BCF)
00165 {
00166     bool has_flux = BCs.HasKey("flux");    // normal flux to boundary
00167     bool has_srcw = BCs.HasKey("srcw");    // water source term
00168     bool has_pw   = BCs.HasKey("pw");      // water pressure
00169 
00170     if (has_flux || has_srcw || has_pw)
00171     {
00172         // flux
00173         if (has_flux)
00174         {
00175             double qn = BCs("flux");
00176             double detJ, coef;
00177             Mat_t  Cf;
00178             FCoordMatrix (IdxEdgeOrFace, Cf);
00179             for (size_t i=0; i<GE->NFIP; ++i)
00180             {
00181                 CalcFaceShape (Cf, GE->FIPs[i], detJ, coef);
00182                 if (GTy==axs_t) // correct Coef for axisymmetric problems
00183                 {
00184                     double radius = 0.0; // calculate radius=x at this FIP
00185                     for (size_t j=0; j<GE->NFN; ++j) radius += GE->FN(j)*Con[GE->FNode(IdxEdgeOrFace,j)]->Vert.C[0];
00186                     coef *= radius; // correct coef
00187                 }
00188                 for (size_t j=0; j<GE->NFN; ++j)
00189                 {
00190                     size_t k = GE->FNode(IdxEdgeOrFace,j);
00191                     Con[k]->AddToPF("qw", -coef*GE->FN(j)*qn, BCF);
00192                 }
00193             }
00194         }
00195 
00196         // source
00197         else if (has_srcw)
00198         {
00199             throw new Fatal("HydroMechElem::SetBCs: 'srcw' is not available yet");
00200 
00201             double srcw = BCs("srcw");
00202             double detJ, coef;
00203             Mat_t  C, B, Bp, N, Np;
00204             CoordMatrix (C);
00205             for (size_t i=0; i<GE->NIP; ++i)
00206             {
00207                 Interp (C, GE->IPs[i], B, Bp, N, Np, detJ, coef);
00208                 for (size_t j=0; j<GE->NN; ++j)
00209                 {
00210                     Con[j]->AddToPF("qw", srcw*coef*Np(0,j), BCF);
00211                 }
00212             }
00213         }
00214 
00215         // prescribed pw
00216         else if (has_pw)
00217         {
00218             double pw = BCs("pw");
00219             for (size_t j=0; j<GE->NFN; ++j)
00220             {
00221                 size_t k = GE->FNode(IdxEdgeOrFace,j);
00222                 Con[k]->SetPU("pw", pw, BCF);
00223             }
00224         }
00225     }
00226 
00227     // other BCs => set by EquilibElem
00228     EquilibElem::SetBCs (IdxEdgeOrFace, BCs, BCF);
00229 
00230     // gravity
00231     if (BCs.HasKey("fgrav"))
00232     {
00233         // force vector
00234         Vec_t  fe(NDp);
00235         set_to_zero (fe);
00236         double detJ, coef;
00237         Mat_t  C, B, Bp, N, Np;
00238         CoordMatrix (C);
00239         for (size_t i=0; i<GE->NIP; ++i)
00240         {
00241             Interp (C, GE->IPs[i], B, Bp, N, Np, detJ, coef);
00242             Mat_t kwsat  (FMdl->kwsatb * FMdl->GamW);
00243             Vec_t kwsatz (kwsat * zv);
00244             fe += (-coef) * trans(Bp) * kwsatz;
00245         }
00246 
00247         // add results to F (external forces)
00248         for (size_t i=0; i<NDp; ++i) Con[i]->AddToPF("qw", fe(i), BCF);
00249     }
00250 }
00251 
00252 inline void HydroMechElem::GetLoc (Array<size_t> & Loc) const
00253 {
00254     Loc.Resize (NDt);
00255     for (size_t i=0; i<GE->NN; ++i)
00256     {
00257         Loc[i*NDim+0] = Con[i]->Eq("ux");
00258         Loc[i*NDim+1] = Con[i]->Eq("uy");  if (NDim==3)
00259         Loc[i*NDim+2] = Con[i]->Eq("uz");
00260         Loc[NDu+i]    = Con[i]->Eq("pw");
00261     }
00262 }
00263 
00264 inline void HydroMechElem::Interp (Mat_t const & C, IntegPoint const & IP, Mat_t & B, Mat_t & Bp, Mat_t & N, Mat_t & Np, double & detJ, double & Coef) const
00265 {
00266     // deriv of shape func w.r.t natural coordinates
00267     GE->Shape  (IP.r, IP.s, IP.t);
00268     GE->Derivs (IP.r, IP.s, IP.t);
00269 
00270     // Jacobian and its determinant
00271     Mat_t J(GE->dNdR * C); // J = dNdR * C
00272     detJ = Det(J);
00273 
00274     // deriv of shape func w.r.t real coordinates
00275     Mat_t Ji;
00276     Inv (J, Ji);
00277     Mat_t dNdX(Ji * GE->dNdR); // dNdX = Inv(J) * dNdR
00278 
00279     // coefficient used during integration
00280     Coef = h*detJ*IP.w;
00281 
00282     // B matrix
00283     B.change_dim (NCo,NDu);
00284     set_to_zero  (B);
00285     if (NDim==2)
00286     {
00287         if (GTy==axs_t)
00288         {
00289             // correct Coef
00290             double radius = 0.0; // radius=x at this IP
00291             for (size_t j=0; j<GE->NN; ++j) radius += GE->N(j)*Con[j]->Vert.C[0];
00292             Coef *= radius;
00293 
00294             // B matrix
00295             for (size_t i=0; i<GE->NN; ++i)
00296             {
00297                 B(0,0+i*NDim) = dNdX(0,i);
00298                 B(1,1+i*NDim) = dNdX(1,i);
00299                 B(2,0+i*NDim) = GE->N(i)/radius;
00300                 B(3,0+i*NDim) = dNdX(1,i)/sqrt(2.0);
00301                 B(3,1+i*NDim) = dNdX(0,i)/sqrt(2.0);
00302             }
00303         }
00304         else // pse_t, psa_t
00305         {
00306             for (size_t i=0; i<GE->NN; ++i)
00307             {
00308                 B(0,0+i*NDim) = dNdX(0,i);
00309                 B(1,1+i*NDim) = dNdX(1,i);
00310                 B(3,0+i*NDim) = dNdX(1,i)/sqrt(2.0);
00311                 B(3,1+i*NDim) = dNdX(0,i)/sqrt(2.0);
00312             }
00313         }
00314     }
00315     else // 3D
00316     {
00317         for (size_t i=0; i<GE->NN; ++i)
00318         {
00319             B(0,0+i*NDim) = dNdX(0,i);
00320             B(1,1+i*NDim) = dNdX(1,i);
00321             B(2,2+i*NDim) = dNdX(2,i);
00322             B(3,0+i*NDim) = dNdX(1,i)/sqrt(2.0);   B(3,1+i*NDim) = dNdX(0,i)/sqrt(2.0);
00323             B(4,1+i*NDim) = dNdX(2,i)/sqrt(2.0);   B(4,2+i*NDim) = dNdX(1,i)/sqrt(2.0);
00324             B(5,2+i*NDim) = dNdX(0,i)/sqrt(2.0);   B(5,0+i*NDim) = dNdX(2,i)/sqrt(2.0);
00325         }
00326     }
00327 
00328     // Bp matrix
00329     Bp = dNdX;
00330 
00331     // N matrix
00332     N.change_dim (NDim,NDu);
00333     set_to_zero  (N);
00334     for (int    i=0; i<NDim;   ++i)
00335     for (size_t j=0; j<GE->NN; ++j)
00336         N(i,i+j*NDim) = GE->N(j);
00337 
00338     // Np matrix
00339     Np.change_dim (1,NDp);
00340     for (size_t j=0; j<GE->NN; ++j) Np(0,j) = GE->N(j);
00341 }
00342 
00343 inline void HydroMechElem::CalcKCM (Mat_t & KK, Mat_t & CC, Mat_t & MM) const
00344 {
00345     // mechanical matrices
00346     Mat_t M, K, D;
00347     M.change_dim (NDu,NDu); // mass matrix
00348     K.change_dim (NDu,NDu); // stiffness matrix
00349     set_to_zero (M);
00350     set_to_zero (K);
00351 
00352     // hydraulic matrices
00353     Mat_t Q, Qb, H, S;
00354     Q .change_dim (NDu,NDp); // coupling matrix
00355     Qb.change_dim (NDu,NDp); // coupling matrix
00356     H .change_dim (NDp,NDp); // permeability matrix
00357     S .change_dim (NDp,NDp); // compressibility matrix
00358     set_to_zero (Q);
00359     set_to_zero (Qb);
00360     set_to_zero (H);
00361     set_to_zero (S);
00362 
00363     // auxiliar matrices
00364     Mat_t C, B, Bp, N, Np;
00365     double detJ, coef;
00366     Mat_t NtN    (NDu,NDu);
00367     Mat_t BtDB   (NDu,NDu);
00368     Mat_t BtmNp  (NDu,NDp);
00369     Mat_t NptNp  (NDp,NDp);
00370     Mat_t BptkBp (NDp,NDp);
00371     CoordMatrix (C);
00372     for (size_t i=0; i<GE->NIP; ++i)
00373     {
00374         FMdl -> TgVars    (FSta[i]); // set c, C, chi
00375         //Mdl  -> Stiffness (Sta[i], D);
00376         FMdl -> Stiffness (Sta[i], FSta[i], D); // TODO: correct this: "effective stiffness"
00377         Interp (C, GE->IPs[i], B, Bp, N, Np, detJ, coef);
00378         NtN    = trans(N)*N;
00379         BtDB   = trans(B)*D*B;
00380         BtmNp  = trans(B)*Im*Np;
00381         NptNp  = trans(Np)*Np;
00382         BptkBp = trans(Bp)*(FMdl->kwsatb)*Bp;
00383         double rw = FMdl->rw(FSta[i]->Sw);
00384         M     += (coef*rho)        * NtN;
00385         K     += (coef)            * BtDB;
00386         Qb    += (coef*FMdl->chi)  * BtmNp;
00387         Q     += (coef*FMdl->c/rw) * BtmNp;
00388         S     += (coef*FMdl->C/rw) * NptNp;
00389         H     += (coef)            * BptkBp;
00390     }
00391 
00392     //std::cout << "S = \n" << PrintMatrix(S) << std::endl;
00393 
00394     // assemble
00395     MM.change_dim (NDt,NDt);
00396     CC.change_dim (NDt,NDt);
00397     KK.change_dim (NDt,NDt);
00398     set_to_zero (MM);
00399     set_to_zero (CC);
00400     set_to_zero (KK);
00401     bool schemeA = true;
00402     for (size_t i=0; i<NDu; ++i)
00403     {
00404         for (size_t j=0; j<NDu; ++j)
00405         {
00406             MM(i,j) = M(i,j);
00407             CC(i,j) = 0.0; // Rayleigh: Am*M + Ak*K
00408             KK(i,j) = K(i,j);
00409         }
00410         for (size_t j=0; j<NDp; ++j) KK(i,NDu+j) = -Qb(i,j);
00411     }
00412     for (size_t i=0; i<NDp; ++i)
00413     {
00414         for (size_t j=0; j<NDu; ++j) CC(NDu+i,j) = Q(j,i);
00415         for (size_t j=0; j<NDp; ++j)
00416         {
00417             KK(NDu+i,NDu+j) = H(i,j);
00418             if (schemeA) CC(NDu+i,NDu+j) = S(i,j);
00419             else         MM(NDu+i,NDu+j) = S(i,j);
00420         }
00421     }
00422 }
00423 
00424 inline void HydroMechElem::UpdateState (Vec_t const & dU, Vec_t * F_int) const
00425 {
00426     // get location array
00427     Array<size_t> loc;
00428     GetLoc (loc);
00429 
00430     // element nodal displacements
00431     Vec_t dUe(NDu);
00432     for (size_t i=0; i<NDu; ++i) dUe(i) = dU(loc[i]);
00433 
00434     // element nodal pore-water pressure
00435     Vec_t dpwe(NDp);
00436     for (size_t i=0; i<NDp; ++i) dpwe(i) = dU(loc[NDu+i]);
00437 
00438     // auxiliary matrices and vectors
00439     Mat_t kBp     (NDim, NDp);
00440     Vec_t kBpdpwe (NDim);
00441 
00442     // update state at each IP
00443     double detJ, coef;
00444     Mat_t  C, B, Bp, N, Np;
00445     Vec_t  dFe(NDu), dsig(NCo), deps(NCo), dfe(NDp);
00446     set_to_zero (dFe);
00447     set_to_zero (dfe);
00448     CoordMatrix (C);
00449     Mat_t BptkBp(NDp,NDp), H(NDp,NDp);
00450     set_to_zero (H);
00451     for (size_t i=0; i<GE->NIP; ++i)
00452     {
00453         // interpolation functions
00454         Interp (C, GE->IPs[i], B, Bp, N, Np, detJ, coef);
00455 
00456         // calculate dpw and deps at IP
00457         Vec_t Npdpwe(Np * dpwe);
00458         double dpw = Npdpwe(0);
00459         deps = B * dUe;
00460 
00461         // update: inputs total stresses, returns total stress increments
00462         FMdl->HMSUp.Update (deps, dpw, Sta[i], FSta[i], dsig);
00463 
00464 #ifdef DO_DEBUG
00465         double normdsig = Norm(dsig);
00466         if (Util::IsNan(normdsig))              throw new Fatal("HydroMechElem::UpdateState: normdsig is NaN");
00467         if (Util::IsNan(FSta[i]->Sw))           throw new Fatal("HydroMechElem::UpdateState: Sw is NaN");
00468         if (Util::IsNan(FSta[i]->pc))           throw new Fatal("HydroMechElem::UpdateState: pc is NaN");
00469         if (Util::IsNan(FMdl->rw(FSta[i]->Sw))) throw new Fatal("HydroMechElem::UpdateState: rw(Sw) is NaN");
00470 #endif
00471 
00472         // element nodal forces
00473         dFe +=  (coef) * trans(B)  * dsig;
00474         //dfe += (-coef) * trans(Bp) * dqw_nograv;
00475  
00476         // assemble H
00477         BptkBp = trans(Bp)*(FMdl->kwsatb)*Bp;
00478         H     += (coef) * BptkBp;
00479     }
00480 
00481     // calc dfe
00482     dfe = H*dpwe;
00483 
00484     // add results to Fint (internal forces)
00485     if (F_int!=NULL)
00486     {
00487         for (size_t i=0; i<NDu; ++i) (*F_int)(loc[i])     += dFe(i);
00488         for (size_t i=0; i<NDp; ++i) (*F_int)(loc[NDu+i]) += dfe(i);
00489     }
00490 }
00491 
00492 inline void HydroMechElem::StateKeys (Array<String> & Keys) const
00493 {
00494     EquilibElem::StateKeys (Keys);
00495     Keys.Push ("n");
00496     Keys.Push ("pc");
00497     Keys.Push ("Sw");
00498     Keys.Push ("rw");
00499     Keys.Push ("qwx");
00500     Keys.Push ("qwy"); if (NDim==3)
00501     Keys.Push ("qwz");
00502     Keys.Push ("H");
00503 }
00504 
00505 inline void HydroMechElem::StateAtIP (SDPair & KeysVals, int IdxIP) const
00506 {
00507     // check
00508     if (FSta[IdxIP]->Sw<0.0) throw new Fatal("HydroMechElem::StateAtIP: Sw<0");
00509 
00510     // output
00511     double rw = FMdl->rw(FSta[IdxIP]->Sw);
00512     EquilibElem::StateAtIP (KeysVals, IdxIP);
00513     KeysVals.Set ("n",  FSta[IdxIP]->n);
00514     KeysVals.Set ("pc", FSta[IdxIP]->pc);
00515     KeysVals.Set ("Sw", FSta[IdxIP]->Sw);
00516     KeysVals.Set ("rw", rw);
00517 
00518     // elevation of point
00519     Vec_t X;
00520     CoordsOfIP (IdxIP, X);
00521     double z = (NDim==2 ? X(1) : X(2)); // the Datum will be z=0 always
00522 
00523     // total water head
00524     double pw = -FSta[IdxIP]->pc;
00525     KeysVals.Set ("H", z + pw/FMdl->GamW);
00526 
00527     // vector of current pw at nodes of element
00528     Vec_t pwe(NDp);
00529     for (size_t i=0; i<GE->NN; ++i) pwe(i) = Con[i]->U("pw");
00530 
00531     // pore-water pressure gradient at IP
00532     double detJ, coef;
00533     Mat_t  C, B, Bp, N, Np;
00534     CoordMatrix (C);
00535     Interp (C, GE->IPs[IdxIP], B, Bp, N, Np, detJ, coef);
00536     Vec_t grad_pw(Bp * pwe);
00537 
00538     // relative specific discharge
00539     grad_pw += FMdl->GamW*zv;          // grad_pw = grad_pw + gamW*z
00540     Vec_t mqw(FMdl->kwsatb * grad_pw); // -qw
00541     KeysVals.Set ("qwx", -rw*mqw(0));
00542     KeysVals.Set ("qwy", -rw*mqw(1)); if (NDim==3)
00543     KeysVals.Set ("qwz", -rw*mqw(2));
00544 }
00545 
00546 inline size_t HydroMechElem::NIVs () const 
00547 {
00548     return NCo*GE->NIP;
00549 }
00550 
00551 inline double HydroMechElem::GetIV (size_t i) const 
00552 {
00553     int iip = static_cast<int>(i) / static_cast<int>(NCo); // index of IP
00554     int ico = static_cast<int>(i) % static_cast<int>(NCo); // index of component
00555     return static_cast<EquilibState const*>(Sta[iip])->Sig(ico);
00556 }
00557 
00558 inline void HydroMechElem::SetIV (size_t i, double Val) 
00559 {
00560     int iip = static_cast<int>(i) / static_cast<int>(NCo); // index of IP
00561     int ico = static_cast<int>(i) % static_cast<int>(NCo); // index of component
00562     static_cast<EquilibState*>(Sta[iip])->Sig(ico) = Val;
00563 }
00564 
00565 inline void HydroMechElem::CalcIVRate (double Time, Vec_t const & U, Vec_t const & V, Vec_t & Rate) const
00566 {
00567     // resize rate
00568     Rate.change_dim (NCo*GE->NIP);
00569 
00570     // get location array
00571     Array<size_t> loc;
00572     GetLoc (loc);
00573 
00574     // element nodal velocities
00575     Vec_t Ve(NDu);
00576     for (size_t i=0; i<NDu; ++i) Ve(i) = V(loc[i]);
00577 
00578     // element dpwdt
00579     Vec_t dpwedt(NDp);
00580     for (size_t i=0; i<NDp; ++i) dpwedt(i) = V(loc[NDu+i]);
00581 
00582     // calc dsigdt
00583     double detJ, coef;
00584     Mat_t  C, B, D, Bp, N, Np;
00585     Vec_t  depsdt(NCo), dsigdt(NCo);
00586     CoordMatrix (C);
00587     for (size_t i=0; i<GE->NIP; ++i)
00588     {
00589         // interpolation functions
00590         Interp (C, GE->IPs[i], B, Bp, N, Np, detJ, coef);
00591 
00592         // calculate dpwdt at IP
00593         Vec_t Npdpwedt(Np * dpwedt);
00594         double dpwdt = Npdpwedt(0);
00595 
00596         // effective stress rate
00597         Mdl->Stiffness (Sta[i], D);
00598         depsdt = B * Ve;
00599         dsigdt = D * depsdt;
00600 
00601         // total stress rate
00602         dsigdt -= (FMdl->chi)*dpwdt*Iv;
00603 
00604         // set rate vector
00605         for (size_t j=0; j<NCo; ++j) Rate(j+i*NCo) = dsigdt(j);
00606     }
00607 }
00608 
00609 
00611 
00612 
00613 // Allocate a new element
00614 Element * HydroMechElemMaker(int NDim, Mesh::Cell const & Cell, Model const * Mdl, Model const * XMdl, SDPair const & Prp, SDPair const & Ini, Array<Node*> const & Nodes) { return new HydroMechElem(NDim,Cell,Mdl,XMdl,Prp,Ini,Nodes); }
00615 
00616 // Register element
00617 int HydroMechElemRegister()
00618 {
00619     ElementFactory["HydroMech"]   = HydroMechElemMaker;
00620     ElementVarKeys["HydroMech2D"] = std::make_pair ("ux uy pw",    "fx fy qw");
00621     ElementVarKeys["HydroMech3D"] = std::make_pair ("ux uy uz pw", "fx fy fz qw");
00622     PROB.Set ("HydroMech", (double)PROB.Keys.Size());
00623     return 0;
00624 }
00625 
00626 // Call register
00627 int __HydroMechElem_dummy_int  = HydroMechElemRegister();
00628 
00629 }; // namespace FEM
00630 
00631 #endif // MECHSYS_HYDROMECH_H
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines