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 CCMpfaFlux |
10 |
|
|
* \brief Fourier's law for cell-centered finite volume schemes with multi-point flux approximation |
11 |
|
|
*/ |
12 |
|
|
#ifndef DUMUX_DISCRETIZATION_CC_MPFA_FOURIERS_LAW_HH |
13 |
|
|
#define DUMUX_DISCRETIZATION_CC_MPFA_FOURIERS_LAW_HH |
14 |
|
|
|
15 |
|
|
#include <dune/common/dynvector.hh> |
16 |
|
|
#include <dune/common/dynmatrix.hh> |
17 |
|
|
|
18 |
|
|
#include <dumux/common/properties.hh> |
19 |
|
|
#include <dumux/discretization/method.hh> |
20 |
|
|
|
21 |
|
|
namespace Dumux { |
22 |
|
|
|
23 |
|
|
//! forward declaration of the method-specific implementation |
24 |
|
|
template<class TypeTag, class DiscretizationMethod> |
25 |
|
|
class FouriersLawImplementation; |
26 |
|
|
|
27 |
|
|
/*! |
28 |
|
|
* \ingroup CCMpfaFlux |
29 |
|
|
* \brief Fourier's law for cell-centered finite volume schemes with multi-point flux approximation |
30 |
|
|
*/ |
31 |
|
|
template <class TypeTag> |
32 |
|
|
class FouriersLawImplementation<TypeTag, DiscretizationMethods::CCMpfa> |
33 |
|
|
{ |
34 |
|
|
using Scalar = GetPropType<TypeTag, Properties::Scalar>; |
35 |
|
|
using Problem = GetPropType<TypeTag, Properties::Problem>; |
36 |
|
|
using GridView = typename GetPropType<TypeTag, Properties::GridGeometry>::GridView; |
37 |
|
|
using Element = typename GridView::template Codim<0>::Entity; |
38 |
|
|
|
39 |
|
|
static constexpr int dim = GridView::dimension; |
40 |
|
|
static constexpr int dimWorld = GridView::dimensionworld; |
41 |
|
|
|
42 |
|
|
using GridGeometry = GetPropType<TypeTag, Properties::GridGeometry>; |
43 |
|
|
using FVElementGeometry = typename GridGeometry::LocalView; |
44 |
|
|
using SubControlVolumeFace = typename FVElementGeometry::SubControlVolumeFace; |
45 |
|
|
using ElementVolumeVariables = typename GetPropType<TypeTag, Properties::GridVolumeVariables>::LocalView; |
46 |
|
|
using GridFluxVariablesCache = GetPropType<TypeTag, Properties::GridFluxVariablesCache>; |
47 |
|
|
using ElementFluxVarsCache = typename GridFluxVariablesCache::LocalView; |
48 |
|
|
using FluxVariablesCache = typename GridFluxVariablesCache::FluxVariablesCache; |
49 |
|
|
|
50 |
|
|
//! Class that fills the cache corresponding to mpfa Darcy's Law |
51 |
|
|
class MpfaFouriersLawCacheFiller |
52 |
|
|
{ |
53 |
|
|
public: |
54 |
|
|
//! Function to fill an MpfaDarcysLawCache of a given scvf |
55 |
|
|
//! This interface has to be met by any cache filler class for heat conduction quantities |
56 |
|
|
template<class FluxVariablesCacheFiller> |
57 |
|
✗ |
static void fill(FluxVariablesCache& scvfFluxVarsCache, |
58 |
|
|
const Problem& problem, |
59 |
|
|
const Element& element, |
60 |
|
|
const FVElementGeometry& fvGeometry, |
61 |
|
|
const ElementVolumeVariables& elemVolVars, |
62 |
|
|
const SubControlVolumeFace& scvf, |
63 |
|
|
const FluxVariablesCacheFiller& fluxVarsCacheFiller) |
64 |
|
|
{ |
65 |
|
|
// get interaction volume from the flux vars cache filler & update the cache |
66 |
|
20111872 |
if (fvGeometry.gridGeometry().vertexUsesSecondaryInteractionVolume(scvf.vertexIndex())) |
67 |
|
|
scvfFluxVarsCache.updateHeatConduction(fluxVarsCacheFiller.secondaryInteractionVolume(), |
68 |
|
|
fluxVarsCacheFiller.secondaryIvLocalFaceData(), |
69 |
|
|
fluxVarsCacheFiller.secondaryIvDataHandle()); |
70 |
|
|
else |
71 |
|
20111872 |
scvfFluxVarsCache.updateHeatConduction(fluxVarsCacheFiller.primaryInteractionVolume(), |
72 |
|
|
fluxVarsCacheFiller.primaryIvLocalFaceData(), |
73 |
|
|
fluxVarsCacheFiller.primaryIvDataHandle()); |
74 |
|
✗ |
} |
75 |
|
|
}; |
76 |
|
|
|
77 |
|
|
//! The cache used in conjunction with the mpfa Fourier's Law |
78 |
|
|
class MpfaFouriersLawCache |
79 |
|
|
{ |
80 |
|
|
using DualGridNodalIndexSet = GetPropType<TypeTag, Properties::DualGridNodalIndexSet>; |
81 |
|
|
using Stencil = typename DualGridNodalIndexSet::NodalGridStencilType; |
82 |
|
|
|
83 |
|
|
static constexpr bool considerSecondaryIVs = GridGeometry::MpfaHelper::considerSecondaryIVs(); |
84 |
|
|
using PrimaryDataHandle = typename ElementFluxVarsCache::PrimaryIvDataHandle::HeatConductionHandle; |
85 |
|
|
using SecondaryDataHandle = typename ElementFluxVarsCache::SecondaryIvDataHandle::HeatConductionHandle; |
86 |
|
|
|
87 |
|
|
//! sets the pointer to the data handle (overload for secondary data handles) |
88 |
|
|
template< bool doSecondary = considerSecondaryIVs, std::enable_if_t<doSecondary, int> = 0 > |
89 |
|
|
void setHandlePointer_(const SecondaryDataHandle& dataHandle) |
90 |
|
|
{ secondaryHandlePtr_ = &dataHandle; } |
91 |
|
|
|
92 |
|
|
//! sets the pointer to the data handle (overload for primary data handles) |
93 |
|
✗ |
void setHandlePointer_(const PrimaryDataHandle& dataHandle) |
94 |
|
20111872 |
{ primaryHandlePtr_ = &dataHandle; } |
95 |
|
|
|
96 |
|
|
public: |
97 |
|
|
// export filler type |
98 |
|
|
using Filler = MpfaFouriersLawCacheFiller; |
99 |
|
|
|
100 |
|
|
/*! |
101 |
|
|
* \brief Update cached objects (transmissibilities). |
102 |
|
|
* This is used for updates with primary interaction volumes. |
103 |
|
|
* |
104 |
|
|
* \param iv The interaction volume this scvf is embedded in |
105 |
|
|
* \param localFaceData iv-local info on this scvf |
106 |
|
|
* \param dataHandle Transmissibility matrix & gravity data of this iv |
107 |
|
|
*/ |
108 |
|
|
template<class IV, class LocalFaceData, class DataHandle> |
109 |
|
|
void updateHeatConduction(const IV& iv, |
110 |
|
|
const LocalFaceData& localFaceData, |
111 |
|
|
const DataHandle& dataHandle) |
112 |
|
|
{ |
113 |
|
20111872 |
switchFluxSign_ = localFaceData.isOutsideFace(); |
114 |
|
20111872 |
stencil_ = &iv.stencil(); |
115 |
|
40223744 |
setHandlePointer_(dataHandle.heatConductionHandle()); |
116 |
|
|
} |
117 |
|
|
|
118 |
|
|
//! The stencil corresponding to the transmissibilities (primary type) |
119 |
|
|
const Stencil& heatConductionStencil() const { return *stencil_; } |
120 |
|
|
|
121 |
|
|
//! The corresponding data handles |
122 |
|
✗ |
const PrimaryDataHandle& heatConductionPrimaryDataHandle() const { return *primaryHandlePtr_; } |
123 |
|
✗ |
const SecondaryDataHandle& heatConductionSecondaryDataHandle() const { return *secondaryHandlePtr_; } |
124 |
|
|
|
125 |
|
|
//! Returns whether or not this scvf is an "outside" face in the scope of the iv. |
126 |
|
✗ |
bool heatConductionSwitchFluxSign() const { return switchFluxSign_; } |
127 |
|
|
|
128 |
|
|
private: |
129 |
|
|
bool switchFluxSign_; |
130 |
|
|
|
131 |
|
|
//! pointers to the corresponding iv-data handles |
132 |
|
|
const PrimaryDataHandle* primaryHandlePtr_; |
133 |
|
|
const SecondaryDataHandle* secondaryHandlePtr_; |
134 |
|
|
|
135 |
|
|
//! The stencil, i.e. the grid indices j |
136 |
|
|
const Stencil* stencil_; |
137 |
|
|
}; |
138 |
|
|
|
139 |
|
|
public: |
140 |
|
|
using DiscretizationMethod = DiscretizationMethods::CCMpfa; |
141 |
|
|
// state the discretization method this implementation belongs to |
142 |
|
|
static constexpr DiscretizationMethod discMethod{}; |
143 |
|
|
|
144 |
|
|
// state the type for the corresponding cache and its filler |
145 |
|
|
using Cache = MpfaFouriersLawCache; |
146 |
|
|
|
147 |
|
|
/*! |
148 |
|
|
* \brief Returns the heat flux within the porous medium |
149 |
|
|
* (in J/s) across the given sub-control volume face. |
150 |
|
|
* \note This law assumes thermal equilibrium between the fluid |
151 |
|
|
* and solid phases, and uses an effective thermal conductivity |
152 |
|
|
* for the overall aggregate. |
153 |
|
|
*/ |
154 |
|
✗ |
static Scalar flux(const Problem& problem, |
155 |
|
|
const Element& element, |
156 |
|
|
const FVElementGeometry& fvGeometry, |
157 |
|
|
const ElementVolumeVariables& elemVolVars, |
158 |
|
|
const SubControlVolumeFace& scvf, |
159 |
|
|
const ElementFluxVarsCache& elemFluxVarsCache) |
160 |
|
|
{ |
161 |
|
✗ |
const auto& fluxVarsCache = elemFluxVarsCache[scvf]; |
162 |
|
|
|
163 |
|
|
// forward to the private function taking the iv data handle |
164 |
|
✗ |
if (fluxVarsCache.usesSecondaryIv()) |
165 |
|
|
return flux_(problem, fluxVarsCache, fluxVarsCache.heatConductionSecondaryDataHandle()); |
166 |
|
|
else |
167 |
|
✗ |
return flux_(problem, fluxVarsCache, fluxVarsCache.heatConductionPrimaryDataHandle()); |
168 |
|
|
} |
169 |
|
|
|
170 |
|
|
private: |
171 |
|
|
template< class Problem, class FluxVarsCache, class DataHandle > |
172 |
|
✗ |
static Scalar flux_(const Problem& problem, |
173 |
|
|
const FluxVarsCache& cache, |
174 |
|
|
const DataHandle& dataHandle) |
175 |
|
|
{ |
176 |
|
✗ |
const bool switchSign = cache.heatConductionSwitchFluxSign(); |
177 |
|
|
|
178 |
|
✗ |
const auto localFaceIdx = cache.ivLocalFaceIndex(); |
179 |
|
✗ |
const auto idxInOutside = cache.indexInOutsideFaces(); |
180 |
|
✗ |
const auto& Tj = dataHandle.uj(); |
181 |
|
✗ |
const auto& tij = dim == dimWorld ? dataHandle.T()[localFaceIdx] |
182 |
|
✗ |
: (!switchSign ? dataHandle.T()[localFaceIdx] |
183 |
|
✗ |
: dataHandle.tijOutside()[localFaceIdx][idxInOutside]); |
184 |
|
✗ |
Scalar scvfFlux = tij*Tj; |
185 |
|
|
|
186 |
|
|
// switch the sign if necessary |
187 |
|
✗ |
if (switchSign) |
188 |
|
✗ |
scvfFlux *= -1.0; |
189 |
|
|
|
190 |
|
✗ |
return scvfFlux; |
191 |
|
|
} |
192 |
|
|
}; |
193 |
|
|
|
194 |
|
|
} // end namespace Dumux |
195 |
|
|
|
196 |
|
|
#endif |
197 |
|
|
|