3.4
DUNE for Multi-{Phase, Component, Scale, Physics, ...} flow and transport in porous media
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 * See the file COPYING for full copying permissions. *
5 * *
6 * This program is free software: you can redistribute it and/or modify *
7 * it under the terms of the GNU General Public License as published by *
8 * the Free Software Foundation, either version 3 of the License, or *
9 * (at your option) any later version. *
10 * *
11 * This program is distributed in the hope that it will be useful, *
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
14 * GNU General Public License for more details. *
15 * *
16 * You should have received a copy of the GNU General Public License *
17 * along with this program. If not, see <http://www.gnu.org/licenses/>. *
18 *****************************************************************************/
24#ifndef DUMUX_PNM_BASE_THROAT_PROPERTIES_HH
25#define DUMUX_PNM_BASE_THROAT_PROPERTIES_HH
26
27#include <string>
28#include <cmath>
29#include <numeric>
30
31#include <dune/common/exceptions.hh>
32#include <dune/common/reservedvector.hh>
33
35
37enum class Shape
39
41inline std::string shapeToString(Shape s)
42{
43 switch (s)
44 {
45 case Shape::scaleneTriangle: return "ScaleneTriangle";
46 case Shape::equilateralTriangle: return "EquilateralTriangle";
47 case Shape::square: return "Square";
48 case Shape::rectangle: return "Rectangle";
49 case Shape::circle: return "Circle";
50 case Shape::twoPlates: return "TwoPlates";
51 case Shape::polygon: return "Polygon";
52 default: DUNE_THROW(Dune::InvalidStateException, "Unknown shape!");
53 }
54}
55
57inline Shape shapeFromString(const std::string& s)
58{
61 else if (s == shapeToString(Shape::square)) return Shape::square;
62 else if (s == shapeToString(Shape::rectangle)) return Shape::rectangle;
63 else if (s == shapeToString(Shape::circle)) return Shape::circle;
64 else if (s == shapeToString(Shape::twoPlates)) return Shape::twoPlates;
65 else if (s == shapeToString(Shape::polygon)) return Shape::polygon;
66 else DUNE_THROW(Dune::InvalidStateException, s << " is not a valid shape");
67}
68
79template<class Scalar>
80inline Scalar averagedRadius(const Scalar poreRadiusOne, const Scalar poreRadiusTwo, const Scalar centerTocenterDist, const Scalar n = 0.1)
81{
82 assert(n > 0.0);
83 using std::sin; using std::cos; using std::pow;
84 const Scalar rOneTilde = poreRadiusOne/centerTocenterDist;
85 const Scalar rTwoTilde = poreRadiusTwo/centerTocenterDist;
86 const Scalar a = sin(M_PI/4.0);
87 const Scalar b = cos(M_PI/4.0);
88 const Scalar rhoOne = rOneTilde*a / pow((1.0 - rOneTilde*b), n);
89 const Scalar rhoTwo = rTwoTilde*a / pow((1.0 - rTwoTilde*b), n);
90 const Scalar rTilde = rhoOne*rhoTwo * pow((pow(rhoOne, 1.0/n) + pow(rhoTwo, 1.0/n)), -n);
91 return rTilde * centerTocenterDist;
92}
93
94
96template<class Scalar>
97inline Dune::ReservedVector<Scalar, 4> cornerHalfAngles(Shape shape)
98{
99 switch(shape)
100 {
102 {
103 const Scalar value = M_PI/6.0;
104 return Dune::ReservedVector<Scalar, 4>{value, value, value};
105 }
106 case Shape::square:
107 {
108 const Scalar value = M_PI/4.0;
109 return Dune::ReservedVector<Scalar, 4>{value, value, value, value};
110 }
111 case Shape::rectangle:
112 {
113 const Scalar value = M_PI/4.0;
114 return Dune::ReservedVector<Scalar, 4>{value, value, value, value};
115 }
116 case Shape::circle:
117 {
118 return Dune::ReservedVector<Scalar, 4>{};
119 }
120 case Shape::polygon: DUNE_THROW(Dune::InvalidStateException, "Corner half angles for polygons must be calculated explicitly");
121 default: DUNE_THROW(Dune::InvalidStateException, "Unkown shape");
122 // TODO implement angles for scaleneTriangle as given by Valvatne & Blunt (2004)
123 }
124}
125
127template<class Scalar>
128inline constexpr Scalar shapeFactorEquilateralTriangle() noexcept
129{
130 using std::sqrt;
131 return sqrt(3.0)/36.0;
132}
133
135template<class Scalar>
136inline constexpr Scalar shapeFactorSquare() noexcept
137{
138 return 1.0/16.0;
139}
140
142template<class Scalar>
143inline constexpr Scalar shapeFactorRectangle(const Scalar inscribedRadius, const Scalar height) noexcept
144{
145 const Scalar a = 2.0*inscribedRadius; // shorter side length
146 const Scalar b = height; // longer side length
147 const Scalar area = a*b;
148 const Scalar perimeter = 2.0*a + 2.0*b;
149 return area / (perimeter*perimeter);
150}
151
153template<class Scalar>
154inline constexpr Scalar shapeFactorCircle() noexcept
155{
156 return 1.0/(4.0*M_PI);
157}
158
160template<class Scalar>
161inline Scalar shapeFactor(Shape shape, const Scalar inscribedRadius)
162{
163 switch(shape)
164 {
165 case Shape::equilateralTriangle: return shapeFactorEquilateralTriangle<Scalar>();
166 case Shape::square: return shapeFactorSquare<Scalar>();
167 case Shape::circle: return shapeFactorCircle<Scalar>();
168 case Shape::twoPlates: return 0.0; // TODO is this a good idea?
169 case Shape::polygon: DUNE_THROW(Dune::InvalidStateException, "The shape factor for a polygon has to be defined by the input data");
170 default: DUNE_THROW(Dune::InvalidStateException, "Unkown shape");
171 }
172}
173
175template<class Scalar>
176inline constexpr Shape shape(const Scalar shapeFactor) noexcept
177{
178 if (shapeFactor < shapeFactorEquilateralTriangle<Scalar>())
180 else if (shapeFactor <= shapeFactorEquilateralTriangle<Scalar>())
182 else if (shapeFactor < shapeFactorSquare<Scalar>())
183 return Shape::rectangle;
184 else if (shapeFactor == shapeFactorSquare<Scalar>())
185 return Shape::square;
186 else if (shapeFactor == shapeFactorCircle<Scalar>())
187 return Shape::circle;
188 else
189 return Shape::polygon;
190}
191
193template<class Scalar>
194inline Scalar totalCrossSectionalArea(const Shape shape, const Scalar inscribedRadius)
195{
196 using std::sqrt;
197 switch(shape)
198 {
199 case Shape::equilateralTriangle: return 3.0*sqrt(3.0)*inscribedRadius*inscribedRadius;
200 case Shape::square: return 4.0*inscribedRadius*inscribedRadius;
201 case Shape::circle: return M_PI*inscribedRadius*inscribedRadius;
202 case Shape::twoPlates: return 2.0*inscribedRadius;
203 default : DUNE_THROW(Dune::InvalidStateException, "Unsupported geometry: " << shapeToString(shape));
204 }
205}
206
208template<class Scalar>
209inline constexpr Scalar totalCrossSectionalAreaForRectangle(const Scalar inscribedRadius, const Scalar height) noexcept
210{
211 return 2.0*inscribedRadius * height;
212}
213
215inline std::size_t numCorners(Shape shape)
216{
217 switch(shape)
218 {
219 case Shape::scaleneTriangle: return 3;
220 case Shape::equilateralTriangle: return 3;
221 case Shape::square: return 4;
222 case Shape::rectangle: return 4;
223 case Shape::circle: return 0;
224 default : DUNE_THROW(Dune::InvalidStateException, "Unsupported geometry: " << shapeToString(shape));
225 }
226}
227
237template<class Scalar>
238inline constexpr Scalar wettingLayerCrossSectionalArea(const Scalar curvatureRadius,
239 const Scalar contactAngle,
240 const Scalar cornerHalfAngle) noexcept
241{
242 using std::sin;
243 using std::cos;
244 return curvatureRadius*curvatureRadius *(cos(contactAngle) * cos(contactAngle + cornerHalfAngle) / sin(cornerHalfAngle)
245 + cornerHalfAngle + contactAngle - M_PI/2.0);
246}
247
248} // end Dumux::PoreNetwork::Throat
249
250#endif
Definition: throatproperties.hh:34
constexpr Scalar totalCrossSectionalAreaForRectangle(const Scalar inscribedRadius, const Scalar height) noexcept
Returns the cross-sectional area of a rectangle.
Definition: throatproperties.hh:209
constexpr Scalar shapeFactorSquare() noexcept
Returns the value of the shape factor for a square.
Definition: throatproperties.hh:136
constexpr Shape shape(const Scalar shapeFactor) noexcept
Returns the shape for a given shape factor.
Definition: throatproperties.hh:176
constexpr Scalar shapeFactorRectangle(const Scalar inscribedRadius, const Scalar height) noexcept
Returns the value of the shape factor for a rectangle.
Definition: throatproperties.hh:143
constexpr Scalar shapeFactorEquilateralTriangle() noexcept
Returns the value of the shape factor for an equilateral triangle.
Definition: throatproperties.hh:128
std::size_t numCorners(Shape shape)
Returns the number of corners of a given geometry.
Definition: throatproperties.hh:215
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:238
Dune::ReservedVector< Scalar, 4 > cornerHalfAngles(Shape shape)
Returns the corner half angle.
Definition: throatproperties.hh:97
Scalar totalCrossSectionalArea(const Shape shape, const Scalar inscribedRadius)
Returns the cross-sectional area of a given geometry.
Definition: throatproperties.hh:194
Shape shapeFromString(const std::string &s)
Get the shape from a string description of the shape.
Definition: throatproperties.hh:57
Shape
Collection of different pore-throat shapes.
Definition: throatproperties.hh:38
constexpr Scalar shapeFactorCircle() noexcept
Returns the value of the shape factor for a cicle.
Definition: throatproperties.hh:154
Scalar shapeFactor(Shape shape, const Scalar inscribedRadius)
Returns the value of the shape factor for a given shape.
Definition: throatproperties.hh:161
std::string shapeToString(Shape s)
Get the shape from a string description of the shape.
Definition: throatproperties.hh:41
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:80