def linearized_manufactured_solution( exact_solution, flux_function=None, diffusion_function=None, max_wavespeed=1.0 ): if flux_function is None: flux_function = flux_functions.Identity() if diffusion_function is None: diffusion_function = flux_functions.Polynomial(degree=0) source_function = ExactOperator( exact_solution, flux_function, diffusion_function, flux_functions.Zero() ) initial_condition = x_functions.FrozenT(exact_solution, 0.0) linearized_diffusion_function = flux_functions.LinearizedAboutQ( diffusion_function, exact_solution ) problem = ConvectionHyperDiffusion( flux_function, linearized_diffusion_function, source_function, initial_condition, max_wavespeed, ) problem.exact_solution = exact_solution return problem
def linearized_manufactured_solution( exact_solution, flux_function=None, diffusion_function=None, max_wavespeed=1.0 ): if flux_function is None: flux_function = flux_functions.Identity() if diffusion_function is None: diffusion_function = flux_functions.Polynomial(degree=0) # source_function could be computed with original diffusion function # or with linearized diffusion function # ? Would that make a difference? source_function = ExactOperator( exact_solution, flux_function, diffusion_function, flux_functions.Zero() ) initial_condition = x_functions.FrozenT(exact_solution, 0.0) linearized_diffusion_function = xt_functions.LinearizedAboutQ( diffusion_function, exact_solution ) problem = ConvectionDiffusion( flux_function, linearized_diffusion_function, source_function, initial_condition, max_wavespeed, ) problem.exact_solution = exact_solution return problem
def linearized_manufactured_solution(exact_solution, diffusion_function=None): if diffusion_function is None: diffusion_function = flux_functions.Polynomial(degree=0) # source_function could be computed with original diffusion function # or with linearized diffusion function # ? Would that make a difference? source_function = ExactOperator( exact_solution, flux_functions.Zero(), diffusion_function, flux_functions.Zero(), ) initial_condition = x_functions.FrozenT(exact_solution, 0.0) # linearize diffusion function new_diffusion_function = xt_functions.LinearizedAboutQ( diffusion_function, exact_solution ) problem = NonlinearDiffusion( new_diffusion_function, source_function, initial_condition ) problem.exact_solution = exact_solution return problem
def __init__( self, source_function=None, initial_condition=None, max_wavespeed=None, moving_reference_frame=False, ): if initial_condition is None: initial_condition = x_functions.Sine(amplitude=0.1, offset=0.15) # wavespeed function = 2 q - 3 q^2 # maximized at q = 1/3, the wavespeed is also 1/3 at this point if max_wavespeed is None: max_wavespeed = 1.0 / 3.0 if moving_reference_frame: flux_function = flux_functions.Polynomial( [0.0, -1.0 * max_wavespeed, 1.0, -1.0] ) else: flux_function = default_flux_function convection_hyper_diffusion.ConvectionHyperDiffusion.__init__( self, flux_function, default_diffusion_function, source_function, initial_condition, max_wavespeed, )
def __init__( self, flux_function=None, diffusion_function=None, source_function=None, initial_condition=default_initial_condition, max_wavespeed=1.0, ): # default to linear hyper diffusion, with diffusion constant 1 if diffusion_function is None: self.diffusion_function = flux_functions.Polynomial(degree=0) else: self.diffusion_function = diffusion_function self.is_diffusive = not isinstance(self.diffusion_function, flux_functions.Zero) self.is_linear_hyperdiffusion = ( isinstance(diffusion_function, flux_functions.Polynomial) and diffusion_function.degree == 0 ) if self.is_linear_hyperdiffusion: self.diffusion_constant = diffusion_function.coeffs[0] self.is_convective = not isinstance(flux_function, flux_functions.Zero) app.App.__init__( self, flux_function, source_function )
def __init__( self, wavespeed=1.0, source_function=None, ): self.wavespeed = wavespeed flux_function = flux_functions.Polynomial([0.0, self.wavespeed]) app.App.__init__(self, flux_function, source_function)
def test_compute_quadrature_matrix(): squared = flux_functions.Polynomial(degree=2) cubed = flux_functions.Polynomial(degree=3) initial_condition = functions.Sine() t = 0.0 x_left = 0.0 x_right = 1.0 for f in [squared, cubed]: for basis_class in basis.BASIS_LIST: for num_basis_cpts in range(1, 6): error_list = [] basis_ = basis_class(num_basis_cpts) for num_elems in [10, 20]: mesh_ = mesh.Mesh1DUniform(x_left, x_right, num_elems) dg_solution = basis_.project(initial_condition, mesh_) quadrature_matrix = ldg_utils.compute_quadrature_matrix( dg_solution, t, f) result = solution.DGSolution(None, basis_, mesh_) direct_quadrature = solution.DGSolution( None, basis_, mesh_) for i in range(mesh_.num_elems): # compute value as B_i Q_i result[i] = np.matmul(quadrature_matrix[i], dg_solution[i]) # also compute quadrature directly for l in range(basis_.num_basis_cpts): quadrature_function = (lambda xi: f( initial_condition( mesh_.transform_to_mesh(xi, i)), xi, ) * initial_condition( mesh_.transform_to_mesh(xi, i)) * basis_. derivative(xi, l)) direct_quadrature[i, l] = math_utils.quadrature( quadrature_function, -1.0, 1.0) # need to multiply by mass inverse direct_quadrature[i] = np.matmul( basis_.mass_matrix_inverse, direct_quadrature[i]) error = (result - direct_quadrature).norm() error_list.append(error) if error_list[-1] != 0.0: order = utils.convergence_order(error_list) assert order >= (num_basis_cpts - 1)
def __init__( self, source_function=None, initial_condition=None, diffusion_constant=1.0 ): # diffusion function is f(q, x, t) = d self.diffusion_constant = diffusion_constant diffusion_function = flux_functions.Polynomial([diffusion_constant]) NonlinearDiffusion.__init__( self, diffusion_function, source_function, initial_condition )
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 manufactured_solution(exact_solution, diffusion_function=None): if diffusion_function is None: diffusion_function = flux_functions.Polynomial(degree=0) source_function = ExactOperator( exact_solution, flux_functions.Zero(), diffusion_function, flux_functions.Zero(), ) initial_condition = x_functions.FrozenT(exact_solution, 0.0) problem = NonlinearDiffusion( diffusion_function, source_function, initial_condition ) problem.exact_solution = exact_solution return problem
def test_linearized_about_q(): original_flux_function = flux_functions.Polynomial(degree=3) q = xt_functions.AdvectingSine() xt_function = xt_functions.LinearizedAboutQ(original_flux_function, q) utils.check_to_from_dict(xt_function, xt_functions) x = 0.5 t = 0.1 assert xt_function(q(x, t), x, t) is not None assert xt_function(x, t) is not None assert xt_function(x, t) == xt_function(q(x, t), x, t) for x in range(10): for t in range(10): assert xt_function(x, t) == original_flux_function(q(x, t), x, t)
def __init__( self, flux_function=None, diffusion_function=None, source_function=None, initial_condition=None, max_wavespeed=1.0, ): # default to linear diffusion with diffusion constant 1 if diffusion_function is None: self.diffusion_function = flux_functions.Polynomial(degree=0) else: self.diffusion_function = diffusion_function app.App.__init__( self, flux_function, source_function, )
def __init__( self, q, flux_function=None, diffusion_function=None, source_function=None, default_t=None, ): self.q = q if flux_function is None: self.flux_function = flux_functions.Zero else: self.flux_function = flux_function if diffusion_function is None: self.diffusion_function = flux_functions.Polynomial(degree=0) else: self.diffusion_function = diffusion_function if source_function is None: self.source_function = flux_functions.Zero() else: self.source_function = source_function xt_functions.XTFunction.__init__(self)
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, )
from pydogpack.mesh import mesh from pydogpack.mesh import boundary from pydogpack.localdiscontinuousgalerkin import utils as ldg_utils from pydogpack.solution import solution from pydogpack.tests.utils import utils from pydogpack.timestepping import time_stepping from pydogpack.timestepping import implicit_runge_kutta from pydogpack.utils import flux_functions from pydogpack.utils import math_utils from pydogpack.utils import x_functions from pydogpack.visualize import plot import numpy as np identity = flux_functions.Identity() squared = flux_functions.Polynomial(degree=2) diffusion_functions = [identity, squared] # (q q_x)_x hyper_diffusion_identity = convection_hyper_diffusion.NonlinearHyperDiffusion( identity) # (q^2 q_x)_x hyper_diffusion_squared = convection_hyper_diffusion.NonlinearHyperDiffusion( squared) test_problems = [hyper_diffusion_identity, hyper_diffusion_squared] tolerance = 1e-5 def test_ldg_constant(): # LDG of one should be zero t = 0.0 for nonlinear_hyper_diffusion in test_problems:
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
def __init__(self, q, source_function=None): flux_function = flux_functions.Polynomial([0.0, 0.0, 0.5]) app.ExactTimeDerivative.__init__(self, q, flux_function, source_function)
def __init__(self, source_function=None): flux_function = flux_functions.Polynomial([0.0, 0.0, 0.5]) super().__init__( flux_function, source_function, )
def __init__(self, q, wavespeed=1.0, source_function=None): self.wavespeed = wavespeed flux_function = flux_functions.Polynomial([0.0, self.wavespeed]) app.ExactOperator.__init__(self, q, flux_function, source_function)
def __init__(self, q, source_function=None): flux_function = flux_functions.Polynomial([0.0, 0.0, 0.5]) app.ExactOperator.__init__(self, q, flux_function, source_function)
def __init__(self, q, wavespeed=1.0, source_function=None): self.wavespeed = wavespeed flux_function = flux_functions.Polynomial([0.0, self.wavespeed]) app.ExactTimeDerivative.__init__(self, q, flux_function, source_function)
from pydogpack.utils import flux_functions from pydogpack.utils import x_functions from apps.onedimensional.convectionhyperdiffusion import convection_hyper_diffusion from apps.onedimensional.convectiondiffusion import convection_diffusion from apps.onedimensional.thinfilm import ldg import numpy as np default_flux_function = flux_functions.Polynomial([0.0, 0.0, 1.0, -1.0]) default_diffusion_function = flux_functions.Polynomial(degree=3) # represents q_t + (q^2 - q^3)_x = -(q^3 q_xxx)_x + s(x) class ThinFilm(convection_hyper_diffusion.ConvectionHyperDiffusion): def __init__( self, source_function=None, initial_condition=None, max_wavespeed=None, moving_reference_frame=False, ): if initial_condition is None: initial_condition = x_functions.Sine(amplitude=0.1, offset=0.15) # wavespeed function = 2 q - 3 q^2 # maximized at q = 1/3, the wavespeed is also 1/3 at this point if max_wavespeed is None: max_wavespeed = 1.0 / 3.0 if moving_reference_frame: flux_function = flux_functions.Polynomial(
from pydogpack.utils import xt_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.convectiondiffusion import convection_diffusion import numpy as np import yaml if __name__ == "__main__": exact_solution = xt_functions.AdvectingSine(amplitude=0.1, offset=0.15) diffusion_function = flux_functions.Polynomial(degree=3) problem = convection_diffusion.NonlinearDiffusion.manufactured_solution( exact_solution, diffusion_function) 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)