예제 #1
0
파일: ogden.go 프로젝트: PatrickSchm/gofem
// Init initialises model
func (o *Ogden) Init(ndim int, pstress bool, prms fun.Prms) (err error) {

	// basic data
	o.Nsig = 2 * ndim

	// parameters
	for _, p := range prms {
		if p.N == "K" {
			o.K = p.V
		}
		if p.N[:3] == "alp" {
			o.Alp = append(o.Alp, p.V)
		}
		if p.N[:3] == "mu" {
			o.Mu = append(o.Mu, p.V)
		}
	}
	if len(o.Alp) != len(o.Mu) {
		return chk.Err("number of alp must be equal to number of mu. %d != %d\n", len(o.Alp), len(o.Mu))
	}

	// auxiliary
	o.Fi = tsr.Alloc2()
	o.b = tsr.Alloc2()
	o.bm = make([]float64, o.Nsig)
	o.λ = make([]float64, 3)
	o.P = tsr.M_AllocEigenprojs(o.Nsig)
	o.τ = make([]float64, 3)
	return
}
예제 #2
0
// Connect connects rod/solid elements in this Rjoint
func (o *Rjoint) Connect(cid2elem []Elem, c *inp.Cell) (nnzK int, err error) {

	// get rod and solid elements
	rodId := c.JlinId
	sldId := c.JsldId
	o.Rod = cid2elem[rodId].(*Rod)
	o.Sld = cid2elem[sldId].(*ElemU)
	if o.Rod == nil {
		err = chk.Err("cannot find joint's rod cell with id == %d", rodId)
		return
	}
	if o.Sld == nil {
		err = chk.Err("cannot find joint's solid cell with id == %d", sldId)
		return
	}

	// total number of dofs
	o.Ny = o.Rod.Nu + o.Sld.Nu

	// material model name
	matdata := o.Sim.MatParams.Get(o.Edat.Mat)
	if matdata == nil {
		err = chk.Err("materials database failed on getting %q material\n", o.Edat.Mat)
		return
	}

	// initialise model
	err = o.Mdl.Init(matdata.Prms)
	if err != nil {
		err = chk.Err("model initialisation failed:\n%v", err)
		return
	}

	// parameters
	for _, p := range matdata.Prms {
		switch p.N {
		case "h":
			o.h = p.V
		case "k1":
			o.k1 = p.V
		case "k2":
			o.k2 = p.V
		case "mu":
			if p.V > 0.0 {
				o.Coulomb = true
			}
		}
	}

	// auxiliary
	nsig := 2 * o.Ndim

	// rod data
	rodH := o.Rod.Cell.Shp
	rodNp := len(o.Rod.IpsElem)
	rodNn := rodH.Nverts
	rodNu := o.Rod.Nu

	// solid data
	sldH := o.Sld.Cell.Shp
	sldS := sldH.S
	sldNp := len(o.Sld.IpsElem)
	sldNn := sldH.Nverts
	sldNu := o.Sld.Nu

	// shape functions of solid @ nodes of rod
	o.Nmat = la.MatAlloc(sldNn, rodNn)
	rodYn := make([]float64, o.Ndim)
	rodRn := make([]float64, 3)
	for m := 0; m < rodNn; m++ {
		for i := 0; i < o.Ndim; i++ {
			rodYn[i] = o.Rod.X[i][m]
		}
		err = sldH.InvMap(rodRn, rodYn, o.Sld.X)
		if err != nil {
			return
		}
		err = sldH.CalcAtR(o.Sld.X, rodRn, false)
		if err != nil {
			return
		}
		for n := 0; n < sldNn; n++ {
			o.Nmat[n][m] = sldH.S[n]
		}
	}

	// coulomb model => σc depends on p values of solid
	if o.Coulomb {

		// allocate variables
		o.Pmat = la.MatAlloc(sldNn, rodNp)
		o.Emat = la.MatAlloc(sldNn, sldNp)
		o.rodRp = la.MatAlloc(rodNp, 3)
		o.σNo = la.MatAlloc(sldNn, nsig)
		o.σIp = make([]float64, nsig)
		o.t1 = make([]float64, o.Ndim)
		o.t2 = make([]float64, o.Ndim)

		// extrapolator matrix
		err = sldH.Extrapolator(o.Emat, o.Sld.IpsElem)
		if err != nil {
			return
		}

		// shape function of solid @ ips of rod
		for idx, ip := range o.Rod.IpsElem {
			rodYp := rodH.IpRealCoords(o.Rod.X, ip)
			err = sldH.InvMap(o.rodRp[idx], rodYp, o.Sld.X)
			if err != nil {
				return
			}
			err = sldH.CalcAtR(o.Sld.X, o.rodRp[idx], false)
			if err != nil {
				return
			}
			for n := 0; n < sldNn; n++ {
				o.Pmat[n][idx] = sldS[n]
			}
		}
	}

	// joint direction @ ip[idx]; corotational system aligned with rod element
	o.e0 = la.MatAlloc(rodNp, o.Ndim)
	o.e1 = la.MatAlloc(rodNp, o.Ndim)
	o.e2 = la.MatAlloc(rodNp, o.Ndim)
	π := make([]float64, o.Ndim) // Eq. (27)
	Q := la.MatAlloc(o.Ndim, o.Ndim)
	α := 666.0
	Jvec := rodH.Jvec3d[:o.Ndim]
	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
		}

		// compute basis vectors
		J := rodH.J
		π[0] = Jvec[0] + α
		π[1] = Jvec[1]
		e0[0] = Jvec[0] / J
		e0[1] = Jvec[1] / J
		if o.Ndim == 3 {
			π[2] = Jvec[2]
			e0[2] = Jvec[2] / J
		}
		la.MatSetDiag(Q, 1)
		la.VecOuterAdd(Q, -1, e0, e0) // Q := I - e0 dyad e0
		la.MatVecMul(e1, 1, Q, π)     // Eq. (29) * norm(E1)
		la.VecScale(e1, 0, 1.0/la.VecNorm(e1), e1)
		if o.Ndim == 3 {
			e2[0] = e0[1]*e1[2] - e0[2]*e1[1]
			e2[1] = e0[2]*e1[0] - e0[0]*e1[2]
			e2[2] = e0[0]*e1[1] - e0[1]*e1[0]
		}

		// compute auxiliary tensors
		if o.Coulomb {
			e1_dy_e1 := tsr.Alloc2()
			e2_dy_e2 := tsr.Alloc2()
			for i := 0; i < o.Ndim; i++ {
				for j := 0; j < o.Ndim; j++ {
					e1_dy_e1[i][j] = e1[i] * e1[j]
					e2_dy_e2[i][j] = e2[i] * e2[j]
				}
			}
		}
	}

	// auxiliary variables
	o.ΔuC = la.MatAlloc(rodNn, o.Ndim)
	o.Δw = make([]float64, o.Ndim)
	o.qb = make([]float64, o.Ndim)
	o.fC = make([]float64, rodNu)

	// temporary Jacobian matrices. see Eq. (57)
	o.Krr = la.MatAlloc(rodNu, rodNu)
	o.Krs = la.MatAlloc(rodNu, sldNu)
	o.Ksr = la.MatAlloc(sldNu, rodNu)
	o.Kss = la.MatAlloc(sldNu, sldNu)

	// debugging
	//if true {
	if false {
		o.debug_print_init()
	}

	// success
	return o.Ny * o.Ny, nil
}