Add a Grid concept

Merged Christian Engwer requested to merge feature/concepts into master

Summary

With C++20 concepts, we have the opportunity to modernize code and get rid of hard-to-reason CRTP patterns. Concepts express type requirements in a much more concise way and give enough information to the compiler to express errors when an interface is not meet. Although compilers are still working on better error messages for concepts, the situation is already much better than for SFINAE and CRTP pattern counterparts. Additionally, concepts may be refined to express additional requirements on the type.

So, this MR attempts to close that gap by introducing concepts for the most important parts of the grid.

Note: This MR was initially implemented using SFINAE concepts by @carsten.graeser and later changed to be C++20 concepts.

Concept Check

You can use the concept to check that grids (or other individual components) fulfill the interface:

// assert that G is a grid
static_assert(Dune::Concept::Grid<Grid>, "G does not implement a dune-grid");

Dune is currently in C++17. That means that concepts should not be used in a way that highers the usage requirements. That's why I have introduced DUNE_GRID_HAVE_CONCEPTS in the concepts.hh header. That allow early users to adopt the code and ourselves to check that grids fulfill the interface without necessarily requiring all users to have C++20 (checks are already working in the CI tests of this MR!)

Concept Refinement

Downstream projects that do not need to enforce C++17 may already choose to use extend the concepts in other ways meaningful to them:

// extend grid concept to be a multi-domain grid 
template<class G>
concept MultiDomainGrid = Dune::Concept::Grid<G> && requires(G grid, std::size_t domain) {
  { grid.subDomain(domain) } -> Dune::Concept::Grid; // sub-domains shall also be a grid
};

Implementation Details

Dimension loops

To implement the concepts in the grid, we need to loop the dimensions of the grid in a generic form. This is not trivial to achieve in a way that is both "testable" and "debuggable". Thus, what is implemented here is testable and has a fair level of debuggability according to @santiago.ospina and @simon.praetorius experiments. See discussion of alternatives here staging/dune-functions!378 (comment 118730).

Archetypes

Archetypes are types that fulfill the concept requirements of a type and may be used to instantiate generic functions inside of concept definitions (see for example Grid::communicate() where the data handle argument is a template). These archetypes are just declarations and only introduced to write proper concept checks.

TODO

Edited by Simon Praetorius

Merge request reports