func Test_imap(tst *testing.T) { //utl.Tsilent = false chk.PrintTitle("Test imap") for name, shape := range factory { gndim := shape.Gndim if gndim == 1 { continue } io.Pfyel("--------------------------------- %-6s---------------------------------\n", name) // check inverse mapping tol := 1e-14 noise := 0.01 if name == "tri10" { tol = 1e-14 } if shape.FaceNvertsMax > 2 { noise = 0.0 } nverts := shape.Nverts C := la.MatAlloc(gndim, nverts) s := []float64{rand.Float64(), rand.Float64(), rand.Float64()} // scale factors la.MatCopy(C, 1.0, shape.NatCoords) _ = tol io.Pf("nverts:%v\n", nverts) io.Pf("gndim:%v\n", gndim) for i := 0; i < gndim; i++ { for j := 0; j < nverts; j++ { C[i][j] *= s[i] C[i][j] += noise * rand.Float64() // noise } } r := make([]float64, 3) x := make([]float64, 3) R := la.MatAlloc(gndim, nverts) for j := 0; j < nverts; j++ { for i := 0; i < gndim; i++ { x[i] = C[i][j] } err := shape.InvMap(r, x, C) io.Pf("r:%v\n", r) _ = err for i := 0; i < gndim; i++ { R[i][j] = r[i] } } chk.Matrix(tst, "checking", tol, R, shape.NatCoords) io.PfGreen("OK\n") } }
// Set copies states // Note: 1) this and other states must have been pre-allocated with the same sizes // 2) this method does not check for errors func (o *State) Set(other *State) { // essential copy(o.Sig, other.Sig) // for plasticity if len(o.Alp) > 0 { copy(o.EpsTr, other.EpsTr) copy(o.Alp, other.Alp) o.Dgam = other.Dgam o.Loading = other.Loading o.ApexReturn = other.ApexReturn } // non-linear elasticity if len(o.EpsE) > 0 { copy(o.EpsE, other.EpsE) } // large deformations if len(o.F) > 0 { la.MatCopy(o.F, 1, other.F) } }
func Test_nls04(tst *testing.T) { //verbose() chk.PrintTitle("nls04. finite differences problem") // grid var g fdm.Grid2D g.Init(1.0, 1.0, 6, 6) // equations numbering var e fdm.Equations peq := utl.IntUnique(g.L, g.R, g.B, g.T) e.Init(g.N, peq) // K11 and K12 var K11, K12 la.Triplet fdm.InitK11andK12(&K11, &K12, &e) // assembly F1 := make([]float64, e.N1) fdm.Assemble(&K11, &K12, F1, nil, &g, &e) // prescribed values U2 := make([]float64, e.N2) for _, eq := range g.L { U2[e.FR2[eq]] = 50.0 } for _, eq := range g.R { U2[e.FR2[eq]] = 0.0 } for _, eq := range g.B { U2[e.FR2[eq]] = 0.0 } for _, eq := range g.T { U2[e.FR2[eq]] = 50.0 } // functions k11 := K11.ToMatrix(nil) k12 := K12.ToMatrix(nil) ffcn := func(fU1, U1 []float64) error { // K11*U1 + K12*U2 - F1 la.VecCopy(fU1, -1, F1) // fU1 := (-F1) la.SpMatVecMulAdd(fU1, 1, k11, U1) // fU1 += K11*U1 la.SpMatVecMulAdd(fU1, 1, k12, U2) // fU1 += K12*U2 return nil } Jfcn := func(dfU1dU1 *la.Triplet, U1 []float64) error { fdm.Assemble(dfU1dU1, &K12, F1, nil, &g, &e) return nil } JfcnD := func(dfU1dU1 [][]float64, U1 []float64) error { la.MatCopy(dfU1dU1, 1, K11.ToMatrix(nil).ToDense()) return nil } prms := map[string]float64{ "atol": 1e-8, "rtol": 1e-8, "ftol": 1e-12, "lSearch": 0.0, } // init var nls_sps NlSolver // sparse analytical var nls_num NlSolver // sparse numerical var nls_den NlSolver // dense analytical nls_sps.Init(e.N1, ffcn, Jfcn, nil, false, false, prms) nls_num.Init(e.N1, ffcn, nil, nil, false, true, prms) nls_den.Init(e.N1, ffcn, nil, JfcnD, true, false, prms) defer nls_sps.Clean() defer nls_num.Clean() defer nls_den.Clean() // results U1sps := make([]float64, e.N1) U1num := make([]float64, e.N1) U1den := make([]float64, e.N1) Usps := make([]float64, e.N) Unum := make([]float64, e.N) Uden := make([]float64, e.N) // solution Uc := []float64{0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 50.0, 25.0, 325.0 / 22.0, 100.0 / 11.0, 50.0 / 11.0, 0.0, 50.0, 775.0 / 22.0, 25.0, 375.0 / 22.0, 100.0 / 11.0, 0.0, 50.0, 450.0 / 11.0, 725.0 / 22.0, 25.0, 325.0 / 22.0, 0.0, 50.0, 500.0 / 11.0, 450.0 / 11.0, 775.0 / 22.0, 25.0, 0.0, 50.0, 50.0, 50.0, 50.0, 50.0, 50.0, } io.PfYel("\n---- sparse -------- Analytical Jacobian -------------------\n") // solve err := nls_sps.Solve(U1sps, false) if err != nil { chk.Panic(err.Error()) } // check fdm.JoinVecs(Usps, U1sps, U2, &e) chk.Vector(tst, "Usps", 1e-14, Usps, Uc) // plot if false { g.Contour("results", "fig_t_heat_square", nil, Usps, 11, false) } io.PfYel("\n---- dense -------- Analytical Jacobian -------------------\n") // solve err = nls_den.Solve(U1den, false) if err != nil { chk.Panic(err.Error()) } // check fdm.JoinVecs(Uden, U1den, U2, &e) chk.Vector(tst, "Uden", 1e-14, Uden, Uc) io.PfYel("\n---- sparse -------- Numerical Jacobian -------------------\n") // solve err = nls_num.Solve(U1num, false) if err != nil { chk.Panic(err.Error()) } // check fdm.JoinVecs(Unum, U1num, U2, &e) chk.Vector(tst, "Unum", 1e-14, Unum, Uc) }
// 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 }