00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #ifndef MECHSYS_BARCELONAX_H
00023 #define MECHSYS_BARCELONAX_H
00024
00025 #ifdef HAVE_CONFIG_H
00026 #include "config.h"
00027 #else
00028 #ifndef REAL
00029 #define REAL double
00030 #endif
00031 #endif
00032
00033
00034 #include <iostream>
00035
00036
00037 #include <blitz/tinyvec-et.h>
00038
00039
00040 #include "models/coupled/coupledmodel.h"
00041 #include "tensors/tensors.h"
00042 #include "tensors/operators.h"
00043 #include "tensors/functions.h"
00044 #include "numerical/integschemesctes.h"
00045 #include "numerical/autostepme.h"
00046 #include "util/string.h"
00047 #include "util/array.h"
00048 #include "util/util.h"
00049
00050 using Tensors::I;
00051 using Tensors::Tensor2;
00052 using Tensors::Tensor4;
00053 using Tensors::Stress_p_q_S_sin3th;
00054 using Tensors::Strain_Ev_Ed;
00055 using Tensors::Mult;
00056
00058 class BarcelonaX : public CoupledModel
00059 {
00060 static REAL Q_ZERO;
00061 public:
00062
00064 typedef blitz::TinyVector<REAL,2> IntVars;
00065 typedef blitz::TinyVector<REAL,2> HardMod;
00066 typedef blitz::TinyVector<REAL,2> T_dFdz;
00067 typedef blitz::TinyVector<REAL,7> AugVec;
00068
00069
00070 BarcelonaX(Array<REAL> const & Prms, Array<REAL> const & IniData);
00071
00072
00073 String Name () const { return "BarcelonaX"; }
00074 void TgStiffness (Tensor4 & D, Tensor2 & d) const;
00075 REAL Sr () const;
00076 REAL phi () const;
00077 REAL n_times_dSr_dPp () const;
00078 void TgPermeability (Tensor2 & k) const;
00079 void FlowVelocity (Tensor1 const & Grad, Tensor1 & Vel) const;
00080 void Actualize (Tensor2 const & DSig, REAL const & DPp, Tensor2 & DEps, REAL & DnSr);
00081 void StressUpdate (Tensor2 const & DEps, REAL const & DPp, Tensor2 & DSig, REAL & DnSr);
00082 void FlowUpdate (REAL const & DPp) {}
00083 void BackupState ();
00084 void RestoreState ();
00085
00086
00087 REAL YieldFunc (Tensor2 const & Sig, IntVars const & z, REAL const & Suc) const;
00088 void Calc_dFdSig_dFdSuc (Tensor2 const & Sig, IntVars const & z, REAL const & Suc, Tensor2 & V, REAL & S) const;
00089 REAL Calc_p0 (REAL const & Suc, REAL const & z0) const;
00090
00091
00092 Tensor2 const & Sig() const { return _sig; };
00093 Tensor2 const & Eps() const { return _eps; };
00094 REAL Pp () const { return _ppr; };
00095 REAL GammaW () const { return _gamaW; }
00096 int nInternalStateValues() const { return 3; }
00097 void InternalStateValues (Array<REAL> & IntStateVals ) const;
00098 void InternalStateNames (Array<String> & IntStateNames) const;
00099
00100
00101 REAL GetM(REAL Theta) const { REAL sin3th=sin(3.0*Theta); return _calc_M(sin3th); }
00102
00103 private:
00104
00105 REAL _v;
00106 Tensor2 _sig;
00107 REAL _suc;
00108 Tensor2 _eps;
00109 IntVars _z;
00110 REAL _ppr;
00111
00112
00113 REAL _bkp_v;
00114 Tensor2 _bkp_sig;
00115 REAL _bkp_suc;
00116 Tensor2 _bkp_eps;
00117 IntVars _bkp_z;
00118 REAL _bkp_ppr;
00119
00120
00121 REAL _lam0;
00122 REAL _kap;
00123 REAL _phics;
00124 REAL _G;
00125 REAL _r;
00126 REAL _bet;
00127 REAL _k;
00128 REAL _lams;
00129 REAL _kaps;
00130 REAL _patm;
00131 REAL _pref;
00132 REAL _BB;
00133
00134
00135 REAL _a;
00136 REAL _b;
00137 REAL _c;
00138 REAL _m;
00139 REAL _ks;
00140 REAL _gamaW;
00141
00142
00143 REAL _Mcs;
00144 REAL _wcs;
00145 REAL _alp;
00146
00147
00148 REAL _num_dLam;
00149 REAL _bkp_num_dLam;
00150
00151
00152 REAL _MAX_ERR_F;
00153 REAL _MIN_HP;
00154
00155
00156 REAL _lam (REAL const & Suc) const;
00157 REAL _psi (REAL const & Suc) const;
00158
00159 void _calc_Ce_ce(REAL const & v, Tensor2 const & Sig, REAL const & Suc, Tensor4 & Ce, Tensor2 & ce) const;
00160 void _calc_De_de(REAL const & v, Tensor2 const & Sig, REAL const & Suc, Tensor4 & De, Tensor2 & de) const;
00161
00162 void _calc_gradients_and_hardening(REAL const & v ,
00163 Tensor2 const & Sig,
00164 IntVars const & z ,
00165 REAL const & Suc,
00166 Tensor2 & r ,
00167 Tensor2 & V ,
00168 T_dFdz & y ,
00169 REAL & S ,
00170 HardMod & HH ,
00171 REAL & hp ) const;
00172
00173 int _tg_deps_dz_given_dsig_and_dsuc(AugVec const & SigSuc ,
00174 Tensor2 const & Eps ,
00175 IntVars const & z ,
00176 AugVec const & dSigSuc,
00177 Tensor2 & dEps ,
00178 IntVars & dz ) const;
00179
00180 int _tg_dsig_dz_given_deps_and_dsuc(AugVec const & EpsSuc ,
00181 Tensor2 const & Sig ,
00182 IntVars const & z ,
00183 AugVec const & dEpsSuc,
00184 Tensor2 & dSig ,
00185 IntVars & dz ) const;
00186
00187 REAL _local_error(Tensor2 const & Ey, Tensor2 const & y_high,
00188 IntVars const & Ez, IntVars const & z_high) const;
00189
00190
00191 REAL _find_intersection_NR(Tensor2 const & dSig_tr,
00192 REAL const & dSuc_tr,
00193 REAL const & F ,
00194 REAL const & F_tr ,
00195 Tensor2 & Sig_int,
00196 REAL & Suc_int) const;
00197
00198
00199 REAL _find_intersection(Tensor2 const & dSig_tr,
00200 REAL const & dSuc_tr,
00201 REAL const & F ,
00202 REAL const & F_tr ,
00203 Tensor2 & Sig_int,
00204 REAL & Suc_int) const;
00205
00206 REAL _calc_M(REAL const & sin3th) const;
00207
00208 };
00209
00210 REAL BarcelonaX::Q_ZERO = 1.0e-7;
00211
00212
00214
00215
00216 inline BarcelonaX::BarcelonaX(Array<REAL> const & Prms, Array<REAL> const & IniData)
00217 : _num_dLam(-1.0)
00218 {
00219
00220
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230 const size_t n_prms = 18;
00231 if (Prms.size()!=n_prms)
00232 throw new Fatal(_("BarcelonaX::BarcelonaX: The number of parameters (%d) is incorrect. It must be equal to %d"), Prms.size(), n_prms);
00233
00234
00235 _lam0 = Prms[0];
00236 _kap = Prms[1];
00237 _phics = Prms[2];
00238 _G = Prms[3];
00239 _r = Prms[4];
00240 _bet = Prms[5];
00241 _k = Prms[6];
00242 _lams = Prms[7];
00243 _kaps = Prms[8];
00244 _patm = Prms[9];
00245 _pref = Prms[10];
00246 _BB = Prms[11];
00247
00248
00249 _a = Prms[12];
00250 _b = Prms[13];
00251 _c = Prms[14];
00252 _m = Prms[15];
00253 _ks = Prms[16];
00254 _gamaW = Prms[17];
00255
00256
00257 REAL sin_phi = sin(Util::ToRad(_phics));
00258 _Mcs = 6.0*sin_phi/(3.0-sin_phi);
00259 _wcs = pow((3.0-sin_phi)/(3.0+sin_phi),4.0);
00260 _alp = (_Mcs*(_Mcs-9.0)*(_Mcs-3.0)) / (9.0*(6.0-_Mcs)*(1.0-_kap/_lam0));
00261
00262
00263
00264
00265 if (IniData.size()!=7)
00266 throw new Fatal(_("BarcelonaX::BarcelonaX: The number of initial data is not sufficiet (it must be equal to 5). { SigX SigY SigZ vini OCR OSI Pp }"));
00267
00268
00269 REAL sig_x = IniData[0];
00270 REAL sig_y = IniData[1];
00271 REAL sig_z = IniData[2];
00272 _v = IniData[3];
00273 REAL OCR = IniData[4];
00274 REAL OSI = IniData[5];
00275 REAL Pp = IniData[6];
00276
00277
00278 REAL sq2=Util::Sq2();
00279 _sig = sig_x, sig_y, sig_z, 0.0*sq2, 0.0*sq2, 0.0*sq2;
00280 _eps = 0.0,0.0,0.0,0.0*sq2,0.0*sq2,0.0*sq2;
00281
00282
00283 _ppr = Pp;
00284 _suc = 0.0 - Pp;
00285 if (_suc<0.0) _suc=0.0;
00286
00287
00288 REAL p,q;
00289 Tensors::Stress_p_q(_sig,p,q);
00290 _z(0) = OCR*p;
00291 _z(1) = OSI+_suc;
00292
00293
00294
00295
00296
00297
00298
00299 _MAX_ERR_F = (0.5/100.0)*_pref*_pref;
00300 _MIN_HP = (5.0/100.0)*_pref*_pref;
00301
00302 }
00303
00304 inline void BarcelonaX::TgStiffness(Tensor4 & D, Tensor2 & d) const
00305 {
00306 if (_num_dLam<0)
00307 {
00308 _calc_De_de(_v,_sig,_suc, D,d);
00309 }
00310 else
00311 {
00312
00313 REAL v=_v;
00314 Tensor2 r;
00315 Tensor2 V;
00316 T_dFdz y;
00317 REAL S;
00318 HardMod HH;
00319 REAL hp;
00320 _calc_gradients_and_hardening(v, _sig, _z, _suc, r, V, y, S, HH, hp);
00321
00322
00323 Tensor4 De;
00324 Tensor2 de;
00325 _calc_De_de(v,_sig,_suc, De,de);
00326
00327
00328 REAL Phi = Tensors::Reduce(V,De,r)+hp;
00329 Tensors::GerX(-1.0/Phi,De,r,V,De,De,D);
00330
00331
00332 Tensors::Dot(De,r, d);
00333 if (_suc > 0.0)
00334 d = de - ((Tensors::Dot(V,de)+S)/Phi)*d;
00335 }
00336 }
00337
00338 inline REAL BarcelonaX::Sr() const
00339 {
00340 if (_suc <= 0.0)
00341 return 1.0;
00342 else
00343 return 1.0/pow(1.0+pow(_suc/_a,_b),_c);
00344 }
00345
00346 inline REAL BarcelonaX::phi() const
00347 {
00348 return Sr();
00349 }
00350
00351 inline REAL BarcelonaX::n_times_dSr_dPp() const
00352 {
00353 if (_suc <= 0.0)
00354 return 0.0;
00355 else
00356 {
00357 REAL dSr_dsuc = -_b*_c*pow(_suc/_a,_b-1.0)/(_a*pow(1.0+pow(_suc/_a,_b),_c+1.0));
00358 REAL dsuc_dPp = -1.0;
00359 REAL dSr_dPp = dSr_dsuc*dsuc_dPp;
00360 REAL n = (_v-1.0)/_v;
00361 return n*dSr_dPp;
00362 }
00363 }
00364
00365 inline void BarcelonaX::TgPermeability(Tensor2 & k) const
00366 {
00367 k = (_ks*pow(Sr(),_m))*I;
00368 }
00369
00370 inline void BarcelonaX::FlowVelocity(Tensor1 const & Grad, Tensor1 & Vel) const
00371 {
00372 Tensor2 K;
00373 TgPermeability(K);
00374 Tensors::Dot(-K,Grad, Vel);
00375 }
00376
00377 inline void BarcelonaX::Actualize(Tensor2 const & DSig, REAL const & DPp, Tensor2 & DEps, REAL & DnSr)
00378 {
00379
00380 Tensor2 eps_ini = _eps;
00381 REAL n_ini = (_v-1.0)/_v;
00382 REAL Sr_ini = Sr();
00383 REAL nSr_ini = n_ini * Sr_ini;
00384
00385
00386 Tensor2 dsig_tr = DSig;
00387 Tensor2 sig_tr = _sig + dsig_tr;
00388 REAL dsuc_tr = 0.0 - DPp;
00389 REAL suc_tr = _suc + dsuc_tr;
00390 if (suc_tr<0.0) { dsuc_tr=0.0-_suc; suc_tr=0.0; }
00391
00392
00393 enum Situation {EL, EL_EPL, EPL};
00394
00395
00396 REAL F = YieldFunc(_sig ,_z,_suc );
00397 REAL F_tr = YieldFunc( sig_tr,_z, suc_tr);
00398 Situation sit;
00399 if (F<0.0)
00400 {
00401 if (F_tr<=0.0) sit=EL;
00402 else sit=EL_EPL;
00403 }
00404 else
00405 {
00406 if (F_tr<=F) sit=EL;
00407 else
00408 {
00409
00410 Tensor2 df_dsig;
00411 REAL df_dsuc;
00412 Calc_dFdSig_dFdSuc(_sig,_z,_suc, df_dsig,df_dsuc);
00413 REAL scalar = Tensors::Dot(df_dsig,dsig_tr) + df_dsuc*dsuc_tr;
00414 if (scalar>=0.0) sit=EPL;
00415 else sit=EL_EPL;
00416 }
00417 }
00418
00419
00420
00421
00422 if (sit==EL)
00423 {
00424
00425 int n_div=_isc.FE_ndiv();
00426 Tensor2 dsig; dsig = dsig_tr/n_div;
00427 REAL dsuc; dsuc = dsuc_tr/n_div;
00428 for (int i=0; i<n_div; ++i)
00429 {
00430
00431 Tensor4 Ce;
00432 Tensor2 ce;
00433 _calc_Ce_ce(_v,_sig,_suc, Ce,ce);
00434
00435
00436 Tensors::Dot(Ce,dsig, DEps);
00437 DEps += ce * dsuc;
00438
00439
00440 _sig += dsig;
00441 _suc += dsuc;
00442 _eps += DEps;
00443
00444 }
00445 }
00446 else
00447 {
00448 if (sit==EL_EPL)
00449 {
00450
00451 Tensor2 sig_int;
00452 REAL suc_int;
00453
00454
00455
00456 _find_intersection(dsig_tr,dsuc_tr,F,F_tr,sig_int,suc_int);
00457
00458
00459
00460 Tensor2 dsig_el; dsig_el = sig_int - _sig;
00461 Tensor2 dsig_epl; dsig_epl = dsig_tr - dsig_el;
00462
00463
00464 REAL dsuc_el = suc_int - _suc;
00465 REAL dsuc_epl = dsuc_tr - dsuc_el;
00466
00467
00468 Tensor4 Ce;
00469 Tensor2 ce;
00470 _calc_Ce_ce(_v,_sig,_suc, Ce,ce);
00471
00472
00473 Tensors::Dot(Ce,dsig_el, DEps);
00474 DEps += ce * dsuc_el;
00475
00476
00477 _sig += dsig_el;
00478 _suc += dsuc_el;
00479 _eps += DEps;
00480
00481
00482
00483 dsig_tr = dsig_epl;
00484 dsuc_tr = dsuc_epl;
00485 }
00486
00487 if (CoupledModel::_isc.Type()==IntegSchemesCtes::FE)
00488 {
00489
00490 int n_div=_isc.FE_ndiv();
00491 Tensor2 dsig; dsig = dsig_tr/n_div;
00492 REAL dsuc; dsuc = dsuc_tr/n_div;
00493 AugVec dsigsuc; dsigsuc = dsig(0),dsig(1),dsig(2),dsig(3),dsig(4),dsig(5),dsuc;
00494 for (int i=0; i<n_div; ++i)
00495 {
00496 IntVars dz;
00497 AugVec sigsuc; sigsuc = _sig(0),_sig(1),_sig(2),_sig(3),_sig(4),_sig(5),_suc;
00498 _tg_deps_dz_given_dsig_and_dsuc(sigsuc, _eps, _z, dsigsuc, DEps, dz);
00499 _sig += dsig;
00500 _suc += dsuc;
00501 _eps += DEps;
00502 _z += dz;
00503 }
00504 }
00505 else
00506 {
00507
00508 AugVec sigsuc; sigsuc = _sig (0),_sig (1),_sig (2),_sig (3),_sig (4),_sig (5),_suc;
00509 AugVec dsigsuc; dsigsuc = dsig_tr(0),dsig_tr(1),dsig_tr(2),dsig_tr(3),dsig_tr(4),dsig_tr(5),dsuc_tr;
00510
00511
00512 AutoStepME<AugVec,Tensor2,IntVars,BarcelonaX> TI(CoupledModel::_isc);
00513
00514
00515 int nss = TI.Solve(this,
00516 &BarcelonaX::_tg_deps_dz_given_dsig_and_dsuc,
00517 &BarcelonaX::_local_error,
00518 sigsuc, _eps, _z, dsigsuc);
00519
00520 if (nss==-1)
00521 throw new Fatal(_("BarcelonaX::Actualize: (Loading) Number of max sub-steps (%d) was not sufficient for AutoStepME."), CoupledModel::_isc.ME_maxSS());
00522
00523
00524 _sig = sigsuc(0),sigsuc(1),sigsuc(2),sigsuc(3),sigsuc(4),sigsuc(5);
00525 _suc = sigsuc(6);
00526 }
00527 }
00528
00529
00530 DEps = _eps - eps_ini;
00531
00532
00533 _v += -(DEps(0)+DEps(1)+DEps(2))*_v;
00534
00535
00536 _ppr += DPp;
00537
00538
00539 REAL n_fin = (_v-1.0)/_v;
00540 REAL Sr_fin = Sr();
00541 REAL nSr_fin = n_fin * Sr_fin;
00542 DnSr = nSr_fin - nSr_ini;
00543
00544 }
00545
00546 inline void BarcelonaX::StressUpdate(Tensor2 const & DEps, REAL const & DPp, Tensor2 & DSig, REAL & DnSr)
00547 {
00548
00549 Tensor2 sig_ini = _sig;
00550 REAL Sr_ini = Sr();
00551
00552
00553 REAL n_times_dSr_dPp_ini = n_times_dSr_dPp();
00554
00555
00556 Tensor4 De;
00557 Tensor2 de;
00558 _calc_De_de(_v,_sig,_suc, De,de);
00559
00560
00561 Tensor2 dsig_tr; Tensors::Dot(De,DEps, dsig_tr); dsig_tr += de*(-DPp);
00562 Tensor2 sig_tr = _sig + dsig_tr;
00563 REAL dsuc_tr = 0.0 - DPp;
00564 REAL suc_tr = _suc + dsuc_tr;
00565 if (suc_tr<0.0) { dsuc_tr=0.0-_suc; suc_tr=0.0; }
00566
00567
00568 enum Situation {EL, EL_EPL, EPL};
00569
00570
00571 REAL F = YieldFunc(_sig ,_z,_suc );
00572 REAL F_tr = YieldFunc( sig_tr,_z, suc_tr);
00573 Situation sit;
00574 if (F<0.0)
00575 {
00576 if (F_tr<=0.0) sit=EL;
00577 else sit=EL_EPL;
00578 }
00579 else
00580 {
00581 if (F_tr<=F) sit=EL;
00582 else
00583 {
00584
00585 Tensor2 V;
00586 REAL S;
00587 Calc_dFdSig_dFdSuc(_sig,_z,_suc, V,S);
00588 _num_dLam = (Tensors::Dot(V,dsig_tr) + S*dsuc_tr);
00589 if (_num_dLam>=0.0) sit=EPL;
00590 else sit=EL_EPL;
00591 }
00592 }
00593
00594
00595
00596
00597 if (sit==EL)
00598 {
00599
00600 _num_dLam = -1.0;
00601
00602
00603 DSig = dsig_tr;
00604
00605
00606 _sig += DSig;
00607 _suc += dsuc_tr;
00608 _eps += DEps;
00609
00610 }
00611 else
00612 {
00613
00614 _num_dLam = +1.0;
00615
00616
00617 Tensor2 deps = DEps;
00618 REAL dsuc = dsuc_tr;
00619
00620
00621 if (sit==EL_EPL)
00622 {
00623
00624
00625
00626 Tensor2 sig_int;
00627 REAL suc_int;
00628 _find_intersection(dsig_tr,dsuc_tr,F,F_tr,sig_int,suc_int);
00629
00630
00631 Tensor4 Ce;
00632 Tensor2 ce;
00633 _calc_Ce_ce(_v,_sig,_suc, Ce,ce);
00634
00635
00636 Tensor2 dsig_el; dsig_el = sig_int - _sig;
00637 REAL dsuc_el = suc_int - _suc;
00638 Tensor2 deps_el; Tensors::Dot(Ce,dsig_el, deps_el);
00639 deps_el += ce*dsuc_el;
00640
00641
00642 _sig += dsig_el;
00643 _suc += dsuc_el;
00644 _eps += deps_el;
00645
00646
00647
00648 deps = DEps - deps_el;
00649 dsuc = dsuc_tr - dsuc_el;
00650 }
00651
00652 if (CoupledModel::_isc.Type()==IntegSchemesCtes::FE)
00653 {
00654
00655 int n_div=_isc.FE_ndiv();
00656 deps = deps/n_div;
00657 dsuc = dsuc/n_div;
00658 AugVec depssuc; depssuc = deps(0),deps(1),deps(2),deps(3),deps(4),deps(5),dsuc;
00659 for (int i=0; i<n_div; ++i)
00660 {
00661 IntVars dz;
00662 AugVec epssuc; epssuc = _eps(0),_eps(1),_eps(2),_eps(3),_eps(4),_eps(5),_suc;
00663 _tg_dsig_dz_given_deps_and_dsuc(epssuc, _sig, _z, depssuc, DSig, dz);
00664 _sig += DSig;
00665 _suc += dsuc;
00666 _eps += deps;
00667 _z += dz;
00668 }
00669 }
00670 else
00671 {
00672
00673 AugVec epssuc; epssuc = _eps(0),_eps(1),_eps(2),_eps(3),_eps(4),_eps(5),_suc;
00674 AugVec depssuc; depssuc = deps(0),deps(1),deps(2),deps(3),deps(4),deps(5),dsuc;
00675
00676
00677 AutoStepME<AugVec,Tensor2,IntVars,BarcelonaX> TI(CoupledModel::_isc);
00678
00679
00680 int nss = TI.Solve(this,
00681 &BarcelonaX::_tg_dsig_dz_given_deps_and_dsuc,
00682 &BarcelonaX::_local_error,
00683 epssuc, _sig, _z, depssuc);
00684
00685 if (nss==-1)
00686 throw new Fatal(_("BarcelonaX::StressUpdate: (Loading) Number of max sub-steps (%d) was not sufficient for AutoStepME."), CoupledModel::_isc.ME_maxSS());
00687
00688
00689 _eps = epssuc(0),epssuc(1),epssuc(2),epssuc(3),epssuc(4),epssuc(5);
00690 _suc = epssuc(6);
00691 }
00692 }
00693
00694
00695 DSig = _sig - sig_ini;
00696
00697
00698 _v += -(DEps(0)+DEps(1)+DEps(2))*_v;
00699
00700
00701 _ppr += DPp;
00702
00703
00704 DnSr = -(DEps(0)+DEps(1)+DEps(2))*Sr_ini + n_times_dSr_dPp_ini*DPp;
00705
00706 }
00707
00708 inline void BarcelonaX::BackupState()
00709 {
00710 _bkp_v = _v;
00711 _bkp_sig = _sig;
00712 _bkp_suc = _suc;
00713 _bkp_eps = _eps;
00714 _bkp_z = _z;
00715 _bkp_ppr = _ppr;
00716 _bkp_num_dLam = _num_dLam;
00717 }
00718
00719 inline void BarcelonaX::RestoreState()
00720 {
00721 _v = _bkp_v;
00722 _sig = _bkp_sig;
00723 _suc = _bkp_suc;
00724 _eps = _bkp_eps;
00725 _z = _bkp_z;
00726 _ppr = _bkp_ppr;
00727 _num_dLam = _bkp_num_dLam;
00728 }
00729
00730 inline REAL BarcelonaX::_lam(REAL const & Suc) const
00731 {
00732 return _lam0*((1.0-_r)*exp(-_bet*Suc) + _r);
00733 }
00734
00735 inline REAL BarcelonaX::_psi(REAL const & Suc) const
00736 {
00737 return (_lam0-_kap)/(_lam(Suc)-_kap);
00738 }
00739
00740 inline REAL BarcelonaX::Calc_p0(REAL const & Suc, REAL const & z0) const
00741 {
00742 return _pref*pow(z0/_pref, _psi(Suc));
00743 }
00744
00745 inline REAL BarcelonaX::YieldFunc(Tensor2 const & Sig, IntVars const & z, REAL const & Suc) const
00746 {
00747 REAL p,q,sin3th;
00748 Tensor2 devS;
00749 Stress_p_q_S_sin3th(Sig, p,q,devS,sin3th);
00750 REAL M = _calc_M(sin3th);
00751 REAL g = - M*M * (p+_k*Suc) * (Calc_p0(Suc,z(0))-p);
00752 REAL C = _pref*_pref*(exp(_BB*(Suc-z(1))/_pref) - exp(-_BB*z(1)/_pref));
00753 REAL F = q*q + g + C;
00754 if (fabs(F)<=_MAX_ERR_F) F=0.0;
00755 return F;
00756 }
00757
00758 inline void BarcelonaX::_calc_Ce_ce(REAL const & v, Tensor2 const & Sig, REAL const & Suc, Tensor4 & Ce, Tensor2 & ce) const
00759 {
00760
00761 REAL p = (Sig(0)+Sig(1)+Sig(2))/3.0;
00762
00763
00764 REAL K = p *v/_kap;
00765 REAL Ks = (Suc+_patm)*v/_kaps;
00766
00767
00768 Tensors::AddScaled(1.0/(2.0*_G), Tensors::Psd, 1.0/(9.0*K), Tensors::IdyI, Ce);
00769
00770
00771 ce = (1.0/(3.0*Ks)) * I;
00772
00773 }
00774
00775 inline void BarcelonaX::_calc_De_de(REAL const & v, Tensor2 const & Sig, REAL const & Suc, Tensor4 & De, Tensor2 & de) const
00776 {
00777
00778 REAL p = (Sig(0)+Sig(1)+Sig(2))/3.0;
00779
00780
00781 REAL K = p *v/_kap;
00782 REAL Ks = (Suc+_patm)*v/_kaps;
00783
00784
00785 Tensors::AddScaled(2.0*_G,Tensors::Psd, K,Tensors::IdyI, De);
00786
00787
00788 if (_suc <= 0.0)
00789 de = 0.0;
00790 else
00791 de = (-K/Ks)*I;
00792 }
00793
00794 inline void BarcelonaX::Calc_dFdSig_dFdSuc(Tensor2 const & Sig, IntVars const & z, REAL const & Suc, Tensor2 & V, REAL & S) const
00795 {
00796
00797 REAL p,q,sin3th;
00798 Tensor2 devS;
00799 Stress_p_q_S_sin3th(Sig, p,q,devS,sin3th);
00800
00801
00802 REAL lam = _lam(Suc);
00803 REAL psi = _psi(Suc);
00804 REAL p0 = Calc_p0(Suc,z(0));
00805 REAL ps = _k*Suc;
00806
00807
00808 REAL M = _calc_M(sin3th);
00809 REAL MM = M*M;
00810 REAL tmp = MM*(2.0*p-p0+ps)/3.0;
00811 REAL dp0_dSuc = p0*log(z(0)/_pref)*psi*_bet*_lam0*(1.0-_r)*exp(-_bet*Suc)/(lam-_kap);
00812 REAL dC_dSuc = _BB*_pref*exp(_BB*(Suc-z(1))/_pref);
00813 REAL dg_dSuc = MM*((p-p0)*_k - (p+ps)*dp0_dSuc);
00814 V = tmp*I + 3.0*devS;
00815 S = dg_dSuc + dC_dSuc;
00816 if (q>Q_ZERO)
00817 {
00818 REAL ss3th = pow(sin3th,2.0);
00819 REAL cos3th = (ss3th>1.0 ? 0.0 : sqrt(1.0-ss3th));
00820 if (cos3th>Q_ZERO)
00821 {
00822 REAL dM_dth = (0.75*M*(1.0-_wcs)*cos3th) / (1.0+_wcs+(_wcs-1.0)*sin3th);
00823 Tensor2 SS; Mult(devS,devS,SS);
00824 Tensor2 dev_SS; dev_SS = SS - (I * (SS(0)+SS(1)+SS(2))/3.0);
00825 Tensor2 dth_dsig; dth_dsig = (1.5/(q*q*cos3th)) * (dev_SS*(3.0/q) - devS*sin3th);
00826 V += dth_dsig*(2.0*M*(p-p0)*(p+ps)*dM_dth);
00827 }
00828 }
00829
00830 }
00831
00832 inline void BarcelonaX::_calc_gradients_and_hardening(REAL const & v,
00833 Tensor2 const & Sig,
00834 IntVars const & z,
00835 REAL const & Suc,
00836 Tensor2 & r,
00837 Tensor2 & V,
00838 T_dFdz & y,
00839 REAL & S,
00840 HardMod & HH,
00841 REAL & hp) const
00842 {
00843
00844 REAL p,q,sin3th;
00845 Tensor2 devS;
00846 Stress_p_q_S_sin3th(Sig, p,q,devS,sin3th);
00847
00848
00849 REAL lam = _lam(Suc);
00850 REAL psi = _psi(Suc);
00851 REAL p0 = Calc_p0(Suc,z(0));
00852 REAL ps = _k*Suc;
00853
00854
00855 REAL C = _pref*_pref*(exp(_BB*(Suc-z(1))/_pref) - exp(-_BB*z(1)/_pref));
00856 REAL M = _calc_M(sin3th);
00857 REAL MM = M*M;
00858 REAL tmp = MM*(2.0*p-p0+ps)/3.0;
00859 REAL dp0_dSuc = p0*log(z(0)/_pref)*psi*_bet*_lam0*(1.0-_r)*exp(-_bet*Suc)/(lam-_kap);
00860 REAL dC_dSuc = _BB*_pref*exp(_BB*(Suc-z(1))/_pref);
00861 REAL dg_dSuc = MM*((p-p0)*_k - (p+ps)*dp0_dSuc);
00862 r = tmp*I + (3.0*_alp)*devS;
00863 V = tmp*I + 3.0 *devS;
00864 S = dg_dSuc + dC_dSuc;
00865 if (q>Q_ZERO)
00866 {
00867 REAL ss3th = pow(sin3th,2.0);
00868 REAL cos3th = (ss3th>1.0 ? 0.0 : sqrt(1.0-ss3th));
00869 if (cos3th>Q_ZERO)
00870 {
00871 REAL dM_dth = (0.75*M*(1.0-_wcs)*cos3th) / (1.0+_wcs+(_wcs-1.0)*sin3th);
00872 Tensor2 SS; Mult(devS,devS,SS);
00873 Tensor2 dev_SS; dev_SS = SS - (I * (SS(0)+SS(1)+SS(2))/3.0);
00874 Tensor2 dth_dsig; dth_dsig = (1.5/(q*q*cos3th)) * (dev_SS*(3.0/q) - devS*sin3th);
00875 V += dth_dsig*(2.0*M*(p-p0)*(p+ps)*dM_dth);
00876 r += dth_dsig*(2.0*M*(p-p0)*(p+ps)*dM_dth);
00877 }
00878 }
00879 y(0) = -MM*psi*p0*(p+ps)/z(0);
00880 y(1) = -_BB*C/_pref;
00881
00882
00883 REAL tr_r = r(0)+r(1)+r(2);
00884 REAL chi0 = (_lam0 - _kap )/v;
00885 REAL chis = (_lams - _kaps)/v;
00886 HH(0) = z(0) *tr_r/chi0;
00887 HH(1) = (z(1)+_patm)*tr_r/chis;
00888
00889
00890 hp = -(y(0)*HH(0)+y(1)*HH(1));
00891
00892 }
00893
00894 inline int BarcelonaX::_tg_deps_dz_given_dsig_and_dsuc(AugVec const & SigSuc,
00895 Tensor2 const & Eps,
00896 IntVars const & z,
00897 AugVec const & dSigSuc,
00898 Tensor2 & dEps,
00899 IntVars & dz) const
00900 {
00901
00902 REAL ev,ed;
00903 Tensors::Strain_Ev_Ed(Eps, ev,ed);
00904 if (ed>CoupledModel::_isc.EdMax())
00905 throw new Warning(_("BarcelonaX::_tg_deps_dz_given_dsig_and_dsuc: Max devaitoric strain Ed=%f greater than EdMax=%f"),ed,_isc.EdMax());
00906
00907
00908 Tensor2 sig; sig = SigSuc(0), SigSuc(1), SigSuc(2), SigSuc(3), SigSuc(4), SigSuc(5);
00909 Tensor2 dsig; dsig = dSigSuc(0),dSigSuc(1),dSigSuc(2),dSigSuc(3),dSigSuc(4),dSigSuc(5);
00910 REAL suc; suc = SigSuc(6);
00911 REAL dsuc; dsuc = dSigSuc(6);
00912
00913
00914 REAL v=_v;
00915 Tensor2 r;
00916 Tensor2 V;
00917 T_dFdz y;
00918 REAL S;
00919 HardMod HH;
00920 REAL hp;
00921 _calc_gradients_and_hardening(v, sig, z, suc, r, V, y, S, HH, hp);
00922
00923
00924 if (fabs(hp/(sig(0)+sig(1)+sig(2)))<=_MIN_HP)
00925 throw new Warning(_("BarcelonaX::_tg_deps_dz_given_dsig_and_dsuc: hp=%f (zero). Maybe it is the start of softening behaviour"),hp);
00926
00927
00928 Tensor4 Cep;
00929 Tensor2 ce;
00930 _calc_Ce_ce(v,sig,suc, Cep,ce);
00931
00932
00933 Tensors::Ger(1.0/hp,r,V, Cep);
00934
00935
00936 Tensor2 cep;
00937 cep = (S/hp)*r + ce;
00938
00939
00940 Tensors::Dot(Cep,dsig, dEps);
00941 dEps += cep*dsuc;
00942
00943
00944 REAL dLam = (Tensors::Dot(V,dsig) + S*dsuc)/hp;
00945 dz = dLam*HH;
00946
00947 return 0;
00948 }
00949
00950 inline int BarcelonaX::_tg_dsig_dz_given_deps_and_dsuc(AugVec const & EpsSuc,
00951 Tensor2 const & Sig,
00952 IntVars const & z,
00953 AugVec const & dEpsSuc,
00954 Tensor2 & dSig,
00955 IntVars & dz) const
00956 {
00957
00958 Tensor2 eps; eps = EpsSuc(0), EpsSuc(1), EpsSuc(2), EpsSuc(3), EpsSuc(4), EpsSuc(5);
00959 Tensor2 deps; deps = dEpsSuc(0),dEpsSuc(1),dEpsSuc(2),dEpsSuc(3),dEpsSuc(4),dEpsSuc(5);
00960 REAL suc; suc = EpsSuc(6);
00961 REAL dsuc; dsuc = dEpsSuc(6);
00962
00963
00964 REAL v=_v;
00965 Tensor2 r;
00966 Tensor2 V;
00967 T_dFdz y;
00968 REAL S;
00969 HardMod HH;
00970 REAL hp;
00971 _calc_gradients_and_hardening(v, Sig, z, suc, r, V, y, S, HH, hp);
00972
00973
00974 Tensor4 De;
00975 Tensor2 de;
00976 _calc_De_de(v,Sig,suc, De,de);
00977
00978
00979 Tensor4 Dep;
00980 REAL Phi = Tensors::Reduce(V,De,r)+hp;
00981 Tensors::GerX(-1.0/Phi,De,r,V,De,De,Dep);
00982
00983
00984 Tensor2 dep;
00985 Tensors::Dot(De,r, dep);
00986 dep = de - ((Tensors::Dot(V,de)+S)/Phi)*dep;
00987
00988
00989 Tensors::Dot(Dep,deps, dSig);
00990 dSig += dep*dsuc;
00991
00992
00993 REAL dLam = (Tensors::Reduce(V,De,deps) + Tensors::Dot(V,de)*dsuc + S*dsuc)/Phi;
00994 dz = dLam*HH;
00995
00996 return 0;
00997 }
00998
00999 inline REAL BarcelonaX::_local_error(Tensor2 const & Ey, Tensor2 const & y_high,
01000 IntVars const & Ez, IntVars const & z_high) const
01001 {
01002 REAL Err_y = Tensors::Norm(Ey)/Tensors::Norm(y_high);
01003 REAL Err_z = sqrt(blitz::dot(Ez,Ez))/sqrt(blitz::dot(z_high,z_high));
01004 return (Err_y>Err_z ? Err_y : Err_z);
01005 }
01006
01007 inline REAL BarcelonaX::_find_intersection_NR(Tensor2 const & dSig_tr,
01008 REAL const & dSuc_tr,
01009 REAL const & F ,
01010 REAL const & F_tr ,
01011 Tensor2 & Sig_int,
01012 REAL & Suc_int) const
01013 {
01014
01015 const REAL ITOL = 1.0e-12;
01016 const int MAXIT = 10;
01017
01018
01019 REAL alpha = -F/(F_tr-F);
01020 REAL F_int;
01021 REAL F_err;
01022 for (int it=1; it<=MAXIT; ++it)
01023 {
01024
01025 Sig_int = _sig + alpha*dSig_tr;
01026 Suc_int = _suc + alpha*dSuc_tr;
01027
01028
01029 F_int = YieldFunc(Sig_int,_z,Suc_int);
01030
01031
01032 F_err = fabs(F_int)/fabs(_z(0));
01033
01034
01035 if (F_err<ITOL) return alpha;
01036
01037
01038 Tensor2 V;
01039 REAL S;
01040 Calc_dFdSig_dFdSuc(Sig_int,_z,Suc_int, V,S);
01041
01042
01043 alpha += -F_int/(Tensors::Dot(V,dSig_tr) + S*dSuc_tr);
01044
01045
01046 if (alpha<0.0 || alpha>1.0) throw new Fatal("BarcelonaX::_find_intersection_NR: Alpha must be inside [0,1].");
01047 }
01048
01049
01050 throw new Fatal("BarcelonaX::_find_intersection_NR: Intersection not found.");
01051
01052 }
01053
01054 inline REAL BarcelonaX::_find_intersection(Tensor2 const & dSig_tr,
01055 REAL const & dSuc_tr,
01056 REAL const & F ,
01057 REAL const & F_tr ,
01058 Tensor2 & Sig_int,
01059 REAL & Suc_int) const
01060 {
01061
01062 REAL alpha;
01063 REAL F_int;
01064
01065
01066
01067
01068
01069
01070 const int ITMAX=40;
01071 const REAL EPS=3.0e-8;
01072 const REAL tol=1.0e-5;
01073
01074 REAL a=0.0;
01075 REAL b=1.0;
01076 REAL c=1.0;
01077 REAL d=0.0,e=0.0,min1=0.0,min2=0.0;
01078 REAL fa=F;
01079 REAL fb=F_tr;
01080 REAL fc,p,q,r,s,tol1,xm;
01081 if ((fa > 0.0 && fb > 0.0) || (fa < 0.0 && fb < 0.0))
01082 throw new Fatal("BarcelonaX::_find_intersection: Root must be bracketed in zbrent");
01083 fc=fb;
01084 int iter;
01085 for (iter=1;iter<=ITMAX;iter++)
01086 {
01087 if ((fb > 0.0 && fc > 0.0) || (fb < 0.0 && fc < 0.0))
01088 {
01089 c=a;
01090 fc=fa;
01091 e=d=b-a;
01092 }
01093 if (fabs(fc) < fabs(fb))
01094 {
01095 a=b;
01096 b=c;
01097 c=a;
01098 fa=fb;
01099 fb=fc;
01100 fc=fa;
01101 }
01102 tol1=2.0*EPS*fabs(b)+0.5*tol;
01103 xm=0.5*(c-b);
01104 if (fabs(xm) <= tol1 || fb == 0.0)
01105 {
01106 alpha = b;
01107 Sig_int = _sig + alpha*dSig_tr;
01108 Suc_int = _suc + alpha*dSuc_tr;
01109 break;
01110 }
01111 if (fabs(e) >= tol1 && fabs(fa) > fabs(fb))
01112 {
01113 s=fb/fa;
01114 if (a == c)
01115 {
01116 p=2.0*xm*s;
01117 q=1.0-s;
01118 }
01119 else
01120 {
01121 q=fa/fc;
01122 r=fb/fc;
01123 p=s*(2.0*xm*q*(q-r)-(b-a)*(r-1.0));
01124 q=(q-1.0)*(r-1.0)*(s-1.0);
01125 }
01126 if (p > 0.0) q = -q;
01127 p=fabs(p);
01128 min1=3.0*xm*q-fabs(tol1*q);
01129 min2=fabs(e*q);
01130 if (2.0*p < (min1 < min2 ? min1 : min2))
01131 {
01132 e=d;
01133 d=p/q;
01134 }
01135 else
01136 {
01137 d=xm;
01138 e=d;
01139 }
01140 }
01141 else
01142 {
01143 d=xm;
01144 e=d;
01145 }
01146 a=b;
01147 fa=fb;
01148 if (fabs(d) > tol1)
01149 b += d;
01150 else
01151 b += Util::Sign(tol1,xm);
01152
01153
01154
01155
01156 alpha = b;
01157 Sig_int = _sig + alpha*dSig_tr;
01158 Suc_int = _suc + alpha*dSuc_tr;
01159 F_int = YieldFunc(Sig_int, _z, Suc_int);
01160 fb = F_int;
01161 }
01162 if (iter>ITMAX)
01163 throw new Fatal("BarcelonaX::_find_intersection: Maximum number of iterations exceeded in zbrent");
01164
01165 return alpha;
01166
01167 }
01168
01169 inline void BarcelonaX::InternalStateValues(Array<REAL> & IntStateVals) const
01170 {
01171 IntStateVals.resize(3);
01172 IntStateVals[0] = _z(0);
01173 IntStateVals[1] = _z(1);
01174 IntStateVals[2] = _v;
01175 }
01176
01177 inline void BarcelonaX::InternalStateNames(Array<String> & IntStateNames) const
01178 {
01179 IntStateNames.resize(3);
01180 IntStateNames[0] = "z0";
01181 IntStateNames[1] = "z1";
01182 IntStateNames[2] = "v";
01183 }
01184
01185 inline REAL BarcelonaX::_calc_M(REAL const & sin3th) const
01186 {
01187 return _Mcs*pow( 2.0*_wcs/(1.0+_wcs+(_wcs-1.0)*sin3th) ,0.25);
01188 }
01189
01190
01192
01193
01194
01195 CoupledModel * BarcelonaXMaker(Array<REAL> const & Prms, Array<REAL> const & IniData)
01196 {
01197 return new BarcelonaX(Prms, IniData);
01198 }
01199
01200
01201 int BarcelonaXRegister()
01202 {
01203 CoupledModelFactory["BarcelonaX"] = BarcelonaXMaker;
01204 return 0;
01205 }
01206
01207
01208 int __BarcelonaX_dummy_int = BarcelonaXRegister();
01209
01210 #endif // MECHSYS_BARCELONAX_H
01211
01212