Beispiel #1
0
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
Beispiel #2
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 #3
0
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
Beispiel #4
0
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
Beispiel #5
0
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
Beispiel #6
0
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
Beispiel #8
0
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
Beispiel #9
0
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
Beispiel #10
0
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
Beispiel #11
0
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
Beispiel #12
0
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
Beispiel #16
0
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],
    )
Beispiel #17
0
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
Beispiel #19
0
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
Beispiel #20
0
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
Beispiel #22
0
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
Beispiel #23
0
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])
Beispiel #24
0
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()
Beispiel #25
0
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(
Beispiel #27
0
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()
Beispiel #28
0
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
Beispiel #30
0
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