Пример #1
0
def test_barycentric_coordinate_map(dims):
    from random import Random
    rng = Random(17)

    n = 5
    unit = np.empty((dims, n))
    from modepy.tools import (
            pick_random_simplex_unit_coordinate,
            unit_to_barycentric,
            barycentric_to_unit,
            barycentric_to_equilateral,
            equilateral_to_unit,)

    for i in range(n):
        unit[:, i] = pick_random_simplex_unit_coordinate(rng, dims)

    bary = unit_to_barycentric(unit)
    assert (np.abs(np.sum(bary, axis=0) - 1) < 1e-15).all()
    assert (bary >= 0).all()
    unit2 = barycentric_to_unit(bary)
    assert la.norm(unit-unit2) < 1e-14

    equi = barycentric_to_equilateral(bary)
    unit3 = equilateral_to_unit(equi)
    assert la.norm(unit-unit3) < 1e-14
Пример #2
0
def test_barycentric_coordinate_map(dims):
    from random import Random
    rng = Random(17)

    n = 5
    unit = np.empty((dims, n))
    from modepy.tools import (
            pick_random_simplex_unit_coordinate,
            unit_to_barycentric,
            barycentric_to_unit,
            barycentric_to_equilateral,
            equilateral_to_unit,)

    for i in range(n):
        unit[:, i] = pick_random_simplex_unit_coordinate(rng, dims)

    bary = unit_to_barycentric(unit)
    assert (np.abs(np.sum(bary, axis=0) - 1) < 1e-15).all()
    assert (bary >= 0).all()
    unit2 = barycentric_to_unit(bary)
    assert la.norm(unit-unit2) < 1e-14

    equi = barycentric_to_equilateral(bary)
    unit3 = equilateral_to_unit(equi)
    assert la.norm(unit-unit3) < 1e-14
Пример #3
0
def get_simplex_element_flip_matrix(order, unit_nodes, permutation=None):
    """
    Generate a resampling matrix that corresponds to a
    permutation of the barycentric coordinates being applied.
    The default permutation is to swap the
    first two barycentric coordinates.

    :param order: The order of the function space on the simplex,
                 (see second argument in
                  :fun:`modepy.simplex_best_available_basis`)
    :param unit_nodes: A np array of unit nodes with shape
                       *(dim, nunit_nodes)*
    :param permutation: Either *None*, or a tuple of shape
                        storing a permutation:
                        the *i*th barycentric coordinate gets mapped to
                        the *permutation[i]*th coordinate.

    :return: A numpy array of shape *(nunit_nodes, nunit_nodes)*
             which, when its transpose is right-applied
             to the matrix of nodes (shaped *(dim, nunit_nodes)*),
             corresponds to the permutation being applied
    """
    from modepy.tools import barycentric_to_unit, unit_to_barycentric

    bary_unit_nodes = unit_to_barycentric(unit_nodes)

    flipped_bary_unit_nodes = bary_unit_nodes.copy()
    if permutation is None:
        flipped_bary_unit_nodes[0, :] = bary_unit_nodes[1, :]
        flipped_bary_unit_nodes[1, :] = bary_unit_nodes[0, :]
    else:
        flipped_bary_unit_nodes[permutation, :] = bary_unit_nodes
    flipped_unit_nodes = barycentric_to_unit(flipped_bary_unit_nodes)

    dim = unit_nodes.shape[0]
    shape = mp.Simplex(dim)
    space = mp.PN(dim, order)
    basis = mp.basis_for_space(space, shape)
    flip_matrix = mp.resampling_matrix(basis.functions, flipped_unit_nodes,
                                       unit_nodes)

    flip_matrix[np.abs(flip_matrix) < 1e-15] = 0

    # Flipping twice should be the identity
    if permutation is None:
        assert la.norm(
            np.dot(flip_matrix, flip_matrix) -
            np.eye(len(flip_matrix))) < 1e-13

    return flip_matrix
Пример #4
0
def flip_simplex_element_group(vertices, grp, grp_flip_flags):
    from modepy.tools import barycentric_to_unit, unit_to_barycentric

    from meshmode.mesh import SimplexElementGroup

    if not isinstance(grp, SimplexElementGroup):
        raise NotImplementedError(
            "flips only supported on "
            "exclusively SimplexElementGroup-based meshes")

    # Swap the first two vertices on elements to be flipped.

    new_vertex_indices = grp.vertex_indices.copy()
    new_vertex_indices[grp_flip_flags, 0] \
            = grp.vertex_indices[grp_flip_flags, 1]
    new_vertex_indices[grp_flip_flags, 1] \
            = grp.vertex_indices[grp_flip_flags, 0]

    # Generate a resampling matrix that corresponds to the
    # first two barycentric coordinates being swapped.

    bary_unit_nodes = unit_to_barycentric(grp.unit_nodes)

    flipped_bary_unit_nodes = bary_unit_nodes.copy()
    flipped_bary_unit_nodes[0, :] = bary_unit_nodes[1, :]
    flipped_bary_unit_nodes[1, :] = bary_unit_nodes[0, :]
    flipped_unit_nodes = barycentric_to_unit(flipped_bary_unit_nodes)

    flip_matrix = mp.resampling_matrix(
        mp.simplex_best_available_basis(grp.dim, grp.order),
        flipped_unit_nodes, grp.unit_nodes)

    flip_matrix[np.abs(flip_matrix) < 1e-15] = 0

    # Flipping twice should be the identity
    assert la.norm(
        np.dot(flip_matrix, flip_matrix) - np.eye(len(flip_matrix))) < 1e-13

    # Apply the flip matrix to the nodes.
    new_nodes = grp.nodes.copy()
    new_nodes[:, grp_flip_flags] = np.einsum("ij,dej->dei", flip_matrix,
                                             grp.nodes[:, grp_flip_flags])

    return SimplexElementGroup(grp.order,
                               new_vertex_indices,
                               new_nodes,
                               unit_nodes=grp.unit_nodes)
Пример #5
0
def flip_simplex_element_group(vertices, grp, grp_flip_flags):
    from modepy.tools import barycentric_to_unit, unit_to_barycentric

    from meshmode.mesh import SimplexElementGroup

    if not isinstance(grp, SimplexElementGroup):
        raise NotImplementedError("flips only supported on "
                "exclusively SimplexElementGroup-based meshes")

    # Swap the first two vertices on elements to be flipped.

    new_vertex_indices = grp.vertex_indices.copy()
    new_vertex_indices[grp_flip_flags, 0] \
            = grp.vertex_indices[grp_flip_flags, 1]
    new_vertex_indices[grp_flip_flags, 1] \
            = grp.vertex_indices[grp_flip_flags, 0]

    # Generate a resampling matrix that corresponds to the
    # first two barycentric coordinates being swapped.

    bary_unit_nodes = unit_to_barycentric(grp.unit_nodes)

    flipped_bary_unit_nodes = bary_unit_nodes.copy()
    flipped_bary_unit_nodes[0, :] = bary_unit_nodes[1, :]
    flipped_bary_unit_nodes[1, :] = bary_unit_nodes[0, :]
    flipped_unit_nodes = barycentric_to_unit(flipped_bary_unit_nodes)

    flip_matrix = mp.resampling_matrix(
            mp.simplex_best_available_basis(grp.dim, grp.order),
            flipped_unit_nodes, grp.unit_nodes)

    flip_matrix[np.abs(flip_matrix) < 1e-15] = 0

    # Flipping twice should be the identity
    assert la.norm(
            np.dot(flip_matrix, flip_matrix)
            - np.eye(len(flip_matrix))) < 1e-13

    # Apply the flip matrix to the nodes.
    new_nodes = grp.nodes.copy()
    new_nodes[:, grp_flip_flags] = np.einsum(
            "ij,dej->dei",
            flip_matrix, grp.nodes[:, grp_flip_flags])

    return SimplexElementGroup(
            grp.order, new_vertex_indices, new_nodes,
            unit_nodes=grp.unit_nodes)
Пример #6
0
    def flip_matrix(self):
        """
            :return: The matrix which should be applied to the
                     *(dim, nunitnodes)*-shaped array of nodes corresponding to
                     an element in order to change orientation - <-> +.

                     The matrix will be *(dim, dim)* and orthogonal with
                     *np.float64* type entries.
        """
        if self._flip_matrix is None:
            # This is very similar to :mod:`meshmode` in processing.py
            # the function :function:`from_simplex_element_group`, but
            # we needed to use firedrake nodes

            from modepy.tools import barycentric_to_unit, unit_to_barycentric

            # Generate a resampling matrix that corresponds to the
            # first two barycentric coordinates being swapped.

            bary_unit_nodes = unit_to_barycentric(self.unit_nodes())

            flipped_bary_unit_nodes = bary_unit_nodes.copy()
            flipped_bary_unit_nodes[0, :] = bary_unit_nodes[1, :]
            flipped_bary_unit_nodes[1, :] = bary_unit_nodes[0, :]
            flipped_unit_nodes = barycentric_to_unit(flipped_bary_unit_nodes)

            from modepy import resampling_matrix, simplex_best_available_basis

            flip_matrix = resampling_matrix(
                simplex_best_available_basis(self.dim(),
                                             self.analog().degree),
                flipped_unit_nodes, self.unit_nodes())

            flip_matrix[np.abs(flip_matrix) < 1e-15] = 0

            # Flipping twice should be the identity
            assert la.norm(
                np.dot(flip_matrix, flip_matrix) -
                np.eye(len(flip_matrix))) < 1e-13

            self._flip_matrix = flip_matrix

        return self._flip_matrix
Пример #7
0
def test_barycentric_coordinate_map(dims):
    n = 100
    from modepy.tools import (
        unit_to_barycentric,
        barycentric_to_unit,
        barycentric_to_equilateral,
        equilateral_to_unit,
    )

    rng = np.random.Generator(np.random.PCG64(17))
    unit = nd.random_nodes_for_shape(shp.Simplex(dims), n, rng=rng)

    bary = unit_to_barycentric(unit)
    assert (np.abs(np.sum(bary, axis=0) - 1) < 1e-15).all()
    assert (bary >= 0).all()
    unit2 = barycentric_to_unit(bary)
    assert la.norm(unit - unit2) < 1e-14

    equi = barycentric_to_equilateral(bary)
    unit3 = equilateral_to_unit(equi)
    assert la.norm(unit - unit3) < 1e-14