GCC Code Coverage Report


Directory: ../../../builds/dumux-repositories/
File: /builds/dumux-repositories/dumux/dumux/multidomain/boundary/stokesdarcy/couplingmanager.hh
Date: 2024-05-04 19:09:25
Exec Total Coverage
Lines: 119 140 85.0%
Functions: 94 143 65.7%
Branches: 161 289 55.7%

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 StokesDarcyCoupling
10 * \copydoc Dumux::StokesDarcyCouplingManager
11 */
12
13 #ifndef DUMUX_STOKES_DARCY_COUPLINGMANAGER_HH
14 #define DUMUX_STOKES_DARCY_COUPLINGMANAGER_HH
15
16 #include <utility>
17 #include <memory>
18
19 #include <dune/common/float_cmp.hh>
20 #include <dune/common/exceptions.hh>
21 #include <dumux/common/properties.hh>
22 #include <dumux/common/numeqvector.hh>
23 #include <dumux/multidomain/staggeredcouplingmanager.hh>
24 #include <dumux/discretization/staggered/elementsolution.hh>
25
26 #include "couplingdata.hh"
27 #include "couplingmapper.hh"
28
29 namespace Dumux {
30
31 /*!
32 * \ingroup StokesDarcyCoupling
33 * \brief Coupling manager for Stokes and Darcy domains with equal dimension.
34 */
35 template<class MDTraits>
36 class StokesDarcyCouplingManager
37 : public StaggeredCouplingManager<MDTraits>
38 {
39 using Scalar = typename MDTraits::Scalar;
40 using ParentType = StaggeredCouplingManager<MDTraits>;
41
42 public:
43 static constexpr auto stokesFaceIdx = typename MDTraits::template SubDomain<0>::Index();
44 static constexpr auto stokesCellCenterIdx = typename MDTraits::template SubDomain<1>::Index();
45 static constexpr auto stokesIdx = stokesFaceIdx;
46 static constexpr auto darcyIdx = typename MDTraits::template SubDomain<2>::Index();
47
48 private:
49
50 using SolutionVector = typename MDTraits::SolutionVector;
51
52 // obtain the type tags of the sub problems
53 using StokesTypeTag = typename MDTraits::template SubDomain<0>::TypeTag;
54 using DarcyTypeTag = typename MDTraits::template SubDomain<2>::TypeTag;
55
56 using CouplingStencils = std::unordered_map<std::size_t, std::vector<std::size_t> >;
57 using CouplingStencil = CouplingStencils::mapped_type;
58
59 // the sub domain type tags
60 template<std::size_t id>
61 using SubDomainTypeTag = typename MDTraits::template SubDomain<id>::TypeTag;
62
63 static constexpr bool isCompositional = GetPropType<SubDomainTypeTag<0>, Properties::ModelTraits>::numFluidComponents()> 1;
64
65 template<std::size_t id> using GridView = typename GetPropType<SubDomainTypeTag<id>, Properties::GridGeometry>::GridView;
66 template<std::size_t id> using Problem = GetPropType<SubDomainTypeTag<id>, Properties::Problem>;
67 template<std::size_t id> using PrimaryVariables = typename MDTraits::template SubDomain<id>::PrimaryVariables;
68 template<std::size_t id> using NumEqVector = Dumux::NumEqVector<PrimaryVariables<id>>;
69 template<std::size_t id> using ElementVolumeVariables = typename GetPropType<SubDomainTypeTag<id>, Properties::GridVolumeVariables>::LocalView;
70 template<std::size_t id> using GridVolumeVariables = GetPropType<SubDomainTypeTag<id>, Properties::GridVolumeVariables>;
71 template<std::size_t id> using VolumeVariables = typename GetPropType<SubDomainTypeTag<id>, Properties::GridVolumeVariables>::VolumeVariables;
72 template<std::size_t id> using GridGeometry = GetPropType<SubDomainTypeTag<id>, Properties::GridGeometry>;
73 template<std::size_t id> using FVElementGeometry = typename GridGeometry<id>::LocalView;
74 template<std::size_t id> using ElementBoundaryTypes = GetPropType<SubDomainTypeTag<id>, Properties::ElementBoundaryTypes>;
75 template<std::size_t id> using ElementFluxVariablesCache = typename GetPropType<SubDomainTypeTag<id>, Properties::GridFluxVariablesCache>::LocalView;
76 template<std::size_t id> using GridVariables = GetPropType<SubDomainTypeTag<id>, Properties::GridVariables>;
77 template<std::size_t id> using Element = typename GridView<id>::template Codim<0>::Entity;
78 template<std::size_t id> using SubControlVolumeFace = typename FVElementGeometry<id>::SubControlVolumeFace;
79
80 using CellCenterSolutionVector = GetPropType<StokesTypeTag, Properties::CellCenterSolutionVector>;
81
82 using VelocityVector = typename Element<stokesIdx>::Geometry::GlobalCoordinate;
83
84 using CouplingMapper = StokesDarcyCouplingMapper;
85
86 22664 struct StationaryStokesCouplingContext
87 {
88 Element<darcyIdx> element;
89 FVElementGeometry<darcyIdx> fvGeometry;
90 std::size_t darcyScvfIdx;
91 std::size_t stokesScvfIdx;
92 VolumeVariables<darcyIdx> volVars;
93 };
94
95 struct StationaryDarcyCouplingContext
96 {
97 Element<stokesIdx> element;
98 FVElementGeometry<stokesIdx> fvGeometry;
99 std::size_t stokesScvfIdx;
100 std::size_t darcyScvfIdx;
101 VelocityVector velocity;
102 VolumeVariables<stokesIdx> volVars;
103 };
104 public:
105
106 using CouplingData = StokesDarcyCouplingData<MDTraits, StokesDarcyCouplingManager<MDTraits>>;
107
108 //! Constructor
109 17 StokesDarcyCouplingManager(std::shared_ptr<const GridGeometry<stokesIdx>> stokesFvGridGeometry,
110 std::shared_ptr<const GridGeometry<darcyIdx>> darcyFvGridGeometry)
111 17 { }
112
113 /*!
114 * \brief Methods to be accessed by main
115 */
116 // \{
117
118 //! Initialize the coupling manager
119 17 void init(std::shared_ptr<const Problem<stokesIdx>> stokesProblem,
120 std::shared_ptr<const Problem<darcyIdx>> darcyProblem,
121 const SolutionVector& curSol)
122 {
123
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 17 times.
119 if (Dune::FloatCmp::ne(stokesProblem->gravity(), darcyProblem->spatialParams().gravity({})))
124 DUNE_THROW(Dune::InvalidStateException, "Both models must use the same gravity vector");
125
126 17 this->setSubProblems(std::make_tuple(stokesProblem, stokesProblem, darcyProblem));
127 17 this->updateSolution(curSol);
128
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 17 times.
17 couplingData_ = std::make_shared<CouplingData>(*this);
129 17 computeStencils();
130 17 }
131
132 // \}
133
134 //! Prepare the coupling stencils
135 17 void computeStencils()
136 {
137 34 couplingMapper_.computeCouplingMapsAndStencils(*this,
138 17 darcyToStokesCellCenterCouplingStencils_,
139 17 darcyToStokesFaceCouplingStencils_,
140 17 stokesCellCenterCouplingStencils_,
141 17 stokesFaceCouplingStencils_);
142
143
2/2
✓ Branch 0 taken 756 times.
✓ Branch 1 taken 17 times.
807 for(auto&& stencil : darcyToStokesCellCenterCouplingStencils_)
144 756 removeDuplicates_(stencil.second);
145
2/2
✓ Branch 0 taken 756 times.
✓ Branch 1 taken 17 times.
807 for(auto&& stencil : darcyToStokesFaceCouplingStencils_)
146 756 removeDuplicates_(stencil.second);
147
2/2
✓ Branch 0 taken 756 times.
✓ Branch 1 taken 17 times.
807 for(auto&& stencil : stokesCellCenterCouplingStencils_)
148 756 removeDuplicates_(stencil.second);
149
2/2
✓ Branch 0 taken 756 times.
✓ Branch 1 taken 17 times.
807 for(auto&& stencil : stokesFaceCouplingStencils_)
150 756 removeDuplicates_(stencil.second);
151 17 }
152
153 /*!
154 * \brief Methods to be accessed by the assembly
155 */
156 // \{
157
158 using ParentType::evalCouplingResidual;
159
160 /*!
161 * \brief prepares all data and variables that are necessary to evaluate the residual of an Darcy element (i.e. Darcy information)
162 */
163 template<std::size_t i, class Assembler, std::enable_if_t<(i == stokesCellCenterIdx || i == stokesFaceIdx), int> = 0>
164 void bindCouplingContext(Dune::index_constant<i> domainI, const Element<stokesCellCenterIdx>& element, const Assembler& assembler) const
165 825824 { bindCouplingContext(domainI, element); }
166
167 /*!
168 * \brief prepares all data and variables that are necessary to evaluate the residual of an Darcy element (i.e. Darcy information)
169 */
170 template<std::size_t i, std::enable_if_t<(i == stokesCellCenterIdx || i == stokesFaceIdx), int> = 0>
171 1651648 void bindCouplingContext(Dune::index_constant<i> domainI, const Element<stokesCellCenterIdx>& element) const
172 {
173
2/2
✓ Branch 0 taken 22664 times.
✓ Branch 1 taken 803160 times.
1651648 stokesCouplingContext_.clear();
174
175
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 825824 times.
1651648 const auto stokesElementIdx = this->problem(stokesIdx).gridGeometry().elementMapper().index(element);
176 1651648 boundStokesElemIdx_ = stokesElementIdx;
177
178 // do nothing if the element is not coupled to the other domain
179
2/2
✓ Branch 2 taken 803160 times.
✓ Branch 3 taken 22664 times.
3303296 if(!couplingMapper_.stokesElementToDarcyElementMap().count(stokesElementIdx))
180 1606320 return;
181
182 // prepare the coupling context
183 90656 const auto& darcyIndices = couplingMapper_.stokesElementToDarcyElementMap().at(stokesElementIdx);
184
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 22664 times.
90656 auto darcyFvGeometry = localView(this->problem(darcyIdx).gridGeometry());
185
4/4
✓ Branch 0 taken 22664 times.
✓ Branch 1 taken 22664 times.
✓ Branch 2 taken 22664 times.
✓ Branch 3 taken 22664 times.
226640 for(auto&& indices : darcyIndices)
186 {
187
5/10
✗ Branch 0 not taken.
✓ Branch 1 taken 22664 times.
✓ Branch 3 taken 22664 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 22664 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 22664 times.
✗ Branch 10 not taken.
✓ Branch 12 taken 22664 times.
✗ Branch 13 not taken.
45328 const auto& darcyElement = this->problem(darcyIdx).gridGeometry().boundingBoxTree().entitySet().entity(indices.eIdx);
188
1/2
✓ Branch 1 taken 22664 times.
✗ Branch 2 not taken.
45328 darcyFvGeometry.bindElement(darcyElement);
189
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 22664 times.
45328 const auto& scv = (*scvs(darcyFvGeometry).begin());
190
191
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 22664 times.
45328 const auto darcyElemSol = elementSolution(darcyElement, this->curSol(darcyIdx), this->problem(darcyIdx).gridGeometry());
192
1/2
✓ Branch 1 taken 22664 times.
✗ Branch 2 not taken.
45328 VolumeVariables<darcyIdx> darcyVolVars;
193
2/4
✓ Branch 1 taken 22664 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 22664 times.
✗ Branch 5 not taken.
90656 darcyVolVars.update(darcyElemSol, this->problem(darcyIdx), darcyElement, scv);
194
195 // add the context
196
3/6
✓ Branch 1 taken 22664 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 22664 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 22664 times.
✗ Branch 8 not taken.
90656 stokesCouplingContext_.push_back({darcyElement, darcyFvGeometry, indices.scvfIdx, indices.flipScvfIdx, darcyVolVars});
197 }
198 }
199
200 /*!
201 * \brief prepares all data and variables that are necessary to evaluate the residual of an Darcy element (i.e. Stokes information)
202 */
203 template<class Assembler>
204 void bindCouplingContext(Dune::index_constant<darcyIdx> domainI, const Element<darcyIdx>& element, const Assembler& assembler) const
205 393456 { bindCouplingContext(domainI, element); }
206
207 /*!
208 * \brief prepares all data and variables that are necessary to evaluate the residual of an Darcy element (i.e. Stokes information)
209 */
210 396276 void bindCouplingContext(Dune::index_constant<darcyIdx> domainI, const Element<darcyIdx>& element) const
211 {
212
2/2
✓ Branch 0 taken 14135 times.
✓ Branch 1 taken 382141 times.
396276 darcyCouplingContext_.clear();
213
214
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 396276 times.
396276 const auto darcyElementIdx = this->problem(darcyIdx).gridGeometry().elementMapper().index(element);
215 396276 boundDarcyElemIdx_ = darcyElementIdx;
216
217 // do nothing if the element is not coupled to the other domain
218
2/2
✓ Branch 2 taken 382124 times.
✓ Branch 3 taken 14152 times.
792552 if(!couplingMapper_.darcyElementToStokesElementMap().count(darcyElementIdx))
219 382124 return;
220
221 // prepare the coupling context
222 28304 const auto& stokesElementIndices = couplingMapper_.darcyElementToStokesElementMap().at(darcyElementIdx);
223
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 14152 times.
14152 auto stokesFvGeometry = localView(this->problem(stokesIdx).gridGeometry());
224
225
4/4
✓ Branch 0 taken 14152 times.
✓ Branch 1 taken 14152 times.
✓ Branch 2 taken 14152 times.
✓ Branch 3 taken 14152 times.
70760 for(auto&& indices : stokesElementIndices)
226 {
227
5/10
✗ Branch 0 not taken.
✓ Branch 1 taken 14152 times.
✓ Branch 3 taken 14152 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 14152 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 14152 times.
✗ Branch 10 not taken.
✓ Branch 12 taken 14152 times.
✗ Branch 13 not taken.
14152 const auto& stokesElement = this->problem(stokesIdx).gridGeometry().boundingBoxTree().entitySet().entity(indices.eIdx);
228 14152 stokesFvGeometry.bindElement(stokesElement);
229
230 14152 VelocityVector faceVelocity(0.0);
231
232
6/6
✓ Branch 0 taken 56608 times.
✓ Branch 1 taken 14152 times.
✓ Branch 2 taken 56608 times.
✓ Branch 3 taken 14152 times.
✓ Branch 4 taken 14152 times.
✓ Branch 5 taken 42456 times.
84912 for(const auto& scvf : scvfs(stokesFvGeometry))
233 {
234
2/2
✓ Branch 0 taken 14152 times.
✓ Branch 1 taken 42456 times.
56608 if(scvf.index() == indices.scvfIdx)
235 70760 faceVelocity[scvf.directionIndex()] = this->curSol(stokesFaceIdx)[scvf.dofIndex()];
236 }
237
238 using PriVarsType = typename VolumeVariables<stokesCellCenterIdx>::PrimaryVariables;
239
2/4
✓ Branch 1 taken 14152 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 14152 times.
✗ Branch 5 not taken.
28304 const auto& cellCenterPriVars = this->curSol(stokesCellCenterIdx)[indices.eIdx];
240
1/2
✓ Branch 1 taken 14152 times.
✗ Branch 2 not taken.
28304 const auto elemSol = makeElementSolutionFromCellCenterPrivars<PriVarsType>(cellCenterPriVars);
241
242 14152 VolumeVariables<stokesIdx> stokesVolVars;
243
7/8
✓ Branch 0 taken 13112 times.
✓ Branch 1 taken 13112 times.
✓ Branch 2 taken 14152 times.
✓ Branch 3 taken 14152 times.
✓ Branch 4 taken 1040 times.
✓ Branch 5 taken 14152 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 1040 times.
47616 for(const auto& scv : scvs(stokesFvGeometry))
244
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 14152 times.
✓ Branch 3 taken 14152 times.
✗ Branch 4 not taken.
14152 stokesVolVars.update(elemSol, this->problem(stokesIdx), stokesElement, scv);
245
246 // add the context
247
4/10
✓ Branch 0 taken 14152 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 14152 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 14152 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 14152 times.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
42456 darcyCouplingContext_.push_back({stokesElement, stokesFvGeometry, indices.scvfIdx, indices.flipScvfIdx, faceVelocity, stokesVolVars});
248 }
249 }
250
251 using StaggeredCouplingManager<MDTraits>::updateCouplingContext;
252
253 //! \copydoc StaggeredCouplingManager::updateCouplingContext
254 template<class LocalAssemblerI>
255 void updateCouplingContext(Dune::index_constant<darcyIdx> domainI,
256 const LocalAssemblerI& localAssemblerI,
257 Dune::index_constant<darcyIdx> domainJ,
258 std::size_t dofIdxGlobalJ,
259 const PrimaryVariables<darcyIdx>& priVarsJ,
260 int pvIdxJ)
261 {
262 4860480 this->curSol(domainJ)[dofIdxGlobalJ][pvIdxJ] = priVarsJ[pvIdxJ];
263 }
264
265 //! \copydoc StaggeredCouplingManager::updateCouplingContext
266 template<class LocalAssemblerI>
267 42632 void updateCouplingContext(Dune::index_constant<darcyIdx> domainI,
268 const LocalAssemblerI& localAssemblerI,
269 Dune::index_constant<stokesCellCenterIdx> domainJ,
270 const std::size_t dofIdxGlobalJ,
271 const PrimaryVariables<stokesCellCenterIdx>& priVarsJ,
272 int pvIdxJ)
273 {
274 85264 this->curSol(domainJ)[dofIdxGlobalJ] = priVarsJ;
275
276
4/4
✓ Branch 0 taken 42632 times.
✓ Branch 1 taken 42632 times.
✓ Branch 2 taken 42632 times.
✓ Branch 3 taken 42632 times.
170528 for (auto& data : darcyCouplingContext_)
277 {
278
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 42632 times.
42632 const auto stokesElemIdx = this->problem(stokesIdx).gridGeometry().elementMapper().index(data.element);
279
280
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 42632 times.
42632 if(stokesElemIdx != dofIdxGlobalJ)
281 continue;
282
283 using PriVarsType = typename VolumeVariables<stokesCellCenterIdx>::PrimaryVariables;
284
2/6
✓ Branch 1 taken 42632 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 42632 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
127896 const auto elemSol = makeElementSolutionFromCellCenterPrivars<PriVarsType>(priVarsJ);
285
286
5/6
✓ Branch 0 taken 42632 times.
✓ Branch 1 taken 42632 times.
✓ Branch 2 taken 42632 times.
✓ Branch 3 taken 42632 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 42632 times.
134976 for(const auto& scv : scvs(data.fvGeometry))
287
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 42632 times.
✓ Branch 3 taken 42632 times.
✗ Branch 4 not taken.
42632 data.volVars.update(elemSol, this->problem(stokesIdx), data.element, scv);
288 }
289 42632 }
290
291 //! \copydoc StaggeredCouplingManager::updateCouplingContext
292 template<class LocalAssemblerI>
293 22664 void updateCouplingContext(Dune::index_constant<darcyIdx> domainI,
294 const LocalAssemblerI& localAssemblerI,
295 Dune::index_constant<stokesFaceIdx> domainJ,
296 const std::size_t dofIdxGlobalJ,
297 const PrimaryVariables<stokesFaceIdx>& priVarsJ,
298 int pvIdxJ)
299 {
300 45328 this->curSol(domainJ)[dofIdxGlobalJ] = priVarsJ;
301
302
4/4
✓ Branch 0 taken 22664 times.
✓ Branch 1 taken 22664 times.
✓ Branch 2 taken 22664 times.
✓ Branch 3 taken 22664 times.
90656 for (auto& data : darcyCouplingContext_)
303 {
304
6/6
✓ Branch 0 taken 90656 times.
✓ Branch 1 taken 22664 times.
✓ Branch 2 taken 90656 times.
✓ Branch 3 taken 22664 times.
✓ Branch 4 taken 22664 times.
✓ Branch 5 taken 67992 times.
135984 for(const auto& scvf : scvfs(data.fvGeometry))
305 {
306
4/4
✓ Branch 0 taken 22664 times.
✓ Branch 1 taken 67992 times.
✓ Branch 2 taken 22664 times.
✓ Branch 3 taken 67992 times.
181312 if(scvf.dofIndex() == dofIdxGlobalJ)
307 45328 data.velocity[scvf.directionIndex()] = priVarsJ;
308 }
309 }
310 22664 }
311
312 //! \copydoc StaggeredCouplingManager::updateCouplingContext
313 template<std::size_t i, class LocalAssemblerI, std::enable_if_t<(i == stokesCellCenterIdx || i == stokesFaceIdx), int> = 0>
314 183168 void updateCouplingContext(Dune::index_constant<i> domainI,
315 const LocalAssemblerI& localAssemblerI,
316 Dune::index_constant<darcyIdx> domainJ,
317 const std::size_t dofIdxGlobalJ,
318 const PrimaryVariables<darcyIdx>& priVarsJ,
319 int pvIdxJ)
320 {
321 366336 this->curSol(domainJ)[dofIdxGlobalJ] = priVarsJ;
322
323
4/4
✓ Branch 0 taken 91584 times.
✓ Branch 1 taken 91584 times.
✓ Branch 2 taken 91584 times.
✓ Branch 3 taken 91584 times.
732672 for (auto& data : stokesCouplingContext_)
324 {
325
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 91584 times.
183168 const auto darcyElemIdx = this->problem(darcyIdx).gridGeometry().elementMapper().index(data.element);
326
327
2/2
✓ Branch 0 taken 320 times.
✓ Branch 1 taken 91264 times.
183168 if(darcyElemIdx != dofIdxGlobalJ)
328 continue;
329
330 732672 const auto darcyElemSol = elementSolution(data.element, this->curSol(darcyIdx), this->problem(darcyIdx).gridGeometry());
331
332
2/2
✓ Branch 0 taken 91584 times.
✓ Branch 1 taken 91584 times.
549504 for(const auto& scv : scvs(data.fvGeometry))
333
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 91584 times.
183168 data.volVars.update(darcyElemSol, this->problem(darcyIdx), data.element, scv);
334 }
335 183168 }
336
337 // \}
338
339 /*!
340 * \brief Access the coupling data
341 */
342 const auto& couplingData() const
343 {
344
0/7
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
1170192 return *couplingData_;
345 }
346
347 /*!
348 * \brief Access the coupling context needed for the Stokes domain
349 */
350 1604692 const auto& stokesCouplingContext(const Element<stokesIdx>& element, const SubControlVolumeFace<stokesIdx>& scvf) const
351 {
352
4/8
✓ Branch 0 taken 1604692 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1604692 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 1604692 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 1604692 times.
3209384 if (stokesCouplingContext_.empty() || boundStokesElemIdx_ != scvf.insideScvIdx())
353 bindCouplingContext(stokesIdx, element);
354
355
2/4
✓ Branch 0 taken 1604692 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1604692 times.
✗ Branch 3 not taken.
4814076 for(const auto& context : stokesCouplingContext_)
356 {
357
1/2
✓ Branch 0 taken 1604692 times.
✗ Branch 1 not taken.
1604692 if(scvf.index() == context.stokesScvfIdx)
358 1604692 return context;
359 }
360
361 DUNE_THROW(Dune::InvalidStateException, "No coupling context found at scvf " << scvf.center());
362 }
363
364 /*!
365 * \brief Access the coupling context needed for the Darcy domain
366 */
367 105180 const auto& darcyCouplingContext(const Element<darcyIdx>& element, const SubControlVolumeFace<darcyIdx>& scvf) const
368 {
369
8/8
✓ Branch 0 taken 105168 times.
✓ Branch 1 taken 12 times.
✓ Branch 2 taken 105168 times.
✓ Branch 3 taken 12 times.
✓ Branch 4 taken 2808 times.
✓ Branch 5 taken 102360 times.
✓ Branch 6 taken 2808 times.
✓ Branch 7 taken 102360 times.
210360 if (darcyCouplingContext_.empty() || boundDarcyElemIdx_ != scvf.insideScvIdx())
370 2820 bindCouplingContext(darcyIdx, element);
371
372
2/4
✓ Branch 0 taken 105180 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 105180 times.
✗ Branch 3 not taken.
315540 for(const auto& context : darcyCouplingContext_)
373 {
374
1/2
✓ Branch 0 taken 105180 times.
✗ Branch 1 not taken.
105180 if(scvf.index() == context.darcyScvfIdx)
375 105180 return context;
376 }
377
378 DUNE_THROW(Dune::InvalidStateException, "No coupling context found at scvf " << scvf.center());
379 }
380
381 /*!
382 * \brief The coupling stencils
383 */
384 // \{
385
386 using StaggeredCouplingManager<MDTraits>::couplingStencil;
387
388 /*!
389 * \brief The Stokes cell center coupling stencil w.r.t. Darcy DOFs.
390 *
391 * \param domainI The Stokes domain index.
392 * \param elementI The Sokes domain element.
393 * \param domainJ The Darcy domain index.
394 */
395 483968 const CouplingStencil& couplingStencil(Dune::index_constant<stokesCellCenterIdx> domainI,
396 const Element<stokesIdx>& elementI,
397 Dune::index_constant<darcyIdx> domainJ) const
398 {
399
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 483968 times.
483968 const auto eIdx = this->problem(domainI).gridGeometry().elementMapper().index(elementI);
400
2/2
✓ Branch 1 taken 12088 times.
✓ Branch 2 taken 471880 times.
483968 if(stokesCellCenterCouplingStencils_.count(eIdx))
401 12088 return stokesCellCenterCouplingStencils_.at(eIdx);
402 else
403 471880 return emptyStencil_;
404 }
405
406 /*!
407 * \brief The coupling stencil of domain I, i.e. which domain J DOFs
408 * the given domain I element's residual depends on.
409 *
410 * \param domainI the index of the domain in which the given element lives.
411 * \param elementI the coupled element of domainI
412 * \param domainJ the domain index of the coupled domain
413 */
414 template<std::size_t i, std::size_t j>
415 const CouplingStencil& couplingStencil(Dune::index_constant<i> domainI,
416 const Element<i>& elementI,
417 Dune::index_constant<j> domainJ) const
418 { return emptyStencil_; }
419
420 /*!
421 * \brief Return the Stokes cell indices that influence the residual of
422 * an element in the Darcy domain.
423 *
424 * \param domainI The darcy domain index.
425 * \param elementI The element in the Darcy domain.
426 * \param domainJ the domain index of the Stokes domain
427 */
428 464384 const CouplingStencil& couplingStencil(Dune::index_constant<darcyIdx> domainI,
429 const Element<darcyIdx>& elementI,
430 Dune::index_constant<stokesCellCenterIdx> domainJ) const
431 {
432
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 464384 times.
464384 const auto eIdx = this->problem(domainI).gridGeometry().elementMapper().index(elementI);
433
2/2
✓ Branch 1 taken 12088 times.
✓ Branch 2 taken 452296 times.
464384 if(darcyToStokesCellCenterCouplingStencils_.count(eIdx))
434 12088 return darcyToStokesCellCenterCouplingStencils_.at(eIdx);
435 else
436 452296 return emptyStencil_;
437 }
438
439 /*!
440 * \brief Return the Stokes face indices that influence the residual of
441 * an element in the Darcy domain.
442 *
443 * \param domainI The darcy domain index.
444 * \param elementI The element in the Darcy domain.
445 * \param domainJ the domain index of the Stokes domain
446 */
447 464384 const CouplingStencil& couplingStencil(Dune::index_constant<darcyIdx> domainI,
448 const Element<darcyIdx>& elementI,
449 Dune::index_constant<stokesFaceIdx> domainJ) const
450 {
451
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 464384 times.
464384 const auto eIdx = this->problem(domainI).gridGeometry().elementMapper().index(elementI);
452
2/2
✓ Branch 1 taken 12088 times.
✓ Branch 2 taken 452296 times.
464384 if (darcyToStokesFaceCouplingStencils_.count(eIdx))
453 12088 return darcyToStokesFaceCouplingStencils_.at(eIdx);
454 else
455 452296 return emptyStencil_;
456 }
457
458 /*!
459 * \brief Return the dof indices of a subdomain that influence the residual of
460 * a sub-control volume face of the Stokes domain.
461 *
462 * \param domainI the index of the domain in which the given element lives.
463 * \param scvfI the coupled sub-control volume face of the Stokes domain
464 * \param domainJ the domain index of the coupled domain
465 */
466 template<std::size_t i, std::size_t j>
467 const CouplingStencil& couplingStencil(Dune::index_constant<i> domainI,
468 const SubControlVolumeFace<stokesIdx>& scvfI,
469 Dune::index_constant<j> domainJ) const
470 { return emptyStencil_; }
471
472 /*!
473 * \brief The coupling stencil of a Stokes face w.r.t. Darcy DOFs.
474 *
475 * \param domainI the index of the Stokes domain
476 * \param scvfI the coupled subcontrolvolume face of the Stokes domain
477 * \param domainJ the index of the Darcy domain
478 */
479 const CouplingStencil& couplingStencil(Dune::index_constant<stokesFaceIdx> domainI,
480 const SubControlVolumeFace<stokesIdx>& scvfI,
481 Dune::index_constant<darcyIdx> domainJ) const
482 {
483 const auto faceDofIdx = scvfI.dofIndex();
484 if(stokesFaceCouplingStencils_.count(faceDofIdx))
485 return stokesFaceCouplingStencils_.at(faceDofIdx);
486 else
487 return emptyStencil_;
488 }
489
490 // \}
491
492 /*!
493 * \brief There are no additional dof dependencies
494 */
495 template<class IdType>
496 const std::vector<std::size_t>& getAdditionalDofDependencies(IdType id, std::size_t stokesElementIdx) const
497 { return emptyStencil_; }
498
499 /*!
500 * \brief There are no additional dof dependencies
501 */
502 template<class IdType>
503 const std::vector<std::size_t>& getAdditionalDofDependenciesInverse(IdType id, std::size_t darcyElementIdx) const
504 { return emptyStencil_; }
505
506 /*!
507 * \brief Returns whether a given free flow scvf is coupled to the other domain
508 */
509 bool isCoupledEntity(Dune::index_constant<stokesIdx>, const SubControlVolumeFace<stokesFaceIdx>& scvf) const
510 {
511
6/6
✓ Branch 2 taken 261268 times.
✓ Branch 3 taken 95744 times.
✓ Branch 4 taken 85256 times.
✓ Branch 5 taken 108914 times.
✓ Branch 8 taken 1330708 times.
✓ Branch 9 taken 3326916 times.
10417612 return stokesFaceCouplingStencils_.count(scvf.dofIndex());
512 }
513
514 /*!
515 * \brief Returns whether a given free flow scvf is coupled to the other domain
516 */
517 bool isCoupledEntity(Dune::index_constant<darcyIdx>, const SubControlVolumeFace<darcyIdx>& scvf) const
518 {
519
16/20
✓ Branch 0 taken 80540 times.
✓ Branch 1 taken 94928 times.
✓ Branch 2 taken 80540 times.
✓ Branch 3 taken 94928 times.
✓ Branch 4 taken 94372 times.
✓ Branch 5 taken 147456 times.
✓ Branch 6 taken 94372 times.
✓ Branch 7 taken 147456 times.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✓ Branch 12 taken 11760 times.
✓ Branch 13 taken 11928 times.
✓ Branch 14 taken 11760 times.
✓ Branch 15 taken 11928 times.
✓ Branch 16 taken 3080 times.
✓ Branch 17 taken 9240 times.
✓ Branch 18 taken 3080 times.
✓ Branch 19 taken 9240 times.
906608 return couplingMapper_.isCoupledDarcyScvf(scvf.index());
520 }
521
522 protected:
523
524 //! Return a reference to an empty stencil
525 std::vector<std::size_t>& emptyStencil()
526 { return emptyStencil_; }
527
528 void removeDuplicates_(std::vector<std::size_t>& stencil)
529 {
530 std::sort(stencil.begin(), stencil.end());
531 stencil.erase(std::unique(stencil.begin(), stencil.end()), stencil.end());
532 }
533
534 private:
535
536 std::vector<bool> isCoupledDarcyDof_;
537 std::shared_ptr<CouplingData> couplingData_;
538
539 std::unordered_map<std::size_t, std::vector<std::size_t> > stokesCellCenterCouplingStencils_;
540 std::unordered_map<std::size_t, std::vector<std::size_t> > stokesFaceCouplingStencils_;
541 std::unordered_map<std::size_t, std::vector<std::size_t> > darcyToStokesCellCenterCouplingStencils_;
542 std::unordered_map<std::size_t, std::vector<std::size_t> > darcyToStokesFaceCouplingStencils_;
543 std::vector<std::size_t> emptyStencil_;
544
545 ////////////////////////////////////////////////////////////////////////////
546 //! The coupling context
547 ////////////////////////////////////////////////////////////////////////////
548 mutable std::vector<StationaryStokesCouplingContext> stokesCouplingContext_;
549 mutable std::vector<StationaryDarcyCouplingContext> darcyCouplingContext_;
550
551 mutable std::size_t boundStokesElemIdx_;
552 mutable std::size_t boundDarcyElemIdx_;
553
554 CouplingMapper couplingMapper_;
555 };
556
557 } // end namespace Dumux
558
559 #endif
560