Beispiel #1
0
    def precompute_helpers(self, solver):
        # Unpack
        ns = solver.physics.NUM_STATE_VARS
        mesh = solver.mesh
        basis = solver.basis
        elem_helpers = solver.elem_helpers
        int_face_helpers = solver.int_face_helpers

        ndims = mesh.ndims
        num_elems = mesh.num_elems
        nb = basis.nb
        nq = elem_helpers.quad_pts.shape[0]

        self.elem_vols, _ = mesh_tools.element_volumes(solver.mesh, solver)
        self.basis_phys_hessian_elems = np.zeros([num_elems, nq, nb, ndims])

        # Basis values in element interior and on faces
        if not solver.basis.skip_interp:
            basis_val_faces = int_face_helpers.faces_to_basisL.copy()
            bshape = basis_val_faces.shape
            basis_val_faces.shape = (bshape[0] * bshape[1], bshape[2])

            self.basis_val_elem_faces = np.vstack(
                (elem_helpers.basis_val, basis_val_faces))
        else:
            self.basis_val_elem_faces = elem_helpers.basis_val

        # Jacobian determinant
        self.djac_elems = elem_helpers.djac_elems

        # Element quadrature weights
        self.quad_wts_elem = elem_helpers.quad_wts

        # identify neighboring elements and store
        elemP_IDs = np.empty([num_elems], dtype=int)
        elemM_IDs = np.empty([num_elems], dtype=int)

        for elem_ID in range(num_elems):
            elemP_IDs[elem_ID] = mesh.elements[elem_ID].face_to_neighbors[1]
            elemM_IDs[elem_ID] = mesh.elements[elem_ID].face_to_neighbors[0]

        self.elemP_IDs = elemP_IDs
        self.elemM_IDs = elemM_IDs

        # Allocate the right and left eigenvectors (needed for scalar case)
        self.right_eigen = np.ones([num_elems, 1, ns, ns])
        self.left_eigen = np.ones([num_elems, 1, ns, ns])

        # Calculate hessian for higher-order weno calculation
        self.basis_ref_hessian = limiter_tools.get_hessian(
            self, basis, elem_helpers.quad_pts)
        ijac_elems = elem_helpers.ijac_elems

        for elem_ID in range(num_elems):
            self.basis_phys_hessian_elems[elem_ID] = \
              limiter_tools.get_phys_hessian(self, basis,
              ijac_elems[elem_ID])
Beispiel #2
0
def test_element_volumes_for_2x2_triangles(filled_mesh):
	'''
	Make sure that two triangles in a 2x2 square each have an area of 2.
	'''
	# Get element volumes
	vol_elems, domain_vol = mesh_tools.element_volumes(filled_mesh, solver=None)
	# These are two 2x2 triangles, so should have an area of 2, totalling to 4
	np.testing.assert_allclose(vol_elems, 2, rtol, atol)
	np.testing.assert_allclose(domain_vol, 4, rtol, atol)
Beispiel #3
0
    def precompute_helpers(self, solver):
        # Unpack
        elem_helpers = solver.elem_helpers
        int_face_helpers = solver.int_face_helpers
        self.elem_vols, _ = mesh_tools.element_volumes(solver.mesh, solver)

        # Basis values in element interior and on faces
        if not solver.basis.skip_interp:
            basis_val_faces = int_face_helpers.faces_to_basisL.copy()
            bshape = basis_val_faces.shape
            basis_val_faces.shape = (bshape[0] * bshape[1], bshape[2])
            self.basis_val_elem_faces = np.vstack(
                (elem_helpers.basis_val, basis_val_faces))
        else:
            self.basis_val_elem_faces = elem_helpers.basis_val

        # Jacobian determinant
        self.djac_elems = elem_helpers.djac_elems

        # Element quadrature weights
        self.quad_wts_elem = elem_helpers.quad_wts
Beispiel #4
0
    def get_basis_and_geom_data(self, mesh, basis, order):
        '''
		Precomputes the basis and geometric data for each element

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

		Outputs:
		--------
			self.basis_val: precomputed basis value [nq, nb]
			self.basis_ref_grad: precomputed basis gradient for the
				reference element [nq, nb, ndims]
			self.basis_phys_grad_elems: precomputed basis gradient for each
				physical element [num_elems, nq, nb, ndims]
			self.jac_elems: precomputed Jacobian for each element
				[num_elems, nq, ndims, ndims]
			self.ijac_elems: precomputed inverse Jacobian for each element
				[num_elems, nq, ndims, ndims]
			self.djac_elems: precomputed determinant of the Jacobian for each
				element [num_elems, nq, 1]
			self.x_elems: precomputed coordinates of the quadrature points
				in physical space [num_elems, nq, ndims]
		'''
        ndims = mesh.ndims
        num_elems = mesh.num_elems
        quad_pts = self.quad_pts
        nq = quad_pts.shape[0]
        nb = basis.nb

        # Allocate
        self.jac_elems = np.zeros([num_elems, nq, ndims, ndims])
        self.ijac_elems = np.zeros([num_elems, nq, ndims, ndims])
        self.djac_elems = np.zeros([num_elems, nq, 1])
        self.x_elems = np.zeros([num_elems, nq, ndims])
        self.basis_phys_grad_elems = np.zeros([num_elems, nq, nb, basis.NDIMS])
        self.normals_elems = np.empty([
            num_elems, mesh.gbasis.NFACES, self.face_quad_pts.shape[0], ndims
        ])

        # Basis data
        basis.get_basis_val_grads(self.quad_pts,
                                  get_val=True,
                                  get_ref_grad=True)

        self.basis_val = basis.basis_val
        self.basis_ref_grad = basis.basis_ref_grad

        for elem_ID in range(mesh.num_elems):
            # Jacobian
            djac, jac, ijac = basis_tools.element_jacobian(mesh,
                                                           elem_ID,
                                                           quad_pts,
                                                           get_djac=True,
                                                           get_jac=True,
                                                           get_ijac=True)
            # Store
            self.jac_elems[elem_ID] = jac
            self.ijac_elems[elem_ID] = ijac
            self.djac_elems[elem_ID] = djac

            # Physical coordinates of quadrature points
            x = mesh_tools.ref_to_phys(mesh, elem_ID, quad_pts)
            # Store
            self.x_elems[elem_ID] = x

            if self.need_phys_grad:
                # Physical gradient
                basis.get_basis_val_grads(quad_pts,
                                          get_phys_grad=True,
                                          ijac=ijac)
                self.basis_phys_grad_elems[elem_ID] = basis.basis_phys_grad
                # [nq, nb, ndims]

            # Face normals
            for i in range(mesh.gbasis.NFACES):
                self.normals_elems[elem_ID, i] = mesh.gbasis.calculate_normals(
                    mesh, elem_ID, i, self.face_quad_pts)

        # Volumes
        self.vol_elems, self.domain_vol = mesh_tools.element_volumes(mesh)
Beispiel #5
0
def get_error(mesh,
              physics,
              solver,
              var_name,
              ord=2,
              print_error=True,
              normalize_by_volume=True):
    '''
	This function computes the Lp-error, where p is the "ord" input argument.

	Inputs:
	-------
	    mesh: mesh object
	    physics: physics object
	    solver: solver object
	    var_name: name of variable to compute error of
	    ord: order of the error
	    print_error: if True, will print total error
	    normalize_by_volume: if True, will normalize the error by the
	    	volume of the domain

	Outputs:
	--------
	    tot_err: total error
	    err_elems: error over each element [num_elems]
	'''
    # Extract info
    time = solver.time
    U = solver.state_coeffs
    basis = solver.basis
    order = solver.order
    if physics.exact_soln is None:
        raise ValueError("No exact solution provided")

    # Get element volumes
    if normalize_by_volume:
        _, tot_vol = mesh_tools.element_volumes(mesh, solver)
    else:
        tot_vol = 1.

    # Allocate, initialize
    err_elems = np.zeros([mesh.num_elems])
    tot_err = 0.

    # Get quadrature data
    quad_order = basis.get_quadrature_order(mesh,
                                            2 * np.amax([order, 1]),
                                            physics=physics)

    gbasis = mesh.gbasis
    quad_pts, quad_wts = gbasis.get_quadrature_data(quad_order)

    # Get x for each element
    xphys = np.empty((mesh.num_elems, ) + quad_pts.shape)
    for elem_ID in range(mesh.num_elems):
        xphys[elem_ID] = mesh_tools.ref_to_phys(mesh, elem_ID, quad_pts)

    # Evaluate exact solution at quadrature points
    u_exact = physics.exact_soln.get_state(physics, x=xphys, t=time)

    # Interpolate state to quadrature points
    basis.get_basis_val_grads(quad_pts, True)
    u = helpers.evaluate_state(U, basis.basis_val)

    # Computed requested quantity
    s = physics.compute_variable(var_name, u)
    s_exact = physics.compute_variable(var_name, u_exact)

    # Loop through elements
    for elem_ID in range(mesh.num_elems):
        # Calculate element-local error
        djac, _, _ = basis_tools.element_jacobian(mesh,
                                                  elem_ID,
                                                  quad_pts,
                                                  get_djac=True)
        err = np.sum((s[elem_ID] - s_exact[elem_ID])**ord * quad_wts * djac)
        err_elems[elem_ID] = err
        tot_err += err_elems[elem_ID]

    tot_err = (tot_err / tot_vol)**(1. / ord)

    # Print if requested
    if print_error:
        print("Total error = %.15f" % (tot_err))

    return tot_err, err_elems