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
28#include <dumux/common/concepts/variables_.hh>
31
36
39
42
43#include "typetraits.hh"
44
45namespace Dumux {
46
52template<class Traits>
54: public CouplingManager<Traits>
55{
56 using ParentType = CouplingManager<Traits>;
57public:
58 static constexpr auto freeFlowMomentumIndex = typename Traits::template SubDomain<0>::Index();
59 static constexpr auto freeFlowMassIndex = typename Traits::template SubDomain<1>::Index();
60
61 // this can be used if the coupling manager is used inside a meta-coupling manager (e.g. multi-binary)
62 // to manager the solution vector storage outside this class
64private:
65 template<std::size_t id> using SubDomainTypeTag = typename Traits::template SubDomain<id>::TypeTag;
66 template<std::size_t id> using PrimaryVariables = GetPropType<SubDomainTypeTag<id>, Properties::PrimaryVariables>;
67 template<std::size_t id> using GridGeometry = GetPropType<SubDomainTypeTag<id>, Properties::GridGeometry>;
68 template<std::size_t id> using GridView = typename GridGeometry<id>::GridView;
69 template<std::size_t id> using Element = typename GridView<id>::template Codim<0>::Entity;
70 template<std::size_t id> using ElementSeed = typename GridView<id>::Grid::template Codim<0>::EntitySeed;
71 template<std::size_t id> using FVElementGeometry = typename GridGeometry<id>::LocalView;
72 template<std::size_t id> using SubControlVolume = typename FVElementGeometry<id>::SubControlVolume;
73 template<std::size_t id> using SubControlVolumeFace = typename FVElementGeometry<id>::SubControlVolumeFace;
74 template<std::size_t id> using GridVariables = typename Traits::template SubDomain<id>::GridVariables;
75 template<std::size_t id> using GridVariablesCache = Concept::GridVariablesCache_t<GridVariables<id>>;
76 template<std::size_t id> using ElementVariables = typename GridVariablesCache<id>::LocalView;
77 template<std::size_t id> using Problem = GetPropType<SubDomainTypeTag<id>, Properties::Problem>;
78 template<std::size_t id> using Variables = Concept::Variables_t<GridVariables<id>>;
79
80 using Scalar = typename Traits::Scalar;
81 using SolutionVector = typename Traits::SolutionVector;
82
83 using CouplingStencilType = std::vector<std::size_t>;
84
85 using GridVariablesTuple = typename Traits::template TupleOfSharedPtr<GridVariables>;
86
87 using FluidSystem = typename Variables<freeFlowMassIndex>::FluidSystem;
88
89 using GlobalPosition = typename SubControlVolumeFace<freeFlowMassIndex>::GlobalPosition;
90 using VelocityVector = GlobalPosition;
91 using ShapeValue = typename Dune::FieldVector<Scalar, 1>;
92
93 static_assert(std::is_same_v<VelocityVector, typename SubControlVolumeFace<freeFlowMomentumIndex>::GlobalPosition>);
94
95 template<class ElementSolution>
96 struct MomentumCouplingContextNoCaching
97 {
98 MomentumCouplingContextNoCaching(ElementSolution&& elemSol)
99 : elemSol_(std::move(elemSol)) {}
100
101 template<class GridVarsCache, class FvElementGeometry, class SubControlVolume>
102 auto vars(const GridVarsCache& gridVarsCache, const FvElementGeometry& fvGeometry, const SubControlVolume& scv) const
103 {
104 const auto& problem = gridVarsCache.problem();
105 Variables<freeFlowMassIndex> variables;
106 if constexpr (Concept::FVGridVariables<GridVariables<freeFlowMassIndex>>)
107 variables.update(elemSol_, problem, fvGeometry.element(), scv);
108 else
109 variables.update(elemSol_, problem, fvGeometry, ipData(fvGeometry, scv));
110 return variables;
111 }
112
113 ElementSolution elemSol_;
114 };
115
116 struct MomentumCouplingContextGlobalCaching
117 {
118 template<class GridVarsCache, class FvElementGeometry, class SubControlVolume>
119 const auto& vars(const GridVarsCache& gridVarsCache, const FvElementGeometry& fvGeometry, const SubControlVolume& scv) const
120 {
121 if constexpr (requires { gridVarsCache.volVars(scv); })
122 return gridVarsCache.volVars(scv);
123 else
124 return gridVarsCache.variables(scv);
125 }
126 };
127
128 using MomentumDiscretizationMethod = typename GridGeometry<freeFlowMomentumIndex>::DiscretizationMethod;
129 using MassDiscretizationMethod = typename GridGeometry<freeFlowMassIndex>::DiscretizationMethod;
130
131 template<std::size_t id> using IpData
132 = Dumux::CVFE::InterpolationPointData<typename GridView<id>::template Codim<0>::Entity::Geometry::LocalCoordinate,
133 typename GridView<id>::template Codim<0>::Entity::Geometry::GlobalCoordinate>;
134
135public:
137 static constexpr auto pressureIdx = Variables<freeFlowMassIndex>::Indices::pressureIdx;
138
142 // \{
143
144 //! use as regular coupling manager
145 void init(std::shared_ptr<Problem<freeFlowMomentumIndex>> momentumProblem,
146 std::shared_ptr<Problem<freeFlowMassIndex>> massProblem,
147 GridVariablesTuple&& gridVariables,
148 const SolutionVector& curSol)
149 {
150 this->setSubProblems(std::make_tuple(momentumProblem, massProblem));
151 gridVariables_ = gridVariables;
152 this->updateSolution(curSol);
153 prevSol_ = nullptr;
154
155 computeCouplingStencils_();
156 }
157
158 //! use as regular coupling manager in a transient setting
159 void init(std::shared_ptr<Problem<freeFlowMomentumIndex>> momentumProblem,
160 std::shared_ptr<Problem<freeFlowMassIndex>> massProblem,
161 GridVariablesTuple&& gridVariables,
162 const SolutionVector& curSol,
163 const SolutionVector& prevSol)
164 {
165 init(momentumProblem, massProblem, std::forward<GridVariablesTuple>(gridVariables), curSol);
166 prevSol_ = &prevSol;
167 }
168
169 //! use as binary coupling manager in multi model context
170 void init(std::shared_ptr<Problem<freeFlowMomentumIndex>> momentumProblem,
171 std::shared_ptr<Problem<freeFlowMassIndex>> massProblem,
172 GridVariablesTuple&& gridVariables,
174 {
175 this->setSubProblems(std::make_tuple(momentumProblem, massProblem));
176 gridVariables_ = gridVariables;
177 this->attachSolution(curSol);
178 prevSol_ = nullptr;
179
180 computeCouplingStencils_();
181 }
182
183 // \}
184
188 // \{
189
193 [[deprecated("This method will be removed after release (3.11). Use pressure(..., ipData) instead!")]]
194 Scalar pressure(const Element<freeFlowMomentumIndex>& element,
195 const FVElementGeometry<freeFlowMomentumIndex>& fvGeometry,
196 const SubControlVolumeFace<freeFlowMomentumIndex>& scvf,
197 const bool considerPreviousTimeStep = false) const
198 {
199 const auto& globalPos = scvf.ipGlobal();
200 const auto& localPos = element.geometry().local(globalPos);
201 return this->pressure(element, fvGeometry, IpData<freeFlowMassIndex>(localPos, globalPos), considerPreviousTimeStep);
202 }
203
207 [[deprecated("This method will be removed after release (3.11). Use pressure(..., ipData) instead!")]]
208 Scalar pressure(const Element<freeFlowMomentumIndex>& element,
209 const FVElementGeometry<freeFlowMomentumIndex>& fvGeometry,
210 const SubControlVolume<freeFlowMomentumIndex>& scv,
211 const bool considerPreviousTimeStep = false) const
212 {
213 return this->pressure(element, fvGeometry, ipData(fvGeometry, scv), considerPreviousTimeStep);
214 }
215
219 template <class IpData>
220 Scalar pressure(const Element<freeFlowMomentumIndex>& element,
221 const FVElementGeometry<freeFlowMomentumIndex>& fvGeometry,
222 const IpData& ipData,
223 const bool considerPreviousTimeStep = false) const
224 {
225 assert(!(considerPreviousTimeStep && !isTransient_()));
226 const auto& gg = Deprecated::gridGeometry(this->problem(freeFlowMassIndex));
227 const auto& sol = considerPreviousTimeStep ? (*prevSol_)[freeFlowMassIndex]
228 : this->curSol(freeFlowMassIndex);
229 const auto elemSol = elementSolution(element, sol, gg);
230 return evalSolutionAtLocalPos(element, element.geometry(), gg, elemSol, ipData.local())[pressureIdx];
231 }
232
236 [[deprecated("This method will be removed after release (3.11). Use density(..., ipData) instead!")]]
237 Scalar density(const Element<freeFlowMomentumIndex>& element,
238 const FVElementGeometry<freeFlowMomentumIndex>& fvGeometry,
239 const SubControlVolumeFace<freeFlowMomentumIndex>& scvf,
240 const bool considerPreviousTimeStep = false) const
241 {
242 const auto& globalPos = scvf.ipGlobal();
243 const auto& localPos = element.geometry().local(globalPos);
244 return this->density(element, fvGeometry, IpData<freeFlowMassIndex>(localPos, globalPos), considerPreviousTimeStep);
245 }
246
250 [[deprecated("This method will be removed after release (3.11). Use density(..., ipData) instead!")]]
251 Scalar density(const Element<freeFlowMomentumIndex>& element,
252 const FVElementGeometry<freeFlowMomentumIndex>& fvGeometry,
253 const SubControlVolume<freeFlowMomentumIndex>& scv,
254 const bool considerPreviousTimeStep = false) const
255 {
256 return this->density(element, fvGeometry, ipData(fvGeometry, scv), considerPreviousTimeStep);
257 }
258
262 template <class IpData>
263 Scalar density(const Element<freeFlowMomentumIndex>& element,
264 const FVElementGeometry<freeFlowMomentumIndex>& fvGeometry,
265 const IpData& ipData,
266 const bool considerPreviousTimeStep = false) const
267 {
268 assert(!(considerPreviousTimeStep && !isTransient_()));
269
270 const auto& sol = considerPreviousTimeStep ? (*prevSol_)[freeFlowMassIndex]
271 : this->curSol(freeFlowMassIndex);
272
273 auto massFvGeometry = localView(Deprecated::gridGeometry(this->problem(freeFlowMassIndex)));
274 massFvGeometry.bind(element);
275 const auto context = makeMomentumCouplingContext_(massFvGeometry, sol);
276 const auto& gridVarsCache = subDomainGridVars_(Dune::index_constant<freeFlowMassIndex>{}, considerPreviousTimeStep);
277
278 if constexpr (MassDiscretizationMethod{} == DiscretizationMethods::cctpfa)
279 {
280 const auto eIdx = fvGeometry.elementIndex();
281 const auto& scv = massFvGeometry.scv(eIdx);
282
283 const auto& variables = context.vars(gridVarsCache, massFvGeometry, scv);
284
285 return variables.density();
286 }
287 else if constexpr (MassDiscretizationMethod{} == DiscretizationMethods::box
288 || MassDiscretizationMethod{} == DiscretizationMethods::fcdiamond)
289 {
290 // TODO: cache the shape values
291 using ShapeValue = typename Dune::FieldVector<Scalar, 1>;
292 const auto& localBasis = massFvGeometry.feLocalBasis();
293 std::vector<ShapeValue> shapeValues;
294 localBasis.evaluateFunction(ipData.local(), shapeValues);
295
296 Scalar rho = 0.0;
297 for (const auto& scv : scvs(massFvGeometry))
298 {
299 const auto& variables = context.vars(gridVarsCache, massFvGeometry, scv);
300 rho += variables.density()*shapeValues[scv.localDofIndex()][0];
301 }
302
303 return rho;
304 }
305 else
306 DUNE_THROW(Dune::NotImplemented,
307 "Density interpolation for discretization scheme " << MassDiscretizationMethod{}
308 );
309 }
310
314 [[deprecated("This method will be removed after release (3.11). Use effectiveViscosity(..., ipData) instead!")]]
315 Scalar effectiveViscosity(const Element<freeFlowMomentumIndex>& element,
316 const FVElementGeometry<freeFlowMomentumIndex>& fvGeometry,
317 const SubControlVolumeFace<freeFlowMomentumIndex>& scvf,
318 const bool considerPreviousTimeStep = false) const
319 {
320 const auto& globalPos = scvf.ipGlobal();
321 const auto& localPos = element.geometry().local(globalPos);
322 return this->effectiveViscosity(element, fvGeometry, IpData<freeFlowMassIndex>(localPos, globalPos), considerPreviousTimeStep);
323 }
324
328 [[deprecated("This method will be removed after release (3.11). Use effectiveViscosity(..., ipData) instead!")]]
329 Scalar effectiveViscosity(const Element<freeFlowMomentumIndex>& element,
330 const FVElementGeometry<freeFlowMomentumIndex>& fvGeometry,
331 const SubControlVolume<freeFlowMomentumIndex>& scv,
332 const bool considerPreviousTimeStep = false) const
333 {
334 return this->effectiveViscosity(element, fvGeometry, ipData(fvGeometry, scv), considerPreviousTimeStep);
335 }
336
340 template <class IpData>
341 Scalar effectiveViscosity(const Element<freeFlowMomentumIndex>& element,
342 const FVElementGeometry<freeFlowMomentumIndex>& fvGeometry,
343 const IpData& ipData,
344 const bool considerPreviousTimeStep = false) const
345 {
346 assert(!(considerPreviousTimeStep && !isTransient_()));
347
348 const auto& sol = considerPreviousTimeStep ? (*prevSol_)[freeFlowMassIndex]
349 : this->curSol(freeFlowMassIndex);
350
351 auto massFvGeometry = localView(Deprecated::gridGeometry(this->problem(freeFlowMassIndex)));
352 massFvGeometry.bind(element);
353 const auto context = makeMomentumCouplingContext_(massFvGeometry, sol);
354 const auto& gridVarsCache = subDomainGridVars_(Dune::index_constant<freeFlowMassIndex>{}, considerPreviousTimeStep);
355
356 if constexpr (MassDiscretizationMethod{} == DiscretizationMethods::cctpfa)
357 {
358 const auto eIdx = fvGeometry.elementIndex();
359 const auto& scv = massFvGeometry.scv(eIdx);
360
361 const auto& variables = context.vars(gridVarsCache, massFvGeometry, scv);
362
363 return variables.viscosity();
364 }
365 else if constexpr (MassDiscretizationMethod{} == DiscretizationMethods::box
366 || MassDiscretizationMethod{} == DiscretizationMethods::fcdiamond)
367 {
368 // TODO: cache the shape values
369 using ShapeValue = typename Dune::FieldVector<Scalar, 1>;
370 const auto& localBasis = massFvGeometry.feLocalBasis();
371 std::vector<ShapeValue> shapeValues;
372 localBasis.evaluateFunction(ipData.local(), shapeValues);
373
374 Scalar mu = 0.0;
375 for (const auto& scv : scvs(massFvGeometry))
376 {
377 const auto& variables = context.vars(gridVarsCache, massFvGeometry, scv);
378 mu += variables.viscosity()*shapeValues[scv.localDofIndex()][0];
379 }
380
381 return mu;
382 }
383 else
384 DUNE_THROW(Dune::NotImplemented,
385 "Viscosity interpolation for discretization scheme " << MassDiscretizationMethod{}
386 );
387 }
388
391 */
392 VelocityVector faceVelocity(const Element<freeFlowMassIndex>& element,
393 const SubControlVolumeFace<freeFlowMassIndex>& scvf) const
394 {
395 // TODO: optimize this function for tpfa where the scvf ip coincides with the dof location
396 auto fvGeometry = localView(Deprecated::gridGeometry(this->problem(freeFlowMomentumIndex)));
397 fvGeometry.bindElement(element);
398
399 const auto& localBasis = fvGeometry.feLocalBasis();
400
401 std::vector<ShapeValue> shapeValues;
402 const auto ipLocal = element.geometry().local(scvf.ipGlobal());
403 localBasis.evaluateFunction(ipLocal, shapeValues);
404
405 // interpolate velocity at scvf
406 VelocityVector velocity(0.0);
407 for (const auto& localDof : localDofs(fvGeometry))
408 velocity.axpy(shapeValues[localDof.index()][0], this->curSol(freeFlowMomentumIndex)[localDof.dofIndex()]);
409
410 return velocity;
411 }
412
415 */
416 VelocityVector elementVelocity(const FVElementGeometry<freeFlowMassIndex>& fvGeometry) const
417 {
418 auto momentumFvGeometry = localView(Deprecated::gridGeometry(this->problem(freeFlowMomentumIndex)));
419 momentumFvGeometry.bindElement(fvGeometry.element());
420
421 const auto& localBasis = momentumFvGeometry.feLocalBasis();
422
423 // interpolate velocity at scvf
424 VelocityVector velocity(0.0);
425 std::vector<ShapeValue> shapeValues;
426 localBasis.evaluateFunction(referenceElement(fvGeometry.element()).position(0,0), shapeValues);
427
428 for (const auto& localDof : localDofs(momentumFvGeometry))
429 velocity.axpy(shapeValues[localDof.index()][0], this->curSol(freeFlowMomentumIndex)[localDof.dofIndex()]);
430
431 return velocity;
432 }
433
437 template <class IpData>
438 VelocityVector velocity(const FVElementGeometry<freeFlowMassIndex>& fvGeometry,
439 const IpData& ipData,
440 const bool considerPreviousTimeStep = false) const
441 {
442 assert(!(considerPreviousTimeStep && !isTransient_()));
443
444 const auto& element = fvGeometry.element();
445 const auto& gg = Deprecated::gridGeometry(this->problem(freeFlowMomentumIndex));
446 auto momentumFvGeometry = localView(gg);
447 momentumFvGeometry.bindElement(fvGeometry.element());
448
449 const auto& sol = considerPreviousTimeStep ? (*prevSol_)[freeFlowMomentumIndex]
451
452 const auto elemSol = elementSolution(element, sol, gg);
453 return evalSolutionAtLocalPos(element, element.geometry(), gg, elemSol, ipData.local());
454 }
455
460 template<std::size_t j>
461 const CouplingStencilType& couplingStencil(Dune::index_constant<freeFlowMomentumIndex> domainI,
462 const Element<freeFlowMomentumIndex>& elementI,
463 const SubControlVolume<freeFlowMomentumIndex>& scvI,
464 Dune::index_constant<j> domainJ) const
465 { return emptyStencil_; }
466
480 */
481 const CouplingStencilType& couplingStencil(Dune::index_constant<freeFlowMassIndex> domainI,
482 const Element<freeFlowMassIndex>& elementI,
483 Dune::index_constant<freeFlowMomentumIndex> domainJ) const
484 {
485 const auto eIdx = Deprecated::gridGeometry(this->problem(freeFlowMassIndex)).elementMapper().index(elementI);
486 return massAndEnergyToMomentumStencils_[eIdx];
487 }
488
496 */
497 const CouplingStencilType& couplingStencil(Dune::index_constant<freeFlowMomentumIndex> domainI,
498 const Element<freeFlowMomentumIndex>& elementI,
499 Dune::index_constant<freeFlowMassIndex> domainJ) const
500 {
501 const auto eIdx = Deprecated::gridGeometry(this->problem(freeFlowMomentumIndex)).elementMapper().index(elementI);
502 return momentumToMassAndEnergyStencils_[eIdx];
503 }
504
505 // \}
506
510 // \{
511
531 template<std::size_t i, std::size_t j, class LocalAssemblerI>
532 void updateCouplingContext(Dune::index_constant<i> domainI,
533 const LocalAssemblerI& localAssemblerI,
534 Dune::index_constant<j> domainJ,
535 std::size_t dofIdxGlobalJ,
536 const PrimaryVariables<j>& priVarsJ,
537 int pvIdxJ)
538 {
539 this->curSol(domainJ)[dofIdxGlobalJ][pvIdxJ] = priVarsJ[pvIdxJ];
540
541 if constexpr (GridVariablesCache<freeFlowMassIndex>::cachingEnabled)
542 {
543 if constexpr (MassDiscretizationMethod{} == DiscretizationMethods::cctpfa)
544 {
545 if constexpr (domainI == freeFlowMomentumIndex && domainJ == freeFlowMassIndex)
546 {
547 const auto& problem = this->problem(domainJ);
548 const auto& deflectedElement = Deprecated::gridGeometry(problem).element(dofIdxGlobalJ);
549 const auto elemSol = elementSolution(deflectedElement, this->curSol(domainJ), Deprecated::gridGeometry(problem));
550 auto fvGeometry = localView(Deprecated::gridGeometry(problem));
551 fvGeometry.bind(deflectedElement);
552 const auto& scv = fvGeometry.scv(dofIdxGlobalJ);
553
554 if constexpr (Concept::FVGridVariables<GridVariables<freeFlowMassIndex>>)
555 subDomainVariables_(Dune::index_constant<freeFlowMassIndex>{}, /*current*/true, scv).update(std::move(elemSol), problem, deflectedElement, scv);
556 else
557 subDomainVariables_(Dune::index_constant<freeFlowMassIndex>{}, /*current*/true, ipData(fvGeometry, scv)).update(std::move(elemSol), problem, deflectedElement, scv);
558 }
559 }
560 else if constexpr (MassDiscretizationMethod{} == DiscretizationMethods::box
561 || MassDiscretizationMethod{} == DiscretizationMethods::fcdiamond)
562 {
563 if constexpr (domainI == freeFlowMomentumIndex && domainJ == freeFlowMassIndex)
564 {
565 const auto& problem = this->problem(domainJ);
566 const auto deflectedElementIdx = Deprecated::gridGeometry(problem).elementMapper().index(localAssemblerI.element());
567 const auto& deflectedElement = Deprecated::gridGeometry(problem).element(deflectedElementIdx);
568 const auto elemSol = elementSolution(deflectedElement, this->curSol(domainJ), Deprecated::gridGeometry(problem));
569 auto fvGeometry = localView(Deprecated::gridGeometry(problem));
570 fvGeometry.bind(deflectedElement);
571
572 // ToDo: Replace once all mass models are also working with local dofs
573 for (const auto& scv : scvs(fvGeometry))
574 {
575 if (scv.dofIndex() == dofIdxGlobalJ)
576 {
577 if constexpr (Concept::FVGridVariables<GridVariables<freeFlowMassIndex>>)
578 this->subDomainVariables_(Dune::index_constant<freeFlowMassIndex>{}, /*current*/true, scv).update(std::move(elemSol), problem, deflectedElement, scv);
579 else
580 this->subDomainVariables_(Dune::index_constant<freeFlowMassIndex>{}, /*current*/true, scv).update(std::move(elemSol), problem, fvGeometry, ipData(fvGeometry, scv));
581 }
582 }
583 }
584 }
585 else
586 DUNE_THROW(Dune::NotImplemented,
587 "Context update for discretization scheme " << MassDiscretizationMethod{}
588 );
589 }
590 }
591
592 // \}
593
596 */
598 {
599 if constexpr (MomentumDiscretizationMethod{} == DiscretizationMethods::fcdiamond)
600 {
601 // use coloring of the mass discretization for both domains
602 // the diamond coloring is a subset (minimum amount of colors) of cctpfa/box coloring
603 elementSets_ = computeColoring(Deprecated::gridGeometry(this->problem(freeFlowMassIndex))).sets;
604 }
605 else
606 {
607 // use coloring of the momentum discretization for both domains
608 elementSets_ = computeColoring(Deprecated::gridGeometry(this->problem(freeFlowMomentumIndex))).sets;
609 }
610 }
611
618 template<std::size_t i, class AssembleElementFunc>
619 void assembleMultithreaded(Dune::index_constant<i> domainId, AssembleElementFunc&& assembleElement) const
620 {
621 if (elementSets_.empty())
622 DUNE_THROW(Dune::InvalidStateException, "Call computeColorsForAssembly before assembling in parallel!");
623
624 // make this element loop run in parallel
625 // for this we have to color the elements so that we don't get
626 // race conditions when writing into the global matrix
627 // each color can be assembled using multiple threads
628 const auto& grid = Deprecated::gridGeometry(this->problem(freeFlowMassIndex)).gridView().grid();
629 for (const auto& elements : elementSets_)
630 {
631 Dumux::parallelFor(elements.size(), [&](const std::size_t eIdx)
632 {
633 const auto element = grid.entity(elements[eIdx]);
634 assembleElement(element);
635 });
636 }
637 }
638
639private:
640 template<std::size_t i>
641 const auto& subDomainGridVars_(Dune::index_constant<i> domainIdx, bool current) const
642 {
643 if constexpr (Concept::FVGridVariables<GridVariables<i>>)
644 return current ? gridVars_(domainIdx).curGridVolVars()
645 : gridVars_(domainIdx).prevGridVolVars();
646 else
647 return current ? gridVars_(domainIdx).curGridVars()
648 : gridVars_(domainIdx).prevGridVars();
649 }
650
651 template<std::size_t i>
652 auto& subDomainGridVars_(Dune::index_constant<i> domainIdx, bool current)
653 {
654 if constexpr (Concept::FVGridVariables<GridVariables<i>>)
655 return current ? gridVars_(domainIdx).curGridVolVars()
656 : gridVars_(domainIdx).prevGridVolVars();
657 else
658 return current ? gridVars_(domainIdx).curGridVars()
659 : gridVars_(domainIdx).prevGridVars();
660 }
661
662 template<std::size_t i, class Scv>
663 auto& subDomainVariables_(Dune::index_constant<i> domainIdx, bool current, const Scv& scv)
664 {
665 if constexpr (Concept::FVGridVariables<GridVariables<i>>)
666 return subDomainGridVars_(domainIdx, current).volVars(scv);
667 else
668 return subDomainGridVars_(domainIdx, current).variables(scv);
669 }
670
671 template<std::size_t i, class Scv>
672 const auto& subDomainVariables_(Dune::index_constant<i> domainIdx, bool current, const Scv& scv) const
673 {
674 if constexpr (Concept::FVGridVariables<GridVariables<i>>)
675 return subDomainGridVars_(domainIdx, current).volVars(scv);
676 else
677 return subDomainGridVars_(domainIdx, current).variables(scv);
678 }
679
680 template<class SolutionVector>
681 auto makeMomentumCouplingContext_(const FVElementGeometry<freeFlowMassIndex>& fvGeometry,
682 const SolutionVector& sol) const
683 {
684 if constexpr (GridVariablesCache<freeFlowMassIndex>::cachingEnabled)
685 return MomentumCouplingContextGlobalCaching{};
686 else
687 return MomentumCouplingContextNoCaching{elementSolution(fvGeometry.element(), sol, Deprecated::gridGeometry(fvGeometry))};
688 }
689
694 template<std::size_t i>
695 const GridVariables<i>& gridVars_(Dune::index_constant<i> domainIdx) const
696 {
697 if (std::get<i>(gridVariables_))
698 return *std::get<i>(gridVariables_);
699 else
700 DUNE_THROW(Dune::InvalidStateException, "The gridVariables pointer was not set. Use setGridVariables() before calling this function");
701 }
702
707 template<std::size_t i>
708 GridVariables<i>& gridVars_(Dune::index_constant<i> domainIdx)
709 {
710 if (std::get<i>(gridVariables_))
711 return *std::get<i>(gridVariables_);
712 else
713 DUNE_THROW(Dune::InvalidStateException, "The gridVariables pointer was not set. Use setGridVariables() before calling this function");
714 }
715
716 void computeCouplingStencils_()
717 {
718 const auto& momentumGridGeometry = Deprecated::gridGeometry(this->problem(freeFlowMomentumIndex));
719 const auto& massGridGeometry = Deprecated::gridGeometry(this->problem(freeFlowMassIndex));
720 auto momentumFvGeometry = localView(momentumGridGeometry);
721 auto massFvGeometry = localView(massGridGeometry);
722
723 massAndEnergyToMomentumStencils_.clear();
724 massAndEnergyToMomentumStencils_.resize(massGridGeometry.gridView().size(0));
725
726 momentumToMassAndEnergyStencils_.clear();
727 momentumToMassAndEnergyStencils_.resize(momentumGridGeometry.gridView().size(0));
728
729 assert(massAndEnergyToMomentumStencils_.size() == momentumToMassAndEnergyStencils_.size());
730 bool hasCubeElements = false;
731
732 for (const auto& element : elements(momentumGridGeometry.gridView()))
733 {
734 if(element.type().isCube())
735 hasCubeElements = true;
736
737 momentumFvGeometry.bindElement(element);
738 massFvGeometry.bindElement(element);
739 const auto eIdx = momentumFvGeometry.elementIndex();
740
741 for (const auto& localDof : localDofs(momentumFvGeometry))
742 massAndEnergyToMomentumStencils_[eIdx].push_back(localDof.dofIndex());
743
744 // ToDo: Replace once all mass models are also working with local dofs
745 for (const auto& scv : scvs(massFvGeometry))
746 momentumToMassAndEnergyStencils_[eIdx].push_back(scv.dofIndex());
747 }
748
749 // Print warning for pq1bubble scheme on cube elements if not using the hybrid variant
750 if constexpr ((MomentumDiscretizationMethod{} == DiscretizationMethods::pq1bubble))
751 {
752 if(hasCubeElements && !GridGeometry<freeFlowMomentumIndex>::enableHybridCVFE)
753 {
754 std::cerr << "Warning: Coupled Navier-Stokes problem on cube elements uses non-hybrid pq1bubble. "
755 << "The hybrid variant is recommended because it implements two bubble functions for stability reasons."
756 << std::endl;
757 }
758 }
759 }
760
761 CouplingStencilType emptyStencil_;
762 std::vector<CouplingStencilType> momentumToMassAndEnergyStencils_;
763 std::vector<CouplingStencilType> massAndEnergyToMomentumStencils_;
764
766 GridVariablesTuple gridVariables_;
767
769 bool isTransient_() const
770 { return prevSol_ != nullptr; }
771
772 const SolutionVector* prevSol_ = nullptr;
773
774 std::deque<std::vector<ElementSeed<freeFlowMomentumIndex>>> elementSets_;
775};
776
777namespace Detail {
778
779// declaration (specialize for different discretization types)
780template<class Traits, class DiscretizationMethod = typename Detail::MomentumDiscretizationMethod<Traits>::type>
782
783// multi-threading is not supported because we have only one coupling context instance and a mutable cache
784template<class Traits, class D>
787
788} // end namespace Detail
789
791template<class T>
795
796} // end namespace Dumux
797
798#endif
The interface of the coupling manager for free flow systems.
Definition couplingmanager_cvfe.hh:55
VelocityVector faceVelocity(const Element< freeFlowMassIndex > &element, const SubControlVolumeFace< freeFlowMassIndex > &scvf) const
Returns the velocity at a given sub control volume face.
Definition couplingmanager_cvfe.hh:391
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:144
static constexpr auto freeFlowMomentumIndex
Definition couplingmanager_cvfe.hh:58
static constexpr auto pressureIdx
Definition couplingmanager_cvfe.hh:136
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_cvfe.hh:236
Scalar effectiveViscosity(const Element< freeFlowMomentumIndex > &element, const FVElementGeometry< freeFlowMomentumIndex > &fvGeometry, const SubControlVolumeFace< freeFlowMomentumIndex > &scvf, const bool considerPreviousTimeStep=false) const
Returns the effective viscosity at a given sub control volume face.
Definition couplingmanager_cvfe.hh:314
VelocityVector elementVelocity(const FVElementGeometry< freeFlowMassIndex > &fvGeometry) const
Returns the velocity at the element center.
Definition couplingmanager_cvfe.hh:415
void assembleMultithreaded(Dune::index_constant< i > domainId, AssembleElementFunc &&assembleElement) const
Execute assembly kernel in parallel.
Definition couplingmanager_cvfe.hh:618
Scalar pressure(const Element< freeFlowMomentumIndex > &element, const FVElementGeometry< freeFlowMomentumIndex > &fvGeometry, const SubControlVolumeFace< freeFlowMomentumIndex > &scvf, const bool considerPreviousTimeStep=false) const
Returns the pressure at a given sub control volume face.
Definition couplingmanager_cvfe.hh:193
void computeColorsForAssembly()
Compute colors for multithreaded assembly.
Definition couplingmanager_cvfe.hh:596
static constexpr auto freeFlowMassIndex
Definition couplingmanager_cvfe.hh:59
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:437
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 element's residual depe...
Definition couplingmanager_cvfe.hh:460
typename ParentType::SolutionVectorStorage SolutionVectorStorage
Definition couplingmanager_cvfe.hh:63
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.
Helpers for deprecation.
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
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:173
@ 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:531
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
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.
A linear system assembler (residual and Jacobian) for finite volume schemes with multiple domains.
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 multistagemultidomainfvassembler.hh:78