Exemple #1
0
// CheckDerivT checks derivatives w.r.t to t for fixed coordinates x
func CheckDerivT(tst *testing.T, o Func, t0, tf float64, xcte []float64, np int, tskip []float64, sktol, dtol, dtol2 float64, ver bool) {
	t := utl.LinSpace(t0, tf, np)
	for i := 0; i < np; i++ {
		g := o.G(t[i], xcte)
		h := o.H(t[i], xcte)
		skip := false
		for _, val := range tskip {
			if math.Abs(val-t[i]) < sktol {
				skip = true
				break
			}
		}
		if skip {
			continue
		}
		dnum := num.DerivCen(func(t float64, args ...interface{}) (res float64) {
			return o.F(t, xcte)
		}, t[i])
		chk.AnaNum(tst, io.Sf("G(%10f)", t[i]), dtol, g, dnum, ver)
		dnum2 := num.DerivCen(func(t float64, args ...interface{}) (res float64) {
			return o.G(t, xcte)
		}, t[i])
		chk.AnaNum(tst, io.Sf("H(%10f)", t[i]), dtol2, h, dnum2, ver)
	}
}
Exemple #2
0
// CheckDerivs compares analytical with numerical derivatives
func (o *Nurbs) CheckDerivs(tst *testing.T, nn int, tol float64, ver bool) {
	dana := make([]float64, 2)
	dnum := make([]float64, 2)
	for _, u := range utl.LinSpace(o.b[0].tmin, o.b[0].tmax, nn) {
		for _, v := range utl.LinSpace(o.b[1].tmin, o.b[1].tmax, nn) {
			uu := []float64{u, v}
			o.CalcBasisAndDerivs(uu)
			for i := 0; i < o.n[0]; i++ {
				for j := 0; j < o.n[1]; j++ {
					l := i + j*o.n[0]
					o.GetDerivL(dana, l)
					o.NumericalDeriv(dnum, uu, l)
					chk.AnaNum(tst, io.Sf("dR[%d][%d][0](%g,%g)", i, j, uu[0], uu[1]), tol, dana[0], dnum[0], ver)
					chk.AnaNum(tst, io.Sf("dR[%d][%d][1](%g,%g)", i, j, uu[0], uu[1]), tol, dana[1], dnum[1], ver)
				}
			}
		}
	}
}
func Test_hyperelast02(tst *testing.T) {

	//verbose()
	chk.PrintTitle("hyperelast02 (linear)")

	E, ν := 1500.0, 0.25
	K := Calc_K_from_Enu(E, ν)
	G := Calc_G_from_Enu(E, ν)
	io.Pforan("K = %v\n", K)
	io.Pforan("G = %v\n", G)

	var m HyperElast1
	m.Init(2, false, []*fun.Prm{
		&fun.Prm{N: "K0", V: K},
		&fun.Prm{N: "G0", V: G},
		&fun.Prm{N: "le", V: 1},
	})
	io.Pforan("m = %+v\n", m)

	ε := []float64{-0.001, -0.002, -0.003}
	σ := make([]float64, 3)
	m.L_update(σ, ε)
	io.Pfblue2("ε = %v\n", ε)
	io.Pfcyan("σ = %v\n", σ)

	D := la.MatAlloc(3, 3)
	m.L_CalcD(D, ε)
	la.PrintMat("D", D, "%14.6f", false)

	tol := 1e-11
	verb := io.Verbose
	var tmp float64
	for i := 0; i < 3; i++ {
		for j := 0; j < 3; j++ {
			dnum := num.DerivCen(func(x float64, args ...interface{}) (res float64) {
				tmp, ε[j] = ε[j], x
				m.L_update(σ, ε)
				res = σ[i]
				ε[j] = tmp
				return
			}, ε[j])
			chk.AnaNum(tst, io.Sf("D%d%d", i, j), tol, D[i][j], dnum, verb)
		}
	}
}
Exemple #4
0
// CheckDerivX checks derivatives w.r.t to x for fixed t
func CheckDerivX(tst *testing.T, o Func, tcte float64, xmin, xmax []float64, np int, xskip [][]float64, sktol, dtol float64, ver bool) {
	ndim := len(xmin)
	dx := make([]float64, ndim)
	for i := 0; i < ndim; i++ {
		dx[i] = (xmax[i] - xmin[i]) / float64(np-1)
	}
	x := make([]float64, ndim)
	g := make([]float64, ndim)
	nz := 1
	if ndim == 3 {
		nz = np
	}
	xtmp := make([]float64, ndim)
	for k := 0; k < nz; k++ {
		if ndim == 3 {
			x[2] = xmin[2] + float64(k)*dx[2]
		}
		for j := 0; j < np; j++ {
			x[1] = xmin[1] + float64(j)*dx[1]
			for i := 0; i < np; i++ {
				x[0] = xmin[0] + float64(i)*dx[0]
				o.Grad(g, tcte, x)
				for l := 0; l < ndim; l++ {
					skip := false
					for _, val := range xskip {
						if math.Abs(val[l]-x[l]) < sktol {
							skip = true
							break
						}
					}
					if skip {
						continue
					}
					dnum := num.DerivCen(func(s float64, args ...interface{}) (res float64) {
						copy(xtmp, x)
						xtmp[l] = s
						return o.F(tcte, xtmp)
					}, x[l])
					chk.AnaNum(tst, io.Sf("dFdX(t,%10v)[%d]", x, l), dtol, g[l], dnum, ver)
				}
			}
		}
	}
}
func Test_hyperelast03(tst *testing.T) {

	//verbose()
	chk.PrintTitle("hyperelast03 (nonlinear)")

	var m HyperElast1
	m.Init(2, false, []*fun.Prm{
		&fun.Prm{N: "kap", V: 0.05},
		&fun.Prm{N: "kapb", V: 20.0},
		&fun.Prm{N: "G0", V: 1500},
		&fun.Prm{N: "pr", V: 2.2},
		&fun.Prm{N: "pt", V: 11.0},
	})
	io.Pforan("m = %+v\n", m)

	ε := []float64{-0.001, -0.002, -0.003}
	σ := make([]float64, 3)
	m.L_update(σ, ε)
	io.Pfblue2("ε = %v\n", ε)
	io.Pfcyan("σ = %v\n", σ)

	D := la.MatAlloc(3, 3)
	m.L_CalcD(D, ε)
	la.PrintMat("D", D, "%14.6f", false)

	tol := 1e-7
	verb := io.Verbose
	var tmp float64
	for i := 0; i < 3; i++ {
		for j := 0; j < 3; j++ {
			dnum := num.DerivCen(func(x float64, args ...interface{}) (res float64) {
				tmp, ε[j] = ε[j], x
				m.L_update(σ, ε)
				res = σ[i]
				ε[j] = tmp
				return
			}, ε[j])
			chk.AnaNum(tst, io.Sf("D%d%d", i, j), tol, D[i][j], dnum, verb)
		}
	}
}
Exemple #6
0
// check performs the checking of Kb using numerical derivatives
func (o *testKb) check(label string, d *Domain, e Elem, Imap, Jmap []int, Kana [][]float64, restore func()) {
	var imap, jmap []int
	if o.ni < 0 {
		imap = Imap
	} else {
		if o.ni <= len(Imap) {
			imap = Imap[:o.ni]
		}
	}
	if o.nj < 0 {
		jmap = Jmap
	} else {
		if o.nj <= len(Jmap) {
			jmap = Jmap[:o.nj]
		}
	}
	step := 1e-6
	//derivfcn := num.DerivForward
	//derivfcn := num.DerivBackward
	derivfcn := num.DerivCentral
	var tmp float64
	for i, I := range imap {
		for j, J := range jmap {
			dnum, _ := derivfcn(func(x float64, args ...interface{}) (res float64) {
				tmp, d.Sol.Y[J] = d.Sol.Y[J], x
				for k := 0; k < d.Ny; k++ {
					o.Fbtmp[k] = 0
					d.Sol.ΔY[k] = d.Sol.Y[k] - o.Yold[k]
				}
				restore()
				e.Update(d.Sol)
				e.AddToRhs(o.Fbtmp, d.Sol)
				res = -o.Fbtmp[I]
				d.Sol.Y[J] = tmp
				return res
			}, d.Sol.Y[J], step)
			chk.AnaNum(o.tst, io.Sf(label+"%3d%3d", i, j), o.tol, Kana[i][j], dnum, o.verb)
		}
	}
}
Exemple #7
0
// testing_compare_results_u compares results with u-formulation
func TestingCompareResultsU(tst *testing.T, simfname, cmpfname string, tolK, tolu, tols float64, skipK, verbose bool) {

	// only root can run this test
	if !Global.Root {
		return
	}

	// read summary
	sum := ReadSum(Global.Dirout, Global.Fnkey)
	if sum == nil {
		tst.Error("cannot read summary file for simulation=%q\n", simfname)
		return
	}

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

	// read file
	buf, err := io.ReadFile(cmpfname)
	if err != nil {
		tst.Errorf("TestingCompareResultsU: ReadFile failed\n")
		return
	}

	// unmarshal json
	var cmp_set T_results_set
	err = json.Unmarshal(buf, &cmp_set)
	if err != nil {
		tst.Errorf("TestingCompareResultsU: Unmarshal failed\n")
		return
	}

	// run comparisons
	dmult := 1.0
	for idx, cmp := range cmp_set {

		// displacements multiplier
		if idx == 0 && math.Abs(cmp.DispMult) > 1e-10 {
			dmult = cmp.DispMult
		}

		// time index
		tidx := idx + 1
		if verbose {
			io.PfYel("\n\ntidx = %d . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .\n", tidx)
		}

		// load gofem results
		if !d.In(sum, tidx, true) {
			tst.Errorf("TestingCompareResultsU: reading of results failed\n")
			return
		}
		if verbose {
			io.Pfyel("time = %v\n", d.Sol.T)
		}

		// check K matrices
		if !skipK {
			if verbose {
				io.Pfgreen(". . . checking K matrices . . .\n")
			}
			for eid, Ksg := range cmp.Kmats {
				if e, ok := d.Elems[eid].(*ElemU); ok {
					if !e.AddToKb(d.Kb, d.Sol, true) {
						tst.Errorf("TestingCompareResultsU: AddToKb failed\n")
						return
					}
					chk.Matrix(tst, io.Sf("K%d", eid), tolK, e.K, Ksg)
				}
			}
		}

		// check displacements
		if verbose {
			io.Pfgreen(". . . checking displacements . . .\n")
		}
		for nid, usg := range cmp.Disp {
			ix := d.Vid2node[nid].Dofs[0].Eq
			iy := d.Vid2node[nid].Dofs[1].Eq
			chk.AnaNum(tst, "ux", tolu, d.Sol.Y[ix], usg[0]*dmult, verbose)
			chk.AnaNum(tst, "uy", tolu, d.Sol.Y[iy], usg[1]*dmult, verbose)
			if len(usg) == 3 {
				iz := d.Vid2node[nid].Dofs[2].Eq
				chk.AnaNum(tst, "uz", tolu, d.Sol.Y[iz], usg[2]*dmult, verbose)
			}
		}

		// check stresses
		if true {
			if verbose {
				io.Pfgreen(". . . checking stresses . . .\n")
			}
			for eid, sig := range cmp.Sigmas {
				if verbose {
					io.Pforan("eid = %d\n", eid)
				}
				if e, ok := d.Cid2elem[eid].(*ElemU); ok {
					for ip, val := range sig {
						if verbose {
							io.Pfgrey2("ip = %d\n", ip)
						}
						σ := e.States[ip].Sig
						if len(val) == 6 {
							chk.AnaNum(tst, "sx ", tols, σ[0], val[0], verbose)
							chk.AnaNum(tst, "sy ", tols, σ[1], val[1], verbose)
						} else {
							chk.AnaNum(tst, "sx ", tols, σ[0], val[0], verbose)
							chk.AnaNum(tst, "sy ", tols, σ[1], val[1], verbose)
							chk.AnaNum(tst, "sxy", tols, σ[3]/SQ2, val[2], verbose)
							if len(val) > 3 { // sx, sy, sxy, sz
								chk.AnaNum(tst, "sz ", tols, σ[2], val[3], verbose)
							}
						}
					}
				}
			}
		}
	}
}
Exemple #8
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})
}
func Test_ops03(tst *testing.T) {

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

	nonsymTol := 1e-15

	dtol := 1e-9
	dver := chk.Verbose

	nd := test_nd
	for idxA := 0; idxA < len(test_nd)-3; idxA++ {
		//for idxA := 0; idxA < 1; idxA++ {

		// tensor and eigenvalues
		A := test_AA[idxA]
		a := M_Alloc2(nd[idxA])
		Ten2Man(a, A)
		io.PfYel("\n\ntst # %d ###################################################################################\n", idxA)
		io.Pfblue2("a = %v\n", a)

		// inverse
		Ai := Alloc2()
		ai := M_Alloc2(nd[idxA])
		detA, err := Inv(Ai, A)
		if err != nil {
			chk.Panic("%v", err)
		}
		deta_ := M_Det(a)
		deta, err := M_Inv(ai, a, MINDET)
		if err != nil {
			chk.Panic("%v", err)
		}
		Ai_ := Alloc2()
		Man2Ten(Ai_, ai)
		aia := M_Alloc2(nd[idxA])
		err = M_Dot(aia, ai, a, nonsymTol)
		if err != nil {
			chk.Panic("%v", err)
		}
		chk.Scalar(tst, "detA", 1e-14, detA, deta)
		chk.Scalar(tst, "deta", 1e-14, deta, deta_)
		chk.Matrix(tst, "Ai", 1e-14, Ai, Ai_)
		chk.Vector(tst, "ai*a", 1e-15, aia, Im[:2*nd[idxA]])
		io.Pforan("ai*a = %v\n", aia)

		// derivative of inverse
		dtol_tmp := dtol
		if idxA == 5 {
			dtol = 1e-8
		}
		var tmp float64
		ai_tmp := M_Alloc2(nd[idxA])
		daida := M_Alloc4(nd[idxA])
		M_InvDeriv(daida, ai)
		io.Pforan("ai = %v\n", ai)
		for i := 0; i < len(a); i++ {
			for j := 0; j < len(a); j++ {
				//dnum, _ := num.DerivForward(func(x float64, args ...interface{}) (res float64) {
				dnum, _ := num.DerivCentral(func(x float64, args ...interface{}) (res float64) {
					tmp, a[j] = a[j], x
					_, err := M_Inv(ai_tmp, a, MINDET)
					a[j] = tmp
					if err != nil {
						chk.Panic("daida failed:\n%v", err)
					}
					return ai_tmp[i]
				}, a[j], 1e-6)
				chk.AnaNum(tst, io.Sf("dai/da[%d][%d]", i, j), dtol, daida[i][j], dnum, dver)
			}
		}
		dtol = dtol_tmp
	}
}
func Test_ops01(tst *testing.T) {

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

	// basic derivatives
	dver := chk.Verbose
	dtol := 1e-5

	// invariants derivatives
	dveri := false
	dtoli1 := []float64{1e-6, 1e-6, 1e-6, 1e-6, 1e-6, 1e-6, 1e-6, 1e-6, 1e-6, 1e-6}
	dtoli2 := []float64{1e-6, 1e-5, 1e-6, 1e-4, 1e-5, 1e-6, 1e-6, 1e-6, 1e-6, 1e-6}
	dtoli3 := []float64{1e-6, 1e-3, 1e-6, 1e-3, 1e-3, 1e-6, 1e-6, 1e-6, 1e-5, 1e-6}

	// lode derivatives
	dverw := chk.Verbose
	dtolw := 1e-8

	nd := test_nd
	for m := 0; m < len(test_nd)-3; m++ {
		//for m := 0; m < 3; m++ {
		A := test_AA[m]
		a := M_Alloc2(nd[m])
		Ten2Man(a, A)
		trA := Tr(A)
		tra := M_Tr(a)
		detA := Det(A)
		deta := M_Det(a)
		devA := Dev(A)
		deva := M_Dev(a)
		devA_ := Alloc2()
		a2 := M_Alloc2(nd[m])
		A2 := Alloc2()
		A2_ := Alloc2()
		trDevA := Tr(devA)
		deva__ := M_Alloc2(nd[m])
		devA__ := Alloc2()
		s2 := M_Alloc2(nd[m])
		M_Sq(a2, a)
		M_Sq(s2, deva)
		Man2Ten(A2, a2)
		Man2Ten(devA_, deva)
		for i := 0; i < 3; i++ {
			for j := 0; j < 3; j++ {
				for k := 0; k < 3; k++ {
					A2_[i][j] += A[i][k] * A[k][j]
				}
			}
		}
		for i := 0; i < len(a); i++ {
			for j := 0; j < len(a); j++ {
				deva__[i] += Psd[i][j] * a[j]
			}
		}
		for i := 0; i < 3; i++ {
			for j := 0; j < 3; j++ {
				for k := 0; k < 3; k++ {
					for l := 0; l < 3; l++ {
						devA__[i][j] += M2TT(Psd, i, j, k, l) * A[k][l]
					}
				}
			}
		}
		// check basic
		if math.Abs(trA-tra) > 1e-17 {
			chk.Panic("tra failed. diff = %g", trA-tra)
		}
		if math.Abs(detA-deta) > 1e-14 {
			chk.Panic("detA failed. diff = %g", detA-deta)
		}
		if math.Abs(trDevA) > 1e-13 {
			chk.Panic("trDevA failed. error = %g", trDevA)
		}
		chk.Matrix(tst, "devA", 1e-13, devA, devA_)
		chk.Matrix(tst, "devA", 1e-13, devA, devA__)
		chk.Vector(tst, "devA", 1e-13, deva, deva__)
		chk.Matrix(tst, "A²", 1e-11, A2, A2_)
		// check tr(s2)
		io.Pfblue2("tr(s²) = %v\n", M_Tr(s2))
		if M_Tr(s2) < 1 {
			chk.Panic("Tr(s2) failed")
		}
		// check derivatives
		da2da := M_Alloc4(nd[m])
		a2tmp := M_Alloc2(nd[m]) // a2tmp == a²
		M_SqDeriv(da2da, a)
		var tmp float64
		for i := 0; i < len(a); i++ {
			for j := 0; j < len(a); j++ {
				dnum, _ := num.DerivCentral(func(x float64, args ...interface{}) (res float64) {
					tmp, a[j] = a[j], x
					M_Sq(a2tmp, a)
					a[j] = tmp
					return a2tmp[i]
				}, a[j], 1e-6)
				chk.AnaNum(tst, io.Sf("da²/da[%d][%d]", i, j), dtol, da2da[i][j], dnum, dver)
			}
		}
		// characteristic invariants
		I1, I2, I3 := M_CharInvs(a)
		I2a := 0.5 * (tra*tra - M_Tr(a2))
		I1_, I2_, I3_, dI1da, dI2da, dI3da := M_CharInvsAndDerivs(a)
		if math.Abs(I1-tra) > 1e-17 {
			chk.Panic("I1 failed (a). error = %v", I1-tra)
		}
		if math.Abs(I2-I2a) > 1e-12 {
			chk.Panic("I2 failed (a). error = %v (I2=%v, I2_=%v)", I2-I2a, I2, I2a)
		}
		if math.Abs(I3-deta) > 1e-17 {
			chk.Panic("I3 failed (a). error = %v", I3-deta)
		}
		if math.Abs(I1-I1_) > 1e-17 {
			chk.Panic("I1 failed (b). error = %v", I1-I1_)
		}
		if math.Abs(I2-I2_) > 1e-17 {
			chk.Panic("I2 failed (b). error = %v", I2-I2_)
		}
		if math.Abs(I3-I3_) > 1e-17 {
			chk.Panic("I3 failed (b). error = %v", I3-I3_)
		}
		// dI1da
		for j := 0; j < len(a); j++ {
			dnum, _ := num.DerivCentral(func(x float64, args ...interface{}) (res float64) {
				tmp, a[j] = a[j], x
				i1, _, _ := M_CharInvs(a)
				a[j] = tmp
				return i1
			}, a[j], 1e-6)
			chk.AnaNum(tst, io.Sf("dI1/da[%d]", j), dtoli1[m], dI1da[j], dnum, dveri)
		}
		// dI2da
		for j := 0; j < len(a); j++ {
			dnum, _ := num.DerivCentral(func(x float64, args ...interface{}) (res float64) {
				tmp, a[j] = a[j], x
				_, i2, _ := M_CharInvs(a)
				a[j] = tmp
				return i2
			}, a[j], 1e-6)
			chk.AnaNum(tst, io.Sf("dI2/da[%d]", j), dtoli2[m], dI2da[j], dnum, dveri)
		}
		// dI3da
		for j := 0; j < len(a); j++ {
			dnum, _ := num.DerivCentral(func(x float64, args ...interface{}) (res float64) {
				tmp, a[j] = a[j], x
				_, _, i3 := M_CharInvs(a)
				a[j] = tmp
				return i3
			}, a[j], 1e-6)
			chk.AnaNum(tst, io.Sf("dI3/da[%d]", j), dtoli3[m], dI3da[j], dnum, dveri)
		}
		// dDet(a)/da
		DdetaDa := make([]float64, len(a))
		M_DetDeriv(DdetaDa, a)
		for j := 0; j < len(a); j++ {
			chk.AnaNum(tst, io.Sf("dDet(a)/da[%d]", j), dtoli3[m], dI3da[j], DdetaDa[j], dveri)
		}
		// lode angle
		if true {
			s := M_Alloc2(nd[m])
			dwda := M_Alloc2(nd[m])
			dwda_ := M_Alloc2(nd[m])
			d2wdada := M_Alloc4(nd[m])
			p, q, w := M_pqws(s, a)
			M_LodeDeriv1(dwda, a, s, p, q, w)
			M_LodeDeriv2(d2wdada, dwda_, a, s, p, q, w)
			chk.Vector(tst, "s", 1e-13, deva, s)
			chk.Vector(tst, "dwda", 1e-13, dwda, dwda_)
			// dwda
			for j := 0; j < len(a); j++ {
				dnum, _ := num.DerivCentral(func(x float64, args ...interface{}) (res float64) {
					tmp, a[j] = a[j], x
					res = M_w(a)
					a[j] = tmp
					return res
				}, a[j], 1e-6)
				chk.AnaNum(tst, io.Sf("dw/da[%d]", j), dtolw, dwda[j], dnum, dverw)
			}
			// d2wdada
			s_tmp := M_Alloc2(nd[m])
			dwda_tmp := M_Alloc2(nd[m])
			for i := 0; i < len(a); i++ {
				for j := 0; j < len(a); j++ {
					dnum, _ := num.DerivCentral(func(x float64, args ...interface{}) (res float64) {
						tmp, a[j] = a[j], x
						p_tmp, q_tmp, w_tmp := M_pqws(s_tmp, a)
						M_LodeDeriv1(dwda_tmp, a, s_tmp, p_tmp, q_tmp, w_tmp)
						a[j] = tmp
						return dwda_tmp[i]
					}, a[j], 1e-6)
					chk.AnaNum(tst, io.Sf("d2w/dada[%d][%d]", i, j), dtolw, d2wdada[i][j], dnum, dverw)
				}
			}
		}
	}
}
Exemple #11
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
}
Exemple #12
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
	}
}
Exemple #13
0
func Test_noncteM01(tst *testing.T) {

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

	prms := []string{"φ", "Mfix"}
	vals := []float64{32, 0}
	var o NcteM
	o.Init(prms, vals)

	// check
	if math.Abs(o.M(1)-o.Mcs) > 1e-17 {
		chk.Panic("M(+1) failed. err = %v", o.M(1)-o.Mcs)
	}
	if o.Mfix {
		if math.Abs(o.M(-1)-o.Mcs) > 1e-17 {
			chk.Panic("M(-1) failed. err = %v", o.M(-1)-o.Mcs)
		}
	} else {
		Mext := 6.0 * math.Sin(32*math.Pi/180) / (3 + math.Sin(32*math.Pi/180))
		if math.Abs(o.M(-1)-Mext) > 1e-15 {
			chk.Panic("M(-1) failed. err = %v", o.M(-1)-Mext)
		}
	}

	ver, tol := chk.Verbose, 1e-9
	var tmp float64
	for _, w := range utl.LinSpace(-1, 1, 11) {
		dMdw := o.DMdw(w)
		d2Mdw2 := o.D2Mdw2(w)
		dnum, _ := num.DerivCentral(func(x float64, args ...interface{}) (res float64) {
			tmp, w = w, x
			res, w = o.M(w), tmp
			return
		}, w, 1e-6)
		chk.AnaNum(tst, "dM/dw  ", tol, dMdw, dnum, ver)
		dnum, _ = num.DerivCentral(func(x float64, args ...interface{}) (res float64) {
			tmp, w = w, x
			res, w = o.DMdw(w), tmp
			return
		}, w, 1e-6)
		chk.AnaNum(tst, "d²M/dw²", tol, d2Mdw2, dnum, ver)
	}

	ver, tol = chk.Verbose, 1e-9
	nd := test_nd
	for m := 0; m < len(test_nd)-3; m++ {
		//for m := 0; m < 3; m++ {
		A := test_AA[m]
		σ := M_Alloc2(nd[m])
		Ten2Man(σ, A)
		s := M_Alloc2(nd[m])
		dMdσ := M_Alloc2(nd[m])
		d2Mdσdσ := M_Alloc4(nd[m])
		p, q, w := M_pqws(s, σ)
		o.Deriv2(d2Mdσdσ, dMdσ, σ, s, p, q, w)
		io.Pforan("σ = %v\n", σ)
		io.Pforan("tr(dMdσ) = %v\n", M_Tr(dMdσ))
		if math.Abs(M_Tr(dMdσ)) > 1e-16 {
			chk.Panic("tr(dMdσ)=%v failed", M_Tr(dMdσ))
		}
		I_dc_d2Mdσdσ := M_Alloc2(nd[m]) // I:d²M/dσdσ
		for j := 0; j < len(σ); j++ {
			for k := 0; k < len(σ); k++ {
				I_dc_d2Mdσdσ[j] += Im[k] * d2Mdσdσ[k][j]
			}
		}
		//io.Pfblue2("I_dc_d2Mdσdσ = %v\n", I_dc_d2Mdσdσ)
		chk.Vector(tst, "I_dc_d2Mdσdσ", 1e-15, I_dc_d2Mdσdσ, nil)
		// dMdσ
		for j := 0; j < len(σ); j++ {
			dnum, _ := num.DerivCentral(func(x float64, args ...interface{}) (res float64) {
				tmp, σ[j] = σ[j], x
				w := M_w(σ)
				σ[j] = tmp
				return o.M(w)
			}, σ[j], 1e-6)
			chk.AnaNum(tst, io.Sf("dM/dσ[%d]", j), tol, dMdσ[j], dnum, ver)
		}
		// d²Mdσdσ
		s_tmp := M_Alloc2(nd[m])
		dMdσ_tmp := M_Alloc2(nd[m])
		for i := 0; i < len(σ); i++ {
			for j := 0; j < len(σ); j++ {
				dnum, _ := num.DerivCentral(func(x float64, args ...interface{}) (res float64) {
					tmp, σ[j] = σ[j], x
					p_tmp, q_tmp, w_tmp := M_pqws(s_tmp, σ)
					o.Deriv1(dMdσ_tmp, σ, s_tmp, p_tmp, q_tmp, w_tmp)
					σ[j] = tmp
					return dMdσ_tmp[i]
				}, σ[j], 1e-6)
				chk.AnaNum(tst, io.Sf("d²M/dσdσ[%d][%d]", i, j), tol, d2Mdσdσ[i][j], dnum, ver)
			}
		}
	}
}
Exemple #14
0
// Check checks derivatives
func Check(tst *testing.T, mdl Model, pc0, sl0, pcf float64, npts int, tolCc, tolD1a, tolD1b, tolD2a, tolD2b float64, verbose bool, pcSkip []float64, tolSkip float64, doplot bool) {

	// nonrate model
	nr_mdl, is_nonrate := mdl.(Nonrate)
	io.Pforan("is_nonrate = %v\n", is_nonrate)

	// for all pc stations
	Pc := utl.LinSpace(pc0, pcf, npts)
	Sl := make([]float64, npts)
	Sl[0] = sl0
	var err error
	for i := 1; i < npts; i++ {

		// update and plot
		Sl[i], err = Update(mdl, Pc[i-1], Sl[i-1], Pc[i]-Pc[i-1])
		if err != nil {
			tst.Errorf("Update failed: %v\n", err)
			return
		}
		if doplot {
			plt.PlotOne(Pc[i], Sl[i], "'ko', clip_on=0")
		}

		// skip point on checking of derivatives
		if doskip(Pc[i], pcSkip, tolSkip) {
			continue
		}

		// wetting flag
		wet := Pc[i]-Pc[i-1] < 0

		// check Cc = dsl/dpc
		io.Pforan("\npc=%g, sl=%g, wetting=%v\n", Pc[i], Sl[i], wet)
		if is_nonrate {

			// analytical Cc
			Cc_ana, err := mdl.Cc(Pc[i], Sl[i], wet)
			if err != nil {
				tst.Errorf("Cc failed: %v\n", err)
				return
			}

			// numerical Cc
			Cc_num, _ := num.DerivCentral(func(x float64, args ...interface{}) float64 {
				return nr_mdl.Sl(x)
			}, Pc[i], 1e-3)
			chk.AnaNum(tst, "Cc = ∂sl/∂pc    ", tolCc, Cc_ana, Cc_num, verbose)
		}

		// compute all derivatives
		L, Lx, J, Jx, Jy, err := mdl.Derivs(Pc[i], Sl[i], wet)
		if err != nil {
			tst.Errorf("Derivs failed: %v\n", err)
			return
		}
		L_ana_A := L
		L_ana_B, err := mdl.L(Pc[i], Sl[i], wet)
		if err != nil {
			tst.Errorf("L failed: %v\n", err)
			return
		}
		Lx_ana := Lx
		Jx_ana := Jx
		Jy_ana := Jy
		J_ana_A := J
		J_ana_B, err := mdl.J(Pc[i], Sl[i], wet)
		if err != nil {
			tst.Errorf("J failed: %v\n", err)
			return
		}

		// numerical L = ∂Cc/∂pc
		L_num, _ := num.DerivCentral(func(x float64, args ...interface{}) float64 {
			Cctmp, _ := mdl.Cc(x, Sl[i], wet)
			return Cctmp
		}, Pc[i], 1e-3)
		chk.AnaNum(tst, "L  = ∂Cc/∂pc    ", tolD1a, L_ana_A, L_num, verbose)

		// numerical Lx := ∂²Cc/∂pc²
		Lx_num, _ := num.DerivCentral(func(x float64, args ...interface{}) float64 {
			Ltmp, _, _, _, _, _ := mdl.Derivs(x, Sl[i], wet)
			return Ltmp
		}, Pc[i], 1e-3)
		chk.AnaNum(tst, "Lx = ∂²Cc/∂pc²  ", tolD2a, Lx_ana, Lx_num, verbose)

		// numerical J := ∂Cc/∂sl (version A)
		J_num, _ := num.DerivCentral(func(x float64, args ...interface{}) float64 {
			Ccval, _ := mdl.Cc(Pc[i], x, wet)
			return Ccval
		}, Sl[i], 1e-3)
		chk.AnaNum(tst, "J  = ∂Cc/∂sl    ", tolD1b, J_ana_A, J_num, verbose)

		// numerical Jx := ∂²Cc/(∂pc ∂sl)
		Jx_num, _ := num.DerivCentral(func(x float64, args ...interface{}) float64 {
			Ltmp, _, _, _, _, _ := mdl.Derivs(Pc[i], x, wet)
			return Ltmp
		}, Sl[i], 1e-3)
		chk.AnaNum(tst, "Jx = ∂²Cc/∂pc∂sl", tolD2b, Jx_ana, Jx_num, verbose)

		// numerical Jy := ∂²Cc/∂sl²
		Jy_num, _ := num.DerivCentral(func(x float64, args ...interface{}) float64 {
			Jtmp, _ := mdl.J(Pc[i], x, wet)
			return Jtmp
		}, Sl[i], 1e-3)
		chk.AnaNum(tst, "Jy = ∂²Cc/∂sl²  ", tolD2b, Jy_ana, Jy_num, verbose)

		// check A and B derivatives
		chk.Scalar(tst, "L_A == L_B", 1e-17, L_ana_A, L_ana_B)
		chk.Scalar(tst, "J_A == J_B", 1e-17, J_ana_A, J_ana_B)
	}
}
Exemple #15
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)
		}
	}
}
Exemple #16
0
// testing_compare_results_u compares results with u-formulation
func TestingCompareResultsU(tst *testing.T, simfilepath, cmpfname, alias string, tolK, tolu, tols float64, skipK, verbose bool) {

	// FEM structure
	fem := NewFEM(simfilepath, alias, false, false, true, false, verbose, 0)

	// set stage
	err := fem.SetStage(0)
	if err != nil {
		chk.Panic("cannot set stage:\n%v", err)
	}

	// zero solution
	err = fem.ZeroStage(0, true)
	if err != nil {
		chk.Panic("cannot zero stage data:\n%v", err)
	}

	// read file with comparison results
	buf, err := io.ReadFile(cmpfname)
	if err != nil {
		tst.Errorf("TestingCompareResultsU: ReadFile failed\n")
		return
	}

	// unmarshal json
	var cmp_set T_results_set
	err = json.Unmarshal(buf, &cmp_set)
	if err != nil {
		tst.Errorf("TestingCompareResultsU: Unmarshal failed\n")
		return
	}

	// run comparisons
	dom := fem.Domains[0]
	dmult := 1.0
	for idx, cmp := range cmp_set {

		// displacements multiplier
		if idx == 0 && math.Abs(cmp.DispMult) > 1e-10 {
			dmult = cmp.DispMult
		}

		// time index
		tidx := idx + 1
		if verbose {
			io.PfYel("\n\ntidx = %d . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .\n", tidx)
		}

		// load gofem results
		err = dom.Read(fem.Summary, tidx, 0, true)
		if err != nil {
			chk.Panic("cannot read 'gofem' results:\n%v", err)
		}
		if verbose {
			io.Pfyel("time = %v\n", dom.Sol.T)
		}

		// check K matrices
		if !skipK {
			if verbose {
				io.Pfgreen(". . . checking K matrices . . .\n")
			}
			for eid, Ksg := range cmp.Kmats {
				if e, ok := dom.Elems[eid].(*ElemU); ok {
					err = e.AddToKb(dom.Kb, dom.Sol, true)
					if err != nil {
						chk.Panic("TestingCompareResultsU: AddToKb failed\n")
					}
					chk.Matrix(tst, io.Sf("K%d", eid), tolK, e.K, Ksg)
				}
				if e, ok := dom.Elems[eid].(*Rod); ok {
					err = e.AddToKb(dom.Kb, dom.Sol, true)
					if err != nil {
						chk.Panic("TestingCompareResultsU: AddToKb failed\n")
					}
					chk.Matrix(tst, io.Sf("K%d", eid), tolK, e.K, Ksg)
				}
				if e, ok := dom.Elems[eid].(*ElastRod); ok {
					err = e.AddToKb(dom.Kb, dom.Sol, true)
					if err != nil {
						chk.Panic("TestingCompareResultsU: AddToKb failed\n")
					}
					chk.Matrix(tst, io.Sf("K%d", eid), tolK, e.K, Ksg)
				}
			}
		}

		// check displacements
		if verbose {
			io.Pfgreen(". . . checking displacements . . .\n")
		}
		for nid, usg := range cmp.Disp {
			ix := dom.Vid2node[nid].Dofs[0].Eq
			iy := dom.Vid2node[nid].Dofs[1].Eq
			chk.AnaNum(tst, "ux", tolu, dom.Sol.Y[ix], usg[0]*dmult, verbose)
			chk.AnaNum(tst, "uy", tolu, dom.Sol.Y[iy], usg[1]*dmult, verbose)
			if len(usg) == 3 {
				iz := dom.Vid2node[nid].Dofs[2].Eq
				chk.AnaNum(tst, "uz", tolu, dom.Sol.Y[iz], usg[2]*dmult, verbose)
			}
		}

		// check stresses
		if true {
			if verbose {
				io.Pfgreen(". . . checking stresses . . .\n")
			}
			for eid, sig := range cmp.Sigmas {
				if verbose {
					io.Pforan("eid = %d\n", eid)
				}
				if e, ok := dom.Cid2elem[eid].(*ElemU); ok {
					for ip, val := range sig {
						if verbose {
							io.Pfgrey2("ip = %d\n", ip)
						}
						σ := e.States[ip].Sig
						if len(val) == 6 {
							chk.AnaNum(tst, "sx ", tols, σ[0], val[0], verbose)
							chk.AnaNum(tst, "sy ", tols, σ[1], val[1], verbose)
						} else {
							chk.AnaNum(tst, "sx ", tols, σ[0], val[0], verbose)
							chk.AnaNum(tst, "sy ", tols, σ[1], val[1], verbose)
							chk.AnaNum(tst, "sxy", tols, σ[3]/SQ2, val[2], verbose)
							if len(val) > 3 { // sx, sy, sxy, sz
								chk.AnaNum(tst, "sz ", tols, σ[2], val[3], verbose)
							}
						}
					}
				}
				if e, ok := dom.Cid2elem[eid].(*Rod); ok {
					for ip, val := range sig {
						if verbose {
							io.Pfgrey2("ip = %d\n", ip)
						}
						σ := e.States[ip].Sig
						chk.AnaNum(tst, "sig", tols, σ, val[0], verbose)
					}
				}
				if e, ok := dom.Cid2elem[eid].(*ElastRod); ok {
					dat := e.OutIpsData()
					for ip, val := range sig {
						if verbose {
							io.Pfgrey2("ip = %d\n", ip)
						}
						res := dat[ip].Calc(dom.Sol)
						σ := res["sig"]
						chk.AnaNum(tst, "sig", tols, σ, val[0], verbose)
					}
				}
			}
		}
	}
}