Line | Branch | Exec | Source |
---|---|---|---|
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 | // | ||
7 | /*! | ||
8 | * \file | ||
9 | * \ingroup PoreNetworkModels | ||
10 | * \brief Provides a grid manager for pore-network models | ||
11 | */ | ||
12 | #ifndef DUMUX_PORE_NETWORK_GRID_MANAGER_HH | ||
13 | #define DUMUX_PORE_NETWORK_GRID_MANAGER_HH | ||
14 | |||
15 | #if HAVE_DUNE_FOAMGRID | ||
16 | |||
17 | #include <iostream> | ||
18 | #include <algorithm> | ||
19 | #include <vector> | ||
20 | |||
21 | #include <dune/common/classname.hh> | ||
22 | #include <dune/common/exceptions.hh> | ||
23 | #include <dune/common/timer.hh> | ||
24 | |||
25 | // FoamGrid specific includes | ||
26 | #include <dune/foamgrid/foamgrid.hh> | ||
27 | #include <dune/foamgrid/dgffoam.hh> | ||
28 | |||
29 | #include <dumux/common/parameters.hh> | ||
30 | #include <dumux/common/exceptions.hh> | ||
31 | |||
32 | #include "griddata.hh" | ||
33 | #include "structuredlatticegridcreator.hh" | ||
34 | |||
35 | namespace Dumux::PoreNetwork { | ||
36 | |||
37 | /*! | ||
38 | * \ingroup PoreNetworkModels | ||
39 | * \brief A grid manager for pore-network models | ||
40 | */ | ||
41 | template<int dimWorld, class GData = Dumux::PoreNetwork::GridData<Dune::FoamGrid<1, dimWorld>>> | ||
42 | class GridManager | ||
43 | { | ||
44 | using GridType = Dune::FoamGrid<1, dimWorld>; | ||
45 | using Element = typename GridType::template Codim<0>::Entity; | ||
46 | using GlobalPosition = typename Element::Geometry::GlobalCoordinate; | ||
47 | |||
48 | public: | ||
49 | using Grid = GridType; | ||
50 | using GridData = GData; | ||
51 | |||
52 | 57 | void init(const std::string& paramGroup = "") | |
53 | { | ||
54 | 57 | Dune::Timer timer; | |
55 | 57 | paramGroup_ = paramGroup; | |
56 | |||
57 | // First try to create it from a DGF file in GridParameterGroup.File | ||
58 |
8/14✓ Branch 1 taken 39 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 39 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 39 times.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✓ Branch 10 taken 39 times.
✓ Branch 11 taken 18 times.
✓ Branch 12 taken 21 times.
✓ Branch 13 taken 18 times.
✓ Branch 14 taken 21 times.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
|
171 | if (hasParamInGroup(paramGroup, "Grid.File")) |
59 | { | ||
60 |
2/6✓ Branch 2 taken 18 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 18 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
|
24 | makeGridFromDgfFile(getParamFromGroup<std::string>(paramGroup, "Grid.File")); |
61 | 24 | loadBalance(); | |
62 | } | ||
63 | else // no grid file found | ||
64 | { | ||
65 | // create a structured grid (1D grid or lattice grid) | ||
66 |
1/4✓ Branch 1 taken 21 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
|
99 | const auto numPores = getParamFromGroup<std::vector<unsigned int>>(paramGroup_, "Grid.NumPores"); |
67 |
4/4✓ Branch 0 taken 3 times.
✓ Branch 1 taken 18 times.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 18 times.
|
66 | if (numPores.size() == 1) |
68 |
1/2✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
|
5 | createOneDGrid_(numPores[0]); |
69 |
1/2✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
|
28 | else if (numPores.size() == dimWorld) |
70 |
1/2✓ Branch 1 taken 18 times.
✗ Branch 2 not taken.
|
28 | makeGridFromStructuredLattice(); |
71 | else | ||
72 | ✗ | DUNE_THROW(ParameterException, | |
73 | "Grid.NumPores parameter has wrong size " << numPores.size() | ||
74 | << ". Should be 1 (for 1D grid) or " | ||
75 | << dimWorld << " (for structured lattice grid)." | ||
76 | ); | ||
77 | |||
78 |
1/2✓ Branch 1 taken 21 times.
✗ Branch 2 not taken.
|
33 | loadBalance(); |
79 | } | ||
80 | |||
81 | 57 | timer.stop(); | |
82 |
2/2✓ Branch 0 taken 21 times.
✓ Branch 1 taken 18 times.
|
57 | const auto gridType = enableDgfGridPointer_ ? "grid from dgf file" : "generic grid from structured lattice"; |
83 | 171 | std::cout << "Creating " << gridType << " with " << grid().leafGridView().size(0) << " elements and " | |
84 | 171 | << grid().leafGridView().size(1) << " vertices took " << timer.elapsed() << " seconds." << std::endl; | |
85 | 57 | } | |
86 | |||
87 | /*! | ||
88 | * \brief Make a grid from a DGF file. | ||
89 | */ | ||
90 | 24 | void makeGridFromDgfFile(const std::string& fileName) | |
91 | { | ||
92 | // We found a file in the input file...does it have a supported extension? | ||
93 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 18 times.
|
48 | const std::string extension = getFileExtension(fileName); |
94 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 18 times.
|
24 | if (extension != "dgf") |
95 | ✗ | DUNE_THROW(Dune::IOError, "Grid type " << Dune::className<Grid>() << " only supports DGF (*.dgf) but the specified filename has extension: *."<< extension); | |
96 | |||
97 | 24 | enableDgfGridPointer_ = true; | |
98 |
9/20✓ Branch 1 taken 18 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 18 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 18 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 18 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 18 times.
✗ Branch 14 not taken.
✓ Branch 16 taken 18 times.
✗ Branch 17 not taken.
✓ Branch 19 taken 18 times.
✗ Branch 20 not taken.
✓ Branch 22 taken 18 times.
✗ Branch 23 not taken.
✓ Branch 25 taken 18 times.
✗ Branch 26 not taken.
✗ Branch 28 not taken.
✗ Branch 29 not taken.
|
120 | dgfGridPtr() = Dune::GridPtr<Grid>(fileName.c_str(), Dune::MPIHelper::getCommunicator()); |
99 |
3/6✓ Branch 1 taken 18 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 18 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 18 times.
|
24 | gridData_ = std::make_shared<GridData>(dgfGridPtr_, paramGroup_); |
100 | |||
101 |
3/6✓ Branch 1 taken 18 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 4 times.
✓ Branch 4 taken 14 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
|
24 | if (getParamFromGroup<bool>(paramGroup_, "Grid.Sanitize", false)) |
102 |
1/2✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
|
8 | sanitizeGrid(); |
103 | 24 | } | |
104 | |||
105 | /*! | ||
106 | * \brief Make a grid based on a structured lattice which allows to randomly delete elements based on Raoof et al. 2009 | ||
107 | */ | ||
108 | 28 | void makeGridFromStructuredLattice() | |
109 | { | ||
110 | 56 | StructuredLatticeGridCreator<dimWorld> creator; | |
111 |
1/2✓ Branch 1 taken 18 times.
✗ Branch 2 not taken.
|
28 | creator.init(paramGroup_); |
112 |
1/2✓ Branch 1 taken 18 times.
✗ Branch 2 not taken.
|
28 | gridPtr() = creator.gridPtr(); |
113 | |||
114 |
3/6✓ Branch 1 taken 18 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 18 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 18 times.
|
28 | gridData_ = std::make_shared<GridData>(gridPtr_, paramGroup_); |
115 | |||
116 |
3/4✓ Branch 1 taken 18 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 14 times.
✓ Branch 4 taken 4 times.
|
28 | if (getParamFromGroup<bool>(paramGroup_, "Grid.Sanitize", true)) |
117 |
1/2✓ Branch 1 taken 14 times.
✗ Branch 2 not taken.
|
20 | sanitizeGrid(); |
118 | else | ||
119 |
1/2✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
|
16 | std::cout << "\nWARNING: Set Grid.Sanitize = true in order to remove insular patches of elements not connected to the boundary." << std::endl; |
120 | |||
121 |
2/4✓ Branch 1 taken 18 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 18 times.
✗ Branch 5 not taken.
|
56 | gridData_->assignParameters(); |
122 | 28 | } | |
123 | |||
124 | /*! | ||
125 | * \brief Returns the filename extension of a given filename | ||
126 | */ | ||
127 | 24 | std::string getFileExtension(const std::string& fileName) const | |
128 | { | ||
129 |
1/2✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
|
24 | std::size_t i = fileName.rfind('.', fileName.length()); |
130 |
1/2✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
|
24 | if (i != std::string::npos) |
131 | 24 | return(fileName.substr(i+1, fileName.length() - i)); | |
132 | else | ||
133 | ✗ | DUNE_THROW(Dune::IOError, "Please provide and extension for your grid file ('"<< fileName << "')!"); | |
134 | return ""; | ||
135 | } | ||
136 | |||
137 | /*! | ||
138 | * \brief Returns a reference to the grid. | ||
139 | */ | ||
140 | 488 | Grid& grid() | |
141 |
2/2✓ Branch 0 taken 83 times.
✓ Branch 1 taken 267 times.
|
488 | { return enableDgfGridPointer_ ? *dgfGridPtr() : *gridPtr(); } |
142 | |||
143 | /*! | ||
144 | * \brief Returns the grid data. | ||
145 | */ | ||
146 | 59 | std::shared_ptr<GridData> getGridData() const | |
147 | { | ||
148 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 41 times.
|
59 | if (!gridData_) |
149 | ✗ | DUNE_THROW(Dune::IOError, "No grid data available"); | |
150 | |||
151 | 59 | return gridData_; | |
152 | } | ||
153 | |||
154 | /*! | ||
155 | * \brief Call loadBalance() function of the grid. | ||
156 | */ | ||
157 | 57 | void loadBalance() | |
158 | { | ||
159 |
2/4✗ Branch 1 not taken.
✓ Branch 2 taken 39 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 39 times.
|
57 | if (Dune::MPIHelper::getCommunication().size() > 1) |
160 | { | ||
161 | // if we may have dgf parameters use load balancing of the dgf pointer | ||
162 | ✗ | if (enableDgfGridPointer_) | |
163 | { | ||
164 | ✗ | dgfGridPtr().loadBalance(); | |
165 | // update the grid data | ||
166 | ✗ | gridData_ = std::make_shared<GridData>(dgfGridPtr(), paramGroup_); | |
167 | } | ||
168 | else | ||
169 | ✗ | gridPtr()->loadBalance(); | |
170 | } | ||
171 | 57 | } | |
172 | |||
173 | /*! | ||
174 | * \brief post-processing to remove insular groups of elements that are not connected to a Dirichlet boundary | ||
175 | */ | ||
176 | 40 | void sanitizeGrid() | |
177 | { | ||
178 | // evaluate the coordination numbers to check if all pores are connected to at least one throat | ||
179 |
1/2✓ Branch 2 taken 24 times.
✗ Branch 3 not taken.
|
80 | gridData_->getCoordinationNumbers(); |
180 | |||
181 | // for dgf grid, copy the data to persistent containers | ||
182 |
2/2✓ Branch 0 taken 4 times.
✓ Branch 1 taken 20 times.
|
40 | if (enableDgfGridPointer_) |
183 | 16 | gridData_->copyDgfData(); | |
184 | |||
185 |
2/2✓ Branch 1 taken 20 times.
✓ Branch 2 taken 4 times.
|
40 | const auto gridView = grid().leafGridView(); |
186 |
4/6✓ Branch 0 taken 20 times.
✓ Branch 1 taken 4 times.
✓ Branch 3 taken 20 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 20 times.
✗ Branch 7 not taken.
|
40 | static const std::string sanitationMode = getParamFromGroup<std::string>(paramGroup_, "Grid.SanitationMode", "KeepLargestCluster"); |
187 | |||
188 | // find the elements to keep, all others will be deleted | ||
189 | 96 | const auto keepElement = [&] | |
190 | { | ||
191 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
|
24 | if (sanitationMode == "UsePoreLabels") |
192 | 24 | return findElementsConnectedToPoreLabel(gridView); | |
193 |
1/2✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
|
24 | else if (sanitationMode == "KeepLargestCluster") |
194 | 24 | return findElementsInLargestCluster(gridView); | |
195 | else | ||
196 | ✗ | DUNE_THROW(Dune::IOError, sanitationMode << "is not a valid sanitation mode. Use KeepLargestCluster or UsePoreLabels."); | |
197 | |||
198 | |||
199 | 24 | }(); | |
200 | |||
201 | 120 | if (std::none_of(keepElement.begin(), keepElement.end(), [](const bool i){return i;})) | |
202 | ✗ | DUNE_THROW(Dune::InvalidStateException, "sanitize() deleted all elements! Check your boundary face indices. " | |
203 | << "If the problem persists, add at least one of your boundary face indices to PruningSeedIndices"); | ||
204 | |||
205 | // remove the elements in the grid | ||
206 | 40 | std::size_t numDeletedElements = 0; | |
207 |
1/2✓ Branch 1 taken 24 times.
✗ Branch 2 not taken.
|
40 | grid().preGrow(); |
208 |
5/6✓ Branch 1 taken 44153 times.
✓ Branch 2 taken 24 times.
✓ Branch 3 taken 44153 times.
✓ Branch 4 taken 24 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 44153 times.
|
44855 | for (const auto& element : elements(gridView)) |
209 | { | ||
210 |
3/4✗ Branch 0 not taken.
✓ Branch 1 taken 44153 times.
✓ Branch 2 taken 131 times.
✓ Branch 3 taken 44022 times.
|
44815 | const auto eIdx = gridView.indexSet().index(element); |
211 |
4/4✓ Branch 0 taken 131 times.
✓ Branch 1 taken 44022 times.
✓ Branch 2 taken 131 times.
✓ Branch 3 taken 44022 times.
|
89630 | if (!keepElement[eIdx]) |
212 | { | ||
213 |
2/4✓ Branch 1 taken 131 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 131 times.
✗ Branch 5 not taken.
|
151 | grid().removeElement(element); |
214 | 151 | ++numDeletedElements; | |
215 | } | ||
216 | } | ||
217 | // triggers the grid growth process | ||
218 |
2/4✓ Branch 1 taken 24 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 24 times.
✗ Branch 5 not taken.
|
40 | grid().grow(); |
219 |
1/2✓ Branch 1 taken 24 times.
✗ Branch 2 not taken.
|
40 | grid().postGrow(); |
220 | |||
221 | // resize the parameters for dgf grids | ||
222 |
2/2✓ Branch 0 taken 4 times.
✓ Branch 1 taken 20 times.
|
40 | if (enableDgfGridPointer_) |
223 |
2/4✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 4 times.
✗ Branch 5 not taken.
|
16 | gridData_->resizeParameterContainers(); |
224 | |||
225 |
2/2✓ Branch 0 taken 7 times.
✓ Branch 1 taken 17 times.
|
40 | if (numDeletedElements > 0) |
226 |
2/4✓ Branch 2 taken 7 times.
✗ Branch 3 not taken.
✓ Branch 6 taken 7 times.
✗ Branch 7 not taken.
|
33 | std::cout << "\nDeleted " << numDeletedElements << " isolated elements.\n" << std::endl; |
227 | 40 | } | |
228 | |||
229 | /*! | ||
230 | * \brief Returns a vector of bool which entries are true for elements connected to pores at the boundary | ||
231 | * with a given pore label. | ||
232 | */ | ||
233 | ✗ | std::vector<bool> findElementsConnectedToPoreLabel(const typename Grid::LeafGridView& gridView) const | |
234 | { | ||
235 | // pruning -- remove elements not connected to a Dirichlet boundary (marker == 1) | ||
236 | ✗ | const auto pruningSeedIndices = getParamFromGroup<std::vector<int>>(paramGroup_, "Grid.PruningSeedIndices", std::vector<int>{1}); | |
237 | ✗ | std::vector<bool> elementIsConnected(gridView.size(0), false); | |
238 | |||
239 | ✗ | auto boundaryIdx = [&](const auto& vertex) | |
240 | { | ||
241 | ✗ | if (enableDgfGridPointer_) | |
242 | ✗ | return static_cast<int>(dgfGridPtr_.parameters(vertex)[gridData_->parameterIndex("PoreLabel")]); | |
243 | else | ||
244 | ✗ | return static_cast<int>(gridData_->poreLabelAtPosForGenericGrid(vertex.geometry().center())); | |
245 | }; | ||
246 | |||
247 | ✗ | for (const auto& element : elements(gridView)) | |
248 | { | ||
249 | ✗ | const auto eIdx = gridView.indexSet().index(element); | |
250 | ✗ | if (elementIsConnected[eIdx]) | |
251 | continue; | ||
252 | |||
253 | // try to find a seed from which to start the search process | ||
254 | ✗ | bool isSeed = false; | |
255 | ✗ | bool hasNeighbor = false; | |
256 | ✗ | for (const auto& intersection : intersections(gridView, element)) | |
257 | { | ||
258 | ✗ | auto vertex = element.template subEntity<1>(intersection.indexInInside()); | |
259 | // seed found | ||
260 | ✗ | if (std::any_of(pruningSeedIndices.begin(), pruningSeedIndices.end(), | |
261 | ✗ | [&]( const int i ){ return i == boundaryIdx(vertex); })) | |
262 | { | ||
263 | ✗ | isSeed = true; | |
264 | // break; | ||
265 | } | ||
266 | |||
267 | ✗ | if (intersection.neighbor()) | |
268 | ✗ | hasNeighbor = true; | |
269 | } | ||
270 | |||
271 | ✗ | if (!hasNeighbor) | |
272 | continue; | ||
273 | |||
274 | ✗ | if (isSeed) | |
275 | { | ||
276 | ✗ | elementIsConnected[eIdx] = true; | |
277 | |||
278 | // use iteration instead of recursion here because the recursion can get too deep | ||
279 | ✗ | recursivelyFindConnectedElements_(gridView, element, elementIsConnected); | |
280 | } | ||
281 | } | ||
282 | |||
283 | ✗ | return elementIsConnected; | |
284 | } | ||
285 | |||
286 | /*! | ||
287 | * \brief Returns a vector of bool which entries are true for elements located in the largest | ||
288 | * connected cluster of the network. | ||
289 | */ | ||
290 | 40 | std::vector<bool> findElementsInLargestCluster(const typename Grid::LeafGridView& gridView) const | |
291 | { | ||
292 | 40 | const auto clusteredElements = clusterElements(gridView); | |
293 | |||
294 |
3/6✓ Branch 0 taken 24 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 24 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 24 times.
✗ Branch 5 not taken.
|
120 | const auto numClusters = *std::max_element(clusteredElements.begin(), clusteredElements.end()) + 1; |
295 |
2/4✓ Branch 2 taken 24 times.
✗ Branch 3 not taken.
✓ Branch 6 taken 24 times.
✗ Branch 7 not taken.
|
120 | std::cout << "\nFound " << numClusters << " unconnected clusters." << std::endl; |
296 | |||
297 | // count number of elements in individual clusters | ||
298 |
4/10✓ Branch 1 taken 24 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 24 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 24 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 24 times.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
|
160 | std::vector<std::size_t> clusterFrequency(numClusters); |
299 |
4/4✓ Branch 0 taken 44153 times.
✓ Branch 1 taken 24 times.
✓ Branch 2 taken 44153 times.
✓ Branch 3 taken 24 times.
|
89750 | for (const auto clusterIdx : clusteredElements) |
300 | 89630 | clusterFrequency[clusterIdx] += 1; | |
301 | |||
302 |
3/6✓ Branch 0 taken 24 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 24 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 24 times.
✗ Branch 5 not taken.
|
120 | const auto largestCluster = std::max_element(clusterFrequency.begin(), clusterFrequency.end()); |
303 | 80 | const auto largestClusterIdx = std::distance(clusterFrequency.begin(), largestCluster); | |
304 | |||
305 |
1/4✓ Branch 3 taken 24 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
|
80 | std::vector<bool> elementsInLargestCluster(gridView.size(0)); |
306 | |||
307 |
4/4✓ Branch 0 taken 44153 times.
✓ Branch 1 taken 24 times.
✓ Branch 2 taken 44153 times.
✓ Branch 3 taken 24 times.
|
44855 | for (int eIdx = 0; eIdx < clusteredElements.size(); ++eIdx) |
308 |
4/4✓ Branch 0 taken 44022 times.
✓ Branch 1 taken 131 times.
✓ Branch 2 taken 44022 times.
✓ Branch 3 taken 131 times.
|
89630 | if (clusteredElements[eIdx] == largestClusterIdx) |
309 | 133992 | elementsInLargestCluster[eIdx] = true; | |
310 | |||
311 | 40 | return elementsInLargestCluster; | |
312 | } | ||
313 | |||
314 | /*! | ||
315 | * \brief Assigns a cluster index for each element. | ||
316 | */ | ||
317 | 40 | std::vector<std::size_t> clusterElements(const typename Grid::LeafGridView& gridView) const | |
318 | { | ||
319 | 80 | std::vector<std::size_t> elementInCluster(gridView.size(0), 0); // initially, all elements are in pseudo cluster 0 | |
320 | 40 | std::size_t clusterIdx = 0; | |
321 | |||
322 |
5/6✓ Branch 1 taken 44153 times.
✓ Branch 2 taken 24 times.
✓ Branch 3 taken 44153 times.
✓ Branch 4 taken 24 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 44153 times.
|
44855 | for (const auto& element : elements(gridView)) |
323 | { | ||
324 |
3/4✗ Branch 0 not taken.
✓ Branch 1 taken 44153 times.
✓ Branch 2 taken 89 times.
✓ Branch 3 taken 44064 times.
|
44815 | const auto eIdx = gridView.indexSet().index(element); |
325 |
4/4✓ Branch 0 taken 89 times.
✓ Branch 1 taken 44064 times.
✓ Branch 2 taken 89 times.
✓ Branch 3 taken 44064 times.
|
89630 | if (elementInCluster[eIdx]) // element already is in a cluster |
326 | continue; | ||
327 | |||
328 | 125 | ++clusterIdx; | |
329 | 125 | elementInCluster[eIdx] = clusterIdx; | |
330 | |||
331 |
1/2✓ Branch 1 taken 89 times.
✗ Branch 2 not taken.
|
125 | recursivelyFindConnectedElements_(gridView, element, elementInCluster, clusterIdx); |
332 | } | ||
333 | |||
334 | // make sure the clusters start with index zero | ||
335 |
4/4✓ Branch 0 taken 44153 times.
✓ Branch 1 taken 24 times.
✓ Branch 2 taken 44153 times.
✓ Branch 3 taken 24 times.
|
89750 | for (auto& clusterIdx : elementInCluster) |
336 | 44815 | clusterIdx -= 1; | |
337 | |||
338 | 40 | return elementInCluster; | |
339 | } | ||
340 | |||
341 | protected: | ||
342 | |||
343 | /*! | ||
344 | * \brief Returns a reference to the grid pointer (std::shared_ptr<Grid>) | ||
345 | */ | ||
346 | 394 | std::shared_ptr<Grid>& gridPtr() | |
347 | { | ||
348 |
1/2✓ Branch 0 taken 288 times.
✗ Branch 1 not taken.
|
394 | if(!enableDgfGridPointer_) |
349 | 394 | return gridPtr_; | |
350 | else | ||
351 | ✗ | DUNE_THROW(Dune::InvalidStateException, "You are using DGF. To get the grid pointer use method dgfGridPtr()!"); | |
352 | } | ||
353 | |||
354 | /*! | ||
355 | * \brief Returns a reference to the DGF grid pointer (Dune::GridPtr<Grid>). | ||
356 | */ | ||
357 | 151 | Dune::GridPtr<Grid>& dgfGridPtr() | |
358 | { | ||
359 |
1/2✓ Branch 0 taken 101 times.
✗ Branch 1 not taken.
|
151 | if(enableDgfGridPointer_) |
360 | 151 | return dgfGridPtr_; | |
361 | else | ||
362 | ✗ | DUNE_THROW(Dune::InvalidStateException, "The DGF grid pointer is only available if the grid was constructed with a DGF file!"); | |
363 | } | ||
364 | |||
365 | /*! | ||
366 | * \brief A state variable if the DGF Dune::GridPtr has been enabled. | ||
367 | * It is always enabled if a DGF grid file was used to create the grid. | ||
368 | */ | ||
369 | bool enableDgfGridPointer_ = false; | ||
370 | |||
371 | std::shared_ptr<Grid> gridPtr_; | ||
372 | Dune::GridPtr<Grid> dgfGridPtr_; | ||
373 | |||
374 | std::shared_ptr<GridData> gridData_; | ||
375 | |||
376 | std::string paramGroup_; | ||
377 | |||
378 | private: | ||
379 | |||
380 | 5 | void createOneDGrid_(unsigned int numPores) | |
381 | { | ||
382 | 10 | const auto lowerLeft = getParamFromGroup<GlobalPosition>(paramGroup_, "Grid.LowerLeft", GlobalPosition(0.0)); | |
383 | 5 | const auto upperRight = getParamFromGroup<GlobalPosition>(paramGroup_, "Grid.UpperRight"); | |
384 | 5 | const auto cells = numPores - 1; | |
385 | |||
386 | // create a step vector | ||
387 | 5 | GlobalPosition step = upperRight; | |
388 | 10 | step -= lowerLeft, step /= cells; | |
389 | |||
390 | // make the grid (structured interval grid in dimworld space) | ||
391 | 10 | Dune::GridFactory<Grid> factory; | |
392 | |||
393 | // create the vertices | ||
394 | 5 | GlobalPosition globalPos = lowerLeft; | |
395 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 42 times.
|
89 | for (unsigned int vIdx = 0; vIdx <= cells; vIdx++, globalPos += step) |
396 |
1/2✓ Branch 1 taken 42 times.
✗ Branch 2 not taken.
|
82 | factory.insertVertex(globalPos); |
397 | |||
398 | // create the cells | ||
399 |
2/2✓ Branch 0 taken 39 times.
✓ Branch 1 taken 3 times.
|
82 | for(unsigned int eIdx = 0; eIdx < cells; eIdx++) |
400 |
4/10✓ Branch 1 taken 39 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 39 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 39 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 39 times.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
|
308 | factory.insertElement(Dune::GeometryTypes::line, {eIdx, eIdx+1}); |
401 | |||
402 |
6/16✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 3 times.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✓ Branch 10 taken 3 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 3 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 3 times.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
✗ Branch 18 not taken.
|
5 | gridPtr() = std::shared_ptr<Grid>(factory.createGrid()); |
403 |
3/6✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 3 times.
|
5 | gridData_ = std::make_shared<GridData>(gridPtr_, paramGroup_); |
404 |
2/4✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
|
10 | gridData_->assignParameters(); |
405 | 5 | } | |
406 | |||
407 | template<class T> | ||
408 | 178 | void recursivelyFindConnectedElements_(const typename Grid::LeafGridView& gridView, | |
409 | const Element& element, | ||
410 | std::vector<T>& elementIsConnected, | ||
411 | T marker = 1) const | ||
412 | { | ||
413 | // use iteration instead of recursion here because the recursion can get too deep | ||
414 | 356 | std::stack<Element> elementStack; | |
415 |
1/2✓ Branch 0 taken 89 times.
✗ Branch 1 not taken.
|
178 | elementStack.push(element); |
416 |
4/4✓ Branch 0 taken 44153 times.
✓ Branch 1 taken 89 times.
✓ Branch 2 taken 44153 times.
✓ Branch 3 taken 89 times.
|
176968 | while (!elementStack.empty()) |
417 | { | ||
418 |
2/2✓ Branch 0 taken 715 times.
✓ Branch 1 taken 43438 times.
|
89736 | auto e = elementStack.top(); |
419 | 88306 | elementStack.pop(); | |
420 |
5/8✓ Branch 1 taken 44153 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 793598 times.
✗ Branch 6 not taken.
✓ Branch 10 taken 747292 times.
✓ Branch 11 taken 2153 times.
✓ Branch 13 taken 749445 times.
✗ Branch 14 not taken.
|
4933894 | for (const auto& intersection : intersections(gridView, e)) |
421 | { | ||
422 |
4/4✓ Branch 0 taken 747292 times.
✓ Branch 1 taken 2153 times.
✓ Branch 2 taken 747292 times.
✓ Branch 3 taken 2153 times.
|
2997780 | if (!intersection.boundary()) |
423 | { | ||
424 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 747292 times.
|
1494584 | auto outside = intersection.outside(); |
425 |
3/4✗ Branch 0 not taken.
✓ Branch 1 taken 747292 times.
✓ Branch 2 taken 44064 times.
✓ Branch 3 taken 703228 times.
|
1494584 | auto nIdx = gridView.indexSet().index(outside); |
426 |
4/6✓ Branch 0 taken 44064 times.
✓ Branch 1 taken 703228 times.
✓ Branch 2 taken 44064 times.
✓ Branch 3 taken 703228 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
|
2989168 | if (!elementIsConnected[nIdx]) |
427 | { | ||
428 |
0/4✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
|
88128 | elementIsConnected[nIdx] = marker; |
429 |
2/2✓ Branch 0 taken 43349 times.
✓ Branch 1 taken 715 times.
|
88128 | elementStack.push(outside); |
430 | } | ||
431 | } | ||
432 | } | ||
433 | } | ||
434 | 178 | } | |
435 | }; | ||
436 | |||
437 | } | ||
438 | |||
439 | #endif // HAVE_DUNE_FOAMGRID | ||
440 | |||
441 | #endif | ||
442 |