version 3.11-dev
Loading...
Searching...
No Matches
couplingmanager_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#ifndef DUMUX_MULTIDOMAIN_FREEFLOW_COUPLING_MANAGER_CVFE_HH
13#define DUMUX_MULTIDOMAIN_FREEFLOW_COUPLING_MANAGER_CVFE_HH
14
15#include <memory>
16#include <tuple>
17#include <vector>
18#include <deque>
19#include <iostream>
20
21#include <dune/common/exceptions.hh>
22#include <dune/common/indices.hh>
23#include <dune/common/float_cmp.hh>
24#include <dune/geometry/referenceelements.hh>
25
27#include <dumux/common/concepts/localdofs_.hh>
29#include <dumux/common/concepts/variables_.hh>
30#include <dumux/common/concepts/ipdata_.hh>
33
39
42
45
46#include "typetraits.hh"
47
48namespace Dumux {
49
55template<class Traits>
57: public CouplingManager<Traits>
58{
59 using ParentType = CouplingManager<Traits>;
60public:
61 static constexpr auto freeFlowMomentumIndex = typename Traits::template SubDomain<0>::Index();
62 static constexpr auto freeFlowMassIndex = typename Traits::template SubDomain<1>::Index();
63
64 // this can be used if the coupling manager is used inside a meta-coupling manager (e.g. multi-binary)
65 // to manager the solution vector storage outside this class
67private:
68 template<std::size_t id> using SubDomainTypeTag = typename Traits::template SubDomain<id>::TypeTag;
69 template<std::size_t id> using PrimaryVariables = GetPropType<SubDomainTypeTag<id>, Properties::PrimaryVariables>;
70 template<std::size_t id> using GridGeometry = GetPropType<SubDomainTypeTag<id>, Properties::GridGeometry>;
71 template<std::size_t id> using GridView = typename GridGeometry<id>::GridView;
72 template<std::size_t id> using Element = typename GridView<id>::template Codim<0>::Entity;
73 template<std::size_t id> using ElementSeed = typename GridView<id>::Grid::template Codim<0>::EntitySeed;
74 template<std::size_t id> using FVElementGeometry = typename GridGeometry<id>::LocalView;
75 template<std::size_t id> using GridVariables = typename Traits::template SubDomain<id>::GridVariables;
76 template<std::size_t id> using GridVariablesCache = Concept::GridVariablesCache_t<GridVariables<id>>;
77 template<std::size_t id> using ElementVariables = typename GridVariablesCache<id>::LocalView;
78 template<std::size_t id> using Problem = GetPropType<SubDomainTypeTag<id>, Properties::Problem>;
79 template<std::size_t id> using Variables = Concept::Variables_t<GridVariables<id>>;
80
81 using Scalar = typename Traits::Scalar;
82 using SolutionVector = typename Traits::SolutionVector;
83
84 using CouplingStencilType = std::vector<std::size_t>;
85
86 using GridVariablesTuple = typename Traits::template TupleOfSharedPtr<GridVariables>;
87
88 using FluidSystem = typename Variables<freeFlowMassIndex>::FluidSystem;
89
90 using GlobalPosition = typename GridGeometry<freeFlowMassIndex>::GlobalCoordinate;
91 using VelocityVector = GlobalPosition;
92 using ShapeValue = typename Dune::FieldVector<Scalar, 1>;
93
94 static_assert(std::is_same_v<VelocityVector, typename GridGeometry<freeFlowMomentumIndex>::GlobalCoordinate>);
95
96 template<class ElementSolution>
97 struct MomentumCouplingContextNoCaching
98 {
99 MomentumCouplingContextNoCaching(ElementSolution&& elemSol)
100 : elemSol_(std::move(elemSol)) {}
101
102 template<class GridVarsCache, class FvElementGeometry, class ScvOrLocalDof>
103 auto vars(const GridVarsCache& gridVarsCache, const FvElementGeometry& fvGeometry, const ScvOrLocalDof& scvOrLocalDof) const
104 {
105 const auto& problem = gridVarsCache.problem();
106 Variables<freeFlowMassIndex> variables;
107 if constexpr (Concept::FVGridVariables<GridVariables<freeFlowMassIndex>>)
108 {
109 // the variables are still updated per sub-control volume
110 if constexpr (Concept::LocalDof<ScvOrLocalDof>)
111 variables.update(elemSol_, problem, fvGeometry.element(), fvGeometry.scv(scvOrLocalDof.index()));
112 else
113 variables.update(elemSol_, problem, fvGeometry.element(), scvOrLocalDof);
114 }
115 else
116 variables.update(elemSol_, problem, fvGeometry, ipData(fvGeometry, scvOrLocalDof));
117 return variables;
118 }
119
120 ElementSolution elemSol_;
121 };
122
123 struct MomentumCouplingContextGlobalCaching
124 {
125 template<class GridVarsCache, class FvElementGeometry, class ScvOrLocalDof>
126 const auto& vars(const GridVarsCache& gridVarsCache, const FvElementGeometry& fvGeometry, const ScvOrLocalDof& scvOrLocalDof) const
127 {
128 if constexpr (requires { gridVarsCache.volVars(scvOrLocalDof); })
129 return gridVarsCache.volVars(scvOrLocalDof);
130 else
131 return gridVarsCache.variables(scvOrLocalDof);
132 }
133 };
134
135 using MomentumDiscretizationMethod = typename GridGeometry<freeFlowMomentumIndex>::DiscretizationMethod;
136 using MassDiscretizationMethod = typename GridGeometry<freeFlowMassIndex>::DiscretizationMethod;
137
138 template<std::size_t id> using IpData
139 = Dumux::CVFE::InterpolationPointData<typename GridView<id>::template Codim<0>::Entity::Geometry::LocalCoordinate,
140 typename GridView<id>::template Codim<0>::Entity::Geometry::GlobalCoordinate>;
141
142public:
144 static constexpr auto pressureIdx = Variables<freeFlowMassIndex>::Indices::pressureIdx;
145
149 // \{
150
151 //! use as regular coupling manager
152 void init(std::shared_ptr<Problem<freeFlowMomentumIndex>> momentumProblem,
153 std::shared_ptr<Problem<freeFlowMassIndex>> massProblem,
154 GridVariablesTuple&& gridVariables,
155 const SolutionVector& curSol)
156 {
157 this->setSubProblems(std::make_tuple(momentumProblem, massProblem));
158 gridVariables_ = gridVariables;
159 this->updateSolution(curSol);
160 prevSol_ = nullptr;
161
162 computeCouplingStencils_();
163 }
164
165 //! use as regular coupling manager in a transient setting
166 void init(std::shared_ptr<Problem<freeFlowMomentumIndex>> momentumProblem,
167 std::shared_ptr<Problem<freeFlowMassIndex>> massProblem,
168 GridVariablesTuple&& gridVariables,
169 const SolutionVector& curSol,
170 const SolutionVector& prevSol)
171 {
172 init(momentumProblem, massProblem, std::forward<GridVariablesTuple>(gridVariables), curSol);
173 prevSol_ = &prevSol;
174 }
175
176 //! use as binary coupling manager in multi model context
177 void init(std::shared_ptr<Problem<freeFlowMomentumIndex>> momentumProblem,
178 std::shared_ptr<Problem<freeFlowMassIndex>> massProblem,
179 GridVariablesTuple&& gridVariables,
181 {
182 this->setSubProblems(std::make_tuple(momentumProblem, massProblem));
183 gridVariables_ = gridVariables;
184 this->attachSolution(curSol);
185 prevSol_ = nullptr;
186
187 computeCouplingStencils_();
188 }
189
190 // \}
191
195 // \{
196
200 template<class ElementDiscretization>
201 [[deprecated("This method will be removed after release (3.11). Use pressure(..., ipData) instead!")]]
202 Scalar pressure(const Element<freeFlowMomentumIndex>& element,
203 const ElementDiscretization& elemDisc,
204 const typename ElementDiscretization::SubControlVolumeFace& scvf,
205 const bool considerPreviousTimeStep = false) const
206 {
207 const auto& globalPos = scvf.ipGlobal();
208 const auto& localPos = element.geometry().local(globalPos);
209 return this->pressure(element, elemDisc, IpData<freeFlowMassIndex>(localPos, globalPos), considerPreviousTimeStep);
210 }
211
215 template<class ElementDiscretization>
216 [[deprecated("This method will be removed after release (3.11). Use pressure(..., ipData) instead!")]]
217 Scalar pressure(const Element<freeFlowMomentumIndex>& element,
218 const ElementDiscretization& elemDisc,
219 const typename ElementDiscretization::SubControlVolume& scv,
220 const bool considerPreviousTimeStep = false) const
221 {
222 return this->pressure(element, elemDisc, ipData(elemDisc, scv), considerPreviousTimeStep);
223 }
224
228 template<Concept::IpData IpData>
229 Scalar pressure(const Element<freeFlowMomentumIndex>& element,
230 const FVElementGeometry<freeFlowMomentumIndex>& fvGeometry,
231 const IpData& ipData,
232 const bool considerPreviousTimeStep = false) const
233 {
234 assert(!(considerPreviousTimeStep && !isTransient_()));
235 const auto& gg = Dumux::gridDiscretization(this->problem(freeFlowMassIndex));
236 const auto& sol = considerPreviousTimeStep ? (*prevSol_)[freeFlowMassIndex]
237 : this->curSol(freeFlowMassIndex);
238 const auto elemSol = elementSolution(element, sol, gg);
239 return evalSolutionAtLocalPos(element, element.geometry(), gg, elemSol, ipData.local())[pressureIdx];
240 }
241
245 template<class ElementDiscretization>
246 [[deprecated("This method will be removed after release (3.11). Use density(..., ipData) instead!")]]
247 Scalar density(const Element<freeFlowMomentumIndex>& element,
248 const ElementDiscretization& elemDisc,
249 const typename ElementDiscretization::SubControlVolumeFace& scvf,
250 const bool considerPreviousTimeStep = false) const
251 {
252 const auto& globalPos = scvf.ipGlobal();
253 const auto& localPos = element.geometry().local(globalPos);
254 return this->density(element, elemDisc, IpData<freeFlowMassIndex>(localPos, globalPos), considerPreviousTimeStep);
255 }
256
260 template<class ElementDiscretization>
261 [[deprecated("This method will be removed after release (3.11). Use density(..., ipData) instead!")]]
262 Scalar density(const Element<freeFlowMomentumIndex>& element,
263 const ElementDiscretization& elemDisc,
264 const typename ElementDiscretization::SubControlVolume& scv,
265 const bool considerPreviousTimeStep = false) const
266 {
267 return this->density(element, elemDisc, ipData(elemDisc, scv), considerPreviousTimeStep);
268 }
269
273 template<Concept::IpData IpData>
274 Scalar density(const Element<freeFlowMomentumIndex>& element,
275 const FVElementGeometry<freeFlowMomentumIndex>& fvGeometry,
276 const IpData& ipData,
277 const bool considerPreviousTimeStep = false) const
278 {
279 assert(!(considerPreviousTimeStep && !isTransient_()));
280
281 const auto& sol = considerPreviousTimeStep ? (*prevSol_)[freeFlowMassIndex]
282 : this->curSol(freeFlowMassIndex);
283
284 auto massFvGeometry = localView(Dumux::gridDiscretization(this->problem(freeFlowMassIndex)));
285 massFvGeometry.bind(element);
286 const auto context = makeMomentumCouplingContext_(massFvGeometry, sol);
287 const auto& gridVarsCache = subDomainGridVars_(Dune::index_constant<freeFlowMassIndex>{}, considerPreviousTimeStep);
288
289 if constexpr (MassDiscretizationMethod{} == DiscretizationMethods::cctpfa)
290 {
291 const auto eIdx = fvGeometry.elementIndex();
292 const auto& scv = massFvGeometry.scv(eIdx);
293
294 const auto& variables = context.vars(gridVarsCache, massFvGeometry, scv);
295
296 return variables.density();
297 }
298 else
299 {
300 // TODO: cache the shape values
301 using ShapeValue = typename Dune::FieldVector<Scalar, 1>;
302 const auto& localBasis = massFvGeometry.feLocalBasis();
303 std::vector<ShapeValue> shapeValues;
304 localBasis.evaluateFunction(ipData.local(), shapeValues);
305
306 Scalar rho = 0.0;
307 for (const auto& localDof : localDofs(massFvGeometry))
308 {
309 const auto& variables = context.vars(gridVarsCache, massFvGeometry, localDof);
310 rho += variables.density()*shapeValues[localDof.index()][0];
311 }
312
313 return rho;
314 }
315 }
316
320 template<class ElementDiscretization>
321 [[deprecated("This method will be removed after release (3.11). Use effectiveViscosity(..., ipData) instead!")]]
322 Scalar effectiveViscosity(const Element<freeFlowMomentumIndex>& element,
323 const ElementDiscretization& elemDisc,
324 const typename ElementDiscretization::SubControlVolumeFace& scvf,
325 const bool considerPreviousTimeStep = false) const
326 {
327 const auto& globalPos = scvf.ipGlobal();
328 const auto& localPos = element.geometry().local(globalPos);
329 return this->effectiveViscosity(element, elemDisc, IpData<freeFlowMassIndex>(localPos, globalPos), considerPreviousTimeStep);
330 }
331
335 template<class ElementDiscretization>
336 [[deprecated("This method will be removed after release (3.11). Use effectiveViscosity(..., ipData) instead!")]]
337 Scalar effectiveViscosity(const Element<freeFlowMomentumIndex>& element,
338 const ElementDiscretization& elemDisc,
339 const typename ElementDiscretization::SubControlVolume& scv,
340 const bool considerPreviousTimeStep = false) const
341 {
342 return this->effectiveViscosity(element, elemDisc, ipData(elemDisc, scv), considerPreviousTimeStep);
343 }
344
348 template<Concept::IpData IpData>
349 Scalar effectiveViscosity(const Element<freeFlowMomentumIndex>& element,
350 const FVElementGeometry<freeFlowMomentumIndex>& fvGeometry,
351 const IpData& ipData,
352 const bool considerPreviousTimeStep = false) const
353 {
354 assert(!(considerPreviousTimeStep && !isTransient_()));
355
356 const auto& sol = considerPreviousTimeStep ? (*prevSol_)[freeFlowMassIndex]
357 : this->curSol(freeFlowMassIndex);
358
359 auto massFvGeometry = localView(Dumux::gridDiscretization(this->problem(freeFlowMassIndex)));
360 massFvGeometry.bind(element);
361 const auto context = makeMomentumCouplingContext_(massFvGeometry, sol);
362 const auto& gridVarsCache = subDomainGridVars_(Dune::index_constant<freeFlowMassIndex>{}, considerPreviousTimeStep);
363
364 if constexpr (MassDiscretizationMethod{} == DiscretizationMethods::cctpfa)
365 {
366 const auto eIdx = fvGeometry.elementIndex();
367 const auto& scv = massFvGeometry.scv(eIdx);
368
369 const auto& variables = context.vars(gridVarsCache, massFvGeometry, scv);
370
371 return variables.viscosity();
372 }
373 else
374 {
375 // TODO: cache the shape values
376 using ShapeValue = typename Dune::FieldVector<Scalar, 1>;
377 const auto& localBasis = massFvGeometry.feLocalBasis();
378 std::vector<ShapeValue> shapeValues;
379 localBasis.evaluateFunction(ipData.local(), shapeValues);
380
381 Scalar mu = 0.0;
382 for (const auto& localDof : localDofs(massFvGeometry))
383 {
384 const auto& variables = context.vars(gridVarsCache, massFvGeometry, localDof);
385 mu += variables.viscosity()*shapeValues[localDof.index()][0];
386 }
387
388 return mu;
389 }
390 }
391
395 template<class SubControlVolumeFace>
396 VelocityVector faceVelocity(const Element<freeFlowMassIndex>& element,
397 const SubControlVolumeFace& scvf) const
398 {
399 // TODO: optimize this function for tpfa where the scvf ip coincides with the dof location
401 fvGeometry.bindElement(element);
402
403 const auto& localBasis = fvGeometry.feLocalBasis();
404
405 std::vector<ShapeValue> shapeValues;
406 const auto ipLocal = element.geometry().local(scvf.ipGlobal());
407 localBasis.evaluateFunction(ipLocal, shapeValues);
408
409 // interpolate velocity at scvf
410 VelocityVector velocity(0.0);
411 for (const auto& localDof : localDofs(fvGeometry))
412 velocity.axpy(shapeValues[localDof.index()][0], this->curSol(freeFlowMomentumIndex)[localDof.dofIndex()]);
413
414 return velocity;
415 }
416
419 */
420 VelocityVector elementVelocity(const FVElementGeometry<freeFlowMassIndex>& fvGeometry) const
421 {
422 auto momentumFvGeometry = localView(Dumux::gridDiscretization(this->problem(freeFlowMomentumIndex)));
423 momentumFvGeometry.bindElement(fvGeometry.element());
424
425 const auto& localBasis = momentumFvGeometry.feLocalBasis();
426
427 // interpolate velocity at scvf
428 VelocityVector velocity(0.0);
429 std::vector<ShapeValue> shapeValues;
430 localBasis.evaluateFunction(referenceElement(fvGeometry.element()).position(0,0), shapeValues);
431
432 for (const auto& localDof : localDofs(momentumFvGeometry))
433 velocity.axpy(shapeValues[localDof.index()][0], this->curSol(freeFlowMomentumIndex)[localDof.dofIndex()]);
434
435 return velocity;
436 }
437
441 template<Concept::IpData IpData>
442 VelocityVector velocity(const FVElementGeometry<freeFlowMassIndex>& fvGeometry,
443 const IpData& ipData,
444 const bool considerPreviousTimeStep = false) const
445 {
446 assert(!(considerPreviousTimeStep && !isTransient_()));
447
448 const auto& element = fvGeometry.element();
450 auto momentumFvGeometry = localView(gg);
451 momentumFvGeometry.bindElement(fvGeometry.element());
452
453 const auto& sol = considerPreviousTimeStep ? (*prevSol_)[freeFlowMomentumIndex]
455
456 const auto elemSol = elementSolution(element, sol, gg);
457 return evalSolutionAtLocalPos(element, element.geometry(), gg, elemSol, ipData.local());
458 }
459
465 template<Concept::IpData IpData>
466 Scalar velocityDivergence(const FVElementGeometry<freeFlowMassIndex>& fvGeometry,
467 const IpData& ipData,
468 const bool considerPreviousTimeStep = false) const
469 {
470 assert(!(considerPreviousTimeStep && !isTransient_()));
471
472 const auto& element = fvGeometry.element();
474
475 const auto& sol = considerPreviousTimeStep ? (*prevSol_)[freeFlowMomentumIndex]
477
478 const auto elemSol = elementSolution(element, sol, gg);
479 const auto gradV = evalGradientsAtLocalPos(element, element.geometry(), gg, elemSol, ipData.local());
480
481 Scalar divV = 0.0;
482 for (int dirIdx = 0; dirIdx < GridView<freeFlowMomentumIndex>::dimension; ++dirIdx)
483 divV += gradV[dirIdx][dirIdx];
484
485 return divV;
486 }
487
492 template<std::size_t j, class SubControlVolume>
493 const CouplingStencilType& couplingStencil(Dune::index_constant<freeFlowMomentumIndex> domainI,
494 const Element<freeFlowMomentumIndex>& elementI,
495 const SubControlVolume& scvI,
496 Dune::index_constant<j> domainJ) const
497 { return emptyStencil_; }
498
512 */
513 const CouplingStencilType& couplingStencil(Dune::index_constant<freeFlowMassIndex> domainI,
514 const Element<freeFlowMassIndex>& elementI,
515 Dune::index_constant<freeFlowMomentumIndex> domainJ) const
516 {
517 const auto eIdx = Dumux::gridDiscretization(this->problem(freeFlowMassIndex)).elementMapper().index(elementI);
518 return massAndEnergyToMomentumStencils_[eIdx];
519 }
520
528 */
529 const CouplingStencilType& couplingStencil(Dune::index_constant<freeFlowMomentumIndex> domainI,
530 const Element<freeFlowMomentumIndex>& elementI,
531 Dune::index_constant<freeFlowMassIndex> domainJ) const
532 {
533 const auto eIdx = Dumux::gridDiscretization(this->problem(freeFlowMomentumIndex)).elementMapper().index(elementI);
534 return momentumToMassAndEnergyStencils_[eIdx];
535 }
536
537 // \}
538
542 // \{
543
563 template<std::size_t i, std::size_t j, class LocalAssemblerI>
564 void updateCouplingContext(Dune::index_constant<i> domainI,
565 const LocalAssemblerI& localAssemblerI,
566 Dune::index_constant<j> domainJ,
567 std::size_t dofIdxGlobalJ,
568 const PrimaryVariables<j>& priVarsJ,
569 int pvIdxJ)
570 {
571 this->curSol(domainJ)[dofIdxGlobalJ][pvIdxJ] = priVarsJ[pvIdxJ];
572
573 if constexpr (GridVariablesCache<freeFlowMassIndex>::cachingEnabled)
574 {
575 if constexpr (MassDiscretizationMethod{} == DiscretizationMethods::cctpfa)
576 {
577 if constexpr (domainI == freeFlowMomentumIndex && domainJ == freeFlowMassIndex)
578 {
579 const auto& problem = this->problem(domainJ);
580 const auto& deflectedElement = Dumux::gridDiscretization(problem).element(dofIdxGlobalJ);
581 const auto elemSol = elementSolution(deflectedElement, this->curSol(domainJ), Dumux::gridDiscretization(problem));
582 auto fvGeometry = localView(Dumux::gridDiscretization(problem));
583 fvGeometry.bind(deflectedElement);
584 const auto& scv = fvGeometry.scv(dofIdxGlobalJ);
585
586 if constexpr (Concept::FVGridVariables<GridVariables<freeFlowMassIndex>>)
587 subDomainVariables_(Dune::index_constant<freeFlowMassIndex>{}, /*current*/true, scv).update(std::move(elemSol), problem, deflectedElement, scv);
588 else
589 subDomainVariables_(Dune::index_constant<freeFlowMassIndex>{}, /*current*/true, ipData(fvGeometry, scv)).update(std::move(elemSol), problem, deflectedElement, scv);
590 }
591 }
592 // all other schemes provide local dofs, including those owning no sub-control volume
593 else
594 {
595 if constexpr (domainI == freeFlowMomentumIndex && domainJ == freeFlowMassIndex)
596 {
597 const auto& problem = this->problem(domainJ);
598 const auto deflectedElementIdx = Dumux::gridDiscretization(problem).elementMapper().index(localAssemblerI.element());
599 const auto& deflectedElement = Dumux::gridDiscretization(problem).element(deflectedElementIdx);
600 const auto elemSol = elementSolution(deflectedElement, this->curSol(domainJ), Dumux::gridDiscretization(problem));
601 auto fvGeometry = localView(Dumux::gridDiscretization(problem));
602 fvGeometry.bind(deflectedElement);
603
604 for (const auto& localDof : localDofs(fvGeometry))
605 {
606 if (localDof.dofIndex() != dofIdxGlobalJ)
607 continue;
608
609 if constexpr (Concept::FVGridVariables<GridVariables<freeFlowMassIndex>>)
610 {
611 const auto& scv = fvGeometry.scv(localDof.index());
612 auto& variables = this->subDomainVariables_(Dune::index_constant<freeFlowMassIndex>{}, /*current*/true, scv);
613 variables.update(elemSol, problem, deflectedElement, scv);
614 }
615 else
616 {
617 auto& variables = this->subDomainVariables_(Dune::index_constant<freeFlowMassIndex>{}, /*current*/true, localDof);
618 variables.update(elemSol, problem, fvGeometry, ipData(fvGeometry, localDof));
619 }
620 }
621 }
622 }
623 }
624 }
625
626 // \}
627
630 */
632 {
633 if constexpr (MomentumDiscretizationMethod{} == DiscretizationMethods::fcdiamond)
634 {
635 // use coloring of the mass discretization for both domains
636 // the diamond coloring is a subset (minimum amount of colors) of cctpfa/box coloring
638 }
639 else
640 {
641 // use coloring of the momentum discretization for both domains
643 }
644 }
645
652 template<std::size_t i, class AssembleElementFunc>
653 void assembleMultithreaded(Dune::index_constant<i> domainId, AssembleElementFunc&& assembleElement) const
654 {
655 if (elementSets_.empty())
656 DUNE_THROW(Dune::InvalidStateException, "Call computeColorsForAssembly before assembling in parallel!");
657
658 // make this element loop run in parallel
659 // for this we have to color the elements so that we don't get
660 // race conditions when writing into the global matrix
661 // each color can be assembled using multiple threads
662 const auto& grid = Dumux::gridDiscretization(this->problem(freeFlowMassIndex)).gridView().grid();
663 for (const auto& elements : elementSets_)
664 {
665 Dumux::parallelFor(elements.size(), [&](const std::size_t eIdx)
666 {
667 const auto element = grid.entity(elements[eIdx]);
668 assembleElement(element);
669 });
670 }
671 }
672
673private:
674 template<std::size_t i>
675 const auto& subDomainGridVars_(Dune::index_constant<i> domainIdx, bool current) const
676 {
677 if constexpr (Concept::FVGridVariables<GridVariables<i>>)
678 return current ? gridVars_(domainIdx).curGridVolVars()
679 : gridVars_(domainIdx).prevGridVolVars();
680 else
681 return current ? gridVars_(domainIdx).curGridVars()
682 : gridVars_(domainIdx).prevGridVars();
683 }
684
685 template<std::size_t i>
686 auto& subDomainGridVars_(Dune::index_constant<i> domainIdx, bool current)
687 {
688 if constexpr (Concept::FVGridVariables<GridVariables<i>>)
689 return current ? gridVars_(domainIdx).curGridVolVars()
690 : gridVars_(domainIdx).prevGridVolVars();
691 else
692 return current ? gridVars_(domainIdx).curGridVars()
693 : gridVars_(domainIdx).prevGridVars();
694 }
695
696 template<std::size_t i, class Scv>
697 auto& subDomainVariables_(Dune::index_constant<i> domainIdx, bool current, const Scv& scv)
698 {
699 if constexpr (Concept::FVGridVariables<GridVariables<i>>)
700 return subDomainGridVars_(domainIdx, current).volVars(scv);
701 else
702 return subDomainGridVars_(domainIdx, current).variables(scv);
703 }
704
705 template<std::size_t i, class Scv>
706 const auto& subDomainVariables_(Dune::index_constant<i> domainIdx, bool current, const Scv& scv) const
707 {
708 if constexpr (Concept::FVGridVariables<GridVariables<i>>)
709 return subDomainGridVars_(domainIdx, current).volVars(scv);
710 else
711 return subDomainGridVars_(domainIdx, current).variables(scv);
712 }
713
714 template<class SolutionVector>
715 auto makeMomentumCouplingContext_(const FVElementGeometry<freeFlowMassIndex>& fvGeometry,
716 const SolutionVector& sol) const
717 {
718 if constexpr (GridVariablesCache<freeFlowMassIndex>::cachingEnabled)
719 return MomentumCouplingContextGlobalCaching{};
720 else
721 return MomentumCouplingContextNoCaching{elementSolution(fvGeometry.element(), sol, Dumux::gridDiscretization(fvGeometry))};
722 }
723
728 template<std::size_t i>
729 const GridVariables<i>& gridVars_(Dune::index_constant<i> domainIdx) const
730 {
731 if (std::get<i>(gridVariables_))
732 return *std::get<i>(gridVariables_);
733 else
734 DUNE_THROW(Dune::InvalidStateException, "The gridVariables pointer was not set. Use setGridVariables() before calling this function");
735 }
736
741 template<std::size_t i>
742 GridVariables<i>& gridVars_(Dune::index_constant<i> domainIdx)
743 {
744 if (std::get<i>(gridVariables_))
745 return *std::get<i>(gridVariables_);
746 else
747 DUNE_THROW(Dune::InvalidStateException, "The gridVariables pointer was not set. Use setGridVariables() before calling this function");
748 }
749
750 void computeCouplingStencils_()
751 {
752 const auto& momentumGridGeometry = Dumux::gridDiscretization(this->problem(freeFlowMomentumIndex));
753 const auto& massGridGeometry = Dumux::gridDiscretization(this->problem(freeFlowMassIndex));
754 auto momentumFvGeometry = localView(momentumGridGeometry);
755 auto massFvGeometry = localView(massGridGeometry);
756
757 massAndEnergyToMomentumStencils_.clear();
758 massAndEnergyToMomentumStencils_.resize(massGridGeometry.gridView().size(0));
759
760 momentumToMassAndEnergyStencils_.clear();
761 momentumToMassAndEnergyStencils_.resize(momentumGridGeometry.gridView().size(0));
762
763 assert(massAndEnergyToMomentumStencils_.size() == momentumToMassAndEnergyStencils_.size());
764 bool hasCubeElements = false;
765
766 for (const auto& element : elements(momentumGridGeometry.gridView()))
767 {
768 if(element.type().isCube())
769 hasCubeElements = true;
770
771 momentumFvGeometry.bindElement(element);
772 massFvGeometry.bindElement(element);
773 const auto eIdx = momentumFvGeometry.elementIndex();
774
775 for (const auto& localDof : localDofs(momentumFvGeometry))
776 massAndEnergyToMomentumStencils_[eIdx].push_back(localDof.dofIndex());
777
778 for (const auto& localDof : localDofs(massFvGeometry))
779 momentumToMassAndEnergyStencils_[eIdx].push_back(localDof.dofIndex());
780 }
781
782 // Print warning for pq1bubble scheme on cube elements if not using the hybrid variant
783 if constexpr ((MomentumDiscretizationMethod{} == DiscretizationMethods::pq1bubble))
784 {
785 if(hasCubeElements && !GridGeometry<freeFlowMomentumIndex>::enableHybridCVFE)
786 {
787 std::cerr << "Warning: Coupled Navier-Stokes problem on cube elements uses non-hybrid pq1bubble. "
788 << "The hybrid variant is recommended because it implements two bubble functions for stability reasons."
789 << std::endl;
790 }
791 }
792 }
793
794 CouplingStencilType emptyStencil_;
795 std::vector<CouplingStencilType> momentumToMassAndEnergyStencils_;
796 std::vector<CouplingStencilType> massAndEnergyToMomentumStencils_;
797
799 GridVariablesTuple gridVariables_;
800
802 bool isTransient_() const
803 { return prevSol_ != nullptr; }
804
805 const SolutionVector* prevSol_ = nullptr;
806
807 std::deque<std::vector<ElementSeed<freeFlowMomentumIndex>>> elementSets_;
808};
809
810namespace Detail {
811
812// declaration (specialize for different discretization types)
813template<class Traits, class DiscretizationMethod = typename Detail::MomentumDiscretizationMethod<Traits>::type>
815
816// multi-threading is not supported because we have only one coupling context instance and a mutable cache
817template<class Traits, class D>
820
821} // end namespace Detail
822
824template<class T>
828
829} // end namespace Dumux
830
831#endif
Traits shared by the multi-domain assemblers.
The interface of the coupling manager for free flow systems.
Definition couplingmanager_cvfe.hh:58
const CouplingStencilType & couplingStencil(Dune::index_constant< freeFlowMomentumIndex > domainI, const Element< freeFlowMomentumIndex > &elementI, const SubControlVolume &scvI, Dune::index_constant< j > domainJ) const
The coupling stencil of domain I, i.e. which domain J DOFs the given domain I element's residual depe...
Definition couplingmanager_cvfe.hh:492
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_cvfe.hh:151
static constexpr auto freeFlowMomentumIndex
Definition couplingmanager_cvfe.hh:61
Scalar effectiveViscosity(const Element< freeFlowMomentumIndex > &element, const ElementDiscretization &elemDisc, const typename ElementDiscretization::SubControlVolumeFace &scvf, const bool considerPreviousTimeStep=false) const
Returns the effective viscosity at a given sub control volume face.
Definition couplingmanager_cvfe.hh:321
static constexpr auto pressureIdx
Definition couplingmanager_cvfe.hh:143
Scalar velocityDivergence(const FVElementGeometry< freeFlowMassIndex > &fvGeometry, const IpData &ipData, const bool considerPreviousTimeStep=false) const
Returns the divergence of the velocity at an interpolation point.
Definition couplingmanager_cvfe.hh:465
Scalar density(const Element< freeFlowMomentumIndex > &element, const ElementDiscretization &elemDisc, const typename ElementDiscretization::SubControlVolumeFace &scvf, const bool considerPreviousTimeStep=false) const
Returns the density at a given sub control volume face.
Definition couplingmanager_cvfe.hh:246
VelocityVector elementVelocity(const FVElementGeometry< freeFlowMassIndex > &fvGeometry) const
Returns the velocity at the element center.
Definition couplingmanager_cvfe.hh:419
void assembleMultithreaded(Dune::index_constant< i > domainId, AssembleElementFunc &&assembleElement) const
Execute assembly kernel in parallel.
Definition couplingmanager_cvfe.hh:652
VelocityVector faceVelocity(const Element< freeFlowMassIndex > &element, const SubControlVolumeFace &scvf) const
Returns the velocity at a given sub control volume face.
Definition couplingmanager_cvfe.hh:395
Scalar pressure(const Element< freeFlowMomentumIndex > &element, const ElementDiscretization &elemDisc, const typename ElementDiscretization::SubControlVolumeFace &scvf, const bool considerPreviousTimeStep=false) const
Returns the pressure at a given sub control volume face.
Definition couplingmanager_cvfe.hh:201
void computeColorsForAssembly()
Compute colors for multithreaded assembly.
Definition couplingmanager_cvfe.hh:630
static constexpr auto freeFlowMassIndex
Definition couplingmanager_cvfe.hh:62
VelocityVector velocity(const FVElementGeometry< freeFlowMassIndex > &fvGeometry, const IpData &ipData, const bool considerPreviousTimeStep=false) const
Returns the velocity at an interpolation point.
Definition couplingmanager_cvfe.hh:441
typename ParentType::SolutionVectorStorage SolutionVectorStorage
Definition couplingmanager_cvfe.hh:66
void attachSolution(const SolutionVectorStorage &curSol)
Attach a solution vector stored outside of this class.
Definition multidomain/couplingmanager.hh:331
void setSubProblems(const std::tuple< std::shared_ptr< SubProblems >... > &problems)
set the pointers to the sub problems
Definition multidomain/couplingmanager.hh:296
const Problem< i > & problem(Dune::index_constant< i > domainIdx) const
Return a reference to the sub problem.
Definition multidomain/couplingmanager.hh:318
SubSolutionVector< i > & curSol(Dune::index_constant< i > domainIdx)
the solution vector of the subproblem
Definition multidomain/couplingmanager.hh:347
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:228
CouplingManager()
Default constructor.
Definition multidomain/couplingmanager.hh:70
typename Traits::template TupleOfSharedPtr< SubSolutionVector > SolutionVectorStorage
the type in which the solution vector is stored in the manager
Definition multidomain/couplingmanager.hh:59
Coloring schemes for shared-memory-parallel assembly.
Defines all properties used in Dumux.
Type traits.
Classes representing interpolation point data for control-volume finite element schemes.
Element solution classes and factory functions.
free functions for the evaluation of primary variable gradients inside elements.
free functions for the evaluation of primary variables inside elements.
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
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
PrimaryVariables evalSolutionAtLocalPos(const Element &element, const typename Element::Geometry &geometry, const typename FVElementGeometry::GridGeometry &gridGeometry, const CVFEElementSolution< FVElementGeometry, PrimaryVariables > &elemSol, const typename Element::Geometry::LocalCoordinate &localPos, bool ignoreState=false)
Interpolates a given cvfe element solution at a given local position. Uses the finite element cache o...
Definition evalsolution.hh:172
auto evalGradientsAtLocalPos(const Element &element, const typename Element::Geometry &geometry, const typename FVElementGeometry::GridGeometry &gridGeometry, const CVFEElementSolution< FVElementGeometry, PrimaryVariables > &elemSol, const typename Element::Geometry::LocalCoordinate &localPos, bool ignoreState=false)
Evaluates the gradient of a given CVFE element solution to a given global position.
Definition evalgradients.hh:106
@ element
Definition fieldtype.hh:23
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_cvfe.hh:563
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.
The available discretization methods in Dumux.
The interface of the coupling manager for multi domain problems.
Some useful type traits.
Definition elementinterpolationpointdatacache.hh:21
Definition cvfelocalresidual.hh:25
Definition method.hh:20
constexpr FCDiamond fcdiamond
Definition method.hh:184
constexpr CCTpfa cctpfa
Definition method.hh:174
constexpr PQ1Bubble pq1bubble
Definition method.hh:180
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