Пример #1
0
// PlotTwoVarsContour plots contour for two variables problem. len(x) == 2
//  Input
//   dirout  -- directory to save files
//   fnkey   -- file name key for eps figure
//   x       -- solution. can be <nil>
//   np      -- number of points for contour
//   extra   -- called just before saving figure
//   axequal -- axis.equal
//   vmin    -- min 0 values
//   vmax    -- max 1 values
//   f       -- function to plot filled contour. can be <nil>
//   gs      -- functions to plot contour @ level 0. can be <nil>
func PlotTwoVarsContour(dirout, fnkey string, x []float64, np int, extra func(), axequal bool,
	vmin, vmax []float64, f TwoVarsFunc_t, gs ...TwoVarsFunc_t) {
	if fnkey == "" {
		return
	}
	chk.IntAssert(len(vmin), 2)
	chk.IntAssert(len(vmax), 2)
	V0, V1 := utl.MeshGrid2D(vmin[0], vmax[0], vmin[1], vmax[1], np, np)
	var Zf [][]float64
	var Zg [][][]float64
	if f != nil {
		Zf = la.MatAlloc(np, np)
	}
	if len(gs) > 0 {
		Zg = utl.Deep3alloc(len(gs), np, np)
	}
	xtmp := make([]float64, 2)
	for i := 0; i < np; i++ {
		for j := 0; j < np; j++ {
			xtmp[0], xtmp[1] = V0[i][j], V1[i][j]
			if f != nil {
				Zf[i][j] = f(xtmp)
			}
			for k, g := range gs {
				Zg[k][i][j] = g(xtmp)
			}
		}
	}
	plt.Reset()
	plt.SetForEps(0.8, 350)
	if f != nil {
		cmapidx := 0
		plt.Contour(V0, V1, Zf, io.Sf("fsz=7, cmapidx=%d", cmapidx))
	}
	for k, _ := range gs {
		plt.ContourSimple(V0, V1, Zg[k], false, 8, "zorder=5, levels=[0], colors=['yellow'], linewidths=[2], clip_on=0")
	}
	if x != nil {
		plt.PlotOne(x[0], x[1], "'r*', label='optimum', zorder=10")
	}
	if extra != nil {
		extra()
	}
	if dirout == "" {
		dirout = "."
	}
	plt.Cross("clr='grey'")
	plt.SetXnticks(11)
	plt.SetYnticks(11)
	if axequal {
		plt.Equal()
	}
	plt.AxisRange(vmin[0], vmax[0], vmin[1], vmax[1])
	args := "leg_out='1', leg_ncol=4, leg_hlen=1.5"
	plt.Gll("$x_0$", "$x_1$", args)
	plt.SaveD(dirout, fnkey+".eps")
}
Пример #2
0
// Init initialises Nurbs
func (o *Nurbs) Init(gnd int, ords []int, knots [][]float64) {

	// essential
	o.gnd = gnd
	o.p = make([]int, 3)

	// B-splines
	o.b = make([]Bspline, o.gnd)
	o.n = make([]int, 3)
	for d := 0; d < o.gnd; d++ {
		o.p[d] = ords[d]
		o.b[d].Init(knots[d], o.p[d])
		o.n[d] = o.b[d].NumBasis()
		if o.n[d] < 2 {
			chk.Panic("number of knots is incorrect for dimension %d. n == %d is invalid", d, o.n[d])
		}
	}
	for d := o.gnd; d < 3; d++ {
		o.n[d] = 1
	}

	// ids of control points
	nctrl := o.n[0] * o.n[1] * o.n[2]
	o.l2i = make([][]int, nctrl)
	for l := 0; l < nctrl; l++ {
		o.l2i[l] = make([]int, 3)
		switch o.gnd {
		case 1:
			o.l2i[l][0] = l
		case 2:
			o.l2i[l][0] = l % o.n[0] // i
			o.l2i[l][1] = l / o.n[0] // j
		case 3:
			c := l % (o.n[0] * o.n[1])
			o.l2i[l][0] = c % o.n[0]            // i
			o.l2i[l][1] = c / o.n[0]            // j
			o.l2i[l][2] = l / (o.n[0] * o.n[1]) // k
		}
	}

	// auxiliary
	o.span = make([]int, 3)
	o.idx = make([]int, 3)
	o.cw = make([]float64, 4)
	o.rr = utl.Deep3alloc(o.p[0]+1, o.p[1]+1, o.p[2]+1)
	o.drr = utl.Deep4alloc(o.p[0]+1, o.p[1]+1, o.p[2]+1, o.gnd)
	o.dww = make([]float64, o.gnd)
}
Пример #3
0
// CheckEigenprojsDerivs checks the derivatives of eigen projectors w.r.t defining tensor
func CheckEigenprojsDerivs(a []float64, tol float64, ver bool, zero float64) {

	// compute eigenvalues and eigenprojectors
	ncp := len(a)
	λ := make([]float64, 3)
	P := la.MatAlloc(3, ncp)
	docalc := func() {
		err := M_EigenValsProjsNum(P, λ, a)
		if err != nil {
			chk.Panic("eigenprojs.go: CheckEigenprojsDerivs failed:\n %v", err.Error())
		}
	}

	// compute derivatives of eigenprojectors
	docalc()
	dPda := utl.Deep3alloc(3, ncp, ncp)
	err := M_EigenProjsDerivAuto(dPda, a, λ, P)
	if err != nil {
		chk.Panic("%v", err)
	}

	// check
	var tmp float64
	has_error := false
	for k := 0; k < 3; k++ {
		for i := 0; i < ncp; i++ {
			for j := 0; j < ncp; j++ {
				dnum, _ := num.DerivCentral(func(x float64, args ...interface{}) (res float64) {
					tmp, a[j] = a[j], x
					docalc()
					a[j] = tmp
					return P[k][i]
				}, a[j], 1e-6)
				err := chk.PrintAnaNum(io.Sf("dP%d[%d]/da[%d]", k, i, j), tol, dPda[k][i][j], dnum, ver)
				if err != nil {
					has_error = true
				}
			}
		}
		if ver {
			io.Pf("\n")
		}
	}
	if has_error {
		chk.Panic(_eigenprojs_err8)
	}
	return
}
Пример #4
0
// Init initialises this structure
func (o *PrincStrainsUp) Init(ndim int, prms fun.Prms, mdl EPmodel) (err error) {

	// constants
	o.Fzero = 1e-9
	o.Nsig = 2 * ndim

	// tolerances
	atol, rtol, ftol := 1e-8, 1e-8, 1e-9

	// flags
	o.Nbsmp = 5
	o.Fcoef = 1.0
	o.ChkJacTol = 1e-4

	// read parameters
	for _, p := range prms {
		switch p.N {

		// tolerances
		case "atol":
			atol = p.V
		case "rtol":
			rtol = p.V
		case "ftol":
			ftol = p.V

			// flags
		case "nbsmp":
			o.Nbsmp = int(p.V)
		case "fcoef":
			o.Fcoef = p.V
		case "lineS":
			o.LineS = p.V
		case "chkJac":
			o.ChkJac = p.V > 0
		case "chkSilent":
			o.ChkSilent = p.V > 0

			// debugging
		case "dbgShowR":
			o.DbgShowR = p.V > 0
		case "dbgOn":
			o.DbgOn = p.V > 0
		case "dbgPlot":
			o.DbgPlot = p.V > 0
		case "dbgEid":
			o.DbgEid = int(p.V)
		case "dbgIpid":
			o.DbgIpId = int(p.V)
		case "dbgTime":
			o.DbgTime = p.V
		}
	}

	// model
	o.Mdl = mdl
	o.Nalp, o.Nsurf = o.Mdl.Info()

	// variables
	o.Lσ = make([]float64, 3)
	o.Lεe = make([]float64, 3)
	o.Lεetr = make([]float64, 3)
	o.P = la.MatAlloc(3, o.Nsig)
	o.αn = make([]float64, o.Nalp)
	o.h = make([]float64, 3)
	o.A = make([]float64, o.Nalp)
	o.N = make([]float64, 3)
	o.Ne = make([]float64, 3)
	o.Nb = make([]float64, 3)
	o.Mb = la.MatAlloc(3, 3)
	o.Mbe = la.MatAlloc(3, 3)
	o.De = la.MatAlloc(3, 3)
	o.Dt = la.MatAlloc(3, 3)
	o.a = la.MatAlloc(o.Nalp, 3)
	o.b = la.MatAlloc(o.Nalp, 3)
	o.be = la.MatAlloc(o.Nalp, 3)
	o.c = la.MatAlloc(o.Nalp, o.Nalp)
	o.x = make([]float64, 4+o.Nalp)
	o.J = la.MatAlloc(4+o.Nalp, 4+o.Nalp)
	o.Ji = la.MatAlloc(4+o.Nalp, 4+o.Nalp)
	o.dPdT = utl.Deep3alloc(3, o.Nsig, o.Nsig)

	// nonlinear solver
	useDn, numJ := true, false
	o.nls.Init(4+o.Nalp, o.ffcn, nil, o.JfcnD, useDn, numJ, map[string]float64{
		"lSearch": o.LineS,
		"atol":    atol,
		"rtol":    rtol,
		"ftol":    ftol,
	})
	o.nls.ChkConv = false
	return
}
Пример #5
0
// Plot plots contour
func (o *SimpleFltProb) Plot(fnkey string) {

	// check
	if !o.C.DoPlot {
		return
	}

	// limits and meshgrid
	xmin, xmax := o.C.RangeFlt[0][0], o.C.RangeFlt[0][1]
	ymin, ymax := o.C.RangeFlt[1][0], o.C.RangeFlt[1][1]

	// auxiliary variables
	X, Y := utl.MeshGrid2D(xmin, xmax, ymin, ymax, o.PltNpts, o.PltNpts)
	Zf := utl.DblsAlloc(o.PltNpts, o.PltNpts)
	var Zg [][][]float64
	var Zh [][][]float64
	if o.ng > 0 {
		Zg = utl.Deep3alloc(o.ng, o.PltNpts, o.PltNpts)
	}
	if o.nh > 0 {
		Zh = utl.Deep3alloc(o.nh, o.PltNpts, o.PltNpts)
	}

	// compute values
	x := make([]float64, 2)
	for i := 0; i < o.PltNpts; i++ {
		for j := 0; j < o.PltNpts; j++ {
			x[0], x[1] = X[i][j], Y[i][j]
			o.Fcn(o.ff[0], o.gg[0], o.hh[0], x)
			Zf[i][j] = o.ff[0][o.PltIdxF]
			for k, g := range o.gg[0] {
				Zg[k][i][j] = g
			}
			for k, h := range o.hh[0] {
				Zh[k][i][j] = h
			}
		}
	}

	// prepare plot area
	plt.Reset()
	plt.SetForEps(0.8, 350)

	// plot f
	if o.PltArgs != "" {
		o.PltArgs = "," + o.PltArgs
	}
	if o.PltCsimple {
		plt.ContourSimple(X, Y, Zf, true, 7, "colors=['k'], fsz=7"+o.PltArgs)
	} else {
		plt.Contour(X, Y, Zf, io.Sf("fsz=7, cmapidx=%d"+o.PltArgs, o.PltCmapIdx))
	}

	// plot g
	clr := "yellow"
	if o.PltCsimple {
		clr = "blue"
	}
	for _, g := range Zg {
		plt.ContourSimple(X, Y, g, false, 7, io.Sf("zorder=5, levels=[0], colors=['%s'], linewidths=[%g], clip_on=0", clr, o.PltLwg))
	}

	// plot h
	clr = "yellow"
	if o.PltCsimple {
		clr = "blue"
	}
	for _, h := range Zh {
		plt.ContourSimple(X, Y, h, false, 7, io.Sf("zorder=5, levels=[0], colors=['%s'], linewidths=[%g], clip_on=0", clr, o.PltLwh))
	}

	// initial populations
	l := "initial population"
	for _, pop := range o.PopsIni {
		for _, ind := range pop {
			x := ind.GetFloats()
			plt.PlotOne(x[0], x[1], io.Sf("'k.', zorder=20, clip_on=0, label='%s'", l))
			l = ""
		}
	}

	// final populations
	l = "final population"
	for _, pop := range o.PopsBest {
		for _, ind := range pop {
			x := ind.GetFloats()
			plt.PlotOne(x[0], x[1], io.Sf("'ko', ms=6, zorder=30, clip_on=0, label='%s', markerfacecolor='none'", l))
			l = ""
		}
	}

	// extra
	if o.PltExtra != nil {
		o.PltExtra()
	}

	// best result
	if o.Nfeasible > 0 {
		x, _, _, _ := o.find_best()
		plt.PlotOne(x[0], x[1], "'m*', zorder=50, clip_on=0, label='best', markeredgecolor='m'")
	}

	// save figure
	plt.Cross("clr='grey'")
	if o.PltAxEqual {
		plt.Equal()
	}
	plt.AxisRange(xmin, xmax, ymin, ymax)
	plt.Gll("$x_0$", "$x_1$", "leg_out=1, leg_ncol=4, leg_hlen=1.5")
	plt.SaveD(o.PltDirout, fnkey+".eps")
}
Пример #6
0
func main() {

	// GA parameters
	opt := new(goga.Optimiser)
	opt.Default()
	opt.Nsol = 6
	opt.Ncpu = 1
	opt.Tf = 10
	opt.EpsH = 1e-3
	opt.Verbose = true
	opt.GenType = "latin"
	//opt.GenType = "halton"
	//opt.GenType = "rnd"
	opt.NormFlt = false
	opt.UseMesh = true
	opt.Nbry = 3

	// define problem
	opt.RptName = "9"
	opt.RptFref = []float64{0.0539498478}
	opt.RptXref = []float64{-1.717143, 1.595709, 1.827247, -0.7636413, -0.7636450}
	opt.FltMin = []float64{-2.3, -2.3, -3.2, -3.2, -3.2}
	opt.FltMax = []float64{+2.3, +2.3, +3.2, +3.2, +3.2}
	ng, nh := 0, 3
	fcn := func(f, g, h, x []float64, ξ []int, cpu int) {
		f[0] = math.Exp(x[0] * x[1] * x[2] * x[3] * x[4])
		h[0] = x[0]*x[0] + x[1]*x[1] + x[2]*x[2] + x[3]*x[3] + x[4]*x[4] - 10.0
		h[1] = x[1]*x[2] - 5.0*x[3]*x[4]
		h[2] = math.Pow(x[0], 3.0) + math.Pow(x[1], 3.0) + 1.0
	}

	// check
	if false {
		f := make([]float64, 1)
		h := make([]float64, 3)
		fcn(f, nil, h, opt.RptXref, nil, 0)
		io.Pforan("f(xref)  = %g  (%g)\n", f[0], opt.RptFref[0])
		io.Pforan("h0(xref) = %g\n", h[0])
		io.Pforan("h1(xref) = %g\n", h[1])
		io.Pforan("h2(xref) = %g\n", h[2])
	}

	// initialise optimiser
	nf := 1
	opt.Init(goga.GenTrialSolutions, nil, fcn, nf, ng, nh)

	// output function
	T := make([]float64, opt.Tf+1)                    // [nT]
	X := utl.Deep3alloc(opt.Nflt, opt.Nsol, opt.Tf+1) // [nx][nsol][nT]
	F := utl.Deep3alloc(opt.Nova, opt.Nsol, opt.Tf+1) // [nf][nsol][nT]
	U := utl.Deep3alloc(opt.Noor, opt.Nsol, opt.Tf+1) // [nu][nsol][nT]
	opt.Output = func(time int, sols []*goga.Solution) {
		T[time] = float64(time)
		for j, s := range sols {
			for i := 0; i < opt.Nflt; i++ {
				X[i][j][time] = s.Flt[i]
			}
			for i := 0; i < opt.Nova; i++ {
				F[i][j][time] = s.Ova[i]
			}
			for i := 0; i < opt.Noor; i++ {
				U[i][j][time] = s.Oor[i]
			}
		}
	}

	// initial population
	fnk := "one-obj-prob9-dbg"
	//S0 := opt.GetSolutionsCopy()
	goga.WriteAllValues("/tmp/goga", fnk, opt)

	// solve
	opt.Solve()

	// print
	if false {
		io.Pf("%13s%13s%13s%13s%10s\n", "f0", "u0", "u1", "u2", "feasible")
		for _, s := range opt.Solutions {
			io.Pf("%13.5e%13.5e%13.5e%13.5e%10v\n", s.Ova[0], s.Oor[0], s.Oor[1], s.Oor[2], s.Feasible())
		}
	}

	// plot: time series
	//a, b := 100, len(T)
	a, b := 0, 1 //len(T)
	if false {
		plt.SetForEps(2.0, 400)
		nrow := opt.Nflt + opt.Nova + opt.Noor
		for j := 0; j < opt.Nsol; j++ {
			for i := 0; i < opt.Nflt; i++ {
				plt.Subplot(nrow, 1, 1+i)
				plt.Plot(T[a:b], X[i][j][a:b], "")
				plt.Gll("$t$", io.Sf("$x_%d$", i), "")
			}
		}
		for j := 0; j < opt.Nsol; j++ {
			for i := 0; i < opt.Nova; i++ {
				plt.Subplot(nrow, 1, 1+opt.Nflt+i)
				plt.Plot(T[a:b], F[i][j][a:b], "")
				plt.Gll("$t$", io.Sf("$f_%d$", i), "")
			}
		}
		for j := 0; j < opt.Nsol; j++ {
			for i := 0; i < opt.Noor; i++ {
				plt.Subplot(nrow, 1, 1+opt.Nflt+opt.Nova+i)
				plt.Plot(T[a:b], U[i][j][a:b], "")
				plt.Gll("$t$", io.Sf("$u_%d$", i), "")
			}
		}
		plt.SaveD("/tmp/goga", fnk+"-time.eps")
	}

	// plot: x-relationships
	if true {
		plt.SetForEps(1, 700)
		ncol := opt.Nflt - 1
		for i := 0; i < opt.Nflt-1; i++ {
			for j := i + 1; j < opt.Nflt; j++ {
				plt.Subplot(ncol, ncol, i*ncol+j)
				if opt.UseMesh {
					opt.Meshes[i][j].CalcDerived(0)
					opt.Meshes[i][j].Draw2d(false, false, nil, 0)
				}
				for k := 0; k < opt.Nsol; k++ {
					plt.Plot(X[i][k][a:b], X[j][k][a:b], "ls='none', marker='.'")
				}
				plt.Gll(io.Sf("$x_%d$", i), io.Sf("$x_%d$", j), "")
			}
		}
		plt.SaveD("/tmp/goga", fnk+"-x.eps")
	}
}
Пример #7
0
func plot_spo751(fnkey string) {

	// constants
	nidx := 20 // selected node at outer surface
	didx := 0  // selected  dof index for plot
	nels := 4  // number of elements
	nips := 4  // number of ips

	// selected P values for stress plot
	Psel := []float64{100, 140, 180, 190}
	tolPsel := 2.0    // tolerance to compare P
	GPa2MPa := 1000.0 // conversion factor

	// input data
	Pcen := 200.0         // [Mpa]
	a, b := 100.0, 200.0  // [mm], [mm]
	E, ν := 210000.0, 0.3 // [MPa], [-]
	σy := 240.0           // [MPa]

	// analytical solution
	var sol ana.PressCylin
	sol.Init([]*fun.Prm{
		&fun.Prm{N: "a", V: a}, &fun.Prm{N: "b", V: b},
		&fun.Prm{N: "E", V: E}, &fun.Prm{N: "ν", V: ν},
		&fun.Prm{N: "σy", V: σy},
	})
	np := 41
	P_ana, Ub_ana := sol.CalcPressDisp(np)
	R_ana, Sr_ana, St_ana := sol.CalcStresses(Psel, np)

	// read summary
	sum := ReadSum(Global.Dirout, Global.Fnkey)

	// allocate domain
	distr := false
	d := NewDomain(Global.Sim.Regions[0], distr)
	if !d.SetStage(0, Global.Sim.Stages[0], distr) {
		io.PfRed("plot_spo751: SetStage failed\n")
		return
	}

	// gofem results
	nto := len(sum.OutTimes)
	P := make([]float64, nto)
	Ub := make([]float64, nto)
	R := utl.Deep3alloc(len(Psel), nels, nips)
	Sr := utl.Deep3alloc(len(Psel), nels, nips)
	St := utl.Deep3alloc(len(Psel), nels, nips)
	i := 0
	for tidx, t := range sum.OutTimes {

		// read results from file
		if !d.In(sum, tidx, true) {
			io.PfRed("plot_spo751: cannot read solution\n")
			return
		}

		// collect results for load versus displacement plot
		nod := d.Nodes[nidx]
		eq := nod.Dofs[didx].Eq
		P[tidx] = t * Pcen
		Ub[tidx] = d.Sol.Y[eq]

		// stresses
		if isPsel(Psel, P[tidx], tolPsel) {
			for j, ele := range d.ElemIntvars {
				e := ele.(*ElemU)
				ipsdat := e.OutIpsData()
				for k, dat := range ipsdat {
					res := dat.Calc(d.Sol)
					x, y := dat.X[0], dat.X[1]
					sx := res["sx"] * GPa2MPa
					sy := res["sy"] * GPa2MPa
					sxy := res["sxy"] * GPa2MPa / math.Sqrt2
					R[i][j][k], Sr[i][j][k], St[i][j][k], _ = ana.PolarStresses(x, y, sx, sy, sxy)
				}
			}
			i++
		}
	}

	// auxiliary data for plotting stresses
	colors := []string{"r", "m", "g", "k", "y", "c", "r", "m"}
	markers1 := []string{"o", "s", "x", ".", "^", "*", "o", "s"}
	markers2 := []string{"+", "+", "+", "+", "+", "+", "+", "+"}

	// plot load displacements
	plt.SetForEps(0.8, 300)
	if true {
		//if false {
		plt.Plot(Ub_ana, P_ana, "'b-', ms=2, label='solution', clip_on=0")
		plt.Plot(Ub, P, "'r.--', label='fem: outer', clip_on=0")
		plt.Gll("$u_x\\;\\mathrm{[mm]}$", "$P\\;\\mathrm{[MPa]}$", "")
		plt.SaveD("/tmp", io.Sf("gofem_%s_disp.eps", fnkey))
	}

	// plot radial stresses
	if true {
		//if false {
		plt.Reset()
		for i, Pval := range Psel {
			plt.Plot(R_ana, Sr_ana[i], "'b-'")
			for k := 0; k < nips; k++ {
				for j := 0; j < nels; j++ {
					args := io.Sf("'%s%s'", colors[i], markers1[i])
					if k > 1 {
						args = io.Sf("'k%s', ms=10", markers2[i])
					}
					if k == 0 && j == 0 {
						args += io.Sf(", label='P=%g'", Pval)
					}
					plt.PlotOne(R[i][j][k], Sr[i][j][k], args)
				}
			}
		}
		plt.Gll("$r\\;\\mathrm{[mm]}$", "$\\sigma_r\\;\\mathrm{[MPa]}$", "leg_loc='lower right'")
		plt.AxisXrange(a, b)
		plt.SaveD("/tmp", io.Sf("gofem_%s_sr.eps", fnkey))
	}

	// plot tangential stresses
	if true {
		//if false {
		plt.Reset()
		for i, Pval := range Psel {
			plt.Plot(R_ana, St_ana[i], "'b-'")
			for k := 0; k < nips; k++ {
				for j := 0; j < nels; j++ {
					args := io.Sf("'%s%s'", colors[i], markers1[i])
					if k > 1 {
						args = io.Sf("'k%s', ms=10", markers2[i])
					}
					if k == 0 && j == 0 {
						args += io.Sf(", label='P=%g'", Pval)
					}
					plt.PlotOne(R[i][j][k], St[i][j][k], args)
				}
			}
		}
		plt.Gll("$r\\;\\mathrm{[mm]}$", "$\\sigma_t\\;\\mathrm{[MPa]}$", "leg_loc='upper left'")
		plt.SaveD("/tmp", io.Sf("gofem_%s_st.eps", fnkey))
	}
}
Пример #8
0
func Test_geninvs01(tst *testing.T) {

	//verbose()
	chk.PrintTitle("geninvs01")

	// coefficients for smp invariants
	smp_a := -1.0
	smp_b := 0.5
	smp_β := 1e-1 // derivative values become too high with
	smp_ϵ := 1e-1 // small β and ϵ @ zero

	// constants for checking derivatives
	dver := chk.Verbose
	dtol := 1e-6
	dtol2 := 1e-6

	// run tests
	nd := test_nd
	for idxA := 0; idxA < len(test_nd); idxA++ {
		//for idxA := 10; idxA < 11; idxA++ {

		// tensor and eigenvalues
		A := test_AA[idxA]
		a := M_Alloc2(nd[idxA])
		Ten2Man(a, A)
		L := make([]float64, 3)
		M_EigenValsNum(L, a)

		// SMP derivs and SMP director
		dndL := la.MatAlloc(3, 3)
		dNdL := make([]float64, 3)
		d2ndLdL := utl.Deep3alloc(3, 3, 3)
		N := make([]float64, 3)
		F := make([]float64, 3)
		G := make([]float64, 3)
		m := SmpDerivs1(dndL, dNdL, N, F, G, L, smp_a, smp_b, smp_β, smp_ϵ)
		SmpDerivs2(d2ndLdL, L, smp_a, smp_b, smp_β, smp_ϵ, m, N, F, G, dNdL, dndL)
		n := make([]float64, 3)
		SmpUnitDirector(n, m, N)

		// SMP invariants
		p, q, err := GenInvs(L, n, smp_a)
		if err != nil {
			chk.Panic("SmpInvs failed:\n%v", err)
		}

		// output
		io.PfYel("\n\ntst # %d ###################################################################################\n", idxA)
		io.Pfblue2("L = %v\n", L)
		io.Pforan("n = %v\n", n)
		io.Pforan("p = %v\n", p)
		io.Pforan("q = %v\n", q)

		// check invariants
		tvec := make([]float64, 3)
		GenTvec(tvec, L, n)
		proj := make([]float64, 3) // projection of tvec along n
		tdn := la.VecDot(tvec, n)  // tvec dot n
		for i := 0; i < 3; i++ {
			proj[i] = tdn * n[i]
		}
		norm_proj := la.VecNorm(proj)
		norm_tvec := la.VecNorm(tvec)
		q_ := GENINVSQEPS + math.Sqrt(norm_tvec*norm_tvec-norm_proj*norm_proj)
		io.Pforan("proj = %v\n", proj)
		io.Pforan("norm(proj) = %v == p\n", norm_proj)
		chk.Scalar(tst, "p", 1e-14, math.Abs(p), norm_proj)
		chk.Scalar(tst, "q", 1e-13, q, q_)

		// dt/dL
		var tmp float64
		N_tmp := make([]float64, 3)
		n_tmp := make([]float64, 3)
		tvec_tmp := make([]float64, 3)
		dtdL := la.MatAlloc(3, 3)
		GenTvecDeriv1(dtdL, L, n, dndL)
		for i := 0; i < 3; i++ {
			for j := 0; j < 3; j++ {
				dnum, _ := num.DerivCentral(func(x float64, args ...interface{}) (res float64) {
					tmp, L[j] = L[j], x
					m_tmp := SmpDirector(N_tmp, L, smp_a, smp_b, smp_β, smp_ϵ)
					SmpUnitDirector(n_tmp, m_tmp, N_tmp)
					GenTvec(tvec_tmp, L, n_tmp)
					L[j] = tmp
					return tvec_tmp[i]
				}, L[j], 1e-6)
				chk.AnaNum(tst, io.Sf("dt/dL[%d][%d]", i, j), dtol, dtdL[i][j], dnum, dver)
			}
		}

		// d²t/dLdL
		io.Pfpink("\nd²t/dLdL\n")
		dNdL_tmp := make([]float64, 3)
		dndL_tmp := la.MatAlloc(3, 3)
		dtdL_tmp := la.MatAlloc(3, 3)
		for i := 0; i < 3; i++ {
			for j := 0; j < 3; j++ {
				for k := 0; k < 3; k++ {
					dnum, _ := num.DerivCentral(func(x float64, args ...interface{}) (res float64) {
						tmp, L[k] = L[k], x
						m_tmp := SmpDerivs1(dndL_tmp, dNdL_tmp, N_tmp, F, G, L, smp_a, smp_b, smp_β, smp_ϵ)
						SmpUnitDirector(n_tmp, m_tmp, N_tmp)
						GenTvecDeriv1(dtdL_tmp, L, n_tmp, dndL_tmp)
						L[k] = tmp
						return dtdL_tmp[i][j]
					}, L[k], 1e-6)
					dana := GenTvecDeriv2(i, j, k, L, dndL, d2ndLdL[i][j][k])
					chk.AnaNum(tst, io.Sf("d²t[%d]/dL[%d]dL[%d]", i, j, k), dtol2, dana, dnum, dver)
				}
			}
		}

		// change tolerance
		dtol_tmp := dtol
		switch idxA {
		case 5, 11:
			dtol = 1e-5
		case 12:
			dtol = 0.0013
		}

		// first order derivatives
		dpdL := make([]float64, 3)
		dqdL := make([]float64, 3)
		p_, q_, err := GenInvsDeriv1(dpdL, dqdL, L, n, dndL, smp_a)
		if err != nil {
			chk.Panic("%v", err)
		}
		chk.Scalar(tst, "p", 1e-17, p, p_)
		chk.Scalar(tst, "q", 1e-17, q, q_)
		var ptmp, qtmp float64
		io.Pfpink("\ndp/dL\n")
		for j := 0; j < 3; j++ {
			dnum, _ := num.DerivCentral(func(x float64, args ...interface{}) (res float64) {
				tmp, L[j] = L[j], x
				m_tmp := SmpDirector(N_tmp, L, smp_a, smp_b, smp_β, smp_ϵ)
				SmpUnitDirector(n_tmp, m_tmp, N_tmp)
				ptmp, _, err = GenInvs(L, n_tmp, smp_a)
				if err != nil {
					chk.Panic("DerivCentral: SmpInvs failed:\n%v", err)
				}
				L[j] = tmp
				return ptmp
			}, L[j], 1e-6)
			chk.AnaNum(tst, io.Sf("dp/dL[%d]", j), dtol, dpdL[j], dnum, dver)
		}
		io.Pfpink("\ndq/dL\n")
		for j := 0; j < 3; j++ {
			dnum, _ := num.DerivCentral(func(x float64, args ...interface{}) (res float64) {
				tmp, L[j] = L[j], x
				m_tmp := SmpDirector(N_tmp, L, smp_a, smp_b, smp_β, smp_ϵ)
				SmpUnitDirector(n_tmp, m_tmp, N_tmp)
				_, qtmp, err = GenInvs(L, n_tmp, smp_a)
				if err != nil {
					chk.Panic("DerivCentral: SmpInvs failed:\n%v", err)
				}
				L[j] = tmp
				return qtmp
			}, L[j], 1e-6)
			chk.AnaNum(tst, io.Sf("dq/dL[%d]", j), dtol, dqdL[j], dnum, dver)
		}

		// recover tolerance
		dtol = dtol_tmp

		// change tolerance
		io.Pforan("dtol2 = %v\n", dtol2)
		dtol2_tmp := dtol2
		switch idxA {
		case 5:
			dtol2 = 1e-5
		case 10:
			dtol2 = 0.72
		case 11:
			dtol2 = 1e-5
		case 12:
			dtol2 = 544
		}

		// second order derivatives
		dpdL_tmp := make([]float64, 3)
		dqdL_tmp := make([]float64, 3)
		d2pdLdL := la.MatAlloc(3, 3)
		d2qdLdL := la.MatAlloc(3, 3)
		GenInvsDeriv2(d2pdLdL, d2qdLdL, L, n, dpdL, dqdL, p, q, dndL, d2ndLdL, smp_a)
		io.Pfpink("\nd²p/dLdL\n")
		for i := 0; i < 3; i++ {
			for j := 0; j < 3; j++ {
				dnum, _ := num.DerivCentral(func(x float64, args ...interface{}) (res float64) {
					tmp, L[j] = L[j], x
					m_tmp := SmpDerivs1(dndL_tmp, dNdL_tmp, N_tmp, F, G, L, smp_a, smp_b, smp_β, smp_ϵ)
					SmpUnitDirector(n_tmp, m_tmp, N_tmp)
					GenInvsDeriv1(dpdL_tmp, dqdL_tmp, L, n_tmp, dndL_tmp, smp_a)
					L[j] = tmp
					return dpdL_tmp[i]
				}, L[j], 1e-6)
				chk.AnaNum(tst, io.Sf("d²p/dL[%d][%d]", i, j), dtol2, d2pdLdL[i][j], dnum, dver)
			}
		}
		io.Pfpink("\nd²q/dLdL\n")
		for i := 0; i < 3; i++ {
			for j := 0; j < 3; j++ {
				dnum, _ := num.DerivCentral(func(x float64, args ...interface{}) (res float64) {
					tmp, L[j] = L[j], x
					m_tmp := SmpDerivs1(dndL_tmp, dNdL_tmp, N_tmp, F, G, L, smp_a, smp_b, smp_β, smp_ϵ)
					SmpUnitDirector(n_tmp, m_tmp, N_tmp)
					GenInvsDeriv1(dpdL_tmp, dqdL_tmp, L, n_tmp, dndL_tmp, smp_a)
					L[j] = tmp
					return dqdL_tmp[i]
				}, L[j], 1e-6)
				chk.AnaNum(tst, io.Sf("d²q/dL[%d][%d]", i, j), dtol2, d2qdLdL[i][j], dnum, dver)
			}
		}

		// recover tolerance
		dtol2 = dtol2_tmp
	}
}
Пример #9
0
func Test_smpinvs02(tst *testing.T) {

	//verbose()
	chk.PrintTitle("smpinvs02")

	// coefficients for smp invariants
	smp_a := -1.0
	smp_b := 0.5
	smp_β := 1e-1 // derivative values become too high with
	smp_ϵ := 1e-1 // small β and ϵ @ zero

	// constants for checking derivatives
	dver := chk.Verbose
	dtol := 1e-9
	dtol2 := 1e-8

	// run tests
	nd := test_nd
	for idxA := 0; idxA < len(test_nd); idxA++ {
		//for idxA := 0; idxA < 1; idxA++ {
		//for idxA := 10; idxA < 11; idxA++ {

		// tensor and eigenvalues
		A := test_AA[idxA]
		a := M_Alloc2(nd[idxA])
		Ten2Man(a, A)
		L := make([]float64, 3)
		M_EigenValsNum(L, a)

		// SMP director
		N := make([]float64, 3)
		n := make([]float64, 3)
		m := SmpDirector(N, L, smp_a, smp_b, smp_β, smp_ϵ)
		SmpUnitDirector(n, m, N)

		// output
		io.PfYel("\n\ntst # %d ###################################################################################\n", idxA)
		io.Pforan("L = %v\n", L)
		io.Pforan("N = %v\n", N)
		io.Pforan("m = %v\n", m)
		io.Pfpink("n = %v\n", n)
		chk.Vector(tst, "L", 1e-12, L, test_λ[idxA])
		chk.Scalar(tst, "norm(n)==1", 1e-15, la.VecNorm(n), 1)
		chk.Scalar(tst, "m=norm(N)", 1e-14, m, la.VecNorm(N))

		// dN/dL
		var tmp float64
		N_tmp := make([]float64, 3)
		dNdL := make([]float64, 3)
		SmpDirectorDeriv1(dNdL, L, smp_a, smp_b, smp_β, smp_ϵ)
		io.Pfpink("\ndNdL = %v\n", dNdL)
		for i := 0; i < 3; i++ {
			dnum, _ := num.DerivCentral(func(x float64, args ...interface{}) (res float64) {
				tmp, L[i] = L[i], x
				SmpDirector(N_tmp, L, smp_a, smp_b, smp_β, smp_ϵ)
				L[i] = tmp
				return N_tmp[i]
			}, L[i], 1e-6)
			chk.AnaNum(tst, io.Sf("dN/dL[%d][%d]", i, i), dtol, dNdL[i], dnum, dver)
		}

		// dm/dL
		n_tmp := make([]float64, 3)
		dmdL := make([]float64, 3)
		SmpNormDirectorDeriv1(dmdL, m, N, dNdL)
		io.Pfpink("\ndmdL = %v\n", dmdL)
		for j := 0; j < 3; j++ {
			dnum, _ := num.DerivCentral(func(x float64, args ...interface{}) (res float64) {
				tmp, L[j] = L[j], x
				m_tmp := SmpDirector(N_tmp, L, smp_a, smp_b, smp_β, smp_ϵ)
				L[j] = tmp
				return m_tmp
			}, L[j], 1e-6)
			chk.AnaNum(tst, io.Sf("dm/dL[%d]", j), dtol, dmdL[j], dnum, dver)
		}

		// dn/dL
		dndL := la.MatAlloc(3, 3)
		SmpUnitDirectorDeriv1(dndL, m, N, dNdL, dmdL)
		io.Pfpink("\ndndL = %v\n", dndL)
		for i := 0; i < 3; i++ {
			for j := 0; j < 3; j++ {
				dnum, _ := num.DerivCentral(func(x float64, args ...interface{}) (res float64) {
					tmp, L[j] = L[j], x
					m_tmp := SmpDirector(N_tmp, L, smp_a, smp_b, smp_β, smp_ϵ)
					SmpUnitDirector(n_tmp, m_tmp, N_tmp)
					L[j] = tmp
					return n_tmp[i]
				}, L[j], 1e-6)
				chk.AnaNum(tst, io.Sf("dn/dL[%d][%d]", i, j), dtol, dndL[i][j], dnum, dver)
			}
		}

		// change tolerance
		dtol2_tmp := dtol2
		if idxA == 10 || idxA == 11 {
			dtol2 = 1e-6
		}

		// d²m/dLdL
		dNdL_tmp := make([]float64, 3)
		dmdL_tmp := make([]float64, 3)
		d2NdL2 := make([]float64, 3)
		d2mdLdL := la.MatAlloc(3, 3)
		SmpDirectorDeriv2(d2NdL2, L, smp_a, smp_b, smp_β, smp_ϵ)
		SmpNormDirectorDeriv2(d2mdLdL, L, smp_a, smp_b, smp_β, smp_ϵ, m, N, dNdL, d2NdL2, dmdL)
		io.Pfpink("\nd2mdLdL = %v\n", d2mdLdL)
		for i := 0; i < 3; i++ {
			for j := 0; j < 3; j++ {
				dnum, _ := num.DerivCentral(func(x float64, args ...interface{}) (res float64) {
					tmp, L[j] = L[j], x
					m_tmp := SmpDirector(N_tmp, L, smp_a, smp_b, smp_β, smp_ϵ)
					SmpDirectorDeriv1(dNdL_tmp, L, smp_a, smp_b, smp_β, smp_ϵ)
					SmpNormDirectorDeriv1(dmdL_tmp, m_tmp, N_tmp, dNdL_tmp)
					L[j] = tmp
					return dmdL_tmp[i]
				}, L[j], 1e-6)
				chk.AnaNum(tst, io.Sf("d2m/dL[%d]dL[%d]", i, j), dtol2, d2mdLdL[i][j], dnum, dver)
			}
		}

		// d²N/dLdL
		io.Pfpink("\nd²N/dLdL\n")
		for i := 0; i < 3; i++ {
			dnum, _ := num.DerivCentral(func(x float64, args ...interface{}) (res float64) {
				tmp, L[i] = L[i], x
				SmpDirectorDeriv1(dNdL_tmp, L, smp_a, smp_b, smp_β, smp_ϵ)
				L[i] = tmp
				return dNdL_tmp[i]
			}, L[i], 1e-6)
			chk.AnaNum(tst, io.Sf("d²N[%d]/dL[%d]dL[%d]", i, i, i), dtol2, d2NdL2[i], dnum, dver)
		}

		// d²n/dLdL
		io.Pfpink("\nd²n/dLdL\n")
		dndL_tmp := la.MatAlloc(3, 3)
		d2ndLdL := utl.Deep3alloc(3, 3, 3)
		SmpUnitDirectorDeriv2(d2ndLdL, m, N, dNdL, d2NdL2, dmdL, n, d2mdLdL, dndL)
		for i := 0; i < 3; i++ {
			for j := 0; j < 3; j++ {
				for k := 0; k < 3; k++ {
					dnum, _ := num.DerivCentral(func(x float64, args ...interface{}) (res float64) {
						tmp, L[k] = L[k], x
						m_tmp := SmpDirector(N_tmp, L, smp_a, smp_b, smp_β, smp_ϵ)
						SmpDirectorDeriv1(dNdL_tmp, L, smp_a, smp_b, smp_β, smp_ϵ)
						SmpNormDirectorDeriv1(dmdL_tmp, m_tmp, N_tmp, dNdL_tmp)
						SmpUnitDirectorDeriv1(dndL_tmp, m_tmp, N_tmp, dNdL_tmp, dmdL_tmp)
						L[k] = tmp
						return dndL_tmp[i][j]
					}, L[k], 1e-6)
					chk.AnaNum(tst, io.Sf("d²n[%d]/dL[%d]dL[%d]", i, j, k), dtol2, d2ndLdL[i][j][k], dnum, dver)
				}
			}
		}

		// recover tolerance
		dtol2 = dtol2_tmp

		// SMP derivs
		//if false {
		if true {
			io.Pfpink("\nSMP derivs\n")
			dndL_ := la.MatAlloc(3, 3)
			dNdL_ := make([]float64, 3)
			d2ndLdL_ := utl.Deep3alloc(3, 3, 3)
			N_ := make([]float64, 3)
			F_ := make([]float64, 3)
			G_ := make([]float64, 3)
			m_ := SmpDerivs1(dndL_, dNdL_, N_, F_, G_, L, smp_a, smp_b, smp_β, smp_ϵ)
			SmpDerivs2(d2ndLdL_, L, smp_a, smp_b, smp_β, smp_ϵ, m_, N_, F_, G_, dNdL_, dndL_)
			chk.Scalar(tst, "m_", 1e-14, m_, m)
			chk.Vector(tst, "N_", 1e-15, N_, N)
			chk.Vector(tst, "dNdL_", 1e-15, dNdL_, dNdL)
			chk.Matrix(tst, "dndL_", 1e-13, dndL_, dndL)
			chk.Deep3(tst, "d2ndLdL_", 1e-11, d2ndLdL_, d2ndLdL)
		}
	}
}
Пример #10
0
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")
	}
}
Пример #11
0
// PlotContour plots contour
func (o *Optimiser) PlotContour(iFlt, jFlt, iOva int, pp *PlotParams) {

	// check
	var x []float64
	if pp.Refx == nil {
		if iFlt > 1 || jFlt > 1 {
			chk.Panic("Refx vector must be given to PlotContour when iFlt or jFlt > 1")
		}
		x = make([]float64, 2)
	} else {
		x = make([]float64, len(pp.Refx))
		copy(x, pp.Refx)
	}

	// limits and meshgrid
	xmin, xmax := o.FltMin[iFlt], o.FltMax[iFlt]
	ymin, ymax := o.FltMin[jFlt], o.FltMax[jFlt]
	if pp.Xrange != nil {
		xmin, xmax = pp.Xrange[0], pp.Xrange[1]
	}
	if pp.Yrange != nil {
		ymin, ymax = pp.Yrange[0], pp.Yrange[1]
	}

	// check objective function
	var sol *Solution // copy of solution for objective function
	if o.MinProb == nil {
		pp.NoG = true
		pp.NoH = true
		sol = NewSolution(o.Nsol, 0, &o.Parameters)
		o.Solutions[0].CopyInto(sol)
		if pp.Refx != nil {
			copy(sol.Flt, pp.Refx)
		}
	}

	// auxiliary variables
	X, Y := utl.MeshGrid2D(xmin, xmax, ymin, ymax, pp.Npts, pp.Npts)
	var Zf [][]float64
	var Zg [][][]float64
	var Zh [][][]float64
	var Za [][]float64
	if !pp.NoF {
		Zf = utl.DblsAlloc(pp.Npts, pp.Npts)
	}
	if o.Ng > 0 && !pp.NoG {
		Zg = utl.Deep3alloc(o.Ng, pp.Npts, pp.Npts)
	}
	if o.Nh > 0 && !pp.NoH {
		Zh = utl.Deep3alloc(o.Nh, pp.Npts, pp.Npts)
	}
	if pp.WithAux {
		Za = utl.DblsAlloc(pp.Npts, pp.Npts)
	}

	// compute values
	grp := 0
	for i := 0; i < pp.Npts; i++ {
		for j := 0; j < pp.Npts; j++ {
			x[iFlt], x[jFlt] = X[i][j], Y[i][j]
			if o.MinProb == nil {
				copy(sol.Flt, x)
				o.ObjFunc(sol, grp)
				if !pp.NoF {
					Zf[i][j] = sol.Ova[iOva]
				}
				if pp.WithAux {
					Za[i][j] = sol.Aux
				}
			} else {
				o.MinProb(o.F[grp], o.G[grp], o.H[grp], x, nil, grp)
				if !pp.NoF {
					Zf[i][j] = o.F[grp][iOva]
				}
				if !pp.NoG {
					for k, g := range o.G[grp] {
						Zg[k][i][j] = g
					}
				}
				if !pp.NoH {
					for k, h := range o.H[grp] {
						Zh[k][i][j] = h
					}
				}
			}
		}
	}

	// plot f
	if !pp.NoF && !pp.OnlyAux {
		txt := "cbar=0"
		if pp.Cbar {
			txt = ""
		}
		if pp.Simple {
			plt.ContourSimple(X, Y, Zf, true, 7, io.Sf("colors=['%s'], fsz=7, %s", pp.FmtF.C, txt))
		} else {
			plt.Contour(X, Y, Zf, io.Sf("fsz=7, cmapidx=%d, %s", pp.CmapIdx, txt))
		}
	}

	// plot g
	if !pp.NoG && !pp.OnlyAux {
		for _, g := range Zg {
			plt.ContourSimple(X, Y, g, false, 7, io.Sf("zorder=5, levels=[0], colors=['%s'], linewidths=[%g], clip_on=0", pp.FmtG.C, pp.FmtG.Lw))
		}
	}

	// plot h
	if !pp.NoH && !pp.OnlyAux {
		for i, h := range Zh {
			if i == pp.IdxH || pp.IdxH < 0 {
				plt.ContourSimple(X, Y, h, false, 7, io.Sf("zorder=5, levels=[0], colors=['%s'], linewidths=[%g], clip_on=0", pp.FmtH.C, pp.FmtH.Lw))
			}
		}
	}

	// plot aux
	if pp.WithAux {
		if pp.OnlyAux {
			txt := "cbar=0"
			if pp.Cbar {
				txt = ""
			}
			if pp.Simple {
				plt.ContourSimple(X, Y, Za, true, 7, io.Sf("colors=['%s'], fsz=7, %s", pp.FmtF.C, txt))
			} else {
				plt.Contour(X, Y, Za, io.Sf("fsz=7, markZero='red', cmapidx=%d, %s", pp.CmapIdx, txt))
			}
		} else {
			plt.ContourSimple(X, Y, Za, false, 7, io.Sf("zorder=5, levels=[0], colors=['%s'], linewidths=[%g], clip_on=0", pp.FmtA.C, pp.FmtA.Lw))
		}
	}

	// limits
	if pp.Limits {
		plt.Plot(
			[]float64{o.FltMin[iFlt], o.FltMax[iFlt], o.FltMax[iFlt], o.FltMin[iFlt], o.FltMin[iFlt]},
			[]float64{o.FltMin[jFlt], o.FltMin[jFlt], o.FltMax[jFlt], o.FltMax[jFlt], o.FltMin[jFlt]},
			"'y--', color='yellow', zorder=10",
		)
	}
}