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 FreeFlowPorousMediumCoupling | ||
10 | * \brief Base class for coupling freeflow and porous medium flow models. | ||
11 | */ | ||
12 | |||
13 | #ifndef DUMUX_MULTIDOMAIN_BOUNDARY_FREEFLOW_POROUSMEDIUM_COUPLINGMANAGER_BASE_HH | ||
14 | #define DUMUX_MULTIDOMAIN_BOUNDARY_FREEFLOW_POROUSMEDIUM_COUPLINGMANAGER_BASE_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/freeflowporousmedium/ffmasspm/couplingmanager.hh> | ||
22 | #include <dumux/multidomain/boundary/freeflowporousmedium/ffmomentumpm/couplingmanager.hh> | ||
23 | #include <dumux/multidomain/freeflow/couplingmanager.hh> | ||
24 | #include <dumux/multidomain/multibinarycouplingmanager.hh> | ||
25 | |||
26 | namespace Dumux { | ||
27 | |||
28 | #ifndef DOXYGEN | ||
29 | namespace FreeFlowPorousMediumDetail { | ||
30 | |||
31 | // global subdomain indices | ||
32 | static constexpr auto freeFlowMomentumIndex = Dune::index_constant<0>(); | ||
33 | static constexpr auto freeFlowMassIndex = Dune::index_constant<1>(); | ||
34 | static constexpr auto porousMediumIndex = Dune::index_constant<2>(); | ||
35 | |||
36 | // coupling indices | ||
37 | static constexpr auto freeFlowMassToFreeFlowMomentumIndex = Dune::index_constant<0>(); | ||
38 | static constexpr auto freeFlowMomentumToPorousMediumIndex = Dune::index_constant<1>(); | ||
39 | static constexpr auto freeFlowMassToPorousMediumIndex = Dune::index_constant<2>(); | ||
40 | static constexpr auto noCouplingIdx = Dune::index_constant<99>(); | ||
41 | |||
42 | constexpr auto makeCouplingManagerMap() | ||
43 | { | ||
44 | auto map = std::array<std::array<std::size_t, 3>, 3>{}; | ||
45 | |||
46 | // free flow (momentum-mass) | ||
47 | map[freeFlowMomentumIndex][freeFlowMassIndex] = freeFlowMassToFreeFlowMomentumIndex; | ||
48 | map[freeFlowMassIndex][freeFlowMomentumIndex] = freeFlowMassToFreeFlowMomentumIndex; | ||
49 | |||
50 | // free flow momentum - porous medium | ||
51 | map[freeFlowMomentumIndex][porousMediumIndex] = freeFlowMomentumToPorousMediumIndex; | ||
52 | map[porousMediumIndex][freeFlowMomentumIndex] = freeFlowMomentumToPorousMediumIndex; | ||
53 | |||
54 | // free flow mass - porous medium | ||
55 | map[freeFlowMassIndex][porousMediumIndex] = freeFlowMassToPorousMediumIndex; | ||
56 | map[porousMediumIndex][freeFlowMassIndex] = freeFlowMassToPorousMediumIndex; | ||
57 | |||
58 | return map; | ||
59 | } | ||
60 | |||
61 | template<std::size_t i> | ||
62 | ✗ | constexpr auto coupledDomains(Dune::index_constant<i> domainI) | |
63 | { | ||
64 | if constexpr (i == freeFlowMomentumIndex) | ||
65 | 27002800 | return std::make_tuple(freeFlowMassIndex, porousMediumIndex); | |
66 | else if constexpr (i == freeFlowMassIndex) | ||
67 | 7065440 | return std::make_tuple(freeFlowMomentumIndex, porousMediumIndex); | |
68 | else // i == porousMediumIndex | ||
69 | 1126240 | return std::make_tuple(freeFlowMomentumIndex, freeFlowMassIndex); | |
70 | } | ||
71 | |||
72 | template<std::size_t i, std::size_t j> | ||
73 | constexpr auto globalToLocalDomainIndices(Dune::index_constant<i>, Dune::index_constant<j>) | ||
74 | { | ||
75 | static_assert(i <= 2 && j <= 2); | ||
76 | static_assert(i != j); | ||
77 | |||
78 | if constexpr (i < j) | ||
79 | return std::pair<Dune::index_constant<0>, Dune::index_constant<1>>{}; | ||
80 | else | ||
81 | return std::pair<Dune::index_constant<1>, Dune::index_constant<0>>{}; | ||
82 | } | ||
83 | |||
84 | struct CouplingMaps | ||
85 | { | ||
86 | static constexpr auto managerMap() | ||
87 | { | ||
88 | return FreeFlowPorousMediumDetail::makeCouplingManagerMap(); | ||
89 | } | ||
90 | |||
91 | template<std::size_t i, std::size_t j> | ||
92 | static constexpr auto globalToLocal(Dune::index_constant<i> domainI, Dune::index_constant<j> domainJ) | ||
93 | { | ||
94 | return FreeFlowPorousMediumDetail::globalToLocalDomainIndices(domainI, domainJ); | ||
95 | } | ||
96 | |||
97 | template<std::size_t i> | ||
98 | ✗ | static constexpr auto coupledDomains(Dune::index_constant<i> domainI) | |
99 | { | ||
100 |
2/12✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
✓ Branch 21 taken 371200 times.
✗ Branch 22 not taken.
✓ Branch 25 taken 371200 times.
✗ Branch 26 not taken.
|
35194480 | return FreeFlowPorousMediumDetail::coupledDomains(domainI); |
101 | } | ||
102 | }; | ||
103 | |||
104 | template<class MDTraits> | ||
105 | struct CouplingManagers | ||
106 | { | ||
107 | template<std::size_t id> | ||
108 | using SubDomainTypeTag = typename MDTraits::template SubDomain<id>::TypeTag; | ||
109 | |||
110 | using FreeFlowTraits = MultiDomainTraits< | ||
111 | SubDomainTypeTag<freeFlowMomentumIndex>, SubDomainTypeTag<freeFlowMassIndex> | ||
112 | >; | ||
113 | |||
114 | using FreeFlowMomentumPorousMediumTraits = MultiDomainTraits< | ||
115 | SubDomainTypeTag<freeFlowMomentumIndex>, SubDomainTypeTag<porousMediumIndex> | ||
116 | >; | ||
117 | |||
118 | using FreeFlowMassPorousMediumTraits = MultiDomainTraits< | ||
119 | SubDomainTypeTag<freeFlowMassIndex>, SubDomainTypeTag<porousMediumIndex> | ||
120 | >; | ||
121 | |||
122 | using FreeFlowCouplingManager | ||
123 | = Dumux::FreeFlowCouplingManager<FreeFlowTraits>; | ||
124 | using FreeFlowMomentumPorousMediumCouplingManager | ||
125 | = Dumux::FreeFlowMomentumPorousMediumCouplingManager<FreeFlowMomentumPorousMediumTraits>; | ||
126 | using FreeFlowMassPorousMediumCouplingManager | ||
127 | = Dumux::FreeFlowMassPorousMediumCouplingManager<FreeFlowMassPorousMediumTraits>; | ||
128 | }; | ||
129 | |||
130 | } // end namespace FreeFlowPorousMediumDetail | ||
131 | #endif // DOXYGEN | ||
132 | |||
133 | /*! | ||
134 | * \ingroup FreeFlowPorousMediumCoupling | ||
135 | * \brief Base coupling manager for coupling freeflow and porous medium flow models | ||
136 | */ | ||
137 | template<class MDTraits> | ||
138 |
1/4✗ Branch 4 not taken.
✗ Branch 5 not taken.
✓ Branch 8 taken 14 times.
✗ Branch 9 not taken.
|
28 | class FreeFlowPorousMediumCouplingManagerBase |
139 | : public MultiBinaryCouplingManager< | ||
140 | MDTraits, | ||
141 | FreeFlowPorousMediumDetail::CouplingMaps, | ||
142 | typename FreeFlowPorousMediumDetail::CouplingManagers<MDTraits>::FreeFlowCouplingManager, | ||
143 | typename FreeFlowPorousMediumDetail::CouplingManagers<MDTraits>::FreeFlowMomentumPorousMediumCouplingManager, | ||
144 | typename FreeFlowPorousMediumDetail::CouplingManagers<MDTraits>::FreeFlowMassPorousMediumCouplingManager | ||
145 | > | ||
146 | { | ||
147 | using ParentType = MultiBinaryCouplingManager< | ||
148 | MDTraits, | ||
149 | FreeFlowPorousMediumDetail::CouplingMaps, | ||
150 | typename FreeFlowPorousMediumDetail::CouplingManagers<MDTraits>::FreeFlowCouplingManager, | ||
151 | typename FreeFlowPorousMediumDetail::CouplingManagers<MDTraits>::FreeFlowMomentumPorousMediumCouplingManager, | ||
152 | typename FreeFlowPorousMediumDetail::CouplingManagers<MDTraits>::FreeFlowMassPorousMediumCouplingManager | ||
153 | >; | ||
154 | |||
155 | using Scalar = typename MDTraits::Scalar; | ||
156 | |||
157 | // the sub domain type tags | ||
158 | template<std::size_t id> | ||
159 | using SubDomainTypeTag = typename MDTraits::template SubDomain<id>::TypeTag; | ||
160 | |||
161 | template<std::size_t id> using Problem = GetPropType<SubDomainTypeTag<id>, Properties::Problem>; | ||
162 | template<std::size_t id> using GridGeometry = GetPropType<SubDomainTypeTag<id>, Properties::GridGeometry>; | ||
163 | template<std::size_t id> using FVElementGeometry = typename GridGeometry<id>::LocalView; | ||
164 | template<std::size_t id> using SubControlVolumeFace = typename FVElementGeometry<id>::SubControlVolumeFace; | ||
165 | template<std::size_t id> using SubControlVolume = typename FVElementGeometry<id>::SubControlVolume; | ||
166 | template<std::size_t id> using ElementVolumeVariables = typename GetPropType<SubDomainTypeTag<id>, Properties::GridVolumeVariables>::LocalView; | ||
167 | template<std::size_t id> using NumEqVector = typename Problem<id>::Traits::NumEqVector; | ||
168 | |||
169 | template<std::size_t id> using GridView = typename GridGeometry<id>::GridView; | ||
170 | template<std::size_t id> using Element = typename GridView<id>::template Codim<0>::Entity; | ||
171 | using SolutionVector = typename MDTraits::SolutionVector; | ||
172 | |||
173 | public: | ||
174 | |||
175 | template<std::size_t i, std::size_t j> | ||
176 | using SubCouplingManager = typename ParentType::template SubCouplingManager<i, j>; | ||
177 | |||
178 | static constexpr auto freeFlowMomentumIndex = FreeFlowPorousMediumDetail::freeFlowMomentumIndex; | ||
179 | static constexpr auto freeFlowMassIndex = FreeFlowPorousMediumDetail::freeFlowMassIndex; | ||
180 | static constexpr auto porousMediumIndex = FreeFlowPorousMediumDetail::porousMediumIndex; | ||
181 | |||
182 | public: | ||
183 | using ParentType::ParentType; | ||
184 | |||
185 | template<class GridVarsTuple> | ||
186 | 14 | void init(std::shared_ptr<Problem<freeFlowMomentumIndex>> freeFlowMomentumProblem, | |
187 | std::shared_ptr<Problem<freeFlowMassIndex>> freeFlowMassProblem, | ||
188 | std::shared_ptr<Problem<porousMediumIndex>> porousMediumProblem, | ||
189 | GridVarsTuple&& gridVarsTuple, | ||
190 | const SolutionVector& curSol) | ||
191 | { | ||
192 | 14 | this->updateSolution(curSol); // generic coupling manager stores tuple of shared_ptr | |
193 | |||
194 | // initialize the binary sub coupling managers | ||
195 | 42 | typename SubCouplingManager<freeFlowMomentumIndex, freeFlowMassIndex>::SolutionVectorStorage ffSolVecTuple; | |
196 | 56 | std::get<0>(ffSolVecTuple) = std::get<freeFlowMomentumIndex>(this->curSol()); | |
197 | 56 | std::get<1>(ffSolVecTuple) = std::get<freeFlowMassIndex>(this->curSol()); | |
198 |
3/10✓ Branch 4 taken 14 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 14 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 14 times.
✗ Branch 9 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
|
56 | this->subCouplingManager(freeFlowMomentumIndex, freeFlowMassIndex).init( |
199 | freeFlowMomentumProblem, freeFlowMassProblem, | ||
200 | 42 | std::make_tuple(std::get<freeFlowMomentumIndex>(gridVarsTuple), std::get<freeFlowMassIndex>(gridVarsTuple)), | |
201 | ffSolVecTuple | ||
202 | ); | ||
203 | |||
204 | 14 | typename SubCouplingManager<freeFlowMassIndex, porousMediumIndex>::SolutionVectorStorage ffMassPmSolVecTuple; | |
205 | 56 | std::get<0>(ffMassPmSolVecTuple) = std::get<freeFlowMassIndex>(this->curSol()); | |
206 | 56 | std::get<1>(ffMassPmSolVecTuple) = std::get<porousMediumIndex>(this->curSol()); | |
207 |
3/10✓ Branch 4 taken 14 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 14 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 14 times.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
|
42 | this->subCouplingManager(freeFlowMassIndex, porousMediumIndex).init( |
208 | freeFlowMassProblem, porousMediumProblem, ffMassPmSolVecTuple | ||
209 | ); | ||
210 | |||
211 | 14 | typename SubCouplingManager<freeFlowMomentumIndex, porousMediumIndex>::SolutionVectorStorage ffMomentumPmSolVecTuple; | |
212 | 56 | std::get<0>(ffMomentumPmSolVecTuple) = std::get<freeFlowMomentumIndex>(this->curSol()); | |
213 | 56 | std::get<1>(ffMomentumPmSolVecTuple) = std::get<porousMediumIndex>(this->curSol()); | |
214 |
3/10✓ Branch 4 taken 14 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 14 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 14 times.
✗ Branch 9 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
|
56 | this->subCouplingManager(freeFlowMomentumIndex, porousMediumIndex).init( |
215 | freeFlowMomentumProblem, porousMediumProblem, ffMomentumPmSolVecTuple | ||
216 | ); | ||
217 | 14 | } | |
218 | |||
219 | template<std::size_t i> | ||
220 | ✗ | const Problem<i>& problem(Dune::index_constant<i> domainI) const | |
221 | { | ||
222 | ✗ | return this->subApply(domainI, [&](const auto& cm, auto&& ii) -> const auto& { | |
223 |
1/8✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 143704 times.
|
143704 | return cm.problem(ii); |
224 |
1/4✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 143704 times.
|
143704 | }); |
225 | } | ||
226 | |||
227 | template<std::size_t i, std::size_t j> | ||
228 | ✗ | bool isCoupled(Dune::index_constant<i> domainI, | |
229 | Dune::index_constant<j> domainJ, | ||
230 | const SubControlVolumeFace<i>& scvf) const | ||
231 | { | ||
232 | ✗ | return this->subApply(domainI, domainJ, [&](const auto& cm, auto&& ii, auto&& jj){ | |
233 |
10/22✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✓ Branch 8 taken 20720 times.
✓ Branch 9 taken 10212 times.
✓ Branch 11 taken 37920 times.
✓ Branch 12 taken 94948 times.
✓ Branch 14 taken 48824 times.
✓ Branch 15 taken 29392 times.
✗ Branch 17 not taken.
✗ Branch 18 not taken.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
✓ Branch 23 taken 600 times.
✓ Branch 24 taken 1568 times.
✗ Branch 25 not taken.
✓ Branch 26 taken 600 times.
✓ Branch 27 taken 1568 times.
|
811692 | return cm.isCoupled(ii, scvf); |
234 |
19/25✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 4 taken 178640 times.
✓ Branch 5 taken 174388 times.
✓ Branch 7 taken 73128 times.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✓ Branch 10 taken 66968 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 960 times.
✓ Branch 13 taken 23136 times.
✓ Branch 14 taken 10212 times.
✓ Branch 15 taken 680 times.
✓ Branch 16 taken 38072 times.
✓ Branch 17 taken 92532 times.
✓ Branch 18 taken 600 times.
✓ Branch 19 taken 49712 times.
✓ Branch 20 taken 28280 times.
✓ Branch 21 taken 600 times.
✓ Branch 22 taken 1568 times.
✗ Branch 23 not taken.
✓ Branch 24 taken 726 times.
✓ Branch 25 taken 240 times.
✓ Branch 27 taken 17931 times.
✓ Branch 28 taken 53319 times.
|
811692 | }); |
235 | } | ||
236 | |||
237 | /*! | ||
238 | * \brief If the boundary entity is on a coupling boundary | ||
239 | * \param domainI the domain index of domain i for which to compute the flux | ||
240 | * \param domainJ the domain index of domain j for which to compute the flux | ||
241 | * \param scv the sub control volume | ||
242 | */ | ||
243 | template<std::size_t i, std::size_t j> | ||
244 | bool isCoupled(Dune::index_constant<i> domainI, | ||
245 | Dune::index_constant<j> domainJ, | ||
246 | const SubControlVolume<i>& scv) const | ||
247 | { | ||
248 | return this->subApply(domainI, domainJ, [&](const auto& cm, auto&& ii, auto&& jj){ | ||
249 | return cm.isCoupled(ii, scv); | ||
250 | }); | ||
251 | } | ||
252 | |||
253 | using ParentType::couplingStencil; | ||
254 | /*! | ||
255 | * \brief returns an iterable container of all indices of degrees of freedom of domain j | ||
256 | * that couple with / influence the residual of the given sub-control volume of domain i | ||
257 | * | ||
258 | * \param domainI the domain index of domain i | ||
259 | * \param elementI the coupled element of domain í | ||
260 | * \param scvI the sub-control volume of domain i | ||
261 | * \param domainJ the domain index of domain j | ||
262 | */ | ||
263 | template<std::size_t j> | ||
264 | ✗ | const auto& couplingStencil(Dune::index_constant<freeFlowMomentumIndex> domainI, | |
265 | const Element<freeFlowMomentumIndex>& elementI, | ||
266 | const SubControlVolume<freeFlowMomentumIndex>& scvI, | ||
267 | Dune::index_constant<j> domainJ) const | ||
268 | { | ||
269 | static_assert(freeFlowMomentumIndex != j); | ||
270 | ✗ | return this->subApply(domainI, domainJ, [&](const auto& cm, auto&& ii, auto&& jj) -> const auto& { | |
271 |
2/6✓ Branch 1 taken 1484800 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 540800 times.
✗ Branch 5 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
|
6076800 | return cm.couplingStencil(ii, elementI, scvI, jj); |
272 |
2/4✓ Branch 1 taken 1484800 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 540800 times.
✗ Branch 5 not taken.
|
6076800 | }); |
273 | } | ||
274 | }; | ||
275 | |||
276 | } // end namespace Dumux | ||
277 | |||
278 | #endif | ||
279 |