예제 #1
0
def test_2d_gauss_theorem(actx_factory):
    """Verify Gauss's theorem explicitly on a mesh"""

    pytest.importorskip("meshpy")

    from meshpy.geometry import make_circle, GeometryBuilder
    from meshpy.triangle import MeshInfo, build

    geob = GeometryBuilder()
    geob.add_geometry(*make_circle(1))
    mesh_info = MeshInfo()
    geob.set(mesh_info)

    mesh_info = build(mesh_info)

    from meshmode.mesh.io import from_meshpy
    mesh = from_meshpy(mesh_info, order=1)

    actx = actx_factory()

    discr = DGDiscretizationWithBoundaries(actx, mesh, order=2)

    def f(x):
        return flat_obj_array(
                sym.sin(3*x[0])+sym.cos(3*x[1]),
                sym.sin(2*x[0])+sym.cos(x[1]))

    gauss_err = bind(discr,
            sym.integral((
                sym.nabla(2) * f(sym.nodes(2))
                ).sum())
            -  # noqa: W504
            sym.integral(
                sym.project("vol", sym.BTAG_ALL)(f(sym.nodes(2)))
                .dot(sym.normal(sym.BTAG_ALL, 2)),
                dd=sym.BTAG_ALL)
            )(actx)

    assert abs(gauss_err) < 1e-13
예제 #2
0
def test_2d_gauss_theorem(actx_factory):
    """Verify Gauss's theorem explicitly on a mesh"""

    pytest.importorskip("meshpy")

    from meshpy.geometry import make_circle, GeometryBuilder
    from meshpy.triangle import MeshInfo, build

    geob = GeometryBuilder()
    geob.add_geometry(*make_circle(1))
    mesh_info = MeshInfo()
    geob.set(mesh_info)

    mesh_info = build(mesh_info)

    from meshmode.mesh.io import from_meshpy
    from meshmode.mesh import BTAG_ALL

    mesh = from_meshpy(mesh_info, order=1)

    actx = actx_factory()

    dcoll = DiscretizationCollection(actx, mesh, order=2)
    volm_disc = dcoll.discr_from_dd(dof_desc.DD_VOLUME)
    x_volm = thaw(volm_disc.nodes(), actx)

    def f(x):
        return flat_obj_array(
            actx.np.sin(3 * x[0]) + actx.np.cos(3 * x[1]),
            actx.np.sin(2 * x[0]) + actx.np.cos(x[1]))

    f_volm = f(x_volm)
    int_1 = op.integral(dcoll, "vol", op.local_div(dcoll, f_volm))

    prj_f = op.project(dcoll, "vol", BTAG_ALL, f_volm)
    normal = thaw(dcoll.normal(BTAG_ALL), actx)
    int_2 = op.integral(dcoll, BTAG_ALL, prj_f.dot(normal))

    assert abs(int_1 - int_2) < 1e-13
예제 #3
0
def test_convergence_advec(ctx_factory,
                           mesh_name,
                           mesh_pars,
                           op_type,
                           flux_type,
                           order,
                           visualize=False):
    """Test whether 2D advection actually converges"""

    cl_ctx = ctx_factory()
    queue = cl.CommandQueue(cl_ctx)
    actx = PyOpenCLArrayContext(queue)

    from pytools.convergence import EOCRecorder
    eoc_rec = EOCRecorder()

    for mesh_par in mesh_pars:
        if mesh_name == "segment":
            from meshmode.mesh.generation import generate_box_mesh
            mesh = generate_box_mesh([np.linspace(-1.0, 1.0, mesh_par)],
                                     order=order)

            dim = 1
            dt_factor = 1.0
        elif mesh_name == "disk":
            pytest.importorskip("meshpy")

            from meshpy.geometry import make_circle, GeometryBuilder
            from meshpy.triangle import MeshInfo, build

            geob = GeometryBuilder()
            geob.add_geometry(*make_circle(1))
            mesh_info = MeshInfo()
            geob.set(mesh_info)

            mesh_info = build(mesh_info, max_volume=mesh_par)

            from meshmode.mesh.io import from_meshpy
            mesh = from_meshpy(mesh_info, order=1)
            dim = 2
            dt_factor = 4
        elif mesh_name.startswith("rect"):
            dim = int(mesh_name[4:])
            from meshmode.mesh.generation import generate_regular_rect_mesh
            mesh = generate_regular_rect_mesh(a=(-0.5, ) * dim,
                                              b=(0.5, ) * dim,
                                              n=(mesh_par, ) * dim,
                                              order=4)

            if dim == 2:
                dt_factor = 4
            elif dim == 3:
                dt_factor = 2
            else:
                raise ValueError("dt_factor not known for %dd" % dim)

        else:
            raise ValueError("invalid mesh name: " + mesh_name)

        v = np.array([0.27, 0.31, 0.1])[:dim]
        norm_v = la.norm(v)

        def f(x):
            return sym.sin(10 * x)

        def u_analytic(x):
            return f(-v.dot(x) / norm_v + sym.var("t", sym.DD_SCALAR) * norm_v)

        from grudge.models.advection import (StrongAdvectionOperator,
                                             WeakAdvectionOperator)
        discr = DGDiscretizationWithBoundaries(actx, mesh, order=order)
        op_class = {
            "strong": StrongAdvectionOperator,
            "weak": WeakAdvectionOperator,
        }[op_type]
        op = op_class(v,
                      inflow_u=u_analytic(sym.nodes(dim, sym.BTAG_ALL)),
                      flux_type=flux_type)

        bound_op = bind(discr, op.sym_operator())

        u = bind(discr, u_analytic(sym.nodes(dim)))(actx, t=0)

        def rhs(t, u):
            return bound_op(t=t, u=u)

        if dim == 3:
            final_time = 0.1
        else:
            final_time = 0.2

        h_max = bind(discr, sym.h_max_from_volume(discr.ambient_dim))(actx)
        dt = dt_factor * h_max / order**2
        nsteps = (final_time // dt) + 1
        dt = final_time / nsteps + 1e-15

        from grudge.shortcuts import set_up_rk4
        dt_stepper = set_up_rk4("u", dt, u, rhs)

        last_u = None

        from grudge.shortcuts import make_visualizer
        vis = make_visualizer(discr, vis_order=order)

        step = 0

        for event in dt_stepper.run(t_end=final_time):
            if isinstance(event, dt_stepper.StateComputed):
                step += 1
                logger.debug("[%04d] t = %.5f", step, event.t)

                last_t = event.t
                last_u = event.state_component

                if visualize:
                    vis.write_vtk_file("fld-%s-%04d.vtu" % (mesh_par, step),
                                       [("u", event.state_component)])

        error_l2 = bind(discr,
                        sym.norm(2,
                                 sym.var("u") - u_analytic(sym.nodes(dim))))(
                                     t=last_t, u=last_u)
        logger.info("h_max %.5e error %.5e", h_max, error_l2)
        eoc_rec.add_data_point(h_max, error_l2)

    logger.info(
        "\n%s", eoc_rec.pretty_print(abscissa_label="h",
                                     error_label="L2 Error"))

    assert eoc_rec.order_estimate() > order
예제 #4
0
def test_convergence_advec(actx_factory,
                           mesh_name,
                           mesh_pars,
                           op_type,
                           flux_type,
                           order,
                           visualize=False):
    """Test whether 2D advection actually converges"""

    actx = actx_factory()

    from pytools.convergence import EOCRecorder
    eoc_rec = EOCRecorder()

    for mesh_par in mesh_pars:
        if mesh_name == "segment":
            mesh = mgen.generate_box_mesh([np.linspace(-1.0, 1.0, mesh_par)],
                                          order=order)

            dim = 1
            dt_factor = 1.0
        elif mesh_name == "disk":
            pytest.importorskip("meshpy")

            from meshpy.geometry import make_circle, GeometryBuilder
            from meshpy.triangle import MeshInfo, build

            geob = GeometryBuilder()
            geob.add_geometry(*make_circle(1))
            mesh_info = MeshInfo()
            geob.set(mesh_info)

            mesh_info = build(mesh_info, max_volume=mesh_par)

            from meshmode.mesh.io import from_meshpy
            mesh = from_meshpy(mesh_info, order=1)
            dim = 2
            dt_factor = 4
        elif mesh_name.startswith("rect"):
            dim = int(mesh_name[-1:])
            mesh = mgen.generate_regular_rect_mesh(
                a=(-0.5, ) * dim,
                b=(0.5, ) * dim,
                nelements_per_axis=(mesh_par, ) * dim,
                order=4)

            if dim == 2:
                dt_factor = 4
            elif dim == 3:
                dt_factor = 2
            else:
                raise ValueError("dt_factor not known for %dd" % dim)
        elif mesh_name.startswith("warped"):
            dim = int(mesh_name[-1:])
            mesh = mgen.generate_warped_rect_mesh(dim,
                                                  order=order,
                                                  nelements_side=mesh_par)

            if dim == 2:
                dt_factor = 4
            elif dim == 3:
                dt_factor = 2
            else:
                raise ValueError("dt_factor not known for %dd" % dim)
        else:
            raise ValueError("invalid mesh name: " + mesh_name)

        v = np.array([0.27, 0.31, 0.1])[:dim]
        norm_v = la.norm(v)

        def f(x):
            return actx.np.sin(10 * x)

        def u_analytic(x, t=0):
            return f(-v.dot(x) / norm_v + t * norm_v)

        from grudge.models.advection import (StrongAdvectionOperator,
                                             WeakAdvectionOperator)
        from meshmode.mesh import BTAG_ALL

        dcoll = DiscretizationCollection(actx, mesh, order=order)
        op_class = {
            "strong": StrongAdvectionOperator,
            "weak": WeakAdvectionOperator
        }[op_type]
        adv_operator = op_class(dcoll,
                                v,
                                inflow_u=lambda t: u_analytic(
                                    thaw(dcoll.nodes(dd=BTAG_ALL), actx), t=t),
                                flux_type=flux_type)

        nodes = thaw(dcoll.nodes(), actx)
        u = u_analytic(nodes, t=0)

        def rhs(t, u):
            return adv_operator.operator(t, u)

        if dim == 3:
            final_time = 0.1
        else:
            final_time = 0.2

        from grudge.dt_utils import h_max_from_volume

        h_max = h_max_from_volume(dcoll, dim=dcoll.ambient_dim)
        dt = dt_factor * h_max / order**2
        nsteps = (final_time // dt) + 1
        dt = final_time / nsteps + 1e-15

        from grudge.shortcuts import set_up_rk4
        dt_stepper = set_up_rk4("u", dt, u, rhs)

        last_u = None

        from grudge.shortcuts import make_visualizer
        vis = make_visualizer(dcoll)

        step = 0

        for event in dt_stepper.run(t_end=final_time):
            if isinstance(event, dt_stepper.StateComputed):
                step += 1
                logger.debug("[%04d] t = %.5f", step, event.t)

                last_t = event.t
                last_u = event.state_component

                if visualize:
                    vis.write_vtk_file("fld-%s-%04d.vtu" % (mesh_par, step),
                                       [("u", event.state_component)])

        error_l2 = op.norm(dcoll, last_u - u_analytic(nodes, t=last_t), 2)
        logger.info("h_max %.5e error %.5e", h_max, error_l2)
        eoc_rec.add_data_point(h_max, actx.to_numpy(error_l2))

    logger.info(
        "\n%s", eoc_rec.pretty_print(abscissa_label="h",
                                     error_label="L2 Error"))

    if mesh_name.startswith("warped"):
        # NOTE: curvilinear meshes are hard
        assert eoc_rec.order_estimate() > order - 0.5
    else:
        assert eoc_rec.order_estimate() > order