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 solve_function(d, e, t, rhs, q_old, t_old, delta_t, F, stages, stage_num): (matrix, vector) = matrix_function(t) q_vector = np.linalg.solve(d * identity + e * matrix, rhs.to_vector() - e * vector) dg_solution = solution.DGSolution(q_vector, rhs.basis, rhs.mesh) return dg_solution
def solve_function(d, e, t, rhs, q_old, t_old, delta_t, F, stages, stage_num): if vector is not None: q_vector = np.linalg.solve(d * identity + e * matrix, rhs.to_vector() - e * vector) else: q_vector = np.linalg.solve(d * identity + e * matrix, rhs.to_vector()) return solution.DGSolution(q_vector, rhs.basis, rhs.mesh)
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 fd_to_dg(fd_solution, boundary_condition=None): if boundary_condition is None: boundary_condition = boundary.Extrapolation() num_elems = fd_solution.mesh.num_elems basis_class = type(fd_solution.basis) basis_ = basis_class(2) dg_solution = solution.DGSolution(None, basis_, fd_solution.mesh) dg_solution[:, 0] = fd_solution.coeffs[:, 0] for i in range(num_elems): dg_solution[:, 1] return dg_solution
def solve_function(d, e, t, rhs, q_old, t_old, delta_t, F, stages, stage_num): basis_ = q_old.basis_ mesh_ = q_old.mesh_ num_eqns = q_old.num_eqns def func(coeffs): q = solution.DGSolution(coeffs, basis_, mesh_, num_eqns) result = d * q + e * F(t, q) - rhs return result.coeffs solution_coeffs = scipy.optimize.newton_krylov(func, rhs.coeffs) return solution.DGSolution(solution_coeffs, basis_, mesh_, num_eqns)
def solve_function(d, e, t, rhs, q_old, t_old, delta_t, F, stages, stage_num): if stage_num > 0: q = stages[stage_num - 1] else: q = q_old for i in range(num_picard_iterations): (matrix, vector) = matrix_function(t, q) q_vector = np.linalg.solve(d * identity + e * matrix, rhs.to_vector() - e * vector) q = solution.DGSolution(q_vector, rhs.basis, rhs.mesh) return q
def rhs_function(t, q, app_): num_elems = q.mesh_.num_elems delta_x = q.mesh_.delta_x a = -1.0 / delta_x F = solution.DGSolution(None, q.basis_, q.mesh_, q.num_eqns) # assume periodic boundary conditions f = fluctuations(q[num_elems - 1, :, :], q[0, :, :], app_) F[num_elems - 1, :, :] += a * f[0] F[0, :, :] += a * f[1] for i in range(1, num_elems): # f = (A^- \Delta Q_{i-1/2}, A^+ \Delta Q_{i-1/2}) f = fluctuations(q[i - 1, :, :], q[i, :, :], app_) F[i - 1, :, :] += a * f[0] F[i, :, :] += a * f[1] return F
def wave_propagation_formulation( dg_solution, t, app_, fluctuation_solver, boundary_condition, ): # Wave Propagation Method # Q^{n+1}_i = Q^n - delta_t/delta_x (A^+ \Delta Q_{i-1/2} + A^- \Delta Q_{i+1/2}) # Wave Propagation Operator # F(t, q)_i = - 1/delta_x (A^+ \Delta Q_{i-1/2} + A^- \Delta Q_{i+1/2}) F = solution.DGSolution( None, dg_solution.basis_, dg_solution.mesh_, dg_solution.num_eqns ) # compute fluctuations and add to F mesh_ = dg_solution.mesh_ for face_index in mesh_.boundary_faces: left_elem_index = mesh_.faces_to_elems[face_index, 0] right_elem_index = mesh_.faces_to_elems[face_index, 1] fluctuations = boundary_condition.evaluate_boundary( dg_solution, face_index, fluctuation_solver, t ) if left_elem_index != -1: F[left_elem_index, :, :] += ( -1.0 / mesh_.elem_volumes[left_elem_index] * fluctuations[0] ) elif right_elem_index != -1: F[right_elem_index, :, :] += ( -1.0 / mesh_.elem_volumes[right_elem_index] * fluctuations[1] ) for face_index in mesh_.interior_faces: left_elem_index = mesh_.faces_to_elems[face_index, 0] right_elem_index = mesh_.faces_to_elems[face_index, 1] fluctuations = fluctuation_solver.solve(dg_solution, face_index, t) F[left_elem_index, :, :] += ( -1.0 / mesh_.elem_volumes[left_elem_index] * fluctuations[0] ) F[right_elem_index, :, :] += ( -1.0 / mesh_.elem_volumes[right_elem_index] * fluctuations[1] ) return F
def read_dogpack_dir(output_dir): parameters_file = output_dir + "/parameters.ini" params = parse_parameters.parse_ini_parameters(output_dir, parameters_file) mesh_ = mesh.from_dogpack_params(params) basis_ = basis_factory.from_dogpack_params(params) num_frames = params["num_frames"] space_order = basis_.space_order num_basis_cpts = basis_.num_basis_cpts num_elems = mesh_.num_elems num_eqns = params["num_eqns"] m_tmp = num_elems * num_eqns * num_basis_cpts dg_solution_list = [] time_list = [] for i_frame in range(num_frames + 1): q_filename = "q" + str(i_frame).zfill(4) + ".dat" with open(output_dir + "/" + q_filename, "r") as q_file: # get time linestring = q_file.readline() linelist = linestring.split() time = np.float64(linelist[0]) time_list.append(time) # store all Legendre coefficients in q_tmp q_tmp = np.zeros(m_tmp, dtype=np.float64) for k in range(0, m_tmp): linestring = q_file.readline() linelist = linestring.split() q_tmp[k] = np.float64(linelist[0]) q_tmp = q_tmp.reshape((num_basis_cpts, num_eqns, num_elems)) # rearrange to match PyDogPack configuration coeffs = np.einsum("ijk->kji", q_tmp) dg_solution = solution.DGSolution(coeffs, basis_, mesh_, num_eqns) dg_solution_list.append(dg_solution) return dg_solution_list, time_list
def func(coeffs): q = solution.DGSolution(coeffs, basis_, mesh_, num_eqns) result = d * q + e * F(t, q) - rhs return result.coeffs
def test_to_from_vector(): dg_solution_vector = dg_solution.to_vector() assert len(dg_solution_vector.shape) == 1 new_solution = solution.DGSolution(None, basis_, mesh_) new_solution.from_vector(dg_solution_vector) assert new_solution == dg_solution
from pydogpack.solution import solution from pydogpack.basis import basis from pydogpack.mesh import mesh from pydogpack.utils import functions from pydogpack.utils import x_functions import numpy as np basis_ = basis.LegendreBasis1D(4) mesh_ = mesh.Mesh1DUniform(0.0, 1.0, 40) dg_solution = solution.DGSolution(None, basis_, mesh_) tolerance = 1e-8 tolerance_2 = 0.1 def test_call(): assert dg_solution(0.0) == 0.0 def test_evaluate_canonical(): assert dg_solution.evaluate_canonical(1.0, 1) == 0.0 def test_evaluate_gradient(): assert dg_solution.evaluate_gradient(0.5) == 0.0 def test_evaluate_gradient_mesh(): assert dg_solution.evaluate_gradient_mesh(0.5) == 0.0
def evaluate_weak_form( dg_solution, t, flux_function, riemann_solver, boundary_condition, nonconservative_function=None, regularization_path=None, source_function=None, ): # \v{q}_t + \div_x \M{f}(\v{q}, x, t) + g(\v{q}, x, t) \v{q}_x = \v{s}(\v{q}, x, t) # See notes for derivation of dg formulation # \M{Q}_{i,t} = # \dintt{\mcK}{}{\M{f}\p{\M{Q}_i \v{\phi}(\v{\xi}), \v{b}_i(\v{\xi}), t} # \p{\v{\phi}'(\v{\xi}) \v{c}_i'(\v{b}_i(\v{\xi}))}^T}{\v{\xi}} \M{M}^{-1} # - 1/m_i \dintt{\partial K_i}{}{\M{f}^* \v{n} \v{\phi}_i^T(\v{x})}{s} \M{M}^{-1} # + \dintt{\mcK}{}{\v{s}\p{\M{Q}_i \v{\phi}_i(\v{x}), \v{x}, t} # \v{\phi}^T\p{\v{\xi}}}{\v{\xi}} \M{M}^{-1} # # - 1/m_i \dintt{-1}{1}{g(Q_i \v{\phi}) Q_i \v{\phi}_{\xi}(\xi) # \v{\phi}^T(\xi)}{\xi} M^{-1} # - 1/(2m_i)\dintt{0}{1}{g(\v{\psi}(s, Q_{i-1} \v{\phi}(1), Q_i \v{\phi}(-1))) # \v{\psi}_s(s, Q_{i-1}\v{\phi}(1), Q_i \v{\phi}(-1))}{s} # \v{\phi}^T(-1) M^{-1} # - 1/(2m_i)\dintt{0}{1}{g(\v{\psi}(s, Q_i \v{\phi}(1), Q_{i+1}\v{\phi}(-1))) # \v{\psi}_s(s, Q_i \v{\phi}(1), Q_{i+1} \v{\phi}(-1))}{s} # \v{\phi}^T(1) M^{-1} # dg_solution = Q, with mesh and basis # numerical_fluxes = \M{f}^* # source_function = \v{s}(\v{q}_h, x, t) # if source_function is None assume zero source function mesh_ = dg_solution.mesh_ basis_ = dg_solution.basis_ transformed_solution = solution.DGSolution(None, basis_, mesh_, dg_solution.num_eqns) # import ipdb; ipdb.set_trace() if source_function is not None: transformed_solution = evaluate_source_term(transformed_solution, source_function, dg_solution, t) if basis_.num_basis_cpts > 1: transformed_solution = project_flux_onto_gradient( transformed_solution, dg_solution, flux_function, t) # numerical_fluxes should be approximate riemann solutions at quadrature points # on every face numerical_fluxes = evaluate_fluxes(dg_solution, t, boundary_condition, riemann_solver) transformed_solution = evaluate_weak_flux(transformed_solution, numerical_fluxes) if nonconservative_function is not None: transformed_solution = evaluate_nonconservative_term( transformed_solution, nonconservative_function, regularization_path, dg_solution, t, boundary_condition, ) return transformed_solution
def dg_to_fd(dg_solution): basis_class = type(dg_solution.basis) basis_ = basis_class(1) fd_solution = solution.DGSolution(dg_solution.coeffs[:, 0], basis_, dg_solution.mesh) return fd_solution