3.6-git
DUNE for Multi-{Phase, Component, Scale, Physics, ...} flow and transport in porous media
porenetwork/2p/fluxvariablescache.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_2P_FLUXVARIABLESCACHE_HH
25#define DUMUX_PNM_2P_FLUXVARIABLESCACHE_HH
26
27#include <array>
28#include <algorithm>
29#include <dune/common/reservedvector.hh>
31
32namespace Dumux::PoreNetwork {
33
39template<class AdvectionType, int maxNumCorners = 4>
41{
42 using Scalar = typename AdvectionType::Scalar;
43 static constexpr auto numPhases = 2;
44 using NumCornerVector = Dune::ReservedVector<Scalar, maxNumCorners>;
45
46public:
47
48 template<class Problem, class Element, class FVElementGeometry,
49 class ElementVolumeVariables, class SubControlVolumeFace>
50 void update(const Problem& problem,
51 const Element& element,
52 const FVElementGeometry& fvGeometry,
53 const ElementVolumeVariables& elemVolVars,
54 const SubControlVolumeFace& scvf,
55 bool invaded)
56 {
57 const auto eIdx = fvGeometry.gridGeometry().elementMapper().index(element);
58 throatCrossSectionShape_ = fvGeometry.gridGeometry().throatCrossSectionShape(eIdx);
59 throatShapeFactor_ = fvGeometry.gridGeometry().throatShapeFactor(eIdx);
60 pc_ = std::max(elemVolVars[0].capillaryPressure(), elemVolVars[1].capillaryPressure());
61 pcEntry_ = problem.spatialParams().pcEntry(element, elemVolVars);
62 pcSnapoff_ = problem.spatialParams().pcSnapoff(element, elemVolVars);
63 throatInscribedRadius_ = problem.spatialParams().throatInscribedRadius(element, elemVolVars);
64 throatLength_ = problem.spatialParams().throatLength(element, elemVolVars);
65 invaded_ = invaded;
66 poreToPoreDistance_ = element.geometry().volume();
67
68 // get the non-wetting phase index
69 using FluidSystem = typename ElementVolumeVariables::VolumeVariables::FluidSystem;
70 const auto& spatialParams = problem.spatialParams();
71 nPhaseIdx_ = 1 - spatialParams.template wettingPhase<FluidSystem>(element, elemVolVars);
72
73 // take the average surface tension of both adjacent pores TODO: is this correct?
74 surfaceTension_ = 0.5*(elemVolVars[0].surfaceTension() + elemVolVars[1].surfaceTension());
75
76 const auto& cornerHalfAngles = spatialParams.cornerHalfAngles(element);
77 wettingLayerArea_.clear(); wettingLayerArea_.resize(cornerHalfAngles.size());
78 const Scalar totalThroatCrossSectionalArea = spatialParams.throatCrossSectionalArea(element, elemVolVars);
79
80 if (invaded) // two-phase flow
81 {
82 const Scalar theta = spatialParams.contactAngle(element, elemVolVars);
83 for (int i = 0; i< cornerHalfAngles.size(); ++i)
85
86 // make sure the wetting phase area does not exceed the total cross-section area
87 throatCrossSectionalArea_[wPhaseIdx()] = std::min(
88 std::accumulate(wettingLayerArea_.begin(), wettingLayerArea_.end(), 0.0),
89 totalThroatCrossSectionalArea
90 );
91 throatCrossSectionalArea_[nPhaseIdx()] = totalThroatCrossSectionalArea - throatCrossSectionalArea_[wPhaseIdx()];
92 }
93 else // single-phase flow
94 {
95 for (int i = 0; i< cornerHalfAngles.size(); ++i)
96 wettingLayerArea_[i] = 0.0;
97
98 throatCrossSectionalArea_[wPhaseIdx()] = totalThroatCrossSectionalArea;
99 throatCrossSectionalArea_[nPhaseIdx()] = 0.0;
100 }
101
102 for (int phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx)
103 {
104 singlePhaseCache_.fill(problem, element, fvGeometry, scvf, elemVolVars, *this, phaseIdx);
105 nonWettingPhaseCache_.fill(problem, element, fvGeometry, scvf, elemVolVars, *this, phaseIdx);
106 wettingLayerCache_.fill(problem, element, fvGeometry, scvf, elemVolVars, *this, phaseIdx);
107 }
108
109 for (int phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx)
110 {
111 transmissibility_[phaseIdx] = AdvectionType::calculateTransmissibility(
112 problem, element, fvGeometry, scvf, elemVolVars, *this, phaseIdx
113 );
114 }
115 }
116
121 { return throatCrossSectionShape_; }
122
126 Scalar throatShapeFactor() const
127 { return throatShapeFactor_; }
128
132 Scalar transmissibility(const int phaseIdx) const
133 { return transmissibility_[phaseIdx]; }
134
138 Scalar throatCrossSectionalArea(const int phaseIdx) const
139 { return throatCrossSectionalArea_[phaseIdx]; }
140
145 { return throatCrossSectionalArea_[0] + throatCrossSectionalArea_[1]; }
146
150 Scalar throatLength() const
151 { return throatLength_; }
152
157 { return throatInscribedRadius_; }
158
162 Scalar pcEntry() const
163 { return pcEntry_; }
164
168 Scalar pcSnapoff() const
169 { return pcSnapoff_; }
170
174 Scalar pc() const
175 { return pc_; }
176
180 Scalar surfaceTension() const
181 { return surfaceTension_; }
182
186 bool invaded() const
187 { return invaded_; }
188
192 Scalar curvatureRadius() const
193 { return surfaceTension_ / pc_;}
194
199 Scalar wettingLayerCrossSectionalArea(const int cornerIdx) const
200 { return wettingLayerArea_[cornerIdx]; }
201
205 std::size_t wPhaseIdx() const
206 { return 1 - nPhaseIdx_; }
207
211 std::size_t nPhaseIdx() const
212 { return nPhaseIdx_; }
213
217 const auto& singlePhaseFlowVariables() const
218 { return singlePhaseCache_; }
219
224 { return nonWettingPhaseCache_; }
225
229 const auto& wettingLayerFlowVariables() const
230 { return wettingLayerCache_; }
231
235 Scalar poreToPoreDistance() const
236 { return poreToPoreDistance_; }
237
238private:
239 Throat::Shape throatCrossSectionShape_;
240 Scalar throatShapeFactor_;
241 std::array<Scalar, numPhases> transmissibility_;
242 std::array<Scalar, numPhases> throatCrossSectionalArea_;
243 Scalar throatLength_;
244 Scalar throatInscribedRadius_;
245 Scalar pcEntry_;
246 Scalar pcSnapoff_;
247 Scalar pc_;
248 Scalar surfaceTension_;
249 bool invaded_;
250 NumCornerVector wettingLayerArea_;
251 std::size_t nPhaseIdx_;
252 Scalar poreToPoreDistance_;
253
254 typename AdvectionType::Transmissibility::SinglePhaseCache singlePhaseCache_;
255 typename AdvectionType::Transmissibility::NonWettingPhaseCache nonWettingPhaseCache_;
256 typename AdvectionType::Transmissibility::WettingLayerCache wettingLayerCache_;
257};
258
259} // end Dumux::PoreNetwork
260
261#endif
This file contains functions related to calculate pore-throat properties.
Definition: discretization/porenetwork/fvelementgeometry.hh:34
std::string capillaryPressure() noexcept
I/O name of capillary pressure.
Definition: name.hh:135
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:255
Dune::ReservedVector< Scalar, 4 > cornerHalfAngles(Shape shape)
Returns the corner half angle.
Definition: throatproperties.hh:97
Shape
Collection of different pore-throat shapes.
Definition: throatproperties.hh:38
Flux variables cache for the two-phase-flow PNM Store data required for flux calculation.
Definition: porenetwork/2p/fluxvariablescache.hh:41
Scalar throatCrossSectionalArea() const
Returns the throats's total cross-sectional area.
Definition: porenetwork/2p/fluxvariablescache.hh:144
Scalar pc() const
Returns the capillary pressure within the throat.
Definition: porenetwork/2p/fluxvariablescache.hh:174
bool invaded() const
Returns true if the throat is invaded by the nonwetting phase.
Definition: porenetwork/2p/fluxvariablescache.hh:186
Scalar poreToPoreDistance() const
Returns the throats's pore-to-pore-center distance.
Definition: porenetwork/2p/fluxvariablescache.hh:235
Scalar wettingLayerCrossSectionalArea(const int cornerIdx) const
Returns the cross-sectional area of a wetting layer within one of the throat's corners.
Definition: porenetwork/2p/fluxvariablescache.hh:199
const auto & nonWettingPhaseFlowVariables() const
Returns the throats's cached flow variables for the nonwetting phase.
Definition: porenetwork/2p/fluxvariablescache.hh:223
Scalar curvatureRadius() const
Returns the curvature radius within the throat.
Definition: porenetwork/2p/fluxvariablescache.hh:192
Scalar throatCrossSectionalArea(const int phaseIdx) const
Returns the throats's cross-sectional area for a given phaseIdx.
Definition: porenetwork/2p/fluxvariablescache.hh:138
Scalar transmissibility(const int phaseIdx) const
Returns the throats's transmissibility.
Definition: porenetwork/2p/fluxvariablescache.hh:132
Scalar pcSnapoff() const
Returns the throats's snap-off capillary pressure.
Definition: porenetwork/2p/fluxvariablescache.hh:168
Scalar throatLength() const
Returns the throats's length.
Definition: porenetwork/2p/fluxvariablescache.hh:150
Throat::Shape throatCrossSectionShape() const
Returns the throats's cross-sectional shape.
Definition: porenetwork/2p/fluxvariablescache.hh:120
Scalar throatShapeFactor() const
Returns the throats's shape factor.
Definition: porenetwork/2p/fluxvariablescache.hh:126
const auto & singlePhaseFlowVariables() const
Returns the throats's cached flow variables for single-phase flow.
Definition: porenetwork/2p/fluxvariablescache.hh:217
Scalar pcEntry() const
Returns the throats's entry capillary pressure.
Definition: porenetwork/2p/fluxvariablescache.hh:162
Scalar throatInscribedRadius() const
Returns the throats's inscribed radius.
Definition: porenetwork/2p/fluxvariablescache.hh:156
std::size_t nPhaseIdx() const
Returns the index of the nonwetting phase.
Definition: porenetwork/2p/fluxvariablescache.hh:211
Scalar surfaceTension() const
Returns the surface tension within the throat.
Definition: porenetwork/2p/fluxvariablescache.hh:180
std::size_t wPhaseIdx() const
Returns the index of the wetting phase.
Definition: porenetwork/2p/fluxvariablescache.hh:205
void update(const Problem &problem, const Element &element, const FVElementGeometry &fvGeometry, const ElementVolumeVariables &elemVolVars, const SubControlVolumeFace &scvf, bool invaded)
Definition: porenetwork/2p/fluxvariablescache.hh:50
const auto & wettingLayerFlowVariables() const
Returns the throats's cached flow variables for the wetting phase.
Definition: porenetwork/2p/fluxvariablescache.hh:229