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.
This file contains functions related to calculate pore-throat properties.
This file contains functions related to calculate pore-body properties.
The available discretization methods in Dumux.
Helper classes to compute the integration elements.
Base class for grid geometries.
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.
Base class for a sub control volume face.
the sub control volume for pore networks