3.6-git
DUNE for Multi-{Phase, Component, Scale, Physics, ...} flow and transport in porous media
discretization/porenetwork/gridgeometry.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 * See the file COPYING for full copying permissions. *
5 * *
6 * This program is free software: you can redistribute it and/or modify *
7 * it under the terms of the GNU General Public License as published by *
8 * the Free Software Foundation, either version 3 of the License, or *
9 * (at your option) any later version. *
10 * *
11 * This program is distributed in the hope that it will be useful, *
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
14 * GNU General Public License for more details. *
15 * *
16 * You should have received a copy of the GNU General Public License *
17 * along with this program. If not, see <http://www.gnu.org/licenses/>. *
18 *****************************************************************************/
24#ifndef DUMUX_DISCRETIZATION_PNM_GRID_GEOMETRY_HH
25#define DUMUX_DISCRETIZATION_PNM_GRID_GEOMETRY_HH
26
27#include <string>
28#include <utility>
29#include <unordered_map>
30#include <functional>
31
32#include <dune/common/exceptions.hh>
33#include <dune/localfunctions/lagrange/lagrangelfecache.hh>
34
39
47
48namespace Dumux::PoreNetwork {
49
54template<class Scalar, class GridView>
56{
57 using GridIndex = typename IndexTraits<GridView>::GridIndex;
58 using SmallLocalIndex = typename IndexTraits<GridView>::SmallLocalIndex;
59 using Label = std::int_least8_t;
60 using Vertex = typename GridView::template Codim<GridView::dimension>::Entity;
61 using Element = typename GridView::template Codim<0>::Entity;
62
63 static const int dim = GridView::dimension;
64
65public:
66
67 template<class GridData>
68 void update(const GridView& gridView, const GridData& gridData)
69 {
70 coordinationNumber_ = gridData.getCoordinationNumbers();
71
72 const auto numThroats = gridView.size(0);
73 throatInscribedRadius_.resize(numThroats);
74 throatLength_.resize(numThroats);
75 throatLabel_.resize(numThroats);
76 throatCrossSectionalArea_.resize(numThroats);
77 throatShapeFactor_.resize(numThroats);
78
79 useSameGeometryForAllPores_ = true;
80 useSameShapeForAllThroats_ = true;
81 overwriteGridDataWithShapeSpecificValues_ = false;
82
83 // first check if the same geometry shall be used for all entities ...
84 if (hasParamInGroup(gridData.paramGroup(), "Grid.ThroatCrossSectionShape"))
85 {
86 const auto throatGeometryInput = getParamFromGroup<std::string>(gridData.paramGroup(), "Grid.ThroatCrossSectionShape");
87 const auto throatGeometry = Throat::shapeFromString(throatGeometryInput);
88 throatGeometry_.resize(1);
89 throatGeometry_[0] = throatGeometry;
90 overwriteGridDataWithShapeSpecificValues_ = getParamFromGroup<bool>(gridData.paramGroup(), "Grid.OverwriteGridDataWithShapeSpecificValues", true);
91
92 std::cout << "Using '" << throatGeometryInput << "' as cross-sectional shape for all throats." << std::endl;
93 }
94 else // .. otherwise, get the corresponding parameter index from the grid data and resize the respective vector
95 {
96 std::cout << "Reading shape factors for throats from grid data." << std::endl;
97 useSameShapeForAllThroats_ = false;
98 throatGeometry_.resize(numThroats);
99 }
100
101 // get the vertex parameters
102 const auto numPores = gridView.size(dim);
103 poreInscribedRadius_.resize(numPores);
104 poreLabel_.resize(numPores);
105 poreVolume_.resize(numPores);
106
107 // first check if the same geometry shall be used for all entities ...
108 if (hasParamInGroup(gridData.paramGroup(), "Grid.PoreGeometry"))
109 {
110 const auto poreGeometryInput = getParamFromGroup<std::string>(gridData.paramGroup(), "Grid.PoreGeometry");
111 poreGeometry_.resize(1);
112 poreGeometry_[0] = Pore::shapeFromString(poreGeometryInput);;
113
114 std::cout << "Using '" << poreGeometryInput << "' as geometry for all pores." << std::endl;
115 }
116 else // .. otherwise, get the corresponding parameter index from the grid data and resize the respective vector
117 {
118 std::cout << "Reading pore shapes from grid data." << std::endl;
119 useSameGeometryForAllPores_ = false;
120 poreGeometry_.resize(numPores);
121 }
122
123
124 for (const auto& vertex : vertices(gridView))
125 {
126 static const auto poreInscribedRadiusIdx = gridData.parameterIndex("PoreInscribedRadius");
127 static const auto poreLabelIdx = gridData.parameterIndex("PoreLabel");
128 const auto vIdx = gridView.indexSet().index(vertex);
129 const auto& params = gridData.parameters(vertex);
130 poreInscribedRadius_[vIdx] = params[poreInscribedRadiusIdx];
131 assert(poreInscribedRadius_[vIdx] > 0.0);
132 poreLabel_[vIdx] = params[poreLabelIdx];
133
135 poreGeometry_[vIdx] = getPoreGeometry_(gridData, vertex);
136
137 poreVolume_[vIdx] = getPoreVolume_(gridData, vertex, vIdx);
138 }
139
140 for (const auto& element : elements(gridView))
141 {
142 const int eIdx = gridView.indexSet().index(element);
143 const auto& params = gridData.parameters(element);
144 static const auto throatInscribedRadiusIdx = gridData.parameterIndex("ThroatInscribedRadius");
145 static const auto throatLengthIdx = gridData.parameterIndex("ThroatLength");
146 throatInscribedRadius_[eIdx] = params[throatInscribedRadiusIdx];
147 throatLength_[eIdx] = params[throatLengthIdx];
148
149 // use a default value if no throat label is given by the grid
150 static const bool gridHasThroatLabel = gridData.gridHasElementParameter("ThroatLabel");
151 if (gridHasThroatLabel)
152 {
153 static const auto throatLabelIdx = gridData.parameterIndex("ThroatLabel");
154 throatLabel_[eIdx] = params[throatLabelIdx];
155 }
156 else
157 {
158 const auto vIdx0 = gridView.indexSet().subIndex(element, 0, dim);
159 const auto vIdx1 = gridView.indexSet().subIndex(element, 1, dim);
160
161 const auto poreLabel0 = poreLabel(vIdx0);
162 const auto poreLabel1 = poreLabel(vIdx1);
163
164 if (poreLabel0 >= 0 && poreLabel1 >= 0)
165 {
166 std::cout << "\n Warning: Throat "
167 << eIdx << " connects two boundary pores with different pore labels. Using the greater pore label as throat label.\n"
168 << "Set the throat labels explicitly in your grid file, if needed." << std::endl;
169 }
170
171 using std::max;
172 throatLabel_[eIdx] = max(poreLabel0, poreLabel1);
173 }
174
176 {
177 static const auto throatShapeFactorIdx = gridData.parameterIndex("ThroatShapeFactor");
178 static const auto throatAreaIdx = gridData.parameterIndex("ThroatCrossSectionalArea");
179 throatShapeFactor_[eIdx] = params[throatShapeFactorIdx];
180 throatGeometry_[eIdx] = Throat::shape(throatShapeFactor_[eIdx]);
181 throatCrossSectionalArea_[eIdx] = params[throatAreaIdx];
182 }
183 else
184 {
185 throatCrossSectionalArea_[eIdx] = getThroatCrossSectionalArea_(gridData, element, eIdx);
186 throatShapeFactor_[eIdx] = getThroatShapeFactor_(gridData, element, eIdx);
187 }
188
189 assert(throatInscribedRadius_[eIdx] > 0.0);
190 assert(throatLength_[eIdx] > 0.0);
191 assert(throatCrossSectionalArea_[eIdx] > 0.0);
192
193 static const bool addThroatVolumeToPoreVolume = getParamFromGroup<bool>(gridData.paramGroup(), "Grid.AddThroatVolumeToPoreVolume", false);
194 if (addThroatVolumeToPoreVolume)
195 {
196 for (int vIdxLocal = 0; vIdxLocal < 2; ++vIdxLocal)
197 {
198 const auto vIdx = gridView.indexSet().subIndex(element, vIdxLocal, dim);
199 poreVolume_[vIdx] += 0.5 * throatCrossSectionalArea_[eIdx] * throatLength_[eIdx];
200 }
201 }
202 }
203
204 maybeResizeContainers_();
205 }
206
208 Label poreLabel(const GridIndex dofIdxGlobal) const
209 { return poreLabel_[dofIdxGlobal]; }
210
212 const std::vector<Label>& poreLabel() const
213 { return poreLabel_; }
214
216 Scalar poreInscribedRadius(const GridIndex dofIdxGlobal) const
217 { return poreInscribedRadius_[dofIdxGlobal]; }
218
220 const std::vector<Scalar>& poreInscribedRadius() const
221 { return poreInscribedRadius_; }
222
224 Scalar poreVolume(const GridIndex dofIdxGlobal) const
225 { return poreVolume_[dofIdxGlobal]; }
226
228 const std::vector<Scalar>& poreVolume() const
229 { return poreVolume_; }
230
232 Scalar throatInscribedRadius(const GridIndex eIdx) const
233 { return throatInscribedRadius_[eIdx]; }
234
236 const std::vector<Scalar>& throatInscribedRadius() const
237 { return throatInscribedRadius_; }
238
240 Scalar throatLength(const GridIndex eIdx) const
241 { return throatLength_[eIdx]; }
242
244 const std::vector<Scalar>& throatLength() const
245 { return throatLength_; }
246
248 Label throatLabel(const GridIndex eIdx) const
249 { return throatLabel_[eIdx]; }
250
252 const std::vector<Label>& throatLabel() const
253 { return throatLabel_; }
254
256 SmallLocalIndex coordinationNumber(const GridIndex dofIdxGlobal) const
257 { return coordinationNumber_[dofIdxGlobal]; }
258
260 const std::vector<SmallLocalIndex>& coordinationNumber() const
261 { return coordinationNumber_; }
262
264 Pore::Shape poreGeometry(const GridIndex vIdx) const
265 { return useSameGeometryForAllPores() ? poreGeometry_[0] : poreGeometry_[vIdx]; }
266
268 const std::vector<Pore::Shape>& poreGeometry() const
269 {
271 {
272 // if a vector of pore geometries is requested (e.g., for vtk output),
273 // resize the container and fill it with the same value everywhere
274 const auto poreGeo = poreGeometry_[0];
275 poreGeometry_.resize(poreInscribedRadius_.size(), poreGeo);
276 }
277
278 return poreGeometry_;
279 }
280
282 Throat::Shape throatCrossSectionShape(const GridIndex eIdx) const
283 { return useSameShapeForAllThroats() ? throatGeometry_[0] : throatGeometry_[eIdx]; }
284
286 const std::vector<Throat::Shape>& throatCrossSectionShape() const
287 {
289 {
290 // if a vector of throat cross section shapes is requested (e.g., for vtk output),
291 // resize the container and fill it with the same value everywhere
292 const auto throatShape = throatGeometry_[0];
293 throatGeometry_.resize(throatInscribedRadius_.size(), throatShape);
294 }
295
296 return throatGeometry_;
297 }
298
300 Scalar throatCrossSectionalArea(const GridIndex eIdx) const
301 { return throatCrossSectionalArea_[eIdx]; }
302
304 const std::vector<Scalar>& throatCrossSectionalArea() const
305 { return throatCrossSectionalArea_; }
306
308 Scalar throatShapeFactor(const GridIndex eIdx) const
309 { return useSameShapeForAllThroats() ? throatShapeFactor_[0] : throatShapeFactor_[eIdx]; }
310
312 const std::vector<Scalar>& throatShapeFactor() const
313 {
315 {
316 // if a vector of throat shape factors is requested (e.g., for vtk output),
317 // resize the container and fill it with the same value everywhere
318 const auto shapeFactor = throatShapeFactor_[0];
319 throatShapeFactor_.resize(throatInscribedRadius_.size(), shapeFactor);
320 }
321
322 return throatShapeFactor_;
323 }
324
327 { return useSameGeometryForAllPores_; }
328
331 { return useSameShapeForAllThroats_; }
332
333private:
334
336 template<class GridData>
337 Pore::Shape getPoreGeometry_(const GridData& gridData, const Vertex& vertex) const
338 {
339 static const auto poreGeometryIdx = gridData.parameterIndex("PoreGeometry");
340 using T = std::underlying_type_t<Pore::Shape>;
341 const auto poreGeometryValue = static_cast<T>(gridData.parameters(vertex)[poreGeometryIdx]);
342 return static_cast<Pore::Shape>(poreGeometryValue);
343 }
344
346 template<class GridData>
347 Scalar getPoreVolume_(const GridData& gridData, const Vertex& vertex, const std::size_t vIdx) const
348 {
349 static const bool gridHasPoreVolume = gridData.gridHasVertexParameter("PoreVolume");
350
351 if (gridHasPoreVolume)
352 {
353 static const auto poreVolumeIdx = gridData.parameterIndex("PoreVolume");
354 return gridData.parameters(vertex)[poreVolumeIdx];
355 }
356 else
357 {
359 {
360 static const Scalar fixedHeight = getParamFromGroup<Scalar>(gridData.paramGroup(), "Grid.PoreHeight", -1.0);
361 const Scalar h = fixedHeight > 0.0 ? fixedHeight : gridData.getParameter(vertex, "PoreHeight");
363 }
364 else
365 return Pore::volume(poreGeometry(vIdx), poreInscribedRadius(vIdx));
366 }
367 }
368
370 template<class GridData>
371 Scalar getThroatCrossSectionalArea_(const GridData& gridData, const Element& element, const std::size_t eIdx) const
372 {
373 static const bool gridHasThroatCrossSectionalArea = gridData.gridHasElementParameter("ThroatCrossSectionalArea");
374 if (gridHasThroatCrossSectionalArea && !overwriteGridDataWithShapeSpecificValues_)
375 {
376 static const auto throatAreaIdx = gridData.parameterIndex("ThroatCrossSectionalArea");
377 return gridData.parameters(element)[throatAreaIdx];
378 }
379 else
380 {
382 {
383 static const auto throatHeight = getParamFromGroup<Scalar>(gridData.paramGroup(), "Grid.ThroatHeight");
384 return Throat::totalCrossSectionalAreaForRectangle(throatInscribedRadius_[eIdx], throatHeight);
385 }
386 else
387 return Throat::totalCrossSectionalArea(shape, throatInscribedRadius_[eIdx]);
388 }
389 }
390
392 template<class GridData>
393 Scalar getThroatShapeFactor_(const GridData& gridData, const Element& element, const std::size_t eIdx) const
394 {
395 static const bool gridHasThroatShapeFactor = gridData.gridHasElementParameter("ThroatShapeFactor");
396 if (gridHasThroatShapeFactor && !overwriteGridDataWithShapeSpecificValues_)
397 {
398 static const auto throatShapeFactorIdx = gridData.parameterIndex("ThroatShapeFactor");
399 return gridData.parameters(element)[throatShapeFactorIdx];
400 }
401 else
402 {
404 {
405 static const auto throatHeight = getParamFromGroup<Scalar>(gridData.paramGroup(), "Grid.ThroatHeight");
406 return Throat::shapeFactorRectangle(throatInscribedRadius_[eIdx], throatHeight);
407 }
409 {
410 static const auto shapeFactor = getParamFromGroup<Scalar>(gridData.paramGroup(), "Grid.ThroatShapeFactor");
411 return shapeFactor;
412 }
413 else
414 return Throat::shapeFactor<Scalar>(shape, throatInscribedRadius_[eIdx]);
415 }
416 }
417
418 void maybeResizeContainers_()
419 {
420 // check if all throat might have the same shape in order to save some memory
422 std::adjacent_find(throatGeometry_.begin(), throatGeometry_.end(), std::not_equal_to<Throat::Shape>() ) == throatGeometry_.end())
423 {
424 std::cout << "All throats feature the same shape, resizing containers" << std::endl;
425 useSameShapeForAllThroats_ = true;
426 const Scalar shapeFactor = throatShapeFactor_[0];
427 const auto throatGeometry = throatGeometry_[0];
428 throatShapeFactor_.resize(1);
429 throatGeometry_.resize(1);
430 throatShapeFactor_[0] = shapeFactor;
431 throatGeometry_[0] = throatGeometry;
432 }
433
434 // check if all throat might have the same shape in order to save some memory
436 std::adjacent_find(poreGeometry_.begin(), poreGeometry_.end(), std::not_equal_to<Pore::Shape>() ) == poreGeometry_.end())
437 {
438 std::cout << "All pores feature the same shape, resizing containers" << std::endl;
439 useSameGeometryForAllPores_ = true;
440 const auto poreGeometry = poreGeometry_[0];
441 poreGeometry_.resize(1);
442 poreGeometry_[0] = poreGeometry;
443 }
444 }
445
446 mutable std::vector<Pore::Shape> poreGeometry_;
447 std::vector<Scalar> poreInscribedRadius_;
448 std::vector<Scalar> poreVolume_;
449 std::vector<Label> poreLabel_; // 0:no, 1:general, 2:coupling1, 3:coupling2, 4:inlet, 5:outlet
450 std::vector<SmallLocalIndex> coordinationNumber_;
451 mutable std::vector<Throat::Shape> throatGeometry_;
452 mutable std::vector<Scalar> throatShapeFactor_;
453 std::vector<Scalar> throatInscribedRadius_;
454 std::vector<Scalar> throatLength_;
455 std::vector<Label> throatLabel_; // 0:no, 1:general, 2:coupling1, 3:coupling2, 4:inlet, 5:outlet
456 std::vector<Scalar> throatCrossSectionalArea_;
457 bool useSameGeometryForAllPores_;
458 bool useSameShapeForAllThroats_;
459 bool overwriteGridDataWithShapeSpecificValues_;
460};
461
467template<class GridView, class MapperTraits = DefaultMapperTraits<GridView>>
469: public MapperTraits
470{
473
474 template<class GridGeometry, bool enableCache>
476
478};
479
485template<class Scalar,
486 class GridView,
487 bool enableGridGeometryCache = false,
490
496template<class Scalar, class GV, class Traits>
497class GridGeometry<Scalar, GV, true, Traits>
498: public BaseGridGeometry<GV, Traits>
499, public Traits::PNMData
500{
503 using GridIndexType = typename IndexTraits<GV>::GridIndex;
504 using LocalIndexType = typename IndexTraits<GV>::LocalIndex;
505 using PNMData = typename Traits::PNMData;
506
507 using Element = typename GV::template Codim<0>::Entity;
508 using CoordScalar = typename GV::ctype;
509 static const int dim = GV::dimension;
510 static const int dimWorld = GV::dimensionworld;
511
512public:
515 static constexpr DiscretizationMethod discMethod{};
516
518 using LocalView = typename Traits::template LocalView<ThisType, true>;
520 using SubControlVolume = typename Traits::SubControlVolume;
522 using SubControlVolumeFace = typename Traits::SubControlVolumeFace;
526 using DofMapper = typename Traits::VertexMapper;
528 using FeCache = Dune::LagrangeLocalFiniteElementCache<CoordScalar, Scalar, dim, 1>;
530 using GridView = GV;
531
533 template<class GridData>
534 GridGeometry(const GridView& gridView, const GridData& gridData)
535 : ParentType(gridView)
536 {
537 static_assert(GridView::dimension == 1, "Porenetwork model only allow GridView::dimension == 1!");
538 update_(gridData);
539 }
540
543 const DofMapper& dofMapper() const
544 { return this->vertexMapper(); }
545
547 std::size_t numScv() const
548 { return numScv_; }
549
551 std::size_t numScvf() const
552 { return numScvf_; }
553
556 std::size_t numBoundaryScvf() const
557 { return 0; }
558
560 std::size_t numDofs() const
561 { return this->vertexMapper().size(); }
562
564 template<class GridData>
565 void update(const GridView& gridView, const GridData& gridData)
566 {
567 ParentType::update(gridView);
568 update_(gridData);
569 }
570
572 template<class GridData>
573 void update(GridView&& gridView, const GridData& gridData)
574 {
575 ParentType::update(std::move(gridView));
576 update_(gridData);
577 }
578
580 const FeCache& feCache() const
581 { return feCache_; }
582
584 const std::array<SubControlVolume, 2>& scvs(GridIndexType eIdx) const
585 { return scvs_[eIdx]; }
586
588 const std::array<SubControlVolumeFace, 1>& scvfs(GridIndexType eIdx) const
589 { return scvfs_[eIdx]; }
590
592 bool dofOnBoundary(GridIndexType dofIdx) const
593 { return boundaryDofIndices_[dofIdx]; }
594
596 bool dofOnPeriodicBoundary(GridIndexType dofIdx) const
597 { return false; }
598
600 GridIndexType periodicallyMappedDof(GridIndexType dofIdx) const
601 { DUNE_THROW(Dune::NotImplemented, "Periodic boundaries"); }
602
604 std::unordered_map<GridIndexType, GridIndexType> periodicVertexMap() const
605 { return std::unordered_map<GridIndexType, GridIndexType>{}; }
606
608 bool hasBoundaryScvf(GridIndexType eIdx) const
609 { return hasBoundaryScvf_[eIdx]; }
610
611private:
612
613 template<class GridData>
614 void update_(const GridData& gridData)
615 {
616 PNMData::update(this->gridView(), gridData);
617
618 scvs_.clear();
619 scvfs_.clear();
620
621 auto numElements = this->gridView().size(0);
622 scvs_.resize(numElements);
623 scvfs_.resize(numElements);
624 hasBoundaryScvf_.resize(numElements, false);
625
626 boundaryDofIndices_.assign(numDofs(), false);
627
628 numScvf_ = numElements;
629 numScv_ = 2*numElements;
630
631 // Build the SCV and SCV faces
632 for (const auto& element : elements(this->gridView()))
633 {
634 // get the element geometry
635 auto eIdx = this->elementMapper().index(element);
636 auto elementGeometry = element.geometry();
637
638 // construct the sub control volumes
639 for (LocalIndexType scvLocalIdx = 0; scvLocalIdx < elementGeometry.corners(); ++scvLocalIdx)
640 {
641 const auto dofIdxGlobal = this->vertexMapper().subIndex(element, scvLocalIdx, dim);
642
643 // get the corners
644 auto corners = std::array{elementGeometry.corner(scvLocalIdx), elementGeometry.center()};
645
646 // get the fractional volume associated with the scv
647 const auto volume = this->poreVolume(dofIdxGlobal) / this->coordinationNumber(dofIdxGlobal);
648
649 scvs_[eIdx][scvLocalIdx] = SubControlVolume(dofIdxGlobal,
650 scvLocalIdx,
651 eIdx,
652 std::move(corners),
653 volume);
654
655 if (this->poreLabel(dofIdxGlobal) > 0)
656 {
657 if (boundaryDofIndices_[dofIdxGlobal])
658 continue;
659
660 boundaryDofIndices_[dofIdxGlobal] = true;
661 hasBoundaryScvf_[eIdx] = true;
662 }
663 }
664
665 // construct the inner sub control volume face
666 auto unitOuterNormal = elementGeometry.corner(1)-elementGeometry.corner(0);
667 unitOuterNormal /= unitOuterNormal.two_norm();
668 LocalIndexType scvfLocalIdx = 0;
669 scvfs_[eIdx][0] = SubControlVolumeFace(elementGeometry.center(),
670 std::move(unitOuterNormal),
671 this->throatCrossSectionalArea(this->elementMapper().index(element)),
672 scvfLocalIdx++,
673 std::array<LocalIndexType, 2>({0, 1}));
674 }
675 }
676
677 const FeCache feCache_;
678
679 std::vector<std::array<SubControlVolume, 2>> scvs_;
680 std::vector<std::array<SubControlVolumeFace, 1>> scvfs_;
681
682 std::size_t numScv_;
683 std::size_t numScvf_;
684
685 // vertices on the boundary
686 std::vector<bool> boundaryDofIndices_;
687 std::vector<bool> hasBoundaryScvf_;
688};
689
696template<class Scalar, class GV, class Traits>
697class GridGeometry<Scalar, GV, false, Traits>
698: public BaseGridGeometry<GV, Traits>
699, public Traits::PNMData
700{
703 using GridIndexType = typename IndexTraits<GV>::GridIndex;
704 using LocalIndexType = typename IndexTraits<GV>::LocalIndex;
705 using PNMData = typename Traits::PNMData;
706
707 static const int dim = GV::dimension;
708 static const int dimWorld = GV::dimensionworld;
709
710 using Element = typename GV::template Codim<0>::Entity;
711 using CoordScalar = typename GV::ctype;
712
713public:
716 static constexpr DiscretizationMethod discMethod{};
717
719 using LocalView = typename Traits::template LocalView<ThisType, false>;
721 using SubControlVolume = typename Traits::SubControlVolume;
723 using SubControlVolumeFace = typename Traits::SubControlVolumeFace;
727 using DofMapper = typename Traits::VertexMapper;
729 using FeCache = Dune::LagrangeLocalFiniteElementCache<CoordScalar, Scalar, dim, 1>;
731 using GridView = GV;
732
734 template<class GridData>
735 GridGeometry(const GridView& gridView, const GridData& gridData)
736 : ParentType(gridView)
737 {
738 static_assert(GridView::dimension == 1, "Porenetwork model only allow GridView::dimension == 1!");
739 update_(gridData);
740 }
741
742
745 const DofMapper& dofMapper() const
746 { return this->vertexMapper(); }
747
749 std::size_t numScv() const
750 { return numScv_; }
751
753 std::size_t numScvf() const
754 { return numScvf_; }
755
758 std::size_t numBoundaryScvf() const
759 { return 0; }
760
762 std::size_t numDofs() const
763 { return this->vertexMapper().size(); }
764
766 template<class GridData>
767 void update(const GridView& gridView, const GridData& gridData)
768 {
769 ParentType::update(gridView);
770 update_(gridData);
771 }
772
774 template<class GridData>
775 void update(GridView&& gridView, const GridData& gridData)
776 {
777 ParentType::update(std::move(gridView));
778 update_(gridData);
779 }
780
782 const FeCache& feCache() const
783 { return feCache_; }
784
786 bool dofOnBoundary(GridIndexType dofIdx) const
787 { return boundaryDofIndices_[dofIdx]; }
788
790 bool dofOnPeriodicBoundary(GridIndexType dofIdx) const
791 { return false; }
792
794 GridIndexType periodicallyMappedDof(GridIndexType dofIdx) const
795 { DUNE_THROW(Dune::NotImplemented, "Periodic boundaries"); }
796
798 std::unordered_map<GridIndexType, GridIndexType> periodicVertexMap() const
799 { return std::unordered_map<GridIndexType, GridIndexType>{}; }
800
801private:
802
803 template<class GridData>
804 void update_(const GridData& gridData)
805 {
806 PNMData::update(this->gridView(), gridData);
807
808 boundaryDofIndices_.assign(numDofs(), false);
809
810 // save global data on the grid's scvs and scvfs
811 numScvf_ = this->gridView().size(0);
812 numScv_ = 2*numScvf_;
813
814 for (const auto& element : elements(this->gridView()))
815 {
816 // treat boundaries
817 for (LocalIndexType vIdxLocal = 0; vIdxLocal < 2; ++vIdxLocal)
818 {
819 const auto vIdxGlobal = this->vertexMapper().subIndex(element, vIdxLocal, dim);
820 if (this->poreLabel(vIdxGlobal) > 0)
821 {
822 if (boundaryDofIndices_[vIdxGlobal])
823 continue;
824
825 boundaryDofIndices_[vIdxGlobal] = true;
826 }
827 }
828 }
829 }
830
831 const FeCache feCache_;
832
833 // Information on the global number of geometries
834 std::size_t numScv_;
835 std::size_t numScvf_;
836
837 // vertices on the boundary
838 std::vector<bool> boundaryDofIndices_;
839};
840
841} // end namespace Dumux::PoreNetwork
842
843#endif
Defines the default element and vertex mapper types.
The infrastructure to retrieve run-time parameters from Dune::ParameterTrees.
Defines the index types used for grid and local indices.
Base class for grid geometries.
Helper classes to compute the integration elements.
The available discretization methods in Dumux.
This file contains functions related to calculate pore-body properties.
This file contains functions related to calculate pore-throat properties.
auto volume(const Geometry &geo, unsigned int integrationOrder=4)
The volume of a given geometry.
Definition: volume.hh:171
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:177
typename Extrusion< T >::type Extrusion_t
Convenience alias for obtaining the extrusion type.
Definition: extrusion.hh:251
CVFE< CVFEMethods::PQ1 > Box
Definition: method.hh:83
Definition: discretization/porenetwork/fvelementgeometry.hh:34
Shape shapeFromString(const std::string &s)
Get the shape from a string description of the shape.
Definition: poreproperties.hh:56
Scalar volume(Shape shape, Scalar inscribedRadius)
Returns the volume of a given geometry based on the inscribed radius.
Definition: poreproperties.hh:73
Shape
Collection of different pore-body shapes.
Definition: poreproperties.hh:35
constexpr Scalar totalCrossSectionalAreaForRectangle(const Scalar inscribedRadius, const Scalar height) noexcept
Returns the cross-sectional area of a rectangle.
Definition: throatproperties.hh:226
constexpr Shape shape(const Scalar shapeFactor) noexcept
Returns the shape for a given shape factor.
Definition: throatproperties.hh:177
constexpr Scalar shapeFactorRectangle(const Scalar inscribedRadius, const Scalar height) noexcept
Returns the value of the shape factor for a rectangle.
Definition: throatproperties.hh:144
Scalar totalCrossSectionalArea(const Shape shape, const Scalar inscribedRadius)
Returns the cross-sectional area of a given geometry.
Definition: throatproperties.hh:211
Shape shapeFromString(const std::string &s)
Get the shape from a string description of the shape.
Definition: throatproperties.hh:57
Shape
Collection of different pore-throat shapes.
Definition: throatproperties.hh:38
Scalar shapeFactor(Shape shape, const Scalar inscribedRadius)
Returns the value of the shape factor for a given shape.
Definition: throatproperties.hh:162
Structure to define the index types used for grid and local indices.
Definition: indextraits.hh:38
typename GridView::IndexSet::IndexType GridIndex
Definition: indextraits.hh:39
std::uint_least8_t SmallLocalIndex
Definition: indextraits.hh:41
Base class for all grid geometries.
Definition: basegridgeometry.hh:61
typename BaseImplementation::GridView GridView
export the grid view type
Definition: basegridgeometry.hh:69
Definition: method.hh:58
Base class for the local geometry for porenetworks.
Definition: discretization/porenetwork/fvelementgeometry.hh:43
Base class for geometry data extraction from the grid data format.
Definition: discretization/porenetwork/gridgeometry.hh:56
Scalar throatCrossSectionalArea(const GridIndex eIdx) const
Returns the throat's cross-sectional area.
Definition: discretization/porenetwork/gridgeometry.hh:300
const std::vector< Scalar > & poreVolume() const
Returns the vector of pore volumes.
Definition: discretization/porenetwork/gridgeometry.hh:228
const std::vector< Scalar > & throatInscribedRadius() const
Returns the vector of inscribed throat radii.
Definition: discretization/porenetwork/gridgeometry.hh:236
bool useSameGeometryForAllPores() const
Returns whether all pores feature the same shape.
Definition: discretization/porenetwork/gridgeometry.hh:326
const std::vector< Label > & poreLabel() const
Returns the vector of pore labels.
Definition: discretization/porenetwork/gridgeometry.hh:212
bool useSameShapeForAllThroats() const
Returns whether all throats feature the same cross-sectional shape.
Definition: discretization/porenetwork/gridgeometry.hh:330
SmallLocalIndex coordinationNumber(const GridIndex dofIdxGlobal) const
Returns the number of throats connected to a pore (coordination number)
Definition: discretization/porenetwork/gridgeometry.hh:256
void update(const GridView &gridView, const GridData &gridData)
Definition: discretization/porenetwork/gridgeometry.hh:68
const std::vector< SmallLocalIndex > & coordinationNumber() const
Returns the vector of coordination numbers.
Definition: discretization/porenetwork/gridgeometry.hh:260
const std::vector< Scalar > & throatShapeFactor() const
Returns the vector of throat shape factors.
Definition: discretization/porenetwork/gridgeometry.hh:312
const std::vector< Scalar > & throatCrossSectionalArea() const
Returns the vector of throat cross-sectional areas.
Definition: discretization/porenetwork/gridgeometry.hh:304
Pore::Shape poreGeometry(const GridIndex vIdx) const
the geometry of the pore
Definition: discretization/porenetwork/gridgeometry.hh:264
Throat::Shape throatCrossSectionShape(const GridIndex eIdx) const
Returns the throat's cross-sectional shape.
Definition: discretization/porenetwork/gridgeometry.hh:282
Label throatLabel(const GridIndex eIdx) const
Returns an index indicating if a throat is touching the domain boundary.
Definition: discretization/porenetwork/gridgeometry.hh:248
const std::vector< Label > & throatLabel() const
Returns the vector of throat labels.
Definition: discretization/porenetwork/gridgeometry.hh:252
Scalar throatLength(const GridIndex eIdx) const
Returns the length of the throat.
Definition: discretization/porenetwork/gridgeometry.hh:240
const std::vector< Throat::Shape > & throatCrossSectionShape() const
Returns the vector of cross-sectional shapes.
Definition: discretization/porenetwork/gridgeometry.hh:286
Scalar poreVolume(const GridIndex dofIdxGlobal) const
Returns the volume of the pore.
Definition: discretization/porenetwork/gridgeometry.hh:224
Scalar throatInscribedRadius(const GridIndex eIdx) const
Returns the inscribed radius of the throat.
Definition: discretization/porenetwork/gridgeometry.hh:232
Label poreLabel(const GridIndex dofIdxGlobal) const
Returns the pore label (e.g. used for setting BCs)
Definition: discretization/porenetwork/gridgeometry.hh:208
Scalar poreInscribedRadius(const GridIndex dofIdxGlobal) const
Returns the inscribed radius of the pore.
Definition: discretization/porenetwork/gridgeometry.hh:216
const std::vector< Scalar > & throatLength() const
Returns the vector of throat lengths.
Definition: discretization/porenetwork/gridgeometry.hh:244
const std::vector< Pore::Shape > & poreGeometry() const
Returns the vector of pore geometries.
Definition: discretization/porenetwork/gridgeometry.hh:268
Scalar throatShapeFactor(const GridIndex eIdx) const
Returns the throat's shape factor.
Definition: discretization/porenetwork/gridgeometry.hh:308
const std::vector< Scalar > & poreInscribedRadius() const
Returns the vector of inscribed pore radii.
Definition: discretization/porenetwork/gridgeometry.hh:220
The default traits.
Definition: discretization/porenetwork/gridgeometry.hh:470
Base class for the finite volume geometry for porenetwork models.
Definition: discretization/porenetwork/gridgeometry.hh:489
Base class for the finite volume geometry for porenetwork models.
Definition: discretization/porenetwork/gridgeometry.hh:500
Dune::LagrangeLocalFiniteElementCache< CoordScalar, Scalar, dim, 1 > FeCache
export the finite element cache type
Definition: discretization/porenetwork/gridgeometry.hh:528
std::size_t numDofs() const
The total number of degrees of freedom.
Definition: discretization/porenetwork/gridgeometry.hh:560
const std::array< SubControlVolume, 2 > & scvs(GridIndexType eIdx) const
Get the local scvs for an element.
Definition: discretization/porenetwork/gridgeometry.hh:584
GridIndexType periodicallyMappedDof(GridIndexType dofIdx) const
The index of the vertex / d.o.f. on the other side of the periodic boundary.
Definition: discretization/porenetwork/gridgeometry.hh:600
std::unordered_map< GridIndexType, GridIndexType > periodicVertexMap() const
Returns the map between dofs across periodic boundaries.
Definition: discretization/porenetwork/gridgeometry.hh:604
typename Traits::SubControlVolumeFace SubControlVolumeFace
export the type of sub control volume
Definition: discretization/porenetwork/gridgeometry.hh:522
const DofMapper & dofMapper() const
Definition: discretization/porenetwork/gridgeometry.hh:543
std::size_t numScv() const
The total number of sub control volumes.
Definition: discretization/porenetwork/gridgeometry.hh:547
bool dofOnPeriodicBoundary(GridIndexType dofIdx) const
If a vertex / d.o.f. is on a periodic boundary (not implemented)
Definition: discretization/porenetwork/gridgeometry.hh:596
bool dofOnBoundary(GridIndexType dofIdx) const
If a vertex / d.o.f. is on the boundary.
Definition: discretization/porenetwork/gridgeometry.hh:592
typename Traits::SubControlVolume SubControlVolume
export the type of sub control volume
Definition: discretization/porenetwork/gridgeometry.hh:520
typename Traits::template LocalView< ThisType, true > LocalView
export the type of the fv element geometry (the local view type)
Definition: discretization/porenetwork/gridgeometry.hh:518
std::size_t numScvf() const
The total number of sun control volume faces.
Definition: discretization/porenetwork/gridgeometry.hh:551
Extrusion_t< Traits > Extrusion
export the type of extrusion
Definition: discretization/porenetwork/gridgeometry.hh:524
const std::array< SubControlVolumeFace, 1 > & scvfs(GridIndexType eIdx) const
Get the local scvfs for an element.
Definition: discretization/porenetwork/gridgeometry.hh:588
std::size_t numBoundaryScvf() const
Definition: discretization/porenetwork/gridgeometry.hh:556
void update(const GridView &gridView, const GridData &gridData)
update all fvElementGeometries (call this after grid adaption)
Definition: discretization/porenetwork/gridgeometry.hh:565
const FeCache & feCache() const
The finite element cache for creating local FE bases.
Definition: discretization/porenetwork/gridgeometry.hh:580
typename Traits::VertexMapper DofMapper
export dof mapper type
Definition: discretization/porenetwork/gridgeometry.hh:526
bool hasBoundaryScvf(GridIndexType eIdx) const
Returns whether one of the geometry's scvfs lies on a boundary.
Definition: discretization/porenetwork/gridgeometry.hh:608
GridGeometry(const GridView &gridView, const GridData &gridData)
Constructor.
Definition: discretization/porenetwork/gridgeometry.hh:534
void update(GridView &&gridView, const GridData &gridData)
update all fvElementGeometries (call this after grid adaption)
Definition: discretization/porenetwork/gridgeometry.hh:573
Base class for the finite volume geometry for porenetwork models.
Definition: discretization/porenetwork/gridgeometry.hh:700
bool dofOnBoundary(GridIndexType dofIdx) const
If a vertex / d.o.f. is on the boundary.
Definition: discretization/porenetwork/gridgeometry.hh:786
Dune::LagrangeLocalFiniteElementCache< CoordScalar, Scalar, dim, 1 > FeCache
export the finite element cache type
Definition: discretization/porenetwork/gridgeometry.hh:729
std::size_t numDofs() const
The total number of degrees of freedom.
Definition: discretization/porenetwork/gridgeometry.hh:762
std::size_t numBoundaryScvf() const
Definition: discretization/porenetwork/gridgeometry.hh:758
void update(GridView &&gridView, const GridData &gridData)
update all fvElementGeometries (call this after grid adaption)
Definition: discretization/porenetwork/gridgeometry.hh:775
void update(const GridView &gridView, const GridData &gridData)
update all fvElementGeometries (call this after grid adaption)
Definition: discretization/porenetwork/gridgeometry.hh:767
std::size_t numScv() const
The total number of sub control volumes.
Definition: discretization/porenetwork/gridgeometry.hh:749
typename Traits::VertexMapper DofMapper
export dof mapper type
Definition: discretization/porenetwork/gridgeometry.hh:727
GridGeometry(const GridView &gridView, const GridData &gridData)
Constructor.
Definition: discretization/porenetwork/gridgeometry.hh:735
const FeCache & feCache() const
The finite element cache for creating local FE bases.
Definition: discretization/porenetwork/gridgeometry.hh:782
typename Traits::SubControlVolumeFace SubControlVolumeFace
export the type of sub control volume
Definition: discretization/porenetwork/gridgeometry.hh:723
std::unordered_map< GridIndexType, GridIndexType > periodicVertexMap() const
Returns the map between dofs across periodic boundaries.
Definition: discretization/porenetwork/gridgeometry.hh:798
Extrusion_t< Traits > Extrusion
export the type of extrusion
Definition: discretization/porenetwork/gridgeometry.hh:725
std::size_t numScvf() const
The total number of sun control volume faces.
Definition: discretization/porenetwork/gridgeometry.hh:753
typename Traits::SubControlVolume SubControlVolume
export the type of sub control volume
Definition: discretization/porenetwork/gridgeometry.hh:721
typename Traits::template LocalView< ThisType, false > LocalView
export the type of the fv element geometry (the local view type)
Definition: discretization/porenetwork/gridgeometry.hh:719
const DofMapper & dofMapper() const
Definition: discretization/porenetwork/gridgeometry.hh:745
GridIndexType periodicallyMappedDof(GridIndexType dofIdx) const
The index of the vertex / d.o.f. on the other side of the periodic boundary.
Definition: discretization/porenetwork/gridgeometry.hh:794
bool dofOnPeriodicBoundary(GridIndexType dofIdx) const
If a vertex / d.o.f. is on a periodic boundary (not implemented)
Definition: discretization/porenetwork/gridgeometry.hh:790
the sub control volume for porenetworks
Definition: discretization/porenetwork/subcontrolvolume.hh:65
Class for a sub control volume face for porenetworks.
Definition: discretization/porenetwork/subcontrolvolumeface.hh:62
Class for grid data attached to dgf or gmsh grid files.
Definition: griddata.hh:66
double getParameter(const Element &element, const std::string &fieldName) const
Get a element parameter.
Definition: griddata.hh:252
const std::vector< double > & parameters(const Vertex &vertex) const
Call the parameters function of the DGF grid pointer if available for vertex data.
Definition: griddata.hh:112
Class for grid data attached to dgf or gmsh grid files.
Definition: porenetwork/griddata.hh:56
bool gridHasElementParameter(const std::string &param) const
Return if a given element parameter is provided by the grid.
Definition: porenetwork/griddata.hh:266
std::vector< SmallLocalIndex > getCoordinationNumbers() const
Returns the coordination numbers for all pore bodies.
Definition: porenetwork/griddata.hh:151
int parameterIndex(const std::string &paramName) const
Return the index for a given parameter name.
Definition: porenetwork/griddata.hh:234
const std::string & paramGroup() const
Return the parameter group.
Definition: porenetwork/griddata.hh:260
const std::vector< double > & parameters(const Vertex &vertex) const
Call the parameters function of the DGF grid pointer if available for vertex data.
Definition: porenetwork/griddata.hh:98
Base class for the local geometry for porenetworks.
the sub control volume for pore networks
Base class for a sub control volume face.