Example #1
0
def run_convergence_test_advec(dtype,
                               flux_type,
                               random_partition,
                               mesh_gen,
                               debug_output=False):
    """Test whether 2/3D advection actually converges"""

    from hedge.timestep import RK4TimeStepper
    from hedge.tools import EOCRecorder
    from math import sin
    from hedge.data import TimeDependentGivenFunction
    from hedge.visualization import SiloVisualizer

    from hedge.backends import guess_run_context
    rcon = guess_run_context(["mpi"])

    # note: x component must remain zero because x-periodicity is used
    v = np.array([0.0, 0.9, 0.3])

    def f(x):
        return sin(x)

    def u_analytic(x, el, t):
        return f(
            (np.dot(-v[:dims], x) / la.norm(v[:dims]) + t * la.norm(v[:dims])))

    def boundary_tagger(vertices, el, face_nr, points):
        face_normal = el.face_normals[face_nr]
        if np.dot(face_normal, v[:len(face_normal)]) < 0:
            return ["inflow"]
        else:
            return ["outflow"]

    mesh = mesh_gen(boundary_tagger)
    eoc_rec = EOCRecorder()

    if random_partition:
        # Distribute elements randomly across nodes.
        # This is bad, efficiency-wise, but it puts stress
        # on the parallel implementation, which is desired here.
        # Another main point of this is to force the code to split
        # a periodic face pair across nodes.
        from random import choice
        partition = [choice(rcon.ranks) for el in mesh.elements]
    else:
        partition = None

    for order in [1, 2, 3, 4]:
        if rcon.is_head_rank:
            mesh_data = rcon.distribute_mesh(mesh, partition)
        else:
            mesh_data = rcon.receive_mesh()

        dims = mesh.points.shape[1]

        discr = rcon.make_discretization(mesh_data,
                                         order=order,
                                         default_scalar_type=dtype)

        op = StrongAdvectionOperator(
            v[:dims],
            inflow_u=TimeDependentGivenFunction(u_analytic),
            flux_type=flux_type)
        if debug_output:
            vis = SiloVisualizer(discr, rcon)

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

        if debug_output and rcon.is_head_rank:
            print "#elements=%d" % len(mesh.elements)

        test_name = "test-%s-o%d-m%s-r%s" % (
            flux_type, order, mesh_gen.__name__, random_partition)

        rhs = op.bind(discr)

        stepper = RK4TimeStepper(dtype=dtype)
        from hedge.timestep import times_and_steps
        final_time = 1
        step_it = times_and_steps(final_time=final_time,
                                  max_dt_getter=lambda t: op.estimate_timestep(
                                      discr, stepper=stepper, t=t, fields=u))

        for step, t, dt in step_it:
            u = stepper(u, t, dt, rhs)

        assert u.dtype == dtype

        u_true = discr.interpolate_volume_function(
            lambda x, el: u_analytic(x, el, final_time))
        error = u - u_true
        l2_error = discr.norm(error)

        if debug_output:
            visf = vis.make_file(test_name + "-final")
            vis.add_data(visf, [("u", u), ("u_true", u_true), ("ic", ic)])
            visf.close()

        eoc_rec.add_data_point(order, l2_error)

    if debug_output and rcon.is_head_rank:
        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] > 3
    assert eoc_rec.estimate_order_of_convergence(2)[-1, 1] > 7
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
Example #4
0
def run_convergence_test_advec(dtype, debug_output=False):
    """Test whether 2/3D advection actually converges"""

    from hedge.mesh.generator import make_ball_mesh, make_box_mesh, make_rect_mesh
    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
    from hedge.visualization import SiloVisualizer

    from hedge.backends import guess_run_context
    rcon = guess_run_context(["mpi"])

    # note: x component must remain zero because x-periodicity is used
    v = numpy.array([0.0,0.9,0.3])

    def f(x):
        return sin(x)

    def u_analytic(x, el, t):
        return f((numpy.dot(-v[:dims],x)/la.norm(v[:dims])+t*la.norm(v[:dims])))

    def boundary_tagger(vertices, el, face_nr, points):
        face_normal = el.face_normals[face_nr]
        if numpy.dot(face_normal, v[:len(face_normal)]) < 0:
            return ["inflow"]
        else:
            return ["outflow"]

    for i_mesh, mesh in enumerate([
        # 2D semiperiodic
        make_rect_mesh(b=(2*pi,3), max_area=0.4,
            periodicity=(True, False),
            subdivisions=(5,10),
            boundary_tagger=boundary_tagger, 
            ),
        # 3D x-periodic
        make_box_mesh((0,0,0), (2*pi, 2, 2), max_volume=0.4,
            periodicity=(True, False, False),
            boundary_tagger=boundary_tagger, 
            ),
        # non-periodic
        make_ball_mesh(r=pi, 
            boundary_tagger=boundary_tagger, max_volume=0.7),
        ]):
        for flux_type in StrongAdvectionOperator.flux_types:
            for random_partition in [True, False]:
                eoc_rec = EOCRecorder()

                if random_partition:
                    # Distribute elements randomly across nodes.
                    # This is bad, efficiency-wise, but it puts stress
                    # on the parallel implementation, which is desired here.
                    # Another main point of this is to force the code to split
                    # a periodic face pair across nodes.
                    from random import choice
                    partition = [choice(rcon.ranks) for el in mesh.elements]
                else:
                    partition = None

                for order in [1,2,3,4]:
                    if rcon.is_head_rank:
                        mesh_data = rcon.distribute_mesh(mesh, partition)
                    else:
                        mesh_data = rcon.receive_mesh()

                    dims = mesh.points.shape[1]

                    discr = rcon.make_discretization(mesh_data, order=order,
                            default_scalar_type=dtype)

                    op = StrongAdvectionOperator(v[:dims], 
                            inflow_u=TimeDependentGivenFunction(u_analytic),
                            flux_type=flux_type)
                    if debug_output:
                        vis = SiloVisualizer(discr, rcon)

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

                    if debug_output and rcon.is_head_rank:
                        print "#elements=%d" % len(mesh.elements)

                    test_name = "test-%s-o%d-m%d-r%s" % (
                            flux_type, order, i_mesh, random_partition)

                    rhs = op.bind(discr)

                    stepper = RK4TimeStepper(dtype=dtype)
                    from hedge.timestep import times_and_steps
                    final_time = 1
                    step_it = times_and_steps(
                            final_time=final_time,
                            max_dt_getter=lambda t: op.estimate_timestep(discr,
                                stepper=stepper, t=t, fields=u))

                    for step, t, dt in step_it:
                        u = stepper(u, t, dt, rhs)

                    assert u.dtype == dtype

                    u_true = discr.interpolate_volume_function(
                            lambda x, el: u_analytic(x, el, final_time))
                    error = u-u_true
                    l2_error = discr.norm(error)

                    if debug_output:
                        visf = vis.make_file(test_name+"-final")
                        vis.add_data(visf, [
                            ("u", u),
                            ("u_true", u_true),
                            ("ic", ic)])
                        visf.close()

                    eoc_rec.add_data_point(order, l2_error)

                if debug_output and rcon.is_head_rank:
                    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] > 3
                assert eoc_rec.estimate_order_of_convergence(2)[-1,1] > 7
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
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