def test_legendre_spacetime_massmatrix(order): ''' This test compares the analytical solution of the space-time MM to the computed one. ''' basis = basis_defs.LegendreQuad(order) mesh = mesh_common.mesh_1D(num_elems=1, xmin=-1., xmax=1.) # Set quadrature basis.set_elem_quadrature_type("GaussLegendre") basis.set_face_quadrature_type("GaussLegendre") MM = basis_st_tools.get_elem_mass_matrix_ader(mesh, basis, order, -1) ''' Reference: Dumbser, M., Enaux, C., and Toro, E. JCP 2008 Vol. 227, Issue 8, Pgs: 3971 - 4001 Appendix B ''' # Multiply by 4.0 caused by reference element shift [0, 1] -> [-1, 1] if order == 1: expected = 4.0 * np.array([[1., 0., 0., 0.], [0., 1. / 3., 0., 0.], [0., 0., 1. / 3., 0], [0., 0., 0., 1. / 9.] ]) elif order == 2: expected = 4.0 * np.array([[1., 0., 0., 0., 0., 0., 0., 0., 0.], [0., 1. / 3., 0., 0., 0., 0., 0., 0., 0.], [0., 0., 1. / 5., 0., 0., 0., 0., 0., 0.], [0., 0., 0., 1. / 3., 0., 0., 0., 0., 0.], [0., 0., 0., 0., 1. / 9., 0., 0., 0., 0.], [0., 0., 0., 0., 0., 1. / 15., 0., 0., 0.], [0., 0., 0., 0., 0., 0., 1. / 5, 0., 0.], [0., 0., 0., 0., 0., 0., 0., 1. / 15., 0.], [0., 0., 0., 0., 0., 0., 0., 0., 1. / 25.]]) # Assert np.testing.assert_allclose(MM, expected, rtol, atol)
def test_mesh_1D_for_3_elements(): ''' Make sure that a 1D mesh with three elements has the correct nodes, neighbors, and faces. ''' # Create mesh mesh = mesh_common.mesh_1D(num_elems=3, xmin=0, xmax=3) # Check node coordinates np.testing.assert_allclose(mesh.node_coords, np.array([[0, 1, 2, 3]]).T, rtol, atol) # Check node IDs of elements np.testing.assert_array_equal(mesh.elem_to_node_IDs, np.array([[0, 1], [1, 2], [2, 3]])) # Check neighbors np.testing.assert_array_equal(mesh.elements[0].face_to_neighbors, np.array([-1, 1])) np.testing.assert_array_equal(mesh.elements[1].face_to_neighbors, np.array([0, 2])) np.testing.assert_array_equal(mesh.elements[2].face_to_neighbors, np.array([1, -1])) # Check faces for face_ID in range(2): assert (mesh.interior_faces[face_ID].elemL_ID == face_ID) assert (mesh.interior_faces[face_ID].elemR_ID == face_ID + 1) assert (mesh.interior_faces[face_ID].faceL_ID == 1) assert (mesh.interior_faces[face_ID].faceR_ID == 0) # Check boundaries assert (mesh.boundary_groups['x1'].boundary_faces[0].elem_ID == 0) assert (mesh.boundary_groups['x1'].boundary_faces[0].face_ID == 0) assert (mesh.boundary_groups['x2'].boundary_faces[0].elem_ID == 2) assert (mesh.boundary_groups['x2'].boundary_faces[0].face_ID == 1)
def test_legendre_spacetime_stiffnessmatrix_spacedir_phys(dt, order): ''' This test compares the analytical solution of the space-time stiffness matrix in space to the computed one. ''' basis = basis_defs.LegendreSeg(order) basis_st = basis_defs.LegendreQuad(order) mesh = mesh_common.mesh_1D(num_elems=1, xmin=0., xmax=1.) # Set quadrature basis.set_elem_quadrature_type("GaussLegendre") basis.set_face_quadrature_type("GaussLegendre") basis_st.set_elem_quadrature_type("GaussLegendre") basis_st.set_face_quadrature_type("GaussLegendre") mesh.gbasis.set_elem_quadrature_type("GaussLegendre") mesh.gbasis.set_face_quadrature_type("GaussLegendre") # Get stiffness matrix in space SMS = basis_st_tools.get_stiffness_matrix_ader(mesh, basis, basis_st, order, dt, elem_ID=0, grad_dir=0, physical_space=True) ''' Reference: Dumbser, M., Enaux, C., and Toro, E. JCP 2008 Vol. 227, Issue 8, Pgs: 3971 - 4001 Appendix B Note: We multiply by 4 here because (unlike Dumbser's paper), we multiply by the inverse jacobian to account for non-ideal meshes See the Quail documentation (Section for ADER-DG: space-time predictor step where the K matrices are defined) ''' if order == 1: expected = 4.0 * np.array([[0., 2., 0., 0.], [0., 0., 0., 0.], [0., 0., 0., 2. / 3.], [0., 0., 0., 0.]]) elif order == 2: expected = 4.0 * np.array([[0., 2., 0., 0., 0., 0., 0., 0., 0.], [0., 0., 2., 0., 0., 0., 0., 0., 0.], [0., 0., 0., 0., 0., 0., 0., 0., 0.], [0., 0., 0., 0., 2. / 3., 0., 0., 0., 0.], [0., 0., 0., 0., 0., 2. / 3., 0., 0., 0.], [0., 0., 0., 0., 0., 0., 0., 0., 0.], [0., 0., 0., 0., 0., 0., 0., 2. / 5., 0.], [0., 0., 0., 0., 0., 0., 0., 0., 2. / 5.], [0., 0., 0., 0., 0., 0., 0., 0., 0.]]) # Assert np.testing.assert_allclose(SMS.transpose(), expected, rtol, atol)
def test_legendre_spacetime_stiffnessmatrix_timedir(dt, order): ''' This test compares the analytical solution of the space-time stiffness matrix in time to the computed one. ''' basis = basis_defs.LegendreSeg(order) basis_st = basis_defs.LegendreQuad(order) mesh = mesh_common.mesh_1D(num_elems=1, xmin=-1., xmax=1.) # Set quadrature basis.set_elem_quadrature_type("GaussLegendre") basis.set_face_quadrature_type("GaussLegendre") basis_st.set_elem_quadrature_type("GaussLegendre") basis_st.set_face_quadrature_type("GaussLegendre") mesh.gbasis.set_elem_quadrature_type("GaussLegendre") mesh.gbasis.set_face_quadrature_type("GaussLegendre") # Get stiffness matrix in time SMT = basis_st_tools.get_stiffness_matrix_ader(mesh, basis, basis_st, order, dt, elem_ID=0, grad_dir=-1, physical_space=False) ''' Reference: Dumbser, M., Enaux, C., and Toro, E. JCP 2008 Vol. 227, Issue 8, Pgs: 3971 - 4001 Appendix B ''' # Multiply by 2.0 caused by reference element shift [0, 1] -> [-1, 1] if order == 1: expected = 2.0 * np.array([[0., 0., 0., 0.], [0., 0., 0., 0.], [2., 0., 0., 0.], [0., 2. / 3., 0., 0.]]) elif order == 2: expected = 2.0 * np.array([[0., 0., 0., 0., 0., 0., 0., 0., 0.], [0., 0., 0., 0., 0., 0., 0., 0., 0.], [0., 0., 0., 0., 0., 0., 0., 0., 0.], [2., 0., 0., 0., 0., 0., 0., 0., 0.], [0., 2. / 3., 0., 0., 0., 0., 0., 0., 0.], [0., 0., 2. / 5., 0., 0., 0., 0., 0., 0.], [0., 0., 0., 2., 0., 0., 0., 0., 0.], [0., 0., 0., 0., 2. / 3., 0., 0., 0., 0.], [0., 0., 0., 0., 0., 2. / 5., 0., 0., 0.]]) # Assert np.testing.assert_allclose(SMT, expected, rtol, atol)
def test_legendre_spacetime_massmatrix(order): ''' This test makes sure that the already tested mass matrix yields the corrected inverse mass matrix with the diagonal inverted. ''' basis = basis_defs.LegendreQuad(order) mesh = mesh_common.mesh_1D(num_elems=1, xmin=-1., xmax=1.) # Set quadrature basis.set_elem_quadrature_type("GaussLegendre") basis.set_face_quadrature_type("GaussLegendre") MM = basis_st_tools.get_elem_mass_matrix_ader(mesh, basis, order, -1) iMM = basis_st_tools.get_elem_inv_mass_matrix_ader(mesh, basis, order, -1) np.testing.assert_allclose(np.diagonal(iMM), 1. / np.diagonal(MM), rtol, atol)
def test_temporal_flux_ader_tnp1(order): ''' This test compares the analytical solution of the space-time temporal flux evaluated at t^{n+1} to the computed one. ''' basis_st = basis_defs.LegendreQuad(order) mesh = mesh_common.mesh_1D(num_elems=1, xmin=-1., xmax=1.) # Set quadrature basis_st.set_elem_quadrature_type("GaussLegendre") basis_st.set_face_quadrature_type("GaussLegendre") mesh.gbasis.set_elem_quadrature_type("GaussLegendre") mesh.gbasis.set_face_quadrature_type("GaussLegendre") # Get flux matrices in time FTL = basis_st_tools.get_temporal_flux_ader(mesh, basis_st, basis_st, order, physical_space=False) ''' Reference: Dumbser, M., Enaux, C., and Toro, E. JCP 2008 Vol. 227, Issue 8, Pgs: 3971 - 4001 Appendix B ''' # Multiply by 2.0 caused by reference element shift [0, 1] -> [-1, 1] if order == 1: expected = 2.0 * np.array([[1., 0., 1., 0.], [ 0., 1. / 3., 0., 1. / 3. ], [1., 0., 1., 0], [0., 1. / 3., 0., 1. / 3.]]) elif order == 2: expected = 2.0 * np.array( [[1., 0., 0., 1., 0., 0., 1., 0., 0.], [0., 1. / 3., 0., 0., 1. / 3., 0., 0., 1. / 3., 0.], [0., 0., 1. / 5., 0., 0., 1. / 5., 0., 0., 1. / 5.], [1., 0., 0., 1., 0., 0., 1., 0., 0.], [0., 1. / 3., 0., 0., 1. / 3., 0., 0., 1. / 3., 0.], [0., 0., 1. / 5., 0., 0., 1. / 5., 0., 0., 1. / 5.], [1., 0., 0., 1., 0., 0., 1., 0., 0.], [0., 1. / 3., 0., 0., 1. / 3., 0., 0., 1. / 3., 0.], [0., 0., 1. / 5., 0., 0., 1. / 5., 0., 0., 1. / 5.]]) # Assert np.testing.assert_allclose(FTL, expected, rtol, atol)
def test_legendre_massmatrix_should_be_diagonal(basis, order): ''' This test ensures that the mass matrix for a Legendre basis is diagonal Inputs: ------- modal_basis: Pytest fixture containing the basis object to be tested order: polynomial order of Legendre basis being tested ''' if basis.NDIMS == 1: mesh = mesh_common.mesh_1D(num_elems=1, xmin=-1., xmax=1.) # Set quadrature basis.set_elem_quadrature_type("GaussLegendre") basis.set_face_quadrature_type("GaussLegendre") mesh.gbasis.set_elem_quadrature_type("GaussLegendre") mesh.gbasis.set_face_quadrature_type("GaussLegendre") iMM = basis_tools.get_elem_inv_mass_matrix(mesh, basis, order, -1) should_be_zero = np.count_nonzero( np.abs(iMM - np.diag(np.diagonal(iMM))) > 10. * atol) elif basis.NDIMS == 2: mesh = mesh_common.mesh_2D(num_elems_x=1, num_elems_y=1, xmin=-1., xmax=1., ymin=-1., ymax=1.) # Set quadrature basis.set_elem_quadrature_type("GaussLegendre") basis.set_face_quadrature_type("GaussLegendre") mesh.gbasis.set_elem_quadrature_type("GaussLegendre") mesh.gbasis.set_face_quadrature_type("GaussLegendre") iMM = basis_tools.get_elem_inv_mass_matrix(mesh, basis, order, -1) should_be_zero = np.count_nonzero( np.abs(iMM - np.diag(np.diagonal(iMM))) > 1e-12) np.testing.assert_allclose(should_be_zero, 0, 0, 0)
def test_lagrange_massmatrix_should_be_symmetric(basis, order): ''' This test ensures that the mass matrix for a Lagrange basis is symmetric Inputs: ------- modal_basis: Pytest fixture containing the basis object to be tested order: polynomial order of Legendre basis being tested ''' if basis.NDIMS == 1: mesh = mesh_common.mesh_1D(num_elems=1, xmin=-1., xmax=1.) # Set quadrature basis.set_elem_quadrature_type("GaussLegendre") basis.set_face_quadrature_type("GaussLegendre") mesh.gbasis.set_elem_quadrature_type("GaussLegendre") mesh.gbasis.set_face_quadrature_type("GaussLegendre") iMM = basis_tools.get_elem_inv_mass_matrix(mesh, basis, order, -1) iMM_T = np.transpose(iMM) elif basis.NDIMS == 2: mesh = mesh_common.mesh_2D(num_elems_x=1, num_elems_y=1, xmin=-1., xmax=1., ymin=-1., ymax=1.) # Set quadrature basis.set_elem_quadrature_type("GaussLegendre") basis.set_face_quadrature_type("GaussLegendre") mesh.gbasis.set_elem_quadrature_type("GaussLegendre") mesh.gbasis.set_face_quadrature_type("GaussLegendre") iMM = basis_tools.get_elem_inv_mass_matrix(mesh, basis, order, -1) iMM_T = np.transpose(iMM) should_be_one = np.abs(iMM - iMM_T) + 1.0 expected = np.ones_like(iMM) np.testing.assert_allclose(should_be_one, expected, 1e-12, 1e-12)
def create_solver_object(): ''' This function creates a solver object that stores the timestepper and its members ''' mesh = mesh_common.mesh_1D(num_elems=1, xmin=0., xmax=1.) params = general.set_solver_params(SolutionOrder=1, FinalTime=10.0, NumTimeSteps=1000, ApplyLimiters=[]) physics = scalar.ConstAdvScalar1D() physics.set_conv_num_flux("LaxFriedrichs") physics.set_physical_params() U = np.array([1.]) physics.set_IC(IC_type="Uniform", state=U) solver = DG.DG(params, physics, mesh) return solver
def create_solver_object(): ''' This function creates a solver object that stores the positivity- preserving limiter object needed for the tests here. ''' mesh = mesh_common.mesh_1D(num_elems=1, xmin=0., xmax=1.) mesh_tools.make_periodic_translational(mesh, x1="x1", x2="x2") params = general.set_solver_params(SolutionOrder=1, SolutionBasis="LagrangeSeg", ApplyLimiters=["PositivityPreserving"]) physics = euler.Euler1D() physics.set_conv_num_flux("Roe") physics.set_physical_params() U = np.array([1., 0., 1.]) physics.set_IC(IC_type="Uniform", state=U) solver = DG.DG(params, physics, mesh) return solver
def test_legendre_spacetime_massmatrix_phys(order): ''' This test compares the analytical solution of the space-time MM to the computed one, but uses a physics element that spans [0.0, 0.5] ''' basis = basis_defs.LegendreQuad(order) mesh = mesh_common.mesh_1D(num_elems=1, xmin=0., xmax=0.5) # Set quadrature basis.set_elem_quadrature_type("GaussLegendre") basis.set_face_quadrature_type("GaussLegendre") MM = basis_st_tools.get_elem_mass_matrix_ader(mesh, basis, order, 0, physical_space=True) ''' Reference: Dumbser, M., Enaux, C., and Toro, E. JCP 2008 Vol. 227, Issue 8, Pgs: 3971 - 4001 Appendix B ''' if order == 1: expected = np.array([[1., 0., 0., 0.], [0., 1. / 3., 0., 0.], [0., 0., 1. / 3., 0], [0., 0., 0., 1. / 9.]]) elif order == 2: expected = np.array([[1., 0., 0., 0., 0., 0., 0., 0., 0.], [0., 1. / 3., 0., 0., 0., 0., 0., 0., 0.], [0., 0., 1. / 5., 0., 0., 0., 0., 0., 0.], [0., 0., 0., 1. / 3., 0., 0., 0., 0., 0.], [0., 0., 0., 0., 1. / 9., 0., 0., 0., 0.], [0., 0., 0., 0., 0., 1. / 15., 0., 0., 0.], [0., 0., 0., 0., 0., 0., 1. / 5, 0., 0.], [0., 0., 0., 0., 0., 0., 0., 1. / 15., 0.], [0., 0., 0., 0., 0., 0., 0., 0., 1. / 25.]]) # Assert np.testing.assert_allclose(MM, expected, rtol, atol)
params["NodeType"] = "GaussLobatto" params["ColocatedPoints"] = True ''' # Polynomial orders orders = range(1, 8) # Number of wavenumbers nL = 501 # 0 for upwind flux, 1 for central flux alpha = 0. ''' Pre-processing ''' norders = len(orders) # Mesh mesh = mesh_common.mesh_1D(num_elems=1, xmin=0., xmax=1.) elem = mesh.elements[0] h = elem.node_coords[1, 0] - elem.node_coords[0, 0] ''' Compute ''' Omega_r_phys_all = np.zeros([nL - 2, norders]) Omega_i_phys_all = np.zeros_like(Omega_r_phys_all) nb_all = np.zeros(norders) for i in range(norders): order = orders[i] Omega_r_phys_all[:,i], Omega_i_phys_all[:,i], nb_all[i], Lplot = \ get_physical_modes(mesh, params, order, nL) ''' Plot '''