From 6fc72f523747e001a2ebcb5a224b8fa4b68658e9 Mon Sep 17 00:00:00 2001 From: Andreas Kloeckner <inform@tiker.net> Date: Sun, 10 Jan 2016 18:47:34 -0600 Subject: [PATCH] Add advection convergence test --- test/test_grudge.py | 125 +++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 124 insertions(+), 1 deletion(-) diff --git a/test/test_grudge.py b/test/test_grudge.py index ee1828a5..18d4aba4 100644 --- a/test/test_grudge.py +++ b/test/test_grudge.py @@ -164,6 +164,8 @@ def test_tri_diff_mat(ctx_factory, dim, order=4): def test_2d_gauss_theorem(ctx_factory): """Verify Gauss's theorem explicitly on a mesh""" + pytest.importorskip("meshpy") + from meshpy.geometry import make_circle, GeometryBuilder from meshpy.triangle import MeshInfo, build @@ -201,8 +203,129 @@ def test_2d_gauss_theorem(ctx_factory): assert abs(gauss_err.get()) < 5e-15 +@pytest.mark.parametrize(("mesh_name", "mesh_pars"), [ + ("disk", [0.1, 0.05]), + ("rect2", [4, 8]), + ("rect3", [4, 6]), + ]) +@pytest.mark.parametrize("flux_type", ["upwind"]) +@pytest.mark.parametrize("order", [3, 4, 5]) +def test_convergence_advec(ctx_factory, mesh_name, mesh_pars, flux_type, order, + visualize=False): + """Test whether 2D advection actually converges""" + + cl_ctx = cl.create_some_context() + queue = cl.CommandQueue(cl_ctx) + + from pytools.convergence import EOCRecorder + eoc_rec = EOCRecorder() + + for mesh_par in mesh_pars: + if mesh_name == "disk": + pytest.importorskip("meshpy") + + from meshpy.geometry import make_circle, GeometryBuilder + from meshpy.triangle import MeshInfo, build + + geob = GeometryBuilder() + geob.add_geometry(*make_circle(1)) + mesh_info = MeshInfo() + geob.set(mesh_info) + + mesh_info = build(mesh_info, max_volume=mesh_par) + + from meshmode.mesh.io import from_meshpy + mesh = from_meshpy(mesh_info, order=1) + h = np.sqrt(mesh_par) + dim = 2 + dt_factor = 4 + + elif mesh_name.startswith("rect"): + dim = int(mesh_name[4:]) + from meshmode.mesh.generation import generate_regular_rect_mesh + mesh = generate_regular_rect_mesh(a=(-0.5,)*dim, b=(0.5,)*dim, + n=(mesh_par,)*dim, order=4) + + h = 1/mesh_par + if dim == 2: + dt_factor = 4 + elif dim == 3: + dt_factor = 2 + else: + raise ValueError("dt_factor not known for %dd" % dim) + + else: + raise ValueError("invalid mesh name: " + mesh_name) + + v = np.array([0.27, 0.31, 0.1])[:dim] + norm_v = la.norm(v) + + def f(x): + return sym.sin(10*x) + + def u_analytic(x): + return f( + -v.dot(x)/norm_v + + sym.var("t", sym.DD_SCALAR)*norm_v) + + from grudge.models.advection import StrongAdvectionOperator + discr = Discretization(cl_ctx, mesh, order=order) + op = StrongAdvectionOperator(v, + inflow_u=u_analytic(sym.nodes(dim, sym.BTAG_ALL)), + flux_type=flux_type) + + bound_op = bind(discr, op.sym_operator()) + + u = bind(discr, u_analytic(sym.nodes(dim)))(queue, t=0) + + def rhs(t, u): + return bound_op(queue, t=t, u=u) + + if dim == 3: + final_time = 0.1 + else: + final_time = 0.2 + + dt = dt_factor * h/order**2 + nsteps = (final_time // dt) + 1 + dt = final_time/nsteps + 1e-15 + + from grudge.shortcuts import set_up_rk4 + dt_stepper = set_up_rk4("u", dt, u, rhs) + + last_u = None + + from grudge.shortcuts import make_visualizer + vis = make_visualizer(discr, vis_order=order) + + step = 0 + + for event in dt_stepper.run(t_end=final_time): + if isinstance(event, dt_stepper.StateComputed): + step += 1 + print(event.t) + + last_t = event.t + last_u = event.state_component + + if visualize: + vis.write_vtk_file("fld-%04d.vtu" % step, + [("u", event.state_component)]) + + error_l2 = bind(discr, + sym.norm(2, sym.var("u")-u_analytic(sym.nodes(dim))))( + queue, t=last_t, u=last_u).get() + print(h, error_l2) + eoc_rec.add_data_point(h, error_l2) + + print(eoc_rec.pretty_print(abscissa_label="h", + error_label="L2 Error")) + + assert eoc_rec.order_estimate() > order + + # You can test individual routines by typing -# $ python test_layer_pot.py 'test_routine()' +# $ python test_grudge.py 'test_routine()' if __name__ == "__main__": import sys -- GitLab