Exemplo n.º 1
0
func GetIntegrationPoints(nip, nipf int, cellType string) (ipsElem, ipsFace []*shp.Ipoint) {

	// get integration points of element
	var err error
	ipsElem, err = shp.GetIps(cellType, nip)
	if LogErr(err, io.Sf("cannot get integration points for element with shape type=%q and nip=%d", cellType, nip)) {
		return nil, nil
	}

	// get integration points of face
	faceType := shp.GetFaceType(cellType)
	ipsFace, err = shp.GetIps(faceType, nipf)
	if LogErr(err, io.Sf("cannot get integration points for face with face-shape type=%q and nip=%d", faceType, nip)) {
		return nil, nil
	}
	return
}
Exemplo n.º 2
0
// NodesOnPlane finds vertices located on {x,y,z} plane and returns an iterator
// that can be used to extract results on the plane. An {u,v}-coordinates system is built
// on the plane.
//  Input:
//    ftag -- cells' face tag; e.g. -31
//  Output:
//    dat -- plane data holding vertices on plane and other information; see above
//  Note:
//    1) this function works with 3D cells only
//    2) faces on cells must be either "qua4" or "qua8" types
//    3) middle nodes in "qua8" are disregarded in order to buidl an {u,v} grid
//    4) the resulting mesh on plane must be equally spaced; i.e. Δx and Δy are constant;
//       but not necessarily equal to each other
func NodesOnPlane(ftag int) *PlaneData {

	// check
	ndim := Dom.Msh.Ndim
	if ndim != 3 {
		chk.Panic("this function works in 3D only")
	}

	// loop over cells on face with given face tag
	var dat PlaneData
	dat.Plane = -1
	dat.Ids = make(map[int]bool)
	dat.Dx = make([]float64, ndim)
	Δx := make([]float64, ndim)
	first := true
	cells := Dom.Msh.FaceTag2cells[ftag]
	for _, cell := range cells {
		ctype := cell.C.Type
		for fidx, cftag := range cell.C.FTags {
			if cftag == ftag {

				// check face type
				ftype := shp.GetFaceType(ctype)
				if !(ftype == "qua4" || ftype == "qua8") {
					chk.Panic("can only handle qua4 or qua8 faces for now. ftype=%q", ftype)
				}

				// vertices on face
				flvids := shp.GetFaceLocalVerts(ctype, fidx)
				nv := len(flvids)
				if nv == 8 {
					nv = 4 // avoid middle nodes
				}
				for i := 0; i < nv; i++ {
					vid := cell.C.Verts[flvids[i]]
					dat.Ids[vid] = true
				}

				// compute and check increments in global coordinates
				for i := 1; i < nv; i++ {
					a := cell.C.Verts[flvids[i]]
					b := cell.C.Verts[flvids[i-1]]
					xa := Dom.Msh.Verts[a].C
					xb := Dom.Msh.Verts[b].C
					for j := 0; j < ndim; j++ {
						Δx[j] = max(Δx[j], math.Abs(xa[j]-xb[j]))
					}
				}
				if first {
					for j := 0; j < ndim; j++ {
						dat.Dx[j] = Δx[j]
					}
					first = false
				} else {
					for j := 0; j < ndim; j++ {
						if math.Abs(dat.Dx[j]-Δx[j]) > 1e-10 {
							chk.Panic("all faces must have the same Δx,Δy,Δz")
						}
					}
				}

				// find which plane vertices are located on => which plane this face is parallel to
				perpto := -1 // "perpendicular to" indicator
				switch {
				case Δx[0] < DIST_TOL: // plane perpendicular to x-axis
					perpto = 0
				case Δx[1] < DIST_TOL: // plane perpendicular to y-axis
					perpto = 1
				case Δx[2] < DIST_TOL: // plane perpendicular to z-axis
					perpto = 2
				default:
					chk.Panic("planes must be perpendicular to one of the x-y-z axes")
				}
				if dat.Plane < 0 {
					dat.Plane = perpto
				} else {
					if perpto != dat.Plane {
						chk.Panic("all planes must be perperdicular to the same axis")
					}
				}
			}
		}
	}

	// uv: indices and increments
	dat.Iu = make([]int, 2)
	dat.Du = make([]float64, 2)
	switch dat.Plane {
	case 0: // plane perpendicular to x-axis
		dat.Iu = []int{1, 2}
	case 1: // plane perpendicular to y-axis
		dat.Iu = []int{0, 2}
	case 2: // plane perpendicular to z-axis
		dat.Iu = []int{0, 1}
	}
	for j := 0; j < 2; j++ {
		dat.Du[j] = dat.Dx[dat.Iu[j]]
	}

	// uv: limits
	dat.Umin = make([]float64, 2)
	dat.Umax = make([]float64, 2)
	first = true
	for vid, _ := range dat.Ids {
		x := Dom.Msh.Verts[vid].C
		if first {
			for j := 0; j < 2; j++ {
				dat.Umin[j] = x[dat.Iu[j]]
				dat.Umax[j] = x[dat.Iu[j]]
			}
			first = false
		} else {
			for j := 0; j < 2; j++ {
				dat.Umin[j] = min(dat.Umin[j], x[dat.Iu[j]])
				dat.Umax[j] = max(dat.Umax[j], x[dat.Iu[j]])
			}
		}
	}

	// uv: size of grid
	dat.Nu = make([]int, 2)
	for j := 0; j < 2; j++ {
		dat.Nu[j] = int((dat.Umax[j]-dat.Umin[j])/dat.Du[j]) + 1
	}

	// uv: bins
	dd := DIST_TOL * 2
	nb := 20
	dat.Ubins.Init([]float64{dat.Umin[0] - dd, dat.Umin[1] - dd}, []float64{dat.Umax[0] + dd, dat.Umax[1] + dd}, nb)
	u := []float64{0, 0}
	for vid, _ := range dat.Ids {
		x := Dom.Msh.Verts[vid].C
		for j := 0; j < 2; j++ {
			u[j] = x[dat.Iu[j]]
		}
		err := dat.Ubins.Append(u, vid)
		if err != nil {
			chk.Panic("cannot append {u,v} coordinate to bins. u=%v", u)
		}
	}

	// allocate F
	dat.F = la.MatAlloc(dat.Nu[0], dat.Nu[1])
	return &dat
}