version 3.7
gridmanager_sub.hh
Go to the documentation of this file.
1// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2// vi: set et ts=4 sw=4 sts=4:
3//
4// SPDX-FileCopyrightInfo: Copyright © DuMux Project contributors, see AUTHORS.md in root folder
5// SPDX-License-Identifier: GPL-3.0-or-later
6//
12#ifndef DUMUX_IO_GRID_MANAGER_SUB_HH
13#define DUMUX_IO_GRID_MANAGER_SUB_HH
14
15#include <memory>
16#include <utility>
17
18#include <dune/common/shared_ptr.hh>
19#include <dune/common/concept.hh>
20#include <dune/grid/yaspgrid.hh>
21
22// SubGrid specific includes
23#if HAVE_DUNE_SUBGRID
24#include <dune/subgrid/subgrid.hh>
27#endif
28
30
33
34#if HAVE_DUNE_SUBGRID
35namespace Dumux {
36namespace Concept {
37
42template<class Element>
43struct ElementSelector
44{
45 template<class F>
46 auto require(F&& f) -> decltype(
47 bool(f(std::declval<const Element&>()))
48 );
49};
50} // end namespace Concept
51
56template <class HostGrid, class HostGridManager = GridManager<HostGrid>>
57class SubGridManagerBase
58: public GridManagerBase<Dune::SubGrid<HostGrid::dimension, HostGrid>>
59{
60 static constexpr int dim = HostGrid::dimension;
61 using HostElement = typename HostGrid::template Codim<0>::Entity;
62 using GlobalPosition = typename HostElement::Geometry::GlobalCoordinate;
63
64public:
66
70 template<class ES,
71 typename std::enable_if_t<Dune::models<Concept::ElementSelector<HostElement>, ES>(), int> = 0>
72 void init(HostGrid& hostGrid,
73 const ES& selector,
74 const std::string& paramGroup = "")
75 {
76 this->gridPtr() = createGrid_(hostGrid, selector, paramGroup);
77 loadBalance();
78 }
79
83 template<class ES,
84 typename std::enable_if_t<Dune::models<Concept::ElementSelector<HostElement>, ES>(), int> = 0>
85 void init(const ES& selector,
86 const std::string& paramGroup = "")
87 {
88 initHostGrid_(paramGroup);
89 this->gridPtr() = createGrid_(hostGridManager_->grid(), selector, paramGroup);
90 loadBalance();
91 }
92
96 void loadBalance()
97 {
98 if (Dune::MPIHelper::getCommunication().size() > 1)
99 this->grid().loadBalance();
100 }
101
102protected:
103
107 template<class ES,
108 typename std::enable_if_t<Dune::models<Concept::ElementSelector<HostElement>, ES>(), int> = 0>
109 static std::unique_ptr<Grid> createGrid_(HostGrid& hostGrid,
110 const ES& selector,
111 const std::string& paramGroup = "")
112 {
113 // A unique pointer to the subgrid.
114 auto subgridPtr = std::make_unique<Grid>(hostGrid);
115
116 // A container to store the host grid elements' ids.
117 std::set<typename HostGrid::Traits::GlobalIdSet::IdType> elementsForSubgrid;
118 const auto& globalIDset = subgridPtr->getHostGrid().globalIdSet();
119
120 // Construct the subgrid.
121 subgridPtr->createBegin();
122
123 // Loop over all elements of the host grid and use the selector to
124 // choose which elements to add to the subgrid.
125 auto hostGridView = subgridPtr->getHostGrid().leafGridView();
126 for (const auto& e : elements(hostGridView))
127 if (selector(e))
128 elementsForSubgrid.insert(globalIDset.template id<0>(e));
129
130 if (elementsForSubgrid.empty())
131 DUNE_THROW(Dune::GridError, "No elements in subgrid");
132
133 subgridPtr->insertSetPartial(elementsForSubgrid);
134 subgridPtr->createEnd();
135
136 // Return a unique pointer to the subgrid.
137 return subgridPtr;
138 }
139
140 void initHostGrid_(const std::string& paramGroup)
141 {
142 hostGridManager_ = std::make_unique<HostGridManager>();
143 hostGridManager_->init(paramGroup);
144 }
145
146 void initHostGrid_(const GlobalPosition& lowerLeft,
147 const GlobalPosition& upperRight,
148 const std::array<int, dim>& cells,
149 const std::string& paramGroup,
150 const int overlap = 1)
151 {
152 hostGridManager_ = std::make_unique<HostGridManager>();
153 hostGridManager_->init(lowerLeft, upperRight, cells, paramGroup, overlap);
154 }
155
159 HostGrid& hostGrid_()
160 {
161 return hostGridManager_->grid();
162 }
163
164 std::unique_ptr<HostGridManager> hostGridManager_;
165};
166
175template<int dim, class HostGrid>
176class GridManager<Dune::SubGrid<dim, HostGrid>>
177: public SubGridManagerBase<HostGrid, GridManager<HostGrid>>
178{};
179
190template<int dim, class Coordinates>
191class GridManager<Dune::SubGrid<dim, Dune::YaspGrid<dim, Coordinates>>>
192: public SubGridManagerBase<Dune::YaspGrid<dim, Coordinates>, GridManager<Dune::YaspGrid<dim, Coordinates>>>
193{
194 using ParentType = SubGridManagerBase<Dune::YaspGrid<dim, Coordinates>,
195 GridManager<Dune::YaspGrid<dim, Coordinates>>>;
196public:
197 using typename ParentType::Grid;
198 using ParentType::init;
199
205 void init(const std::string& paramGroup = "")
206 {
207 // check if there is an image file we can construct the element selector from
208 if (hasParamInGroup(paramGroup, "Grid.Image"))
209 {
210 const auto imgFileName = getParamFromGroup<std::string>(paramGroup, "Grid.Image");
211 const auto ext = this->getFileExtension(imgFileName);
212 if (ext == "pbm")
213 {
214 if (dim != 2)
215 DUNE_THROW(Dune::GridError, "Portable Bitmap Format only supports dim == 2");
216
217 // read image
218 const auto img = NetPBMReader::readPBM(imgFileName);
219 createGridFromImage_(img, paramGroup);
220 }
221 else
222 DUNE_THROW(Dune::IOError, "The SubGridManager doesn't support image files with extension: *." << ext);
223
224 }
225 else
226 DUNE_THROW(Dune::IOError, "SubGridManager couldn't construct element selector. Specify Grid.Image in the input file!");
227 }
228
229private:
230 template<class Img>
231 void createGridFromImage_(const Img& img, const std::string& paramGroup)
232 {
233 using GlobalPosition = typename ParentType::Grid::template Codim<0>::Geometry::GlobalCoordinate;
234 const bool repeated = hasParamInGroup(paramGroup,"Grid.Repeat");
235
236 // get the number of cells
237 const std::array<int, dim> imageDimensions{static_cast<int>(img.header().nCols), static_cast<int>(img.header().nRows)};
238 std::array<int, dim> cells{imageDimensions[0], imageDimensions[1]};
239
240 std::array<int, dim> repeatsDefault; repeatsDefault.fill(1);
241 const auto numRepeats = getParamFromGroup<std::array<int, dim>>(paramGroup, "Grid.Repeat", repeatsDefault);
242 for (int i = 0; i < dim; i++)
243 cells[i] = cells[i] * numRepeats[i];
244
245 // get the corner coordinates
246 const auto [lowerLeft, upperRight] = [&]()
247 {
248 const auto lowerLeft = getParamFromGroup<GlobalPosition>(paramGroup, "Grid.LowerLeft", GlobalPosition(0.0));
249 if (hasParamInGroup(paramGroup, "Grid.PixelDimensions"))
250 {
251 auto upperRight = getParamFromGroup<GlobalPosition>(paramGroup, "Grid.PixelDimensions");
252 for (int i = 0; i < upperRight.size(); ++i)
253 upperRight[i] *= cells[i];
254 upperRight += lowerLeft;
255 return std::make_pair(lowerLeft, upperRight);
256 }
257 else
258 return std::make_pair(lowerLeft, getParamFromGroup<GlobalPosition>(paramGroup, "Grid.UpperRight"));
259 }();
260
261 // construct the host grid
262 this->initHostGrid_(lowerLeft, upperRight, cells, paramGroup);
263
264 // check if the marker is customized, per default
265 // we mark all cells that are encoded as 0
266 const bool marked = getParamFromGroup<bool>(paramGroup, "Grid.Marker", false);
267
268 // Create the element selector for a single image
269 const auto elementSelector = [&](const auto& element)
270 {
271 auto eIdx = this->hostGrid_().leafGridView().indexSet().index(element);
272
273 // if the hostgrid was refined, get the index of the original, un-refined
274 // host grid element which fits with the image's indices
275 if (element.hasFather())
276 {
277 auto level0Element = element.father();
278 while (level0Element.hasFather())
279 level0Element = level0Element.father();
280
281 assert(level0Element.level() == 0);
282 eIdx = this->hostGrid_().levelGridView(0).indexSet().index(level0Element);
283 }
284 return img[eIdx] == marked;
285 };
286
287 // Create the element selector for a repeated image
288 const auto repeatedElementSelector = [&](const auto& element)
289 {
290 auto eIdx = this->hostGrid_().leafGridView().indexSet().index(element);
291
292 // if the hostgrid was refined, get the index of the original, un-refined
293 // host grid element which fits with the image's indices
294 if (element.hasFather())
295 {
296 auto level0Element = element.father();
297 while (level0Element.hasFather())
298 level0Element = level0Element.father();
299
300 assert(level0Element.level() == 0);
301 eIdx = this->hostGrid_().levelGridView(0).indexSet().index(level0Element);
302 }
303
304 // figure out the size of the repeat, and the size of the target repeated grid
305 const int numCols = imageDimensions[0];
306 const int numRows = imageDimensions[1];
307
308 // map the eIdx to the original img index
309 const int repeatUnitIndex = eIdx % (numCols * numRepeats[0] * numRows);
310 const int imgI = repeatUnitIndex % numCols;
311 const int imgJ = repeatUnitIndex / (numCols * numRepeats[0]);
312 return img[ (imgJ * numCols + imgI) ] == marked;
313 };
314
315 // create the grid
316 if (repeated)
317 this->gridPtr() = this->createGrid_(this->hostGrid_(), repeatedElementSelector, paramGroup);
318 else
319 this->gridPtr() = this->createGrid_(this->hostGrid_(), elementSelector, paramGroup);
320
321 this->loadBalance();
322 }
323};
324
326template<int dim, class HostGrid>
327class BoundaryFlag<Dune::SubGrid<dim, HostGrid>>
328{
329public:
330 BoundaryFlag() : flag_(-1) {}
331
332 template<class Intersection>
333 BoundaryFlag(const Intersection& i) : flag_(-1) {}
334
335 using value_type = int;
336
337 value_type get() const
338 { DUNE_THROW(Dune::NotImplemented, "Sub-grid doesn't implement boundary segment indices!"); }
339
340private:
341 int flag_;
342};
343
344} // end namespace Dumux
345#endif // HAVE_DUNE_SUBGRID
346#endif
Boundary flag to store e.g. in sub control volume faces.
std::size_t value_type
Definition: boundaryflag.hh:39
value_type get() const
Definition: boundaryflag.hh:41
void loadBalance()
Call loadBalance() function of the grid.
Definition: gridmanager_base.hh:86
std::shared_ptr< Grid > & gridPtr()
Returns a reference to the grid pointer (std::shared_ptr<Grid>)
Definition: gridmanager_base.hh:134
void init(const std::string &modelParamGroup="")
Make the grid. Implement this method in the specialization of this class for a grid type.
Definition: gridmanager_base.hh:63
std::string getFileExtension(const std::string &fileName) const
Returns the filename extension of a given filename.
Definition: gridmanager_base.hh:156
static Result< bool > readPBM(const std::string &fileName, const bool useDuneGridOrdering=true)
Reads a *pbm (black and white) in ASCII or binary encoding. Returns a struct that contains both the p...
Definition: rasterimagereader.hh:81
Definition: consistentlyorientedgrid.hh:23
Provides a grid manager for all supported grid managers with input file interfaces....
Definition: adapt.hh:17
bool hasParamInGroup(const std::string &paramGroup, const std::string &param)
Check whether a key exists in the parameter tree with a model group prefix.
Definition: parameters.hh:165
Definition: common/pdesolver.hh:24
The infrastructure to retrieve run-time parameters from Dune::ParameterTrees.
A simple reader class for raster images.
A simple writer class for raster images.