Exemple #1
0
def calculate_2D_normals(mesh, elem_ID, face_ID, quad_pts):
    '''
	Calculate the normals for 2D shapes (triangles and quadrilaterals).

	Inputs:
	-------
		mesh: mesh object
		elem_ID: element index
		face_ID: face index
		quad_pts: points in reference space at which to calculate normals

	Outputs:
	--------
		normals: normal vector [nq, ndims]
	'''
    gbasis = mesh.gbasis
    gorder = mesh.gorder
    elem_coords = mesh.elements[elem_ID].node_coords
    ''' Get face coordinates '''
    # Get local IDs of face nodes
    fnodes = gbasis.get_local_face_node_nums(gorder, face_ID)
    # Instantiate segment basis
    basis_seg = basis_defs.LagrangeSeg(gorder)
    # Compute basis values
    basis_ref_grad = basis_seg.get_grads(quad_pts)
    # Extract coordinates of face nodes
    face_coords = elem_coords[fnodes]
    ''' Calculate 2D normals '''
    xphys_grad = np.matmul(
        face_coords.transpose(),
        basis_ref_grad)[:, :, 0]  # gradient of physical space w.r.t ref space
    normals = xphys_grad[:, ::-1]
    normals[:, 1] *= -1.

    return normals  # [nq, ndims]
Exemple #2
0
def set_basis(order, basis_name):
    '''
	Sets the basis class given the basis_name string argument

	Inputs:
	-------
		order: solution order
		basis_name: name of the basis function we wish to instantiate
			as a class

	Outputs:
	--------
		basis: instantiated basis class

	Raise:
	------
		If the basis class is not defined, returns a NotImplementedError
	'''
    if BasisType[basis_name] == BasisType.LagrangeSeg:
        basis = basis_defs.LagrangeSeg(order)
    elif BasisType[basis_name] == BasisType.LegendreSeg:
        basis = basis_defs.LegendreSeg(order)
    elif BasisType[basis_name] == BasisType.LagrangeQuad:
        basis = basis_defs.LagrangeQuad(order)
    elif BasisType[basis_name] == BasisType.LegendreQuad:
        basis = basis_defs.LegendreQuad(order)
    elif BasisType[basis_name] == BasisType.LagrangeTri:
        basis = basis_defs.LagrangeTri(order)
    elif BasisType[basis_name] == BasisType.HierarchicH1Tri:
        basis = basis_defs.HierarchicH1Tri(order)
    else:
        raise NotImplementedError

    return basis
Exemple #3
0
def ref_to_phys_time(mesh, time, dt, tref, basis=None):
    '''
    This function converts reference time coordinates to physical
    time coordinates

    Intputs:
    --------
        mesh: mesh object
        elem_ID: element ID
        time: current solution time
        dt: solution time step
        tref: time in reference space [nq, 1]
        basis: basis object

	Outputs:
	--------
        tphys: coordinates in temporal space [nq, 1]
    '''
    gorder = 1
    if basis is None:
        basis = basis_defs.LagrangeSeg(gorder)
        basis.get_basis_val_grads(tref, get_val=True)

    tphys = (time / 2.) * (1. - tref) + (time + dt) / 2. * (1. + tref)

    return tphys, basis
Exemple #4
0
    def get_geom_data(self, mesh, basis, order):
        '''
		Precomputes the geometric data for the ADER-DG scheme

		Inputs:
		-------
			mesh: mesh object
			basis: basis object
			order: solution order

		Outputs:
		--------
			self.jac_elems: precomputed Jacobian for each element
				[num_elems, nb, ndims, ndims]
			self.ijac_elems: precomputed inverse Jacobian for each element
				[num_elems, nb, ndims, ndims]
			self.djac_elems: precomputed determinant of the Jacobian for each
				element [num_elems, nb, 1]
			self.x_elems: precomputed coordinates of the nodal points
				in physical space [num_elems, nb, ndims]
		'''
        ndims = mesh.ndims
        num_elems = mesh.num_elems
        nb = basis.nb
        gbasis = mesh.gbasis
        tile_basis = basis_defs.LagrangeSeg(order)

        # Define geometric basis for tiling jac, ijac, and djac
        xnodes = gbasis.get_nodes(order)
        nnodes = xnodes.shape[0]

        tile_xnodes = tile_basis.get_nodes(order)
        tile_nnodes = tile_xnodes.shape[0]

        # Allocate
        self.jac_elems = np.zeros([num_elems, nb, ndims, ndims])
        self.ijac_elems = np.zeros([num_elems, nb, ndims, ndims])
        self.djac_elems = np.zeros([num_elems, nb, 1])
        self.x_elems = np.zeros([num_elems, nb, ndims])

        for elem_ID in range(mesh.num_elems):
            # Jacobian
            djac, jac, ijac = basis_tools.element_jacobian(mesh,
                                                           elem_ID,
                                                           xnodes,
                                                           get_djac=True,
                                                           get_jac=True,
                                                           get_ijac=True)

            self.jac_elems[elem_ID] = np.tile(jac, (tile_nnodes, 1, 1))
            self.ijac_elems[elem_ID] = np.tile(ijac, (tile_nnodes, 1, 1))
            self.djac_elems[elem_ID] = np.tile(djac, (tile_nnodes, 1))

            # Physical coordinates of nodal points
            x = mesh_tools.ref_to_phys(mesh, elem_ID, xnodes)
            # Store
            self.x_elems[elem_ID] = np.tile(x, (tile_nnodes, 1))
Exemple #5
0
def get_lagrange_basis_3D(xq, xnodes, basis_val=None, basis_ref_grad=None):
    '''
	Calculates the 3D Lagrange basis functions

	Inputs:
	-------
		xq: coordinates of quadrature points [nq, ndims]
		xnodes: coordinates of nodes in 1D ref space [nb, ndims]

	Outputs:
	--------
		basis_val: evaluated basis [nq, nb]
		basis_ref_grad: evaluated gradient of basis [nq, nb, ndims]
	'''
    if basis_ref_grad is not None:
        gradx = np.zeros((xq.shape[0], xnodes.shape[0], 1))
        grady = np.zeros_like(gradx)
        gradz = np.zeros_like(gradx)
    else:
        gradx = None
        grady = None
        gradz = None
    # Always need basis_val
    valx = np.zeros((xq.shape[0], xnodes.shape[0]))
    valy = np.zeros_like(valx)
    valz = np.zeros_like(valx)

    # Get 1D basis values first
    nnodes_1D = xnodes.shape[0]
    lagrange_eq_seg = basis_defs.LagrangeSeg(nnodes_1D - 1)
    get_lagrange_basis_1D(xq[:, 0].reshape(-1, 1), xnodes, valx, gradx)
    get_lagrange_basis_1D(xq[:, 1].reshape(-1, 1), xnodes, valy, grady)
    get_lagrange_basis_1D(xq[:, 2].reshape(-1, 1), xnodes, valz, gradz)

    # Tensor products to get 3D basis values
    if basis_val is not None:
        for i in range(xq.shape[0]):
            basis_val[i, :] = np.reshape(
                np.outer(np.outer(valx[i, :], valy[i, :]), valz[i, :]), (-1, ),
                'F')
    if basis_ref_grad is not None:
        for i in range(xq.shape[0]):
            basis_ref_grad[i, :, 0] = np.reshape(
                np.outer(np.outer(gradx[i, :, 0], valy[i, :]), valz[i, :]),
                (-1, ), 'F')
            basis_ref_grad[i, :, 1] = np.reshape(
                np.outer(np.outer(valx[i, :], grady[i, :, 0]), valz[i, :]),
                (-1, ), 'F')
            basis_ref_grad[i, :, 2] = np.reshape(
                np.outer(np.outer(valx[i, :], valy[i, :]), gradz[i, :, 0]),
                (-1, ), 'F')
Exemple #6
0
	def __init__(self, ndims=1, num_nodes=1, num_elems=1, gbasis=None,
			gorder=1):
		if gbasis is None:
			gbasis = basis_defs.LagrangeSeg(1)

		self.ndims = ndims
		self.num_nodes = num_nodes
		self.node_coords = None
		self.num_interior_faces = 0
		self.interior_faces = []
		self.num_boundary_groups = 0
		self.boundary_groups = {}
		self.gbasis = gbasis
		self.gorder = gorder
		self.num_elems = num_elems
		self.num_nodes_per_elem = gbasis.get_num_basis_coeff(gorder)
		self.elem_to_node_IDs = np.zeros(0, dtype=int)
		self.elements = []
Exemple #7
0
def create_gmsh_element_database():
    '''
	This function creates a database that holds information about all
	supported Gmsh elements.

	Outputs:
	--------
		gmsh_element_database: Gmsh element database
	'''
    gmsh_element_database = {}
    '''
	Assume most element types are not supported
	Only fill in supported elements
	'''

    # Point
    etype_num = 15
    elem_data = GmshElementData()
    gmsh_element_database.update({etype_num: elem_data})
    elem_data.gorder = 0
    elem_data.gbasis = basis_defs.PointShape()  # shape here instead of gbasis
    elem_data.num_nodes = 1
    elem_data.node_order = np.array([0])

    # Line segments (q = 1 to q = 11)
    etype_nums = np.array([1, 8, 26, 27, 28, 62, 63, 64, 65, 66])
    for i in range(etype_nums.shape[0]):
        etype_num = etype_nums[i]
        elem_data = GmshElementData()
        gmsh_element_database.update({etype_num: elem_data})
        gorder = i + 1
        elem_data.gorder = gorder
        elem_data.gbasis = basis_defs.LagrangeSeg(gorder)
        elem_data.num_nodes = gorder + 1
        elem_data.node_order = gmsh_node_order_seg(gorder)

    # Triangles (q = 1 to q = 10)
    etype_nums = np.array([2, 9, 21, 23, 25, 42, 43, 44, 45, 46])
    for i in range(etype_nums.shape[0]):
        etype_num = etype_nums[i]
        elem_data = GmshElementData()
        gmsh_element_database.update({etype_num: elem_data})
        gorder = i + 1
        elem_data.gorder = gorder
        elem_data.gbasis = basis_defs.LagrangeTri(gorder)
        elem_data.num_nodes = (gorder + 1) * (gorder + 2) // 2
        elem_data.node_order = gmsh_node_order_tri(gorder)

    # Quadrilaterals (q = 1 to q = 11)
    etype_nums = np.array([3, 10, 36, 37, 38, 47, 48, 49, 50, 51])
    for i in range(etype_nums.shape[0]):
        etype_num = etype_nums[i]
        elem_data = GmshElementData()
        gmsh_element_database.update({etype_num: elem_data})
        gorder = i + 1
        elem_data.gorder = gorder
        elem_data.gbasis = basis_defs.LagrangeQuad(gorder)
        elem_data.num_nodes = (gorder + 1)**2
        elem_data.node_order = gmsh_node_order_quadril(gorder)

    return gmsh_element_database
Exemple #8
0
def mesh_1D(num_elems=10, xmin=-1., xmax=1.):
    '''
	This function creates a 1D uniform mesh.

	Inputs:
	-------
		num_elems: number of mesh elements
		xmin: minimum x-coordinate
		xmax: maximum x-coordinate

	Outputs:
	--------
		mesh: mesh object

	Notes:
	------
		Two boundary groups are created:
		x1: located at x = xmin
		x2: located at x = xmax
	'''
    ''' Create mesh and set node coordinates '''
    num_nodes = num_elems + 1
    mesh = mesh_defs.Mesh(ndims=1, num_nodes=num_nodes)
    mesh.node_coords = np.zeros([mesh.num_nodes, mesh.ndims])
    mesh.node_coords[:, 0] = np.linspace(xmin, xmax, mesh.num_nodes)
    # Set parameters
    mesh.set_params(gbasis=basis_defs.LagrangeSeg(1),
                    gorder=1,
                    num_elems=num_elems)
    ''' Interior faces '''
    mesh.num_interior_faces = num_elems - 1
    mesh.allocate_interior_faces()
    for i in range(mesh.num_interior_faces):
        interior_face = mesh.interior_faces[i]
        interior_face.elemL_ID = i
        interior_face.faceL_ID = 1
        interior_face.elemR_ID = i + 1
        interior_face.faceR_ID = 0
    ''' Boundary groups and faces '''
    # Left
    boundary_group = mesh.add_boundary_group("x1")
    boundary_group.num_boundary_faces = 1
    boundary_group.allocate_boundary_faces()
    boundary_face = boundary_group.boundary_faces[0]
    boundary_face.elem_ID = 0
    boundary_face.face_ID = 0
    # Right
    boundary_group = mesh.add_boundary_group("x2")
    boundary_group.num_boundary_faces = 1
    boundary_group.allocate_boundary_faces()
    boundary_face = boundary_group.boundary_faces[0]
    boundary_face.elem_ID = num_elems - 1
    boundary_face.face_ID = 1
    ''' Create element-to-node-ID map '''
    mesh.allocate_elem_to_node_IDs_map()
    for elem_ID in range(mesh.num_elems):
        for n in range(mesh.num_nodes_per_elem):
            mesh.elem_to_node_IDs[elem_ID][n] = elem_ID + n
    ''' Create element objects '''
    mesh.create_elements()

    return mesh
import numerics.basis.tools as basis_tools

import processing.plot as plot
'''
Parameters
'''
p = 4  # polynomial order
plot_all = True  # if True, will plot all basis functions
b = 0  # the (b+1)th basis function will be plotted if plot_all is False

# Node type (matters for nodal basis only)
node_type = "Equidistant"
# node_type = "GaussLobatto"

# Basis type
basis = basis_defs.LagrangeSeg(p)  # Lagranage basis
# basis = basis_defs.LegendreSeg(p) # Legendre basis
'''
Pre-processing
'''
# Solution nodes
basis.get_1d_nodes = basis_tools.set_1D_node_calc(node_type)
# Sample points
p_plot = 100  # (p_plot + 1) points
xp = basis.equidistant_nodes(p_plot)
'''
Evaluate
'''
basis.get_basis_val_grads(xp, get_val=True)
'''
Plot