![]() |
MechSys
1.0
Computing library for simulations in continuum and discrete mechanics
|
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