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 FreeFlowPoreNetworkCoupling | ||
10 | * \copydoc Dumux::FreeFlowPoreNetworkCouplingManager | ||
11 | */ | ||
12 | |||
13 | #ifndef DUMUX_MULTIDOMAIN_BOUNDARY_FREEFLOW_PORENETWORK_COUPLINGMANAGER_HH | ||
14 | #define DUMUX_MULTIDOMAIN_BOUNDARY_FREEFLOW_PORENETWORK_COUPLINGMANAGER_HH | ||
15 | |||
16 | #include <utility> | ||
17 | #include <memory> | ||
18 | |||
19 | #include <dune/common/indices.hh> | ||
20 | #include <dumux/common/properties.hh> | ||
21 | #include <dumux/multidomain/boundary/freeflowporenetwork/ffmassporenetwork/couplingmanager.hh> | ||
22 | #include <dumux/multidomain/boundary/freeflowporenetwork/ffmomentumporenetwork/couplingmanager.hh> | ||
23 | #include <dumux/multidomain/freeflow/couplingmanager.hh> | ||
24 | #include <dumux/multidomain/multibinarycouplingmanager.hh> | ||
25 | |||
26 | #include "couplingconditions.hh" | ||
27 | #include "couplingmapper.hh" | ||
28 | |||
29 | namespace Dumux { | ||
30 | |||
31 | namespace FreeFlowPoreNetworkDetail { | ||
32 | |||
33 | // global subdomain indices | ||
34 | static constexpr auto freeFlowMomentumIndex = Dune::index_constant<0>(); | ||
35 | static constexpr auto freeFlowMassIndex = Dune::index_constant<1>(); | ||
36 | static constexpr auto poreNetworkIndex = Dune::index_constant<2>(); | ||
37 | |||
38 | // coupling indices | ||
39 | static constexpr auto freeFlowMassToFreeFlowMomentumIndex = Dune::index_constant<0>(); | ||
40 | static constexpr auto freeFlowMomentumToPoreNetworkIndex = Dune::index_constant<1>(); | ||
41 | static constexpr auto freeFlowMassToPoreNetworkIndex = Dune::index_constant<2>(); | ||
42 | static constexpr auto noCouplingIdx = Dune::index_constant<99>(); | ||
43 | |||
44 | constexpr auto makeCouplingManagerMap() | ||
45 | { | ||
46 | auto map = std::array<std::array<std::size_t, 3>, 3>{}; | ||
47 | |||
48 | // free flow (momentum-mass) | ||
49 | map[freeFlowMomentumIndex][freeFlowMassIndex] = freeFlowMassToFreeFlowMomentumIndex; | ||
50 | map[freeFlowMassIndex][freeFlowMomentumIndex] = freeFlowMassToFreeFlowMomentumIndex; | ||
51 | |||
52 | // free flow momentum - porous medium | ||
53 | map[freeFlowMomentumIndex][poreNetworkIndex] = freeFlowMomentumToPoreNetworkIndex; | ||
54 | map[poreNetworkIndex][freeFlowMomentumIndex] = freeFlowMomentumToPoreNetworkIndex; | ||
55 | |||
56 | // free flow mass - porous medium | ||
57 | map[freeFlowMassIndex][poreNetworkIndex] = freeFlowMassToPoreNetworkIndex; | ||
58 | map[poreNetworkIndex][freeFlowMassIndex] = freeFlowMassToPoreNetworkIndex; | ||
59 | |||
60 | return map; | ||
61 | } | ||
62 | |||
63 | template<std::size_t i> | ||
64 | ✗ | constexpr auto coupledDomains(Dune::index_constant<i> domainI) | |
65 | { | ||
66 | if constexpr (i == freeFlowMomentumIndex) | ||
67 | 68410 | return std::make_tuple(freeFlowMassIndex, poreNetworkIndex); | |
68 | else if constexpr (i == freeFlowMassIndex) | ||
69 | 18486 | return std::make_tuple(freeFlowMomentumIndex, poreNetworkIndex); | |
70 | else // i == poreNetworkIndex | ||
71 | 247 | return std::make_tuple(freeFlowMomentumIndex, freeFlowMassIndex); | |
72 | } | ||
73 | |||
74 | template<std::size_t i, std::size_t j> | ||
75 | constexpr auto globalToLocalDomainIndices(Dune::index_constant<i>, Dune::index_constant<j>) | ||
76 | { | ||
77 | static_assert(i <= 2 && j <= 2); | ||
78 | static_assert(i != j); | ||
79 | |||
80 | if constexpr (i < j) | ||
81 | return std::pair<Dune::index_constant<0>, Dune::index_constant<1>>{}; | ||
82 | else | ||
83 | return std::pair<Dune::index_constant<1>, Dune::index_constant<0>>{}; | ||
84 | } | ||
85 | |||
86 | struct CouplingMaps | ||
87 | { | ||
88 | static constexpr auto managerMap() | ||
89 | { | ||
90 | return FreeFlowPoreNetworkDetail::makeCouplingManagerMap(); | ||
91 | } | ||
92 | |||
93 | template<std::size_t i, std::size_t j> | ||
94 | static constexpr auto globalToLocal(Dune::index_constant<i> domainI, Dune::index_constant<j> domainJ) | ||
95 | { | ||
96 | return FreeFlowPoreNetworkDetail::globalToLocalDomainIndices(domainI, domainJ); | ||
97 | } | ||
98 | |||
99 | template<std::size_t i> | ||
100 | ✗ | static constexpr auto coupledDomains(Dune::index_constant<i> domainI) | |
101 | { | ||
102 |
3/14✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 5 not taken.
✓ Branch 6 taken 33 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 33 times.
✗ Branch 17 not taken.
✗ Branch 18 not taken.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
✗ Branch 23 not taken.
✗ Branch 24 not taken.
✓ Branch 26 taken 966 times.
✗ Branch 27 not taken.
|
87143 | return FreeFlowPoreNetworkDetail::coupledDomains(domainI); |
103 | } | ||
104 | }; | ||
105 | |||
106 | template<class MDTraits> | ||
107 | struct CouplingManagers | ||
108 | { | ||
109 | template<std::size_t id> | ||
110 | using SubDomainTypeTag = typename MDTraits::template SubDomain<id>::TypeTag; | ||
111 | |||
112 | using FreeFlowTraits = MultiDomainTraits< | ||
113 | SubDomainTypeTag<freeFlowMomentumIndex>, SubDomainTypeTag<freeFlowMassIndex> | ||
114 | >; | ||
115 | |||
116 | using FreeFlowMomentumPoreNetworkTraits = MultiDomainTraits< | ||
117 | SubDomainTypeTag<freeFlowMomentumIndex>, SubDomainTypeTag<poreNetworkIndex> | ||
118 | >; | ||
119 | |||
120 | using FreeFlowMassPoreNetworkTraits = MultiDomainTraits< | ||
121 | SubDomainTypeTag<freeFlowMassIndex>, SubDomainTypeTag<poreNetworkIndex> | ||
122 | >; | ||
123 | |||
124 | using FreeFlowCouplingManager | ||
125 | = Dumux::FreeFlowCouplingManager<FreeFlowTraits>; | ||
126 | using FreeFlowMomentumPoreNetworkCouplingManager | ||
127 | = Dumux::FreeFlowMomentumPoreNetworkCouplingManager<FreeFlowMomentumPoreNetworkTraits>; | ||
128 | using FreeFlowMassPoreNetworkCouplingManager | ||
129 | = Dumux::FreeFlowMassPoreNetworkCouplingManager<FreeFlowMassPoreNetworkTraits>; | ||
130 | }; | ||
131 | |||
132 | } // end namespace Detail | ||
133 | |||
134 | /*! | ||
135 | * \ingroup FreeFlowPoreNetworkCoupling | ||
136 | * \brief Coupling manager for coupling freeflow and pore-network models | ||
137 | */ | ||
138 | template<class MDTraits> | ||
139 |
1/4✗ Branch 4 not taken.
✗ Branch 5 not taken.
✓ Branch 8 taken 2 times.
✗ Branch 9 not taken.
|
4 | class FreeFlowPoreNetworkCouplingManager |
140 | : public MultiBinaryCouplingManager< | ||
141 | MDTraits, | ||
142 | FreeFlowPoreNetworkDetail::CouplingMaps, | ||
143 | typename FreeFlowPoreNetworkDetail::CouplingManagers<MDTraits>::FreeFlowCouplingManager, | ||
144 | typename FreeFlowPoreNetworkDetail::CouplingManagers<MDTraits>::FreeFlowMomentumPoreNetworkCouplingManager, | ||
145 | typename FreeFlowPoreNetworkDetail::CouplingManagers<MDTraits>::FreeFlowMassPoreNetworkCouplingManager | ||
146 | > | ||
147 | { | ||
148 | using ParentType = MultiBinaryCouplingManager< | ||
149 | MDTraits, | ||
150 | FreeFlowPoreNetworkDetail::CouplingMaps, | ||
151 | typename FreeFlowPoreNetworkDetail::CouplingManagers<MDTraits>::FreeFlowCouplingManager, | ||
152 | typename FreeFlowPoreNetworkDetail::CouplingManagers<MDTraits>::FreeFlowMomentumPoreNetworkCouplingManager, | ||
153 | typename FreeFlowPoreNetworkDetail::CouplingManagers<MDTraits>::FreeFlowMassPoreNetworkCouplingManager | ||
154 | >; | ||
155 | |||
156 | using ThisType = FreeFlowPoreNetworkCouplingManager<MDTraits>; | ||
157 | |||
158 | using Scalar = typename MDTraits::Scalar; | ||
159 | |||
160 | // the sub domain type tags | ||
161 | template<std::size_t id> | ||
162 | using SubDomainTypeTag = typename MDTraits::template SubDomain<id>::TypeTag; | ||
163 | |||
164 | template<std::size_t id> using Problem = GetPropType<SubDomainTypeTag<id>, Properties::Problem>; | ||
165 | template<std::size_t id> using GridGeometry = GetPropType<SubDomainTypeTag<id>, Properties::GridGeometry>; | ||
166 | template<std::size_t id> using FVElementGeometry = typename GridGeometry<id>::LocalView; | ||
167 | template<std::size_t id> using SubControlVolumeFace = typename FVElementGeometry<id>::SubControlVolumeFace; | ||
168 | template<std::size_t id> using SubControlVolume = typename FVElementGeometry<id>::SubControlVolume; | ||
169 | template<std::size_t id> using ElementVolumeVariables = typename GetPropType<SubDomainTypeTag<id>, Properties::GridVolumeVariables>::LocalView; | ||
170 | template<std::size_t id> using NumEqVector = typename Problem<id>::Traits::NumEqVector; | ||
171 | |||
172 | template<std::size_t id> using GridView = typename GridGeometry<id>::GridView; | ||
173 | template<std::size_t id> using Element = typename GridView<id>::template Codim<0>::Entity; | ||
174 | using SolutionVector = typename MDTraits::SolutionVector; | ||
175 | |||
176 | using CouplingConditions = FreeFlowPoreNetworkCouplingConditions<MDTraits, FreeFlowPoreNetworkCouplingManager<MDTraits>>; | ||
177 | using CouplingMapper = StaggeredFreeFlowPoreNetworkCouplingMapper; | ||
178 | |||
179 | public: | ||
180 | |||
181 | template<std::size_t i, std::size_t j> | ||
182 | using SubCouplingManager = typename ParentType::template SubCouplingManager<i, j>; | ||
183 | |||
184 | static constexpr auto freeFlowMomentumIndex = FreeFlowPoreNetworkDetail::freeFlowMomentumIndex; | ||
185 | static constexpr auto freeFlowMassIndex = FreeFlowPoreNetworkDetail::freeFlowMassIndex; | ||
186 | static constexpr auto poreNetworkIndex = FreeFlowPoreNetworkDetail::poreNetworkIndex; | ||
187 | |||
188 | public: | ||
189 | using ParentType::ParentType; | ||
190 | |||
191 | template<class GridVarsTuple> | ||
192 | 2 | void init(std::shared_ptr<Problem<freeFlowMomentumIndex>> freeFlowMomentumProblem, | |
193 | std::shared_ptr<Problem<freeFlowMassIndex>> freeFlowMassProblem, | ||
194 | std::shared_ptr<Problem<poreNetworkIndex>> poreNetworkProblem, | ||
195 | GridVarsTuple&& gridVarsTuple, | ||
196 | const SolutionVector& curSol) | ||
197 | { | ||
198 | 2 | this->updateSolution(curSol); // generic coupling manager stores tuple of shared_ptr | |
199 | |||
200 |
0/2✗ Branch 1 not taken.
✗ Branch 2 not taken.
|
2 | auto couplingMapper = std::make_shared<CouplingMapper>(); |
201 |
4/8✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 2 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 2 times.
✗ Branch 11 not taken.
|
8 | couplingMapper->update(freeFlowMomentumProblem->gridGeometry(), |
202 |
2/4✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
|
4 | freeFlowMassProblem->gridGeometry(), |
203 |
2/4✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
|
4 | poreNetworkProblem->gridGeometry() |
204 | ); | ||
205 | |||
206 | // initialize the binary sub coupling managers | ||
207 |
1/2✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
|
2 | typename SubCouplingManager<freeFlowMomentumIndex, freeFlowMassIndex>::SolutionVectorStorage ffSolVecTuple; |
208 | 8 | std::get<0>(ffSolVecTuple) = std::get<freeFlowMomentumIndex>(this->curSol()); | |
209 | 8 | std::get<1>(ffSolVecTuple) = std::get<freeFlowMassIndex>(this->curSol()); | |
210 |
3/10✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 2 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 2 times.
✗ Branch 9 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
|
8 | this->subCouplingManager(freeFlowMomentumIndex, freeFlowMassIndex).init( |
211 | freeFlowMomentumProblem, freeFlowMassProblem, | ||
212 | 6 | std::make_tuple(std::get<freeFlowMomentumIndex>(gridVarsTuple), std::get<freeFlowMassIndex>(gridVarsTuple)), | |
213 | ffSolVecTuple | ||
214 | ); | ||
215 | |||
216 | 2 | typename SubCouplingManager<freeFlowMassIndex, poreNetworkIndex>::SolutionVectorStorage ffMassPmSolVecTuple; | |
217 | 8 | std::get<0>(ffMassPmSolVecTuple) = std::get<freeFlowMassIndex>(this->curSol()); | |
218 | 8 | std::get<1>(ffMassPmSolVecTuple) = std::get<poreNetworkIndex>(this->curSol()); | |
219 |
4/14✓ Branch 5 taken 2 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 2 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 2 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 2 times.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
✗ Branch 18 not taken.
|
8 | this->subCouplingManager(freeFlowMassIndex, poreNetworkIndex).init( |
220 | freeFlowMassProblem, poreNetworkProblem, couplingMapper, ffMassPmSolVecTuple | ||
221 | ); | ||
222 | |||
223 | 2 | typename SubCouplingManager<freeFlowMomentumIndex, poreNetworkIndex>::SolutionVectorStorage ffMomentumPmSolVecTuple; | |
224 | 8 | std::get<0>(ffMomentumPmSolVecTuple) = std::get<freeFlowMomentumIndex>(this->curSol()); | |
225 | 8 | std::get<1>(ffMomentumPmSolVecTuple) = std::get<poreNetworkIndex>(this->curSol()); | |
226 |
4/14✓ Branch 5 taken 2 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 2 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 2 times.
✗ Branch 10 not taken.
✓ Branch 12 taken 2 times.
✗ Branch 13 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
✗ Branch 18 not taken.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
|
12 | this->subCouplingManager(freeFlowMomentumIndex, poreNetworkIndex).init( |
227 | freeFlowMomentumProblem, poreNetworkProblem, | ||
228 | 6 | std::make_tuple(std::get<freeFlowMomentumIndex>(gridVarsTuple), std::get<poreNetworkIndex>(gridVarsTuple)), | |
229 | couplingMapper, ffMomentumPmSolVecTuple | ||
230 | ); | ||
231 | 2 | } | |
232 | |||
233 | /*! | ||
234 | * \brief Returns the mass flux across the coupling boundary. | ||
235 | */ | ||
236 | 168 | auto massCouplingCondition(Dune::index_constant<poreNetworkIndex> domainI, Dune::index_constant<freeFlowMassIndex> domainJ, | |
237 | const FVElementGeometry<poreNetworkIndex>& fvGeometry, | ||
238 | const typename FVElementGeometry<poreNetworkIndex>::SubControlVolume& scv, | ||
239 | const ElementVolumeVariables<poreNetworkIndex>& elemVolVars) const | ||
240 | { | ||
241 | |||
242 | 168 | const auto& couplingContext = this->subApply(domainI, domainJ, [&](const auto& cm, auto&& ii, auto&& jj) -> const auto& { | |
243 |
0/2✗ Branch 2 not taken.
✗ Branch 3 not taken.
|
168 | return cm.couplingContext(ii, fvGeometry, scv); |
244 | }); | ||
245 | |||
246 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 168 times.
|
168 | const auto& freeFlowMassGridGeometry = this->subApply(domainI, domainJ, [&](const auto& cm, auto&& ii, auto&& jj) -> const auto& { |
247 |
1/6✗ Branch 0 not taken.
✓ Branch 1 taken 168 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
|
168 | return cm.problem(jj).gridGeometry(); |
248 | }); | ||
249 | |||
250 |
4/4✓ Branch 0 taken 648 times.
✓ Branch 1 taken 168 times.
✓ Branch 2 taken 648 times.
✓ Branch 3 taken 168 times.
|
1152 | for (auto& c : couplingContext) |
251 | { | ||
252 |
1/2✓ Branch 1 taken 648 times.
✗ Branch 2 not taken.
|
648 | const auto& freeFlowElement = freeFlowMassGridGeometry.element(c.scv.elementIndex()); |
253 |
2/4✓ Branch 1 taken 648 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 648 times.
✗ Branch 5 not taken.
|
1296 | c.velocity = this->subCouplingManager(freeFlowMomentumIndex, freeFlowMassIndex).faceVelocity(freeFlowElement, c.scvf); |
254 | } | ||
255 | |||
256 | 168 | return CouplingConditions::massCouplingCondition(domainI, domainJ, fvGeometry, scv, elemVolVars, couplingContext); | |
257 | } | ||
258 | |||
259 | /*! | ||
260 | * \brief Returns the mass flux across the coupling boundary. | ||
261 | */ | ||
262 | ✗ | auto massCouplingCondition(Dune::index_constant<freeFlowMassIndex> domainI, Dune::index_constant<poreNetworkIndex> domainJ, | |
263 | const FVElementGeometry<freeFlowMassIndex>& fvGeometry, | ||
264 | const typename FVElementGeometry<freeFlowMassIndex>::SubControlVolumeFace& scvf, | ||
265 | const ElementVolumeVariables<freeFlowMassIndex>& elemVolVars) const | ||
266 | { | ||
267 | |||
268 | ✗ | const auto& couplingContext = this->subApply(domainI, domainJ, [&](const auto& cm, auto&& ii, auto&& jj) -> const auto& { | |
269 | ✗ | return cm.couplingContext(ii, fvGeometry, scvf); | |
270 | }); | ||
271 | |||
272 | ✗ | couplingContext.velocity = this->subCouplingManager(freeFlowMomentumIndex, freeFlowMassIndex).faceVelocity(fvGeometry.element(), scvf); | |
273 | ✗ | return CouplingConditions::massCouplingCondition(domainI, domainJ, fvGeometry, scvf, elemVolVars, couplingContext); | |
274 | } | ||
275 | |||
276 | //////////////////////// Conditions for FreeFlowMomentum - PoreNetwork coupling ////////// | ||
277 | /////////////////////////////////////////////////////////////////////////////////////////// | ||
278 | |||
279 | ✗ | NumEqVector<freeFlowMomentumIndex> momentumCouplingCondition(Dune::index_constant<freeFlowMomentumIndex> domainI, | |
280 | Dune::index_constant<poreNetworkIndex> domainJ, | ||
281 | const FVElementGeometry<freeFlowMomentumIndex>& fvGeometry, | ||
282 | const typename FVElementGeometry<freeFlowMomentumIndex>::SubControlVolumeFace& scvf, | ||
283 | const ElementVolumeVariables<freeFlowMomentumIndex>& elemVolVars) const | ||
284 | { | ||
285 | ✗ | if (scvf.isLateral()) | |
286 | ✗ | return NumEqVector<freeFlowMomentumIndex>(0.0); | |
287 | |||
288 | ✗ | const auto& context = this->subCouplingManager(freeFlowMomentumIndex, poreNetworkIndex).couplingContext( | |
289 | fvGeometry, scvf | ||
290 | ); | ||
291 | |||
292 | ✗ | return CouplingConditions::momentumCouplingCondition(fvGeometry, scvf, elemVolVars, context); | |
293 | } | ||
294 | |||
295 | ✗ | Scalar coupledPoreInscribedRadius(const FVElementGeometry<freeFlowMomentumIndex>& fvGeometry, | |
296 | const typename FVElementGeometry<freeFlowMomentumIndex>::SubControlVolumeFace& scvf) const | ||
297 | { | ||
298 | ✗ | const auto& context = this->subCouplingManager(freeFlowMomentumIndex, poreNetworkIndex).couplingContext( | |
299 | fvGeometry, scvf | ||
300 | ); | ||
301 | |||
302 | 3606 | const auto& pnmScv = [&] | |
303 | { | ||
304 |
1/2✓ Branch 0 taken 7212 times.
✗ Branch 1 not taken.
|
10818 | for (const auto& scv : scvs(context.fvGeometry)) |
305 |
2/2✓ Branch 0 taken 3606 times.
✓ Branch 1 taken 3606 times.
|
7212 | if (scv.dofIndex() == context.poreNetworkDofIdx) |
306 | 3606 | return scv; | |
307 | |||
308 | ✗ | DUNE_THROW(Dune::InvalidStateException, "No scv found"); | |
309 | ✗ | }(); | |
310 | |||
311 | ✗ | return context.elemVolVars[pnmScv].poreInscribedRadius(); | |
312 | } | ||
313 | |||
314 | 3606 | auto interfaceThroatVelocity(const FVElementGeometry<freeFlowMomentumIndex>& fvGeometry, | |
315 | const typename FVElementGeometry<freeFlowMomentumIndex>::SubControlVolumeFace& scvf) const | ||
316 | { | ||
317 |
2/4✓ Branch 0 taken 3606 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3606 times.
✗ Branch 3 not taken.
|
7212 | const auto& context = this->subCouplingManager(freeFlowMomentumIndex, poreNetworkIndex).couplingContext( |
318 | fvGeometry, scvf | ||
319 | ); | ||
320 | |||
321 | 3606 | return CouplingConditions::interfaceThroatVelocity(fvGeometry, scvf, context); | |
322 | } | ||
323 | |||
324 | // //////////////////////// Conditions for FreeFlowMomentum - FreeFlowMass coupling ////////// | ||
325 | // /////////////////////////////////////////////////////////////////////////////////////////// | ||
326 | |||
327 | /*! | ||
328 | * \brief Returns the pressure at a given sub control volume face. | ||
329 | */ | ||
330 | ✗ | Scalar pressure(const Element<freeFlowMomentumIndex>& element, | |
331 | const FVElementGeometry<freeFlowMomentumIndex>& fvGeometry, | ||
332 | const SubControlVolumeFace<freeFlowMomentumIndex>& scvf) const | ||
333 | { | ||
334 | 41518 | return this->subCouplingManager(freeFlowMomentumIndex, freeFlowMassIndex).pressure( | |
335 | element, fvGeometry, scvf | ||
336 | 41518 | ); | |
337 | } | ||
338 | |||
339 | /*! | ||
340 | * \brief Returns the pressure at the center of a sub control volume corresponding to a given sub control volume face. | ||
341 | * This is used for setting a Dirichlet pressure for the mass model when a fixed pressure for the momentum balance is set at another | ||
342 | * boundary. Since the the pressure at the given scvf is solution-dependent and thus unknown a priori, we just use the value | ||
343 | * of the interior cell here. | ||
344 | */ | ||
345 | Scalar cellPressure(const Element<freeFlowMomentumIndex>& element, | ||
346 | const SubControlVolumeFace<freeFlowMomentumIndex>& scvf) const | ||
347 | { | ||
348 | return this->subCouplingManager(freeFlowMomentumIndex, freeFlowMassIndex).cellPressure( | ||
349 | element, scvf | ||
350 | ); | ||
351 | } | ||
352 | |||
353 | /*! | ||
354 | * \brief Returns the density at a given sub control volume face. | ||
355 | */ | ||
356 | Scalar density(const Element<freeFlowMomentumIndex>& element, | ||
357 | const FVElementGeometry<freeFlowMomentumIndex>& fvGeometry, | ||
358 | const SubControlVolumeFace<freeFlowMomentumIndex>& scvf, | ||
359 | const bool considerPreviousTimeStep = false) const | ||
360 | { | ||
361 | ✗ | return this->subCouplingManager(freeFlowMomentumIndex, freeFlowMassIndex).density( | |
362 | element, fvGeometry, scvf, considerPreviousTimeStep | ||
363 | ✗ | ); | |
364 | } | ||
365 | |||
366 | auto insideAndOutsideDensity(const Element<freeFlowMomentumIndex>& element, | ||
367 | const FVElementGeometry<freeFlowMomentumIndex>& fvGeometry, | ||
368 | const SubControlVolumeFace<freeFlowMomentumIndex>& scvf, | ||
369 | const bool considerPreviousTimeStep = false) const | ||
370 | { | ||
371 | ✗ | return this->subCouplingManager(freeFlowMomentumIndex, freeFlowMassIndex).insideAndOutsideDensity( | |
372 | element, fvGeometry, scvf, considerPreviousTimeStep | ||
373 | ✗ | ); | |
374 | } | ||
375 | |||
376 | /*! | ||
377 | * \brief Returns the density at a given sub control volume. | ||
378 | */ | ||
379 | Scalar density(const Element<freeFlowMomentumIndex>& element, | ||
380 | const SubControlVolume<freeFlowMomentumIndex>& scv, | ||
381 | const bool considerPreviousTimeStep = false) const | ||
382 | { | ||
383 | 43760 | return this->subCouplingManager(freeFlowMomentumIndex, freeFlowMassIndex).density( | |
384 | element, scv, considerPreviousTimeStep | ||
385 | 43760 | ); | |
386 | } | ||
387 | |||
388 | /*! | ||
389 | * \brief Returns the pressure at a given sub control volume face. | ||
390 | */ | ||
391 | Scalar effectiveViscosity(const Element<freeFlowMomentumIndex>& element, | ||
392 | const FVElementGeometry<freeFlowMomentumIndex>& fvGeometry, | ||
393 | const SubControlVolumeFace<freeFlowMomentumIndex>& scvf) const | ||
394 | { | ||
395 | 147914 | return this->subCouplingManager(freeFlowMomentumIndex, freeFlowMassIndex).effectiveViscosity( | |
396 | element, fvGeometry, scvf | ||
397 | 147914 | ); | |
398 | } | ||
399 | |||
400 | /*! | ||
401 | * \brief Returns the velocity at a given sub control volume face. | ||
402 | */ | ||
403 | auto faceVelocity(const Element<freeFlowMassIndex>& element, | ||
404 | const SubControlVolumeFace<freeFlowMassIndex>& scvf) const | ||
405 | { | ||
406 | 48841 | return this->subCouplingManager(freeFlowMomentumIndex, freeFlowMassIndex).faceVelocity( | |
407 | element, scvf | ||
408 | 48841 | ); | |
409 | } | ||
410 | |||
411 | template<std::size_t i> | ||
412 | const Problem<i>& problem(Dune::index_constant<i> domainI) const | ||
413 | { | ||
414 | return this->subApply(domainI, [&](const auto& cm, auto&& ii) -> const auto& { | ||
415 | return cm.problem(ii); | ||
416 | }); | ||
417 | } | ||
418 | |||
419 | template<std::size_t i, std::size_t j> | ||
420 | ✗ | bool isCoupled(Dune::index_constant<i> domainI, | |
421 | Dune::index_constant<j> domainJ, | ||
422 | const SubControlVolumeFace<i>& scvf) const | ||
423 | { | ||
424 | ✗ | return this->subApply(domainI, domainJ, [&](const auto& cm, auto&& ii, auto&& jj){ | |
425 |
6/6✓ Branch 4 taken 405 times.
✓ Branch 5 taken 3151 times.
✓ Branch 7 taken 225 times.
✓ Branch 8 taken 1770 times.
✓ Branch 10 taken 288 times.
✓ Branch 11 taken 2409 times.
|
17980 | return cm.isCoupled(ii, scvf); |
426 |
12/14✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 4 taken 4491 times.
✓ Branch 5 taken 3061 times.
✓ Branch 7 taken 405 times.
✓ Branch 8 taken 3151 times.
✓ Branch 10 taken 225 times.
✓ Branch 11 taken 1770 times.
✓ Branch 13 taken 288 times.
✓ Branch 14 taken 2409 times.
✓ Branch 16 taken 95 times.
✓ Branch 17 taken 865 times.
✓ Branch 19 taken 126 times.
✓ Branch 20 taken 1094 times.
|
17980 | }); |
427 | } | ||
428 | |||
429 | /*! | ||
430 | * \brief If the boundary entity is on a coupling boundary | ||
431 | * \param domainI the domain index of domain i for which to compute the flux | ||
432 | * \param domainJ the domain index of domain j for which to compute the flux | ||
433 | * \param scv the sub control volume | ||
434 | */ | ||
435 | template<std::size_t i, std::size_t j> | ||
436 | ✗ | bool isCoupled(Dune::index_constant<i> domainI, | |
437 | Dune::index_constant<j> domainJ, | ||
438 | const SubControlVolume<i>& scv) const | ||
439 | { | ||
440 | ✗ | return this->subApply(domainI, domainJ, [&](const auto& cm, auto&& ii, auto&& jj){ | |
441 |
8/8✓ Branch 0 taken 168 times.
✓ Branch 1 taken 262 times.
✓ Branch 2 taken 168 times.
✓ Branch 3 taken 262 times.
✓ Branch 4 taken 14 times.
✓ Branch 5 taken 44 times.
✓ Branch 6 taken 14 times.
✓ Branch 7 taken 44 times.
|
976 | return cm.isCoupled(ii, scv); |
442 |
8/8✓ Branch 0 taken 168 times.
✓ Branch 1 taken 262 times.
✓ Branch 2 taken 168 times.
✓ Branch 3 taken 262 times.
✓ Branch 4 taken 14 times.
✓ Branch 5 taken 44 times.
✓ Branch 6 taken 14 times.
✓ Branch 7 taken 44 times.
|
976 | }); |
443 | } | ||
444 | |||
445 | // /*! | ||
446 | // * \brief Returns whether a given scvf is coupled to the other domain | ||
447 | // */ | ||
448 | // bool isCoupledLateralScvf(Dune::index_constant<freeFlowMomentumIndex> domainI, | ||
449 | // Dune::index_constant<poreNetworkIndex> domainJ, | ||
450 | // const SubControlVolumeFace<freeFlowMomentumIndex>& scvf) const | ||
451 | // { | ||
452 | // return this->subApply(domainI, domainJ, [&](const auto& cm, auto&& ii, auto&& jj){ | ||
453 | // return cm.isCoupledLateralScvf(ii, scvf); | ||
454 | // }); | ||
455 | // } | ||
456 | |||
457 | |||
458 | using ParentType::couplingStencil; | ||
459 | /*! | ||
460 | * \brief returns an iterable container of all indices of degrees of freedom of domain j | ||
461 | * that couple with / influence the residual of the given sub-control volume of domain i | ||
462 | * | ||
463 | * \param domainI the domain index of domain i | ||
464 | * \param elementI the coupled element of domain í | ||
465 | * \param scvI the sub-control volume of domain i | ||
466 | * \param domainJ the domain index of domain j | ||
467 | */ | ||
468 | template<std::size_t j> | ||
469 | ✗ | const auto& couplingStencil(Dune::index_constant<freeFlowMomentumIndex> domainI, | |
470 | const Element<freeFlowMomentumIndex>& elementI, | ||
471 | const SubControlVolume<freeFlowMomentumIndex>& scvI, | ||
472 | Dune::index_constant<j> domainJ) const | ||
473 | { | ||
474 | static_assert(freeFlowMomentumIndex != j); | ||
475 | ✗ | return this->subApply(domainI, domainJ, [&](const auto& cm, auto&& ii, auto&& jj) -> const auto& { | |
476 |
2/6✓ Branch 1 taken 3864 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1632 times.
✗ Branch 5 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
|
16488 | return cm.couplingStencil(ii, elementI, scvI, jj); |
477 |
2/4✓ Branch 1 taken 3864 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1632 times.
✗ Branch 5 not taken.
|
16488 | }); |
478 | } | ||
479 | }; | ||
480 | |||
481 | } // end namespace Dumux | ||
482 | |||
483 | #endif | ||
484 |