24#ifndef DUMUX_PORE_NETWORK_GRID_MANAGER_HH
25#define DUMUX_PORE_NETWORK_GRID_MANAGER_HH
32#include <dune/common/classname.hh>
33#include <dune/common/exceptions.hh>
34#include <dune/common/timer.hh>
37#include <dune/foamgrid/foamgrid.hh>
38#include <dune/foamgrid/dgffoam.hh>
51template<
int dimWorld,
class GData = Dumux::PoreNetwork::Gr
idData<Dune::FoamGr
id<1, dimWorld>>>
54 using GridType = Dune::FoamGrid<1, dimWorld>;
55 using Element =
typename GridType::template Codim<0>::Entity;
56 using GlobalPosition =
typename Element::Geometry::GlobalCoordinate;
59 using Grid = GridType;
60 using GridData = GData;
62 void init(
const std::string& paramGroup =
"")
65 paramGroup_ = paramGroup;
70 makeGridFromDgfFile(getParamFromGroup<std::string>(paramGroup,
"Grid.File"));
79 catch(Dune::RangeError& e)
81 makeGridFromStructuredLattice();
88 const auto gridType = enableDgfGridPointer_ ?
"grid from dgf file" :
"generic grid from structured lattice";
89 std::cout <<
"Creating " << gridType <<
" with " << grid().leafGridView().size(0) <<
" elements and "
90 << grid().leafGridView().size(1) <<
" vertices took " << timer.elapsed() <<
" seconds." << std::endl;
96 void makeGridFromDgfFile(
const std::string& fileName)
99 const std::string extension = getFileExtension(fileName);
100 if (extension !=
"dgf")
101 DUNE_THROW(Dune::IOError,
"Grid type " << Dune::className<Grid>() <<
" only supports DGF (*.dgf) but the specified filename has extension: *."<< extension);
103 enableDgfGridPointer_ =
true;
104 dgfGridPtr() = Dune::GridPtr<Grid>(fileName.c_str(), Dune::MPIHelper::getCommunicator());
105 gridData_ = std::make_shared<GridData>(dgfGridPtr_, paramGroup_);
107 if (getParamFromGroup<bool>(paramGroup_,
"Grid.Sanitize",
false))
114 void makeGridFromStructuredLattice()
116 StructuredLatticeGridCreator<dimWorld> creator;
117 creator.init(paramGroup_);
118 gridPtr() = creator.gridPtr();
120 gridData_ = std::make_shared<GridData>(gridPtr_, paramGroup_);
122 if (getParamFromGroup<bool>(paramGroup_,
"Grid.Sanitize",
true))
125 std::cout <<
"\nWARNING: Set Grid.Sanitize = true in order to remove insular patches of elements not connected to the boundary." << std::endl;
127 gridData_->assignParameters();
133 std::string getFileExtension(
const std::string& fileName)
const
135 std::size_t i = fileName.rfind(
'.', fileName.length());
136 if (i != std::string::npos)
137 return(fileName.substr(i+1, fileName.length() - i));
139 DUNE_THROW(Dune::IOError,
"Please provide and extension for your grid file ('"<< fileName <<
"')!");
147 {
return enableDgfGridPointer_ ? *dgfGridPtr() : *gridPtr(); }
152 std::shared_ptr<GridData> getGridData()
const
155 DUNE_THROW(Dune::IOError,
"No grid data available");
165 if (Dune::MPIHelper::getCollectiveCommunication().size() > 1)
168 if (enableDgfGridPointer_)
170 dgfGridPtr().loadBalance();
172 gridData_ = std::make_shared<GridData>(dgfGridPtr(), paramGroup_);
175 gridPtr()->loadBalance();
185 gridData_->getCoordinationNumbers();
188 if (enableDgfGridPointer_)
189 gridData_->copyDgfData();
191 const auto gridView = grid().leafGridView();
192 static const std::string sanitationMode = getParamFromGroup<std::string>(paramGroup_,
"Grid.SanitationMode",
"KeepLargestCluster");
195 const auto keepElement = [&]
197 if (sanitationMode ==
"UsePoreLabels")
198 return findElementsConnectedToPoreLabel(gridView);
199 else if (sanitationMode ==
"KeepLargestCluster")
200 return findElementsInLargestCluster(gridView);
202 DUNE_THROW(Dune::IOError, sanitationMode <<
"is not a valid sanitation mode. Use KeepLargestCluster or UsePoreLabels.");
207 if (std::none_of(keepElement.begin(), keepElement.end(), [](
const bool i){return i;}))
208 DUNE_THROW(Dune::InvalidStateException,
"sanitize() deleted all elements! Check your boundary face indices. "
209 <<
"If the problem persisits, add at least one of your boundary face indices to PruningSeedIndices");
212 std::size_t numDeletedElements = 0;
214 for (
const auto& element : elements(gridView))
216 const auto eIdx = gridView.indexSet().index(element);
217 if (!keepElement[eIdx])
219 grid().removeElement(element);
220 ++numDeletedElements;
228 if (enableDgfGridPointer_)
229 gridData_->resizeParameterContainers();
231 if (numDeletedElements > 0)
232 std::cout <<
"\nDeleted " << numDeletedElements <<
" isolated elements.\n" << std::endl;
239 std::vector<bool> findElementsConnectedToPoreLabel(
const typename Grid::LeafGridView& gridView)
const
242 const auto pruningSeedIndices = getParamFromGroup<std::vector<int>>(paramGroup_,
"Grid.PruningSeedIndices", std::vector<int>{1});
243 std::vector<bool> elementIsConnected(gridView.size(0),
false);
245 auto boundaryIdx = [&](
const auto&
vertex)
247 if (enableDgfGridPointer_)
248 return static_cast<int>(dgfGridPtr_.parameters(vertex)[gridData_->parameterIndex(
"PoreLabel")]);
250 return static_cast<int>(gridData_->poreLabelAtPosForGenericGrid(
vertex.geometry().center()));
253 for (
const auto& element : elements(gridView))
255 const auto eIdx = gridView.indexSet().index(element);
256 if (elementIsConnected[eIdx])
261 bool hasNeighbor =
false;
262 for (
const auto& intersection : intersections(gridView, element))
264 auto vertex =
element.template subEntity<1>(intersection.indexInInside());
266 if (std::any_of(pruningSeedIndices.begin(), pruningSeedIndices.end(),
267 [&](
const int i ){ return i == boundaryIdx(vertex); }))
273 if (intersection.neighbor())
282 elementIsConnected[eIdx] =
true;
285 recursivelyFindConnectedElements_(gridView, element, elementIsConnected);
289 return elementIsConnected;
296 std::vector<bool> findElementsInLargestCluster(
const typename Grid::LeafGridView& gridView)
const
298 const auto clusteredElements = clusterElements(gridView);
300 const auto numClusters = *std::max_element(clusteredElements.begin(), clusteredElements.end()) + 1;
301 std::cout <<
"\nFound " << numClusters <<
" unconnected clusters." << std::endl;
304 std::vector<std::size_t> clusterFrequency(numClusters);
305 for (
const auto clusterIdx : clusteredElements)
306 clusterFrequency[clusterIdx] += 1;
308 const auto largestCluster = std::max_element(clusterFrequency.begin(), clusterFrequency.end());
309 const auto largestClusterIdx =
std::distance(clusterFrequency.begin(), largestCluster);
311 std::vector<bool> elementsInLargestCluster(gridView.size(0));
313 for (
int eIdx = 0; eIdx < clusteredElements.size(); ++eIdx)
314 if (clusteredElements[eIdx] == largestClusterIdx)
315 elementsInLargestCluster[eIdx] =
true;
317 return elementsInLargestCluster;
323 std::vector<std::size_t> clusterElements(
const typename Grid::LeafGridView& gridView)
const
325 std::vector<std::size_t> elementInCluster(gridView.size(0), 0);
326 std::size_t clusterIdx = 0;
328 for (
const auto& element : elements(gridView))
330 const auto eIdx = gridView.indexSet().index(element);
331 if (elementInCluster[eIdx])
335 elementInCluster[eIdx] = clusterIdx;
337 recursivelyFindConnectedElements_(gridView, element, elementInCluster, clusterIdx);
341 for (
auto& clusterIdx : elementInCluster)
344 return elementInCluster;
352 std::shared_ptr<Grid>& gridPtr()
354 if(!enableDgfGridPointer_)
357 DUNE_THROW(Dune::InvalidStateException,
"You are using DGF. To get the grid pointer use method dgfGridPtr()!");
363 Dune::GridPtr<Grid>& dgfGridPtr()
365 if(enableDgfGridPointer_)
368 DUNE_THROW(Dune::InvalidStateException,
"The DGF grid pointer is only available if the grid was constructed with a DGF file!");
375 bool enableDgfGridPointer_ =
false;
377 std::shared_ptr<Grid> gridPtr_;
378 Dune::GridPtr<Grid> dgfGridPtr_;
380 std::shared_ptr<GridData> gridData_;
382 std::string paramGroup_;
386 void createOneDGrid_()
388 const auto lowerLeft = getParamFromGroup<GlobalPosition>(paramGroup_,
"Grid.LowerLeft", GlobalPosition(0.0));
389 const auto upperRight = getParamFromGroup<GlobalPosition>(paramGroup_,
"Grid.UpperRight");
390 const auto numPores = getParamFromGroup<unsigned int>(paramGroup_,
"Grid.NumPores");
391 const auto cells = numPores - 1;
394 GlobalPosition step = upperRight;
395 step -= lowerLeft, step /= cells;
398 Dune::GridFactory<Grid> factory;
401 GlobalPosition globalPos = lowerLeft;
402 for (
unsigned int vIdx = 0; vIdx <= cells; vIdx++, globalPos += step)
403 factory.insertVertex(globalPos);
406 for(
unsigned int eIdx = 0; eIdx < cells; eIdx++)
409 gridPtr() = std::shared_ptr<Grid>(factory.createGrid());
410 gridData_ = std::make_shared<GridData>(gridPtr_, paramGroup_);
411 gridData_->assignParameters();
415 void recursivelyFindConnectedElements_(
const typename Grid::LeafGridView& gridView,
416 const Element& element,
417 std::vector<T>& elementIsConnected,
421 std::stack<Element> elementStack;
422 elementStack.push(element);
423 while (!elementStack.empty())
425 auto e = elementStack.top();
427 for (
const auto& intersection : intersections(gridView, e))
429 if (!intersection.boundary())
431 auto outside = intersection.outside();
432 auto nIdx = gridView.indexSet().index(outside);
433 if (!elementIsConnected[nIdx])
435 elementIsConnected[nIdx] = marker;
436 elementStack.push(outside);
The infrastructure to retrieve run-time parameters from Dune::ParameterTrees.
Creates a network grid from a structured lattice. Connections can be randomly deleted.
ctype distance(const Dune::FieldVector< ctype, dimWorld > &a, const Dune::FieldVector< ctype, dimWorld > &b)
Compute the shortest distance between two points.
Definition: distance.hh:138
bool hasParamInGroup(const std::string ¶mGroup, const std::string ¶m)
Check whether a key exists in the parameter tree with a model group prefix.
Definition: parameters.hh:374
Definition: discretization/porenetwork/fvelementgeometry.hh:33
constexpr Line line
Definition: couplingmanager1d3d_line.hh:43