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 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 | 33522720 | constexpr auto coupledDomains(Dune::index_constant<i> domainI) | |
63 | { | ||
64 | if constexpr (i == freeFlowMomentumIndex) | ||
65 | 28089600 | return std::make_tuple(freeFlowMassIndex, porousMediumIndex); | |
66 | else if constexpr (i == freeFlowMassIndex) | ||
67 | 4258240 | return std::make_tuple(freeFlowMomentumIndex, porousMediumIndex); | |
68 | else // i == porousMediumIndex | ||
69 | 1174880 | 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 | 33522720 | static constexpr auto coupledDomains(Dune::index_constant<i> domainI) | |
99 | { | ||
100 | 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 | 30 | 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 | template<std::size_t id> | ||
174 | using SubSolutionVector | ||
175 | = std::decay_t<decltype(std::declval<SolutionVector>()[Dune::index_constant<id>()])>; | ||
176 | |||
177 | public: | ||
178 | |||
179 | template<std::size_t i, std::size_t j> | ||
180 | using SubCouplingManager = typename ParentType::template SubCouplingManager<i, j>; | ||
181 | |||
182 | static constexpr auto freeFlowMomentumIndex = FreeFlowPorousMediumDetail::freeFlowMomentumIndex; | ||
183 | static constexpr auto freeFlowMassIndex = FreeFlowPorousMediumDetail::freeFlowMassIndex; | ||
184 | static constexpr auto porousMediumIndex = FreeFlowPorousMediumDetail::porousMediumIndex; | ||
185 | |||
186 | public: | ||
187 | using ParentType::ParentType; | ||
188 | |||
189 | template<class GridVarsTuple> | ||
190 | 14 | void init(std::shared_ptr<Problem<freeFlowMomentumIndex>> freeFlowMomentumProblem, | |
191 | std::shared_ptr<Problem<freeFlowMassIndex>> freeFlowMassProblem, | ||
192 | std::shared_ptr<Problem<porousMediumIndex>> porousMediumProblem, | ||
193 | GridVarsTuple&& gridVarsTuple, | ||
194 | const SolutionVector& curSol) | ||
195 | { | ||
196 | // initialize sub coupling manager that are not stationary or transient problem specific | ||
197 |
3/10✓ Branch 3 taken 14 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 14 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 14 times.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
|
42 | this->init_(freeFlowMomentumProblem, freeFlowMassProblem, porousMediumProblem, std::forward<GridVarsTuple>(gridVarsTuple), curSol); |
198 | |||
199 | // initialize stationary-specific sub coupling manager for free-flow | ||
200 | using FFSol = typename SubCouplingManager<freeFlowMomentumIndex, freeFlowMassIndex>::SolutionVectorStorage; | ||
201 |
2/6✓ Branch 5 taken 14 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 14 times.
✗ Branch 8 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
|
70 | this->subCouplingManager(freeFlowMomentumIndex, freeFlowMassIndex).init( |
202 | freeFlowMomentumProblem, freeFlowMassProblem, | ||
203 | 14 | std::make_tuple(std::get<freeFlowMomentumIndex>(gridVarsTuple), std::get<freeFlowMassIndex>(gridVarsTuple)), | |
204 | 14 | FFSol{ std::get<freeFlowMomentumIndex>(this->curSol()), std::get<freeFlowMassIndex>(this->curSol()) } | |
205 | ); | ||
206 | 14 | } | |
207 | |||
208 | template<class GridVarsTuple> | ||
209 | 1 | void init(std::shared_ptr<Problem<freeFlowMomentumIndex>> freeFlowMomentumProblem, | |
210 | std::shared_ptr<Problem<freeFlowMassIndex>> freeFlowMassProblem, | ||
211 | std::shared_ptr<Problem<porousMediumIndex>> porousMediumProblem, | ||
212 | GridVarsTuple&& gridVarsTuple, | ||
213 | const SolutionVector& curSol, | ||
214 | const SolutionVector& prevSol) | ||
215 | { | ||
216 | // initialize sub coupling manager that are not stationary or transient problem specific | ||
217 |
3/10✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 1 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
|
3 | this->init_(freeFlowMomentumProblem, freeFlowMassProblem, porousMediumProblem, std::forward<GridVarsTuple>(gridVarsTuple), curSol); |
218 | |||
219 | using FFSol = typename SubCouplingManager<freeFlowMomentumIndex, freeFlowMassIndex>::SolutionVectorStorage; | ||
220 | using FFPrevSol = std::tuple<const SubSolutionVector<freeFlowMomentumIndex>*, const SubSolutionVector<freeFlowMassIndex>*>; | ||
221 |
2/6✓ Branch 5 taken 1 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
|
5 | this->subCouplingManager(freeFlowMomentumIndex, freeFlowMassIndex).init( |
222 | freeFlowMomentumProblem, freeFlowMassProblem, | ||
223 | 1 | std::make_tuple(std::get<freeFlowMomentumIndex>(gridVarsTuple), std::get<freeFlowMassIndex>(gridVarsTuple)), | |
224 | 1 | FFSol{ std::get<freeFlowMomentumIndex>(this->curSol()), std::get<freeFlowMassIndex>(this->curSol()) }, | |
225 | 1 | FFPrevSol{ &prevSol[freeFlowMomentumIndex], &prevSol[freeFlowMassIndex] } | |
226 | ); | ||
227 | 1 | } | |
228 | |||
229 | template<std::size_t i> | ||
230 | 178360 | const Problem<i>& problem(Dune::index_constant<i> domainI) const | |
231 | { | ||
232 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 178360 times.
|
178360 | return this->subApply(domainI, [&](const auto& cm, auto&& ii) -> const auto& { |
233 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 178360 times.
|
178360 | return cm.problem(ii); |
234 | }); | ||
235 | } | ||
236 | |||
237 | template<std::size_t i, std::size_t j> | ||
238 | 1268540 | bool isCoupled(Dune::index_constant<i> domainI, | |
239 | Dune::index_constant<j> domainJ, | ||
240 | const SubControlVolumeFace<i>& scvf) const | ||
241 | { | ||
242 |
19/19✓ Branch 1 taken 203080 times.
✓ Branch 2 taken 209764 times.
✓ Branch 4 taken 119708 times.
✓ Branch 5 taken 73800 times.
✓ Branch 7 taken 72448 times.
✓ Branch 8 taken 6596 times.
✓ Branch 10 taken 38880 times.
✓ Branch 11 taken 11108 times.
✓ Branch 13 taken 58224 times.
✓ Branch 14 taken 53648 times.
✓ Branch 16 taken 38528 times.
✓ Branch 17 taken 93132 times.
✓ Branch 19 taken 30340 times.
✓ Branch 20 taken 29345 times.
✓ Branch 22 taken 726 times.
✓ Branch 23 taken 240 times.
✓ Branch 25 taken 4164 times.
✓ Branch 26 taken 4164 times.
✓ Branch 21 taken 53073 times.
|
1268540 | return this->subApply(domainI, domainJ, [&](const auto& cm, auto&& ii, auto&& jj){ |
243 |
13/13✓ Branch 3 taken 5480 times.
✓ Branch 4 taken 27316 times.
✓ Branch 6 taken 18160 times.
✓ Branch 7 taken 49040 times.
✓ Branch 9 taken 10080 times.
✓ Branch 10 taken 62328 times.
✓ Branch 12 taken 1568 times.
✓ Branch 13 taken 600 times.
✓ Branch 15 taken 30340 times.
✓ Branch 16 taken 11660 times.
✓ Branch 5 taken 10212 times.
✓ Branch 8 taken 28280 times.
✓ Branch 11 taken 92532 times.
|
1268540 | return cm.isCoupled(ii, scvf); |
244 | }); | ||
245 | } | ||
246 | |||
247 | /*! | ||
248 | * \brief If the boundary entity is on a coupling boundary | ||
249 | * \param domainI the domain index of domain i for which to compute the flux | ||
250 | * \param domainJ the domain index of domain j for which to compute the flux | ||
251 | * \param scv the sub control volume | ||
252 | */ | ||
253 | template<std::size_t i, std::size_t j> | ||
254 | bool isCoupled(Dune::index_constant<i> domainI, | ||
255 | Dune::index_constant<j> domainJ, | ||
256 | const SubControlVolume<i>& scv) const | ||
257 | { | ||
258 | return this->subApply(domainI, domainJ, [&](const auto& cm, auto&& ii, auto&& jj){ | ||
259 | return cm.isCoupled(ii, scv); | ||
260 | }); | ||
261 | } | ||
262 | |||
263 | using ParentType::couplingStencil; | ||
264 | /*! | ||
265 | * \brief returns an iterable container of all indices of degrees of freedom of domain j | ||
266 | * that couple with / influence the residual of the given sub-control volume of domain i | ||
267 | * | ||
268 | * \param domainI the domain index of domain i | ||
269 | * \param elementI the coupled element of domain í | ||
270 | * \param scvI the sub-control volume of domain i | ||
271 | * \param domainJ the domain index of domain j | ||
272 | */ | ||
273 | template<std::size_t j> | ||
274 | 4176000 | const auto& couplingStencil(Dune::index_constant<freeFlowMomentumIndex> domainI, | |
275 | const Element<freeFlowMomentumIndex>& elementI, | ||
276 | const SubControlVolume<freeFlowMomentumIndex>& scvI, | ||
277 | Dune::index_constant<j> domainJ) const | ||
278 | { | ||
279 | static_assert(freeFlowMomentumIndex != j); | ||
280 |
1/2✓ Branch 2 taken 542400 times.
✗ Branch 3 not taken.
|
4176000 | return this->subApply(domainI, domainJ, [&](const auto& cm, auto&& ii, auto&& jj) -> const auto& { |
281 |
1/2✓ Branch 2 taken 542400 times.
✗ Branch 3 not taken.
|
4176000 | return cm.couplingStencil(ii, elementI, scvI, jj); |
282 | }); | ||
283 | } | ||
284 | private: | ||
285 | /* | ||
286 | * \brief Initializes sub-coupling managers for stationary and transient problems | ||
287 | */ | ||
288 | template<class GridVarsTuple> | ||
289 | 15 | void init_(std::shared_ptr<Problem<freeFlowMomentumIndex>> freeFlowMomentumProblem, | |
290 | std::shared_ptr<Problem<freeFlowMassIndex>> freeFlowMassProblem, | ||
291 | std::shared_ptr<Problem<porousMediumIndex>> porousMediumProblem, | ||
292 | GridVarsTuple&& gridVarsTuple, | ||
293 | const SolutionVector& curSol) | ||
294 | { | ||
295 | 15 | this->updateSolution(curSol); // generic coupling manager stores tuple of shared_ptr | |
296 | |||
297 | // initialize the binary sub coupling managers | ||
298 | using FFMassPMSol = typename SubCouplingManager<freeFlowMassIndex, porousMediumIndex>::SolutionVectorStorage; | ||
299 |
2/6✓ Branch 4 taken 15 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 15 times.
✗ Branch 7 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
|
60 | this->subCouplingManager(freeFlowMassIndex, porousMediumIndex).init( |
300 | freeFlowMassProblem, porousMediumProblem, | ||
301 | 15 | FFMassPMSol{ std::get<freeFlowMassIndex>(this->curSol()), std::get<porousMediumIndex>(this->curSol()) } | |
302 | ); | ||
303 | |||
304 | using FFMomPMSol = typename SubCouplingManager<freeFlowMomentumIndex, porousMediumIndex>::SolutionVectorStorage; | ||
305 |
2/6✓ Branch 4 taken 15 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 15 times.
✗ Branch 7 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
|
60 | this->subCouplingManager(freeFlowMomentumIndex, porousMediumIndex).init( |
306 | freeFlowMomentumProblem, porousMediumProblem, | ||
307 | 15 | FFMomPMSol{ std::get<freeFlowMomentumIndex>(this->curSol()), std::get<porousMediumIndex>(this->curSol()) } | |
308 | ); | ||
309 | 15 | } | |
310 | }; | ||
311 | |||
312 | } // end namespace Dumux | ||
313 | |||
314 | #endif | ||
315 |