GCC Code Coverage Report


Directory: ../../../builds/dumux-repositories/
File: dumux/dumux/discretization/cellcentered/mpfa/elementfluxvariablescache.hh
Date: 2025-04-12 19:19:20
Exec Total Coverage
Lines: 164 166 98.8%
Functions: 135 136 99.3%
Branches: 147 191 77.0%

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 CCMpfaDiscretization
10 * \brief The element-local object of flux variables caches
11 */
12 #ifndef DUMUX_DISCRETIZATION_CCMPFA_ELEMENT_FLUXVARSCACHE_HH
13 #define DUMUX_DISCRETIZATION_CCMPFA_ELEMENT_FLUXVARSCACHE_HH
14
15 #include <algorithm>
16 #include <cassert>
17 #include <type_traits>
18 #include <vector>
19 #include <utility>
20
21 #include <dune/common/exceptions.hh>
22
23 namespace Dumux {
24
25 /*!
26 * \ingroup CCMpfaDiscretization
27 * \brief Structure to store interaction volumes and data handles
28 */
29 template<class PrimaryIV, class PrimaryIVDataHandle,
30 class SecondaryIV, class SecondaryIVDataHandle>
31
7/14
✓ Branch 1 taken 30228 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 7749299 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 236038 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 5784 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 50000 times.
✗ Branch 14 not taken.
✓ Branch 16 taken 964000 times.
✗ Branch 17 not taken.
✓ Branch 19 taken 100 times.
✗ Branch 20 not taken.
9035449 struct InteractionVolumeDataStorage
32 {
33 std::vector<PrimaryIV> primaryInteractionVolumes;
34 std::vector<SecondaryIV> secondaryInteractionVolumes;
35
36 std::vector<PrimaryIVDataHandle> primaryDataHandles;
37 std::vector<SecondaryIVDataHandle> secondaryDataHandles;
38 };
39
40 /*!
41 * \ingroup CCMpfaDiscretization
42 * \brief The flux variables caches for an element
43 * \note The class is specialized for a version with and without caching.
44 * If grid caching is enabled the flux caches are stored for the whole
45 * gridview in the corresponding GridFluxVariablesCache. This is memory
46 * intensive but faster. For caching disabled, the flux caches are locally
47 * computed for each element whenever needed.
48 */
49 template<class GFVC, bool cachingEnabled>
50 class CCMpfaElementFluxVariablesCache;
51
52 /*!
53 * \ingroup CCMpfaDiscretization
54 * \brief The flux variables caches for an element with caching enabled
55 */
56 template<class GFVC>
57
2/4
✓ Branch 5 taken 6919380 times.
✗ Branch 6 not taken.
✓ Branch 9 taken 13056 times.
✗ Branch 10 not taken.
18932928 class CCMpfaElementFluxVariablesCache<GFVC, true>
58 {
59 public:
60 //! export the interaction volume types
61 using PrimaryInteractionVolume = typename GFVC::PrimaryInteractionVolume;
62 using SecondaryInteractionVolume = typename GFVC::SecondaryInteractionVolume;
63
64 //! export the data handle types used
65 using PrimaryIvDataHandle = typename GFVC::PrimaryIvDataHandle;
66 using SecondaryIvDataHandle = typename GFVC::SecondaryIvDataHandle;
67
68 //! export the flux variable cache type
69 using FluxVariablesCache = typename GFVC::FluxVariablesCache;
70
71 //! make it possible to query if caching is enabled
72 static constexpr bool cachingEnabled = true;
73
74 //! export the type of the grid flux variables
75 using GridFluxVariablesCache = GFVC;
76
77 private:
78 //! the flux variable cache filler type
79 using FluxVariablesCacheFiller = typename GFVC::Traits::FluxVariablesCacheFiller;
80
81 //! Class to store the flux variables caches related to boundary interaction volumes
82 6959936 class BoundaryCacheData
83 {
84 // allow the element flux variables class access to private members
85 friend CCMpfaElementFluxVariablesCache<GFVC, true>;
86
87 public:
88 //! access operators
89 template<class SubControlVolumeFace>
90 17069786 const FluxVariablesCache& operator [](const SubControlVolumeFace& scvf) const
91 17069786 { return fluxVarCaches_[getLocalIdx_(scvf.index())]; }
92
93 template<class SubControlVolumeFace>
94 26142576 FluxVariablesCache& operator [](const SubControlVolumeFace& scvf)
95
7/7
✓ Branch 1 taken 2870520 times.
✓ Branch 2 taken 5559464 times.
✓ Branch 3 taken 1546071 times.
✓ Branch 4 taken 5674371 times.
✓ Branch 5 taken 812485 times.
✓ Branch 6 taken 4389225 times.
✓ Branch 0 taken 8112 times.
26142576 { return fluxVarCaches_[getLocalIdx_(scvf.index())]; }
96
97 //! clear all containers
98 6959936 void clear()
99 {
100
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6959936 times.
6959936 fluxVarCaches_.clear();
101
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6959936 times.
6959936 cacheScvfIndices_.clear();
102
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6959936 times.
6959936 ivDataStorage_.primaryInteractionVolumes.clear();
103
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6959936 times.
6959936 ivDataStorage_.secondaryInteractionVolumes.clear();
104
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6959936 times.
6959936 ivDataStorage_.primaryDataHandles.clear();
105
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6959936 times.
6959936 ivDataStorage_.secondaryDataHandles.clear();
106 6959936 }
107
108 private:
109 //! map a global scvf index to the local storage index
110 43212362 int getLocalIdx_(const int scvfIdx) const
111 {
112
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 43212362 times.
43212362 auto it = std::find(cacheScvfIndices_.begin(), cacheScvfIndices_.end(), scvfIdx);
113
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 43212362 times.
43212362 assert(it != cacheScvfIndices_.end() && "Could not find the local idx for the given scvf idx!");
114 43212362 return std::distance(cacheScvfIndices_.begin(), it);
115 }
116
117 std::vector<std::size_t> cacheScvfIndices_;
118 std::vector<FluxVariablesCache> fluxVarCaches_;
119
120 // stored boundary interaction volumes and handles
121 using IVDataStorage = InteractionVolumeDataStorage<PrimaryInteractionVolume,
122 PrimaryIvDataHandle,
123 SecondaryInteractionVolume,
124 SecondaryIvDataHandle>;
125 IVDataStorage ivDataStorage_;
126 };
127
128 public:
129 //! The constructor
130 6959936 CCMpfaElementFluxVariablesCache(const GridFluxVariablesCache& global)
131
2/4
✓ Branch 1 taken 27500 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 6932436 times.
✗ Branch 5 not taken.
6959936 : gridFluxVarsCachePtr_(&global)
132 {}
133
134 /*!
135 * \brief bind the local view (r-value overload)
136 * This overload is called when an instance of this class is a temporary in the usage context
137 * This allows a usage like this: `const auto view = localView(...).bind(element);`
138 */
139 template<class FVElementGeometry, class ElementVolumeVariables>
140 CCMpfaElementFluxVariablesCache bindElement(const typename FVElementGeometry::GridGeometry::GridView::template Codim<0>::Entity& element,
141 const FVElementGeometry& fvGeometry,
142 const ElementVolumeVariables& elemVolVars) &&
143 {
144 this->bindElement_(element, fvGeometry, elemVolVars);
145 return std::move(*this);
146 }
147
148 //! Specialization for the global caching being enabled - do nothing here
149 template<class FVElementGeometry, class ElementVolumeVariables>
150 void bindElement(const typename FVElementGeometry::GridGeometry::GridView::template Codim<0>::Entity& element,
151 const FVElementGeometry& fvGeometry,
152 const ElementVolumeVariables& elemVolVars) &
153 { this->bindElement_(element, fvGeometry, elemVolVars); }
154
155 /*!
156 * \brief bind the local view (r-value overload)
157 * This overload is called when an instance of this class is a temporary in the usage context
158 * This allows a usage like this: `const auto view = localView(...).bind(element);`
159 */
160 template<class FVElementGeometry, class ElementVolumeVariables>
161 27500 CCMpfaElementFluxVariablesCache bind(const typename FVElementGeometry::GridGeometry::GridView::template Codim<0>::Entity& element,
162 const FVElementGeometry& fvGeometry,
163 const ElementVolumeVariables& elemVolVars) &&
164 {
165
1/2
✓ Branch 1 taken 27500 times.
✗ Branch 2 not taken.
27500 this->bind_(element, fvGeometry, elemVolVars);
166 27500 return std::move(*this);
167 }
168
169 //! Specialization for the global caching being enabled - do nothing here
170 template<class FVElementGeometry, class ElementVolumeVariables>
171 6932436 void bind(const typename FVElementGeometry::GridGeometry::GridView::template Codim<0>::Entity& element,
172 const FVElementGeometry& fvGeometry,
173 const ElementVolumeVariables& elemVolVars) &
174 6932436 { this->bind_(element, fvGeometry, elemVolVars); }
175
176 /*!
177 * \brief bind the local view (r-value overload)
178 * This overload is called when an instance of this class is a temporary in the usage context
179 * This allows a usage like this: `const auto view = localView(...).bind(element);`
180 */
181 template<class FVElementGeometry, class ElementVolumeVariables>
182 CCMpfaElementFluxVariablesCache bindScvf(const typename FVElementGeometry::GridGeometry::GridView::template Codim<0>::Entity& element,
183 const FVElementGeometry& fvGeometry,
184 const ElementVolumeVariables& elemVolVars,
185 const typename FVElementGeometry::SubControlVolumeFace& scvf) &&
186 {
187 this->bindScvf_(element, fvGeometry, elemVolVars, scvf);
188 return std::move(*this);
189 }
190
191 //! Specialization for the global caching being enabled - do nothing here
192 template<class FVElementGeometry, class ElementVolumeVariables>
193 void bindScvf(const typename FVElementGeometry::GridGeometry::GridView::template Codim<0>::Entity& element,
194 const FVElementGeometry& fvGeometry,
195 const ElementVolumeVariables& elemVolVars,
196 const typename FVElementGeometry::SubControlVolumeFace& scvf) &
197 { this->bindScvf_(element, fvGeometry, elemVolVars, scvf); }
198
199 //! Specialization for the global caching being enabled - do nothing here
200 template<class FVElementGeometry, class ElementVolumeVariables>
201 3820714 void update(const typename FVElementGeometry::GridGeometry::GridView::template Codim<0>::Entity& element,
202 const FVElementGeometry& fvGeometry,
203 const ElementVolumeVariables& elemVolVars)
204 {
205 // Update only if the filler puts solution-dependent stuff into the caches
206 if (FluxVariablesCacheFiller::isSolDependent)
207 {
208 // helper class to fill flux variables caches
209 3820714 FluxVariablesCacheFiller filler(gridFluxVarsCachePtr_->problem());
210
211 // first, set all the caches to "outdated"
212
2/2
✓ Branch 0 taken 6661014 times.
✓ Branch 1 taken 3820714 times.
10481728 for (auto& cache : boundaryCacheData_.fluxVarCaches_)
213 6661014 cache.setUpdateStatus(false);
214
215 // go through the caches maybe update them
216
2/2
✓ Branch 0 taken 6661014 times.
✓ Branch 1 taken 3820714 times.
10481728 for (auto scvfIdx : boundaryCacheData_.cacheScvfIndices_)
217 {
218 6661014 const auto& scvf = fvGeometry.scvf(scvfIdx);
219
2/2
✓ Branch 1 taken 1154829 times.
✓ Branch 2 taken 5506185 times.
6661014 auto& scvfCache = boundaryCacheData_[scvf];
220
2/2
✓ Branch 0 taken 1154829 times.
✓ Branch 1 taken 5506185 times.
6661014 if (!scvfCache.isUpdated())
221 1154829 filler.fill(boundaryCacheData_, scvfCache, boundaryCacheData_.ivDataStorage_,
222 fvGeometry, elemVolVars, scvf);
223 }
224 }
225 3820714 }
226
227 //! access operators in the case of caching
228 template<class SubControlVolumeFace>
229 542643342 const FluxVariablesCache& operator [](const SubControlVolumeFace& scvf) const
230
2/2
✓ Branch 0 taken 525573556 times.
✓ Branch 1 taken 17069786 times.
542643342 { return !isEmbeddedInBoundaryIV_(scvf) ? (*gridFluxVarsCachePtr_)[scvf] : boundaryCacheData_[scvf]; }
231
232 //! access to the interaction volume an scvf is embedded in
233 template<class SubControlVolumeFace>
234 const PrimaryInteractionVolume& primaryInteractionVolume(const SubControlVolumeFace& scvf) const
235 {
236 return isEmbeddedInBoundaryIV_(scvf)
237 ? boundaryCacheData_.ivDataStorage_.primaryInteractionVolumes[ (*this)[scvf].ivIndexInContainer() ]
238 : gridFluxVarsCachePtr_->primaryInteractionVolume(scvf);
239 }
240
241 //! access to the data handle of an interaction volume an scvf is embedded in
242 template<class SubControlVolumeFace>
243 const PrimaryIvDataHandle& primaryDataHandle(const SubControlVolumeFace& scvf) const
244 {
245 return isEmbeddedInBoundaryIV_(scvf)
246 ? boundaryCacheData_.ivDataStorage_.primaryDataHandles[ (*this)[scvf].ivIndexInContainer() ]
247 : gridFluxVarsCachePtr_->primaryDataHandle(scvf);
248 }
249
250 //! access to the interaction volume an scvf is embedded in
251 template<class SubControlVolumeFace>
252 const SecondaryInteractionVolume& secondaryInteractionVolume(const SubControlVolumeFace& scvf) const
253 {
254 return isEmbeddedInBoundaryIV_(scvf)
255 ? boundaryCacheData_.ivDataStorage_.secondaryInteractionVolumes[ (*this)[scvf].ivIndexInContainer() ]
256 : gridFluxVarsCachePtr_->secondaryInteractionVolume(scvf);
257 }
258
259 //! access to the data handle of an interaction volume an scvf is embedded in
260 template<class SubControlVolumeFace>
261 const SecondaryIvDataHandle& secondaryDataHandle(const SubControlVolumeFace& scvf) const
262 {
263 return isEmbeddedInBoundaryIV_(scvf)
264 ? boundaryCacheData_.ivDataStorage_.secondaryDataHandles[ (*this)[scvf].ivIndexInContainer() ]
265 : gridFluxVarsCachePtr_->secondaryDataHandle(scvf);
266 }
267
268 //! The global object we are a restriction of
269 const GridFluxVariablesCache& gridFluxVarsCache() const
270 { return *gridFluxVarsCachePtr_; }
271
272 private:
273
274
275 //! Bind the flux var caches for scvfs inside the element only
276 template<class FVElementGeometry, class ElementVolumeVariables>
277 void bindElement_(const typename FVElementGeometry::GridGeometry::GridView::template Codim<0>::Entity& element,
278 const FVElementGeometry& fvGeometry,
279 const ElementVolumeVariables& elemVolVars)
280 { DUNE_THROW(Dune::NotImplemented, "Local element binding of the flux variables cache in mpfa schemes"); }
281
282 //! Specialization for the global caching being enabled - do nothing here
283 template<class FVElementGeometry, class ElementVolumeVariables>
284 6959936 void bind_(const typename FVElementGeometry::GridGeometry::GridView::template Codim<0>::Entity& element,
285 const FVElementGeometry& fvGeometry,
286 const ElementVolumeVariables& elemVolVars)
287 {
288 6959936 boundaryCacheData_.clear();
289
290 // find out how much memory needs to be reserved
291 6959936 std::size_t numPrimaryIv; numPrimaryIv = 0;
292 6959936 std::size_t numSecondaryIv; numSecondaryIv = 0;
293 6959936 std::size_t numCaches; numCaches = 0;
294
295 6959936 const auto& gridGeometry = fvGeometry.gridGeometry();
296 6959936 const auto& gridIvIndexSets = gridGeometry.gridInteractionVolumeIndexSets();
297
298 // lambda to check if a scvf was handled already
299 18430293 auto scvfHandled = [&] (auto idx)
300 {
301 11470357 return std::find(boundaryCacheData_.cacheScvfIndices_.begin(),
302 boundaryCacheData_.cacheScvfIndices_.end(),
303 11470357 idx) != boundaryCacheData_.cacheScvfIndices_.end();
304 };
305
306 // lambda to increase counters for a given scvf
307
2/2
✓ Branch 0 taken 6410274 times.
✓ Branch 1 taken 59820846 times.
73191056 auto handleScvf = [&] (const auto& scvf, const auto& indexSet, bool isSecondary)
308 {
309 66231120 const auto& scvfIndices = indexSet.gridScvfIndices();
310
2/2
✓ Branch 0 taken 6410274 times.
✓ Branch 1 taken 59820846 times.
66231120 if ( indexSet.nodalIndexSet().numBoundaryScvfs() > 0
311
4/4
✓ Branch 0 taken 6410274 times.
✓ Branch 1 taken 59820846 times.
✓ Branch 2 taken 1350191 times.
✓ Branch 3 taken 5060083 times.
66231120 && !std::any_of(scvfIndices.begin(), scvfIndices.end(), scvfHandled) )
312 {
313
2/2
✓ Branch 1 taken 5304 times.
✓ Branch 2 taken 1344887 times.
1350191 boundaryCacheData_.cacheScvfIndices_.insert(boundaryCacheData_.cacheScvfIndices_.end(),
314 scvfIndices.begin(),
315 scvfIndices.end());
316 1350191 numCaches += scvfIndices.size();
317
2/2
✓ Branch 0 taken 5304 times.
✓ Branch 1 taken 1344887 times.
1350191 if (isSecondary) numSecondaryIv++;
318 1344887 else numPrimaryIv++;
319 }
320 };
321
322 // search for ivs at boundary vertices
323
4/4
✓ Branch 0 taken 10608 times.
✓ Branch 1 taken 53101972 times.
✓ Branch 2 taken 7051328 times.
✓ Branch 3 taken 13056 times.
60072516 for (const auto& scvf : scvfs(fvGeometry))
324
2/2
✓ Branch 0 taken 10608 times.
✓ Branch 1 taken 93840 times.
53112580 gridGeometry.vertexUsesSecondaryInteractionVolume(scvf.vertexIndex()) ?
325 10608 handleScvf(scvf, gridIvIndexSets.secondaryIndexSet(scvf), true) :
326 53101972 handleScvf(scvf, gridIvIndexSets.primaryIndexSet(scvf), false) ;
327
328 // skip the rest if there are no boundary caches to be created
329
2/2
✓ Branch 0 taken 727633 times.
✓ Branch 1 taken 6232303 times.
6959936 if (numCaches > 0)
330 {
331 727633 const auto& assemblyMapI = gridGeometry.connectivityMap()[gridGeometry.elementMapper().index(element)];
332
333
2/2
✓ Branch 0 taken 4514083 times.
✓ Branch 1 taken 727633 times.
5241716 for (const auto& dataJ : assemblyMapI)
334 {
335
2/2
✓ Branch 0 taken 13118540 times.
✓ Branch 1 taken 4514083 times.
17632623 for (const auto& scvfJIdx : dataJ.scvfsJ)
336 {
337
2/2
✓ Branch 0 taken 10336 times.
✓ Branch 1 taken 30192 times.
13118540 const auto& scvfJ = fvGeometry.scvf(scvfJIdx);
338
2/2
✓ Branch 0 taken 10336 times.
✓ Branch 1 taken 30192 times.
13118540 if (gridGeometry.vertexUsesSecondaryInteractionVolume(scvfJ.vertexIndex()))
339 10336 handleScvf(scvfJ, gridIvIndexSets.secondaryIndexSet(scvfJ), true);
340 else
341 13108204 handleScvf(scvfJ, gridIvIndexSets.primaryIndexSet(scvfJ), false);
342 }
343 }
344
345 // now prepare the caches of all scvfs that have been found to be handled
346 727633 boundaryCacheData_.ivDataStorage_.primaryInteractionVolumes.reserve(numPrimaryIv);
347 727633 boundaryCacheData_.ivDataStorage_.secondaryInteractionVolumes.reserve(numSecondaryIv);
348 727633 boundaryCacheData_.ivDataStorage_.primaryDataHandles.reserve(numPrimaryIv);
349 727633 boundaryCacheData_.ivDataStorage_.secondaryDataHandles.reserve(numSecondaryIv);
350
351 727633 boundaryCacheData_.fluxVarCaches_.resize(numCaches);
352
2/2
✓ Branch 0 taken 6410274 times.
✓ Branch 1 taken 727633 times.
7137907 for (auto& cache : boundaryCacheData_.fluxVarCaches_)
353 6410274 cache.setUpdateStatus(false);
354
355 727633 FluxVariablesCacheFiller filler(gridFluxVarsCachePtr_->problem());
356
2/2
✓ Branch 0 taken 6410274 times.
✓ Branch 1 taken 727633 times.
7137907 for (auto scvfIdx : boundaryCacheData_.cacheScvfIndices_)
357 {
358 6410274 const auto& scvf = fvGeometry.scvf(scvfIdx);
359
2/2
✓ Branch 1 taken 1350191 times.
✓ Branch 2 taken 5060083 times.
6410274 auto& cache = boundaryCacheData_[scvf];
360
2/2
✓ Branch 0 taken 1350191 times.
✓ Branch 1 taken 5060083 times.
6410274 if (!cache.isUpdated())
361 1350191 filler.fill(boundaryCacheData_, cache, boundaryCacheData_.ivDataStorage_,
362 fvGeometry, elemVolVars, scvf, /*forceUpdate*/true);
363 }
364 }
365 6959936 }
366
367 //! Bind the flux var caches for an individual scvf
368 template<class FVElementGeometry, class ElementVolumeVariables>
369 void bindScvf_(const typename FVElementGeometry::GridGeometry::GridView::template Codim<0>::Entity& element,
370 const FVElementGeometry& fvGeometry,
371 const ElementVolumeVariables& elemVolVars,
372 const typename FVElementGeometry::SubControlVolumeFace& scvf)
373 { DUNE_THROW(Dune::NotImplemented, "Scvf-local binding of the flux variables cache in mpfa schemes"); }
374
375 //! returns true if an scvf is contained in an interaction volume that touches the boundary
376 template<class SubControlVolumeFace>
377 542643342 bool isEmbeddedInBoundaryIV_(const SubControlVolumeFace& scvf) const
378 {
379
2/2
✓ Branch 0 taken 522160836 times.
✓ Branch 1 taken 20482506 times.
542643342 const auto& gridGeometry = gridFluxVarsCachePtr_->problem().gridGeometry();
380
2/2
✓ Branch 0 taken 522160836 times.
✓ Branch 1 taken 20482506 times.
542643342 const auto& gridIvIndexSets = gridGeometry.gridInteractionVolumeIndexSets();
381
2/2
✓ Branch 0 taken 120080 times.
✓ Branch 1 taken 3532800 times.
3652880 if (gridGeometry.vertexUsesSecondaryInteractionVolume(scvf.vertexIndex()))
382 120080 return gridIvIndexSets.secondaryIndexSet(scvf).nodalIndexSet().numBoundaryScvfs() > 0;
383 else
384
2/2
✓ Branch 0 taken 522040756 times.
✓ Branch 1 taken 16949706 times.
542523262 return gridIvIndexSets.primaryIndexSet(scvf).nodalIndexSet().numBoundaryScvfs() > 0;
385 }
386
387 const GridFluxVariablesCache* gridFluxVarsCachePtr_;
388
389 // we store those caches that touch the boundary locally here
390 // for the case that the boundary conditions change, which would
391 // leave the grid-wide cache outdated.
392 BoundaryCacheData boundaryCacheData_;
393 };
394
395 /*!
396 * \ingroup CCMpfaDiscretization
397 * \brief The flux variables caches for an element with caching disabled
398 */
399 template<class GFVC>
400 class CCMpfaElementFluxVariablesCache<GFVC, false>
401 {
402 //! the flux variable cache filler type
403 using FluxVariablesCacheFiller = typename GFVC::Traits::FluxVariablesCacheFiller;
404
405 public:
406 //! export the interaction volume types
407 using PrimaryInteractionVolume = typename GFVC::PrimaryInteractionVolume;
408 using SecondaryInteractionVolume = typename GFVC::SecondaryInteractionVolume;
409
410 //! export the data handle types used
411 using PrimaryIvDataHandle = typename GFVC::PrimaryIvDataHandle;
412 using SecondaryIvDataHandle = typename GFVC::SecondaryIvDataHandle;
413
414 //! export the flux variable cache type
415 using FluxVariablesCache = typename GFVC::FluxVariablesCache;
416
417
418 //! make it possible to query if caching is enabled
419 static constexpr bool cachingEnabled = false;
420
421 //! export the type of the grid flux variables
422 using GridFluxVariablesCache = GFVC;
423
424 2075519 CCMpfaElementFluxVariablesCache(const GridFluxVariablesCache& global)
425
8/16
✓ Branch 1 taken 2728 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 816072 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 236832 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 5786 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 50000 times.
✗ Branch 14 not taken.
✓ Branch 16 taken 964000 times.
✗ Branch 17 not taken.
✓ Branch 19 taken 100 times.
✗ Branch 20 not taken.
✓ Branch 22 taken 1 times.
✗ Branch 23 not taken.
2075519 : gridFluxVarsCachePtr_(&global) {}
426
427 /*!
428 * \brief Prepares the transmissibilities of the scv faces in an element
429 * \note the fvGeometry is assumed to be bound to the same element
430 * \note this function has to be called prior to flux calculations on the element.
431 */
432 template<class FVElementGeometry, class ElementVolumeVariables>
433 void bindElement(const typename FVElementGeometry::GridGeometry::GridView::template Codim<0>::Entity& element,
434 const FVElementGeometry& fvGeometry,
435 const ElementVolumeVariables& elemVolVars) &
436 {
437 // For mpfa schemes we will have to prepare the caches of all scvfs that are
438 // embedded in the interaction volumes in which the element-local scvfs are embedded
439 DUNE_THROW(Dune::NotImplemented, "Local element binding of the flux variables cache in mpfa schemes");
440 }
441
442 /*!
443 * \brief bind the local view (r-value overload)
444 * This overload is called when an instance of this class is a temporary in the usage context
445 * This allows a usage like this: `const auto view = localView(...).bind(element);`
446 */
447 template<class FVElementGeometry, class ElementVolumeVariables>
448 CCMpfaElementFluxVariablesCache bindElement(const typename FVElementGeometry::GridGeometry::GridView::template Codim<0>::Entity& element,
449 const FVElementGeometry& fvGeometry,
450 const ElementVolumeVariables& elemVolVars) &&
451 {
452 this->bindElement(element, fvGeometry, elemVolVars);
453 return std::move(*this);
454 }
455
456 /*!
457 * \brief Prepares the transmissibilities of the scv faces in the stencil of an element
458 * \note the fvGeometry is assumed to be bound to the same element
459 * \note this function has to be called prior to flux calculations on the element.
460 */
461 template<class FVElementGeometry, class ElementVolumeVariables>
462 3112089 void bind(const typename FVElementGeometry::GridGeometry::GridView::template Codim<0>::Entity& element,
463 const FVElementGeometry& fvGeometry,
464 const ElementVolumeVariables& elemVolVars) &
465 {
466 3112089 clear_();
467
468 // some references for convenience
469 3112089 const auto& problem = gridFluxVarsCache().problem();
470 3112089 const auto& gridGeometry = fvGeometry.gridGeometry();
471
472 // the assembly map of the given element
473 3112089 const auto& assemblyMapI = gridGeometry.connectivityMap()[gridGeometry.elementMapper().index(element)];
474
475 // reserve memory for scvf index container
476 3112089 unsigned int numNeighborScvfs = 0;
477
2/2
✓ Branch 0 taken 20297855 times.
✓ Branch 1 taken 2089977 times.
35679320 for (const auto& dataJ : assemblyMapI)
478 32567231 numNeighborScvfs += dataJ.scvfsJ.size();
479 3112089 globalScvfIndices_.resize(fvGeometry.numScvf() + numNeighborScvfs);
480
481 // set the scvf indices in scvf index container
482 3112089 unsigned int i = 0;
483
2/2
✓ Branch 0 taken 14672788 times.
✓ Branch 1 taken 2089977 times.
23917549 for (const auto& scvf : scvfs(fvGeometry))
484 20805460 globalScvfIndices_[i++] = scvf.index();
485
2/2
✓ Branch 0 taken 20297855 times.
✓ Branch 1 taken 2089977 times.
35679320 for (const auto& dataJ : assemblyMapI)
486
2/2
✓ Branch 0 taken 54800422 times.
✓ Branch 1 taken 20297855 times.
117968517 for (auto scvfIdx : dataJ.scvfsJ)
487 85401286 globalScvfIndices_[i++] = scvfIdx;
488
489 // Reserve memory (over-) estimate for interaction volumes and corresponding data.
490 // The overestimate doesn't hurt as we are not in a memory-limited configuration.
491 // We need to avoid reallocation because in the caches we store pointers to the data handles.
492 // Default -> each facet has two neighbors (local adaption) and all scvfs belongs to different ivs.
493 // If you want to use higher local differences change the parameter below.
494 3112089 constexpr auto numIvEstimate = FVElementGeometry::maxNumElementScvfs
495 * GridFluxVariablesCache::Traits::maxLocalElementLevelDifference();
496 3112089 ivDataStorage_.primaryInteractionVolumes.reserve(numIvEstimate);
497 3112089 ivDataStorage_.secondaryInteractionVolumes.reserve(numIvEstimate);
498 3112089 ivDataStorage_.primaryDataHandles.reserve(numIvEstimate);
499 3112089 ivDataStorage_.secondaryDataHandles.reserve(numIvEstimate);
500
501 // helper class to fill flux variables caches
502 3112089 FluxVariablesCacheFiller filler(problem);
503
504 // resize the cache container
505 3112089 fluxVarsCache_.resize(globalScvfIndices_.size());
506
507 // go through the caches and fill them
508 3112089 i = 0;
509
2/2
✓ Branch 0 taken 14672788 times.
✓ Branch 1 taken 2089977 times.
23917549 for (const auto& scvf : scvfs(fvGeometry))
510 {
511
2/2
✓ Branch 0 taken 7336394 times.
✓ Branch 1 taken 7336394 times.
20805460 auto& scvfCache = fluxVarsCache_[i++];
512
2/2
✓ Branch 0 taken 7336394 times.
✓ Branch 1 taken 7336394 times.
20805460 if (!scvfCache.isUpdated())
513 10402730 filler.fill(*this, scvfCache, ivDataStorage_, fvGeometry, elemVolVars, scvf, true);
514 }
515
516
2/2
✓ Branch 0 taken 20297855 times.
✓ Branch 1 taken 2089977 times.
35679320 for (const auto& dataJ : assemblyMapI)
517 {
518
2/2
✓ Branch 0 taken 54800422 times.
✓ Branch 1 taken 20297855 times.
117968517 for (const auto scvfIdx : dataJ.scvfsJ)
519 {
520
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 54800422 times.
85401286 auto& scvfCache = fluxVarsCache_[i++];
521
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 54800422 times.
85401286 if (!scvfCache.isUpdated())
522 filler.fill(*this, scvfCache, ivDataStorage_, fvGeometry, elemVolVars, fvGeometry.scvf(scvfIdx), true);
523 }
524 }
525 3112089 }
526
527 /*!
528 * \brief bind the local view (r-value overload)
529 * This overload is called when an instance of this class is a temporary in the usage context
530 * This allows a usage like this: `const auto view = localView(...).bind(element);`
531 */
532 template<class FVElementGeometry, class ElementVolumeVariables>
533 57101 CCMpfaElementFluxVariablesCache bind(const typename FVElementGeometry::GridGeometry::GridView::template Codim<0>::Entity& element,
534 const FVElementGeometry& fvGeometry,
535 const ElementVolumeVariables& elemVolVars) &&
536 {
537
5/10
✓ Branch 1 taken 2728 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 3973 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 300 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 50000 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 100 times.
✗ Branch 14 not taken.
57101 this->bind(element, fvGeometry, elemVolVars);
538 57101 return std::move(*this);
539 }
540
541 /*!
542 * \brief Prepares the transmissibilities of a single scv face
543 * \note the fvGeometry is assumed to be bound to the same element
544 * \note this function has to be called prior to flux calculations on this scvf.
545 */
546 template<class FVElementGeometry, class ElementVolumeVariables>
547 void bindScvf(const typename FVElementGeometry::GridGeometry::GridView::template Codim<0>::Entity& element,
548 const FVElementGeometry& fvGeometry,
549 const ElementVolumeVariables& elemVolVars,
550 const typename FVElementGeometry::SubControlVolumeFace& scvf) &
551 {
552 // For mpfa schemes we will have to prepare the caches of all
553 // scvfs that are embedded in the interaction volumes this scvf is embedded
554 DUNE_THROW(Dune::NotImplemented, "Scvf-local binding of the flux variables cache in mpfa schemes");
555 }
556
557 /*!
558 * \brief bind the local view (r-value overload)
559 * This overload is called when an instance of this class is a temporary in the usage context
560 * This allows a usage like this: `const auto view = localView(...).bind(element);`
561 */
562 template<class FVElementGeometry, class ElementVolumeVariables>
563 CCMpfaElementFluxVariablesCache bindScvf(const typename FVElementGeometry::GridGeometry::GridView::template Codim<0>::Entity& element,
564 const FVElementGeometry& fvGeometry,
565 const ElementVolumeVariables& elemVolVars,
566 const typename FVElementGeometry::SubControlVolumeFace& scvf) &&
567 {
568 this->bindScvf(element, fvGeometry, elemVolVars, scvf);
569 return std::move(*this);
570 }
571
572 /*!
573 * \brief Update the transmissibilities if the volume variables have changed
574 * \note Results in undefined behaviour if called before bind() or with a different element
575 */
576 template<class FVElementGeometry, class ElementVolumeVariables>
577 2616872 void update(const typename FVElementGeometry::GridGeometry::GridView::template Codim<0>::Entity& element,
578 const FVElementGeometry& fvGeometry,
579 const ElementVolumeVariables& elemVolVars)
580 {
581 // Update only if the filler puts
582 // solution-dependent stuff into the caches
583 if (FluxVariablesCacheFiller::isSolDependent)
584 {
585 2616872 const auto& problem = gridFluxVarsCache().problem();
586 2616872 const auto& gridGeometry = fvGeometry.gridGeometry();
587 2616872 const auto& assemblyMapI = gridGeometry.connectivityMap()[gridGeometry.elementMapper().index(element)];
588
589 // helper class to fill flux variables caches
590 2616872 FluxVariablesCacheFiller filler(problem);
591
592 // set all the caches to "outdated"
593
2/2
✓ Branch 0 taken 80279720 times.
✓ Branch 1 taken 2616872 times.
82896592 for (auto& cache : fluxVarsCache_)
594 80279720 cache.setUpdateStatus(false);
595
596 // go through the caches maybe update them
597 2616872 unsigned int i = 0;
598
2/2
✓ Branch 0 taken 20879432 times.
✓ Branch 1 taken 2616872 times.
23496304 for (const auto& scvf : scvfs(fvGeometry))
599 {
600
2/2
✓ Branch 0 taken 10439716 times.
✓ Branch 1 taken 10439716 times.
20879432 auto& scvfCache = fluxVarsCache_[i++];
601
2/2
✓ Branch 0 taken 10439716 times.
✓ Branch 1 taken 10439716 times.
20879432 if (!scvfCache.isUpdated())
602 10439716 filler.fill(*this, scvfCache, ivDataStorage_, fvGeometry, elemVolVars, scvf);
603 }
604
605
2/2
✓ Branch 0 taken 19749236 times.
✓ Branch 1 taken 2616872 times.
22366108 for (const auto& dataJ : assemblyMapI)
606 {
607
2/2
✓ Branch 0 taken 59400288 times.
✓ Branch 1 taken 19749236 times.
79149524 for (const auto scvfIdx : dataJ.scvfsJ)
608 {
609
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 59400288 times.
59400288 auto& scvfCache = fluxVarsCache_[i++];
610
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 59400288 times.
59400288 if (!scvfCache.isUpdated())
611 filler.fill(*this, scvfCache, ivDataStorage_, fvGeometry, elemVolVars, fvGeometry.scvf(scvfIdx));
612 }
613 }
614 }
615 2616872 }
616
617 //! access operators in the case of no caching
618 template<class SubControlVolumeFace, typename std::enable_if_t<!std::is_integral<SubControlVolumeFace>::value, int> = 0>
619 310602143 const FluxVariablesCache& operator [](const SubControlVolumeFace& scvf) const
620
3/4
✓ Branch 1 taken 60161 times.
✓ Branch 2 taken 1766400 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 2000 times.
310602143 { return fluxVarsCache_[getLocalScvfIdx_(scvf.index())]; }
621
622 //! access operators in the case of no caching
623 const FluxVariablesCache& operator [](const std::size_t scvfIdx) const
624 { return fluxVarsCache_[getLocalScvfIdx_(scvfIdx)]; }
625
626 //! access operators in the case of no caching
627 template<class SubControlVolumeFace, typename std::enable_if_t<!std::is_integral<SubControlVolumeFace>::value, int> = 0>
628 149752930 FluxVariablesCache& operator [](const SubControlVolumeFace& scvf)
629
2/2
✓ Branch 1 taken 10556546 times.
✓ Branch 2 taken 12251646 times.
149752930 { return fluxVarsCache_[getLocalScvfIdx_(scvf.index())]; }
630
631 //! access operators in the case of no caching
632 FluxVariablesCache& operator [](const std::size_t scvfIdx)
633 { return fluxVarsCache_[getLocalScvfIdx_(scvfIdx)]; }
634
635 //! access to the interaction volume an scvf is embedded in
636 template<class SubControlVolumeFace>
637 121 const PrimaryInteractionVolume& primaryInteractionVolume(const SubControlVolumeFace& scvf) const
638
1/2
✓ Branch 2 taken 121 times.
✗ Branch 3 not taken.
121 { return ivDataStorage_.primaryInteractionVolumes[ (*this)[scvf].ivIndexInContainer() ]; }
639
640 //! access to the data handle of an interaction volume an scvf is embedded in
641 template<class SubControlVolumeFace>
642 121 const PrimaryIvDataHandle& primaryDataHandle(const SubControlVolumeFace& scvf) const
643
1/2
✓ Branch 1 taken 121 times.
✗ Branch 2 not taken.
121 { return ivDataStorage_.primaryDataHandles[ (*this)[scvf].ivIndexInContainer() ]; }
644
645 //! access to the interaction volume an scvf is embedded in
646 template<class SubControlVolumeFace>
647 const SecondaryInteractionVolume& secondaryInteractionVolume(const SubControlVolumeFace& scvf) const
648 { return ivDataStorage_.secondaryInteractionVolumes[ (*this)[scvf].ivIndexInContainer() ]; }
649
650 //! access to the data handle of an interaction volume an scvf is embedded in
651 template<class SubControlVolumeFace>
652 const SecondaryIvDataHandle& secondaryDataHandle(const SubControlVolumeFace& scvf) const
653 { return ivDataStorage_.secondaryDataHandles[ (*this)[scvf].ivIndexInContainer() ]; }
654
655 //! The global object we are a restriction of
656 4706849 const GridFluxVariablesCache& gridFluxVarsCache() const
657 4706849 { return *gridFluxVarsCachePtr_; }
658
659 private:
660 const GridFluxVariablesCache* gridFluxVarsCachePtr_;
661
662 //! clears all containers
663 3112089 void clear_()
664 {
665
2/2
✓ Branch 0 taken 14458 times.
✓ Branch 1 taken 2075519 times.
3112089 fluxVarsCache_.clear();
666
2/2
✓ Branch 0 taken 14458 times.
✓ Branch 1 taken 2075519 times.
3112089 globalScvfIndices_.clear();
667
2/2
✓ Branch 0 taken 14458 times.
✓ Branch 1 taken 2075519 times.
3112089 ivDataStorage_.primaryInteractionVolumes.clear();
668
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2089977 times.
3112089 ivDataStorage_.secondaryInteractionVolumes.clear();
669
2/2
✓ Branch 0 taken 14458 times.
✓ Branch 1 taken 2075519 times.
3112089 ivDataStorage_.primaryDataHandles.clear();
670
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2089977 times.
3112089 ivDataStorage_.secondaryDataHandles.clear();
671 3112089 }
672
673 //! get index of an scvf in the local container
674 460355073 unsigned int getLocalScvfIdx_(const int scvfIdx) const
675 {
676
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 422206297 times.
460355073 auto it = std::find(globalScvfIndices_.begin(), globalScvfIndices_.end(), scvfIdx);
677
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 422206297 times.
460355073 assert(it != globalScvfIndices_.end() && "Could not find the flux vars cache for scvfIdx");
678 460355073 return std::distance(globalScvfIndices_.begin(), it);
679 }
680
681 // the local flux vars caches and corresponding indices
682 std::vector<FluxVariablesCache> fluxVarsCache_;
683 std::vector<std::size_t> globalScvfIndices_;
684
685 // stored interaction volumes and handles
686 using IVDataStorage = InteractionVolumeDataStorage<PrimaryInteractionVolume,
687 PrimaryIvDataHandle,
688 SecondaryInteractionVolume,
689 SecondaryIvDataHandle>;
690 IVDataStorage ivDataStorage_;
691 };
692
693 } // end namespace
694
695 #endif
696