Example #1
0
// xfem_set_info sets extra information for XFEM elements
func xfem_set_info(info *Info, cell *inp.Cell, edat *inp.ElemData) (ykeys []string) {

	// flags
	xmat, xcrk, xfem := false, false, false
	if s_xmat, found := io.Keycode(edat.Extra, "xmat"); found {
		xmat = io.Atob(s_xmat)
		xfem = true
	}
	if s_xcrk, found := io.Keycode(edat.Extra, "xcrk"); found {
		xcrk = io.Atob(s_xcrk)
		xfem = true
	}
	_ = xcrk // TODO

	// skip if not XFEM
	if !xfem {
		return
	}

	// extra information
	nverts := cell.Shp.Nverts
	if xmat {
		for m := 0; m < nverts; m++ {
			info.Dofs[m] = append(info.Dofs[m], "am")
		}
		info.Y2F["am"] = "nil"
		info.T2vars = append(info.T2vars, "am")
	}
	return
}
Example #2
0
func GetSolidFlags(extra string) (useB, debug bool, thickness float64) {

	// defaults
	useB = false
	debug = false
	thickness = 1.0

	// flag: use B matrix
	if s_useB, found := io.Keycode(extra, "useB"); found {
		useB = io.Atob(s_useB)
	}

	// fix useB flag in case of axisymmetric simulation
	if Global.Sim.Data.Axisym {
		useB = true
	}

	// flag: thickess => plane-stress
	if s_thick, found := io.Keycode(extra, "thick"); found {
		thickness = io.Atof(s_thick)
	}

	// fix thickness flag
	if !Global.Sim.Data.Pstress {
		thickness = 1.0
	}

	// flag: debug
	if s_debug, found := io.Keycode(extra, "debug"); found {
		debug = io.Atob(s_debug)
	}
	return
}
Example #3
0
// get_porous_parameters extracts parameters based on region data
func get_porous_parameters(mdb *inp.MatDb, reg *inp.Region, ctag int) (RhoS0, nf0 float64, err error) {
	edat := reg.Etag2data(ctag)
	mat := mdb.Get(edat.Mat)
	if mat.Model != "group" {
		err = chk.Err("geost: material type describing layer must be 'group' with porous data")
		return
	}
	if matname, found := io.Keycode(mat.Extra, "p"); found {
		m := mdb.Get(matname)
		for _, p := range m.Prms {
			switch p.N {
			case "RhoS0":
				RhoS0 = p.V
			case "nf0":
				nf0 = p.V
			}
		}
	}
	if RhoS0 < 1e-7 {
		err = chk.Err("geost: initial density of solids RhoS0=%g is incorrect", RhoS0)
		return
	}
	if nf0 < 1e-7 {
		err = chk.Err("geost: initial porosity nf0=%g is incorrect", nf0)
	}
	return
}
Example #4
0
// GroupGet parses group data
//  Note: returns nil on failure
func (o MatDb) GroupGet(matname, key string) *Material {
	mat := o.Get(matname)
	if mat == nil {
		return nil
	}
	if submatname, found := io.Keycode(mat.Extra, key); found {
		return o.Get(submatname)
	}
	return nil
}
Example #5
0
// GroupGet3 parses group data
func (o MatDb) GroupGet3(matname, key1, key2, key3 string) (m1, m2, m3 *Material, err error) {
	mat := o.Get(matname)
	if mat == nil {
		err = chk.Err("cannot find material named %q", matname)
		return
	}
	var submat1, submat2, submat3 string
	var found bool
	if submat1, found = io.Keycode(mat.Extra, key1); found {
		m1 = o.Get(submat1)
	} else {
		err = chk.Err("cannot find key %q in grouped material data %q", key1, mat.Extra)
		return
	}
	if submat2, found = io.Keycode(mat.Extra, key2); found {
		m2 = o.Get(submat2)
	} else {
		err = chk.Err("cannot find key %q in grouped material data %q", key2, mat.Extra)
		return
	}
	if submat3, found = io.Keycode(mat.Extra, key3); found {
		m3 = o.Get(submat3)
	} else {
		err = chk.Err("cannot find key %q in grouped material data %q", key3, mat.Extra)
		return
	}
	errmsg := ""
	if m1 == nil {
		errmsg += io.Sf("material data in grouped materials (!%s:%s) cannot be found\n", key1, submat1)
	}
	if m2 == nil {
		errmsg += io.Sf("material data in grouped materials (!%s:%s) cannot be found\n", key2, submat2)
	}
	if m3 == nil {
		errmsg += io.Sf("material data in grouped materials (!%s:%s) cannot be found\n", key3, submat3)
	}
	if errmsg != "" {
		err = chk.Err(errmsg)
	}
	return
}
Example #6
0
func GetSeepFaceFlags(extra string) (Macaulay bool, BetRamp, Kappa float64) {

	// defaults
	Macaulay = false
	BetRamp = math.Ln2 / 0.01
	Kappa = 1.0

	// use macaulay function ?
	if s_mac, found := io.Keycode(extra, "mac"); found {
		Macaulay = io.Atob(s_mac)
	}

	// coefficient for smooth ramp function
	if s_bet, found := io.Keycode(extra, "bet"); found {
		BetRamp = io.Atof(s_bet)
	}

	// κ coefficient
	if s_kap, found := io.Keycode(extra, "kap"); found {
		Kappa = io.Atof(s_kap)
	}
	return
}
Example #7
0
// Init initialises this structure
func (o *SmallElasticity) Init(ndim int, pstress bool, prms fun.Prms) (err error) {
	o.Nsig = 2 * ndim
	o.Pse = pstress
	var has_E, has_ν, has_l, has_G, has_K bool
	for _, p := range prms {
		switch p.N {
		case "E":
			o.E, has_E = p.V, true
		case "nu":
			o.Nu, has_ν = p.V, true
		case "l":
			o.L, has_l = p.V, true
		case "G":
			o.G, has_G = p.V, true
		case "K":
			o.K, has_K = p.V, true
		}
		if skgc, found := io.Keycode(p.Extra, "kgc"); found {
			o.Kgc = GetKgc(skgc, prms)
			if o.Kgc == nil {
				return chk.Err("cannot find kgc model named %s", skgc)
			}
			err = o.Kgc.Init(prms)
			if err != nil {
				return
			}
		}
	}
	switch {
	case has_E && has_ν:
		o.L = Calc_l_from_Enu(o.E, o.Nu)
		o.G = Calc_G_from_Enu(o.E, o.Nu)
		o.K = Calc_K_from_Enu(o.E, o.Nu)
	case has_l && has_G:
		o.E = Calc_E_from_lG(o.L, o.G)
		o.Nu = Calc_nu_from_lG(o.L, o.G)
		o.K = Calc_K_from_lG(o.L, o.G)
	case has_K && has_G:
		o.E = Calc_E_from_KG(o.K, o.G)
		o.Nu = Calc_nu_from_KG(o.K, o.G)
		o.L = Calc_l_from_KG(o.K, o.G)
	case has_K && has_ν:
		o.E = Calc_E_from_Knu(o.K, o.Nu)
		o.G = Calc_G_from_Knu(o.K, o.Nu)
		o.L = Calc_l_from_Knu(o.K, o.Nu)
	default:
		return chk.Err("combination of Elastic constants is incorrect. options are {E,nu}, {l,G}, {K,G} and {K,nu}\n")
	}
	return
}
Example #8
0
// xfem_init initialises variables need by xfem model
func (o *ElemU) xfem_init(edat *inp.ElemData) {

	// flags
	o.Xmat, o.Xcrk, o.Xfem = false, false, false
	if s_xmat, found := io.Keycode(edat.Extra, "xmat"); found {
		o.Xmat = io.Atob(s_xmat)
		o.Xfem = true
	}
	if s_xcrk, found := io.Keycode(edat.Extra, "xcrk"); found {
		o.Xcrk = io.Atob(s_xcrk)
		o.Xfem = true
	}

	// skip if not XFEM
	if !o.Xfem {
		return
	}

	// auxiliary variables
	switch {
	case o.Xmat:
		o.Na = 1
	case o.Xcrk:
		o.Na = 4 // TODO: this is 2D only
		if o.Ndim != 2 {
			chk.Panic("xfem with crack works in 2D only for now")
		}
	}

	// allocate extrem XFEM coupling matrices
	nverts := o.Cell.Shp.Nverts
	o.Amap = make([]int, o.Na*nverts)
	o.Kua = la.MatAlloc(o.Nu, o.Na)
	o.Kau = la.MatAlloc(o.Na, o.Nu)
	o.Kaa = la.MatAlloc(o.Na, o.Na)
}
Example #9
0
func GetAndInitSolidModel(mdb *inp.MatDb, matname, simfnk string, ndim int, pstress bool) (mdl msolid.Model, prms fun.Prms, err error) {

	// material name
	matdata := mdb.Get(matname)
	if matdata == nil {
		err = chk.Err("materials database failed on getting %q (solid) material\n", matname)
		return
	}
	mdlname := matdata.Model

	// handle groups
	if mdlname == "group" {
		if s_matname, found := io.Keycode(matdata.Extra, "s"); found {
			matname = s_matname
			matdata = mdb.Get(matname)
			if matdata == nil {
				err = chk.Err("materials database failed on getting %q (solid/sub) material\n", matname)
				return
			}
			mdlname = matdata.Model
		} else {
			err = chk.Err("cannot find solid model in grouped material data. 's' subkey needed in Extra field")
			return
		}
	}

	// initialise model
	mdl, existent := msolid.GetModel(simfnk, matname, mdlname, false)
	if mdl == nil {
		err = chk.Err("cannot find solid model named %q", mdlname)
		return
	}
	if !existent {
		err = mdl.Init(ndim, pstress, matdata.Prms)
		if err != nil {
			err = chk.Err("solid model initialisation failed:\n%v", err)
			return
		}
	}

	// results
	prms = matdata.Prms
	return
}
Example #10
0
// register element
func init() {

	// information allocator
	infogetters["rod"] = func(cellType string, faceConds []*FaceCond) *Info {

		// new info
		var info Info

		// number of nodes in element
		nverts := shp.GetNverts(cellType)

		// solution variables
		ykeys := []string{"ux", "uy"}
		if Global.Ndim == 3 {
			ykeys = []string{"ux", "uy", "uz"}
		}
		info.Dofs = make([][]string, nverts)
		for m := 0; m < nverts; m++ {
			info.Dofs[m] = ykeys
		}

		// maps
		info.Y2F = map[string]string{"ux": "fx", "uy": "fy", "uz": "fz"}

		// t1 and t2 variables
		info.T2vars = ykeys
		return &info
	}

	// element allocator
	eallocators["rod"] = func(cellType string, faceConds []*FaceCond, cid int, edat *inp.ElemData, x [][]float64) Elem {

		// basic data
		var o Rod
		o.Cid = cid
		o.X = x
		o.Shp = shp.Get(cellType)
		ndim := Global.Ndim
		o.Nu = ndim * o.Shp.Nverts

		var err error

		// material model name
		matname := edat.Mat
		matdata := Global.Sim.Mdb.Get(matname)
		if LogErrCond(matdata == nil, "materials database failed on getting %q material\n", matname) {
			return nil
		}
		mdlname := matdata.Model
		o.Model = msolid.GetOnedSolid(Global.Sim.Data.FnameKey, matname, mdlname, false)
		if LogErrCond(o.Model == nil, "cannot find model named %s\n", mdlname) {
			return nil
		}
		err = o.Model.Init(ndim, matdata.Prms)
		if LogErr(err, "Model.Init failed") {
			return nil
		}

		// parameters
		for _, p := range matdata.Prms {
			switch p.N {
			case "A":
				o.A = p.V
			case "rho":
				o.Rho = p.V
			}
		}

		// integration points
		var nip int
		if s_nip, found := io.Keycode(edat.Extra, "nip"); found {
			nip = io.Atoi(s_nip)
		}
		o.IpsElem, err = shp.GetIps(o.Shp.Type, nip)
		if LogErr(err, "GetIps failed") {
			return nil
		}
		nip = len(o.IpsElem)

		// scratchpad. computed @ each ip
		o.K = la.MatAlloc(o.Nu, o.Nu)
		o.M = la.MatAlloc(o.Nu, o.Nu)
		o.ue = make([]float64, o.Nu)
		o.Rus = make([]float64, o.Nu)

		// scratchpad. computed @ each ip
		o.grav = make([]float64, ndim)
		o.us = make([]float64, ndim)
		o.fi = make([]float64, o.Nu)

		// return new element
		return &o
	}
}
Example #11
0
// register element
func init() {

	// information allocator
	infogetters["p"] = func(cellType string, faceConds []*FaceCond) *Info {

		// new info
		var info Info

		// number of nodes in element
		nverts := shp.GetNverts(cellType)

		// solution variables
		ykeys := []string{"pl"}
		info.Dofs = make([][]string, nverts)
		for m := 0; m < nverts; m++ {
			info.Dofs[m] = ykeys
		}

		// maps
		info.Y2F = map[string]string{"pl": "ql"}

		// vertices on seepage faces
		lverts := GetVertsWithCond(faceConds, "seep")
		for _, m := range lverts {
			if m < nverts { // avoid adding vertices of superelement (e.g. qua8 vertices in this qua4 cell)
				info.Dofs[m] = append(info.Dofs[m], "fl")
			}
		}
		if len(lverts) > 0 {
			ykeys = append(ykeys, "fl")
			info.Y2F["fl"] = "nil"
		}

		// t1 and t2 variables
		info.T1vars = ykeys
		return &info
	}

	// element allocator
	eallocators["p"] = func(cellType string, faceConds []*FaceCond, cid int, edat *inp.ElemData, x [][]float64) Elem {

		// basic data
		var o ElemP
		o.Cid = cid
		o.X = x
		o.Shp = shp.Get(cellType)
		o.Np = o.Shp.Nverts

		// integration points
		o.IpsElem, o.IpsFace = GetIntegrationPoints(edat.Nip, edat.Nipf, cellType)
		if o.IpsElem == nil || o.IpsFace == nil {
			return nil
		}
		nip := len(o.IpsElem)

		// models
		o.Mdl = GetAndInitPorousModel(edat.Mat)
		if o.Mdl == nil {
			return nil
		}

		// local starred variables
		o.ψl = make([]float64, nip)

		// scratchpad. computed @ each ip
		ndim := Global.Ndim
		o.g = make([]float64, ndim)
		o.gpl = make([]float64, ndim)
		o.ρwl = make([]float64, ndim)
		o.tmp = make([]float64, ndim)
		o.Kpp = la.MatAlloc(o.Np, o.Np)
		o.res = new(mporous.LsVars)

		// vertices on seepage faces
		var seepverts []int
		lverts := GetVertsWithCond(faceConds, "seep")
		for _, m := range lverts {
			if m < o.Np { // avoid adding vertices of superelement (e.g. qua8 vertices in this qua4 cell)
				seepverts = append(seepverts, m)
			}
		}

		o.Nf = len(seepverts)
		o.HasSeep = o.Nf > 0
		if o.HasSeep {

			// vertices on seepage face; numbering
			o.SeepId2vid = seepverts
			o.Vid2seepId = utl.IntVals(o.Np, -1)
			o.Fmap = make([]int, o.Nf)
			for μ, m := range o.SeepId2vid {
				o.Vid2seepId[m] = μ
			}

			// flags
			o.Macaulay, o.βrmp, o.κ = GetSeepFaceFlags(edat.Extra)

			// allocate coupling matrices
			o.Kpf = la.MatAlloc(o.Np, o.Nf)
			o.Kfp = la.MatAlloc(o.Nf, o.Np)
			o.Kff = la.MatAlloc(o.Nf, o.Nf)
		}

		// set natural boundary conditions
		for idx, fc := range faceConds {
			o.NatBcs = append(o.NatBcs, &NaturalBc{fc.Cond, fc.FaceId, fc.Func, fc.Extra})

			// allocate extrapolation structures
			if fc.Cond == "ql" || fc.Cond == "seep" {
				nv := o.Shp.Nverts
				nip := len(o.IpsElem)
				o.ρl_ex = make([]float64, nv)
				o.dρldpl_ex = la.MatAlloc(nv, nv)
				o.Emat = la.MatAlloc(nv, nip)
				o.DoExtrap = true
				if LogErr(o.Shp.Extrapolator(o.Emat, o.IpsElem), "element allocation") {
					return nil
				}
			}

			// additional seepage condition structures: hydrostatic flags
			if fc.Cond == "seep" {
				if len(o.Hst) == 0 {
					o.Hst = make([]bool, len(faceConds))
				}
				if s_val, found := io.Keycode(fc.Extra, "plmax"); found {
					o.Hst[idx] = (s_val == "hst")
				}
			}
		}

		// return new element
		return &o
	}
}
Example #12
0
// Set sets a constraint if it does NOT exist yet.
//  key   -- can be Dof key such as "ux", "uy" or constraint type such as "mpc" or "rigid"
//  extra -- is a keycode-style data. e.g. "!type:incsup2d !alp:30"
//  Notes: 1) the default for key is single point constraint; e.g. "ux", "uy", ...
//         2) hydraulic head can be set with key == "H"
func (o *EssentialBcs) Set(key string, nodes []*Node, fcn fun.Func, extra string) (err error) {

	// len(nod) must be greater than 0
	chk.IntAssertLessThan(0, len(nodes)) // 0 < len(nod)

	// skip nil node
	if nodes[0] == nil {
		return
	}

	// space dimension
	ndim := len(nodes[0].Vert.C)

	// rigid element
	if key == "rigid" {
		a := nodes[0].Dofs
		for i := 1; i < len(nodes); i++ {
			for j, b := range nodes[i].Dofs {
				o.add(key, []int{a[j].Eq, b.Eq}, []float64{1, -1}, &fun.Zero)
			}
		}
		return // success
	}

	// inclined support
	if key == "incsup" {

		// check
		if ndim != 2 {
			return chk.Err("inclined support works only in 2D for now")
		}

		// get data
		var α float64
		if val, found := io.Keycode(extra, "alp"); found {
			α = io.Atof(val) * math.Pi / 180.0
		}
		co, si := math.Cos(α), math.Sin(α)

		// set for all nodes
		for _, nod := range nodes {

			// find existent constraints and deactivate them
			eqx := nod.Dofs[0].Eq
			eqy := nod.Dofs[1].Eq
			for _, eq := range []int{eqx, eqy} {
				for _, idx := range o.Eq2idx[eq] {
					pair := o.BcsTmp[idx]
					if pair.bc.Key != "rigid" {
						pair.bc.Inact = true
					}
				}
			}

			// set constraint
			o.add(key, []int{eqx, eqy}, []float64{co, si}, &fun.Zero)
		}
		return // success
	}

	// hydraulic head
	if key == "hst" {

		// set for all nodes
		for _, nod := range nodes {

			// create function
			// Note: fcn is a shift such that  pl = pl(z) - shift(t)
			d := nod.GetDof("pl")
			if d == nil {
				continue // node doesn't have key. ex: pl in qua8/qua4 elements
			}
			z := nod.Vert.C[1] // 2D
			if ndim == 3 {
				z = nod.Vert.C[2] // 3D
			}
			plVal, _, err := o.HydFcn.Calc(z)
			if err != nil {
				return chk.Err("cannot set hst (hydrostatic) essential boundary condition")
			}
			pl := fun.Add{
				B: 1, Fb: &fun.Cte{C: plVal},
				A: -1, Fa: fcn,
			}

			// set constraint
			o.add_single("pl", d.Eq, &pl)
		}
		return // success
	}

	// single-point constraint
	for _, nod := range nodes {
		d := nod.GetDof(key)
		if d == nil {
			return // success
		}
		o.add_single(key, d.Eq, fcn)
	}

	// success
	return
}
Example #13
0
// register element
func init() {

	// information allocator
	infogetters["p"] = func(sim *inp.Simulation, cell *inp.Cell, edat *inp.ElemData) *Info {

		// new info
		var info Info

		// number of nodes in element
		nverts := cell.GetNverts(edat.Lbb)

		// solution variables
		ykeys := []string{"pl"}
		info.Dofs = make([][]string, nverts)
		for m := 0; m < nverts; m++ {
			info.Dofs[m] = ykeys
		}

		// maps
		info.Y2F = map[string]string{"pl": "ql"}

		// vertices on seepage faces
		if len(cell.FaceBcs) > 0 {
			lverts := cell.FaceBcs.GetVerts("seep")
			for _, m := range lverts {
				if m < nverts { // avoid adding vertices of superelement (e.g. qua8 vertices in this qua4 cell)
					info.Dofs[m] = append(info.Dofs[m], "fl")
				}
			}
			if len(lverts) > 0 {
				ykeys = append(ykeys, "fl")
				info.Y2F["fl"] = "nil"
			}
		}

		// t1 and t2 variables
		info.T1vars = ykeys
		return &info
	}

	// element allocator
	eallocators["p"] = func(sim *inp.Simulation, cell *inp.Cell, edat *inp.ElemData, x [][]float64) Elem {

		// basic data
		var o ElemP
		o.Cell = cell
		o.X = x
		o.Np = o.Cell.Shp.Nverts
		o.Ndim = sim.Ndim

		// integration points
		var err error
		o.IpsElem, o.IpsFace, err = o.Cell.Shp.GetIps(edat.Nip, edat.Nipf)
		if err != nil {
			chk.Panic("cannot allocate integration points of p-element with nip=%d and nipf=%d:\n%v", edat.Nip, edat.Nipf, err)
		}
		nip := len(o.IpsElem)

		// models
		o.Mdl, err = GetAndInitPorousModel(sim.MatParams, edat.Mat, sim.Key)
		if err != nil {
			chk.Panic("cannot get model for p-element {tag=%d id=%d material=%q}:\n%v", cell.Tag, cell.Id, edat.Mat, err)
		}

		// local starred variables
		o.ψl = make([]float64, nip)

		// scratchpad. computed @ each ip
		o.g = make([]float64, o.Ndim)
		o.gpl = make([]float64, o.Ndim)
		o.ρwl = make([]float64, o.Ndim)
		o.tmp = make([]float64, o.Ndim)
		o.Kpp = la.MatAlloc(o.Np, o.Np)
		o.res = new(mporous.LsVars)

		// vertices on seepage faces
		var seepverts []int
		if len(cell.FaceBcs) > 0 {
			lverts := cell.FaceBcs.GetVerts("seep")
			for _, m := range lverts {
				if m < o.Np { // avoid adding vertices of superelement (e.g. qua8 vertices in this qua4 cell)
					seepverts = append(seepverts, m)
				}
			}
		}

		o.Nf = len(seepverts)
		o.HasSeep = o.Nf > 0
		if o.HasSeep {

			// vertices on seepage face; numbering
			o.SeepId2vid = seepverts
			o.Vid2seepId = utl.IntVals(o.Np, -1)
			o.Fmap = make([]int, o.Nf)
			for μ, m := range o.SeepId2vid {
				o.Vid2seepId[m] = μ
			}

			// flags
			o.Macaulay, o.βrmp, o.κ = GetSeepFaceFlags(edat.Extra)

			// allocate coupling matrices
			o.Kpf = la.MatAlloc(o.Np, o.Nf)
			o.Kfp = la.MatAlloc(o.Nf, o.Np)
			o.Kff = la.MatAlloc(o.Nf, o.Nf)
		}

		// set natural boundary conditions
		for idx, fc := range cell.FaceBcs {
			o.NatBcs = append(o.NatBcs, &NaturalBc{fc.Cond, fc.FaceId, fc.Func, fc.Extra})

			// allocate extrapolation structures
			if fc.Cond == "ql" || fc.Cond == "seep" {
				nv := o.Cell.Shp.Nverts
				nip := len(o.IpsElem)
				o.ρl_ex = make([]float64, nv)
				o.dρldpl_ex = la.MatAlloc(nv, nv)
				o.Emat = la.MatAlloc(nv, nip)
				o.DoExtrap = true
				err = o.Cell.Shp.Extrapolator(o.Emat, o.IpsElem)
				if err != nil {
					chk.Panic("cannot build extrapolator matrix for p-element:\n%v", err)
				}
			}

			// additional seepage condition structures: hydrostatic flags
			if fc.Cond == "seep" {
				if len(o.Hst) == 0 {
					o.Hst = make([]bool, len(cell.FaceBcs))
				}
				if s_val, found := io.Keycode(fc.Extra, "plmax"); found {
					o.Hst[idx] = (s_val == "hst")
				}
			}
		}

		// return new element
		return &o
	}
}