GCC Code Coverage Report


Directory: ../../../builds/dumux-repositories/
File: /builds/dumux-repositories/dumux/dumux/multidomain/boundary/freeflowporenetwork/couplingmanager.hh
Date: 2024-09-21 20:52:54
Exec Total Coverage
Lines: 56 84 66.7%
Functions: 4 21 19.0%
Branches: 76 184 41.3%

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