diff --git a/test/test_grudge.py b/test/test_grudge.py
index f246a895c2bf2b1229986c52c152d405aebf68b4..342c73a042c622d8bf16acd540280283f178fbff 100644
--- a/test/test_grudge.py
+++ b/test/test_grudge.py
@@ -1,4 +1,7 @@
-__copyright__ = "Copyright (C) 2015 Andreas Kloeckner"
+__copyright__ = """
+Copyright (C) 2015 Andreas Kloeckner
+Copyright (C) 2021 University of Illinois Board of Trustees
+"""
 
 __license__ = """
 Permission is hereby granted, free of charge, to any person obtaining a copy
@@ -32,6 +35,8 @@ from pytools.obj_array import flat_obj_array, make_obj_array
 from grudge import sym, bind, DiscretizationCollection
 
 import grudge.dof_desc as dof_desc
+import grudge.op as op
+
 
 import pytest
 from meshmode.array_context import (  # noqa
@@ -67,17 +72,13 @@ def test_inverse_metric(actx_factory, dim):
     from meshmode.mesh.processing import map_mesh
     mesh = map_mesh(mesh, m)
 
-    discr = DiscretizationCollection(actx, mesh, order=4)
+    dcoll = DiscretizationCollection(actx, mesh, order=4)
 
-    sym_op = (
-            sym.forward_metric_derivative_mat(mesh.dim)
-            .dot(
-                sym.inverse_metric_derivative_mat(mesh.dim)
-                )
-            .reshape(-1))
+    from grudge.geometry import \
+        forward_metric_derivative_mat, inverse_metric_derivative_mat
 
-    op = bind(discr, sym_op)
-    mat = op(actx).reshape(mesh.dim, mesh.dim)
+    mat = forward_metric_derivative_mat(actx, dcoll).dot(
+        inverse_metric_derivative_mat(actx, dcoll))
 
     for i in range(mesh.dim):
         for j in range(mesh.dim):
@@ -120,48 +121,50 @@ def test_mass_mat_trig(actx_factory, ambient_dim, discr_tag):
     mesh = mgen.generate_regular_rect_mesh(
             a=(a,)*ambient_dim, b=(b,)*ambient_dim,
             nelements_per_axis=(nel_1d,)*ambient_dim, order=1)
-    discr = DiscretizationCollection(
+    dcoll = DiscretizationCollection(
         actx, mesh, order=order,
         discr_tag_to_group_factory=discr_tag_to_group_factory
     )
 
-    def _get_variables_on(dd):
-        sym_f = sym.var("f", dd=dd)
-        sym_x = sym.nodes(ambient_dim, dd=dd)
-        sym_ones = sym.Ones(dd)
-
-        return sym_f, sym_x, sym_ones
+    def f(x):
+        return actx.np.sin(x[0])**2
 
-    sym_f, sym_x, sym_ones = _get_variables_on(dof_desc.DD_VOLUME)
-    f_volm = actx.to_numpy(flatten(bind(discr, sym.cos(sym_x[0])**2)(actx)))
-    ones_volm = actx.to_numpy(flatten(bind(discr, sym_ones)(actx)))
+    volm_disc = dcoll.discr_from_dd(dof_desc.DD_VOLUME)
+    x_volm = thaw(actx, volm_disc.nodes())
+    f_volm = f(x_volm)
+    ones_volm = volm_disc.zeros(actx) + 1
 
-    sym_f, sym_x, sym_ones = _get_variables_on(dd_quad)
-    f_quad = bind(discr, sym.cos(sym_x[0])**2)(actx)
-    ones_quad = bind(discr, sym_ones)(actx)
+    quad_disc = dcoll.discr_from_dd(dd_quad)
+    x_quad = thaw(actx, quad_disc.nodes())
+    f_quad = f(x_quad)
+    ones_quad = quad_disc.zeros(actx) + 1
 
-    mass_op = bind(discr, sym.MassOperator(dd_quad, dof_desc.DD_VOLUME)(sym_f))
+    mop_1 = op.mass(dcoll, dd_quad, f_quad)
+    num_integral_1 = np.dot(actx.to_numpy(flatten(ones_volm)),
+                            actx.to_numpy(flatten(mop_1)))
 
-    num_integral_1 = np.dot(ones_volm, actx.to_numpy(flatten(mass_op(f=f_quad))))
     err_1 = abs(num_integral_1 - true_integral)
     assert err_1 < 1e-9, err_1
 
-    num_integral_2 = np.dot(f_volm, actx.to_numpy(flatten(mass_op(f=ones_quad))))
+    mop_2 = op.mass(dcoll, dd_quad, ones_quad)
+    num_integral_2 = np.dot(actx.to_numpy(flatten(f_volm)),
+                            actx.to_numpy(flatten(mop_2)))
+
     err_2 = abs(num_integral_2 - true_integral)
     assert err_2 < 1.0e-9, err_2
 
     if discr_tag is dof_desc.DISCR_TAG_BASE:
         # NOTE: `integral` always makes a square mass matrix and
         # `QuadratureSimplexGroupFactory` does not have a `mass_matrix` method.
-        num_integral_3 = bind(discr,
-                sym.integral(sym_f, dd=dd_quad))(f=f_quad)
+        num_integral_3 = np.dot(actx.to_numpy(flatten(f_quad)),
+                                actx.to_numpy(flatten(mop_2)))
         err_3 = abs(num_integral_3 - true_integral)
         assert err_3 < 5.0e-10, err_3
 
 # }}}
 
 
-# {{{ mass operator surface area
+# {{{ mass operator on surface
 
 def _ellipse_surface_area(radius, aspect_ratio):
     # https://docs.scipy.org/doc/scipy/reference/generated/scipy.special.ellipe.html
@@ -226,8 +229,8 @@ def test_mass_surface_area(actx_factory, name):
 
     for resolution in builder.resolutions:
         mesh = builder.get_mesh(resolution, builder.mesh_order)
-        discr = DiscretizationCollection(actx, mesh, order=builder.order)
-        volume_discr = discr.discr_from_dd(dof_desc.DD_VOLUME)
+        dcoll = DiscretizationCollection(actx, mesh, order=builder.order)
+        volume_discr = dcoll.discr_from_dd(dof_desc.DD_VOLUME)
 
         logger.info("ndofs:     %d", volume_discr.ndofs)
         logger.info("nelements: %d", volume_discr.mesh.nelements)
@@ -235,8 +238,10 @@ def test_mass_surface_area(actx_factory, name):
         # {{{ compute surface area
 
         dd = dof_desc.DD_VOLUME
-        sym_op = sym.NodalSum(dd)(sym.MassOperator(dd, dd)(sym.Ones(dd)))
-        approx_surface_area = bind(discr, sym_op)(actx)
+        ones_volm = volume_discr.zeros(actx) + 1
+        flattened_mass_weights = flatten(op.mass(dcoll, dd, ones_volm))
+        approx_surface_area = np.dot(actx.to_numpy(flatten(ones_volm)),
+                                     actx.to_numpy(flattened_mass_weights))
 
         logger.info("surface: got {:.5e} / expected {:.5e}".format(
             approx_surface_area, surface_area))
@@ -244,21 +249,24 @@ def test_mass_surface_area(actx_factory, name):
 
         # }}}
 
-        h_max = bind(discr, sym.h_max_from_volume(
-            discr.ambient_dim, dim=discr.dim, dd=dd))(actx)
-        eoc.add_data_point(h_max, area_error + 1.0e-16)
+        # {{{ compute h_max using mass weights
+
+        h_max = actx.np.max(flattened_mass_weights) ** (1/dcoll.dim)
+
+        # }}}
+
+        eoc.add_data_point(h_max, area_error)
 
     # }}}
 
     logger.info("surface area error\n%s", str(eoc))
 
-    assert eoc.max_error() < 1.0e-14 \
-            or eoc.order_estimate() > builder.order
+    assert eoc.max_error() < 3e-13 or eoc.order_estimate() > builder.order
 
 # }}}
 
 
-# {{{ surface mass inverse
+# {{{ mass inverse on surfaces
 
 @pytest.mark.parametrize("name", ["2-1-ellipse", "spheroid"])
 def test_surface_mass_operator_inverse(actx_factory, name):
@@ -284,39 +292,44 @@ def test_surface_mass_operator_inverse(actx_factory, name):
 
     for resolution in builder.resolutions:
         mesh = builder.get_mesh(resolution, builder.mesh_order)
-        discr = DiscretizationCollection(actx, mesh, order=builder.order)
-        volume_discr = discr.discr_from_dd(dof_desc.DD_VOLUME)
+        dcoll = DiscretizationCollection(actx, mesh, order=builder.order)
+        volume_discr = dcoll.discr_from_dd(dof_desc.DD_VOLUME)
 
         logger.info("ndofs:     %d", volume_discr.ndofs)
         logger.info("nelements: %d", volume_discr.mesh.nelements)
 
         # {{{ compute inverse mass
 
+        def f(x):
+            return actx.np.cos(4.0 * x[0])
+
         dd = dof_desc.DD_VOLUME
-        sym_f = sym.cos(4.0 * sym.nodes(mesh.ambient_dim, dd)[0])
-        sym_op = sym.InverseMassOperator(dd, dd)(
-                sym.MassOperator(dd, dd)(sym.var("f")))
+        x_volm = thaw(actx, volume_discr.nodes())
+        f_volm = f(x_volm)
 
-        f = bind(discr, sym_f)(actx)
-        f_inv = bind(discr, sym_op)(actx, f=f)
+        res = op.inverse_mass(
+            dcoll, op.mass(dcoll, dd, f_volm)
+        )
 
-        inv_error = bind(discr,
-                sym.norm(2, sym.var("x") - sym.var("y"))
-                / sym.norm(2, sym.var("y")))(actx, x=f_inv, y=f)
+        inv_error = actx.np.linalg.norm(res - f_volm, ord=2)
+
+        # }}}
+
+        # {{{ compute h_max from mass weights
+
+        ones_volm = volume_discr.zeros(actx) + 1
+        flattened_mass_weights = flatten(op.mass(dcoll, dd, ones_volm))
+        h_max = actx.np.max(flattened_mass_weights) ** (1/dcoll.dim)
 
         # }}}
 
-        h_max = bind(discr, sym.h_max_from_volume(
-            discr.ambient_dim, dim=discr.dim, dd=dd))(actx)
         eoc.add_data_point(h_max, inv_error)
 
     # }}}
 
     logger.info("inverse mass error\n%s", str(eoc))
 
-    # NOTE: both cases give 1.0e-16-ish at the moment, but just to be on the
-    # safe side, choose a slightly larger tolerance
-    assert eoc.max_error() < 1.0e-14
+    assert eoc.max_error() < 5e-13
 
 # }}}
 
@@ -422,24 +435,25 @@ def test_tri_diff_mat(actx_factory, dim, order=4):
     from pytools.convergence import EOCRecorder
     axis_eoc_recs = [EOCRecorder() for axis in range(dim)]
 
+    def f(x, axis):
+        return actx.np.sin(3*x[axis])
+
+    def df(x, axis):
+        return 3*actx.np.cos(3*x[axis])
+
     for n in [4, 8, 16]:
         mesh = mgen.generate_regular_rect_mesh(a=(-0.5,)*dim, b=(0.5,)*dim,
                 nelements_per_axis=(n,)*dim, order=4)
 
-        discr = DiscretizationCollection(actx, mesh, order=4)
-        nabla = sym.nabla(dim)
+        dcoll = DiscretizationCollection(actx, mesh, order=4)
+        volume_discr = dcoll.discr_from_dd(dof_desc.DD_VOLUME)
+        x = thaw(actx, volume_discr.nodes())
 
         for axis in range(dim):
-            x = sym.nodes(dim)
-
-            f = bind(discr, sym.sin(3*x[axis]))(actx)
-            df = bind(discr, 3*sym.cos(3*x[axis]))(actx)
-
-            sym_op = nabla[axis](sym.var("f"))
-            bound_op = bind(discr, sym_op)
-            df_num = bound_op(f=f)
+            df_num = op.local_grad(dcoll, f(x, axis))[axis]
+            df_volm = df(x, axis)
 
-            linf_error = actx.np.linalg.norm(df_num - df, ord=np.inf)
+            linf_error = actx.np.linalg.norm(df_num - df_volm, ord=np.inf)
             axis_eoc_recs[axis].add_data_point(1/n, linf_error)
 
     for axis, eoc_rec in enumerate(axis_eoc_recs):
diff --git a/test/test_new_world_grudge.py b/test/test_new_world_grudge.py
deleted file mode 100644
index 30b2d08241bac910ffb0a690523466dd79a9a0cc..0000000000000000000000000000000000000000
--- a/test/test_new_world_grudge.py
+++ /dev/null
@@ -1,375 +0,0 @@
-__copyright__ = """
-Copyright (C) 2021 University of Illinois Board of Trustees
-"""
-
-__license__ = """
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-THE SOFTWARE.
-"""
-
-import numpy as np
-
-from meshmode import _acf       # noqa: F401
-from meshmode.dof_array import flatten, thaw
-from meshmode.array_context import (  # noqa
-        pytest_generate_tests_for_pyopencl_array_context
-        as pytest_generate_tests)
-import meshmode.mesh.generation as mgen
-
-import grudge.op as op
-
-from grudge import DiscretizationCollection
-import grudge.dof_desc as dof_desc
-
-import pytest
-
-import logging
-
-logger = logging.getLogger(__name__)
-
-
-# {{{ inverse metric
-
-@pytest.mark.parametrize("dim", [2, 3])
-def test_inverse_metric(actx_factory, dim):
-    actx = actx_factory()
-
-    mesh = mgen.generate_regular_rect_mesh(
-        a=(-0.5,)*dim, b=(0.5,)*dim,
-        nelements_per_axis=(6,)*dim, order=4
-    )
-
-    def m(x):
-        result = np.empty_like(x)
-        result[0] = (
-                1.5*x[0] + np.cos(x[0])
-                + 0.1*np.sin(10*x[1]))
-        result[1] = (
-                0.05*np.cos(10*x[0])
-                + 1.3*x[1] + np.sin(x[1]))
-        if len(x) == 3:
-            result[2] = x[2]
-        return result
-
-    from meshmode.mesh.processing import map_mesh
-    mesh = map_mesh(mesh, m)
-
-    dcoll = DiscretizationCollection(actx, mesh, order=4)
-
-    from grudge.geometry import \
-        forward_metric_derivative_mat, inverse_metric_derivative_mat
-
-    mat = forward_metric_derivative_mat(actx, dcoll).dot(
-        inverse_metric_derivative_mat(actx, dcoll))
-
-    for i in range(mesh.dim):
-        for j in range(mesh.dim):
-            tgt = 1 if i == j else 0
-
-            err = actx.np.linalg.norm(mat[i, j] - tgt, ord=np.inf)
-            logger.info("error[%d, %d]: %.5e", i, j, err)
-            assert err < 1.0e-12, (i, j, err)
-
-# }}}
-
-
-# {{{ mass operator
-
-@pytest.mark.parametrize("ambient_dim", [1, 2, 3])
-@pytest.mark.parametrize("quad_tag", [dof_desc.QTAG_NONE, "OVSMP"])
-def test_mass_mat_trig(actx_factory, ambient_dim, quad_tag):
-    """Check the integral of some trig functions on an interval
-    using the mass matrix.
-    """
-    actx = actx_factory()
-
-    nelements = 17
-    order = 4
-
-    a = -4.0 * np.pi
-    b = +9.0 * np.pi
-    true_integral = 13*np.pi/2 * (b - a)**(ambient_dim - 1)
-
-    from meshmode.discretization.poly_element import \
-        QuadratureSimplexGroupFactory
-
-    dd_quad = dof_desc.DOFDesc(dof_desc.DTAG_VOLUME_ALL, quad_tag)
-
-    if quad_tag is dof_desc.QTAG_NONE:
-        quad_tag_to_group_factory = {}
-    else:
-        quad_tag_to_group_factory = {
-            quad_tag: QuadratureSimplexGroupFactory(order=2*order)
-        }
-
-    mesh = mgen.generate_regular_rect_mesh(
-        a=(a,)*ambient_dim, b=(b,)*ambient_dim,
-        n=(nelements,)*ambient_dim,
-        order=1
-    )
-    dcoll = DiscretizationCollection(
-        actx, mesh, order=order,
-        quad_tag_to_group_factory=quad_tag_to_group_factory
-    )
-
-    def f(x):
-        return actx.np.sin(x[0])**2
-
-    volm_disc = dcoll.discr_from_dd(dof_desc.DD_VOLUME)
-    x_volm = thaw(actx, volm_disc.nodes())
-    f_volm = f(x_volm)
-    ones_volm = volm_disc.zeros(actx) + 1
-
-    quad_disc = dcoll.discr_from_dd(dd_quad)
-    x_quad = thaw(actx, quad_disc.nodes())
-    f_quad = f(x_quad)
-    ones_quad = quad_disc.zeros(actx) + 1
-
-    mop_1 = op.mass(dcoll, dd_quad, f_quad)
-    num_integral_1 = np.dot(actx.to_numpy(flatten(ones_volm)),
-                            actx.to_numpy(flatten(mop_1)))
-
-    err_1 = abs(num_integral_1 - true_integral)
-    assert err_1 < 1e-9, err_1
-
-    mop_2 = op.mass(dcoll, dd_quad, ones_quad)
-    num_integral_2 = np.dot(actx.to_numpy(flatten(f_volm)),
-                            actx.to_numpy(flatten(mop_2)))
-
-    err_2 = abs(num_integral_2 - true_integral)
-    assert err_2 < 1.0e-9, err_2
-
-# }}}
-
-
-# {{{ mass operator on surface
-
-def _ellipse_surface_area(radius, aspect_ratio):
-    # https://docs.scipy.org/doc/scipy/reference/generated/scipy.special.ellipe.html
-    eccentricity = 1.0 - (1/aspect_ratio)**2
-
-    if abs(aspect_ratio - 2.0) < 1.0e-14:
-        # NOTE: hardcoded value so we don't need scipy for the test
-        ellip_e = 1.2110560275684594
-    else:
-        from scipy.special import ellipe        # pylint: disable=no-name-in-module
-        ellip_e = ellipe(eccentricity)
-
-    return 4.0 * radius * ellip_e
-
-
-def _spheroid_surface_area(radius, aspect_ratio):
-    # https://en.wikipedia.org/wiki/Ellipsoid#Surface_area
-    a = 1.0
-    c = aspect_ratio
-
-    if a < c:
-        e = np.sqrt(1.0 - (a/c)**2)
-        return 2.0 * np.pi * radius**2 * (1.0 + (c/a) / e * np.arcsin(e))
-    else:
-        e = np.sqrt(1.0 - (c/a)**2)
-        return 2.0 * np.pi * radius**2 * (1 + (c/a)**2 / e * np.arctanh(e))
-
-
-@pytest.mark.parametrize("name", [
-    "2-1-ellipse", "spheroid", "box2d", "box3d"
-    ])
-def test_mass_surface_area(actx_factory, name):
-    actx = actx_factory()
-
-    # {{{ cases
-
-    if name == "2-1-ellipse":
-        from mesh_data import EllipseMeshBuilder
-        builder = EllipseMeshBuilder(radius=3.1, aspect_ratio=2.0)
-        surface_area = _ellipse_surface_area(builder.radius, builder.aspect_ratio)
-    elif name == "spheroid":
-        from mesh_data import SpheroidMeshBuilder
-        builder = SpheroidMeshBuilder()
-        surface_area = _spheroid_surface_area(builder.radius, builder.aspect_ratio)
-    elif name == "box2d":
-        from mesh_data import BoxMeshBuilder
-        builder = BoxMeshBuilder(ambient_dim=2)
-        surface_area = 1.0
-    elif name == "box3d":
-        from mesh_data import BoxMeshBuilder
-        builder = BoxMeshBuilder(ambient_dim=3)
-        surface_area = 1.0
-    else:
-        raise ValueError("unknown geometry name: %s" % name)
-
-    # }}}
-
-    # {{{ convergence
-
-    from pytools.convergence import EOCRecorder
-    eoc = EOCRecorder()
-
-    for resolution in builder.resolutions:
-        mesh = builder.get_mesh(resolution, builder.mesh_order)
-        dcoll = DiscretizationCollection(actx, mesh, order=builder.order)
-        volume_discr = dcoll.discr_from_dd(dof_desc.DD_VOLUME)
-
-        logger.info("ndofs:     %d", volume_discr.ndofs)
-        logger.info("nelements: %d", volume_discr.mesh.nelements)
-
-        # {{{ compute surface area
-
-        dd = dof_desc.DD_VOLUME
-        ones_volm = volume_discr.zeros(actx) + 1
-        flattened_mass_weights = flatten(op.mass(dcoll, dd, ones_volm))
-        approx_surface_area = np.dot(actx.to_numpy(flatten(ones_volm)),
-                                     actx.to_numpy(flattened_mass_weights))
-
-        logger.info("surface: got {:.5e} / expected {:.5e}".format(
-            approx_surface_area, surface_area))
-        area_error = abs(approx_surface_area - surface_area) / abs(surface_area)
-
-        # }}}
-
-        # {{{ compute h_max using mass weights
-
-        h_max = actx.np.max(flattened_mass_weights) ** (1/dcoll.dim)
-
-        # }}}
-
-        eoc.add_data_point(h_max, area_error)
-
-    # }}}
-
-    logger.info("surface area error\n%s", str(eoc))
-
-    assert eoc.max_error() < 3e-13 or eoc.order_estimate() > builder.order
-
-# }}}
-
-
-# {{{ mass inverse on surfaces
-
-@pytest.mark.parametrize("name", ["2-1-ellipse", "spheroid"])
-def test_surface_mass_operator_inverse(actx_factory, name):
-    actx = actx_factory()
-
-    # {{{ cases
-
-    if name == "2-1-ellipse":
-        from mesh_data import EllipseMeshBuilder
-        builder = EllipseMeshBuilder(radius=3.1, aspect_ratio=2.0)
-    elif name == "spheroid":
-        from mesh_data import SpheroidMeshBuilder
-        builder = SpheroidMeshBuilder()
-    else:
-        raise ValueError("unknown geometry name: %s" % name)
-
-    # }}}
-
-    # {{{ convergence
-
-    from pytools.convergence import EOCRecorder
-    eoc = EOCRecorder()
-
-    for resolution in builder.resolutions:
-        mesh = builder.get_mesh(resolution, builder.mesh_order)
-        dcoll = DiscretizationCollection(actx, mesh, order=builder.order)
-        volume_discr = dcoll.discr_from_dd(dof_desc.DD_VOLUME)
-
-        logger.info("ndofs:     %d", volume_discr.ndofs)
-        logger.info("nelements: %d", volume_discr.mesh.nelements)
-
-        # {{{ compute inverse mass
-
-        def f(x):
-            return actx.np.cos(4.0 * x[0])
-
-        dd = dof_desc.DD_VOLUME
-        x_volm = thaw(actx, volume_discr.nodes())
-        f_volm = f(x_volm)
-
-        res = op.inverse_mass(
-            dcoll, op.mass(dcoll, dd, f_volm)
-        )
-
-        inv_error = actx.np.linalg.norm(res - f_volm, ord=2)
-
-        # }}}
-
-        # {{{ compute h_max from mass weights
-
-        ones_volm = volume_discr.zeros(actx) + 1
-        flattened_mass_weights = flatten(op.mass(dcoll, dd, ones_volm))
-        h_max = actx.np.max(flattened_mass_weights) ** (1/dcoll.dim)
-
-        # }}}
-
-        eoc.add_data_point(h_max, inv_error)
-
-    # }}}
-
-    logger.info("inverse mass error\n%s", str(eoc))
-
-    assert eoc.max_error() < 5e-13
-
-# }}}
-
-
-# {{{ diff operator
-
-@pytest.mark.parametrize("dim", [1, 2, 3])
-def test_tri_diff_mat(actx_factory, dim, order=4):
-    """Check differentiation matrix along the coordinate axes on a disk
-
-    Uses sines as the function to differentiate.
-    """
-
-    actx = actx_factory()
-
-    from pytools.convergence import EOCRecorder
-    axis_eoc_recs = [EOCRecorder() for axis in range(dim)]
-
-    def f(x, axis):
-        return actx.np.sin(3*x[axis])
-
-    def df(x, axis):
-        return 3*actx.np.cos(3*x[axis])
-
-    for n in [4, 8, 16]:
-        mesh = mgen.generate_regular_rect_mesh(
-            a=(-0.5,)*dim, b=(0.5,)*dim,
-            nelements_per_axis=(n,)*dim, order=4
-        )
-
-        dcoll = DiscretizationCollection(actx, mesh, order=4)
-        volume_discr = dcoll.discr_from_dd(dof_desc.DD_VOLUME)
-        x = thaw(actx, volume_discr.nodes())
-
-        for axis in range(dim):
-
-            df_num = op.local_grad(dcoll, f(x, axis))[axis]
-            df_volm = df(x, axis)
-
-            linf_error = actx.np.linalg.norm(df_num - df_volm, ord=np.inf)
-            axis_eoc_recs[axis].add_data_point(1/n, linf_error)
-
-    for axis, eoc_rec in enumerate(axis_eoc_recs):
-        logger.info("axis %d\n%s", axis, eoc_rec)
-        assert eoc_rec.order_estimate() > order - 0.25
-
-# }}}
-
-
-# vim: foldmethod=marker