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-FileCopyrightText: 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 PQ1BubbleDiscretization | ||
10 | * \brief Base class for the finite volume geometry vector for the pq1bubble method | ||
11 | * This builds up the sub control volumes and sub control volume faces | ||
12 | * for each element of the grid partition. | ||
13 | */ | ||
14 | #ifndef DUMUX_DISCRETIZATION_PQ1BUBBLE_GRID_GEOMETRY_HH | ||
15 | #define DUMUX_DISCRETIZATION_PQ1BUBBLE_GRID_GEOMETRY_HH | ||
16 | |||
17 | #include <utility> | ||
18 | #include <unordered_map> | ||
19 | #include <type_traits> | ||
20 | |||
21 | #include <dune/grid/common/mcmgmapper.hh> | ||
22 | |||
23 | #include <dumux/discretization/method.hh> | ||
24 | |||
25 | #include <dumux/common/indextraits.hh> | ||
26 | #include <dumux/common/defaultmappertraits.hh> | ||
27 | |||
28 | #include <dumux/geometry/center.hh> | ||
29 | #include <dumux/geometry/volume.hh> | ||
30 | |||
31 | #include <dumux/discretization/basegridgeometry.hh> | ||
32 | #include <dumux/discretization/pq1bubble/geometryhelper.hh> | ||
33 | #include <dumux/discretization/pq1bubble/fvelementgeometry.hh> | ||
34 | #include <dumux/discretization/pq1bubble/subcontrolvolume.hh> | ||
35 | #include <dumux/discretization/pq1bubble/subcontrolvolumeface.hh> | ||
36 | #include <dumux/discretization/pq1bubble/pq1bubblefecache.hh> | ||
37 | #include <dumux/discretization/extrusion.hh> | ||
38 | |||
39 | #include <dumux/io/grid/periodicgridtraits.hh> | ||
40 | |||
41 | namespace Dumux { | ||
42 | |||
43 | namespace Detail { | ||
44 | template<class T> | ||
45 | using EnableHybridCVFE | ||
46 | = typename T::EnableHybridCVFE; | ||
47 | |||
48 | template<class T> | ||
49 | static constexpr bool enablesHybridCVFE | ||
50 | = Dune::Std::detected_or_t<std::false_type, EnableHybridCVFE, T>{}; | ||
51 | |||
52 | template<class GV, class T> | ||
53 | using PQ1BubbleGeometryHelper_t = Dune::Std::detected_or_t< | ||
54 | std::conditional_t<enablesHybridCVFE<T>, | ||
55 | Dumux::HybridPQ1BubbleGeometryHelper<GV, typename T::SubControlVolume, typename T::SubControlVolumeFace>, | ||
56 | Dumux::PQ1BubbleGeometryHelper<GV, typename T::SubControlVolume, typename T::SubControlVolumeFace> | ||
57 | >, | ||
58 | SpecifiesGeometryHelper, | ||
59 | T | ||
60 | >; | ||
61 | } // end namespace Detail | ||
62 | |||
63 | template <class GridView> | ||
64 | struct PQ1BubbleMapperTraits :public DefaultMapperTraits<GridView> | ||
65 | { | ||
66 | using DofMapper = Dune::MultipleCodimMultipleGeomTypeMapper<GridView>; | ||
67 | |||
68 | /** | ||
69 | * \brief layout for elements and vertices | ||
70 | * | ||
71 | */ | ||
72 | 14 | static Dune::MCMGLayout layout() | |
73 | { | ||
74 |
2/2✓ Branch 0 taken 60 times.
✓ Branch 1 taken 28 times.
|
88 | return [](Dune::GeometryType gt, int dimgrid) { |
75 |
4/4✓ Branch 0 taken 60 times.
✓ Branch 1 taken 28 times.
✓ Branch 2 taken 28 times.
✓ Branch 3 taken 32 times.
|
88 | return (gt.dim() == dimgrid) || (gt.dim() == 0); |
76 |
1/2✓ Branch 1 taken 14 times.
✗ Branch 2 not taken.
|
14 | }; |
77 | } | ||
78 | }; | ||
79 | |||
80 | /*! | ||
81 | * \ingroup PQ1BubbleDiscretization | ||
82 | * \brief The default traits for the pq1bubble finite volume grid geometry | ||
83 | * Defines the scv and scvf types and the mapper types | ||
84 | * \tparam the grid view type | ||
85 | */ | ||
86 | template<class GridView, class MapperTraits = PQ1BubbleMapperTraits<GridView>> | ||
87 | struct PQ1BubbleDefaultGridGeometryTraits | ||
88 | : public MapperTraits | ||
89 | { | ||
90 | using SubControlVolume = PQ1BubbleSubControlVolume<GridView>; | ||
91 | using SubControlVolumeFace = PQ1BubbleSubControlVolumeFace<GridView>; | ||
92 | |||
93 | template<class GridGeometry, bool enableCache> | ||
94 | using LocalView = PQ1BubbleFVElementGeometry<GridGeometry, enableCache>; | ||
95 | }; | ||
96 | |||
97 | /*! | ||
98 | * \ingroup PQ1BubbleDiscretization | ||
99 | * \brief The default traits for the hybrid pq1bubble finite volume grid geometry | ||
100 | * Defines the scv and scvf types and the mapper types | ||
101 | * \tparam the grid view type | ||
102 | */ | ||
103 | template<class BaseTraits> | ||
104 | struct HybridPQ1BubbleCVFEGridGeometryTraits | ||
105 | : public BaseTraits | ||
106 | { using EnableHybridCVFE = std::true_type; }; | ||
107 | |||
108 | /*! | ||
109 | * \ingroup PQ1BubbleDiscretization | ||
110 | * \brief Base class for the finite volume geometry vector for pq1bubble schemes | ||
111 | * This builds up the sub control volumes and sub control volume faces | ||
112 | * \note For caching enabled we store the fv geometries for the whole grid view which is memory intensive but faster | ||
113 | */ | ||
114 | template<class Scalar, | ||
115 | class GV, | ||
116 | bool enableCaching = true, | ||
117 | class Traits = PQ1BubbleDefaultGridGeometryTraits<GV>> | ||
118 | class PQ1BubbleFVGridGeometry | ||
119 | : public BaseGridGeometry<GV, Traits> | ||
120 | { | ||
121 | using ThisType = PQ1BubbleFVGridGeometry<Scalar, GV, enableCaching, Traits>; | ||
122 | using ParentType = BaseGridGeometry<GV, Traits>; | ||
123 | using GridIndexType = typename IndexTraits<GV>::GridIndex; | ||
124 | using LocalIndexType = typename IndexTraits<GV>::LocalIndex; | ||
125 | |||
126 | using Element = typename GV::template Codim<0>::Entity; | ||
127 | using CoordScalar = typename GV::ctype; | ||
128 | static const int dim = GV::dimension; | ||
129 | static const int dimWorld = GV::dimensionworld; | ||
130 | |||
131 | static_assert(dim > 1, "Only implemented for dim > 1"); | ||
132 | |||
133 | public: | ||
134 | //! export the discretization method this geometry belongs to | ||
135 | using DiscretizationMethod = DiscretizationMethods::PQ1Bubble; | ||
136 | static constexpr DiscretizationMethod discMethod{}; | ||
137 | |||
138 | static constexpr bool enableHybridCVFE = Detail::enablesHybridCVFE<Traits>; | ||
139 | |||
140 | //! export basic grid geometry type for the alternative constructor | ||
141 | using BasicGridGeometry = BasicGridGeometry_t<GV, Traits>; | ||
142 | //! export the type of the fv element geometry (the local view type) | ||
143 | using LocalView = typename Traits::template LocalView<ThisType, true>; | ||
144 | //! export the type of sub control volume | ||
145 | using SubControlVolume = typename Traits::SubControlVolume; | ||
146 | //! export the type of sub control volume | ||
147 | using SubControlVolumeFace = typename Traits::SubControlVolumeFace; | ||
148 | //! export the type of extrusion | ||
149 | using Extrusion = Extrusion_t<Traits>; | ||
150 | //! export dof mapper type | ||
151 | using DofMapper = typename Traits::DofMapper; | ||
152 | //! export the finite element cache type | ||
153 | using FeCache = Dumux::PQ1BubbleFECache<CoordScalar, Scalar, dim>; | ||
154 | //! export the grid view type | ||
155 | using GridView = GV; | ||
156 | //! export whether the grid(geometry) supports periodicity | ||
157 | using SupportsPeriodicity = typename PeriodicGridTraits<typename GV::Grid>::SupportsPeriodicity; | ||
158 | |||
159 | //! Constructor with basic grid geometry used to share state with another grid geometry on the same grid view | ||
160 | 14 | PQ1BubbleFVGridGeometry(std::shared_ptr<BasicGridGeometry> gg) | |
161 | : ParentType(std::move(gg)) | ||
162 |
1/2✓ Branch 1 taken 14 times.
✗ Branch 2 not taken.
|
14 | , dofMapper_(this->gridView(), Traits::layout()) |
163 | 14 | , cache_(*this) | |
164 |
4/8✓ Branch 1 taken 14 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 14 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 14 times.
✓ Branch 9 taken 14 times.
✗ Branch 10 not taken.
|
28 | , periodicGridTraits_(this->gridView().grid()) |
165 | { | ||
166 |
1/2✓ Branch 1 taken 14 times.
✗ Branch 2 not taken.
|
14 | update_(); |
167 | 14 | } | |
168 | |||
169 | //! Constructor | ||
170 | 14 | PQ1BubbleFVGridGeometry(const GridView& gridView) | |
171 |
1/2✓ Branch 1 taken 14 times.
✗ Branch 2 not taken.
|
14 | : PQ1BubbleFVGridGeometry(std::make_shared<BasicGridGeometry>(gridView)) |
172 | 14 | {} | |
173 | |||
174 | //! The dofMapper | ||
175 | 112070269 | const DofMapper& dofMapper() const | |
176 |
7/12✓ Branch 0 taken 4 times.
✓ Branch 1 taken 6 times.
✓ Branch 3 taken 4 times.
✓ Branch 4 taken 2 times.
✓ Branch 6 taken 6 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 4 times.
✗ Branch 10 not taken.
✓ Branch 12 taken 6 times.
✗ Branch 13 not taken.
✗ Branch 2 not taken.
✗ Branch 5 not taken.
|
4714113 | { return dofMapper_; } |
177 | |||
178 | //! The total number of sub control volumes | ||
179 | std::size_t numScv() const | ||
180 | { return numScv_; } | ||
181 | |||
182 | //! The total number of sub control volume faces | ||
183 | std::size_t numScvf() const | ||
184 | { return numScvf_; } | ||
185 | |||
186 | //! The total number of boundary sub control volume faces | ||
187 | 2 | std::size_t numBoundaryScvf() const | |
188 |
2/4✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
|
2 | { return numBoundaryScvf_; } |
189 | |||
190 | //! The total number of degrees of freedom | ||
191 | 86 | std::size_t numDofs() const | |
192 |
6/13✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 11 times.
✗ Branch 5 not taken.
✓ Branch 9 taken 9 times.
✗ Branch 10 not taken.
✓ Branch 12 taken 5 times.
✗ Branch 13 not taken.
✓ Branch 6 taken 2 times.
✗ Branch 7 not taken.
✓ Branch 15 taken 1 times.
✗ Branch 16 not taken.
✗ Branch 8 not taken.
|
73 | { return this->dofMapper().size(); } |
193 | |||
194 | //! update all geometries (call this after grid adaption) | ||
195 | void update(const GridView& gridView) | ||
196 | { | ||
197 | ParentType::update(gridView); | ||
198 | update_(); | ||
199 | } | ||
200 | |||
201 | //! update all geometries (call this after grid adaption) | ||
202 | void update(GridView&& gridView) | ||
203 | { | ||
204 | ParentType::update(std::move(gridView)); | ||
205 | update_(); | ||
206 | } | ||
207 | |||
208 | //! The finite element cache for creating local FE bases | ||
209 | 19787966 | const FeCache& feCache() const | |
210 | 19787966 | { return feCache_; } | |
211 | |||
212 | //! If a vertex / d.o.f. is on the boundary | ||
213 | 2692076 | bool dofOnBoundary(GridIndexType dofIdx) const | |
214 |
4/4✓ Branch 0 taken 74970 times.
✓ Branch 1 taken 2501314 times.
✓ Branch 2 taken 2047 times.
✓ Branch 3 taken 113745 times.
|
2692076 | { return boundaryDofIndices_[dofIdx]; } |
215 | |||
216 | //! If a vertex / d.o.f. is on a periodic boundary | ||
217 | 72336 | bool dofOnPeriodicBoundary(GridIndexType dofIdx) const | |
218 |
0/4✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
|
144672 | { return periodicDofMap_.count(dofIdx); } |
219 | |||
220 | //! The index of the vertex / d.o.f. on the other side of the periodic boundary | ||
221 | ✗ | GridIndexType periodicallyMappedDof(GridIndexType dofIdx) const | |
222 | ✗ | { return periodicDofMap_.at(dofIdx); } | |
223 | |||
224 | //! Returns the map between dofs across periodic boundaries | ||
225 | const std::unordered_map<GridIndexType, GridIndexType>& periodicDofMap() const | ||
226 | 25 | { return periodicDofMap_; } | |
227 | |||
228 | //! local view of this object (constructed with the internal cache) | ||
229 | 1363076 | friend inline LocalView localView(const PQ1BubbleFVGridGeometry& gg) | |
230 |
13/17✓ Branch 1 taken 11 times.
✓ Branch 2 taken 6 times.
✓ Branch 5 taken 7 times.
✓ Branch 6 taken 1 times.
✓ Branch 8 taken 4801 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 21601 times.
✗ Branch 12 not taken.
✓ Branch 14 taken 21604 times.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✓ Branch 17 taken 1 times.
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 42002 times.
✓ Branch 7 taken 903 times.
✓ Branch 10 taken 4 times.
✓ Branch 13 taken 2 times.
|
840964 | { return { gg.cache_ }; } |
231 | |||
232 | private: | ||
233 | class PQ1BubbleGridGeometryCache | ||
234 | { | ||
235 | friend class PQ1BubbleFVGridGeometry; | ||
236 | public: | ||
237 | //! export the geometry helper type | ||
238 | using GeometryHelper = Detail::PQ1BubbleGeometryHelper_t<GV, Traits>; | ||
239 | |||
240 | 14 | explicit PQ1BubbleGridGeometryCache(const PQ1BubbleFVGridGeometry& gg) | |
241 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 14 times.
|
14 | : gridGeometry_(&gg) |
242 | {} | ||
243 | |||
244 | 135326286 | const PQ1BubbleFVGridGeometry& gridGeometry() const | |
245 |
12/16✓ Branch 1 taken 66114 times.
✓ Branch 2 taken 100622 times.
✓ Branch 12 taken 4412 times.
✓ Branch 13 taken 9600 times.
✓ Branch 15 taken 5052 times.
✗ Branch 16 not taken.
✓ Branch 10 taken 7200 times.
✗ Branch 11 not taken.
✓ Branch 3 taken 203864 times.
✓ Branch 0 taken 1580 times.
✓ Branch 9 taken 4800 times.
✗ Branch 14 not taken.
✓ Branch 4 taken 41160 times.
✓ Branch 5 taken 2177904 times.
✓ Branch 18 taken 1920 times.
✗ Branch 19 not taken.
|
132465762 | { return *gridGeometry_; } |
246 | |||
247 | //! Get the global sub control volume indices of an element | ||
248 | 114378189 | const std::vector<SubControlVolume>& scvs(GridIndexType eIdx) const | |
249 |
4/5✓ Branch 1 taken 7406 times.
✓ Branch 2 taken 921130 times.
✓ Branch 3 taken 56830 times.
✓ Branch 4 taken 231314 times.
✗ Branch 5 not taken.
|
113789177 | { return scvs_[eIdx]; } |
250 | |||
251 | //! Get the global sub control volume face indices of an element | ||
252 | 5645311 | const std::vector<SubControlVolumeFace>& scvfs(GridIndexType eIdx) const | |
253 |
1/5✗ Branch 0 not taken.
✓ Branch 1 taken 12000 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 2 not taken.
|
5500451 | { return scvfs_[eIdx]; } |
254 | |||
255 | //! Returns whether one of the geometry's scvfs lies on a boundary | ||
256 | 42775 | bool hasBoundaryScvf(GridIndexType eIdx) const | |
257 |
2/4✓ Branch 0 taken 1362 times.
✓ Branch 1 taken 41413 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
|
42775 | { return hasBoundaryScvf_[eIdx]; } |
258 | |||
259 | //! Local mappings necessary to construct geometries of scvfs | ||
260 | 664 | const std::vector<std::array<LocalIndexType, 2>>& scvfBoundaryGeometryKeys(GridIndexType eIdx) const | |
261 | 664 | { return scvfBoundaryGeometryKeys_.at(eIdx); } | |
262 | |||
263 | private: | ||
264 | 14 | void clear_() | |
265 | { | ||
266 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 14 times.
|
14 | scvs_.clear(); |
267 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 14 times.
|
14 | scvfs_.clear(); |
268 | 14 | hasBoundaryScvf_.clear(); | |
269 | 14 | scvfBoundaryGeometryKeys_.clear(); | |
270 | 14 | } | |
271 | |||
272 | std::vector<std::vector<SubControlVolume>> scvs_; | ||
273 | std::vector<std::vector<SubControlVolumeFace>> scvfs_; | ||
274 | std::vector<bool> hasBoundaryScvf_; | ||
275 | std::unordered_map<GridIndexType, std::vector<std::array<LocalIndexType, 2>>> scvfBoundaryGeometryKeys_; | ||
276 | |||
277 | const PQ1BubbleFVGridGeometry* gridGeometry_; | ||
278 | }; | ||
279 | |||
280 | public: | ||
281 | //! the cache type (only the caching implementation has this) | ||
282 | //! this alias should only be used by the local view implementation | ||
283 | using Cache = PQ1BubbleGridGeometryCache; | ||
284 | |||
285 | private: | ||
286 | using GeometryHelper = typename Cache::GeometryHelper; | ||
287 | |||
288 | 14 | void update_() | |
289 | { | ||
290 | 14 | cache_.clear_(); | |
291 | 14 | dofMapper_.update(this->gridView()); | |
292 | |||
293 | 14 | auto numElements = this->gridView().size(0); | |
294 | 14 | cache_.scvs_.resize(numElements); | |
295 | 14 | cache_.scvfs_.resize(numElements); | |
296 | 14 | cache_.hasBoundaryScvf_.resize(numElements, false); | |
297 | |||
298 | 14 | boundaryDofIndices_.assign(numDofs(), false); | |
299 | |||
300 | 14 | numScv_ = 0; | |
301 | 14 | numScvf_ = 0; | |
302 | 14 | numBoundaryScvf_ = 0; | |
303 | |||
304 | // Build the scvs and scv faces | ||
305 |
6/9✓ Branch 2 taken 9 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 3 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 12000 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 12000 times.
✓ Branch 11 taken 3 times.
✓ Branch 1 taken 111266 times.
|
156385 | for (const auto& element : elements(this->gridView())) |
306 | { | ||
307 |
2/4✓ Branch 1 taken 12000 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 12000 times.
✗ Branch 5 not taken.
|
123261 | auto eIdx = this->elementMapper().index(element); |
308 | |||
309 | // get the element geometry | ||
310 |
1/2✓ Branch 1 taken 12000 times.
✗ Branch 2 not taken.
|
123261 | auto elementGeometry = element.geometry(); |
311 |
1/2✓ Branch 1 taken 12000 times.
✗ Branch 2 not taken.
|
123261 | const auto refElement = referenceElement(elementGeometry); |
312 | |||
313 | // instantiate the geometry helper | ||
314 |
1/2✓ Branch 1 taken 12000 times.
✗ Branch 2 not taken.
|
123261 | GeometryHelper geometryHelper(elementGeometry); |
315 | |||
316 | 123261 | numScv_ += geometryHelper.numScv(); | |
317 | // construct the sub control volumes | ||
318 |
2/4✓ Branch 1 taken 12000 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 12000 times.
✗ Branch 5 not taken.
|
123261 | cache_.scvs_[eIdx].resize(geometryHelper.numScv()); |
319 | |||
320 | // Scvs related to control volumes | ||
321 |
4/4✓ Branch 1 taken 559813 times.
✓ Branch 2 taken 111261 times.
✓ Branch 3 taken 49600 times.
✓ Branch 4 taken 12000 times.
|
671074 | for (LocalIndexType scvLocalIdx = 0; scvLocalIdx < geometryHelper.numScv(); ++scvLocalIdx) |
322 | { | ||
323 |
1/2✓ Branch 1 taken 49600 times.
✗ Branch 2 not taken.
|
547813 | auto corners = geometryHelper.getScvCorners(scvLocalIdx); |
324 | 547813 | cache_.scvs_[eIdx][scvLocalIdx] = SubControlVolume( | |
325 |
1/2✓ Branch 1 taken 22069 times.
✗ Branch 2 not taken.
|
547813 | geometryHelper.scvVolume(scvLocalIdx, corners), |
326 | 1095626 | geometryHelper.dofPosition(scvLocalIdx), | |
327 |
1/2✓ Branch 1 taken 547813 times.
✗ Branch 2 not taken.
|
1095626 | Dumux::center(corners), |
328 | scvLocalIdx, | ||
329 | eIdx, | ||
330 | 547813 | GeometryHelper::dofIndex(this->dofMapper(), element, scvLocalIdx), | |
331 |
1/2✓ Branch 1 taken 49600 times.
✗ Branch 2 not taken.
|
547813 | geometryHelper.isOverlappingScv(scvLocalIdx) |
332 | ); | ||
333 | } | ||
334 | |||
335 | // construct the sub control volume faces | ||
336 |
1/2✓ Branch 1 taken 12000 times.
✗ Branch 2 not taken.
|
123261 | const auto numInteriorScvfs = GeometryHelper::numInteriorScvf(elementGeometry.type()); |
337 | 123261 | numScvf_ += numInteriorScvfs; | |
338 |
1/2✓ Branch 1 taken 12000 times.
✗ Branch 2 not taken.
|
123261 | cache_.scvfs_[eIdx].resize(numInteriorScvfs); |
339 | 123261 | LocalIndexType scvfLocalIdx = 0; | |
340 |
2/2✓ Branch 0 taken 857932 times.
✓ Branch 1 taken 123261 times.
|
981193 | for (; scvfLocalIdx < numInteriorScvfs; ++scvfLocalIdx) |
341 | { | ||
342 |
1/2✓ Branch 1 taken 75200 times.
✗ Branch 2 not taken.
|
857932 | const auto scvPair = geometryHelper.getScvPairForScvf(scvfLocalIdx); |
343 |
1/2✓ Branch 1 taken 75200 times.
✗ Branch 2 not taken.
|
857932 | const auto corners = geometryHelper.getScvfCorners(scvfLocalIdx); |
344 | 857932 | const auto area = Dumux::convexPolytopeVolume<dim-1>( | |
345 | geometryHelper.getInteriorScvfGeometryType(scvfLocalIdx), | ||
346 |
1/2✓ Branch 1 taken 75200 times.
✗ Branch 2 not taken.
|
1760004 | [&](unsigned int i){ return corners[i]; } |
347 | ); | ||
348 | |||
349 | 857932 | cache_.scvfs_[eIdx][scvfLocalIdx] = SubControlVolumeFace( | |
350 | 857932 | Dumux::center(corners), | |
351 | area, | ||
352 | 857932 | geometryHelper.normal(corners, scvPair), | |
353 | std::move(scvPair), | ||
354 | scvfLocalIdx, | ||
355 |
2/4✓ Branch 1 taken 75200 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 75200 times.
✗ Branch 5 not taken.
|
1715864 | geometryHelper.isOverlappingScvf(scvfLocalIdx) |
356 | ); | ||
357 | } | ||
358 | |||
359 | // construct the sub control volume faces on the domain boundary | ||
360 |
7/9✓ Branch 2 taken 174566 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 91746 times.
✓ Branch 6 taken 132420 times.
✓ Branch 7 taken 392704 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 18358 times.
✓ Branch 10 taken 284186 times.
✓ Branch 1 taken 33101 times.
|
1305696 | for (const auto& intersection : intersections(this->gridView(), element)) |
361 | { | ||
362 |
3/4✓ Branch 0 taken 7452 times.
✓ Branch 1 taken 119840 times.
✓ Branch 2 taken 580 times.
✗ Branch 3 not taken.
|
127872 | if (intersection.boundary() && !intersection.neighbor()) |
363 | { | ||
364 |
1/2✓ Branch 1 taken 5866 times.
✗ Branch 2 not taken.
|
7452 | cache_.hasBoundaryScvf_[eIdx] = true; |
365 | |||
366 | 7452 | const auto localFacetIndex = intersection.indexInInside(); | |
367 |
2/4✓ Branch 1 taken 5866 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 5286 times.
✗ Branch 5 not taken.
|
7452 | const auto numBoundaryScvf = GeometryHelper::numBoundaryScvf(elementGeometry.type(), localFacetIndex); |
368 | 7452 | numScvf_ += numBoundaryScvf; | |
369 | 7452 | numBoundaryScvf_ += numBoundaryScvf; | |
370 | |||
371 |
2/2✓ Branch 0 taken 17430 times.
✓ Branch 1 taken 7452 times.
|
24882 | for (unsigned int isScvfLocalIdx = 0; isScvfLocalIdx < numBoundaryScvf; ++isScvfLocalIdx) |
372 | { | ||
373 | // find the scvs this scvf is belonging to | ||
374 |
1/2✓ Branch 1 taken 14246 times.
✗ Branch 2 not taken.
|
17430 | const auto scvPair = geometryHelper.getScvPairForBoundaryScvf(localFacetIndex, isScvfLocalIdx); |
375 |
1/2✓ Branch 1 taken 14246 times.
✗ Branch 2 not taken.
|
17430 | const auto corners = geometryHelper.getBoundaryScvfCorners(localFacetIndex, isScvfLocalIdx); |
376 | 17430 | const auto area = Dumux::convexPolytopeVolume<dim-1>( | |
377 | geometryHelper.getBoundaryScvfGeometryType(isScvfLocalIdx), | ||
378 | 42426 | [&](unsigned int i){ return corners[i]; } | |
379 | ); | ||
380 |
3/5✓ Branch 1 taken 14678 times.
✓ Branch 2 taken 2752 times.
✓ Branch 4 taken 5544 times.
✗ Branch 5 not taken.
✗ Branch 3 not taken.
|
17430 | cache_.scvfs_[eIdx].emplace_back( |
381 | 34860 | Dumux::center(corners), | |
382 | area, | ||
383 |
1/2✓ Branch 1 taken 14246 times.
✗ Branch 2 not taken.
|
17430 | intersection.centerUnitOuterNormal(), |
384 | std::move(scvPair), | ||
385 | scvfLocalIdx, | ||
386 | typename SubControlVolumeFace::Traits::BoundaryFlag{ intersection }, | ||
387 |
1/2✓ Branch 1 taken 13086 times.
✗ Branch 2 not taken.
|
17430 | geometryHelper.isOverlappingBoundaryScvf(localFacetIndex) |
388 | ); | ||
389 | |||
390 | // store look-up map to construct boundary scvf geometries | ||
391 |
2/4✓ Branch 1 taken 14246 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 14246 times.
✗ Branch 5 not taken.
|
17430 | cache_.scvfBoundaryGeometryKeys_[eIdx].emplace_back(std::array<LocalIndexType, 2>{{ |
392 | static_cast<LocalIndexType>(localFacetIndex), | ||
393 | static_cast<LocalIndexType>(isScvfLocalIdx) | ||
394 | }}); | ||
395 | |||
396 | // increment local counter | ||
397 | 17430 | scvfLocalIdx++; | |
398 | } | ||
399 | |||
400 | // TODO also move this to helper class | ||
401 | // add all vertices on the intersection to the set of boundary vertices | ||
402 |
2/2✓ Branch 0 taken 17430 times.
✓ Branch 1 taken 7452 times.
|
24882 | for (int localVIdx = 0; localVIdx < numBoundaryScvf; ++localVIdx) |
403 | { | ||
404 | 17430 | const auto vIdx = refElement.subEntity(localFacetIndex, 1, localVIdx, dim); | |
405 |
1/2✓ Branch 1 taken 14246 times.
✗ Branch 2 not taken.
|
17430 | const auto vIdxGlobal = this->dofMapper().subIndex(element, vIdx, dim); |
406 | 17430 | boundaryDofIndices_[vIdxGlobal] = true; | |
407 | } | ||
408 | } | ||
409 | |||
410 | // inform the grid geometry if we have periodic boundaries | ||
411 |
1/2✓ Branch 1 taken 340144 times.
✗ Branch 2 not taken.
|
424550 | else if (periodicGridTraits_.isPeriodic(intersection)) |
412 | { | ||
413 | this->setPeriodic(); | ||
414 | |||
415 | // find the mapped periodic vertex of all vertices on periodic boundaries | ||
416 | const auto fIdx = intersection.indexInInside(); | ||
417 | const auto numFaceVerts = refElement.size(fIdx, 1, dim); | ||
418 | const auto eps = 1e-7*(elementGeometry.corner(1) - elementGeometry.corner(0)).two_norm(); | ||
419 | for (int localVIdx = 0; localVIdx < numFaceVerts; ++localVIdx) | ||
420 | { | ||
421 | const auto vIdx = refElement.subEntity(fIdx, 1, localVIdx, dim); | ||
422 | const auto vIdxGlobal = this->dofMapper().subIndex(element, vIdx, dim); | ||
423 | const auto vPos = elementGeometry.corner(vIdx); | ||
424 | |||
425 | const auto& outside = intersection.outside(); | ||
426 | const auto outsideGeometry = outside.geometry(); | ||
427 | for (const auto& isOutside : intersections(this->gridView(), outside)) | ||
428 | { | ||
429 | // only check periodic vertices of the periodic neighbor | ||
430 | if (periodicGridTraits_.isPeriodic(isOutside)) | ||
431 | { | ||
432 | const auto fIdxOutside = isOutside.indexInInside(); | ||
433 | const auto numFaceVertsOutside = refElement.size(fIdxOutside, 1, dim); | ||
434 | for (int localVIdxOutside = 0; localVIdxOutside < numFaceVertsOutside; ++localVIdxOutside) | ||
435 | { | ||
436 | const auto vIdxOutside = refElement.subEntity(fIdxOutside, 1, localVIdxOutside, dim); | ||
437 | const auto vPosOutside = outsideGeometry.corner(vIdxOutside); | ||
438 | const auto shift = std::abs((this->bBoxMax()-this->bBoxMin())*intersection.centerUnitOuterNormal()); | ||
439 | if (std::abs((vPosOutside-vPos).two_norm() - shift) < eps) | ||
440 | periodicDofMap_[vIdxGlobal] = this->dofMapper().subIndex(outside, vIdxOutside, dim); | ||
441 | } | ||
442 | } | ||
443 | } | ||
444 | } | ||
445 | } | ||
446 | } | ||
447 | } | ||
448 | |||
449 | // error check: periodic boundaries currently don't work for pq1bubble in parallel | ||
450 |
1/6✗ Branch 0 not taken.
✓ Branch 1 taken 14 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
|
14 | if (this->isPeriodic() && this->gridView().comm().size() > 1) |
451 | ✗ | DUNE_THROW(Dune::NotImplemented, "Periodic boundaries for pq1bubble method for parallel simulations!"); | |
452 | 14 | } | |
453 | |||
454 | DofMapper dofMapper_; | ||
455 | |||
456 | const FeCache feCache_; | ||
457 | |||
458 | std::size_t numScv_; | ||
459 | std::size_t numScvf_; | ||
460 | std::size_t numBoundaryScvf_; | ||
461 | |||
462 | // vertices on the boundary | ||
463 | std::vector<bool> boundaryDofIndices_; | ||
464 | |||
465 | // a map for periodic boundary vertices | ||
466 | std::unordered_map<GridIndexType, GridIndexType> periodicDofMap_; | ||
467 | |||
468 | Cache cache_; | ||
469 | |||
470 | PeriodicGridTraits<typename GridView::Grid> periodicGridTraits_; | ||
471 | }; | ||
472 | |||
473 | } // end namespace Dumux | ||
474 | |||
475 | #endif | ||
476 |