![]() |
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_ELASTOPLASTIC_H 00021 #define MECHSYS_ELASTOPLASTIC_H 00022 00023 // MechSys 00024 #include <mechsys/models/model.h> 00025 #include <mechsys/models/equilibstate.h> 00026 #include <mechsys/models/smpinvs.h> 00027 #include <mechsys/numerical/root.h> 00028 00029 class ElastoPlastic : public Model 00030 { 00031 public: 00032 // enums 00033 enum FCrit_t { VM_t, MC_t, GE_t }; 00034 00035 // Constructor & Destructor 00036 ElastoPlastic (int NDim, SDPair const & Prms, size_t NIv=3, char const * Name="ElastoPlastic(VM)", bool DerivedModel=false); 00037 virtual ~ElastoPlastic () {} 00038 00039 // Derived methods 00040 virtual void Rate (State const * Sta, Vec_t const & DEpsDt, Vec_t & DSigDt, Vec_t & DIvsDt) const; 00041 virtual void TgIncs (State const * Sta, Vec_t & DEps, Vec_t & DSig, Vec_t & DIvs) const; 00042 virtual void Stiffness (State const * Sta, Mat_t & D) const; 00043 virtual size_t CorrectDrift (State * Sta) const; 00044 virtual bool LoadCond (State const * Sta, Vec_t const & DEps, double & alpInt) const; 00045 00046 // Internal methods to be overloaded by derived classes 00047 virtual void InitIvs (SDPair const & Ini, State * Sta) const; 00048 virtual void Gradients (Vec_t const & Sig, Vec_t const & Ivs, bool Potential=false) const; 00049 virtual void Hardening (Vec_t const & Sig, Vec_t const & Ivs) const; 00050 virtual double YieldFunc (Vec_t const & Sig, Vec_t const & Ivs) const; 00051 virtual void ExtraDIvs (Vec_t & DIvs) const; 00052 virtual double CalcE (Vec_t const & Sig, Vec_t const & Ivs) const { return E; } 00053 virtual void ELStiff (Vec_t const & Sig, Vec_t const & Ivs) const; 00054 00055 // Constants 00056 bool Derived; 00057 double E; 00058 double nu; 00059 FCrit_t FC; 00060 double kVM; 00061 double kGE; 00062 double kGEpot; 00063 double pTol; 00064 double Hb; 00065 double sphi; 00066 double spsi; 00067 double FTol; 00068 double DCFTol; 00069 size_t DCMaxIt; 00070 double qTol; 00071 bool NewSU; 00072 double BetSU; 00073 double AlpSU; 00074 00075 // State data (mutable/scratch-pad) 00076 mutable double pc, pm, r2; 00077 mutable SMPInvs SMP; 00078 mutable Vec_t SigB; 00079 mutable Vec_t Sig0, Ivs0, SigA, DSigTr; 00080 mutable Vec_t DEpsEl; 00081 mutable Vec_t DEpsPl; 00082 mutable Vec_t V; 00083 mutable Vec_t W; 00084 mutable Vec_t Y; 00085 mutable Vec_t H; 00086 mutable Mat_t De; 00087 mutable Mat_t Dep; 00088 mutable Vec_t VDe; 00089 mutable Vec_t DeW; 00090 mutable Vec_t s; 00091 mutable Vec_t dthdsig; 00092 mutable Vec_t dgdsig; 00093 mutable Vec_t dI1dsig,dI2dsig,dI3dsig; 00094 mutable double p, q, t, th, g, I1, I2, I3; 00095 00096 // Methods for yield surface crossing 00097 double Fa (double Alp, void*) { SigA=Sig0+Alp*DSigTr; return YieldFunc(SigA,Ivs0); } 00098 double dFada (double Alp, void*) { SigA=Sig0+Alp*DSigTr; Gradients(SigA,Ivs0); return dot(V,DSigTr); } 00099 00100 // Auxiliary methods 00101 void Calc_pq (Vec_t const & Sig) const { p=Calc_poct(Sig); q=Calc_qoct(Sig); } 00102 void Calc_pqt (Vec_t const & Sig) const { OctInvs(Sig,p,q,t); th=asin(t)/3.0; } 00103 void Calc_pqg (Vec_t const & Sig, double sinp) const { OctInvs(Sig,p,q,t); th=asin(t)/3.0; g=Util::SQ2*sinp/(Util::SQ3*cos(th)-sinp*sin(th)); } 00104 void Calc_dgdsig (Vec_t const & Sig, double sinp) const 00105 { 00106 OctInvs (Sig, p,q,t,th,s, qTol, &dthdsig); 00107 g = Util::SQ2*sinp/(Util::SQ3*cos(th)-sinp*sin(th)); 00108 double dgdth = g*(Util::SQ3*sin(th)+sinp*cos(th))/(Util::SQ3*cos(th)-sinp*sin(th)); 00109 dgdsig = dgdth * dthdsig; 00110 } 00111 00112 void Calc_arc (double M) const 00113 { 00114 double den = 1.0 + M*M; 00115 pc = pTol/(1.0-M/sqrt(den)); 00116 pm = pc/den; 00117 r2 = pow(pc*M,2.0)/den; 00118 } 00119 }; 00120 00121 00123 00124 00125 inline ElastoPlastic::ElastoPlastic (int NDim, SDPair const & Prms, size_t NIv, char const * Name, bool Deriv) 00126 : Model (NDim, Prms, NIv, Name), 00127 Derived (Deriv), 00128 E (0.0), 00129 nu (0.0), 00130 FC (VM_t), 00131 kVM (0.0), 00132 pTol (1.0e-5), 00133 Hb (0.0), 00134 FTol (1.0e-7), 00135 DCFTol (1.0e-8), 00136 DCMaxIt (10), 00137 qTol (1.0e-7), 00138 NewSU (false) 00139 { 00140 // resize scratchpad arrays 00141 SigB .change_dim (NCps); 00142 Sig0 .change_dim (NCps); 00143 Ivs0 .change_dim (NIvs); 00144 SigA .change_dim (NCps); 00145 DSigTr .change_dim (NCps); 00146 DEpsEl .change_dim (NCps); 00147 V .change_dim (NCps); 00148 W .change_dim (NCps); 00149 Y .change_dim (NIvs); 00150 H .change_dim (NIvs); 00151 De .change_dim (NCps,NCps); 00152 Dep .change_dim (NCps,NCps); 00153 VDe .change_dim (NCps); 00154 DeW .change_dim (NCps); 00155 s .change_dim (NCps); 00156 dthdsig.change_dim (NCps); 00157 dgdsig .change_dim (NCps); 00158 dI1dsig.change_dim (NCps); 00159 dI2dsig.change_dim (NCps); 00160 dI3dsig.change_dim (NCps); 00161 00162 // reference pressure 00163 if (Prms.HasKey("ptol")) pTol = Prms("ptol"); 00164 00165 if (!Derived) // for instance, CamClay 00166 { 00167 // parameters 00168 if (!Prms.HasKey("E")) throw new Fatal("ElastoPlastic::ElastoPlastic: Young modulus (E) must be provided"); 00169 if (!Prms.HasKey("nu")) throw new Fatal("ElastoPlastic::ElastoPlastic: Poisson coefficient (nu) must be provided"); 00170 E = Prms("E"); 00171 nu = Prms("nu"); 00172 if (Prms.HasKey("MC")) { Name="ElastoPlastic(MC)"; FC = MC_t; } 00173 if (Prms.HasKey("DP")) { Name="ElastoPlastic(DP)"; FC = GE_t; SMP.b = 0.0; } 00174 if (Prms.HasKey("MN")) { Name="ElastoPlastic(MN)"; FC = GE_t; SMP.b = 0.5; } 00175 if (Prms.HasKey("GE")) { Name="ElastoPlastic(GE)"; FC = GE_t; SMP.b = Prms("b"); } 00176 if (FC==VM_t) 00177 { 00178 if (Prms.HasKey("sY")) kVM = sqrt(2.0/3.0)*Prms("sY"); 00179 else if (Prms.HasKey("c")) kVM = (GTy==psa_t ? sqrt(2.0)*Prms("c") : 2.0*sqrt(2.0/3.0)*Prms("c")); 00180 else throw new Fatal("ElastoPlastic::ElastoPlastic: With VM (von Mises), either sY (uniaxial yield stress) or c (undrained cohesion) must be provided"); 00181 } 00182 else 00183 { 00184 if (!Prms.HasKey("phi")) throw new Fatal("ElastoPlastic::ElastoPlastic: friction angle phi (degrees) must be provided"); 00185 double c = (Prms.HasKey("c") ? Prms("c") : 0.0); 00186 double phi_deg = Prms("phi"); 00187 double phi_rad = phi_deg*Util::PI/180.0; 00188 double psi_rad = phi_rad; 00189 if (phi_deg<1.0e-3) throw new Fatal("ElastoPlastic::ElastoPlastic: Friction angle (phi [deg]) must be greater than zero (1.0e-3). phi=%g is invalid",phi_deg); 00190 if (c<0.0) throw new Fatal("ElastoPlastic::ElastoPlastic: 'cohesion' must be greater than zero. c=%g is invalid",c); 00191 if (Prms.HasKey("psi")) psi_rad = Prms("psi")*Util::PI/180.0; 00192 sphi = sin(phi_rad); 00193 spsi = sin(psi_rad); 00194 if (FC==GE_t) 00195 { 00196 // yield surface 00197 double A = (1.0+sphi)/(1.0-sphi); 00198 if (NCps==4) SigA = -A, -1., -1., 0.; 00199 else SigA = -A, -1., -1., 0., 0., 0.; 00200 SMP.Calc (SigA, false); 00201 kGE = SMP.sq/SMP.sp; 00202 // potential 00203 A = (1.0+spsi)/(1.0-spsi); 00204 if (NCps==4) SigA = -A, -1., -1., 0.; 00205 else SigA = -A, -1., -1., 0., 0., 0.; 00206 SMP.Calc (SigA, false); 00207 kGEpot = SMP.sq/SMP.sp; 00208 } 00209 } 00210 00211 // hardening 00212 if (Prms.HasKey("Hp")) Hb = (2.0/3.0)*Prms("Hp"); // Hp=H_prime 00213 00214 // internal values 00215 IvNames = "z0", "evp", "edp"; 00216 } 00217 00218 // new stress update parmeters 00219 NewSU = (Prms.HasKey("newsu") ? (int)Prms("newsu") : false); 00220 if (NewSU) 00221 { 00222 BetSU = Prms("betsu"); 00223 AlpSU = Prms("alpsu"); 00224 } 00225 } 00226 00227 inline void ElastoPlastic::Rate (State const * Sta, Vec_t const & DEpsDt, Vec_t & DSigDt, Vec_t & DIvsDt) const 00228 { 00229 // state 00230 EquilibState const * sta = static_cast<EquilibState const *>(Sta); 00231 00232 // zero internal values (if any) 00233 DIvsDt.change_dim (NIvs); 00234 set_to_zero (DIvsDt); 00235 00236 // De: elastic stiffness 00237 ELStiff (sta->Sig, sta->Ivs); 00238 00239 // increments 00240 double aint; 00241 if (LoadCond(sta, DEpsDt, aint)) 00242 { 00243 // gradients, flow rule, hardening, and hp 00244 Gradients (sta->Sig, sta->Ivs); 00245 Gradients (sta->Sig, sta->Ivs, true); 00246 Hardening (sta->Sig, sta->Ivs); 00247 double hp = (NIvs>0 ? Y(0)*H(0) : 0.0); 00248 00249 // plastic multiplier 00250 Mult (V, De, VDe); 00251 double phi = dot(VDe,W) - hp; 00252 double Lam = dot(VDe,DEpsDt)/phi; 00253 00254 // increments 00255 DEpsPl = Lam*W; 00256 DEpsEl = DEpsDt - DEpsPl; 00257 DSigDt = De*DEpsEl; 00258 00259 // increment of internal values 00260 DIvsDt = Lam*H; 00261 00262 // plastic strains => extra DIvs 00263 ExtraDIvs (DIvsDt); 00264 } 00265 else 00266 { 00267 // stress increment 00268 DSigDt = De*DEpsDt; 00269 00270 // new stress update 00271 if (NewSU) DIvsDt(0) = -dot(V, DSigDt) / Y(0); 00272 } 00273 00274 // correct strain increment for plane stress 00275 if (GTy==pse_t) throw new Fatal("ElastoPlastic::Rate: this method does not work with plane-stress (pse)"); 00276 } 00277 00278 inline void ElastoPlastic::TgIncs (State const * Sta, Vec_t & DEps, Vec_t & DSig, Vec_t & DIvs) const 00279 { 00280 // state 00281 EquilibState const * sta = static_cast<EquilibState const *>(Sta); 00282 00283 // zero internal values (if any) 00284 DIvs.change_dim (NIvs); 00285 set_to_zero (DIvs); 00286 00287 // De: elastic stiffness 00288 ELStiff (sta->Sig, sta->Ivs); 00289 00290 // increments 00291 if (sta->Ldg) 00292 { 00293 // gradients, flow rule, hardening, and hp 00294 Gradients (sta->Sig, sta->Ivs); 00295 Gradients (sta->Sig, sta->Ivs, true); 00296 Hardening (sta->Sig, sta->Ivs); 00297 double hp = (NIvs>0 ? Y(0)*H(0) : 0.0); 00298 00299 // plastic multiplier 00300 Mult (V, De, VDe); 00301 double phi = dot(VDe,W) - hp; 00302 double Lam = dot(VDe,DEps)/phi; 00303 00304 // increments 00305 DEpsPl = Lam*W; 00306 DEpsEl = DEps - DEpsPl; 00307 DSig = De*DEpsEl; 00308 00309 // increment of internal values 00310 DIvs = Lam*H; 00311 00312 // plastic strains => extra DIvs 00313 ExtraDIvs (DIvs); 00314 } 00315 else 00316 { 00317 // stress increment 00318 DSig = De*DEps; 00319 00320 // new stress update 00321 if (NewSU) DIvs(0) = -dot(V, DSig) / Y(0); 00322 } 00323 00324 // correct strain increment for plane stress 00325 if (GTy==pse_t) DEps(2) = -nu*(DSig(0)+DSig(1))/CalcE(sta->Sig, sta->Ivs); 00326 } 00327 00328 inline void ElastoPlastic::Stiffness (State const * Sta, Mat_t & D) const 00329 { 00330 // state 00331 EquilibState const * sta = static_cast<EquilibState const *>(Sta); 00332 00333 // De: elastic stiffness 00334 ELStiff (sta->Sig, sta->Ivs); 00335 00336 // stiffness 00337 if (sta->Ldg) 00338 { 00339 // gradients, flow rule, hardening, and hp 00340 Gradients (sta->Sig, sta->Ivs); 00341 Gradients (sta->Sig, sta->Ivs, true); 00342 Hardening (sta->Sig, sta->Ivs); 00343 double hp = (NIvs>0 ? Y(0)*H(0) : 0.0); 00344 00345 // auxiliary vectors 00346 Mult (V, De, VDe); 00347 double phi = dot(VDe,W) - hp; 00348 DeW = De*W; 00349 00350 // elastoplastic stiffness 00351 D.change_dim (NCps, NCps); 00352 for (size_t i=0; i<NCps; ++i) 00353 for (size_t j=0; j<NCps; ++j) 00354 D(i,j) = De(i,j) - DeW(i)*VDe(j)/phi; 00355 } 00356 else D = De; 00357 00358 // plane stress 00359 if (GTy==pse_t) 00360 { 00361 for (size_t i=0; i<NCps; ++i) 00362 { 00363 D(2,i) = 0.0; 00364 D(i,2) = 0.0; 00365 } 00366 } 00367 } 00368 00369 inline size_t ElastoPlastic::CorrectDrift (State * Sta) const 00370 { 00371 // state 00372 EquilibState * sta = static_cast<EquilibState *>(Sta); 00373 00374 // iterations 00375 double fnew = YieldFunc (sta->Sig, sta->Ivs); 00376 size_t it = 0; 00377 //if (NewSU) fnew = fabs(fnew); // TODO: should do this, but it does not converge 00378 while (fnew>DCFTol && it<DCMaxIt) 00379 { 00380 // gradients, flow rule, hardening, and hp 00381 Gradients (sta->Sig, sta->Ivs); 00382 Gradients (sta->Sig, sta->Ivs, true); 00383 Hardening (sta->Sig, sta->Ivs); 00384 double hp = (NIvs>0 ? Y(0)*H(0) : 0.0); 00385 00386 // elastic stiffness 00387 if (it==0) ELStiff (sta->Sig, sta->Ivs); 00388 00389 // auxiliary vectors 00390 Mult (V, De, VDe); 00391 double dgam = fnew/(dot(VDe,W)-hp); 00392 DeW = De*W; 00393 00394 // update stress and ivs (only) 00395 sta->Sig -= dgam*DeW; 00396 sta->Ivs += dgam*H; 00397 fnew = YieldFunc (sta->Sig, sta->Ivs); 00398 //if (NewSU) fnew = fabs(fnew); // TODO: should do this, but it does not converge 00399 00400 // check convergence 00401 if (fabs(fnew)<DCFTol) break; 00402 it++; 00403 } 00404 00405 // check number of iterations 00406 if (it>=DCMaxIt) throw new Fatal("ElastoPlastic::CorrectDrift: Yield surface drift correction did not converge after %d iterations (fnew=%g, DCFTol=%g)",it,fnew,DCFTol); 00407 return it; 00408 } 00409 00410 inline bool ElastoPlastic::LoadCond (State const * Sta, Vec_t const & DEps, double & alpInt) const 00411 { 00412 // default return values 00413 alpInt = -1.0; // no intersection 00414 bool ldg = false; // => unloading (or crossing) 00415 00416 // current state 00417 EquilibState const * sta = static_cast<EquilibState const *>(Sta); 00418 00419 // trial state 00420 ELStiff (sta->Sig, sta->Ivs); 00421 DSigTr = De * DEps; 00422 SigA = sta->Sig + DSigTr; 00423 00424 // yield function values 00425 double f = YieldFunc (sta->Sig, sta->Ivs); 00426 double f_tr = YieldFunc (SigA, sta->Ivs); 00427 00428 // numerator of Lagrange multiplier 00429 Gradients (sta->Sig, sta->Ivs); 00430 double numL = dot(V, DSigTr); 00431 00432 // new stress update 00433 if (NewSU) 00434 { 00435 if (numL>0.0) ldg = true; 00436 return ldg; 00437 } 00438 00439 // going outside 00440 if (f_tr>0.0) 00441 { 00442 bool crossing = false; 00443 if (f<-FTol && f_tr>FTol) // (f<0.0) does not work, (f<-FTol) does not work 00444 { 00445 Sig0 = sta->Sig; 00446 Ivs0 = sta->Ivs; 00447 crossing = true; 00448 } 00449 else if (numL<-1.e-5)//qTol) // (numL<0.0) does not work, since it may be equal to -0.0 => neutral loading 00450 { 00451 // moving stress state slighlty to the inside of the yield surface in order to have f=-FTol 00452 double df = -FTol - f; 00453 double dalp = df / numL; // numL = dfdalpha 00454 Sig0 = sta->Sig + dalp*DSigTr; 00455 Ivs0 = sta->Ivs; 00456 crossing = true; 00457 double fnew = YieldFunc (Sig0, Ivs0); 00458 if (fnew>0.0) 00459 { 00460 std::ostringstream oss; 00461 oss << "f=" << f << ", f_tr=" << f_tr << ", numL=" << numL << std::endl; 00462 oss << "Sig = " << PrintVector(sta->Sig); 00463 oss << "Ivs = " << PrintVector(sta->Ivs); 00464 throw new Fatal("ElastoPlastic::LoadCond: __internal_error__: correction for numL<0 failed (dalp=%g, fnew=%g)\n%s",dalp,fnew,oss.str().c_str()); 00465 } 00466 //throw new Fatal("ElastoPlastic::LoadCond: Strain increment is too large (f=%g, f_tr=%g, numL=%g). Crossing and going all the way through the yield surface to the other side.",f,f_tr,numL); 00467 } 00468 if (crossing) 00469 { 00470 Numerical::Root<ElastoPlastic> root(const_cast<ElastoPlastic*>(this), &ElastoPlastic::Fa, &ElastoPlastic::dFada); 00471 //root.Scheme = "Newton"; 00472 //root.Verbose = true; 00473 root.MaxIt = 100; 00474 alpInt = root.Solve (0.0, 1.0); 00475 if (alpInt<0) throw new Fatal("ElastoPlastic::LoadCond: alpInt=%g must be positive",alpInt); 00476 } 00477 else ldg = true; 00478 } 00479 00480 // return true if there is loading. returns false (unloading) with intersection 00481 return ldg; 00482 } 00483 00484 inline void ElastoPlastic::InitIvs (SDPair const & Ini, State * Sta) const 00485 { 00486 // initialize state 00487 EquilibState * sta = static_cast<EquilibState*>(Sta); 00488 sta->Init (Ini, NIvs); 00489 00490 // internal variables 00491 sta->Ivs(0) = 0.0; // z0 00492 sta->Ivs(1) = 0.0; // evp 00493 sta->Ivs(2) = 0.0; // edp 00494 00495 // new stress update 00496 if (NewSU) 00497 { 00498 q = Calc_qoct (sta->Sig); 00499 if (q>qTol) throw new Fatal("ElastoPlastic::InitIvs: qoct==%g must be smaller than qTol==%g for the time being",q,qTol); 00500 } 00501 else 00502 { 00503 switch (FC) 00504 { 00505 case VM_t: { sta->Ivs(0) = 1.0; break; } 00506 case MC_t: { sta->Ivs(0) = sphi; break; } 00507 case GE_t: { sta->Ivs(0) = kGE; break; } 00508 } 00509 } 00510 00511 // check initial yield function 00512 double f = YieldFunc (sta->Sig, sta->Ivs); 00513 if (f>FTol) throw new Fatal("ElastoPlastic:InitIvs: stress point (sig=(%g,%g,%g,%g]) is outside yield surface (f=%g) with z0=%g",sta->Sig(0),sta->Sig(1),sta->Sig(2),sta->Sig(3)/Util::SQ2,f,sta->Ivs(0)); 00514 if (NewSU && f<-FTol) throw new Fatal("ElastoPlastic:InitIvs: stress point (sig=(%g,%g,%g,%g]) is outside yield surface (f=%g) with z0=%g",sta->Sig(0),sta->Sig(1),sta->Sig(2),sta->Sig(3)/Util::SQ2,f,sta->Ivs(0)); 00515 } 00516 00517 inline void ElastoPlastic::Gradients (Vec_t const & Sig, Vec_t const & Ivs, bool Potential) const 00518 { 00519 Vec_t * VorW = &V; 00520 if (Potential) VorW = &W; 00521 else 00522 { 00523 Y(0) = 0.0; // dfdz0 00524 Y(1) = 0.0; // dfdz1 00525 Y(2) = 0.0; // dfdz2 00526 } 00527 00528 // pertubation 00529 SigA = Sig; 00530 if (NewSU) 00531 { 00532 q = Calc_qoct (SigA); 00533 if (q<qTol) 00534 { 00535 if (SigA(3)<0.0) SigA(3) -= qTol*Util::SQ2; 00536 else SigA(3) += qTol*Util::SQ2; 00537 } 00538 } 00539 00540 switch (FC) 00541 { 00542 case VM_t: 00543 { 00544 OctInvs (SigA, p,q,s, qTol); 00545 (*VorW) = s/(q*kVM); 00546 if (NewSU && !Potential) Y(0) = -1.0; 00547 break; 00548 } 00549 case MC_t: 00550 { 00551 // gradients: V 00552 Calc_dgdsig (SigA, (Potential ? spsi : Ivs(0))); 00553 Calc_arc (g); 00554 double dfdp = -g; 00555 double dfdq = 1.0; 00556 double dfdg = -p; 00557 if (p<pm) 00558 { 00559 dfdp = 2.0*(p-pc); 00560 dfdq = 2.0*q; 00561 dfdg = 2.0*g*(r2-pc*pc)/(1.0+g*g); 00562 } 00563 if (q>qTol) (*VorW) = (-dfdp/Util::SQ3)*I + (dfdq/q)*s + dfdg*dgdsig; 00564 else (*VorW) = (-dfdp/Util::SQ3)*I; 00565 00566 // gradients: y0 00567 if (NewSU && !Potential) 00568 { 00569 double dgdz0 = (Util::SQ2+g*sin(th))/(Util::SQ3*cos(th)-Ivs(0)*sin(th)); 00570 Y(0) = dfdg * dgdz0; 00571 } 00572 break; 00573 } 00574 case GE_t: 00575 { 00576 // gradients: V 00577 SMP.Calc (SigA, true); 00578 double M = (Potential ? kGEpot : Ivs(0)); 00579 Calc_arc (M); 00580 double dfdp = -M; 00581 double dfdq = 1.0; 00582 if (SMP.sp<pm) 00583 { 00584 dfdp = 2.0*(SMP.sp-pc); 00585 dfdq = 2.0*SMP.sq; 00586 } 00587 (*VorW) = dfdp*SMP.dspdSig + dfdq*SMP.dsqdSig; 00588 00589 // gradients: y0 00590 if (NewSU && !Potential) 00591 { 00592 if (SMP.sp<pm) Y(0) = 2.0*M*(r2-pc*pc)/(1.0+M*M); 00593 else Y(0) = -SMP.sp; 00594 } 00595 break; 00596 } 00597 } 00598 } 00599 00600 inline void ElastoPlastic::Hardening (Vec_t const & Sig, Vec_t const & Ivs) const 00601 { 00602 // internal values 00603 H(0) = 0.0; 00604 H(1) = 0.0; 00605 H(2) = 0.0; 00606 00607 // new stress update 00608 if (NewSU) 00609 { 00610 double D = 0.0; 00611 switch (FC) 00612 { 00613 case VM_t: 00614 { 00615 q = Calc_qoct (Sig); 00616 D = q/kVM - 1.0; 00617 break; 00618 } 00619 case MC_t: 00620 { 00621 Calc_pqg (Sig, sphi); 00622 Calc_arc (g); 00623 if (p<pm) D = q*q + pow(p-pc,2.0) - r2; 00624 else D = q - g*p; 00625 break; 00626 } 00627 case GE_t: 00628 { 00629 SMP.Calc (Sig, false); 00630 Calc_arc (kGE); 00631 if (SMP.sp<pm) D = SMP.sq*SMP.sq + pow(SMP.sp-pc,2.0) - r2; 00632 else D = SMP.sq - kGE*SMP.sp; 00633 break; 00634 } 00635 } 00636 double H1 = 0.0; 00637 if (D>0.0) D = 0.0; 00638 H(0) = AlpSU + (H1-AlpSU)*exp(BetSU*D); 00639 } 00640 } 00641 00642 inline double ElastoPlastic::YieldFunc (Vec_t const & Sig, Vec_t const & Ivs) const 00643 { 00644 double f = 1e+8; 00645 switch (FC) 00646 { 00647 case VM_t: 00648 { 00649 q = Calc_qoct (Sig); 00650 f = q/kVM - Ivs(0); 00651 break; 00652 } 00653 case MC_t: 00654 { 00655 Calc_pqg (Sig, Ivs(0)); 00656 Calc_arc (g); 00657 if (p<pm) f = q*q + pow(p-pc,2.0) - r2; 00658 else f = q - g*p; 00659 break; 00660 } 00661 case GE_t: 00662 { 00663 SMP.Calc (Sig, false); 00664 Calc_arc (Ivs(0)); 00665 if (SMP.sp<pm) f = SMP.sq*SMP.sq + pow(SMP.sp-pc,2.0) - r2; 00666 else f = SMP.sq - Ivs(0)*SMP.sp; 00667 } 00668 } 00669 return f; 00670 } 00671 00672 inline void ElastoPlastic::ExtraDIvs (Vec_t & DIvs) const 00673 { 00674 if (Derived) return; 00675 DIvs(1) = Calc_ev (DEpsPl); // devp 00676 DIvs(2) = Calc_ed (DEpsPl); // dedp 00677 } 00678 00679 inline void ElastoPlastic::ELStiff (Vec_t const & Sig, Vec_t const & Ivs) const 00680 { 00681 /* 00682 if (NLElastic) 00683 { 00684 double K = Calc_K (E, nu); 00685 double G = Calc_G (E, nu); 00686 De = (2.0*G)*Psd + K*IdyI; 00687 } 00688 */ 00689 00690 if (NDim==2) 00691 { 00692 if (GTy==pse_t) 00693 { 00694 double c = CalcE(Sig,Ivs)/(1.0-nu*nu); 00695 De = c, c*nu, 0.0, 0.0, 00696 c*nu, c, 0.0, 0.0, 00697 0.0, 0.0, 0.0, 0.0, 00698 0.0, 0.0, 0.0, c*(1.0-nu); 00699 } 00700 else if (GTy==psa_t || GTy==axs_t) 00701 { 00702 double c = CalcE(Sig,Ivs)/((1.0+nu)*(1.0-2.0*nu)); 00703 De = c*(1.0-nu), c*nu , c*nu , 0.0, 00704 c*nu , c*(1.0-nu), c*nu , 0.0, 00705 c*nu , c*nu , c*(1.0-nu), 0.0, 00706 0.0 , 0.0 , 0.0 , c*(1.0-2.0*nu); 00707 } 00708 else throw new Fatal("ElastoPlastic::Stiffness: 2D: This model is not available for GeometryType = %s",GTypeToStr(GTy).CStr()); 00709 } 00710 else 00711 { 00712 if (GTy==d3d_t) 00713 { 00714 double c = CalcE(Sig,Ivs)/((1.0+nu)*(1.0-2.0*nu)); 00715 De = c*(1.0-nu), c*nu , c*nu , 0.0, 0.0, 0.0, 00716 c*nu , c*(1.0-nu), c*nu , 0.0, 0.0, 0.0, 00717 c*nu , c*nu , c*(1.0-nu), 0.0, 0.0, 0.0, 00718 0.0 , 0.0 , 0.0 , c*(1.0-2.0*nu), 0.0, 0.0, 00719 0.0 , 0.0 , 0.0 , 0.0, c*(1.0-2.0*nu), 0.0, 00720 0.0 , 0.0 , 0.0 , 0.0, 0.0, c*(1.0-2.0*nu); 00721 } 00722 else throw new Fatal("ElastoPlastic::Stiffness: 3D: This model is not available for GeometryType = %s",GTypeToStr(GTy).CStr()); 00723 } 00724 } 00725 00726 00728 00729 00730 Model * ElastoPlasticMaker(int NDim, SDPair const & Prms, Model const * O) { return new ElastoPlastic(NDim,Prms); } 00731 00732 int ElastoPlasticRegister() 00733 { 00734 ModelFactory ["ElastoPlastic"] = ElastoPlasticMaker; 00735 MODEL.Set ("ElastoPlastic", (double)MODEL.Keys.Size()); 00736 MODEL_PRM_NAMES["ElastoPlastic"].Resize (17); 00737 MODEL_PRM_NAMES["ElastoPlastic"] = "E", "nu", "sY", "c", "phi", "Hp", "psi", "VM", "DP", "MC", "MN", "GE", "b", "ptol", "newsu", "betsu", "alpsu"; 00738 MODEL_IVS_NAMES["ElastoPlastic"].Resize (0); 00739 return 0; 00740 } 00741 00742 int __ElastoPlastic_dummy_int = ElastoPlasticRegister(); 00743 00744 00745 #endif // MECHSYS_ELASTOPLASTIC_H