// ReadTable loads path from datafile in table format // Note: n -- number of lines to read. use -1 to read all lines func (o *Path) ReadTable(ndim, nincs, niout int, fname string, n int, mσ, mε float64, stresspath bool) (err error) { // constants o.Nincs, o.Niout = nincs, niout // read data table keys, d, err := io.ReadTable(fname) if err != nil { return } if n < 0 { n = len(d[keys[0]]) } // find x-y-z keys ex, ey, ez := "ex", "ey", "ez" sx, sy, sz := "sx", "sy", "sz" for _, key := range keys { switch key { case "Ex": ex, ey, ez = "Ex", "Ey", "Ez" case "Ea": ex, ey, ez = "Et", "Er", "Ea" case "ea": ex, ey, ez = "et", "er", "ea" case "Sx": sx, sy, sz = "Sx", "Sy", "Sz" case "Sa": sx, sy, sz = "St", "Sr", "Sa" case "sa": sx, sy, sz = "st", "sr", "sa" } } // set stress path if stresspath { o.Sx, o.Sy, o.Sz = make([]float64, n), make([]float64, n), make([]float64, n) for i := 0; i < n; i++ { o.Sx[i], o.Sy[i], o.Sz[i] = mσ*d[sx][i], mσ*d[sy][i], mσ*d[sz][i] } o.UseS = utl.IntVals(n, 1) // set strain path } else { o.Ex, o.Ey, o.Ez = make([]float64, n), make([]float64, n), make([]float64, n) for i := 0; i < n; i++ { o.Ex[i], o.Ey[i], o.Ez[i] = mε*d[ex][i], mε*d[ey][i], mε*d[ez][i] } o.Sx, o.Sy, o.Sz = []float64{mσ * d[sx][0]}, []float64{mσ * d[sy][0]}, []float64{mσ * d[sz][0]} o.UseE = utl.IntVals(n, 1) } // set additional information return o.Init(ndim) }
// contact_init initialises variables need by contact model func (o *ElemU) contact_init(edat *inp.ElemData) { // vertices on faces with contact var contactverts []int if len(o.Cell.FaceBcs) > 0 { lverts := o.Cell.FaceBcs.GetVerts("contact") for _, m := range lverts { contactverts = append(contactverts, m) } } o.Nq = len(contactverts) // contact flag o.HasContact = o.Nq > 0 if !o.HasContact { return } // vertices on contact face; numbering o.ContactId2vid = contactverts o.Vid2contactId = utl.IntVals(o.Nu, -1) o.Qmap = make([]int, o.Nq) for μ, m := range o.ContactId2vid { o.Vid2contactId[m] = μ } // flags o.Macaulay, o.βrmp, o.κ = GetContactFaceFlags(edat.Extra) // allocate coupling matrices o.Kuq = la.MatAlloc(o.Nu, o.Nq) o.Kqu = la.MatAlloc(o.Nq, o.Nu) o.Kqq = la.MatAlloc(o.Nq, o.Nq) }
// 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 } }
// Init initialises states variables after {Sx, Sy, Sz} or {Ex, Ey, Ez} have been set func (o *Path) Init(ndim int) (err error) { // constants o.ndim = ndim o.ncp = 2 * ndim // size of slices and flags hasS, hasE := false, false allS, allE := true, true nSx, nSy, nSz := len(o.Sx), len(o.Sy), len(o.Sz) nEx, nEy, nEz := len(o.Ex), len(o.Ey), len(o.Ez) if nSx > 0 { hasS, allE = true, false } if nSy > 0 { hasS, allE = true, false } if nSz > 0 { hasS, allE = true, false } if nEx > 0 { hasE, allS = true, false } if nEy > 0 { hasE, allS = true, false } if nEz > 0 { hasE, allS = true, false } // check nS if nSx != nSy || nSx != nSz { return chk.Err(_path_err02, nSx, nSy, nSz) } // check for initial stresses if nSx < 1 || nSy < 1 || nSz < 1 { return chk.Err(_path_err03) } // unset hasS if only initial stress were given if nSx == 1 { hasS, allE = false, true if !hasE { return chk.Err(_path_err04) } } // other checks o.size = 0 // number of path components if hasS { o.size = nSx } if hasE { if nEx != nEy || nEx != nEz { return chk.Err(_path_err05, nEx, nEy, nEz) } o.size = nEx } if hasS && hasE { if nEx != nSx || nEy != nSx || nEz != nSx { return chk.Err(_path_err06) } } if !allS && !allE { if len(o.UseS) != nSx || len(o.UseE) != nSx { return chk.Err(_path_err07, len(o.UseS), len(o.UseE), nSx) } } // check size and Nincs if o.size < 2 { return chk.Err(_path_err08) } if o.Nincs < 1 { o.Nincs = 1 } // multipliers if o.MultS < 1e-7 { o.MultS = 1 } if o.MultE < 1e-7 { o.MultE = 1 } // set use flags if allS { o.UseS = utl.IntVals(o.size, 1) o.UseE = make([]int, o.size) } if allE { o.UseE = utl.IntVals(o.size, 1) o.UseS = make([]int, o.size) } return }
// 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 } }