Пример #1
0
func Test_groups01(tst *testing.T) {

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

	Init(0)

	ng := 3            // number of groups
	nints := 12        // number of integers
	size := nints / ng // groups size
	ints := utl.IntRange(nints)
	groups := utl.IntsAlloc(ng, size)
	hists := make([]*IntHistogram, ng)
	for i := 0; i < ng; i++ {
		hists[i] = &IntHistogram{Stations: utl.IntRange(nints + 1)}
	}
	IntGetGroups(groups, ints)
	io.Pfcyan("groups = %v\n", groups)
	for i := 0; i < NSAMPLES; i++ {
		IntGetGroups(groups, ints)
		for j := 0; j < ng; j++ {
			check_repeated(groups[j])
			hists[j].Count(groups[j], false)
		}
	}
	for i := 0; i < ng; i++ {
		io.Pf("\n")
		io.Pf(TextHist(hists[i].GenLabels("%d"), hists[i].Counts, 60))
	}
}
Пример #2
0
// PlotDerivs plots derivatives of basis functions in I
// option =  0 : use CalcBasisAndDerivs
//           1 : use NumericalDeriv
func (o *Bspline) PlotDerivs(args string, npts, option int) {
	nmks := 10
	tt := utl.LinSpace(o.tmin, o.tmax, npts)
	I := utl.IntRange(o.NumBasis())
	f := make([]float64, len(tt))
	lbls := []string{"N\\&dN", "numD"}
	var cmd string
	for _, i := range I {
		for j, t := range tt {
			switch option {
			case 0:
				o.CalcBasisAndDerivs(t)
				f[j] = o.GetDeriv(i)
			case 1:
				f[j] = o.NumericalDeriv(t, i)
			}
		}
		if strings.Contains(args, "marker") {
			cmd = io.Sf("label=r'%s:%d', color=GetClr(%d, 2) %s", lbls[option], i, i, args)
		} else {
			cmd = io.Sf("label=r'%s:%d', marker=(None if %d %%2 == 0 else GetMrk(%d/2,1)), markevery=(%d-1)/%d, clip_on=0, color=GetClr(%d, 2) %s", lbls[option], i, i, i, npts, nmks, i, args)
		}
		plt.Plot(tt, f, cmd)
	}
	plt.Gll("$t$", io.Sf(`$\frac{\mathrm{d}N_{i,%d}}{\mathrm{d}t}$`, o.p), io.Sf("leg=1, leg_out=1, leg_ncol=%d, leg_hlen=1.5, leg_fsz=7", o.NumBasis()))
	o.plt_ticks_spans()
}
Пример #3
0
func Test_MTint01(tst *testing.T) {

	//verbose()
	chk.PrintTitle("MTint01. integers (Mersenne Twister)")

	Init(1234)

	nints := 10
	vals := make([]int, NSAMPLES)

	// using MTint
	t0 := time.Now()
	for i := 0; i < NSAMPLES; i++ {
		vals[i] = MTint(0, nints-1)
	}
	io.Pforan("time elapsed = %v\n", time.Now().Sub(t0))

	hist := IntHistogram{Stations: utl.IntRange(nints + 1)}
	hist.Count(vals, true)
	io.Pfyel(TextHist(hist.GenLabels("%d"), hist.Counts, 60))

	// using MTints
	t0 = time.Now()
	MTints(vals, 0, nints-1)
	io.Pforan("time elapsed = %v\n", time.Now().Sub(t0))

	hist.Count(vals, true)
	io.Pfcyan(TextHist(hist.GenLabels("%d"), hist.Counts, 60))
}
Пример #4
0
func Test_MTshuffleInts01(tst *testing.T) {

	//verbose()
	chk.PrintTitle("MTshuffleInts01. Mersenne Twister")

	Init(0)

	n := 10
	nums := utl.IntRange(n)
	io.Pfgreen("before = %v\n", nums)
	MTintShuffle(nums)
	io.Pfcyan("after  = %v\n", nums)

	sort.Ints(nums)
	io.Pforan("sorted = %v\n", nums)
	chk.Ints(tst, "nums", nums, utl.IntRange(n))
}
Пример #5
0
func (g *Grid2D) Init(lx, ly float64, nx, ny int) {
	g.Lx, g.Ly = lx, ly
	g.Nx, g.Ny, g.N = nx, ny, nx*ny
	g.Dx, g.Dy = g.Lx/float64(nx-1), g.Ly/float64(ny-1)
	g.Dxx, g.Dyy = g.Dx*g.Dx, g.Dy*g.Dy

	g.L = utl.IntRange3(0, g.N, g.Nx)
	g.R = utl.IntAddScalar(g.L, g.Nx-1)
	g.B = utl.IntRange(g.Nx)
	g.T = utl.IntAddScalar(g.B, (g.Ny-1)*g.Nx)
}
Пример #6
0
func Test_GOshuffleInts01(tst *testing.T) {

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

	Init(0)

	n := 10
	nums := utl.IntRange(n)
	io.Pfgreen("before = %v\n", nums)
	IntShuffle(nums)
	io.Pfcyan("after  = %v\n", nums)

	sort.Ints(nums)
	io.Pforan("sorted = %v\n", nums)
	chk.Ints(tst, "nums", nums, utl.IntRange(n))

	shufled := IntGetShuffled(nums)
	io.Pfyel("shufled = %v\n", shufled)
	sort.Ints(shufled)
	chk.Ints(tst, "shufled", shufled, utl.IntRange(n))
}
Пример #7
0
func Test_getunique01(tst *testing.T) {

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

	Init(0)

	nsel := 5 // number of selections
	size := 10
	nums := utl.IntRange(size)
	hist := IntHistogram{Stations: utl.IntRange(size + 5)}
	sel := IntGetUnique(nums, nsel)
	io.Pfgreen("nums = %v\n", nums)
	io.Pfcyan("sel  = %v\n", sel)
	for i := 0; i < NSAMPLES; i++ {
		sel := IntGetUnique(nums, nsel)
		check_repeated(sel)
		hist.Count(sel, false)
		//io.Pfgrey("sel  = %v\n", sel)
	}

	io.Pf(TextHist(hist.GenLabels("%d"), hist.Counts, 60))
}
Пример #8
0
// FactoryNurbs1dCurveA generates a NURBS 1D curve
func FactoryNurbs1dCurveA() (b *Nurbs) {
	verts := [][]float64{
		{0.0, 0.0, 0, 1},
		{1.0, 0.2, 0, 1},
		{0.5, 1.5, 0, 1},
		{2.5, 2.0, 0, 1},
		{2.0, 0.4, 0, 1},
		{3.0, 0.0, 0, 1},
	}
	knots := [][]float64{
		{0, 0, 0, 0, 0.3, 0.7, 1, 1, 1, 1},
	}
	b = new(Nurbs)
	b.Init(1, []int{3}, knots)
	b.SetControl(verts, utl.IntRange(len(verts)))
	return
}
Пример #9
0
func Test_ends02(tst *testing.T) {

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

	rnd.Init(0)

	size := 20
	ncuts := 10
	nsamples := 100
	hist := rnd.IntHistogram{Stations: utl.IntRange(size + 3)}
	for i := 0; i < nsamples; i++ {
		ends := GenerateCxEnds(size, ncuts, nil)
		hist.Count(ends, false)
	}
	io.Pf("%s\n", rnd.TextHist(hist.GenLabels("%d"), hist.Counts, 60))
}
Пример #10
0
// ElemBryLocalInds returns the local (element) indices of control points @ boundaries
// (if element would have all surfaces @ boundaries)
func (o *Nurbs) ElemBryLocalInds() (I [][]int) {
	switch o.gnd {
	case 1:
		return
	case 2:
		I = make([][]int, 2*o.gnd)
		nx, ny := o.p[0]+1, o.p[1]+1
		I[3] = utl.IntRange3(0, nx*ny, nx)
		I[1] = utl.IntAddScalar(I[3], nx-1)
		I[0] = utl.IntRange(nx)
		I[2] = utl.IntAddScalar(I[0], (ny-1)*nx)
	case 3:
		I = make([][]int, 2*o.gnd)
		chk.Panic("3D NURBS: ElemBryLocalInds: TODO") // TODO
	}
	return
}
Пример #11
0
func Test_mwicz01(tst *testing.T) {

	//verbose()
	chk.PrintTitle("mwicz01. Michalewicz mutation")

	var ops OpsData
	ops.SetDefault()
	ops.Pm = 1.0
	ops.Tmax = 10

	rnd.Init(0)

	ops.Xrange = [][]float64{{0, 2}, {1, 3}, {2, 4}, {3, 5}, {4, 6}}
	T := utl.IntRange(int(ops.Tmax))
	for _, t := range T {
		io.Pf("t=%v Δ=%v\n", t, ops.MwiczDelta(float64(t), 1))
	}
	for _, t := range T {
		A := []float64{0, 1, 2, 3, 4}
		FltMutationMwicz(A, t, &ops)
		io.Pforan("A = %.8f\n", A)
	}

	if chk.Verbose {
		b := 2.0
		f := func(r, tb float64) float64 {
			return math.Pow(r, math.Pow(1.0-tb, b))
		}
		np := 21
		r, tb := utl.MeshGrid2D(0, 1, 0, 1, np, np) // tb = t/tmax
		z := la.MatAlloc(np, np)
		for i := 0; i < np; i++ {
			for j := 0; j < np; j++ {
				z[i][j] = f(r[i][j], tb[i][j])
			}
		}
		plt.Surface(tb, r, z, "linewidth=0.8")
		plt.Gll("tb", "r", "")
		plt.SaveD("/tmp/goga", "test_mwicz01.eps")
		//plt.Show()
	}
}
Пример #12
0
func Test_getunique02(tst *testing.T) {

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

	Init(0)

	nsel := 5 // number of selections
	start := 2
	endp1 := 10
	hist := IntHistogram{Stations: utl.IntRange(endp1 + 3)}
	sel := IntGetUniqueN(start, endp1, nsel)
	io.Pfcyan("sel  = %v\n", sel)
	for i := 0; i < NSAMPLES; i++ {
		sel := IntGetUniqueN(start, endp1, nsel)
		check_repeated(sel)
		hist.Count(sel, false)
		//io.Pfgrey("sel  = %v\n", sel)
	}

	io.Pf(TextHist(hist.GenLabels("%d"), hist.Counts, 60))
}
Пример #13
0
// FactoryNurbs2dStrip generates a NURBS of a 2D strip (x-quadratic, y-linear)
func FactoryNurbs2dStrip() (b *Nurbs) {
	verts := [][]float64{
		{0.00, 0.00, 0, 0.80}, // 0
		{0.25, 0.15, 0, 1.00}, // 1
		{0.50, 0.00, 0, 0.70}, // 2
		{0.75, 0.00, 0, 1.20}, // 3
		{1.00, 0.10, 0, 1.10}, // 4
		{0.00, 0.40, 0, 0.90}, // 5
		{0.25, 0.55, 0, 0.60}, // 6
		{0.50, 0.40, 0, 1.50}, // 7
		{0.75, 0.40, 0, 1.40}, // 8
		{1.00, 0.50, 0, 0.50}, // 9
	}
	knots := [][]float64{
		{0, 0, 0, 1, 2, 3, 3, 3},
		{0, 0, 1, 1},
	}
	b = new(Nurbs)
	b.Init(2, []int{2, 1}, knots)
	b.SetControl(verts, utl.IntRange(len(verts)))
	return
}
Пример #14
0
func Test_p01a(tst *testing.T) {

	/* this tests simulates seepage flow along a column
	 * by reducing the initial hydrostatic pressure at
	 * at the bottom of the column
	 *
	 *      Nodes / Tags                 Equations
	 *
	 *     8 o----o----o 9 (-5)      22 o----o----o 21
	 *       |   14    |                |   24    |
	 *       |         |                |         |
	 *    21 o    o    o 22 (-6)     25 o    o    o 23
	 *       |   26    |                |   26    |
	 *       |         |                |         |
	 *     6 o----o----o 7 (-4)      16 o----o----o 15
	 *       |   13    |                |   18    |
	 *       |         |                |         |
	 *    19 |    o    o 20 (-6)     19 |    o    o 17
	 *       |   25    |                |   20    |
	 *       |         |                |         |
	 *     4 o----o----o 5 (-3)      10 o----o----o 9
	 *       |   12    |                |   12    |
	 *       |         |                |         |
	 *    17 o    o    o 18 (-6)     13 o    o    o 11
	 *       |   24    |                |   14    |
	 *       |         |                |         |
	 *     2 o----o----o 3 (-2)       3 o----o----o 2
	 *       |   11    |                |    6    |
	 *       |         |                |         |
	 *    15 o    o    o 16 (-6)      7 o    o    o 5
	 *       |   23    |                |    8    |
	 *       |         |                |         |
	 *     0 o----o----o 1 (-1)       0 o----o----o 1
	 *           10                          4
	 */

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

	// start simulation
	analysis := NewFEM("data/p01.sim", "", true, false, false, false, chk.Verbose, 0)

	// set stage
	err := analysis.SetStage(0)
	if err != nil {
		tst.Errorf("SetStage failed:\n%v", err)
		return
	}

	// initialise solution vectros
	err = analysis.ZeroStage(0, true)
	if err != nil {
		tst.Errorf("ZeroStage failed:\n%v", err)
		return
	}

	// domain
	dom := analysis.Domains[0]

	// nodes and elements
	chk.IntAssert(len(dom.Nodes), 27)
	chk.IntAssert(len(dom.Elems), 4)

	// check dofs
	for _, nod := range dom.Nodes {
		chk.IntAssert(len(nod.Dofs), 1)
		chk.StrAssert(nod.Dofs[0].Key, "pl")
	}

	// check equations
	nids, eqs := get_nids_eqs(dom)
	chk.Ints(tst, "nids", nids, []int{
		0, 1, 3, 2, 10, 16, 11, 15, 23,
		5, 4, 18, 12, 17, 24,
		7, 6, 20, 13, 19, 25,
		9, 8, 22, 14, 21, 26,
	})
	chk.Ints(tst, "eqs", eqs, utl.IntRange(27))

	// check pmap
	pmaps := [][]int{
		{0, 1, 2, 3, 4, 5, 6, 7, 8},
		{3, 2, 9, 10, 6, 11, 12, 13, 14},
		{10, 9, 15, 16, 12, 17, 18, 19, 20},
		{16, 15, 21, 22, 18, 23, 24, 25, 26},
	}
	for i, ele := range dom.Elems {
		e := ele.(*ElemP)
		io.Pforan("e%d.pmap = %v\n", e.Id(), e.Pmap)
		chk.Ints(tst, "pmap", e.Pmap, pmaps[i])
	}

	// constraints
	chk.IntAssert(len(dom.EssenBcs.Bcs), 3)
	var ct_pl_eqs []int // equations with pl prescribed [sorted]
	for _, c := range dom.EssenBcs.Bcs {
		chk.IntAssert(len(c.Eqs), 1)
		eq := c.Eqs[0]
		io.Pforan("key=%v eq=%v\n", c.Key, eq)
		switch c.Key {
		case "pl":
			ct_pl_eqs = append(ct_pl_eqs, eq)
		default:
			tst.Errorf("key %s is incorrect", c.Key)
		}
	}
	sort.Ints(ct_pl_eqs)
	chk.Ints(tst, "equations with pl prescribed", ct_pl_eqs, []int{0, 1, 4})

	// initial values @ nodes
	io.Pforan("initial values @ nodes\n")
	for _, nod := range dom.Nodes {
		z := nod.Vert.C[1]
		eq := nod.Dofs[0].Eq
		pl := dom.Sol.Y[eq]
		plC, _, _ := dom.HydSta.Calc(z)
		chk.Scalar(tst, io.Sf("nod %3d : pl(@ %4g)= %6g", nod.Vert.Id, z, pl), 1e-17, pl, plC)
	}

	// intial values @ integration points
	io.Pforan("initial values @ integration points\n")
	for _, ele := range dom.Elems {
		e := ele.(*ElemP)
		for idx, ip := range e.IpsElem {
			s := e.States[idx]
			z := e.Cell.Shp.IpRealCoords(e.X, ip)[1]
			_, ρLC, _ := dom.HydSta.Calc(z)
			chk.Scalar(tst, io.Sf("sl(@ %18g)= %18g", z, s.A_sl), 1e-17, s.A_sl, 1)
			chk.Scalar(tst, io.Sf("ρL(@ %18g)= %18g", z, s.A_ρL), 1e-13, s.A_ρL, ρLC)
		}
	}
}
Пример #15
0
func Test_out01(tst *testing.T) {

	// finalise analysis process and catch errors
	defer func() {
		if err := recover(); err != nil {
			tst.Fail()
			io.PfRed("ERROR: %v\n", err)
		}
	}()

	// test title
	//verbose()
	chk.PrintTitle("out01")

	// start simulation
	processing := fem.NewFEM("data/onequa4.sim", "", true, true, false, false, chk.Verbose, 0)

	// run simulation
	err := processing.Run()
	if err != nil {
		tst.Errorf("Run failed:\n%v", err)
		return
	}

	// start post-processing
	Start("data/onequa4.sim", 0, 0)

	// define points
	Define("A B C D", N{0, 1, 2, 3})
	Define("a b c d", P{{0, 0}, {0, 1}, {-1, 2}, {-1, 3}})
	Define("!right side", Along{{1, 0}, {1, 1}})
	io.Pfcyan("Entities = %v\n", Results)

	// check slices
	nnod := 4
	nele := 1
	nip := 4
	chk.IntAssert(len(Dom.Nodes), nnod)
	chk.IntAssert(len(Ipoints), nele*nip)
	chk.IntAssert(len(Cid2ips), 1)
	chk.IntAssert(len(Ipkey2ips), 4)
	chk.IntAssert(len(Ipkeys), 4)
	for key, ips := range Ipkey2ips {
		chk.Ints(tst, io.Sf("%s : ips", key), ips, utl.IntRange(4))
	}

	// load results
	LoadResults(nil)

	// check points
	nlabels := []string{"A", "B", "C", "D"}
	for _, l := range nlabels {
		if _, ok := Results[l]; !ok {
			chk.Panic("1: %q alias in Entities is not available", l)
		}
	}
	plabels := []string{"a", "b", "c", "d"}
	for _, l := range plabels {
		if _, ok := Results[l]; !ok {
			chk.Panic("2: %q alias in Entities is not available", l)
		}
	}
	if _, ok := Results["right side"]; !ok {
		chk.Panic("3: %q alias in Entities is not available", "right side")
	}

	// check u-keys
	ukeys := []string{"ux", "uy"}
	for _, l := range nlabels {
		for _, p := range Results[l] {
			//io.Pfyel("p = %v\n", p)
			if p == nil {
				chk.Panic("1: p is nil")
			}
			for _, key := range ukeys {
				if _, ok := p.Vals[key]; !ok {
					chk.Panic("%s is not available in point", key)
				}
			}
		}
	}

	// check s-keys
	skeys := fem.StressKeys(Dom.Sim.Ndim)
	for _, l := range plabels {
		for _, p := range Results[l] {
			//io.Pfgreen("q = %v\n", p)
			if p == nil {
				chk.Panic("2: p is nil")
			}
			for _, key := range skeys {
				if _, ok := p.Vals[key]; !ok {
					chk.Panic("%s is not available in point", key)
				}
			}
		}
	}

	// check GetRes
	uxC := GetRes("ux", "C", 0)
	uxR := GetRes("ux", "right side", -1)
	io.Pforan("uxC = %v\n", uxC)
	io.Pforan("uxR = %v\n", uxR)
	chk.IntAssert(len(uxC), 2)
	idx := len(uxC) - 1
	chk.Vector(tst, "uxR", 1e-17, uxR, []float64{uxC[idx], uxC[idx]})

	// solution
	var sol ana.CteStressPstrain
	sol.Init(fun.Prms{
		&fun.Prm{N: "qnH", V: -50},
		&fun.Prm{N: "qnV", V: -100},
	})

	// check displacements
	tolu := 1e-15
	for _, l := range nlabels {
		x := GetCoords(l)
		ux := GetRes("ux", l, 0)
		uy := GetRes("uy", l, 0)
		io.Pforan("ux=%v uy=%v\n", ux, uy)
		for j, t := range Times {
			io.Pfyel("t=%g\n", t)
			sol.CheckDispl(tst, t, []float64{ux[j], uy[j]}, x, tolu)
		}
	}

	// check stresses
	tolσ := 1e-14
	for _, l := range plabels {
		x := GetCoords(l)
		sx := GetRes("sx", l, 0)
		sy := GetRes("sy", l, 0)
		sz := GetRes("sz", l, 0)
		sxy := GetRes("sxy", l, 0)
		for j, t := range Times {
			io.Pfyel("t=%g\n", t)
			sol.CheckStress(tst, t, []float64{sx[j], sy[j], sz[j], sxy[j]}, x, tolσ)
		}
	}
}
Пример #16
0
func test_contact01a(tst *testing.T) {

	/*     Nodes                           Equations:
	 *                   7                                  33,34
	 *     6 o-----o-----o-----o-----o 8       35 o-----o-----o-----o-----o 45,46,47
	 *       |    13     |    14     |         36 |   39,40   |   51,52   |
	 *       |           |           |            |         37|           | 48
	 *    18 o    [2]    o19  [3]    o 20      41 o     o   38o     o     o 49
	 *       |    23     |    24     |         42 |   43,44   |   53,54   | 50
	 *       |           |           |            |          4|           |
	 *     3 o-----o-----o-----o-----o 5        6 o-----o-----o-----o-----o 21,22,23
	 *       |    11    4|    12     |          7 |   12,13  5|   29,30   |
	 *       |           |           |            |           |           | 26
	 *    15 o    [0]    o16  [1]    o 17   14,15 o     o   10o     o     o 27
	 *       |    21     |    22     |            |   16,17 11|   31,32   | 28
	 *       |           |           |            |           |           |
	 *     0 o-----o-----o-----o-----o 2        0 o-----o-----o-----o-----o 18
	 *             9     1     10               1       8     2   24,25     19
	 *                                                  9     3             20
	 */

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

	// start simulation
	analysis := NewFEM("data/contact01.sim", "", true, false, false, false, chk.Verbose, 0)

	// set stage
	err := analysis.SetStage(0)
	if err != nil {
		tst.Errorf("SetStage failed:\n%v", err)
		return
	}

	// initialise solution vectros
	err = analysis.ZeroStage(0, true)
	if err != nil {
		tst.Errorf("ZeroStage failed:\n%v", err)
		return
	}

	// domain
	dom := analysis.Domains[0]

	// nodes and elements
	chk.IntAssert(len(dom.Nodes), 25)
	chk.IntAssert(len(dom.Elems), 4)

	// check equations
	nids, eqs := get_nids_eqs(dom)
	chk.Ints(tst, "nids", nids, []int{0, 1, 4, 3, 9, 16, 11, 15, 21, 2, 5, 10, 17, 12, 22, 7, 6, 19, 13, 18, 23, 8, 20, 14, 24})
	chk.Ints(tst, "eqs", eqs, utl.IntRange(55))

	// vertices with "qbn"
	contactverts := map[int]bool{2: true, 17: true, 5: true, 20: true, 8: true}

	// check dofs
	var contacteqs []int
	for _, nod := range dom.Nodes {
		if contactverts[nod.Vert.Id] {
			chk.IntAssert(len(nod.Dofs), 3)
			contacteqs = append(contacteqs, nod.Dofs[2].Eq)
		} else {
			chk.IntAssert(len(nod.Dofs), 2)
		}
	}
	sort.Ints(contacteqs)
	io.Pforan("contacteqs = %v\n", contacteqs)
	chk.Ints(tst, "contacteqs", contacteqs, []int{20, 23, 28, 47, 50})

	// check Qmap
	e1 := dom.Elems[1].(*ElemU)
	chk.Ints(tst, "e1.Qmap", e1.Qmap, []int{20, 23, 28})
	e3 := dom.Elems[3].(*ElemU)
	chk.Ints(tst, "e3.Qmap", e3.Qmap, []int{23, 47, 50})
}
Пример #17
0
// Solve solves optimisation problem
func (o *Optimiser) Solve() {

	// benchmark
	if o.Verbose {
		t0 := gotime.Now()
		defer func() {
			io.Pf("\nnfeval = %d\n", o.Nfeval)
			io.Pfblue2("cpu time = %v\n", gotime.Now().Sub(t0))
		}()
	}

	// output
	if o.Output != nil {
		o.Output(0, o.Solutions)
	}

	// perform evolution
	done := make(chan int, o.Ncpu)
	time := 0
	texc := time + o.DtExc
	for time < o.Tf {

		// run groups in parallel. up to exchange time
		for icpu := 0; icpu < o.Ncpu; icpu++ {
			go func(cpu int) {
				nfeval := 0
				for t := time; t < texc; t++ {
					if cpu == 0 && o.Verbose {
						io.Pf("time = %10d\r", t+1)
					}
					nfeval += o.EvolveOneGroup(cpu)
				}
				done <- nfeval
			}(icpu)
		}
		for cpu := 0; cpu < o.Ncpu; cpu++ {
			o.Nfeval += <-done
		}

		// compute metrics with all solutions included
		o.Metrics.Compute(o.Solutions)

		// exchange via tournament
		if o.Ncpu > 1 {
			if o.ExcTour {
				for i := 0; i < o.Ncpu; i++ {
					j := (i + 1) % o.Ncpu
					I := rnd.IntGetUnique(o.Groups[i].Indices, 2)
					J := rnd.IntGetUnique(o.Groups[j].Indices, 2)
					A, B := o.Groups[i].All[I[0]], o.Groups[i].All[I[1]]
					a, b := o.Groups[j].All[J[0]], o.Groups[j].All[J[1]]
					o.Tournament(A, B, a, b, o.Metrics)
				}
			}

			// exchange one randomly
			if o.ExcOne {
				rnd.IntGetGroups(o.cpupairs, utl.IntRange(o.Ncpu))
				for _, pair := range o.cpupairs {
					i, j := pair[0], pair[1]
					n := utl.Imin(o.Groups[i].Ncur, o.Groups[j].Ncur)
					k := rnd.Int(0, n)
					A := o.Groups[i].All[k]
					B := o.Groups[j].All[k]
					B.CopyInto(o.tmp)
					A.CopyInto(B)
					o.tmp.CopyInto(A)
				}
			}
		}

		// update time variables
		time += o.DtExc
		texc += o.DtExc
		time = utl.Imin(time, o.Tf)
		texc = utl.Imin(texc, o.Tf)

		// output
		if o.Output != nil {
			o.Output(time, o.Solutions)
		}
	}
}
Пример #18
0
func Test_spo751a(tst *testing.T) {

	/* de Souza Neto, Perić and Owen, ex 7.5.1 p244
	 *
	 *                       22
	 *                        .
	 *                  19  ,' `.
	 *                    ,'     '.
	 *              17  ,'         \
	 *                .'            \
	 *           14 ,' `.            \ 21
	 *         12 ,'     \            '
	 *       9  .'        \            '
	 *     7  ,' `.        \ 16         '
	 *   4  .'     \        .           `
	 *  2  ' `.     \ 11     .          |
	 *    `.   \ 6   .       |          |
	 *     1.   .    |       |          |
	 *      |   |    |       |          |
	 *      -----------------------------
	 *      0 3 5 8 10  13  15    18   20
	 */

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

	// start simulation
	analysis := NewFEM("data/spo751.sim", "", true, false, false, false, chk.Verbose, 0)

	// set stage
	err := analysis.SetStage(0)
	if err != nil {
		tst.Errorf("SetStage failed:\n%v", err)
		return
	}

	// initialise solution vectros
	err = analysis.ZeroStage(0, true)
	if err != nil {
		tst.Errorf("ZeroStage failed:\n%v", err)
		return
	}

	// domain
	dom := analysis.Domains[0]

	// nodes and elements
	chk.IntAssert(len(dom.Nodes), 23)
	chk.IntAssert(len(dom.Elems), 4)

	// check dofs
	for _, nod := range dom.Nodes {
		chk.IntAssert(len(nod.Dofs), 2)
	}

	// check equations
	nids, eqs := get_nids_eqs(dom)
	chk.Ints(tst, "nids", nids, []int{0, 5, 7, 2, 3, 6, 4, 1, 10, 12, 8, 11, 9, 15, 17, 13, 16, 14, 20, 22, 18, 21, 19})
	chk.Ints(tst, "eqs", eqs, utl.IntRange(23*2))

	// check solution arrays
	ny := 23 * 2
	nλ := 9 + 9
	nyb := ny + nλ
	chk.IntAssert(len(dom.Sol.Y), ny)
	chk.IntAssert(len(dom.Sol.Dydt), 0)
	chk.IntAssert(len(dom.Sol.D2ydt2), 0)
	chk.IntAssert(len(dom.Sol.Psi), 0)
	chk.IntAssert(len(dom.Sol.Zet), 0)
	chk.IntAssert(len(dom.Sol.Chi), 0)
	chk.IntAssert(len(dom.Sol.L), nλ)
	chk.IntAssert(len(dom.Sol.ΔY), ny)

	// check linear solver arrays
	chk.IntAssert(len(dom.Fb), nyb)
	chk.IntAssert(len(dom.Wb), nyb)

	// check umap
	umaps := [][]int{
		{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15},
		{2, 3, 16, 17, 18, 19, 4, 5, 20, 21, 22, 23, 24, 25, 10, 11},
		{16, 17, 26, 27, 28, 29, 18, 19, 30, 31, 32, 33, 34, 35, 22, 23},
		{26, 27, 36, 37, 38, 39, 28, 29, 40, 41, 42, 43, 44, 45, 32, 33},
	}
	for i, ele := range dom.Elems {
		e := ele.(*ElemU)
		io.Pforan("e%d.umap = %v\n", e.Id(), e.Umap)
		chk.Ints(tst, "umap", e.Umap, umaps[i])
	}

	// constraints
	chk.IntAssert(len(dom.EssenBcs.Bcs), nλ)
	var ct_uy_eqs []int // constrained uy equations [sorted]
	var ct_incsup_xeqs []int
	var ct_incsup_yeqs []int
	αrad := 120.0 * math.Pi / 180.0
	cα, sα := math.Cos(αrad), math.Sin(αrad)
	for _, c := range dom.EssenBcs.Bcs {
		chk.IntAssertLessThanOrEqualTo(1, len(c.Eqs)) // 1 ≤ neqs
		io.Pforan("c.Key=%s c.Eqs=%v\n", c.Key, c.Eqs)
		if len(c.Eqs) == 1 {
			if c.Key == "uy" {
				ct_uy_eqs = append(ct_uy_eqs, c.Eqs[0])
				continue
			}
		} else {
			if c.Key == "incsup" {
				ct_incsup_xeqs = append(ct_incsup_xeqs, c.Eqs[0])
				ct_incsup_yeqs = append(ct_incsup_yeqs, c.Eqs[1])
				chk.AnaNum(tst, "cos(α)", 1e-15, c.ValsA[0], cα, false)
				chk.AnaNum(tst, "sin(α)", 1e-15, c.ValsA[1], sα, false)
				continue
			}
		}
		tst.Errorf("key %s is incorrect", c.Key)
	}
	sort.Ints(ct_uy_eqs)
	sort.Ints(ct_incsup_xeqs)
	sort.Ints(ct_incsup_yeqs)
	chk.Ints(tst, "constrained uy equations", ct_uy_eqs, []int{1, 3, 9, 17, 21, 27, 31, 37, 41})
	chk.Ints(tst, "incsup x equations", ct_incsup_xeqs, []int{4, 6, 12, 18, 24, 28, 34, 38, 44})
	chk.Ints(tst, "incsup y equations", ct_incsup_yeqs, []int{5, 7, 13, 19, 25, 29, 35, 39, 45})
}
Пример #19
0
func Test_nurbs01(tst *testing.T) {

	/*  4 (1,2)             (2,2) 6
	    5  2@o--------------o@3   7
	         |              |
	         |              |      @     -- control point
	         |              |      o     -- node
	         |              |      (a,b) -- span
	         |              |
	         |              |
	    0  0@o--------------o@1   2
	    1 (1,1)             (2,1) 3
	*/

	//verbose()
	chk.PrintTitle("nurb01. square with initial stress")

	// fem
	analysis := NewFEM("data/nurbs01.sim", "", true, false, false, false, chk.Verbose, 0)

	// set stage
	err := analysis.SetStage(0)
	if err != nil {
		tst.Errorf("SetStage failed:\n%v", err)
		return
	}

	// initialise solution vectors
	err = analysis.ZeroStage(0, true)
	if err != nil {
		tst.Errorf("ZeroStage failed:\n%v", err)
		return
	}

	// domain
	dom := analysis.Domains[0]

	// draw NURBS
	if false {
		nurbs := dom.Msh.Cells[0].Shp.Nurbs
		gm.PlotNurbs("/tmp/gofem", "test_nurbs01", nurbs, 21, false, nil)
	}

	// nodes and elements
	chk.IntAssert(len(dom.Nodes), 4)
	chk.IntAssert(len(dom.Elems), 1)

	// check dofs
	for _, nod := range dom.Nodes {
		chk.IntAssert(len(nod.Dofs), 2)
		chk.StrAssert(nod.Dofs[0].Key, "ux")
		chk.StrAssert(nod.Dofs[1].Key, "uy")
	}

	// check equations
	nids, eqs := get_nids_eqs(dom)
	chk.Ints(tst, "eqs", eqs, utl.IntRange(4*2))
	chk.Ints(tst, "nids", nids, []int{0, 1, 2, 3})

	// check Umap
	Umaps := [][]int{
		{0, 1, 2, 3, 4, 5, 6, 7},
	}
	for i, ele := range dom.Elems {
		e := ele.(*ElemU)
		io.Pfpink("%2d : Umap = %v\n", e.Id(), e.Umap)
		chk.Ints(tst, "Umap", e.Umap, Umaps[i])
	}

	// constraints
	chk.IntAssert(len(dom.EssenBcs.Bcs), 4)
	var ct_ux_eqs []int // equations with ux prescribed [sorted]
	var ct_uy_eqs []int // equations with uy prescribed [sorted]
	for _, c := range dom.EssenBcs.Bcs {
		chk.IntAssert(len(c.Eqs), 1)
		eq := c.Eqs[0]
		io.Pfgrey("key=%v eq=%v\n", c.Key, eq)
		switch c.Key {
		case "ux":
			ct_ux_eqs = append(ct_ux_eqs, eq)
		case "uy":
			ct_uy_eqs = append(ct_uy_eqs, eq)
		default:
			tst.Errorf("key %s is incorrect", c.Key)
		}
	}
	sort.Ints(ct_ux_eqs)
	sort.Ints(ct_uy_eqs)
	chk.Ints(tst, "equations with ux prescribed", ct_ux_eqs, []int{0, 4})
	chk.Ints(tst, "equations with uy prescribed", ct_uy_eqs, []int{1, 3})

	// check displacements
	tolu := 1e-16
	for _, n := range dom.Nodes {
		eqx := n.GetEq("ux")
		eqy := n.GetEq("uy")
		u := []float64{dom.Sol.Y[eqx], dom.Sol.Y[eqy]}
		chk.Vector(tst, "u", tolu, u, nil)
	}

	// analytical solution
	qnV, qnH := -100.0, -50.0
	ν := 0.25
	σx, σy := qnH, qnV
	σz := ν * (σx + σy)
	σref := []float64{σx, σy, σz, 0}

	// check stresses
	e := dom.Elems[0].(*ElemU)
	tols := 1e-13
	for idx, _ := range e.IpsElem {
		σ := e.States[idx].Sig
		io.Pforan("σ = %v\n", σ)
		chk.Vector(tst, "σ", tols, σ, σref)
	}
}
Пример #20
0
func Test_up01a(tst *testing.T) {

	/* this tests simulates seepage flow along a column
	 * by reducing the initial hydrostatic pressure at
	 * at the bottom of the column
	 *
	 *   using mesh from col104elay.msh
	 *
	 *      Nodes / Tags                       Equations
	 *                              ux uy pl               ux uy pl
	 *     8 o----o----o 9 (-5)     53 54 55  o----o----o  50 51 52
	 *       |   14    |             .  .  .  |  58 59  |   .  .  .
	 *       |  (-1)   |             .  .  .  |         |   .  .  .
	 *    21 o    o    o 22 (-6)    60 61  .  o    o    o  56 57  .
	 *       |   26    |             .  .  .  |  62 63  |   .  .  .
	 *       |         |             .  .  .  |         |   .  .  .
	 *     6 o----o----o 7 (-4)     39 40 41  o----o----o  36 37 38
	 *       |   13    |             .  .  .  |  44 45  |   .  .  .
	 *       |  (-1)   |             .  .  .  |         |   .  .  .
	 *    19 |    o    o 20 (-6)    46 47  .  |    o    o  42 43  .
	 *       |   25    |             .  .  .  |  48 49  |   .  .  .
	 *       |         |             .  .  .  |         |   .  .  .
	 *     4 o----o----o 5 (-3)     25 26 27  o----o----o  22 23 24
	 *       |   12    |             .  .  .  |  30 31  |   .  .  .
	 *       |  (-2)   |             .  .  .  |         |   .  .  .
	 *    17 o    o    o 18 (-6)    32 33  .  o    o    o  28 29  .
	 *       |   24    |             .  .  .  |  34 35  |   .  .  .
	 *       |         |             .  .  .  |         |   .  .  .
	 *     2 o----o----o 3 (-2)      9 10 11  o----o----o   6  7  8
	 *       |   11    |             .  .  .  |  16 17  |   .  .  .
	 *       |  (-2)   |             .  .  .  |         |   .  .  .
	 *    15 o    o    o 16 (-6)    18 19     o    o    o  14 15
	 *       |   23    |             .  .  .  |  20 21  |   .  .  .
	 *       |         |             .  .  .  |         |   .  .  .
	 *     0 o----o----o 1 (-1)      0  1  2  o----o----o   3  4  5
	 *           10                              12 13
	 */

	// capture errors and flush log
	defer End()

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

	// start simulation
	if !Start("data/up01.sim", true, chk.Verbose) {
		chk.Panic("cannot start simulation")
	}

	// domain
	distr := false
	dom := NewDomain(Global.Sim.Regions[0], distr)
	if dom == nil {
		chk.Panic("cannot allocate new domain")
	}

	// set stage
	if !dom.SetStage(0, Global.Sim.Stages[0], distr) {
		chk.Panic("cannot set stage")
	}

	// nodes and elements
	chk.IntAssert(len(dom.Nodes), 27)
	chk.IntAssert(len(dom.Elems), 4)

	if true {

		// nodes with pl
		nods_with_pl := map[int]bool{0: true, 2: true, 4: true, 6: true, 8: true, 1: true, 3: true, 5: true, 7: true, 9: true}

		// check dofs
		for _, nod := range dom.Nodes {
			if nods_with_pl[nod.Vert.Id] {
				chk.IntAssert(len(nod.Dofs), 3)
				chk.StrAssert(nod.Dofs[0].Key, "ux")
				chk.StrAssert(nod.Dofs[1].Key, "uy")
				chk.StrAssert(nod.Dofs[2].Key, "pl")
			} else {
				chk.IntAssert(len(nod.Dofs), 2)
				chk.StrAssert(nod.Dofs[0].Key, "ux")
				chk.StrAssert(nod.Dofs[1].Key, "uy")
			}
		}

		// check equations
		nids, eqs := get_nids_eqs(dom)
		chk.Ints(tst, "eqs", eqs, utl.IntRange(10*3+17*2))
		chk.Ints(tst, "nids", nids, []int{
			0, 1, 3, 2, 10, 16, 11, 15, 23,
			5, 4, 18, 12, 17, 24,
			7, 6, 20, 13, 19, 25,
			9, 8, 22, 14, 21, 26,
		})

		// check pmap
		Pmaps := [][]int{
			{2, 5, 8, 11},
			{11, 8, 24, 27},
			{27, 24, 38, 41},
			{41, 38, 52, 55},
		}
		Umaps := [][]int{
			{0, 1, 3, 4, 6, 7, 9, 10, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21},
			{9, 10, 6, 7, 22, 23, 25, 26, 16, 17, 28, 29, 30, 31, 32, 33, 34, 35},
			{25, 26, 22, 23, 36, 37, 39, 40, 30, 31, 42, 43, 44, 45, 46, 47, 48, 49},
			{39, 40, 36, 37, 50, 51, 53, 54, 44, 45, 56, 57, 58, 59, 60, 61, 62, 63},
		}
		for i, ele := range dom.Elems {
			e := ele.(*ElemUP)
			io.Pfpink("%2d : Pmap = %v\n", e.Id(), e.P.Pmap)
			io.Pfpink("%2d : Umap = %v\n", e.Id(), e.U.Umap)
			chk.Ints(tst, "Pmap", e.P.Pmap, Pmaps[i])
			chk.Ints(tst, "Umap", e.U.Umap, Umaps[i])
		}

		// constraints
		chk.IntAssert(len(dom.EssenBcs.Bcs), 9*2+2+3)
		var ct_ux_eqs []int // equations with ux prescribed [sorted]
		var ct_uy_eqs []int // equations with uy prescribed [sorted]
		var ct_pl_eqs []int // equations with pl prescribed [sorted]
		for _, c := range dom.EssenBcs.Bcs {
			chk.IntAssert(len(c.Eqs), 1)
			eq := c.Eqs[0]
			io.Pfgrey("key=%v eq=%v\n", c.Key, eq)
			switch c.Key {
			case "ux":
				ct_ux_eqs = append(ct_ux_eqs, eq)
			case "uy":
				ct_uy_eqs = append(ct_uy_eqs, eq)
			case "pl":
				ct_pl_eqs = append(ct_pl_eqs, eq)
			default:
				tst.Errorf("key %s is incorrect", c.Key)
			}
		}
		sort.Ints(ct_ux_eqs)
		sort.Ints(ct_uy_eqs)
		sort.Ints(ct_pl_eqs)
		chk.Ints(tst, "equations with ux prescribed", ct_ux_eqs, []int{0, 3, 6, 9, 14, 18, 22, 25, 28, 32, 36, 39, 42, 46, 50, 53, 56, 60})
		chk.Ints(tst, "equations with uy prescribed", ct_uy_eqs, []int{1, 4, 13})
		chk.Ints(tst, "equations with pl prescribed", ct_pl_eqs, []int{2, 5})

	}

	// initial values @ nodes
	io.Pforan("initial values @ nodes\n")
	for _, nod := range dom.Nodes {
		z := nod.Vert.C[1]
		for _, dof := range nod.Dofs {
			u := dom.Sol.Y[dof.Eq]
			switch dof.Key {
			case "ux":
				chk.Scalar(tst, io.Sf("nod %3d : ux(@ %4g)= %6g", nod.Vert.Id, z, u), 1e-17, u, 0)
			case "uy":
				chk.Scalar(tst, io.Sf("nod %3d : uy(@ %4g)= %6g", nod.Vert.Id, z, u), 1e-17, u, 0)
			case "pl":
				plC, _, _ := Global.HydroSt.Calc(z)
				chk.Scalar(tst, io.Sf("nod %3d : pl(@ %4g)= %6g", nod.Vert.Id, z, u), 1e-13, u, plC)
			}
		}
	}

	// intial values @ integration points
	io.Pforan("initial values @ integration points\n")
	for _, ele := range dom.Elems {
		e := ele.(*ElemUP)
		for idx, ip := range e.P.IpsElem {
			s := e.P.States[idx]
			z := e.P.Shp.IpRealCoords(e.P.X, ip)[1]
			chk.AnaNum(tst, io.Sf("sl(z=%11.8f)", z), 1e-17, s.A_sl, 1, chk.Verbose)
		}
	}

	// parameters
	ν := 0.2            // Poisson's coefficient
	K0 := ν / (1.0 - ν) // earth pressure at rest
	nf := 0.3           // porosity
	sl := 1.0           // saturation
	ρL := 1.0           // intrinsic (real) density of liquid
	ρS_top := 2.0       // intrinsic (real) density of solids in top layer
	ρS_bot := 3.0       // intrinsic (real) density of solids in bottom layer
	h := 5.0            // height of each layer
	g := 10.0           // gravity

	// densities
	nl := nf * sl         // volume fraction of luqid
	ns := 1.0 - nf        // volume fraction of solid
	ρl := nl * ρL         // partial density of liquid
	ρs_top := ns * ρS_top // partial density of solids in top layer
	ρs_bot := ns * ρS_bot // partial density of solids in bottom layer
	ρ_top := ρl + ρs_top  // density of mixture in top layer
	ρ_bot := ρl + ρs_bot  // density of mixture in bottom layer

	// absolute values of stresses
	σV_z5 := ρ_top * g * h     // total vertical stress @ elevation z = 5 m (absolute value)
	σV_z0 := σV_z5 + ρ_bot*g*h // total vertical stress @ elevation z = 0 m (absolute value)
	io.Pfyel("ρ_top       = %g\n", ρ_top)
	io.Pfyel("ρ_bot       = %g\n", ρ_bot)
	io.Pfyel("|ΔσV_top|   = %g\n", ρ_top*g*h)
	io.Pfyel("|ΔσV_bot|   = %g\n", ρ_bot*g*h)
	io.PfYel("|σV|(@ z=0) = %g\n", σV_z0)
	io.PfYel("|σV|(@ z=5) = %g\n", σV_z5)

	// stress functions
	var sig fun.Pts
	var pres fun.Pts
	sig.Init(fun.Prms{
		&fun.Prm{N: "t0", V: 0.00}, {N: "y0", V: -σV_z0},
		&fun.Prm{N: "t1", V: 5.00}, {N: "y1", V: -σV_z5},
		&fun.Prm{N: "t2", V: 10.00}, {N: "y2", V: 0.0},
	})
	pres.Init(fun.Prms{
		&fun.Prm{N: "t0", V: 0.00}, {N: "y0", V: 100},
		&fun.Prm{N: "t1", V: 10.00}, {N: "y1", V: 0},
	})

	// check stresses
	io.Pforan("initial stresses @ integration points\n")
	for _, ele := range dom.Elems {
		e := ele.(*ElemUP)
		for idx, ip := range e.U.IpsElem {
			z := e.U.Shp.IpRealCoords(e.U.X, ip)[1]
			σe := e.U.States[idx].Sig
			sv := sig.F(z, nil)
			sve := sv + pres.F(z, nil)
			she := sve * K0
			if math.Abs(σe[2]-σe[0]) > 1e-17 {
				tst.Errorf("σx is not equal to σz: %g != %g\n", σe[2], σe[0])
				return
			}
			if math.Abs(σe[3]) > 1e-17 {
				tst.Errorf("σxy is not equal to zero: %g != 0\n", σe[3])
				return
			}
			chk.AnaNum(tst, io.Sf("sx(z=%11.8f)", z), 0.0003792, σe[0], she, chk.Verbose)
			chk.AnaNum(tst, io.Sf("sy(z=%11.8f)", z), 0.001517, σe[1], sve, chk.Verbose)
		}
	}
	return
}
Пример #21
0
func Test_int02(tst *testing.T) {

	//verbose()
	chk.PrintTitle("int02. TSP")

	// location / coordinates of stations
	locations := [][]float64{
		{60, 200}, {180, 200}, {80, 180}, {140, 180}, {20, 160}, {100, 160}, {200, 160},
		{140, 140}, {40, 120}, {100, 120}, {180, 100}, {60, 80}, {120, 80}, {180, 60},
		{20, 40}, {100, 40}, {200, 40}, {20, 20}, {60, 20}, {160, 20},
	}
	nstations := len(locations)

	// parameters
	C := NewConfParams()
	C.Nova = 1
	C.Noor = 0
	C.Nisl = 4
	C.Ninds = 24
	C.RegTol = 0.3
	C.RegPct = 0.2
	//C.Dtmig = 30
	C.GAtype = "crowd"
	C.ParetoPhi = 0.1
	C.Elite = false
	C.DoPlot = false //chk.Verbose
	//C.Rws = true
	C.SetIntOrd(nstations)
	C.CalcDerived()

	// initialise random numbers generator
	rnd.Init(0)

	// objective value function
	C.OvaOor = func(ind *Individual, idIsland, t int, report *bytes.Buffer) {
		L := locations
		ids := ind.Ints
		//io.Pforan("ids = %v\n", ids)
		dist := 0.0
		for i := 1; i < nstations; i++ {
			a, b := ids[i-1], ids[i]
			dist += math.Sqrt(math.Pow(L[b][0]-L[a][0], 2.0) + math.Pow(L[b][1]-L[a][1], 2.0))
		}
		a, b := ids[nstations-1], ids[0]
		dist += math.Sqrt(math.Pow(L[b][0]-L[a][0], 2.0) + math.Pow(L[b][1]-L[a][1], 2.0))
		ind.Ovas[0] = dist
		return
	}

	// evolver
	evo := NewEvolver(C)

	// print initial population
	pop := evo.Islands[0].Pop
	//io.Pf("\n%v\n", pop.Output(nil, false))

	// 0,4,8,11,14,17,18,15,12,19,13,16,10,6,1,3,7,9,5,2 894.363
	if false {
		for i, x := range []int{0, 4, 8, 11, 14, 17, 18, 15, 12, 19, 13, 16, 10, 6, 1, 3, 7, 9, 5, 2} {
			pop[0].Ints[i] = x
		}
		evo.Islands[0].CalcOvs(pop, 0)
		evo.Islands[0].CalcDemeritsAndSort(pop)
	}

	// check initial population
	ints := make([]int, nstations)
	if false {
		for i := 0; i < C.Ninds; i++ {
			for j := 0; j < nstations; j++ {
				ints[j] = pop[i].Ints[j]
			}
			sort.Ints(ints)
			chk.Ints(tst, "ints", ints, utl.IntRange(nstations))
		}
	}

	// run
	evo.Run()
	//io.Pf("%v\n", pop.Output(nil, false))
	io.Pfgreen("best = %v\n", evo.Best.Ints)
	io.Pfgreen("best OVA = %v  (871.117353844847)\n\n", evo.Best.Ovas[0])

	// best = [18 17 14 11 8 4 0 2 5 9 12 7 6 1 3 10 16 13 19 15]
	// best OVA = 953.4643474956656

	// best = [8 11 14 17 18 15 12 19 16 13 10 6 1 3 7 9 5 2 0 4]
	// best OVA = 871.117353844847

	// best = [5 2 0 4 8 11 14 17 18 15 12 19 16 13 10 6 1 3 7 9]
	// best OVA = 871.1173538448469

	// best = [6 10 13 16 19 15 18 17 14 11 8 4 0 2 5 9 12 7 3 1]
	// best OVA = 880.7760751923065

	// check final population
	if false {
		for i := 0; i < C.Ninds; i++ {
			for j := 0; j < nstations; j++ {
				ints[j] = pop[i].Ints[j]
			}
			sort.Ints(ints)
			chk.Ints(tst, "ints", ints, utl.IntRange(nstations))
		}
	}

	// plot travelling salesman path
	if C.DoPlot {
		plt.SetForEps(1, 300)
		X, Y := make([]float64, nstations), make([]float64, nstations)
		for k, id := range evo.Best.Ints {
			X[k], Y[k] = locations[id][0], locations[id][1]
			plt.PlotOne(X[k], Y[k], "'r.', ms=5, clip_on=0, zorder=20")
			plt.Text(X[k], Y[k], io.Sf("%d", id), "fontsize=7, clip_on=0, zorder=30")
		}
		plt.Plot(X, Y, "'b-', clip_on=0, zorder=10")
		plt.Plot([]float64{X[0], X[nstations-1]}, []float64{Y[0], Y[nstations-1]}, "'b-', clip_on=0, zorder=10")
		plt.Equal()
		plt.AxisRange(10, 210, 10, 210)
		plt.Gll("$x$", "$y$", "")
		plt.SaveD("/tmp/goga", "test_evo04.eps")
	}
}