コード例 #1
0
ファイル: plotter.go プロジェクト: PaddySchmidt/gofem
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)
		}
	}
}
コード例 #2
0
ファイル: munkres.go プロジェクト: PaddySchmidt/gosl
// 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
}
コード例 #3
0
ファイル: io.go プロジェクト: yunpeng1/gosl
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
}
コード例 #4
0
ファイル: munkres.go プロジェクト: PaddySchmidt/gosl
// 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
}
コード例 #5
0
ファイル: algos.go プロジェクト: PaddySchmidt/gofem
// 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
}
コード例 #6
0
ファイル: geost.go プロジェクト: PaddySchmidt/gofem
// 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
}
コード例 #7
0
ファイル: metrics.go プロジェクト: cpmech/goga
// 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
}
コード例 #8
0
ファイル: s_richardson.go プロジェクト: PaddySchmidt/gofem
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
}
コード例 #9
0
ファイル: plotter.go プロジェクト: PaddySchmidt/gofem
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)
		}
	}
}
コード例 #10
0
ファイル: stat.go プロジェクト: cpmech/goga
// 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)
			}
		}
	}
}
コード例 #11
0
ファイル: topology.go プロジェクト: PaddySchmidt/gofem
// 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
}
コード例 #12
0
ファイル: plotter.go プロジェクト: PaddySchmidt/gofem
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)
		}
	}
}
コード例 #13
0
ファイル: plotter.go プロジェクト: PaddySchmidt/gofem
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)
		}
	}
}
コード例 #14
0
ファイル: io.go プロジェクト: yunpeng1/gosl
// 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)
}
コード例 #15
0
ファイル: t_floats_test.go プロジェクト: postfix/goga-1
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")
	}
}
コード例 #16
0
ファイル: out.go プロジェクト: PaddySchmidt/gofem
// 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
	}
}
コード例 #17
0
ファイル: msh.go プロジェクト: PaddySchmidt/gofem
// 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
}
コード例 #18
0
ファイル: graph.go プロジェクト: yunpeng1/gosl
// 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)
}
コード例 #19
0
ファイル: plotter.go プロジェクト: PaddySchmidt/gofem
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)
		}
	}
}