![]() |
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_FEM_EQUILIBELEM_H 00021 #define MECHSYS_FEM_EQUILIBELEM_H 00022 00023 // MechSys 00024 #include <mechsys/fem/element.h> 00025 #include <mechsys/models/equilibstate.h> 00026 #include <mechsys/models/stressupdate.h> 00027 00028 namespace FEM 00029 { 00030 00031 class EquilibElem : public Element 00032 { 00033 public: 00034 // Static 00035 static size_t NCo; 00036 static size_t NDu; 00037 00038 // Constructor & Destructor 00039 EquilibElem (int NDim, 00040 Mesh::Cell const & Cell, 00041 Model const * Mdl, 00042 Model const * XMdl, 00043 SDPair const & Prp, 00044 SDPair const & Ini, 00045 Array<Node*> const & Nodes); 00046 virtual ~EquilibElem () {} 00047 00048 // Methods 00049 virtual void SetBCs (size_t IdxEdgeOrFace, SDPair const & BCs, BCFuncs * BCF); 00050 virtual void GetLoc (Array<size_t> & Loc) const; 00051 void CalcK (Mat_t & K) const; 00052 void CalcM (Mat_t & M) const; 00053 virtual void UpdateState (Vec_t const & dU, Vec_t * F_int=NULL) const; 00054 virtual void SetFint (Vec_t * Fint=NULL) const; 00055 virtual void StateKeys (Array<String> & Keys) const; 00056 virtual void StateAtIP (SDPair & KeysVals, int IdxIP) const; 00057 00058 // Internal methods 00059 void CalcB (Mat_t const & C, IntegPoint const & IP, Mat_t & B, double & detJ, double & Coef) const; 00060 void CalcN (Mat_t const & C, IntegPoint const & IP, Mat_t & N, double & detJ, double & Coef) const; 00061 00062 // Methods for the Runge-Kutta method 00063 virtual size_t NIVs () const; 00064 virtual double GetIV (size_t i) const; 00065 virtual void SetIV (size_t i, double Val); 00066 virtual void CalcIVRate (double Time, Vec_t const & U, Vec_t const & V, Vec_t & Rate) const; 00067 virtual void CorrectIVs (); 00068 00069 // Constants 00070 double h; 00071 double rho; 00072 }; 00073 00074 size_t EquilibElem::NCo = 0; 00075 size_t EquilibElem::NDu = 0; 00076 00077 00079 00080 00081 inline EquilibElem::EquilibElem (int NDim, Mesh::Cell const & Cell, Model const * Mdl, Model const * XMdl, SDPair const & Prp, SDPair const & Ini, Array<Node*> const & Nodes) 00082 : Element(NDim,Cell,Mdl,XMdl,Prp,Ini,Nodes) 00083 { 00084 // check 00085 if (GE==NULL) throw new Fatal("EquilibElem::EquilibElem: GE (geometry element) must be defined"); 00086 if (Mdl==NULL) throw new Fatal("EquilibElem::EquilibElem: Model must be defined"); 00087 00088 // set constants of this class (just once) 00089 if (NDu==0) 00090 { 00091 NCo = 2*NDim; 00092 NDu = NDim*GE->NN; 00093 } 00094 00095 // parameters/properties 00096 h = (Prp.HasKey("h") ? Prp("h") : 1.0); 00097 rho = Mdl->Rho;//(Prp.HasKey("rho") ? Prp("rho") : 1.0); 00098 if (h<1.0e-8) throw new Fatal("EquilibElem::EquilibElem: The thickness of the element must be greater than 1.0e-8. h=%g is invalid",h); 00099 if (rho<1.0e-8) throw new Fatal("EquilibElem::EquilibElem: 'rho' must be greater than zero (rho=%g is invalid)",rho); 00100 00101 // allocate and initialize state at each IP 00102 for (size_t i=0; i<GE->NIP; ++i) 00103 { 00104 Sta.Push (new EquilibState(NDim)); 00105 Mdl->InitIvs (Ini, Sta[i]); 00106 } 00107 00108 // set initial values 00109 bool geosta = (Prp.HasKey("geosta") ? Prp("geosta")>0 : false); 00110 if (geosta) 00111 { 00112 double z_surf = Prp("surf"); 00113 double K0 = Prp("K0"); 00114 bool pos_pw = (Prp.HasKey("pospw") ? Prp("pospw")>0 : false); 00115 bool has_water = Prp.HasKey("water"); 00116 double z_water = 0; 00117 if (GTy==pse_t) throw new Fatal("EquilibElem::EquilibElem: For geostatic stresses, geometry cannot be of 'plane-stress' (pse) type"); 00118 if (!Prp.HasKey("K0")) throw new Fatal("EquilibElem::EquilibElem: For geostatic stresses, 'K0' must be provided in 'Prp' dictionary"); 00119 if (!Prp.HasKey("surf")) throw new Fatal("EquilibElem::EquilibElem: For geostatic stresses, 'surf' must be provided in 'Prp' dictionary"); 00120 if (has_water) 00121 { 00122 z_water = Prp("water"); 00123 if (z_water>z_surf) throw new Fatal("EquilibElem::EquilibElem: For geostatic stresses, 'water' must be smaller than or equal to 'surf'"); 00124 // TODO: this last condition can be removed, but sv calculation in the next lines must be corrected 00125 } 00126 if (Mdl->GamW <0.0) throw new Fatal("EquilibElem::EquilibElem: For geostatic stresses, 'gamW' must be positive"); 00127 if (Mdl->GamNat<0.0) throw new Fatal("EquilibElem::EquilibElem: For geostatic stresses, 'gamNat' must be positive"); 00128 if (Mdl->GamSat<0.0) throw new Fatal("EquilibElem::EquilibElem: For geostatic stresses, 'gamSat' must be positive"); 00129 for (size_t i=0; i<GE->NIP; ++i) 00130 { 00131 // elevation of point 00132 Vec_t X; 00133 CoordsOfIP (i, X); 00134 double z = (NDim==2 ? X(1) : X(2)); 00135 if (z>z_surf) throw new Fatal("EquilibElem::EquilibElem: 'surf' must be greater than any point in the domain.\n\tThere is a point [%g,%g,%g] above surf=%g.",X(0),X(1),(NDim==3?X(2):0.0),z_surf); 00136 00137 // pore-water pressure and total vertical stress 00138 double pw = 0.0; 00139 double sv; 00140 if (has_water) 00141 { 00142 double hw = z_water-z; // column of water 00143 pw = (hw>0.0 ? Mdl->GamW*hw : (pos_pw ? 0.0 : Mdl->GamW*hw)); 00144 if (z>z_water) sv = (z_surf-z)*Mdl->GamNat; 00145 else sv = (z_surf-z_water)*Mdl->GamNat + (z_water-z)*Mdl->GamSat; 00146 } 00147 else sv = (z_surf-z)*Mdl->GamNat; 00148 sv *= (-1.0); // convert soil-mech. convention to classical mech. convention 00149 00150 // vertical and horizontal effective stresses 00151 double sv_ = sv + pw; // effective vertical stresss 00152 double sh_ = K0*sv_; // effective horizontal stress 00153 double sh = sh_ - pw; // total horizontal stress 00154 00155 // set stress tensor with __total__ stresses 00156 Vec_t & sig = static_cast<EquilibState *>(Sta[i])->Sig; 00157 if (NDim==2) sig = sh, sv, sh, 0.0; 00158 else sig = sh, sh, sv, 0.0,0.0,0.0; 00159 } 00160 } 00161 00162 // set F in nodes due to initial stresses 00163 SetFint (); 00164 } 00165 00166 inline void EquilibElem::SetBCs (size_t IdxEdgeOrFace, SDPair const & BCs, BCFuncs * BCF) 00167 { 00168 // deactivate/activate commands 00169 if (BCs.HasKey("deactivate")) 00170 { 00171 // check 00172 if (!Active) throw new Fatal("EquilibElem::SetBCs: 'deactivate' command failed: Element # %d is already inactive",Cell.ID); 00173 00174 // calc force to be applied after removal of element 00175 double gra = (BCs.HasKey("gravity") ? BCs("gravity") : 0.0); 00176 double detJ, coef; 00177 Mat_t C, B; 00178 Vec_t Fi(NDu), Fb(NDu); 00179 set_to_zero (Fi); 00180 set_to_zero (Fb); 00181 CoordMatrix (C); 00182 size_t idx_grav = (NDim==2 ? 1 : 2); 00183 for (size_t i=0; i<GE->NIP; ++i) 00184 { 00185 // internal forces 00186 GE->Shape (GE->IPs[i].r, GE->IPs[i].s, GE->IPs[i].t); 00187 CalcB (C, GE->IPs[i], B, detJ, coef); 00188 Vec_t const & sig = static_cast<EquilibState const *>(Sta[i])->Sig; 00189 Fi += (coef) * trans(B)*sig; 00190 00191 // body forces 00192 for (size_t j=0; j<GE->NN; ++j) Fb(idx_grav+j*NDim) += -coef*GE->N(j)*rho*gra; 00193 } 00194 00195 // set nodes 00196 for (size_t i=0; i<GE->NN; ++i) 00197 { 00198 // remove sharing information 00199 Con[i]->NShares--; 00200 if (Con[i]->NShares<0) throw new Fatal("EquilibElem::SetBCs: __internal_error__: 'deactivate' command failed: NShares==%d must be positive",Con[i]->NShares<0); 00201 00202 // clear all values in node in case it becomes inactive 00203 if (Con[i]->NShares==0) Con[i]->Clear(); 00204 else 00205 { 00206 // set boundary conditions 00207 Con[i]->AddToPF("fx", Fi(0+i*NDim) - Fb(0+i*NDim), BCF); 00208 Con[i]->AddToPF("fy", Fi(1+i*NDim) - Fb(1+i*NDim), BCF); if (NDim==3) 00209 Con[i]->AddToPF("fz", Fi(2+i*NDim) - Fb(2+i*NDim), BCF); 00210 } 00211 } 00212 00213 // clear state at IPs 00214 SDPair inis; 00215 inis.Set("zero",1.); 00216 for (size_t i=0; i<GE->NIP; ++i) Sta[i]->Init (inis, size(static_cast<EquilibState const *>(Sta[i])->Ivs)); 00217 00218 // deactivate element 00219 Active = false; 00220 return; // must return otherwise 'gravity' may be set in the following code 00221 } 00222 else if (BCs.HasKey("activate")) 00223 { 00224 // check 00225 if (Active) throw new Fatal("EquilibElem::SetBCs: 'activate' command failed: Element # %d is already active",Cell.ID); 00226 00227 // add information to shares array in nodes 00228 for (size_t i=0; i<GE->NN; ++i) Con[i]->NShares++; 00229 00230 // clear state at IPs 00231 SDPair inis; 00232 inis.Set("zero",1.); 00233 for (size_t i=0; i<GE->NIP; ++i) Sta[i]->Init (inis, size(static_cast<EquilibState const *>(Sta[i])->Ivs)); 00234 00235 // activate 00236 Active = true; 00237 // continue to set gravity 00238 } 00239 00240 // check 00241 if (!Active) throw new Fatal("EquilibElem::SetBCs: Element %d is inactive",Cell.ID); 00242 00243 bool has_bx = BCs.HasKey("bx"); // x component of body force 00244 bool has_by = BCs.HasKey("by"); // y component of body force 00245 bool has_bz = BCs.HasKey("bz"); // z component of body force 00246 bool has_cbx = BCs.HasKey("cbx"); // centrifugal body force along x (in axisymmetric problems) 00247 bool has_qx = BCs.HasKey("qx"); // x component of distributed loading 00248 bool has_qy = BCs.HasKey("qy"); // y component of distributed loading 00249 bool has_qz = BCs.HasKey("qz"); // z component of distributed loading 00250 bool has_qn = BCs.HasKey("qn"); // normal distributed loading 00251 bool has_qt = BCs.HasKey("qt"); // tangential distributed loading (2D only) 00252 bool has_ux = BCs.HasKey("ux"); // x displacement 00253 bool has_uy = BCs.HasKey("uy"); // y displacement 00254 bool has_uz = BCs.HasKey("uz"); // z displacement 00255 bool has_sup = BCs.HasKey("incsup"); // inclined support 00256 bool has_gra = BCs.HasKey("gravity"); // gravity 00257 00258 // force components specified 00259 if (has_bx || has_by || has_bz || has_cbx || has_gra || 00260 has_qx || has_qy || has_qz || has_qn || has_qt) 00261 { 00262 // body forces 00263 if (has_bx || has_by || has_bz || has_cbx || has_gra) // prescribed body forces 00264 { 00265 // matrix of coordinates of nodes 00266 Mat_t C; 00267 CoordMatrix (C); 00268 00269 // loading 00270 double bx = (has_bx ? BCs("bx") : 0.0); 00271 double by = (has_by ? BCs("by") : 0.0); 00272 double bz = (has_bz ? BCs("bz") : 0.0); 00273 bx = (has_cbx ? BCs("cbx") : bx ); 00274 if (has_gra) 00275 { 00276 if (NDim==2) by = -rho*BCs("gravity"); 00277 else bz = -rho*BCs("gravity"); 00278 } 00279 00280 // set 00281 for (size_t i=0; i<GE->NIP; ++i) 00282 { 00283 // geometric data 00284 GE->Shape (GE->IPs[i].r, GE->IPs[i].s, GE->IPs[i].t); 00285 GE->Derivs (GE->IPs[i].r, GE->IPs[i].s, GE->IPs[i].t); 00286 00287 // Jacobian and its determinant 00288 Mat_t J(GE->dNdR * C); // J = dNdR * C 00289 double detJ = Det(J); 00290 00291 // coefficient used during integration 00292 double coef = h*detJ*GE->IPs[i].w; 00293 if (GTy==axs_t) 00294 { 00295 // calculate radius=x at this IP 00296 double radius = 0.0; 00297 for (size_t j=0; j<GE->NN; ++j) radius += GE->N(j)*Con[j]->Vert.C[0]; 00298 00299 // correct coef 00300 if (has_cbx) coef *= radius*radius; 00301 else coef *= radius; 00302 } 00303 00304 // set boundary conditions 00305 for (size_t j=0; j<GE->NN; ++j) 00306 { 00307 Con[j]->AddToPF("fx", coef*GE->N(j)*bx, BCF); 00308 Con[j]->AddToPF("fy", coef*GE->N(j)*by, BCF); if (NDim==3) 00309 Con[j]->AddToPF("fz", coef*GE->N(j)*bz, BCF); 00310 } 00311 } 00312 } 00313 00314 // surface loading 00315 if (has_qx || has_qy || has_qz || has_qn || has_qt) 00316 { 00317 // matrix of coordinates of edge/face 00318 Mat_t Cf; 00319 FCoordMatrix (IdxEdgeOrFace, Cf); 00320 00321 // loading 00322 double qx = (has_qx ? BCs("qx") : 0.0); 00323 double qy = (has_qy ? BCs("qy") : 0.0); 00324 double qz = (has_qz ? BCs("qz") : 0.0); 00325 double qn = (has_qn ? BCs("qn") : 0.0); 00326 double qt = (has_qt ? BCs("qt") : 0.0); 00327 00328 // set 00329 for (size_t i=0; i<GE->NFIP; ++i) 00330 { 00331 // geometric data 00332 GE->FaceShape (GE->FIPs[i].r, GE->FIPs[i].s); 00333 GE->FaceDerivs (GE->FIPs[i].r, GE->FIPs[i].s); 00334 00335 // face/edge Jacobian and its determinant 00336 Mat_t J(GE->FdNdR * Cf); 00337 00338 // coefficient used during integration 00339 double coef = h*GE->FIPs[i].w; // *detJ is not necessary since qx,qy,qz are already multiplied by detJ (due to normal) 00340 00341 if (GTy==axs_t) 00342 { 00343 // calculate radius=x at this FIP 00344 double radius = 0.0; 00345 for (size_t j=0; j<GE->NFN; ++j) radius += GE->FN(j)*Con[GE->FNode(IdxEdgeOrFace,j)]->Vert.C[0]; 00346 coef *= radius; // correct coef 00347 } 00348 00349 // calculate qx, qy and qz from qn and qt 00350 if (has_qn || has_qt) 00351 { 00352 // normal to edge/face 00353 Vec_t n(NDim); // normal multiplied by detJ 00354 if (NDim==2) n = J(0,1), -J(0,0); 00355 else 00356 { 00357 // vectorial product 00358 Vec_t a(3); a = J(0,0), J(0,1), J(0,2); 00359 Vec_t b(3); b = J(1,0), J(1,1), J(1,2); 00360 n = a(1)*b(2) - a(2)*b(1), 00361 a(2)*b(0) - a(0)*b(2), 00362 a(0)*b(1) - a(1)*b(0); 00363 } 00364 00365 // loading 00366 if (NDim==2) 00367 { 00368 qx = n(0)*qn - n(1)*qt; 00369 qy = n(1)*qn + n(0)*qt; 00370 } 00371 else 00372 { 00373 qx = n(0)*qn; 00374 qy = n(1)*qn; 00375 qz = n(2)*qn; 00376 } 00377 } 00378 00379 // set boundary conditions 00380 for (size_t j=0; j<GE->NFN; ++j) 00381 { 00382 size_t k = GE->FNode(IdxEdgeOrFace,j); 00383 Con[k]->AddToPF("fx", coef*GE->FN(j)*qx, BCF); 00384 Con[k]->AddToPF("fy", coef*GE->FN(j)*qy, BCF); if (NDim==3) 00385 Con[k]->AddToPF("fz", coef*GE->FN(j)*qz, BCF); 00386 } 00387 } 00388 } 00389 } 00390 00391 // prescribed displacements 00392 else if (has_ux || has_uy || has_uz || has_sup) 00393 { 00394 double ux = (has_ux ? BCs("ux") : 0.0); 00395 double uy = (has_uy ? BCs("uy") : 0.0); 00396 double uz = (has_uz ? BCs("uz") : 0.0); 00397 double alpha = (has_sup ? BCs("alpha") : 0.0); 00398 for (size_t j=0; j<GE->NFN; ++j) 00399 { 00400 size_t k = GE->FNode(IdxEdgeOrFace,j); 00401 if (has_ux) Con[k]->SetPU("ux", ux, BCF); 00402 if (has_uy) Con[k]->SetPU("uy", uy, BCF); 00403 if (has_uz) Con[k]->SetPU("uz", uz, BCF); 00404 if (has_sup) Con[k]->SetIncSup (alpha); 00405 } 00406 } 00407 } 00408 00409 inline void EquilibElem::GetLoc (Array<size_t> & Loc) const 00410 { 00411 Loc.Resize (NDu); 00412 for (size_t i=0; i<GE->NN; ++i) 00413 { 00414 Loc[i*NDim+0] = Con[i]->Eq("ux"); 00415 Loc[i*NDim+1] = Con[i]->Eq("uy"); if (NDim==3) 00416 Loc[i*NDim+2] = Con[i]->Eq("uz"); 00417 } 00418 } 00419 00420 inline void EquilibElem::CalcK (Mat_t & K) const 00421 { 00422 double detJ, coef; 00423 Mat_t C, D, B; 00424 K.change_dim (NDu, NDu); 00425 set_to_zero (K); 00426 CoordMatrix (C); 00427 for (size_t i=0; i<GE->NIP; ++i) 00428 { 00429 Mdl->Stiffness (Sta[i], D); 00430 CalcB (C, GE->IPs[i], B, detJ, coef); 00431 K += (coef) * trans(B)*D*B; 00432 } 00433 } 00434 00435 inline void EquilibElem::CalcM (Mat_t & M) const 00436 { 00437 double detJ, coef; 00438 Mat_t C, N; 00439 M.change_dim (NDu, NDu); 00440 set_to_zero (M); 00441 CoordMatrix (C); 00442 for (size_t i=0; i<GE->NIP; ++i) 00443 { 00444 CalcN (C, GE->IPs[i], N, detJ, coef); 00445 M += (rho*coef) * trans(N)*N; 00446 } 00447 } 00448 00449 inline void EquilibElem::CalcB (Mat_t const & C, IntegPoint const & IP, Mat_t & B, double & detJ, double & Coef) const 00450 { 00451 // deriv of shape func w.r.t natural coordinates 00452 GE->Derivs (IP.r, IP.s, IP.t); 00453 00454 // Jacobian and its determinant 00455 Mat_t J(GE->dNdR * C); // J = dNdR * C 00456 detJ = Det(J); 00457 00458 // deriv of shape func w.r.t real coordinates 00459 Mat_t Ji; 00460 Inv (J, Ji); 00461 Mat_t dNdX(Ji * GE->dNdR); // dNdX = Inv(J) * dNdR 00462 00463 // coefficient used during integration 00464 Coef = h*detJ*IP.w; 00465 00466 00467 00468 //std::cout << "J = \n" << PrintMatrix(J); 00469 //std::cout << "dNdR = \n" << PrintMatrix(GE->dNdR); 00470 //std::cout << "C = \n" << PrintMatrix(C); 00471 //std::cout << "dNdX = \n" << PrintMatrix(dNdX); 00472 //printf("detJ = %g\n", detJ); 00473 00474 00475 // B matrix 00476 B.change_dim (NCo, NDu); 00477 set_to_zero (B); 00478 if (NDim==2) 00479 { 00480 if (GTy==axs_t) 00481 { 00482 // shape functions 00483 GE->Shape (IP.r, IP.s, IP.t); 00484 00485 // correct Coef 00486 double radius = 0.0; // radius=x at this IP 00487 for (size_t j=0; j<GE->NN; ++j) radius += GE->N(j)*Con[j]->Vert.C[0]; 00488 Coef *= radius; 00489 00490 // B matrix 00491 for (size_t i=0; i<GE->NN; ++i) 00492 { 00493 B(0,0+i*NDim) = dNdX(0,i); 00494 B(1,1+i*NDim) = dNdX(1,i); 00495 B(2,0+i*NDim) = GE->N(i)/radius; 00496 B(3,0+i*NDim) = dNdX(1,i)/sqrt(2.0); 00497 B(3,1+i*NDim) = dNdX(0,i)/sqrt(2.0); 00498 } 00499 //std::cout << "B = \n" << PrintMatrix(B); 00500 } 00501 else // pse_t, psa_t 00502 { 00503 for (size_t i=0; i<GE->NN; ++i) 00504 { 00505 B(0,0+i*NDim) = dNdX(0,i); 00506 B(1,1+i*NDim) = dNdX(1,i); 00507 B(3,0+i*NDim) = dNdX(1,i)/sqrt(2.0); 00508 B(3,1+i*NDim) = dNdX(0,i)/sqrt(2.0); 00509 } 00510 } 00511 } 00512 else // 3D 00513 { 00514 for (size_t i=0; i<GE->NN; ++i) 00515 { 00516 B(0,0+i*NDim) = dNdX(0,i); 00517 B(1,1+i*NDim) = dNdX(1,i); 00518 B(2,2+i*NDim) = dNdX(2,i); 00519 B(3,0+i*NDim) = dNdX(1,i)/sqrt(2.0); B(3,1+i*NDim) = dNdX(0,i)/sqrt(2.0); 00520 B(4,1+i*NDim) = dNdX(2,i)/sqrt(2.0); B(4,2+i*NDim) = dNdX(1,i)/sqrt(2.0); 00521 B(5,2+i*NDim) = dNdX(0,i)/sqrt(2.0); B(5,0+i*NDim) = dNdX(2,i)/sqrt(2.0); 00522 } 00523 } 00524 } 00525 00526 inline void EquilibElem::CalcN (Mat_t const & C, IntegPoint const & IP, Mat_t & N, double & detJ, double & Coef) const 00527 { 00528 // deriv of shape func w.r.t natural coordinates 00529 GE->Shape (IP.r, IP.s, IP.t); 00530 GE->Derivs (IP.r, IP.s, IP.t); 00531 00532 // Jacobian and its determinant 00533 Mat_t J(GE->dNdR * C); // J = dNdR * C 00534 detJ = Det(J); 00535 00536 // coefficient used during integration 00537 Coef = h*detJ*IP.w; 00538 00539 // N matrix 00540 N.change_dim (NDim, NDu); 00541 set_to_zero (N); 00542 if (GTy==axs_t) 00543 { 00544 double radius = 0.0; // radius=x at this IP 00545 for (size_t j=0; j<GE->NN; ++j) radius += GE->N(j)*Con[j]->Vert.C[0]; 00546 Coef *= radius; // correct coef for axisymmetric problems 00547 } 00548 for (int i=0; i<NDim; ++i) 00549 for (size_t j=0; j<GE->NN; ++j) 00550 N(i,i+j*NDim) = GE->N(j); 00551 } 00552 00553 inline void EquilibElem::UpdateState (Vec_t const & dU, Vec_t * F_int) const 00554 { 00555 // get location array 00556 Array<size_t> loc; 00557 GetLoc (loc); 00558 00559 // element nodal displacements 00560 Vec_t dUe(NDu); 00561 for (size_t i=0; i<loc.Size(); ++i) dUe(i) = dU(loc[i]); 00562 00563 // update state at each IP 00564 double detJ, coef; 00565 Mat_t C, B; 00566 Vec_t dFe(NDu), dsig(NCo), deps(NCo); 00567 set_to_zero (dFe); 00568 CoordMatrix (C); 00569 for (size_t i=0; i<GE->NIP; ++i) 00570 { 00571 // B matrix 00572 CalcB (C, GE->IPs[i], B, detJ, coef); 00573 00574 // strain and stress increments 00575 deps = B * dUe; 00576 std::cout << "deps = " << PrintVector(deps); 00577 Mdl->SUp.Update (deps, Sta[i], dsig); 00578 00579 // element nodal forces 00580 dFe += (coef) * trans(B)*dsig; 00581 } 00582 00583 // add results to Fint (internal forces) 00584 if (F_int!=NULL) for (size_t i=0; i<loc.Size(); ++i) (*F_int)(loc[i]) += dFe(i); 00585 } 00586 00587 inline void EquilibElem::SetFint (Vec_t * Fint) const 00588 { 00589 // element force 00590 double detJ, coef; 00591 Mat_t C, B; 00592 Vec_t Fe(NDu); 00593 CoordMatrix (C); 00594 set_to_zero (Fe); 00595 for (size_t i=0; i<GE->NIP; ++i) 00596 { 00597 CalcB (C, GE->IPs[i], B, detJ, coef); 00598 Vec_t const & sig = static_cast<EquilibState const *>(Sta[i])->Sig; 00599 Fe += (coef) * trans(B)*sig; 00600 } 00601 00602 // set nodes 00603 if (Fint==NULL) 00604 { 00605 for (size_t i=0; i<GE->NN; ++i) 00606 { 00607 Con[i]->F("fx") += Fe(0+i*NDim); 00608 Con[i]->F("fy") += Fe(1+i*NDim); if (NDim==3) 00609 Con[i]->F("fz") += Fe(2+i*NDim); 00610 } 00611 } 00612 00613 // return Fint 00614 else 00615 { 00616 Array<size_t> loc; 00617 GetLoc (loc); 00618 for (size_t i=0; i<loc.Size(); ++i) (*Fint)(loc[i]) += Fe(i); 00619 } 00620 } 00621 00622 inline void EquilibElem::StateKeys (Array<String> & Keys) const 00623 { 00624 Keys = EquilibState::Keys; 00625 for (size_t i=0; i<Mdl->NIvs; ++i) Keys.Push (Mdl->IvNames[i]); 00626 } 00627 00628 inline void EquilibElem::StateAtIP (SDPair & KeysVals, int IdxIP) const 00629 { 00630 Vec_t const & sig = static_cast<EquilibState const *>(Sta[IdxIP])->Sig; 00631 Vec_t const & eps = static_cast<EquilibState const *>(Sta[IdxIP])->Eps; 00632 Vec_t const & ivs = static_cast<EquilibState const *>(Sta[IdxIP])->Ivs; 00633 00634 if (NDim==2) 00635 { 00636 KeysVals.Set("sx sy sz sxy ex ey ez exy pcam qcam ev ed", 00637 sig(0), sig(1), sig(2), sig(3)/Util::SQ2, 00638 eps(0), eps(1), eps(2), eps(3)/Util::SQ2, 00639 Calc_pcam(sig), Calc_qcam(sig), Calc_ev(eps), Calc_ed(eps)); 00640 } 00641 else 00642 { 00643 KeysVals.Set("sx sy sz sxy syz szx ex ey ez exy eyz ezx pcam qcam ev ed", 00644 sig(0), sig(1), sig(2), sig(3)/Util::SQ2, sig(4)/Util::SQ2, sig(5)/Util::SQ2, 00645 eps(0), eps(1), eps(2), eps(3)/Util::SQ2, eps(4)/Util::SQ2, eps(5)/Util::SQ2, 00646 Calc_pcam(sig), Calc_qcam(sig), Calc_ev(eps), Calc_ed(eps)); 00647 } 00648 for (size_t k=0; k<Mdl->NIvs; ++k) KeysVals.Set(Mdl->IvNames[k].CStr(), ivs(k)); 00649 } 00650 00651 inline size_t EquilibElem::NIVs () const 00652 { 00653 size_t niv = size(static_cast<EquilibState const*>(Sta[0])->Ivs); 00654 return (NCo+niv)*GE->NIP; 00655 } 00656 00657 inline double EquilibElem::GetIV (size_t i) const 00658 { 00659 size_t niv = size(static_cast<EquilibState const*>(Sta[0])->Ivs); 00660 size_t iip = static_cast<int>(i) / static_cast<int>(NCo+niv); // index of IP 00661 size_t ico = static_cast<int>(i) % static_cast<int>(NCo+niv); // index of component/iv 00662 if (ico<NCo) return static_cast<EquilibState const*>(Sta[iip])->Sig(ico); 00663 else return static_cast<EquilibState const*>(Sta[iip])->Ivs(ico-NCo); 00664 } 00665 00666 inline void EquilibElem::SetIV (size_t i, double Val) 00667 { 00668 size_t niv = size(static_cast<EquilibState const*>(Sta[0])->Ivs); 00669 size_t iip = static_cast<int>(i) / static_cast<int>(NCo+niv); // index of IP 00670 size_t ico = static_cast<int>(i) % static_cast<int>(NCo+niv); // index of component 00671 if (ico<NCo) static_cast<EquilibState*>(Sta[iip])->Sig(ico) = Val; 00672 else static_cast<EquilibState*>(Sta[iip])->Ivs(ico-NCo) = Val; 00673 } 00674 00675 inline void EquilibElem::CalcIVRate (double Time, Vec_t const & U, Vec_t const & V, Vec_t & Rate) const 00676 { 00677 // resize rate 00678 size_t niv = size(static_cast<EquilibState const*>(Sta[0])->Ivs); 00679 Rate.change_dim ((NCo+niv)*GE->NIP); 00680 00681 // get location array 00682 Array<size_t> loc; 00683 GetLoc (loc); 00684 00685 // element nodal velocities 00686 Vec_t Ve(NDu); 00687 for (size_t i=0; i<loc.Size(); ++i) Ve(i) = V(loc[i]); 00688 00689 // calc dsigdt 00690 double detJ, coef; 00691 Mat_t C, B, D; 00692 Vec_t depsdt(NCo), dsigdt(NCo), divsdt(niv); 00693 CoordMatrix (C); 00694 for (size_t i=0; i<GE->NIP; ++i) 00695 { 00696 CalcB (C, GE->IPs[i], B, detJ, coef); 00697 depsdt = B * Ve; 00698 Mdl->Rate (Sta[i], depsdt, dsigdt, divsdt); 00699 for (size_t j=0; j<NCo; ++j) Rate( j+i*(NCo+niv)) = dsigdt(j); 00700 for (size_t j=0; j<niv; ++j) Rate(NCo+j+i*(NCo+niv)) = divsdt(j); 00701 } 00702 } 00703 00704 inline void EquilibElem::CorrectIVs () 00705 { 00706 if (Mdl->SUp.CDrift) 00707 { 00708 for (size_t i=0; i<GE->NIP; ++i) Mdl->CorrectDrift (Sta[i]); 00709 } 00710 } 00711 00712 00714 00715 00716 // Allocate a new element 00717 Element * EquilibElemMaker(int NDim, Mesh::Cell const & Cell, Model const * Mdl, Model const * XMdl, SDPair const & Prp, SDPair const & Ini, Array<Node*> const & Nodes) { return new EquilibElem(NDim,Cell,Mdl,XMdl,Prp,Ini,Nodes); } 00718 00719 // Register element 00720 int EquilibElemRegister() 00721 { 00722 ElementFactory ["Equilib"] = EquilibElemMaker; 00723 ElementVarKeys ["Equilib2D"] = std::make_pair ("ux uy", "fx fy"); 00724 ElementVarKeys ["Equilib3D"] = std::make_pair ("ux uy uz", "fx fy fz"); 00725 ElementExtraKeys["Equilib2D"] = Array<String> ("activate", "deactivate", "grav", "qn", "qt"); 00726 ElementExtraKeys["Equilib3D"] = Array<String> ("activate", "deactivate", "grav", "qn"); 00727 PROB.Set ("Equilib", (double)PROB.Keys.Size()); 00728 return 0; 00729 } 00730 00731 // Call register 00732 int __EquilibElem_dummy_int = EquilibElemRegister(); 00733 00734 }; // namespace FEM 00735 00736 #endif // MECHSYS_FEM_EQUILIBELEM