version 3.11-dev
Loading...
Searching...
No Matches
poromechanics/poroelastic_large_deformations/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-FileCopyrightText: Copyright © DuMux Project contributors, see AUTHORS.md in root folder
5// SPDX-License-Identifier: GPL-3.0-or-later
6//
13#ifndef DUMUX_POROMECHANICS_POROELASTIC_LARGE_DEFORMATIONS_COUPLING_MANAGER_HH
14#define DUMUX_POROMECHANICS_POROELASTIC_LARGE_DEFORMATIONS_COUPLING_MANAGER_HH
15
16#include <array>
17#include <deque>
18#include <limits>
19#include <memory>
20#include <tuple>
21#include <type_traits>
22#include <utility>
23#include <vector>
24
25#include <dune/common/exceptions.hh>
26#include <dune/common/fmatrix.hh>
27#include <dune/common/indices.hh>
28#include <dune/common/reservedvector.hh>
29
31#include <dumux/common/concepts/ipdata_.hh>
36
37namespace Dumux {
38
47template<class MDTraits>
49{
50 using ParentType = CouplingManager<MDTraits>;
51
52 template<std::size_t id> using SubDomainTypeTag = typename MDTraits::template SubDomain<id>::TypeTag;
53 template<std::size_t id> using GridDiscretization = GetPropType<SubDomainTypeTag<id>, Properties::GridGeometry>;
54 template<std::size_t id> using ElementDiscretization = typename GridDiscretization<id>::LocalView;
55 template<std::size_t id> using GridView = typename GridDiscretization<id>::GridView;
56 template<std::size_t id> using Element = typename GridView<id>::template Codim<0>::Entity;
57 template<std::size_t id> using ElementSeed = typename GridView<id>::Grid::template Codim<0>::EntitySeed;
58
59 using Scalar = typename MDTraits::Scalar;
60 using SolutionVector = typename MDTraits::SolutionVector;
61
62 static constexpr std::size_t momIdx_ = 0;
63 static constexpr std::size_t spIdx_ = 1;
64 static constexpr std::size_t fpIdx_ = 2;
65
66 using GlobalPosition = typename Element<0>::Geometry::GlobalCoordinate;
67 using LocalPosition = typename Element<0>::Geometry::LocalCoordinate;
68 using Tensor = Dune::FieldMatrix<Scalar, GridView<0>::dimension, GridView<0>::dimension>;
69 static constexpr int dim = GridView<0>::dimension;
70
71public:
72 static constexpr auto momentumIdx = Dune::index_constant<momIdx_>{};
73 static constexpr auto solidPressureIdx = Dune::index_constant<spIdx_>{};
74 static constexpr auto fluidPressureIdx = Dune::index_constant<fpIdx_>{};
75
76 using CouplingStencilType = std::vector<std::size_t>;
77
79 std::shared_ptr<GridDiscretization<momIdx_>> momGridDisc,
80 std::shared_ptr<GridDiscretization<spIdx_>> spGridDisc,
81 std::shared_ptr<GridDiscretization<fpIdx_>> fpGridDisc)
82 {
83 buildStencils_(*momGridDisc, *spGridDisc, *fpGridDisc);
84 }
85
86 void init(
87 std::shared_ptr<GetPropType<SubDomainTypeTag<momIdx_>, Properties::Problem>> momProblem,
88 std::shared_ptr<GetPropType<SubDomainTypeTag<spIdx_>, Properties::Problem>> spProblem,
89 std::shared_ptr<GetPropType<SubDomainTypeTag<fpIdx_>, Properties::Problem>> fpProblem,
90 const SolutionVector& curSol)
91 {
93 this->setSubProblems(std::make_tuple(momProblem, spProblem, fpProblem));
94 }
95
101 template<std::size_t i, class LocalAssemblerI, std::size_t j>
102 typename LocalAssemblerI::LocalResidual::ElementResidualVector
103 evalCouplingResidual(Dune::index_constant<i>,
104 const LocalAssemblerI& localAssemblerI,
105 Dune::index_constant<j>, std::size_t)
106 {
107 const auto [tWeight, sWeight] = localAssemblerI.assembler().currentStageWeights();
108 return localAssemblerI.evalLocalResidualForStage(localAssemblerI.curElemVars(), tWeight, sWeight);
109 }
110
111 template<std::size_t i, std::size_t j>
112 const CouplingStencilType& couplingStencil(Dune::index_constant<i>,
113 const Element<j>& element,
114 Dune::index_constant<j>) const
115 {
116 static_assert(i != j);
117 const auto eIdx = this->problem(Dune::index_constant<j>{})
118 .gridDiscretization().elementMapper().index(element);
119 return stencils_[j][i][eIdx];
120 }
121
122 template<Concept::IpData IpData>
123 Scalar solidPressure(const ElementDiscretization<momIdx_>& elemDisc,
124 const IpData& ipData) const
125 { return pressure_(elemDisc.element(), ipData, this->curSol(solidPressureIdx)); }
126
127 template<Concept::IpData IpData>
128 Scalar fluidPressure(const ElementDiscretization<momIdx_>& elemDisc,
129 const IpData& ipData) const
130 { return pressure_(elemDisc.element(), ipData, this->curSol(fluidPressureIdx)); }
131
132 template<Concept::IpData IpData>
133 Tensor deformationGradient(const ElementDiscretization<fpIdx_>& elemDisc,
134 const IpData& ipData) const
135 {
136 const auto& momGridDisc = this->problem(momentumIdx).gridDiscretization();
137 const auto& element = elemDisc.element();
138 const auto& momSol = this->curSol(momentumIdx);
139
140 // the basis gradients only depend on the reference geometry and are cached per element and
141 // integration point; points are compared in local coordinates, so the tolerance scales with
142 // the element size
143 thread_local std::size_t cachedEIdx = std::numeric_limits<std::size_t>::max();
144 thread_local std::vector<IpGradients_> ipCache;
145
146 const auto eIdx = momGridDisc.elementMapper().index(element);
147 if (eIdx != cachedEIdx) { ipCache.clear(); cachedEIdx = eIdx; }
148
149 const auto& ipLocal = ipData.local();
150 const IpGradients_* grads = nullptr;
151 for (const auto& entry : ipCache)
152 if ((entry.ipLocal - ipLocal).two_norm2() < 1e-20) { grads = &entry; break; }
153
154 if (grads == nullptr)
155 {
156 const auto elemDiscMom = localView(momGridDisc).bindElement(element);
157 const auto& localBasis = elemDiscMom.feLocalBasis();
158 using ShapeJac = typename std::decay_t<decltype(localBasis)>::Traits::JacobianType;
159 thread_local std::vector<ShapeJac> shapeJac;
160 localBasis.evaluateJacobian(ipLocal, shapeJac);
161 const auto jacInvT = element.geometry().jacobianInverseTransposed(ipLocal);
162
163 IpGradients_ entry;
164 entry.ipLocal = ipLocal;
165 for (const auto& localDof : localDofs(elemDiscMom))
166 {
167 GlobalPosition gradN;
168 jacInvT.mv(shapeJac[localDof.index()][0], gradN);
169 entry.dofGrads.push_back({localDof.dofIndex(), gradN});
170 }
171 ipCache.push_back(std::move(entry));
172 grads = &ipCache.back();
173 }
174
175 Tensor F(0.0);
176 for (const auto& dg : grads->dofGrads)
177 for (int d = 0; d < dim; ++d)
178 F[d].axpy(momSol[dg.dofIndex][d], dg.gradN);
179 for (int d = 0; d < dim; ++d) F[d][d] += 1.0;
180 return F;
181 }
182
184 {
185 elementSets_ = computeColoring(
187 }
188
189 template<std::size_t i, class AssembleElementFunc>
190 void assembleMultithreaded(Dune::index_constant<i>, AssembleElementFunc&& f) const
191 {
192 if (elementSets_.empty())
193 DUNE_THROW(Dune::InvalidStateException,
194 "Call computeColorsForAssembly before parallel assembly!");
195 const auto& grid = this->problem(Dune::index_constant<i>{})
196 .gridDiscretization().gridView().grid();
197 for (const auto& elems : elementSets_)
198 Dumux::parallelFor(elems.size(), [&](std::size_t n)
199 { f(grid.entity(elems[n])); });
200 }
201
202 template<std::size_t i>
203 auto& curSol(Dune::index_constant<i> id) { return ParentType::curSol(id); }
204 template<std::size_t i>
205 const auto& curSol(Dune::index_constant<i> id) const { return ParentType::curSol(id); }
206 const SolutionVector& curSol() const { return ParentType::curSol(); }
207
208private:
209 struct DofGrad_ { std::size_t dofIndex; GlobalPosition gradN; };
210 static constexpr std::size_t maxMomLocalDofs_ = 32;
211 struct IpGradients_
212 {
213 LocalPosition ipLocal;
214 Dune::ReservedVector<DofGrad_, maxMomLocalDofs_> dofGrads;
215 };
216
217 struct DofShape_ { std::size_t dofIndex; Scalar shapeValue; };
218 static constexpr std::size_t maxPresLocalDofs_ = 8;
219 struct IpShapes_
220 {
221 LocalPosition ipLocal;
222 Dune::ReservedVector<DofShape_, maxPresLocalDofs_> dofShapes;
223 };
224
225 // solid and fluid pressure are both interpolated with the basis of the fluid pressure
226 // discretization, so both need the same discretization
227 template<class IpData, class SolVec>
228 Scalar pressure_(const Element<fpIdx_>& element,
229 const IpData& ipData,
230 const SolVec& sol) const
231 {
232 thread_local std::size_t cachedEIdx = std::numeric_limits<std::size_t>::max();
233 thread_local std::vector<IpShapes_> ipCache;
234
235 const auto& presGridDisc = this->problem(fluidPressureIdx).gridDiscretization();
236 const auto eIdx = presGridDisc.elementMapper().index(element);
237 if (eIdx != cachedEIdx) { ipCache.clear(); cachedEIdx = eIdx; }
238
239 const auto& ipLocal = ipData.local();
240 const IpShapes_* shapes = nullptr;
241 for (const auto& entry : ipCache)
242 if ((entry.ipLocal - ipLocal).two_norm2() < 1e-20) { shapes = &entry; break; }
243
244 if (shapes == nullptr)
245 {
246 const auto elemDiscPres = localView(presGridDisc).bindElement(element);
247 const auto& localBasis = elemDiscPres.feLocalBasis();
248 using RangeType = typename std::decay_t<decltype(localBasis)>::Traits::RangeType;
249 thread_local std::vector<RangeType> shapeVals;
250 localBasis.evaluateFunction(ipLocal, shapeVals);
251
252 IpShapes_ entry;
253 entry.ipLocal = ipLocal;
254 for (const auto& localDof : localDofs(elemDiscPres))
255 entry.dofShapes.push_back({localDof.dofIndex(), shapeVals[localDof.index()][0]});
256 ipCache.push_back(std::move(entry));
257 shapes = &ipCache.back();
258 }
259
260 Scalar p = 0.0;
261 for (const auto& ds : shapes->dofShapes)
262 p += sol[ds.dofIndex][0] * ds.shapeValue;
263 return p;
264 }
265
266 void buildStencils_(const GridDiscretization<momIdx_>& momGridDisc,
267 const GridDiscretization<spIdx_>& spGridDisc,
268 const GridDiscretization<fpIdx_>& fpGridDisc)
269 {
270 const std::size_t n = fpGridDisc.gridView().size(0);
271 for (auto& arr : stencils_)
272 for (auto& s : arr)
273 {
274 s.clear();
275 s.resize(n);
276 }
277
278 auto elemDiscMom = localView(momGridDisc);
279 auto elemDiscSp = localView(spGridDisc);
280
281 for (const auto& element : elements(fpGridDisc.gridView()))
282 {
283 elemDiscMom.bindElement(element);
284 elemDiscSp.bindElement(element);
285 const std::size_t eIdx = fpGridDisc.elementMapper().index(element);
286
287 for (const auto& localDof : localDofs(elemDiscMom))
288 {
289 stencils_[momIdx_][spIdx_][eIdx].push_back(localDof.dofIndex());
290 stencils_[momIdx_][fpIdx_][eIdx].push_back(localDof.dofIndex());
291 }
292 for (const auto& localDof : localDofs(elemDiscSp))
293 {
294 stencils_[spIdx_][momIdx_][eIdx].push_back(localDof.dofIndex());
295 stencils_[fpIdx_][momIdx_][eIdx].push_back(localDof.dofIndex());
296 }
297 }
298 }
299
301 std::array<std::array<std::vector<CouplingStencilType>, 3>, 3> stencils_;
302
303 std::deque<std::vector<ElementSeed<momIdx_>>> elementSets_;
304};
305
306template<class MDTraits>
309
310} // end namespace Dumux
311#endif
Traits shared by the multi-domain assemblers.
void setSubProblems(const std::tuple< std::shared_ptr< SubProblems >... > &problems)
Definition multidomain/couplingmanager.hh:296
const Problem< i > & problem(Dune::index_constant< i > domainIdx) const
Definition multidomain/couplingmanager.hh:318
SubSolutionVector< i > & curSol(Dune::index_constant< i > domainIdx)
Definition multidomain/couplingmanager.hh:347
void updateSolution(const SolutionVector &curSol)
Definition multidomain/couplingmanager.hh:228
CouplingManager()
Definition multidomain/couplingmanager.hh:70
Coupling manager for the large-deformation poroelastic model.
Definition poromechanics/poroelastic_large_deformations/couplingmanager.hh:49
Tensor deformationGradient(const ElementDiscretization< fpIdx_ > &elemDisc, const IpData &ipData) const
Definition poromechanics/poroelastic_large_deformations/couplingmanager.hh:133
const SolutionVector & curSol() const
Definition poromechanics/poroelastic_large_deformations/couplingmanager.hh:206
void computeColorsForAssembly()
Definition poromechanics/poroelastic_large_deformations/couplingmanager.hh:183
Scalar fluidPressure(const ElementDiscretization< momIdx_ > &elemDisc, const IpData &ipData) const
Definition poromechanics/poroelastic_large_deformations/couplingmanager.hh:128
PoroElasticLargeDefCouplingManager(std::shared_ptr< GridDiscretization< momIdx_ > > momGridDisc, std::shared_ptr< GridDiscretization< spIdx_ > > spGridDisc, std::shared_ptr< GridDiscretization< fpIdx_ > > fpGridDisc)
Definition poromechanics/poroelastic_large_deformations/couplingmanager.hh:78
const CouplingStencilType & couplingStencil(Dune::index_constant< i >, const Element< j > &element, Dune::index_constant< j >) const
Definition poromechanics/poroelastic_large_deformations/couplingmanager.hh:112
Scalar solidPressure(const ElementDiscretization< momIdx_ > &elemDisc, const IpData &ipData) const
Definition poromechanics/poroelastic_large_deformations/couplingmanager.hh:123
void init(std::shared_ptr< GetPropType< SubDomainTypeTag< momIdx_ >, Properties::Problem > > momProblem, std::shared_ptr< GetPropType< SubDomainTypeTag< spIdx_ >, Properties::Problem > > spProblem, std::shared_ptr< GetPropType< SubDomainTypeTag< fpIdx_ >, Properties::Problem > > fpProblem, const SolutionVector &curSol)
Definition poromechanics/poroelastic_large_deformations/couplingmanager.hh:86
static constexpr auto fluidPressureIdx
Definition poromechanics/poroelastic_large_deformations/couplingmanager.hh:74
const auto & curSol(Dune::index_constant< i > id) const
Definition poromechanics/poroelastic_large_deformations/couplingmanager.hh:205
std::vector< std::size_t > CouplingStencilType
Definition poromechanics/poroelastic_large_deformations/couplingmanager.hh:76
static constexpr auto momentumIdx
Definition poromechanics/poroelastic_large_deformations/couplingmanager.hh:72
void assembleMultithreaded(Dune::index_constant< i >, AssembleElementFunc &&f) const
Definition poromechanics/poroelastic_large_deformations/couplingmanager.hh:190
static constexpr auto solidPressureIdx
Definition poromechanics/poroelastic_large_deformations/couplingmanager.hh:73
auto & curSol(Dune::index_constant< i > id)
Definition poromechanics/poroelastic_large_deformations/couplingmanager.hh:203
LocalAssemblerI::LocalResidual::ElementResidualVector evalCouplingResidual(Dune::index_constant< i >, const LocalAssemblerI &localAssemblerI, Dune::index_constant< j >, std::size_t)
Evaluate the residual of domain i w.r.t. a perturbation in domain j.
Definition poromechanics/poroelastic_large_deformations/couplingmanager.hh:103
Coloring schemes for shared-memory-parallel assembly.
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 parallelFor(const std::size_t count, const FunctorType &functor)
A parallel for loop (multithreading).
Definition parallel_for.hh:160
typename GetProp< TypeTag, Property >::type GetPropType
get the type alias defined in the property
Definition propertysystem.hh:296
decltype(auto) gridDiscretization(const T &t, Args &&... args)
The grid discretization.
Definition griddiscretization.hh:65
The interface of the coupling manager for multi domain problems.
typename ScalarType< X >::Type Scalar
Definition odesolver.hh:52
Definition adapt.hh:17
auto computeColoring(const GridGeometry &gg, int verbosity=1)
Compute iterable lists of element seeds partitioned by color.
Definition coloring.hh:243
auto localDofs(const FVElementGeometry &fvGeometry)
range over local dofs
Definition localdof.hh:50
Parallel for loop (multithreading).
Type trait that is specialized for coupling manager supporting multithreaded assembly.
Definition assemblytraits.hh:43