3.5-git
DUNE for Multi-{Phase, Component, Scale, Physics, ...} flow and transport in porous media
Loading...
Searching...
No Matches
multidomain/boundary/freeflowporousmedium/ffmasspm/couplingmanager.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 * See the file COPYING for full copying permissions. *
5 * *
6 * This program is free software: you can redistribute it and/or modify *
7 * it under the terms of the GNU General Public License as published by *
8 * the Free Software Foundation, either version 3 of the License, or *
9 * (at your option) any later version. *
10 * *
11 * This program is distributed in the hope that it will be useful, *
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
14 * GNU General Public License for more details. *
15 * *
16 * You should have received a copy of the GNU General Public License *
17 * along with this program. If not, see <http://www.gnu.org/licenses/>. *
18 *****************************************************************************/
24
25#ifndef DUMUX_MULTIDOMAIN_BOUNDARY_FFPM_FFMASSPM_COUPLINGMANAGER_HH
26#define DUMUX_MULTIDOMAIN_BOUNDARY_FFPM_FFMASSPM_COUPLINGMANAGER_HH
27
28#include <utility>
29#include <memory>
30
31#include <dune/common/float_cmp.hh>
32#include <dune/common/exceptions.hh>
37
38namespace Dumux {
39
44template<class MDTraits>
46: public CouplingManager<MDTraits>
47{
48 using Scalar = typename MDTraits::Scalar;
49 using ParentType = CouplingManager<MDTraits>;
50
51public:
52 static constexpr auto freeFlowMassIndex = typename MDTraits::template SubDomain<0>::Index();
53 static constexpr auto porousMediumIndex = typename MDTraits::template SubDomain<1>::Index();
54
56private:
57
58 // obtain the type tags of the sub problems
59 using FreeFlowMassTypeTag = typename MDTraits::template SubDomain<freeFlowMassIndex>::TypeTag;
60 using PorousMediumTypeTag = typename MDTraits::template SubDomain<porousMediumIndex>::TypeTag;
61
62 using CouplingStencils = std::unordered_map<std::size_t, std::vector<std::size_t> >;
63 using CouplingStencil = CouplingStencils::mapped_type;
64
65 // the sub domain type tags
66 template<std::size_t id>
67 using SubDomainTypeTag = typename MDTraits::template SubDomain<id>::TypeTag;
68
69 template<std::size_t id> using GridView = typename GetPropType<SubDomainTypeTag<id>, Properties::GridGeometry>::GridView;
70 template<std::size_t id> using Problem = GetPropType<SubDomainTypeTag<id>, Properties::Problem>;
71 template<std::size_t id> using ElementVolumeVariables = typename GetPropType<SubDomainTypeTag<id>, Properties::GridVolumeVariables>::LocalView;
72 template<std::size_t id> using GridVolumeVariables = GetPropType<SubDomainTypeTag<id>, Properties::GridVolumeVariables>;
73 template<std::size_t id> using VolumeVariables = typename GetPropType<SubDomainTypeTag<id>, Properties::GridVolumeVariables>::VolumeVariables;
74 template<std::size_t id> using GridGeometry = GetPropType<SubDomainTypeTag<id>, Properties::GridGeometry>;
75 template<std::size_t id> using FVElementGeometry = typename GridGeometry<id>::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 PrimaryVariables = GetPropType<SubDomainTypeTag<id>, Properties::PrimaryVariables>;
79 template<std::size_t id> using SubControlVolumeFace = typename FVElementGeometry<id>::SubControlVolumeFace;
80 template<std::size_t id> using SubControlVolume = typename FVElementGeometry<id>::SubControlVolume;
81
82 using VelocityVector = typename Element<freeFlowMassIndex>::Geometry::GlobalCoordinate;
83
84 struct FreeFlowMassCouplingContext
85 {
86 Element<porousMediumIndex> element;
87 VolumeVariables<porousMediumIndex> volVars;
88 FVElementGeometry<porousMediumIndex> fvGeometry;
89 std::size_t dofIdx;
90 std::size_t freeFlowMassScvfIdx;
91 std::size_t porousMediumScvfIdx;
92 mutable VelocityVector velocity; // velocity needs to be set externally, not availabe in this class
93 };
94
95 struct PorousMediumCouplingContext
96 {
97 Element<freeFlowMassIndex> element;
98 VolumeVariables<freeFlowMassIndex> volVars;
99 FVElementGeometry<freeFlowMassIndex> fvGeometry;
100 std::size_t dofIdx;
101 std::size_t porousMediumScvfIdx;
102 std::size_t freeFlowMassScvfIdx;
103 mutable VelocityVector velocity; // velocity needs to be set externally, not availabe in this class
104 };
105
106 using CouplingMapper = DarcyDarcyBoundaryCouplingMapper<MDTraits>; // TODO rename/generalize class
107
108public:
109
113 // \{
114
116 void init(std::shared_ptr<Problem<freeFlowMassIndex>> freeFlowMassProblem,
117 std::shared_ptr<Problem<porousMediumIndex>> darcyProblem,
119 {
120 this->setSubProblems(std::make_tuple(freeFlowMassProblem, darcyProblem));
121 this->attachSolution(curSol);
122
123 couplingMapper_.update(*this);
124 }
125
126 // \}
127
131 // \{
132
136 template<std::size_t i, class Assembler>
137 void bindCouplingContext(Dune::index_constant<i> domainI, const Element<i>& element, const Assembler& assembler) const
138 {
139 bindCouplingContext_(domainI, element);
140 }
141
145 template<std::size_t i, std::size_t j, class LocalAssemblerI>
146 void updateCouplingContext(Dune::index_constant<i> domainI,
147 const LocalAssemblerI& localAssemblerI,
148 Dune::index_constant<j> domainJ,
149 std::size_t dofIdxGlobalJ,
150 const PrimaryVariables<j>& priVarsJ,
151 int pvIdxJ)
152 {
153 this->curSol(domainJ)[dofIdxGlobalJ][pvIdxJ] = priVarsJ[pvIdxJ];
154
155 // we need to update all solution-depenent components of the coupling context
156 // the dof of domain J has been deflected
157 // if domainJ == freeFlowMassIndex: update volvars in the PorousMediumCouplingContext
158 // if domainJ == porousMediumIndex: update volvars in the FreeFlowMassCouplingContext
159 // as the update is symmetric we only need to write this once
160 auto& context = std::get<1-j>(couplingContext_);
161 for (auto& c : context)
162 {
163 if (c.dofIdx == dofIdxGlobalJ)
164 {
165 const auto elemSol = elementSolution(c.element, this->curSol(domainJ), this->problem(domainJ).gridGeometry());
166 const auto& scv = *scvs(c.fvGeometry).begin();
167 c.volVars.update(elemSol, this->problem(domainJ), c.element, scv);
168 }
169 }
170 }
171
172 // \}
173
177 template<std::size_t i>
178 const auto& couplingContext(Dune::index_constant<i> domainI,
179 const FVElementGeometry<i>& fvGeometry,
180 const SubControlVolumeFace<i> scvf) const
181 {
182 auto& contexts = std::get<i>(couplingContext_);
183
184 if (contexts.empty() || couplingContextBoundForElement_[i] != scvf.insideScvIdx())
185 bindCouplingContext_(domainI, fvGeometry);
186
187 for (const auto& context : contexts)
188 {
189 const auto expectedScvfIdx = domainI == freeFlowMassIndex ? context.freeFlowMassScvfIdx : context.porousMediumScvfIdx;
190 if (scvf.index() == expectedScvfIdx)
191 return context;
192 }
193
194 DUNE_THROW(Dune::InvalidStateException, "No coupling context found at scvf " << scvf.center());
195 }
196
200 // \{
201
205 template<std::size_t i, std::size_t j>
206 const CouplingStencil& couplingStencil(Dune::index_constant<i> domainI,
207 const Element<i>& element,
208 Dune::index_constant<j> domainJ) const
209 {
210 const auto eIdx = this->problem(domainI).gridGeometry().elementMapper().index(element);
211 return couplingMapper_.couplingStencil(domainI, eIdx, domainJ);
212 }
213
214 // \}
215
219 template<std::size_t i>
220 bool isCoupled(Dune::index_constant<i> domainI, const SubControlVolumeFace<i>& scvf) const
221 { return couplingMapper_.isCoupled(domainI, scvf); }
222
223private:
227 template<std::size_t i>
228 bool isCoupledElement_(Dune::index_constant<i> domainI, std::size_t eIdx) const
229 { return couplingMapper_.isCoupledElement(domainI, eIdx); }
230
232 template<std::size_t i>
233 VolumeVariables<i> volVars_(Dune::index_constant<i> domainI,
234 const Element<i>& element,
235 const SubControlVolume<i>& scv) const
236 {
237 VolumeVariables<i> volVars;
238 const auto elemSol = elementSolution(
239 element, this->curSol(domainI), this->problem(domainI).gridGeometry()
240 );
241 volVars.update(elemSol, this->problem(domainI), element, scv);
242 return volVars;
243 }
244
248 template<std::size_t i>
249 void bindCouplingContext_(Dune::index_constant<i> domainI, const Element<i>& element) const
250 {
251 const auto fvGeometry = localView(this->problem(domainI).gridGeometry()).bindElement(element);
252 bindCouplingContext_(domainI, fvGeometry);
253 }
254
258 template<std::size_t i>
259 void bindCouplingContext_(Dune::index_constant<i> domainI, const FVElementGeometry<i>& fvGeometry) const
260 {
261 auto& context = std::get<domainI>(couplingContext_);
262 context.clear();
263
264 const auto eIdx = this->problem(domainI).gridGeometry().elementMapper().index(fvGeometry.element());
265
266 // do nothing if the element is not coupled to the other domain
267 if (!isCoupledElement_(domainI, eIdx))
268 return;
269
270 couplingContextBoundForElement_[domainI] = eIdx;
271
272 for (const auto& scvf : scvfs(fvGeometry))
273 {
274 if (isCoupled(domainI, scvf))
275 {
276 const auto otherElementIdx = couplingMapper_.outsideElementIndex(domainI, scvf);
277 constexpr auto domainJ = Dune::index_constant<1-domainI>();
278 const auto& otherGridGeometry = this->problem(domainJ).gridGeometry();
279 const auto& otherElement = otherGridGeometry.element(otherElementIdx);
280 auto otherFvGeometry = localView(otherGridGeometry).bindElement(otherElement);
281
282 // there is only one scv for TPFA
283 context.push_back({
284 otherElement,
285 volVars_(domainJ, otherElement, *std::begin(scvs(otherFvGeometry))),
286 std::move(otherFvGeometry),
287 otherElementIdx,
288 scvf.index(),
289 couplingMapper_.flipScvfIndex(domainI, scvf),
290 VelocityVector{}
291 });
292 }
293 }
294 }
295
296 mutable std::tuple<std::vector<FreeFlowMassCouplingContext>, std::vector<PorousMediumCouplingContext>> couplingContext_;
297 mutable std::array<std::size_t, 2> couplingContextBoundForElement_;
298
299 CouplingMapper couplingMapper_;
300};
301
302} // end namespace Dumux
303
304#endif
GridCache::LocalView localView(const GridCache &gridCache)
Free function to get the local view of a grid cache object.
Definition localview.hh:38
auto elementSolution(const Element &element, const SolutionVector &sol, const GridGeometry &gg) -> std::enable_if_t< GridGeometry::discMethod==DiscretizationMethods::box, BoxElementSolution< typename GridGeometry::LocalView, std::decay_t< decltype(std::declval< SolutionVector >()[0])> > >
Make an element solution for box schemes.
Definition box/elementsolution.hh:118
Definition adapt.hh:29
typename Properties::Detail::GetPropImpl< TypeTag, Property >::type::type GetPropType
get the type alias defined in the property
Definition propertysystem.hh:150
A vector of primary variables.
Definition common/properties.hh:49
Property to specify the type of a problem which has to be solved.
Definition common/properties.hh:57
Definition common/properties.hh:102
The type for a global container for the volume variables.
Definition common/properties.hh:109
The grid variables object managing variable data on the grid (volvars/fluxvars cache).
Definition common/properties.hh:123
bool isCoupledElement(Dune::index_constant< i >, std::size_t eIdx) const
Return if an element residual with index eIdx of domain i is coupled to domain j.
Definition boundary/darcydarcy/couplingmapper.hh:190
Coupling manager for Stokes and Darcy domains with equal dimension.
Definition multidomain/boundary/freeflowporousmedium/ffmasspm/couplingmanager.hh:47
void bindCouplingContext(Dune::index_constant< i > domainI, const Element< i > &element, const Assembler &assembler) const
Methods to be accessed by the assembly.
Definition multidomain/boundary/freeflowporousmedium/ffmasspm/couplingmanager.hh:137
void init(std::shared_ptr< Problem< freeFlowMassIndex > > freeFlowMassProblem, std::shared_ptr< Problem< porousMediumIndex > > darcyProblem, SolutionVectorStorage &curSol)
Methods to be accessed by main.
Definition multidomain/boundary/freeflowporousmedium/ffmasspm/couplingmanager.hh:116
static constexpr auto porousMediumIndex
Definition multidomain/boundary/freeflowporousmedium/ffmasspm/couplingmanager.hh:53
const CouplingStencil & couplingStencil(Dune::index_constant< i > domainI, const Element< i > &element, Dune::index_constant< j > domainJ) const
The coupling stencils.
Definition multidomain/boundary/freeflowporousmedium/ffmasspm/couplingmanager.hh:206
bool isCoupled(Dune::index_constant< i > domainI, const SubControlVolumeFace< i > &scvf) const
Returns whether a given scvf is coupled to the other domain.
Definition multidomain/boundary/freeflowporousmedium/ffmasspm/couplingmanager.hh:220
static constexpr auto freeFlowMassIndex
Definition multidomain/boundary/freeflowporousmedium/ffmasspm/couplingmanager.hh:52
const auto & couplingContext(Dune::index_constant< i > domainI, const FVElementGeometry< i > &fvGeometry, const SubControlVolumeFace< i > scvf) const
Access the coupling context needed for the Stokes domain.
Definition multidomain/boundary/freeflowporousmedium/ffmasspm/couplingmanager.hh:178
typename ParentType::SolutionVectorStorage SolutionVectorStorage
Definition multidomain/boundary/freeflowporousmedium/ffmasspm/couplingmanager.hh:55
void updateCouplingContext(Dune::index_constant< i > domainI, const LocalAssemblerI &localAssemblerI, Dune::index_constant< j > domainJ, std::size_t dofIdxGlobalJ, const PrimaryVariables< j > &priVarsJ, int pvIdxJ)
Update the coupling context.
Definition multidomain/boundary/freeflowporousmedium/ffmasspm/couplingmanager.hh:146
void attachSolution(SolutionVectorStorage &curSol)
Definition multidomain/couplingmanager.hh:333
decltype(auto) curSol()
Definition multidomain/couplingmanager.hh:369
void setSubProblems(const std::tuple< std::shared_ptr< SubProblems >... > &problems)
Definition multidomain/couplingmanager.hh:298
const Problem< i > & problem(Dune::index_constant< i > domainIdx) const
Definition multidomain/couplingmanager.hh:320
SubSolutionVector< i > & curSol(Dune::index_constant< i > domainIdx)
Definition multidomain/couplingmanager.hh:349
CouplingManager()
Definition multidomain/couplingmanager.hh:93
typename Traits::template TupleOfSharedPtr< SubSolutionVector > SolutionVectorStorage
the type in which the solution vector is stored in the manager
Definition multidomain/couplingmanager.hh:82
The local element solution class for staggered methods.
The interface of the coupling manager for multi domain problems.
the default mapper for conforming equal dimension boundary coupling between two domains (box or cc)
Declares all properties used in Dumux.