Beispiel #1
0
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
Beispiel #2
0
    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
Beispiel #3
0
 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)
Beispiel #4
0
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)
Beispiel #5
0
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
Beispiel #6
0
    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)
Beispiel #7
0
    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
Beispiel #8
0
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
Beispiel #9
0
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
Beispiel #10
0
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
Beispiel #11
0
 def func(coeffs):
     q = solution.DGSolution(coeffs, basis_, mesh_, num_eqns)
     result = d * q + e * F(t, q) - rhs
     return result.coeffs
Beispiel #12
0
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
Beispiel #13
0
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
Beispiel #14
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
Beispiel #15
0
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