def test_projection():
    """Test whether projection between different orders works"""

    from hedge.mesh.generator import make_disk_mesh
    from hedge.discretization import Projector
    from hedge.discretization.local import TriangleDiscretization
    from hedge.tools import EOCRecorder
    from math import sin, pi, sqrt

    from numpy import dot

    a = numpy.array([1, 3])

    def u_analytic(x, el):
        return sin(dot(a, x))

    mesh = make_disk_mesh(r=pi, max_area=0.5)

    discr2 = discr_class(mesh, TriangleDiscretization(2), debug=discr_class.noninteractive_debug_flags())
    discr5 = discr_class(mesh, TriangleDiscretization(5), debug=discr_class.noninteractive_debug_flags())
    p2to5 = Projector(discr2, discr5)
    p5to2 = Projector(discr5, discr2)

    u2 = discr2.interpolate_volume_function(u_analytic)
    u2_i = p5to2(p2to5(u2))
    assert discr2.norm(u2 - u2_i) < 3e-15
def test_projection():
    """Test whether projection between different orders works"""

    from hedge.mesh.generator import make_disk_mesh
    from hedge.discretization import Projector
    from hedge.discretization.local import TriangleDiscretization
    from math import sin, pi

    from numpy import dot

    a = numpy.array([1, 3])

    def u_analytic(x, el):
        return sin(dot(a, x))

    mesh = make_disk_mesh(r=pi, max_area=0.5)

    discr2 = discr_class(mesh,
                         TriangleDiscretization(2),
                         debug=discr_class.noninteractive_debug_flags())
    discr5 = discr_class(mesh,
                         TriangleDiscretization(5),
                         debug=discr_class.noninteractive_debug_flags())
    p2to5 = Projector(discr2, discr5)
    p5to2 = Projector(discr5, discr2)

    u2 = discr2.interpolate_volume_function(u_analytic)
    u2_i = p5to2(p2to5(u2))
    assert discr2.norm(u2 - u2_i) < 3e-15
def test_tri_mass_mat_trig():
    """Check the integral of some trig functions on a square using the mass matrix"""

    from hedge.mesh.generator import make_square_mesh
    from hedge.discretization.local import TriangleDiscretization
    from math import sqrt, pi, cos, sin

    mesh = make_square_mesh(a=-pi, b=pi, max_area=(2 * pi / 10) ** 2 / 2)
    discr = discr_class(mesh, TriangleDiscretization(8), debug=discr_class.noninteractive_debug_flags())

    f = discr.interpolate_volume_function(lambda x, el: cos(x[0]) ** 2 * sin(x[1]) ** 2)
    ones = discr.interpolate_volume_function(lambda x, el: 1)

    from hedge.optemplate import MassOperator

    mass_op = MassOperator()

    num_integral_1 = numpy.dot(ones, mass_op.apply(discr, f))
    num_integral_2 = numpy.dot(f, mass_op.apply(discr, ones))
    true_integral = pi ** 2
    err_1 = abs(num_integral_1 - true_integral)
    err_2 = abs(num_integral_2 - true_integral)
    # print err_1, err_2
    assert err_1 < 1e-10
    assert err_2 < 1e-10
def test_1d_mass_mat_trig():
    """Check the integral of some trig functions on an interval using the mass
    matrix
    """
    from hedge.mesh.generator import make_uniform_1d_mesh
    from hedge.discretization.local import IntervalDiscretization
    from math import pi, cos
    from numpy import dot

    mesh = make_uniform_1d_mesh(-4 * pi, 9 * pi, 17, periodic=True)
    discr = discr_class(mesh,
                        IntervalDiscretization(8),
                        debug=discr_class.noninteractive_debug_flags())

    f = discr.interpolate_volume_function(lambda x, el: cos(x[0])**2)
    ones = discr.interpolate_volume_function(lambda x, el: 1)

    from hedge.optemplate import MassOperator
    mass_op = MassOperator()

    num_integral_1 = dot(ones, mass_op.apply(discr, f))
    num_integral_2 = dot(f, mass_op.apply(discr, ones))
    num_integral_3 = discr.integral(f)

    true_integral = 13 * pi / 2
    err_1 = abs(num_integral_1 - true_integral)
    err_2 = abs(num_integral_2 - true_integral)
    err_3 = abs(num_integral_3 - true_integral)

    assert err_1 < 1e-10
    assert err_2 < 1e-10
    assert err_3 < 1e-10
def test_1d_mass_mat_trig():
    """Check the integral of some trig functions on an interval using the mass matrix"""
    from hedge.mesh.generator import make_uniform_1d_mesh
    from hedge.discretization.local import IntervalDiscretization
    from math import sqrt, pi, cos, sin
    from numpy import dot

    mesh = make_uniform_1d_mesh(-4 * pi, 9 * pi, 17, periodic=True)
    discr = discr_class(mesh, IntervalDiscretization(8), debug=discr_class.noninteractive_debug_flags())

    f = discr.interpolate_volume_function(lambda x, el: cos(x[0]) ** 2)
    ones = discr.interpolate_volume_function(lambda x, el: 1)

    from hedge.optemplate import MassOperator

    mass_op = MassOperator()

    num_integral_1 = dot(ones, mass_op.apply(discr, f))
    num_integral_2 = dot(f, mass_op.apply(discr, ones))
    num_integral_3 = discr.integral(f)

    true_integral = 13 * pi / 2
    err_1 = abs(num_integral_1 - true_integral)
    err_2 = abs(num_integral_2 - true_integral)
    err_3 = abs(num_integral_3 - true_integral)

    assert err_1 < 1e-10
    assert err_2 < 1e-10
    assert err_3 < 1e-10
def test_tri_mass_mat_trig():
    """Check the integral of some trig functions on a square using the mass matrix"""

    from hedge.mesh.generator import make_square_mesh
    from hedge.discretization.local import TriangleDiscretization
    from math import pi, cos, sin

    mesh = make_square_mesh(a=-pi, b=pi, max_area=(2 * pi / 10)**2 / 2)
    discr = discr_class(mesh,
                        TriangleDiscretization(8),
                        debug=discr_class.noninteractive_debug_flags())

    f = discr.interpolate_volume_function(
        lambda x, el: cos(x[0])**2 * sin(x[1])**2)
    ones = discr.interpolate_volume_function(lambda x, el: 1)

    from hedge.optemplate import MassOperator
    mass_op = MassOperator()

    num_integral_1 = numpy.dot(ones, mass_op.apply(discr, f))
    num_integral_2 = numpy.dot(f, mass_op.apply(discr, ones))
    true_integral = pi**2
    err_1 = abs(num_integral_1 - true_integral)
    err_2 = abs(num_integral_2 - true_integral)
    #print err_1, err_2
    assert err_1 < 1e-10
    assert err_2 < 1e-10
def test_tri_diff_mat():
    """Check differentiation matrix along the coordinate axes on a disk

    Uses sines as the function to differentiate.
    """
    from hedge.mesh.generator import make_disk_mesh
    from hedge.discretization.local import TriangleDiscretization
    from math import sin, cos, sqrt

    from hedge.optemplate import make_nabla

    nabla = make_nabla(2)

    for coord in [0, 1]:
        mesh = make_disk_mesh()
        discr = discr_class(make_disk_mesh(), TriangleDiscretization(4), debug=discr_class.noninteractive_debug_flags())
        f = discr.interpolate_volume_function(lambda x, el: sin(3 * x[coord]))
        df = discr.interpolate_volume_function(lambda x, el: 3 * cos(3 * x[coord]))

        df_num = nabla[coord].apply(discr, f)
        # discr.visualize_vtk("diff-err.vtk",
        # [("f", f), ("df", df), ("df_num", df_num), ("error", error)])

        linf_error = la.norm(df_num - df, numpy.Inf)
        print linf_error
        assert linf_error < 4e-5
def test_tri_diff_mat():
    """Check differentiation matrix along the coordinate axes on a disk

    Uses sines as the function to differentiate.
    """
    from hedge.mesh.generator import make_disk_mesh
    from hedge.discretization.local import TriangleDiscretization
    from math import sin, cos

    from hedge.optemplate import make_nabla
    nabla = make_nabla(2)

    for coord in [0, 1]:
        discr = discr_class(make_disk_mesh(),
                            TriangleDiscretization(4),
                            debug=discr_class.noninteractive_debug_flags())
        f = discr.interpolate_volume_function(lambda x, el: sin(3 * x[coord]))
        df = discr.interpolate_volume_function(
            lambda x, el: 3 * cos(3 * x[coord]))

        df_num = nabla[coord].apply(discr, f)
        #discr.visualize_vtk("diff-err.vtk",
        #[("f", f), ("df", df), ("df_num", df_num), ("error", error)])

        linf_error = la.norm(df_num - df, numpy.Inf)
        print linf_error
        assert linf_error < 4e-5
def test_quadrature_tri_mass_mat_monomial():
    """Check that quadrature integration on triangles is exact as designed."""

    from hedge.mesh.generator import make_square_mesh

    mesh = make_square_mesh(a=-1, b=1, max_area=4 * 1 / 8 + 0.001)
    order = 4
    discr = discr_class(
        mesh, order=order, debug=discr_class.noninteractive_debug_flags(), quad_min_degrees={"quad": 3 * order}
    )

    m, n = 2, 1
    f = Monomial((m, n))
    f_vec = discr.interpolate_volume_function(lambda x, el: f(x))

    from hedge.discretization import ones_on_volume

    ones = ones_on_volume(discr)

    if False:
        from hedge.visualization import SiloVisualizer

        vis = SiloVisualizer(discr)
        visf = vis.make_file("test")
        vis.add_data(visf, [("f", f_vec * f_vec)])
        visf.close()

    from hedge.optemplate import MassOperator, Field, QuadratureGridUpsampler

    f_fld = Field("f")
    mass_op = discr.compile(MassOperator()(f_fld * f_fld))
    from hedge.optemplate.primitives import make_common_subexpression as cse

    f_upsamp = cse(QuadratureGridUpsampler("quad")(f_fld))
    quad_mass_op = discr.compile(MassOperator()(f_upsamp * f_upsamp))

    num_integral_1 = numpy.dot(ones, mass_op(f=f_vec))
    num_integral_2 = numpy.dot(ones, quad_mass_op(f=f_vec))
    true_integral = 4 / ((2 * m + 1) * (2 * n + 1))
    err_1 = abs(num_integral_1 - true_integral)
    err_2 = abs(num_integral_2 - true_integral)
    print num_integral_1, num_integral_2, true_integral
    print err_1, err_2
    assert err_1 > 1e-8
    assert err_2 < 1e-14
def test_filter():
    """Exercise mode-based filtering."""

    from hedge.mesh.generator import make_disk_mesh
    from hedge.discretization.local import TriangleDiscretization
    from math import sin

    mesh = make_disk_mesh(r=3.4, max_area=0.5)
    discr = discr_class(mesh,
                        TriangleDiscretization(5),
                        debug=discr_class.noninteractive_debug_flags())

    from hedge.optemplate.operators import FilterOperator
    from hedge.discretization import ExponentialFilterResponseFunction
    half_filter = FilterOperator(lambda mid, ldis: 0.5)
    for eg in discr.element_groups:
        fmat = half_filter.matrix(eg)
        n, m = fmat.shape
        assert la.norm(fmat - 0.5 * numpy.eye(n, m)) < 2e-15

    from numpy import dot

    def test_freq(n):
        a = numpy.array([1, n])

        def u_analytic(x, el):
            return sin(dot(a, x))

        exp_filter = FilterOperator(ExponentialFilterResponseFunction(0.9, 3)) \
                .bind(discr)

        u = discr.interpolate_volume_function(u_analytic)
        filt_u = exp_filter(u)

        int_error = abs(discr.integral(u) - discr.integral(filt_u))
        l2_ratio = discr.norm(filt_u) / discr.norm(u)
        assert int_error < 1e-14
        assert 0.96 < l2_ratio < 0.99999

    test_freq(3)
    test_freq(5)
    test_freq(9)
    test_freq(17)
def test_quadrature_tri_mass_mat_monomial():
    """Check that quadrature integration on triangles is exact as designed."""

    from hedge.mesh.generator import make_square_mesh

    mesh = make_square_mesh(a=-1, b=1, max_area=4 * 1 / 8 + 0.001)
    order = 4
    discr = discr_class(mesh,
                        order=order,
                        debug=discr_class.noninteractive_debug_flags(),
                        quad_min_degrees={"quad": 3 * order})

    m, n = 2, 1
    f = Monomial((m, n))
    f_vec = discr.interpolate_volume_function(lambda x, el: f(x))

    from hedge.discretization import ones_on_volume
    ones = ones_on_volume(discr)

    if False:
        from hedge.visualization import SiloVisualizer
        vis = SiloVisualizer(discr)
        visf = vis.make_file("test")
        vis.add_data(visf, [("f", f_vec * f_vec)])
        visf.close()

    from hedge.optemplate import (MassOperator, Field, QuadratureGridUpsampler)
    f_fld = Field("f")
    mass_op = discr.compile(MassOperator()(f_fld * f_fld))
    from hedge.optemplate.primitives import make_common_subexpression as cse
    f_upsamp = cse(QuadratureGridUpsampler("quad")(f_fld))
    quad_mass_op = discr.compile(MassOperator()(f_upsamp * f_upsamp))

    num_integral_1 = numpy.dot(ones, mass_op(f=f_vec))
    num_integral_2 = numpy.dot(ones, quad_mass_op(f=f_vec))
    true_integral = 4 / ((2 * m + 1) * (2 * n + 1))
    err_1 = abs(num_integral_1 - true_integral)
    err_2 = abs(num_integral_2 - true_integral)
    print num_integral_1, num_integral_2, true_integral
    print err_1, err_2
    assert err_1 > 1e-8
    assert err_2 < 1e-14
Example #12
0
def test_filter():
    """Exercise mode-based filtering."""

    from hedge.mesh.generator import make_disk_mesh
    from hedge.discretization.local import TriangleDiscretization
    from math import sin

    mesh = make_disk_mesh(r=3.4, max_area=0.5)
    discr = discr_class(mesh, TriangleDiscretization(5),
            debug=discr_class.noninteractive_debug_flags())

    from hedge.optemplate.operators import FilterOperator
    from hedge.discretization import ExponentialFilterResponseFunction
    half_filter = FilterOperator(lambda mid, ldis: 0.5)
    for eg in discr.element_groups:
        fmat = half_filter.matrix(eg)
        n, m = fmat.shape
        assert la.norm(fmat - 0.5*numpy.eye(n, m)) < 2e-15

    from numpy import dot

    def test_freq(n):
        a = numpy.array([1, n])

        def u_analytic(x, el):
            return sin(dot(a, x))

        exp_filter = FilterOperator(ExponentialFilterResponseFunction(0.9, 3)) \
                .bind(discr)

        u = discr.interpolate_volume_function(u_analytic)
        filt_u = exp_filter(u)

        int_error = abs(discr.integral(u) - discr.integral(filt_u))
        l2_ratio = discr.norm(filt_u) / discr.norm(u)
        assert int_error < 1e-14
        assert 0.96 < l2_ratio < 0.99999

    test_freq(3)
    test_freq(5)
    test_freq(9)
    test_freq(17)
def test_convergence_advec_2d():
    """Test whether 2D advection actually converges"""

    import pyublas  # noqa
    from hedge.mesh.generator import make_disk_mesh, make_regular_rect_mesh
    from hedge.discretization.local import TriangleDiscretization
    from hedge.timestep import RK4TimeStepper
    from hedge.tools import EOCRecorder
    from math import sin, pi
    from hedge.models.advection import StrongAdvectionOperator
    from hedge.data import TimeDependentGivenFunction

    v = numpy.array([0.27, 0])
    norm_a = la.norm(v)

    from numpy import dot

    def f(x):
        return sin(x)

    def u_analytic(x, el, t):
        return f((-dot(v, x) / norm_a + t * norm_a))

    def boundary_tagger(vertices, el, face_nr, all_v):
        if dot(el.face_normals[face_nr], v) < 0:
            return ["inflow"]
        else:
            return ["outflow"]

    for mesh in [
            # non-periodic
            make_disk_mesh(r=pi, boundary_tagger=boundary_tagger,
                           max_area=0.5),
            # periodic
            make_regular_rect_mesh(
                a=(0, 0),
                b=(2 * pi, 1),
                n=(8, 4),
                periodicity=(True, False),
                boundary_tagger=boundary_tagger,
            )
    ]:
        for flux_type in StrongAdvectionOperator.flux_types:
            eoc_rec = EOCRecorder()

            for order in [1, 2, 3, 4, 5, 6]:
                discr = discr_class(
                    mesh,
                    TriangleDiscretization(order),
                    debug=discr_class.noninteractive_debug_flags())
                op = StrongAdvectionOperator(
                    v,
                    inflow_u=TimeDependentGivenFunction(u_analytic),
                    flux_type=flux_type)

                u = discr.interpolate_volume_function(
                    lambda x, el: u_analytic(x, el, 0))

                stepper = RK4TimeStepper()
                dt = op.estimate_timestep(discr, stepper=stepper)
                nsteps = int(1 / dt)
                rhs = op.bind(discr)
                for step in range(nsteps):
                    u = stepper(u, step * dt, dt, rhs)

                u_true = discr.interpolate_volume_function(
                    lambda x, el: u_analytic(x, el, nsteps * dt))
                error = u - u_true
                error_l2 = discr.norm(error)
                eoc_rec.add_data_point(order, error_l2)

            if False:
                print "%s\n%s\n" % (flux_type.upper(), "-" * len(flux_type))
                print eoc_rec.pretty_print(abscissa_label="Poly. Order",
                                           error_label="L2 Error")

            assert eoc_rec.estimate_order_of_convergence()[0, 1] > 4
            assert eoc_rec.estimate_order_of_convergence(2)[-1, 1] > 10
def test_symmetry_preservation_2d():
    """Test whether we preserve symmetry in a symmetric 2D advection problem"""
    from numpy import dot

    def make_mesh():
        array = numpy.array

        #
        #    1---8---2
        #    |7 /|\ 1|
        #    | / | \ |
        #    |/ 6|0 \|
        #    5---4---7
        #    |\ 5|3 /|
        #    | \ | / |
        #    |4 \|/ 2|
        #    0---6---3
        #
        points = [
            array([-0.5, -0.5]),
            array([-0.5, 0.5]),
            array([0.5, 0.5]),
            array([0.5, -0.5]),
            array([0.0, 0.0]),
            array([-0.5, 0.0]),
            array([0.0, -0.5]),
            array([0.5, 0.0]),
            array([0.0, 0.5])
        ]

        elements = [
            [8, 7, 4],
            [8, 7, 2],
            [6, 7, 3],
            [7, 4, 6],
            [5, 6, 0],
            [5, 6, 4],
            [5, 8, 4],
            [1, 5, 8],
        ]

        def boundary_tagger(vertices, el, face_nr, all_v):
            if dot(el.face_normals[face_nr], v) < 0:
                return ["inflow"]
            else:
                return ["outflow"]

        from hedge.mesh import make_conformal_mesh
        return make_conformal_mesh(points, elements, boundary_tagger)

    from hedge.discretization import SymmetryMap
    from hedge.timestep import RK4TimeStepper
    from hedge.models.advection import StrongAdvectionOperator
    from hedge.data import TimeDependentGivenFunction

    v = numpy.array([-1, 0])

    mesh = make_mesh()
    discr = discr_class(mesh,
                        order=4,
                        debug=discr_class.noninteractive_debug_flags())

    #ref_discr = DynamicDiscretization(mesh, order=4)

    def f(x):
        if x < 0.5:
            return 0
        else:
            return (x - 0.5)

    #def f(x):
    #return sin(5*x)

    def u_analytic(x, el, t):
        return f(-dot(v, x) + t)

    u = discr.interpolate_volume_function(lambda x, el: u_analytic(x, el, 0))

    sym_map = SymmetryMap(discr, lambda x: numpy.array([x[0], -x[1]]), {
        0: 3,
        2: 1,
        5: 6,
        7: 4
    })

    for flux_type in StrongAdvectionOperator.flux_types:
        stepper = RK4TimeStepper()
        op = StrongAdvectionOperator(
            v,
            inflow_u=TimeDependentGivenFunction(u_analytic),
            flux_type=flux_type)

        dt = op.estimate_timestep(discr, stepper=stepper)
        nsteps = int(1 / dt)
        rhs = op.bind(discr)
        #test_comp = [ "bflux"]
        #test_rhs = op.bind(discr, test_comp)
        #ref_rhs = op.bind(ref_discr, test_comp)
        for step in xrange(nsteps):
            u = stepper(u, step * dt, dt, rhs)
            sym_error_u = u - sym_map(u)
            sym_error_u_l2 = discr.norm(sym_error_u)

            if False:
                from hedge.visualization import SiloVisualizer
                vis = SiloVisualizer(discr)
                visf = vis.make_file("test-%s-%04d" % (flux_type, step))
                vis.add_data(
                    visf,
                    [
                        ("u", u),
                        ("sym_u", sym_map(u)),
                        ("sym_diff", u - sym_map(u)),
                        ("rhs", rhs(step * dt, u)),
                        #("rhs_test", test_rhs(step*dt, u)),
                        #("rhs_ref", ref_rhs(step*dt, u)),
                        #("rhs_diff", test_rhs(step*dt, u)-ref_rhs(step*dt, u)),
                    ])

                print sym_error_u_l2
            assert sym_error_u_l2 < 4e-15
def test_interior_fluxes_tet():
    """Check tetrahedron surface integrals computed using interior fluxes
    against their known values.
    """

    import meshpy.tet as tet
    from math import pi, sin, cos

    mesh_info = tet.MeshInfo()

    # construct a two-box extrusion of this base
    base = [(-pi, -pi, 0), (pi, -pi, 0), (pi, pi, 0), (-pi, pi, 0)]

    # first, the nodes
    mesh_info.set_points(base + [(x, y, z + pi)
                                 for x, y, z in base] + [(x, y, z + pi + 1)
                                                         for x, y, z in base])

    # next, the facets

    # vertex indices for a box missing the -z face
    box_without_minus_z = [
        [4, 5, 6, 7],
        [0, 4, 5, 1],
        [1, 5, 6, 2],
        [2, 6, 7, 3],
        [3, 7, 4, 0],
    ]

    def add_to_all_vertex_indices(facets, increment):
        return [[pt + increment for pt in facet] for facet in facets]

    mesh_info.set_facets(
        [[0, 1, 2, 3]]  # base
        + box_without_minus_z  # first box
        + add_to_all_vertex_indices(box_without_minus_z, 4)  # second box
    )

    # set the volume properties -- this is where the tet size constraints are
    mesh_info.regions.resize(2)
    mesh_info.regions[0] = [
        0,
        0,
        pi / 2,  # point in volume -> first box
        0,  # region tag (user-defined number)
        0.5,  # max tet volume in region
    ]
    mesh_info.regions[1] = [
        0,
        0,
        pi + 0.5,  # point in volume -> second box
        1,  # region tag (user-defined number,  arbitrary)
        0.1,  # max tet volume in region
    ]

    generated_mesh = tet.build(mesh_info,
                               attributes=True,
                               volume_constraints=True)

    from hedge.mesh import make_conformal_mesh
    mesh = make_conformal_mesh(generated_mesh.points, generated_mesh.elements)

    from hedge.discretization.local import TetrahedronDiscretization
    from hedge.discretization import ones_on_volume
    discr = discr_class(mesh,
                        TetrahedronDiscretization(4),
                        debug=discr_class.noninteractive_debug_flags())

    def f_u(x, el):
        if generated_mesh.element_attributes[el.id] == 1:
            return cos(x[0] - x[1] + x[2])
        else:
            return 0

    def f_l(x, el):
        if generated_mesh.element_attributes[el.id] == 0:
            return sin(x[0] - x[1] + x[2])
        else:
            return 0

    u_l = discr.interpolate_volume_function(f_l)
    u_u = discr.interpolate_volume_function(f_u)
    u = u_l + u_u

    # visualize the produced field
    #from hedge.visualization import SiloVisualizer
    #vis = SiloVisualizer(discr)
    #visf = vis.make_file("sandwich")
    #vis.add_data(visf,
    #[("u_l", u_l), ("u_u", u_u)],
    #expressions=[("u", "u_l+u_u")])

    # make sure the surface integral of the difference
    # between top and bottom is zero
    from hedge.flux import make_normal, FluxScalarPlaceholder
    from hedge.optemplate import Field, get_flux_operator

    fluxu = FluxScalarPlaceholder()
    res = discr.compile(
        get_flux_operator(
            (fluxu.int - fluxu.ext) * make_normal(discr.dimensions)[1]) *
        Field("u"))(u=u)

    ones = ones_on_volume(discr)
    assert abs(numpy.dot(res, ones)) < 5e-14
def test_interior_fluxes_tri():
    """Check triangle surface integrals computed using interior fluxes
    against their known values.
    """

    from math import pi, sin, cos

    def round_trip_connect(start, end):
        for i in range(start, end):
            yield i, i + 1
        yield end, start

    a = -pi
    b = pi
    points = [(a, 0), (b, 0), (a, -1), (b, -1), (a, 1), (b, 1)]

    import meshpy.triangle as triangle

    mesh_info = triangle.MeshInfo()
    mesh_info.set_points(points)
    mesh_info.set_facets([(0, 1), (1, 3), (3, 2), (2, 0), (0, 4), (4, 5),
                          (1, 5)])

    mesh_info.regions.resize(2)
    mesh_info.regions[0] = [
        0,
        -0.5,  # coordinate
        1,  # lower element tag
        0.1,  # max area
    ]
    mesh_info.regions[1] = [
        0,
        0.5,  # coordinate
        2,  # upper element tag
        0.01,  # max area
    ]

    generated_mesh = triangle.build(mesh_info,
                                    attributes=True,
                                    volume_constraints=True)

    #triangle.write_gnuplot_mesh("mesh.dat", generated_mesh)

    def element_tagger(el):
        if generated_mesh.element_attributes[el.id] == 1:
            return ["upper"]
        else:
            return ["lower"]

    from hedge.mesh import make_conformal_mesh
    mesh = make_conformal_mesh(generated_mesh.points, generated_mesh.elements)

    from hedge.discretization.local import TriangleDiscretization
    from hedge.discretization import ones_on_volume
    discr = discr_class(mesh,
                        TriangleDiscretization(4),
                        debug=discr_class.noninteractive_debug_flags())

    def f_u(x, el):
        if generated_mesh.element_attributes[el.id] == 1:
            return cos(x[0] - x[1])
        else:
            return 0

    def f_l(x, el):
        if generated_mesh.element_attributes[el.id] == 0:
            return sin(x[0] - x[1])
        else:
            return 0

    # u_l = discr.interpolate_volume_function(f_l)
    u_u = discr.interpolate_volume_function(f_u)
    u = u_u + u_u

    #discr.visualize_vtk("dual.vtk", [("u", u)])

    from hedge.flux import make_normal, FluxScalarPlaceholder
    from hedge.optemplate import Field, get_flux_operator
    fluxu = FluxScalarPlaceholder()
    res = discr.compile(
        get_flux_operator(
            (fluxu.int - fluxu.ext) * make_normal(discr.dimensions)[1]) *
        Field("u"))(u=u)

    ones = ones_on_volume(discr)
    err = abs(numpy.dot(res, ones))
    #print err
    assert err < 5e-14
Example #17
0
def test_2d_gauss_theorem():
    """Verify Gauss's theorem explicitly on a mesh"""

    from hedge.mesh.generator import make_disk_mesh
    from math import sin, cos, sqrt, exp, pi
    from numpy import dot

    mesh = make_disk_mesh()
    order = 2

    discr = discr_class(mesh, order=order, debug=discr_class.noninteractive_debug_flags())
    ref_discr = discr_class(mesh, order=order)

    from hedge.flux import make_normal, FluxScalarPlaceholder

    normal = make_normal(discr.dimensions)
    flux_f_ph = FluxScalarPlaceholder(0)
    one_sided_x = flux_f_ph.int * normal[0]
    one_sided_y = flux_f_ph.int * normal[1]

    def f1(x, el):
        return sin(3 * x[0]) + cos(3 * x[1])

    def f2(x, el):
        return sin(2 * x[0]) + cos(x[1])

    from hedge.discretization import ones_on_volume

    ones = ones_on_volume(discr)
    f1_v = discr.interpolate_volume_function(f1)
    f2_v = discr.interpolate_volume_function(f2)

    from hedge.optemplate import BoundaryPair, Field, make_nabla, get_flux_operator

    nabla = make_nabla(discr.dimensions)
    diff_optp = nabla[0] * Field("f1") + nabla[1] * Field("f2")

    divergence = nabla[0].apply(discr, f1_v) + nabla[1].apply(discr, f2_v)
    int_div = discr.integral(divergence)

    flux_optp = get_flux_operator(one_sided_x)(BoundaryPair(Field("f1"), Field("fz"))) + get_flux_operator(one_sided_y)(
        BoundaryPair(Field("f2"), Field("fz"))
    )

    from hedge.mesh import TAG_ALL

    bdry_val = discr.compile(flux_optp)(f1=f1_v, f2=f2_v, fz=discr.boundary_zeros(TAG_ALL))
    ref_bdry_val = ref_discr.compile(flux_optp)(f1=f1_v, f2=f2_v, fz=discr.boundary_zeros(TAG_ALL))

    boundary_int = dot(bdry_val, ones)

    if False:
        from hedge.visualization import SiloVisualizer

        vis = SiloVisualizer(discr)
        visf = vis.make_file("test")

        from hedge.tools import make_obj_array
        from hedge.mesh import TAG_ALL

        vis.add_data(
            visf,
            [
                ("bdry", bdry_val),
                ("ref_bdry", ref_bdry_val),
                ("div", divergence),
                ("f", make_obj_array([f1_v, f2_v])),
                ("n", discr.volumize_boundary_field(discr.boundary_normals(TAG_ALL), TAG_ALL)),
            ],
            expressions=[("bdiff", "bdry-ref_bdry")],
        )

        # print abs(boundary_int-int_div)

    assert abs(boundary_int - int_div) < 5e-15
Example #18
0
def test_interior_fluxes_tri():
    """Check triangle surface integrals computed using interior fluxes
    against their known values.
    """

    from math import pi, sin, cos

    def round_trip_connect(start, end):
        for i in range(start, end):
            yield i, i + 1
        yield end, start

    a = -pi
    b = pi
    points = [(a, 0), (b, 0), (a, -1), (b, -1), (a, 1), (b, 1)]

    import meshpy.triangle as triangle

    mesh_info = triangle.MeshInfo()
    mesh_info.set_points(points)
    mesh_info.set_facets([(0, 1), (1, 3), (3, 2), (2, 0), (0, 4), (4, 5), (1, 5)])

    mesh_info.regions.resize(2)
    mesh_info.regions[0] = [0, -0.5, 1, 0.1]  # coordinate  # lower element tag  # max area
    mesh_info.regions[1] = [0, 0.5, 2, 0.01]  # coordinate  # upper element tag  # max area

    generated_mesh = triangle.build(mesh_info, attributes=True, volume_constraints=True)
    # triangle.write_gnuplot_mesh("mesh.dat", generated_mesh)

    def element_tagger(el):
        if generated_mesh.element_attributes[el.id] == 1:
            return ["upper"]
        else:
            return ["lower"]

    from hedge.mesh import make_conformal_mesh

    mesh = make_conformal_mesh(generated_mesh.points, generated_mesh.elements)

    from hedge.discretization.local import TriangleDiscretization
    from hedge.discretization import ones_on_volume

    discr = discr_class(mesh, TriangleDiscretization(4), debug=discr_class.noninteractive_debug_flags())

    def f_u(x, el):
        if generated_mesh.element_attributes[el.id] == 1:
            return cos(x[0] - x[1])
        else:
            return 0

    def f_l(x, el):
        if generated_mesh.element_attributes[el.id] == 0:
            return sin(x[0] - x[1])
        else:
            return 0

    u_l = discr.interpolate_volume_function(f_l)
    u_u = discr.interpolate_volume_function(f_u)
    u = u_u + u_u

    # discr.visualize_vtk("dual.vtk", [("u", u)])

    from hedge.flux import make_normal, FluxScalarPlaceholder
    from hedge.optemplate import Field, get_flux_operator

    fluxu = FluxScalarPlaceholder()
    res = discr.compile(get_flux_operator((fluxu.int - fluxu.ext) * make_normal(discr.dimensions)[1]) * Field("u"))(u=u)

    from hedge.discretization import ones_on_volume

    ones = ones_on_volume(discr)
    err = abs(numpy.dot(res, ones))
    # print err
    assert err < 5e-14
def test_2d_gauss_theorem():
    """Verify Gauss's theorem explicitly on a mesh"""

    from hedge.mesh.generator import make_disk_mesh
    from math import sin, cos
    from numpy import dot

    mesh = make_disk_mesh()
    order = 2

    discr = discr_class(mesh,
                        order=order,
                        debug=discr_class.noninteractive_debug_flags())
    ref_discr = discr_class(mesh, order=order)

    from hedge.flux import make_normal, FluxScalarPlaceholder

    normal = make_normal(discr.dimensions)
    flux_f_ph = FluxScalarPlaceholder(0)
    one_sided_x = flux_f_ph.int * normal[0]
    one_sided_y = flux_f_ph.int * normal[1]

    def f1(x, el):
        return sin(3 * x[0]) + cos(3 * x[1])

    def f2(x, el):
        return sin(2 * x[0]) + cos(x[1])

    from hedge.discretization import ones_on_volume
    ones = ones_on_volume(discr)
    f1_v = discr.interpolate_volume_function(f1)
    f2_v = discr.interpolate_volume_function(f2)

    from hedge.optemplate import BoundaryPair, Field, make_nabla, \
            get_flux_operator
    nabla = make_nabla(discr.dimensions)

    divergence = nabla[0].apply(discr, f1_v) + nabla[1].apply(discr, f2_v)
    int_div = discr.integral(divergence)

    flux_optp = (
        get_flux_operator(one_sided_x)(BoundaryPair(Field("f1"),
                                                    Field("fz"))) +
        get_flux_operator(one_sided_y)(BoundaryPair(Field("f2"), Field("fz"))))

    from hedge.mesh import TAG_ALL
    bdry_val = discr.compile(flux_optp)(f1=f1_v,
                                        f2=f2_v,
                                        fz=discr.boundary_zeros(TAG_ALL))
    ref_bdry_val = ref_discr.compile(flux_optp)(
        f1=f1_v, f2=f2_v, fz=discr.boundary_zeros(TAG_ALL))

    boundary_int = dot(bdry_val, ones)

    if False:
        from hedge.visualization import SiloVisualizer
        vis = SiloVisualizer(discr)
        visf = vis.make_file("test")

        from hedge.tools import make_obj_array
        from hedge.mesh import TAG_ALL
        vis.add_data(visf, [
            ("bdry", bdry_val),
            ("ref_bdry", ref_bdry_val),
            ("div", divergence),
            ("f", make_obj_array([f1_v, f2_v])),
            ("n",
             discr.volumize_boundary_field(discr.boundary_normals(TAG_ALL),
                                           TAG_ALL)),
        ],
                     expressions=[("bdiff", "bdry-ref_bdry")])

        #print abs(boundary_int-int_div)

    assert abs(boundary_int - int_div) < 5e-15
Example #20
0
def test_interior_fluxes_tet():
    """Check tetrahedron surface integrals computed using interior fluxes
    against their known values.
    """

    import meshpy.tet as tet
    from math import pi, sin, cos

    mesh_info = tet.MeshInfo()

    # construct a two-box extrusion of this base
    base = [(-pi, -pi, 0), (pi, -pi, 0), (pi, pi, 0), (-pi, pi, 0)]

    # first, the nodes
    mesh_info.set_points(base + [(x, y, z + pi) for x, y, z in base] + [(x, y, z + pi + 1) for x, y, z in base])

    # next, the facets

    # vertex indices for a box missing the -z face
    box_without_minus_z = [[4, 5, 6, 7], [0, 4, 5, 1], [1, 5, 6, 2], [2, 6, 7, 3], [3, 7, 4, 0]]

    def add_to_all_vertex_indices(facets, increment):
        return [[pt + increment for pt in facet] for facet in facets]

    mesh_info.set_facets(
        [[0, 1, 2, 3]]  # base
        + box_without_minus_z  # first box
        + add_to_all_vertex_indices(box_without_minus_z, 4)  # second box
    )

    # set the volume properties -- this is where the tet size constraints are
    mesh_info.regions.resize(2)
    mesh_info.regions[0] = [
        0,
        0,
        pi / 2,  # point in volume -> first box
        0,  # region tag (user-defined number)
        0.5,  # max tet volume in region
    ]
    mesh_info.regions[1] = [
        0,
        0,
        pi + 0.5,  # point in volume -> second box
        1,  # region tag (user-defined number, arbitrary)
        0.1,  # max tet volume in region
    ]

    generated_mesh = tet.build(mesh_info, attributes=True, volume_constraints=True)

    from hedge.mesh import make_conformal_mesh

    mesh = make_conformal_mesh(generated_mesh.points, generated_mesh.elements)

    from hedge.discretization.local import TetrahedronDiscretization
    from hedge.discretization import ones_on_volume

    discr = discr_class(mesh, TetrahedronDiscretization(4), debug=discr_class.noninteractive_debug_flags())

    def f_u(x, el):
        if generated_mesh.element_attributes[el.id] == 1:
            return cos(x[0] - x[1] + x[2])
        else:
            return 0

    def f_l(x, el):
        if generated_mesh.element_attributes[el.id] == 0:
            return sin(x[0] - x[1] + x[2])
        else:
            return 0

    u_l = discr.interpolate_volume_function(f_l)
    u_u = discr.interpolate_volume_function(f_u)
    u = u_l + u_u

    # visualize the produced field
    # from hedge.visualization import SiloVisualizer
    # vis = SiloVisualizer(discr)
    # visf = vis.make_file("sandwich")
    # vis.add_data(visf,
    # [("u_l", u_l), ("u_u", u_u)],
    # expressions=[("u", "u_l+u_u")])

    # make sure the surface integral of the difference
    # between top and bottom is zero
    from hedge.flux import make_normal, FluxScalarPlaceholder
    from hedge.optemplate import Field, get_flux_operator

    fluxu = FluxScalarPlaceholder()
    res = discr.compile(get_flux_operator((fluxu.int - fluxu.ext) * make_normal(discr.dimensions)[1]) * Field("u"))(u=u)

    from hedge.discretization import ones_on_volume

    ones = ones_on_volume(discr)
    assert abs(numpy.dot(res, ones)) < 5e-14
Example #21
0
def test_convergence_advec_2d():
    """Test whether 2D advection actually converges"""

    import pyublas
    from hedge.mesh.generator import make_disk_mesh, make_regular_rect_mesh
    from hedge.discretization.local import TriangleDiscretization
    from hedge.timestep import RK4TimeStepper
    from hedge.tools import EOCRecorder
    from math import sin, pi, sqrt
    from hedge.models.advection import StrongAdvectionOperator
    from hedge.data import TimeDependentGivenFunction

    v = numpy.array([0.27, 0])
    norm_a = la.norm(v)

    from numpy import dot

    def f(x):
        return sin(x)

    def u_analytic(x, el, t):
        return f((-dot(v, x) / norm_a + t * norm_a))

    def boundary_tagger(vertices, el, face_nr, all_v):
        if dot(el.face_normals[face_nr], v) < 0:
            return ["inflow"]
        else:
            return ["outflow"]

    for mesh in [
        # non-periodic
        make_disk_mesh(r=pi, boundary_tagger=boundary_tagger, max_area=0.5),
        # periodic
        make_regular_rect_mesh(
            a=(0, 0), b=(2 * pi, 1), n=(8, 4), periodicity=(True, False), boundary_tagger=boundary_tagger
        ),
    ]:
        for flux_type in StrongAdvectionOperator.flux_types:
            eoc_rec = EOCRecorder()

            for order in [1, 2, 3, 4, 5, 6]:
                discr = discr_class(mesh, TriangleDiscretization(order), debug=discr_class.noninteractive_debug_flags())
                op = StrongAdvectionOperator(v, inflow_u=TimeDependentGivenFunction(u_analytic), flux_type=flux_type)

                u = discr.interpolate_volume_function(lambda x, el: u_analytic(x, el, 0))

                stepper = RK4TimeStepper()
                dt = op.estimate_timestep(discr, stepper=stepper)
                nsteps = int(1 / dt)
                rhs = op.bind(discr)
                for step in range(nsteps):
                    u = stepper(u, step * dt, dt, rhs)

                u_true = discr.interpolate_volume_function(lambda x, el: u_analytic(x, el, nsteps * dt))
                error = u - u_true
                error_l2 = discr.norm(error)
                eoc_rec.add_data_point(order, error_l2)

            if False:
                print "%s\n%s\n" % (flux_type.upper(), "-" * len(flux_type))
                print eoc_rec.pretty_print(abscissa_label="Poly. Order", error_label="L2 Error")

            assert eoc_rec.estimate_order_of_convergence()[0, 1] > 4
            assert eoc_rec.estimate_order_of_convergence(2)[-1, 1] > 10
Example #22
0
def test_symmetry_preservation_2d():
    """Test whether we preserve symmetry in a symmetric 2D advection problem"""
    from numpy import dot

    def make_mesh():
        array = numpy.array

        #
        #    1---8---2
        #    |7 /|\ 1|
        #    | / | \ |
        #    |/ 6|0 \|
        #    5---4---7
        #    |\ 5|3 /|
        #    | \ | / |
        #    |4 \|/ 2|
        #    0---6---3
        #
        points = [
            array([-0.5, -0.5]),
            array([-0.5, 0.5]),
            array([0.5, 0.5]),
            array([0.5, -0.5]),
            array([0.0, 0.0]),
            array([-0.5, 0.0]),
            array([0.0, -0.5]),
            array([0.5, 0.0]),
            array([0.0, 0.5]),
        ]

        elements = [[8, 7, 4], [8, 7, 2], [6, 7, 3], [7, 4, 6], [5, 6, 0], [5, 6, 4], [5, 8, 4], [1, 5, 8]]

        def boundary_tagger(vertices, el, face_nr, all_v):
            if dot(el.face_normals[face_nr], v) < 0:
                return ["inflow"]
            else:
                return ["outflow"]

        from hedge.mesh import make_conformal_mesh

        return make_conformal_mesh(points, elements, boundary_tagger)

    from hedge.discretization import SymmetryMap
    from hedge.discretization.local import TriangleDiscretization
    from hedge.timestep import RK4TimeStepper
    from math import sqrt, sin
    from hedge.models.advection import StrongAdvectionOperator
    from hedge.data import TimeDependentGivenFunction

    v = numpy.array([-1, 0])

    mesh = make_mesh()
    discr = discr_class(mesh, order=4, debug=discr_class.noninteractive_debug_flags())
    # ref_discr = DynamicDiscretization(mesh, order=4)

    def f(x):
        if x < 0.5:
            return 0
        else:
            return x - 0.5

    # def f(x):
    # return sin(5*x)

    def u_analytic(x, el, t):
        return f(-dot(v, x) + t)

    u = discr.interpolate_volume_function(lambda x, el: u_analytic(x, el, 0))

    sym_map = SymmetryMap(discr, lambda x: numpy.array([x[0], -x[1]]), {0: 3, 2: 1, 5: 6, 7: 4})

    for flux_type in StrongAdvectionOperator.flux_types:
        stepper = RK4TimeStepper()
        op = StrongAdvectionOperator(v, inflow_u=TimeDependentGivenFunction(u_analytic), flux_type=flux_type)

        dt = op.estimate_timestep(discr, stepper=stepper)
        nsteps = int(1 / dt)
        rhs = op.bind(discr)
        # test_comp = [ "bflux"]
        # test_rhs = op.bind(discr, test_comp)
        # ref_rhs = op.bind(ref_discr, test_comp)
        for step in xrange(nsteps):
            u = stepper(u, step * dt, dt, rhs)
            sym_error_u = u - sym_map(u)
            sym_error_u_l2 = discr.norm(sym_error_u)

            if False:
                from hedge.visualization import SiloVisualizer

                vis = SiloVisualizer(discr)
                visf = vis.make_file("test-%s-%04d" % (flux_type, step))
                vis.add_data(
                    visf,
                    [
                        ("u", u),
                        ("sym_u", sym_map(u)),
                        ("sym_diff", u - sym_map(u)),
                        ("rhs", rhs(step * dt, u)),
                        ("rhs_test", test_rhs(step * dt, u)),
                        ("rhs_ref", ref_rhs(step * dt, u)),
                        ("rhs_diff", test_rhs(step * dt, u) - ref_rhs(step * dt, u)),
                    ],
                )

                print sym_error_u_l2
            assert sym_error_u_l2 < 4e-15