version 3.11-dev
Loading...
Searching...
No Matches
couplingmanager_cvfe_cvfe.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//
12
13#ifndef DUMUX_MULTIDOMAIN_BOUNDARY_FREEFLOW_POROUSMEDIUM_COUPLINGMANAGER_CVFE_CVFE_HH
14#define DUMUX_MULTIDOMAIN_BOUNDARY_FREEFLOW_POROUSMEDIUM_COUPLINGMANAGER_CVFE_CVFE_HH
15
16#include <algorithm>
17#include <array>
18#include <deque>
19#include <iostream>
20#include <type_traits>
21#include <utility>
22#include <vector>
23
24#include <dune/common/exceptions.hh>
25#include <dune/common/hybridutilities.hh>
26#include <dune/common/timer.hh>
27
28#include <dumux/common/concepts/variables_.hh>
32#include <dumux/io/format.hh>
36
39
40namespace Dumux {
41
42
48template<class MDTraits>
51{
53
54 using Scalar = typename MDTraits::Scalar;
55
56 // the sub domain type tags
57 template<std::size_t id>
58 using SubDomainTypeTag = typename MDTraits::template SubDomain<id>::TypeTag;
59
60 template<std::size_t id> using Problem = GetPropType<SubDomainTypeTag<id>, Properties::Problem>;
61 template<std::size_t id> using GridDiscretization = GetPropType<SubDomainTypeTag<id>, Properties::GridGeometry>;
62 template<std::size_t id> using ElementDiscretization = typename GridDiscretization<id>::LocalView;
63 template<std::size_t id> using SubControlVolumeFace = typename ElementDiscretization<id>::SubControlVolumeFace;
64 template<std::size_t id> using SubControlVolume = typename ElementDiscretization<id>::SubControlVolume;
65 template<std::size_t id> using GridVariables = GetPropType<SubDomainTypeTag<id>, Properties::GridVariables>;
66 template<std::size_t id> using GridVariablesCache = Concept::GridVariablesCache_t<GridVariables<id>>;
67 template<std::size_t id> using ElementVariables = typename GridVariablesCache<id>::LocalView;
68
69 template<std::size_t id> using GridView = typename GridDiscretization<id>::GridView;
70 template<std::size_t id> using Element = typename GridView<id>::template Codim<0>::Entity;
71 template<std::size_t id> using ElementSeed = typename GridView<id>::Grid::template Codim<0>::EntitySeed;
72 using SolutionVector = typename MDTraits::SolutionVector;
73
75
76public:
80
84 template<std::size_t i, std::size_t j>
85 auto massCouplingCondition(Dune::index_constant<i> domainI, Dune::index_constant<j> domainJ,
86 const ElementDiscretization<i>& elemDisc,
87 const SubControlVolumeFace<i>& scvf,
88 const ElementVariables<i>& elemVars) const
89 {
90 static_assert(domainI != freeFlowMomentumIndex && domainJ != freeFlowMomentumIndex);
91
92 const auto& couplingContext = this->subApply(domainI, domainJ, [&](const auto& cm, auto&& ii, auto&& jj) {
93 return cm.couplingContext(ii, elemDisc, ipData(elemDisc, scvf));
94 });
95
96 const auto& outsideElemDisc = couplingContext.elemDisc;
97 const auto& ffMassElemDisc = [&]() -> const auto& {
98 if constexpr (i == porousMediumIndex)
99 return outsideElemDisc;
100 else
101 return elemDisc;
102 }();
103
104 using VelocityVector = typename GridDiscretization<freeFlowMomentumIndex>::GlobalCoordinate;
105 VelocityVector intVelocity(0.0);
106 // We apply the velocity-related quadrature rule
107 for (const auto& qpData : CVFE::quadratureRule(elemDisc, scvf, typename GridDiscretization<freeFlowMomentumIndex>::ScvfQuadratureRule{}))
108 {
109 const auto& faceIpData = qpData.ipData();
110 const auto ffMassFaceIpData = ipData(ffMassElemDisc, faceIpData.global());
111 intVelocity += qpData.weight()
112 * this->subCouplingManager(freeFlowMomentumIndex, freeFlowMassIndex).velocity(ffMassElemDisc, ffMassFaceIpData);
113 }
114
115 // For the densities we interpolate at the interpolation point and do not use a quadrature rule
116 const auto& ip = ipData(elemDisc, scvf);
117 const auto& outsideIp = ipData(outsideElemDisc, ip.global());
118 Scalar insideDensity = CouplingConditions::density(elemDisc, elemVars, ip);
119 Scalar outsideDensity = CouplingConditions::density(outsideElemDisc, couplingContext, outsideIp);
120
121 const auto normalIntVelocity = intVelocity * scvf.unitOuterNormal();
122 const bool insideIsUpstream = normalIntVelocity > 0.0;
123 return CouplingConditions::advectiveFlux(insideDensity, outsideDensity, normalIntVelocity, insideIsUpstream);
124 }
125
128 template<class FaceIpData>
129 Scalar pmPressure(Dune::index_constant<freeFlowMomentumIndex> domainI,
130 Dune::index_constant<porousMediumIndex> domainJ,
131 const ElementDiscretization<freeFlowMomentumIndex>& elemDisc,
132 const ElementVariables<freeFlowMomentumIndex>& elemVars,
133 const FaceIpData& faceIpData) const
134 {
135 const auto& context = this->subCouplingManager(freeFlowMomentumIndex, porousMediumIndex).couplingContext(
136 domainI, elemDisc, faceIpData
137 );
138
139 return CouplingConditions::pressure(context.elemDisc, context, ipData(context.elemDisc, faceIpData.global()));
140 }
141
145 template<class FaceIpData>
146 auto darcyPermeability(const ElementDiscretization<freeFlowMomentumIndex>& elemDisc,
147 const FaceIpData& faceIpData) const
148 {
149 const auto& context = this->subCouplingManager(freeFlowMomentumIndex, porousMediumIndex).couplingContext(
150 Dune::index_constant<freeFlowMomentumIndex>(), elemDisc, faceIpData
151 );
152
153 return CouplingConditions::darcyPermeability(elemDisc, faceIpData, context);
154 }
155
160 template<class FaceIpData>
161 auto darcyVelocity(const ElementDiscretization<freeFlowMomentumIndex>& elemDisc,
162 const FaceIpData& faceIpData) const
163 {
164 const auto& context = this->subCouplingManager(freeFlowMomentumIndex, porousMediumIndex).couplingContext(
165 Dune::index_constant<freeFlowMomentumIndex>(), elemDisc, faceIpData
166 );
167
168 return CouplingConditions::darcyVelocity(context, ipData(context.elemDisc, faceIpData.global()));
169 }
170
173
177 Scalar pressure(const Element<freeFlowMomentumIndex>& element,
178 const ElementDiscretization<freeFlowMomentumIndex>& elemDisc,
179 const SubControlVolumeFace<freeFlowMomentumIndex>& scvf) const
180 {
182 element, elemDisc, scvf
183 );
184 }
185
189 template <class IpData>
190 Scalar pressure(const Element<freeFlowMomentumIndex>& element,
191 const ElementDiscretization<freeFlowMomentumIndex>& elemDisc,
192 const IpData& ipData,
193 const bool considerPreviousTimeStep = false) const
194 {
196 element, elemDisc, ipData, considerPreviousTimeStep
197 );
198 }
199
203 Scalar density(const Element<freeFlowMomentumIndex>& element,
204 const ElementDiscretization<freeFlowMomentumIndex>& elemDisc,
205 const SubControlVolumeFace<freeFlowMomentumIndex>& scvf,
206 const bool considerPreviousTimeStep = false) const
207 {
209 element, elemDisc, scvf, considerPreviousTimeStep
210 );
211 }
212
216 template <class IpData>
217 Scalar density(const Element<freeFlowMomentumIndex>& element,
218 const ElementDiscretization<freeFlowMomentumIndex>& elemDisc,
219 const IpData& ipData,
220 const bool considerPreviousTimeStep = false) const
221 {
223 element, elemDisc, ipData, considerPreviousTimeStep
224 );
225 }
226
230 auto insideAndOutsideDensity(const Element<freeFlowMomentumIndex>& element,
231 const ElementDiscretization<freeFlowMomentumIndex>& elemDisc,
232 const SubControlVolumeFace<freeFlowMomentumIndex>& scvf,
233 const bool considerPreviousTimeStep = false) const
234 {
235 return this->subCouplingManager(freeFlowMomentumIndex, freeFlowMassIndex).insideAndOutsideDensity(
236 element, elemDisc, scvf, considerPreviousTimeStep
237 );
238 }
239
243 Scalar density(const Element<freeFlowMomentumIndex>& element,
244 const ElementDiscretization<freeFlowMomentumIndex>& elemDisc,
245 const SubControlVolume<freeFlowMomentumIndex>& scv,
246 const bool considerPreviousTimeStep = false) const
247 {
249 element, elemDisc, scv, considerPreviousTimeStep
250 );
251 }
252
256 Scalar effectiveViscosity(const Element<freeFlowMomentumIndex>& element,
257 const ElementDiscretization<freeFlowMomentumIndex>& elemDisc,
258 const SubControlVolumeFace<freeFlowMomentumIndex>& scvf) const
259 {
260 return this->subCouplingManager(freeFlowMomentumIndex, freeFlowMassIndex).effectiveViscosity(
261 element, elemDisc, scvf
262 );
263 }
264
268 template <class IpData>
269 Scalar effectiveViscosity(const Element<freeFlowMomentumIndex>& element,
270 const ElementDiscretization<freeFlowMomentumIndex>& elemDisc,
271 const IpData& ipData,
272 const bool considerPreviousTimeStep = false) const
273 {
274 return this->subCouplingManager(freeFlowMomentumIndex, freeFlowMassIndex).effectiveViscosity(
275 element, elemDisc, ipData, considerPreviousTimeStep
276 );
277 }
278
282 auto faceVelocity(const Element<freeFlowMassIndex>& element,
283 const SubControlVolumeFace<freeFlowMassIndex>& scvf) const
284 {
286 element, scvf
287 );
288 }
289
293 template <class IpData>
294 auto velocity(const ElementDiscretization<freeFlowMassIndex>& elemDisc,
295 const IpData& ipData) const
296 {
298 elemDisc, ipData
299 );
300 }
301
305 auto elementVelocity(const ElementDiscretization<freeFlowMassIndex>& elemDisc) const
306 {
307 return this->subCouplingManager(freeFlowMomentumIndex, freeFlowMassIndex).elementVelocity(
308 elemDisc
309 );
310 }
311
321 {
322 elementSets_ = computeColoring_(std::index_sequence<freeFlowMomentumIndex, freeFlowMassIndex>{});
323 elementSetsPM_ = computeColoring_(std::index_sequence<porousMediumIndex>{});
324 }
325
332 template<std::size_t i, class AssembleElementFunc>
333 void assembleMultithreaded(Dune::index_constant<i> domainId, AssembleElementFunc&& assembleElement) const
334 {
335 if constexpr (i == porousMediumIndex)
336 {
337 if (elementSetsPM_.empty())
338 DUNE_THROW(Dune::InvalidStateException, "Call computeColorsForAssembly before assembling in parallel!");
339
340 const auto& grid = Dumux::gridDiscretization(this->problem(porousMediumIndex)).gridView().grid();
341 for (const auto& elements : elementSetsPM_)
342 {
343 Dumux::parallelFor(elements.size(), [&](const std::size_t eIdx)
344 {
345 const auto element = grid.entity(elements[eIdx]);
346 assembleElement(element);
347 });
348 }
349 }
350 else
351 {
352 if (elementSets_.empty())
353 DUNE_THROW(Dune::InvalidStateException, "Call computeColorsForAssembly before assembling in parallel!");
354
355 const auto& grid = Dumux::gridDiscretization(this->problem(freeFlowMomentumIndex)).gridView().grid();
356 for (const auto& elements : elementSets_)
357 {
358 Dumux::parallelFor(elements.size(), [&](const std::size_t eIdx)
359 {
360 const auto element = grid.entity(elements[eIdx]);
361 assembleElement(element);
362 });
363 }
364 }
365 }
366
367private:
373 template<std::size_t i, std::size_t... is>
374 auto computeColoring_(std::index_sequence<i, is...> assembledDomains) const
375 {
376 Dune::Timer timer;
377
378 static constexpr std::size_t numSubDomains = MDTraits::numSubDomains;
379 std::array<std::size_t, numSubDomains+1> dofOffset{};
380 Dune::Hybrid::forEach(std::make_index_sequence<numSubDomains>{}, [&](auto domainJ)
381 { dofOffset[domainJ+1] = dofOffset[domainJ] + Dumux::gridDiscretization(this->problem(domainJ)).numDofs(); });
382
383 const auto& gridDiscretization = Dumux::gridDiscretization(this->problem(Dune::index_constant<i>{}));
384 const auto& gridView = gridDiscretization.gridView();
385 const auto& elementMapper = gridDiscretization.elementMapper();
386
387 // the touched degrees of freedom of each element, numbered consecutively over all domains
388 std::vector<std::vector<std::size_t>> touchedDofs(gridView.size(0));
389 for (const auto& element : elements(gridView))
390 {
391 auto& dofs = touchedDofs[elementMapper.index(element)];
392 Dune::Hybrid::forEach(assembledDomains, [&](auto domainI)
393 {
394 const auto elemDisc = localView(Dumux::gridDiscretization(this->problem(domainI))).bindElement(element);
395 for (const auto& localDof : localDofs(elemDisc))
396 dofs.push_back(dofOffset[domainI] + localDof.dofIndex());
397
398 Dune::Hybrid::forEach(std::make_index_sequence<numSubDomains>{}, [&](auto domainJ)
399 {
400 if constexpr (decltype(domainJ)::value != std::decay_t<decltype(domainI)>::value)
401 for (const auto dofJ : this->couplingStencil(domainI, element, domainJ))
402 dofs.push_back(dofOffset[domainJ] + dofJ);
403 });
404 });
405
406 std::sort(dofs.begin(), dofs.end());
407 dofs.erase(std::unique(dofs.begin(), dofs.end()), dofs.end());
408 }
409
410 std::vector<std::vector<std::size_t>> elementsTouchingDof(dofOffset.back());
411 for (std::size_t eIdx = 0; eIdx < touchedDofs.size(); ++eIdx)
412 for (const auto dof : touchedDofs[eIdx])
413 elementsTouchingDof[dof].push_back(eIdx);
414
415 std::deque<std::vector<ElementSeed<i>>> sets;
416 std::vector<int> colors(gridView.size(0), -1);
417 std::vector<int> neighborColors;
418 std::vector<bool> colorUsed;
419 for (const auto& element : elements(gridView))
420 {
421 const auto eIdx = elementMapper.index(element);
422 neighborColors.clear();
423 for (const auto dof : touchedDofs[eIdx])
424 for (const auto nIdx : elementsTouchingDof[dof])
425 neighborColors.push_back(colors[nIdx]);
426
427 const auto color = Detail::smallestAvailableColor(neighborColors, colorUsed);
428 colors[eIdx] = color;
429 if (color < sets.size())
430 sets[color].push_back(element.seed());
431 else
432 sets.push_back(std::vector<ElementSeed<i>>{ element.seed() });
433 }
434
435 std::cout << Fmt::format("Colored {} elements with {} colors in {} seconds.\n",
436 gridView.size(0), sets.size(), timer.elapsed());
437
438 return sets;
439 }
440
441 std::deque<std::vector<ElementSeed<freeFlowMomentumIndex>>> elementSets_;
442 std::deque<std::vector<ElementSeed<porousMediumIndex>>> elementSetsPM_;
443};
444
445template<class T>
449
450} // end namespace Dumux
451
452#endif
Traits shared by the multi-domain assemblers.
Base coupling manager for coupling freeflow and porous medium flow models.
Definition couplingmanager_base.hh:146
static constexpr auto porousMediumIndex
Definition couplingmanager_base.hh:183
static constexpr auto freeFlowMassIndex
Definition couplingmanager_base.hh:182
const auto & couplingStencil(Dune::index_constant< freeFlowMomentumIndex > domainI, const Element< freeFlowMomentumIndex > &elementI, const SubControlVolume< freeFlowMomentumIndex > &scvI, Dune::index_constant< j > domainJ) const
returns an iterable container of all indices of degrees of freedom of domain j that couple with / inf...
Definition couplingmanager_base.hh:291
const Problem< i > & problem(Dune::index_constant< i > domainI) const
Definition couplingmanager_base.hh:229
static constexpr auto freeFlowMomentumIndex
Definition couplingmanager_base.hh:181
Coupling manager for coupling free flow and porous medium flow models, all discretized with control-v...
Definition couplingmanager_cvfe_cvfe.hh:51
void computeColorsForAssembly()
Compute colors for multithreaded assembly.
Definition couplingmanager_cvfe_cvfe.hh:320
auto insideAndOutsideDensity(const Element< freeFlowMomentumIndex > &element, const ElementDiscretization< freeFlowMomentumIndex > &elemDisc, const SubControlVolumeFace< freeFlowMomentumIndex > &scvf, const bool considerPreviousTimeStep=false) const
Returns the inside and outside densities at a given sub control volume face.
Definition couplingmanager_cvfe_cvfe.hh:230
Scalar density(const Element< freeFlowMomentumIndex > &element, const ElementDiscretization< freeFlowMomentumIndex > &elemDisc, const IpData &ipData, const bool considerPreviousTimeStep=false) const
Returns the density at a given interpolation point.
Definition couplingmanager_cvfe_cvfe.hh:217
Scalar pmPressure(Dune::index_constant< freeFlowMomentumIndex > domainI, Dune::index_constant< porousMediumIndex > domainJ, const ElementDiscretization< freeFlowMomentumIndex > &elemDisc, const ElementVariables< freeFlowMomentumIndex > &elemVars, const FaceIpData &faceIpData) const
Definition couplingmanager_cvfe_cvfe.hh:129
void assembleMultithreaded(Dune::index_constant< i > domainId, AssembleElementFunc &&assembleElement) const
Execute assembly kernel in parallel.
Definition couplingmanager_cvfe_cvfe.hh:333
auto massCouplingCondition(Dune::index_constant< i > domainI, Dune::index_constant< j > domainJ, const ElementDiscretization< i > &elemDisc, const SubControlVolumeFace< i > &scvf, const ElementVariables< i > &elemVars) const
Returns the mass flux across the coupling boundary.
Definition couplingmanager_cvfe_cvfe.hh:85
auto velocity(const ElementDiscretization< freeFlowMassIndex > &elemDisc, const IpData &ipData) const
Returns the velocity at an interpolation point.
Definition couplingmanager_cvfe_cvfe.hh:294
Scalar density(const Element< freeFlowMomentumIndex > &element, const ElementDiscretization< freeFlowMomentumIndex > &elemDisc, const SubControlVolume< freeFlowMomentumIndex > &scv, const bool considerPreviousTimeStep=false) const
Returns the density at a given sub control volume.
Definition couplingmanager_cvfe_cvfe.hh:243
auto faceVelocity(const Element< freeFlowMassIndex > &element, const SubControlVolumeFace< freeFlowMassIndex > &scvf) const
Returns the velocity at a given sub control volume face.
Definition couplingmanager_cvfe_cvfe.hh:282
Scalar pressure(const Element< freeFlowMomentumIndex > &element, const ElementDiscretization< freeFlowMomentumIndex > &elemDisc, const SubControlVolumeFace< freeFlowMomentumIndex > &scvf) const
Returns the pressure at a given sub control volume face.
Definition couplingmanager_cvfe_cvfe.hh:177
Scalar pressure(const Element< freeFlowMomentumIndex > &element, const ElementDiscretization< freeFlowMomentumIndex > &elemDisc, const IpData &ipData, const bool considerPreviousTimeStep=false) const
Returns the pressure at a given interpolation point.
Definition couplingmanager_cvfe_cvfe.hh:190
static constexpr auto freeFlowMomentumIndex
Definition couplingmanager_cvfe_cvfe.hh:77
static constexpr auto porousMediumIndex
Definition couplingmanager_cvfe_cvfe.hh:79
Scalar density(const Element< freeFlowMomentumIndex > &element, const ElementDiscretization< freeFlowMomentumIndex > &elemDisc, const SubControlVolumeFace< freeFlowMomentumIndex > &scvf, const bool considerPreviousTimeStep=false) const
Returns the density at a given sub control volume face.
Definition couplingmanager_cvfe_cvfe.hh:203
Scalar effectiveViscosity(const Element< freeFlowMomentumIndex > &element, const ElementDiscretization< freeFlowMomentumIndex > &elemDisc, const SubControlVolumeFace< freeFlowMomentumIndex > &scvf) const
Returns the effective viscosity at a given sub control volume face.
Definition couplingmanager_cvfe_cvfe.hh:256
auto elementVelocity(const ElementDiscretization< freeFlowMassIndex > &elemDisc) const
Returns the velocity at the element center.
Definition couplingmanager_cvfe_cvfe.hh:305
auto darcyVelocity(const ElementDiscretization< freeFlowMomentumIndex > &elemDisc, const FaceIpData &faceIpData) const
Returns the Darcy velocity of the coupled porous-medium element at a face interpolation point of the ...
Definition couplingmanager_cvfe_cvfe.hh:161
Scalar effectiveViscosity(const Element< freeFlowMomentumIndex > &element, const ElementDiscretization< freeFlowMomentumIndex > &elemDisc, const IpData &ipData, const bool considerPreviousTimeStep=false) const
Returns the effective viscosity at a interpolation point.
Definition couplingmanager_cvfe_cvfe.hh:269
static constexpr auto freeFlowMassIndex
Definition couplingmanager_cvfe_cvfe.hh:78
auto darcyPermeability(const ElementDiscretization< freeFlowMomentumIndex > &elemDisc, const FaceIpData &faceIpData) const
Returns the intrinsic permeability of the coupled Darcy element.
Definition couplingmanager_cvfe_cvfe.hh:146
Coloring schemes for shared-memory-parallel assembly.
Coupling conditions for a Darcy model and a (Navier-)Stokes model, both discretized with control-volu...
Base class for coupling freeflow and porous medium flow models.
Formatting based on the fmt-library which implements std::format of C++20.
Type traits for classes providing a grid discretization.
GridCache::LocalView localView(const GridCache &gridCache)
Free function to get the local view of a grid cache object.
Definition localview.hh:26
FFPMCouplingConditionsCvfeImpl< MDTraits, CouplingManager, GetPropType< typename MDTraits::template SubDomain< 0 >::TypeTag, Properties::ModelTraits >::enableEnergyBalance(),(GetPropType< typename MDTraits::template SubDomain< 0 >::TypeTag, Properties::ModelTraits >::numFluidComponents() > 1) > FFPMCouplingConditionsCvfe
Coupling conditions for a Darcy model and a (Navier-)Stokes model, both discretized with control-volu...
Definition couplingconditions_cvfe_cvfe.hh:44
@ element
Definition fieldtype.hh:23
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
Class representing dofs on elements for control-volume finite element schemes.
auto quadratureRule(const FVElementGeometry &fvGeometry, const typename FVElementGeometry::SubControlVolume &scv, QuadratureRules::MidpointQuadrature)
Midpoint quadrature for scv.
Definition quadraturerules.hh:160
Definition adapt.hh:17
auto localDofs(const FVElementGeometry &fvGeometry)
range over local dofs
Definition localdof.hh:50
Parallel for loop (multithreading).
Quadrature rules over sub-control volumes and sub-control volume faces.
Type trait that is specialized for coupling manager supporting multithreaded assembly.
Definition assemblytraits.hh:43