Beispiel #1
0
// 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)
}
Beispiel #2
0
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
}
Beispiel #3
0
// 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
}