![]() |
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_BBMX_H 00021 #define MECHSYS_BBMX_H 00022 00023 // MechSys 00024 #include <mechsys/models/model.h> 00025 00026 class BBMx : public Model 00027 { 00028 public: 00029 // Constructor 00030 BBMx (int NDim, SDPair const & Prms); 00031 00032 // Derived methods 00033 void InitIvs (SDPair const & Ini, State * Sta) const; 00034 void TgIncs (State const * Sta, double pw, Vec_t & DEps, double Dpw, Vec_t & DSig, Vec_t & DIvs) const; 00035 void Stiffness (State const * Sta, double pw, Mat_t & D, Vec_t & d) const; 00036 bool LoadCond (State const * Sta, double pw, Vec_t const & DEps, double Dpw) const; 00037 size_t CorrectDrift (State * Sta, double & pw) const; 00038 00039 // Internal methods 00040 void Gradients (Vec_t const & Sig, Vec_t const & Ivs, double pc) const; 00041 void Hardening (Vec_t const & Sig, Vec_t const & Ivs, double pc) const; 00042 void Calc_De_de (Vec_t const & Sig, Vec_t const & Ivs, double pc) const; 00043 00044 // Parameters and constants 00045 double lam0,kap,phi,nu,r,bet,kc,lams,kaps,B,c0,c1; 00046 double Mcs,wcs,pref; 00047 00048 // Initial values 00049 mutable double v0; 00050 00051 // Data 00052 double qTol; 00053 00054 // Scratchpad 00055 mutable double p, q, t, th; 00056 mutable Vec_t dthdsig; 00057 mutable Vec_t s; 00058 mutable Vec_t V; 00059 mutable double S; 00060 mutable Vec_t W; 00061 mutable Vec_t Y; 00062 mutable Vec_t H; 00063 mutable Mat_t De; 00064 mutable Vec_t de; 00065 mutable Mat_t Dep; 00066 mutable Vec_t VDe; 00067 mutable Vec_t DeW; 00068 mutable Vec_t DEpsEl; 00069 mutable Vec_t DEpsPl; 00070 mutable Vec_t DSigTr; 00071 00072 // Auxiliary methods 00073 double Calc_lam (double pc) const { return (pc>0.0 ? lam0*((1.0-r)*exp(-bet*pc)+r) : lam0); } 00074 double Calc_psi (double pc) const { return (pc>0.0 ? (lam0-kap)/(Calc_lam(pc)-kap) : 1.0); } 00075 double Calc_ps (double pc) const { return (pc>0.0 ? kc*pc : pc); } 00076 double Calc_p0 (double z0, double pc) const { return (pc>0.0 ? pref*pow(z0/pref, Calc_psi(pc)) : z0-pc); } 00077 double Calc_C (double z1, double pc) const { return (pc>0.0 ? pref*pref*(exp(B*(pc-z1)/pref)-exp(-B*z1/pref)) : 0.0); } 00078 double Calc_M (double sin3th) const { return Mcs*pow(2.0*wcs/(1.0+wcs-(1.0-wcs)*sin3th),1.0/4.0); } 00079 }; 00080 00081 00083 00084 00085 inline BBMx::BBMx (int NDim, SDPair const & Prms) 00086 : Model (NDim, Prms, /*niv*/4, "BBMx"), pref(1.0), qTol(1.0e-7) 00087 { 00088 // set hm model 00089 HMCoup = true; 00090 00091 // parameters 00092 lam0 = Prms("lam0"); 00093 kap = Prms("kap"); 00094 phi = Prms("phi"); 00095 nu = Prms("nu"); 00096 r = Prms("r"); 00097 bet = Prms("bet"); 00098 kc = Prms("kc"); 00099 lams = Prms("lams"); 00100 kaps = Prms("kaps"); 00101 B = Prms("B"); 00102 c0 = Prms("c0"); 00103 c1 = Prms("c1"); 00104 00105 // constants 00106 double sin_phi = sin(phi*Util::PI/180.0); 00107 Mcs = Phi2M(phi,"oct"); 00108 wcs = pow((3.0-sin_phi)/(3.0+sin_phi),4.0); 00109 00110 // internal values 00111 IvNames = "z0", "z1", "z2", "z3"; 00112 00113 // check 00114 if (GTy==pse_t) throw new Fatal("BBMx::BBMx: This model does not work for plane-stress (pse)"); 00115 00116 // allocate memory 00117 s .change_dim (NCps); 00118 dthdsig.change_dim (NCps); 00119 V .change_dim (NCps); 00120 W .change_dim (NCps); 00121 Y .change_dim (NIvs); 00122 H .change_dim (NIvs); 00123 De .change_dim (NCps,NCps); 00124 de .change_dim (NCps); 00125 Dep .change_dim (NCps,NCps); 00126 VDe .change_dim (NCps); 00127 DeW .change_dim (NCps); 00128 DEpsEl .change_dim (NCps); 00129 DEpsPl .change_dim (NCps); 00130 DSigTr .change_dim (NCps); 00131 } 00132 00133 inline void BBMx::InitIvs (SDPair const & Ini, State * Sta) const 00134 { 00135 // initialize state 00136 EquilibState * sta = static_cast<EquilibState*>(Sta); 00137 sta->Init (Ini, NIvs); 00138 v0 = Ini("v0"); 00139 00140 // invariants 00141 OctInvs (sta->Sig, p,q,t,th,s, qTol); 00142 double M = Calc_M (t); 00143 00144 // internal variables 00145 double pc0 = -Ini("pw"); 00146 double p0 = p+(q*q)/(p*M*M); 00147 double OCR = (Ini.HasKey("OCR") ? Ini("OCR") : 1.0); 00148 double OSI = (Ini.HasKey("OSI") ? Ini("OSI") : 1.0); 00149 sta->Ivs(0) = p0; 00150 sta->Ivs(1) = pc0; 00151 sta->Ivs(2) = OCR*p0; 00152 sta->Ivs(3) = sta->Ivs(1) + OSI; 00153 } 00154 00155 inline void BBMx::TgIncs (State const * Sta, double pw, Vec_t & DEps, double Dpw, Vec_t & DSig, Vec_t & DIvs) const 00156 { 00157 // state 00158 EquilibState const * sta = static_cast<EquilibState const *>(Sta); 00159 00160 // zero internal values 00161 DIvs.change_dim (NIvs); 00162 set_to_zero (DIvs); 00163 00164 // De and de: elastic stiffness 00165 double pc = -pw; 00166 double Dpc = -Dpw; 00167 Calc_De_de (sta->Sig, sta->Ivs, pc); 00168 00169 // increments 00170 if (sta->Ldg) 00171 { 00172 // gradients, flow rule, hardening, and hp 00173 Gradients (sta->Sig, sta->Ivs, pc); 00174 Hardening (sta->Sig, sta->Ivs, pc); 00175 double hp = Y(0)*H(0) + Y(1)*H(1); 00176 00177 // plastic multiplier 00178 Mult (V, De, VDe); 00179 double phi = dot(VDe,W) - hp; 00180 double Lam = (dot(VDe,DEps) + dot(V,de)*Dpc + S*Dpc)/phi; 00181 00182 // increments 00183 DEpsPl = Lam*W; 00184 DEpsEl = DEps - DEpsPl; 00185 DSig = De*DEpsEl; 00186 00187 // increment of internal values 00188 DIvs = Lam*H; 00189 } 00190 else 00191 { 00192 // stress increment 00193 DSig = De*DEps; 00194 00195 // new stress update 00196 DIvs(0) = -dot(V, DSig) / Y(0); 00197 DIvs(1) = Dpc; 00198 } 00199 } 00200 00201 inline void BBMx::Stiffness (State const * Sta, double pw, Mat_t & D, Vec_t & d) const 00202 { 00203 // state 00204 EquilibState const * sta = static_cast<EquilibState const *>(Sta); 00205 00206 // De and de: elastic stiffness 00207 double pc = -pw; 00208 Calc_De_de (sta->Sig, sta->Ivs, pc); 00209 00210 // stiffness 00211 if (sta->Ldg) 00212 { 00213 // gradients, flow rule, hardening, and hp 00214 Gradients (sta->Sig, sta->Ivs, pc); 00215 Hardening (sta->Sig, sta->Ivs, pc); 00216 double hp = Y(0)*H(0) + Y(1)*H(1); 00217 00218 // auxiliary vectors 00219 Mult (V, De, VDe); 00220 double phi = dot(VDe,W) - hp; 00221 DeW = De*W; 00222 00223 // elastoplastic stiffness 00224 D.change_dim (NCps, NCps); 00225 for (size_t i=0; i<NCps; ++i) 00226 for (size_t j=0; j<NCps; ++j) 00227 D(i,j) = De(i,j) - DeW(i)*VDe(j)/phi; 00228 00229 // dep 00230 d = de - ((dot(V,de)+S)/phi)*DeW; 00231 } 00232 else 00233 { 00234 D = De; 00235 d = de; 00236 } 00237 } 00238 00239 inline bool BBMx::LoadCond (State const * Sta, double pw, Vec_t const & DEps, double Dpw) const 00240 { 00241 // state 00242 EquilibState const * sta = static_cast<EquilibState const *>(Sta); 00243 00244 // numerator of Lagrange multiplier 00245 double pc = -pw; 00246 double dpc = -Dpw; 00247 Calc_De_de (sta->Sig, sta->Ivs, pc); 00248 Gradients (sta->Sig, sta->Ivs, pc); 00249 DSigTr = De * DEps; 00250 double numL = dot(V, DSigTr) + dot(V,de)*dpc + S*dpc; 00251 if (numL>0.0) return true; 00252 else return false; 00253 } 00254 00255 inline size_t BBMx::CorrectDrift (State * Sta, double & pw) const 00256 { 00257 // state 00258 //EquilibState * sta = static_cast<EquilibState *>(Sta); 00259 00260 // iterations 00261 //double fnew = YieldFunc (sta->Sig, sta->Ivs, pw); 00262 size_t it = 0; 00263 /* 00264 while (fnew>DCFTol && it<DCMaxIt) 00265 { 00266 // gradients, flow rule, hardening, and hp 00267 Gradients (sta->Sig, sta->Ivs, -pw); 00268 Hardening (sta->Sig, sta->Ivs, -pw); 00269 double hp = Y(0)*H(0) + Y(1)*H(1); 00270 00271 // elastic stiffness 00272 if (it==0) Calc_De_de (sta->Sig, sta->Ivs, -pw); 00273 00274 // auxiliary vectors 00275 Mult (V, De, VDe); 00276 double dgam = fnew/(dot(VDe,W)-hp); 00277 DeW = De*W; 00278 00279 // update stress and ivs (only) 00280 sta->Sig -= dgam*DeW; 00281 sta->Ivs += dgam*H; 00282 fnew = YieldFunc (sta->Sig, sta->Ivs); 00283 //if (NewSU) fnew = fabs(fnew); // TODO: should do this, but it does not converge 00284 00285 // check convergence 00286 if (fabs(fnew)<DCFTol) break; 00287 it++; 00288 } 00289 00290 // check number of iterations 00291 if (it>=DCMaxIt) throw new Fatal("BBMx::CorrectDrift: Yield surface drift correction did not converge after %d iterations (fnew=%g, DCFTol=%g)",it,fnew,DCFTol); 00292 */ 00293 return it; 00294 } 00295 00296 inline void BBMx::Gradients (Vec_t const & Sig, Vec_t const & Ivs, double pc) const 00297 { 00298 // variables 00299 OctInvs (Sig, p,q,t,th,s, qTol, &dthdsig); 00300 double lam = Calc_lam (pc); 00301 double psi = Calc_psi (pc); 00302 double ps = Calc_ps (pc); 00303 double p0 = Calc_p0 (Ivs(0), pc); 00304 00305 // auxiliary variables 00306 double M = Calc_M (t); 00307 double MM = M*M; 00308 double dfdp = MM*(2.0*p+ps-p0); 00309 double m = -dfdp/Util::SQ3; 00310 00311 // gradients: pc 00312 double dCdpc = 0.0; 00313 double dp0dpc = -1.0; 00314 double dpsdpc = 1.0; 00315 if (pc>0.0) 00316 { 00317 double dlamdpc = -bet*lam0*(1.0-r)*exp(-bet*pc); 00318 double dpsidpc = (-psi/(lam-kap))*dlamdpc; 00319 dCdpc = pref*B*exp(B*(pc-Ivs(1))/pref); 00320 dp0dpc = p0*log(Ivs(0)/pref)*dpsidpc; 00321 dpsdpc = kc; 00322 } 00323 S = dCdpc - MM*dpsdpc*(p0-p) - MM*dp0dpc*(ps+p); 00324 00325 // gradients: sig 00326 if (q>qTol) 00327 { 00328 double dMdt = 0.25*M*(1.0-wcs)/(1.0+wcs-(1.0-wcs)*t); 00329 double dtdth = 3.0*cos(3.0*th); 00330 double dMdth = dMdt*dtdth; 00331 double dfdth = -2.0*M*dMdth*(p0-p)*(ps+p); 00332 V = 2.0*s + m*I + dfdth*dthdsig; 00333 } 00334 else V = m*I; 00335 W = V; 00336 00337 // internal variables 00338 double dCdz1 = 0.0; 00339 double dp0dz0 = 1.0; 00340 if (pc>0.0) 00341 { 00342 dCdz1 = -B*Calc_C(Ivs(1),pc)/pref; 00343 dp0dz0 = pref*psi*pow(Ivs(0)/pref,psi)/Ivs(0); 00344 } 00345 Y(0) = -MM*dp0dz0*(ps+p); 00346 Y(1) = dCdz1; 00347 Y(2) = 0.0; 00348 Y(3) = 0.0; 00349 } 00350 00351 inline void BBMx::Hardening (Vec_t const & Sig, Vec_t const & Ivs, double pc) const 00352 { 00353 double trW = W(0)+W(1)+W(2); 00354 double chi0 = -(lam0 - kap )/v0; 00355 double chis = -(lams - kaps)/v0; 00356 double L0 = c0*pow(log( Ivs(2)/ Ivs(0)) ,2.0); 00357 double L1 = c1*pow(log(1.0+Ivs(3)/(1.0+Ivs(1))),2.0); 00358 H(2) = Ivs(2)*trW/chi0; 00359 H(3) = Ivs(3)*trW/chis; 00360 H(0) = Ivs(0)*(trW+L0)/chi0; 00361 H(1) = Ivs(1)*(trW+L1)/chis; 00362 } 00363 00364 inline void BBMx::Calc_De_de (Vec_t const & Sig, Vec_t const & Ivs, double pc) const 00365 { 00366 // bulk modulus 00367 double pcam = fabs(Sig(0)+Sig(1)+Sig(2))/3.0; 00368 double K = pcam*v0/kap; 00369 double Kc = pc *v0/kaps; 00370 00371 // elastic stiffness 00372 double G = Calc_G_ (K, nu); 00373 De = (2.0*G)*Psd + K*IdyI; 00374 if (pc>0.0) de = (-K/Kc)*I; 00375 else set_to_zero(de); 00376 } 00377 00378 00380 00381 00382 Model * BBMxMaker(int NDim, SDPair const & Prms, Model const * O) { return new BBMx(NDim,Prms); } 00383 00384 int BBMxRegister() 00385 { 00386 ModelFactory ["BBMx"] = BBMxMaker; 00387 MODEL.Set ("BBMx", (double)MODEL.Keys.Size()); 00388 MODEL_PRM_NAMES["BBMx"].Resize(12); 00389 MODEL_PRM_NAMES["BBMx"] = "lam0", "kap", "phi", "nu", "r", "bet", "kc", "lams", "kaps", "B", "c0", "c1"; 00390 MODEL_IVS_NAMES["BBMx"].Resize(3); 00391 MODEL_IVS_NAMES["BBMx"] = "v0", "OCR", "OSI"; 00392 return 0; 00393 } 00394 00395 int __BBMx_dummy_int = BBMxRegister(); 00396 00397 #endif // MECHSYS_BBMX_H