![]() |
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 // This is the mixed u-sig element (usigelem) with the condensation of the local DOFs 00021 00022 #ifndef MECHSYS_FEM_USIGCONDELEM_H 00023 #define MECHSYS_FEM_USIGCONDELEM_H 00024 00025 // MechSys 00026 #include <mechsys/fem/element.h> 00027 #include <mechsys/models/equilibstate.h> 00028 #include <mechsys/models/stressupdate.h> 00029 00030 namespace FEM 00031 { 00032 00033 class USigCondElem : public Element 00034 { 00035 public: 00036 // static 00037 static size_t NCo; 00038 static size_t NDs; 00039 static size_t NDu; 00040 00041 // Constructor 00042 USigCondElem (int NDim, 00043 Mesh::Cell const & Cell, 00044 Model const * Mdl, 00045 Model const * XMdl, 00046 SDPair const & Prp, 00047 SDPair const & Ini, 00048 Array<Node*> const & Nodes); 00049 00050 // Destructor 00051 ~USigCondElem () { if (GEs!=NULL) delete GEs; } 00052 00053 // Methods 00054 void GetLoc (Array<size_t> & Loc) const; 00055 void SetBCs (size_t IdxEdgeOrFace, SDPair const & BCs, BCFuncs * BCF); 00056 void CalcK (Mat_t & K) const; 00057 void CalcFint (Vec_t * F_int=NULL) const; 00058 void UpdateState (Vec_t const & dU, Vec_t * F_int=NULL) const; 00059 void StateKeys (Array<String> & Keys) const; 00060 void StateAtIP (SDPair & KeysVals, int IdxIP) const; 00061 00062 // Internal methods 00063 void Matrices (Mat_t & Ai, Mat_t & Q) const; 00064 void Interp (Mat_t const & C, IntegPoint const & IP, Mat_t & B, Mat_t & N, Mat_t & Nsig, double & detJ, double & Coef) const; 00065 00066 // Constants 00067 GeomElem * GEs; 00068 mutable long FirstEQsig; 00069 }; 00070 00071 size_t USigCondElem::NCo = 0; 00072 size_t USigCondElem::NDs = 0; 00073 size_t USigCondElem::NDu = 0; 00074 00075 00077 00078 00079 inline USigCondElem::USigCondElem (int NDim, Mesh::Cell const & Cell, Model const * Mdl, Model const * XMdl, SDPair const & Prp, SDPair const & Ini, Array<Node*> const & Nodes) 00080 : Element(NDim,Cell,Mdl,XMdl,Prp,Ini,Nodes) 00081 { 00082 // check GE 00083 if (GE==NULL) throw new Fatal("USigCondElem::USigCondElem: GE (geometry element) must be defined"); 00084 if (GTy==pse_t) throw new Fatal("USigCondElem::USigCondElem: This element does not work for plane-stress (pse)"); 00085 if (Mdl==NULL) throw new Fatal("USigCondElem::USigCondElem: Model must be defined"); 00086 00087 // local nodes 00088 if (strcmp(GE->Name.CStr(),"Quad8")==0) GEs = AllocGeomElem ("Quad4", NDim); 00089 else throw new Fatal("USigCondElem::USigCondElem: GE must be Quad8 for the time being"); 00090 00091 // set constants of this class (once) 00092 if (NDs==0) 00093 { 00094 NCo = 2*NDim; 00095 NDs = NCo*GEs->NN; 00096 NDu = NDim*GE->NN; 00097 } 00098 00099 // allocate and initialize state at each local node 00100 for (size_t i=0; i<GEs->NN; ++i) 00101 { 00102 Sta.Push (new EquilibState(NDim)); 00103 Mdl->InitIvs (Ini, Sta[i]); // initialize with effective stresses 00104 } 00105 00106 // set F in nodes due to initial stresses 00107 double detJ, coef; 00108 Mat_t C, B, N, Ns; 00109 Vec_t Fe(NDu); 00110 CoordMatrix (C); 00111 set_to_zero (Fe); 00112 for (size_t i=0; i<GE->NIP; ++i) 00113 { 00114 Interp (C, GE->IPs[i], B, N, Ns, detJ, coef); 00115 Vec_t const & sig = static_cast<EquilibState const *>(Sta[i])->Sig; 00116 Fe += (coef) * trans(B)*sig; 00117 } 00118 for (size_t i=0; i<GE->NN; ++i) 00119 { 00120 Con[i]->F("fx") += Fe(0+i*NDim); 00121 Con[i]->F("fy") += Fe(1+i*NDim); if (NDim==3) 00122 Con[i]->F("fz") += Fe(2+i*NDim); 00123 } 00124 } 00125 00126 inline void USigCondElem::SetBCs (size_t IdxEdgeOrFace, SDPair const & BCs, BCFuncs * BCF) 00127 { 00128 // deactivate/activate commands 00129 if (BCs.HasKey("deactivate")) throw new Fatal("USigCondElem::SetBCs: 'deactivate' command failed: method not implemented yet"); 00130 if (BCs.HasKey("activate")) throw new Fatal("USigCondElem::SetBCs: 'activate' command failed: method not implemented yet"); 00131 00132 // check 00133 if (!Active) throw new Fatal("USigCondElem::SetBCs: Element %d is inactive",Cell.ID); 00134 00135 bool has_bx = BCs.HasKey("bx"); // x component of body force 00136 bool has_by = BCs.HasKey("by"); // y component of body force 00137 bool has_bz = BCs.HasKey("bz"); // z component of body force 00138 bool has_cbx = BCs.HasKey("cbx"); // centrifugal body force along x (in axisymmetric problems) 00139 bool has_qx = BCs.HasKey("qx"); // x component of distributed loading 00140 bool has_qy = BCs.HasKey("qy"); // y component of distributed loading 00141 bool has_qz = BCs.HasKey("qz"); // z component of distributed loading 00142 bool has_qn = BCs.HasKey("qn"); // normal distributed loading 00143 bool has_qt = BCs.HasKey("qt"); // tangential distributed loading (2D only) 00144 bool has_ux = BCs.HasKey("ux"); // x displacement 00145 bool has_uy = BCs.HasKey("uy"); // y displacement 00146 bool has_uz = BCs.HasKey("uz"); // z displacement 00147 bool has_sup = BCs.HasKey("incsup"); // inclined support 00148 00149 // force components specified 00150 if (has_bx || has_by || has_bz || has_cbx || 00151 has_qx || has_qy || has_qz || has_qn || has_qt) 00152 { 00153 // body forces 00154 if (has_bx || has_by || has_bz || has_cbx) // prescribed body forces 00155 { 00156 // matrix of coordinates of nodes 00157 Mat_t C; 00158 CoordMatrix (C); 00159 00160 // loading 00161 double bx = (has_bx ? BCs("bx") : 0.0); 00162 double by = (has_by ? BCs("by") : 0.0); 00163 double bz = (has_bz ? BCs("bz") : 0.0); 00164 bx = (has_cbx ? BCs("cbx") : bx ); 00165 00166 // set 00167 for (size_t i=0; i<GE->NIP; ++i) 00168 { 00169 // geometric data 00170 GE->Shape (GE->IPs[i].r, GE->IPs[i].s, GE->IPs[i].t); 00171 GE->Derivs (GE->IPs[i].r, GE->IPs[i].s, GE->IPs[i].t); 00172 00173 // Jacobian and its determinant 00174 Mat_t J(GE->dNdR * C); // J = dNdR * C 00175 double detJ = Det(J); 00176 00177 // coefficient used during integration 00178 double coef = detJ*GE->IPs[i].w; 00179 if (GTy==axs_t) 00180 { 00181 // calculate radius=x at this IP 00182 double radius = 0.0; 00183 for (size_t j=0; j<GE->NN; ++j) radius += GE->N(j)*Con[j]->Vert.C[0]; 00184 00185 // correct coef 00186 if (has_cbx) coef *= radius*radius; 00187 else coef *= radius; 00188 } 00189 00190 // set boundary conditions 00191 for (size_t j=0; j<GE->NN; ++j) 00192 { 00193 Con[j]->AddToPF("fx", coef*GE->N(j)*bx, BCF); 00194 Con[j]->AddToPF("fy", coef*GE->N(j)*by, BCF); if (NDim==3) 00195 Con[j]->AddToPF("fz", coef*GE->N(j)*bz, BCF); 00196 } 00197 } 00198 } 00199 00200 // surface loading 00201 if (has_qx || has_qy || has_qz || has_qn || has_qt) 00202 { 00203 // matrix of coordinates of edge/face 00204 Mat_t Cf; 00205 FCoordMatrix (IdxEdgeOrFace, Cf); 00206 00207 // loading 00208 double qx = (has_qx ? BCs("qx") : 0.0); 00209 double qy = (has_qy ? BCs("qy") : 0.0); 00210 double qz = (has_qz ? BCs("qz") : 0.0); 00211 double qn = (has_qn ? BCs("qn") : 0.0); 00212 double qt = (has_qt ? BCs("qt") : 0.0); 00213 00214 // set 00215 for (size_t i=0; i<GE->NFIP; ++i) 00216 { 00217 // geometric data 00218 GE->FaceShape (GE->FIPs[i].r, GE->FIPs[i].s); 00219 GE->FaceDerivs (GE->FIPs[i].r, GE->FIPs[i].s); 00220 00221 // face/edge Jacobian and its determinant 00222 Mat_t J(GE->FdNdR * Cf); 00223 00224 // coefficient used during integration 00225 double coef = GE->FIPs[i].w; // *detJ is not necessary since qx,qy,qz are already multiplied by detJ (due to normal) 00226 00227 if (GTy==axs_t) 00228 { 00229 // calculate radius=x at this FIP 00230 double radius = 0.0; 00231 for (size_t j=0; j<GE->NFN; ++j) radius += GE->FN(j)*Con[GE->FNode(IdxEdgeOrFace,j)]->Vert.C[0]; 00232 coef *= radius; // correct coef 00233 } 00234 00235 // calculate qx, qy and qz from qn and qt 00236 if (has_qn || has_qt) 00237 { 00238 // normal to edge/face 00239 Vec_t n(NDim); // normal multiplied by detJ 00240 if (NDim==2) n = J(0,1), -J(0,0); 00241 else 00242 { 00243 // vectorial product 00244 Vec_t a(3); a = J(0,0), J(0,1), J(0,2); 00245 Vec_t b(3); b = J(1,0), J(1,1), J(1,2); 00246 n = a(1)*b(2) - a(2)*b(1), 00247 a(2)*b(0) - a(0)*b(2), 00248 a(0)*b(1) - a(1)*b(0); 00249 } 00250 00251 // loading 00252 if (NDim==2) 00253 { 00254 qx = n(0)*qn - n(1)*qt; 00255 qy = n(1)*qn + n(0)*qt; 00256 } 00257 else 00258 { 00259 qx = n(0)*qn; 00260 qy = n(1)*qn; 00261 qz = n(2)*qn; 00262 } 00263 } 00264 00265 // set boundary conditions 00266 for (size_t j=0; j<GE->NFN; ++j) 00267 { 00268 size_t k = GE->FNode(IdxEdgeOrFace,j); 00269 Con[k]->AddToPF("fx", coef*GE->FN(j)*qx, BCF); 00270 Con[k]->AddToPF("fy", coef*GE->FN(j)*qy, BCF); if (NDim==3) 00271 Con[k]->AddToPF("fz", coef*GE->FN(j)*qz, BCF); 00272 } 00273 } 00274 } 00275 } 00276 00277 // prescribed displacements 00278 else if (has_ux || has_uy || has_uz || has_sup) 00279 { 00280 double ux = (has_ux ? BCs("ux") : 0.0); 00281 double uy = (has_uy ? BCs("uy") : 0.0); 00282 double uz = (has_uz ? BCs("uz") : 0.0); 00283 double alpha = (has_sup ? BCs("alpha") : 0.0); 00284 for (size_t j=0; j<GE->NFN; ++j) 00285 { 00286 size_t k = GE->FNode(IdxEdgeOrFace,j); 00287 if (has_ux) Con[k]->SetPU("ux", ux, BCF); 00288 if (has_uy) Con[k]->SetPU("uy", uy, BCF); 00289 if (has_uz) Con[k]->SetPU("uz", uz, BCF); 00290 if (has_sup) Con[k]->SetIncSup (alpha); 00291 } 00292 } 00293 } 00294 00295 inline void USigCondElem::GetLoc (Array<size_t> & Loc) const 00296 { 00297 Loc.Resize (NDu); 00298 for (size_t i=0; i<GE->NN; ++i) 00299 { 00300 Loc[i*NDim+0] = Con[i]->Eq("ux"); 00301 Loc[i*NDim+1] = Con[i]->Eq("uy"); if (NDim==3) 00302 Loc[i*NDim+2] = Con[i]->Eq("uz"); 00303 } 00304 } 00305 00306 inline void USigCondElem::Matrices (Mat_t & Ai, Mat_t & Q) const 00307 { 00308 // submatrices 00309 Q.change_dim (NDs,NDu); 00310 set_to_zero (Q); 00311 00312 // auxiliar matrices 00313 double detJ, coef; 00314 Mat_t NtDiN (NDs,NDs); 00315 Mat_t NtB (NDs,NDu); 00316 Mat_t N, Nsig, A(NDs,NDs), B, C, D(NCo,NCo), Di; 00317 CoordMatrix (C); 00318 set_to_zero (A); 00319 00320 double E = 1000.0; 00321 double nu = 0.2; 00322 double c = E/((1.0+nu)*(1.0-2.0*nu)); 00323 D = c*(1.0-nu), c*nu , c*nu , 0.0, 00324 c*nu , c*(1.0-nu), c*nu , 0.0, 00325 c*nu , c*nu , c*(1.0-nu), 0.0, 00326 0.0 , 0.0 , 0.0 , c*(1.0-2.0*nu); 00327 00328 for (size_t i=0; i<GE->NIP; ++i) 00329 { 00330 Interp (C, GE->IPs[i], B, N, Nsig, detJ, coef); 00331 00332 Inv (D, Di); 00333 00334 NtDiN = trans(Nsig)*Di*Nsig; 00335 NtB = trans(Nsig)*B; 00336 A -= (coef) * NtDiN; 00337 Q += (coef) * NtB; 00338 } 00339 00340 Inv (A, Ai); 00341 } 00342 00343 inline void USigCondElem::CalcK (Mat_t & K) const 00344 { 00345 Mat_t Ai, Q; 00346 Matrices (Ai, Q); 00347 K.change_dim (NDu,NDu); 00348 00349 K = (-1.)*trans(Q)*Ai*Q; 00350 } 00351 00352 inline void USigCondElem::Interp (Mat_t const & C, IntegPoint const & IP, Mat_t & B, Mat_t & N, Mat_t & Nsig, double & detJ, double & Coef) const 00353 { 00354 // deriv of shape func w.r.t natural coordinates 00355 GE ->Shape (IP.r, IP.s, IP.t); 00356 GE ->Derivs (IP.r, IP.s, IP.t); 00357 GEs->Shape (IP.r, IP.s, IP.t); 00358 00359 // Jacobian and its determinant 00360 Mat_t J(GE->dNdR * C); // J = dNdR * C 00361 detJ = Det(J); 00362 00363 // deriv of shape func w.r.t real coordinates 00364 Mat_t Ji; 00365 Inv (J, Ji); 00366 Mat_t dNdX(Ji * GE->dNdR); // dNdX = Inv(J) * dNdR 00367 00368 // coefficient used during integration 00369 Coef = detJ*IP.w; 00370 00371 // B matrix 00372 B.change_dim (NCo,NDu); 00373 set_to_zero (B); 00374 if (NDim==2) 00375 { 00376 if (GTy==axs_t) 00377 { 00378 // correct Coef 00379 double radius = 0.0; // radius=x at this IP 00380 for (size_t j=0; j<GE->NN; ++j) radius += GE->N(j)*Con[j]->Vert.C[0]; 00381 Coef *= radius; 00382 00383 // B matrix 00384 for (size_t i=0; i<GE->NN; ++i) 00385 { 00386 B(0,0+i*NDim) = dNdX(0,i); 00387 B(1,1+i*NDim) = dNdX(1,i); 00388 B(2,0+i*NDim) = GE->N(i)/radius; 00389 B(3,0+i*NDim) = dNdX(1,i)/sqrt(2.0); 00390 B(3,1+i*NDim) = dNdX(0,i)/sqrt(2.0); 00391 } 00392 } 00393 else // pse_t, psa_t 00394 { 00395 for (size_t i=0; i<GE->NN; ++i) 00396 { 00397 B(0,0+i*NDim) = dNdX(0,i); 00398 B(1,1+i*NDim) = dNdX(1,i); 00399 B(3,0+i*NDim) = dNdX(1,i)/sqrt(2.0); 00400 B(3,1+i*NDim) = dNdX(0,i)/sqrt(2.0); 00401 } 00402 } 00403 } 00404 else // 3D 00405 { 00406 for (size_t i=0; i<GE->NN; ++i) 00407 { 00408 B(0,0+i*NDim) = dNdX(0,i); 00409 B(1,1+i*NDim) = dNdX(1,i); 00410 B(2,2+i*NDim) = dNdX(2,i); 00411 B(3,0+i*NDim) = dNdX(1,i)/sqrt(2.0); B(3,1+i*NDim) = dNdX(0,i)/sqrt(2.0); 00412 B(4,1+i*NDim) = dNdX(2,i)/sqrt(2.0); B(4,2+i*NDim) = dNdX(1,i)/sqrt(2.0); 00413 B(5,2+i*NDim) = dNdX(0,i)/sqrt(2.0); B(5,0+i*NDim) = dNdX(2,i)/sqrt(2.0); 00414 } 00415 } 00416 00417 // N matrix 00418 N.change_dim (NDim,NDu); 00419 set_to_zero (N); 00420 for (int i=0; i<NDim; ++i) 00421 for (size_t j=0; j<GE->NN; ++j) 00422 N(i,i+j*NDim) = GE->N(j); 00423 00424 // Nsig matrix 00425 Nsig.change_dim (NCo,NDs); 00426 set_to_zero (Nsig); 00427 for (size_t i=0; i<NCo; ++i) 00428 for (size_t j=0; j<GEs->NN; ++j) 00429 Nsig(i,i+j*NCo) = GEs->N(j); 00430 } 00431 00432 inline void USigCondElem::UpdateState (Vec_t const & dU, Vec_t * F_int) const 00433 { 00434 } 00435 00436 inline void USigCondElem::StateKeys (Array<String> & Keys) const 00437 { 00438 } 00439 00440 inline void USigCondElem::StateAtIP (SDPair & KeysVals, int IdxIP) const 00441 { 00442 } 00443 00444 00446 00447 00448 // Allocate a new element 00449 Element * USigCondMaker(int NDim, Mesh::Cell const & Cell, Model const * Mdl, Model const * XMdl, SDPair const & Prp, SDPair const & Ini, Array<Node*> const & Nodes) { return new USigCondElem(NDim,Cell,Mdl,XMdl,Prp,Ini,Nodes); } 00450 00451 // Register element 00452 int USigCondRegister() 00453 { 00454 ElementFactory["USigCond"] = USigCondMaker; 00455 ElementVarKeys["USigCond2D"] = std::make_pair ("ux uy", "fx fy"); 00456 ElementVarKeys["USigCond3D"] = std::make_pair ("ux uy uz", "fx fy fz"); 00457 PROB.Set ("USigCond", (double)PROB.Keys.Size()); 00458 return 0; 00459 } 00460 00461 // Call register 00462 int __USigCond_dummy_int = USigCondRegister(); 00463 00464 }; // namespace FEM 00465 00466 #endif // MECHSYS_FEM_USIGCONDELEM_H