예제 #1
0
파일: algos.go 프로젝트: PatrickSchm/gofem
// Extrapolator computes the extrapolation matrix for this Shape with a combination of integration points 'ips'
//  Note: E[nverts][nip] must be pre-allocated
func (o *Shape) Extrapolator(E [][]float64, ips []*Ipoint) (err error) {
	la.MatFill(E, 0)
	nip := len(ips)
	N := o.GetShapeMatAtIps(ips)
	if nip < o.Nverts {
		ξ := o.GetNodesNatCoordsMat()
		ξh := o.GetIpsNatCoordsMat(ips)
		ξhi := la.MatAlloc(o.Gndim+1, nip)
		Ni := la.MatAlloc(o.Nverts, nip)
		err = la.MatInvG(Ni, N, 1e-10)
		if err != nil {
			return
		}
		err = la.MatInvG(ξhi, ξh, 1e-10)
		if err != nil {
			return
		}
		ξhξhI := la.MatAlloc(nip, nip) // ξh * inv(ξh)
		for k := 0; k < o.Gndim+1; k++ {
			for j := 0; j < nip; j++ {
				for i := 0; i < nip; i++ {
					ξhξhI[i][j] += ξh[i][k] * ξhi[k][j]
				}
				for i := 0; i < o.Nverts; i++ {
					E[i][j] += ξ[i][k] * ξhi[k][j] // ξ * inv(ξh)
				}
			}
		}
		for i := 0; i < o.Nverts; i++ {
			for j := 0; j < nip; j++ {
				for k := 0; k < nip; k++ {
					I_kj := 0.0
					if j == k {
						I_kj = 1.0
					}
					E[i][j] += Ni[i][k] * (I_kj - ξhξhI[k][j])
				}
			}
		}
	} else {
		err = la.MatInvG(E, N, 1e-10)
		if err != nil {
			return
		}
	}
	return
}
예제 #2
0
// CalcD computes algorithmic tangent operator
func (o *PrincStrainsUp) CalcD(D [][]float64, s *State) (err error) {

	// elastic response
	if !s.Loading {
		o.Mdl.ElastD(D, s)
		return
	}

	// eigenvalues/projectors of trial elastic strain
	err = tsr.M_EigenValsProjsNum(o.P, o.Lεetr, s.EpsTr)
	if err != nil {
		return
	}

	// derivatives of eigenprojectors w.r.t trial elastic strains
	err = tsr.M_EigenProjsDerivAuto(o.dPdT, s.EpsTr, o.Lεetr, o.P)
	if err != nil {
		io.Pforan("EpsTr = %v\n", s.EpsTr)
		io.Pforan("Lεetr = %v\n", o.Lεetr)
		la.PrintMat("P", o.P, "%10g", false)
		return
	}

	// eigenvalues of strains
	err = tsr.M_EigenValsNum(o.Lεe, s.EpsE)
	if err != nil {
		return
	}

	// compute Lσ, De and Jacobian
	o.Mdl.E_CalcSig(o.Lσ, o.Lεe)
	err = o.Mdl.L_SecondDerivs(o.N, o.Nb, o.A, o.h, o.Mb, o.a, o.b, o.c, o.Lσ, s.Alp)
	if err != nil {
		return err
	}
	o.Mdl.E_CalcDe(o.De, o.Lεe)
	o.calcJafterDerivs(o.J, o.Lεe, s.Alp, s.Dgam)

	// invert Jacobian => Ji
	err = la.MatInvG(o.Ji, o.J, 1e-10)
	if err != nil {
		return
	}

	// compute De and Dt = De * Ji
	for i := 0; i < 3; i++ {
		for j := 0; j < 3; j++ {
			o.Dt[i][j] = 0
			for k := 0; k < 3; k++ {
				o.Dt[i][j] += o.De[i][k] * o.Ji[k][j]
			}
		}
	}

	// compute D
	for i := 0; i < o.Nsig; i++ {
		for j := 0; j < o.Nsig; j++ {
			D[i][j] = 0.0
			for k := 0; k < 3; k++ {
				for l := 0; l < 3; l++ {
					D[i][j] += o.Dt[k][l] * o.P[k][i] * o.P[l][j]
				}
				D[i][j] += o.Lσ[k] * o.dPdT[k][i][j]
			}
		}
	}
	return
}
예제 #3
0
// Solve solves non-linear problem f(x) == 0
func (o *NlSolver) Solve(x []float64, silent bool) (err error) {

	// compute scaling vector
	la.VecScaleAbs(o.scal, o.atol, o.rtol, x) // scal := Atol + Rtol*abs(x)

	// evaluate function @ x
	err = o.Ffcn(o.fx, x) // fx := f(x)
	o.NFeval, o.NJeval = 1, 0
	if err != nil {
		return
	}

	// show message
	if !silent {
		o.msg("", 0, 0, 0, true, false)
	}

	// iterations
	var Ldx, Ldx_prev, Θ float64 // RMS norm of delta x, convergence rate
	var fx_max float64
	var nfv int
	for o.It = 0; o.It < o.MaxIt; o.It++ {

		// check convergence on f(x)
		fx_max = la.VecLargest(o.fx, 1.0) // den = 1.0
		if fx_max < o.ftol {
			if !silent {
				o.msg("fx_max(ini)", o.It, Ldx, fx_max, false, true)
			}
			break
		}

		// show message
		if !silent {
			o.msg("", o.It, Ldx, fx_max, false, false)
		}

		// output
		if o.Out != nil {
			o.Out(x)
		}

		// evaluate Jacobian @ x
		if o.It == 0 || !o.CteJac {
			if o.useDn {
				err = o.JfcnDn(o.J, x)
			} else {
				if o.numJ {
					err = Jacobian(&o.Jtri, o.Ffcn, x, o.fx, o.w, false)
					o.NFeval += o.neq
				} else {
					err = o.JfcnSp(&o.Jtri, x)
				}
			}
			o.NJeval += 1
			if err != nil {
				return
			}
		}

		// dense solution
		if o.useDn {

			// invert matrix
			err = la.MatInvG(o.Ji, o.J, 1e-10)
			if err != nil {
				return chk.Err(_nls_err1, err.Error())
			}

			// solve linear system (compute mdx) and compute lin-search data
			o.φ = 0.0
			for i := 0; i < o.neq; i++ {
				o.mdx[i], o.dφdx[i] = 0.0, 0.0
				for j := 0; j < o.neq; j++ {
					o.mdx[i] += o.Ji[i][j] * o.fx[j] // mdx  = inv(J) * fx
					o.dφdx[i] += o.J[j][i] * o.fx[j] // dφdx = tra(J) * fx
				}
				o.φ += o.fx[i] * o.fx[i]
			}
			o.φ *= 0.5

			// sparse solution
		} else {

			// init sparse solver
			if o.It == 0 {
				symmetric, verbose, timing := false, false, false
				err := o.lis.InitR(&o.Jtri, symmetric, verbose, timing)
				if err != nil {
					return chk.Err(_nls_err9, err.Error())
				}
			}

			// factorisation (must be done for all iterations)
			o.lis.Fact()

			// solve linear system => compute mdx
			o.lis.SolveR(o.mdx, o.fx, false) // mdx = inv(J) * fx   false => !sumToRoot

			// compute lin-search data
			if o.Lsearch {
				o.φ = 0.5 * la.VecDot(o.fx, o.fx)
				la.SpTriMatTrVecMul(o.dφdx, &o.Jtri, o.fx) // dφdx := transpose(J) * fx
			}
		}

		//io.Pforan("φ    = %v\n", o.φ)
		//io.Pforan("dφdx = %v\n", o.dφdx)

		// update x
		Ldx = 0.0
		for i := 0; i < o.neq; i++ {
			o.x0[i] = x[i]
			x[i] -= o.mdx[i]
			Ldx += (o.mdx[i] / o.scal[i]) * (o.mdx[i] / o.scal[i])
		}
		Ldx = math.Sqrt(Ldx / float64(o.neq))

		// calculate fx := f(x) @ update x
		err = o.Ffcn(o.fx, x)
		o.NFeval += 1
		if err != nil {
			return
		}

		// check convergence on f(x) => avoid line-search if converged already
		fx_max = la.VecLargest(o.fx, 1.0) // den = 1.0
		if fx_max < o.ftol {
			if !silent {
				o.msg("fx_max", o.It, Ldx, fx_max, false, true)
			}
			break
		}

		// check convergence on Ldx
		if Ldx < o.fnewt {
			if !silent {
				o.msg("Ldx", o.It, Ldx, fx_max, false, true)
			}
			break
		}

		// call line-search => update x and fx
		if o.Lsearch {
			nfv, err = LineSearch(x, o.fx, o.Ffcn, o.mdx, o.x0, o.dφdx, o.φ, o.LsMaxIt, true)
			o.NFeval += nfv
			if err != nil {
				return chk.Err(_nls_err2, err.Error())
			}
			Ldx = 0.0
			for i := 0; i < o.neq; i++ {
				Ldx += ((x[i] - o.x0[i]) / o.scal[i]) * ((x[i] - o.x0[i]) / o.scal[i])
			}
			Ldx = math.Sqrt(Ldx / float64(o.neq))
			fx_max = la.VecLargest(o.fx, 1.0) // den = 1.0
			if Ldx < o.fnewt {
				if !silent {
					o.msg("Ldx(linsrch)", o.It, Ldx, fx_max, false, true)
				}
				break
			}
		}

		// check convergence rate
		if o.It > 0 && o.ChkConv {
			Θ = Ldx / Ldx_prev
			if Θ > 0.99 {
				return chk.Err(_nls_err3, Θ, Ldx, Ldx_prev)
			}
		}
		Ldx_prev = Ldx
	}

	// output
	if o.Out != nil {
		o.Out(x)
	}

	// check convergence
	if o.It == o.MaxIt {
		err = chk.Err(_nls_err4, o.It)
	}
	return
}