version 3.10-dev
couplingmanager_staggered.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//
12#ifndef DUMUX_MULTIDOMAIN_FREEFLOW_COUPLING_MANAGER_STAGGERED_HH
13#define DUMUX_MULTIDOMAIN_FREEFLOW_COUPLING_MANAGER_STAGGERED_HH
14
15#include <memory>
16#include <tuple>
17#include <vector>
18#include <deque>
19
20#include <dune/common/exceptions.hh>
21#include <dune/common/indices.hh>
22#include <dune/common/float_cmp.hh>
23
26
30
34
37
38namespace Dumux {
39
45template<class Traits>
47: public CouplingManager<Traits>
48{
50public:
51 static constexpr auto freeFlowMomentumIndex = typename Traits::template SubDomain<0>::Index();
52 static constexpr auto freeFlowMassIndex = typename Traits::template SubDomain<1>::Index();
53
54 // this can be used if the coupling manager is used inside a meta-coupling manager (e.g. multi-binary)
55 // to manager the solution vector storage outside this class
57private:
58 template<std::size_t id> using SubDomainTypeTag = typename Traits::template SubDomain<id>::TypeTag;
59 template<std::size_t id> using PrimaryVariables = GetPropType<SubDomainTypeTag<id>, Properties::PrimaryVariables>;
60 template<std::size_t id> using GridGeometry = GetPropType<SubDomainTypeTag<id>, Properties::GridGeometry>;
61 template<std::size_t id> using GridView = typename GridGeometry<id>::GridView;
62 template<std::size_t id> using Element = typename GridView<id>::template Codim<0>::Entity;
63 template<std::size_t id> using ElementSeed = typename GridView<id>::Grid::template Codim<0>::EntitySeed;
64 template<std::size_t id> using FVElementGeometry = typename GridGeometry<id>::LocalView;
65 template<std::size_t id> using SubControlVolume = typename FVElementGeometry<id>::SubControlVolume;
66 template<std::size_t id> using SubControlVolumeFace = typename FVElementGeometry<id>::SubControlVolumeFace;
67 template<std::size_t id> using GridVariables = typename Traits::template SubDomain<id>::GridVariables;
68 template<std::size_t id> using ElementVolumeVariables = typename GridVariables<id>::GridVolumeVariables::LocalView;
69 template<std::size_t id> using GridFluxVariablesCache = typename GridVariables<id>::GridFluxVariablesCache;
70 template<std::size_t id> using Problem = GetPropType<SubDomainTypeTag<id>, Properties::Problem>;
71 template<std::size_t id> using VolumeVariables = GetPropType<SubDomainTypeTag<id>, Properties::VolumeVariables>;
72
73 using Scalar = typename Traits::Scalar;
74 using SolutionVector = typename Traits::SolutionVector;
75
76 template<std::size_t id>
77 using SubSolutionVector
78 = std::decay_t<decltype(std::declval<SolutionVector>()[Dune::index_constant<id>()])>;
79
80 template<std::size_t id>
81 using ConstSubSolutionVectorPtr = const SubSolutionVector<id>*;
82
83 using PrevSolutionVectorStorage = typename Traits::template Tuple<ConstSubSolutionVectorPtr>;
84
85 using CouplingStencilType = std::vector<std::size_t>;
86
87 using GridVariablesTuple = typename Traits::template TupleOfSharedPtr<GridVariables>;
88
89 using FluidSystem = typename VolumeVariables<freeFlowMassIndex>::FluidSystem;
90
91 using VelocityVector = typename SubControlVolumeFace<freeFlowMassIndex>::GlobalPosition;
92 static_assert(std::is_same_v<VelocityVector, typename SubControlVolumeFace<freeFlowMomentumIndex>::GlobalPosition>);
93
94 struct MomentumCouplingContext
95 {
96 FVElementGeometry<freeFlowMassIndex> fvGeometry;
97 ElementVolumeVariables<freeFlowMassIndex> curElemVolVars;
98 ElementVolumeVariables<freeFlowMassIndex> prevElemVolVars;
99 std::size_t eIdx;
100 };
101
102 struct MassAndEnergyCouplingContext
103 {
104 MassAndEnergyCouplingContext(FVElementGeometry<freeFlowMomentumIndex>&& f, const std::size_t i)
105 : fvGeometry(std::move(f))
106 , eIdx(i)
107 {}
108
109 FVElementGeometry<freeFlowMomentumIndex> fvGeometry;
110 std::size_t eIdx;
111 };
112
113public:
114
115 static constexpr auto pressureIdx = VolumeVariables<freeFlowMassIndex>::Indices::pressureIdx;
116
120 // \{
121
123 void init(std::shared_ptr<Problem<freeFlowMomentumIndex>> momentumProblem,
124 std::shared_ptr<Problem<freeFlowMassIndex>> massProblem,
125 GridVariablesTuple&& gridVariables,
126 const SolutionVector& curSol)
127 {
128 this->setSubProblems(std::make_tuple(momentumProblem, massProblem));
129 gridVariables_ = gridVariables;
130 this->updateSolution(curSol);
131
132 computeCouplingStencils_();
133 }
134
136 void init(std::shared_ptr<Problem<freeFlowMomentumIndex>> momentumProblem,
137 std::shared_ptr<Problem<freeFlowMassIndex>> massProblem,
138 GridVariablesTuple&& gridVariables,
139 const SolutionVector& curSol,
140 const SolutionVector& prevSol)
141 {
142 init(momentumProblem, massProblem, std::forward<GridVariablesTuple>(gridVariables), curSol);
143
144 Dune::Hybrid::forEach(std::make_index_sequence<Traits::numSubDomains>{}, [&](auto i)
145 { std::get<i>(prevSolutions_) = &prevSol[i]; });
146 }
147
149 void init(std::shared_ptr<Problem<freeFlowMomentumIndex>> momentumProblem,
150 std::shared_ptr<Problem<freeFlowMassIndex>> massProblem,
151 GridVariablesTuple&& gridVariables,
153 {
154 this->setSubProblems(std::make_tuple(momentumProblem, massProblem));
155 gridVariables_ = gridVariables;
156 this->attachSolution(curSol);
157
158 computeCouplingStencils_();
159 }
160
162 void init(std::shared_ptr<Problem<freeFlowMomentumIndex>> momentumProblem,
163 std::shared_ptr<Problem<freeFlowMassIndex>> massProblem,
164 GridVariablesTuple&& gridVariables,
166 const PrevSolutionVectorStorage& prevSol)
167 {
168 init(momentumProblem, massProblem, std::forward<GridVariablesTuple>(gridVariables), curSol);
169 prevSolutions_ = prevSol;
170 }
171
172 // \}
173
175
193 template<std::size_t j, class LocalAssemblerI>
194 decltype(auto) evalCouplingResidual(Dune::index_constant<freeFlowMomentumIndex> domainI,
195 const LocalAssemblerI& localAssemblerI,
196 const SubControlVolume<freeFlowMomentumIndex>& scvI,
197 Dune::index_constant<j> domainJ,
198 std::size_t dofIdxGlobalJ) const
199 {
200 const auto& problem = localAssemblerI.problem();
201 const auto& element = localAssemblerI.element();
202 const auto& fvGeometry = localAssemblerI.fvGeometry();
203 const auto& curElemVolVars = localAssemblerI.curElemVolVars();
204 const auto& prevElemVolVars = localAssemblerI.prevElemVolVars();
205 typename LocalAssemblerI::ElementResidualVector residual(localAssemblerI.element().subEntities(1));
206 const auto& localResidual = localAssemblerI.localResidual();
207
208 localResidual.evalSource(residual, problem, element, fvGeometry, curElemVolVars, scvI);
209
210 for (const auto& scvf : scvfs(fvGeometry, scvI))
211 localResidual.evalFlux(residual, problem, element, fvGeometry, curElemVolVars, localAssemblerI.elemBcTypes(), localAssemblerI.elemFluxVarsCache(), scvf);
212
213 if (!localAssemblerI.assembler().isStationaryProblem())
214 {
215 assert(isTransient_());
216 localResidual.evalStorage(residual, problem, element, fvGeometry, prevElemVolVars, curElemVolVars, scvI);
217 }
218
219 return residual;
220 }
221
225 // \{
226
230 Scalar pressure(const Element<freeFlowMomentumIndex>& element,
231 const FVElementGeometry<freeFlowMomentumIndex>& fvGeometry,
232 const SubControlVolumeFace<freeFlowMomentumIndex>& scvf) const
233 {
234 assert(scvf.isFrontal() && !scvf.isLateral() && !scvf.boundary());
235 return this->curSol(freeFlowMassIndex)[fvGeometry.elementIndex()][pressureIdx];
236 }
237
244 Scalar cellPressure(const Element<freeFlowMassIndex>& element,
245 const SubControlVolumeFace<freeFlowMassIndex>& scvf) const
246 {
247 return this->curSol(freeFlowMassIndex)[scvf.insideScvIdx()][pressureIdx];
248 }
249
253 Scalar density(const Element<freeFlowMomentumIndex>& element,
254 const FVElementGeometry<freeFlowMomentumIndex>& fvGeometry,
255 const SubControlVolumeFace<freeFlowMomentumIndex>& scvf,
256 const bool considerPreviousTimeStep = false) const
257 {
258 assert(!(considerPreviousTimeStep && !isTransient_()));
259 bindCouplingContext_(Dune::index_constant<freeFlowMomentumIndex>(), element, fvGeometry.elementIndex());
260 const auto& insideMomentumScv = fvGeometry.scv(scvf.insideScvIdx());
261 const auto& insideMassScv = momentumCouplingContext_()[0].fvGeometry.scv(insideMomentumScv.elementIndex());
262
263 const auto rho = [&](const auto& elemVolVars)
264 {
265 if (scvf.boundary())
266 return elemVolVars[insideMassScv].density();
267 else
268 {
269 const auto& outsideMomentumScv = fvGeometry.scv(scvf.outsideScvIdx());
270 const auto& outsideMassScv = momentumCouplingContext_()[0].fvGeometry.scv(outsideMomentumScv.elementIndex());
271 // TODO distance weighting
272 return 0.5*(elemVolVars[insideMassScv].density() + elemVolVars[outsideMassScv].density());
273 }
274 };
275
276 return considerPreviousTimeStep ? rho(momentumCouplingContext_()[0].prevElemVolVars)
277 : rho(momentumCouplingContext_()[0].curElemVolVars);
278 }
279
280 auto insideAndOutsideDensity(const Element<freeFlowMomentumIndex>& element,
281 const FVElementGeometry<freeFlowMomentumIndex>& fvGeometry,
282 const SubControlVolumeFace<freeFlowMomentumIndex>& scvf,
283 const bool considerPreviousTimeStep = false) const
284 {
285 assert(!(considerPreviousTimeStep && !isTransient_()));
286 bindCouplingContext_(Dune::index_constant<freeFlowMomentumIndex>(), element, fvGeometry.elementIndex());
287 const auto& insideMomentumScv = fvGeometry.scv(scvf.insideScvIdx());
288 const auto& insideMassScv = momentumCouplingContext_()[0].fvGeometry.scv(insideMomentumScv.elementIndex());
289
290 const auto result = [&](const auto& elemVolVars)
291 {
292 if (scvf.boundary())
293 return std::make_pair(elemVolVars[insideMassScv].density(), elemVolVars[insideMassScv].density());
294 else
295 {
296 const auto& outsideMomentumScv = fvGeometry.scv(scvf.outsideScvIdx());
297 const auto& outsideMassScv = momentumCouplingContext_()[0].fvGeometry.scv(outsideMomentumScv.elementIndex());
298 return std::make_pair(elemVolVars[insideMassScv].density(), elemVolVars[outsideMassScv].density());
299 }
300 };
301
302 return considerPreviousTimeStep ? result(momentumCouplingContext_()[0].prevElemVolVars)
303 : result(momentumCouplingContext_()[0].curElemVolVars);
304 }
305
309 Scalar density(const Element<freeFlowMomentumIndex>& element,
310 const SubControlVolume<freeFlowMomentumIndex>& scv,
311 const bool considerPreviousTimeStep = false) const
312 {
313 assert(!(considerPreviousTimeStep && !isTransient_()));
314 bindCouplingContext_(Dune::index_constant<freeFlowMomentumIndex>(), element, scv.elementIndex());
315 const auto& massScv = (*scvs(momentumCouplingContext_()[0].fvGeometry).begin());
316
317 return considerPreviousTimeStep ? momentumCouplingContext_()[0].prevElemVolVars[massScv].density()
318 : momentumCouplingContext_()[0].curElemVolVars[massScv].density();
319 }
320
324 Scalar effectiveViscosity(const Element<freeFlowMomentumIndex>& element,
325 const FVElementGeometry<freeFlowMomentumIndex>& fvGeometry,
326 const SubControlVolumeFace<freeFlowMomentumIndex>& scvf) const
327 {
328 bindCouplingContext_(Dune::index_constant<freeFlowMomentumIndex>(), element, fvGeometry.elementIndex());
329
330 const auto& insideMomentumScv = fvGeometry.scv(scvf.insideScvIdx());
331 const auto& insideMassScv = momentumCouplingContext_()[0].fvGeometry.scv(insideMomentumScv.elementIndex());
332
333 if (scvf.boundary())
334 return momentumCouplingContext_()[0].curElemVolVars[insideMassScv].viscosity();
335
336 const auto& outsideMomentumScv = fvGeometry.scv(scvf.outsideScvIdx());
337 const auto& outsideMassScv = momentumCouplingContext_()[0].fvGeometry.scv(outsideMomentumScv.elementIndex());
338
339 const auto mu = [&](const auto& elemVolVars)
340 {
341 // TODO distance weighting
342 return 0.5*(elemVolVars[insideMassScv].viscosity() + elemVolVars[outsideMassScv].viscosity());
343 };
344
345 return mu(momentumCouplingContext_()[0].curElemVolVars);
346 }
347
351 Scalar effectiveViscosity(const Element<freeFlowMomentumIndex>& element,
352 const FVElementGeometry<freeFlowMomentumIndex>& fvGeometry,
353 const SubControlVolume<freeFlowMomentumIndex>& scv) const
354 {
355 bindCouplingContext_(Dune::index_constant<freeFlowMomentumIndex>(), element, fvGeometry.elementIndex());
356 const auto& insideMassScv = momentumCouplingContext_()[0].fvGeometry.scv(scv.elementIndex());
357 return momentumCouplingContext_()[0].curElemVolVars[insideMassScv].viscosity();
358 }
359
363 VelocityVector faceVelocity(const Element<freeFlowMassIndex>& element,
364 const SubControlVolumeFace<freeFlowMassIndex>& scvf) const
365 {
366 // TODO: rethink this! Maybe we only need scvJ.dofIndex()
367 bindCouplingContext_(Dune::index_constant<freeFlowMassIndex>(), element, scvf.insideScvIdx()/*eIdx*/);
368
369 // the TPFA scvf index corresponds to the staggered scv index (might need mapping)
370 const auto localMomentumScvIdx = massScvfToMomentumScvIdx_(scvf, massAndEnergyCouplingContext_()[0].fvGeometry);
371 const auto& scvJ = massAndEnergyCouplingContext_()[0].fvGeometry.scv(localMomentumScvIdx);
372
373 // create a unit normal vector oriented in positive coordinate direction
374 typename SubControlVolumeFace<freeFlowMassIndex>::GlobalPosition velocity;
375 velocity[scvJ.dofAxis()] = 1.0;
376
377 // create the actual velocity vector
378 velocity *= this->curSol(freeFlowMomentumIndex)[scvJ.dofIndex()];
379
380 return velocity;
381 }
382
392 template<std::size_t j>
393 const CouplingStencilType& couplingStencil(Dune::index_constant<freeFlowMomentumIndex> domainI,
394 const Element<freeFlowMomentumIndex>& elementI,
395 const SubControlVolume<freeFlowMomentumIndex>& scvI,
396 Dune::index_constant<j> domainJ) const
397 { return emptyStencil_; }
398
413 const CouplingStencilType& couplingStencil(Dune::index_constant<freeFlowMassIndex> domainI,
414 const Element<freeFlowMassIndex>& elementI,
415 Dune::index_constant<freeFlowMomentumIndex> domainJ) const
416 {
417 const auto eIdx = this->problem(freeFlowMassIndex).gridGeometry().elementMapper().index(elementI);
418 return massAndEnergyToMomentumStencils_[eIdx];
419 }
420
430 const CouplingStencilType& couplingStencil(Dune::index_constant<freeFlowMomentumIndex> domainI,
431 const Element<freeFlowMomentumIndex>& elementI,
432 const SubControlVolume<freeFlowMomentumIndex>& scvI,
433 Dune::index_constant<freeFlowMassIndex> domainJ) const
434 {
435 return momentumToMassAndEnergyStencils_[scvI.index()];
436 }
437
438 // \}
439
443 // \{
444
446 template<std::size_t i, std::size_t j, class LocalAssemblerI>
447 void updateCouplingContext(Dune::index_constant<i> domainI,
448 const LocalAssemblerI& localAssemblerI,
449 Dune::index_constant<j> domainJ,
450 std::size_t dofIdxGlobalJ,
451 const PrimaryVariables<j>& priVarsJ,
452 int pvIdxJ)
453 {
454 this->curSol(domainJ)[dofIdxGlobalJ][pvIdxJ] = priVarsJ[pvIdxJ];
455
456 if constexpr (domainI == freeFlowMomentumIndex && domainJ == freeFlowMassIndex)
457 {
458 bindCouplingContext_(domainI, localAssemblerI.element());
459
460 const auto& problem = this->problem(domainJ);
461 const auto& deflectedElement = problem.gridGeometry().element(dofIdxGlobalJ);
462 const auto elemSol = elementSolution(deflectedElement, this->curSol(domainJ), problem.gridGeometry());
463 const auto& fvGeometry = momentumCouplingContext_()[0].fvGeometry;
464 const auto scvIdxJ = dofIdxGlobalJ;
465 const auto& scv = fvGeometry.scv(scvIdxJ);
466
467 if constexpr (ElementVolumeVariables<freeFlowMassIndex>::GridVolumeVariables::cachingEnabled)
468 gridVars_(freeFlowMassIndex).curGridVolVars().volVars(scv).update(std::move(elemSol), problem, deflectedElement, scv);
469 else
470 momentumCouplingContext_()[0].curElemVolVars[scv].update(std::move(elemSol), problem, deflectedElement, scv);
471 }
472 }
473
474 // \}
475
480 {
481 // use coloring of the fc staggered discretization for both domains
482 elementSets_ = computeColoring(this->problem(freeFlowMomentumIndex).gridGeometry()).sets;
483 }
484
491 template<std::size_t i, class AssembleElementFunc>
492 void assembleMultithreaded(Dune::index_constant<i> domainI, AssembleElementFunc&& assembleElement) const
493 {
494 if (elementSets_.empty())
495 DUNE_THROW(Dune::InvalidStateException, "Call computeColorsForAssembly before assembling in parallel!");
496
497 // make this element loop run in parallel
498 // for this we have to color the elements so that we don't get
499 // race conditions when writing into the global matrix
500 // each color can be assembled using multiple threads
501 const auto& grid = this->problem(freeFlowMomentumIndex).gridGeometry().gridView().grid();
502 for (const auto& elements : elementSets_)
503 {
504 Dumux::parallelFor(elements.size(), [&](const std::size_t eIdx)
505 {
506 const auto element = grid.entity(elements[eIdx]);
507 assembleElement(element);
508 });
509 }
510 }
511
512private:
513 void bindCouplingContext_(Dune::index_constant<freeFlowMomentumIndex> domainI,
514 const Element<freeFlowMomentumIndex>& elementI) const
515 {
516 const auto eIdx = this->problem(freeFlowMomentumIndex).gridGeometry().elementMapper().index(elementI);
517 bindCouplingContext_(domainI, elementI, eIdx);
518 }
519
520 void bindCouplingContext_(Dune::index_constant<freeFlowMomentumIndex> domainI,
521 const Element<freeFlowMomentumIndex>& elementI,
522 const std::size_t eIdx) const
523 {
524 if (momentumCouplingContext_().empty())
525 {
526 auto fvGeometry = localView(this->problem(freeFlowMassIndex).gridGeometry());
527 fvGeometry.bind(elementI);
528
529 auto curElemVolVars = localView(gridVars_(freeFlowMassIndex).curGridVolVars());
530 curElemVolVars.bind(elementI, fvGeometry, this->curSol(freeFlowMassIndex));
531
532 auto prevElemVolVars = isTransient_() ? localView(gridVars_(freeFlowMassIndex).prevGridVolVars())
533 : localView(gridVars_(freeFlowMassIndex).curGridVolVars());
534
535 if (isTransient_())
536 prevElemVolVars.bindElement(elementI, fvGeometry, prevSol_(freeFlowMassIndex));
537
538 momentumCouplingContext_().emplace_back(MomentumCouplingContext{std::move(fvGeometry), std::move(curElemVolVars), std::move(prevElemVolVars), eIdx});
539 }
540 else if (eIdx != momentumCouplingContext_()[0].eIdx)
541 {
542 momentumCouplingContext_()[0].eIdx = eIdx;
543 momentumCouplingContext_()[0].fvGeometry.bind(elementI);
544 momentumCouplingContext_()[0].curElemVolVars.bind(elementI, momentumCouplingContext_()[0].fvGeometry, this->curSol(freeFlowMassIndex));
545
546 if (isTransient_())
547 momentumCouplingContext_()[0].prevElemVolVars.bindElement(elementI, momentumCouplingContext_()[0].fvGeometry, prevSol_(freeFlowMassIndex));
548 }
549 }
550
551 void bindCouplingContext_(Dune::index_constant<freeFlowMassIndex> domainI,
552 const Element<freeFlowMassIndex>& elementI) const
553 {
554 const auto eIdx = this->problem(freeFlowMassIndex).gridGeometry().elementMapper().index(elementI);
555 bindCouplingContext_(domainI, elementI, eIdx);
556 }
557
558 void bindCouplingContext_(Dune::index_constant<freeFlowMassIndex> domainI,
559 const Element<freeFlowMassIndex>& elementI,
560 const std::size_t eIdx) const
561 {
562 if (massAndEnergyCouplingContext_().empty())
563 {
564 const auto& gridGeometry = this->problem(freeFlowMomentumIndex).gridGeometry();
565 auto fvGeometry = localView(gridGeometry);
566 fvGeometry.bindElement(elementI);
567 massAndEnergyCouplingContext_().emplace_back(std::move(fvGeometry), eIdx);
568 }
569 else if (eIdx != massAndEnergyCouplingContext_()[0].eIdx)
570 {
571 massAndEnergyCouplingContext_()[0].eIdx = eIdx;
572 massAndEnergyCouplingContext_()[0].fvGeometry.bindElement(elementI);
573 }
574 }
575
580 template<std::size_t i>
581 const GridVariables<i>& gridVars_(Dune::index_constant<i> domainIdx) const
582 {
583 if (std::get<i>(gridVariables_))
584 return *std::get<i>(gridVariables_);
585 else
586 DUNE_THROW(Dune::InvalidStateException, "The gridVariables pointer was not set. Use setGridVariables() before calling this function");
587 }
588
593 template<std::size_t i>
594 GridVariables<i>& gridVars_(Dune::index_constant<i> domainIdx)
595 {
596 if (std::get<i>(gridVariables_))
597 return *std::get<i>(gridVariables_);
598 else
599 DUNE_THROW(Dune::InvalidStateException, "The gridVariables pointer was not set. Use setGridVariables() before calling this function");
600 }
601
602
603 void computeCouplingStencils_()
604 {
605 // TODO higher order
606 const auto& momentumGridGeometry = this->problem(freeFlowMomentumIndex).gridGeometry();
607 auto momentumFvGeometry = localView(momentumGridGeometry);
608 massAndEnergyToMomentumStencils_.clear();
609 massAndEnergyToMomentumStencils_.resize(momentumGridGeometry.gridView().size(0));
610
611 momentumToMassAndEnergyStencils_.clear();
612 momentumToMassAndEnergyStencils_.resize(momentumGridGeometry.numScv());
613
614 for (const auto& element : elements(momentumGridGeometry.gridView()))
615 {
616 const auto eIdx = momentumGridGeometry.elementMapper().index(element);
617 momentumFvGeometry.bind(element);
618 for (const auto& scv : scvs(momentumFvGeometry))
619 {
620 massAndEnergyToMomentumStencils_[eIdx].push_back(scv.dofIndex());
621 momentumToMassAndEnergyStencils_[scv.index()].push_back(eIdx);
622
623 // extend the stencil for fluids with variable viscosity and density,
624 if constexpr (FluidSystem::isCompressible(0/*phaseIdx*/))
625 // if constexpr (FluidSystem::isCompressible(0/*phaseIdx*/) || !FluidSystem::viscosityIsConstant(0/*phaseIdx*/)) // TODO fix on master
626 {
627 for (const auto& scvf : scvfs(momentumFvGeometry, scv))
628 {
629 if (scvf.isLateral() && !scvf.boundary())
630 {
631 const auto& outsideScv = momentumFvGeometry.scv(scvf.outsideScvIdx());
632 momentumToMassAndEnergyStencils_[scv.index()].push_back(outsideScv.elementIndex());
633 }
634 }
635 }
636 }
637 }
638 }
639
640 std::size_t massScvfToMomentumScvIdx_(const SubControlVolumeFace<freeFlowMassIndex>& massScvf,
641 [[maybe_unused]] const FVElementGeometry<freeFlowMomentumIndex>& momentumFVGeometry) const
642 {
643 if constexpr (ConsistentlyOrientedGrid<typename GridView<freeFlowMomentumIndex>::Grid>{})
644 return massScvf.index();
645 else
646 {
647 static const bool makeConsistentlyOriented = getParam<bool>("Grid.MakeConsistentlyOriented", true);
648 if (!makeConsistentlyOriented)
649 return massScvf.index();
650
651 for (const auto& momentumScv : scvs(momentumFVGeometry))
652 {
653 typename SubControlVolumeFace<freeFlowMassIndex>::GlobalPosition momentumUnitOuterNormal(0.0);
654 momentumUnitOuterNormal[momentumScv.dofAxis()] = momentumScv.directionSign();
655 if (Dune::FloatCmp::eq<typename GridView<freeFlowMomentumIndex>::ctype>(massScvf.unitOuterNormal()*momentumUnitOuterNormal, 1.0))
656 return momentumScv.index();
657 }
658 DUNE_THROW(Dune::InvalidStateException, "No Momentum SCV found");
659 }
660 }
661
662 CouplingStencilType emptyStencil_;
663 std::vector<CouplingStencilType> momentumToMassAndEnergyStencils_;
664 std::vector<CouplingStencilType> massAndEnergyToMomentumStencils_;
665
666 // the coupling context exists for each thread
667 // TODO this is a bad pattern, just like mutable caches
668 // we should really construct and pass the context and not store it globally
669 std::vector<MomentumCouplingContext>& momentumCouplingContext_() const
670 {
671 thread_local static std::vector<MomentumCouplingContext> c;
672 return c;
673 }
674
675 // the coupling context exists for each thread
676 std::vector<MassAndEnergyCouplingContext>& massAndEnergyCouplingContext_() const
677 {
678 thread_local static std::vector<MassAndEnergyCouplingContext> c;
679 return c;
680 }
681
683 GridVariablesTuple gridVariables_;
684
685 bool isTransient_() const
686 { return std::get<0>(prevSolutions_) != nullptr; }
687
688 template<std::size_t i>
689 const SubSolutionVector<i>& prevSol_(Dune::index_constant<i>) const
690 { return *std::get<i>(prevSolutions_); }
691
692 PrevSolutionVectorStorage prevSolutions_;
693
694 std::deque<std::vector<ElementSeed<freeFlowMomentumIndex>>> elementSets_;
695};
696
698template<class T>
700: public std::false_type {};
701
702} // end namespace Dumux
703
704#endif
The interface of the coupling manager for multi domain problems.
Definition: multidomain/couplingmanager.hh:37
void attachSolution(const SolutionVectorStorage &curSol)
Attach a solution vector stored outside of this class.
Definition: multidomain/couplingmanager.hh:311
void setSubProblems(const std::tuple< std::shared_ptr< SubProblems >... > &problems)
set the pointers to the sub problems
Definition: multidomain/couplingmanager.hh:276
const Problem< i > & problem(Dune::index_constant< i > domainIdx) const
Return a reference to the sub problem.
Definition: multidomain/couplingmanager.hh:298
std::vector< std::size_t > CouplingStencilType
default type used for coupling element stencils
Definition: multidomain/couplingmanager.hh:53
SubSolutionVector< i > & curSol(Dune::index_constant< i > domainIdx)
the solution vector of the subproblem
Definition: multidomain/couplingmanager.hh:327
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:208
typename Traits::template TupleOfSharedPtr< SubSolutionVector > SolutionVectorStorage
the type in which the solution vector is stored in the manager
Definition: multidomain/couplingmanager.hh:60
typename Traits::SolutionVector SolutionVector
the type of the solution vector
Definition: multidomain/couplingmanager.hh:56
The interface of the coupling manager for free flow systems.
Definition: couplingmanager_staggered.hh:48
Scalar pressure(const Element< freeFlowMomentumIndex > &element, const FVElementGeometry< freeFlowMomentumIndex > &fvGeometry, const SubControlVolumeFace< freeFlowMomentumIndex > &scvf) const
Returns the pressure at a given frontal sub control volume face.
Definition: couplingmanager_staggered.hh:230
static constexpr auto freeFlowMomentumIndex
Definition: couplingmanager_staggered.hh:51
Scalar effectiveViscosity(const Element< freeFlowMomentumIndex > &element, const FVElementGeometry< freeFlowMomentumIndex > &fvGeometry, const SubControlVolumeFace< freeFlowMomentumIndex > &scvf) const
Returns the pressure at a given sub control volume face.
Definition: couplingmanager_staggered.hh:324
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: couplingmanager_staggered.hh:447
decltype(auto) evalCouplingResidual(Dune::index_constant< freeFlowMomentumIndex > domainI, const LocalAssemblerI &localAssemblerI, const SubControlVolume< freeFlowMomentumIndex > &scvI, Dune::index_constant< j > domainJ, std::size_t dofIdxGlobalJ) const
evaluates the element residual of a coupled element of domain i which depends on the variables at the...
Definition: couplingmanager_staggered.hh:194
static constexpr auto freeFlowMassIndex
Definition: couplingmanager_staggered.hh:52
void assembleMultithreaded(Dune::index_constant< i > domainI, AssembleElementFunc &&assembleElement) const
Execute assembly kernel in parallel.
Definition: couplingmanager_staggered.hh:492
Scalar density(const Element< freeFlowMomentumIndex > &element, const SubControlVolume< freeFlowMomentumIndex > &scv, const bool considerPreviousTimeStep=false) const
Returns the density at a given sub control volume.
Definition: couplingmanager_staggered.hh:309
void init(std::shared_ptr< Problem< freeFlowMomentumIndex > > momentumProblem, std::shared_ptr< Problem< freeFlowMassIndex > > massProblem, GridVariablesTuple &&gridVariables, const SolutionVector &curSol)
Methods to be accessed by main.
Definition: couplingmanager_staggered.hh:123
const CouplingStencilType & couplingStencil(Dune::index_constant< freeFlowMomentumIndex > domainI, const Element< freeFlowMomentumIndex > &elementI, const SubControlVolume< freeFlowMomentumIndex > &scvI, Dune::index_constant< j > domainJ) const
The coupling stencil of domain I, i.e. which domain J DOFs the given domain I scv's residual depends ...
Definition: couplingmanager_staggered.hh:393
auto insideAndOutsideDensity(const Element< freeFlowMomentumIndex > &element, const FVElementGeometry< freeFlowMomentumIndex > &fvGeometry, const SubControlVolumeFace< freeFlowMomentumIndex > &scvf, const bool considerPreviousTimeStep=false) const
Definition: couplingmanager_staggered.hh:280
void init(std::shared_ptr< Problem< freeFlowMomentumIndex > > momentumProblem, std::shared_ptr< Problem< freeFlowMassIndex > > massProblem, GridVariablesTuple &&gridVariables, const typename ParentType::SolutionVectorStorage &curSol)
use as binary coupling manager in multi model context
Definition: couplingmanager_staggered.hh:149
const CouplingStencilType & couplingStencil(Dune::index_constant< freeFlowMomentumIndex > domainI, const Element< freeFlowMomentumIndex > &elementI, const SubControlVolume< freeFlowMomentumIndex > &scvI, Dune::index_constant< freeFlowMassIndex > domainJ) const
returns an iterable container of all indices of degrees of freedom of domain j that couple with / inf...
Definition: couplingmanager_staggered.hh:430
void init(std::shared_ptr< Problem< freeFlowMomentumIndex > > momentumProblem, std::shared_ptr< Problem< freeFlowMassIndex > > massProblem, GridVariablesTuple &&gridVariables, const SolutionVector &curSol, const SolutionVector &prevSol)
use as regular coupling manager in a transient setting
Definition: couplingmanager_staggered.hh:136
Scalar effectiveViscosity(const Element< freeFlowMomentumIndex > &element, const FVElementGeometry< freeFlowMomentumIndex > &fvGeometry, const SubControlVolume< freeFlowMomentumIndex > &scv) const
Returns the pressure at a given sub control volume.
Definition: couplingmanager_staggered.hh:351
static constexpr auto pressureIdx
Definition: couplingmanager_staggered.hh:115
const CouplingStencilType & couplingStencil(Dune::index_constant< freeFlowMassIndex > domainI, const Element< freeFlowMassIndex > &elementI, Dune::index_constant< freeFlowMomentumIndex > domainJ) const
returns an iterable container of all indices of degrees of freedom of domain j that couple with / inf...
Definition: couplingmanager_staggered.hh:413
void init(std::shared_ptr< Problem< freeFlowMomentumIndex > > momentumProblem, std::shared_ptr< Problem< freeFlowMassIndex > > massProblem, GridVariablesTuple &&gridVariables, const typename ParentType::SolutionVectorStorage &curSol, const PrevSolutionVectorStorage &prevSol)
use as binary coupling manager in multi model context and for transient problems
Definition: couplingmanager_staggered.hh:162
Scalar density(const Element< freeFlowMomentumIndex > &element, const FVElementGeometry< freeFlowMomentumIndex > &fvGeometry, const SubControlVolumeFace< freeFlowMomentumIndex > &scvf, const bool considerPreviousTimeStep=false) const
Returns the density at a given sub control volume face.
Definition: couplingmanager_staggered.hh:253
Scalar cellPressure(const Element< freeFlowMassIndex > &element, const SubControlVolumeFace< freeFlowMassIndex > &scvf) const
Returns the pressure at the center of a sub control volume corresponding to a given sub control volum...
Definition: couplingmanager_staggered.hh:244
VelocityVector faceVelocity(const Element< freeFlowMassIndex > &element, const SubControlVolumeFace< freeFlowMassIndex > &scvf) const
Returns the velocity at a given sub control volume face.
Definition: couplingmanager_staggered.hh:363
void computeColorsForAssembly()
Compute colors for multithreaded assembly.
Definition: couplingmanager_staggered.hh:479
Coloring schemes for shared-memory-parallel assembly.
Defines all properties used in Dumux.
Type traits.
Element solution classes and factory functions.
free functions for the evaluation of primary variables inside elements.
GridCache::LocalView localView(const GridCache &gridCache)
Free function to get the local view of a grid cache object.
Definition: localview.hh:26
auto elementSolution(const Element &element, const SolutionVector &sol, const GridGeometry &gg) -> std::enable_if_t< GridGeometry::discMethod==DiscretizationMethods::cctpfa||GridGeometry::discMethod==DiscretizationMethods::ccmpfa, CCElementSolution< typename GridGeometry::LocalView, std::decay_t< decltype(std::declval< SolutionVector >()[0])> > >
Make an element solution for cell-centered schemes.
Definition: cellcentered/elementsolution.hh:101
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
The available discretization methods in Dumux.
The interface of the coupling manager for multi domain problems.
A linear system assembler (residual and Jacobian) for finite volume schemes with multiple domains.
Definition: adapt.hh:17
auto computeColoring(const GridGeometry &gg, int verbosity=1)
Compute iterable lists of element seeds partitioned by color.
Definition: coloring.hh:239
Parallel for loop (multithreading)
Type trait that is specialized for coupling manager supporting multithreaded assembly.
Definition: multistagemultidomainfvassembler.hh:78