예제 #1
0
파일: e_u.go 프로젝트: PatrickSchm/gofem
// 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
}
예제 #2
0
파일: e_rod.go 프로젝트: PaddySchmidt/gofem
// 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
}
예제 #3
0
파일: e_rod.go 프로젝트: PatrickSchm/gofem
// 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
}
예제 #4
0
// 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
}
예제 #5
0
파일: algos.go 프로젝트: PatrickSchm/gofem
// 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
}
예제 #6
0
파일: e_phi.go 프로젝트: PaddySchmidt/gofem
// 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
}
예제 #7
0
파일: e_phi.go 프로젝트: PatrickSchm/gofem
// 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
}
예제 #8
0
파일: e_u.go 프로젝트: PatrickSchm/gofem
// 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
}
예제 #9
0
파일: e_up.go 프로젝트: PatrickSchm/gofem
// 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
}
예제 #10
0
파일: e_p.go 프로젝트: PatrickSchm/gofem
// 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
}
예제 #11
0
파일: e_p.go 프로젝트: PatrickSchm/gofem
// 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
}
예제 #12
0
// 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
}
예제 #13
0
// 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
}
예제 #14
0
파일: e_u.go 프로젝트: PaddySchmidt/gofem
// 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
}