GCC Code Coverage Report


Directory: ../../../builds/dumux-repositories/
File: /builds/dumux-repositories/dumux/dumux/flux/ccmpfa/fickslaw.hh
Date: 2024-05-04 19:09:25
Exec Total Coverage
Lines: 43 51 84.3%
Functions: 39 82 47.6%
Branches: 28 34 82.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-FileCopyrightInfo: 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 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
0/4
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
302288248 if (fvGeometry.gridGeometry().vertexUsesSecondaryInteractionVolume(scvf.vertexIndex()))
75 scvfFluxVarsCache.updateDiffusion(fluxVarsCacheFiller.secondaryInteractionVolume(),
76 fluxVarsCacheFiller.secondaryIvLocalFaceData(),
77 fluxVarsCacheFiller.secondaryIvDataHandle(),
78 phaseIdx, compIdx);
79 else
80 302288248 scvfFluxVarsCache.updateDiffusion(fluxVarsCacheFiller.primaryInteractionVolume(),
81 fluxVarsCacheFiller.primaryIvLocalFaceData(),
82 fluxVarsCacheFiller.primaryIvDataHandle(),
83 phaseIdx, compIdx);
84 }
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 void setHandlePointer_(const SecondaryDataHandle& dataHandle)
101 { secondaryHandlePtr_ = &dataHandle; }
102
103 //! sets the pointer to the data handle (overload for primary data handles)
104 void setHandlePointer_(const PrimaryDataHandle& dataHandle)
105 302288248 { 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 void updateDiffusion(const IV& iv,
121 const LocalFaceData& localFaceData,
122 const DataHandle& dataHandle,
123 unsigned int phaseIdx, unsigned int compIdx)
124 {
125 604576496 stencil_[phaseIdx][compIdx] = &iv.stencil();
126 604576496 switchFluxSign_[phaseIdx][compIdx] = localFaceData.isOutsideFace();
127 604576496 setHandlePointer_(dataHandle.diffusionHandle());
128 }
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 const PrimaryDataHandle& diffusionPrimaryDataHandle() const { return *primaryHandlePtr_; }
136 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 bool diffusionSwitchFluxSign(unsigned int phaseIdx, unsigned int compIdx) const
140
2/2
✓ Branch 0 taken 4112126 times.
✓ Branch 1 taken 3757222 times.
317882352 { 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 278602352 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 278602352 const auto& fluxVarsCache = elemFluxVarsCache[scvf];
184
185 278602352 ComponentFluxVector componentFlux(0.0);
186
2/2
✓ Branch 0 taken 557204704 times.
✓ Branch 1 taken 278602352 times.
835807056 for (int compIdx = 0; compIdx < numComponents; compIdx++)
187 {
188 if constexpr (!FluidSystem::isTracerFluidSystem())
189
2/2
✓ Branch 0 taken 239322352 times.
✓ Branch 1 taken 239322352 times.
478644704 if (compIdx == FluidSystem::getMainComponent(phaseIdx))
190 continue;
191
192 // calculate the density at the interface
193 317882352 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.
317882352 if (fluxVarsCache.usesSecondaryIv())
197 120080 componentFlux[compIdx] = rho*computeVolumeFlux(problem,
198 fluxVarsCache,
199 fluxVarsCache.diffusionSecondaryDataHandle(),
200 phaseIdx, compIdx);
201 else
202 317762272 componentFlux[compIdx] = rho*computeVolumeFlux(problem,
203 fluxVarsCache,
204 fluxVarsCache.diffusionPrimaryDataHandle(),
205 phaseIdx, compIdx);
206 }
207
208 // accumulate the phase component flux
209
2/2
✓ Branch 0 taken 478644704 times.
✓ Branch 1 taken 239322352 times.
757247056 for (int compIdx = 0; compIdx < numComponents; compIdx++)
210 if constexpr (!FluidSystem::isTracerFluidSystem())
211
2/2
✓ Branch 0 taken 239322352 times.
✓ Branch 1 taken 239322352 times.
478644704 if (compIdx != FluidSystem::getMainComponent(phaseIdx) && BalanceEqOpts::mainComponentIsBalanced(phaseIdx))
212 717967056 componentFlux[FluidSystem::getMainComponent(phaseIdx)] -= componentFlux[compIdx];
213
214 278602352 return componentFlux;
215 }
216
217 private:
218 template< class Problem, class FluxVarsCache, class DataHandle >
219 321535232 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 317882352 times.
321535232 dataHandle.setPhaseIndex(phaseIdx);
225
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 317882352 times.
321535232 dataHandle.setComponentIndex(compIdx);
226
227
2/2
✓ Branch 0 taken 4112126 times.
✓ Branch 1 taken 3757222 times.
321535232 const bool switchSign = cache.diffusionSwitchFluxSign(phaseIdx, compIdx);
228
229 321535232 const auto localFaceIdx = cache.ivLocalFaceIndex();
230 321535232 const auto idxInOutside = cache.indexInOutsideFaces();
231
2/2
✓ Branch 0 taken 4112126 times.
✓ Branch 1 taken 3757222 times.
321535232 const auto& xj = dataHandle.uj();
232
2/2
✓ Branch 0 taken 4112126 times.
✓ Branch 1 taken 3757222 times.
635201116 const auto& tij = dim == dimWorld ? dataHandle.T()[localFaceIdx]
233 12336378 : (!switchSign ? dataHandle.T()[localFaceIdx]
234 15028888 : dataHandle.tijOutside()[localFaceIdx][idxInOutside]);
235 321535232 Scalar scvfFlux = tij*xj;
236
237 // switch the sign if necessary
238
2/2
✓ Branch 0 taken 158333330 times.
✓ Branch 1 taken 159549022 times.
321535232 if (switchSign)
239 160149586 scvfFlux *= -1.0;
240
241 321535232 return scvfFlux;
242 }
243
244 //! compute the density at branching facets for network grids as arithmetic mean
245 317882352 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 317214928 times.
✓ Branch 1 taken 667424 times.
317882352 if (!scvf.boundary())
251 {
252 317214928 const Scalar rhoInside = massOrMolarDensity(elemVolVars[scvf.insideScvIdx()], referenceSystem, phaseIdx);
253
254 317214928 Scalar rho = rhoInside;
255
4/4
✓ Branch 0 taken 317214928 times.
✓ Branch 1 taken 317214928 times.
✓ Branch 2 taken 7793888 times.
✓ Branch 3 taken 7793888 times.
1593868528 for (const auto outsideIdx : scvf.outsideScvIndices())
256 {
257 317214928 const Scalar rhoOutside = massOrMolarDensity(elemVolVars[outsideIdx], referenceSystem, phaseIdx);
258 317214928 rho += rhoOutside;
259 }
260 642223744 return rho/(scvf.outsideScvIndices().size()+1);
261 }
262 else
263 1334848 return massOrMolarDensity(elemVolVars[scvf.outsideScvIdx()], referenceSystem, phaseIdx);
264 }
265 };
266
267 } // end namespace
268
269 #endif
270