Beispiel #1
0
// explicit Runge-Kutta step function
func erk_step(o *ODE, y []float64, x float64, args ...interface{}) (rerr float64, err error) {

	for i := 0; i < o.nstg; i++ {
		o.u[i] = x + o.h*o.erkdat.c[i]
		la.VecCopy(o.v[i], 1, y)
		for j := 0; j < i; j++ {
			la.VecAdd(o.v[i], o.h*o.erkdat.a[i][j], o.f[j])
		}
		if i == 0 && o.erkdat.usefp && !o.first {
			la.VecCopy(o.f[i], 1, o.f[o.nstg-1])
		} else {
			o.nfeval += 1
			err = o.fcn(o.f[i], o.u[i], o.v[i], args...)
			if err != nil {
				return
			}
		}
	}

	var lerrm float64 // m component of local error estimate
	for m := 0; m < o.ndim; m++ {
		lerrm = 0.0
		for i := 0; i < o.nstg; i++ {
			o.w[0][m] += o.erkdat.b[i] * o.f[i][m] * o.h
			lerrm += (o.erkdat.be[i] - o.erkdat.b[i]) * o.f[i][m] * o.h
		}
		rerr += math.Pow(lerrm/o.scal[m], 2.0)
	}
	rerr = max(math.Sqrt(rerr/float64(o.ndim)), 1.0e-10)

	return
}
Beispiel #2
0
// contact_add_to_rhs adds contribution to rhs due to contact modelling
func (o *ElemU) contact_add_to_rhs(fb []float64, sol *Solution) (err error) {

	// compute surface integral
	var qb, db, rmp, rx, rq float64
	for _, nbc := range o.NatBcs {

		// loop over ips of face
		for _, ipf := range o.IpsFace {

			// interpolation functions and gradients @ face
			iface := nbc.IdxFace
			err = o.Cell.Shp.CalcAtFaceIp(o.X, ipf, iface)
			if err != nil {
				return
			}
			Sf := o.Cell.Shp.Sf
			nvec := o.Cell.Shp.Fnvec

			// select natural boundary condition type
			switch nbc.Key {

			// contact
			case "contact":

				// variables extrapolated to face
				qb = o.fipvars(iface, sol)
				xf := o.Cell.Shp.FaceIpRealCoords(o.X, ipf, iface)
				la.VecAdd(xf, 1, o.us) // add displacement: x = X + u
				db = o.contact_g(xf)

				// compute residuals
				coef := ipf[3] * o.Thickness
				Jf := la.VecNorm(nvec)
				rmp = o.contact_ramp(qb + o.κ*db)
				rx = rmp
				rq = qb - rmp
				for j, m := range o.Cell.Shp.FaceLocalVerts[iface] {
					μ := o.Vid2contactId[m]
					fb[o.Qmap[μ]] -= coef * Sf[j] * rq * Jf // -residual
					for i := 0; i < o.Ndim; i++ {
						r := o.Umap[i+m*o.Ndim]
						fb[r] -= coef * Sf[j] * rx * nvec[i] // -extra term
					}
				}
			}
		}
	}
	return
}
Beispiel #3
0
// contact_add_to_jac adds coupled equations due to contact modelling to Jacobian
func (o *ElemU) contact_add_to_jac(Kb *la.Triplet, sol *Solution) (err error) {

	// clear matrices
	for i := 0; i < o.Nq; i++ {
		for j := 0; j < o.Nq; j++ {
			o.Kqq[i][j] = 0
		}
		for j := 0; j < o.Nu; j++ {
			o.Kqu[i][j] = 0
			o.Kuq[j][i] = 0
		}
	}

	// compute surface integral
	var qb, db, Hb float64
	dddu := make([]float64, o.Ndim)
	for _, nbc := range o.NatBcs {

		// loop over ips of face
		for _, ipf := range o.IpsFace {

			// contact
			switch nbc.Key {
			case "contact":

				// interpolation functions and gradients @ face
				iface := nbc.IdxFace
				err = o.Cell.Shp.CalcAtFaceIp(o.X, ipf, iface)
				if err != nil {
					return
				}
				Sf := o.Cell.Shp.Sf
				nvec := o.Cell.Shp.Fnvec
				coef := ipf[3] * o.Thickness
				Jf := la.VecNorm(nvec)

				// variables extrapolated to face
				qb = o.fipvars(iface, sol)
				xf := o.Cell.Shp.FaceIpRealCoords(o.X, ipf, iface)
				la.VecAdd(xf, 1, o.us) // add displacement: x = X + u
				db = o.contact_g(xf)
				o.contact_dgdx(dddu, xf)

				// compute derivatives
				Hb = o.contact_rampD1(qb + o.κ*db)
				for i, m := range o.Cell.Shp.FaceLocalVerts[iface] {
					μ := o.Vid2contactId[m]
					for j, n := range o.Cell.Shp.FaceLocalVerts[iface] {
						ν := o.Vid2contactId[n]
						o.Kqq[μ][ν] += coef * Jf * Sf[i] * Sf[j] * (1.0 - Hb)
						for k := 0; k < o.Ndim; k++ {
							r := k + m*o.Ndim
							c := k + n*o.Ndim
							val := coef * Sf[i] * Sf[j] * Hb * o.κ * dddu[k] * Jf
							o.Kuq[r][ν] += coef * Sf[i] * Sf[j] * Hb * nvec[k]
							o.Kqu[μ][c] -= val
							o.K[r][c] += val
						}
					}
				}
			}
		}
	}

	// add Ks to sparse matrix Kb
	for i, I := range o.Qmap {
		for j, J := range o.Qmap {
			Kb.Put(I, J, o.Kqq[i][j])
		}
		for j, J := range o.Umap {
			Kb.Put(I, J, o.Kqu[i][j])
			Kb.Put(J, I, o.Kuq[j][i])
		}
	}
	for i, I := range o.Umap {
		for j, J := range o.Umap {
			Kb.Put(I, J, o.K[i][j])
		}
	}
	return
}