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 // finite element discretizations have local dofs but no sub-control volumes
593 else if constexpr (!requires (FVElementGeometry<freeFlowMassIndex>& lv) { scvs(lv); })
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 this->subDomainVariables_(
608 Dune::index_constant<freeFlowMassIndex>{}, /*current*/true, localDof
609 ).update(std::move(elemSol), problem, fvGeometry, ipData(fvGeometry, localDof));
610 }
611 }
612 }
613 else if constexpr (MassDiscretizationMethod{} == DiscretizationMethods::box
614 || MassDiscretizationMethod{} == DiscretizationMethods::fcdiamond)
615 {
616 if constexpr (domainI == freeFlowMomentumIndex && domainJ == freeFlowMassIndex)
617 {
618 const auto& problem = this->problem(domainJ);
619 const auto deflectedElementIdx = Dumux::gridDiscretization(problem).elementMapper().index(localAssemblerI.element());
620 const auto& deflectedElement = Dumux::gridDiscretization(problem).element(deflectedElementIdx);
621 const auto elemSol = elementSolution(deflectedElement, this->curSol(domainJ), Dumux::gridDiscretization(problem));
622 auto fvGeometry = localView(Dumux::gridDiscretization(problem));
623 fvGeometry.bind(deflectedElement);
624
625 // ToDo: Replace once all mass models are also working with local dofs
626 for (const auto& scv : scvs(fvGeometry))
627 {
628 if (scv.dofIndex() == dofIdxGlobalJ)
629 {
630 if constexpr (Concept::FVGridVariables<GridVariables<freeFlowMassIndex>>)
631 this->subDomainVariables_(Dune::index_constant<freeFlowMassIndex>{}, /*current*/true, scv).update(std::move(elemSol), problem, deflectedElement, scv);
632 else
633 this->subDomainVariables_(Dune::index_constant<freeFlowMassIndex>{}, /*current*/true, scv).update(std::move(elemSol), problem, fvGeometry, ipData(fvGeometry, scv));
634 }
635 }
636 }
637 }
638 else
639 DUNE_THROW(Dune::NotImplemented,
640 "Context update for discretization scheme " << MassDiscretizationMethod{}
641 );
642 }
643 }
644
645 // \}
646
649 */
651 {
652 if constexpr (MomentumDiscretizationMethod{} == DiscretizationMethods::fcdiamond)
653 {
654 // use coloring of the mass discretization for both domains
655 // the diamond coloring is a subset (minimum amount of colors) of cctpfa/box coloring
657 }
658 else
659 {
660 // use coloring of the momentum discretization for both domains
662 }
663 }
664
671 template<std::size_t i, class AssembleElementFunc>
672 void assembleMultithreaded(Dune::index_constant<i> domainId, AssembleElementFunc&& assembleElement) const
673 {
674 if (elementSets_.empty())
675 DUNE_THROW(Dune::InvalidStateException, "Call computeColorsForAssembly before assembling in parallel!");
676
677 // make this element loop run in parallel
678 // for this we have to color the elements so that we don't get
679 // race conditions when writing into the global matrix
680 // each color can be assembled using multiple threads
681 const auto& grid = Dumux::gridDiscretization(this->problem(freeFlowMassIndex)).gridView().grid();
682 for (const auto& elements : elementSets_)
683 {
684 Dumux::parallelFor(elements.size(), [&](const std::size_t eIdx)
685 {
686 const auto element = grid.entity(elements[eIdx]);
687 assembleElement(element);
688 });
689 }
690 }
691
692private:
693 template<std::size_t i>
694 const auto& subDomainGridVars_(Dune::index_constant<i> domainIdx, bool current) const
695 {
696 if constexpr (Concept::FVGridVariables<GridVariables<i>>)
697 return current ? gridVars_(domainIdx).curGridVolVars()
698 : gridVars_(domainIdx).prevGridVolVars();
699 else
700 return current ? gridVars_(domainIdx).curGridVars()
701 : gridVars_(domainIdx).prevGridVars();
702 }
703
704 template<std::size_t i>
705 auto& subDomainGridVars_(Dune::index_constant<i> domainIdx, bool current)
706 {
707 if constexpr (Concept::FVGridVariables<GridVariables<i>>)
708 return current ? gridVars_(domainIdx).curGridVolVars()
709 : gridVars_(domainIdx).prevGridVolVars();
710 else
711 return current ? gridVars_(domainIdx).curGridVars()
712 : gridVars_(domainIdx).prevGridVars();
713 }
714
715 template<std::size_t i, class Scv>
716 auto& subDomainVariables_(Dune::index_constant<i> domainIdx, bool current, const Scv& scv)
717 {
718 if constexpr (Concept::FVGridVariables<GridVariables<i>>)
719 return subDomainGridVars_(domainIdx, current).volVars(scv);
720 else
721 return subDomainGridVars_(domainIdx, current).variables(scv);
722 }
723
724 template<std::size_t i, class Scv>
725 const auto& subDomainVariables_(Dune::index_constant<i> domainIdx, bool current, const Scv& scv) const
726 {
727 if constexpr (Concept::FVGridVariables<GridVariables<i>>)
728 return subDomainGridVars_(domainIdx, current).volVars(scv);
729 else
730 return subDomainGridVars_(domainIdx, current).variables(scv);
731 }
732
733 template<class SolutionVector>
734 auto makeMomentumCouplingContext_(const FVElementGeometry<freeFlowMassIndex>& fvGeometry,
735 const SolutionVector& sol) const
736 {
737 if constexpr (GridVariablesCache<freeFlowMassIndex>::cachingEnabled)
738 return MomentumCouplingContextGlobalCaching{};
739 else
740 return MomentumCouplingContextNoCaching{elementSolution(fvGeometry.element(), sol, Dumux::gridDiscretization(fvGeometry))};
741 }
742
747 template<std::size_t i>
748 const GridVariables<i>& gridVars_(Dune::index_constant<i> domainIdx) const
749 {
750 if (std::get<i>(gridVariables_))
751 return *std::get<i>(gridVariables_);
752 else
753 DUNE_THROW(Dune::InvalidStateException, "The gridVariables pointer was not set. Use setGridVariables() before calling this function");
754 }
755
760 template<std::size_t i>
761 GridVariables<i>& gridVars_(Dune::index_constant<i> domainIdx)
762 {
763 if (std::get<i>(gridVariables_))
764 return *std::get<i>(gridVariables_);
765 else
766 DUNE_THROW(Dune::InvalidStateException, "The gridVariables pointer was not set. Use setGridVariables() before calling this function");
767 }
768
769 void computeCouplingStencils_()
770 {
771 const auto& momentumGridGeometry = Dumux::gridDiscretization(this->problem(freeFlowMomentumIndex));
772 const auto& massGridGeometry = Dumux::gridDiscretization(this->problem(freeFlowMassIndex));
773 auto momentumFvGeometry = localView(momentumGridGeometry);
774 auto massFvGeometry = localView(massGridGeometry);
775
776 massAndEnergyToMomentumStencils_.clear();
777 massAndEnergyToMomentumStencils_.resize(massGridGeometry.gridView().size(0));
778
779 momentumToMassAndEnergyStencils_.clear();
780 momentumToMassAndEnergyStencils_.resize(momentumGridGeometry.gridView().size(0));
781
782 assert(massAndEnergyToMomentumStencils_.size() == momentumToMassAndEnergyStencils_.size());
783 bool hasCubeElements = false;
784
785 for (const auto& element : elements(momentumGridGeometry.gridView()))
786 {
787 if(element.type().isCube())
788 hasCubeElements = true;
789
790 momentumFvGeometry.bindElement(element);
791 massFvGeometry.bindElement(element);
792 const auto eIdx = momentumFvGeometry.elementIndex();
793
794 for (const auto& localDof : localDofs(momentumFvGeometry))
795 massAndEnergyToMomentumStencils_[eIdx].push_back(localDof.dofIndex());
796
797 for (const auto& localDof : localDofs(massFvGeometry))
798 momentumToMassAndEnergyStencils_[eIdx].push_back(localDof.dofIndex());
799 }
800
801 // Print warning for pq1bubble scheme on cube elements if not using the hybrid variant
802 if constexpr ((MomentumDiscretizationMethod{} == DiscretizationMethods::pq1bubble))
803 {
804 if(hasCubeElements && !GridGeometry<freeFlowMomentumIndex>::enableHybridCVFE)
805 {
806 std::cerr << "Warning: Coupled Navier-Stokes problem on cube elements uses non-hybrid pq1bubble. "
807 << "The hybrid variant is recommended because it implements two bubble functions for stability reasons."
808 << std::endl;
809 }
810 }
811 }
812
813 CouplingStencilType emptyStencil_;
814 std::vector<CouplingStencilType> momentumToMassAndEnergyStencils_;
815 std::vector<CouplingStencilType> massAndEnergyToMomentumStencils_;
816
818 GridVariablesTuple gridVariables_;
819
821 bool isTransient_() const
822 { return prevSol_ != nullptr; }
823
824 const SolutionVector* prevSol_ = nullptr;
825
826 std::deque<std::vector<ElementSeed<freeFlowMomentumIndex>>> elementSets_;
827};
828
829namespace Detail {
830
831// declaration (specialize for different discretization types)
832template<class Traits, class DiscretizationMethod = typename Detail::MomentumDiscretizationMethod<Traits>::type>
834
835// multi-threading is not supported because we have only one coupling context instance and a mutable cache
836template<class Traits, class D>
839
840} // end namespace Detail
841
843template<class T>
847
848} // end namespace Dumux
849
850#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:671
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:649
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 variablesadapter.hh:17
Definition cvfelocalresidual.hh:25
Definition method.hh:20
constexpr FCDiamond fcdiamond
Definition method.hh:184
constexpr CCTpfa cctpfa
Definition method.hh:174
constexpr Box box
Definition method.hh:176
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
std::ranges::range auto scvs(const FVElementGeometry &fvGeometry, const LocalDof &localDof)
Definition localdof.hh:82
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