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-FileCopyrightText: 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 | 28523768 | 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 | if (fvGeometry.gridGeometry().vertexUsesSecondaryInteractionVolume(scvf.vertexIndex())) | ||
67 | scvfFluxVarsCache.updateHeatConduction(fluxVarsCacheFiller.secondaryInteractionVolume(), | ||
68 | fluxVarsCacheFiller.secondaryIvLocalFaceData(), | ||
69 | fluxVarsCacheFiller.secondaryIvDataHandle()); | ||
70 | else | ||
71 | 28523768 | scvfFluxVarsCache.updateHeatConduction(fluxVarsCacheFiller.primaryInteractionVolume(), | |
72 | 28523768 | fluxVarsCacheFiller.primaryIvLocalFaceData(), | |
73 | 28523768 | 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 | 28523768 | void setHandlePointer_(const PrimaryDataHandle& dataHandle) | |
94 | 28523768 | { 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 | 28523768 | void updateHeatConduction(const IV& iv, | |
110 | const LocalFaceData& localFaceData, | ||
111 | const DataHandle& dataHandle) | ||
112 | { | ||
113 | 28523768 | switchFluxSign_ = localFaceData.isOutsideFace(); | |
114 | 28523768 | stencil_ = &iv.stencil(); | |
115 | 28523768 | 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 | 17279840 | 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 | 17279840 | 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 | 17279840 | 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 | 17279840 | 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 | 17279840 | return flux_(problem, fluxVarsCache, fluxVarsCache.heatConductionPrimaryDataHandle()); | |
168 | } | ||
169 | |||
170 | private: | ||
171 | template< class Problem, class FluxVarsCache, class DataHandle > | ||
172 | 17279840 | static Scalar flux_(const Problem& problem, | |
173 | const FluxVarsCache& cache, | ||
174 | const DataHandle& dataHandle) | ||
175 | { | ||
176 |
2/2✓ Branch 0 taken 5419480 times.
✓ Branch 1 taken 4951208 times.
|
17279840 | const bool switchSign = cache.heatConductionSwitchFluxSign(); |
177 | |||
178 |
2/2✓ Branch 0 taken 5419480 times.
✓ Branch 1 taken 4951208 times.
|
17279840 | const auto localFaceIdx = cache.ivLocalFaceIndex(); |
179 | 17279840 | const auto idxInOutside = cache.indexInOutsideFaces(); | |
180 |
2/2✓ Branch 0 taken 5419480 times.
✓ Branch 1 taken 4951208 times.
|
17279840 | const auto& Tj = dataHandle.uj(); |
181 |
2/2✓ Branch 0 taken 5419480 times.
✓ Branch 1 taken 4951208 times.
|
17279840 | const auto& tij = dim == dimWorld ? dataHandle.T()[localFaceIdx] |
182 | 5419480 | : (!switchSign ? dataHandle.T()[localFaceIdx] | |
183 | 4951208 | : dataHandle.tijOutside()[localFaceIdx][idxInOutside]); | |
184 | 17279840 | Scalar scvfFlux = tij*Tj; | |
185 | |||
186 | // switch the sign if necessary | ||
187 |
2/2✓ Branch 0 taken 8289592 times.
✓ Branch 1 taken 8990248 times.
|
17279840 | if (switchSign) |
188 | 8289592 | scvfFlux *= -1.0; | |
189 | |||
190 | 17279840 | return scvfFlux; | |
191 | } | ||
192 | }; | ||
193 | |||
194 | } // end namespace Dumux | ||
195 | |||
196 | #endif | ||
197 |