35#ifndef DUMUX_IO_CVFE_LAGRANGE_GRID_HH
36#define DUMUX_IO_CVFE_LAGRANGE_GRID_HH
40#if DUMUX_HAVE_GRIDFORMAT
48#include <gridformat/traits/dune.hpp>
49#include <gridformat/grid/traits.hpp>
50#include <gridformat/grid/cell_type.hpp>
52#include <dune/geometry/referenceelements.hh>
53#include <dune/grid/common/mcmgmapper.hh>
54#include <dune/localfunctions/lagrange/lagrangelfecache.hh>
62namespace CVFELagrangeDetail {
72inline std::tuple<int, int, int> vtkSortKey(
const Dune::GeometryType& gt,
const auto& key)
74 using namespace GridFormat::Dune::LagrangeDetail;
75 const int codim = key.codim();
76 const int vtkSub = dune_to_gfmt_sub_entity(gt, key.subEntity(), codim);
77 const bool rev = gt.isTriangle() && codim == 1 && key.subEntity() == 1;
78 const int within = rev ? -(int(key.index())) : int(key.index());
79 return {-codim, vtkSub, within};
85template<
int k,
class Gr
idView>
86using PQkDofHelpers = std::conditional_t<k == 2,
87 Dumux::PQ2LagrangeDofHelper<GridView>,
88 Dumux::PQ3LagrangeDofHelper<GridView>>;
93int lagrangeLayout(Dune::GeometryType gt,
int )
95 const int d = gt.dim();
99 for (
int i = 0; i < d; ++i) r *= k - 1;
104 if (k - 1 < d)
return 0;
106 for (
int i = 0; i < d; ++i) r = r * (k - 1 - i) / (i + 1);
109 DUNE_THROW(Dune::NotImplemented,
"Lagrange layout for geometry type " << gt);
128template<
class GV,
int k>
129class CVFELagrangeGrid
131 static_assert(k >= 2,
"CVFELagrangeGrid requires k >= 2");
133 using Element =
typename GV::template Codim<0>::Entity;
134 using ElementGeometry =
typename Element::Geometry;
135 using GlobalCoordinate =
typename ElementGeometry::GlobalCoordinate;
136 using Scalar =
typename GV::ctype;
137 static constexpr int dim = GV::dimension;
139 using DofMapper = Dune::MultipleCodimMultipleGeomTypeMapper<GV>;
140 using FECache = Dune::LagrangeLocalFiniteElementCache<Scalar, Scalar, dim, k>;
141 using GeomHelper = CVFELagrangeDetail::PQkDofHelpers<k, GV>;
145 std::size_t dofIndex;
146 GlobalCoordinate coordinates;
151 using Cell = Element;
152 using Point = PointData;
153 using Position = GlobalCoordinate;
155 explicit CVFELagrangeGrid(
const GV& gv)
157 , dofMapper_{gv, CVFELagrangeDetail::lagrangeLayout<k>}
160 void update(
const GV& gv)
163 dofMapper_.update(gv);
167 const GV& gridView()
const {
return gridView_; }
169 std::size_t numberOfPoints()
const {
return usedDofs_.size(); }
170 std::size_t numberOfCells()
const {
return numCells_; }
172 std::size_t numberOfCellPoints(
const Element& e)
const
173 {
return feCache_.get(e.type()).localCoefficients().size(); }
177 return std::views::iota(std::size_t{0}, usedDofs_.size())
178 | std::views::transform([
this](std::size_t vtkIdx) {
179 const auto dofIdx = usedDofs_[vtkIdx];
180 return Point{vtkIdx, dofIdx, positions_[dofIdx]};
185 {
return GridFormat::Traits::Cells<GV>::get(gridView_); }
187 auto points(
const Element& e)
const
189 const auto eIdx = gridView_.indexSet().index(e);
190 const std::size_t n = connectivity_[eIdx].size();
191 return std::views::iota(std::size_t{0}, n)
192 | std::views::transform([
this, eIdx](std::size_t vtk) {
193 const auto vtkIdx = connectivity_[eIdx][vtk];
194 const auto dofIdx = usedDofs_[vtkIdx];
195 return Point{vtkIdx, dofIdx, positions_[dofIdx]};
202 const auto& gv = gridView_;
203 const std::size_t numAllDofs = dofMapper_.size();
205 positions_.assign(numAllDofs, GlobalCoordinate{});
206 connectivity_.assign(gv.size(0), {});
209 std::vector<bool> used(numAllDofs,
false);
210 const auto& idSet = gv.grid().globalIdSet();
212 for (
const auto& element : GridFormat::Traits::Cells<GV>::get(gv))
215 const auto eIdx = gv.indexSet().index(element);
216 const auto geo =
element.geometry();
217 const auto gt =
element.type();
218 const auto& lc = feCache_.get(gt).localCoefficients();
219 const int n =
static_cast<int>(lc.size());
221 std::vector<std::pair<std::tuple<int,int,int>,
int>> sortable(n);
222 for (
int i = 0; i < n; ++i)
223 sortable[i] = {CVFELagrangeDetail::vtkSortKey(gt, lc.localKey(i)), i};
224 std::sort(sortable.begin(), sortable.end());
226 connectivity_[eIdx].resize(n);
227 for (
int vtk = 0; vtk < n; ++vtk)
229 const int i = sortable[vtk].second;
230 const auto& lk = lc.localKey(i);
231 const auto g = GeomHelper::dofIndex(dofMapper_, element, lk, idSet);
232 connectivity_[eIdx][vtk] = g;
233 positions_[g] = GeomHelper::dofPosition(geo, lk);
238 vtk_of_dof_.assign(numAllDofs, std::size_t(-1));
240 usedDofs_.reserve(numAllDofs);
241 for (std::size_t g = 0; g < numAllDofs; ++g)
242 if (used[g]) { vtk_of_dof_[g] = usedDofs_.size(); usedDofs_.push_back(g); }
244 for (
auto& conn : connectivity_)
245 for (
auto& idx : conn)
246 idx = vtk_of_dof_[idx];
250 DofMapper dofMapper_;
252 std::size_t numCells_{0};
253 std::vector<GlobalCoordinate> positions_;
254 std::vector<std::vector<std::size_t>> connectivity_;
255 std::vector<std::size_t> usedDofs_;
256 std::vector<std::size_t> vtk_of_dof_;
263namespace GridFormat::Traits {
266template<
class GV,
int k>
267struct Points<Dumux::IO::CVFELagrangeGrid<GV, k>> {
268 static auto get(
const Dumux::IO::CVFELagrangeGrid<GV, k>& grid)
269 {
return grid.points(); }
272template<
class GV,
int k>
273struct Cells<Dumux::IO::CVFELagrangeGrid<GV, k>> {
274 static auto get(
const Dumux::IO::CVFELagrangeGrid<GV, k>& grid)
275 {
return grid.cells(); }
278template<
class GV,
int k>
279struct NumberOfPoints<Dumux::IO::CVFELagrangeGrid<GV, k>> {
280 static auto get(
const Dumux::IO::CVFELagrangeGrid<GV, k>& grid)
281 {
return grid.numberOfPoints(); }
284template<
class GV,
int k>
285struct NumberOfCells<Dumux::IO::CVFELagrangeGrid<GV, k>> {
286 static auto get(
const Dumux::IO::CVFELagrangeGrid<GV, k>& grid)
287 {
return grid.numberOfCells(); }
290template<
class GV,
int k>
291struct NumberOfCellPoints<Dumux::IO::CVFELagrangeGrid<GV, k>,
292 typename Dumux::IO::CVFELagrangeGrid<GV, k>::Cell> {
293 static auto get(
const Dumux::IO::CVFELagrangeGrid<GV, k>& grid,
294 const typename Dumux::IO::CVFELagrangeGrid<GV, k>::Cell& cell)
295 {
return grid.numberOfCellPoints(cell); }
298template<
class GV,
int k>
299struct CellPoints<Dumux::IO::CVFELagrangeGrid<GV, k>,
300 typename Dumux::IO::CVFELagrangeGrid<GV, k>::Cell> {
301 static auto get(
const Dumux::IO::CVFELagrangeGrid<GV, k>& grid,
302 const typename Dumux::IO::CVFELagrangeGrid<GV, k>::Cell& cell)
303 {
return grid.points(cell); }
306template<
class GV,
int k>
307struct CellType<Dumux::IO::CVFELagrangeGrid<GV, k>,
308 typename Dumux::IO::CVFELagrangeGrid<GV, k>::Cell> {
309 static auto get(
const Dumux::IO::CVFELagrangeGrid<GV, k>&,
310 const typename Dumux::IO::CVFELagrangeGrid<GV, k>::Cell& cell)
311 {
return GridFormat::Dune::LagrangeDetail::cell_type(cell.type()); }
314template<
class GV,
int k>
315struct PointCoordinates<Dumux::IO::CVFELagrangeGrid<GV, k>,
316 typename Dumux::IO::CVFELagrangeGrid<GV, k>::Point> {
317 static const auto& get(
const Dumux::IO::CVFELagrangeGrid<GV, k>&,
318 const typename Dumux::IO::CVFELagrangeGrid<GV, k>::Point& point)
319 {
return point.coordinates; }
322template<
class GV,
int k>
323struct PointId<Dumux::IO::CVFELagrangeGrid<GV, k>,
324 typename Dumux::IO::CVFELagrangeGrid<GV, k>::Point> {
325 static auto get(
const Dumux::IO::CVFELagrangeGrid<GV, k>&,
326 const typename Dumux::IO::CVFELagrangeGrid<GV, k>::Point& point)
327 {
return point.index; }
333namespace GridFormat::Dune::Traits {
337template<
class GV,
int k>
338struct GridView<Dumux::IO::CVFELagrangeGrid<GV, k>> {
340 static const auto& get(
const Dumux::IO::CVFELagrangeGrid<GV, k>& grid)
341 {
return grid.gridView(); }
Definition cvfegridfunction.hh:31
Lightweight DOF helper for order-2 Lagrange elements.
Lightweight DOF helper for order-3 Lagrange elements.