00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #ifndef MECHSYS_GENERICEP_H
00023 #define MECHSYS_GENERICEP_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 #define Z0_MINUS_Z1_TOL 1.0e-7
00034 #define CP_ZERO 1.0e-5
00035
00036 #include "models/equilibmodel.h"
00037 #include "tensors/tensors.h"
00038 #include "tensors/operators.h"
00039 #include "tensors/functions.h"
00040 #include "numerical/autostepme.h"
00041 #include "util/string.h"
00042
00043 using Tensors::Tensor2;
00044 using Tensors::Reduce;
00045 using Tensors::GerX;
00046 using Tensors::Dot;
00047 using Tensors::Norm;
00048 using blitz::dot;
00049 using Tensors::Ger;
00050
00051 template<unsigned int nIntVars>
00052 class GenericEP : public EquilibModel
00053 {
00054 public:
00056 typedef blitz::TinyVector<REAL,nIntVars> IntVars;
00057 typedef blitz::TinyVector<REAL,nIntVars> HardMod;
00058 typedef blitz::TinyVector<REAL,nIntVars> T_dfdz;
00059
00060
00061 GenericEP() : _num_dLam(1.0) {}
00062
00063
00064 virtual ~GenericEP() {}
00065
00066
00067 void TgStiffness (Tensors::Tensor4 & D) const;
00068 void Actualize (Tensors::Tensor2 const & DSig, Tensors::Tensor2 & DEps);
00069 void StressUpdate (Tensors::Tensor2 const & DEps, Tensors::Tensor2 & DSig);
00070 void BackupState ();
00071 void RestoreState ();
00072
00073
00074 virtual int nAdditionalInternalStateValues () const { return 0; }
00075 virtual void AdditionalInternalStateValues (Array<REAL> & IntStateVals) const {};
00076 virtual void AdditionalInternalStateNames (Array<String> & IntStateNames) const {};
00077
00078
00079 int nInternalStateValues () const { return nIntVars+1+nAdditionalInternalStateValues(); };
00080 void InternalStateValues (Array<REAL> & IntStateVals ) const;
00081 void InternalStateNames (Array<String> & IntStateNames) const;
00082
00083 protected:
00084
00085 REAL _v;
00086 IntVars _z;
00087 REAL _v_bkp;
00088 IntVars _z_bkp;
00089
00090
00091 virtual void _calc_grads_hards(REAL const & v ,
00092 Tensor2 const & Sig,
00093 IntVars const & z ,
00094 Tensor2 & r ,
00095 Tensor2 & V ,
00096 T_dfdz & y ,
00097 HardMod & HH ,
00098 REAL & cp ) const =0;
00099
00100 virtual void _calc_De(REAL const & v, Tensors::Tensor2 const & Sig, IntVars const & z, bool IsUnloading, Tensors::Tensor4 & De) const =0;
00101 virtual void _calc_Ce(REAL const & v, Tensors::Tensor2 const & Sig, IntVars const & z, bool IsUnloading, Tensors::Tensor4 & Ce) const =0;
00102 virtual void _unloading_update_int_vars() =0;
00103 virtual void _calc_dz(Tensors::Tensor2 const & dSig, Tensors::Tensor2 const & dEps, REAL const & dLam, HardMod const & HH, IntVars & dz) const =0;
00104
00105 private:
00106
00107 REAL _num_dLam;
00108 REAL _bkp_num_dLam;
00109
00110
00111 int _Dep_times_dEps(Tensor2 const & Eps,
00112 Tensor2 const & Sig,
00113 IntVars const & z,
00114 Tensor2 const & dEps,
00115 Tensor2 & dSig,
00116 IntVars & dz) const;
00117
00118
00119 int _Cep_times_dSig(Tensor2 const & Sig,
00120 Tensor2 const & Eps,
00121 IntVars const & z,
00122 Tensor2 const & dSig,
00123 Tensor2 & dEps,
00124 IntVars & dz) const;
00125
00126
00127 int _De_times_dEps(Tensor2 const & Eps,
00128 Tensor2 const & Sig,
00129 float const & dummy1,
00130 Tensor2 const & dEps,
00131 Tensor2 & dSig,
00132 float & dummy2) const;
00133
00134
00135 int _Ce_times_dSig(Tensor2 const & Sig,
00136 Tensor2 const & Eps,
00137 float const & dummy1,
00138 Tensor2 const & dSig,
00139 Tensor2 & dEps,
00140 float & dummy2) const;
00141
00142
00143 REAL _local_error(Tensor2 const & Ey ,
00144 Tensor2 const & y_high,
00145 IntVars const & Ez ,
00146 IntVars const & z_high) const;
00147
00148 REAL _local_error(Tensor2 const & Ey ,
00149 Tensor2 const & y_high,
00150 float const & dummy1,
00151 float const & dummy2) const;
00152 };
00153
00154
00156
00157
00158 template<unsigned int nIntVars>
00159 inline void GenericEP<nIntVars>::TgStiffness(Tensors::Tensor4 & D) const
00160 {
00161 if (_num_dLam<0)
00162 {
00163 _calc_De(_v, _sig, _z, true, D);
00164 }
00165 else
00166 {
00167
00168 Tensor2 r,V; T_dfdz y; HardMod HH; REAL cp;
00169 _calc_grads_hards(_v, _sig, _z, r, V, y, HH, cp);
00170
00171
00172 Tensors::Tensor4 De;
00173 _calc_De(_v, _sig, _z, false, De);
00174 REAL Phi = Reduce(V,De,r)+cp;
00175 GerX(-1.0/Phi,De,r,V,De,De, D);
00176 }
00177 }
00178
00179 template<unsigned int nIntVars>
00180 inline void GenericEP<nIntVars>::Actualize(Tensors::Tensor2 const & DSig, Tensors::Tensor2 & DEps)
00181 {
00182
00183 Tensor2 eps_ini = _eps;
00184
00185
00186 Tensor2 r,V; T_dfdz y; HardMod HH; REAL cp;
00187 _calc_grads_hards(_v, _sig, _z, r, V, y, HH, cp);
00188
00189
00190 REAL dLam = Dot(V,DSig)/cp;
00191
00192
00193 if (dLam<0.0)
00194 {
00195 if (EquilibModel::_isc.Type()==IntegSchemesCtes::FE)
00196 {
00197
00198 int n_div = _isc.FE_ndiv();
00199 Tensor2 dsig = DSig/n_div;
00200 float dummy;
00201 for (int i=0; i<n_div; ++i)
00202 {
00203 _Ce_times_dSig(_sig, _eps, dummy, dsig, DEps, dummy);
00204 _sig += dsig;
00205 _eps += DEps;
00206 }
00207 }
00208 else
00209 {
00210
00211 AutoStepME<Tensor2, Tensor2, float, GenericEP<nIntVars> > TI(EquilibModel::_isc);
00212
00213
00214 float dummy;
00215 int nss = TI.Solve(this,
00216 &GenericEP<nIntVars>::_Ce_times_dSig ,
00217 &GenericEP<nIntVars>::_local_error ,
00218 _sig, _eps, dummy, DSig);
00219
00220 if (nss==-1)
00221 throw new Fatal(_("GenericEP::Actualize: (Unloading) Number of max sub-steps (%d) was not sufficient for AutoStepME."), EquilibModel::_isc.ME_maxSS());
00222 }
00223
00224 _unloading_update_int_vars();
00225 }
00226 else
00227 {
00228 if (EquilibModel::_isc.Type()==IntegSchemesCtes::FE)
00229 {
00230
00231 int n_div = _isc.FE_ndiv();
00232 Tensor2 dsig = DSig/n_div;
00233 for (int i=0; i<n_div; ++i)
00234 {
00235 IntVars dz;
00236 _Cep_times_dSig(_sig, _eps, _z, dsig, DEps, dz);
00237 _sig += dsig;
00238 _eps += DEps;
00239 _z += dz;
00240 }
00241 }
00242 else
00243 {
00244
00245 AutoStepME<Tensor2, Tensor2, IntVars, GenericEP<nIntVars> > TI(EquilibModel::_isc);
00246
00247
00248 int nss = TI.Solve(this,
00249 &GenericEP<nIntVars>::_Cep_times_dSig,
00250 &GenericEP<nIntVars>::_local_error ,
00251 _sig, _eps, _z, DSig);
00252
00253 if (nss==-1)
00254 throw new Fatal(_("GenericEP::Actualize: (Loading) Number of max sub-steps (%d) was not sufficient for AutoStepME."), EquilibModel::_isc.ME_maxSS());
00255 }
00256 }
00257
00258
00259 DEps = _eps - eps_ini;
00260
00261
00262 _v += -(DEps(0)+DEps(1)+DEps(2))*_v;
00263
00264 }
00265
00266 template<unsigned int nIntVars>
00267 inline void GenericEP<nIntVars>::StressUpdate(Tensors::Tensor2 const & DEps, Tensors::Tensor2 & DSig)
00268 {
00269
00270 Tensor2 sig_ini = _sig;
00271
00272
00273 Tensor2 r,V; T_dfdz y; HardMod HH; REAL cp;
00274 _calc_grads_hards(_v, _sig, _z, r, V, y, HH, cp);
00275
00276
00277 Tensors::Tensor4 De;
00278 if (_num_dLam<0) _calc_De(_v, _sig, _z, true, De);
00279 else _calc_De(_v, _sig, _z, false, De);
00280 _num_dLam = Reduce(V,De,DEps);
00281
00282
00283 if (_num_dLam<0.0)
00284 {
00285 if (EquilibModel::_isc.Type()==IntegSchemesCtes::FE)
00286 {
00287
00288 int n_div = _isc.FE_ndiv();
00289 Tensor2 deps = DEps/n_div;
00290 float dummy;
00291 for (int i=0; i<n_div; ++i)
00292 {
00293 _De_times_dEps(_eps, _sig, dummy, deps, DSig, dummy);
00294 _sig += DSig;
00295 _eps += deps;
00296 }
00297 }
00298 else
00299 {
00300
00301 AutoStepME<Tensor2, Tensor2, float, GenericEP<nIntVars> > TI(EquilibModel::_isc);
00302
00303
00304 float dummy;
00305 int nss = TI.Solve(this,
00306 &GenericEP<nIntVars>::_De_times_dEps ,
00307 &GenericEP<nIntVars>::_local_error ,
00308 _eps, _sig, dummy, DEps);
00309
00310 if (nss==-1)
00311 throw new Fatal(_("GenericEP::Actualize: (Unloading) Number of max sub-steps (%d) was not sufficient for AutoStepME."), EquilibModel::_isc.ME_maxSS());
00312 }
00313
00314 _unloading_update_int_vars();
00315 }
00316 else
00317 {
00318 if (EquilibModel::_isc.Type()==IntegSchemesCtes::FE)
00319 {
00320
00321 int n_div = _isc.FE_ndiv();
00322 Tensor2 deps = DEps/n_div;
00323 for (int i=0; i<n_div; ++i)
00324 {
00325 IntVars dz;
00326 _Dep_times_dEps(_eps, _sig, _z, deps, DSig, dz);
00327 _sig += DSig;
00328 _eps += deps;
00329 _z += dz;
00330 }
00331 }
00332 else
00333 {
00334
00335 AutoStepME<Tensor2, Tensor2, IntVars, GenericEP<nIntVars> > TI(EquilibModel::_isc);
00336
00337
00338 int nss = TI.Solve(this,
00339 &GenericEP<nIntVars>::_Dep_times_dEps,
00340 &GenericEP<nIntVars>::_local_error ,
00341 _eps, _sig, _z, DEps);
00342
00343 if (nss==-1)
00344 throw new Fatal(_("GenericEP::StressUpdate: (Loading) Number of max sub-steps (%d) was not sufficient for AutoStepME."), EquilibModel::_isc.ME_maxSS());
00345 }
00346 }
00347
00348
00349 DSig = _sig - sig_ini;
00350
00351
00352 _v += -(DEps(0)+DEps(1)+DEps(2))*_v;
00353
00354 }
00355
00356 template<unsigned int nIntVars>
00357 inline void GenericEP<nIntVars>::BackupState()
00358 {
00359 _sig_bkp = _sig;
00360 _eps_bkp = _eps;
00361 _v_bkp = _v;
00362 _z_bkp = _z;
00363 _bkp_num_dLam = _num_dLam;
00364 }
00365
00366 template<unsigned int nIntVars>
00367 inline void GenericEP<nIntVars>::RestoreState()
00368 {
00369 _sig = _sig_bkp;
00370 _eps = _eps_bkp;
00371 _v = _v_bkp;
00372 _z = _z_bkp;
00373 _num_dLam = _bkp_num_dLam;
00374 }
00375
00376 template<unsigned int nIntVars>
00377 inline int GenericEP<nIntVars>::_Dep_times_dEps(Tensor2 const & Eps,
00378 Tensor2 const & Sig,
00379 IntVars const & z,
00380 Tensor2 const & dEps,
00381 Tensor2 & dSig,
00382 IntVars & dz) const
00383 {
00384
00385 REAL v=_v;
00386 Tensor2 r,V; T_dfdz y; HardMod HH; REAL cp;
00387 _calc_grads_hards(v, Sig, z, r, V, y, HH, cp);
00388
00389
00390 Tensors::Tensor4 De,Dep;
00391 _calc_De(v, Sig, z, false, De);
00392 REAL Phi = Reduce(V,De,r)+cp;
00393 GerX(-1.0/Phi,De,r,V,De,De,Dep);
00394
00395
00396 Dot(Dep, dEps, dSig);
00397 REAL dLam = Reduce(V,De,dEps)/Phi;
00398
00399
00400 _calc_dz(dSig,dEps,dLam,HH, dz);
00401
00402 return 0;
00403 }
00404
00405 template<unsigned int nIntVars>
00406 inline int GenericEP<nIntVars>::_Cep_times_dSig(Tensor2 const & Sig,
00407 Tensor2 const & Eps,
00408 IntVars const & z,
00409 Tensor2 const & dSig,
00410 Tensor2 & dEps,
00411 IntVars & dz) const
00412 {
00413
00414 REAL v=_v;
00415 Tensor2 r,V; T_dfdz y; HardMod HH; REAL cp;
00416 _calc_grads_hards(v, Sig, z, r, V, y, HH, cp);
00417
00418
00419 if (fabs(cp/(_sig(0)+_sig(1)+_sig(2)))<=CP_ZERO)
00420 throw new Warning(_("GenericEP<%s>::_Cep_times_dSig: hp=%f. Maybe it is the start of softening behaviour"),this->Name().GetSTL().c_str(),cp);
00421
00422
00423 REAL Ev,Ed; Tensors::Strain_Ev_Ed(Eps, Ev, Ed);
00424 if (Ed>EquilibModel::_isc.EdMax())
00425 throw new Warning(_("GenericEP<%s>::_Cep_times_dSig: Ed=%f (%) greater than EdMax=%f (%)"),this->Name().GetSTL().c_str(),Ed*100.0,EquilibModel::_isc.EdMax()*100);
00426
00427
00428
00429 Tensors::Tensor4 Cep;
00430 _calc_Ce(v, Sig, z, false, Cep);
00431 Ger(1.0/cp,r,V,Cep);
00432
00433
00434 Dot(Cep, dSig, dEps);
00435 REAL dLam = Dot(V,dSig)/cp;
00436
00437
00438 _calc_dz(dSig,dEps,dLam,HH, dz);
00439
00440 return 0;
00441 }
00442
00443 template<unsigned int nIntVars>
00444 inline int GenericEP<nIntVars>::_De_times_dEps(Tensor2 const & Eps,
00445 Tensor2 const & Sig,
00446 float const & dummy1,
00447 Tensor2 const & dEps,
00448 Tensor2 & dSig,
00449 float & dummy2) const
00450 {
00451 Tensors::Tensor4 De;
00452 _calc_De(_v, Sig, _z, true, De);
00453 Dot(De,dEps,dSig);
00454 return 0;
00455 }
00456
00457 template<unsigned int nIntVars>
00458 inline int GenericEP<nIntVars>::_Ce_times_dSig(Tensor2 const & Sig,
00459 Tensor2 const & Eps,
00460 float const & dummy1,
00461 Tensor2 const & dSig,
00462 Tensor2 & dEps,
00463 float & dummy2) const
00464 {
00465 Tensors::Tensor4 Ce;
00466 _calc_Ce(_v, Sig, _z, true, Ce);
00467 Dot(Ce,dSig,dEps);
00468 return 0;
00469 }
00470
00471 template<unsigned int nIntVars>
00472 inline REAL GenericEP<nIntVars>::_local_error(Tensor2 const & Ey ,
00473 Tensor2 const & y_high,
00474 IntVars const & Ez ,
00475 IntVars const & z_high) const
00476 {
00477 REAL Err_y = Norm(Ey)/Norm(y_high);
00478 REAL Err_z = sqrt(dot(Ez,Ez))/sqrt(dot(z_high,z_high));
00479 return (Err_y>Err_z ? Err_y : Err_z);
00480 }
00481
00482 template<unsigned int nIntVars>
00483 inline REAL GenericEP<nIntVars>::_local_error(Tensor2 const & Ey ,
00484 Tensor2 const & y_high,
00485 float const & dummy1,
00486 float const & dummy2) const
00487 {
00488 return Norm(Ey)/Norm(y_high);
00489 }
00490
00491 template<unsigned int nIntVars>
00492 inline void GenericEP<nIntVars>::InternalStateValues(Array<REAL> & IntStateVals) const
00493 {
00494 int nIntStateVals = nIntVars+1+nAdditionalInternalStateValues();
00495 IntStateVals.resize(nIntStateVals);
00496 for (unsigned int i_intvar=0; i_intvar<nIntVars; ++i_intvar)
00497 IntStateVals[i_intvar] = _z(i_intvar);
00498 IntStateVals[nIntVars] = _v;
00499 if (nAdditionalInternalStateValues()>0)
00500 {
00501 Array<REAL> values;
00502 AdditionalInternalStateValues(values);
00503 for (int i=0; i<nAdditionalInternalStateValues(); ++i)
00504 IntStateVals[nIntVars+1+i] = values[i];
00505 }
00506 }
00507
00508 template<unsigned int nIntVars>
00509 inline void GenericEP<nIntVars>::InternalStateNames(Array<String> & IntStateNames) const
00510 {
00511 int nIntStateNames = nIntVars+1+nAdditionalInternalStateValues();
00512 IntStateNames.resize(nIntStateNames);
00513 for (unsigned int i_intvar=0; i_intvar<nIntVars; ++i_intvar)
00514 {
00515 std::ostringstream str_z; str_z << "z" << i_intvar;
00516 IntStateNames[i_intvar] = str_z.str();
00517 }
00518 IntStateNames[nIntVars] = "v";
00519 if (nAdditionalInternalStateValues()>0)
00520 {
00521 Array<String> names;
00522 AdditionalInternalStateNames(names);
00523 for (int i=0; i<nAdditionalInternalStateValues(); ++i)
00524 IntStateNames[nIntVars+1+i] = names[i];
00525 }
00526 }
00527
00528 #endif // MECHSYS_GENERICEP_H
00529
00530