Beispiel #1
0
// CheckDSdR checks dSdR derivatives of shape structures
func CheckDSdR(tst *testing.T, shape *Shape, r []float64, tol float64, verbose bool) {

	// auxiliary
	r_tmp := make([]float64, len(r))
	S_tmp := make([]float64, shape.Nverts)

	// analytical
	shape.Func(shape.S, shape.DSdR, r, true, -1)

	// numerical
	for n := 0; n < shape.Nverts; n++ {
		for i := 0; i < shape.Gndim; i++ {
			dSndRi, _ := num.DerivCentral(func(t float64, args ...interface{}) (Sn float64) {
				copy(r_tmp, r)
				r_tmp[i] = t
				shape.Func(S_tmp, nil, r_tmp, false, -1)
				Sn = S_tmp[n]
				return
			}, r[i], 1e-1)
			if verbose {
				io.Pfgrey2("  dS%ddR%d @ %5.2f = %v (num: %v)\n", n, i, r, shape.DSdR[n][i], dSndRi)
			}
			if math.Abs(shape.DSdR[n][i]-dSndRi) > tol {
				tst.Errorf("nurbs dS%ddR%d failed with err = %g\n", n, i, math.Abs(shape.DSdR[n][i]-dSndRi))
				return
			}
		}
	}
}
Beispiel #2
0
func main() {

	// define function and derivative function
	y_fcn := func(x float64) float64 { return math.Sin(x) }
	dydx_fcn := func(x float64) float64 { return math.Cos(x) }
	d2ydx2_fcn := func(x float64) float64 { return -math.Sin(x) }

	// run test for 11 points
	X := utl.LinSpace(0, 2*math.Pi, 11)
	io.Pf("          %8s %23s %23s %23s\n", "x", "analytical", "numerical", "error")
	for _, x := range X {

		// analytical derivatives
		dydx_ana := dydx_fcn(x)
		d2ydx2_ana := d2ydx2_fcn(x)

		// numerical derivative: dydx
		dydx_num, _ := num.DerivCentral(func(t float64, args ...interface{}) float64 {
			return y_fcn(t)
		}, x, 1e-3)

		// numerical derivative d2ydx2
		d2ydx2_num, _ := num.DerivCentral(func(t float64, args ...interface{}) float64 {
			return dydx_fcn(t)
		}, x, 1e-3)

		// check
		chk.PrintAnaNum(io.Sf("dy/dx   @ %.6f", x), 1e-10, dydx_ana, dydx_num, true)
		chk.PrintAnaNum(io.Sf("d²y/dx² @ %.6f", x), 1e-10, d2ydx2_ana, d2ydx2_num, true)
	}

	// generate 101 points for plotting
	X = utl.LinSpace(0, 2*math.Pi, 101)
	Y := make([]float64, len(X))
	for i, x := range X {
		Y[i] = y_fcn(x)
	}

	// plot
	plt.SetForPng(0.75, 300, 150)
	plt.Plot(X, Y, "'b.-', clip_on=0, markevery=10, label='y(x)=sin(x)'")
	plt.Gll("x", "y", "")
	plt.SaveD("/tmp/gosl", "num_deriv01.png")
}
Beispiel #3
0
func main() {

	// define function and derivative function
	y_fcn := func(x float64) float64 { return math.Sin(x) }
	dydx_fcn := func(x float64) float64 { return math.Cos(x) }
	d2ydx2_fcn := func(x float64) float64 { return -math.Sin(x) }

	// run test for 11 points
	X := utl.LinSpace(0, 2*math.Pi, 11)
	for _, x := range X {

		// analytical derivatives
		dydx_ana := dydx_fcn(x)
		d2ydx2_ana := d2ydx2_fcn(x)

		// numerical derivative: dydx
		dydx_num, _ := num.DerivCentral(func(t float64, args ...interface{}) float64 {
			return y_fcn(t)
		}, x, 1e-3)

		// numerical derivative d2ydx2
		d2ydx2_num, _ := num.DerivCentral(func(t float64, args ...interface{}) float64 {
			return dydx_fcn(t)
		}, x, 1e-3)

		// check
		chk.PrintAnaNum(io.Sf("dy/dx   @ %.6f", x), 1e-10, dydx_ana, dydx_num, true)
		chk.PrintAnaNum(io.Sf("d²y/dx² @ %.6f", x), 1e-10, d2ydx2_ana, d2ydx2_num, true)
	}

	// generate 101 points
	X = utl.LinSpace(0, 2*math.Pi, 101)
	Y := make([]float64, len(X))
	for i, x := range X {
		Y[i] = y_fcn(x)
	}

	// plot
	plt.Plot(X, Y, "'b.-'")
	plt.Gll("x", "y", "")
	plt.Show()
}
Beispiel #4
0
// CheckEigenprojsDerivs checks the derivatives of eigen projectors w.r.t defining tensor
func CheckEigenprojsDerivs(a []float64, tol float64, ver bool, zero float64) {

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

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

	// check
	var tmp float64
	has_error := false
	for k := 0; k < 3; k++ {
		for i := 0; i < ncp; i++ {
			for j := 0; j < ncp; j++ {
				dnum, _ := num.DerivCentral(func(x float64, args ...interface{}) (res float64) {
					tmp, a[j] = a[j], x
					docalc()
					a[j] = tmp
					return P[k][i]
				}, a[j], 1e-6)
				err := chk.PrintAnaNum(io.Sf("dP%d[%d]/da[%d]", k, i, j), tol, dPda[k][i][j], dnum, ver)
				if err != nil {
					has_error = true
				}
			}
		}
		if ver {
			io.Pf("\n")
		}
	}
	if has_error {
		chk.Panic(_eigenprojs_err8)
	}
	return
}
Beispiel #5
0
// CheckDSdx checks G=dSdx derivatives of shape structures
func CheckDSdx(tst *testing.T, shape *Shape, xmat [][]float64, x []float64, tol float64, verbose bool) {

	// find r corresponding to x
	r := make([]float64, 3)
	err := shape.InvMap(r, x, xmat)
	if err != nil {
		tst.Errorf("InvMap failed:\n%v", err)
		return
	}

	// analytical
	err = shape.CalcAtIp(xmat, r, true)
	if err != nil {
		tst.Errorf("CalcAtIp failed:\n%v", err)
		return
	}

	// numerical
	x_tmp := make([]float64, len(x))
	for n := 0; n < shape.Nverts; n++ {
		for i := 0; i < shape.Gndim; i++ {
			dSnDxi, _ := num.DerivCentral(func(t float64, args ...interface{}) (Sn float64) {
				copy(x_tmp, x)
				x_tmp[i] = t
				err = shape.InvMap(r, x_tmp, xmat)
				if err != nil {
					tst.Errorf("InvMap failed:\n%v", err)
					return
				}
				err = shape.CalcAtIp(xmat, r, false)
				if err != nil {
					tst.Errorf("CalcAtIp failed:\n%v", err)
					return
				}
				Sn = shape.S[n]
				return
			}, x[i], 1e-1)
			if verbose {
				io.Pfgrey2("  dS%dDx%d @ %5.2f = %v (num: %v)\n", n, i, x, shape.G[n][i], dSnDxi)
			}
			if math.Abs(shape.G[n][i]-dSnDxi) > tol {
				tst.Errorf("nurbs dS%dDx%d failed with err = %g\n", n, i, math.Abs(shape.G[n][i]-dSnDxi))
				return
			}
		}
	}
}
Beispiel #6
0
// checkDerivs checks dSdR derivatives of shape structures
func checkDerivs(tst *testing.T, shape string, r []float64, tol float64, verbose bool) {

	// information
	fcn := Functions[shape]
	ndim := GeomNdim[shape]
	nverts := NumVerts[shape]

	// allocate slices
	S := make([]float64, nverts)
	dSdR := utl.DblsAlloc(nverts, ndim)

	// auxiliary
	r_tmp := make([]float64, len(r))
	S_tmp := make([]float64, nverts)

	// analytical
	fcn(S, dSdR, r, true)

	// numerical
	for n := 0; n < nverts; n++ {
		for i := 0; i < ndim; i++ {
			dSndRi, _ := num.DerivCentral(func(t float64, args ...interface{}) (Sn float64) {
				copy(r_tmp, r)
				r_tmp[i] = t
				fcn(S_tmp, nil, r_tmp, false)
				Sn = S_tmp[n]
				return
			}, r[i], 1e-1)
			if verbose {
				io.Pfgrey2("  dS%ddR%d @ %5.2f = %v (num: %v)\n", n, i, r, dSdR[n][i], dSndRi)
			}
			if math.Abs(dSdR[n][i]-dSndRi) > tol {
				tst.Errorf("nurbs dS%ddR%d failed with err = %g\n", n, i, math.Abs(dSdR[n][i]-dSndRi))
				return
			}
		}
	}
}
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)
				}
			}
		}
	}
}
Beispiel #9
0
func Test_shape01(tst *testing.T) {

	//utl.Tsilent = false
	chk.PrintTitle("Test shape01")

	for name, shape := range factory {

		io.Pfyel("--------------------------------- %-6s---------------------------------\n", name)

		// check S
		tol := 1e-17
		errS := 0.0
		if name == "tri10" {
			tol = 1e-14
		}
		for n := 0; n < shape.Nverts; n++ {
			rst := []float64{0, 0, 0}
			for i := 0; i < shape.Gndim; i++ {
				rst[i] = shape.NatCoords[i][n]
			}
			shape.Func(shape.S, shape.dSdR, rst[0], rst[1], rst[2], false)
			io.Pforan("S = %v\n", shape.S)
			for m := 0; m < shape.Nverts; m++ {
				if n == m {
					errS += math.Abs(shape.S[m] - 1.0)
				} else {
					errS += math.Abs(shape.S[m])
				}
			}
		}
		if errS > tol {
			tst.Errorf("%s failed with err = %g\n", name, errS)
			return
		}

		// check dSdR
		tol = 1e-14
		h := 1.0e-1
		S_temp := make([]float64, shape.Nverts)
		if name == "lin5" || name == "tri15" || name == "lin4" || name == "tri10" || name == "qua12" || name == "qua16" {
			tol = 1.0e-10
		}
		for n := 0; n < shape.Nverts; n++ {
			rst := []float64{0, 0, 0}
			for i := 0; i < shape.Gndim; i++ {
				rst[i] = shape.NatCoords[i][n]
			}
			// analytical
			shape.Func(shape.S, shape.dSdR, rst[0], rst[1], rst[2], true)
			// numerical
			for i := 0; i < shape.Gndim; i++ {
				dSndRi, _ := num.DerivCentral(func(x float64, args ...interface{}) (Sn float64) {
					rst_temp := []float64{rst[0], rst[1], rst[2]}
					rst_temp[i] = x
					shape.Func(S_temp, nil, rst_temp[0], rst_temp[1], rst_temp[2], false)
					Sn = S_temp[n]
					return
				}, rst[i], h)
				io.Pfgrey2("  dS%ddR%d @ [% 4.1f % 4.1f % 4.1f] = %v (num: %v)\n", n, i, rst[0], rst[1], rst[2], shape.dSdR[n][i], dSndRi)
				tol2 := tol
				if name == "tri15" && n == 11 && i == 1 {
					tol2 = 1.0e-9
				}
				if math.Abs(shape.dSdR[n][i]-dSndRi) > tol2 {
					tst.Errorf("%s dS%ddR%d failed with err = %g\n", name, n, i, math.Abs(shape.dSdR[n][i]-dSndRi))
					return
				}
				//chk.Scalar(tst, fmt.Sprintf("dS%ddR%d", n, i), tol2, dSdR[n][i], dSndRi)
			}
		}

		// check face vertices
		tol = 1e-17
		errS = 0.0
		if name == "tri10" {
			tol = 1e-14
		}

		nfaces := len(shape.FaceLocalV)
		if nfaces == 0 {
			continue
		}
		for k := 0; k < nfaces; k++ {
			for n := range shape.FaceLocalV[k] {
				rst := []float64{0, 0, 0}
				for i := 0; i < shape.Gndim; i++ {
					rst[i] = shape.NatCoords[i][n]
				}
				shape.Func(shape.S, shape.dSdR, rst[0], rst[1], rst[2], false)
				io.Pforan("S = %v\n", shape.S)
				for m := range shape.FaceLocalV[k] {
					if n == m {
						errS += math.Abs(shape.S[m] - 1.0)
					} else {
						errS += math.Abs(shape.S[m])
					}
				}
			}
		}
		io.Pforan("%g\n", errS)
		if errS > tol {
			tst.Errorf("%s failed with err = %g\n", name, errS)
			return
		}

		io.PfGreen("OK\n")
	}
}
Beispiel #10
0
// CheckDerivs check derivatives computed by isotropic function
func (o *IsoFun) CheckDerivs(A []float64, tol, tol2, tolq, tol3 float64, ver bool, args ...interface{}) (err error) {

	// L and invariants
	chk.IntAssert(len(A), o.ncp)
	L := make([]float64, 3)
	err = M_EigenValsNum(L, A)
	if err != nil {
		return
	}
	p, q, err := GenInvs(L, o.n, o.a)
	if err != nil {
		return
	}
	io.Pforan("L     = %v\n", L)
	io.Pforan("p, q  = %v, %v\n", p, q)

	// constants
	h := 1e-6
	var has_error error

	// derivatives of callback functions ///////////////

	// df/dp, df/dq, d²f/dp², d²f/dq², d²f/dpdq
	dfdp, dfdq := o.gfcn(p, q, args...)
	d2fdp2, d2fdq2, d2fdpdq := o.hfcn(p, q, args...)
	if ver {
		io.Pfpink("\nd w.r.t invariants . . . \n")
	}

	// check df/dp
	dfdp_num, _ := num.DerivCentral(func(x float64, notused ...interface{}) (res float64) {
		return o.ffcn(x, q, args...)
	}, p, h)
	err = chk.PrintAnaNum("df/dp   ", tol, dfdp, dfdp_num, ver)
	if err != nil {
		has_error = err
	}

	// check df/dq
	dfdq_num, _ := num.DerivCentral(func(x float64, notused ...interface{}) (res float64) {
		return o.ffcn(p, x, args...)
	}, q, h)
	err = chk.PrintAnaNum("df/dq   ", tol, dfdq, dfdq_num, ver)
	if err != nil {
		has_error = err
	}

	// check d²f/dp²
	d2fdp2_num, _ := num.DerivCentral(func(x float64, notused ...interface{}) (res float64) {
		dfdp_tmp, _ := o.gfcn(x, q, args...)
		return dfdp_tmp
	}, p, h)
	err = chk.PrintAnaNum("d²f/dp² ", tol, d2fdp2, d2fdp2_num, ver)
	if err != nil {
		has_error = err
	}

	// check d²f/dq²
	d2fdq2_num, _ := num.DerivCentral(func(x float64, notused ...interface{}) (res float64) {
		_, dfdq_tmp := o.gfcn(p, x, args...)
		return dfdq_tmp
	}, q, h)
	err = chk.PrintAnaNum("d²f/dq² ", tol, d2fdq2, d2fdq2_num, ver)
	if err != nil {
		has_error = err
	}

	// check d²f/dpdq
	d2fdpdq_num, _ := num.DerivCentral(func(x float64, notused ...interface{}) (res float64) {
		dfdp_tmp, _ := o.gfcn(p, x, args...)
		return dfdp_tmp
	}, q, h)
	err = chk.PrintAnaNum("d²f/dpdq", tol, d2fdpdq, d2fdpdq_num, ver)
	if err != nil {
		has_error = err
	}

	// derivatives w.r.t eigenvalues ///////////////////

	// df/dL and d²f/dLdL
	_, err = o.Gp(L, args...)
	if err != nil {
		chk.Panic("Gp failed:\n%v", err)
	}
	err = o.HafterGp(args...)
	if err != nil {
		chk.Panic("HafterGp failed:\n%v", err)
	}
	dfdL := make([]float64, 3)
	d2pdLdL := la.MatAlloc(3, 3)
	d2qdLdL := la.MatAlloc(3, 3)
	d2fdLdL := la.MatAlloc(3, 3)
	copy(dfdL, o.DfdL)
	la.MatCopy(d2pdLdL, 1, o.d2pdLdL)
	la.MatCopy(d2qdLdL, 1, o.d2qdLdL)
	la.MatCopy(d2fdLdL, 1, o.DgdL)

	// check df/dL
	if ver {
		io.Pfpink("\ndf/dL . . . . . . . . \n")
	}
	var fval, tmp float64
	for j := 0; j < 3; j++ {
		dnum, _ := num.DerivCentral(func(x float64, notused ...interface{}) (res float64) {
			tmp, L[j] = L[j], x
			defer func() { L[j] = tmp }()
			fval, err = o.Fp(L, args...)
			if err != nil {
				chk.Panic("Fp failed:\n%v", err)
			}
			return fval
		}, L[j], h)
		err := chk.PrintAnaNum(io.Sf("df/dL[%d]", j), tol, dfdL[j], dnum, ver)
		if err != nil {
			has_error = err
		}
	}

	// check d²p/dLdL
	if ver {
		io.Pfpink("\nd²p/dLdL . . . . . . . . \n")
	}
	for i := 0; i < 3; i++ {
		for j := 0; j < 3; j++ {
			dnum, _ := num.DerivCentral(func(x float64, notused ...interface{}) (res float64) {
				tmp, L[j] = L[j], x
				defer func() { L[j] = tmp }()
				_, err = o.Gp(L, args...)
				if err != nil {
					chk.Panic("Gp failed\n%v", err)
				}
				return o.dpdL[i]
			}, L[j], h)
			err := chk.PrintAnaNum(io.Sf("d²p/dL[%d]dL[%d]", i, j), tol2, d2pdLdL[i][j], dnum, ver)
			if err != nil {
				has_error = err
			}
		}
	}

	// check d²q/dLdL
	if ver {
		io.Pfpink("\nd²q/dLdL . . . . . . . . \n")
	}
	for i := 0; i < 3; i++ {
		for j := 0; j < 3; j++ {
			dnum, _ := num.DerivCentral(func(x float64, notused ...interface{}) (res float64) {
				tmp, L[j] = L[j], x
				defer func() { L[j] = tmp }()
				_, err = o.Gp(L, args...)
				if err != nil {
					chk.Panic("Gp failed\n%v", err)
				}
				return o.dqdL[i]
			}, L[j], h)
			err := chk.PrintAnaNum(io.Sf("d²q/dL[%d]dL[%d]", i, j), tolq, d2qdLdL[i][j], dnum, ver)
			if err != nil {
				has_error = err
			}
		}
	}

	// check d²f/dLdL
	if ver {
		io.Pfpink("\nd²f/dLdL . . . . . . . . \n")
	}
	for i := 0; i < 3; i++ {
		for j := 0; j < 3; j++ {
			dnum, _ := num.DerivCentral(func(x float64, notused ...interface{}) (res float64) {
				tmp, L[j] = L[j], x
				defer func() { L[j] = tmp }()
				_, err = o.Gp(L, args...)
				if err != nil {
					chk.Panic("Gp failed\n%v", err)
				}
				return o.DfdL[i]
			}, L[j], h)
			err := chk.PrintAnaNum(io.Sf("d²f/dL[%d]dL[%d]", i, j), tol2, d2fdLdL[i][j], dnum, ver)
			if err != nil {
				has_error = err
			}
		}
	}

	// derivatives w.r.t full tensor ///////////////////

	// dfdA and d²f/dAdA
	ncp := len(A)
	dfdA := make([]float64, ncp)
	d2fdAdA := la.MatAlloc(ncp, ncp)
	_, err = o.Ga(dfdA, A, args...) // also computes P, L and Acpy
	if err != nil {
		chk.Panic("Ga failed:\n%v", err)
	}
	err = o.HafterGa(d2fdAdA, args...) // also computes dPdA
	if err != nil {
		chk.Panic("HafterGa failed:\n%v", err)
	}

	// check df/dA
	if ver {
		io.Pfpink("\ndf/dA . . . . . . . . \n")
	}
	for j := 0; j < ncp; j++ {
		dnum, _ := num.DerivCentral(func(x float64, notused ...interface{}) (res float64) {
			tmp, A[j] = A[j], x
			defer func() { A[j] = tmp }()
			fval, err = o.Fa(A, args...)
			if err != nil {
				chk.Panic("Fa failed:\n%v", err)
			}
			return fval
		}, A[j], h)
		err := chk.PrintAnaNum(io.Sf("df/dA[%d]", j), tol, dfdA[j], dnum, ver)
		if err != nil {
			has_error = err
		}
	}

	// check dP/dA
	if false {
		for k := 0; k < 3; k++ {
			if ver {
				io.Pfpink("\ndP%d/dA . . . . . . . . \n", k)
			}
			for i := 0; i < ncp; i++ {
				for j := 0; j < ncp; j++ {
					dnum, _ := num.DerivCentral(func(x float64, notused ...interface{}) (res float64) {
						tmp, A[j] = A[j], x
						defer func() { A[j] = tmp }()
						err = M_EigenValsProjsNum(o.P, o.L, o.Acpy)
						if err != nil {
							chk.Panic("M_EigenValsProjsNum failed:\n%v", err)
						}
						return o.P[k][i]
					}, A[j], h)
					err := chk.PrintAnaNum(io.Sf("dP%d/dA[%d]dA[%d]", k, i, j), tol, o.dPdA[k][i][j], dnum, ver)
					if err != nil {
						has_error = err
					}
				}
			}
		}
	}

	// check d²f/dAdA
	if ver {
		io.Pfpink("\nd²f/dAdA . . . . . . . . \n")
	}
	dfdA_tmp := make([]float64, ncp)
	for i := 0; i < ncp; i++ {
		for j := 0; j < ncp; j++ {
			dnum, _ := num.DerivCentral(func(x float64, notused ...interface{}) (res float64) {
				tmp, A[j] = A[j], x
				defer func() { A[j] = tmp }()
				_, err = o.Ga(dfdA_tmp, A, args...)
				if err != nil {
					chk.Panic("Ga failed:\n%v", err)
				}
				return dfdA_tmp[i]
			}, A[j], h)
			dtol := tol2
			if i == j && (i == 3 || i == 4 || i == 5) {
				dtol = tol3
			}
			err := chk.PrintAnaNum(io.Sf("d²f/dA[%d]dA[%d]", i, j), dtol, d2fdAdA[i][j], dnum, ver)
			if err != nil {
				has_error = err
			}
		}
	}

	// any errors?
	if has_error != nil {
		err = has_error
	}
	return
}
Beispiel #11
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
	}
}
Beispiel #12
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)
			}
		}
	}
}
Beispiel #13
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)
	}
}
Beispiel #14
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)
		}
	}
}
Beispiel #15
0
// M_EigenProjsDerivNum returns the derivatives of the eigenprojectors w.r.t its defining tensor
// using the finite differences method.
//  Input:
//    a -- tensor in Mandel basis
//    h -- step size for finite differences
//  Output:
//    dPda -- derivatives [3][ncp][ncp]
func M_EigenProjsDerivNum(dPda [][][]float64, a []float64, h float64) (err error) {
	ncp := len(a)
	λ := make([]float64, 3)
	P := la.MatAlloc(3, ncp)
	Q := Alloc2()
	A := Alloc2()
	q2p := func(k int) {
		switch k {
		case 0:
			P[0][0] = Q[0][0] * Q[0][0]
			P[0][1] = Q[1][0] * Q[1][0]
			P[0][2] = Q[2][0] * Q[2][0]
			P[0][3] = Q[0][0] * Q[1][0] * SQ2
			if ncp == 6 {
				P[0][4] = Q[1][0] * Q[2][0] * SQ2
				P[0][5] = Q[2][0] * Q[0][0] * SQ2
			}
		case 1:
			P[1][0] = Q[0][1] * Q[0][1]
			P[1][1] = Q[1][1] * Q[1][1]
			P[1][2] = Q[2][1] * Q[2][1]
			P[1][3] = Q[0][1] * Q[1][1] * SQ2
			if ncp == 6 {
				P[1][4] = Q[1][1] * Q[2][1] * SQ2
				P[1][5] = Q[2][1] * Q[0][1] * SQ2
			}
		case 2:
			P[2][0] = Q[0][2] * Q[0][2]
			P[2][1] = Q[1][2] * Q[1][2]
			P[2][2] = Q[2][2] * Q[2][2]
			P[2][3] = Q[0][2] * Q[1][2] * SQ2
			if ncp == 6 {
				P[2][4] = Q[1][2] * Q[2][2] * SQ2
				P[2][5] = Q[2][2] * Q[0][2] * SQ2
			}
		}
	}
	var tmp float64
	failed := false
	for k := 0; k < 3; k++ {
		for i := 0; i < ncp; i++ {
			for j := 0; j < ncp; j++ {
				dPda[k][i][j], _ = num.DerivCentral(func(x float64, args ...interface{}) float64 {
					tmp, a[j] = a[j], x
					defer func() { a[j] = tmp }()
					Man2Ten(A, a)
					_, err = la.Jacobi(Q, λ, A)
					if err != nil {
						failed = true
						return 0
					}
					q2p(k)
					return P[k][i]
				}, a[j], h)
				if failed {
					return
				}
			}
		}
	}
	return
}