GCC Code Coverage Report


Directory: ../../../builds/dumux-repositories/
File: /builds/dumux-repositories/dumux/dumux/material/fluidmatrixinteractions/porenetwork/throat/transmissibility2p.hh
Date: 2024-05-04 19:09:25
Exec Total Coverage
Lines: 31 38 81.6%
Functions: 6 7 85.7%
Branches: 6 10 60.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-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 Fluidmatrixinteractions
10 * \ingroup PoreNetworkModels
11 * \brief Implementation of the transmissibility laws for throats
12 */
13 #ifndef DUMUX_PNM_THROAT_TRANSMISSIBILITY_2P_HH
14 #define DUMUX_PNM_THROAT_TRANSMISSIBILITY_2P_HH
15
16 #include <dumux/porenetwork/common/throatproperties.hh>
17 #include "emptycache.hh"
18
19 namespace Dumux::PoreNetwork {
20
21 namespace WettingLayerTransmissibility {
22
23 struct CreviceResistanceFactorZhou
24 {
25 /*!
26 * \brief Returns the crevice resistance factor used for calculating the w-phase conductance in an invaded pore throat
27 *
28 * \param alpha The corner half angle
29 * \param theta The contact angle
30 * \param f The boundary condition factor for the fluid interface (0 = free boundary)
31 *
32 * Zhou et al. (1997), eq. 19; Singh & Mohanty (2002), eq 8
33 */
34 template<class Scalar>
35 7678560 static Scalar beta(const Scalar alpha, const Scalar theta, const Scalar f = 0)
36 {
37 using std::sin;
38 using std::cos;
39 using std::tan;
40 7678560 const Scalar sinAlpha = sin(alpha);
41 7678560 const Scalar sinSum = sin(alpha + theta);
42 7678560 const Scalar cosSum = cos(alpha + theta);
43 7678560 const Scalar phi1 = cosSum*cosSum + cosSum*sinSum*tan(alpha);
44 7678560 const Scalar phi2 = 1 - theta/(M_PI/2 - alpha);
45 7678560 const Scalar phi3 = cosSum / cos(alpha);
46 7678560 const Scalar B = (M_PI/2 - alpha)*tan(alpha);
47
48 7678560 Scalar result = 12*sinAlpha*sinAlpha*(1-B)*(1-B)*(phi1 - B*phi2)*(phi3 + f*B*phi2)*(phi3 + f*B*phi2);
49 7678560 result /= (1-sinAlpha)*(1-sinAlpha)*B*B*(phi1 - B*phi2)*(phi1 - B*phi2)*(phi1 - B*phi2);
50 7678560 return result;
51 }
52 };
53
54
55 template<class Scalar, class CreviceResistanceFactor = CreviceResistanceFactorZhou>
56 struct RansohoffRadke
57 {
58
1/4
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 6 taken 31352 times.
✗ Branch 7 not taken.
316534 class WettingLayerCache
59 {
60 using NumCornerVector = Dune::ReservedVector<Scalar, 4>;
61 public:
62 template<class Problem, class Element, class FVElementGeometry, class ElementVolumeVariables, class FluxVariablesCache>
63 1919640 void fill(const Problem& problem,
64 const Element& element,
65 const FVElementGeometry& fvGeometry,
66 const typename FVElementGeometry::SubControlVolumeFace& scvf,
67 const ElementVolumeVariables& elemVolVars,
68 const FluxVariablesCache& fluxVarsCache,
69 const int phaseIdx)
70 {
71 1919640 const auto& spatialParams = problem.spatialParams();
72 1919640 const auto& cornerHalfAngles = spatialParams.cornerHalfAngles(element);
73 1919640 const Scalar contactAngle = spatialParams.contactAngle(element, elemVolVars);
74
75 3839280 beta_.clear(); beta_.resize(cornerHalfAngles.size());
76
2/2
✓ Branch 0 taken 7678560 times.
✓ Branch 1 taken 1919640 times.
9598200 for (int i = 0; i< cornerHalfAngles.size(); ++i)
77 23035680 beta_[i] = CreviceResistanceFactor::beta(cornerHalfAngles[i], contactAngle);
78 1919640 }
79
80 Scalar creviceResistanceFactor(const int cornerIdx) const
81 739656 { return beta_[cornerIdx]; }
82
83 private:
84 NumCornerVector beta_;
85 };
86
87 /*!
88 * \brief Returns the integral conductivity of all wetting layers occupying the corners of a throat
89 */
90 template<class Element, class FVElementGeometry, class FluxVariablesCache>
91 92457 static Scalar wettingLayerTransmissibility(const Element& element,
92 const FVElementGeometry& fvGeometry,
93 const typename FVElementGeometry::SubControlVolumeFace& scvf,
94 const FluxVariablesCache& fluxVarsCache)
95 {
96 92457 const Scalar throatLength = fluxVarsCache.throatLength();
97 92457 const Scalar rC = fluxVarsCache.curvatureRadius();
98
99 184914 const auto eIdx = fvGeometry.gridGeometry().elementMapper().index(element);
100
1/2
✓ Branch 0 taken 92457 times.
✗ Branch 1 not taken.
92457 const auto shape = fvGeometry.gridGeometry().throatCrossSectionShape(eIdx);
101 92457 const auto numCorners = Throat::numCorners(shape);
102
103 // treat the wetting film layer in each corner of the throat individually (might have different corner half-angle and beta)
104 92457 Scalar result = 0.0;
105
2/2
✓ Branch 1 taken 369828 times.
✓ Branch 2 taken 92457 times.
462285 for (int i = 0; i < numCorners; ++i)
106 1479312 result += fluxVarsCache.wettingLayerCrossSectionalArea(i) * rC*rC / (throatLength*fluxVarsCache.wettingLayerFlowVariables().creviceResistanceFactor(i));
107
108 92457 return result;
109 }
110 };
111 } // end namespace WettingLayerTransmissibility
112
113 namespace NonWettingPhaseTransmissibility {
114
115 //! TODO: evaluate and maybe remove
116 template<class Scalar>
117 struct Mogensen
118 {
119 using NonWettingPhaseCache = EmptyCache;
120
121 template<class Element, class FVElementGeometry, class FluxVariablesCache>
122 static Scalar nonWettingPhaseTransmissibility(const Element& element,
123 const FVElementGeometry& fvGeometry,
124 const typename FVElementGeometry::SubControlVolumeFace& scvf,
125 const FluxVariablesCache& fluxVarsCache)
126 {
127 // Mogensen et al. (1999), does not really revover the single phase value
128 using std::sqrt;
129 const Scalar throatLength = fluxVarsCache.throatLength();
130 const auto nPhaseIdx = fluxVarsCache.nPhaseIdx();
131 const Scalar aNw = fluxVarsCache.throatCrossSectionalArea(nPhaseIdx);
132 const Scalar rEff = 0.5*(sqrt(aNw / M_PI) + fluxVarsCache.throatInscribedRadius());
133 const Scalar result = M_PI/(8*throatLength) * rEff*rEff*rEff*rEff;
134 return result;
135 }
136 };
137
138 //! TODO: evaluate and maybe remove
139 template<class Scalar, class SinglePhaseTransmissibilityLaw>
140 struct Valvatne
141 {
142 using NonWettingPhaseCache = EmptyCache;
143
144 template<class Element, class FVElementGeometry, class FluxVariablesCache>
145 static Scalar nonWettingPhaseTransmissibility(const Element& element,
146 const FVElementGeometry& fvGeometry,
147 const typename FVElementGeometry::SubControlVolumeFace& scvf,
148 const FluxVariablesCache& fluxVarsCache)
149 {
150 // Tora et al. (2012), also does not fully recover single-phase value, but is closer
151 using std::sqrt;
152 const auto nPhaseIdx = fluxVarsCache.nPhaseIdx();
153 const Scalar aNw = fluxVarsCache.throatCrossSectionalArea(nPhaseIdx);
154 const Scalar aTot = fluxVarsCache.throatCrossSectionalArea();
155
156 const Scalar result = SinglePhaseTransmissibilityLaw::singlePhaseTransmissibility(element, fvGeometry, scvf, fluxVarsCache)
157 * aNw / aTot;
158
159 return result;
160 }
161 };
162
163 template<class Scalar>
164 struct BakkeOren
165 {
166 using NonWettingPhaseCache = EmptyCache;
167
168 /*!
169 * \brief Returns the conductivity of a throat.
170 *
171 * See Bakke & Oren (1997), eq. 9
172 */
173 template<class Element, class FVElementGeometry, class FluxVariablesCache>
174 static Scalar nonWettingPhaseTransmissibility(const Element& element,
175 const FVElementGeometry& fvGeometry,
176 const typename FVElementGeometry::SubControlVolumeFace& scvf,
177 const FluxVariablesCache& fluxVarsCache)
178 {
179 // Tora et al. (2012), quite close for single-phase value of square
180 using std::sqrt;
181 const Scalar throatLength = fluxVarsCache.throatLength();
182 const auto nPhaseIdx = fluxVarsCache.nPhaseIdx();
183 const Scalar aNw = fluxVarsCache.throatCrossSectionalArea(nPhaseIdx);
184 const Scalar rEff = 0.5*(sqrt(aNw / M_PI) + fluxVarsCache.throatInscribedRadius());
185 const Scalar result = rEff*rEff*aNw / (8.0*throatLength);
186 return result;
187 }
188 };
189 } // end namespace NonWettingPhaseTransmissibility
190 } // end namespace Dumux::PoreNetwork
191
192 #endif
193