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_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_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_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 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_ldg_matrix_irk(): p_func = convection_hyper_diffusion.HyperDiffusion.periodic_exact_solution problem = p_func(x_functions.Sine(offset=2.0), diffusion_constant=1.0) t_initial = 0.0 t_final = 0.1 bc = boundary.Periodic() exact_solution = lambda x: problem.exact_solution(x, t_final) 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 = [] # constant matrix n = 20 for num_elems in [n, 2 * n]: mesh_ = mesh.Mesh1DUniform(0.0, 1.0, num_elems) delta_t = mesh_.delta_x / 5 dg_solution = basis_.project(problem.initial_condition, mesh_) # constant matrix time doesn't matter tuple_ = problem.ldg_matrix(dg_solution, t_initial, bc, bc, bc, bc) matrix = tuple_[0] vector = tuple_[1] rhs_function = problem.get_implicit_operator(bc, bc, bc, bc) solve_function = time_stepping.get_solve_function_constant_matrix( matrix, vector) new_solution = time_stepping.time_step_loop_implicit( dg_solution, t_initial, t_final, delta_t, irk, rhs_function, solve_function, ) dg_error = math_utils.compute_dg_error(new_solution, exact_solution) error = dg_error.norm() error_list.append(error) # plot.plot_dg_1d(new_solution, function=exact_solution) # plot.plot(dg_error) order = utils.convergence_order(error_list) # if not already at machine error if error_list[0] > 1e-10 and error_list[1] > 1e-10: assert order >= num_basis_cpts
def test_diffusion_ldg_polynomials_exact(): # LDG Diffusion should be exactly second derivative of polynomials in the interior bc = boundary.Extrapolation() t = 0.0 # x^i should be exact for i+1 or more basis_cpts for i in range(2, 5): diffusion.initial_condition = x_functions.Polynomial(degree=i) exact_solution = diffusion.exact_time_derivative( diffusion.initial_condition, t) for num_basis_cpts in range(i + 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(diffusion.initial_condition, mesh_) L = diffusion.ldg_operator(dg_solution, t, bc, bc) dg_error = math_utils.compute_dg_error(L, exact_solution) error = dg_error.norm(slice(1, -1)) # plot.plot_dg_1d(dg_error, elem_slice=slice(1, -1)) assert error < tolerance
def test_diffusion_ldg_polynomials_convergence(): # LDG Diffusion should converge at 1st order for 1 basis_cpt # or at num_basis_cpts - 2 for more basis_cpts bc = boundary.Extrapolation() t = 0.0 for nonlinear_diffusion in test_problems: d = nonlinear_diffusion.diffusion_function.degree # having problems at i >= d with convergence rate # still small error just not converging properly # exact solution is grows rapidly as x increases in this situation # error must larger at x = 1 then at x = 0 # could also not be in asymptotic regime for i in range(1, d): nonlinear_diffusion.initial_condition = x_functions.Polynomial( degree=i) exact_solution = nonlinear_diffusion.exact_time_derivative( nonlinear_diffusion.initial_condition, t) for num_basis_cpts in [1] + list(range(3, i + 1)): for basis_class in basis.BASIS_LIST: error_list = [] basis_ = basis_class(num_basis_cpts) for num_elems in [30, 60]: mesh_ = mesh.Mesh1DUniform(0.0, 1.0, num_elems) dg_solution = basis_.project( nonlinear_diffusion.initial_condition, mesh_) L = nonlinear_diffusion.ldg_operator( dg_solution, t, bc, bc) dg_error = math_utils.compute_dg_error( L, exact_solution) error = dg_error.norm(slice(1, -1)) 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 - 2
def test_ldg_polynomials_exact(): # LDG HyperDiffusion should be exact for polynomials in the interior bc = boundary.Extrapolation() t = 0.0 # x^i should be exact for i+1 or more basis_cpts # needs lot more basis components if f(q, x, t) = q^2 for nonlinear_hyper_diffusion in [hyper_diffusion_identity]: for i in range(3, 5): nonlinear_hyper_diffusion.initial_condition = x_functions.Polynomial( degree=i) exact_solution = nonlinear_hyper_diffusion.exact_time_derivative( nonlinear_hyper_diffusion.initial_condition, t) for num_basis_cpts in range(i + 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( 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(slice(2, -2)) # plot.plot_dg_1d(L, function=exact_solution, elem_slice=slice(1, -1)) assert error < 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 # having problems at i >= 3 with convergence rate # still small error just not converging properly for i in range(3, 5): thin_film_diffusion.initial_condition = x_functions.Polynomial(degree=i) thin_film_diffusion.initial_condition.set_coeff((1.0 / i), i) exact_solution = thin_film_diffusion.exact_time_derivative( thin_film_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 [40, 80]: mesh_ = mesh.Mesh1DUniform(0.0, 1.0, num_elems) dg_solution = basis_.project( thin_film_diffusion.initial_condition, mesh_ ) L = thin_film_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 and error_list[0] > 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_xxxx + s(x, t)) exact_solution = flux_functions.AdvectingSine(offset=2.0) p_class = convection_hyper_diffusion.ConvectionHyperDiffusion diffusion_constant = 0.05 diffusion_function = flux_functions.Polynomial([diffusion_constant]) problem = p_class.manufactured_solution( exact_solution, diffusion_function=diffusion_function) t_initial = 0.0 bc = boundary.Periodic() 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) n = 20 cfl = cfl_list[num_basis_cpts - 1] t_final = cfl * (1.0 / n) / exact_solution.wavespeed exact_solution_final = lambda x: exact_solution(x, t_final) for basis_class in [basis.LegendreBasis1D]: 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, bc, bc, include_source=False) # this is a constant matrix case (matrix, vector) = problem.ldg_matrix(dg_solution, t_initial, bc, bc, 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) order = utils.convergence_order(error_list) with open("hyper_diffusion_linear_test.yml", "a") as file: dict_ = dict() subdict = dict() subdict["cfl"] = cfl subdict["n"] = n subdict["diffusion_constant"] = diffusion_constant 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) if error_list[0] > 1e-10 and error_list[1] > 1e-10: assert order >= num_basis_cpts