From c5f88fab3cdeca596e42e424dfbdba865f4789da Mon Sep 17 00:00:00 2001 From: Felix Schindler <felix.schindler@wwu.de> Date: Thu, 25 Jan 2018 15:00:10 +0100 Subject: [PATCH] [test.spaces.dg] add tests for DiscontinuousLagrangeSpace --- dune/gdt/test/spaces/dg_lagrange.cc | 894 ++++++++++++++++++++++++++++ 1 file changed, 894 insertions(+) create mode 100644 dune/gdt/test/spaces/dg_lagrange.cc diff --git a/dune/gdt/test/spaces/dg_lagrange.cc b/dune/gdt/test/spaces/dg_lagrange.cc new file mode 100644 index 000000000..517288a1a --- /dev/null +++ b/dune/gdt/test/spaces/dg_lagrange.cc @@ -0,0 +1,894 @@ +// This file is part of the dune-gdt project: +// https://github.com/dune-community/dune-gdt +// Copyright 2010-2017 dune-gdt developers and contributors. All rights reserved. +// License: Dual licensed as BSD 2-Clause License (http://opensource.org/licenses/BSD-2-Clause) +// or GPL-2.0+ (http://opensource.org/licenses/gpl-license) +// with "runtime exception" (http://www.dune-project.org/license.html) +// Authors: +// Felix Schindler (2018) + +#include <dune/xt/common/test/main.hxx> // <- this one has to come first (includes the config.h)! + +#include <algorithm> +#include <memory> +#include <tuple> + +#include <dune/geometry/quadraturerules.hh> +#include <dune/geometry/referenceelements.hh> +#include <dune/geometry/refinement.hh> + +#include <dune/grid/common/rangegenerators.hh> + +#include <dune/xt/common/fvector.hh> +#include <dune/xt/common/numeric_cast.hh> +#include <dune/xt/grid/gridprovider/cube.hh> + +#include <dune/gdt/spaces/dg/default.hh> + + +template <class GridLayerType, int p> +struct DiscontinuousLagrangeSpace : public ::testing::Test +{ + using SpaceType = Dune::GDT::DiscontinuousLagrangeSpace<GridLayerType, p>; + using D = typename SpaceType::DomainFieldType; + static const constexpr size_t d = SpaceType::dimDomain; + + virtual std::shared_ptr<GridLayerType> grid_layer() = 0; + + std::shared_ptr<SpaceType> space; + + ~DiscontinuousLagrangeSpace() = default; + + void SetUp() override final + { + ASSERT_TRUE(grid_layer() != nullptr && grid_layer() != 0); + space = std::shared_ptr<SpaceType>(new SpaceType(*grid_layer())); + } + + void TearDown() override final + { + space.reset(); + } + + void basis_exists_on_each_element_with_correct_size() + { + ASSERT_TRUE(grid_layer() != nullptr && grid_layer() != 0); + ASSERT_TRUE(space != nullptr && space != 0); + for (auto&& element : elements(*grid_layer())) + EXPECT_EQ(Dune::numLagrangePoints(element.geometry().type().id(), d, p), + space->base_function_set(element).size()); + } + + void basis_exists_on_each_element_with_correct_order() + { + ASSERT_TRUE(grid_layer() != nullptr && grid_layer() != 0); + ASSERT_TRUE(space != nullptr && space != 0); + for (auto&& element : elements(*grid_layer())) + EXPECT_EQ(p, space->base_function_set(element).order()); + } + + void mapper_reports_correct_num_DoFs_on_each_element() + { + ASSERT_TRUE(grid_layer() != nullptr && grid_layer() != 0); + ASSERT_TRUE(space != nullptr && space != 0); + for (auto&& element : elements(*grid_layer())) + EXPECT_EQ(Dune::numLagrangePoints(element.geometry().type().id(), d, p), space->mapper().numDofs(element)); + } + + void mapper_reports_correct_max_num_DoFs() + { + ASSERT_TRUE(grid_layer() != nullptr && grid_layer() != 0); + ASSERT_TRUE(space != nullptr && space != 0); + size_t max_num_dofs = 0; + for (auto&& element : elements(*grid_layer())) + max_num_dofs = std::max(max_num_dofs, space->mapper().numDofs(element)); + EXPECT_LE(max_num_dofs, space->mapper().maxNumDofs()); + } + + void mapper_maps_correctly() + { + ASSERT_TRUE(grid_layer() != nullptr && grid_layer() != 0); + ASSERT_TRUE(space != nullptr && space != 0); + // we want to check that the numbering is consecutive and that each global index exists only once + std::set<size_t> global_indices; + // we test both call variants + std::set<size_t> map_to_global; + for (auto&& element : Dune::elements(*grid_layer())) { + for (const auto& global_index : space->mapper().globalIndices(element)) + global_indices.insert(global_index); + for (size_t ii = 0; ii < space->mapper().numDofs(element); ++ii) + map_to_global.insert(space->mapper().mapToGlobal(element, ii)); + } + // check for consecutive numbering + EXPECT_EQ(0, *global_indices.begin()); + EXPECT_EQ(global_indices.size() - 1, *global_indices.rbegin()); + EXPECT_EQ(0, *map_to_global.begin()); + EXPECT_EQ(map_to_global.size() - 1, *map_to_global.rbegin()); + // check that the mapper is of the same opinion + EXPECT_EQ(space->mapper().size(), global_indices.size()); + EXPECT_EQ(space->mapper().size(), map_to_global.size()); + // check that each global index is unique + for (const auto& global_index : global_indices) + EXPECT_EQ(1, global_indices.count(global_index)); + for (const auto& global_index : map_to_global) + EXPECT_EQ(1, map_to_global.count(global_index)); + } // ... mapper_maps_correctly(...) + + void lagrange_points_exist_on_each_element_with_correct_size() + { + ASSERT_TRUE(grid_layer() != nullptr && grid_layer() != 0); + ASSERT_TRUE(space != nullptr && space != 0); + for (auto&& element : elements(*grid_layer())) + EXPECT_EQ(Dune::numLagrangePoints(element.geometry().type().id(), d, p), space->lagrange_points(element).size()); + } + + void basis_is_lagrange_basis() + { + ASSERT_TRUE(grid_layer() != nullptr && grid_layer() != 0); + ASSERT_TRUE(space != nullptr && space != 0); + double tolerance = 1e-15; + for (auto&& element : elements(*grid_layer())) { + const auto basis = space->base_function_set(element); + const auto lagrange_points = space->lagrange_points(element); + EXPECT_EQ(lagrange_points.size(), basis.size()); + for (size_t ii = 0; ii < lagrange_points.size(); ++ii) { + const auto values = basis.evaluate(lagrange_points[ii]); + for (size_t jj = 0; jj < basis.size(); ++jj) { + ASSERT_TRUE(Dune::XT::Common::FloatCmp::eq(values[jj][0], ii == jj ? 1. : 0., tolerance, tolerance)) + << "lagrange_points[" << ii << "] = " << lagrange_points[ii] + << "\nbasis.evaluate(lagrange_points[ii]) = " << values; + } + } + } + } // ... basis_is_lagrange_basis(...) + + void basis_jacobians_seem_to_be_correct() + { + ASSERT_TRUE(grid_layer() != nullptr && grid_layer() != 0); + ASSERT_TRUE(space != nullptr && space != 0); + for (auto&& element : elements(*grid_layer())) { + const auto& reference_element = Dune::ReferenceElements<D, d>::general(element.geometry().type()); + const auto basis = space->base_function_set(element); + const double h = 1e-6; + for (const auto& quadrature_point : Dune::QuadratureRules<D, d>::rule(element.geometry().type(), basis.order())) { + const auto& xx = quadrature_point.position(); + const auto& J_inv_T = element.geometry().jacobianInverseTransposed(xx); + const auto jacobians = basis.jacobian(xx); + EXPECT_EQ(basis.size(), jacobians.size()); + const auto values_xx = basis.evaluate(xx); + EXPECT_EQ(basis.size(), values_xx.size()); + auto approximate_jacobians = jacobians; + // compute approximate partial derivatives + for (size_t dd = 0; dd < d; ++dd) { + // try to find a suitable x + h + auto xx_plus_h = xx; + xx_plus_h[dd] += h; + if (!reference_element.checkInside(xx_plus_h)) { + xx_plus_h[dd] -= 2. * h; + } + ASSERT_TRUE(reference_element.checkInside(xx_plus_h)) << "xx_plus_h = " << xx_plus_h + << " is not inside the reference element!"; + const auto values_xx_plus_h = basis.evaluate(xx_plus_h); + EXPECT_EQ(basis.size(), values_xx_plus_h.size()); + for (size_t ii = 0; ii < basis.size(); ++ii) { + approximate_jacobians[ii][0][dd] = (values_xx_plus_h[ii] - values_xx[ii]) / (xx_plus_h[dd] - xx[dd]); + if (xx_plus_h[dd] - xx[dd] < 0) + approximate_jacobians[ii][0][dd] *= -1.; + } + } + // transform + auto tmp_jac = approximate_jacobians[0][0]; + for (size_t ii = 0; ii < basis.size(); ++ii) { + J_inv_T.mv(approximate_jacobians[ii][0], tmp_jac); + approximate_jacobians[ii][0] = tmp_jac; + } + // check + double tolerance = 1e-4; + for (size_t ii = 0; ii < basis.size(); ++ii) + EXPECT_TRUE( + Dune::XT::Common::FloatCmp::eq(jacobians[ii][0], approximate_jacobians[ii][0], tolerance, tolerance)) + << "ii = " << ii << "\njacobians[ii][0] = " << jacobians[ii][0] << "\n" + << "approximate_jacobians[ii][0] = " << approximate_jacobians[ii][0] << "\n" + << "absolue L_infty error: " << (jacobians[ii][0] - approximate_jacobians[ii][0]).infinity_norm() << "\n" + << "relative L_infty error: " + << (jacobians[ii][0] - approximate_jacobians[ii][0]).infinity_norm() / jacobians[ii][0].infinity_norm(); + } + } + } // ... basis_jacobians_seem_to_be_correct(...) +}; // struct DiscontinuousLagrangeSpace + + +template <class G, int p> +struct DiscontinuousLagrangeSpaceOnSimplicialLeafView + : public DiscontinuousLagrangeSpace<typename Dune::XT::Grid::GridProvider<G>::LeafGridViewType, p> +{ + using GridProviderType = Dune::XT::Grid::GridProvider<G>; + using LeafGridViewType = typename GridProviderType::LeafGridViewType; + + GridProviderType grid_provider; + std::shared_ptr<LeafGridViewType> leaf_view; + + DiscontinuousLagrangeSpaceOnSimplicialLeafView() // (i) negative coordinates and not the same as the reference + : grid_provider(Dune::XT::Grid::make_cube_grid<G>(-1.5, -1, 3).grid_ptr()) // element, + { // (ii) at least 3 elements to have fully inner ones, + grid_provider.global_refine(1); // (iii) refine at least once to obtain all kinds of orientations + leaf_view = std::make_shared<LeafGridViewType>(grid_provider.leaf_view()); + } + + ~DiscontinuousLagrangeSpaceOnSimplicialLeafView() = default; + + std::shared_ptr<LeafGridViewType> grid_layer() override final + { + return leaf_view; + } +}; // struct DiscontinuousLagrangeSpaceOnSimplicialLeafView + + +using SimplicialGrids = ::testing::Types<ONED_1D, + YASP_1D_EQUIDISTANT_OFFSET +#if HAVE_DUNE_ALUGRID + , + ALU_2D_SIMPLEX_CONFORMING, + ALU_2D_SIMPLEX_NONCONFORMING +#endif +#if HAVE_DUNE_UGGRID || HAVE_UG + , + UG_2D +#endif +#if HAVE_DUNE_ALUGRID + , + ALU_3D_SIMPLEX_CONFORMING, + ALU_3D_SIMPLEX_NONCONFORMING +#endif +#if HAVE_DUNE_UGGRID || HAVE_UG + , + UG_3D +#endif + >; + + +template <class G> +using Order0SimplicialDiscontinuousLagrangeSpace = DiscontinuousLagrangeSpaceOnSimplicialLeafView<G, 0>; +TYPED_TEST_CASE(Order0SimplicialDiscontinuousLagrangeSpace, SimplicialGrids); +TYPED_TEST(Order0SimplicialDiscontinuousLagrangeSpace, basis_exists_on_each_element_with_correct_size) +{ + this->basis_exists_on_each_element_with_correct_size(); +} +TYPED_TEST(Order0SimplicialDiscontinuousLagrangeSpace, basis_exists_on_each_element_with_correct_order) +{ + this->basis_exists_on_each_element_with_correct_order(); +} +TYPED_TEST(Order0SimplicialDiscontinuousLagrangeSpace, mapper_reports_correct_num_DoFs_on_each_element) +{ + this->mapper_reports_correct_num_DoFs_on_each_element(); +} +TYPED_TEST(Order0SimplicialDiscontinuousLagrangeSpace, mapper_reports_correct_max_num_DoFs) +{ + this->mapper_reports_correct_max_num_DoFs(); +} +TYPED_TEST(Order0SimplicialDiscontinuousLagrangeSpace, mapper_maps_correctly) +{ + this->mapper_maps_correctly(); +} +TYPED_TEST(Order0SimplicialDiscontinuousLagrangeSpace, lagrange_points_exist_on_each_element_with_correct_size) +{ + this->lagrange_points_exist_on_each_element_with_correct_size(); +} +TYPED_TEST(Order0SimplicialDiscontinuousLagrangeSpace, basis_is_lagrange_basis) +{ + this->basis_is_lagrange_basis(); +} +TYPED_TEST(Order0SimplicialDiscontinuousLagrangeSpace, basis_jacobians_seem_to_be_correct) +{ + this->basis_jacobians_seem_to_be_correct(); +} + + +template <class G> +using Order1SimplicialDiscontinuousLagrangeSpace = DiscontinuousLagrangeSpaceOnSimplicialLeafView<G, 1>; +TYPED_TEST_CASE(Order1SimplicialDiscontinuousLagrangeSpace, SimplicialGrids); +TYPED_TEST(Order1SimplicialDiscontinuousLagrangeSpace, basis_exists_on_each_element_with_correct_size) +{ + this->basis_exists_on_each_element_with_correct_size(); +} +TYPED_TEST(Order1SimplicialDiscontinuousLagrangeSpace, basis_exists_on_each_element_with_correct_order) +{ + this->basis_exists_on_each_element_with_correct_order(); +} +TYPED_TEST(Order1SimplicialDiscontinuousLagrangeSpace, mapper_reports_correct_num_DoFs_on_each_element) +{ + this->mapper_reports_correct_num_DoFs_on_each_element(); +} +TYPED_TEST(Order1SimplicialDiscontinuousLagrangeSpace, mapper_reports_correct_max_num_DoFs) +{ + this->mapper_reports_correct_max_num_DoFs(); +} +TYPED_TEST(Order1SimplicialDiscontinuousLagrangeSpace, mapper_maps_correctly) +{ + this->mapper_maps_correctly(); +} +TYPED_TEST(Order1SimplicialDiscontinuousLagrangeSpace, lagrange_points_exist_on_each_element_with_correct_size) +{ + this->lagrange_points_exist_on_each_element_with_correct_size(); +} +TYPED_TEST(Order1SimplicialDiscontinuousLagrangeSpace, basis_is_lagrange_basis) +{ + this->basis_is_lagrange_basis(); +} +TYPED_TEST(Order1SimplicialDiscontinuousLagrangeSpace, basis_jacobians_seem_to_be_correct) +{ + this->basis_jacobians_seem_to_be_correct(); +} + + +template <class G> +using Order2SimplicialDiscontinuousLagrangeSpace = DiscontinuousLagrangeSpaceOnSimplicialLeafView<G, 2>; +TYPED_TEST_CASE(Order2SimplicialDiscontinuousLagrangeSpace, SimplicialGrids); +TYPED_TEST(Order2SimplicialDiscontinuousLagrangeSpace, basis_exists_on_each_element_with_correct_size) +{ + this->basis_exists_on_each_element_with_correct_size(); +} +TYPED_TEST(Order2SimplicialDiscontinuousLagrangeSpace, basis_exists_on_each_element_with_correct_order) +{ + this->basis_exists_on_each_element_with_correct_order(); +} +TYPED_TEST(Order2SimplicialDiscontinuousLagrangeSpace, mapper_reports_correct_num_DoFs_on_each_element) +{ + this->mapper_reports_correct_num_DoFs_on_each_element(); +} +TYPED_TEST(Order2SimplicialDiscontinuousLagrangeSpace, mapper_reports_correct_max_num_DoFs) +{ + this->mapper_reports_correct_max_num_DoFs(); +} +TYPED_TEST(Order2SimplicialDiscontinuousLagrangeSpace, mapper_maps_correctly) +{ + this->mapper_maps_correctly(); +} +TYPED_TEST(Order2SimplicialDiscontinuousLagrangeSpace, lagrange_points_exist_on_each_element_with_correct_size) +{ + this->lagrange_points_exist_on_each_element_with_correct_size(); +} +TYPED_TEST(Order2SimplicialDiscontinuousLagrangeSpace, basis_is_lagrange_basis) +{ + this->basis_is_lagrange_basis(); +} +TYPED_TEST(Order2SimplicialDiscontinuousLagrangeSpace, basis_jacobians_seem_to_be_correct) +{ + this->basis_jacobians_seem_to_be_correct(); +} + + +template <class G, int p> +struct DiscontinuousLagrangeSpaceOnCubicLeafView + : public DiscontinuousLagrangeSpace<typename Dune::XT::Grid::GridProvider<G>::LeafGridViewType, p> +{ + using GridProviderType = Dune::XT::Grid::GridProvider<G>; + using LeafGridViewType = typename GridProviderType::LeafGridViewType; + + std::shared_ptr<GridProviderType> grid_provider; + std::shared_ptr<LeafGridViewType> leaf_view; + + DiscontinuousLagrangeSpaceOnCubicLeafView() + { + using D = typename G::ctype; + static const constexpr size_t d = G::dimension; + Dune::FieldVector<D, d> lower_left(-1.5); // (i) negative coordinates and not the same as the reference element + Dune::FieldVector<D, d> upper_right(-1.); + std::array<unsigned int, d> num_elements; // (ii) at least 3 elements to have fully inner ones + std::fill(num_elements.begin(), num_elements.end(), 3); + grid_provider = std::make_shared<GridProviderType>( + Dune::StructuredGridFactory<G>::createCubeGrid(lower_left, upper_right, num_elements)); + leaf_view = std::make_shared<LeafGridViewType>(grid_provider->leaf_view()); + } + + ~DiscontinuousLagrangeSpaceOnCubicLeafView() = default; + + std::shared_ptr<LeafGridViewType> grid_layer() override final + { + return leaf_view; + } +}; // struct DiscontinuousLagrangeSpaceOnCubicLeafView + + +using CubicGrids = ::testing::Types<YASP_2D_EQUIDISTANT_OFFSET +#if HAVE_DUNE_ALUGRID + , + ALU_2D_CUBE +#endif +#if HAVE_DUNE_UGGRID || HAVE_UG + , + UG_2D +#endif + , + YASP_3D_EQUIDISTANT_OFFSET +#if HAVE_DUNE_ALUGRID + , + ALU_3D_CUBE +#endif +#if HAVE_DUNE_UGGRID || HAVE_UG + , + UG_3D +#endif + >; + + +template <class G> +using Order0CubicDiscontinuousLagrangeSpace = DiscontinuousLagrangeSpaceOnCubicLeafView<G, 0>; +TYPED_TEST_CASE(Order0CubicDiscontinuousLagrangeSpace, CubicGrids); +TYPED_TEST(Order0CubicDiscontinuousLagrangeSpace, basis_exists_on_each_element_with_correct_size) +{ + this->basis_exists_on_each_element_with_correct_size(); +} +TYPED_TEST(Order0CubicDiscontinuousLagrangeSpace, basis_exists_on_each_element_with_correct_order) +{ + this->basis_exists_on_each_element_with_correct_order(); +} +TYPED_TEST(Order0CubicDiscontinuousLagrangeSpace, mapper_reports_correct_num_DoFs_on_each_element) +{ + this->mapper_reports_correct_num_DoFs_on_each_element(); +} +TYPED_TEST(Order0CubicDiscontinuousLagrangeSpace, mapper_reports_correct_max_num_DoFs) +{ + this->mapper_reports_correct_max_num_DoFs(); +} +TYPED_TEST(Order0CubicDiscontinuousLagrangeSpace, mapper_maps_correctly) +{ + this->mapper_maps_correctly(); +} +TYPED_TEST(Order0CubicDiscontinuousLagrangeSpace, lagrange_points_exist_on_each_element_with_correct_size) +{ + this->lagrange_points_exist_on_each_element_with_correct_size(); +} +TYPED_TEST(Order0CubicDiscontinuousLagrangeSpace, basis_is_lagrange_basis) +{ + this->basis_is_lagrange_basis(); +} +TYPED_TEST(Order0CubicDiscontinuousLagrangeSpace, basis_jacobians_seem_to_be_correct) +{ + this->basis_jacobians_seem_to_be_correct(); +} + + +template <class G> +using Order1CubicDiscontinuousLagrangeSpace = DiscontinuousLagrangeSpaceOnCubicLeafView<G, 1>; +TYPED_TEST_CASE(Order1CubicDiscontinuousLagrangeSpace, CubicGrids); +TYPED_TEST(Order1CubicDiscontinuousLagrangeSpace, basis_exists_on_each_element_with_correct_size) +{ + this->basis_exists_on_each_element_with_correct_size(); +} +TYPED_TEST(Order1CubicDiscontinuousLagrangeSpace, basis_exists_on_each_element_with_correct_order) +{ + this->basis_exists_on_each_element_with_correct_order(); +} +TYPED_TEST(Order1CubicDiscontinuousLagrangeSpace, mapper_reports_correct_num_DoFs_on_each_element) +{ + this->mapper_reports_correct_num_DoFs_on_each_element(); +} +TYPED_TEST(Order1CubicDiscontinuousLagrangeSpace, mapper_reports_correct_max_num_DoFs) +{ + this->mapper_reports_correct_max_num_DoFs(); +} +TYPED_TEST(Order1CubicDiscontinuousLagrangeSpace, mapper_maps_correctly) +{ + this->mapper_maps_correctly(); +} +TYPED_TEST(Order1CubicDiscontinuousLagrangeSpace, lagrange_points_exist_on_each_element_with_correct_size) +{ + this->lagrange_points_exist_on_each_element_with_correct_size(); +} +TYPED_TEST(Order1CubicDiscontinuousLagrangeSpace, basis_is_lagrange_basis) +{ + this->basis_is_lagrange_basis(); +} +TYPED_TEST(Order1CubicDiscontinuousLagrangeSpace, basis_jacobians_seem_to_be_correct) +{ + this->basis_jacobians_seem_to_be_correct(); +} + + +template <class G> +using Order2CubicDiscontinuousLagrangeSpace = DiscontinuousLagrangeSpaceOnCubicLeafView<G, 2>; +TYPED_TEST_CASE(Order2CubicDiscontinuousLagrangeSpace, CubicGrids); +TYPED_TEST(Order2CubicDiscontinuousLagrangeSpace, basis_exists_on_each_element_with_correct_size) +{ + this->basis_exists_on_each_element_with_correct_size(); +} +TYPED_TEST(Order2CubicDiscontinuousLagrangeSpace, basis_exists_on_each_element_with_correct_order) +{ + this->basis_exists_on_each_element_with_correct_order(); +} +TYPED_TEST(Order2CubicDiscontinuousLagrangeSpace, mapper_reports_correct_num_DoFs_on_each_element) +{ + this->mapper_reports_correct_num_DoFs_on_each_element(); +} +TYPED_TEST(Order2CubicDiscontinuousLagrangeSpace, mapper_reports_correct_max_num_DoFs) +{ + this->mapper_reports_correct_max_num_DoFs(); +} +TYPED_TEST(Order2CubicDiscontinuousLagrangeSpace, mapper_maps_correctly) +{ + this->mapper_maps_correctly(); +} +TYPED_TEST(Order2CubicDiscontinuousLagrangeSpace, lagrange_points_exist_on_each_element_with_correct_size) +{ + this->lagrange_points_exist_on_each_element_with_correct_size(); +} +TYPED_TEST(Order2CubicDiscontinuousLagrangeSpace, basis_is_lagrange_basis) +{ + this->basis_is_lagrange_basis(); +} +TYPED_TEST(Order2CubicDiscontinuousLagrangeSpace, basis_jacobians_seem_to_be_correct) +{ + this->basis_jacobians_seem_to_be_correct(); +} + + +template <class G, int p> +struct DiscontinuousLagrangeSpaceOnPrismLeafView + : public DiscontinuousLagrangeSpace<typename Dune::XT::Grid::GridProvider<G>::LeafGridViewType, p> +{ + using GridProviderType = Dune::XT::Grid::GridProvider<G>; + using LeafGridViewType = typename GridProviderType::LeafGridViewType; + + std::shared_ptr<GridProviderType> grid_provider; + std::shared_ptr<LeafGridViewType> leaf_view; + + DiscontinuousLagrangeSpaceOnPrismLeafView() + { + using D = typename G::ctype; + static const constexpr size_t d = G::dimension; + if (d == 3) { + Dune::GridFactory<G> factory; + for (auto&& vertex : {Dune::XT::Common::FieldVector<D, d>({-1., -1.5, -1.5}), + Dune::XT::Common::FieldVector<D, d>({-1., -1., -1.5}), + Dune::XT::Common::FieldVector<D, d>({-1.5, -1.5, -1.5}), + Dune::XT::Common::FieldVector<D, d>({-1., -1.5, -1.}), + Dune::XT::Common::FieldVector<D, d>({-1., -1., -1.}), + Dune::XT::Common::FieldVector<D, d>({-1.5, -1.5, -1.})}) { + factory.insertVertex(vertex); + } + factory.insertElement(Dune::GeometryType(Dune::GeometryType::prism, 3), {0, 1, 2, 3, 4, 5}); + grid_provider = std::make_shared<GridProviderType>(factory.createGrid()); + grid_provider->global_refine(1); + leaf_view = std::make_shared<LeafGridViewType>(grid_provider->leaf_view()); + } else { + // cannot use ASSERT_... in a ctor + EXPECT_TRUE(false) << "Does not make sense in " << d << "d!\n" + << "=> ALL OTHER TESTS WILL FAIL FOR THIS GRID!!!"; + grid_provider = nullptr; + leaf_view = nullptr; + } + } // DiscontinuousLagrangeSpaceOnPrismLeafView(...) + + ~DiscontinuousLagrangeSpaceOnPrismLeafView() = default; + + std::shared_ptr<LeafGridViewType> grid_layer() override final + { + return leaf_view; + } +}; // struct DiscontinuousLagrangeSpaceOnPrismLeafView + + +using PrismGrids = ::testing::Types< +#if HAVE_DUNE_UGGRID || HAVE_UG + UG_3D +#endif + >; + + +template <class G> +using Order0PrismDiscontinuousLagrangeSpace = DiscontinuousLagrangeSpaceOnPrismLeafView<G, 0>; +TYPED_TEST_CASE(Order0PrismDiscontinuousLagrangeSpace, PrismGrids); +TYPED_TEST(Order0PrismDiscontinuousLagrangeSpace, basis_exists_on_each_element_with_correct_size) +{ + this->basis_exists_on_each_element_with_correct_size(); +} +TYPED_TEST(Order0PrismDiscontinuousLagrangeSpace, basis_exists_on_each_element_with_correct_order) +{ + this->basis_exists_on_each_element_with_correct_order(); +} +TYPED_TEST(Order0PrismDiscontinuousLagrangeSpace, mapper_reports_correct_num_DoFs_on_each_element) +{ + this->mapper_reports_correct_num_DoFs_on_each_element(); +} +TYPED_TEST(Order0PrismDiscontinuousLagrangeSpace, mapper_reports_correct_max_num_DoFs) +{ + this->mapper_reports_correct_max_num_DoFs(); +} +TYPED_TEST(Order0PrismDiscontinuousLagrangeSpace, mapper_maps_correctly) +{ + this->mapper_maps_correctly(); +} +TYPED_TEST(Order0PrismDiscontinuousLagrangeSpace, lagrange_points_exist_on_each_element_with_correct_size) +{ + this->lagrange_points_exist_on_each_element_with_correct_size(); +} +TYPED_TEST(Order0PrismDiscontinuousLagrangeSpace, basis_is_lagrange_basis) +{ + this->basis_is_lagrange_basis(); +} +TYPED_TEST(Order0PrismDiscontinuousLagrangeSpace, basis_jacobians_seem_to_be_correct) +{ + this->basis_jacobians_seem_to_be_correct(); +} + + +template <class G> +using Order1PrismDiscontinuousLagrangeSpace = DiscontinuousLagrangeSpaceOnPrismLeafView<G, 1>; +TYPED_TEST_CASE(Order1PrismDiscontinuousLagrangeSpace, PrismGrids); +TYPED_TEST(Order1PrismDiscontinuousLagrangeSpace, basis_exists_on_each_element_with_correct_size) +{ + this->basis_exists_on_each_element_with_correct_size(); +} +TYPED_TEST(Order1PrismDiscontinuousLagrangeSpace, basis_exists_on_each_element_with_correct_order) +{ + this->basis_exists_on_each_element_with_correct_order(); +} +TYPED_TEST(Order1PrismDiscontinuousLagrangeSpace, mapper_reports_correct_num_DoFs_on_each_element) +{ + this->mapper_reports_correct_num_DoFs_on_each_element(); +} +TYPED_TEST(Order1PrismDiscontinuousLagrangeSpace, mapper_reports_correct_max_num_DoFs) +{ + this->mapper_reports_correct_max_num_DoFs(); +} +TYPED_TEST(Order1PrismDiscontinuousLagrangeSpace, mapper_maps_correctly) +{ + this->mapper_maps_correctly(); +} +TYPED_TEST(Order1PrismDiscontinuousLagrangeSpace, lagrange_points_exist_on_each_element_with_correct_size) +{ + this->lagrange_points_exist_on_each_element_with_correct_size(); +} +TYPED_TEST(Order1PrismDiscontinuousLagrangeSpace, basis_is_lagrange_basis) +{ + this->basis_is_lagrange_basis(); +} +TYPED_TEST(Order1PrismDiscontinuousLagrangeSpace, basis_jacobians_seem_to_be_correct) +{ + this->basis_jacobians_seem_to_be_correct(); +} + + +template <class G> +using Order2PrismDiscontinuousLagrangeSpace = DiscontinuousLagrangeSpaceOnPrismLeafView<G, 2>; +TYPED_TEST_CASE(Order2PrismDiscontinuousLagrangeSpace, PrismGrids); +TYPED_TEST(Order2PrismDiscontinuousLagrangeSpace, basis_exists_on_each_element_with_correct_size) +{ + this->basis_exists_on_each_element_with_correct_size(); +} +TYPED_TEST(Order2PrismDiscontinuousLagrangeSpace, basis_exists_on_each_element_with_correct_order) +{ + this->basis_exists_on_each_element_with_correct_order(); +} +TYPED_TEST(Order2PrismDiscontinuousLagrangeSpace, mapper_reports_correct_num_DoFs_on_each_element) +{ + this->mapper_reports_correct_num_DoFs_on_each_element(); +} +TYPED_TEST(Order2PrismDiscontinuousLagrangeSpace, mapper_reports_correct_max_num_DoFs) +{ + this->mapper_reports_correct_max_num_DoFs(); +} +TYPED_TEST(Order2PrismDiscontinuousLagrangeSpace, mapper_maps_correctly) +{ + this->mapper_maps_correctly(); +} +TYPED_TEST(Order2PrismDiscontinuousLagrangeSpace, lagrange_points_exist_on_each_element_with_correct_size) +{ + this->lagrange_points_exist_on_each_element_with_correct_size(); +} +TYPED_TEST(Order2PrismDiscontinuousLagrangeSpace, basis_is_lagrange_basis) +{ + this->basis_is_lagrange_basis(); +} +TYPED_TEST(Order2PrismDiscontinuousLagrangeSpace, basis_jacobians_seem_to_be_correct) +{ + this->basis_jacobians_seem_to_be_correct(); +} + + +template <class G, int p> +struct DiscontinuousLagrangeSpaceOnMixedLeafView + : public DiscontinuousLagrangeSpace<typename Dune::XT::Grid::GridProvider<G>::LeafGridViewType, p> +{ + using GridProviderType = Dune::XT::Grid::GridProvider<G>; + using LeafGridViewType = typename GridProviderType::LeafGridViewType; + + std::shared_ptr<GridProviderType> grid_provider; + std::shared_ptr<LeafGridViewType> leaf_view; + + DiscontinuousLagrangeSpaceOnMixedLeafView() + { + using D = typename G::ctype; + static const constexpr size_t d = G::dimension; + switch (d) { + case 1: { + // cannot use ASSERT_... in a ctor + EXPECT_TRUE(false) << "Does not make sense in 1d (all cubes are simplices)!\n" + << "=> ALL OTHER TESTS WILL FAIL FOR THIS GRID!!!"; + grid_provider = nullptr; + leaf_view = nullptr; + break; + } + case 2: { + Dune::GridFactory<G> factory; + for (auto&& vertex : {Dune::XT::Common::FieldVector<D, d>({-1., -1.5}), + Dune::XT::Common::FieldVector<D, d>({-1., -1.25}), + Dune::XT::Common::FieldVector<D, d>({-1., -1.}), + Dune::XT::Common::FieldVector<D, d>({-1.5, -1.5}), + Dune::XT::Common::FieldVector<D, d>({-1.5, -1.25}), + Dune::XT::Common::FieldVector<D, d>({-1.5, -1.}), + Dune::XT::Common::FieldVector<D, d>({-1.75, -1.25})}) { + factory.insertVertex(vertex); + } + factory.insertElement(Dune::GeometryType(Dune::GeometryType::cube, 2), {3, 0, 4, 1}); + factory.insertElement(Dune::GeometryType(Dune::GeometryType::cube, 2), {4, 1, 5, 2}); + factory.insertElement(Dune::GeometryType(Dune::GeometryType::simplex, 2), {4, 6, 3}); + factory.insertElement(Dune::GeometryType(Dune::GeometryType::simplex, 2), {4, 5, 6}); + grid_provider = std::make_shared<GridProviderType>(factory.createGrid()); + grid_provider->global_refine(1); + leaf_view = std::make_shared<LeafGridViewType>(grid_provider->leaf_view()); + break; + } + case 3: { + Dune::GridFactory<G> factory; + for (auto&& vertex : {Dune::XT::Common::FieldVector<D, d>({-1., -1.5, -1.}), + Dune::XT::Common::FieldVector<D, d>({-1., -1.25, -1.}), + Dune::XT::Common::FieldVector<D, d>({-1., -1., -1.}), + Dune::XT::Common::FieldVector<D, d>({-1.5, -1.5, -1.}), + Dune::XT::Common::FieldVector<D, d>({-1.5, -1.25, -1.}), + Dune::XT::Common::FieldVector<D, d>({-1.5, -1., -1.}), + Dune::XT::Common::FieldVector<D, d>({-1., -1.5, -1.5}), + Dune::XT::Common::FieldVector<D, d>({-1., -1.25, -1.5}), + Dune::XT::Common::FieldVector<D, d>({-1., -1., -1.5}), + Dune::XT::Common::FieldVector<D, d>({-1.5, -1.5, -1.5}), + Dune::XT::Common::FieldVector<D, d>({-1.5, -1.25, -1.5}), + Dune::XT::Common::FieldVector<D, d>({-1.5, -1., -1.5}), + Dune::XT::Common::FieldVector<D, d>({-1.75, -1.25, -1.})}) { + factory.insertVertex(vertex); + } + factory.insertElement(Dune::GeometryType(Dune::GeometryType::cube, 3), {3, 0, 4, 1, 9, 6, 10, 7}); + factory.insertElement(Dune::GeometryType(Dune::GeometryType::cube, 3), {4, 1, 5, 2, 10, 7, 11, 8}); + factory.insertElement(Dune::GeometryType(Dune::GeometryType::simplex, 3), {4, 12, 3, 10}); + factory.insertElement(Dune::GeometryType(Dune::GeometryType::simplex, 3), {4, 5, 12, 10}); + grid_provider = std::make_shared<GridProviderType>(factory.createGrid()); + grid_provider->global_refine(1); + leaf_view = std::make_shared<LeafGridViewType>(grid_provider->leaf_view()); + break; + } + default: { + // cannot use ASSERT_... in a ctor + EXPECT_TRUE(false) << "Not implemented yet for dimension " << d << "!\n" + << "=> ALL OTHER TESTS WILL FAIL FOR THIS GRID!!!"; + grid_provider = nullptr; + leaf_view = nullptr; + } + } + } // DiscontinuousLagrangeSpaceOnMixedLeafView(...) + + ~DiscontinuousLagrangeSpaceOnMixedLeafView() = default; + + std::shared_ptr<LeafGridViewType> grid_layer() override final + { + return leaf_view; + } +}; // struct DiscontinuousLagrangeSpaceOnMixedLeafView + + +using MixedGrids = ::testing::Types< +#if HAVE_DUNE_UGGRID || HAVE_UG + UG_2D, + UG_3D +#endif + >; + + +template <class G> +using Order0MixedDiscontinuousLagrangeSpace = DiscontinuousLagrangeSpaceOnMixedLeafView<G, 0>; +TYPED_TEST_CASE(Order0MixedDiscontinuousLagrangeSpace, MixedGrids); +TYPED_TEST(Order0MixedDiscontinuousLagrangeSpace, basis_exists_on_each_element_with_correct_size) +{ + this->basis_exists_on_each_element_with_correct_size(); +} +TYPED_TEST(Order0MixedDiscontinuousLagrangeSpace, basis_exists_on_each_element_with_correct_order) +{ + this->basis_exists_on_each_element_with_correct_order(); +} +TYPED_TEST(Order0MixedDiscontinuousLagrangeSpace, mapper_reports_correct_num_DoFs_on_each_element) +{ + this->mapper_reports_correct_num_DoFs_on_each_element(); +} +TYPED_TEST(Order0MixedDiscontinuousLagrangeSpace, mapper_reports_correct_max_num_DoFs) +{ + this->mapper_reports_correct_max_num_DoFs(); +} +TYPED_TEST(Order0MixedDiscontinuousLagrangeSpace, mapper_maps_correctly) +{ + this->mapper_maps_correctly(); +} +TYPED_TEST(Order0MixedDiscontinuousLagrangeSpace, lagrange_points_exist_on_each_element_with_correct_size) +{ + this->lagrange_points_exist_on_each_element_with_correct_size(); +} +TYPED_TEST(Order0MixedDiscontinuousLagrangeSpace, basis_is_lagrange_basis) +{ + this->basis_is_lagrange_basis(); +} +TYPED_TEST(Order0MixedDiscontinuousLagrangeSpace, basis_jacobians_seem_to_be_correct) +{ + this->basis_jacobians_seem_to_be_correct(); +} + + +template <class G> +using Order1MixedDiscontinuousLagrangeSpace = DiscontinuousLagrangeSpaceOnMixedLeafView<G, 1>; +TYPED_TEST_CASE(Order1MixedDiscontinuousLagrangeSpace, MixedGrids); +TYPED_TEST(Order1MixedDiscontinuousLagrangeSpace, basis_exists_on_each_element_with_correct_size) +{ + this->basis_exists_on_each_element_with_correct_size(); +} +TYPED_TEST(Order1MixedDiscontinuousLagrangeSpace, basis_exists_on_each_element_with_correct_order) +{ + this->basis_exists_on_each_element_with_correct_order(); +} +TYPED_TEST(Order1MixedDiscontinuousLagrangeSpace, mapper_reports_correct_num_DoFs_on_each_element) +{ + this->mapper_reports_correct_num_DoFs_on_each_element(); +} +TYPED_TEST(Order1MixedDiscontinuousLagrangeSpace, mapper_reports_correct_max_num_DoFs) +{ + this->mapper_reports_correct_max_num_DoFs(); +} +TYPED_TEST(Order1MixedDiscontinuousLagrangeSpace, mapper_maps_correctly) +{ + this->mapper_maps_correctly(); +} +TYPED_TEST(Order1MixedDiscontinuousLagrangeSpace, lagrange_points_exist_on_each_element_with_correct_size) +{ + this->lagrange_points_exist_on_each_element_with_correct_size(); +} +TYPED_TEST(Order1MixedDiscontinuousLagrangeSpace, basis_is_lagrange_basis) +{ + this->basis_is_lagrange_basis(); +} +TYPED_TEST(Order1MixedDiscontinuousLagrangeSpace, basis_jacobians_seem_to_be_correct) +{ + this->basis_jacobians_seem_to_be_correct(); +} + + +template <class G> +using Order2MixedDiscontinuousLagrangeSpace = DiscontinuousLagrangeSpaceOnMixedLeafView<G, 2>; +TYPED_TEST_CASE(Order2MixedDiscontinuousLagrangeSpace, MixedGrids); +TYPED_TEST(Order2MixedDiscontinuousLagrangeSpace, basis_exists_on_each_element_with_correct_size) +{ + this->basis_exists_on_each_element_with_correct_size(); +} +TYPED_TEST(Order2MixedDiscontinuousLagrangeSpace, basis_exists_on_each_element_with_correct_order) +{ + this->basis_exists_on_each_element_with_correct_order(); +} +TYPED_TEST(Order2MixedDiscontinuousLagrangeSpace, mapper_reports_correct_num_DoFs_on_each_element) +{ + this->mapper_reports_correct_num_DoFs_on_each_element(); +} +TYPED_TEST(Order2MixedDiscontinuousLagrangeSpace, mapper_reports_correct_max_num_DoFs) +{ + this->mapper_reports_correct_max_num_DoFs(); +} +TYPED_TEST(Order2MixedDiscontinuousLagrangeSpace, mapper_maps_correctly) +{ + this->mapper_maps_correctly(); +} +TYPED_TEST(Order2MixedDiscontinuousLagrangeSpace, lagrange_points_exist_on_each_element_with_correct_size) +{ + this->lagrange_points_exist_on_each_element_with_correct_size(); +} +TYPED_TEST(Order2MixedDiscontinuousLagrangeSpace, basis_is_lagrange_basis) +{ + this->basis_is_lagrange_basis(); +} +TYPED_TEST(Order2MixedDiscontinuousLagrangeSpace, basis_jacobians_seem_to_be_correct) +{ + this->basis_jacobians_seem_to_be_correct(); +} -- GitLab