MechSys  1.0
Computing library for simulations in continuum and discrete mechanics
/home/dorival/mechsys/lib/models/elastoplastic.h
Go to the documentation of this file.
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
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines