// AddToRhs adds -R to global residual vector fb func (o *ElemU) AddToRhs(fb []float64, sol *Solution) (ok bool) { // clear fi vector if using B matrix if o.UseB { la.VecFill(o.fi, 0) } // for each integration point dc := Global.DynCoefs ndim := Global.Ndim nverts := o.Shp.Nverts for idx, ip := range o.IpsElem { // interpolation functions, gradients and variables @ ip if !o.ipvars(idx, sol) { return } // auxiliary coef := o.Shp.J * ip.W * o.Thickness S := o.Shp.S G := o.Shp.G // add internal forces to fb if o.UseB { radius := 1.0 if Global.Sim.Data.Axisym { radius = o.Shp.AxisymGetRadius(o.X) coef *= radius } IpBmatrix(o.B, ndim, nverts, G, radius, S) la.MatTrVecMulAdd(o.fi, coef, o.B, o.States[idx].Sig) // fi += coef * tr(B) * σ } else { for m := 0; m < nverts; m++ { for i := 0; i < ndim; i++ { r := o.Umap[i+m*ndim] for j := 0; j < ndim; j++ { fb[r] -= coef * tsr.M2T(o.States[idx].Sig, i, j) * G[m][j] // -fi } } } } // dynamic term if !Global.Sim.Data.Steady { for m := 0; m < nverts; m++ { for i := 0; i < ndim; i++ { r := o.Umap[i+m*ndim] fb[r] -= coef * S[m] * (o.Rho*(dc.α1*o.us[i]-o.ζs[idx][i]-o.grav[i]) + o.Cdam*(dc.α4*o.us[i]-o.χs[idx][i])) // -RuBar } } } } // assemble fb if using B matrix if o.UseB { for i, I := range o.Umap { fb[I] -= o.fi[i] } } // external forces return o.add_surfloads_to_rhs(fb, sol) }
// Update perform (tangent) update func (o *Rjoint) Update(sol *Solution) (err error) { // auxiliary nsig := 2 * o.Ndim rodH := o.Rod.Cell.Shp rodS := rodH.S rodNn := rodH.Nverts sldH := o.Sld.Cell.Shp sldNn := sldH.Nverts // extrapolate stresses at integration points of solid element to its nodes if o.Coulomb { la.MatFill(o.σNo, 0) for idx, _ := range o.Sld.IpsElem { σ := o.Sld.States[idx].Sig for i := 0; i < nsig; i++ { for m := 0; m < sldNn; m++ { o.σNo[m][i] += o.Emat[m][idx] * σ[i] } } } } // interpolate Δu of solid to find ΔuC @ rod node; Eq (30) var r, I int for m := 0; m < rodNn; m++ { for i := 0; i < o.Ndim; i++ { o.ΔuC[m][i] = 0 for n := 0; n < sldNn; n++ { r = i + n*o.Ndim I = o.Sld.Umap[r] o.ΔuC[m][i] += o.Nmat[n][m] * sol.ΔY[I] // Eq (30) } } } // loop over ips of rod var Δwb0, Δwb1, Δwb2, σc float64 for idx, ip := range o.Rod.IpsElem { // auxiliary e0, e1, e2 := o.e0[idx], o.e1[idx], o.e2[idx] // interpolation functions and gradients err = rodH.CalcAtIp(o.Rod.X, ip, true) if err != nil { return } // interpolated relative displacements @ ip of join; Eqs (31) and (32) for i := 0; i < o.Ndim; i++ { o.Δw[i] = 0 for m := 0; m < rodNn; m++ { r = i + m*o.Ndim I = o.Rod.Umap[r] o.Δw[i] += rodS[m] * (o.ΔuC[m][i] - sol.ΔY[I]) // Eq (31) and (32) } } // relative displacents in the coratational system Δwb0, Δwb1, Δwb2 = 0, 0, 0 for i := 0; i < o.Ndim; i++ { Δwb0 += e0[i] * o.Δw[i] Δwb1 += e1[i] * o.Δw[i] Δwb2 += e2[i] * o.Δw[i] } // new confining stress σc = 0.0 if o.Coulomb { // calculate σIp for j := 0; j < nsig; j++ { o.σIp[j] = 0 for n := 0; n < sldNn; n++ { o.σIp[j] += o.Pmat[n][idx] * o.σNo[n][j] } } // calculate t1 and t2 for i := 0; i < o.Ndim; i++ { o.t1[i], o.t2[i] = 0, 0 for j := 0; j < o.Ndim; j++ { o.t1[i] += tsr.M2T(o.σIp, i, j) * e1[j] o.t2[i] += tsr.M2T(o.σIp, i, j) * e2[j] } } // calculate p1, p2 and σcNew p1, p2 := 0.0, 0.0 for i := 0; i < o.Ndim; i++ { p1 += o.t1[i] * e1[i] p2 += o.t2[i] * e2[i] } // σcNew σc = -(p1 + p2) / 2.0 } // update model err = o.Mdl.Update(o.States[idx], σc, Δwb0) if err != nil { return } o.States[idx].Phi[0] += o.k1 * Δwb1 // qn1 o.States[idx].Phi[1] += o.k2 * Δwb2 // qn2 // debugging //if true { if false { o.debug_update(idx, Δwb0, Δwb1, Δwb2, σc) } } return }
// adds -R to global residual vector fb func (o ElemUP) AddToRhs(fb []float64, sol *Solution) (ok bool) { // clear variables if o.P.DoExtrap { la.VecFill(o.P.ρl_ex, 0) } if o.U.UseB { la.VecFill(o.U.fi, 0) } // for each integration point dc := Global.DynCoefs ndim := Global.Ndim u_nverts := o.U.Shp.Nverts p_nverts := o.P.Shp.Nverts var coef, plt, klr, ρl, ρ, p, Cpl, Cvs, divvs float64 var r int for idx, ip := range o.U.IpsElem { // interpolation functions, gradients and variables @ ip if !o.ipvars(idx, sol) { return } coef = o.U.Shp.J * ip.W S := o.U.Shp.S G := o.U.Shp.G Sb := o.P.Shp.S Gb := o.P.Shp.G // axisymmetric case radius := 1.0 if Global.Sim.Data.Axisym { radius = o.U.Shp.AxisymGetRadius(o.U.X) coef *= radius } // auxiliary σe := o.U.States[idx].Sig divvs = dc.α4*o.divus - o.U.divχs[idx] // divergence of Eq. (35a) [1] // tpm variables plt = dc.β1*o.P.pl - o.P.ψl[idx] // Eq. (35c) [1] klr = o.P.Mdl.Cnd.Klr(o.P.States[idx].A_sl) if LogErr(o.P.Mdl.CalcLs(o.P.res, o.P.States[idx], o.P.pl, o.divus, false), "AddToRhs") { return } ρl = o.P.res.A_ρl ρ = o.P.res.A_ρ p = o.P.res.A_p Cpl = o.P.res.Cpl Cvs = o.P.res.Cvs // compute ρwl. see Eq (34b) and (35) of [1] for i := 0; i < ndim; i++ { o.P.ρwl[i] = 0 for j := 0; j < ndim; j++ { o.P.ρwl[i] += klr * o.P.Mdl.Klsat[i][j] * o.hl[j] } } // p: add negative of residual term to fb; see Eqs. (38a) and (45a) of [1] for m := 0; m < p_nverts; m++ { r = o.P.Pmap[m] fb[r] -= coef * Sb[m] * (Cpl*plt + Cvs*divvs) for i := 0; i < ndim; i++ { fb[r] += coef * Gb[m][i] * o.P.ρwl[i] // += coef * div(ρl*wl) } if o.P.DoExtrap { // Eq. (19) of [2] o.P.ρl_ex[m] += o.P.Emat[m][idx] * ρl } } // u: add negative of residual term to fb; see Eqs. (38b) and (45b) [1] if o.U.UseB { IpBmatrix(o.U.B, ndim, u_nverts, G, radius, S) la.MatTrVecMulAdd(o.U.fi, coef, o.U.B, σe) // fi += coef * tr(B) * σ for m := 0; m < u_nverts; m++ { for i := 0; i < ndim; i++ { r = o.U.Umap[i+m*ndim] fb[r] -= coef * S[m] * ρ * o.bs[i] fb[r] += coef * p * G[m][i] } } } else { for m := 0; m < u_nverts; m++ { for i := 0; i < ndim; i++ { r = o.U.Umap[i+m*ndim] fb[r] -= coef * S[m] * ρ * o.bs[i] for j := 0; j < ndim; j++ { fb[r] -= coef * tsr.M2T(σe, i, j) * G[m][j] } fb[r] += coef * p * G[m][i] } } } } // add fi term to fb, if using B matrix if o.U.UseB { for i, I := range o.U.Umap { fb[I] -= o.U.fi[i] } } // external forces if len(o.U.NatBcs) > 0 { if !o.U.add_surfloads_to_rhs(fb, sol) { return } } // contribution from natural boundary conditions if len(o.P.NatBcs) > 0 { return o.P.add_natbcs_to_rhs(fb, sol) } return true }
// AddToRhs adds -R to global residual vector fb func (o *ElemU) AddToRhs(fb []float64, sol *Solution) (err error) { // clear fi vector if using B matrix if o.UseB { la.VecFill(o.fi, 0) } // for each integration point nverts := o.Cell.Shp.Nverts for idx, ip := range o.IpsElem { // interpolation functions, gradients and variables @ ip err = o.ipvars(idx, sol) if err != nil { return } // auxiliary coef := o.Cell.Shp.J * ip[3] * o.Thickness S := o.Cell.Shp.S G := o.Cell.Shp.G // add internal forces to fb if o.UseB { radius := 1.0 if sol.Axisym { radius = o.Cell.Shp.AxisymGetRadius(o.X) coef *= radius } IpBmatrix(o.B, o.Ndim, nverts, G, radius, S, sol.Axisym) la.MatTrVecMulAdd(o.fi, coef, o.B, o.States[idx].Sig) // fi += coef * tr(B) * σ } else { for m := 0; m < nverts; m++ { for i := 0; i < o.Ndim; i++ { r := o.Umap[i+m*o.Ndim] for j := 0; j < o.Ndim; j++ { fb[r] -= coef * tsr.M2T(o.States[idx].Sig, i, j) * G[m][j] // -fi } } } } // dynamic term if !sol.Steady { α1 := sol.DynCfs.α1 α4 := sol.DynCfs.α4 for m := 0; m < nverts; m++ { for i := 0; i < o.Ndim; i++ { r := o.Umap[i+m*o.Ndim] fb[r] -= coef * S[m] * (o.Rho*(α1*o.us[i]-o.ζs[idx][i]-o.grav[i]) + o.Cdam*(α4*o.us[i]-o.χs[idx][i])) // -RuBar } } } } // assemble fb if using B matrix if o.UseB { for i, I := range o.Umap { fb[I] -= o.fi[i] } } // external forces err = o.add_surfloads_to_rhs(fb, sol) if err != nil { return } // contact: additional term to fb err = o.contact_add_to_rhs(fb, sol) // xfem: additional term to fb err = o.xfem_add_to_rhs(fb, sol) return }