// ramp implements the ramp function func (o *ElemP) ramp(x float64) float64 { if o.Macaulay { return fun.Ramp(x) } return fun.Sramp(x, o.βrmp) }
func solve_problem(fnkey string, problem int) (opt *goga.Optimiser) { // GA parameters opt = new(goga.Optimiser) opt.Default() // options for report opt.RptFmtF = "%.4f" opt.RptFmtX = "%.3f" opt.RptFmtFdev = "%.1e" opt.RptWordF = "\\beta" opt.HistFmt = "%.2f" opt.HistNdig = 3 opt.HistDelFmin = 0.005 opt.HistDelFmax = 0.005 // FORM data var lsft LSF_T var vars rnd.Variables // simple problem or FEM sim if fnkey == "simple" { opt.Read("ga-simple.json") opt.ProbNum = problem lsft, vars = get_simple_data(opt) fnkey += io.Sf("-%d", opt.ProbNum) io.Pf("\n----------------------------------- simple problem %d --------------------------------\n", opt.ProbNum) } else { opt.Read("ga-" + fnkey + ".json") lsft, vars = get_femsim_data(opt, fnkey) io.Pf("\n----------------------------------- femsim %s --------------------------------\n", fnkey) } // set limits nx := len(vars) opt.FltMin = make([]float64, nx) opt.FltMax = make([]float64, nx) for i, dat := range vars { opt.FltMin[i] = dat.Min opt.FltMax[i] = dat.Max } // log input var buf bytes.Buffer io.Ff(&buf, "%s", opt.LogParams()) io.WriteFileVD("/tmp/gosl", fnkey+".log", &buf) // initialise distributions err := vars.Init() if err != nil { chk.Panic("cannot initialise distributions:\n%v", err) } // plot distributions if opt.PlotSet1 { io.Pf(". . . . . . . . plot distributions . . . . . . . .\n") np := 201 for i, dat := range vars { plt.SetForEps(0.75, 250) dat.PlotPdf(np, "'b-',lw=2,zorder=1000") //plt.AxisXrange(dat.Min, dat.Max) plt.SetXnticks(15) plt.SaveD("/tmp/sims", io.Sf("distr-%s-%d.eps", fnkey, i)) } return } // objective function nf := 1 var ng, nh int var fcn goga.MinProb_t var obj goga.ObjFunc_t switch opt.Strategy { // argmin_x{ β(y(x)) | lsf(x) ≤ 0 } // f ← sqrt(y dot y) // g ← -lsf(x) ≥ 0 // h ← out-of-range in case Transform fails case 0: ng, nh = 1, 1 fcn = func(f, g, h, x []float64, ξ []int, cpu int) { // original and normalised variables h[0] = 0 y, invalid := vars.Transform(x) if invalid { h[0] = 1 return } // objective value f[0] = math.Sqrt(la.VecDot(y, y)) // β // inequality constraint lsf, failed := lsft(x, cpu) g[0] = -lsf h[0] = failed } // argmin_x{ β(y(x)) | lsf(x) = 0 } // f ← sqrt(y dot y) // h0 ← lsf(x) // h1 ← out-of-range in case Transform fails case 1: ng, nh = 0, 2 fcn = func(f, g, h, x []float64, ξ []int, cpu int) { // original and normalised variables h[0], h[1] = 0, 0 y, invalid := vars.Transform(x) if invalid { h[0], h[1] = 1, 1 return } // objective value f[0] = math.Sqrt(la.VecDot(y, y)) // β // equality constraint lsf, failed := lsft(x, cpu) h[0] = lsf h[1] = failed // induce minmisation of h0 //f[0] += math.Abs(lsf) } case 2: opt.Nova = 1 opt.Noor = 2 obj = func(sol *goga.Solution, cpu int) { // clear out-of-range values sol.Oor[0] = 0 // invalid transformation or FEM failed sol.Oor[1] = 0 // g(x) ≤ 0 was violated // original and normalised variables x := sol.Flt y, invalid := vars.Transform(x) if invalid { sol.Oor[0] = goga.INF sol.Oor[1] = goga.INF return } // objective value sol.Ova[0] = math.Sqrt(la.VecDot(y, y)) // β // inequality constraint lsf, failed := lsft(x, cpu) sol.Oor[0] = failed sol.Oor[1] = fun.Ramp(lsf) } default: chk.Panic("strategy %d is not available", opt.Strategy) } // initialise optimiser opt.Init(goga.GenTrialSolutions, obj, fcn, nf, ng, nh) // solve io.Pf(". . . . . . . . running . . . . . . . .\n") opt.RunMany("", "") goga.StatF(opt, 0, true) io.Pfblue2("Tsys = %v\n", opt.SysTimeAve) // check goga.CheckFront0(opt, true) // results sols := goga.GetFeasible(opt.Solutions) if len(sols) > 0 { goga.SortByOva(sols, 0) best := sols[0] io.Pforan("x = %.6f\n", best.Flt) io.Pforan("xref = %.6f\n", opt.RptXref) io.Pforan("β = %v (%v)\n", best.Ova[0], opt.RptFref[0]) } return }
// RunFEM runs FE analysis. func (o *FemData) RunFEM(Enabled []int, Areas []float64, draw int, debug bool) (mobility, failed, weight, umax, smax, errU, errS float64) { // check for NaNs defer func() { if math.IsNaN(mobility) || math.IsNaN(failed) || math.IsNaN(weight) || math.IsNaN(umax) || math.IsNaN(smax) || math.IsNaN(errU) || math.IsNaN(errS) { io.PfRed("enabled := %+#v\n", Enabled) io.PfRed("areas := %+#v\n", Areas) chk.Panic("NaN: mobility=%v failed=%v weight=%v umax=%v smax=%v errU=%v errS=%v\n", mobility, failed, weight, umax, smax, errU, errS) } }() // set connectivity if o.Opt.BinInt { for cid, ena := range Enabled { o.Dom.Msh.Cells[cid].Disabled = true if ena == 1 { o.Dom.Msh.Cells[cid].Disabled = false } } } else { for _, cell := range o.Dom.Msh.Cells { cid := cell.Id xid := o.Cid2xid[cid] o.Dom.Msh.Cells[cid].Disabled = true if Areas[xid] >= o.Opt.aEps { o.Dom.Msh.Cells[cid].Disabled = false } } } // set stage o.Analysis.SetStage(0) // check for required vertices nnod := len(o.Dom.Nodes) for _, vid := range o.ReqVids { if o.Dom.Vid2node[vid] == nil { //io.Pforan("required vertex (%d) missing\n", vid) mobility, failed, errU, errS = float64(1+2*nnod), 1, 1, 1 return } } // compute mobility if o.Opt.Mobility { m := len(o.Dom.Elems) d := len(o.Dom.EssenBcs.Bcs) M := 2*nnod - m - d if M > 0 { //io.Pforan("full mobility: M=%v\n", M) mobility, failed, errU, errS = float64(M), 1, 1, 1 return } } // set elements' cross-sectional areas and compute weight for _, elem := range o.Dom.Elems { ele := elem.(*fem.ElastRod) cid := ele.Cell.Id xid := o.Cid2xid[cid] ele.Mdl.A = Areas[xid] ele.Recompute(false) weight += ele.Mdl.Rho * ele.Mdl.A * ele.L } // run FE analysis err := o.Analysis.SolveOneStage(0, true) if err != nil { //io.Pforan("analysis failed\n") mobility, failed, errU, errS = 0, 1, 1, 1 return } // find maximum deflection // Note that sometimes a mechanism can happen that makes the tip to move upwards if o.VidU >= 0 { eq := o.Dom.Vid2node[o.VidU].GetEq("uy") uy := o.Dom.Sol.Y[eq] umax = math.Abs(uy) } else { for _, nod := range o.Dom.Nodes { eq := nod.GetEq("uy") uy := o.Dom.Sol.Y[eq] umax = utl.Max(umax, math.Abs(uy)) } } errU = fun.Ramp(umax - o.Opt.Uawd) // find max stress for _, elem := range o.Dom.Elems { ele := elem.(*fem.ElastRod) tag := ele.Cell.Tag sig := ele.CalcSig(o.Dom.Sol) smax = utl.Max(smax, math.Abs(sig)) errS = utl.Max(errS, o.Opt.CalcErrSig(tag, sig)) } errS = fun.Ramp(errS) // draw if draw > 0 { lwds := make(map[int]float64) for _, elem := range o.Dom.Elems { ele := elem.(*fem.ElastRod) cid := ele.Cell.Id lwds[cid] = 0.1 + ele.Mdl.A/20.0 } o.Dom.Msh.Draw2d(true, false, lwds, 1) //plt.Title(io.Sf("weight=%.3f deflection=%.6f", weight, umax), "") //plt.SaveD("/tmp/goga", io.Sf("mesh-topology-%03d.eps", draw)) } // debug if false && (umax > 0 && errS < 1e-10) { io.PfYel("enabled := %+#v\n", Enabled) io.Pf("areas := %+#v\n", Areas) io.Pf("weight = %v\n", weight) io.Pf("umax = %v\n", umax) io.Pf("smax = %v\n", smax) io.Pf("errU = %v\n", errU) io.Pf("errS = %v\n", errS) // post-processing msh := o.Dom.Msh vid := msh.VertTag2verts[-4][0].Id nod := o.Dom.Vid2node[vid] eqy := nod.GetEq("uy") uy := o.Dom.Sol.Y[eqy] io.Pfblue2("%2d : uy = %g\n", vid, uy) } return }