GCC Code Coverage Report


Directory: ../../../builds/dumux-repositories/
File: dumux/dumux/flux/ccmpfa/fickslaw.hh
Date: 2025-04-12 19:19:20
Exec Total Coverage
Lines: 61 61 100.0%
Functions: 41 41 100.0%
Branches: 34 36 94.4%

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 CCMpfaFlux
10 * \brief Fick's law for cell-centered finite volume schemes with multi-point flux approximation
11 */
12 #ifndef DUMUX_DISCRETIZATION_CC_MPFA_FICKS_LAW_HH
13 #define DUMUX_DISCRETIZATION_CC_MPFA_FICKS_LAW_HH
14
15 #include <dune/common/fvector.hh>
16 #include <dumux/common/properties.hh>
17 #include <dumux/discretization/method.hh>
18
19 #include <dumux/flux/fickiandiffusioncoefficients.hh>
20 #include <dumux/flux/referencesystemformulation.hh>
21
22 namespace Dumux {
23
24 //! forward declaration of the method-specific implementation
25 template<class TypeTag, class DiscretizationMethod, ReferenceSystemFormulation referenceSystem>
26 class FicksLawImplementation;
27
28 /*!
29 * \ingroup CCMpfaFlux
30 * \brief Fick's law for cell-centered finite volume schemes with multi-point flux approximation
31 */
32 template <class TypeTag, ReferenceSystemFormulation referenceSystem>
33 class FicksLawImplementation<TypeTag, DiscretizationMethods::CCMpfa, referenceSystem>
34 {
35 using Scalar = GetPropType<TypeTag, Properties::Scalar>;
36 using Problem = GetPropType<TypeTag, Properties::Problem>;
37 using GridView = typename GetPropType<TypeTag, Properties::GridGeometry>::GridView;
38 using Element = typename GridView::template Codim<0>::Entity;
39
40 static constexpr int dim = GridView::dimension;
41 static constexpr int dimWorld = GridView::dimensionworld;
42
43 using GridGeometry = GetPropType<TypeTag, Properties::GridGeometry>;
44 using FVElementGeometry = typename GridGeometry::LocalView;
45 using FluidSystem = GetPropType<TypeTag, Properties::FluidSystem>;
46 using SubControlVolumeFace = typename FVElementGeometry::SubControlVolumeFace;
47 using ElementVolumeVariables = typename GetPropType<TypeTag, Properties::GridVolumeVariables>::LocalView;
48 using GridFluxVariablesCache = GetPropType<TypeTag, Properties::GridFluxVariablesCache>;
49 using ElementFluxVariablesCache = typename GridFluxVariablesCache::LocalView;
50 using FluxVariablesCache = typename GridFluxVariablesCache::FluxVariablesCache;
51 using BalanceEqOpts = GetPropType<TypeTag, Properties::BalanceEqOpts>;
52
53 static constexpr int numComponents = GetPropType<TypeTag, Properties::ModelTraits>::numFluidComponents();
54 static constexpr int numPhases = GetPropType<TypeTag, Properties::ModelTraits>::numFluidPhases();
55 using ComponentFluxVector = Dune::FieldVector<Scalar, numComponents>;
56
57 //! Class that fills the cache corresponding to mpfa Fick's Law
58 class MpfaFicksLawCacheFiller
59 {
60 public:
61 //! Function to fill an MpfaFicksLawCache of a given scvf
62 //! This interface has to be met by any diffusion-related cache filler class
63 template<class FluxVariablesCacheFiller>
64
2/2
✓ Branch 0 taken 211904 times.
✓ Branch 1 taken 3770288 times.
314682336 static void fill(FluxVariablesCache& scvfFluxVarsCache,
65 unsigned int phaseIdx, unsigned int compIdx,
66 const Problem& problem,
67 const Element& element,
68 const FVElementGeometry& fvGeometry,
69 const ElementVolumeVariables& elemVolVars,
70 const SubControlVolumeFace& scvf,
71 const FluxVariablesCacheFiller& fluxVarsCacheFiller)
72 {
73 // get interaction volume related data from the filler class & update the cache
74
2/2
✓ Branch 0 taken 211904 times.
✓ Branch 1 taken 3770288 times.
3982192 if (fvGeometry.gridGeometry().vertexUsesSecondaryInteractionVolume(scvf.vertexIndex()))
75 211904 scvfFluxVarsCache.updateDiffusion(fluxVarsCacheFiller.secondaryInteractionVolume(),
76 211904 fluxVarsCacheFiller.secondaryIvLocalFaceData(),
77 211904 fluxVarsCacheFiller.secondaryIvDataHandle(),
78 phaseIdx, compIdx);
79 else
80 314470432 scvfFluxVarsCache.updateDiffusion(fluxVarsCacheFiller.primaryInteractionVolume(),
81 314470432 fluxVarsCacheFiller.primaryIvLocalFaceData(),
82 314470432 fluxVarsCacheFiller.primaryIvDataHandle(),
83 phaseIdx, compIdx);
84 3982192 }
85 };
86
87 //! The cache used in conjunction with the mpfa Fick's Law
88 class MpfaFicksLawCache
89 {
90 using DualGridNodalIndexSet = GetPropType<TypeTag, Properties::DualGridNodalIndexSet>;
91 using Stencil = typename DualGridNodalIndexSet::NodalGridStencilType;
92
93 static constexpr int numPhases = GetPropType<TypeTag, Properties::ModelTraits>::numFluidPhases();
94 static constexpr bool considerSecondaryIVs = GridGeometry::MpfaHelper::considerSecondaryIVs();
95 using PrimaryDataHandle = typename ElementFluxVariablesCache::PrimaryIvDataHandle::DiffusionHandle;
96 using SecondaryDataHandle = typename ElementFluxVariablesCache::SecondaryIvDataHandle::DiffusionHandle;
97
98 //! sets the pointer to the data handle (overload for secondary data handles)
99 template< bool doSecondary = considerSecondaryIVs, std::enable_if_t<doSecondary, int> = 0 >
100 211904 void setHandlePointer_(const SecondaryDataHandle& dataHandle)
101 211904 { secondaryHandlePtr_ = &dataHandle; }
102
103 //! sets the pointer to the data handle (overload for primary data handles)
104 314470432 void setHandlePointer_(const PrimaryDataHandle& dataHandle)
105 314470432 { primaryHandlePtr_ = &dataHandle; }
106
107 public:
108 // export filler type
109 using Filler = MpfaFicksLawCacheFiller;
110
111 /*!
112 * \brief Update cached objects (transmissibilities).
113 * This is used for updates with primary interaction volumes.
114 *
115 * \param iv The interaction volume this scvf is embedded in
116 * \param localFaceData iv-local info on this scvf
117 * \param dataHandle Transmissibility matrix & gravity data of this iv
118 */
119 template<class IV, class LocalFaceData, class DataHandle>
120 314682336 void updateDiffusion(const IV& iv,
121 const LocalFaceData& localFaceData,
122 const DataHandle& dataHandle,
123 unsigned int phaseIdx, unsigned int compIdx)
124 {
125 314682336 stencil_[phaseIdx][compIdx] = &iv.stencil();
126 314682336 switchFluxSign_[phaseIdx][compIdx] = localFaceData.isOutsideFace();
127 314682336 setHandlePointer_(dataHandle.diffusionHandle());
128 3982192 }
129
130 //! The stencils corresponding to the transmissibilities
131 const Stencil& diffusionStencil(unsigned int phaseIdx, unsigned int compIdx) const
132 { return *stencil_[phaseIdx][compIdx]; }
133
134 //! The corresponding data handles
135 322967680 const PrimaryDataHandle& diffusionPrimaryDataHandle() const { return *primaryHandlePtr_; }
136 120080 const SecondaryDataHandle& diffusionSecondaryDataHandle() const { return *secondaryHandlePtr_; }
137
138 //! Returns whether or not this scvf is an "outside" face in the scope of the iv.
139 323087760 bool diffusionSwitchFluxSign(unsigned int phaseIdx, unsigned int compIdx) const
140 323087760 { return switchFluxSign_[phaseIdx][compIdx]; }
141
142
143 private:
144 //! phase-/component- specific data
145 std::array< std::array<bool, numComponents>, numPhases > switchFluxSign_;
146 std::array< std::array<const Stencil*, numComponents>, numPhases > stencil_;
147
148 //! pointers to the corresponding iv-data handles
149 const PrimaryDataHandle* primaryHandlePtr_;
150 const SecondaryDataHandle* secondaryHandlePtr_;
151 };
152
153 public:
154 using DiscretizationMethod = DiscretizationMethods::CCMpfa;
155 // state the discretization method this implementation belongs to
156 static constexpr DiscretizationMethod discMethod{};
157
158 //return the reference system
159 static constexpr ReferenceSystemFormulation referenceSystemFormulation()
160 { return referenceSystem; }
161
162 // state the type for the corresponding cache and its filler
163 using Cache = MpfaFicksLawCache;
164
165 // export the diffusion container
166 using DiffusionCoefficientsContainer = FickianDiffusionCoefficients<Scalar, numPhases, numComponents>;
167
168 /*!
169 * \brief Returns the diffusive fluxes of all components within
170 * a fluid phase across the given sub-control volume face.
171 * The computed fluxes are given in mole/s or kg/s, depending
172 * on the template parameter ReferenceSystemFormulation.
173 */
174 283807760 static ComponentFluxVector flux(const Problem& problem,
175 const Element& element,
176 const FVElementGeometry& fvGeometry,
177 const ElementVolumeVariables& elemVolVars,
178 const SubControlVolumeFace& scvf,
179 const int phaseIdx,
180 const ElementFluxVariablesCache& elemFluxVarsCache)
181 {
182 // obtain this scvf's cache
183 283807760 const auto& fluxVarsCache = elemFluxVarsCache[scvf];
184
185 283807760 ComponentFluxVector componentFlux(0.0);
186
2/2
✓ Branch 0 taken 567615520 times.
✓ Branch 1 taken 283807760 times.
851423280 for (int compIdx = 0; compIdx < numComponents; compIdx++)
187 {
188 if constexpr (!FluidSystem::isTracerFluidSystem())
189
2/2
✓ Branch 0 taken 244527760 times.
✓ Branch 1 taken 244527760 times.
489055520 if (compIdx == FluidSystem::getMainComponent(phaseIdx))
190 244527760 continue;
191
192 // calculate the density at the interface
193
2/2
✓ Branch 1 taken 120080 times.
✓ Branch 2 taken 3532800 times.
323087760 const auto rho = interpolateDensity(elemVolVars, scvf, phaseIdx);
194
195 // compute the flux
196
2/2
✓ Branch 0 taken 120080 times.
✓ Branch 1 taken 3532800 times.
3652880 if (fluxVarsCache.usesSecondaryIv())
197 120080 componentFlux[compIdx] = rho*computeVolumeFlux(problem,
198 fluxVarsCache,
199 120080 fluxVarsCache.diffusionSecondaryDataHandle(),
200 phaseIdx, compIdx);
201 else
202 322967680 componentFlux[compIdx] = rho*computeVolumeFlux(problem,
203 fluxVarsCache,
204 322967680 fluxVarsCache.diffusionPrimaryDataHandle(),
205 phaseIdx, compIdx);
206 }
207
208 // accumulate the phase component flux
209
2/2
✓ Branch 0 taken 489055520 times.
✓ Branch 1 taken 244527760 times.
772863280 for (int compIdx = 0; compIdx < numComponents; compIdx++)
210 if constexpr (!FluidSystem::isTracerFluidSystem())
211
2/2
✓ Branch 0 taken 244527760 times.
✓ Branch 1 taken 244527760 times.
489055520 if (compIdx != FluidSystem::getMainComponent(phaseIdx) && BalanceEqOpts::mainComponentIsBalanced(phaseIdx))
212 244527760 componentFlux[FluidSystem::getMainComponent(phaseIdx)] -= componentFlux[compIdx];
213
214 283807760 return componentFlux;
215 }
216
217 private:
218 template< class Problem, class FluxVarsCache, class DataHandle >
219 326740640 static Scalar computeVolumeFlux(const Problem& problem,
220 const FluxVarsCache& cache,
221 const DataHandle& dataHandle,
222 int phaseIdx, int compIdx)
223 {
224
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 323087760 times.
326740640 dataHandle.setPhaseIndex(phaseIdx);
225
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 323087760 times.
326740640 dataHandle.setComponentIndex(compIdx);
226
227
2/2
✓ Branch 0 taken 6749926 times.
✓ Branch 1 taken 6167102 times.
326740640 const bool switchSign = cache.diffusionSwitchFluxSign(phaseIdx, compIdx);
228
229
2/2
✓ Branch 0 taken 6749926 times.
✓ Branch 1 taken 6167102 times.
326740640 const auto localFaceIdx = cache.ivLocalFaceIndex();
230 326740640 const auto idxInOutside = cache.indexInOutsideFaces();
231
2/2
✓ Branch 0 taken 6749926 times.
✓ Branch 1 taken 6167102 times.
326740640 const auto& xj = dataHandle.uj();
232
2/2
✓ Branch 0 taken 6749926 times.
✓ Branch 1 taken 6167102 times.
326740640 const auto& tij = dim == dimWorld ? dataHandle.T()[localFaceIdx]
233 6749926 : (!switchSign ? dataHandle.T()[localFaceIdx]
234 6167102 : dataHandle.tijOutside()[localFaceIdx][idxInOutside]);
235 326740640 Scalar scvfFlux = tij*xj;
236
237 // switch the sign if necessary
238
2/2
✓ Branch 0 taken 160821578 times.
✓ Branch 1 taken 162266182 times.
326740640 if (switchSign)
239 162637834 scvfFlux *= -1.0;
240
241 326740640 return scvfFlux;
242 }
243
244 //! compute the density at branching facets for network grids as arithmetic mean
245
2/2
✓ Branch 0 taken 322370944 times.
✓ Branch 1 taken 716816 times.
323087760 static Scalar interpolateDensity(const ElementVolumeVariables& elemVolVars,
246 const SubControlVolumeFace& scvf,
247 const unsigned int phaseIdx)
248 {
249 // use arithmetic mean of the densities around the scvf
250
2/2
✓ Branch 0 taken 322370944 times.
✓ Branch 1 taken 716816 times.
323087760 if (!scvf.boundary())
251 {
252 322370944 const Scalar rhoInside = massOrMolarDensity(elemVolVars[scvf.insideScvIdx()], referenceSystem, phaseIdx);
253
254 322370944 Scalar rho = rhoInside;
255
2/2
✓ Branch 0 taken 322370944 times.
✓ Branch 1 taken 322370944 times.
644741888 for (const auto outsideIdx : scvf.outsideScvIndices())
256 {
257 322370944 const Scalar rhoOutside = massOrMolarDensity(elemVolVars[outsideIdx], referenceSystem, phaseIdx);
258 322370944 rho += rhoOutside;
259 }
260 322370944 return rho/(scvf.outsideScvIndices().size()+1);
261 }
262 else
263 716816 return massOrMolarDensity(elemVolVars[scvf.outsideScvIdx()], referenceSystem, phaseIdx);
264 }
265 };
266
267 } // end namespace
268
269 #endif
270