GCC Code Coverage Report


Directory: ../../../builds/dumux-repositories/
File: /builds/dumux-repositories/dumux/dumux/material/fluidmatrixinteractions/porenetwork/throat/transmissibility1p.hh
Date: 2024-09-21 20:52:54
Exec Total Coverage
Lines: 55 59 93.2%
Functions: 4 17 23.5%
Branches: 45 100 45.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 single-phase transmissibility laws for throats
12 */
13 #ifndef DUMUX_PNM_THROAT_TRANSMISSIBILITY_1P_HH
14 #define DUMUX_PNM_THROAT_TRANSMISSIBILITY_1P_HH
15
16 #include <dumux/common/parameters.hh>
17 #include <dumux/porenetwork/common/throatproperties.hh>
18 #include "emptycache.hh"
19
20 namespace Dumux::PoreNetwork {
21
22 /*!
23 * \ingroup Fluidmatrixinteractions
24 * \ingroup PoreNetworkModels
25 * \brief Collection of single-phase flow throat transmissibilities based on
26 * Bruus, H. (2011). Acoustofluidics 1: Governing equations in microfluidics. Lab on a Chip, 11(22), 3742-3751.
27 * https://backend.orbit.dtu.dk/ws/portalfiles/portal/5900070/rsc%5B1%5D.pdf
28 */
29 template<class Scalar>
30 class TransmissibilityBruus
31 {
32 public:
33
34 using SinglePhaseCache = EmptyCache;
35
36 template<class Problem, class Element, class FVElementGeometry, class ElementVolumeVariables, class FluxVariablesCache>
37 static Scalar singlePhaseTransmissibility(const Problem& problem,
38 const Element& element,
39 const FVElementGeometry& fvGeometry,
40 const typename FVElementGeometry::SubControlVolumeFace& scvf,
41 const ElementVolumeVariables& elemVolVars,
42 const FluxVariablesCache& fluxVarsCache,
43 const int phaseIdx)
44 {
45
0/2
✗ Branch 0 not taken.
✗ Branch 1 not taken.
780 const auto shape = fluxVarsCache.throatCrossSectionShape();
46
0/2
✗ Branch 0 not taken.
✗ Branch 1 not taken.
780 const Scalar throatInscribedRadius = fluxVarsCache.throatInscribedRadius();
47
0/2
✗ Branch 0 not taken.
✗ Branch 1 not taken.
780 const Scalar throatLength = fluxVarsCache.throatLength();
48
0/2
✗ Branch 0 not taken.
✗ Branch 1 not taken.
780 const Scalar area = fluxVarsCache.throatCrossSectionalArea();
49 1560 return singlePhaseTransmissibility(shape, throatInscribedRadius, throatLength, area);
50 }
51
52 //! Returns the conductivity of a throat when only one phase is present.
53 static Scalar singlePhaseTransmissibility(const Throat::Shape shape,
54 const Scalar inscribedRadius,
55 const Scalar throatLength,
56 const Scalar area)
57 780 { return 1.0 / rHydThroat_(shape, inscribedRadius, throatLength, area); }
58
59 protected:
60
61 785 static Scalar rHydThroat_(const Throat::Shape shape,
62 const Scalar radius,
63 const Scalar length,
64 const Scalar area)
65 {
66
5/6
✓ Branch 0 taken 457 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 325 times.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
785 switch(shape)
67 {
68 457 case Throat::Shape::square:
69 {
70 457 const Scalar sideLength = 2.0*radius;
71 457 return 28.4*length * 1.0/(sideLength*sideLength*sideLength*sideLength);
72 }
73 1 case Throat::Shape::circle:
74 {
75 1 return 8.0/M_PI * length * 1.0/(radius*radius*radius*radius);
76 }
77 1 case Throat::Shape::equilateralTriangle:
78 {
79 using std::sqrt;
80 static Scalar sqrt3 = sqrt(3.0);
81 1 const Scalar sideLength = 6.0/sqrt3 * radius;
82 1 return 320.0/sqrt3 * length * 1.0/(sideLength*sideLength*sideLength*sideLength);
83 }
84 325 case Throat::Shape::twoPlates:
85 {
86 // the distance between the two parallel plates
87 325 const Scalar width = 2*radius;
88 325 return 12.0/(width*width*width) * length;
89 }
90 1 case Throat::Shape::rectangle:
91 {
92 // requires width >> height for good accuracy
93 1 Scalar height = 2.0*radius;
94 1 Scalar width = area/height;
95
96 using std::swap;
97
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (width < height)
98 swap(width, height);
99
100 1 return 12.0*length / (1.0 - 0.63*(height/width)) * 1.0/(height*height*height*width);
101 }
102 default: DUNE_THROW(Dune::InvalidStateException, "Throat geometry not supported");
103 }
104 }
105 };
106
107 /*!
108 * \ingroup Fluidmatrixinteractions
109 * \ingroup PoreNetworkModels
110 * \brief Single-phase flow throat transmissibility based on Patzek & Silin (2001) https://doi.org/10.1006/jcis.2000.7413
111 */
112 template<class Scalar, bool considerPoreResistance = false, bool interpolateK = false>
113 class TransmissibilityPatzekSilin
114 {
115 static_assert(!interpolateK, "Interpolation of k not implemented");
116 public:
117
118 using SinglePhaseCache = EmptyCache;
119
120 template<class Problem, class Element, class FVElementGeometry, class ElementVolumeVariables, class FluxVariablesCache>
121 7230483 static Scalar singlePhaseTransmissibility(const Problem& problem,
122 const Element& element,
123 const FVElementGeometry& fvGeometry,
124 const typename FVElementGeometry::SubControlVolumeFace& scvf,
125 const ElementVolumeVariables& elemVolVars,
126 const FluxVariablesCache& fluxVarsCache,
127 const int phaseIdx)
128 {
129
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 3615243 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 3 times.
7230486 assert(fluxVarsCache.throatCrossSectionShape() != Throat::Shape::twoPlates && "TwoPlates not supported. Use TransmissibilityBruus instead!");
130
131 7230483 const Scalar shapeFactor = fluxVarsCache.throatShapeFactor();
132
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
7230483 const Scalar area = fluxVarsCache.throatCrossSectionalArea();
133
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1 times.
7230483 const Scalar throatLength = fluxVarsCache.throatLength();
134 14460966 const Scalar throatTransmissibility = singlePhaseTransmissibility(shapeFactor, throatLength, area);
135
136 if constexpr (!considerPoreResistance)
137 3 return throatTransmissibility;
138 else
139 {
140
3/6
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 2 times.
✗ Branch 8 not taken.
4 static const bool considerPoreResistanceOnRuntime = getParamFromGroup<bool>(problem.paramGroup(), "Transmissibility.ConsiderPoreResistance", true);
141
1/2
✓ Branch 0 taken 3615240 times.
✗ Branch 1 not taken.
7230480 if (!considerPoreResistanceOnRuntime)
142 return throatTransmissibility;
143
144
2/4
✓ Branch 0 taken 3615240 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3615240 times.
✗ Branch 3 not taken.
14460960 const auto& scv0 = fvGeometry.scv(scvf.insideScvIdx());
145
2/4
✓ Branch 0 taken 3615240 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3615240 times.
✗ Branch 3 not taken.
14460960 const auto& scv1 = fvGeometry.scv(scvf.outsideScvIdx());
146
147
1/2
✓ Branch 0 taken 3615240 times.
✗ Branch 1 not taken.
7230480 const auto& spatialParams = problem.spatialParams();
148
1/2
✓ Branch 0 taken 3615240 times.
✗ Branch 1 not taken.
7230480 const auto elemSol = elementSolution(element, elemVolVars, fvGeometry);
149
150 // TODO maybe include this in fluxVarsCache if this is general enough
151
1/2
✓ Branch 0 taken 3615240 times.
✗ Branch 1 not taken.
7230480 const Scalar poreLength0 = spatialParams.poreLength(element, scv0, elemSol);
152
1/2
✓ Branch 0 taken 3615240 times.
✗ Branch 1 not taken.
7230480 const Scalar poreLength1 = spatialParams.poreLength(element, scv1, elemSol);
153
154
1/2
✓ Branch 0 taken 3615240 times.
✗ Branch 1 not taken.
7230480 const Scalar poreShapeFactor0 = spatialParams.poreShapeFactor(element, scv0, elemSol);
155
1/2
✓ Branch 0 taken 3615240 times.
✗ Branch 1 not taken.
7230480 const Scalar poreShapeFactor1 = spatialParams.poreShapeFactor(element, scv1, elemSol);
156
157
1/2
✓ Branch 0 taken 3615240 times.
✗ Branch 1 not taken.
7230480 const Scalar poreCrossSectionalArea0 = spatialParams.poreCrossSectionalArea(element, scv0, elemSol);
158
1/2
✓ Branch 0 taken 3615240 times.
✗ Branch 1 not taken.
7230480 const Scalar poreCrossSectionalArea1 = spatialParams.poreCrossSectionalArea(element, scv1, elemSol);
159
160 14460960 const Scalar poreTransmissibility0 = singlePhaseTransmissibility(poreShapeFactor0, poreLength0, poreCrossSectionalArea0);
161 14460960 const Scalar poreTransmissibility1 = singlePhaseTransmissibility(poreShapeFactor1, poreLength1, poreCrossSectionalArea1);
162
163 7230480 return 1 / (1.0/throatTransmissibility + 1.0/poreTransmissibility0 + 1.0/poreTransmissibility1);
164 }
165 }
166
167 //! Returns the conductivity of a throat when only one phase is present. See Patzek & Silin (2001)
168 static Scalar singlePhaseTransmissibility(const Scalar shapeFactor,
169 const Scalar length,
170 const Scalar area)
171 {
172 21691446 const Scalar k = k_(shapeFactor);
173
4/4
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 2522975 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 1092263 times.
7230483 return k * area*area * shapeFactor / length;
174 }
175
176 private:
177 static Scalar k_(const Scalar shapeFactor)
178 {
179
7/12
✓ Branch 0 taken 2522978 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 2522976 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2522976 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 1092264 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 1092264 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 1092264 times.
✗ Branch 11 not taken.
10845723 if (shapeFactor <= Throat::shapeFactorEquilateralTriangle<Scalar>())
180 return 0.6; // == 3/5
181
7/12
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 2522977 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 2522976 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 2522976 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 1092264 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 1092264 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 1092264 times.
10845722 else if (shapeFactor <= Throat::shapeFactorSquare<Scalar>())
182 return 0.5623;
183 else // circle
184 return 0.5;
185 }
186
187 // TODO interpolation
188 };
189
190
191 //! Used by Joeakar-Niasar
192 template<class Scalar>
193 class TransmissibilityAzzamDullien
194 {
195 public:
196
197 using SinglePhaseCache = EmptyCache;
198
199 template<class Problem, class Element, class FVElementGeometry, class ElementVolumeVariables, class FluxVariablesCache>
200 static Scalar singlePhaseTransmissibility(const Problem& problem,
201 const Element& element,
202 const FVElementGeometry& fvGeometry,
203 const typename FVElementGeometry::SubControlVolumeFace& scvf,
204 const ElementVolumeVariables& elemVolVars,
205 const FluxVariablesCache& fluxVarsCache,
206 const int phaseIdx)
207 {
208 328526 const Scalar throatInscribedRadius = fluxVarsCache.throatInscribedRadius();
209 328526 const Scalar throatLength = fluxVarsCache.throatLength();
210 657052 return singlePhaseTransmissibility(throatInscribedRadius, throatLength);
211 }
212
213 //! Returns the conductivity of a throat when only one phase is present.
214 static Scalar singlePhaseTransmissibility(const Scalar radius,
215 const Scalar length)
216 {
217 328526 const Scalar rEff= std::sqrt(4.0/M_PI)*radius ;
218 328526 return M_PI/(8.0*length) *rEff*rEff*rEff*rEff ;
219 }
220 };
221
222 } // end namespace Dumux::Porenetwork
223
224 #endif
225