Ejemplo n.º 1
0
func Test_mylab01(tst *testing.T) {

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

	I := make([]int, 5)
	IntFill(I, 666)
	J := IntVals(5, 666)
	Js := StrVals(5, "666")
	M := IntsAlloc(3, 4)
	N := DblsAlloc(3, 4)
	S := StrsAlloc(2, 3)
	A := IntRange(-1)
	a := IntRange2(0, 0)
	b := IntRange2(0, 1)
	c := IntRange2(0, 5)
	C := IntRange3(0, -5, -1)
	d := IntRange2(2, 5)
	D := IntRange2(-2, 5)
	e := IntAddScalar(D, 2)
	f := DblOnes(5)
	ff := DblVals(5, 666)
	g := []int{1, 2, 3, 4, 3, 4, 2, 1, 1, 2, 3, 4, 4, 2, 3, 7, 8, 3, 8, 3, 9, 0, 11, 23, 1, 2, 32, 12, 4, 32, 4, 11, 37}
	h := IntUnique(g)
	G := []int{1, 2, 3, 38, 3, 5, 3, 1, 2, 15, 38, 1, 11}
	H := IntUnique(D, C, G, []int{16, 39})
	X, Y := MeshGrid2D(3, 6, 10, 20, 4, 3)
	P := [][]int{
		{1, 2, 3, 4, 5},
		{-1, -2, -3, -4, -5},
		{6, 7, 8, 9, 10},
	}
	Pc := IntsClone(P)
	chk.Ints(tst, "I", I, []int{666, 666, 666, 666, 666})
	chk.Ints(tst, "J", J, []int{666, 666, 666, 666, 666})
	chk.Strings(tst, "Js", Js, []string{"666", "666", "666", "666", "666"})
	chk.Ints(tst, "A", A, []int{})
	chk.Ints(tst, "a", a, []int{})
	chk.Ints(tst, "b", b, []int{0})
	chk.Ints(tst, "c", c, []int{0, 1, 2, 3, 4})
	chk.Ints(tst, "C", C, []int{0, -1, -2, -3, -4})
	chk.Ints(tst, "d", d, []int{2, 3, 4})
	chk.Ints(tst, "D", D, []int{-2, -1, 0, 1, 2, 3, 4})
	chk.Ints(tst, "e", e, []int{0, 1, 2, 3, 4, 5, 6})
	chk.Vector(tst, "f", 1e-16, f, []float64{1, 1, 1, 1, 1})
	chk.Vector(tst, "ff", 1e-16, ff, []float64{666, 666, 666, 666, 666})
	chk.Ints(tst, "h", h, []int{0, 1, 2, 3, 4, 7, 8, 9, 11, 12, 23, 32, 37})
	chk.Ints(tst, "H", H, []int{-4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 11, 15, 16, 38, 39})
	chk.IntMat(tst, "M", M, [][]int{{0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}})
	chk.Matrix(tst, "N", 1e-17, N, [][]float64{{0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}})
	chk.Matrix(tst, "X", 1e-17, X, [][]float64{{3, 4, 5, 6}, {3, 4, 5, 6}, {3, 4, 5, 6}})
	chk.Matrix(tst, "Y", 1e-17, Y, [][]float64{{10, 10, 10, 10}, {15, 15, 15, 15}, {20, 20, 20, 20}})
	chk.StrMat(tst, "S", S, [][]string{{"", "", ""}, {"", "", ""}})
	chk.IntMat(tst, "Pc", Pc, P)
}
Ejemplo n.º 2
0
func Test_hc01(tst *testing.T) {

	//verbose()
	chk.PrintTitle("hc01. hypercube")

	Init(111)

	n := 10
	x := LatinIHS(2, n, 5)
	io.Pforan("x = %v\n", x)

	xcor := [][]int{
		{2, 9, 5, 8, 1, 4, 3, 10, 7, 6},
		{3, 10, 1, 2, 7, 4, 9, 6, 5, 8},
	}
	chk.IntMat(tst, "x", x, xcor)

	if chk.Verbose {
		xrange := [][]float64{
			{-1.0, 1.0},
			{0.0, 2.0},
		}
		PlotHc2d("/tmp/gosl", "test_hc01", x, xrange)
	}
}
Ejemplo n.º 3
0
func Test_nurbs04(tst *testing.T) {

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

	// NURBS
	a := FactoryNurbs2dPlateHole()
	b := a.KrefineN(2, false)
	c := a.KrefineN(4, false)

	// tolerace for normalised space comparisons
	tol := 1e-7

	// tags
	a_vt := tag_verts(a, tol)
	a_ct := map[string]int{
		"0_0": -1,
		"0_1": -2,
	}
	b_vt := tag_verts(b, tol)
	c_vt := tag_verts(c, tol)

	// write .msh files
	WriteMshD("/tmp/gosl/gm", "m_nurbs04a", []*Nurbs{a}, a_vt, a_ct, tol)
	WriteMshD("/tmp/gosl/gm", "m_nurbs04b", []*Nurbs{b}, b_vt, nil, tol)
	WriteMshD("/tmp/gosl/gm", "m_nurbs04c", []*Nurbs{c}, c_vt, nil, tol)

	// read .msh file back and check
	a_read := ReadMsh("/tmp/gosl/gm/m_nurbs04a")[0]
	chk.IntAssert(a_read.gnd, a.gnd)
	chk.Ints(tst, "p", a.p, a_read.p)
	chk.Ints(tst, "n", a.n, a_read.n)
	chk.Deep4(tst, "Q", 1.0e-17, a.Q, a_read.Q)
	chk.IntMat(tst, "l2i", a.l2i, a_read.l2i)

	// plot
	if chk.Verbose {
		PlotNurbs("/tmp/gosl/gm", "nurbs04a.png", a_read, 41, true, nil)
		PlotTwoNurbs("/tmp/gosl/gm", "nurbs04b.png", a, b, 41, true, nil)
		PlotTwoNurbs("/tmp/gosl/gm", "nurbs04c.png", a, c, 41, true, nil)
	}
}
Ejemplo n.º 4
0
func Test_mylab01(tst *testing.T) {

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

	I := make([]int, 5)
	IntFill(I, 666)
	J := IntVals(5, 666)
	Js := StrVals(5, "666")
	M := IntsAlloc(3, 4)
	N := DblsAlloc(3, 4)
	A := IntRange(-1)
	a := IntRange2(0, 0)
	b := IntRange2(0, 1)
	c := IntRange2(0, 5)
	C := IntRange3(0, -5, -1)
	d := IntRange2(2, 5)
	D := IntRange2(-2, 5)
	e := IntAddScalar(D, 2)
	f := DblOnes(5)
	ff := DblVals(5, 666)
	g := []int{1, 2, 3, 4, 3, 4, 2, 1, 1, 2, 3, 4, 4, 2, 3, 7, 8, 3, 8, 3, 9, 0, 11, 23, 1, 2, 32, 12, 4, 32, 4, 11, 37}
	h := IntUnique(g)
	G := []int{1, 2, 3, 38, 3, 5, 3, 1, 2, 15, 38, 1, 11}
	H := IntUnique(D, C, G, []int{16, 39})
	X, Y := MeshGrid2D(3, 6, 10, 20, 4, 3)
	io.Pf("I  = %v\n", I)
	io.Pf("Js = %v\n", Js)
	io.Pf("J  = %v\n", J)
	io.Pf("A  = %v\n", A)
	io.Pf("a  = %v\n", a)
	io.Pf("b  = %v\n", b)
	io.Pf("c  = %v\n", c)
	io.Pf("C  = %v\n", C)
	io.Pf("d  = %v\n", d)
	io.Pf("D  = %v\n", D)
	io.Pf("e  = %v\n", e)
	io.Pf("f  = %v\n", f)
	io.Pf("G  = %v\n", G)
	io.Pf("H  = %v\n", H)
	io.Pf("g  = %v\n", g)
	io.Pf("h  = %v\n", h)
	io.Pf("M  = %v\n", M)
	io.Pf("N  = %v\n", N)
	io.Pf("X  = %v\n", X)
	io.Pf("Y  = %v\n", Y)
	chk.Ints(tst, "I", I, []int{666, 666, 666, 666, 666})
	chk.Ints(tst, "J", J, []int{666, 666, 666, 666, 666})
	chk.Strings(tst, "Js", Js, []string{"666", "666", "666", "666", "666"})
	chk.Ints(tst, "A", A, []int{})
	chk.Ints(tst, "a", a, []int{})
	chk.Ints(tst, "b", b, []int{0})
	chk.Ints(tst, "c", c, []int{0, 1, 2, 3, 4})
	chk.Ints(tst, "C", C, []int{0, -1, -2, -3, -4})
	chk.Ints(tst, "d", d, []int{2, 3, 4})
	chk.Ints(tst, "D", D, []int{-2, -1, 0, 1, 2, 3, 4})
	chk.Ints(tst, "e", e, []int{0, 1, 2, 3, 4, 5, 6})
	chk.Vector(tst, "f", 1e-16, f, []float64{1, 1, 1, 1, 1})
	chk.Vector(tst, "ff", 1e-16, ff, []float64{666, 666, 666, 666, 666})
	chk.Ints(tst, "h", h, []int{0, 1, 2, 3, 4, 7, 8, 9, 11, 12, 23, 32, 37})
	chk.Ints(tst, "H", H, []int{-4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 11, 15, 16, 38, 39})
	chk.IntMat(tst, "M", M, [][]int{{0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}})
	chk.Matrix(tst, "N", 1e-17, N, [][]float64{{0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}})
	chk.Matrix(tst, "X", 1e-17, X, [][]float64{{3, 4, 5, 6}, {3, 4, 5, 6}, {3, 4, 5, 6}})
	chk.Matrix(tst, "Y", 1e-17, Y, [][]float64{{10, 10, 10, 10}, {15, 15, 15, 15}, {20, 20, 20, 20}})
}
Ejemplo n.º 5
0
func Test_nurbs01(tst *testing.T) {

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

	// NURBS
	b := FactoryNurbs2dStrip()
	elems := b.Elements()
	nbasis := b.GetElemNumBasis()
	io.Pforan("nbasis = %v\n", nbasis)
	chk.IntAssert(nbasis, 6) // orders := (2,1) => nbasis = (2+1)*(1+1) = 6

	// check basis and elements
	chk.Ints(tst, "elem[0]", elems[0], []int{2, 3, 1, 2})
	chk.Ints(tst, "elem[1]", elems[1], []int{3, 4, 1, 2})
	chk.Ints(tst, "elem[2]", elems[2], []int{4, 5, 1, 2})
	chk.Ints(tst, "ibasis0", b.IndBasis(elems[0]), []int{0, 1, 2, 5, 6, 7})
	chk.Ints(tst, "ibasis1", b.IndBasis(elems[1]), []int{1, 2, 3, 6, 7, 8})
	chk.Ints(tst, "ibasis2", b.IndBasis(elems[2]), []int{2, 3, 4, 7, 8, 9})
	chk.IntAssert(b.GetElemNumBasis(), len(b.IndBasis(elems[0])))

	// check derivatives
	b.CheckDerivs(tst, 11, 1e-5, false)

	// check spans
	solE := [][]int{{2, 3, 1, 2}, {3, 4, 1, 2}, {4, 5, 1, 2}}
	solL := [][]int{{0, 1, 2, 5, 6, 7}, {1, 2, 3, 6, 7, 8}, {2, 3, 4, 7, 8, 9}}
	for k, e := range elems {
		L := b.IndBasis(e)
		io.Pforan("e=%v: L=%v\n", e, L)
		chk.Ints(tst, "span", e, solE[k])
		chk.Ints(tst, "L", L, solL[k])
	}

	// check indices along curve
	io.Pf("\n------------ indices along curve -------------\n")
	chk.Ints(tst, "l0s2a0", b.IndsAlongCurve(0, 2, 0), []int{0, 1, 2})
	chk.Ints(tst, "l0s3a0", b.IndsAlongCurve(0, 3, 0), []int{1, 2, 3})
	chk.Ints(tst, "l0s4a0", b.IndsAlongCurve(0, 4, 0), []int{2, 3, 4})
	chk.Ints(tst, "l0s2a1", b.IndsAlongCurve(0, 2, 1), []int{5, 6, 7})
	chk.Ints(tst, "l0s3a1", b.IndsAlongCurve(0, 3, 1), []int{6, 7, 8})
	chk.Ints(tst, "l0s4a1", b.IndsAlongCurve(0, 4, 1), []int{7, 8, 9})
	chk.Ints(tst, "l1s1a0", b.IndsAlongCurve(1, 1, 0), []int{0, 5})
	chk.Ints(tst, "l1s1a1", b.IndsAlongCurve(1, 1, 1), []int{1, 6})
	chk.Ints(tst, "l1s1a2", b.IndsAlongCurve(1, 1, 2), []int{2, 7})
	chk.Ints(tst, "l1s1a3", b.IndsAlongCurve(1, 1, 3), []int{3, 8})
	chk.Ints(tst, "l1s1a4", b.IndsAlongCurve(1, 1, 4), []int{4, 9})

	// extract surfaces and check
	io.Pf("\n------------ extract surfaces -------------\n")
	surfs := b.ExtractSurfaces()
	chk.Deep4(tst, "surf0: Q", 1e-15, surfs[0].Q, [][][][]float64{
		{{{0, 0, 0, 0.8}}},         // 0
		{{{0, 0.4 * 0.9, 0, 0.9}}}, // 5
	})
	chk.Deep4(tst, "surf1: Q", 1e-15, surfs[1].Q, [][][][]float64{
		{{{1.0 * 1.1, 0.1 * 1.1, 0, 1.1}}}, // 4
		{{{1.0 * 0.5, 0.5 * 0.5, 0, 0.5}}}, // 9
	})
	chk.Deep4(tst, "surf2: Q", 1e-15, surfs[2].Q, [][][][]float64{
		{{{0.00 * 0.80, 0.00 * 0.80, 0, 0.80}}}, // 0
		{{{0.25 * 1.00, 0.15 * 1.00, 0, 1.00}}}, // 1
		{{{0.50 * 0.70, 0.00 * 0.70, 0, 0.70}}}, // 2
		{{{0.75 * 1.20, 0.00 * 1.20, 0, 1.20}}}, // 3
		{{{1.00 * 1.10, 0.10 * 1.10, 0, 1.10}}}, // 4
	})
	chk.Deep4(tst, "surf3: Q", 1e-15, surfs[3].Q, [][][][]float64{
		{{{0.00 * 0.90, 0.40 * 0.90, 0, 0.90}}}, // 5
		{{{0.25 * 0.60, 0.55 * 0.60, 0, 0.60}}}, // 6
		{{{0.50 * 1.50, 0.40 * 1.50, 0, 1.50}}}, // 7
		{{{0.75 * 1.40, 0.40 * 1.40, 0, 1.40}}}, // 8
		{{{1.00 * 0.50, 0.50 * 0.50, 0, 0.50}}}, // 9
	})

	io.Pf("\n------------ elem bry local inds -----------\n")
	elembryinds := b.ElemBryLocalInds()
	io.Pforan("elembryinds = %v\n", elembryinds)
	chk.IntMat(tst, "elembryinds", elembryinds, [][]int{
		{0, 1, 2},
		{2, 5},
		{3, 4, 5},
		{0, 3},
	})

	// refine NURBS
	c := b.Krefine([][]float64{
		{0.5, 1.5, 2.5},
		{0.5},
	})
	elems = c.Elements()
	chk.IntAssert(c.GetElemNumBasis(), len(c.IndBasis(elems[0])))

	// check refined elements: round 1
	io.Pf("\n------------ refined -------------\n")
	chk.Ints(tst, "elem[0]", elems[0], []int{2, 3, 1, 2})
	chk.Ints(tst, "elem[1]", elems[1], []int{3, 4, 1, 2})
	chk.Ints(tst, "elem[2]", elems[2], []int{4, 5, 1, 2})
	chk.Ints(tst, "elem[3]", elems[3], []int{5, 6, 1, 2})
	chk.Ints(tst, "elem[4]", elems[4], []int{6, 7, 1, 2})
	chk.Ints(tst, "elem[5]", elems[5], []int{7, 8, 1, 2})

	// check refined elements: round 2
	chk.Ints(tst, "elem[ 6]", elems[6], []int{2, 3, 2, 3})
	chk.Ints(tst, "elem[ 7]", elems[7], []int{3, 4, 2, 3})
	chk.Ints(tst, "elem[ 8]", elems[8], []int{4, 5, 2, 3})
	chk.Ints(tst, "elem[ 9]", elems[9], []int{5, 6, 2, 3})
	chk.Ints(tst, "elem[10]", elems[10], []int{6, 7, 2, 3})
	chk.Ints(tst, "elem[11]", elems[11], []int{7, 8, 2, 3})

	// check refined basis: round 1
	chk.Ints(tst, "basis0", c.IndBasis(elems[0]), []int{0, 1, 2, 8, 9, 10})
	chk.Ints(tst, "basis1", c.IndBasis(elems[1]), []int{1, 2, 3, 9, 10, 11})
	chk.Ints(tst, "basis2", c.IndBasis(elems[2]), []int{2, 3, 4, 10, 11, 12})
	chk.Ints(tst, "basis3", c.IndBasis(elems[3]), []int{3, 4, 5, 11, 12, 13})
	chk.Ints(tst, "basis4", c.IndBasis(elems[4]), []int{4, 5, 6, 12, 13, 14})
	chk.Ints(tst, "basis5", c.IndBasis(elems[5]), []int{5, 6, 7, 13, 14, 15})

	// check refined basis: round 2
	chk.Ints(tst, "basis6", c.IndBasis(elems[6]), []int{8, 9, 10, 16, 17, 18})
	chk.Ints(tst, "basis7", c.IndBasis(elems[7]), []int{9, 10, 11, 17, 18, 19})
	chk.Ints(tst, "basis8", c.IndBasis(elems[8]), []int{10, 11, 12, 18, 19, 20})
	chk.Ints(tst, "basis9", c.IndBasis(elems[9]), []int{11, 12, 13, 19, 20, 21})
	chk.Ints(tst, "basis10", c.IndBasis(elems[10]), []int{12, 13, 14, 20, 21, 22})
	chk.Ints(tst, "basis11", c.IndBasis(elems[11]), []int{13, 14, 15, 21, 22, 23})

	io.Pf("\n------------ refined: inds along curve -------------\n")
	chk.Ints(tst, "l0s2a0", c.IndsAlongCurve(0, 2, 0), []int{0, 1, 2})
	chk.Ints(tst, "l0s7a0", c.IndsAlongCurve(0, 7, 0), []int{5, 6, 7})
	chk.Ints(tst, "l0s3a2", c.IndsAlongCurve(0, 3, 2), []int{17, 18, 19})
	chk.Ints(tst, "l0s7a2", c.IndsAlongCurve(0, 7, 2), []int{21, 22, 23})
	chk.Ints(tst, "l1s1a0", c.IndsAlongCurve(1, 1, 0), []int{0, 8})
	chk.Ints(tst, "l1s1a0", c.IndsAlongCurve(1, 2, 0), []int{8, 16})
	chk.Ints(tst, "l1s2a7", c.IndsAlongCurve(1, 1, 7), []int{7, 15})
	chk.Ints(tst, "l1s2a7", c.IndsAlongCurve(1, 2, 7), []int{15, 23})

	// plot
	if chk.Verbose {
		io.Pf("\n------------ plot -------------\n")
		PlotNurbs("/tmp/gosl/gm", "nurbs01a.png", b, 41, true, func() {
			colors := []string{"#e78005", "#3944db", "#983cc3", "#529174"}
			for k, surf := range surfs {
				surf.DrawCtrl2d(true, io.Sf(", ls='none', marker='o', ms=4, zorder=20, color='%s'", colors[k]), "va='top', size=7")
				surf.DrawElems2d(21, true, io.Sf(", ls='none', marker='o', ms=4, zorder=20, color='%s'", colors[k]), "va='top', size=7")
			}
		})
		PlotNurbsBasis("/tmp/gosl/gm", "nurbs01b.png", b, 0, 7)
		PlotNurbsDerivs("/tmp/gosl/gm", "nurbs01c.png", b, 0, 7)
		PlotTwoNurbs("/tmp/gosl/gm", "nurbs01d.png", b, c, 41, true, nil)
	}
}
Ejemplo n.º 6
0
func Test_nurbs08(tst *testing.T) {

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

	a := get_nurbs_B()
	a_el := a.Elements()
	a_en := a.Enodes()
	chk.Ints(tst, "a_el[0]", a_el[0], []int{2, 3, 2, 3})
	chk.Ints(tst, "a_el[1]", a_el[1], []int{3, 4, 2, 3})
	chk.Ints(tst, "a_en[0]", a_en[0], []int{0, 1, 2, 4, 5, 6, 8, 9, 10})
	chk.Ints(tst, "a_en[1]", a_en[1], []int{1, 2, 3, 5, 6, 7, 9, 10, 11})

	b := a.KrefineN(2, false)
	b_el := b.Elements()
	b_en := b.Enodes()
	chk.Ints(tst, "b_el[0]", b_el[0], []int{2, 3, 2, 3})
	chk.Ints(tst, "b_el[1]", b_el[1], []int{3, 4, 2, 3})
	chk.Ints(tst, "b_el[2]", b_el[2], []int{4, 5, 2, 3})
	chk.Ints(tst, "b_el[3]", b_el[3], []int{5, 6, 2, 3})
	chk.Ints(tst, "b_el[4]", b_el[4], []int{2, 3, 3, 4})
	chk.Ints(tst, "b_el[5]", b_el[5], []int{3, 4, 3, 4})
	chk.Ints(tst, "b_el[6]", b_el[6], []int{4, 5, 3, 4})
	chk.Ints(tst, "b_el[7]", b_el[7], []int{5, 6, 3, 4})
	chk.Ints(tst, "b_en[0]", b_en[0], []int{0, 1, 2, 6, 7, 8, 12, 13, 14})
	chk.Ints(tst, "b_en[1]", b_en[1], []int{1, 2, 3, 7, 8, 9, 13, 14, 15})
	chk.Ints(tst, "b_en[2]", b_en[2], []int{2, 3, 4, 8, 9, 10, 14, 15, 16})
	chk.Ints(tst, "b_en[3]", b_en[3], []int{3, 4, 5, 9, 10, 11, 15, 16, 17})
	chk.Ints(tst, "b_en[4]", b_en[4], []int{6, 7, 8, 12, 13, 14, 18, 19, 20})
	chk.Ints(tst, "b_en[5]", b_en[5], []int{7, 8, 9, 13, 14, 15, 19, 20, 21})
	chk.Ints(tst, "b_en[6]", b_en[6], []int{8, 9, 10, 14, 15, 16, 20, 21, 22})
	chk.Ints(tst, "b_en[7]", b_en[7], []int{9, 10, 11, 15, 16, 17, 21, 22, 23})

	c := a.KrefineN(4, false)

	a_vt := tag_verts(a)
	a_ct := map[string]int{
		"0_0": -1,
		"0_1": -2,
	}
	b_vt := tag_verts(b)
	c_vt := tag_verts(c)

	WriteMshD("/tmp/gosl", "m_nurbs08a", []*Nurbs{a}, a_vt, a_ct)
	WriteMshD("/tmp/gosl", "m_nurbs08b", []*Nurbs{b}, b_vt, nil)
	WriteMshD("/tmp/gosl", "m_nurbs08c", []*Nurbs{c}, c_vt, nil)

	B := ReadMsh("/tmp/gosl/m_nurbs08a")

	if a.gnd != B[0].gnd {
		chk.Panic("Read: gnd is wrong")
	}
	chk.Ints(tst, "Read: p", a.p, B[0].p)
	chk.Ints(tst, "Read: n", a.n, B[0].n)
	chk.Deep4(tst, "Read: Q", 1.0e-17, a.Q, B[0].Q)
	chk.IntMat(tst, "Read: l2i", a.l2i, B[0].l2i)

	if T_NURBS_SAVE {
		do_plot_nurbs_refined(a, c)
		plt.SaveD("/tmp/gosl", "t_nurbs08.eps")
		do_plot_nurbs(B[0])
		plt.SaveD("/tmp/gosl", "t_nurbs08_read.eps")
	}
}