GeometryType cannot be used as a template parameter
Back when I cleaned up the GeometryType, the consensus seemed that we really don't need the BasicType anymore. While cleaning up PDELab for 2.6, we've stumbled across BasicType in a few places and got rid of it in most of them, but we have found one problematic case (see also pdelab/dune-pdelab#102):
In PDELab, we have a unified interface for picking the correct LocalFiniteElement from dune-localfunctions depending on the GridView:
using FEM = RaviartThomasLocalFiniteElementMap<GV,DomainField,RangeField,rt_order>;
That class inspects the GridView and picks the correct implementation from dune-localfunctions, e.g. Dune::RT0Cube2DLocalFiniteElement<D,R>. This inspection fails for grids that do not export compile-time information about their unique cell GeometryType - mostly UG as it supports mixed grids. Right now, the user can work around this problem by explicitly specifying the BasicType:
using FEM = RaviartThomasLocalFiniteElementMap<GV,DomainField,RangeField,rt_order,Dune::GeometryType::simplex>;
That workaround now triggers lots of deprecation warnings.
We basically want the user to be able to say in a template parameter: Pick an implementation that works for tetrahedral or hexahedral elements. The easy solution
RaviartThomasLocalFiniteElementMap<...,Dune::GeometryTypes::simplex(GV::dimension)>
does not work because you can only have certain built-in types as template parameters.
I see three (two-and-a-half) possible solutions:
-
Revert the deprecation of
BasicTypeand postpone a real solution: the cheap way out. Maybe not a bad idea considering where we are in the release process of 2.6. Short term I would really like this and re-deprecate after 2.6 is out. -
Use the
topologyId(accessible viaGeometryType::id()) instead of theBasictype. That works, but you still need two template parameters to encode aGeometryTypein the general case (dimension andtopologyId). Moreover, explaining to users why they have to writeDune::GeometryTypes::simplex(dim).id() // note the trailing .id()won't be easy...
-
Settle on
GlobalGeometryTypeIndexas the "canonical" encoding ofGeometryTypein a single template parameter and provide implicit andconstexpr-capable roundtripping between aGeometryTypeand its index:template<GeometryTypeIndex gt_index> struct FEM { static constexpr GeometryType gt(gt_index); }; int test() { constexpr auto gt = GeometryTypes::triangle; FEM fem<gt>(); constexpr auto gt2 = fem.gt; static_assert(gt == gt2, "this should work"); }This can be easily implemented by adding a
enum class GeometryTypeIndexand the necessary implicit conversion operators. This should not create unwanted implicit conversions, asenum classdoes not implicitly cast into its underlying type.
I am in favor of 1. and 3. Even though we are really late in the release, 3. seems rather low-risk as it is just a straight interface addition. @all: Thoughts?