// Ureset fixes internal variables after u (displacements) have been zeroed func (o *ElemU) Ureset(sol *Solution) (ok bool) { for idx, _ := range o.IpsElem { if len(o.States[idx].F) > 0 { la.MatFill(o.States[idx].F, 0) la.MatFill(o.StatesBkp[idx].F, 0) } } return true }
// AddToKb adds element K to global Jacobian matrix Kb func (o *Rod) AddToKb(Kb *la.Triplet, sol *Solution, firstIt bool) (err error) { // zero K matrix la.MatFill(o.K, 0) la.MatFill(o.M, 0) // TODO: implement mass matrix // for each integration point var E float64 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 := ip[3] Jvec := o.Cell.Shp.Jvec3d G := o.Cell.Shp.Gvec J := o.Cell.Shp.J // add contribution to consistent tangent matrix for m := 0; m < nverts; m++ { for n := 0; n < nverts; n++ { for i := 0; i < o.Ndim; i++ { for j := 0; j < o.Ndim; j++ { r := i + m*o.Ndim c := j + n*o.Ndim E, err = o.Model.CalcD(o.States[idx], firstIt) if err != nil { return } o.K[r][c] += coef * o.A * E * G[m] * G[n] * Jvec[i] * Jvec[j] / J } } } } } // 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 }
// adds element K to global Jacobian matrix Kb func (o Rod) AddToKb(Kb *la.Triplet, sol *Solution, firstIt bool) (ok bool) { // zero K matrix la.MatFill(o.K, 0) la.MatFill(o.M, 0) // for each integration point nverts := o.Shp.Nverts ndim := Global.Ndim for idx, ip := range o.IpsElem { // interpolation functions, gradients and variables @ ip if !o.ipvars(idx, sol) { return } // auxiliary coef := ip.W Jvec := o.Shp.Jvec3d G := o.Shp.Gvec J := o.Shp.J // add contribution to consistent tangent matrix for m := 0; m < nverts; m++ { for n := 0; n < nverts; n++ { for i := 0; i < ndim; i++ { for j := 0; j < ndim; j++ { r := i + m*ndim c := j + n*ndim E, err := o.Model.CalcD(o.States[idx], firstIt) if LogErr(err, "AddToKb") { return } o.K[r][c] += coef * o.A * E * G[m] * G[n] * Jvec[i] * Jvec[j] / J } } } } } // 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 }
// CalcD computes D = dσ_new/dε_new (consistent) func (o SmallElasticity) CalcD(D [][]float64, s *State) (err error) { if o.Pse { if o.Nsig != 4 { return chk.Err("for plane-stress analyses, D must be 4x4. nsig = %d is incorrect.\n", o.Nsig) } if o.Kgc != nil { return chk.Err("plane-stress analysis does not work with nonlinear K and G\n") } c := o.E / (1.0 - o.Nu*o.Nu) la.MatFill(D, 0) D[0][0] = c D[0][1] = c * o.Nu D[1][0] = c * o.Nu D[1][1] = c D[3][3] = c * (1.0 - o.Nu) return } if o.Kgc != nil { o.K, o.G = o.Kgc.Calc(s) } for i := 0; i < o.Nsig; i++ { for j := 0; j < o.Nsig; j++ { D[i][j] = o.K*tsr.Im[i]*tsr.Im[j] + 2*o.G*tsr.Psd[i][j] } } return }
// Extrapolator computes the extrapolation matrix for this Shape with a combination of integration points 'ips' // Note: E[nverts][nip] must be pre-allocated func (o *Shape) Extrapolator(E [][]float64, ips []*Ipoint) (err error) { la.MatFill(E, 0) nip := len(ips) N := o.GetShapeMatAtIps(ips) if nip < o.Nverts { ξ := o.GetNodesNatCoordsMat() ξh := o.GetIpsNatCoordsMat(ips) ξhi := la.MatAlloc(o.Gndim+1, nip) Ni := la.MatAlloc(o.Nverts, nip) err = la.MatInvG(Ni, N, 1e-10) if err != nil { return } err = la.MatInvG(ξhi, ξh, 1e-10) if err != nil { return } ξhξhI := la.MatAlloc(nip, nip) // ξh * inv(ξh) for k := 0; k < o.Gndim+1; k++ { for j := 0; j < nip; j++ { for i := 0; i < nip; i++ { ξhξhI[i][j] += ξh[i][k] * ξhi[k][j] } for i := 0; i < o.Nverts; i++ { E[i][j] += ξ[i][k] * ξhi[k][j] // ξ * inv(ξh) } } } for i := 0; i < o.Nverts; i++ { for j := 0; j < nip; j++ { for k := 0; k < nip; k++ { I_kj := 0.0 if j == k { I_kj = 1.0 } E[i][j] += Ni[i][k] * (I_kj - ξhξhI[k][j]) } } } } else { err = la.MatInvG(E, N, 1e-10) if err != nil { return } } return }
// AddToKb adds element K to global Jacobian matrix Kb func (o *ElemPhi) AddToKb(Kb *la.Triplet, sol *Solution, firstIt bool) (err error) { // auxiliary nverts := o.Cell.Shp.Nverts // zero K matrix la.MatFill(o.K, 0) dt := sol.Dt * 2 // for each integration point for iip, ip := range o.IpsElem { // interpolation functions and gradients err = o.Cell.Shp.CalcAtIp(o.X, ip, true) if err != nil { return } // auxiliary variables coef := o.Cell.Shp.J * ip[3] S := o.Cell.Shp.S G := o.Cell.Shp.G // add to right hand side vector for m := 0; m < nverts; m++ { for n := 0; n < nverts; n++ { o.K[m][n] -= coef * (S[m]*S[n] + dt*dt/6.0*(o.v_0[iip][0]*G[m][0]+o.v_0[iip][1]*G[m][1])*(o.v_0[iip][0]*G[n][0]+o.v_0[iip][1]*G[n][1])) / dt } } } // 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 }
// AddToKb adds element K to global Jacobian matrix Kb func (o *ElemPhi) AddToKb(Kb *la.Triplet, sol *Solution, firstIt bool) (ok bool) { // auxiliary β1 := Global.DynCoefs.β1 nverts := o.Shp.Nverts // zero K matrix la.MatFill(o.K, 0) // for each integration point for _, ip := range o.IpsElem { // interpolation functions and gradients if LogErr(o.Shp.CalcAtIp(o.X, ip, true), "InterpStarVars") { return } // auxiliary variables coef := o.Shp.J * ip.W S := o.Shp.S // add to right hand side vector for m := 0; m < nverts; m++ { for n := 0; n < nverts; n++ { o.K[m][n] += coef * S[m] * S[n] * β1 } } } // 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) (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 }
// 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 }
// add_natbcs_to_jac adds contribution from natural boundary conditions to Jacobian func (o ElemP) add_natbcs_to_jac(sol *Solution) (ok bool) { // clear matrices if o.HasSeep { for i := 0; i < o.Np; i++ { for j := 0; j < o.Nf; j++ { o.Kpf[i][j] = 0 o.Kfp[j][i] = 0 } } la.MatFill(o.Kff, 0) } // compute surface integral nverts := o.Shp.Nverts var shift float64 var ρl, pl, fl, plmax, g, rmp, rmpD float64 var drxdpl, drxdfl, drfdpl, drfdfl float64 for idx, nbc := range o.NatBcs { // plmax shift shift = nbc.Fcn.F(sol.T, nil) // loop over ips of face for jdx, ipf := range o.IpsFace { // interpolation functions and gradients @ face iface := nbc.IdxFace if LogErr(o.Shp.CalcAtFaceIp(o.X, ipf, iface), "add_natbcs_to_jac") { return } Sf := o.Shp.Sf Jf := la.VecNorm(o.Shp.Fnvec) coef := ipf.W * Jf // select natural boundary condition type switch nbc.Key { case "seep": // variables extrapolated to face ρl, pl, fl = o.fipvars(iface, sol) plmax = o.Plmax[idx][jdx] - shift if plmax < 0 { plmax = 0 } // compute derivatives g = pl - plmax // Eq. (24) rmp = o.ramp(fl + o.κ*g) rmpD = o.rampD1(fl + o.κ*g) drxdpl = ρl * o.κ * rmpD // first term in Eq. (A.4) (without Sn) drxdfl = ρl * rmpD // Eq. (A.5) (without Sn) drfdpl = -o.κ * rmpD // Eq. (A.6) (corrected with κ and without Sn) drfdfl = 1.0 - rmpD // Eq. (A.7) (without Sn) for i, m := range o.Shp.FaceLocalV[iface] { μ := o.Vid2seepId[m] for j, n := range o.Shp.FaceLocalV[iface] { ν := o.Vid2seepId[n] o.Kpp[m][n] += coef * Sf[i] * Sf[j] * drxdpl o.Kpf[m][ν] += coef * Sf[i] * Sf[j] * drxdfl o.Kfp[μ][n] += coef * Sf[i] * Sf[j] * drfdpl o.Kff[μ][ν] += coef * Sf[i] * Sf[j] * drfdfl } for n := 0; n < nverts; n++ { // Eqs. (18) and (22) for l, r := range o.Shp.FaceLocalV[iface] { o.Kpp[m][n] += coef * Sf[i] * Sf[l] * o.dρldpl_ex[r][n] * rmp } } } } } } return true }
// AddToKb adds element K to global Jacobian matrix Kb func (o ElemP) AddToKb(Kb *la.Triplet, sol *Solution, firstIt bool) (ok bool) { // clear matrices la.MatFill(o.Kpp, 0) ndim := Global.Ndim nverts := o.Shp.Nverts if o.DoExtrap { for i := 0; i < nverts; i++ { o.ρl_ex[i] = 0 for j := 0; j < nverts; j++ { o.dρldpl_ex[i][j] = 0 } } } // for each integration point Cl := o.Mdl.Cl β1 := Global.DynCoefs.β1 var coef, plt, klr, ρL, ρl, Cpl, dCpldpl, dklrdpl float64 for idx, ip := range o.IpsElem { // interpolation functions, gradients and variables @ ip if !o.ipvars(idx, sol) { return } coef = o.Shp.J * ip.W S := o.Shp.S G := o.Shp.G // tpm variables plt = β1*o.pl - o.ψl[idx] klr = o.Mdl.Cnd.Klr(o.States[idx].A_sl) ρL = o.States[idx].A_ρL if LogErr(o.Mdl.CalcLs(o.res, o.States[idx], o.pl, 0, true), "AddToKb") { return } ρl = o.res.A_ρl Cpl = o.res.Cpl dCpldpl = o.res.DCpldpl dklrdpl = o.res.Dklrdpl // Kpp := dRpl/dpl. see Eqs. (18), (A.2) and (A.3) of [1] for n := 0; n < nverts; n++ { for j := 0; j < ndim; j++ { o.tmp[j] = S[n]*dklrdpl*(ρL*o.g[j]-o.gpl[j]) + klr*(S[n]*Cl*o.g[j]-G[n][j]) } for m := 0; m < nverts; m++ { o.Kpp[m][n] += coef * S[m] * S[n] * (dCpldpl*plt + β1*Cpl) for i := 0; i < ndim; i++ { for j := 0; j < ndim; j++ { o.Kpp[m][n] -= coef * G[m][i] * o.Mdl.Klsat[i][j] * o.tmp[j] } } if o.DoExtrap { // inner summation term in Eq. (22) o.dρldpl_ex[m][n] += o.Emat[m][idx] * Cpl * S[n] } } if o.DoExtrap { // Eq. (19) o.ρl_ex[n] += o.Emat[n][idx] * ρl } } } // add to Kb if o.HasSeep { // contribution from natural boundary conditions if !o.add_natbcs_to_jac(sol) { return } // add to sparse matrix Kb for i, I := range o.Pmap { for j, J := range o.Pmap { Kb.Put(I, J, o.Kpp[i][j]) } for j, J := range o.Fmap { Kb.Put(I, J, o.Kpf[i][j]) Kb.Put(J, I, o.Kfp[j][i]) } } for i, I := range o.Fmap { for j, J := range o.Fmap { Kb.Put(I, J, o.Kff[i][j]) } } } else { // add to sparse matrix Kb for i, I := range o.Pmap { for j, J := range o.Pmap { Kb.Put(I, J, o.Kpp[i][j]) } } } return true }
// 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 element K to global Jacobian matrix Kb func (o *Rjoint) AddToKb(Kb *la.Triplet, sol *Solution, firstIt bool) (err error) { // auxiliary rodH := o.Rod.Cell.Shp rodS := rodH.S rodNn := rodH.Nverts sldH := o.Sld.Cell.Shp sldNn := sldH.Nverts // zero K matrices for i, _ := range o.Rod.Umap { for j, _ := range o.Rod.Umap { o.Krr[i][j] = 0 } for j, _ := range o.Sld.Umap { o.Krs[i][j] = 0 o.Ksr[j][i] = 0 } } la.MatFill(o.Kss, 0) // auxiliary var coef float64 var DτDω float64 var Dwb0Du_nj, Dwb1Du_nj, Dwb2Du_nj float64 var DτDu_nj, DqbDu_nij float64 var Dwb0Dur_nj, Dwb1Dur_nj, Dwb2Dur_nj float64 var DqbDur_nij float64 // loop over rod's integration points 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 } coef = ip[3] * rodH.J // model derivatives DτDω, err = o.Mdl.CalcD(o.States[idx], firstIt) if err != nil { return } // compute derivatives for j := 0; j < o.Ndim; j++ { // Krr and Ksr; derivatives with respect to ur_nj for n := 0; n < rodNn; n++ { // ∂wb/∂ur Eq (A.4) Dwb0Dur_nj = -rodS[n] * e0[j] Dwb1Dur_nj = -rodS[n] * e1[j] Dwb2Dur_nj = -rodS[n] * e2[j] // compute ∂■/∂ur derivatives c := j + n*o.Ndim for i := 0; i < o.Ndim; i++ { // ∂qb/∂ur Eq (A.2) DqbDur_nij = o.h*e0[i]*(DτDω*Dwb0Dur_nj) + o.k1*e1[i]*Dwb1Dur_nj + o.k2*e2[i]*Dwb2Dur_nj // Krr := ∂fr/∂ur Eq (58) for m := 0; m < rodNn; m++ { r := i + m*o.Ndim o.Krr[r][c] -= coef * rodS[m] * DqbDur_nij } // Ksr := ∂fs/∂ur Eq (60) for m := 0; m < sldNn; m++ { r := i + m*o.Ndim for p := 0; p < rodNn; p++ { o.Ksr[r][c] += coef * o.Nmat[m][p] * rodS[p] * DqbDur_nij } } } } // Krs and Kss for n := 0; n < sldNn; n++ { // ∂wb/∂us Eq (A.5) Dwb0Du_nj, Dwb1Du_nj, Dwb2Du_nj = 0, 0, 0 for m := 0; m < rodNn; m++ { Dwb0Du_nj += rodS[m] * o.Nmat[n][m] * e0[j] Dwb1Du_nj += rodS[m] * o.Nmat[n][m] * e1[j] Dwb2Du_nj += rodS[m] * o.Nmat[n][m] * e2[j] } // ∂τ/∂us_nj hightlighted term in Eq (A.3) DτDu_nj = DτDω * Dwb0Du_nj // compute ∂■/∂us derivatives c := j + n*o.Ndim for i := 0; i < o.Ndim; i++ { // ∂qb/∂us Eq (A.3) DqbDu_nij = o.h*e0[i]*DτDu_nj + o.k1*e1[i]*Dwb1Du_nj + o.k2*e2[i]*Dwb2Du_nj // Krs := ∂fr/∂us Eq (59) for m := 0; m < rodNn; m++ { r := i + m*o.Ndim o.Krs[r][c] -= coef * rodS[m] * DqbDu_nij } // Kss := ∂fs/∂us Eq (61) for m := 0; m < sldNn; m++ { r := i + m*o.Ndim for p := 0; p < rodNn; p++ { o.Kss[r][c] += coef * o.Nmat[m][p] * rodS[p] * DqbDu_nij } } } } } } // debug //if true { if false { o.debug_print_K() } // add K to sparse matrix Kb for i, I := range o.Rod.Umap { for j, J := range o.Rod.Umap { Kb.Put(I, J, o.Krr[i][j]) } for j, J := range o.Sld.Umap { Kb.Put(I, J, o.Krs[i][j]) Kb.Put(J, I, o.Ksr[j][i]) } } for i, I := range o.Sld.Umap { for j, J := range o.Sld.Umap { Kb.Put(I, J, o.Kss[i][j]) } } return }
// 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 }