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 }
// Str2Dbl converts a slice of strings to a slice of doubles (float64) func Str2Dbl(s []string) (v []float64) { v = make([]float64, len(s)) for i := 0; i < len(s); i++ { v[i] = io.Atof(s[i]) } return }
// DblSplit splits a string into floats func DblSplit(s string) (r []float64) { ss := strings.Fields(s) r = make([]float64, len(ss)) for i, v := range ss { r[i] = io.Atof(v) } return }
// ReadGraphTable reads data and allocate graph func ReadGraphTable(fname string, bargera bool) *Graph { // data var ne int var edges [][]int var weights []float64 // Bar-Gera format files from: http://www.bgu.ac.il/~bargera/tntp/ if bargera { k := 0 reading_meta := true io.ReadLines(fname, func(idx int, line string) (stop bool) { if len(line) < 1 { return false } line = strings.TrimSpace(line) if line[0] == '~' { return false } if reading_meta { switch { case strings.HasPrefix(line, "<NUMBER OF LINKS>"): res := strings.Split(line, "<NUMBER OF LINKS>") ne = io.Atoi(strings.TrimSpace(res[1])) edges = make([][]int, ne) weights = make([]float64, ne) case strings.HasPrefix(line, "<END OF METADATA>"): reading_meta = false } return false } l := strings.Fields(line) edges[k] = []int{io.Atoi(l[0]) - 1, io.Atoi(l[1]) - 1} weights[k] = io.Atof(l[4]) k++ return false }) } else { _, dat, err := io.ReadTable(fname) if err != nil { chk.Panic("cannot read datafile\n%v", err) } ne = len(dat["from"]) // number of edges edges = make([][]int, ne) weights = make([]float64, ne) for i := 0; i < ne; i++ { edges[i] = []int{int(dat["from"][i]) - 1, int(dat["to"][i]) - 1} weights[i] = dat["cost"][i] } } // graph var G Graph G.Init(edges, weights, nil, nil) return &G }
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 }
// ReadSmat reads a smat matrix back func ReadSmat(fn string) *Triplet { var t Triplet io.ReadLines(fn, func(idx int, line string) (stop bool) { r := strings.Fields(line) if idx == 0 { m, n, nnz := io.Atoi(r[0]), io.Atoi(r[1]), io.Atoi(r[2]) t.Init(m, n, nnz) } else { t.Put(io.Atoi(r[0]), io.Atoi(r[1]), io.Atof(r[2])) } return }) return &t }
func main() { // input data simfile := "simfile.sim" zmin := 0.0 zmax := 3.0 npts := 11 // parse flags flag.Parse() if len(flag.Args()) > 0 { simfile = flag.Arg(0) } if len(flag.Args()) > 1 { zmin = io.Atof(flag.Arg(1)) } if len(flag.Args()) > 2 { zmax = io.Atob(flag.Arg(2)) } if len(flag.Args()) > 3 { npts = io.Atoi(flag.Arg(3)) } // print input data io.Pf("\nInput data\n") io.Pf("==========\n") io.Pf(" simfile = %30s // simulation filename\n", simfile) io.Pf(" zmin = %30s // min elevation\n", zmin) io.Pf(" zmax = %30v // max elevation\n", zmax) io.Pf(" npts = %30v // number of points\n", npts) io.Pf("\n") // sim file sim := inp.ReadSim("", simfile, false) if sim == nil { io.PfRed("cannot read sim file\n") return } // layer var lay fem.GeoLayer lay.Zmin = zmin lay.Zmax = zmax lay.Cl = sim.WaterRho0 / sim.WaterBulk //if !lay.ReadPorousParameters(sim.Regions[0], // TODO }
func main() { // input data simfn := "elast.sim" matname := "lrm1" pcmax := 30.0 npts := 101 // parse flags flag.Parse() if len(flag.Args()) > 0 { simfn = flag.Arg(0) } if len(flag.Args()) > 1 { matname = flag.Arg(1) } if len(flag.Args()) > 2 { pcmax = io.Atof(flag.Arg(2)) } if len(flag.Args()) > 3 { npts = io.Atoi(flag.Arg(3)) } // check extension if io.FnExt(simfn) == "" { simfn += ".sim" } // print input data io.Pf("\nInput data\n") io.Pf("==========\n") io.Pf(" simfn = %30s // simulation filename\n", simfn) io.Pf(" matname = %30s // material name\n", matname) io.Pf(" pcmax = %30v // max pc\n", pcmax) io.Pf(" npts = %30v // number of points\n", npts) io.Pf("\n") // load simulation sim := inp.ReadSim("", simfn, "lrm_", false) if sim == nil { io.PfRed("cannot load simulation\n") return } // get material data mat := sim.Mdb.Get(matname) if mat == nil { io.PfRed("cannot get material\n") return } io.Pforan("mat = %v\n", mat) // get and initialise model mdl := mreten.GetModel(simfn, matname, mat.Model, false) if mdl == nil { io.PfRed("cannot allocate model\n") return } mdl.Init(mat.Prms) // plot drying path d_Pc := utl.LinSpace(0, pcmax, npts) d_Sl := make([]float64, npts) d_Sl[0] = 1 var err error for i := 1; i < npts; i++ { d_Sl[i], err = mreten.Update(mdl, d_Pc[i-1], d_Sl[i-1], d_Pc[i]-d_Pc[i-1]) if err != nil { io.PfRed("drying: cannot updated model\n%v\n", err) return } } plt.Plot(d_Pc, d_Sl, io.Sf("'b-', label='%s (dry)', clip_on=0", matname)) // plot wetting path w_Pc := utl.LinSpace(pcmax, 0, npts) w_Sl := make([]float64, npts) w_Sl[0] = d_Sl[npts-1] for i := 1; i < npts; i++ { w_Sl[i], err = mreten.Update(mdl, w_Pc[i-1], w_Sl[i-1], w_Pc[i]-w_Pc[i-1]) if err != nil { io.PfRed("wetting: cannot updated model\n%v\n", err) return } } plt.Plot(w_Pc, w_Sl, io.Sf("'c-', label='%s (wet)', clip_on=0", matname)) // save results type Results struct{ Pc, Sl []float64 } res := Results{append(d_Pc, w_Pc...), append(d_Sl, w_Sl...)} var buf bytes.Buffer enc := json.NewEncoder(&buf) err = enc.Encode(&res) if err != nil { io.PfRed("cannot encode results\n") return } fn := path.Join(sim.Data.DirOut, matname+".dat") io.WriteFile(fn, &buf) io.Pf("file <[1;34m%s[0m> written\n", fn) // show figure plt.AxisYrange(0, 1) plt.Cross() plt.Gll("$p_c$", "$s_{\\ell}$", "") plt.Show() }
// nice_num returns a truncated float func nice_num(x float64) float64 { s := io.Sf("%.2f", x) return io.Atof(s) }
// nice returns a truncated float func nice(x float64, ndigits int) float64 { s := io.Sf("%."+io.Sf("%d", ndigits)+"f", x) return io.Atof(s) }
// ReadLPfortran reads linear program from particular fortran file // download LP files from here: http://users.clas.ufl.edu/hager/coap/format.html // Output: // A -- compressed-column sparse matrix where: // Ap -- pointers to the begining of storage of column (size n+1) // Ai -- row indices for each non zero entry (input, nnz A) // Ax -- non zero entries (input, nnz A) // b -- right hand side (input, size m) // c -- objective vector (minimize, size n) // l -- lower bounds on variables (size n) // u -- upper bounds on variables (size n) func ReadLPfortran(fn string) (A *la.CCMatrix, b, c, l, u []float64) { // variables var m int // number or rows (input) var n int // number of columns (input) var Ap []int // pointers to the begining of storage of column (size n+1) var Ai []int // row indices for each non zero entry (input, nnz A) var Ax []float64 // non zero entries (input, nnz A) var z0 float64 // initial fixed value for objective // auxiliary reading_Ap := false reading_Ai := false reading_Ax := false reading_b := false reading_c := false reading_z0 := false reading_l := false reading_u := false atof := func(s string) float64 { return io.Atof(strings.Replace(s, "D", "E", 1)) } // read data k := 0 io.ReadLines(fn, func(idx int, line string) (stop bool) { if idx == 0 { // skip name return } str := strings.Fields(line) if idx == 1 { // read m and m m, n = io.Atoi(str[0]), io.Atoi(str[1]) Ap = make([]int, n+1) k = 0 reading_Ap = true return } for _, s := range str { if reading_Ap { if k == n+1 { reading_Ap = false reading_Ai = true nnz := Ap[n] Ai = make([]int, nnz) Ax = make([]float64, nnz) b = make([]float64, m) c = make([]float64, n) l = make([]float64, n) u = make([]float64, n) k = 0 } else { Ap[k] = io.Atoi(s) - 1 // subtract 1 because of Fortran indexing } } if reading_Ai { if k == Ap[n] { reading_Ai = false reading_Ax = true k = 0 } else { Ai[k] = io.Atoi(s) - 1 // subtract 1 because of Fortran indexing } } if reading_Ax { if k == Ap[n] { reading_Ax = false reading_b = true k = 0 } else { Ax[k] = atof(s) } } if reading_b { if k == m { reading_b = false reading_c = true k = 0 } else { b[k] = atof(s) } } if reading_c { if k == n { reading_c = false reading_z0 = true k = 0 } else { c[k] = atof(s) } } if reading_z0 { z0 = atof(s) _ = z0 reading_z0 = false reading_l = true k = 0 return } if reading_l { if k == n { reading_l = false reading_u = true k = 0 } else { l[k] = atof(s) } } if reading_u { if k == n { reading_u = false k = 0 } else { u[k] = atof(s) } } k++ } return }) // debug if false { io.Pforan("Ap = %v\n", Ap) io.Pfcyan("Ai = %v\n", Ai) io.Pfyel("Ax = %v\n", Ax) io.Pf("b = %v\n", b) io.Pforan("c = %v\n", c) io.Pfcyan("l = %v\n", l) io.Pfyel("u = %v\n", u) } // results A = new(la.CCMatrix) A.Set(m, n, Ap, Ai, Ax) return }
// 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 }
// PlotDiagMoment plots bending moment diagram // Input: // M -- moment along stations // withtext -- show bending moment values // numfmt -- number format for values. use "" to chose default one // tolM -- tolerance to clip absolute values of M // sf -- scaling factor func (o *Beam) PlotDiagMoment(M []float64, withtext bool, numfmt string, tolM, sf float64) { // number of stations nstations := len(M) ds := 1.0 / float64(nstations-1) // nodes var xa, xb []float64 var u []float64 // out-of-pane vector if o.Ndim == 2 { xa = []float64{o.X[0][0], o.X[1][0], 0} xb = []float64{o.X[0][1], o.X[1][1], 0} u = []float64{0, 0, 1} } else { chk.Panic("TODO: 3D beam diagram") } // unit vector along beam v := make([]float64, 3) sum := 0.0 for j := 0; j < o.Ndim; j++ { v[j] = xb[j] - xa[j] sum += v[j] * v[j] } sum = math.Sqrt(sum) for j := 0; j < o.Ndim; j++ { v[j] /= sum } // unit normal n := make([]float64, 3) // normal utl.CrossProduct3d(n, u, v) // n := u cross v // auxiliary vectors x := make([]float64, o.Ndim) // station m := make([]float64, o.Ndim) // vector pointing to other side c := make([]float64, o.Ndim) // centre imin, imax := utl.DblArgMinMax(M) // draw text function draw_text := func(mom float64) { if math.Abs(mom) > tolM { α := math.Atan2(-n[1], -n[0]) * 180.0 / math.Pi str := io.Sf("%g", mom) if numfmt != "" { str = io.Sf(numfmt, mom) } else { if len(str) > 10 { str = io.Sf("%.10f", mom) // truncate number str = io.Sf("%g", io.Atof(str)) } } plt.Text(c[0], c[1], str, io.Sf("ha='center', size=7, rotation=%g, clip_on=0", α)) } } // draw pts := utl.DblsAlloc(nstations, 2) xx, yy := make([]float64, 2), make([]float64, 2) for i := 0; i < nstations; i++ { // station s := float64(i) * ds for j := 0; j < o.Ndim; j++ { x[j] = (1.0-s)*o.X[j][0] + s*o.X[j][1] } // auxiliary vectors for j := 0; j < o.Ndim; j++ { m[j] = x[j] - sf*M[i]*n[j] c[j] = (x[j] + m[j]) / 2.0 } // points on diagram pts[i][0], pts[i][1] = m[0], m[1] xx[0], xx[1] = x[0], m[0] yy[0], yy[1] = x[1], m[1] // draw clr, lw := "#919191", 1.0 if i == imin || i == imax { lw = 2 if M[i] < 0 { clr = "#9f0000" } else { clr = "#109f24" } } plt.Plot(xx, yy, io.Sf("'-', color='%s', lw=%g, clip_on=0", clr, lw)) if withtext { if i == imin || i == imax { // draw text @ min/max draw_text(M[i]) } else { if i == 0 || i == nstations-1 { // draw text @ extremities draw_text(M[i]) } } } } // draw polyline plt.DrawPolyline(pts, &plt.Sty{Ec: "k", Fc: "none", Lw: 1}, "") }