// adds element K to global Jacobian matrix Kb func (o ElemUP) AddToKb(Kb *la.Triplet, sol *Solution, firstIt bool) (ok bool) { // clear matrices ndim := Global.Ndim u_nverts := o.U.Shp.Nverts p_nverts := o.P.Shp.Nverts la.MatFill(o.P.Kpp, 0) for i := 0; i < o.U.Nu; i++ { for j := 0; j < o.P.Np; j++ { o.Kup[i][j] = 0 o.Kpu[j][i] = 0 } for j := 0; j < o.U.Nu; j++ { o.U.K[i][j] = 0 } } if o.P.DoExtrap { for i := 0; i < p_nverts; i++ { o.P.ρl_ex[i] = 0 for j := 0; j < p_nverts; j++ { o.P.dρldpl_ex[i][j] = 0 } for j := 0; j < o.U.Nu; j++ { o.dρldus_ex[i][j] = 0 } } } // for each integration point dc := Global.DynCoefs var coef, plt, klr, ρL, Cl, divvs float64 var ρl, ρ, Cpl, Cvs, dρdpl, dpdpl, dCpldpl, dCvsdpl, dklrdpl, dCpldusM, dρldusM, dρdusM float64 var r, c 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 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) ρL = o.P.States[idx].A_ρL Cl = o.P.Mdl.Cl if LogErr(o.P.Mdl.CalcLs(o.P.res, o.P.States[idx], o.P.pl, o.divus, true), "AddToKb") { return } ρl = o.P.res.A_ρl ρ = o.P.res.A_ρ Cpl = o.P.res.Cpl Cvs = o.P.res.Cvs dρdpl = o.P.res.Dρdpl dpdpl = o.P.res.Dpdpl dCpldpl = o.P.res.DCpldpl dCvsdpl = o.P.res.DCvsdpl dklrdpl = o.P.res.Dklrdpl dCpldusM = o.P.res.DCpldusM dρldusM = o.P.res.DρldusM dρdusM = o.P.res.DρdusM // Kpu, Kup and Kpp for n := 0; n < p_nverts; n++ { for j := 0; j < ndim; j++ { // Kpu := ∂Rl^n/∂us^m and Kup := ∂Rus^m/∂pl^n; see Eq (47) of [1] for m := 0; m < u_nverts; m++ { c = j + m*ndim // add ∂rlb/∂us^m: Eqs (A.3) and (A.6) of [1] o.Kpu[n][c] += coef * Sb[n] * (dCpldusM*plt + dc.α4*Cvs) * G[m][j] // add ∂(ρl.wl)/∂us^m: Eq (A.8) of [1] for i := 0; i < ndim; i++ { o.Kpu[n][c] += coef * Gb[n][i] * S[m] * dc.α1 * ρL * klr * o.P.Mdl.Klsat[i][j] } // add ∂rl/∂pl^n and ∂p/∂pl^n: Eqs (A.9) and (A.11) of [1] o.Kup[c][n] += coef * (S[m]*Sb[n]*dρdpl*o.bs[j] - G[m][j]*Sb[n]*dpdpl) // for seepage face if o.P.DoExtrap { o.dρldus_ex[n][c] += o.P.Emat[n][idx] * dρldusM * G[m][j] } } // term in brackets in Eq (A.7) of [1] o.P.tmp[j] = Sb[n]*dklrdpl*o.hl[j] - klr*(Sb[n]*Cl*o.bs[j]+Gb[n][j]) } // Kpp := ∂Rl^m/∂pl^n; see Eq (47) of [1] for m := 0; m < p_nverts; m++ { // add ∂rlb/dpl^n: Eq (A.5) of [1] o.P.Kpp[m][n] += coef * Sb[m] * Sb[n] * (dCpldpl*plt + dCvsdpl*divvs + dc.β1*Cpl) // add ∂(ρl.wl)/∂us^m: Eq (A.7) of [1] for i := 0; i < ndim; i++ { for j := 0; j < ndim; j++ { o.P.Kpp[m][n] -= coef * Gb[m][i] * o.P.Mdl.Klsat[i][j] * o.P.tmp[j] } } // inner summation term in Eq (22) of [2] if o.P.DoExtrap { o.P.dρldpl_ex[m][n] += o.P.Emat[m][idx] * Cpl * Sb[n] } } // Eq. (19) of [2] if o.P.DoExtrap { o.P.ρl_ex[n] += o.P.Emat[n][idx] * ρl } } // Kuu: add ∂rub^m/∂us^n; see Eqs (47) and (A.10) of [1] for m := 0; m < u_nverts; m++ { for i := 0; i < ndim; i++ { r = i + m*ndim for n := 0; n < u_nverts; n++ { for j := 0; j < ndim; j++ { c = j + n*ndim o.U.K[r][c] += coef * S[m] * (S[n]*dc.α1*ρ*tsr.It[i][j] + dρdusM*o.bs[i]*G[n][j]) } } } } // consistent tangent model matrix if LogErr(o.U.MdlSmall.CalcD(o.U.D, o.U.States[idx], firstIt), "AddToKb") { return } // Kuu: add stiffness term ∂(σe・G^m)/∂us^n if o.U.UseB { IpBmatrix(o.U.B, ndim, u_nverts, G, radius, S) la.MatTrMulAdd3(o.U.K, coef, o.U.B, o.U.D, o.U.B) // K += coef * tr(B) * D * B } else { IpAddToKt(o.U.K, u_nverts, ndim, coef, G, o.U.D) } } // contribution from natural boundary conditions if o.P.HasSeep { if !o.P.add_natbcs_to_jac(sol) { return } if !o.add_natbcs_to_jac(sol) { return } } // add K to sparse matrix Kb // _ _ // | Kuu Kup 0 | // | Kpu Kpp Kpf | // |_ Kfu Kfp Kff _| // for i, I := range o.P.Pmap { for j, J := range o.P.Pmap { Kb.Put(I, J, o.P.Kpp[i][j]) } for j, J := range o.P.Fmap { Kb.Put(I, J, o.P.Kpf[i][j]) Kb.Put(J, I, o.P.Kfp[j][i]) } for j, J := range o.U.Umap { Kb.Put(I, J, o.Kpu[i][j]) Kb.Put(J, I, o.Kup[j][i]) } } for i, I := range o.P.Fmap { for j, J := range o.P.Fmap { Kb.Put(I, J, o.P.Kff[i][j]) } } for i, I := range o.U.Umap { for j, J := range o.U.Umap { Kb.Put(I, J, o.U.K[i][j]) } } return true }
// AddToKb adds element K to global Jacobian matrix Kb func (o *ElemU) AddToKb(Kb *la.Triplet, sol *Solution, firstIt bool) (ok bool) { // zero K matrix la.MatFill(o.K, 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 } // check Jacobian if o.Shp.J < 0 { LogErrCond(true, "ElemU: eid=%d: Jacobian is negative = %g\n", o.Id(), o.Shp.J) return } // auxiliary coef := o.Shp.J * ip.W * o.Thickness S := o.Shp.S G := o.Shp.G // consistent tangent model matrix if LogErr(o.MdlSmall.CalcD(o.D, o.States[idx], firstIt), "AddToKb") { return } // add contribution to consistent tangent matrix 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.MatTrMulAdd3(o.K, coef, o.B, o.D, o.B) // K += coef * tr(B) * D * B } else { IpAddToKt(o.K, nverts, ndim, coef, G, o.D) } // dynamic term if !Global.Sim.Data.Steady { for m := 0; m < nverts; m++ { for i := 0; i < ndim; i++ { r := i + m*ndim for n := 0; n < nverts; n++ { c := i + n*ndim o.K[r][c] += coef * S[m] * S[n] * (o.Rho*dc.α1 + o.Cdam*dc.α4) } } } } } // add K to sparse matrix Kb for i, I := range o.Umap { for j, J := range o.Umap { Kb.Put(I, J, o.K[i][j]) } } return true }
// AddToKb adds element K to global Jacobian matrix Kb func (o *ElemU) AddToKb(Kb *la.Triplet, sol *Solution, firstIt bool) (err error) { // zero K matrix la.MatFill(o.K, 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 } // check Jacobian if o.Cell.Shp.J < 0 { return chk.Err("ElemU: eid=%d: Jacobian is negative = %g\n", o.Id(), o.Cell.Shp.J) } // auxiliary coef := o.Cell.Shp.J * ip[3] * o.Thickness S := o.Cell.Shp.S G := o.Cell.Shp.G // consistent tangent model matrix err = o.MdlSmall.CalcD(o.D, o.States[idx], firstIt) if err != nil { return } // add contribution to consistent tangent matrix 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.MatTrMulAdd3(o.K, coef, o.B, o.D, o.B) // K += coef * tr(B) * D * B } else { IpAddToKt(o.K, nverts, o.Ndim, coef, G, o.D) } // 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 := i + m*o.Ndim for n := 0; n < nverts; n++ { c := i + n*o.Ndim o.K[r][c] += coef * S[m] * S[n] * (o.Rho*α1 + o.Cdam*α4) } } } } } // add Ks to sparse matrix Kb switch { case o.HasContact: err = o.contact_add_to_jac(Kb, sol) case o.Xfem: err = o.xfem_add_to_jac(Kb, sol) default: for i, I := range o.Umap { for j, J := range o.Umap { Kb.Put(I, J, o.K[i][j]) } } } return }