![]() |
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_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