예제 #1
0
def test_nodal_dg_interop(actx_factory, dim):
    pytest.importorskip("oct2py")
    actx = actx_factory()

    download_nodal_dg_if_not_present()
    order = 4

    from meshmode.mesh.generation import generate_regular_rect_mesh
    mesh = generate_regular_rect_mesh(a=(-0.5, ) * dim,
                                      b=(0.5, ) * dim,
                                      n=(8, ) * dim,
                                      order=order)

    from meshmode.interop.nodal_dg import NodalDGContext
    with NodalDGContext("./nodal-dg/Codes1.1") as ndgctx:
        ndgctx.set_mesh(mesh, order=order)

        discr = ndgctx.get_discr(actx)

        for ax in range(dim):
            x_ax = ndgctx.pull_dof_array(actx, ndgctx.AXES[ax])
            err = flat_norm(x_ax - discr.nodes()[ax], np.inf)
            assert err < 1e-15

        n0 = thaw(actx, discr.nodes()[0])

        ndgctx.push_dof_array("n0", n0)
        n0_2 = ndgctx.pull_dof_array(actx, "n0")

        assert flat_norm(n0 - n0_2, np.inf) < 1e-15
예제 #2
0
def test_chained_connection(ctx_factory, ndim, visualize=False):
    ctx = ctx_factory()
    queue = cl.CommandQueue(ctx)
    actx = PyOpenCLArrayContext(queue)

    discr = create_discretization(actx, ndim, nelements=10)
    connections = []
    conn = create_refined_connection(actx, discr, threshold=np.inf)
    connections.append(conn)
    conn = create_refined_connection(actx, conn.to_discr, threshold=np.inf)
    connections.append(conn)

    from meshmode.discretization.connection import \
            ChainedDiscretizationConnection
    chained = ChainedDiscretizationConnection(connections)

    def f(x):
        from functools import reduce
        return 0.1 * reduce(lambda x, y: x * actx.np.sin(5 * y), x)

    x = thaw(actx, connections[0].from_discr.nodes())
    fx = f(x)
    f1 = chained(fx)
    f2 = connections[1](connections[0](fx))

    assert flat_norm(f1-f2, np.inf) / flat_norm(f2) < 1e-11
예제 #3
0
def main():
    logging.basicConfig(level=logging.INFO)

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

    nel_1d = 16
    from meshmode.mesh.generation import generate_regular_rect_mesh
    mesh = generate_regular_rect_mesh(a=(-0.5, -0.5),
                                      b=(0.5, 0.5),
                                      nelements_per_axis=(nel_1d, nel_1d))

    order = 3

    # no deep meaning here, just a fudge factor
    dt = 0.7 / (nel_1d * order**2)

    logger.info("%d elements", mesh.nelements)

    discr = DGDiscretization(actx, mesh, order=order)

    fields = WaveState(
        u=bump(actx, discr),
        v=make_obj_array([discr.zeros(actx) for i in range(discr.dim)]),
    )

    from meshmode.discretization.visualization import make_visualizer
    vis = make_visualizer(actx, discr.volume_discr)

    def rhs(t, q):
        return wave_operator(actx, discr, c=1, q=q)

    t = 0
    t_final = 3
    istep = 0
    while t < t_final:
        fields = rk4_step(fields, t, dt, rhs)

        if istep % 10 == 0:
            # FIXME: Maybe an integral function to go with the
            # DOFArray would be nice?
            assert len(fields.u) == 1
            logger.info("[%05d] t %.5e / %.5e norm %.5e", istep, t, t_final,
                        flat_norm(fields.u, 2))
            vis.write_vtk_file("fld-wave-min-%04d.vtu" % istep, [
                ("q", fields),
            ])

        t += dt
        istep += 1

    assert flat_norm(fields.u, 2) < 100
예제 #4
0
def test_mean_curvature(ctx_factory,
                        discr_name,
                        resolutions,
                        discr_and_ref_mean_curvature_getter,
                        visualize=False):
    ctx = ctx_factory()
    queue = cl.CommandQueue(ctx)
    actx = PyOpenCLArrayContext(queue)

    from pytools.convergence import EOCRecorder
    eoc = EOCRecorder()

    for r in resolutions:
        discr, ref_mean_curvature = \
                discr_and_ref_mean_curvature_getter(actx, r)
        mean_curvature = bind(discr,
                              sym.mean_curvature(discr.ambient_dim))(actx)

        h = 1.0 / r
        from meshmode.dof_array import flat_norm
        h_error = flat_norm(mean_curvature - ref_mean_curvature, np.inf)
        eoc.add_data_point(h, h_error)
    print(eoc)

    order = min([g.order for g in discr.groups])
    assert eoc.order_estimate() > order - 1.1
예제 #5
0
def test_inverse_metric(actx_factory, dim):
    actx = actx_factory()

    mesh = mgen.generate_regular_rect_mesh(a=(-0.5, ) * dim,
                                           b=(0.5, ) * dim,
                                           nelements_per_axis=(6, ) * dim,
                                           order=4)

    def m(x):
        result = np.empty_like(x)
        result[0] = (1.5 * x[0] + np.cos(x[0]) + 0.1 * np.sin(10 * x[1]))
        result[1] = (0.05 * np.cos(10 * x[0]) + 1.3 * x[1] + np.sin(x[1]))
        if len(x) == 3:
            result[2] = x[2]
        return result

    from meshmode.mesh.processing import map_mesh
    mesh = map_mesh(mesh, m)

    dcoll = DiscretizationCollection(actx, mesh, order=4)

    from grudge.geometry import \
        forward_metric_derivative_mat, inverse_metric_derivative_mat

    mat = forward_metric_derivative_mat(actx, dcoll).dot(
        inverse_metric_derivative_mat(actx, dcoll))

    for i in range(mesh.dim):
        for j in range(mesh.dim):
            tgt = 1 if i == j else 0

            err = flat_norm(mat[i, j] - tgt, ord=np.inf)
            logger.info("error[%d, %d]: %.5e", i, j, err)
            assert err < 1.0e-12, (i, j, err)
예제 #6
0
def simple_mpi_communication_entrypoint():
    cl_ctx = cl.create_some_context()
    queue = cl.CommandQueue(cl_ctx)
    actx = PyOpenCLArrayContext(queue, force_device_scalars=True)

    from meshmode.distributed import MPIMeshDistributor, get_partition_by_pymetis
    from meshmode.mesh import BTAG_ALL

    from mpi4py import MPI
    comm = MPI.COMM_WORLD
    num_parts = comm.Get_size()

    mesh_dist = MPIMeshDistributor(comm)

    if mesh_dist.is_mananger_rank():
        from meshmode.mesh.generation import generate_regular_rect_mesh
        mesh = generate_regular_rect_mesh(a=(-1,)*2,
                                          b=(1,)*2,
                                          nelements_per_axis=(2,)*2)

        part_per_element = get_partition_by_pymetis(mesh, num_parts)

        local_mesh = mesh_dist.send_mesh_parts(mesh, part_per_element, num_parts)
    else:
        local_mesh = mesh_dist.receive_mesh_part()

    dcoll = DiscretizationCollection(actx, local_mesh, order=5,
            mpi_communicator=comm)

    x = thaw(dcoll.nodes(), actx)
    myfunc = actx.np.sin(np.dot(x, [2, 3]))

    from grudge.dof_desc import as_dofdesc

    dd_int = as_dofdesc("int_faces")
    dd_vol = as_dofdesc("vol")
    dd_af = as_dofdesc("all_faces")

    all_faces_func = op.project(dcoll, dd_vol, dd_af, myfunc)
    int_faces_func = op.project(dcoll, dd_vol, dd_int, myfunc)
    bdry_faces_func = op.project(dcoll, BTAG_ALL, dd_af,
                                 op.project(dcoll, dd_vol, BTAG_ALL, myfunc))

    hopefully_zero = (
        op.project(
            dcoll, "int_faces", "all_faces",
            dcoll.opposite_face_connection()(int_faces_func)
        )
        + sum(op.project(dcoll, tpair.dd, "all_faces", tpair.int)
              for tpair in op.cross_rank_trace_pairs(dcoll, myfunc))
    ) - (all_faces_func - bdry_faces_func)

    error = actx.to_numpy(flat_norm(hopefully_zero, ord=np.inf))

    print(__file__)
    with np.printoptions(threshold=100000000, suppress=True):
        logger.debug(hopefully_zero)
    logger.info("error: %.5e", error)

    assert error < 1e-14
예제 #7
0
def test_flatten_unflatten(actx_factory):
    actx = actx_factory()

    ambient_dim = 2
    from meshmode.mesh.generation import generate_regular_rect_mesh
    mesh = generate_regular_rect_mesh(a=(-0.5, ) * ambient_dim,
                                      b=(+0.5, ) * ambient_dim,
                                      n=(3, ) * ambient_dim,
                                      order=1)
    discr = Discretization(actx, mesh, PolynomialWarpAndBlendGroupFactory(3))
    a = np.random.randn(discr.ndofs)

    from meshmode.dof_array import flatten, unflatten
    a_round_trip = actx.to_numpy(
        flatten(unflatten(actx, discr, actx.from_numpy(a))))
    assert np.array_equal(a, a_round_trip)

    from meshmode.dof_array import flatten_to_numpy, unflatten_from_numpy
    a_round_trip = flatten_to_numpy(actx, unflatten_from_numpy(actx, discr, a))
    assert np.array_equal(a, a_round_trip)

    x = thaw(discr.nodes(), actx)
    avg_mass = DOFArray(
        actx,
        tuple([(np.pi + actx.zeros((grp.nelements, 1), a.dtype))
               for grp in discr.groups]))

    c = MyContainer(name="flatten",
                    mass=avg_mass,
                    momentum=make_obj_array([x, x, x]),
                    enthalpy=x)

    from meshmode.dof_array import unflatten_like
    c_round_trip = unflatten_like(actx, flatten(c), c)
    assert flat_norm(c - c_round_trip) < 1.0e-8
예제 #8
0
def simple_mpi_communication_entrypoint():
    cl_ctx = cl.create_some_context()
    queue = cl.CommandQueue(cl_ctx)
    actx = PyOpenCLArrayContext(queue)

    from meshmode.distributed import MPIMeshDistributor, get_partition_by_pymetis

    from mpi4py import MPI
    comm = MPI.COMM_WORLD
    num_parts = comm.Get_size()

    mesh_dist = MPIMeshDistributor(comm)

    if mesh_dist.is_mananger_rank():
        from meshmode.mesh.generation import generate_regular_rect_mesh
        mesh = generate_regular_rect_mesh(a=(-1, ) * 2,
                                          b=(1, ) * 2,
                                          n=(3, ) * 2)

        part_per_element = get_partition_by_pymetis(mesh, num_parts)

        local_mesh = mesh_dist.send_mesh_parts(mesh, part_per_element,
                                               num_parts)
    else:
        local_mesh = mesh_dist.receive_mesh_part()

    vol_discr = DGDiscretizationWithBoundaries(actx,
                                               local_mesh,
                                               order=5,
                                               mpi_communicator=comm)

    sym_x = sym.nodes(local_mesh.dim)
    myfunc_symb = sym.sin(np.dot(sym_x, [2, 3]))
    myfunc = bind(vol_discr, myfunc_symb)(actx)

    sym_all_faces_func = sym.cse(
        sym.project("vol", "all_faces")(sym.var("myfunc")))
    sym_int_faces_func = sym.cse(
        sym.project("vol", "int_faces")(sym.var("myfunc")))
    sym_bdry_faces_func = sym.cse(
        sym.project(sym.BTAG_ALL,
                    "all_faces")(sym.project("vol",
                                             sym.BTAG_ALL)(sym.var("myfunc"))))

    bound_face_swap = bind(
        vol_discr,
        sym.project("int_faces", "all_faces")(
            sym.OppositeInteriorFaceSwap("int_faces")(sym_int_faces_func)) -
        (sym_all_faces_func - sym_bdry_faces_func))

    hopefully_zero = bound_face_swap(myfunc=myfunc)
    error = flat_norm(hopefully_zero, np.inf)

    print(__file__)
    with np.printoptions(threshold=100000000, suppress=True):
        logger.debug(hopefully_zero)
    logger.info("error: %.5e", error)

    assert error < 1e-14
예제 #9
0
def test_elementwise_reductions(actx_factory):
    actx = actx_factory()

    from mesh_data import BoxMeshBuilder
    builder = BoxMeshBuilder(ambient_dim=1)

    nelements = 4
    mesh = builder.get_mesh(nelements, builder.mesh_order)
    dcoll = DiscretizationCollection(actx, mesh, order=builder.order)
    x = thaw(dcoll.nodes(), actx)

    def f(x):
        return actx.np.sin(x[0])

    field = f(x)
    mins = []
    maxs = []
    sums = []
    for gidx, grp_f in enumerate(field):
        min_res = np.empty(grp_f.shape)
        max_res = np.empty(grp_f.shape)
        sum_res = np.empty(grp_f.shape)
        for eidx in range(dcoll._volume_discr.groups[gidx].nelements):
            element_data = actx.to_numpy(grp_f[eidx])
            min_res[eidx, :] = np.min(element_data)
            max_res[eidx, :] = np.max(element_data)
            sum_res[eidx, :] = np.sum(element_data)
        mins.append(actx.from_numpy(min_res))
        maxs.append(actx.from_numpy(max_res))
        sums.append(actx.from_numpy(sum_res))

    from meshmode.dof_array import DOFArray, flat_norm

    ref_mins = DOFArray(actx, data=tuple(mins))
    ref_maxs = DOFArray(actx, data=tuple(maxs))
    ref_sums = DOFArray(actx, data=tuple(sums))

    elem_mins = op.elementwise_min(dcoll, field)
    elem_maxs = op.elementwise_max(dcoll, field)
    elem_sums = op.elementwise_sum(dcoll, field)

    assert flat_norm(elem_mins - ref_mins, ord=np.inf) < 1.e-15
    assert flat_norm(elem_maxs - ref_maxs, ord=np.inf) < 1.e-15
    assert flat_norm(elem_sums - ref_sums, ord=np.inf) < 1.e-15
예제 #10
0
def test_modal_coefficients_by_projection(actx_factory, quad_group_factory):
    group_cls = SimplexElementGroup
    modal_group_factory = ModalSimplexGroupFactory
    actx = actx_factory()
    order = 10
    m_order = 5

    # Make a regular rectangle mesh
    mesh = mgen.generate_regular_rect_mesh(a=(0, 0),
                                           b=(5, 3),
                                           npoints_per_axis=(10, 6),
                                           order=order,
                                           group_cls=group_cls)

    # Make discretizations
    nodal_disc = Discretization(actx, mesh, quad_group_factory(order))
    modal_disc = Discretization(actx, mesh, modal_group_factory(m_order))

    # Make connections one using quadrature projection
    nodal_to_modal_conn_quad = NodalToModalDiscretizationConnection(
        nodal_disc, modal_disc, allow_approximate_quad=True)

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

    x_nodal = thaw(nodal_disc.nodes()[0], actx)
    nodal_f = f(x_nodal)

    # Compute modal coefficients we expect to get
    import modepy as mp

    grp, = nodal_disc.groups
    shape = mp.Simplex(grp.dim)
    space = mp.space_for_shape(shape, order=m_order)
    basis = mp.orthonormal_basis_for_space(space, shape)
    quad = grp.quadrature_rule()

    nodal_f_data = actx.to_numpy(nodal_f[0])
    vdm = mp.vandermonde(basis.functions, quad.nodes)
    w_diag = np.diag(quad.weights)

    modal_data = []
    for _, nodal_data in enumerate(nodal_f_data):
        # Compute modal data in each element: V.T * W * nodal_data
        elem_modal_f = np.dot(vdm.T, np.dot(w_diag, nodal_data))
        modal_data.append(elem_modal_f)

    modal_data = actx.from_numpy(np.asarray(modal_data))
    modal_f_expected = DOFArray(actx, data=(modal_data, ))

    # Map nodal coefficients using the quadrature-based projection
    modal_f_computed = nodal_to_modal_conn_quad(nodal_f)

    err = flat_norm(modal_f_expected - modal_f_computed)

    assert err <= 1e-13
예제 #11
0
    def run(nelements, order):
        discr = create_discretization(actx,
                                      ndim,
                                      nelements=nelements,
                                      order=order,
                                      mesh_name=mesh_name)

        threshold = 1.0
        connections = []
        conn = create_refined_connection(actx, discr, threshold=threshold)
        connections.append(conn)
        if ndim == 2:
            # NOTE: additional refinement makes the 3D meshes explode in size
            conn = create_refined_connection(actx,
                                             conn.to_discr,
                                             threshold=threshold)
            connections.append(conn)
            conn = create_refined_connection(actx,
                                             conn.to_discr,
                                             threshold=threshold)
            connections.append(conn)

        from meshmode.discretization.connection import \
                ChainedDiscretizationConnection
        chained = ChainedDiscretizationConnection(connections)
        from meshmode.discretization.connection import \
                L2ProjectionInverseDiscretizationConnection
        reverse = L2ProjectionInverseDiscretizationConnection(chained)

        # create test vector
        from_nodes = thaw(chained.from_discr.nodes(), actx)
        to_nodes = thaw(chained.to_discr.nodes(), actx)

        from_x = 0
        to_x = 0
        for d in range(ndim):
            from_x = from_x + actx.np.cos(from_nodes[d])**(d + 1)
            to_x = to_x + actx.np.cos(to_nodes[d])**(d + 1)

        from_interp = reverse(to_x)

        return (1.0 / nelements, flat_norm(from_interp - from_x, np.inf) /
                flat_norm(from_x, np.inf))
예제 #12
0
def test_sanity_qhull_nd(actx_factory, dim, order):
    pytest.importorskip("scipy")

    logging.basicConfig(level=logging.INFO)
    actx = actx_factory()

    from scipy.spatial import Delaunay  # pylint: disable=no-name-in-module
    verts = np.random.rand(1000, dim)
    dtri = Delaunay(verts)

    # pylint: disable=no-member
    from meshmode.mesh.io import from_vertices_and_simplices
    mesh = from_vertices_and_simplices(dtri.points.T,
                                       dtri.simplices,
                                       fix_orientation=True)

    from meshmode.discretization import Discretization
    low_discr = Discretization(actx, mesh,
                               PolynomialEquidistantSimplexGroupFactory(order))
    high_discr = Discretization(
        actx, mesh, PolynomialEquidistantSimplexGroupFactory(order + 1))

    from meshmode.discretization.connection import make_same_mesh_connection
    cnx = make_same_mesh_connection(actx, high_discr, low_discr)

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

    x_low = thaw(low_discr.nodes()[0], actx)
    f_low = f(x_low)

    x_high = thaw(high_discr.nodes()[0], actx)
    f_high_ref = f(x_high)

    f_high_num = cnx(f_low)

    err = (flat_norm(f_high_ref - f_high_num, np.inf) /
           flat_norm(f_high_ref, np.inf))

    print(err)
    assert err < 1e-2
예제 #13
0
def test_container_norm(actx_factory, ord):
    actx = actx_factory()

    ary_dof, ary_of_dofs, mat_of_dofs, dc_of_dofs = _get_test_containers(actx)

    from pytools.obj_array import make_obj_array
    c = MyContainer(name="hey",
                    mass=1,
                    momentum=make_obj_array([2, 3]),
                    enthalpy=5)
    n1 = actx.np.linalg.norm(make_obj_array([c, c]), ord)
    n2 = np.linalg.norm([1, 2, 3, 5] * 2, ord)

    assert abs(n1 - n2) < 1e-12
    assert abs(flat_norm(ary_dof, ord) -
               actx.np.linalg.norm(ary_dof, ord)) < 1e-12
예제 #14
0
def test_inverse_modal_connections(actx_factory, nodal_group_factory):

    if nodal_group_factory is LegendreGaussLobattoTensorProductGroupFactory:
        group_cls = TensorProductElementGroup
        modal_group_factory = ModalTensorProductGroupFactory
    else:
        group_cls = SimplexElementGroup
        modal_group_factory = ModalSimplexGroupFactory

    actx = actx_factory()
    order = 4

    def f(x):
        return 2 * actx.np.sin(20 * x) + 0.5 * actx.np.cos(10 * x)

    # Make a regular rectangle mesh
    mesh = mgen.generate_regular_rect_mesh(a=(0, 0),
                                           b=(5, 3),
                                           npoints_per_axis=(10, 6),
                                           order=order,
                                           group_cls=group_cls)

    # Make discretizations
    nodal_disc = Discretization(actx, mesh, nodal_group_factory(order))
    modal_disc = Discretization(actx, mesh, modal_group_factory(order))

    # Make connections
    nodal_to_modal_conn = NodalToModalDiscretizationConnection(
        nodal_disc, modal_disc)
    modal_to_nodal_conn = ModalToNodalDiscretizationConnection(
        modal_disc, nodal_disc)

    x_nodal = thaw(nodal_disc.nodes()[0], actx)
    nodal_f = f(x_nodal)

    # Map nodal coefficients of f to modal coefficients
    modal_f = nodal_to_modal_conn(nodal_f)
    # Now map the modal coefficients back to nodal
    nodal_f_2 = modal_to_nodal_conn(modal_f)

    # This error should be small since we composed a map with
    # its inverse
    err = flat_norm(nodal_f - nodal_f_2)

    assert err <= 1e-13
예제 #15
0
def test_inverse_modal_connections_quadgrid(actx_factory):
    actx = actx_factory()
    order = 5

    def f(x):
        return 1 + 2 * x + 3 * x**2

    # Make a regular rectangle mesh
    mesh = mgen.generate_regular_rect_mesh(
        a=(0, 0),
        b=(5, 3),
        npoints_per_axis=(10, 6),
        order=order,
        group_cls=QuadratureSimplexGroupFactory.mesh_group_class)

    dcoll = DiscretizationCollection(
        actx,
        mesh,
        discr_tag_to_group_factory={
            dof_desc.DISCR_TAG_BASE:
            PolynomialWarpAndBlend2DRestrictingGroupFactory(order),
            dof_desc.DISCR_TAG_QUAD:
            QuadratureSimplexGroupFactory(2 * order)
        })

    # Use dof descriptors on the quadrature grid
    dd_modal = dof_desc.DD_VOLUME_MODAL
    dd_quad = dof_desc.DOFDesc(dof_desc.DTAG_VOLUME_ALL,
                               dof_desc.DISCR_TAG_QUAD)

    x_quad = thaw(dcoll.discr_from_dd(dd_quad).nodes()[0], actx)
    quad_f = f(x_quad)

    # Map nodal coefficients of f to modal coefficients
    forward_conn = dcoll.connection_from_dds(dd_quad, dd_modal)
    modal_f = forward_conn(quad_f)
    # Now map the modal coefficients back to nodal
    backward_conn = dcoll.connection_from_dds(dd_modal, dd_quad)
    quad_f_2 = backward_conn(modal_f)

    # This error should be small since we composed a map with
    # its inverse
    err = flat_norm(quad_f - quad_f_2)

    assert err <= 1e-11
예제 #16
0
def test_quadrature_based_modal_connection_reverse(actx_factory,
                                                   quad_group_factory):

    group_cls = SimplexElementGroup
    modal_group_factory = ModalSimplexGroupFactory
    actx = actx_factory()
    order = 10
    m_order = 5

    # Make a regular rectangle mesh
    mesh = mgen.generate_regular_rect_mesh(a=(0, 0),
                                           b=(5, 3),
                                           npoints_per_axis=(10, 6),
                                           order=order,
                                           group_cls=group_cls)

    # Make discretizations
    nodal_disc = Discretization(actx, mesh, quad_group_factory(order))
    modal_disc = Discretization(actx, mesh, modal_group_factory(m_order))

    # Make connections one using quadrature projection
    nodal_to_modal_conn_quad = NodalToModalDiscretizationConnection(
        nodal_disc, modal_disc)

    # And the reverse connection
    modal_to_nodal_conn = ModalToNodalDiscretizationConnection(
        modal_disc, nodal_disc)

    def f(x):
        return 1 + 2 * x + 3 * x**2

    x_nodal = thaw(nodal_disc.nodes()[0], actx)
    nodal_f = f(x_nodal)

    # Map nodal coefficients using the quadrature-based projection
    modal_f_quad = nodal_to_modal_conn_quad(nodal_f)

    # Back to nodal
    nodal_f_computed = modal_to_nodal_conn(modal_f_quad)

    err = flat_norm(nodal_f - nodal_f_computed)

    assert err <= 1e-11
예제 #17
0
def test_tri_diff_mat(ctx_factory, dim, order=4):
    """Check differentiation matrix along the coordinate axes on a disk

    Uses sines as the function to differentiate.
    """

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

    from meshmode.mesh.generation import generate_regular_rect_mesh

    from pytools.convergence import EOCRecorder
    axis_eoc_recs = [EOCRecorder() for axis in range(dim)]

    for n in [10, 20]:
        mesh = generate_regular_rect_mesh(a=(-0.5, ) * dim,
                                          b=(0.5, ) * dim,
                                          n=(n, ) * dim,
                                          order=4)

        discr = DGDiscretizationWithBoundaries(actx, mesh, order=4)
        nabla = sym.nabla(dim)

        for axis in range(dim):
            x = sym.nodes(dim)

            f = bind(discr, sym.sin(3 * x[axis]))(actx)
            df = bind(discr, 3 * sym.cos(3 * x[axis]))(actx)

            sym_op = nabla[axis](sym.var("f"))
            bound_op = bind(discr, sym_op)
            df_num = bound_op(f=f)

            linf_error = flat_norm(df_num - df, np.Inf)
            axis_eoc_recs[axis].add_data_point(1 / n, linf_error)

    for axis, eoc_rec in enumerate(axis_eoc_recs):
        logger.info("axis %d\n%s", axis, eoc_rec)
        assert eoc_rec.order_estimate() >= order
예제 #18
0
def test_inverse_modal_connections(actx_factory, nodal_group_factory):
    actx = actx_factory()
    order = 4

    def f(x):
        return 2 * actx.np.sin(20 * x) + 0.5 * actx.np.cos(10 * x)

    # Make a regular rectangle mesh
    mesh = mgen.generate_regular_rect_mesh(
        a=(0, 0),
        b=(5, 3),
        npoints_per_axis=(10, 6),
        order=order,
        group_cls=nodal_group_factory.mesh_group_class)

    dcoll = DiscretizationCollection(actx,
                                     mesh,
                                     discr_tag_to_group_factory={
                                         dof_desc.DISCR_TAG_BASE:
                                         nodal_group_factory(order)
                                     })

    dd_modal = dof_desc.DD_VOLUME_MODAL
    dd_volume = dof_desc.DD_VOLUME

    x_nodal = thaw(dcoll.discr_from_dd(dd_volume).nodes()[0], actx)
    nodal_f = f(x_nodal)

    # Map nodal coefficients of f to modal coefficients
    forward_conn = dcoll.connection_from_dds(dd_volume, dd_modal)
    modal_f = forward_conn(nodal_f)
    # Now map the modal coefficients back to nodal
    backward_conn = dcoll.connection_from_dds(dd_modal, dd_volume)
    nodal_f_2 = backward_conn(modal_f)

    # This error should be small since we composed a map with
    # its inverse
    err = flat_norm(nodal_f - nodal_f_2)

    assert err <= 1e-13
예제 #19
0
def test_tri_diff_mat(actx_factory, dim, order=4):
    """Check differentiation matrix along the coordinate axes on a disk

    Uses sines as the function to differentiate.
    """

    actx = actx_factory()

    from pytools.convergence import EOCRecorder
    axis_eoc_recs = [EOCRecorder() for axis in range(dim)]

    def f(x, axis):
        return actx.np.sin(3 * x[axis])

    def df(x, axis):
        return 3 * actx.np.cos(3 * x[axis])

    for n in [4, 8, 16]:
        mesh = mgen.generate_regular_rect_mesh(a=(-0.5, ) * dim,
                                               b=(0.5, ) * dim,
                                               nelements_per_axis=(n, ) * dim,
                                               order=4)

        dcoll = DiscretizationCollection(actx, mesh, order=4)
        volume_discr = dcoll.discr_from_dd(dof_desc.DD_VOLUME)
        x = thaw(volume_discr.nodes(), actx)

        for axis in range(dim):
            df_num = op.local_grad(dcoll, f(x, axis))[axis]
            df_volm = df(x, axis)

            linf_error = flat_norm(df_num - df_volm, ord=np.inf)
            axis_eoc_recs[axis].add_data_point(1 / n,
                                               actx.to_numpy(linf_error))

    for axis, eoc_rec in enumerate(axis_eoc_recs):
        logger.info("axis %d\n%s", axis, eoc_rec)
        assert eoc_rec.order_estimate() > order - 0.25
예제 #20
0
def test_inverse_metric(ctx_factory, dim):
    cl_ctx = ctx_factory()
    queue = cl.CommandQueue(cl_ctx)
    actx = PyOpenCLArrayContext(queue)

    from meshmode.mesh.generation import generate_regular_rect_mesh
    mesh = generate_regular_rect_mesh(a=(-0.5, ) * dim,
                                      b=(0.5, ) * dim,
                                      n=(6, ) * dim,
                                      order=4)

    def m(x):
        result = np.empty_like(x)
        result[0] = (1.5 * x[0] + np.cos(x[0]) + 0.1 * np.sin(10 * x[1]))
        result[1] = (0.05 * np.cos(10 * x[0]) + 1.3 * x[1] + np.sin(x[1]))
        if len(x) == 3:
            result[2] = x[2]
        return result

    from meshmode.mesh.processing import map_mesh
    mesh = map_mesh(mesh, m)

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

    sym_op = (sym.forward_metric_derivative_mat(mesh.dim).dot(
        sym.inverse_metric_derivative_mat(mesh.dim)).reshape(-1))

    op = bind(discr, sym_op)
    mat = op(actx).reshape(mesh.dim, mesh.dim)

    for i in range(mesh.dim):
        for j in range(mesh.dim):
            tgt = 1 if i == j else 0

            err = flat_norm(mat[i, j] - tgt, np.inf)
            logger.info("error[%d, %d]: %.5e", i, j, err)
            assert err < 1.0e-12, (i, j, err)
예제 #21
0
def test_diffusion_compare_to_nodal_dg(actx_factory,
                                       problem,
                                       order,
                                       print_err=False):
    """Compares diffusion operator to Hesthaven/Warburton Nodal-DG code."""
    pytest.importorskip("oct2py")

    actx = actx_factory()

    p = problem

    assert p.dim == 1
    assert p.alpha == 1.

    from meshmode.interop.nodal_dg import download_nodal_dg_if_not_present
    download_nodal_dg_if_not_present()

    sym_diffusion_u = sym_diffusion(p.dim, p.alpha, p.sym_u)

    for n in [4, 8, 16, 32, 64]:
        mesh = p.get_mesh(n)

        from meshmode.interop.nodal_dg import NodalDGContext
        with NodalDGContext("./nodal-dg/Codes1.1") as ndgctx:
            ndgctx.set_mesh(mesh, order=order)

            t = 1.23456789

            from grudge.eager import EagerDGDiscretization
            discr_mirgecom = EagerDGDiscretization(actx, mesh, order=order)
            nodes_mirgecom = thaw(actx, discr_mirgecom.nodes())

            def sym_eval_mirgecom(expr):
                return sym.EvaluationMapper({
                    "x": nodes_mirgecom,
                    "t": t
                })(expr)

            u_mirgecom = sym_eval_mirgecom(p.sym_u)

            diffusion_u_mirgecom = diffusion_operator(
                discr_mirgecom,
                alpha=p.alpha,
                boundaries=p.get_boundaries(discr_mirgecom, actx, t),
                u=u_mirgecom)

            discr_ndg = ndgctx.get_discr(actx)
            nodes_ndg = thaw(actx, discr_ndg.nodes())

            def sym_eval_ndg(expr):
                return sym.EvaluationMapper({"x": nodes_ndg, "t": t})(expr)

            u_ndg = sym_eval_ndg(p.sym_u)

            ndgctx.push_dof_array("u", u_ndg)
            ndgctx.octave.push("t", t)
            ndgctx.octave.eval("[rhs] = HeatCRHS1D(u,t)", verbose=False)
            diffusion_u_ndg = ndgctx.pull_dof_array(actx, "rhs")

            err = (flat_norm(diffusion_u_mirgecom - diffusion_u_ndg, np.inf) /
                   flat_norm(diffusion_u_ndg, np.inf))

            if print_err:
                diffusion_u_exact = sym_eval_mirgecom(sym_diffusion_u)
                err_exact = (flat_norm(
                    diffusion_u_mirgecom - diffusion_u_exact, np.inf) /
                             flat_norm(diffusion_u_exact, np.inf))
                print(err, err_exact)

            assert err < 1e-9
예제 #22
0
def test_partition_interpolation(ctx_factory, dim, mesh_pars,
                                 num_parts, num_groups, part_method):
    np.random.seed(42)
    group_factory = PolynomialWarpAndBlendGroupFactory
    cl_ctx = ctx_factory()
    queue = cl.CommandQueue(cl_ctx)
    actx = PyOpenCLArrayContext(queue)

    order = 4

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

    for n in mesh_pars:
        from meshmode.mesh.generation import generate_warped_rect_mesh
        base_mesh = generate_warped_rect_mesh(dim, order=order, n=n)

        if num_groups > 1:
            from meshmode.mesh.processing import split_mesh_groups
            # Group every Nth element
            element_flags = np.arange(base_mesh.nelements,
                        dtype=base_mesh.element_id_dtype) % num_groups
            mesh = split_mesh_groups(base_mesh, element_flags)
        else:
            mesh = base_mesh

        if part_method == "random":
            part_per_element = np.random.randint(num_parts, size=mesh.nelements)
        else:
            pytest.importorskip('pymetis')

            from meshmode.distributed import get_partition_by_pymetis
            part_per_element = get_partition_by_pymetis(mesh, num_parts,
                    connectivity=part_method)

        from meshmode.mesh.processing import partition_mesh
        part_meshes = [
            partition_mesh(mesh, part_per_element, i)[0] for i in range(num_parts)]

        connected_parts = set()
        for i_local_part, part_mesh in enumerate(part_meshes):
            from meshmode.distributed import get_connected_partitions
            neighbors = get_connected_partitions(part_mesh)
            for i_remote_part in neighbors:
                connected_parts.add((i_local_part, i_remote_part))

        from meshmode.discretization import Discretization
        vol_discrs = [Discretization(actx, part_meshes[i], group_factory(order))
                        for i in range(num_parts)]

        from meshmode.mesh import BTAG_PARTITION
        from meshmode.discretization.connection import (make_face_restriction,
                                                        make_partition_connection,
                                                        check_connection)

        for i_local_part, i_remote_part in connected_parts:
            # Mark faces within local_mesh that are connected to remote_mesh
            local_bdry_conn = make_face_restriction(actx, vol_discrs[i_local_part],
                                                    group_factory(order),
                                                    BTAG_PARTITION(i_remote_part))

            # Mark faces within remote_mesh that are connected to local_mesh
            remote_bdry_conn = make_face_restriction(actx, vol_discrs[i_remote_part],
                                                     group_factory(order),
                                                     BTAG_PARTITION(i_local_part))

            bdry_nelements = sum(
                    grp.nelements for grp in local_bdry_conn.to_discr.groups)
            remote_bdry_nelements = sum(
                    grp.nelements for grp in remote_bdry_conn.to_discr.groups)
            assert bdry_nelements == remote_bdry_nelements, \
                    "partitions do not have the same number of connected elements"

            # Gather just enough information for the connection
            local_bdry = local_bdry_conn.to_discr
            local_mesh = part_meshes[i_local_part]
            local_adj_groups = [local_mesh.facial_adjacency_groups[i][None]
                                for i in range(len(local_mesh.groups))]
            local_batches = [local_bdry_conn.groups[i].batches
                                for i in range(len(local_mesh.groups))]
            local_from_elem_faces = [[batch.to_element_face
                                            for batch in grp_batches]
                                        for grp_batches in local_batches]
            local_from_elem_indices = [[batch.to_element_indices.get(queue=queue)
                                            for batch in grp_batches]
                                        for grp_batches in local_batches]

            remote_bdry = remote_bdry_conn.to_discr
            remote_mesh = part_meshes[i_remote_part]
            remote_adj_groups = [remote_mesh.facial_adjacency_groups[i][None]
                                for i in range(len(remote_mesh.groups))]
            remote_batches = [remote_bdry_conn.groups[i].batches
                                for i in range(len(remote_mesh.groups))]
            remote_from_elem_faces = [[batch.to_element_face
                                            for batch in grp_batches]
                                        for grp_batches in remote_batches]
            remote_from_elem_indices = [[batch.to_element_indices.get(queue=queue)
                                            for batch in grp_batches]
                                        for grp_batches in remote_batches]

            # Connect from remote_mesh to local_mesh
            remote_to_local_conn = make_partition_connection(
                    actx, local_bdry_conn, i_local_part, remote_bdry,
                    remote_adj_groups, remote_from_elem_faces,
                    remote_from_elem_indices)

            # Connect from local mesh to remote mesh
            local_to_remote_conn = make_partition_connection(
                    actx, remote_bdry_conn, i_remote_part, local_bdry,
                    local_adj_groups, local_from_elem_faces,
                    local_from_elem_indices)

            check_connection(actx, remote_to_local_conn)
            check_connection(actx, local_to_remote_conn)

            true_local_points = f(thaw(actx, local_bdry.nodes()[0]))
            remote_points = local_to_remote_conn(true_local_points)
            local_points = remote_to_local_conn(remote_points)

            err = flat_norm(true_local_points - local_points, np.inf)

            # Can't currently expect exact results due to limitations of
            # interpolation 'snapping' in DirectDiscretizationConnection's
            # _resample_point_pick_indices
            assert err < 1e-11
예제 #23
0
def test_boundary_interpolation(actx_factory, group_factory, boundary_tag,
                                mesh_name, dim, mesh_pars, per_face_groups):
    if (group_factory is LegendreGaussLobattoTensorProductGroupFactory
            and mesh_name == "blob"):
        pytest.skip("tensor products not implemented on blobs")

    actx = actx_factory()

    if group_factory is LegendreGaussLobattoTensorProductGroupFactory:
        group_cls = TensorProductElementGroup
    else:
        group_cls = SimplexElementGroup

    from meshmode.discretization import Discretization
    from meshmode.discretization.connection import (make_face_restriction,
                                                    check_connection)

    from pytools.convergence import EOCRecorder
    eoc_rec = EOCRecorder()

    order = 4

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

    for mesh_par in mesh_pars:
        # {{{ get mesh

        if mesh_name == "blob":
            assert dim == 2

            h = float(mesh_par)

            #from meshmode.mesh.io import generate_gmsh, FileSource
            # print("BEGIN GEN")
            # mesh = generate_gmsh(
            #         FileSource("blob-2d.step"), 2, order=order,
            #         force_ambient_dim=2,
            #         other_options=[
            #             "-string", "Mesh.CharacteristicLengthMax = %s;" % h]
            #         )
            # print("END GEN")
            from meshmode.mesh.io import read_gmsh
            mesh = read_gmsh("blob2d-order%d-h%s.msh" % (order, mesh_par),
                             force_ambient_dim=2)
        elif mesh_name == "warp":
            mesh = mgen.generate_warped_rect_mesh(dim,
                                                  order=order,
                                                  nelements_side=mesh_par,
                                                  group_cls=group_cls)

            h = 1 / mesh_par

        elif mesh_name == "rect":
            mesh = mgen.generate_regular_rect_mesh(
                a=(0, ) * dim,
                b=(1, ) * dim,
                order=order,
                nelements_per_axis=(mesh_par, ) * dim,
                group_cls=group_cls)

            h = 1 / mesh_par
        else:
            raise ValueError("mesh_name not recognized")

        # }}}

        vol_discr = Discretization(actx, mesh, group_factory(order))
        print("h=%s -> %d elements" %
              (h, sum(mgrp.nelements for mgrp in mesh.groups)))

        x = thaw(vol_discr.nodes()[0], actx)
        vol_f = f(x)

        bdry_connection = make_face_restriction(
            actx,
            vol_discr,
            group_factory(order),
            boundary_tag,
            per_face_groups=per_face_groups)
        check_connection(actx, bdry_connection)
        bdry_discr = bdry_connection.to_discr

        bdry_x = thaw(bdry_discr.nodes()[0], actx)
        bdry_f = f(bdry_x)
        bdry_f_2 = bdry_connection(vol_f)

        if mesh_name == "blob" and dim == 2 and mesh.nelements < 500:
            from meshmode.discretization.connection.direct import \
                    make_direct_full_resample_matrix
            mat = actx.to_numpy(
                make_direct_full_resample_matrix(actx, bdry_connection))
            bdry_f_2_by_mat = mat.dot(flatten_to_numpy(actx, vol_f))

            mat_error = la.norm(
                flatten_to_numpy(actx, bdry_f_2) - bdry_f_2_by_mat)
            assert mat_error < 1e-14, mat_error

        err = flat_norm(bdry_f - bdry_f_2, np.inf)
        eoc_rec.add_data_point(h, err)

    order_slack = 0.75 if mesh_name == "blob" else 0.5
    print(eoc_rec)
    assert (eoc_rec.order_estimate() >= order - order_slack
            or eoc_rec.max_error() < 3.6e-13)
예제 #24
0
def test_mesh_multiple_groups(actx_factory, ambient_dim, visualize=False):
    actx = actx_factory()

    order = 4

    mesh = mgen.generate_regular_rect_mesh(a=(-0.5, ) * ambient_dim,
                                           b=(0.5, ) * ambient_dim,
                                           nelements_per_axis=(8, ) *
                                           ambient_dim,
                                           order=order)
    assert len(mesh.groups) == 1

    from meshmode.mesh.processing import split_mesh_groups
    element_flags = np.any(
        mesh.vertices[0, mesh.groups[0].vertex_indices] < 0.0,
        axis=1).astype(np.int64)
    mesh = split_mesh_groups(mesh, element_flags)

    assert len(mesh.groups) == 2  # pylint: disable=no-member
    assert mesh.facial_adjacency_groups
    assert mesh.nodal_adjacency

    if visualize and ambient_dim == 2:
        from meshmode.mesh.visualization import draw_2d_mesh
        draw_2d_mesh(mesh,
                     draw_vertex_numbers=False,
                     draw_element_numbers=True,
                     draw_face_numbers=False,
                     set_bounding_box=True)

        import matplotlib.pyplot as plt
        plt.savefig("test_mesh_multiple_groups_2d_elements.png", dpi=300)

    from meshmode.discretization import Discretization
    discr = Discretization(actx, mesh,
                           PolynomialWarpAndBlendGroupFactory(order))

    if visualize:
        group_id = discr.empty(actx, dtype=np.int32)
        for igrp, vec in enumerate(group_id):
            vec.fill(igrp)

        from meshmode.discretization.visualization import make_visualizer
        vis = make_visualizer(actx, discr, vis_order=order)
        vis.write_vtk_file("mesh_multiple_groups.vtu",
                           [("group_id", group_id)],
                           overwrite=True)

    # check face restrictions
    from meshmode.discretization.connection import (
        make_face_restriction, make_face_to_all_faces_embedding,
        make_opposite_face_connection, check_connection)
    for boundary_tag in [BTAG_ALL, FACE_RESTR_INTERIOR, FACE_RESTR_ALL]:
        conn = make_face_restriction(
            actx,
            discr,
            group_factory=PolynomialWarpAndBlendGroupFactory(order),
            boundary_tag=boundary_tag,
            per_face_groups=False)
        check_connection(actx, conn)

        bdry_f = conn.to_discr.zeros(actx) + 1

        if boundary_tag == FACE_RESTR_INTERIOR:
            opposite = make_opposite_face_connection(actx, conn)
            check_connection(actx, opposite)

            op_bdry_f = opposite(bdry_f)
            error = flat_norm(bdry_f - op_bdry_f, np.inf)
            assert error < 1.0e-11, error

        if boundary_tag == FACE_RESTR_ALL:
            embedding = make_face_to_all_faces_embedding(
                actx, conn, conn.to_discr)
            check_connection(actx, embedding)

            em_bdry_f = embedding(bdry_f)
            error = flat_norm(bdry_f - em_bdry_f)
            assert error < 1.0e-11, error

    # check some derivatives (nb: flatten is a generator)
    import pytools
    ref_axes = pytools.flatten([[i] for i in range(ambient_dim)])

    from meshmode.discretization import num_reference_derivative
    x = thaw(discr.nodes(), actx)
    num_reference_derivative(discr, ref_axes, x[0])
예제 #25
0
def test_partition_interpolation(actx_factory, dim, mesh_pars,
                                 num_parts, num_groups, part_method):
    np.random.seed(42)
    group_factory = PolynomialWarpAndBlendGroupFactory
    actx = actx_factory()

    order = 4

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

    for n in mesh_pars:
        from meshmode.mesh.generation import generate_warped_rect_mesh
        base_mesh = generate_warped_rect_mesh(dim, order=order, nelements_side=n)

        if num_groups > 1:
            from meshmode.mesh.processing import split_mesh_groups
            # Group every Nth element
            element_flags = np.arange(base_mesh.nelements,
                        dtype=base_mesh.element_id_dtype) % num_groups
            mesh = split_mesh_groups(base_mesh, element_flags)
        else:
            mesh = base_mesh

        if part_method == "random":
            part_per_element = np.random.randint(num_parts, size=mesh.nelements)
        else:
            pytest.importorskip("pymetis")

            from meshmode.distributed import get_partition_by_pymetis
            part_per_element = get_partition_by_pymetis(mesh, num_parts,
                    connectivity=part_method)

        from meshmode.mesh.processing import partition_mesh
        part_meshes = [
            partition_mesh(mesh, part_per_element, i)[0] for i in range(num_parts)]

        connected_parts = set()
        for i_local_part, part_mesh in enumerate(part_meshes):
            from meshmode.distributed import get_connected_partitions
            neighbors = get_connected_partitions(part_mesh)
            for i_remote_part in neighbors:
                connected_parts.add((i_local_part, i_remote_part))

        from meshmode.discretization import Discretization
        vol_discrs = [Discretization(actx, part_meshes[i], group_factory(order))
                        for i in range(num_parts)]

        from meshmode.mesh import BTAG_PARTITION
        from meshmode.discretization.connection import (make_face_restriction,
                                                        make_partition_connection,
                                                        check_connection)

        for i_local_part, i_remote_part in connected_parts:
            # Mark faces within local_mesh that are connected to remote_mesh
            local_bdry_conn = make_face_restriction(actx, vol_discrs[i_local_part],
                                                    group_factory(order),
                                                    BTAG_PARTITION(i_remote_part))

            # Mark faces within remote_mesh that are connected to local_mesh
            remote_bdry_conn = make_face_restriction(actx, vol_discrs[i_remote_part],
                                                     group_factory(order),
                                                     BTAG_PARTITION(i_local_part))

            bdry_nelements = sum(
                    grp.nelements for grp in local_bdry_conn.to_discr.groups)
            remote_bdry_nelements = sum(
                    grp.nelements for grp in remote_bdry_conn.to_discr.groups)
            assert bdry_nelements == remote_bdry_nelements, \
                    "partitions do not have the same number of connected elements"

            local_bdry = local_bdry_conn.to_discr

            remote_bdry = remote_bdry_conn.to_discr

            from meshmode.distributed import make_remote_group_infos
            remote_to_local_conn = make_partition_connection(
                    actx,
                    local_bdry_conn=local_bdry_conn,
                    i_local_part=i_local_part,
                    remote_bdry_discr=remote_bdry,
                    remote_group_infos=make_remote_group_infos(
                        actx, remote_bdry_conn))

            # Connect from local mesh to remote mesh
            local_to_remote_conn = make_partition_connection(
                    actx,
                    local_bdry_conn=remote_bdry_conn,
                    i_local_part=i_remote_part,
                    remote_bdry_discr=local_bdry,
                    remote_group_infos=make_remote_group_infos(
                        actx, local_bdry_conn))

            check_connection(actx, remote_to_local_conn)
            check_connection(actx, local_to_remote_conn)

            true_local_points = f(thaw(local_bdry.nodes()[0], actx))
            remote_points = local_to_remote_conn(true_local_points)
            local_points = remote_to_local_conn(remote_points)

            err = flat_norm(true_local_points - local_points, np.inf)

            # Can't currently expect exact results due to limitations of
            # interpolation "snapping" in DirectDiscretizationConnection's
            # _resample_point_pick_indices
            assert err < 1e-11
예제 #26
0
def test_opposite_face_interpolation(actx_factory, group_factory, mesh_name,
                                     dim, mesh_pars):
    if (group_factory is LegendreGaussLobattoTensorProductGroupFactory
            and mesh_name in ["segment", "blob"]):
        pytest.skip("tensor products not implemented on blobs")

    logging.basicConfig(level=logging.INFO)
    actx = actx_factory()

    if group_factory is LegendreGaussLobattoTensorProductGroupFactory:
        group_cls = TensorProductElementGroup
    else:
        group_cls = SimplexElementGroup

    from meshmode.discretization import Discretization
    from meshmode.discretization.connection import (
        make_face_restriction, make_opposite_face_connection, check_connection)

    from pytools.convergence import EOCRecorder
    eoc_rec = EOCRecorder()

    order = 5

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

    for mesh_par in mesh_pars:
        # {{{ get mesh

        if mesh_name == "segment":
            assert dim == 1

            mesh = mgen.generate_box_mesh([np.linspace(-0.5, 0.5, mesh_par)],
                                          order=order,
                                          group_cls=group_cls)
            h = 1.0 / mesh_par
        elif mesh_name == "blob":
            assert dim == 2

            h = mesh_par

            from meshmode.mesh.io import generate_gmsh, FileSource
            print("BEGIN GEN")
            mesh = generate_gmsh(
                FileSource("blob-2d.step"),
                2,
                order=order,
                force_ambient_dim=2,
                other_options=[
                    "-string",
                    "Mesh.CharacteristicLengthMax = %s;" % h
                ],
                target_unit="MM",
            )
            print("END GEN")
        elif mesh_name == "warp":
            mesh = mgen.generate_warped_rect_mesh(dim,
                                                  order=order,
                                                  nelements_side=mesh_par,
                                                  group_cls=group_cls)

            h = 1 / mesh_par
        else:
            raise ValueError("mesh_name not recognized")

        # }}}

        vol_discr = Discretization(actx, mesh, group_factory(order))
        print("h=%s -> %d elements" %
              (h, sum(mgrp.nelements for mgrp in mesh.groups)))

        bdry_connection = make_face_restriction(actx, vol_discr,
                                                group_factory(order),
                                                FACE_RESTR_INTERIOR)
        bdry_discr = bdry_connection.to_discr

        opp_face = make_opposite_face_connection(actx, bdry_connection)
        check_connection(actx, opp_face)

        bdry_x = thaw(bdry_discr.nodes()[0], actx)
        bdry_f = f(bdry_x)
        bdry_f_2 = opp_face(bdry_f)

        err = flat_norm(bdry_f - bdry_f_2, np.inf)
        eoc_rec.add_data_point(h, err)

    print(eoc_rec)
    assert (eoc_rec.order_estimate() >= order - 0.5
            or eoc_rec.max_error() < 1.7e-13)
예제 #27
0
def test_all_faces_interpolation(actx_factory, group_factory, mesh_name, dim,
                                 mesh_pars, per_face_groups):
    if (group_factory is LegendreGaussLobattoTensorProductGroupFactory
            and mesh_name == "blob"):
        pytest.skip("tensor products not implemented on blobs")

    actx = actx_factory()

    if group_factory is LegendreGaussLobattoTensorProductGroupFactory:
        group_cls = TensorProductElementGroup
    else:
        group_cls = SimplexElementGroup

    from meshmode.discretization import Discretization
    from meshmode.discretization.connection import (
        make_face_restriction, make_face_to_all_faces_embedding,
        check_connection)

    from pytools.convergence import EOCRecorder
    eoc_rec = EOCRecorder()

    order = 4

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

    for mesh_par in mesh_pars:
        # {{{ get mesh

        if mesh_name == "blob":
            assert dim == 2

            h = mesh_par

            from meshmode.mesh.io import generate_gmsh, FileSource
            print("BEGIN GEN")
            mesh = generate_gmsh(
                FileSource("blob-2d.step"),
                2,
                order=order,
                force_ambient_dim=2,
                other_options=[
                    "-string",
                    "Mesh.CharacteristicLengthMax = %s;" % h
                ],
                target_unit="MM",
            )
            print("END GEN")
        elif mesh_name == "warp":
            mesh = mgen.generate_warped_rect_mesh(dim,
                                                  order=4,
                                                  nelements_side=mesh_par,
                                                  group_cls=group_cls)

            h = 1 / mesh_par
        else:
            raise ValueError("mesh_name not recognized")

        # }}}

        vol_discr = Discretization(actx, mesh, group_factory(order))
        print("h=%s -> %d elements" %
              (h, sum(mgrp.nelements for mgrp in mesh.groups)))

        all_face_bdry_connection = make_face_restriction(
            actx,
            vol_discr,
            group_factory(order),
            FACE_RESTR_ALL,
            per_face_groups=per_face_groups)
        all_face_bdry_discr = all_face_bdry_connection.to_discr

        for ito_grp, ceg in enumerate(all_face_bdry_connection.groups):
            for ibatch, batch in enumerate(ceg.batches):
                assert np.array_equal(
                    actx.to_numpy(actx.thaw(batch.from_element_indices)),
                    np.arange(vol_discr.mesh.nelements))

                if per_face_groups:
                    assert ito_grp == batch.to_element_face
                else:
                    assert ibatch == batch.to_element_face

        all_face_x = thaw(all_face_bdry_discr.nodes()[0], actx)
        all_face_f = f(all_face_x)

        all_face_f_2 = all_face_bdry_discr.zeros(actx)

        for boundary_tag in [
                BTAG_ALL,
                FACE_RESTR_INTERIOR,
        ]:
            bdry_connection = make_face_restriction(
                actx,
                vol_discr,
                group_factory(order),
                boundary_tag,
                per_face_groups=per_face_groups)
            bdry_discr = bdry_connection.to_discr

            bdry_x = thaw(bdry_discr.nodes()[0], actx)
            bdry_f = f(bdry_x)

            all_face_embedding = make_face_to_all_faces_embedding(
                actx, bdry_connection, all_face_bdry_discr)

            check_connection(actx, all_face_embedding)

            all_face_f_2 = all_face_f_2 + all_face_embedding(bdry_f)

        err = flat_norm(all_face_f - all_face_f_2, np.inf)
        eoc_rec.add_data_point(h, err)

    print(eoc_rec)
    assert (eoc_rec.order_estimate() >= order - 0.5
            or eoc_rec.max_error() < 1e-14)
def test_refinement_connection(actx_factory,
                               refiner_cls,
                               group_factory,
                               mesh_name,
                               dim,
                               mesh_pars,
                               mesh_order,
                               refine_flags,
                               visualize=False):
    from random import seed
    seed(13)

    # Discretization order
    order = 5

    actx = actx_factory()

    from meshmode.discretization import Discretization
    from meshmode.discretization.connection import (make_refinement_connection,
                                                    check_connection)

    from pytools.convergence import EOCRecorder
    eoc_rec = EOCRecorder()

    for mesh_par in mesh_pars:
        # {{{ get mesh

        if mesh_name == "circle":
            assert dim == 1
            h = 1 / mesh_par
            mesh = make_curve_mesh(partial(ellipse, 1),
                                   np.linspace(0, 1, mesh_par + 1),
                                   order=mesh_order)
        elif mesh_name == "blob":
            if mesh_order == 5:
                pytest.xfail(
                    "https://gitlab.tiker.net/inducer/meshmode/issues/2")
            assert dim == 2
            mesh = get_blob_mesh(mesh_par, mesh_order)
            h = float(mesh_par)
        elif mesh_name == "warp":
            from meshmode.mesh.generation import generate_warped_rect_mesh
            mesh = generate_warped_rect_mesh(dim, order=mesh_order, n=mesh_par)
            h = 1 / mesh_par
        else:
            raise ValueError("mesh_name not recognized")

        # }}}

        from meshmode.mesh.processing import find_bounding_box
        mesh_bbox_low, mesh_bbox_high = find_bounding_box(mesh)
        mesh_ext = mesh_bbox_high - mesh_bbox_low

        def f(x):
            result = 1
            if mesh_name == "blob":
                factor = 15
            else:
                factor = 9

            for iaxis in range(len(x)):
                result = result * actx.np.sin(factor *
                                              (x[iaxis] / mesh_ext[iaxis]))

            return result

        discr = Discretization(actx, mesh, group_factory(order))

        refiner = refiner_cls(mesh)
        flags = refine_flags(mesh)
        refiner.refine(flags)

        connection = make_refinement_connection(actx, refiner, discr,
                                                group_factory(order))
        check_connection(actx, connection)

        fine_discr = connection.to_discr

        x = thaw(actx, discr.nodes())
        x_fine = thaw(actx, fine_discr.nodes())
        f_coarse = f(x)
        f_interp = connection(f_coarse)
        f_true = f(x_fine)

        if visualize == "dots":
            import matplotlib.pyplot as plt
            x = x.get(actx.queue)
            err = np.array(
                np.log10(1e-16 + np.abs((f_interp - f_true).get(actx.queue))),
                dtype=float)
            import matplotlib.cm as cm
            cmap = cm.ScalarMappable(cmap=cm.jet)
            cmap.set_array(err)
            plt.scatter(x[0], x[1], c=cmap.to_rgba(err), s=20, cmap=cmap)
            plt.colorbar(cmap)
            plt.show()

        elif visualize == "vtk":
            from meshmode.discretization.visualization import make_visualizer
            fine_vis = make_visualizer(actx, fine_discr, mesh_order)

            fine_vis.write_vtk_file(
                "refine-fine-%s-%dd-%s.vtu" % (mesh_name, dim, mesh_par), [
                    ("f_interp", f_interp),
                    ("f_true", f_true),
                ])

        err = flat_norm(f_interp - f_true, np.inf)
        eoc_rec.add_data_point(h, err)

    order_slack = 0.5
    if mesh_name == "blob" and order > 1:
        order_slack = 1

    print(eoc_rec)
    assert (eoc_rec.order_estimate() >= order - order_slack
            or eoc_rec.max_error() < 1e-14)
예제 #29
0
def test_modal_truncation(actx_factory, nodal_group_factory, dim, mesh_pars):

    if nodal_group_factory is LegendreGaussLobattoTensorProductGroupFactory:
        group_cls = TensorProductElementGroup
        modal_group_factory = ModalTensorProductGroupFactory
    else:
        group_cls = SimplexElementGroup
        modal_group_factory = ModalSimplexGroupFactory

    actx = actx_factory()
    order = 5
    truncated_order = 3

    from pytools.convergence import EOCRecorder
    eoc_rec = EOCRecorder()

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

    for mesh_par in mesh_pars:

        # Make the mesh
        mesh = mgen.generate_warped_rect_mesh(dim,
                                              order=order,
                                              nelements_side=mesh_par,
                                              group_cls=group_cls)
        h = 1 / mesh_par

        # Make discretizations
        nodal_disc = Discretization(actx, mesh, nodal_group_factory(order))
        modal_disc = Discretization(actx, mesh, modal_group_factory(order))

        # Make connections (nodal -> modal)
        nodal_to_modal_conn = NodalToModalDiscretizationConnection(
            nodal_disc, modal_disc)

        # And the reverse connection (modal -> nodal)
        modal_to_nodal_conn = ModalToNodalDiscretizationConnection(
            modal_disc, nodal_disc)

        x_nodal = thaw(nodal_disc.nodes()[0], actx)
        nodal_f = f(x_nodal)

        # Map to modal
        modal_f = nodal_to_modal_conn(nodal_f)

        # Now we compute the basis function indices corresonding
        # to modes > truncated_order
        mgrp, = modal_disc.groups
        mgrp_mode_ids = mgrp.basis_obj().mode_ids
        truncation_matrix = np.identity(len(mgrp_mode_ids))
        for mode_idx, mode_id in enumerate(mgrp_mode_ids):
            if sum(mode_id) > truncated_order:
                truncation_matrix[mode_idx, mode_idx] = 0

        # Zero out the modal coefficients corresponding to
        # the targeted modes.
        modal_f_data = actx.to_numpy(modal_f[0])
        num_elem, _ = modal_f_data.shape
        for el_idx in range(num_elem):
            modal_f_data[el_idx] = np.dot(truncation_matrix,
                                          modal_f_data[el_idx])

        modal_f_data = actx.from_numpy(modal_f_data)
        modal_f_truncated = DOFArray(actx, data=(modal_f_data, ))

        # Now map truncated modal coefficients back to nodal
        nodal_f_truncated = modal_to_nodal_conn(modal_f_truncated)

        err = flat_norm(nodal_f - nodal_f_truncated)
        eoc_rec.add_data_point(h, err)
        threshold_lower = 0.8 * truncated_order
        threshold_upper = 1.2 * truncated_order

    assert threshold_upper >= eoc_rec.order_estimate() >= threshold_lower