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_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_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_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_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 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_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_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 get_wave_propagation_rhs_function( app_, fluctuation_solver=None, boundary_condition=None ): # default to roe fluctuation_solver if fluctuation_solver is None: fluctuation_solver = fluctuation_solvers.RoeFluctuationSolver(app_) # default to periodic boundary conditions if boundary_condition is None: boundary_condition = boundary.Periodic() def rhs_function(t, q): return wave_propagation_formulation( q, t, app_, fluctuation_solver, boundary_condition ) return rhs_function
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_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_advection_finite_time(): def initial_condition(x): return np.sin(2.0 * np.pi * x) advection_ = advection.Advection(initial_condition=initial_condition) riemann_solver = riemann_solvers.LocalLaxFriedrichs( advection_.flux_function, advection_.wavespeed_function ) boundary_condition = boundary.Periodic() time_initial = 0.0 time_final = 0.5 def test_function(dg_solution): explicit_time_stepper = explicit_runge_kutta.get_time_stepper( dg_solution.basis.num_basis_cpts ) cfl = dg_utils.standard_cfls(dg_solution.basis.num_basis_cpts) delta_t = dg_utils.get_delta_t( cfl, advection_.wavespeed, dg_solution.mesh.delta_x ) rhs_function = lambda time, q: dg_utils.dg_weak_formulation( q, advection_.flux_function, riemann_solver, boundary_condition ) return time_stepping.time_step_loop_explicit( dg_solution, time_initial, time_final, delta_t, explicit_time_stepper, rhs_function, ) order_check_function = lambda order, num_basis_cpts: order >= num_basis_cpts utils.basis_convergence( test_function, initial_condition, lambda x: advection_.exact_solution(x, time_final), order_check_function, basis_list=[basis.LegendreBasis1D], basis_cpt_list=[4], )
def test_periodic(): bc = boundary.Periodic() 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_0 = bc.evaluate_boundary(dg_solution, boundary_faces[0], riemann_solver, t) flux_1 = bc.evaluate_boundary(dg_solution, boundary_faces[1], riemann_solver, t) # fluxes should be the same assert flux_0 == flux_1
def test_ldg_matrix_irk(): diffusion = convection_diffusion.Diffusion.periodic_exact_solution() t_initial = 0.0 t_final = 0.1 bc = boundary.Periodic() basis_ = basis.LegendreBasis1D(1) exact_solution = lambda x: diffusion.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 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(diffusion.initial_condition, mesh_) # constant matrix time doesn't matter tuple_ = diffusion.ldg_matrix(dg_solution, t_initial, bc, bc) matrix = tuple_[0] # vector = tuple_[1] rhs_function = diffusion.get_implicit_operator(bc, bc) solve_function = time_stepping.get_solve_function_constant_matrix( matrix) 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) error_list.append(error) order = utils.convergence_order(error_list) assert order >= num_basis_cpts
def test_ldg_operator_polynomial_zero(): # LDG of x, x^2 should be zero in interior t = 0.0 for n in range(1, 3): thin_film_diffusion.initial_condition = x_functions.Polynomial(degree=n) for bc in [boundary.Periodic(), boundary.Extrapolation()]: for basis_class in basis.BASIS_LIST: # for 1 < num_basis_cpts <= i not enough information # to compute derivatives get rounding errors for num_basis_cpts in [1] + list(range(n + 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) error = L.norm(slice(2, -2)) # plot.plot_dg_1d(L, elem_slice=slice(-2, 2)) assert error <= tolerance
def get_dg_rhs_function( flux_function, source_function=None, riemann_solver=None, boundary_condition=None, nonconservative_function=None, regularization_path=None, is_weak=True, ): # for PDE q_t + f(q, x, t)_x = s(q, x, t) # or q_t = -f(q, x, t)_x + s(q, x, t) # get DG discretization of F(t, q) = -f(q, x, t)_x + s(q, x, t) # return function F(t, q) - used in time_stepping methods if riemann_solver is None: riemann_solver = riemann_solvers.LocalLaxFriedrichs(flux_function) if boundary_condition is None: boundary_condition = boundary.Periodic() if is_weak: def rhs_function(t, q): return evaluate_weak_form( q, t, flux_function, riemann_solver, boundary_condition, nonconservative_function, regularization_path, source_function, ) else: def rhs_function(t, q): return evaluate_strong_form(q, t, flux_function, riemann_solver, boundary_condition, source_function) return rhs_function
def test_linearized_mms_operator_matrix_equivalency(): g = x_functions.Sine(offset=2.0) r = -4.0 * np.power(np.pi, 2) exact_solution = flux_functions.ExponentialFunction(g, r) t = 0.0 bc = boundary.Periodic() p_func = convection_diffusion.NonlinearDiffusion.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) dg_solution = basis_.project(problem.initial_condition, mesh_) L = problem.ldg_operator(dg_solution, t, bc, bc) tuple_ = problem.ldg_matrix(dg_solution, t, bc, bc) matrix = tuple_[0] vector = tuple_[1] dg_vector = dg_solution.to_vector() error = np.linalg.norm(L.to_vector() - np.matmul(matrix, dg_vector) - vector) assert error < tolerance
def test_advection_one_time_step(): def initial_condition(x): return np.sin(2.0 * np.pi * x) advection_ = advection.Advection(initial_condition=initial_condition) riemann_solver = riemann_solvers.LocalLaxFriedrichs( advection_.flux_function, advection_.wavespeed_function ) explicit_time_stepper = explicit_runge_kutta.ForwardEuler() boundary_condition = boundary.Periodic() cfl = 1.0 for basis_class in basis.BASIS_LIST: basis_ = basis_class(1) error_list = [] for num_elems in [20, 40]: mesh_ = mesh.Mesh1DUniform(0.0, 1.0, num_elems) dg_solution = basis_.project(advection_.initial_condition, mesh_) delta_t = dg_utils.get_delta_t(cfl, advection_.wavespeed, mesh_.delta_x) time_initial = 0.0 time_final = delta_t rhs_function = lambda time, q: dg_utils.dg_weak_formulation( q, advection_.flux_function, riemann_solver, boundary_condition ) final_solution = time_stepping.time_step_loop_explicit( dg_solution, time_initial, time_final, delta_t, explicit_time_stepper, rhs_function, ) error = math_utils.compute_error( final_solution, lambda x: advection_.exact_solution(x, time_final) ) error_list.append(error) order = utils.convergence_order(error_list) assert order >= 1
def test_advection_operator(): # test that dg_operator acting on projected initial condition converges to # exact time derivative # will lose one order of accuracy for i in range(2): if i == 0: sin = x_functions.Sine() cos = x_functions.Cosine() initial_condition = x_functions.ComposedVector([sin, cos]) else: initial_condition = x_functions.Sine() wavespeed = 1.0 exact_solution = advection.ExactSolution(initial_condition, wavespeed) exact_time_derivative = advection.ExactTimeDerivative(exact_solution, wavespeed) initial_time_derivative = x_functions.FrozenT(exact_time_derivative, 0.0) app_ = advection.Advection(wavespeed) riemann_solver = riemann_solvers.LocalLaxFriedrichs(app_.flux_function) boundary_condition = boundary.Periodic() for basis_class in basis.BASIS_LIST: for num_basis_cpts in range(1, 5): basis_ = basis_class(num_basis_cpts) error_list = [] for num_elems in [20, 40]: mesh_ = mesh.Mesh1DUniform(0.0, 1.0, num_elems) dg_sol = basis_.project(initial_condition, mesh_) dg_operator = app_.get_explicit_operator( riemann_solver, boundary_condition ) F = dg_operator(0.0, dg_sol) error = math_utils.compute_error(F, initial_time_derivative) error_list.append(error) order = utils.convergence_order(error_list) assert order >= max([1.0, num_basis_cpts - 1])
def test_bounds_limiter_sine(): bounds_limiter = shock_capturing_limiters.BoundsLimiter() basis_ = basis.LegendreBasis1D(3) mesh_ = mesh.Mesh1DUniform(0, 1, 10) func = x_functions.Sine(1.0, 1.0, 0.0) dg_solution = basis_.project(func, mesh_) boundary_condition = boundary.Periodic() app_ = advection.Advection() problem_ = problem.Problem(app_, dg_solution) problem_.boundary_condition = boundary_condition initial_solution = dg_solution.copy() limited_solution = bounds_limiter.limit_solution(problem, dg_solution) # limited solution should be same as initial solution as smooth assert (limited_solution - initial_solution).norm() == 0.0 func = x_functions.Sine(1.0, 10.0, 0.0) dg_solution = basis_.project(func, mesh_) initial_solution = dg_solution.copy() limited_solution = bounds_limiter.limit_solution(problem, dg_solution) # with higher wavenumber the limiter should chop off maxima assert limited_solution.norm() <= initial_solution.norm()
def test_dg_operator(): # test that dg_operator converges to exact_time_derivative in smooth case initial_condition = x_functions.Sine(offset=2.0) max_wavespeed = 3.0 problem = smooth_example.SmoothExample(initial_condition, max_wavespeed) riemann_solver = riemann_solvers.LocalLaxFriedrichs(problem) boundary_condition = boundary.Periodic() x_left = 0.0 x_right = 1.0 exact_time_derivative = burgers.ExactTimeDerivative( problem.initial_condition) exact_time_derivative_initial = x_functions.FrozenT( exact_time_derivative, 0.0) for basis_class in basis.BASIS_LIST: for num_basis_cpts in range(1, 5): basis_ = basis_class(num_basis_cpts) error_list = [] for num_elems in [40, 80]: mesh_ = mesh.Mesh1DUniform(x_left, x_right, num_elems) dg_solution = basis_.project(problem.initial_condition, mesh_) explicit_operator = problem.app_.get_explicit_operator( riemann_solver, boundary_condition) dg_time_derivative = explicit_operator(0.0, dg_solution) error = math_utils.compute_error( dg_time_derivative, exact_time_derivative_initial) error_list.append(error) order = test_utils.convergence_order(error_list) if num_basis_cpts > 1: assert order >= num_basis_cpts - 1 else: assert order >= 1
from pydogpack.utils import functions from pydogpack.utils import flux_functions from pydogpack.basis import basis from pydogpack.mesh import mesh from pydogpack.mesh import boundary from apps.onedimensional.thinfilm import thin_film import numpy as np import yaml if __name__ == "__main__": exact_solution = flux_functions.AdvectingSine(amplitude=0.1, offset=0.15) problem = thin_film.ThinFilm.manufactured_solution(exact_solution) t = 0.0 bc = boundary.Periodic() n = 10 dict_ = dict() for bc in [boundary.Periodic(), boundary.Extrapolation()]: dict_[str(bc)] = dict() dict_bc = dict_[str(bc)] for basis_class in basis.BASIS_LIST: dict_bc[basis_class.string] = dict() dict_basis = dict_bc[basis_class.string] for num_basis_cpts in range(1, 4): dict_basis[num_basis_cpts] = dict() dict_cpt = dict_basis[num_basis_cpts] basis_ = basis_class(num_basis_cpts) for num_elems in range(10, 90, 10): mesh_ = mesh.Mesh1DUniform(0.0, 1.0, num_elems) dg_solution = basis_.project(problem.initial_condition, mesh_) (matrix, vector) = problem.ldg_matrix(
from pydogpack.basis import basis from pydogpack.mesh import mesh from pydogpack.mesh import boundary from apps.onedimensional.thinfilm import thin_film import numpy as np import yaml import matplotlib.pyplot as plt import pdb if __name__ == "__main__": with open("spectra.yml", "r") as file: dict_ = yaml.safe_load(file) bc = boundary.Periodic() basis_class = basis.LegendreBasis1D for num_basis_cpts in range(1, 4): data = dict_[str(bc)][basis_class.string][num_basis_cpts] plot_data = dict() for num_elems in data.keys(): real = data[num_elems]["real"] imag = data[num_elems]["imag"] if (np.max(real) > 0.0): print(np.max(real)) eigvals = np.array(real) + 1j * np.array(imag) max_eigval = np.max(np.abs(eigvals)) plot_data[num_elems] = max_eigval plt.plot(list(plot_data.keys()), list(plot_data.values()), 'o') plt.show()
def get_defaults( dg_solution, t, diffusion_function=None, source_function=None, q_boundary_condition=None, r_boundary_condition=None, q_numerical_flux=None, r_numerical_flux=None, quadrature_matrix_function=None, ): basis_ = dg_solution.basis mesh_ = dg_solution.mesh Q = dg_solution # default to linear diffusion with diffusion constant 1 if diffusion_function is None: diffusion_function = flux_functions.Polynomial(degree=0) # if is linear diffusion then diffusion_function will be constant is_linear = ( isinstance(diffusion_function, flux_functions.Polynomial) and diffusion_function.degree == 0 ) if is_linear: diffusion_constant = diffusion_function.coeffs[0] # default to 0 source if source_function is None: source_function = flux_functions.Zero() # default boundary conditions if q_boundary_condition is None: q_boundary_condition = boundary.Periodic() if r_boundary_condition is None: r_boundary_condition = boundary.Periodic() # Default numerical fluxes if q_numerical_flux is None: q_numerical_flux = riemann_solvers.RightSided( flux_functions.Polynomial([0.0, -1.0]) ) if r_numerical_flux is None: if is_linear: r_numerical_flux = riemann_solvers.LeftSided( flux_functions.Polynomial([0.0, -1.0 * diffusion_constant]) ) else: def wavespeed_function(x): # need to make sure q is evaluated on left side of interfaces if mesh_.is_interface(x): vertex_index = mesh_.get_vertex_index(x) left_elem_index = mesh_.faces_to_elems[vertex_index, 0] # if on left boundary if left_elem_index == -1: if isinstance(q_boundary_condition, boundary.Periodic): left_elem_index = mesh_.get_rightmost_elem_index() q = Q(mesh_.x_right, left_elem_index) else: left_elem_index = mesh_.get_leftmost_elem_index() q = Q(x, left_elem_index) else: q = Q(x, left_elem_index) else: q = Q(x) return -1.0 * diffusion_function(q, x, t) r_numerical_flux = riemann_solvers.LeftSided( flux_functions.VariableAdvection(wavespeed_function) ) # default quadrature function is to directly compute using dg_solution # and diffusion_function if quadrature_matrix_function is None: # if diffusion_function is a constant, # then quadrature_matrix_function will be constant, -e M^{-1}S^T # where e is diffusion constant if is_linear: quadrature_matrix_function = dg_utils.get_quadrature_matrix_function_matrix( -1.0 * diffusion_constant * basis_.mass_inverse_stiffness_transpose ) else: # M^{-1} \dintt{D_i}{-f(Q, x, t) R \Phi_x}{x} = B_i R_i quadrature_matrix_function = ldg_utils.get_quadrature_matrix_function( dg_solution, t, lambda q, x, t: -1.0 * diffusion_function(q, x, t) ) return ( diffusion_function, source_function, q_boundary_condition, r_boundary_condition, q_numerical_flux, r_numerical_flux, quadrature_matrix_function, )
def test_imex_linearized_mms(): # advection with linearized diffusion # (q_t + q_x = (f(x, t) q_xx + s(x, t)) exact_solution = flux_functions.AdvectingSine(amplitude=0.1, offset=0.15) p_class = convection_hyper_diffusion.ConvectionHyperDiffusion p_func = p_class.linearized_manufactured_solution t_initial = 0.0 bc = boundary.Periodic() for diffusion_function in [squared]: problem = p_func(exact_solution, None, diffusion_function) cfl_list = [0.9, 0.15, 0.1] for num_basis_cpts in range(2, 4): imex = imex_runge_kutta.get_time_stepper(num_basis_cpts) cfl = cfl_list[num_basis_cpts - 1] 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.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_function = lambda t: problem.ldg_matrix( dg_solution, t, bc, bc, bc, bc, include_source=False) solve_operator = time_stepping.get_solve_function_matrix( matrix_function) final_solution = time_stepping.time_step_loop_imex( dg_solution, t_initial, t_final, delta_t, imex, explicit_operator, implicit_operator, solve_operator, ) error = math_utils.compute_error(final_solution, exact_solution_final) error_list.append(error) # plot.plot_dg_1d(final_solution, function=exact_solution_final) order = utils.convergence_order(error_list) with open("hyper_diffusion_linearized_mms_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) assert order >= num_basis_cpts
def test_imex_nonlinear_mms(): wavenumber = 1.0 / 20.0 x_left = 0.0 x_right = 40.0 exact_solution = flux_functions.AdvectingSine( amplitude=0.1, wavenumber=wavenumber, offset=0.15 ) p_func = thin_film.ThinFilm.manufactured_solution t_initial = 0.0 bc = boundary.Periodic() problem = p_func(exact_solution) cfl_list = [0.5, 0.1, 0.1] n = 40 for num_basis_cpts in range(3, 4): imex = imex_runge_kutta.get_time_stepper(num_basis_cpts) cfl = cfl_list[num_basis_cpts - 1] t_final = 10 * cfl * ((x_right - x_left) / 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(x_left, x_right, 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 ) matrix_function = lambda t, q: problem.ldg_matrix( q, t, bc, bc, bc, bc, include_source=False ) solve_operator = time_stepping.get_solve_function_picard( matrix_function, num_basis_cpts, num_elems * num_basis_cpts ) final_solution = time_stepping.time_step_loop_imex( dg_solution, t_initial, t_final, delta_t, imex, explicit_operator, implicit_operator, solve_operator, ) error = math_utils.compute_error(final_solution, exact_solution_final) error_list.append(error) # plot.plot_dg_1d(final_solution, function=exact_solution_final) with open("thin_film_nonlinear_mms_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