def test_linearized_mms_ldg_matrix_independence_from_dg_solution(): g = x_functions.Sine(offset=2.0) r = -4.0 * np.power(np.pi, 2) exact_solution = flux_functions.ExponentialFunction(g, r) t_initial = 0.0 bc = boundary.Periodic() p_class = convection_hyper_diffusion.NonlinearHyperDiffusion p_func = p_class.linearized_manufactured_solution for diffusion_function in diffusion_functions: problem = p_func(exact_solution, diffusion_function) for basis_class in basis.BASIS_LIST: for num_basis_cpts in range(1, 4): basis_ = basis_class(num_basis_cpts) mesh_ = mesh.Mesh1DUniform(0.0, 1.0, 20) sine_dg = basis_.project(x_functions.Sine(offset=2.0), mesh_) cosine_dg = basis_.project(x_functions.Cosine(offset=2.0), mesh_) tuple_ = problem.ldg_matrix(sine_dg, t_initial, bc, bc, bc, bc) sine_matrix = tuple_[0] sine_vector = tuple_[1] tuple_ = problem.ldg_matrix(cosine_dg, t_initial, bc, bc, bc, bc) cosine_matrix = tuple_[0] cosine_vector = tuple_[1] assert np.linalg.norm(sine_matrix - cosine_matrix) <= tolerance assert np.linalg.norm(sine_vector - cosine_vector) <= tolerance
def test_ldg_polynomials_convergence(): # LDG Diffusion should converge at 1st order for 1 basis_cpt # or at num_basis_cpts - 4 for more basis_cpts bc = boundary.Extrapolation() t = 0.0 for i in range(4, 7): hyper_diffusion.initial_condition = x_functions.Polynomial(degree=i) exact_solution = hyper_diffusion.exact_time_derivative( hyper_diffusion.initial_condition, t) for num_basis_cpts in [1] + list(range(5, i + 1)): for basis_class in basis.BASIS_LIST: error_list = [] basis_ = basis_class(num_basis_cpts) for num_elems in [10, 20]: mesh_ = mesh.Mesh1DUniform(0.0, 1.0, num_elems) dg_solution = basis_.project( hyper_diffusion.initial_condition, mesh_) L = hyper_diffusion.ldg_operator(dg_solution, t, bc, bc, bc, bc) dg_error = math_utils.compute_dg_error(L, exact_solution) error = dg_error.norm(slice(2, -2)) error_list.append(error) # plot.plot_dg_1d(L, function=exact_solution, elem_slice=slice(1, -1)) order = utils.convergence_order(error_list) # if already at machine precision don't check convergence if error_list[-1] > tolerance: if num_basis_cpts == 1: assert order >= 1 else: assert order >= num_basis_cpts - 4
def test_matrix_operator_equivalency(): t = 0.0 for bc in [boundary.Periodic(), boundary.Extrapolation()]: for nonlinear_hyper_diffusion in test_problems: nonlinear_hyper_diffusion.initial_condition = x_functions.Sine( offset=2.0) for num_basis_cpts in range(1, 6): for basis_class in basis.BASIS_LIST: basis_ = basis_class(num_basis_cpts) mesh_ = mesh.Mesh1DUniform(0.0, 1.0, 20) dg_solution = basis_.project( nonlinear_hyper_diffusion.initial_condition, mesh_) L = nonlinear_hyper_diffusion.ldg_operator( dg_solution, t, bc, bc, bc, bc) dg_vector = dg_solution.to_vector() tuple_ = nonlinear_hyper_diffusion.ldg_matrix( dg_solution, t, bc, bc, bc, bc) matrix = tuple_[0] vector = tuple_[1] dg_error_vector = (L.to_vector() - np.matmul(matrix, dg_vector) - vector) dg_error = solution.DGSolution(dg_error_vector, basis_, mesh_) error = dg_error.norm() / L.norm() # plot.plot_dg_1d(dg_error) assert error <= tolerance
def test_evaluate_weak_form(): periodic_bc = boundary.Periodic() t = 0.0 for problem in test_problems: exact_time_derivative = problem.exact_time_derivative initial_time_derivative = x_functions.FrozenT(exact_time_derivative, 0.0) riemann_solver = riemann_solvers.LocalLaxFriedrichs(problem) for basis_class in basis.BASIS_LIST: for num_basis_cpts in range(1, 4): error_list = [] basis_ = basis_class(num_basis_cpts) for num_elems in [20, 40]: mesh_ = mesh.Mesh1DUniform(0.0, 1.0, num_elems) dg_solution = basis_.project(initial_condition, mesh_) result = dg_utils.evaluate_weak_form( dg_solution, t, problem.app_.flux_function, riemann_solver, periodic_bc, problem.app_.nonconservative_function, problem.app_.regularization_path, problem.app_.source_function) error = math_utils.compute_error(result, initial_time_derivative) error_list.append(error) order = utils.convergence_order(error_list) if num_basis_cpts == 1: assert order >= 1 else: assert order >= num_basis_cpts - 1
def test_ldg_cos(): # LDG Diffusion should converge at 1st order for 1 basis_cpt # or at num_basis_cpts - 4 for more basis_cpts t = 0.0 bc = boundary.Periodic() for nonlinear_hyper_diffusion in [hyper_diffusion_identity]: nonlinear_hyper_diffusion.initial_condition = x_functions.Cosine( offset=2.0) exact_solution = nonlinear_hyper_diffusion.exact_time_derivative( nonlinear_hyper_diffusion.initial_condition, t) for num_basis_cpts in [1] + list(range(5, 6)): for basis_class in basis.BASIS_LIST: error_list = [] basis_ = basis_class(num_basis_cpts) for num_elems in [10, 20]: mesh_ = mesh.Mesh1DUniform(0.0, 1.0, num_elems) dg_solution = basis_.project( nonlinear_hyper_diffusion.initial_condition, mesh_) L = nonlinear_hyper_diffusion.ldg_operator( dg_solution, t, bc, bc, bc, bc) dg_error = math_utils.compute_dg_error(L, exact_solution) error = dg_error.norm() error_list.append(error) # plot.plot_dg_1d(L, function=exact_solution) order = utils.convergence_order(error_list) # if already at machine precision don't check convergence if error_list[-1] > tolerance: if num_basis_cpts == 1: assert order >= 1 else: assert order >= num_basis_cpts - 4
def test_linearized_mms_ldg_convergence(): # LDG Diffusion should converge at 1st order for 1 basis_cpt # or at num_basis_cpts - 2 for more basis_cpts t = 0.0 bc = boundary.Periodic() p_class = convection_hyper_diffusion.NonlinearHyperDiffusion p_func = p_class.linearized_manufactured_solution exact_solution = flux_functions.AdvectingSine(offset=2.0) for diffusion_function in diffusion_functions: problem = p_func(exact_solution, diffusion_function) exact_time_derivative = problem.exact_time_derivative( exact_solution, t) for num_basis_cpts in [1] + list(range(5, 6)): for basis_class in basis.BASIS_LIST: error_list = [] basis_ = basis_class(num_basis_cpts) # 10 and 20 elems maybe not in asymptotic regime yet for num_elems in [20, 40]: mesh_ = mesh.Mesh1DUniform(0.0, 1.0, num_elems) dg_solution = basis_.project(exact_solution, mesh_, t) L = problem.ldg_operator(dg_solution, t, bc, bc) dg_error = math_utils.compute_dg_error( L, exact_time_derivative) error = dg_error.norm() error_list.append(error) # plot.plot_dg_1d(L, function=exact_time_derivative) order = utils.convergence_order(error_list) # if already at machine precision don't check convergence if error_list[-1] > tolerance: if num_basis_cpts == 1: assert order >= 1 else: assert order >= num_basis_cpts - 4
def test_imex_linear_diffusion(): # advection with linear diffusion # (q_t + q_x = q_xx + s(x, t)) exact_solution = xt_functions.AdvectingSine(offset=2.0) problem = convection_diffusion.ConvectionDiffusion.manufactured_solution( exact_solution) t_initial = 0.0 bc = boundary.Periodic() error_dict = dict() cfl_list = [0.9, 0.3, 0.1] for num_basis_cpts in range(1, 4): imex = imex_runge_kutta.get_time_stepper(num_basis_cpts) cfl = cfl_list[num_basis_cpts - 1] # take 10 timesteps at coarsest time interval n = 20 t_final = cfl * (1.0 / n) / exact_solution.wavespeed exact_solution_final = lambda x: exact_solution(x, t_final) for basis_class in basis.BASIS_LIST: basis_ = basis_class(num_basis_cpts) error_list = [] for num_elems in [n, 2 * n]: mesh_ = mesh.Mesh1DUniform(0.0, 1.0, num_elems) delta_t = cfl * mesh_.delta_x / exact_solution.wavespeed dg_solution = basis_.project(problem.initial_condition, mesh_) # weak dg form with flux_function and source term explicit_operator = problem.get_explicit_operator(bc) # ldg discretization of diffusion_function implicit_operator = problem.get_implicit_operator( bc, bc, include_source=False) # this is a constant matrix case (matrix, vector) = problem.ldg_matrix(dg_solution, t_initial, bc, bc, include_source=False) solve_operator = time_stepping.get_solve_function_constant_matrix( matrix, vector) final_solution = time_stepping.time_step_loop_imex( dg_solution, t_initial, t_final, delta_t, imex, explicit_operator, implicit_operator, solve_operator, ) dg_error = math_utils.compute_dg_error(final_solution, exact_solution_final) error = dg_error.norm() error_list.append(error) # plot.plot_dg_1d(final_solution, function=exact_solution_final) # plot.plot_dg_1d(dg_error) error_dict[num_basis_cpts] = error_list order = utils.convergence_order(error_list) assert order >= num_basis_cpts
def check_solution_operations_1d(basis_, tol2=tolerance): mesh_ = mesh.Mesh1DUniform(-1.0, 1.0, 100) # checking not inplace operations also checks inplace operations # as not inplace operators refer to inplace operations cos = x_functions.Cosine() sin = x_functions.Sine() cos_sol = basis_.project(cos, mesh_) sin_sol = basis_.project(sin, mesh_) # addition def func(x): return cos(x) + sin(x) new_sol = basis_.do_solution_operation(cos_sol, sin_sol, operator.iadd) projected_sol = basis_.project(func, mesh_) error = np.linalg.norm(new_sol.coeffs - projected_sol.coeffs) assert error <= tolerance # subtraction def func(x): return cos(x) - sin(x) new_sol = basis_.do_solution_operation(cos_sol, sin_sol, operator.isub) projected_sol = basis_.project(func, mesh_) error = np.linalg.norm(new_sol.coeffs - projected_sol.coeffs) assert error <= tolerance # multiplication, division, and power won't be exact for modal bases # multiplication def func(x): return cos(x) * sin(x) new_sol = basis_.do_solution_operation(cos_sol, sin_sol, operator.imul) projected_sol = basis_.project(func, mesh_) error = np.linalg.norm(new_sol.coeffs - projected_sol.coeffs) assert error <= tol2 # division def func(x): return cos(x) / (sin(x) + 2) sin_p2_sol = basis_.do_constant_operation(sin_sol, 2, operator.iadd) new_sol = basis_.do_solution_operation(cos_sol, sin_p2_sol, operator.itruediv) projected_sol = basis_.project(func, mesh_) error = np.linalg.norm(new_sol.coeffs - projected_sol.coeffs) assert error <= tol2 # power def func(x): return (cos(x) + 2)**(sin(x) + 2) cos_p2_sol = basis_.do_constant_operation(cos_sol, 2, operator.iadd) new_sol = basis_.do_solution_operation(cos_p2_sol, sin_p2_sol, operator.ipow) projected_sol = basis_.project(func, mesh_) error = np.linalg.norm(new_sol.coeffs - projected_sol.coeffs) assert error <= tol2
def test_mesh1d_get_left_right_elems(): mesh1d_uniform = mesh.Mesh1DUniform(0.0, 1.0, 10) for elem_index in range(mesh1d_uniform.num_elems): assert mesh1d_uniform.get_left_elem_index(elem_index) == elem_index - 1 if elem_index < mesh1d_uniform.num_elems - 1: assert mesh1d_uniform.get_right_elem_index( elem_index) == elem_index + 1 else: assert mesh1d_uniform.get_right_elem_index(elem_index) == -1
def test_compute_dg_error(): f = lambda x: np.cos(x) for basis_class in basis.BASIS_LIST: for num_basis_cpts in range(1, 3): basis_ = basis_class(num_basis_cpts) mesh_ = mesh.Mesh1DUniform(0.0, 1.0, 10) dg_solution = basis_.project(f, mesh_) dg_error = math_utils.compute_dg_error(dg_solution, f) print(dg_error)
def test_diffusion_ldg_constant(): # LDG of one should be zero diffusion.initial_condition = x_functions.Polynomial(degree=0) t = 0.0 bc = boundary.Periodic() for num_basis_cpts in range(1, 5): for basis_class in basis.BASIS_LIST: basis_ = basis_class(num_basis_cpts) mesh_ = mesh.Mesh1DUniform(0.0, 1.0, 10) dg_solution = basis_.project(diffusion.initial_condition, mesh_) L = diffusion.ldg_operator(dg_solution, t, bc, bc) assert L.norm() <= tolerance
def test_legendre_limit_higher_moments_1d(): num_elems = 10 ic = x_functions.Sine() limiting_constants = np.random.random_sample(num_elems) legendre_basis = basis.LegendreBasis1D(3) mesh_ = mesh.Mesh1DUniform(0, 1, num_elems) dg_solution = legendre_basis.project(ic, mesh_) initial_total_integral = dg_solution.total_integral() limited_solution = legendre_basis.limit_higher_moments( dg_solution, limiting_constants) final_total_integral = limited_solution.total_integral() assert initial_total_integral == final_total_integral
def test_derivative_dirichlet(): f = lambda q: 0.0 derivative_dirichlet = ldg_utils.DerivativeDirichlet(f, 1.0) initial_condition = lambda x: np.cos(2.0 * np.pi * x) initial_condition_integral = lambda x: np.zeros(x.shape) for basis_class in basis.BASIS_LIST: for num_basis_cpts in range(1, 4): basis_ = basis_class(num_basis_cpts) mesh_ = mesh.Mesh1DUniform(0.0, 1.0, 20) dg_solution = basis_.project(initial_condition, mesh_) integral_dg_solution = basis_.project(initial_condition_integral, mesh_) dg_solution.integral = integral_dg_solution.coeffs for i in mesh_.boundary_faces: boundary_flux = derivative_dirichlet.evaluate_boundary( dg_solution, i, None) # should be same as interior value # as integral satisfies boundary conditions interior_value = dg_solution(mesh_.vertices[mesh_.faces[i]]) boundary_forcing = np.abs(boundary_flux - interior_value) assert boundary_forcing <= tolerance initial_condition = lambda x: np.cos(2.0 * np.pi * x) initial_condition_integral = lambda x: np.ones(x.shape) for basis_class in basis.BASIS_LIST: for num_basis_cpts in range(1, 4): basis_ = basis_class(num_basis_cpts) mesh_ = mesh.Mesh1DUniform(0.0, 1.0, 20) dg_solution = basis_.project(initial_condition, mesh_) integral_dg_solution = basis_.project(initial_condition_integral, mesh_) dg_solution.integral = integral_dg_solution.coeffs for i in mesh_.boundary_faces: boundary_flux = derivative_dirichlet.evaluate_boundary( dg_solution, i, None) # should be differenct from interior value # as integral does not satisfies boundary conditions interior_value = dg_solution(mesh_.vertices[mesh_.faces[i]]) boundary_forcing = np.abs(boundary_flux - interior_value) assert boundary_forcing >= tolerance
def test_compute_error(): f = lambda x: np.cos(x) for basis_class in basis.BASIS_LIST: for num_basis_cpts in range(1, 3): errorList = [] basis_ = basis_class(num_basis_cpts) for num_elems in [10, 20]: mesh_ = mesh.Mesh1DUniform(0.0, 1.0, num_elems) dg_solution = basis_.project(f, mesh_) error = math_utils.compute_error(dg_solution, f) errorList.append(error) order = utils.convergence_order(errorList) assert order >= num_basis_cpts
def test_get_faces_to_elems(): mesh1d_uniform = mesh.Mesh1DUniform(0.0, 1.0, 10) mesh2d_cartesian = mesh.Mesh2DCartesian(0.0, 1.0, 0.0, 1.0, 10, 10) mesh2d_unstructured = mesh.Mesh2DUnstructuredRectangle( 0.0, 1.0, 0.0, 1.0, 10, 10) mesh_array = [mesh1d_uniform, mesh2d_cartesian, mesh2d_unstructured] for mesh_ in mesh_array: faces_to_elems = mesh_._get_faces_to_elems(mesh_.faces, mesh_.elems, mesh_.boundary_faces) for i_face in range(mesh_.num_faces): for i_elem in faces_to_elems[i_face]: assert math_utils.isin(i_elem, mesh_.face_to_elems[i_face])
def test_get_elems_to_faces(): mesh1d_uniform = mesh.Mesh1DUniform(0.0, 1.0, 10) mesh2d_cartesian = mesh.Mesh2DCartesian(0.0, 1.0, 0.0, 1.0, 10, 10) mesh2d_unstructured = mesh.Mesh2DUnstructuredRectangle( 0.0, 1.0, 0.0, 1.0, 10, 10) mesh_array = [mesh1d_uniform, mesh2d_cartesian, mesh2d_unstructured] for mesh_ in mesh_array: elems_to_faces = mesh_._get_elems_to_faces(mesh_.faces, mesh_.elems, mesh_.num_faces_per_elem) for i_elem in range(mesh_.num_elems): for i_face in elems_to_faces[i_elem]: assert math_utils.isin(i_face, mesh_.elems_to_faces[i_elem])
def test_diffusion_ldg_polynomials_zero(): # LDG Diffusion of x should be zero in interior bc = boundary.Extrapolation() diffusion.initial_condition = x_functions.Polynomial(degree=1) t = 0.0 for num_basis_cpts in range(1, 5): for basis_class in basis.BASIS_LIST: basis_ = basis_class(num_basis_cpts) mesh_ = mesh.Mesh1DUniform(0.0, 1.0, 10) dg_solution = basis_.project(diffusion.initial_condition, mesh_) L = diffusion.ldg_operator(dg_solution, t, bc, bc) error = np.linalg.norm(L.coeffs[1:-1, :]) # plot.plot_dg_1d(L, elem_slice=slice(1, -1)) assert error < tolerance
def test_mesh1d_transform_to_mesh(): mesh1d_uniform = mesh.Mesh1DUniform(0.0, 1.0, 10) for i in range(mesh1d_uniform.num_elems): left_vertex_index = mesh1d_uniform.elems[i, 0] left_vertex = mesh1d_uniform.vertices[left_vertex_index] x = mesh1d_uniform.transform_to_mesh(-1.0, i) assert np.abs(x - left_vertex) <= tolerance right_vertex_index = mesh1d_uniform.elems[i, 1] right_vertex = mesh1d_uniform.vertices[right_vertex_index] x = mesh1d_uniform.transform_to_mesh(1.0, i) assert np.abs(x - right_vertex) <= tolerance elem_center = mesh1d_uniform.get_elem_center(i) x = mesh1d_uniform.transform_to_mesh(0.0, i) assert np.abs(elem_center - x) <= tolerance
def test_mesh1d_transform_to_canonical(): mesh1d_uniform = mesh.Mesh1DUniform(0.0, 1.0, 10) for i in range(mesh1d_uniform.num_elems): left_vertex_index = mesh1d_uniform.elems[i, 0] left_vertex = mesh1d_uniform.vertices[left_vertex_index] xi = mesh1d_uniform.transform_to_canonical(left_vertex, i) assert np.abs(xi + 1.0) <= tolerance right_vertex_index = mesh1d_uniform.elems[i, 1] right_vertex = mesh1d_uniform.vertices[right_vertex_index] xi = mesh1d_uniform.transform_to_canonical(right_vertex, i) assert np.abs(xi - 1.0) <= tolerance elem_center = mesh1d_uniform.get_elem_center(i) xi = mesh1d_uniform.transform_to_canonical(elem_center) assert np.abs(xi) <= tolerance
def check_constant_operations_1d(basis_): mesh_ = mesh.Mesh1DUniform(-1.0, 1.0, 10) coeffs = np.ones(basis_.space_order) dg_solution = basis_.project(x_functions.Polynomial(coeffs), mesh_) constant = 2.0 # addition new_sol = basis_.do_constant_operation(dg_solution, constant, operator.iadd) new_coeffs = coeffs.copy() new_coeffs[0] += constant projected_sol = basis_.project(x_functions.Polynomial(new_coeffs), mesh_) error = np.linalg.norm(new_sol.coeffs - projected_sol.coeffs) assert error <= tolerance # subtraction new_sol = basis_.do_constant_operation(dg_solution, constant, operator.isub) new_coeffs = coeffs.copy() new_coeffs[0] -= constant projected_sol = basis_.project(x_functions.Polynomial(new_coeffs), mesh_) error = np.linalg.norm(new_sol.coeffs - projected_sol.coeffs) assert error <= tolerance # multiplication new_sol = basis_.do_constant_operation(dg_solution, constant, operator.imul) new_coeffs = coeffs * constant projected_sol = basis_.project(x_functions.Polynomial(new_coeffs), mesh_) error = np.linalg.norm(new_sol.coeffs - projected_sol.coeffs) assert error <= tolerance # division new_sol = basis_.do_constant_operation(dg_solution, constant, operator.itruediv) new_coeffs = coeffs / constant projected_sol = basis_.project(x_functions.Polynomial(new_coeffs), mesh_) error = np.linalg.norm(new_sol.coeffs - projected_sol.coeffs) assert error <= tolerance # power - squaring deg = basis_.num_basis_cpts // 2 dg_solution = basis_.project(x_functions.Polynomial(degree=deg), mesh_) new_sol = basis_.do_constant_operation(dg_solution, 2.0, operator.ipow) new_deg = deg * 2 projected_sol = basis_.project(x_functions.Polynomial(degree=new_deg), mesh_) error = np.linalg.norm(new_sol.coeffs - projected_sol.coeffs) assert error <= tolerance
def test_compute_quadrature_matrix_one(): # quadrature_matrix should be same as M^{-1} S^T t = 0.0 f = flux_functions.Polynomial(degree=0) initial_condition = functions.Sine() for basis_class in basis.BASIS_LIST: for num_basis_cpts in range(1, 6): basis_ = basis_class(num_basis_cpts) mesh_ = mesh.Mesh1DUniform(0.0, 1.0, 10) dg_solution = basis_.project(initial_condition, mesh_) quadrature_matrix = ldg_utils.compute_quadrature_matrix( dg_solution, t, f) error = quadrature_matrix - basis_.mass_inverse_stiffness_transpose assert np.linalg.norm(error) <= tolerance
def test_linearized_mms_ldg_irk(): # g = functions.Sine(offset=2.0) # r = -1.0 # exact_solution = flux_functions.ExponentialFunction(g, r) exact_solution = flux_functions.AdvectingSine(offset=2.0) t_initial = 0.0 t_final = 0.1 exact_solution_final = lambda x: exact_solution(x, t_final) bc = boundary.Periodic() p_class = convection_hyper_diffusion.NonlinearHyperDiffusion p_func = p_class.linearized_manufactured_solution for diffusion_function in diffusion_functions: problem = p_func(exact_solution, diffusion_function) for num_basis_cpts in range(1, 3): irk = implicit_runge_kutta.get_time_stepper(num_basis_cpts) for basis_class in basis.BASIS_LIST: basis_ = basis_class(num_basis_cpts) error_list = [] for i in [1, 2]: if i == 1: delta_t = 0.01 num_elems = 20 else: delta_t = 0.005 num_elems = 40 mesh_ = mesh.Mesh1DUniform(0.0, 1.0, num_elems) dg_solution = basis_.project(problem.initial_condition, mesh_) # time_dependent_matrix time does matter matrix_function = lambda t: problem.ldg_matrix( dg_solution, t, bc, bc, bc, bc) rhs_function = problem.get_implicit_operator( bc, bc, bc, bc) solve_function = time_stepping.get_solve_function_matrix( matrix_function) new_solution = time_stepping.time_step_loop_implicit( dg_solution, t_initial, t_final, delta_t, irk, rhs_function, solve_function, ) error = math_utils.compute_error(new_solution, exact_solution_final) error_list.append(error) # plot.plot_dg_1d(new_solution, function=exact_solution_final) order = utils.convergence_order(error_list) assert order >= num_basis_cpts
def test_nonlinear_mms_ldg_irk(): exact_solution = flux_functions.AdvectingSine(amplitude=0.1, offset=0.15) t_initial = 0.0 t_final = 0.1 exact_solution_final = lambda x: exact_solution(x, t_final) bc = boundary.Periodic() p_func = thin_film.ThinFilmDiffusion.manufactured_solution problem = p_func(exact_solution) for num_basis_cpts in range(1, 3): irk = implicit_runge_kutta.get_time_stepper(num_basis_cpts) cfl = 0.5 for basis_class in basis.BASIS_LIST: basis_ = basis_class(num_basis_cpts) error_list = [] n = 40 for num_elems in [n, 2 * n]: mesh_ = mesh.Mesh1DUniform(0.0, 1.0, num_elems) delta_t = cfl * mesh_.delta_x / exact_solution.wavespeed dg_solution = basis_.project(problem.initial_condition, mesh_) # time_dependent_matrix time does matter matrix_function = lambda t, q: problem.ldg_matrix(q, t, bc, bc, bc, bc) rhs_function = problem.get_implicit_operator(bc, bc, bc, bc) solve_function = time_stepping.get_solve_function_picard( matrix_function, num_basis_cpts, num_elems * num_basis_cpts ) new_solution = time_stepping.time_step_loop_implicit( dg_solution, t_initial, t_final, delta_t, irk, rhs_function, solve_function, ) error = math_utils.compute_error(new_solution, exact_solution_final) error_list.append(error) # plot.plot_dg_1d(new_solution, function=exact_solution_final) with open("thin_film_nonlinear_irk_test.yml", "a") as file: dict_ = dict() subdict = dict() subdict["cfl"] = cfl subdict["n"] = n subdict["error0"] = float(error_list[0]) subdict["error1"] = float(error_list[1]) subdict["order"] = float(np.log2(error_list[0] / error_list[1])) dict_[num_basis_cpts] = subdict yaml.dump(dict_, file, default_flow_style=False) order = utils.convergence_order(error_list) assert order >= num_basis_cpts
def test_mesh1d_uniform(): mesh1d_uniform = mesh.Mesh1DUniform(0.0, 1.0, 10) assert mesh1d_uniform.num_elems == 10 assert mesh1d_uniform.num_vertices == 11 for i in range(mesh1d_uniform.num_elems): assert mesh1d_uniform.elem_volumes[i] == 0.1 x = np.random.rand(10) for xi in x: elem_index = mesh1d_uniform.get_elem_index(xi) elem = mesh1d_uniform.elems[elem_index] vertex_1 = mesh1d_uniform.vertices[elem[0]] vertex_2 = mesh1d_uniform.vertices[elem[1]] assert xi >= np.min([vertex_1, vertex_2]) assert xi <= np.max([vertex_1, vertex_2])
def test_ldg_operator_constant(): # LDG of one should be zero thin_film_diffusion.initial_condition = x_functions.Polynomial(degree=0) t = 0.0 for bc in [boundary.Periodic(), boundary.Extrapolation()]: for basis_class in basis.BASIS_LIST: for num_basis_cpts in range(1, 5): basis_ = basis_class(num_basis_cpts) mesh_ = mesh.Mesh1DUniform(0.0, 1.0, 10) dg_solution = basis_.project( thin_film_diffusion.initial_condition, mesh_ ) L = thin_film_diffusion.ldg_operator(dg_solution, t, bc, bc, bc, bc) # plot.plot_dg_1d(L) assert L.norm() <= tolerance
def test_ldg_constant(): # LDG of one should be zero t = 0.0 for nonlinear_hyper_diffusion in test_problems: nonlinear_hyper_diffusion.initial_condition = x_functions.Polynomial( degree=0) for bc in [boundary.Periodic(), boundary.Extrapolation()]: for num_basis_cpts in range(1, 5): for basis_class in basis.BASIS_LIST: basis_ = basis_class(num_basis_cpts) mesh_ = mesh.Mesh1DUniform(0.0, 1.0, 10) dg_solution = basis_.project( nonlinear_hyper_diffusion.initial_condition, mesh_) L = nonlinear_hyper_diffusion.ldg_operator( dg_solution, t, bc, bc, bc, bc) assert L.norm() <= tolerance
def test_neumann(): boundary_derivative_function = flux_functions.Zero() bc = boundary.Neumann(boundary_derivative_function) basis_ = basis.LegendreBasis1D(3) mesh_ = mesh.Mesh1DUniform(0.0, 1.0, 10) f = x_functions.Sine() dg_solution = basis_.project(f, mesh_) problem = smooth_scalar_example.SmoothScalarExample(1.0, f) riemann_solver = riemann_solvers.LocalLaxFriedrichs(problem) boundary_faces = mesh_.boundary_faces t = 0.0 flux = bc.evaluate_boundary(dg_solution, boundary_faces[0], riemann_solver, t) assert flux is not None
def test_ldg_constant(): # LDG discretization of 1 should be zero hyper_diffusion.initial_condition = x_functions.Polynomial(degree=0) t = 0.0 for bc in [boundary.Periodic(), boundary.Extrapolation()]: for basis_class in basis.BASIS_LIST: for num_basis_cpts in range(1, 6): basis_ = basis_class(num_basis_cpts) mesh_ = mesh.Mesh1DUniform(0.0, 1.0, 10) dg_solution = basis_.project(hyper_diffusion.initial_condition, mesh_) L = hyper_diffusion.ldg_operator(dg_solution, t, bc, bc, bc, bc) # plot.plot_dg_1d(L) error = L.norm() # quadrature_error can add up in higher basis_cpts assert error <= 1e-4
def test_ldg_operator_equal_matrix(): f = x_functions.Sine() t = 0.0 for bc in [boundary.Periodic(), boundary.Extrapolation()]: for num_basis_cpts in range(1, 6): for basis_class in basis.BASIS_LIST: basis_ = basis_class(num_basis_cpts) mesh_ = mesh.Mesh1DUniform(0.0, 1.0, 10) dg_solution = basis_.project(f, mesh_) L = diffusion.ldg_operator(dg_solution, t, bc, bc) dg_vector = dg_solution.to_vector() tuple_ = diffusion.ldg_matrix(dg_solution, t, bc, bc) matrix = tuple_[0] vector = tuple_[1] error = np.linalg.norm(L.to_vector() - np.matmul(matrix, dg_vector) - vector) assert error <= tolerance
def test_interior(): bc = boundary.Extrapolation() basis_ = basis.LegendreBasis1D(3) mesh_ = mesh.Mesh1DUniform(0.0, 1.0, 10) f = x_functions.Sine() dg_solution = basis_.project(f, mesh_) problem = smooth_scalar_example.SmoothScalarExample(1.0, f) riemann_solver = riemann_solvers.LocalLaxFriedrichs(problem) boundary_faces = mesh_.boundary_faces t = 0.0 flux = bc.evaluate_boundary(dg_solution, boundary_faces[0], riemann_solver, t) x = mesh_.get_face_position(boundary_faces[0]) assert flux == dg_solution(x)