// Calc_c computes the elastic/plastic transition zone // TODO: check what's 'c' exactly func (o *PressCylin) Calc_c(P float64) float64 { var nls num.NlSolver defer nls.Clean() o.P_fx = P Res := []float64{(o.a + o.b) / 2.0} // initial values nls.Init(1, o.fx_fun, nil, o.dfdx_fun, true, false, nil) nls.Solve(Res, true) return Res[0] }
// CalcEps0 computes initial strains from stresses (s.Sig) // Note: initial strains are elastic strains => εe_ini := ε0 func (o *HyperElast1) CalcEps0(s *State) { s0 := make([]float64, o.Nsig) s0no, p0, q0 := tsr.M_devσ(s0, s.Sig) ev0 := -p0 / o.K0 ed0 := q0 / (3.0 * o.G0) if !o.le { var nls num.NlSolver nls.Init(2, func(fx, x []float64) error { // ev=x[0], ed=x[1] εv, εd := x[0], x[1] p, q := o.Calc_pq(εv, εd) fx[0] = p - p0 fx[1] = q - q0 return nil }, nil, func(J [][]float64, x []float64) (err error) { εv, εd := x[0], x[1] pv := o.pa * math.Exp(-o.a*εv) Dvv := o.a * (1.0 + 1.5*o.a*o.κb*εd*εd) * pv Dvd := -3.0 * o.a * o.κb * εd * pv Ddd := 3.0 * (o.G0 + o.κb*pv) J[0][0] = -Dvv J[0][1] = -Dvd J[1][0] = Dvd J[1][1] = Ddd return nil }, true, false, map[string]float64{"lSearch": 0}) x := []float64{ev0, ed0} nls.SetTols(1e-10, 1e-10, 1e-14, num.EPS) //nls.ChkConv = false //nls.CheckJ(x, 1e-6, true, false) silent := true err := nls.Solve(x, silent) if err != nil { chk.Panic("HyperElast1: CalcEps0: non-linear solver failed:\n%v", err) } ev0, ed0 = x[0], x[1] } if s0no > 0 { for i := 0; i < o.Nsig; i++ { s.EpsE[i] = ev0*tsr.Im[i]/3.0 + tsr.SQ3by2*ed0*(s0[i]/s0no) } return } for i := 0; i < o.Nsig; i++ { s.EpsE[i] = ev0 * tsr.Im[i] / 3.0 } }
// Run computes β starting witn an initial guess func (o *ReliabFORM) Run(βtrial float64, verbose bool, args ...interface{}) (β float64, μ, σ, x []float64) { // initial random variables β = βtrial nx := len(o.μ) μ = make([]float64, nx) // mean values (equivalent normal value) σ = make([]float64, nx) // deviation values (equivalent normal value) x = make([]float64, nx) // current vector of random variables defining min(β) for i := 0; i < nx; i++ { μ[i] = o.μ[i] σ[i] = o.σ[i] x[i] = o.μ[i] } // lognormal distribution structure var lnd DistLogNormal // has lognormal random variable? haslrv := false for _, found := range o.lrv { if found { haslrv = true break } } // function to compute β with x-constant // gβ(β) = g(μ - β・A・σ) = 0 var err error gβfcn := func(fy, y []float64) error { βtmp := y[0] for i := 0; i < nx; i++ { o.xtmp[i] = μ[i] - βtmp*o.α[i]*σ[i] } fy[0], err = o.gfcn(o.xtmp, args) if err != nil { chk.Panic("cannot compute gfcn(%v):\n%v", o.xtmp, err) } return nil } // derivative of gβ w.r.t β hβfcn := func(dfdy [][]float64, y []float64) error { βtmp := y[0] for i := 0; i < nx; i++ { o.xtmp[i] = μ[i] - βtmp*o.α[i]*σ[i] } err = o.hfcn(o.dgdx, o.xtmp, args) if err != nil { chk.Panic("cannot compute hfcn(%v):\n%v", o.xtmp, err) } dfdy[0][0] = 0 for i := 0; i < nx; i++ { dfdy[0][0] -= o.dgdx[i] * o.α[i] * σ[i] } return nil } // nonlinear solver with y[0] = β // solving: gβ(β) = g(μ - β・A・σ) = 0 var nls num.NlSolver nls.Init(1, gβfcn, nil, hβfcn, true, false, nil) defer nls.Clean() // message if verbose { io.Pf("\n%s", io.StrThickLine(60)) } // plotting plot := o.PlotFnk != "" if nx != 2 { plot = false } if plot { if o.PlotNp < 3 { o.PlotNp = 41 } var umin, umax, vmin, vmax float64 if o.PlotCf < 1 { o.PlotCf = 2 } if len(o.PlotUrange) == 0 { umin, umax = μ[0]-o.PlotCf*μ[0], μ[0]+o.PlotCf*μ[0] vmin, vmax = μ[1]-o.PlotCf*μ[1], μ[1]+o.PlotCf*μ[1] } else { chk.IntAssert(len(o.PlotUrange), 2) chk.IntAssert(len(o.PlotVrange), 2) umin, umax = o.PlotUrange[0], o.PlotUrange[1] vmin, vmax = o.PlotVrange[0], o.PlotVrange[1] } o.PlotU, o.PlotV = utl.MeshGrid2D(umin, umax, vmin, vmax, o.PlotNp, o.PlotNp) o.PlotZ = la.MatAlloc(o.PlotNp, o.PlotNp) plt.SetForEps(0.8, 300) for i := 0; i < o.PlotNp; i++ { for j := 0; j < o.PlotNp; j++ { o.xtmp[0] = o.PlotU[i][j] o.xtmp[1] = o.PlotV[i][j] o.PlotZ[i][j], err = o.gfcn(o.xtmp, args) if err != nil { chk.Panic("cannot compute gfcn(%v):\n%v", x, err) } } } plt.Contour(o.PlotU, o.PlotV, o.PlotZ, "") plt.ContourSimple(o.PlotU, o.PlotV, o.PlotZ, true, 8, "levels=[0], colors=['yellow']") plt.PlotOne(x[0], x[1], "'ro', label='initial'") } // iterations to find β var dat VarData B := []float64{β} itB := 0 for itB = 0; itB < o.NmaxItB; itB++ { // message if verbose { gx, err := o.gfcn(x, args) if err != nil { chk.Panic("cannot compute gfcn(%v):\n%v", x, err) } io.Pf("%s itB=%d β=%g g=%g\n", io.StrThinLine(60), itB, β, gx) } // plot if plot { plt.PlotOne(x[0], x[1], "'r.'") } // compute direction cosines itA := 0 for itA = 0; itA < o.NmaxItA; itA++ { // has lognormal random variable (lrv) if haslrv { // find equivalent normal mean and std deviation for lognormal variables for i := 0; i < nx; i++ { if o.lrv[i] { // set distribution dat.M, dat.S = o.μ[i], o.σ[i] lnd.Init(&dat) // update μ and σ fx := lnd.Pdf(x[i]) Φinvx := (math.Log(x[i]) - lnd.M) / lnd.S φx := math.Exp(-Φinvx*Φinvx/2.0) / math.Sqrt2 / math.SqrtPi σ[i] = φx / fx μ[i] = x[i] - Φinvx*σ[i] } } } // compute direction cosines err = o.hfcn(o.dgdx, x, args) if err != nil { chk.Panic("cannot compute hfcn(%v):\n%v", x, err) } den := 0.0 for i := 0; i < nx; i++ { den += math.Pow(o.dgdx[i]*σ[i], 2.0) } den = math.Sqrt(den) αerr := 0.0 // difference on α for i := 0; i < nx; i++ { αnew := o.dgdx[i] * σ[i] / den αerr += math.Pow(αnew-o.α[i], 2.0) o.α[i] = αnew } αerr = math.Sqrt(αerr) // message if verbose { io.Pf(" itA=%d\n", itA) io.Pf("%12s%12s%12s%12s\n", "x", "μ", "σ", "α") for i := 0; i < nx; i++ { io.Pf("%12.3f%12.3f%12.3f%12.3f\n", x[i], μ[i], σ[i], o.α[i]) } } // update x-star for i := 0; i < nx; i++ { x[i] = μ[i] - β*o.α[i]*σ[i] } // check convergence on α if itA > 1 && αerr < o.TolA { if verbose { io.Pfgrey(". . . converged on α with αerr=%g . . .\n", αerr) } break } } // failed to converge on α if itA == o.NmaxItA { chk.Panic("failed to convege on α") } // compute new β B[0] = β nls.Solve(B, o.NlsSilent) βerr := math.Abs(B[0] - β) β = B[0] if o.NlsCheckJ { nls.CheckJ(B, o.NlsCheckJtol, true, false) } // update x-star for i := 0; i < nx; i++ { x[i] = μ[i] - β*o.α[i]*σ[i] } // check convergence on β if βerr < o.TolB { if verbose { io.Pfgrey2(". . . converged on β with βerr=%g . . .\n", βerr) } break } } // failed to converge on β if itB == o.NmaxItB { chk.Panic("failed to converge on β") } // message if verbose { gx, err := o.gfcn(x, args) if err != nil { chk.Panic("cannot compute gfcn(%v):\n%v", x, err) } io.Pfgreen("x = %v\n", x) io.Pfgreen("g = %v\n", gx) io.PfGreen("β = %v\n", β) } // plot if plot { plt.Gll("$x_0$", "$x_1$", "") plt.Cross("") plt.SaveD("/tmp/gosl", "fig_form_"+o.PlotFnk+".eps") } return }
func main() { PI := math.Pi yf := func(x float64) float64 { return 1.0 - math.Sqrt(x) - math.Sin(10.0*math.Pi*x)*x } dydx := func(x float64) float64 { return -math.Sin(10.0*PI*x) - 10.0*PI*x*math.Cos(10.0*PI*x) - 1.0/(2.0*math.Sqrt(x)) } var nlsDY num.NlSolver nlsDY.Init(1, func(fx, x []float64) error { fx[0] = dydx(x[0]) return nil }, nil, nil, false, true, nil) defer nlsDY.Clean() X := []float64{0.09, 0.25, 0.45, 0.65, 0.85} Y := make([]float64, len(X)) for i, x := range X { // find min xx := []float64{x} err := nlsDY.Solve(xx, true) if err != nil { io.PfRed("dydx nls failed:\n%v", err) return } X[i] = xx[0] Y[i] = yf(X[i]) } // find next point along horizontal line Xnext := []float64{0.2, 0.4, 0.6, 0.8} Ynext := make([]float64, len(Xnext)) for i, xnext := range Xnext { var nlsX num.NlSolver nlsX.Init(1, func(fx, x []float64) error { fx[0] = Y[i] - yf(x[0]) return nil }, nil, nil, false, true, nil) defer nlsX.Clean() xx := []float64{xnext} err := nlsX.Solve(xx, true) if err != nil { io.PfRed("dydx nls failed:\n%v", err) return } Xnext[i] = xx[0] Ynext[i] = yf(Xnext[i]) } // auxiliary points XX := []float64{ 0, X[0], Xnext[0], X[1], Xnext[1], X[2], Xnext[2], X[3], Xnext[3], X[4], } YY := []float64{ 1, Y[0], Ynext[0], Y[1], Ynext[1], Y[2], Ynext[2], Y[3], Ynext[3], Y[4], } io.Pforan("XX = %.3f\n", XX) io.Pforan("YY = %.3f\n", YY) // find arc-length arclen := 0.0 for i := 0; i < len(XX); i += 2 { a := XX[i] b := XX[i+1] if i == 0 { a += 1e-7 } var quad num.Simp quad.Init(func(x float64) float64 { return math.Sqrt(1.0 + math.Pow(dydx(x), 2.0)) }, a, b, 1e-4) res, err := quad.Integrate() if err != nil { io.PfRed("quad failed:\n%v", err) return } arclen += res io.Pf("int(...) from %.15f to %.15f = %g\n", a, b, res) } io.Pforan("arclen = %v\n", arclen) np := 201 xx := utl.LinSpace(0, 1, np) yy := make([]float64, np) for i := 0; i < np; i++ { yy[i] = yf(xx[i]) } plt.Plot(xx, yy, "'b-', clip_on=0") for i, x := range X { plt.PlotOne(x, Y[i], "'r|', mew=2, ms=30, clip_on=0") } for i, x := range Xnext { plt.PlotOne(x, Ynext[i], "'r_', mew=2, ms=30, clip_on=0") } for i := 0; i < len(XX); i += 2 { x0, y0 := XX[i], YY[i] x1, y1 := XX[i+1], YY[i+1] plt.Arrow(x0, y0, x1, y1, "") } plt.SetXnticks(11) plt.Gll("x", "y", "") plt.SaveD("/tmp/goga", "calcZDT3pts.eps") }