diff --git a/CHANGELOG.md b/CHANGELOG.md index bc1688bc7080bd7bb237807e5f851b690e54a2f2..e38634f23dc4e699659070f0ba0a8008a551a9ce 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,8 +3,14 @@ SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception --> +## Changelog + - Provide `communicate()` method in `OneDGrid` and `IdentityGrid` +- Grid concepts are here! A `Grid` can now be inspected and also its components checked for valid + interfaces at compilation time using c++20 concepts. Note, this feature is still in development and + might be subject to changes. + # Master (will become release 2.9) - UGGrid is now thread safe on the grid view. diff --git a/doc/doxygen/Doxylocal b/doc/doxygen/Doxylocal index 09b12c7737f88a9f70cf5b7f4cd7e91e24befeaf..1f38c1a310a6857b4d67161263e518ecc4332aec 100644 --- a/doc/doxygen/Doxylocal +++ b/doc/doxygen/Doxylocal @@ -9,6 +9,7 @@ INPUT += @srcdir@/mainpage.txt \ @top_srcdir@/dune/grid/albertagrid \ @top_srcdir@/dune/grid/albertagrid.hh \ @top_srcdir@/dune/grid/common \ + @top_srcdir@/dune/grid/concepts \ @top_srcdir@/dune/grid/geometrygrid.hh \ @top_srcdir@/dune/grid/geometrygrid \ @top_srcdir@/dune/grid/identitygrid.hh \ diff --git a/dune/grid/CMakeLists.txt b/dune/grid/CMakeLists.txt index 0a7ecfb86ad4458dca31a0816047f9674106cf46..793a567a57abe92398eb2d410c10ebe72a85ceea 100644 --- a/dune/grid/CMakeLists.txt +++ b/dune/grid/CMakeLists.txt @@ -3,6 +3,7 @@ add_subdirectory(albertagrid) add_subdirectory(common) +add_subdirectory(concepts) add_subdirectory(geometrygrid) add_subdirectory(identitygrid) add_subdirectory(io) diff --git a/dune/grid/concepts.hh b/dune/grid/concepts.hh new file mode 100644 index 0000000000000000000000000000000000000000..cc7b2d13e1e49dc645a92ea31e6835fe27ac8f75 --- /dev/null +++ b/dune/grid/concepts.hh @@ -0,0 +1,53 @@ +// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root +// SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception +// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- +// vi: set et ts=4 sw=2 sts=2: +#ifndef DUNE_GRID_CONCEPTS_HH +#define DUNE_GRID_CONCEPTS_HH + +/** + * This file contains a convenience definition that checks if concepts are available + * If DUNE_GRID_HAVE_CONCEPTS is true, the dune-grid concepts are available and + * have been included. + * + * In order to enable these concepts, you need the following: + * (i) A C++20 compiler with concepts (i.e. __cpp_concepts >= 201907L) + * (ii) The concepts in the standard library (i.e. __cpp_lib_concepts >= 202002L) + * (iii) A C++ compiler that supports unevaluated context lambdas (i.e. + * can compile `using = decltype([]{})`). This is automatically tested by + * CMake and exposed as a macro definition + * `DUNE_HAVE_CXX_UNEVALUATED_CONTEXT_LAMBDA`. + * + * - `gcc>=9` and `clang>=12` are known to fulfill (i) and (iii). + * - `libstdc++>10` and `libc++>=13` are known to fulfill (ii). + */ + +// check whether c++20 concept can be used +#if __has_include() && __has_include() + #include + #if __cpp_concepts >= 201907L && __cpp_lib_concepts >= 202002L && DUNE_HAVE_CXX_UNEVALUATED_CONTEXT_LAMBDA + #ifndef DUNE_GRID_HAVE_CONCEPTS + #define DUNE_GRID_HAVE_CONCEPTS 1 + #endif + #endif +#endif + +//! Grid concepts are available +#if DUNE_GRID_HAVE_CONCEPTS + +// Include all concept headers +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#endif // DUNE_GRID_HAVE_CONCEPTS + +#endif // DUNE_GRID_CONCEPTS_HH \ No newline at end of file diff --git a/dune/grid/concepts/CMakeLists.txt b/dune/grid/concepts/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..d26a98d2b1962468fd74f47a313df4715a60e5d3 --- /dev/null +++ b/dune/grid/concepts/CMakeLists.txt @@ -0,0 +1,18 @@ +# SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root +# SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception + +install(FILES + datahandle.hh + entity.hh + entityiterator.hh + entityset.hh + geometry.hh + grid.hh + gridview.hh + indexidset.hh + intersection.hh + intersectioniterator.hh + messagebuffer.hh + DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/dune/grid/concepts) + +add_subdirectory(archetypes) \ No newline at end of file diff --git a/dune/grid/concepts/archetypes/CMakeLists.txt b/dune/grid/concepts/archetypes/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..bd6d5e44bffd3c56b864bce4f8d3946c8a73fc2c --- /dev/null +++ b/dune/grid/concepts/archetypes/CMakeLists.txt @@ -0,0 +1,9 @@ +# SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root +# SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception + +install(FILES + datahandle.hh + entity.hh + geometry.hh + messagebuffer.hh + DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/dune/grid/concepts/archetypes) diff --git a/dune/grid/concepts/archetypes/datahandle.hh b/dune/grid/concepts/archetypes/datahandle.hh new file mode 100644 index 0000000000000000000000000000000000000000..6a123f32a5ff122e2704a40f53795da3f60301e9 --- /dev/null +++ b/dune/grid/concepts/archetypes/datahandle.hh @@ -0,0 +1,36 @@ +// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root +// SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception +// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- +// vi: set et ts=4 sw=2 sts=2: +#ifndef DUNE_GRID_CONCEPTS_ARCHETYPES_COMMDATAHANDLE_HH +#define DUNE_GRID_CONCEPTS_ARCHETYPES_COMMDATAHANDLE_HH + +#include + +#include + +#ifndef DOXYGEN +namespace Dune::Concept::Archetypes { + +template +struct CommDataHandle : public Dune::CommDataHandleIF, Data> +{ + using DataType = Data; + + bool contains (int dim, int codim) const; + bool fixedSize (int dim, int codim) const; + + template + std::size_t size (const Entity& entity) const; + + template + void gather (Buffer& buffer, const Entity& entity) const; + + template + void scatter (Buffer& buffer, const Entity& entity, std::size_t size); +}; + +} // end namespace Dune::Concept::Archetypes +#endif // DOXYGEN + +#endif // DUNE_GRID_CONCEPTS_ARCHETYPES_COMMDATAHANDLE_HH diff --git a/dune/grid/concepts/archetypes/entity.hh b/dune/grid/concepts/archetypes/entity.hh new file mode 100644 index 0000000000000000000000000000000000000000..76680e2a315f0252548df9c01fd89bb068e44af5 --- /dev/null +++ b/dune/grid/concepts/archetypes/entity.hh @@ -0,0 +1,51 @@ +// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root +// SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception +// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- +// vi: set et ts=4 sw=2 sts=2: +#ifndef DUNE_GRID_CONCEPT_ARCHETYPES_ENTITY_HH +#define DUNE_GRID_CONCEPT_ARCHETYPES_ENTITY_HH + +#include +#include +#include +#include + +#ifndef DOXYGEN +namespace Dune::Concept::Archetypes { + +template +struct EntitySeed +{ + static constexpr int codimension = codim; + bool isValid () const; +}; + + +template +struct Entity +{ + static constexpr int dimension = dim; + static constexpr int codimension = codim; + static constexpr int mydimension = dim - codim; + + using Geometry = Archetypes::Geometry; + using EntitySeed = Archetypes::EntitySeed; + + int level () const; + Dune::PartitionType partitionType () const; + Geometry geometry () const; + Dune::GeometryType type () const; + unsigned int subEntities (int cd) const; + EntitySeed seed () const; + + template + Archetypes::Entity subEntity (int i) const; + + bool operator== (Entity const& entity) const; + bool operator!= (Entity const& entity) const; +}; + +} // end namespace Dune::Concept::Archetypes +#endif // DOXYGEN + +#endif // DUNE_GRID_CONCEPT_ARCHETYPES_ENTITY_HH diff --git a/dune/grid/concepts/archetypes/geometry.hh b/dune/grid/concepts/archetypes/geometry.hh new file mode 100644 index 0000000000000000000000000000000000000000..443eb579644eb6daf53d4700e347bfeacec437cd --- /dev/null +++ b/dune/grid/concepts/archetypes/geometry.hh @@ -0,0 +1,56 @@ +// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root +// SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception +// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- +// vi: set et ts=4 sw=2 sts=2: +#ifndef DUNE_GRID_CONCEPTS_ARCHETYPES_GEOMETRY_HH +#define DUNE_GRID_CONCEPTS_ARCHETYPES_GEOMETRY_HH + +#include +#include +#include + +#ifndef DOXYGEN +namespace Dune::Concept::Archetypes { + +struct ReferenceElement {}; + +template +struct Geometry +{ + static constexpr int mydimension = mydim; + static constexpr int coorddimension = cdim; + + using ctype = double; + using Volume = ctype; + using LocalCoordinate = Dune::FieldVector; + using GlobalCoordinate = Dune::FieldVector; + using Jacobian = Dune::FieldMatrix; + using JacobianTransposed = Dune::FieldMatrix; + using JacobianInverse = Dune::FieldMatrix; + using JacobianInverseTransposed = Dune::FieldMatrix; + + Dune::GeometryType type () const; + bool affine () const; + int corners () const; + + GlobalCoordinate corner (int i) const; + GlobalCoordinate global (const LocalCoordinate& local) const; + LocalCoordinate local (const GlobalCoordinate& global) const; + GlobalCoordinate center () const; + + Volume integrationElement (const LocalCoordinate& local) const; + Volume volume () const; + + Jacobian jacobian (const LocalCoordinate& local) const; + JacobianTransposed jacobianTransposed (const LocalCoordinate& local) const; + JacobianInverse jacobianInverse (const LocalCoordinate& local) const; + JacobianInverseTransposed jacobianInverseTransposed (const LocalCoordinate& local) const; +}; + +template +Archetypes::ReferenceElement referenceElement (const Geometry& g); + +} // end namespace Dune::Concept::Archetypes +#endif // DOXYGEN + +#endif // DUNE_GRID_CONCEPTS_ARCHETYPES_GEOMETRY_HH diff --git a/dune/grid/concepts/archetypes/messagebuffer.hh b/dune/grid/concepts/archetypes/messagebuffer.hh new file mode 100644 index 0000000000000000000000000000000000000000..0d4fa109761a1215c26cf45382ed24af04c177b4 --- /dev/null +++ b/dune/grid/concepts/archetypes/messagebuffer.hh @@ -0,0 +1,21 @@ +// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root +// SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception +// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- +// vi: set et ts=4 sw=2 sts=2: +#ifndef DUNE_GRID_CONCEPTS_ARCHETYPES_MESSAGEBUFFER_HH +#define DUNE_GRID_CONCEPTS_ARCHETYPES_MESSAGEBUFFER_HH + +#ifndef DOXYGEN +namespace Dune::Concept::Archetypes { + +template +struct MessageBuffer +{ + void write(const DataType& data); + void read(DataType& data); +}; + +} // end namespace Dune::Concept::Archetypes +#endif // DOXYGEN + +#endif // DUNE_GRID_CONCEPTS_ARCHETYPES_MESSAGEBUFFER_HH diff --git a/dune/grid/concepts/datahandle.hh b/dune/grid/concepts/datahandle.hh new file mode 100644 index 0000000000000000000000000000000000000000..614ef61d9fdbd8c3d3f3770a049954322c345c27 --- /dev/null +++ b/dune/grid/concepts/datahandle.hh @@ -0,0 +1,37 @@ +// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root +// SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception +// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- +// vi: set et ts=4 sw=2 sts=2: +#ifndef DUNE_GRID_CONCEPTS_DATAHANDLE_HH +#define DUNE_GRID_CONCEPTS_DATAHANDLE_HH + +#include + +#include +#include +#include + +namespace Dune::Concept { + +template +concept CommDataHandle = requires(const DH chandle, const Archetypes::Entity<2,0>& entity) +{ + typename DH::DataType; + + { chandle.contains(/*dim*/ 0, /*codim*/ 0) } -> std::convertible_to; + { chandle.fixedSize(/*dim*/ 0, /*codim*/ 0) } -> std::convertible_to; + { chandle.size(entity) } -> std::integral; + + requires requires(DH handle, Archetypes::MessageBuffer buffer) + { + handle.gather(buffer, entity); + handle.scatter(buffer, entity, /*size*/ 0u); + }; +}; + +static_assert(CommDataHandle< Archetypes::CommDataHandle >); + +} // end namespace Dune::Concept + + +#endif // DUNE_GRID_CONCEPTS_DATAHANDLE_HH diff --git a/dune/grid/concepts/entity.hh b/dune/grid/concepts/entity.hh new file mode 100644 index 0000000000000000000000000000000000000000..840c5c2d8e9faa68ce9138fc6e4ba886c7c5c5f6 --- /dev/null +++ b/dune/grid/concepts/entity.hh @@ -0,0 +1,110 @@ +// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root +// SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception +// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- +// vi: set et ts=4 sw=2 sts=2: +#ifndef DUNE_GRID_CONCEPT_ENTITY_HH +#define DUNE_GRID_CONCEPT_ENTITY_HH + +#include +#include + +#include +#include +#include +#include +#include + +namespace Dune::Concept { + +/** + * @brief Model of an entity seed + * @ingroup GridConcepts + * @details Dune::EntitySeed is a template for this model + */ +template +concept EntitySeed = requires(const S seed) +{ + requires std::default_initializable; + { S::codimension } -> std::convertible_to; + { seed.isValid() } -> std::convertible_to; +}; + +static_assert(EntitySeed< Archetypes::EntitySeed<0> >); + + +/** + * @brief Model of a grid entity for any codimension + * @ingroup GridConcepts + * @details Dune::Entity is a template for this model. + */ +template +concept EntityGeneral = std::regular && requires(const E e, unsigned int codim) +{ + requires Geometry; + requires EntitySeed; + requires E::mydimension == (E::dimension - E::codimension); + { e.level() } -> std::convertible_to; + { e.partitionType() } -> std::convertible_to; + { e.geometry() } -> std::convertible_to; + { e.type() } -> std::convertible_to; + { e.subEntities(codim) } -> std::convertible_to; + { e.seed() } -> std::convertible_to; +}; + +static_assert(EntityGeneral< Archetypes::Entity<2,0> >); + + +namespace Impl { + + template + concept EntityCodimExtended = requires(const E e, int subEntity) + { + { e.template subEntity(subEntity) } -> EntityGeneral; + }; + + template + concept AllEntityCodimsExtended = requires(std::make_integer_sequence codims) + { + [](std::integer_sequence) + requires (Impl::EntityCodimExtended &&...) {} (codims); + }; + +} // end namespace Impl + +/** + * @brief Model of a grid entity with extended requirements for codimension 0 + * @ingroup GridConcepts + * @details Dune::Entity of codimension 0 is a template for this model. + */ +template +concept EntityExtended = EntityGeneral && requires(const E e, int maxLevel) +{ + requires (E::codimension == 0); + requires Geometry; + { e.father() } -> std::convertible_to; + { e.hasFather() } -> std::convertible_to; + { e.isLeaf() } -> std::convertible_to; + { e.isRegular() } -> std::convertible_to; + { e.geometryInFather() } -> std::convertible_to; + { e.hbegin(maxLevel) } -> std::convertible_to; + { e.hend(maxLevel) } -> std::convertible_to; + { e.isNew() } -> std::convertible_to; + { e.mightVanish() } -> std::convertible_to; + { e.hasBoundaryIntersections() } -> std::convertible_to; + requires Impl::AllEntityCodimsExtended; + requires std::same_as::Entity>; +}; + +/** + * @brief Model of a grid entity + * @ingroup GridConcepts + * @details Codimension 0 entities are required to have an extended interface. + * Dune::Entity is a template for this model. + */ +template +concept Entity = EntityGeneral && ((E::codimension != 0) || EntityExtended); + +} // end namespace Dune::Concept + + +#endif // DUNE_GRID_CONCEPT_ENTITY_HH diff --git a/dune/grid/concepts/entityiterator.hh b/dune/grid/concepts/entityiterator.hh new file mode 100644 index 0000000000000000000000000000000000000000..3a33dc34ecb172ce946993a14a3a86dc536194f6 --- /dev/null +++ b/dune/grid/concepts/entityiterator.hh @@ -0,0 +1,28 @@ +// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root +// SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception +// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- +// vi: set et ts=4 sw=2 sts=2: +#ifndef DUNE_GRID_CONCEPTS_ENTITY_ITERATOR_HH +#define DUNE_GRID_CONCEPTS_ENTITY_ITERATOR_HH + +#include +#include + +#include + +namespace Dune::Concept { + +/** + * @brief Model of an entity iterator + * @ingroup GridConcepts + * @details Dune::EntityIterator is a template for this model + */ +template +concept EntityIterator = std::forward_iterator && std::default_initializable && requires +{ + requires Entity; +}; + +} // end namespace Dune::Concept + +#endif // DUNE_GRID_CONCEPTS_ENTITY_ITERATOR_HH diff --git a/dune/grid/concepts/entityset.hh b/dune/grid/concepts/entityset.hh new file mode 100644 index 0000000000000000000000000000000000000000..e3f6387359255c365d34b37f09ce51d8bd24233b --- /dev/null +++ b/dune/grid/concepts/entityset.hh @@ -0,0 +1,78 @@ +// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root +// SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception +// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- +// vi: set et ts=4 sw=2 sts=2: +#ifndef DUNE_GRID_CONCEPTS_ENTITY_SET_HH +#define DUNE_GRID_CONCEPTS_ENTITY_SET_HH + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +namespace Dune::Concept { +namespace Impl { + + template + concept EntitySetEssentials = std::copyable && requires(const ES es, Dune::GeometryType type, int codim) + { + typename ES::Traits; + typename ES::ctype; + requires IndexSet; + requires Intersection; + requires IntersectionIterator; + { ES::conforming } -> std::convertible_to; + { ES::dimension } -> std::convertible_to; + { ES::dimensionworld } -> std::convertible_to; + { es.grid() } -> std::convertible_to; + { es.indexSet() } -> std::convertible_to; + { es.size(codim) } -> std::convertible_to; + { es.size(type) } -> std::convertible_to; + { es.comm() } -> std::convertible_to; + { es.overlapSize(codim) } -> std::convertible_to; + { es.ghostSize(codim) } -> std::convertible_to; + + requires requires(Archetypes::CommDataHandle& handle, + InterfaceType iface, CommunicationDirection dir) + { + es.communicate(handle, iface, dir); + }; + }; + +} // end namespace Impl + +/** + * @brief Model of an entity set + * @ingroup GridConcepts + * @details An entity set is an iterable set of entities whose index set can + * contiguously index all the iterated entities. A Dune::GridView is a + * template for this model, but not necessarily the only one. In particular, + * entity sets are used to enumerate sub-ranges of entities contained in the + * grid view. + */ +template +concept EntitySet = Impl::EntitySetEssentials && requires(const ES es) +{ + requires (codim != 0) || requires(const typename ES::template Codim::Entity& entity) + { + { es.ibegin(entity) } -> std::convertible_to; + { es.iend(entity) } -> std::convertible_to; + }; + requires Geometry::Geometry>; + requires Geometry::LocalGeometry>; + requires EntityIterator::Iterator>; + { es.template begin() } -> std::convertible_to::Iterator>; + { es.template end() } -> std::convertible_to::Iterator>; +}; + +} // end namespace Dune::Concept + +#endif // DUNE_GRID_CONCEPTS_ENTITY_SET_HH diff --git a/dune/grid/concepts/geometry.hh b/dune/grid/concepts/geometry.hh new file mode 100644 index 0000000000000000000000000000000000000000..2793528c97f3f36e57c7ee68eb02ad09335830ec --- /dev/null +++ b/dune/grid/concepts/geometry.hh @@ -0,0 +1,54 @@ +// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root +// SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception +// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- +// vi: set et ts=4 sw=2 sts=2: +#ifndef DUNE_GRID_CONCEPTS_GEOMETRY_HH +#define DUNE_GRID_CONCEPTS_GEOMETRY_HH + +#include + +#include +#include +#include +#include + +namespace Dune::Concept { + +template +concept ReferenceElement = true; + +static_assert(ReferenceElement< Archetypes::ReferenceElement >); + + +/** + * @brief Model of a geometry object + * @ingroup GridConcepts + * @details Dune::Geometry is a template for this model + */ +template +concept Geometry = requires(const G g, typename G::GlobalCoordinate global, typename G::LocalCoordinate local) +{ + typename G::ctype; + { G::mydimension } -> std::convertible_to; + { G::coorddimension } -> std::convertible_to; + { g.type() } -> std::convertible_to; + { g.affine() } -> std::convertible_to; + { g.corners() } -> std::convertible_to; + { g.corner(/*i*/ int{}) } -> std::convertible_to; + { g.global(local) } -> std::convertible_to; + { g.local(global) } -> std::convertible_to; + { g.integrationElement(local) } -> std::convertible_to; + { g.volume() } -> std::convertible_to; + { g.center() } -> std::convertible_to; + { g.jacobian(local) } -> std::convertible_to; + { g.jacobianInverse(local) } -> std::convertible_to; + { g.jacobianTransposed(local) } -> std::convertible_to; + { g.jacobianInverseTransposed(local) } -> std::convertible_to; + { referenceElement(g) } -> ReferenceElement; +}; + +static_assert(Geometry< Archetypes::Geometry<2,3> >); + +} // end namespace Dune::Concept + +#endif // DUNE_GRID_CONCEPTS_GEOMETRY_HH diff --git a/dune/grid/concepts/grid.hh b/dune/grid/concepts/grid.hh new file mode 100644 index 0000000000000000000000000000000000000000..7bc15e00f3c3d20177f6f6ef8d844c1e219685f7 --- /dev/null +++ b/dune/grid/concepts/grid.hh @@ -0,0 +1,145 @@ +// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root +// SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception +// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- +// vi: set et ts=4 sw=2 sts=2: +#ifndef DUNE_GRID_CONCEPTS_GRID_HH +#define DUNE_GRID_CONCEPTS_GRID_HH + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +/*!@defgroup GridConcepts Grid Concepts + * @{ + * @par Description + * This group gathers several concepts related to grids. + * @} + */ + +namespace Dune::Concept { +namespace Impl { + + template, + class Interior = typename Traits::template Partition, + class IBorder = typename Traits::template Partition, + class Overlap = typename Traits::template Partition, + class OFront = typename Traits::template Partition, + class All = typename Traits::template Partition, + class Ghost = typename Traits::template Partition> + concept GridCodim = requires(const G cg, const typename Traits::EntitySeed& seed) + { + requires Geometry; + requires Geometry; + requires EntityIterator; + requires EntityIterator; + requires EntityIterator; + requires EntityIterator; + requires EntityIterator; + requires EntityIterator; + requires EntityIterator; + requires EntityIterator; + requires EntityIterator; + requires EntityIterator; + requires EntityIterator; + requires EntityIterator; + requires EntityIterator; + requires EntityIterator; + + requires Entity; + requires EntitySeed; + { cg.entity(seed) } -> std::convertible_to; + + requires (not Dune::Capabilities::canCommunicate::v) || + requires(G g, Archetypes::CommDataHandle& handle) + { + { g.loadBalance(handle) } -> std::convertible_to; + }; + }; + + + template + concept AllGridCodims = requires(std::make_integer_sequence codims) + { + [](std::integer_sequence) + requires (GridCodim &&...) {} (codims); + }; + +} // end namespace Impl + + +/** + * @brief Model of a grid + * @ingroup GridConcepts + * @details Dune::Grid is a template for this model + */ +template +concept Grid = requires(const G cg, int level, int codim, Dune::GeometryType type) +{ + // static constants + { G::dimension } -> std::convertible_to; + { G::dimensionworld } -> std::convertible_to; + + // type and concepts requirements + requires GridView; + requires GridView; + requires Intersection; + requires Intersection; + requires IntersectionIterator; + requires IntersectionIterator; + requires IndexSet; + requires IndexSet; + requires IdSet; + requires IdSet; + requires std::same_as; + requires std::same_as; + requires Impl::AllGridCodims; + typename G::ctype; + typename G::HierarchicIterator; + + // const methods + { cg.maxLevel() } -> std::convertible_to; + { cg.size(level, codim) } -> std::convertible_to; + { cg.size(codim) } -> std::convertible_to; + { cg.size(level, type) } -> std::convertible_to; + { cg.size(type) } -> std::convertible_to; + { cg.numBoundarySegments() } -> std::convertible_to; + { cg.levelGridView(level) } -> std::convertible_to; + { cg.leafGridView() } -> std::convertible_to; + { cg.globalIdSet() } -> std::convertible_to; + { cg.localIdSet() } -> std::convertible_to; + { cg.levelIndexSet(level) } -> std::convertible_to; + { cg.leafIndexSet() } -> std::convertible_to; + { cg.comm() } -> std::convertible_to; + + // mutable methods + requires requires(G g, int refCount, const typename G::template Codim<0>::Entity& entity) + { + { g.mark(refCount,entity) } -> std::convertible_to; + { g.getMark(entity) } -> std::convertible_to; + { g.preAdapt() } -> std::convertible_to; + { g.adapt() } -> std::convertible_to; + { g.loadBalance() } -> std::convertible_to; + g.globalRefine(refCount); + g.postAdapt(); + }; +}; + +} // end namespace Dune::Concept + +#endif // DUNE_GRID_CONCEPTS_GRID_HH diff --git a/dune/grid/concepts/gridview.hh b/dune/grid/concepts/gridview.hh new file mode 100644 index 0000000000000000000000000000000000000000..af20d4fd516a1b81d4ddd931a17edb21f4ec3714 --- /dev/null +++ b/dune/grid/concepts/gridview.hh @@ -0,0 +1,64 @@ +// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root +// SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception +// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- +// vi: set et ts=4 sw=2 sts=2: +#ifndef DUNE_GRID_CONCEPTS_GRIDVIEW_HH +#define DUNE_GRID_CONCEPTS_GRIDVIEW_HH + +#include + +#include +#include +#include + +#include + +namespace Dune::Concept { +namespace Impl { + + template::template Partition::Iterator> + concept EntityPartitionSpan = requires(const ES es) + { + requires EntityIterator; + { es.template begin() } -> std::convertible_to; + { es.template end() } -> std::convertible_to; + }; + + + template + concept EntitySetAllPartitions = EntitySet && requires + { + requires EntityPartitionSpan; + requires EntityPartitionSpan; + requires EntityPartitionSpan; + requires EntityPartitionSpan; + requires EntityPartitionSpan; + }; + + template + requires Dune::Capabilities::hasEntityIterator::v + void requireEntitySetAllPartitions() + requires EntitySetAllPartitions {} + + template + requires (not Dune::Capabilities::hasEntityIterator::v) + void requireEntitySetAllPartitions() {} + +} // end namespace Impl + +/** + * @brief Model of a grid view + * @ingroup GridConcepts + * @details Dune::GridView is a template for this model + */ +template +concept GridView = EntitySet && requires(std::make_integer_sequence dims) +{ + [](std::integer_sequence) requires + requires { (Impl::requireEntitySetAllPartitions(),...); }{} (dims); +}; + +} // end namespace Dune::Concept + +#endif // DUNE_GRID_CONCEPTS_GRIDVIEW_HH diff --git a/dune/grid/concepts/indexidset.hh b/dune/grid/concepts/indexidset.hh new file mode 100644 index 0000000000000000000000000000000000000000..e152b913080b726d1bbd67ed17d0a70847fa7361 --- /dev/null +++ b/dune/grid/concepts/indexidset.hh @@ -0,0 +1,93 @@ +// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root +// SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception +// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- +// vi: set et ts=4 sw=2 sts=2: +#ifndef DUNE_GRID_CONCEPTS_INDEX_SET_HH +#define DUNE_GRID_CONCEPTS_INDEX_SET_HH + +#include +#include + +#include +#include +#include + +namespace Dune::Concept { +namespace Impl { + + template::Entity> + concept IndexSetEntityCodim = requires(const IS is, int i, unsigned int sub_codim, const E& entity) + { + requires Entity; + { is.template index(entity) } -> std::convertible_to; + { is.index(entity) } -> std::convertible_to; + { is.template subIndex(entity, i, sub_codim) } -> std::convertible_to; + { is.subIndex(entity, i, sub_codim) } -> std::convertible_to; + { is.contains(entity) } -> std::convertible_to; + }; + + template + concept AllIndexSetEntityCodims = requires(std::make_integer_sequence codims) + { + [](std::integer_sequence) + requires (IndexSetEntityCodim &&...) {} (codims); + }; + +} // end namespace Impl + +/** + * @brief Model of an index set + * @ingroup GridConcepts + * @details Dune::Grid::LevelIndexSet and Dune::Grid::LeafIndexSet are templates + * for this model + */ +template +concept IndexSet = requires(const IS is, Dune::GeometryType type, int sub_codim) +{ + { IS::dimension } -> std::convertible_to; + { is.types(sub_codim) } -> std::convertible_to; + { is.size(type) } -> std::convertible_to; + { is.size(sub_codim) } -> std::convertible_to; + requires std::integral; + typename IS::Types; + requires Impl::AllIndexSetEntityCodims; +}; + + +namespace Impl { + + template::Entity> + concept IdSetEntityCodim = requires(const IS is, const E& entity) + { + requires Entity; + { is.template id(entity) } -> std::convertible_to; + { is.id(entity) } -> std::convertible_to; + }; + + template + concept AllIdSetEntityCodims = requires(std::make_integer_sequence codims) + { + [](std::integer_sequence) + requires (IdSetEntityCodim &&...) {} (codims); + }; + +} // end namespace Impl + +/** + * @brief Model of an id set + * @ingroup GridConcepts + * @details Dune::Grid::GlobalIdSet and Dune::Grid::LocalIdSet are templates + * for this model + */ +template +concept IdSet = requires(const IS is, const typename IS::template Codim<0>::Entity& entity, int i, unsigned int codim) +{ + { is.subId(entity,i,codim) } -> std::convertible_to; + requires Impl::AllIdSetEntityCodims; +}; + +} // end namespace Dune::Concept + +#endif // DUNE_GRID_CONCEPTS_INDEX_SET_HH diff --git a/dune/grid/concepts/intersection.hh b/dune/grid/concepts/intersection.hh new file mode 100644 index 0000000000000000000000000000000000000000..72e81089fba05f4e56d7991a879eaa530738ed12 --- /dev/null +++ b/dune/grid/concepts/intersection.hh @@ -0,0 +1,51 @@ +// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root +// SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception +// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- +// vi: set et ts=4 sw=2 sts=2: +#ifndef DUNE_GRID_CONCEPTS_INTERSECTION_HH +#define DUNE_GRID_CONCEPTS_INTERSECTION_HH + +#include +#include + +#include +#include +#include + +namespace Dune::Concept { + +/** + * @brief Model of an intersection + * @ingroup GridConcepts + * @details Dune::Grid::Intersection is a template for this model + */ +template +concept Intersection = std::regular && requires(const I i, typename I::LocalCoordinate local) +{ + requires EntityGeneral; + requires Geometry; + requires Geometry; + typename I::ctype; + { I::mydimension } -> std::convertible_to; + { I::dimensionworld } -> std::convertible_to; + { i.boundary() } -> std::convertible_to; + { i.boundarySegmentIndex() } -> std::convertible_to; + { i.neighbor() } -> std::convertible_to; + { i.inside() } -> std::convertible_to; + { i.outside() } -> std::convertible_to; + { i.conforming() } -> std::convertible_to; + { i.geometryInInside() } -> std::convertible_to; + { i.geometryInOutside() } -> std::convertible_to; + { i.geometry() } -> std::convertible_to; + { i.type() } -> std::convertible_to; + { i.indexInInside() } -> std::convertible_to; + { i.indexInOutside() } -> std::convertible_to; + { i.outerNormal(local) } -> std::convertible_to; + { i.integrationOuterNormal(local) } -> std::convertible_to; + { i.unitOuterNormal(local) } -> std::convertible_to; + { i.centerUnitOuterNormal() } -> std::convertible_to; +}; + +} // end namespace Dune::Concept + +#endif // DUNE_GRID_CONCEPTS_INTERSECTION_HH diff --git a/dune/grid/concepts/intersectioniterator.hh b/dune/grid/concepts/intersectioniterator.hh new file mode 100644 index 0000000000000000000000000000000000000000..966ed0eabe260988aa0d5171e6d6033092afc13a --- /dev/null +++ b/dune/grid/concepts/intersectioniterator.hh @@ -0,0 +1,28 @@ +// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root +// SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception +// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- +// vi: set et ts=4 sw=2 sts=2: +#ifndef DUNE_GRID_CONCEPTS_INTERSECTION_ITERATOR_HH +#define DUNE_GRID_CONCEPTS_INTERSECTION_ITERATOR_HH + +#include +#include + +#include + +namespace Dune::Concept { + +/** + * @brief Model of an intersection iterator + * @ingroup GridConcepts + * @details Dune::IntersectionIterator is a template for this model + */ +template +concept IntersectionIterator = std::forward_iterator && std::default_initializable && requires +{ + requires Intersection; +}; + +} // end namespace Dune::Concept + +#endif // DUNE_GRID_CONCEPTS_INTERSECTION_ITERATOR_HH diff --git a/dune/grid/concepts/messagebuffer.hh b/dune/grid/concepts/messagebuffer.hh new file mode 100644 index 0000000000000000000000000000000000000000..a42d9f7d5ed3c327bafea60a16fe3a7a6cbc7a0a --- /dev/null +++ b/dune/grid/concepts/messagebuffer.hh @@ -0,0 +1,28 @@ +// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root +// SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception +// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- +// vi: set et ts=4 sw=2 sts=2: +#ifndef DUNE_GRID_CONCEPT_MESSAGEBUFFER_HH +#define DUNE_GRID_CONCEPT_MESSAGEBUFFER_HH + +#include + +namespace Dune::Concept { + +/** + * @brief Model of a message buffer + * @ingroup GridConcepts + */ +template +concept MessageBuffer = requires(MB mb, DataType& data) +{ + mb.write(data); + mb.read(data); +}; + +static_assert(Concept::MessageBuffer, unsigned char>); + +} // end namespace Dune::Concept + + +#endif // DUNE_GRID_CONCEPT_MESSAGEBUFFER_HH diff --git a/dune/grid/test/CMakeLists.txt b/dune/grid/test/CMakeLists.txt index 8cc87bf5f48edbcc8dd87c08c29a67e33b07876b..d3862750817c9ee7df96d2e4d4dbf955c85c339a 100644 --- a/dune/grid/test/CMakeLists.txt +++ b/dune/grid/test/CMakeLists.txt @@ -3,6 +3,8 @@ add_subdirectory(yasp) +dune_add_test(SOURCES test-concepts.cc) + dune_add_test(SOURCES geometrygrid-coordfunction-copyconstructor.cc) dune_add_test(NAME test-geogrid-yaspgrid diff --git a/dune/grid/test/checkentitylifetime.hh b/dune/grid/test/checkentitylifetime.hh index 8a9bc3faba1fd4549b4bae76de8a7f8e60ee8074..c80886005e66ca6356ab22ecfcda37e3717661d5 100644 --- a/dune/grid/test/checkentitylifetime.hh +++ b/dune/grid/test/checkentitylifetime.hh @@ -18,6 +18,7 @@ #include #include #include +#include #if not defined(DUNE_ENTITY_LIFETIME_CHECK_ELEMENT_COUNT) #define DUNE_ENTITY_LIFETIME_CHECK_ELEMENT_COUNT 32 @@ -38,9 +39,10 @@ bool checkEntityLifetimeForCodim(GV gv, std::size_t check_element_count, Dune::C << " entities" << std::endl; check_element_count = gv.size(codim); } - + using Iterator = typename GV::template Codim::Iterator; auto& index_set = gv.indexSet(); auto& id_set = gv.grid().localIdSet(); + Iterator entity_iterator = gv.template begin(); std::vector indices; std::vector ids; @@ -52,6 +54,9 @@ bool checkEntityLifetimeForCodim(GV gv, std::size_t check_element_count, Dune::C std::size_t i = 0; for (const auto& e : entities(gv,Dune::Codim())) { +#if DUNE_GRID_HAVE_CONCEPTS + static_assert(Dune::Concept::Entity>); +#endif if (++i > check_element_count) break; indices.push_back(index_set.index(e)); @@ -81,6 +86,15 @@ bool checkEntityLifetimeForCodim(GV gv, std::size_t check_element_count, Dune::C " (" << entity_list[i].geometry().corner(0) << " != " << coords[i] << ")"); } +#if DUNE_GRID_HAVE_CONCEPTS + static_assert(Dune::Concept::GridView); + static_assert(Dune::Concept::IndexSet); + static_assert(Dune::Concept::IdSet); + static_assert(Dune::Concept::IdSet); + static_assert(Dune::Concept::EntityIterator); + static_assert(Dune::Concept::Grid); +#endif + return true; } diff --git a/dune/grid/test/checkintersectionlifetime.hh b/dune/grid/test/checkintersectionlifetime.hh index 741c9413ea1617d3e37fc2bedbc1ccb9c2dfeb9c..97e41cae2844a4ff72010e46df8c2eb27e835fc4 100644 --- a/dune/grid/test/checkintersectionlifetime.hh +++ b/dune/grid/test/checkintersectionlifetime.hh @@ -17,6 +17,8 @@ #include +#include + template void checkIntersectionLifetime(GV gv, std::size_t check_element_count = 32) { @@ -40,6 +42,17 @@ void checkIntersectionLifetime(GV gv, std::size_t check_element_count = 32) std::vector > intersection_list; std::vector > coords; + auto entity_iterator = gv.template begin<0>(); + + auto intersection_iterator = gv.ibegin(*entity_iterator); + +#if DUNE_GRID_HAVE_CONCEPTS + static_assert(Dune::Concept::EntityIterator); + static_assert(Dune::Concept::IntersectionIterator); + static_assert(Dune::Concept::Entity>); + static_assert(Dune::Concept::Intersection>); +#endif + // store indices + entities + intersections + coordinates { std::size_t i = 0; @@ -53,6 +66,12 @@ void checkIntersectionLifetime(GV gv, std::size_t check_element_count = 32) coords.push_back({}); for (const auto& is : intersections(gv,e)) { + +#if DUNE_GRID_HAVE_CONCEPTS + static_assert(Dune::Concept::Entity>); + static_assert(Dune::Concept::Intersection>); +#endif + indices.back().push_back(is.indexInInside()); intersection_list.back().push_back(is); coords.back().push_back(is.geometry().corner(0)); diff --git a/dune/grid/test/test-concepts.cc b/dune/grid/test/test-concepts.cc new file mode 100644 index 0000000000000000000000000000000000000000..de77b1cfc40ec35ca82ea412a72985df11f08b3b --- /dev/null +++ b/dune/grid/test/test-concepts.cc @@ -0,0 +1,63 @@ +// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root +// SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception +// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- +// vi: set et ts=4 sw=2 sts=2: +#ifdef HAVE_CONFIG_H +#include +#endif + +#include + +#if DUNE_GRID_HAVE_CONCEPTS + +#include +#include +#include +#include + +#if HAVE_ALBERTA +#include +#endif + +#if HAVE_DUNE_UGGRID +#include +#endif + + +int main ( int argc, char **argv ) +{ + Dune::MPIHelper::instance( argc, argv ); + + static_assert(Dune::Concept::Grid< Dune::OneDGrid >); + static_assert(Dune::Concept::Grid< Dune::YaspGrid<1> >); + static_assert(Dune::Concept::Grid< Dune::YaspGrid<2> >); + static_assert(Dune::Concept::Grid< Dune::YaspGrid<3> >); + +#if HAVE_ALBERTA + static_assert(Dune::Concept::Grid< Dune::AlbertaGrid<1,1> >); + static_assert(Dune::Concept::Grid< Dune::AlbertaGrid<1,2> >); + static_assert(Dune::Concept::Grid< Dune::AlbertaGrid<1,3> >); + static_assert(Dune::Concept::Grid< Dune::AlbertaGrid<2,2> >); + static_assert(Dune::Concept::Grid< Dune::AlbertaGrid<2,3> >); + static_assert(Dune::Concept::Grid< Dune::AlbertaGrid<3,3> >); +#endif + +#if HAVE_DUNE_UGGRID + static_assert(Dune::Concept::Grid< Dune::UGGrid<2> >); + static_assert(Dune::Concept::Grid< Dune::UGGrid<3> >); +#endif + + // check grid wrappers + static_assert(Dune::Concept::Grid< Dune::GeometryGrid< Dune::YaspGrid<1> > >); + static_assert(Dune::Concept::Grid< Dune::IdentityGrid< Dune::YaspGrid<1> > >); + +} + +#else // DUNE_GRID_HAVE_CONCEPTS + +int main() +{ + return 77; +} + +#endif // DUNE_GRID_HAVE_CONCEPTS