diff --git a/meshmode/discretization/__init__.py b/meshmode/discretization/__init__.py
index db3712ddb1de6075dd381513a069f7484fc388f9..ac5fdc8ed3a0302485aa9fe4e2391f191bd5d8ce 100644
--- a/meshmode/discretization/__init__.py
+++ b/meshmode/discretization/__init__.py
@@ -30,6 +30,7 @@ import pyopencl.array  # noqa
 
 __doc__ = """
 .. autoclass:: ElementGroupBase
+.. autoclass:: InterpolatoryElementGroupBase
 .. autoclass:: ElementGroupFactory
 .. autoclass:: Discretization
 """
@@ -60,28 +61,6 @@ class ElementGroupBase(object):
         Returns a :class:`numpy.ndarray` of shape ``(dim, nunit_nodes)``
         of reference coordinates of interpolation nodes.
 
-    .. method:: basis()
-
-        Returns a :class:`list` of basis functions that take arrays
-        of shape ``(dim, n)`` and return an array of shape (n,)``
-        (which performs evaluation of the basis function).
-
-    .. method:: grad_basis()
-
-        :returns: a :class:`tuple` of functions, each of which
-            accepts arrays of shape *(dims, npts)* and returns a
-            :class:`tuple` of length *dims* containing the
-            derivatives along each axis as an array of size
-            *npts*.  'Scalar' evaluation, by passing just one
-            vector of length *dims*, is also supported.
-
-    .. method:: diff_matrices()
-
-        Return a :attr:`dim`-long :class:`tuple` of matrices of
-        shape ``(nunit_nodes, nunit_nodes)``, each of which,
-        when applied to an array of nodal values, take derivatives
-        in the reference (r,s,t) directions.
-
     .. method:: weights()
 
         Returns an array of length :attr:`nunit_nodes` containing
@@ -113,6 +92,14 @@ class ElementGroupBase(object):
     def dim(self):
         return self.mesh_el_group.dim
 
+    def basis(self):
+        raise NoninterpolatoryElementGroupError("'%s' "
+                "is not equipped with a unisolvent function space "
+                "and therefore cannot be used for interpolation")
+
+    grad_basis = basis
+    diff_matrices = basis
+
     def _nodes(self):
         # Not cached, because the global nodes array is what counts.
         # This is just used to build that.
@@ -137,6 +124,38 @@ class ElementGroupBase(object):
 # }}}
 
 
+# {{{ interpolatory element group base
+
+class InterpolatoryElementGroupBase(ElementGroupBase):
+    """A subclass of :class:`ElementGroupBase` that is equipped with a
+    function space.
+
+    .. method:: basis()
+
+        Returns a :class:`list` of basis functions that take arrays
+        of shape ``(dim, n)`` and return an array of shape (n,)``
+        (which performs evaluation of the basis function).
+
+    .. method:: grad_basis()
+
+        :returns: a :class:`tuple` of functions, each of which
+            accepts arrays of shape *(dims, npts)* and returns a
+            :class:`tuple` of length *dims* containing the
+            derivatives along each axis as an array of size
+            *npts*.  'Scalar' evaluation, by passing just one
+            vector of length *dims*, is also supported.
+
+    .. method:: diff_matrices()
+
+        Return a :attr:`dim`-long :class:`tuple` of matrices of
+        shape ``(nunit_nodes, nunit_nodes)``, each of which,
+        when applied to an array of nodal values, take derivatives
+        in the reference (r,s,t) directions.
+    """
+
+# }}}
+
+
 # {{{ group factories
 
 class ElementGroupFactory(object):
@@ -156,6 +175,7 @@ class OrderBasedGroupFactory(ElementGroupFactory):
 
         return self.group_class(mesh_el_group, self.order, node_nr_base)
 
+
 # }}}
 
 
diff --git a/meshmode/discretization/poly_element.py b/meshmode/discretization/poly_element.py
index 898dde7e73c4e88407614a0dd86daf2596b585e0..1d25e337d146d57f9d52dccb08e855f99c135664 100644
--- a/meshmode/discretization/poly_element.py
+++ b/meshmode/discretization/poly_element.py
@@ -62,12 +62,12 @@ Group factories
 # loopy sees strides that it doesn't expect and complains.
 
 
-from meshmode.discretization import ElementGroupBase
+from meshmode.discretization import ElementGroupBase, InterpolatoryElementGroupBase
 
 
 # {{{ base class for poynomial elements
 
-class PolynomialElementGroupBase(ElementGroupBase):
+class PolynomialElementGroupBase(InterpolatoryElementGroupBase):
     @memoize_method
     def mass_matrix(self):
         assert self.is_orthogonal_basis()