func (o *Plotter) Plot_Dgam_f(x, y []float64, res []*State, sts [][]float64, last bool) { if o.m == nil { o.set_empty() return } nr := len(res) k := nr - 1 ys := o.m.YieldFuncs(res[0]) fc0 := ys[0] xmi, xma, ymi, yma := res[0].Dgam, res[0].Dgam, fc0, fc0 for i := 0; i < nr; i++ { x[i] = res[i].Dgam ys = o.m.YieldFuncs(res[i]) y[i] = ys[0] xmi = utl.Min(xmi, x[i]) xma = utl.Max(xma, x[i]) ymi = utl.Min(ymi, y[i]) yma = utl.Max(yma, y[i]) } //o.DrawRamp(xmi, xma, ymi, yma) plt.Plot(x, y, io.Sf("'r.', ls='%s', clip_on=0, color='%s', marker='%s', label=r'%s'", o.Ls, o.Clr, o.Mrk, o.Lbl)) plt.PlotOne(x[0], y[0], io.Sf("'bo', clip_on=0, color='%s', marker='%s', ms=%d", o.SpClr, o.SpMrk, o.SpMs)) plt.PlotOne(x[k], y[k], io.Sf("'bs', clip_on=0, color='%s', marker='%s', ms=%d", o.SpClr, o.EpMrk, o.EpMs)) if last { plt.Gll("$\\Delta\\gamma$", "$f$", "") if lims, ok := o.Lims["Dgam,f"]; ok { plt.AxisLims(lims) } } }
// step6: add min value to every element of each covered row, and subtract it from every element of // each uncovered column. next_step = 4 func (o *Munkres) step6() (next_step int) { // find min value xmin := math.MaxFloat64 for i := 0; i < o.nrow; i++ { for j := 0; j < o.ncol; j++ { if !o.row_covered[i] && !o.col_covered[j] { xmin = utl.Min(xmin, o.C[i][j]) } } } // add/subtract min value for i := 0; i < o.nrow; i++ { for j := 0; j < o.ncol; j++ { if o.row_covered[i] { o.C[i][j] += xmin } if !o.col_covered[j] { o.C[i][j] -= xmin } } } return 4 }
func GetLimits(o *Nurbs) (xmin, xmax, xdel []float64) { xmin = []float64{math.Inf(+1), math.Inf(+1), math.Inf(+1)} xmax = []float64{math.Inf(-1), math.Inf(-1), math.Inf(-1)} xdel = []float64{0, 0, 0} for k := 0; k < o.n[2]; k++ { for j := 0; j < o.n[1]; j++ { for i := 0; i < o.n[0]; i++ { x := o.GetQ(i, j, k) for r := 0; r < o.gnd; r++ { xmin[r] = utl.Min(xmin[r], x[r]) xmax[r] = utl.Max(xmax[r], x[r]) } } } } for i := 0; i < 3; i++ { xdel[i] = xmax[i] - xmin[i] } for i := o.gnd; i < 3; i++ { xmin[i] = 0 xmax[i] = 0 xdel[i] = 0 } return }
// step1: for each row of the cost matrix, find the smallest element and subtract it from every // element in its row. next_step = 2 func (o *Munkres) step1() (next_step int) { var xmin float64 for i := 0; i < o.nrow; i++ { xmin = o.C[i][0] for j := 1; j < o.ncol; j++ { xmin = utl.Min(xmin, o.C[i][j]) } for j := 0; j < o.ncol; j++ { o.C[i][j] -= xmin } } return 2 }
// CellBryDist returns the shortest distance between R and the boundary of the cell in natural coordinates // TODO: test this func (o *Shape) CellBryDist(R []float64) float64 { r, s, t := R[0], R[1], 0.0 if len(R) > 2 { t = R[2] } bgeo := o.BasicType // fundamental geometry of cell if bgeo == "tri3" { return utl.Min(r, utl.Min(s, 1.0-r-s)) } if bgeo == "qua4" { return utl.Min(1.0-math.Abs(r), 1.0-math.Abs(s)) } if bgeo == "hex8" { return utl.Min(1.0-math.Abs(r), utl.Min(1.0-math.Abs(s), 1.0-math.Abs(t))) } if bgeo == "tet4" { return utl.Min(r, utl.Min(s, utl.Min(t, 1.0-r-s-t))) } chk.Panic("cannot handle BasicType=%q yet", bgeo) return 0 // must not reach this point }
// SetGeoSt sets the initial state to a hydrostatic condition func (o *Domain) SetGeoSt(stg *inp.Stage) (err error) { // check layers definition geo := stg.GeoSt if len(geo.Layers) < 1 { return chk.Err("geost: layers must be defined by specifying what tags belong to which layer") } // get region if len(o.Sim.Regions) != 1 { return chk.Err("geost: can only handle one domain for now") } reg := o.Sim.Regions[0] // gravity grav := o.Sim.Gravity.F(0, nil) // fix UseK0 nlayers := len(geo.Layers) if len(geo.UseK0) != nlayers { geo.UseK0 = make([]bool, nlayers) } // initialise layers var L GeoLayers L = make([]*GeoLayer, nlayers) ndim := o.Sim.Ndim nodehandled := make(map[int]bool) ctaghandled := make(map[int]bool) // required to make sure all elements were initialised for i, tags := range geo.Layers { // new layer L[i] = new(GeoLayer) L[i].Tags = tags L[i].Zmin = o.Sim.MaxElev L[i].Zmax = 0 L[i].Cl = o.Sim.WaterRho0 / o.Sim.WaterBulk // get porous parameters L[i].RhoS0, L[i].nf0, err = get_porous_parameters(o.Sim.MatParams, reg, tags[0]) if err != nil { return } // parameters if geo.UseK0[i] { L[i].K0 = geo.K0[i] } else { L[i].K0 = geo.Nu[i] / (1.0 - geo.Nu[i]) } if L[i].K0 < 1e-7 { return chk.Err("geost: K0 or Nu is incorect: K0=%g, Nu=%g", L[i].K0, geo.Nu) } // for each tag of cells in this layer for _, tag := range tags { // check tags cells := o.Msh.CellTag2cells[tag] if len(cells) < 1 { return chk.Err("geost: there are no cells with tag = %d", tag) } // set nodes and elements and find min and max z-coordinates for _, c := range cells { L[i].Elems = append(L[i].Elems, o.Cid2elem[c.Id]) for _, v := range c.Verts { if !nodehandled[v] { L[i].Nodes = append(L[i].Nodes, o.Vid2node[v]) } L[i].Zmin = utl.Min(L[i].Zmin, o.Msh.Verts[v].C[ndim-1]) L[i].Zmax = utl.Max(L[i].Zmax, o.Msh.Verts[v].C[ndim-1]) nodehandled[v] = true } ctaghandled[c.Tag] = true } } } // make sure all elements tags were handled for tag, _ := range o.Msh.CellTag2cells { if !ctaghandled[tag] { return chk.Err("geost: there are cells not included in any layer: ctag=%d", tag) } } // sort layers from top to bottom sort.Sort(L) // set previous/top states in layers and compute Sol.Y for i, lay := range L { // previous state var top *geostate ρS := lay.RhoS0 nf := lay.nf0 sl := 1.0 if i == 0 { pl := (o.Sim.WaterLevel - o.Sim.MaxElev) * o.Sim.WaterRho0 * grav ρL := o.Sim.WaterRho0 ρ := nf*sl*ρL + (1.0-nf)*ρS σV := -o.Sim.Data.Surch top = &geostate{pl, ρL, ρ, σV} } else { top, err = L[i-1].Calc(L[i-1].Zmin) if err != nil { return chk.Err("cannot compute state @ bottom of layer:\n%v", err) } ρL := top.ρL top.ρ = nf*sl*ρL + (1.0-nf)*ρS } // start layer lay.Start(top, grav) // set nodes for _, nod := range lay.Nodes { z := nod.Vert.C[ndim-1] s, err := lay.Calc(z) if err != nil { return chk.Err("cannot compute state @ node z = %g\n%v", z, err) } dof := nod.GetDof("pl") if dof != nil { o.Sol.Y[dof.Eq] = s.pl } } // set elements for _, elem := range lay.Elems { if ele, okk := elem.(ElemIntvars); okk { // build slices coords := ele.Ipoints() nip := len(coords) svT := make([]float64, nip) // total vertical stresses for i := 0; i < nip; i++ { z := coords[i][ndim-1] s, err := lay.Calc(z) if err != nil { return chk.Err("cannot compute state @ ip z = %g\n%v", z, err) } svT[i] = -s.σV } ivs := map[string][]float64{"svT": svT, "K0": []float64{lay.K0}} // set element's states err = ele.SetIniIvs(o.Sol, ivs) if err != nil { return chk.Err("geost: element's internal values setting failed:\n%v", err) } } } } return }
// Compute computes limits, find non-dominated Pareto fronts, and compute crowd distances func (o *Metrics) Compute(sols []*Solution) (nfronts int) { // reset variables and find limits z := o.Fsizes nsol := len(sols) for i, sol := range sols { // reset values sol.Nwins = 0 sol.Nlosses = 0 sol.FrontId = 0 sol.DistCrowd = 0 sol.DistNeigh = INF z[i] = 0 // check oors for j := 0; j < o.prms.Noor; j++ { if math.IsNaN(sol.Oor[j]) { chk.Panic("NaN found in out-of-range value array\n\txFlt = %v\n\txInt = %v\n\tova = %v\n\toor = %v", sol.Flt, sol.Int, sol.Ova, sol.Oor) } } // ovas range for j := 0; j < o.prms.Nova; j++ { x := sol.Ova[j] if math.IsNaN(x) { chk.Panic("NaN found in objective value array\n\txFlt = %v\n\txInt = %v\n\tova = %v\n\toor = %v", sol.Flt, sol.Int, sol.Ova, sol.Oor) } if i == 0 { o.Omin[j] = x o.Omax[j] = x } else { o.Omin[j] = utl.Min(o.Omin[j], x) o.Omax[j] = utl.Max(o.Omax[j], x) } } // floats range for j := 0; j < o.prms.Nflt; j++ { x := sol.Flt[j] if i == 0 { o.Fmin[j] = x o.Fmax[j] = x } else { o.Fmin[j] = utl.Min(o.Fmin[j], x) o.Fmax[j] = utl.Max(o.Fmax[j], x) } } // ints range for j := 0; j < o.prms.Nint; j++ { x := sol.Int[j] if i == 0 { o.Imin[j] = x o.Imax[j] = x } else { o.Imin[j] = utl.Imin(o.Imin[j], x) o.Imax[j] = utl.Imax(o.Imax[j], x) } } } // compute neighbour distance for i := 0; i < nsol; i++ { A := sols[i] for j := i + 1; j < nsol; j++ { B := sols[j] o.closest(A, B) } } // skip if single-objective problem if o.prms.Nova < 2 { return } // compute wins/losses data for i := 0; i < nsol; i++ { A := sols[i] for j := i + 1; j < nsol; j++ { B := sols[j] A_win, B_win := A.Compare(B) if A_win { A.WinOver[A.Nwins] = B A.Nwins++ B.Nlosses++ } if B_win { B.WinOver[B.Nwins] = A B.Nwins++ A.Nlosses++ } } } // first front for _, sol := range sols { if sol.Nlosses == 0 { o.Fronts[0][z[0]] = sol z[0]++ } } // next fronts for r, front := range o.Fronts { if z[r] == 0 { break } s := r + 1 nfronts++ for i := 0; i < z[r]; i++ { A := front[i] for j := 0; j < A.Nwins; j++ { B := A.WinOver[j] B.Nlosses-- if B.Nlosses == 0 { // B belongs to next front B.FrontId = s o.Fronts[s][z[s]] = B z[s]++ } } } } // crowd distances for r := 0; r < nfronts; r++ { l, m := z[r], z[r]-1 if l == 1 { o.Fronts[r][0].DistCrowd = -1 continue } F := o.Fronts[r][:l] for j := 0; j < o.prms.Nova; j++ { SortByOva(F, j) δ := o.Omax[j] - o.Omin[j] + 1e-15 F[0].DistCrowd = INF F[m].DistCrowd = INF for i := 1; i < m; i++ { F[i].DistCrowd += ((F[i].Ova[j] - F[i-1].Ova[j]) / δ) * ((F[i+1].Ova[j] - F[i].Ova[j]) / δ) } } } return }
func (o *RichardsonExtrap) Run(tf float64, dtFunc, dtoFunc fun.Func, verbose bool, dbgKb DebugKb_t) (err error) { // constants dat := o.doms[0].Sim.Solver atol := dat.REatol rtol := dat.RErtol mmin := dat.REmmin mmax := dat.REmmax mfac := dat.REmfac // control t := o.doms[0].Sol.T tout := t + dtoFunc.F(t, nil) steady := o.doms[0].Sim.Data.Steady // first output if o.sum != nil { err = o.sum.SaveDomains(t, o.doms, false) if err != nil { return chk.Err("cannot save results:\n%v", err) } } // domain and variables d := o.doms[0] o.Y_big = make([]float64, d.Ny) // time loop o.Δt = dtFunc.F(t, nil) o.Δtcpy = o.Δt var ΔtOld, rerrOld float64 for t < tf { // check for continued divergence if o.ndiverg >= dat.NdvgMax { return chk.Err("continuous divergence after %d steps reached", o.ndiverg) } // check time increment if o.Δt < dat.DtMin { return chk.Err("Δt increment is too small: %g < %g", o.Δt, dat.DtMin) } // dynamic coefficients if !steady { err = o.dc.CalcBoth(o.Δt) if err != nil { return chk.Err("cannot compute dynamic coefficients:\n%v", err) } } // check for maximum number of substeps o.nsteps += 1 if o.nsteps >= dat.REnssmax { return chk.Err("RE: max number of steps reached: %d", o.nsteps) } // backup domain d.backup() // single step with Δt d.Sol.T = t + o.Δt d.Sol.Dt = o.Δt o.diverging, err = run_iterations(t+o.Δt, o.Δt, d, o.dc, o.sum, dbgKb) if err != nil { return chk.Err("single step with Δt: run_iterations failed:\n%v", err) } if dat.DvgCtrl { if o.divergence_control(d, "big step", verbose) { continue } } // save intermediate state for i := 0; i < d.Ny; i++ { o.Y_big[i] = d.Sol.Y[i] } // restore initial state d.restore() // 1st halved step d.Sol.T = t + o.Δt/2.0 d.Sol.Dt = o.Δt / 2.0 o.diverging, err = run_iterations(t+o.Δt/2.0, o.Δt/2.0, d, o.dc, o.sum, dbgKb) if err != nil { return chk.Err("1st halved step: run_iterations failed:\n%v", err) } if dat.DvgCtrl { if o.divergence_control(d, "1st half step", verbose) { continue } } // 2nd halved step d.Sol.T = t + o.Δt d.Sol.Dt = o.Δt o.diverging, err = run_iterations(t+o.Δt, o.Δt/2.0, d, o.dc, o.sum, dbgKb) if err != nil { return chk.Err("2nd halved step: run_iterations failed:\n%v", err) } if dat.DvgCtrl { if o.divergence_control(d, "2nd half step", verbose) { continue } } // Richardson's extrapolation error rerr := la.VecRmsError(d.Sol.Y, o.Y_big, atol, rtol, d.Sol.Y) / 3.0 // step size change m := utl.Min(mmax, utl.Max(mmin, mfac*math.Pow(1.0/rerr, 1.0/2.0))) ΔtNew := m * o.Δt // accepted if rerr < 1.0 { // update variables o.naccept += 1 t += o.Δt d.Sol.T = t // output if verbose { if !dat.ShowR { io.PfWhite("%30.15f\r", t) } } if t >= tout || o.laststep { if o.sum != nil { err = o.sum.SaveDomains(t, o.doms, false) if err != nil { return chk.Err("cannot save results:\n%v", err) } } tout += dtoFunc.F(t, nil) } // reached final time if o.laststep { if verbose { io.Pfgreen("\n\nRichardson extrapolation succeeded\n") } return } // predictive controller of Gustafsson if !dat.REnogus { if o.naccept > 1 { m = mfac * (o.Δt / ΔtOld) * math.Sqrt(1.0/rerr) * math.Sqrt(rerrOld/rerr) if m*o.Δt < ΔtNew { o.ngustaf += 1 } ΔtNew = utl.Min(ΔtNew, m*o.Δt) } ΔtOld = o.Δt rerrOld = utl.Max(0.9, rerr) // 1e-2 } // next step size if o.reject { // do not alow Δt to grow if previous was a reject ΔtNew = utl.Min(o.Δt, ΔtNew) } o.reject = false o.Δt = ΔtNew if t+ΔtNew-tf >= 0.0 { o.laststep = true o.Δt = tf - t } // rejected } else { // restore state d.restore() // set flags o.nreject += 1 o.reject = true o.laststep = false // next step size o.Δt = ΔtNew if t+o.Δt > tf { o.Δt = tf - t } } } return }
func (o *Plotter) Plot_p_q(x, y []float64, res []*State, sts [][]float64, last bool) { // stress path nr := len(res) k := nr - 1 var xmi, xma, ymi, yma float64 for i := 0; i < nr; i++ { x[i], y[i] = o.P[i], o.Q[i] if o.Multq { mult := fun.Sign(o.W[i]) y[i] *= mult } if o.UseOct { x[i] *= tsr.SQ3 y[i] *= tsr.SQ2by3 } if i == 0 { xmi, xma = x[i], x[i] ymi, yma = y[i], y[i] } else { xmi = utl.Min(xmi, x[i]) xma = utl.Max(xma, x[i]) ymi = utl.Min(ymi, y[i]) yma = utl.Max(yma, y[i]) } if o.SMPon { x[i], y[i], _ = tsr.M_pq_smp(res[i].Sig, o.SMPa, o.SMPb, o.SMPβ, o.SMPϵ) } } plt.Plot(x, y, io.Sf("'r.', ls='%s', clip_on=0, color='%s', marker='%s', label=r'%s'", o.Ls, o.Clr, o.Mrk, o.Lbl)) plt.PlotOne(x[0], y[0], io.Sf("'bo', clip_on=0, color='%s', marker='%s', ms=%d", o.SpClr, o.SpMrk, o.SpMs)) plt.PlotOne(x[k], y[k], io.Sf("'bs', clip_on=0, color='%s', marker='%s', ms=%d", o.SpClr, o.EpMrk, o.EpMs)) // yield surface if o.WithYs && o.m != nil { mx, my := 1.0, 1.0 if o.UseOct { mx, my = tsr.SQ3, tsr.SQ2by3 } if o.UsePmin { xmi = utl.Min(xmi, o.Pmin*mx) } if o.UsePmax { xma = utl.Max(xma, o.Pmax*mx) yma = utl.Max(yma, o.Pmax*my) } xmi, xma, ymi, yma = o.fix_range(xmi, xmi, xma, ymi, yma) if o.PqLims != nil { xmi, xma, ymi, yma = o.PqLims[0], o.PqLims[1], o.PqLims[2], o.PqLims[3] } //io.Pforan("xmi,xma ymi,yma = %v,%v %v,%v\n", xmi,xma, ymi,yma) dx := (xma - xmi) / float64(o.NptsPq-1) dy := (yma - ymi) / float64(o.NptsPq-1) xx := la.MatAlloc(o.NptsPq, o.NptsPq) yy := la.MatAlloc(o.NptsPq, o.NptsPq) za := la.MatAlloc(o.NptsPq, o.NptsPq) zb := la.MatAlloc(o.NptsPq, o.NptsPq) var p, q, σa, σb, σc, λ0, λ1, λ2 float64 v := NewState(len(res[0].Sig), len(res[0].Alp), false, len(res[0].EpsE) > 0) for k := 0; k < nr; k++ { copy(v.Alp, res[k].Alp) v.Dgam = res[k].Dgam for i := 0; i < o.NptsPq; i++ { for j := 0; j < o.NptsPq; j++ { xx[i][j] = xmi + float64(i)*dx yy[i][j] = ymi + float64(j)*dy p, q = xx[i][j], yy[i][j] if o.UseOct { p /= tsr.SQ3 q /= tsr.SQ2by3 } σa, σb, σc = tsr.PQW2O(p, q, o.W[k]) λ0, λ1, λ2 = tsr.O2L(σa, σb, σc) v.Sig[0], v.Sig[1], v.Sig[2] = λ0, λ1, λ2 ys := o.m.YieldFuncs(v) za[i][j] = ys[0] if o.nsurf > 1 { zb[i][j] = ys[1] } if o.SMPon { xx[i][j], yy[i][j], _ = tsr.M_pq_smp(v.Sig, o.SMPa, o.SMPb, o.SMPβ, o.SMPϵ) } } } plt.ContourSimple(xx, yy, za, false, 8, io.Sf("colors=['%s'], levels=[0], linestyles=['%s'], linewidths=[%g], clip_on=0", o.YsClr0, o.YsLs0, o.YsLw0)+o.ArgsYs) if o.nsurf > 1 { plt.ContourSimple(xx, yy, zb, false, 8, io.Sf("colors=['%s'], levels=[0], linestyles=['%s'], linewidths=[%g], clip_on=0", o.YsClr1, o.YsLs1, o.YsLw1)+o.ArgsYs) } } } // predictor-corrector if len(o.PreCor) > 1 { var p, q, pnew, qnew float64 for i := 1; i < len(o.PreCor); i++ { p = tsr.M_p(o.PreCor[i-1]) q = tsr.M_q(o.PreCor[i-1]) pnew = tsr.M_p(o.PreCor[i]) qnew = tsr.M_q(o.PreCor[i]) if o.UseOct { p *= tsr.SQ3 pnew *= tsr.SQ3 q *= tsr.SQ2by3 qnew *= tsr.SQ2by3 } if o.SMPon { p, q, _ = tsr.M_pq_smp(o.PreCor[i-1], o.SMPa, o.SMPb, o.SMPβ, o.SMPϵ) pnew, qnew, _ = tsr.M_pq_smp(o.PreCor[i], o.SMPa, o.SMPb, o.SMPβ, o.SMPϵ) } if math.Abs(pnew-p) > 1e-10 || math.Abs(qnew-q) > 1e-10 { plt.Arrow(p, q, pnew, qnew, io.Sf("sc=%d, fc='%s', ec='%s'", o.ArrWid, o.ClrPC, o.ClrPC)) } } } // settings if last { plt.Equal() xl, yl := "$p_{cam}$", "$q_{cam}$" if o.UseOct { xl, yl = "$p_{oct}$", "$q_{oct}$" } if o.SMPon { xl, yl = "$p_{smp}$", "$q_{smp}$" } if o.AxLblX != "" { xl = o.AxLblX } if o.AxLblY != "" { yl = o.AxLblY } plt.Gll(xl, yl, "leg_out=1, leg_ncol=4, leg_hlen=1.5") if lims, ok := o.Lims["p,q"]; ok { plt.AxisLims(lims) } if lims, ok := o.Lims["p,q,ys"]; ok { plt.AxisLims(lims) } } }
// RunMany runs many trials in order to produce statistical data func (o *Optimiser) RunMany(dirout, fnkey string) { // benchmark t0 := time.Now() defer func() { o.SysTimeTot = time.Now().Sub(t0) var tmp int64 for _, dur := range o.SysTimes { tmp += dur.Nanoseconds() } tmp /= int64(o.Nsamples) o.SysTimeAve = time.Duration(tmp) }() // disable verbose flag temporarily if o.Verbose { defer func() { o.Verbose = true }() o.Verbose = false } // remove previous results if fnkey != "" { io.RemoveAll(dirout + "/" + fnkey + "-*.res") } // allocate variables o.SysTimes = make([]time.Duration, o.Nsamples) o.BestOvas = make([][]float64, o.Nova) o.BestFlts = make([][]float64, o.Nflt) o.BestInts = make([][]int, o.Nint) o.BestOfBestOva = make([]float64, o.Nova) o.BestOfBestFlt = make([]float64, o.Nflt) o.BestOfBestInt = make([]int, o.Nint) // perform trials for itrial := 0; itrial < o.Nsamples; itrial++ { // re-generate solutions o.Nfeval = 0 if itrial > 0 { o.generate_solutions(itrial) } // save initial solutions if fnkey != "" { WriteAllValues(dirout, io.Sf("%s-%04d_ini", fnkey, itrial), o) } // message if o.VerbStat { io.Pf(". . . running trial # %d\n", itrial) } // solve timeIni := time.Now() o.Solve() o.SysTimes[itrial] = time.Now().Sub(timeIni) // sort if o.Nova > 1 { // multi-objective SortByFrontThenOva(o.Solutions, 0) } else { // single-objective SortByOva(o.Solutions, 0) } // feasible solution if o.Solutions[0].Feasible() { // best solution best := o.Solutions[0] for i := 0; i < o.Nova; i++ { o.BestOvas[i] = append(o.BestOvas[i], best.Ova[i]) } for i := 0; i < o.Nflt; i++ { o.BestFlts[i] = append(o.BestFlts[i], best.Flt[i]) } for i := 0; i < o.Nint; i++ { o.BestInts[i] = append(o.BestInts[i], best.Int[i]) } // best of all trials first_best := len(o.BestOvas[0]) == 1 if first_best { copy(o.BestOfBestOva, best.Ova) copy(o.BestOfBestFlt, best.Flt) copy(o.BestOfBestInt, best.Int) } else { if best.Ova[0] < o.BestOfBestOva[0] { copy(o.BestOfBestOva, best.Ova) copy(o.BestOfBestFlt, best.Flt) copy(o.BestOfBestInt, best.Int) } } // check multi-objective results if o.F1F0_func != nil { var rms_err float64 var nfeasible int for _, sol := range o.Solutions { if sol.Feasible() && sol.FrontId == 0 { f0, f1 := sol.Ova[0], sol.Ova[1] f1_cor := o.F1F0_func(f0) rms_err += math.Pow(f1-f1_cor, 2.0) nfeasible++ } } if nfeasible > 0 { rms_err = math.Sqrt(rms_err / float64(nfeasible)) o.F1F0_err = append(o.F1F0_err, rms_err) } } // arc-length along Pareto front if o.Nova == 2 { if best.Feasible() && best.FrontId == 0 && o.Solutions[1].FrontId == 0 { dist := 0.0 for i := 1; i < o.Nsol; i++ { if o.Solutions[i].FrontId == 0 { F0, F1 := o.Solutions[i-1].Ova[0], o.Solutions[i-1].Ova[1] f0, f1 := o.Solutions[i].Ova[0], o.Solutions[i].Ova[1] if o.F1F0_f0ranges != nil { a := o.find_f0_spot(F0) b := o.find_f0_spot(f0) if a == -1 || b == -1 { continue } if a != b { //io.Pforan("\nF0=%g is in [%g,%g]\n", F0, o.F1F0_f0ranges[a][0], o.F1F0_f0ranges[a][1]) //io.Pfpink("f0=%g is in [%g,%g]\n", f0, o.F1F0_f0ranges[b][0], o.F1F0_f0ranges[b][1]) continue } } dist += math.Sqrt(math.Pow(f0-F0, 2.0) + math.Pow(f1-F1, 2.0)) } } o.F1F0_arcLen = append(o.F1F0_arcLen, dist) } } // multiple OVAs if o.Nova > 1 && o.Multi_fcnErr != nil { var rms_err float64 var nfeasible int for _, sol := range o.Solutions { if sol.Feasible() && sol.FrontId == 0 { f_err := o.Multi_fcnErr(sol.Ova) rms_err += f_err * f_err nfeasible++ } } if nfeasible > 0 { rms_err = math.Sqrt(rms_err / float64(nfeasible)) o.Multi_err = append(o.Multi_err, rms_err) } } // IGD metric if o.Nova > 1 && len(o.Multi_fStar) > 0 { o.Multi_IGD = append(o.Multi_IGD, StatIgd(o, o.Multi_fStar)) } // save final solutions if fnkey != "" { f0min := best.Ova[0] for _, sol := range o.Solutions { f0min = utl.Min(f0min, sol.Ova[0]) } WriteAllValues(dirout, io.Sf("%s-%04d_f0min=%g", fnkey, itrial, f0min), o) } } } }
// NodesOnPlane finds vertices located on {x,y,z} plane and returns an iterator // that can be used to extract results on the plane. An {u,v}-coordinates system is built // on the plane. // Input: // ftag -- cells' face tag; e.g. -31 // Output: // dat -- plane data holding vertices on plane and other information; see above // Note: // 1) this function works with 3D cells only // 2) faces on cells must be either "qua4" or "qua8" types // 3) middle nodes in "qua8" are disregarded in order to buidl an {u,v} grid // 4) the resulting mesh on plane must be equally spaced; i.e. Δx and Δy are constant; // but not necessarily equal to each other func NodesOnPlane(ftag int) *PlaneData { // check ndim := Dom.Msh.Ndim if ndim != 3 { chk.Panic("this function works in 3D only") } // loop over cells on face with given face tag var dat PlaneData dat.Plane = -1 dat.Ids = make(map[int]bool) dat.Dx = make([]float64, ndim) Δx := make([]float64, ndim) first := true cells := Dom.Msh.FaceTag2cells[ftag] for _, cell := range cells { for fidx, cftag := range cell.C.FTags { if cftag == ftag { // check face type ftype := cell.C.Shp.FaceType if !(ftype == "qua4" || ftype == "qua8") { chk.Panic("can only handle qua4 or qua8 faces for now. ftype=%q", ftype) } // vertices on face flvids := cell.C.Shp.FaceLocalVerts[fidx] nv := len(flvids) if nv == 8 { nv = 4 // avoid middle nodes } for i := 0; i < nv; i++ { vid := cell.C.Verts[flvids[i]] dat.Ids[vid] = true } // compute and check increments in global coordinates for i := 1; i < nv; i++ { a := cell.C.Verts[flvids[i]] b := cell.C.Verts[flvids[i-1]] xa := Dom.Msh.Verts[a].C xb := Dom.Msh.Verts[b].C for j := 0; j < ndim; j++ { Δx[j] = utl.Max(Δx[j], math.Abs(xa[j]-xb[j])) } } if first { for j := 0; j < ndim; j++ { dat.Dx[j] = Δx[j] } first = false } else { for j := 0; j < ndim; j++ { if math.Abs(dat.Dx[j]-Δx[j]) > 1e-10 { chk.Panic("all faces must have the same Δx,Δy,Δz") } } } // find which plane vertices are located on => which plane this face is parallel to perpto := -1 // "perpendicular to" indicator switch { case Δx[0] < DIST_TOL: // plane perpendicular to x-axis perpto = 0 case Δx[1] < DIST_TOL: // plane perpendicular to y-axis perpto = 1 case Δx[2] < DIST_TOL: // plane perpendicular to z-axis perpto = 2 default: chk.Panic("planes must be perpendicular to one of the x-y-z axes") } if dat.Plane < 0 { dat.Plane = perpto } else { if perpto != dat.Plane { chk.Panic("all planes must be perperdicular to the same axis") } } } } } // uv: indices and increments dat.Iu = make([]int, 2) dat.Du = make([]float64, 2) switch dat.Plane { case 0: // plane perpendicular to x-axis dat.Iu = []int{1, 2} case 1: // plane perpendicular to y-axis dat.Iu = []int{0, 2} case 2: // plane perpendicular to z-axis dat.Iu = []int{0, 1} } for j := 0; j < 2; j++ { dat.Du[j] = dat.Dx[dat.Iu[j]] } // uv: limits dat.Umin = make([]float64, 2) dat.Umax = make([]float64, 2) first = true for vid, _ := range dat.Ids { x := Dom.Msh.Verts[vid].C if first { for j := 0; j < 2; j++ { dat.Umin[j] = x[dat.Iu[j]] dat.Umax[j] = x[dat.Iu[j]] } first = false } else { for j := 0; j < 2; j++ { dat.Umin[j] = utl.Min(dat.Umin[j], x[dat.Iu[j]]) dat.Umax[j] = utl.Max(dat.Umax[j], x[dat.Iu[j]]) } } } // uv: size of grid dat.Nu = make([]int, 2) for j := 0; j < 2; j++ { dat.Nu[j] = int((dat.Umax[j]-dat.Umin[j])/dat.Du[j]) + 1 } // uv: bins dd := DIST_TOL * 2 nb := 20 dat.Ubins.Init([]float64{dat.Umin[0] - dd, dat.Umin[1] - dd}, []float64{dat.Umax[0] + dd, dat.Umax[1] + dd}, nb) u := []float64{0, 0} for vid, _ := range dat.Ids { x := Dom.Msh.Verts[vid].C for j := 0; j < 2; j++ { u[j] = x[dat.Iu[j]] } err := dat.Ubins.Append(u, vid) if err != nil { chk.Panic("cannot append {u,v} coordinate to bins. u=%v", u) } } // allocate F dat.F = la.MatAlloc(dat.Nu[0], dat.Nu[1]) return &dat }
func (o *Plotter) Plot_oct(x, y []float64, res []*State, sts [][]float64, last bool) { // stress path nr := len(res) k := nr - 1 var σa, σb, xmi, xma, ymi, yma float64 for i := 0; i < nr; i++ { σa, σb, _ = tsr.PQW2O(o.P[i], o.Q[i], o.W[i]) x[i], y[i] = σa, σb o.maxR = utl.Max(o.maxR, math.Sqrt(σa*σa+σb*σb)) if i == 0 { xmi, xma = x[i], x[i] ymi, yma = y[i], y[i] } else { xmi = utl.Min(xmi, x[i]) xma = utl.Max(xma, x[i]) ymi = utl.Min(ymi, y[i]) yma = utl.Max(yma, y[i]) } } plt.Plot(x, y, io.Sf("'r.', ls='%s', clip_on=0, color='%s', marker='%s', label=r'%s'", o.Ls, o.Clr, o.Mrk, o.Lbl)) plt.PlotOne(x[0], y[0], io.Sf("'bo', clip_on=0, color='%s', marker='%s', ms=%d", o.SpClr, o.SpMrk, o.SpMs)) plt.PlotOne(x[k], y[k], io.Sf("'bs', clip_on=0, color='%s', marker='%s', ms=%d", o.SpClr, o.EpMrk, o.EpMs)) // fix range and max radius xmi, xma, ymi, yma = o.fix_range(0, xmi, xma, ymi, yma) rr := math.Sqrt((xma-xmi)*(xma-xmi) + (yma-ymi)*(yma-ymi)) if o.maxR < rr { o.maxR = rr } if o.maxR < 1e-10 { o.maxR = 1 } if yma > -xmi { xmi = -yma } if o.OctLims != nil { xmi, xma, ymi, yma = o.OctLims[0], o.OctLims[1], o.OctLims[2], o.OctLims[3] } //xmi, xma, ymi, yma = -20000, 20000, -20000, 20000 // yield surface var σcmax float64 if o.WithYs && o.m != nil { //io.Pforan("xmi,xma ymi,yma = %v,%v %v,%v\n", xmi,xma, ymi,yma) dx := (xma - xmi) / float64(o.NptsOct-1) dy := (yma - ymi) / float64(o.NptsOct-1) xx := la.MatAlloc(o.NptsOct, o.NptsOct) yy := la.MatAlloc(o.NptsOct, o.NptsOct) zz := la.MatAlloc(o.NptsOct, o.NptsOct) var λ0, λ1, λ2, σc float64 v := NewState(len(res[0].Sig), len(res[0].Alp), false, len(res[0].EpsE) > 0) for k := 0; k < nr; k++ { copy(v.Alp, res[k].Alp) v.Dgam = res[k].Dgam σc = tsr.M_p(res[k].Sig) * tsr.SQ3 //σc = 30000 σcmax = utl.Max(σcmax, σc) for i := 0; i < o.NptsOct; i++ { for j := 0; j < o.NptsOct; j++ { xx[i][j] = xmi + float64(i)*dx yy[i][j] = ymi + float64(j)*dy λ0, λ1, λ2 = tsr.O2L(xx[i][j], yy[i][j], σc) v.Sig[0], v.Sig[1], v.Sig[2] = λ0, λ1, λ2 ys := o.m.YieldFuncs(v) zz[i][j] = ys[0] } } plt.ContourSimple(xx, yy, zz, false, 8, io.Sf("colors=['%s'], levels=[0], linestyles=['%s'], linewidths=[%g], clip_on=0", o.YsClr0, o.YsLs0, o.YsLw0)+o.ArgsYs) } } // predictor-corrector if len(o.PreCor) > 1 { var σa, σb, σanew, σbnew float64 for i := 1; i < len(o.PreCor); i++ { σa, σb, _ = tsr.M_oct(o.PreCor[i-1]) σanew, σbnew, _ = tsr.M_oct(o.PreCor[i]) if math.Abs(σanew-σa) > 1e-7 || math.Abs(σbnew-σb) > 1e-7 { //plt.Plot([]float64{σa,σanew}, []float64{σb,σbnew}, "'k+', ms=3, color='k'") plt.Arrow(σa, σb, σanew, σbnew, io.Sf("sc=%d, fc='%s', ec='%s'", o.ArrWid, o.ClrPC, o.ClrPC)) } o.maxR = utl.Max(o.maxR, math.Sqrt(σa*σa+σb*σb)) o.maxR = utl.Max(o.maxR, math.Sqrt(σanew*σanew+σbnew*σbnew)) } } // rosette and settings if last { tsr.PlotRefOct(o.Phi, σcmax, true) tsr.PlotRosette(o.maxR, false, true, true, 6) if o.OctAxOff { plt.AxisOff() } plt.Gll("$\\sigma_a$", "$\\sigma_b$", "") if lims, ok := o.Lims["oct"]; ok { plt.AxisLims(lims) } if lims, ok := o.Lims["oct,ys"]; ok { plt.AxisLims(lims) } } }
func (o *Plotter) Plot_s3_s1(x, y []float64, res []*State, sts [][]float64, last bool) { // stress path nr := len(res) k := nr - 1 x2 := make([]float64, nr) var xmi, xma, ymi, yma float64 for i := 0; i < nr; i++ { σ1, σ2, σ3, err := tsr.M_PrincValsNum(res[i].Sig) if err != nil { chk.Panic("computation of eigenvalues failed", err) } x[i], y[i] = -tsr.SQ2*σ3, -σ1 x2[i] = -tsr.SQ2 * σ2 if i == 0 { xmi, xma = x[i], x[i] ymi, yma = y[i], y[i] } else { xmi = utl.Min(utl.Min(xmi, x[i]), x2[i]) xma = utl.Max(utl.Max(xma, x[i]), x2[i]) ymi = utl.Min(ymi, y[i]) yma = utl.Max(yma, y[i]) } } plt.Plot(x, y, io.Sf("'r.', ls='%s', clip_on=0, color='%s', marker='%s', label=r'$\\sigma_3$ %s'", o.Ls, o.Clr, o.Mrk, o.Lbl)) plt.Plot(x2, y, io.Sf("'r.', ls='%s', clip_on=0, color='%s', marker='%s', label=r'$\\sigma_2$ %s'", o.LsAlt, o.Clr, o.Mrk, o.Lbl)) plt.PlotOne(x[0], y[0], io.Sf("'bo', clip_on=0, color='%s', marker='%s', ms=%d", o.SpClr, o.SpMrk, o.SpMs)) plt.PlotOne(x[k], y[k], io.Sf("'bs', clip_on=0, color='%s', marker='%s', ms=%d", o.SpClr, o.EpMrk, o.EpMs)) // yield surface if o.WithYs && o.m != nil { if o.UsePmin { xmi = utl.Min(xmi, o.Pmin*tsr.SQ2) ymi = utl.Min(ymi, o.Pmin) } if o.UsePmax { xma = utl.Max(xma, o.Pmax*tsr.SQ2) yma = utl.Max(yma, o.Pmax) } xmi, xma, ymi, yma = o.fix_range(0, xmi, xma, ymi, yma) if o.S3s1Lims != nil { xmi, xma, ymi, yma = o.S3s1Lims[0], o.S3s1Lims[1], o.S3s1Lims[2], o.S3s1Lims[3] } //io.Pforan("xmi,xma ymi,yma = %v,%v %v,%v\n", xmi,xma, ymi,yma) dx := (xma - xmi) / float64(o.NptsSig-1) dy := (yma - ymi) / float64(o.NptsSig-1) xx := la.MatAlloc(o.NptsSig, o.NptsSig) yy := la.MatAlloc(o.NptsSig, o.NptsSig) zz := la.MatAlloc(o.NptsSig, o.NptsSig) v := NewState(len(res[0].Sig), len(res[0].Alp), false, len(res[0].EpsE) > 0) for k := 0; k < nr; k++ { copy(v.Alp, res[k].Alp) v.Dgam = res[k].Dgam for i := 0; i < o.NptsSig; i++ { for j := 0; j < o.NptsSig; j++ { xx[i][j] = xmi + float64(i)*dx yy[i][j] = ymi + float64(j)*dy v.Sig[0], v.Sig[1], v.Sig[2] = -yy[i][j], -xx[i][j]/tsr.SQ2, -xx[i][j]/tsr.SQ2 ys := o.m.YieldFuncs(v) zz[i][j] = ys[0] } } plt.ContourSimple(xx, yy, zz, false, 8, io.Sf("colors=['%s'], levels=[0], linestyles=['%s'], linewidths=[%g], clip_on=0", o.YsClr0, o.YsLs0, o.YsLw0)+o.ArgsYs) } } // predictor-corrector if len(o.PreCor) > 1 { var σ3, σ1, σ3new, σ1new float64 for i := 1; i < len(o.PreCor); i++ { σ1, _, σ3, _ = tsr.M_PrincValsNum(o.PreCor[i-1]) σ1new, _, σ3new, _ = tsr.M_PrincValsNum(o.PreCor[i]) if math.Abs(σ3new-σ3) > 1e-7 || math.Abs(σ1new-σ1) > 1e-7 { plt.Arrow(-σ3*tsr.SQ2, -σ1, -σ3new*tsr.SQ2, -σ1new, io.Sf("sc=%d, fc='%s', ec='%s'", o.ArrWid, o.ClrPC, o.ClrPC)) } } } // settings if last { plt.Equal() plt.Gll("$-\\sqrt{2}\\sigma_3$", "$-\\sigma_1$", "leg=1, leg_out=1, leg_ncol=4, leg_hlen=2") if lims, ok := o.Lims["s3,s1"]; ok { plt.AxisLims(lims) } if lims, ok := o.Lims["s3,s1,ys"]; ok { plt.AxisLims(lims) } } }
// WriteMshD writes .msh file // Input: // vtagged -- maps hashed id of control point to vertex tag // ctagged -- maps idOfNurbs_localIdOfElem to cell tag // tol -- tolerance for normalized numbers comparison when generating hashes, e.g. 1e-7 func WriteMshD(dirout, fnk string, nurbss []*Nurbs, vtagged map[int]int, ctagged map[string]int, tol float64) { // compute limits xmin, xmax, xdel := GetLimits(nurbss[0]) for r := 1; r < len(nurbss); r++ { xmi, xma, _ := GetLimits(nurbss[r]) for i := 0; i < 3; i++ { xmin[i] = utl.Min(xmin[i], xmi[i]) xmax[i] = utl.Min(xmax[i], xma[i]) } } if len(nurbss) > 1 { for i := 0; i < 3; i++ { xdel[i] = xmax[i] - xmin[i] } } var buf bytes.Buffer io.Ff(&buf, "{\n \"verts\" : [\n") verts := make(map[int]int) vid := 0 for _, o := range nurbss { for k := 0; k < o.n[2]; k++ { for j := 0; j < o.n[1]; j++ { for i := 0; i < o.n[0]; i++ { x := o.GetQ(i, j, k) hsh := HashPoint(x, xmin, xdel, tol) if _, ok := verts[hsh]; !ok { tag := 0 if vtagged != nil { if val, tok := vtagged[hsh]; tok { tag = val } } // TODO: remove this if math.Abs(x[0]) < 1e-7 { tag = -100 // vertical } if math.Abs(x[1]) < 1e-7 { tag = -200 // horizontal } if len(verts) > 0 { io.Ff(&buf, ",\n") } io.Ff(&buf, " { \"id\":%3d, \"tag\":%3d, \"c\":[%24.17e,%24.17e,%24.17e,%24.17e] }", vid, tag, x[0], x[1], x[2], x[3]) verts[hsh] = vid vid += 1 } } } } } io.Ff(&buf, "\n ],\n \"nurbss\" : [\n") for sid, o := range nurbss { if sid > 0 { io.Ff(&buf, ",\n") } io.Ff(&buf, " { \"id\":%d, \"gnd\":%d, \"ords\":[%d,%d,%d],\n", sid, o.gnd, o.p[0], o.p[1], o.p[2]) io.Ff(&buf, " \"knots\":[\n") for d := 0; d < o.gnd; d++ { if d > 0 { io.Ff(&buf, ",\n") } io.Ff(&buf, " [") for i, t := range o.b[d].T { if i > 0 { io.Ff(&buf, ",") } io.Ff(&buf, "%24.17e", t) } io.Ff(&buf, "]") } io.Ff(&buf, "\n ],\n \"ctrls\":[") first := true for k := 0; k < o.n[2]; k++ { for j := 0; j < o.n[1]; j++ { for i := 0; i < o.n[0]; i++ { if !first { io.Ff(&buf, ",") } x := o.GetQ(i, j, k) hsh := HashPoint(x, xmin, xdel, tol) io.Ff(&buf, "%d", verts[hsh]) if first { first = false } } } } io.Ff(&buf, "]\n }") } io.Ff(&buf, "\n ],\n \"cells\" : [\n") ndim := nurbss[0].gnd bry := make([]bool, 2*ndim) fti2d := []int{2, 1, 3, 0} ftags := []int{-10, -11, -20, -21, -30, -31} cid := 0 for sid, o := range nurbss { spanmin := make([]int, ndim) spanmax := make([]int, ndim) for i := 0; i < ndim; i++ { spanmin[i] = o.p[i] spanmax[i] = o.n[i] // TODO: check this } elems := o.Elements() for eid, e := range elems { ibasis := o.IndBasis(e) if cid > 0 { io.Ff(&buf, ",\n") } tag := -1 if ctagged != nil { if val, tok := ctagged[io.Sf("%d_%d", sid, eid)]; tok { tag = val } } // TODO: find a better way to tag cells if e[1] == spanmax[0] && e[2] == spanmin[1] { tag = -2 } io.Ff(&buf, " { \"id\":%3d, \"tag\":%2d, \"nrb\":%d, \"part\":0, \"type\":\"nurbs\",", cid, tag, sid) io.Ff(&buf, " \"span\":[") for k, idx := range e { if k > 0 { io.Ff(&buf, ",") } io.Ff(&buf, "%d", idx) } io.Ff(&buf, "], \"verts\":[") for i, l := range ibasis { if i > 0 { io.Ff(&buf, ",") } x := o.GetQl(l) hsh := HashPoint(x, xmin, xdel, tol) io.Ff(&buf, "%d", verts[hsh]) } var onbry bool for i := 0; i < 2*ndim; i++ { bry[i] = false } for i := 0; i < ndim; i++ { smin, smax := e[i*ndim], e[i*ndim+1] if smin == spanmin[i] { bry[i*ndim] = true onbry = true } if smax == spanmax[i] { bry[i*ndim+1] = true onbry = true } } io.Ff(&buf, "]") if onbry && ndim > 1 { io.Ff(&buf, ", \"ftags\":[") for i := 0; i < 2*ndim; i++ { tag := 0 I := i if ndim == 2 { I = fti2d[i] } if bry[I] { if ndim == 2 { tag = ftags[fti2d[i]] // TODO: replace this by a better approach if i == 2 { r := spanmin[0] + (spanmax[0]-spanmin[0])/2 //io.Pforan("e[0]=%v r=%v\n", e[0], r) if e[0] >= r { tag = -24 } } } else { tag = ftags[i] } } if i > 0 { io.Ff(&buf, ",") } io.Ff(&buf, "%d", tag) } io.Ff(&buf, "]") } io.Ff(&buf, " }") cid += 1 } } io.Ff(&buf, "\n ]\n}") io.WriteFileVD(dirout, fnk+".msh", &buf) }
func Test_flt03(tst *testing.T) { //verbose() chk.PrintTitle("flt03. sin⁶(5 π x) multimodal") // configuration C := NewConfParams() C.Nova = 1 C.Noor = 2 C.Nisl = 4 C.Ninds = 24 C.GAtype = "crowd" C.DiffEvol = true C.CrowdSize = 3 C.ParetoPhi = 0.01 C.CompProb = true C.Tf = 100 C.Dtmig = 60 C.RangeFlt = [][]float64{{0, 0.9999999999999}} C.PopFltGen = PopFltGen C.CalcDerived() rnd.Init(C.Seed) // post-processing function values := utl.Deep3alloc(C.Tf/10, C.Nisl, C.Ninds) C.PostProc = func(idIsland, time int, pop Population) { if time%10 == 0 { k := time / 10 for i, ind := range pop { values[k][idIsland][i] = ind.GetFloat(0) } } } // functions yfcn := func(x float64) float64 { return math.Pow(math.Sin(5.0*math.Pi*x), 6.0) } fcn := func(f, g, h []float64, x []float64) { f[0] = -yfcn(x[0]) } // simple problem sim := NewSimpleFltProb(fcn, 1, 0, 0, C) sim.Run(chk.Verbose) // write histograms and plot if chk.Verbose { // write histograms var buf bytes.Buffer hist := rnd.Histogram{Stations: utl.LinSpace(0, 1, 13)} for k := 0; k < C.Tf/10; k++ { for i := 0; i < C.Nisl; i++ { clear := false if i == 0 { clear = true } hist.Count(values[k][i], clear) } io.Ff(&buf, "\ntime=%d\n%v", k*10, rnd.TextHist(hist.GenLabels("%4.2f"), hist.Counts, 60)) } io.WriteFileVD("/tmp/goga", "test_flt03_hist.txt", &buf) // plot plt.SetForEps(0.8, 300) xmin := sim.Evo.Islands[0].Pop[0].GetFloat(0) xmax := xmin for k := 0; k < C.Nisl; k++ { for _, ind := range sim.Evo.Islands[k].Pop { x := ind.GetFloat(0) y := yfcn(x) xmin = utl.Min(xmin, x) xmax = utl.Max(xmax, x) plt.PlotOne(x, y, "'r.',clip_on=0,zorder=20") } } np := 401 X := utl.LinSpace(0, 1, np) Y := make([]float64, np) for i := 0; i < np; i++ { Y[i] = yfcn(X[i]) } plt.Plot(X, Y, "'b-',clip_on=0,zorder=10") plt.Gll("$x$", "$y$", "") plt.SaveD("/tmp/goga", "test_flt03_func.eps") } }
// Start starts handling of results given a simulation input file func Start(simfnpath string, stageIdx, regionIdx int) { // fem structure Analysis = fem.NewFEM(simfnpath, "", false, false, true, false, false, 0) Dom = Analysis.Domains[regionIdx] Sum = Analysis.Summary // set stage err := Analysis.SetStage(stageIdx) if err != nil { chk.Panic("cannot set stage:\n%v", err) } // initialise solution vectors err = Analysis.ZeroStage(stageIdx, true) if err != nil { chk.Panic("cannot initialise solution vectors:\n%v", err) } // clear previous data Ipoints = make([]*fem.OutIpData, 0) Cid2ips = make([][]int, len(Dom.Msh.Cells)) Ipkey2ips = make(map[string][]int) Ipkeys = make(map[string]bool) Planes = make(map[string]*PlaneData) Results = make(map[string]Points) TimeInds = make([]int, 0) Times = make([]float64, 0) Splots = make([]*SplotDat, 0) // bins m := Dom.Msh δ := TolC * 2 xi := []float64{m.Xmin - δ, m.Ymin - δ} xf := []float64{m.Xmax + δ, m.Ymax + δ} if m.Ndim == 3 { xi = append(xi, m.Zmin-δ) xf = append(xf, m.Zmax+δ) } err = NodBins.Init(xi, xf, Ndiv) if err != nil { chk.Panic("cannot initialise bins for nodes: %v", err) } err = IpsBins.Init(xi, xf, Ndiv) if err != nil { chk.Panic("cannot initialise bins for integration points: %v", err) } // add nodes to bins for _, nod := range Dom.Nodes { err := NodBins.Append(nod.Vert.C, nod.Vert.Id) if err != nil { return } } // to find limits ndim := Dom.Msh.Ndim IpsMin = make([]float64, ndim) IpsMax = make([]float64, ndim) first := true // add integration points to slice of ips and to bins for cid, ele := range Dom.Cid2elem { if ele == nil { continue } dat := ele.OutIpsData() nip := len(dat) ids := make([]int, nip) for i, d := range dat { // add to bins ipid := len(Ipoints) ids[i] = ipid Ipoints = append(Ipoints, d) err = IpsBins.Append(d.X, ipid) if err != nil { chk.Panic("cannot append to bins of integration points: %v", err) } // set auxiliary map vals := d.Calc(Dom.Sol) for key, _ := range vals { utl.StrIntsMapAppend(&Ipkey2ips, key, ipid) Ipkeys[key] = true } // limits if first { for j := 0; j < ndim; j++ { IpsMin[j] = d.X[j] IpsMax[j] = d.X[j] } first = false } else { for j := 0; j < ndim; j++ { IpsMin[j] = utl.Min(IpsMin[j], d.X[j]) IpsMax[j] = utl.Max(IpsMax[j], d.X[j]) } } } Cid2ips[cid] = ids } }
// ReadMsh reads a mesh for FE analyses // Note: returns nil on errors func ReadMsh(dir, fn string, goroutineId int) (o *Mesh, err error) { // new mesh o = new(Mesh) // read file o.FnamePath = filepath.Join(dir, fn) b, err := io.ReadFile(o.FnamePath) if err != nil { return } // decode err = json.Unmarshal(b, &o) if err != nil { return } // check if len(o.Verts) < 2 { err = chk.Err("at least 2 vertices are required in mesh\n") return } if len(o.Cells) < 1 { err = chk.Err("at least 1 cell is required in mesh\n") return } // variables for NURBS var controlpts [][]float64 has_nurbs := false if len(o.Nurbss) > 0 { controlpts = make([][]float64, len(o.Verts)) has_nurbs = true } // vertex related derived data o.Ndim = 2 o.Xmin = o.Verts[0].C[0] o.Ymin = o.Verts[0].C[1] if len(o.Verts[0].C) > 2 { o.Zmin = o.Verts[0].C[2] } o.Xmax = o.Xmin o.Ymax = o.Ymin o.Zmax = o.Zmin o.VertTag2verts = make(map[int][]*Vert) for i, v := range o.Verts { // check vertex id if v.Id != i { err = chk.Err("vertices ids must coincide with order in \"verts\" list. %d != %d\n", v.Id, i) return } // ndim nd := len(v.C) if nd < 2 || nd > 4 { err = chk.Err("number of space dimensions must be 2, 3 or 4 (NURBS). %d is invalid\n", nd) return } if nd == 3 { if math.Abs(v.C[2]) > Ztol { o.Ndim = 3 } } // tags if v.Tag < 0 { verts := o.VertTag2verts[v.Tag] o.VertTag2verts[v.Tag] = append(verts, v) } // limits o.Xmin = utl.Min(o.Xmin, v.C[0]) o.Xmax = utl.Max(o.Xmax, v.C[0]) o.Ymin = utl.Min(o.Ymin, v.C[1]) o.Ymax = utl.Max(o.Ymax, v.C[1]) if nd > 2 { o.Zmin = utl.Min(o.Zmin, v.C[2]) o.Zmax = utl.Max(o.Zmax, v.C[2]) } // control points to initialise NURBS if has_nurbs { controlpts[i] = make([]float64, 4) for j := 0; j < 4; j++ { controlpts[i][j] = v.C[j] } } } // allocate NURBSs o.PtNurbs = make([]*gm.Nurbs, len(o.Nurbss)) o.NrbFaces = make([][]*gm.Nurbs, len(o.Nurbss)) for i, d := range o.Nurbss { o.PtNurbs[i] = new(gm.Nurbs) o.PtNurbs[i].Init(d.Gnd, d.Ords, d.Knots) o.PtNurbs[i].SetControl(controlpts, d.Ctrls) o.NrbFaces[i] = o.PtNurbs[i].ExtractSurfaces() } // derived data o.CellTag2cells = make(map[int][]*Cell) o.FaceTag2cells = make(map[int][]CellFaceId) o.FaceTag2verts = make(map[int][]int) o.SeamTag2cells = make(map[int][]CellSeamId) o.Ctype2cells = make(map[string][]*Cell) o.Part2cells = make(map[int][]*Cell) for i, c := range o.Cells { // check id and tag if c.Id != i { err = chk.Err("cells ids must coincide with order in \"verts\" list. %d != %d\n", c.Id, i) return } if c.Tag >= 0 { err = chk.Err("cells tags must be negative. %d is incorrect\n", c.Tag) return } // get shape structure switch c.Type { case "joint": c.IsJoint = true case "nurbs": c.Shp = shp.GetShapeNurbs(o.PtNurbs[c.Nrb], o.NrbFaces[c.Nrb], c.Span) if c.Shp == nil { err = chk.Err("cannot allocate \"shape\" structure for cell type = %q\n", c.Type) return } default: c.Shp = shp.Get(c.Type, goroutineId) if c.Shp == nil { err = chk.Err("cannot allocate \"shape\" structure for cell type = %q\n", c.Type) return } } c.GoroutineId = goroutineId // face tags cells := o.CellTag2cells[c.Tag] o.CellTag2cells[c.Tag] = append(cells, c) for i, ftag := range c.FTags { if ftag < 0 { pairs := o.FaceTag2cells[ftag] o.FaceTag2cells[ftag] = append(pairs, CellFaceId{c, i}) for _, l := range c.Shp.FaceLocalVerts[i] { utl.IntIntsMapAppend(&o.FaceTag2verts, ftag, o.Verts[c.Verts[l]].Id) } } } // seam tags if o.Ndim == 3 { for i, stag := range c.STags { if stag < 0 { pairs := o.SeamTag2cells[stag] o.SeamTag2cells[stag] = append(pairs, CellSeamId{c, i}) } } } // cell type => cells cells = o.Ctype2cells[c.Type] o.Ctype2cells[c.Type] = append(cells, c) // partition => cells cells = o.Part2cells[c.Part] o.Part2cells[c.Part] = append(cells, c) } // remove duplicates for ftag, verts := range o.FaceTag2verts { o.FaceTag2verts[ftag] = utl.IntUnique(verts) } // results return }
// Draw draws grid // r -- radius of circles // W -- width of paths // dwt -- δwt for positioning text (w = W/2) // arrow_scale -- scale for arrows. use 0 for default value func (o *Graph) Draw(dirout, fname string, r, W, dwt, arrow_scale float64, verts_lbls map[int]string, verts_fsz float64, verts_clr string, edges_lbls map[int]string, edges_fsz float64, edges_clr string) { if len(o.Verts) < 1 { return } xmin, ymin := o.Verts[0][0], o.Verts[0][1] xmax, ymax := xmin, ymin var lbl string for i, v := range o.Verts { if verts_lbls == nil { lbl = io.Sf("%d", i) } else { lbl = verts_lbls[i] } plt.Text(v[0], v[1], lbl, io.Sf("clip_on=0, color='%s', fontsize=%g, ha='center', va='center'", verts_clr, verts_fsz)) plt.Circle(v[0], v[1], r, "clip_on=0, ec='k', lw=0.8") xmin, ymin = utl.Min(xmin, v[0]), utl.Min(ymin, v[1]) xmax, ymax = utl.Max(xmax, v[0]), utl.Max(ymax, v[1]) } if W > 2*r { W = 1.8 * r } w := W / 2.0 xa, xb := make([]float64, 2), make([]float64, 2) xc, dx := make([]float64, 2), make([]float64, 2) mu, nu := make([]float64, 2), make([]float64, 2) xi, xj := make([]float64, 2), make([]float64, 2) l := math.Sqrt(r*r - w*w) var L float64 if arrow_scale <= 0 { arrow_scale = 20 } for k, e := range o.Edges { L = 0.0 for i := 0; i < 2; i++ { xa[i] = o.Verts[e[0]][i] xb[i] = o.Verts[e[1]][i] xc[i] = (xa[i] + xb[i]) / 2.0 dx[i] = xb[i] - xa[i] L += dx[i] * dx[i] } L = math.Sqrt(L) mu[0], mu[1] = dx[0]/L, dx[1]/L nu[0], nu[1] = -dx[1]/L, dx[0]/L for i := 0; i < 2; i++ { xi[i] = xa[i] + l*mu[i] - w*nu[i] xj[i] = xb[i] - l*mu[i] - w*nu[i] xc[i] = (xi[i]+xj[i])/2.0 - dwt*nu[i] } plt.Arrow(xi[0], xi[1], xj[0], xj[1], io.Sf("st='->', sc=%g", arrow_scale)) if edges_lbls == nil { lbl = io.Sf("%d", k) } else { lbl = edges_lbls[k] } plt.Text(xc[0], xc[1], lbl, io.Sf("clip_on=0, color='%s', fontsize=%g, ha='center', va='center'", edges_clr, edges_fsz)) } xmin -= r xmax += r ymin -= r ymax += r plt.AxisOff() plt.Equal() plt.AxisRange(xmin, xmax, ymin, ymax) plt.SaveD(dirout, fname) }
func (o *Plotter) Plot_p_ev(x, y []float64, res []*State, sts [][]float64, last bool) { nr := len(res) if len(sts) != nr { return } k := nr - 1 var x0, x1 []float64 if !o.NoAlp { x0, x1 = make([]float64, nr), make([]float64, nr) } withα := false if o.LogP { xmin := o.calc_x(o.P[0]) xmax := xmin for i := 0; i < nr; i++ { x[i], y[i] = o.calc_x(o.P[i]), o.Ev[i]*100.0 if !o.NoAlp && len(res[i].Alp) > 0 { withα = true x0[i] = o.calc_x(res[i].Alp[0]) if o.nsurf > 1 { x1[i] = o.calc_x(res[i].Alp[1]) } } xmin = utl.Min(xmin, x[i]) xmax = utl.Max(xmax, x[i]) } } else { xmin := o.P[0] xmax := xmin for i := 0; i < nr; i++ { x[i], y[i] = o.P[i], o.Ev[i]*100.0 if !o.NoAlp && len(res[i].Alp) > 0 { withα = true x0[i] = res[i].Alp[0] if o.nsurf > 1 { x1[i] = res[i].Alp[1] } } xmin = utl.Min(xmin, x[i]) xmax = utl.Max(xmax, x[i]) } } if withα { plt.Plot(x0, y, io.Sf("'r-', ls='--', lw=3, clip_on=0, color='grey', label=r'%s'", o.Lbl+" $\\alpha_0$")) if o.nsurf > 1 { plt.Plot(x1, y, io.Sf("'r-', ls=':', lw=3, clip_on=0, color='grey', label=r'%s'", o.Lbl+" $\\alpha_1$")) } } plt.Plot(x, y, io.Sf("'r.', ls='-', clip_on=0, color='%s', marker='%s', label=r'%s'", o.Clr, o.Mrk, o.Lbl)) plt.PlotOne(x[0], y[0], io.Sf("'bo', clip_on=0, color='%s', marker='%s', ms=%d", o.SpClr, o.SpMrk, o.SpMs)) plt.PlotOne(x[k], y[k], io.Sf("'bs', clip_on=0, color='%s', marker='%s', ms=%d", o.SpClr, o.EpMrk, o.EpMs)) if last { xlbl := "$p$" if o.LogP { xlbl = "$\\log{[1+(p+p_t)/p_r]}$" } plt.Gll(xlbl, "$\\varepsilon_v\\;[\\%]$", "leg_out=1, leg_ncol=4, leg_hlen=2") if lims, ok := o.Lims["p,ev"]; ok { plt.AxisLims(lims) } } }