예제 #1
0
def test_simp_mass_and_diff_matrices_by_monomial():
    """Verify simplicial mass and differentiation matrices using monomials"""

    from hedge.discretization.local import IntervalDiscretization, TriangleDiscretization, TetrahedronDiscretization
    from pytools import generate_nonnegative_integer_tuples_summing_to_at_most

    from operator import add, mul

    thresh = 1e-13

    from numpy import dot

    for el in [IntervalDiscretization(5), TriangleDiscretization(3), TetrahedronDiscretization(5)]:
        for comb in generate_nonnegative_integer_tuples_summing_to_at_most(el.order, el.dimensions):
            ones = numpy.ones((el.node_count(),))
            unodes = el.unit_nodes()
            f = Monomial(comb)
            f_n = numpy.array([f(x) for x in unodes])
            int_f_n = dot(ones, dot(el.mass_matrix(), f_n))
            int_f = f.simplex_integral()
            err = la.norm(int_f - int_f_n)
            if err > thresh:
                print "bad", el, comb, int_f, int_f_n, err
            assert err < thresh

            dmats = el.differentiation_matrices()
            for i in range(el.dimensions):
                df = f.diff(i)
                df = numpy.array([df(x) for x in unodes]) / 2
                df_n = dot(dmats[i], f_n)
                err = la.norm(df - df_n, numpy.Inf)
                if err > thresh:
                    print "bad-diff", comb, i, err
                assert err < thresh
예제 #2
0
    def face_basis(self):
        from pytools import generate_nonnegative_integer_tuples_summing_to_at_most

        return [TriangleBasisFunction(*mode_tup)
                for mode_tup in
                generate_nonnegative_integer_tuples_summing_to_at_most(
                    self.order, self.dimensions-1)]
예제 #3
0
    def face_basis(self):
        from pytools import generate_nonnegative_integer_tuples_summing_to_at_most

        return [
            TriangleBasisFunction(*mode_tup) for mode_tup in
            generate_nonnegative_integer_tuples_summing_to_at_most(
                self.order, self.dimensions - 1)
        ]
예제 #4
0
    def lexicographic_node_tuples(self):
        from pytools import \
                generate_nonnegative_integer_tuples_summing_to_at_most
        result = list(
            generate_nonnegative_integer_tuples_summing_to_at_most(
                self.order, self.dimensions))

        assert len(result) == self.node_count()
        return result
예제 #5
0
파일: local.py 프로젝트: paulcazeaux/hedge
    def generate_mode_identifiers(self):
        """Generate a hashable objects identifying each basis function,
        in order.

        The output from this function is required to be in the same order
        as that of L{basis_functions} and L{grad_basis_functions}, and thereby
        also from L{vandermonde}.
        """
        from pytools import generate_nonnegative_integer_tuples_summing_to_at_most

        return generate_nonnegative_integer_tuples_summing_to_at_most(self.order, self.dimensions)
예제 #6
0
    def generate_mode_identifiers(self):
        """Generate a hashable objects identifying each basis function,
        in order.

        The output from this function is required to be in the same order
        as that of L{basis_functions} and L{grad_basis_functions}, and thereby
        also from L{vandermonde}.
        """
        from pytools import \
                generate_nonnegative_integer_tuples_summing_to_at_most

        return generate_nonnegative_integer_tuples_summing_to_at_most(
            self.order, self.dimensions)
예제 #7
0
파일: local.py 프로젝트: inducer/pydgeon
    def node_tuples(self):
        """Generate tuples enumerating the node indices present
        in this element. Each tuple has a length equal to the dimension
        of the element. The tuples constituents are non-negative integers
        whose sum is less than or equal to the order of the element.

        The order in which these nodes are generated dictates the local
        node numbering.
        """
        from pytools import \
                generate_nonnegative_integer_tuples_summing_to_at_most
        return list(
                generate_nonnegative_integer_tuples_summing_to_at_most(
                    self.N, self.dimensions))
예제 #8
0
    def lexicographic_node_tuples(self):
        """Generate tuples enumerating the node indices present
        in this element. Each tuple has a length equal to the dimension
        of the element. The tuples constituents are non-negative integers
        whose sum is less than or equal to the order of the element.
        """
        from pytools import \
                generate_nonnegative_integer_tuples_summing_to_at_most
        result = list(
                generate_nonnegative_integer_tuples_summing_to_at_most(
                    self.order, self.dimensions))

        assert len(result) == self.node_count()
        return result
예제 #9
0
파일: local.py 프로젝트: yjobic/pydgeon
    def node_tuples(self):
        """Generate tuples enumerating the node indices present
        in this element. Each tuple has a length equal to the dimension
        of the element. The tuples constituents are non-negative integers
        whose sum is less than or equal to the order of the element.

        The order in which these nodes are generated dictates the local
        node numbering.
        """
        from pytools import \
                generate_nonnegative_integer_tuples_summing_to_at_most
        return list(
            generate_nonnegative_integer_tuples_summing_to_at_most(
                self.N, self.dimensions))
예제 #10
0
    def lexicographic_node_tuples(self):
        """Generate tuples enumerating the node indices present
        in this element. Each tuple has a length equal to the dimension
        of the element. The tuples constituents are non-negative integers
        whose sum is less than or equal to the order of the element.
        """
        from pytools import \
                generate_nonnegative_integer_tuples_summing_to_at_most
        result = list(
            generate_nonnegative_integer_tuples_summing_to_at_most(
                self.order, self.dimensions))

        assert len(result) == self.node_count()
        return result
예제 #11
0
파일: local.py 프로젝트: paulcazeaux/hedge
    def face_indices(self):
        """Return a list of face index lists. Each face index list contains
        the local node numbers of the nodes on that face.
        """

        node_tup_to_idx = dict((ituple, idx) for idx, ituple in enumerate(self.node_tuples()))

        from pytools import generate_nonnegative_integer_tuples_summing_to_at_most

        enum_order_nodes_gen = generate_nonnegative_integer_tuples_summing_to_at_most(self.order, self.dimensions)

        faces = [[] for i in range(self.dimensions + 1)]

        for node_tup in enum_order_nodes_gen:
            for face_idx in self.faces_for_node_tuple(node_tup):
                faces[face_idx].append(node_tup_to_idx[node_tup])

        return [tuple(fi) for fi in faces]
예제 #12
0
    def node_tuples(self):
        """Generate tuples enumerating the node indices present
        in this element. Each tuple has a length equal to the dimension
        of the element. The tuples constituents are non-negative integers
        whose sum is less than or equal to the order of the element.

        The order in which these nodes are generated dictates the local
        node numbering.
        """
        from pytools import \
                generate_nonnegative_integer_tuples_summing_to_at_most
        node_tups = list(
            generate_nonnegative_integer_tuples_summing_to_at_most(
                self.order, self.dimensions))

        if not self.fancy_node_ordering:
            return node_tups

        faces_to_nodes = {}
        for node_tup in node_tups:
            faces_to_nodes.setdefault(
                frozenset(self.faces_for_node_tuple(node_tup)),
                []).append(node_tup)

        result = []

        def add_face_nodes(faces):
            result.extend(faces_to_nodes.get(frozenset(faces), []))

        add_face_nodes([])
        add_face_nodes([0])
        add_face_nodes([0, 1])
        add_face_nodes([1])
        add_face_nodes([1, 2])
        add_face_nodes([2])
        add_face_nodes([0, 2])

        assert set(result) == set(node_tups)
        assert len(result) == len(node_tups)

        return result
예제 #13
0
    def node_tuples(self):
        """Generate tuples enumerating the node indices present
        in this element. Each tuple has a length equal to the dimension
        of the element. The tuples constituents are non-negative integers
        whose sum is less than or equal to the order of the element.

        The order in which these nodes are generated dictates the local
        node numbering.
        """
        from pytools import \
                generate_nonnegative_integer_tuples_summing_to_at_most
        node_tups = list(
                generate_nonnegative_integer_tuples_summing_to_at_most(
                    self.order, self.dimensions))

        if not self.fancy_node_ordering:
            return node_tups

        faces_to_nodes = {}
        for node_tup in node_tups:
            faces_to_nodes.setdefault(
                    frozenset(self.faces_for_node_tuple(node_tup)),
                    []).append(node_tup)

        result = []

        def add_face_nodes(faces):
            result.extend(faces_to_nodes.get(frozenset(faces), []))

        add_face_nodes([])
        add_face_nodes([0])
        add_face_nodes([0, 1])
        add_face_nodes([1])
        add_face_nodes([1, 2])
        add_face_nodes([2])
        add_face_nodes([0, 2])

        assert set(result) == set(node_tups)
        assert len(result) == len(node_tups)

        return result
예제 #14
0
def test_simp_cubature():
    """Check that Grundmann-Moeller cubature works as advertised"""
    from pytools import generate_nonnegative_integer_tuples_summing_to_at_most
    from hedge.quadrature import SimplexCubature
    from hedge.quadrature import (
            XiaoGimbutasSimplexCubature,
            SimplexCubature)
    from hedge.tools.mathematics import Monomial

    for cub_class in [
            XiaoGimbutasSimplexCubature,
            SimplexCubature]:
        for dim in range(2,3+1):
            for s in range(1, 3+1):
                cub = cub_class(s, dim)
                for comb in generate_nonnegative_integer_tuples_summing_to_at_most(
                        cub.exact_to, dim):
                    f = Monomial(comb)
                    i_f = cub(f)
                    err = abs(i_f - f.simplex_integral())
                    assert err < 6e-15
예제 #15
0
def test_simp_cubature():
    """Check that Grundmann-Moeller cubature works as advertised"""
    from pytools import generate_nonnegative_integer_tuples_summing_to_at_most
    from hedge.quadrature import SimplexCubature
    from hedge.quadrature import (
            XiaoGimbutasSimplexCubature,
            SimplexCubature)
    from hedge.tools.mathematics import Monomial

    for cub_class in [
            XiaoGimbutasSimplexCubature,
            SimplexCubature]:
        for dim in range(2,3+1):
            for s in range(1, 3+1):
                cub = cub_class(s, dim)
                for comb in generate_nonnegative_integer_tuples_summing_to_at_most(
                        cub.exact_to, dim):
                    f = Monomial(comb)
                    i_f = cub(f)
                    err = abs(i_f - f.simplex_integral())
                    assert err < 6e-15
예제 #16
0
def test_simp_mass_and_diff_matrices_by_monomial():
    """Verify simplicial mass and differentiation matrices using monomials"""

    from hedge.discretization.local import \
            IntervalDiscretization, \
            TriangleDiscretization, \
            TetrahedronDiscretization
    from pytools import generate_nonnegative_integer_tuples_summing_to_at_most

    thresh = 1e-13

    from numpy import dot
    for el in [
            IntervalDiscretization(5),
            TriangleDiscretization(3),
            TetrahedronDiscretization(5),
    ]:
        for comb in generate_nonnegative_integer_tuples_summing_to_at_most(
                el.order, el.dimensions):
            ones = numpy.ones((el.node_count(), ))
            unodes = el.unit_nodes()
            f = Monomial(comb)
            f_n = numpy.array([f(x) for x in unodes])
            int_f_n = dot(ones, dot(el.mass_matrix(), f_n))
            int_f = f.simplex_integral()
            err = la.norm(int_f - int_f_n)
            if err > thresh:
                print "bad", el, comb, int_f, int_f_n, err
            assert err < thresh

            dmats = el.differentiation_matrices()
            for i in range(el.dimensions):
                df = f.diff(i)
                df = numpy.array([df(x) for x in unodes]) / 2
                df_n = dot(dmats[i], f_n)
                err = la.norm(df - df_n, numpy.Inf)
                if err > thresh:
                    print "bad-diff", comb, i, err
                assert err < thresh
예제 #17
0
    def face_indices(self):
        """Return a list of face index lists. Each face index list contains
        the local node numbers of the nodes on that face.
        """

        node_tup_to_idx = dict(
            (ituple, idx) for idx, ituple in enumerate(self.node_tuples()))

        from pytools import \
                generate_nonnegative_integer_tuples_summing_to_at_most

        enum_order_nodes_gen = \
                generate_nonnegative_integer_tuples_summing_to_at_most(
                        self.order, self.dimensions)

        faces = [[] for i in range(self.dimensions + 1)]

        for node_tup in enum_order_nodes_gen:
            for face_idx in self.faces_for_node_tuple(node_tup):
                faces[face_idx].append(node_tup_to_idx[node_tup])

        return [tuple(fi) for fi in faces]
예제 #18
0
    def node_tuples(self):
        """Generate tuples enumerating the node indices present
        in this element. Each tuple has a length equal to the dimension
        of the element. The tuples constituents are non-negative integers
        whose sum is less than or equal to the order of the element.

        The order in which these nodes are generated dictates the local
        node numbering.
        """
        from pytools import \
                generate_nonnegative_integer_tuples_summing_to_at_most
        node_tups = list(
                generate_nonnegative_integer_tuples_summing_to_at_most(
                    self.order, self.dimensions))

        if False:
            # hand-tuned node order
            faces_to_nodes = {}
            for node_tup in node_tups:
                faces_to_nodes.setdefault(
                        frozenset(self.faces_for_node_tuple(node_tup)),
                        []).append(node_tup)

            result = []

            def add_face_nodes(faces):
                result.extend(faces_to_nodes.get(frozenset(faces), []))

            add_face_nodes([0, 3])
            add_face_nodes([0])
            add_face_nodes([0, 2])
            add_face_nodes([0, 1])
            add_face_nodes([0, 1, 2])
            add_face_nodes([0, 1, 3])
            add_face_nodes([0, 2, 3])
            add_face_nodes([1])
            add_face_nodes([1, 2])
            add_face_nodes([1, 2, 3])
            add_face_nodes([1, 3])
            add_face_nodes([2])
            add_face_nodes([2, 3])
            add_face_nodes([3])
            add_face_nodes([])

            assert set(result) == set(node_tups)
            assert len(result) == len(node_tups)

        if True:
            # average-sort heuristic node order
            from pytools import average

            def order_number_for_node_tuple(nt):
                faces = self.faces_for_node_tuple(nt)
                if not faces:
                    return -1
                elif len(faces) >= 3:
                    return 1000
                else:
                    return average(faces)

            def cmp_node_tuples(nt1, nt2):
                return cmp(
                        order_number_for_node_tuple(nt1),
                        order_number_for_node_tuple(nt2))

            result = node_tups
            #result.sort(cmp_node_tuples)

        #for i, nt in enumerate(result):
            #fnt = self.faces_for_node_tuple(nt)
            #print i, nt, fnt

        return result
예제 #19
0
    def node_tuples(self):
        """Generate tuples enumerating the node indices present
        in this element. Each tuple has a length equal to the dimension
        of the element. The tuples constituents are non-negative integers
        whose sum is less than or equal to the order of the element.

        The order in which these nodes are generated dictates the local
        node numbering.
        """
        from pytools import \
                generate_nonnegative_integer_tuples_summing_to_at_most
        node_tups = list(
            generate_nonnegative_integer_tuples_summing_to_at_most(
                self.order, self.dimensions))

        if False:
            # hand-tuned node order
            faces_to_nodes = {}
            for node_tup in node_tups:
                faces_to_nodes.setdefault(
                    frozenset(self.faces_for_node_tuple(node_tup)),
                    []).append(node_tup)

            result = []

            def add_face_nodes(faces):
                result.extend(faces_to_nodes.get(frozenset(faces), []))

            add_face_nodes([0, 3])
            add_face_nodes([0])
            add_face_nodes([0, 2])
            add_face_nodes([0, 1])
            add_face_nodes([0, 1, 2])
            add_face_nodes([0, 1, 3])
            add_face_nodes([0, 2, 3])
            add_face_nodes([1])
            add_face_nodes([1, 2])
            add_face_nodes([1, 2, 3])
            add_face_nodes([1, 3])
            add_face_nodes([2])
            add_face_nodes([2, 3])
            add_face_nodes([3])
            add_face_nodes([])

            assert set(result) == set(node_tups)
            assert len(result) == len(node_tups)

        if True:
            # average-sort heuristic node order
            from pytools import average

            def order_number_for_node_tuple(nt):
                faces = self.faces_for_node_tuple(nt)
                if not faces:
                    return -1
                elif len(faces) >= 3:
                    return 1000
                else:
                    return average(faces)

            def cmp_node_tuples(nt1, nt2):
                return cmp(order_number_for_node_tuple(nt1),
                           order_number_for_node_tuple(nt2))

            result = node_tups
            #result.sort(cmp_node_tuples)

        #for i, nt in enumerate(result):
        #fnt = self.faces_for_node_tuple(nt)
        #print i, nt, fnt

        return result