version 3.8
throatproperties.hh
Go to the documentation of this file.
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//
12#ifndef DUMUX_PNM_BASE_THROAT_PROPERTIES_HH
13#define DUMUX_PNM_BASE_THROAT_PROPERTIES_HH
14
15#include <string>
16#include <cmath>
17#include <numeric>
18
19#include <dune/common/exceptions.hh>
20#include <dune/common/reservedvector.hh>
21
23
25enum class Shape
27
29inline std::string shapeToString(Shape s)
30{
31 switch (s)
32 {
33 case Shape::scaleneTriangle: return "ScaleneTriangle";
34 case Shape::equilateralTriangle: return "EquilateralTriangle";
35 case Shape::square: return "Square";
36 case Shape::rectangle: return "Rectangle";
37 case Shape::circle: return "Circle";
38 case Shape::twoPlates: return "TwoPlates";
39 case Shape::polygon: return "Polygon";
40 default: DUNE_THROW(Dune::InvalidStateException, "Unknown shape!");
41 }
42}
43
45inline Shape shapeFromString(const std::string& s)
46{
49 else if (s == shapeToString(Shape::square)) return Shape::square;
50 else if (s == shapeToString(Shape::rectangle)) return Shape::rectangle;
51 else if (s == shapeToString(Shape::circle)) return Shape::circle;
52 else if (s == shapeToString(Shape::twoPlates)) return Shape::twoPlates;
53 else if (s == shapeToString(Shape::polygon)) return Shape::polygon;
54 else DUNE_THROW(Dune::InvalidStateException, s << " is not a valid shape");
55}
56
67template<class Scalar>
68inline Scalar averagedRadius(const Scalar poreRadiusOne, const Scalar poreRadiusTwo, const Scalar centerTocenterDist, const Scalar n = 0.1)
69{
70 assert(n > 0.0);
71 using std::sin; using std::cos; using std::pow;
72 const Scalar rOneTilde = poreRadiusOne/centerTocenterDist;
73 const Scalar rTwoTilde = poreRadiusTwo/centerTocenterDist;
74 const Scalar a = sin(M_PI/4.0);
75 const Scalar b = cos(M_PI/4.0);
76 const Scalar rhoOne = rOneTilde*a / pow((1.0 - rOneTilde*b), n);
77 const Scalar rhoTwo = rTwoTilde*a / pow((1.0 - rTwoTilde*b), n);
78 const Scalar rTilde = rhoOne*rhoTwo * pow((pow(rhoOne, 1.0/n) + pow(rhoTwo, 1.0/n)), -n);
79 return rTilde * centerTocenterDist;
80}
81
82
84template<class Scalar>
85inline Dune::ReservedVector<Scalar, 4> cornerHalfAngles(Shape shape)
86{
87 switch(shape)
88 {
90 {
91 const Scalar value = M_PI/6.0;
92 return Dune::ReservedVector<Scalar, 4>{value, value, value};
93 }
94 case Shape::square:
95 {
96 const Scalar value = M_PI/4.0;
97 return Dune::ReservedVector<Scalar, 4>{value, value, value, value};
98 }
100 {
101 const Scalar value = M_PI/4.0;
102 return Dune::ReservedVector<Scalar, 4>{value, value, value, value};
103 }
104 case Shape::circle:
105 {
106 const Scalar value = 0.5*M_PI; // we define the (single) corner angle of a circle as 180°
107 return { value };
108 }
109 case Shape::polygon: DUNE_THROW(Dune::InvalidStateException, "Corner half angles for polygons must be calculated explicitly");
110 default: DUNE_THROW(Dune::InvalidStateException, "Unknown shape");
111 // TODO implement angles for scaleneTriangle as given by Valvatne & Blunt (2004)
112 }
113}
114
116template<class Scalar>
117inline constexpr Scalar shapeFactorEquilateralTriangle() noexcept
118{
119 using std::sqrt;
120 return sqrt(3.0)/36.0;
121}
122
124template<class Scalar>
125inline constexpr Scalar shapeFactorSquare() noexcept
126{
127 return 1.0/16.0;
128}
129
131template<class Scalar>
132inline constexpr Scalar shapeFactorRectangle(const Scalar inscribedRadius, const Scalar height) noexcept
133{
134 const Scalar a = 2.0*inscribedRadius; // shorter side length
135 const Scalar b = height; // longer side length
136 const Scalar area = a*b;
137 const Scalar perimeter = 2.0*a + 2.0*b;
138 return area / (perimeter*perimeter);
139}
140
142template<class Scalar>
143inline constexpr Scalar shapeFactorCircle() noexcept
144{
145 return 1.0/(4.0*M_PI);
146}
147
149template<class Scalar>
150inline Scalar shapeFactor(Shape shape, const Scalar inscribedRadius)
151{
152 switch(shape)
153 {
154 case Shape::equilateralTriangle: return shapeFactorEquilateralTriangle<Scalar>();
155 case Shape::square: return shapeFactorSquare<Scalar>();
156 case Shape::circle: return shapeFactorCircle<Scalar>();
157 case Shape::twoPlates: return 0.0; // TODO is this a good idea?
158 case Shape::polygon: DUNE_THROW(Dune::InvalidStateException, "The shape factor for a polygon has to be defined by the input data");
159 default: DUNE_THROW(Dune::InvalidStateException, "Unknown shape");
160 }
161}
162
164template<class Scalar>
165inline constexpr Shape shape(const Scalar shapeFactor) noexcept
166{
167 if (shapeFactor < shapeFactorEquilateralTriangle<Scalar>())
169 else if (shapeFactor <= shapeFactorEquilateralTriangle<Scalar>())
171 else if (shapeFactor < shapeFactorSquare<Scalar>())
172 return Shape::rectangle;
173 else if (shapeFactor == shapeFactorSquare<Scalar>())
174 return Shape::square;
175 else if (shapeFactor == shapeFactorCircle<Scalar>())
176 return Shape::circle;
177 else
178 return Shape::polygon;
179}
180
183{
184 switch (shape)
185 {
186 case Shape::equilateralTriangle: return true;
187 case Shape::square: return true;
188 case Shape::circle: return true;
189 case Shape::rectangle: return false;
190 case Shape::scaleneTriangle: return false;
191 case Shape::polygon: DUNE_THROW(Dune::InvalidStateException, "Equality of Corner half angles for polygons must be determined explicitly");
192 default:
193 DUNE_THROW(Dune::InvalidStateException, "Unknown shape");
194 }
195}
196
198template<class Scalar>
199inline Scalar totalCrossSectionalArea(const Shape shape, const Scalar inscribedRadius)
200{
201 using std::sqrt;
202 switch(shape)
203 {
204 case Shape::equilateralTriangle: return 3.0*sqrt(3.0)*inscribedRadius*inscribedRadius;
205 case Shape::square: return 4.0*inscribedRadius*inscribedRadius;
206 case Shape::circle: return M_PI*inscribedRadius*inscribedRadius;
207 case Shape::twoPlates: return 2.0*inscribedRadius;
208 default : DUNE_THROW(Dune::InvalidStateException, "Unsupported geometry: " << shapeToString(shape));
209 }
210}
211
213template<class Scalar>
214inline constexpr Scalar totalCrossSectionalAreaForRectangle(const Scalar inscribedRadius, const Scalar height) noexcept
215{
216 return 2.0*inscribedRadius * height;
217}
218
220inline std::size_t numCorners(Shape shape)
221{
222 switch(shape)
223 {
224 case Shape::scaleneTriangle: return 3;
225 case Shape::equilateralTriangle: return 3;
226 case Shape::square: return 4;
227 case Shape::rectangle: return 4;
228 case Shape::circle: return 0;
229 default : DUNE_THROW(Dune::InvalidStateException, "Unsupported geometry: " << shapeToString(shape));
230 }
231}
232
242template<class Scalar>
243inline constexpr Scalar wettingLayerCrossSectionalArea(const Scalar curvatureRadius,
244 const Scalar contactAngle,
245 const Scalar cornerHalfAngle) noexcept
246{
247 using std::sin;
248 using std::cos;
249 return curvatureRadius*curvatureRadius *(cos(contactAngle) * cos(contactAngle + cornerHalfAngle) / sin(cornerHalfAngle)
250 + cornerHalfAngle + contactAngle - M_PI/2.0);
251}
252
253} // end Dumux::PoreNetwork::Throat
254
255#endif
Definition: throatproperties.hh:22
constexpr Scalar totalCrossSectionalAreaForRectangle(const Scalar inscribedRadius, const Scalar height) noexcept
Returns the cross-sectional area of a rectangle.
Definition: throatproperties.hh:214
constexpr Scalar shapeFactorSquare() noexcept
Returns the value of the shape factor for a square.
Definition: throatproperties.hh:125
constexpr Shape shape(const Scalar shapeFactor) noexcept
Returns the shape for a given shape factor.
Definition: throatproperties.hh:165
constexpr Scalar shapeFactorRectangle(const Scalar inscribedRadius, const Scalar height) noexcept
Returns the value of the shape factor for a rectangle.
Definition: throatproperties.hh:132
constexpr Scalar shapeFactorEquilateralTriangle() noexcept
Returns the value of the shape factor for an equilateral triangle.
Definition: throatproperties.hh:117
std::size_t numCorners(Shape shape)
Returns the number of corners of a given geometry.
Definition: throatproperties.hh:220
constexpr Scalar wettingLayerCrossSectionalArea(const Scalar curvatureRadius, const Scalar contactAngle, const Scalar cornerHalfAngle) noexcept
Return the cross-sectional area of a wetting layer residing in a corner of a throat.
Definition: throatproperties.hh:243
Dune::ReservedVector< Scalar, 4 > cornerHalfAngles(Shape shape)
Returns the corner half angle.
Definition: throatproperties.hh:85
Scalar totalCrossSectionalArea(const Shape shape, const Scalar inscribedRadius)
Returns the cross-sectional area of a given geometry.
Definition: throatproperties.hh:199
Shape shapeFromString(const std::string &s)
Get the shape from a string description of the shape.
Definition: throatproperties.hh:45
Shape
Collection of different pore-throat shapes.
Definition: throatproperties.hh:26
constexpr Scalar shapeFactorCircle() noexcept
Returns the value of the shape factor for a circle.
Definition: throatproperties.hh:143
Scalar shapeFactor(Shape shape, const Scalar inscribedRadius)
Returns the value of the shape factor for a given shape.
Definition: throatproperties.hh:150
std::string shapeToString(Shape s)
Get the shape from a string description of the shape.
Definition: throatproperties.hh:29
bool isRegularShape(Shape shape)
Returns if a shape is regular.
Definition: throatproperties.hh:182
Scalar averagedRadius(const Scalar poreRadiusOne, const Scalar poreRadiusTwo, const Scalar centerTocenterDist, const Scalar n=0.1)
Returns the radius of a pore throat.
Definition: throatproperties.hh:68