version 3.10-dev
multibinarycouplingmanager.hh
Go to the documentation of this file.
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//
13#ifndef DUMUX_MULTIDOMAIN_MULTIBINARY_COUPLINGMANAGER_HH
14#define DUMUX_MULTIDOMAIN_MULTIBINARY_COUPLINGMANAGER_HH
15
16#include <utility>
17#include <memory>
18#include <dune/common/hybridutilities.hh>
21
22namespace Dumux {
23
24namespace Detail {
25
26template <std::size_t, typename Tuple>
27struct HasIndex;
28
29template <std::size_t i, typename... Indices>
30struct HasIndex<i, std::tuple<Indices...>>
31: std::disjunction<std::is_same<Dune::index_constant<i>, Indices>...>
32{};
33
34} // end namespace Detail
35
48template<class MDTraits, class CouplingMap, class ...CouplingMgrs>
50{
51 // the sub domain type tags
52 template<std::size_t id>
53 using SubDomainTypeTag = typename MDTraits::template SubDomain<id>::TypeTag;
54
55 template<std::size_t id> using GridGeometry = GetPropType<SubDomainTypeTag<id>, Properties::GridGeometry>;
56 template<std::size_t id> using GridView = typename GridGeometry<id>::GridView;
57 template<std::size_t id> using Element = typename GridView<id>::template Codim<0>::Entity;
58 template<std::size_t id> using FVElementGeometry = typename GridGeometry<id>::LocalView;
59 template<std::size_t id> using SubControlVolumeFace = typename FVElementGeometry<id>::SubControlVolumeFace;
60 template<std::size_t id> using SubControlVolume = typename FVElementGeometry<id>::SubControlVolume;
61 using CouplingStencil = std::vector<std::size_t>;
62
63 template<std::size_t id>
64 using SubCouplingManagerT = typename std::tuple_element_t<id, std::tuple<CouplingMgrs...>>;
65
66 using CMIndices = std::make_index_sequence<sizeof...(CouplingMgrs)>;
68
69 template<std::size_t id>
70 using SubSolutionVector = std::decay_t<decltype(std::declval<typename MDTraits::SolutionVector>()[Dune::index_constant<id>()])>;
71 using SolutionVectors = typename MDTraits::template TupleOfSharedPtr<SubSolutionVector>;
72
73 static constexpr auto couplingManagerMap_ = CouplingMap::managerMap();
74
76 template<std::size_t i, std::size_t j>
77 static constexpr auto globalToLocal_(Dune::index_constant<i> domainI, Dune::index_constant<j> domainJ)
78 {
79 static_assert(i <= MDTraits::numSubDomains && j <= MDTraits::numSubDomains);
80 return CouplingMap::globalToLocal(domainI, domainJ);
81 }
82
84 template<class Map, std::size_t i, std::size_t j>
85 static constexpr bool isCoupled_(Dune::index_constant<i> domainI, Dune::index_constant<j>)
86 { return Detail::HasIndex<j, std::decay_t<decltype(Map::coupledDomains(domainI))>>::value; }
87
89 template<std::size_t i, std::size_t j>
90 static constexpr auto subCouplingManagerIndex_(Dune::index_constant<i> domainI, Dune::index_constant<j> domainJ)
91 {
92 static_assert(
93 isCoupled_<CouplingMap>(domainI, domainJ),
94 "Sub-coupling manager only exists for coupled domains."
95 );
96 return couplingManagerMap_[i][j];
97 }
98
99public:
100 template<std::size_t i, std::size_t j>
101 using SubCouplingManager = SubCouplingManagerT<couplingManagerMap_[i][j]>;
102
104 {
105 using namespace Dune::Hybrid;
106 forEach(couplingManagers_, [&](auto&& couplingManager)
107 {
108 couplingManager = std::make_shared<typename std::decay_t<decltype(couplingManager)>::element_type>();
109 });
110
111 forEach(solutionVectors_, [&](auto&& solutionVector)
112 {
113 solutionVector = std::make_shared<typename std::decay_t<decltype(solutionVector)>::element_type>();
114 });
115 }
116
118 template<std::size_t i, std::size_t j>
119 auto& subCouplingManager(Dune::index_constant<i> domainI,
120 Dune::index_constant<j> domainJ)
121 {
122 constexpr auto idx = subCouplingManagerIndex_(domainI, domainJ);
123 return *std::get<idx>(couplingManagers_);
124 }
125
127 template<std::size_t i, std::size_t j>
128 const auto& subCouplingManager(Dune::index_constant<i> domainI,
129 Dune::index_constant<j> domainJ) const
130 {
131 constexpr auto idx = subCouplingManagerIndex_(domainI, domainJ);
132 return *std::get<idx>(couplingManagers_);
133 }
134
136 template<std::size_t i, std::size_t j, class Apply>
137 decltype(auto) subApply(Dune::index_constant<i> domainI,
138 Dune::index_constant<j> domainJ,
139 Apply&& apply)
140 {
141 constexpr auto localIndices = globalToLocal_(domainI, domainJ);
142 return apply(subCouplingManager(domainI, domainJ), localIndices.first, localIndices.second);
143 }
144
146 template<std::size_t i, std::size_t j, class Apply>
147 decltype(auto) subApply(Dune::index_constant<i> domainI,
148 Dune::index_constant<j> domainJ,
149 const Apply& apply) const
150 {
151 constexpr auto localIndices = globalToLocal_(domainI, domainJ);
152 return apply(subCouplingManager(domainI, domainJ), localIndices.first, localIndices.second);
153 }
154
156 template<std::size_t i, class Apply>
157 decltype(auto) subApply(Dune::index_constant<i> domainI, Apply&& apply)
158 {
159 constexpr auto dm = CouplingMap::coupledDomains(domainI);
160 static_assert(std::tuple_size_v<std::decay_t<decltype(dm)>> != 0, "subApply on uncoupled domain!");
161 constexpr auto domainJ = std::get<0>(dm);
162 constexpr auto localIndices = globalToLocal_(domainI, domainJ);
163 return apply(subCouplingManager(domainI, domainJ), localIndices.first);
164 }
165
167 template<std::size_t i, class Apply>
168 decltype(auto) subApply(Dune::index_constant<i> domainI, const Apply& apply) const
169 {
170 constexpr auto dm = CouplingMap::coupledDomains(domainI);
171 static_assert(std::tuple_size_v<std::decay_t<decltype(dm)>> != 0, "subApply on uncoupled domain!");
172 constexpr auto domainJ = std::get<0>(dm);
173 constexpr auto localIndices = globalToLocal_(domainI, domainJ);
174 return apply(subCouplingManager(domainI, domainJ), localIndices.first);
175 }
176
178 void updateSolution(const typename MDTraits::SolutionVector& curSol)
179 {
180 using namespace Dune::Hybrid;
181 forEach(integralRange(Dune::Hybrid::size(solutionVectors_)), [&](const auto id)
182 {
183 *std::get<id>(solutionVectors_) = curSol[id];
184 });
185 }
186
195 template<std::size_t id, class JacobianPattern>
196 void extendJacobianPattern(Dune::index_constant<id> domainI, JacobianPattern& pattern) const
197 {}
198
202 template<std::size_t i, class Entity, std::size_t j>
203 const auto& couplingStencil(Dune::index_constant<i> domainI,
204 const Entity& entity,
205 Dune::index_constant<j> domainJ) const
206 {
207 // if the domains are coupled according to the map, forward to sub-coupling manager
208 if constexpr (isCoupled_<CouplingMap>(domainI, domainJ))
209 return subApply(domainI, domainJ, [&](const auto& cm, auto&& ii, auto&& jj) -> const auto& {
210 return cm.couplingStencil(ii, entity, jj);
211 });
212 else
213 return emptyStencil_;
214 }
215
216 // ! evaluate coupling residual for the derivative low dim DOF with respect to bulk DOF
217 // ! we only need to evaluate the part of the residual that will be influence by the bulk DOF
218 template<std::size_t i, class LocalAssemblerI, std::size_t j>
219 decltype(auto) evalCouplingResidual(Dune::index_constant<i> domainI,
220 const SubControlVolumeFace<i>& scvfI,
221 const LocalAssemblerI& localAssemblerI,
222 Dune::index_constant<j> domainJ,
223 std::size_t dofIdxGlobalJ) const
224 {
225 if constexpr (i == j || isCoupled_<CouplingMap>(domainI, domainJ))
226 return subApply(domainI, domainJ, [&](const auto& cm, auto&& ii, auto&& jj) -> decltype(auto) {
227 return cm.evalCouplingResidual(ii, scvfI, localAssemblerI, jj, dofIdxGlobalJ);
228 });
229 else
230 {
231 DUNE_THROW(Dune::InvalidStateException,
232 "Calling evalCouplingResidual for uncoupled domains " << i << " and " << j
233 );
234 return localAssemblerI.evalLocalResidual();
235 }
236 }
237
240 template<std::size_t i, class LocalAssemblerI, std::size_t j>
241 decltype(auto) evalCouplingResidual(Dune::index_constant<i> domainI,
242 const LocalAssemblerI& localAssemblerI,
243 Dune::index_constant<j> domainJ,
244 std::size_t dofIdxGlobalJ) const
245 {
246 if constexpr (i == j || isCoupled_<CouplingMap>(domainI, domainJ))
247 return subApply(domainI, domainJ, [&](const auto& cm, auto&& ii, auto&& jj) -> decltype(auto) {
248 return cm.evalCouplingResidual(ii, localAssemblerI, jj, dofIdxGlobalJ);
249 });
250 else
251 {
252 DUNE_THROW(Dune::InvalidStateException,
253 "Calling evalCouplingResidual for uncoupled domains " << i << " and " << j
254 );
255 return localAssemblerI.evalLocalResidual();
256 }
257 }
258
261 template<std::size_t i, class LocalAssemblerI, std::size_t j>
262 decltype(auto) evalCouplingResidual(Dune::index_constant<i> domainI,
263 const LocalAssemblerI& localAssemblerI,
264 const SubControlVolume<i>& scvI,
265 Dune::index_constant<j> domainJ,
266 std::size_t dofIdxGlobalJ) const
267 {
268 if constexpr (i == j || isCoupled_<CouplingMap>(domainI, domainJ))
269 return subApply(domainI, domainJ, [&](const auto& cm, auto&& ii, auto&& jj) -> decltype(auto) {
270 return cm.evalCouplingResidual(ii, localAssemblerI, scvI, jj, dofIdxGlobalJ);
271 });
272 else
273 {
274 DUNE_THROW(Dune::InvalidStateException,
275 "Calling evalCouplingResidual for uncoupled domains " << i << " and " << j
276 );
277 return localAssemblerI.evalLocalResidual();
278 }
279 }
280
284 template<std::size_t i, class LocalAssemblerI, std::size_t j, class PrimaryVariables>
285 void updateCouplingContext(Dune::index_constant<i> domainI,
286 const LocalAssemblerI& localAssemblerI,
287 Dune::index_constant<j> domainJ,
288 const std::size_t dofIdxGlobalJ,
289 const PrimaryVariables& priVars,
290 int pvIdxJ)
291 {
292 // only one other manager needs to take action if i != j
293 if constexpr (i != j)
294 {
295 if constexpr (isCoupled_<CouplingMap>(domainI, domainJ))
296 subApply(domainI, domainJ, [&](auto& cm, auto&& ii, auto&& jj){
297 cm.updateCouplingContext(ii, localAssemblerI, jj, dofIdxGlobalJ, priVars, pvIdxJ);
298 });
299 }
300 else
301 {
302 // for i == j, we need to call all relevant managers where domainI is involved and make sure that the
303 // context is updated with respect to its own domain (I-I coupling context)
304 using namespace Dune::Hybrid;
305 forEach(CouplingMap::coupledDomains(domainI), [&](const auto domainJ){
306 static_assert(domainI != domainJ);
307 subApply(domainI, domainJ, [&](auto& cm, auto&& ii, auto&& jj){
308 cm.updateCouplingContext(ii, localAssemblerI, ii, dofIdxGlobalJ, priVars, pvIdxJ);
309 });
310 });
311 }
312 }
313
315 template<std::size_t i, class Assembler = int>
316 void bindCouplingContext(Dune::index_constant<i> domainI, const Element<i>& element, const Assembler& assembler = 0)
317 {
318 // for the coupling blocks
319 using namespace Dune::Hybrid;
320 forEach(CouplingMap::coupledDomains(domainI), [&](const auto domainJ){
321 subApply(domainI, domainJ, [&](auto& cm, auto&& ii, auto&& jj) -> void {
322 cm.bindCouplingContext(ii, element, assembler);
323 });
324 });
325 }
326
331 template<std::size_t i>
332 decltype(auto) numericEpsilon(Dune::index_constant<i> domainI,
333 const std::string& paramGroup) const
334 {
335 return subApply(domainI, [&](const auto& cm, auto&& ii) -> decltype(auto) {
336 return cm.numericEpsilon(ii, paramGroup);
337 });
338 }
339
346 template<std::size_t i, class LocalAssemblerI, class JacobianMatrixDiagBlock, class GridVariables>
347 void evalAdditionalDomainDerivatives(Dune::index_constant<i> domainI,
348 const LocalAssemblerI& localAssemblerI,
349 const typename LocalAssemblerI::LocalResidual::ElementResidualVector& origResiduals,
350 JacobianMatrixDiagBlock& A,
351 GridVariables& gridVariables)
352 {}
353
354 template<std::size_t i, class LocalAssemblerI, class UpdatableElementVolVars, class UpdatableFluxVarCache>
355 void updateCoupledVariables(Dune::index_constant<i> domainI,
356 const LocalAssemblerI& localAssemblerI,
357 UpdatableElementVolVars& elemVolVars,
358 UpdatableFluxVarCache& elemFluxVarsCache)
359 {
360 // for the coupling blocks
361 using namespace Dune::Hybrid;
362 forEach(CouplingMap::coupledDomains(domainI), [&](const auto domainJ){
363 subApply(domainI, domainJ, [&](auto& cm, auto&& ii, auto&& jj){
364 cm.updateCoupledVariables(ii, localAssemblerI, elemVolVars, elemFluxVarsCache);
365 });
366 });
367 }
368
369protected:
370 SolutionVectors& curSol()
371 { return solutionVectors_; }
372
373 const SolutionVectors& curSol() const
374 { return solutionVectors_; }
375
376private:
377 CouplingManagers couplingManagers_;
378 SolutionVectors solutionVectors_;
379
380 CouplingStencil emptyStencil_;
381};
382
383} // end namespace Dumux
384
385#endif
Coupling manager that combines an arbitrary number of binary coupling manager (coupling two domains e...
Definition: multibinarycouplingmanager.hh:50
decltype(auto) evalCouplingResidual(Dune::index_constant< i > domainI, const LocalAssemblerI &localAssemblerI, const SubControlVolume< i > &scvI, Dune::index_constant< j > domainJ, std::size_t dofIdxGlobalJ) const
Definition: multibinarycouplingmanager.hh:262
decltype(auto) evalCouplingResidual(Dune::index_constant< i > domainI, const LocalAssemblerI &localAssemblerI, Dune::index_constant< j > domainJ, std::size_t dofIdxGlobalJ) const
Definition: multibinarycouplingmanager.hh:241
SubCouplingManagerT< couplingManagerMap_[i][j]> SubCouplingManager
Definition: multibinarycouplingmanager.hh:101
const auto & couplingStencil(Dune::index_constant< i > domainI, const Entity &entity, Dune::index_constant< j > domainJ) const
Return the coupling element stencil for a given bulk domain element.
Definition: multibinarycouplingmanager.hh:203
MultiBinaryCouplingManager()
Definition: multibinarycouplingmanager.hh:103
void evalAdditionalDomainDerivatives(Dune::index_constant< i > domainI, const LocalAssemblerI &localAssemblerI, const typename LocalAssemblerI::LocalResidual::ElementResidualVector &origResiduals, JacobianMatrixDiagBlock &A, GridVariables &gridVariables)
evaluate additional derivatives of the element residual of a domain with respect to dofs in the same ...
Definition: multibinarycouplingmanager.hh:347
decltype(auto) numericEpsilon(Dune::index_constant< i > domainI, const std::string &paramGroup) const
return the numeric epsilon used for deflecting primary variables of coupled domain i.
Definition: multibinarycouplingmanager.hh:332
decltype(auto) subApply(Dune::index_constant< i > domainI, Dune::index_constant< j > domainJ, Apply &&apply)
apply a function to the domainI-domainJ sub coupling manager using its local indices
Definition: multibinarycouplingmanager.hh:137
auto & subCouplingManager(Dune::index_constant< i > domainI, Dune::index_constant< j > domainJ)
return the binary sub-coupling manager
Definition: multibinarycouplingmanager.hh:119
void updateCoupledVariables(Dune::index_constant< i > domainI, const LocalAssemblerI &localAssemblerI, UpdatableElementVolVars &elemVolVars, UpdatableFluxVarCache &elemFluxVarsCache)
Definition: multibinarycouplingmanager.hh:355
void extendJacobianPattern(Dune::index_constant< id > domainI, JacobianPattern &pattern) const
extend the jacobian pattern of the diagonal block of domain i by those entries that are not already i...
Definition: multibinarycouplingmanager.hh:196
decltype(auto) subApply(Dune::index_constant< i > domainI, Apply &&apply)
apply a function to a sub coupling manager containing this domain
Definition: multibinarycouplingmanager.hh:157
void bindCouplingContext(Dune::index_constant< i > domainI, const Element< i > &element, const Assembler &assembler=0)
Bind the coupling context for a low dim element TODO remove Assembler.
Definition: multibinarycouplingmanager.hh:316
void updateCouplingContext(Dune::index_constant< i > domainI, const LocalAssemblerI &localAssemblerI, Dune::index_constant< j > domainJ, const std::size_t dofIdxGlobalJ, const PrimaryVariables &priVars, int pvIdxJ)
Update the coupling context for the bulk face residual w.r.t to the lowDim dofs.
Definition: multibinarycouplingmanager.hh:285
decltype(auto) evalCouplingResidual(Dune::index_constant< i > domainI, const SubControlVolumeFace< i > &scvfI, const LocalAssemblerI &localAssemblerI, Dune::index_constant< j > domainJ, std::size_t dofIdxGlobalJ) const
Definition: multibinarycouplingmanager.hh:219
const SolutionVectors & curSol() const
Definition: multibinarycouplingmanager.hh:373
decltype(auto) subApply(Dune::index_constant< i > domainI, const Apply &apply) const
apply a function to a sub coupling manager containing this domain
Definition: multibinarycouplingmanager.hh:168
SolutionVectors & curSol()
Definition: multibinarycouplingmanager.hh:370
void updateSolution(const typename MDTraits::SolutionVector &curSol)
Update the solution vector before assembly.
Definition: multibinarycouplingmanager.hh:178
const auto & subCouplingManager(Dune::index_constant< i > domainI, Dune::index_constant< j > domainJ) const
return the binary sub-coupling manager
Definition: multibinarycouplingmanager.hh:128
decltype(auto) subApply(Dune::index_constant< i > domainI, Dune::index_constant< j > domainJ, const Apply &apply) const
apply a function to the domainI-domainJ sub coupling manager using its local indices
Definition: multibinarycouplingmanager.hh:147
Defines all properties used in Dumux.
typename GetProp< TypeTag, Property >::type GetPropType
get the type alias defined in the property
Definition: propertysystem.hh:296
Traits for multidomain problems.
constexpr auto coupledDomains(Dune::index_constant< i > domainI)
Definition: multidomain/boundary/freeflowporenetwork/couplingmanager.hh:64
Definition: adapt.hh:17
Definition: multibinarycouplingmanager.hh:27
typename makeFromIndexedType< std::tuple, PtrType, Indices >::type type
Definition: multidomain/traits.hh:79