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
BasicType
and 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 aGeometryType
in 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
GlobalGeometryTypeIndex
as the "canonical" encoding ofGeometryType
in a single template parameter and provide implicit andconstexpr
-capable roundtripping between aGeometryType
and 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 GeometryTypeIndex
and the necessary implicit conversion operators. This should not create unwanted implicit conversions, asenum class
does 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?