Esempio n. 1
0
def test_nodal_face_mass_matrix(dim, order=3):
    from modepy.tools import unit_vertices
    all_verts = unit_vertices(dim).T

    basis = mp.simplex_onb(dim, order)

    np.set_printoptions(linewidth=200)

    from modepy.matrices import nodal_face_mass_matrix
    volume_nodes = mp.warp_and_blend_nodes(dim, order)
    face_nodes = mp.warp_and_blend_nodes(dim - 1, order)

    for iface in range(dim + 1):
        verts = np.hstack([all_verts[:, :iface], all_verts[:, iface + 1:]])

        fmm = nodal_face_mass_matrix(basis, volume_nodes, face_nodes, order,
                                     verts)
        fmm2 = nodal_face_mass_matrix(basis, volume_nodes, face_nodes,
                                      order + 1, verts)

        assert la.norm(fmm - fmm2, np.inf) < 1e-11

        fmm[np.abs(fmm) < 1e-13] = 0

        print(fmm)
        nnz = np.sum(np.abs(fmm) > 0)
        print(nnz)

    print(
        mp.mass_matrix(
            mp.simplex_onb(dim - 1, order),
            mp.warp_and_blend_nodes(dim - 1, order),
        ))
Esempio n. 2
0
def test_nodal_face_mass_matrix(dim, order=3):
    from modepy.tools import unit_vertices
    all_verts = unit_vertices(dim).T

    basis = mp.simplex_onb(dim, order)

    np.set_printoptions(linewidth=200)

    from modepy.matrices import nodal_face_mass_matrix
    volume_nodes = mp.warp_and_blend_nodes(dim, order)
    face_nodes = mp.warp_and_blend_nodes(dim-1, order)

    for iface in range(dim+1):
        verts = np.hstack([all_verts[:, :iface], all_verts[:, iface+1:]])

        fmm = nodal_face_mass_matrix(basis, volume_nodes, face_nodes, order,
                verts)
        fmm2 = nodal_face_mass_matrix(basis, volume_nodes, face_nodes, order+1,
                verts)

        assert la.norm(fmm-fmm2, np.inf) < 1e-11

        fmm[np.abs(fmm) < 1e-13] = 0

        print(fmm)
        nnz = np.sum(np.abs(fmm) > 0)
        print(nnz)

    print(mp.mass_matrix(
        mp.simplex_onb(dim-1, order),
        mp.warp_and_blend_nodes(dim-1, order), ))
Esempio n. 3
0
    def __init__(self, cell):
        """
            :arg cell: a :class:`fiat.FIAT.reference_element.Simplex`.
        """
        # Ensure this cell is actually a simplex
        assert isinstance(cell, Simplex)

        super(SimplexCellAnalog, self).__init__(cell)

        # Stored as (dim, nunit_vertices)
        self._unit_vertices = tools.unit_vertices(cell.get_dimension()).T

        # Maps firedrake reference vertices to :mod:`meshmode`
        # unit vertices by x -> Ax + b, where A is :attr:`_mat`
        # and b is :attr:`_shift`
        reference_vertices = np.array(cell.vertices).T
        self._mat, self._shift = get_affine_mapping(reference_vertices,
                                                    self._unit_vertices)
Esempio n. 4
0
def test_modal_face_mass_matrix(dim, order=3):
    from modepy.tools import unit_vertices
    all_verts = unit_vertices(dim).T

    basis = mp.simplex_onb(dim, order)

    # np.set_printoptions(linewidth=200)

    from modepy.matrices import modal_face_mass_matrix
    for iface in range(dim + 1):
        verts = np.hstack([all_verts[:, :iface], all_verts[:, iface + 1:]])

        fmm = modal_face_mass_matrix(basis, order, verts)
        fmm2 = modal_face_mass_matrix(basis, order + 1, verts)

        assert la.norm(fmm - fmm2, np.inf) < 1e-11

        fmm[np.abs(fmm) < 1e-13] = 0

        print(fmm)
        nnz = np.sum(fmm > 0)
        print(nnz)
Esempio n. 5
0
def test_modal_face_mass_matrix(dim, order=3):
    from modepy.tools import unit_vertices
    all_verts = unit_vertices(dim).T

    basis = mp.simplex_onb(dim, order)

    # np.set_printoptions(linewidth=200)

    from modepy.matrices import modal_face_mass_matrix
    for iface in range(dim+1):
        verts = np.hstack([all_verts[:, :iface], all_verts[:, iface+1:]])

        fmm = modal_face_mass_matrix(basis, order, verts)
        fmm2 = modal_face_mass_matrix(basis, order+1, verts)

        assert la.norm(fmm-fmm2, np.inf) < 1e-11

        fmm[np.abs(fmm) < 1e-13] = 0

        print(fmm)
        nnz = np.sum(fmm > 0)
        print(nnz)
Esempio n. 6
0
def test_sanity_single_element(ctx_getter, dim, order, visualize=False):
    pytest.importorskip("pytential")

    cl_ctx = ctx_getter()
    queue = cl.CommandQueue(cl_ctx)

    from modepy.tools import unit_vertices
    vertices = unit_vertices(dim).T.copy()

    center = np.empty(dim, np.float64)
    center.fill(-0.5)

    import modepy as mp
    from meshmode.mesh import SimplexElementGroup, Mesh, BTAG_ALL
    mg = SimplexElementGroup(
        order=order,
        vertex_indices=np.arange(dim + 1, dtype=np.int32).reshape(1, -1),
        nodes=mp.warp_and_blend_nodes(dim, order).reshape(dim, 1, -1),
        dim=dim)

    mesh = Mesh(vertices, [mg],
                nodal_adjacency=None,
                facial_adjacency_groups=None)

    from meshmode.discretization import Discretization
    from meshmode.discretization.poly_element import \
            PolynomialWarpAndBlendGroupFactory
    vol_discr = Discretization(cl_ctx, mesh,
                               PolynomialWarpAndBlendGroupFactory(order + 3))

    # {{{ volume calculation check

    vol_x = vol_discr.nodes().with_queue(queue)

    vol_one = vol_x[0].copy()
    vol_one.fill(1)
    from pytential import norm, integral  # noqa

    from pytools import factorial
    true_vol = 1 / factorial(dim) * 2**dim

    comp_vol = integral(vol_discr, queue, vol_one)
    rel_vol_err = abs(true_vol - comp_vol) / true_vol

    assert rel_vol_err < 1e-12

    # }}}

    # {{{ boundary discretization

    from meshmode.discretization.connection import make_face_restriction
    bdry_connection = make_face_restriction(
        vol_discr, PolynomialWarpAndBlendGroupFactory(order + 3), BTAG_ALL)
    bdry_discr = bdry_connection.to_discr

    # }}}

    # {{{ visualizers

    from meshmode.discretization.visualization import make_visualizer
    #vol_vis = make_visualizer(queue, vol_discr, 4)
    bdry_vis = make_visualizer(queue, bdry_discr, 4)

    # }}}

    from pytential import bind, sym
    bdry_normals = bind(bdry_discr,
                        sym.normal(dim))(queue).as_vector(dtype=object)

    if visualize:
        bdry_vis.write_vtk_file("boundary.vtu",
                                [("bdry_normals", bdry_normals)])

    from pytential import bind, sym
    normal_outward_check = bind(
        bdry_discr,
        sym.normal(dim)
        | (sym.nodes(dim) + 0.5 * sym.ones_vec(dim)),
    )(queue).as_scalar() > 0

    assert normal_outward_check.get().all(), normal_outward_check.get()
Esempio n. 7
0
 def vertex_unit_coordinates(self):
     from modepy.tools import unit_vertices
     return unit_vertices(self.dim)
Esempio n. 8
0
 def vertex_unit_coordinates(self):
     from modepy.tools import unit_vertices
     return unit_vertices(self.dim)
Esempio n. 9
0
def test_sanity_single_element(ctx_getter, dim, order, visualize=False):
    pytest.importorskip("pytential")

    cl_ctx = ctx_getter()
    queue = cl.CommandQueue(cl_ctx)

    from modepy.tools import unit_vertices
    vertices = unit_vertices(dim).T.copy()

    center = np.empty(dim, np.float64)
    center.fill(-0.5)

    import modepy as mp
    from meshmode.mesh import SimplexElementGroup, Mesh, BTAG_ALL
    mg = SimplexElementGroup(
            order=order,
            vertex_indices=np.arange(dim+1, dtype=np.int32).reshape(1, -1),
            nodes=mp.warp_and_blend_nodes(dim, order).reshape(dim, 1, -1),
            dim=dim)

    mesh = Mesh(vertices, [mg], nodal_adjacency=None, facial_adjacency_groups=None)

    from meshmode.discretization import Discretization
    from meshmode.discretization.poly_element import \
            PolynomialWarpAndBlendGroupFactory
    vol_discr = Discretization(cl_ctx, mesh,
            PolynomialWarpAndBlendGroupFactory(order+3))

    # {{{ volume calculation check

    vol_x = vol_discr.nodes().with_queue(queue)

    vol_one = vol_x[0].copy()
    vol_one.fill(1)
    from pytential import norm, integral  # noqa

    from pytools import factorial
    true_vol = 1/factorial(dim) * 2**dim

    comp_vol = integral(vol_discr, queue, vol_one)
    rel_vol_err = abs(true_vol - comp_vol) / true_vol

    assert rel_vol_err < 1e-12

    # }}}

    # {{{ boundary discretization

    from meshmode.discretization.connection import make_face_restriction
    bdry_connection = make_face_restriction(
            vol_discr, PolynomialWarpAndBlendGroupFactory(order + 3),
            BTAG_ALL)
    bdry_discr = bdry_connection.to_discr

    # }}}

    # {{{ visualizers

    from meshmode.discretization.visualization import make_visualizer
    #vol_vis = make_visualizer(queue, vol_discr, 4)
    bdry_vis = make_visualizer(queue, bdry_discr, 4)

    # }}}

    from pytential import bind, sym
    bdry_normals = bind(bdry_discr, sym.normal())(queue).as_vector(dtype=object)

    if visualize:
        bdry_vis.write_vtk_file("boundary.vtu", [
            ("bdry_normals", bdry_normals)
            ])

    from pytential import bind, sym
    normal_outward_check = bind(bdry_discr,
            sym.normal()
            |
            (sym.Nodes() + 0.5*sym.ones_vec(dim)),
            )(queue).as_scalar() > 0

    assert normal_outward_check.get().all(), normal_outward_check.get()
Esempio n. 10
0
def get_affine_reference_simplex_mapping(ambient_dim, firedrake_to_meshmode=True):
    """
    Returns a function which takes a numpy array points
    on one reference cell and maps each
    point to another using a positive affine map.

    :arg ambient_dim: The spatial dimension
    :arg firedrake_to_meshmode: If true, the returned function maps from
        the firedrake reference element to
        meshmode, if false maps from
        meshmode to firedrake. More specifically,
        :mod:`firedrake` uses the standard :mod:`FIAT`
        simplex and :mod:`meshmode` uses
        :mod:`modepy`'s
        `unit coordinates <https://documen.tician.de/modepy/nodes.html>`_.
    :return: A function which takes a numpy array of *n* points with
             shape *(dim, n)* on one reference cell and maps
             each point to another using a positive affine map.
             Note that the returned function performs
             no input validation.
    """
    # validate input
    if not isinstance(ambient_dim, int):
        raise TypeError("'ambient_dim' must be an int, not "
                        f"'{type(ambient_dim)}'")
    if ambient_dim < 0:
        raise ValueError("'ambient_dim' must be non-negative")
    if not isinstance(firedrake_to_meshmode, bool):
        raise TypeError("'firedrake_to_meshmode' must be a bool, not "
                        f"'{type(firedrake_to_meshmode)}'")

    from FIAT.reference_element import ufc_simplex
    from modepy.tools import unit_vertices
    # Get the unit vertices from each system,
    # each stored with shape *(dim, nunit_vertices)*
    firedrake_unit_vertices = np.array(ufc_simplex(ambient_dim).vertices).T
    modepy_unit_vertices = unit_vertices(ambient_dim).T

    if firedrake_to_meshmode:
        from_verts = firedrake_unit_vertices
        to_verts = modepy_unit_vertices
    else:
        from_verts = modepy_unit_vertices
        to_verts = firedrake_unit_vertices

    # Compute matrix A and vector b so that A f_i + b -> t_i
    # for each "from" vertex f_i and corresponding "to" vertex t_i
    assert from_verts.shape == to_verts.shape
    dim, nvects = from_verts.shape

    # If we only have one vertex, have A = I and b = to_vert - from_vert
    if nvects == 1:
        shift = to_verts[:, 0] - from_verts[:, 0]

        def affine_map(points):
            return points + shift[:, np.newaxis]
    # Otherwise, we have to solve for A and b
    else:
        # span verts: v1 - v0, v2 - v0, ...
        from_span_verts = from_verts[:, 1:] - from_verts[:, 0, np.newaxis]
        to_span_verts = to_verts[:, 1:] - to_verts[:, 0, np.newaxis]
        # mat maps (fj - f0) -> (tj - t0), our "A"
        mat = la.solve(from_span_verts, to_span_verts)
        # A f0 + b -> t0 so b = t0 - A f0
        shift = to_verts[:, 0] - np.matmul(mat, from_verts[:, 0])

        # Explicitly ensure A is positive
        if la.det(mat) < 0:
            from meshmode.mesh.processing import get_simplex_element_flip_matrix
            flip_matrix = get_simplex_element_flip_matrix(1, to_verts)
            mat = np.matmul(flip_matrix, mat)

        def affine_map(points):
            return np.matmul(mat, points) + shift[:, np.newaxis]

    return affine_map