Beispiel #1
0
// CalcAtIp calculates volume data such as S and G at natural coordinate r
//  Input:
//   x[ndim][nverts+?] -- coordinates matrix of solid element
//   ip                -- integration point
//  Output:
//   S, DSdR, DxdR, DRdx, G, and J
func (o *Shape) CalcAtIp(x [][]float64, ip *Ipoint, derivs bool) (err error) {

	// S and dSdR
	o.Func(o.S, o.dSdR, ip.R, ip.S, ip.T, derivs)
	if !derivs {
		return
	}

	if o.Gndim == 1 {
		// calculate Jvec3d == dxdR
		for i := 0; i < len(x); i++ {
			o.Jvec3d[i] = 0.0
			for m := 0; m < o.Nverts; m++ {
				o.Jvec3d[i] += x[i][m] * o.dSdR[m][0] // dxdR := x * dSdR
			}
		}

		// calculate J = norm of Jvec3d
		o.J = la.VecNorm(o.Jvec3d)

		// calculate G
		for m := 0; m < o.Nverts; m++ {
			o.Gvec[m] = o.dSdR[m][0] / o.J
		}

		return
	}

	// dxdR := sum_n x * dSdR   =>  dx_i/dR_j := sum_n x^n_i * dS^n/dR_j
	for i := 0; i < len(x); i++ {
		for j := 0; j < o.Gndim; j++ {
			o.dxdR[i][j] = 0.0
			for n := 0; n < o.Nverts; n++ {
				o.dxdR[i][j] += x[i][n] * o.dSdR[n][j]
			}
		}
	}

	// dRdx := inv(dxdR)
	o.J, err = la.MatInv(o.dRdx, o.dxdR, MINDET)
	if err != nil {
		return
	}

	// G == dSdx := dSdR * dRdx  =>  dS^m/dR_i := sum_i dS^m/dR_i * dR_i/dx_j
	la.MatMul(o.G, 1, o.dSdR, o.dRdx)
	return
}
Beispiel #2
0
// InvMap computes the natural coordinates r, given the real coordinate y
//  Input:
//   y[ndim]           -- are the 2D/3D point coordinates
//   x[ndim][nverts+?] -- coordinates matrix of solid element
//  Output:
//   r[3] -- are the natural coordinates of given point
func (o *Shape) InvMap(r, y []float64, x [][]float64) (err error) {

	// check
	if o.Gndim == 1 {
		return chk.Err("Inverse mapping is not implemented in 1D\n")
	}

	var δRnorm float64
	e := make([]float64, o.Gndim)  // residual
	δr := make([]float64, o.Gndim) // corrector
	r[0], r[1], r[2] = 0, 0, 0     // first trial
	it := 0
	derivs := true
	for it = 0; it < INVMAP_NIT; it++ {

		// shape functions and derivatives
		o.Func(o.S, o.dSdR, r[0], r[1], r[2], derivs)

		// residual: e = y - x * S
		for i := 0; i < o.Gndim; i++ {
			e[i] = y[i]
			for j := 0; j < o.Nverts; j++ {
				e[i] -= x[i][j] * o.S[j]
			}
		}

		// Jmat == dxdR = x * dSdR;
		for i := 0; i < len(x); i++ {
			for j := 0; j < o.Gndim; j++ {
				o.dxdR[i][j] = 0.0
				for k := 0; k < o.Nverts; k++ {
					o.dxdR[i][j] += x[i][k] * o.dSdR[k][j] // dxdR := x * dSdR
				}
			}
		}

		// Jimat == dRdx = Jmat.inverse();
		o.J, err = la.MatInv(o.dRdx, o.dxdR, MINDET)
		if err != nil {
			return
		}

		// corrector: dR = Jimat * e
		for i := 0; i < o.Gndim; i++ {
			δr[i] = 0.0
			for j := 0; j < o.Gndim; j++ {
				δr[i] += o.dRdx[i][j] * e[j]
			}
		}

		// converged?
		δRnorm = 0.0
		for i := 0; i < o.Gndim; i++ {
			r[i] += δr[i]
			δRnorm += δr[i] * δr[i]
			// fix r outside range
			if r[i] < -1.0 || r[i] > 1.0 {
				if math.Abs(r[i]-(-1.0)) < INVMAP_TOL {
					r[i] = -1.0
				}
				if math.Abs(r[i]-1.0) < INVMAP_TOL {
					r[i] = 1.0
				}
			}

		}
		if math.Sqrt(δRnorm) < INVMAP_TOL {
			break
		}
	}

	// check
	if it == INVMAP_NIT {
		return
	}
	return
}