// CalcD computes D = dσ_new/dε_new consistent with StressUpdate func (o *VonMises) CalcD(D [][]float64, s *State, firstIt bool) (err error) { // set first Δγ if firstIt { s.Dgam = 0 } // elastic if !s.Loading { return o.SmallElasticity.CalcD(D, s) } // elastoplastic => consistent stiffness σ := s.Sig Δγ := s.Dgam p, q := tsr.M_p(σ), tsr.M_q(σ) qtr := q + Δγ*3.0*o.G m := 1.0 - Δγ*3.0*o.G/qtr nstr := tsr.SQ2by3 * qtr // norm(str) for i := 0; i < o.Nsig; i++ { o.ten[i] = (σ[i] + p*tsr.Im[i]) / (m * nstr) // ten := unit(str) = snew / (m * nstr) } hp := 3.0*o.G + o.H a1 := o.K b2 := 6.0 * o.G * o.G * (Δγ/qtr - 1.0/hp) for i := 0; i < o.Nsig; i++ { for j := 0; j < o.Nsig; j++ { D[i][j] = 2.0*o.G*m*tsr.Psd[i][j] + a1*tsr.Im[i]*tsr.Im[j] + b2*o.ten[i]*o.ten[j] } } return }
// Update updates stresses for given strains func (o *DruckerPrager) Update(s *State, ε, Δε []float64, eid, ipid int, time float64) (err error) { // set flags s.Loading = false // => not elastoplastic s.ApexReturn = false // => not return-to-apex s.Dgam = 0 // Δγ := 0 // accessors σ := s.Sig α0 := &s.Alp[0] // copy of α0 at beginning of step α0ini := *α0 // trial stress var devΔε_i float64 trΔε := Δε[0] + Δε[1] + Δε[2] for i := 0; i < o.Nsig; i++ { devΔε_i = Δε[i] - trΔε*tsr.Im[i]/3.0 o.ten[i] = σ[i] + o.K*trΔε*tsr.Im[i] + 2.0*o.G*devΔε_i // ten := σtr } ptr, qtr := tsr.M_p(o.ten), tsr.M_q(o.ten) // trial yield function ftr := qtr - o.M*ptr - o.qy0 - o.H*(*α0) // elastic update if ftr <= 0.0 { copy(σ, o.ten) // σ := ten = σtr return } // elastoplastic update var str_i float64 hp := 3.0*o.G + o.K*o.M*o.Mb + o.H s.Dgam = ftr / hp *α0 += s.Dgam pnew := ptr + s.Dgam*o.K*o.Mb m := 1.0 - s.Dgam*3.0*o.G/qtr for i := 0; i < o.Nsig; i++ { str_i = o.ten[i] + ptr*tsr.Im[i] σ[i] = m*str_i - pnew*tsr.Im[i] } s.Loading = true // check for apex singularity acone := qtr - s.Dgam*3.0*o.G if acone < 0 { s.Dgam = (-o.M*ptr - o.qy0 - o.H*α0ini) / (3.0*o.K*o.M + o.H) *α0 = α0ini + s.Dgam pnew = ptr + s.Dgam*3.0*o.K for i := 0; i < o.Nsig; i++ { σ[i] = -pnew * tsr.Im[i] } s.ApexReturn = true } return }
// CalcD computes D = dσ_new/dε_new consistent with StressUpdate func (o *DruckerPrager) CalcD(D [][]float64, s *State, firstIt bool) (err error) { // set first Δγ if firstIt { s.Dgam = 0 } // elastic if !s.Loading { return o.SmallElasticity.CalcD(D, s) } // return to apex if s.ApexReturn { a1 := o.K * o.H / (3.0*o.K*o.M + o.H) for i := 0; i < o.Nsig; i++ { for j := 0; j < o.Nsig; j++ { D[i][j] = a1 * tsr.Im[i] * tsr.Im[j] } } return } // elastoplastic => consistent stiffness σ := s.Sig Δγ := s.Dgam p, q := tsr.M_p(σ), tsr.M_q(σ) qtr := q + Δγ*3.0*o.G m := 1.0 - Δγ*3.0*o.G/qtr nstr := tsr.SQ2by3 * qtr // norm(str) for i := 0; i < o.Nsig; i++ { o.ten[i] = (σ[i] + p*tsr.Im[i]) / (m * nstr) // ten := unit(str) = snew / (m * nstr) } hp := 3.0*o.G + o.K*o.M*o.Mb + o.H a1 := o.K - o.K*o.K*o.Mb*o.M/hp a2 := -2.0 * o.G * o.K * o.Mb * tsr.SQ3by2 / hp b1 := -tsr.SQ6 * o.G * o.M * o.K / hp b2 := 6.0 * o.G * o.G * (Δγ/qtr - 1.0/hp) for i := 0; i < o.Nsig; i++ { for j := 0; j < o.Nsig; j++ { D[i][j] = 2.0*o.G*m*tsr.Psd[i][j] + a1*tsr.Im[i]*tsr.Im[j] + a2*tsr.Im[i]*o.ten[j] + b1*o.ten[i]*tsr.Im[j] + b2*o.ten[i]*o.ten[j] } } return }
// Update updates stresses for given strains func (o *VonMises) Update(s *State, ε, Δε []float64, eid, ipid int, time float64) (err error) { // set flags s.Loading = false // => not elastoplastic s.ApexReturn = false // => not return-to-apex s.Dgam = 0 // Δγ := 0 // accessors σ := s.Sig α0 := &s.Alp[0] // trial stress var devΔε_i float64 trΔε := Δε[0] + Δε[1] + Δε[2] for i := 0; i < o.Nsig; i++ { devΔε_i = Δε[i] - trΔε*tsr.Im[i]/3.0 o.ten[i] = σ[i] + o.K*trΔε*tsr.Im[i] + 2.0*o.G*devΔε_i // ten := σtr } ptr, qtr := tsr.M_p(o.ten), tsr.M_q(o.ten) // trial yield function ftr := qtr - o.qy0 - o.H*(*α0) // elastic update if ftr <= 0.0 { copy(σ, o.ten) // σ := ten = σtr return } // elastoplastic update var str_i float64 hp := 3.0*o.G + o.H s.Dgam = ftr / hp *α0 += s.Dgam pnew := ptr m := 1.0 - s.Dgam*3.0*o.G/qtr for i := 0; i < o.Nsig; i++ { str_i = o.ten[i] + ptr*tsr.Im[i] σ[i] = m*str_i - pnew*tsr.Im[i] } s.Loading = true return }
func (o *Plotter) Plot_p_q(x, y []float64, res []*State, sts [][]float64, last bool) { // stress path nr := len(res) k := nr - 1 var xmi, xma, ymi, yma float64 for i := 0; i < nr; i++ { x[i], y[i] = o.P[i], o.Q[i] if o.Multq { mult := fun.Sign(o.W[i]) y[i] *= mult } if o.UseOct { x[i] *= tsr.SQ3 y[i] *= tsr.SQ2by3 } if i == 0 { xmi, xma = x[i], x[i] ymi, yma = y[i], y[i] } else { xmi = min(xmi, x[i]) xma = max(xma, x[i]) ymi = min(ymi, y[i]) yma = max(yma, y[i]) } if o.SMPon { x[i], y[i], _ = tsr.M_pq_smp(res[i].Sig, o.SMPa, o.SMPb, o.SMPβ, o.SMPϵ) } } plt.Plot(x, y, io.Sf("'r.', ls='%s', clip_on=0, color='%s', marker='%s', label=r'%s'", o.Ls, o.Clr, o.Mrk, o.Lbl)) plt.PlotOne(x[0], y[0], io.Sf("'bo', clip_on=0, color='%s', marker='%s', ms=%d", o.SpClr, o.SpMrk, o.SpMs)) plt.PlotOne(x[k], y[k], io.Sf("'bs', clip_on=0, color='%s', marker='%s', ms=%d", o.SpClr, o.EpMrk, o.EpMs)) // yield surface if o.WithYs && o.m != nil { mx, my := 1.0, 1.0 if o.UseOct { mx, my = tsr.SQ3, tsr.SQ2by3 } if o.UsePmin { xmi = min(xmi, o.Pmin*mx) } if o.UsePmax { xma = max(xma, o.Pmax*mx) yma = max(yma, o.Pmax*my) } xmi, xma, ymi, yma = o.fix_range(xmi, xmi, xma, ymi, yma) if o.PqLims != nil { xmi, xma, ymi, yma = o.PqLims[0], o.PqLims[1], o.PqLims[2], o.PqLims[3] } //io.Pforan("xmi,xma ymi,yma = %v,%v %v,%v\n", xmi,xma, ymi,yma) dx := (xma - xmi) / float64(o.NptsPq-1) dy := (yma - ymi) / float64(o.NptsPq-1) xx := la.MatAlloc(o.NptsPq, o.NptsPq) yy := la.MatAlloc(o.NptsPq, o.NptsPq) za := la.MatAlloc(o.NptsPq, o.NptsPq) zb := la.MatAlloc(o.NptsPq, o.NptsPq) var p, q, σa, σb, σc, λ0, λ1, λ2 float64 v := NewState(len(res[0].Sig), len(res[0].Alp), false, len(res[0].EpsE) > 0) for k := 0; k < nr; k++ { copy(v.Alp, res[k].Alp) v.Dgam = res[k].Dgam for i := 0; i < o.NptsPq; i++ { for j := 0; j < o.NptsPq; j++ { xx[i][j] = xmi + float64(i)*dx yy[i][j] = ymi + float64(j)*dy p, q = xx[i][j], yy[i][j] if o.UseOct { p /= tsr.SQ3 q /= tsr.SQ2by3 } σa, σb, σc = tsr.PQW2O(p, q, o.W[k]) λ0, λ1, λ2 = tsr.O2L(σa, σb, σc) v.Sig[0], v.Sig[1], v.Sig[2] = λ0, λ1, λ2 ys := o.m.YieldFuncs(v) za[i][j] = ys[0] if o.nsurf > 1 { zb[i][j] = ys[1] } if o.SMPon { xx[i][j], yy[i][j], _ = tsr.M_pq_smp(v.Sig, o.SMPa, o.SMPb, o.SMPβ, o.SMPϵ) } } } plt.ContourSimple(xx, yy, za, io.Sf("colors=['%s'], levels=[0], linestyles=['%s'], linewidths=[%g], clip_on=0", o.YsClr0, o.YsLs0, o.YsLw0)+o.ArgsYs) if o.nsurf > 1 { plt.ContourSimple(xx, yy, zb, io.Sf("colors=['%s'], levels=[0], linestyles=['%s'], linewidths=[%g], clip_on=0", o.YsClr1, o.YsLs1, o.YsLw1)+o.ArgsYs) } } } // predictor-corrector if len(o.PreCor) > 1 { var p, q, pnew, qnew float64 for i := 1; i < len(o.PreCor); i++ { p = tsr.M_p(o.PreCor[i-1]) q = tsr.M_q(o.PreCor[i-1]) pnew = tsr.M_p(o.PreCor[i]) qnew = tsr.M_q(o.PreCor[i]) if o.UseOct { p *= tsr.SQ3 pnew *= tsr.SQ3 q *= tsr.SQ2by3 qnew *= tsr.SQ2by3 } if o.SMPon { p, q, _ = tsr.M_pq_smp(o.PreCor[i-1], o.SMPa, o.SMPb, o.SMPβ, o.SMPϵ) pnew, qnew, _ = tsr.M_pq_smp(o.PreCor[i], o.SMPa, o.SMPb, o.SMPβ, o.SMPϵ) } if math.Abs(pnew-p) > 1e-10 || math.Abs(qnew-q) > 1e-10 { plt.Arrow(p, q, pnew, qnew, io.Sf("sc=%d, fc='%s', ec='%s'", o.ArrWid, o.ClrPC, o.ClrPC)) } } } // settings if last { plt.Equal() xl, yl := "$p_{cam}$", "$q_{cam}$" if o.UseOct { xl, yl = "$p_{oct}$", "$q_{oct}$" } if o.SMPon { xl, yl = "$p_{smp}$", "$q_{smp}$" } if o.AxLblX != "" { xl = o.AxLblX } if o.AxLblY != "" { yl = o.AxLblY } plt.Gll(xl, yl, "leg_out=1, leg_ncol=4, leg_hlen=1.5") if lims, ok := o.Lims["p,q"]; ok { plt.AxisLims(lims) } if lims, ok := o.Lims["p,q,ys"]; ok { plt.AxisLims(lims) } } }
// YieldFs computes the yield functions func (o DruckerPrager) YieldFuncs(s *State) []float64 { p, q := tsr.M_p(s.Sig), tsr.M_q(s.Sig) α0 := s.Alp[0] return []float64{q - o.M*p - o.qy0 - o.H*α0} }
// YieldFs computes the yield functions func (o VonMises) YieldFuncs(s *State) []float64 { q := tsr.M_q(s.Sig) α0 := s.Alp[0] return []float64{q - o.qy0 - o.H*α0} }