version 3.7
geomechanics/poroelastic/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// 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_POROMECHANICS_COUPLING_MANAGER_HH
14#define DUMUX_POROMECHANICS_COUPLING_MANAGER_HH
15
16#include <algorithm>
17#include <type_traits>
18
22
23namespace Dumux {
24
37template< class MDTraits,
38 std::size_t PMFlowId = 0,
39 std::size_t PoroMechId = PMFlowId+1 >
40class PoroMechanicsCouplingManager : public virtual CouplingManager< MDTraits >
41{
43
44 // the sub-domain type tags
45 template<std::size_t id> using SubDomainTypeTag = typename MDTraits::template SubDomain<id>::TypeTag;
46
47 // further types specific to the sub-problems
48 template<std::size_t id> using Scalar = GetPropType<SubDomainTypeTag<id>, Properties::Scalar>;
49 template<std::size_t id> using Problem = GetPropType<SubDomainTypeTag<id>, Properties::Problem>;
50 template<std::size_t id> using LocalResidual = GetPropType<SubDomainTypeTag<id>, Properties::LocalResidual>;
51 template<std::size_t id> using GridVariables = GetPropType<SubDomainTypeTag<id>, Properties::GridVariables>;
52 template<std::size_t id> using PrimaryVariables = typename GridVariables<id>::PrimaryVariables;
53 template<std::size_t id> using GridVolumeVariables = typename GridVariables<id>::GridVolumeVariables;
54 template<std::size_t id> using ElementVolumeVariables = typename GridVolumeVariables<id>::LocalView;
55 template<std::size_t id> using VolumeVariables = typename GridVolumeVariables<id>::VolumeVariables;
56 template<std::size_t id> using GridGeometry = typename GridVariables<id>::GridGeometry;
57 template<std::size_t id> using FVElementGeometry = typename GridGeometry<id>::LocalView;
58 template<std::size_t id> using GridView = typename GridGeometry<id>::GridView;
59 template<std::size_t id> using GridIndexType = typename GridView<id>::IndexSet::IndexType;
60 template<std::size_t id> using Element = typename GridView<id>::template Codim<0>::Entity;
61 template<std::size_t id> using GlobalPosition = typename Element<id>::Geometry::GlobalCoordinate;
62
64 static_assert(std::is_same< GridView<PMFlowId>, GridView<PoroMechId> >::value,
65 "The grid types of the two sub-problems have to be equal!");
66
68 static_assert(GridGeometry<PoroMechId>::discMethod == DiscretizationMethods::box,
69 "Poro-mechanical problem must be discretized with the box scheme for this coupling manager!");
70
71 static_assert(GridGeometry<PMFlowId>::discMethod == DiscretizationMethods::cctpfa ||
72 GridGeometry<PMFlowId>::discMethod == DiscretizationMethods::ccmpfa,
73 "Porous medium flow problem must be discretized with a cell-centered scheme for this coupling manager!");
74
76 static_assert(!GetPropType<SubDomainTypeTag<PMFlowId>, Properties::GridVariables>::GridVolumeVariables::cachingEnabled,
77 "Poromechanics framework does not yet work for enabled grid volume variables caching");
78
80 template<std::size_t id>
81 using CouplingIndexType = typename std::conditional< id == PMFlowId,
82 GridIndexType<PoroMechId>,
83 GridIndexType<PMFlowId> >::type;
84
90 struct PoroMechanicsCouplingContext
91 {
92 // We need unique ptrs because the local views have no default constructor
93 Element<PMFlowId> pmFlowElement;
94 std::unique_ptr< FVElementGeometry<PMFlowId> > pmFlowFvGeometry;
95 std::unique_ptr< ElementVolumeVariables<PMFlowId> > pmFlowElemVolVars;
96 };
97
98public:
99
100 // export the domain ids
101 static constexpr auto pmFlowId = Dune::index_constant<PMFlowId>();
102 static constexpr auto poroMechId = Dune::index_constant<PoroMechId>();
103
109 template<std::size_t i, std::size_t j = (i == PMFlowId) ? PoroMechId : PMFlowId>
110 using CouplingStencilType = typename std::conditional< i == PMFlowId,
111 std::vector< CouplingIndexType<i> >,
112 std::array< CouplingIndexType<i>, 1> >::type;
113
115 using SolutionVector = typename MDTraits::SolutionVector;
116
124 void init(std::shared_ptr< Problem<PMFlowId> > pmFlowProblem,
125 std::shared_ptr< Problem<PoroMechId> > poroMechanicalProblem,
126 const SolutionVector& curSol)
127 {
128 // set the sub problems
129 this->setSubProblem(pmFlowProblem, pmFlowId);
130 this->setSubProblem(poroMechanicalProblem, poroMechId);
131
132 // copy the solution vector
134 // set up the coupling map pmfow -> poromechanics
135 initializeCouplingMap_();
136 }
137
141 const CouplingStencilType<PMFlowId>& couplingStencil(Dune::index_constant<PMFlowId> pmFlowDomainId,
142 const Element<PMFlowId>& element,
143 Dune::index_constant<PoroMechId> poroMechDomainId) const
144 {
145 return pmFlowCouplingMap_[ this->problem(pmFlowId).gridGeometry().elementMapper().index(element) ];
146 }
147
151 const CouplingStencilType<PoroMechId> couplingStencil(Dune::index_constant<PoroMechId> poroMechDomainId,
152 const Element<PoroMechId>& element,
153 Dune::index_constant<PMFlowId> pmFlowDomainId) const
154 {
155 const auto eIdx = this->problem(pmFlowId).gridGeometry().elementMapper().index(element);
156 return CouplingStencilType<PoroMechId>{ {eIdx} };
157 }
158
161
166 template< class Assembler >
167 void bindCouplingContext(Dune::index_constant<PoroMechId> poroMechDomainId,
168 const Element<PoroMechId>& element,
169 const Assembler& assembler)
170 {
171 // first reset the context
172 poroMechCouplingContext_.pmFlowFvGeometry.reset(nullptr);
173 poroMechCouplingContext_.pmFlowElemVolVars.reset(nullptr);
174
175 // prepare the fvGeometry and the element volume variables
176 // these quantities will be used later to obtain the effective pressure
177 const auto fvGeometry = localView( this->problem(pmFlowId).gridGeometry() ).bindElement(element);
178 const auto elemVolVars = localView(assembler.gridVariables(Dune::index_constant<PMFlowId>()).curGridVolVars()).bindElement(element,
179 fvGeometry,
180 this->curSol(Dune::index_constant<PMFlowId>()));
181
182 poroMechCouplingContext_.pmFlowElement = element;
183 poroMechCouplingContext_.pmFlowFvGeometry = std::make_unique< FVElementGeometry<PMFlowId> >(fvGeometry);
184 poroMechCouplingContext_.pmFlowElemVolVars = std::make_unique< ElementVolumeVariables<PMFlowId> >(elemVolVars);
185 }
186
192 template< class PoroMechLocalAssembler >
193 void updateCouplingContext(Dune::index_constant<PoroMechId> poroMechDomainId,
194 const PoroMechLocalAssembler& poroMechLocalAssembler,
195 Dune::index_constant<PMFlowId> pmFlowDomainId,
196 GridIndexType<PMFlowId> dofIdxGlobalJ,
197 const PrimaryVariables<PMFlowId>& priVarsJ,
198 unsigned int pvIdxJ)
199 {
200 // communicate the deflected pm flow domain primary variable
201 ParentType::updateCouplingContext(poroMechDomainId, poroMechLocalAssembler, pmFlowDomainId, dofIdxGlobalJ, priVarsJ, pvIdxJ);
202
203 // now, update the coupling context (i.e. elemVolVars)
204 const auto& element = poroMechCouplingContext_.pmFlowElement;
205 const auto& fvGeometry = *poroMechCouplingContext_.pmFlowFvGeometry;
206 poroMechCouplingContext_.pmFlowElemVolVars->bindElement(element, fvGeometry, this->curSol(pmFlowDomainId));
207 }
208
215 template< class PoroMechLocalAssembler >
216 void updateCouplingContext(Dune::index_constant<PoroMechId> poroMechDomainIdI,
217 const PoroMechLocalAssembler& poroMechLocalAssembler,
218 Dune::index_constant<PoroMechId> poroMechDomainIdJ,
219 GridIndexType<PoroMechId> dofIdxGlobalJ,
220 const PrimaryVariables<PoroMechId>& priVarsJ,
221 unsigned int pvIdxJ)
222 {
223 // communicate the deflected displacement
224 ParentType::updateCouplingContext(poroMechDomainIdI, poroMechLocalAssembler, poroMechDomainIdJ, dofIdxGlobalJ, priVarsJ, pvIdxJ);
225
226 // now, update the coupling context (i.e. elemVolVars)
227 (*poroMechCouplingContext_.pmFlowElemVolVars).bindElement(poroMechCouplingContext_.pmFlowElement,
228 *poroMechCouplingContext_.pmFlowFvGeometry,
229 this->curSol(Dune::index_constant<PMFlowId>()));
230 }
231
236 template< std::size_t j, class PMFlowLocalAssembler >
237 void updateCouplingContext(Dune::index_constant<PMFlowId> pmFlowDomainId,
238 const PMFlowLocalAssembler& pmFlowLocalAssembler,
239 Dune::index_constant<j> domainIdJ,
240 GridIndexType<j> dofIdxGlobalJ,
241 const PrimaryVariables<j>& priVarsJ,
242 unsigned int pvIdxJ)
243 {
244 // communicate the deflected displacement
245 ParentType::updateCouplingContext(pmFlowDomainId, pmFlowLocalAssembler, domainIdJ, dofIdxGlobalJ, priVarsJ, pvIdxJ);
246 }
247
250
256 template< class PMFlowLocalAssembler, class UpdatableFluxVarCache >
257 void updateCoupledVariables(Dune::index_constant<PMFlowId> pmFlowDomainId,
258 const PMFlowLocalAssembler& pmFlowLocalAssembler,
259 ElementVolumeVariables<PMFlowId>& elemVolVars,
260 UpdatableFluxVarCache& elemFluxVarsCache)
261 {
262 // update the element volume variables to obtain the updated porosity/permeability
263 elemVolVars.bind(pmFlowLocalAssembler.element(),
264 pmFlowLocalAssembler.fvGeometry(),
265 this->curSol(pmFlowDomainId));
266
267 // update the transmissibilities subject to the new permeabilities
268 elemFluxVarsCache.update(pmFlowLocalAssembler.element(),
269 pmFlowLocalAssembler.fvGeometry(),
270 elemVolVars);
271 }
272
278 template< class PoroMechLocalAssembler, class UpdatableFluxVarCache >
279 void updateCoupledVariables(Dune::index_constant<PoroMechId> poroMechDomainId,
280 const PoroMechLocalAssembler& poroMechLocalAssembler,
281 ElementVolumeVariables<PoroMechId>& elemVolVars,
282 UpdatableFluxVarCache& elemFluxVarsCache)
283 {
284 elemVolVars.bind(poroMechLocalAssembler.element(),
285 poroMechLocalAssembler.fvGeometry(),
286 this->curSol(poroMechDomainId));
287 }
288
295 template< class PMFlowLocalAssembler >
296 typename LocalResidual<PMFlowId>::ElementResidualVector
297 evalCouplingResidual(Dune::index_constant<PMFlowId> pmFlowDomainId,
298 const PMFlowLocalAssembler& pmFlowLocalAssembler,
299 Dune::index_constant<PoroMechId> poroMechDomainId,
300 GridIndexType<PoroMechId> dofIdxGlobalJ)
301 {
302 auto res = pmFlowLocalAssembler.localResidual().evalFluxAndSource(pmFlowLocalAssembler.element(),
303 pmFlowLocalAssembler.fvGeometry(),
304 pmFlowLocalAssembler.curElemVolVars(),
305 pmFlowLocalAssembler.elemFluxVarsCache(),
306 pmFlowLocalAssembler.elemBcTypes());
307
308 // If the residual instationary, evaluate storage
309 if (!pmFlowLocalAssembler.localResidual().isStationary())
310 res += pmFlowLocalAssembler.localResidual().evalStorage(pmFlowLocalAssembler.element(),
311 pmFlowLocalAssembler.fvGeometry(),
312 pmFlowLocalAssembler.prevElemVolVars(),
313 pmFlowLocalAssembler.curElemVolVars());
314
315 return res;
316 }
317
324 template< class PoroMechLocalAssembler >
325 typename LocalResidual<PoroMechId>::ElementResidualVector
326 evalCouplingResidual(Dune::index_constant<PoroMechId> poroMechDomainId,
327 const PoroMechLocalAssembler& poroMechLocalAssembler,
328 Dune::index_constant<PMFlowId> pmFlowDomainId,
329 GridIndexType<PMFlowId> dofIdxGlobalJ)
330 {
331 return poroMechLocalAssembler.localResidual().evalFluxAndSource(poroMechLocalAssembler.element(),
332 poroMechLocalAssembler.fvGeometry(),
333 poroMechLocalAssembler.curElemVolVars(),
334 poroMechLocalAssembler.elemFluxVarsCache(),
335 poroMechLocalAssembler.elemBcTypes());
336 }
337
339 const VolumeVariables<PMFlowId>& getPMFlowVolVars(const Element<PoroMechId>& element) const
340 {
342 const auto eIdx = this->problem(poroMechId).gridGeometry().elementMapper().index(element);
343 return (*poroMechCouplingContext_.pmFlowElemVolVars)[eIdx];
344 }
345
351 template<std::size_t i>
352 const auto& curSol(Dune::index_constant<i> domainIdx) const
353 { return ParentType::curSol(domainIdx); }
354
355
356private:
362 void initializeCouplingMap_()
363 {
364 // some references for convenience
365 const auto& pmFlowGridGeom = this->problem(pmFlowId).gridGeometry();
366 const auto& poroMechGridGeom = this->problem(poroMechId).gridGeometry();
367
368 // make sure the two grids are really the same. Note that if the two grids
369 // happen to have equal number of elements by chance, we don't detect this source of error.
370 if (pmFlowGridGeom.gridView().size(0) != poroMechGridGeom.gridView().size(0))
371 DUNE_THROW(Dune::InvalidStateException, "The two sub-problems are assumed to operate on the same mesh!");
372
373 pmFlowCouplingMap_.resize(pmFlowGridGeom.gridView().size(0));
374 static constexpr int dim = GridView<PMFlowId>::dimension;
375 for (const auto& element : elements(pmFlowGridGeom.gridView()))
376 {
377 const auto eIdx = pmFlowGridGeom.elementMapper().index(element);
378
379 // firstly, the element couples to the nodal dofs in itself
380 for (int i = 0; i < element.geometry().corners(); ++i)
381 pmFlowCouplingMap_[eIdx].push_back( poroMechGridGeom.vertexMapper().subIndex(element, i , dim) );
382
383 // the pm flow problem couples to the same elements as in its own stencil
384 // due to the dependency of the residual on all permeabilities in its stencil,
385 // which in turn depend on the mechanical deformations.
386 const auto& inverseConnectivity = pmFlowGridGeom.connectivityMap()[eIdx];
387 for (const auto& dataJ : inverseConnectivity)
388 for (int i = 0; i < element.geometry().corners(); ++i)
389 pmFlowCouplingMap_[dataJ.globalJ].push_back( poroMechGridGeom.vertexMapper().subIndex(element, i , dim) );
390 }
391
392 // make stencils unique
393 for (auto& stencil : pmFlowCouplingMap_)
394 {
395 std::sort(stencil.begin(), stencil.end());
396 stencil.erase(std::unique(stencil.begin(), stencil.end()), stencil.end());
397 }
398 }
399
400 // Container for storing the coupling element stencils for the pm flow domain
401 std::vector< CouplingStencilType<PMFlowId> > pmFlowCouplingMap_;
402
403 // the coupling context of the poromechanics domain
404 PoroMechanicsCouplingContext poroMechCouplingContext_;
405};
406
407} //end namespace Dumux
408
409#endif
The interface of the coupling manager for multi domain problems.
Definition: multidomain/couplingmanager.hh:48
void updateCoupledVariables(Dune::index_constant< i > domainI, const LocalAssemblerI &localAssemblerI, UpdatableElementVolVars &elemVolVars, UpdatableFluxVarCache &elemFluxVarsCache)
update variables of domain i that depend on variables in domain j after the coupling context has been...
Definition: multidomain/couplingmanager.hh:208
void setSubProblem(std::shared_ptr< SubProblem > problem, Dune::index_constant< i > domainIdx)
set a pointer to one of the sub problems
Definition: multidomain/couplingmanager.hh:300
const Problem< i > & problem(Dune::index_constant< i > domainIdx) const
Return a reference to the sub problem.
Definition: multidomain/couplingmanager.hh:309
void bindCouplingContext(Dune::index_constant< i > domainI, const Element< i > &elementI, const Assembler &assembler)
prepares all data and variables that are necessary to evaluate the residual of the element of domain ...
Definition: multidomain/couplingmanager.hh:157
SubSolutionVector< i > & curSol(Dune::index_constant< i > domainIdx)
the solution vector of the subproblem
Definition: multidomain/couplingmanager.hh:338
void updateSolution(const SolutionVector &curSol)
Updates the entire solution vector, e.g. before assembly or after grid adaption Overload might want t...
Definition: multidomain/couplingmanager.hh:219
Coupling manager for porous medium flow problems coupled to a poro-mechanical problem.
Definition: geomechanics/poroelastic/couplingmanager.hh:41
void bindCouplingContext(Dune::index_constant< PoroMechId > poroMechDomainId, const Element< PoroMechId > &element, const Assembler &assembler)
For the assembly of the element residual of an element of the poro-mechanics domain,...
Definition: geomechanics/poroelastic/couplingmanager.hh:167
typename std::conditional< i==PMFlowId, std::vector< CouplingIndexType< i > >, std::array< CouplingIndexType< i >, 1 > >::type CouplingStencilType
The types used for coupling stencils. An element of the poro-mechanical domain always only couples to...
Definition: geomechanics/poroelastic/couplingmanager.hh:112
void updateCoupledVariables(Dune::index_constant< PoroMechId > poroMechDomainId, const PoroMechLocalAssembler &poroMechLocalAssembler, ElementVolumeVariables< PoroMechId > &elemVolVars, UpdatableFluxVarCache &elemFluxVarsCache)
Update the poro-mechanics volume variables after the coupling context has been updated....
Definition: geomechanics/poroelastic/couplingmanager.hh:279
void updateCoupledVariables(Dune::index_constant< PMFlowId > pmFlowDomainId, const PMFlowLocalAssembler &pmFlowLocalAssembler, ElementVolumeVariables< PMFlowId > &elemVolVars, UpdatableFluxVarCache &elemFluxVarsCache)
Update the porous medium flow domain volume variables and flux variables cache after the coupling con...
Definition: geomechanics/poroelastic/couplingmanager.hh:257
const VolumeVariables< PMFlowId > & getPMFlowVolVars(const Element< PoroMechId > &element) const
Return the porous medium flow variables an element/scv of the poromech domain couples to.
Definition: geomechanics/poroelastic/couplingmanager.hh:339
void updateCouplingContext(Dune::index_constant< PMFlowId > pmFlowDomainId, const PMFlowLocalAssembler &pmFlowLocalAssembler, Dune::index_constant< j > domainIdJ, GridIndexType< j > dofIdxGlobalJ, const PrimaryVariables< j > &priVarsJ, unsigned int pvIdxJ)
We need this overload to avoid ambiguity. However, for the porous medium flow domain weonly have to u...
Definition: geomechanics/poroelastic/couplingmanager.hh:237
static constexpr auto pmFlowId
Definition: geomechanics/poroelastic/couplingmanager.hh:101
void updateCouplingContext(Dune::index_constant< PoroMechId > poroMechDomainIdI, const PoroMechLocalAssembler &poroMechLocalAssembler, Dune::index_constant< PoroMechId > poroMechDomainIdJ, GridIndexType< PoroMechId > dofIdxGlobalJ, const PrimaryVariables< PoroMechId > &priVarsJ, unsigned int pvIdxJ)
After deflection of the solution in the poromechanics domain during element residual assembly in that...
Definition: geomechanics/poroelastic/couplingmanager.hh:216
void updateCouplingContext(Dune::index_constant< PoroMechId > poroMechDomainId, const PoroMechLocalAssembler &poroMechLocalAssembler, Dune::index_constant< PMFlowId > pmFlowDomainId, GridIndexType< PMFlowId > dofIdxGlobalJ, const PrimaryVariables< PMFlowId > &priVarsJ, unsigned int pvIdxJ)
After deflection of the solution in the porous medium flow domain during element residual assembly in...
Definition: geomechanics/poroelastic/couplingmanager.hh:193
LocalResidual< PMFlowId >::ElementResidualVector evalCouplingResidual(Dune::index_constant< PMFlowId > pmFlowDomainId, const PMFlowLocalAssembler &pmFlowLocalAssembler, Dune::index_constant< PoroMechId > poroMechDomainId, GridIndexType< PoroMechId > dofIdxGlobalJ)
Evaluates the coupling element residual of the porous medium flow domain with respect to the poro-mec...
Definition: geomechanics/poroelastic/couplingmanager.hh:297
void init(std::shared_ptr< Problem< PMFlowId > > pmFlowProblem, std::shared_ptr< Problem< PoroMechId > > poroMechanicalProblem, const SolutionVector &curSol)
Initialize the coupling manager.
Definition: geomechanics/poroelastic/couplingmanager.hh:124
const CouplingStencilType< PoroMechId > couplingStencil(Dune::index_constant< PoroMechId > poroMechDomainId, const Element< PoroMechId > &element, Dune::index_constant< PMFlowId > pmFlowDomainId) const
Return the coupling element stencil for a given poro-mechanical domain element.
Definition: geomechanics/poroelastic/couplingmanager.hh:151
const auto & curSol(Dune::index_constant< i > domainIdx) const
the solution vector of the subproblem
Definition: geomechanics/poroelastic/couplingmanager.hh:352
typename MDTraits::SolutionVector SolutionVector
the type of the solution vector
Definition: geomechanics/poroelastic/couplingmanager.hh:115
LocalResidual< PoroMechId >::ElementResidualVector evalCouplingResidual(Dune::index_constant< PoroMechId > poroMechDomainId, const PoroMechLocalAssembler &poroMechLocalAssembler, Dune::index_constant< PMFlowId > pmFlowDomainId, GridIndexType< PMFlowId > dofIdxGlobalJ)
Evaluates the coupling element residual of the poromechanical domain with respect to the porous mediu...
Definition: geomechanics/poroelastic/couplingmanager.hh:326
static constexpr auto poroMechId
Definition: geomechanics/poroelastic/couplingmanager.hh:102
const CouplingStencilType< PMFlowId > & couplingStencil(Dune::index_constant< PMFlowId > pmFlowDomainId, const Element< PMFlowId > &element, Dune::index_constant< PoroMechId > poroMechDomainId) const
Return the coupling stencil for a given porous medium flow domain element.
Definition: geomechanics/poroelastic/couplingmanager.hh:141
Defines all properties used in Dumux.
GridCache::LocalView localView(const GridCache &gridCache)
Free function to get the local view of a grid cache object.
Definition: localview.hh:26
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)
updates all data and variables that are necessary to evaluate the residual of the element of domain i...
Definition: multidomain/couplingmanager.hh:183
typename GetProp< TypeTag, Property >::type GetPropType
get the type alias defined in the property
Definition: propertysystem.hh:267
The available discretization methods in Dumux.
The interface of the coupling manager for multi domain problems.
constexpr CCMpfa ccmpfa
Definition: method.hh:146
constexpr CCTpfa cctpfa
Definition: method.hh:145
constexpr Box box
Definition: method.hh:147
Definition: adapt.hh:17