Line | Branch | Exec | Source |
---|---|---|---|
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 | // | ||
7 | /*! | ||
8 | * \file | ||
9 | * \ingroup MultiDomain | ||
10 | * \brief Freeflow coupling managers (Navier-Stokes mass-momentum coupling) | ||
11 | */ | ||
12 | #ifndef DUMUX_MULTIDOMAIN_FREEFLOW_COUPLING_MANAGER_STAGGERED_HH | ||
13 | #define DUMUX_MULTIDOMAIN_FREEFLOW_COUPLING_MANAGER_STAGGERED_HH | ||
14 | |||
15 | #include <memory> | ||
16 | #include <tuple> | ||
17 | #include <vector> | ||
18 | #include <deque> | ||
19 | |||
20 | #include <dune/common/exceptions.hh> | ||
21 | #include <dune/common/indices.hh> | ||
22 | #include <dune/common/float_cmp.hh> | ||
23 | |||
24 | #include <dumux/common/properties.hh> | ||
25 | #include <dumux/common/typetraits/typetraits.hh> | ||
26 | |||
27 | #include <dumux/discretization/method.hh> | ||
28 | #include <dumux/discretization/evalsolution.hh> | ||
29 | #include <dumux/discretization/elementsolution.hh> | ||
30 | |||
31 | #include <dumux/multidomain/couplingmanager.hh> | ||
32 | #include <dumux/multidomain/fvassembler.hh> | ||
33 | #include <dumux/discretization/facecentered/staggered/consistentlyorientedgrid.hh> | ||
34 | |||
35 | #include <dumux/parallel/parallel_for.hh> | ||
36 | #include <dumux/assembly/coloring.hh> | ||
37 | |||
38 | namespace Dumux { | ||
39 | |||
40 | /*! | ||
41 | * \ingroup MultiDomain | ||
42 | * \brief The interface of the coupling manager for free flow systems | ||
43 | * \note coupling manager the face-centered staggered discretization scheme | ||
44 | */ | ||
45 | template<class Traits> | ||
46 | class FCStaggeredFreeFlowCouplingManager | ||
47 | : public CouplingManager<Traits> | ||
48 | { | ||
49 | using ParentType = CouplingManager<Traits>; | ||
50 | public: | ||
51 | static constexpr auto freeFlowMomentumIndex = typename Traits::template SubDomain<0>::Index(); | ||
52 | static constexpr auto freeFlowMassIndex = typename Traits::template SubDomain<1>::Index(); | ||
53 | |||
54 | // this can be used if the coupling manager is used inside a meta-coupling manager (e.g. multi-binary) | ||
55 | // to manager the solution vector storage outside this class | ||
56 | using SolutionVectorStorage = typename ParentType::SolutionVectorStorage; | ||
57 | private: | ||
58 | template<std::size_t id> using SubDomainTypeTag = typename Traits::template SubDomain<id>::TypeTag; | ||
59 | template<std::size_t id> using PrimaryVariables = GetPropType<SubDomainTypeTag<id>, Properties::PrimaryVariables>; | ||
60 | template<std::size_t id> using GridGeometry = GetPropType<SubDomainTypeTag<id>, Properties::GridGeometry>; | ||
61 | template<std::size_t id> using GridView = typename GridGeometry<id>::GridView; | ||
62 | template<std::size_t id> using Element = typename GridView<id>::template Codim<0>::Entity; | ||
63 | template<std::size_t id> using ElementSeed = typename GridView<id>::Grid::template Codim<0>::EntitySeed; | ||
64 | template<std::size_t id> using FVElementGeometry = typename GridGeometry<id>::LocalView; | ||
65 | template<std::size_t id> using SubControlVolume = typename FVElementGeometry<id>::SubControlVolume; | ||
66 | template<std::size_t id> using SubControlVolumeFace = typename FVElementGeometry<id>::SubControlVolumeFace; | ||
67 | template<std::size_t id> using GridVariables = typename Traits::template SubDomain<id>::GridVariables; | ||
68 | template<std::size_t id> using ElementVolumeVariables = typename GridVariables<id>::GridVolumeVariables::LocalView; | ||
69 | template<std::size_t id> using GridFluxVariablesCache = typename GridVariables<id>::GridFluxVariablesCache; | ||
70 | template<std::size_t id> using Problem = GetPropType<SubDomainTypeTag<id>, Properties::Problem>; | ||
71 | template<std::size_t id> using VolumeVariables = GetPropType<SubDomainTypeTag<id>, Properties::VolumeVariables>; | ||
72 | |||
73 | using Scalar = typename Traits::Scalar; | ||
74 | using SolutionVector = typename Traits::SolutionVector; | ||
75 | |||
76 | template<std::size_t id> | ||
77 | using SubSolutionVector | ||
78 | = std::decay_t<decltype(std::declval<SolutionVector>()[Dune::index_constant<id>()])>; | ||
79 | |||
80 | template<std::size_t id> | ||
81 | using ConstSubSolutionVectorPtr = const SubSolutionVector<id>*; | ||
82 | |||
83 | using PrevSolutionVectorStorage = typename Traits::template Tuple<ConstSubSolutionVectorPtr>; | ||
84 | |||
85 | using CouplingStencilType = std::vector<std::size_t>; | ||
86 | |||
87 | using GridVariablesTuple = typename Traits::template TupleOfSharedPtr<GridVariables>; | ||
88 | |||
89 | using FluidSystem = typename VolumeVariables<freeFlowMassIndex>::FluidSystem; | ||
90 | |||
91 | using VelocityVector = typename SubControlVolumeFace<freeFlowMassIndex>::GlobalPosition; | ||
92 | static_assert(std::is_same_v<VelocityVector, typename SubControlVolumeFace<freeFlowMomentumIndex>::GlobalPosition>); | ||
93 | |||
94 | struct MomentumCouplingContext | ||
95 | { | ||
96 | FVElementGeometry<freeFlowMassIndex> fvGeometry; | ||
97 | ElementVolumeVariables<freeFlowMassIndex> curElemVolVars; | ||
98 | ElementVolumeVariables<freeFlowMassIndex> prevElemVolVars; | ||
99 | std::size_t eIdx; | ||
100 | }; | ||
101 | |||
102 | ✗ | struct MassAndEnergyCouplingContext | |
103 | { | ||
104 | 66 | MassAndEnergyCouplingContext(FVElementGeometry<freeFlowMomentumIndex>&& f, const std::size_t i) | |
105 | 66 | : fvGeometry(std::move(f)) | |
106 | 66 | , eIdx(i) | |
107 | {} | ||
108 | |||
109 | FVElementGeometry<freeFlowMomentumIndex> fvGeometry; | ||
110 | std::size_t eIdx; | ||
111 | }; | ||
112 | |||
113 | public: | ||
114 | |||
115 | static constexpr auto pressureIdx = VolumeVariables<freeFlowMassIndex>::Indices::pressureIdx; | ||
116 | |||
117 | /*! | ||
118 | * \brief Methods to be accessed by main | ||
119 | */ | ||
120 | // \{ | ||
121 | |||
122 | //! use as regular coupling manager | ||
123 | 45 | void init(std::shared_ptr<Problem<freeFlowMomentumIndex>> momentumProblem, | |
124 | std::shared_ptr<Problem<freeFlowMassIndex>> massProblem, | ||
125 | GridVariablesTuple&& gridVariables, | ||
126 | const SolutionVector& curSol) | ||
127 | { | ||
128 | 90 | this->momentumCouplingContext_().clear(); | |
129 | 90 | this->massAndEnergyCouplingContext_().clear(); | |
130 | |||
131 | 90 | this->setSubProblems(std::make_tuple(momentumProblem, massProblem)); | |
132 | 45 | gridVariables_ = gridVariables; | |
133 | 45 | this->updateSolution(curSol); | |
134 | |||
135 | 45 | computeCouplingStencils_(); | |
136 | 45 | } | |
137 | |||
138 | //! use as regular coupling manager in a transient setting | ||
139 | 23 | void init(std::shared_ptr<Problem<freeFlowMomentumIndex>> momentumProblem, | |
140 | std::shared_ptr<Problem<freeFlowMassIndex>> massProblem, | ||
141 | GridVariablesTuple&& gridVariables, | ||
142 | const SolutionVector& curSol, | ||
143 | const SolutionVector& prevSol) | ||
144 | { | ||
145 |
2/6✓ Branch 2 taken 23 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 23 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
|
46 | init(momentumProblem, massProblem, std::forward<GridVariablesTuple>(gridVariables), curSol); |
146 | |||
147 | 23 | Dune::Hybrid::forEach(std::make_index_sequence<Traits::numSubDomains>{}, [&](auto i) | |
148 | 23 | { std::get<i>(prevSolutions_) = &prevSol[i]; }); | |
149 | 23 | } | |
150 | |||
151 | //! use as binary coupling manager in multi model context | ||
152 | 21 | void init(std::shared_ptr<Problem<freeFlowMomentumIndex>> momentumProblem, | |
153 | std::shared_ptr<Problem<freeFlowMassIndex>> massProblem, | ||
154 | GridVariablesTuple&& gridVariables, | ||
155 | const typename ParentType::SolutionVectorStorage& curSol) | ||
156 | { | ||
157 | 42 | this->momentumCouplingContext_().clear(); | |
158 | 42 | this->massAndEnergyCouplingContext_().clear(); | |
159 | |||
160 | 42 | this->setSubProblems(std::make_tuple(momentumProblem, massProblem)); | |
161 | 21 | gridVariables_ = gridVariables; | |
162 | 21 | this->attachSolution(curSol); | |
163 | |||
164 | 21 | computeCouplingStencils_(); | |
165 | 21 | } | |
166 | |||
167 | //! use as binary coupling manager in multi model context and for transient problems | ||
168 | 5 | void init(std::shared_ptr<Problem<freeFlowMomentumIndex>> momentumProblem, | |
169 | std::shared_ptr<Problem<freeFlowMassIndex>> massProblem, | ||
170 | GridVariablesTuple&& gridVariables, | ||
171 | const typename ParentType::SolutionVectorStorage& curSol, | ||
172 | const PrevSolutionVectorStorage& prevSol) | ||
173 | { | ||
174 |
2/6✓ Branch 2 taken 5 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 5 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
|
10 | init(momentumProblem, massProblem, std::forward<GridVariablesTuple>(gridVariables), curSol); |
175 | 5 | prevSolutions_ = prevSol; | |
176 | 5 | } | |
177 | |||
178 | // \} | ||
179 | |||
180 | using CouplingManager<Traits>::evalCouplingResidual; | ||
181 | |||
182 | /*! | ||
183 | * \brief evaluates the element residual of a coupled element of domain i which depends on the variables | ||
184 | * at the degree of freedom with index dofIdxGlobalJ of domain j | ||
185 | * | ||
186 | * \param domainI the domain index of domain i | ||
187 | * \param localAssemblerI the local assembler assembling the element residual of an element of domain i | ||
188 | * \param scvI the sub-control-volume of domain i | ||
189 | * \param domainJ the domain index of domain j | ||
190 | * \param dofIdxGlobalJ the index of the degree of freedom of domain j which has an influence on the element residual of domain i | ||
191 | * | ||
192 | * \note the element whose residual is to be evaluated can be retrieved from the local assembler | ||
193 | * as localAssemblerI.element() as well as all up-to-date variables and caches. | ||
194 | * \note the default implementation evaluates the complete element residual | ||
195 | * if only parts (i.e. only certain scvs, or only certain terms of the residual) of the residual are coupled | ||
196 | * to dof with index dofIdxGlobalJ the function can be overloaded in the coupling manager | ||
197 | * \return the element residual | ||
198 | */ | ||
199 | template<std::size_t j, class LocalAssemblerI> | ||
200 | 26774876 | decltype(auto) evalCouplingResidual(Dune::index_constant<freeFlowMomentumIndex> domainI, | |
201 | const LocalAssemblerI& localAssemblerI, | ||
202 | const SubControlVolume<freeFlowMomentumIndex>& scvI, | ||
203 | Dune::index_constant<j> domainJ, | ||
204 | std::size_t dofIdxGlobalJ) const | ||
205 | { | ||
206 | 26774876 | const auto& problem = localAssemblerI.problem(); | |
207 | 26774876 | const auto& element = localAssemblerI.element(); | |
208 | 26774876 | const auto& fvGeometry = localAssemblerI.fvGeometry(); | |
209 | 26774876 | const auto& curElemVolVars = localAssemblerI.curElemVolVars(); | |
210 | 26774876 | const auto& prevElemVolVars = localAssemblerI.prevElemVolVars(); | |
211 | 26831452 | typename LocalAssemblerI::ElementResidualVector residual(localAssemblerI.element().subEntities(1)); | |
212 | 26774876 | const auto& localResidual = localAssemblerI.localResidual(); | |
213 | |||
214 | 26774876 | localResidual.evalSource(residual, problem, element, fvGeometry, curElemVolVars, scvI); | |
215 | |||
216 |
2/2✓ Branch 2 taken 81195952 times.
✓ Branch 3 taken 26774876 times.
|
189166780 | for (const auto& scvf : scvfs(fvGeometry, scvI)) |
217 | 81195952 | localResidual.evalFlux(residual, problem, element, fvGeometry, curElemVolVars, localAssemblerI.elemBcTypes(), localAssemblerI.elemFluxVarsCache(), scvf); | |
218 | |||
219 |
2/2✓ Branch 0 taken 19166600 times.
✓ Branch 1 taken 7608276 times.
|
26774876 | if (!localAssemblerI.assembler().isStationaryProblem()) |
220 | { | ||
221 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 19166600 times.
|
19166600 | assert(isTransient_()); |
222 | 19166600 | localResidual.evalStorage(residual, problem, element, fvGeometry, prevElemVolVars, curElemVolVars, scvI); | |
223 | } | ||
224 | |||
225 | 26774876 | return residual; | |
226 | } | ||
227 | |||
228 | /*! | ||
229 | * \name member functions concerning the coupling stencils | ||
230 | */ | ||
231 | // \{ | ||
232 | |||
233 | /*! | ||
234 | * \brief Returns the pressure at a given _frontal_ sub control volume face. | ||
235 | */ | ||
236 |
1/2✓ Branch 0 taken 103819484 times.
✗ Branch 1 not taken.
|
103819484 | Scalar pressure(const Element<freeFlowMomentumIndex>& element, |
237 | const FVElementGeometry<freeFlowMomentumIndex>& fvGeometry, | ||
238 | const SubControlVolumeFace<freeFlowMomentumIndex>& scvf) const | ||
239 | { | ||
240 |
2/4✓ Branch 0 taken 103819484 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 103819484 times.
|
103819484 | assert(scvf.isFrontal() && !scvf.isLateral() && !scvf.boundary()); |
241 | 103819484 | return this->curSol(freeFlowMassIndex)[fvGeometry.elementIndex()][pressureIdx]; | |
242 | } | ||
243 | |||
244 | /*! | ||
245 | * \brief Returns the pressure at the center of a sub control volume corresponding to a given sub control volume face. | ||
246 | * This is used for setting a Dirichlet pressure for the mass model when a fixed pressure for the momentum balance is set at another | ||
247 | * boundary. Since the the pressure at the given scvf is solution-dependent and thus unknown a priori, we just use the value | ||
248 | * of the interior cell here. | ||
249 | */ | ||
250 | 18395 | Scalar cellPressure(const Element<freeFlowMassIndex>& element, | |
251 | const SubControlVolumeFace<freeFlowMassIndex>& scvf) const | ||
252 | { | ||
253 |
2/3✓ Branch 1 taken 14925 times.
✗ Branch 2 not taken.
✓ Branch 0 taken 3470 times.
|
18395 | return this->curSol(freeFlowMassIndex)[scvf.insideScvIdx()][pressureIdx]; |
254 | } | ||
255 | |||
256 | /*! | ||
257 | * \brief Returns the density at a given sub control volume face. | ||
258 | */ | ||
259 | 67194798 | Scalar density(const Element<freeFlowMomentumIndex>& element, | |
260 | const FVElementGeometry<freeFlowMomentumIndex>& fvGeometry, | ||
261 | const SubControlVolumeFace<freeFlowMomentumIndex>& scvf, | ||
262 | const bool considerPreviousTimeStep = false) const | ||
263 | { | ||
264 |
1/4✗ Branch 0 not taken.
✓ Branch 1 taken 67194798 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
|
67194798 | assert(!(considerPreviousTimeStep && !isTransient_())); |
265 | 67194798 | bindCouplingContext_(Dune::index_constant<freeFlowMomentumIndex>(), element, fvGeometry.elementIndex()); | |
266 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 65282646 times.
|
67194798 | const auto& insideMomentumScv = fvGeometry.scv(scvf.insideScvIdx()); |
267 | 69106950 | const auto& insideMassScv = momentumCouplingContext_()[0].fvGeometry.scv(insideMomentumScv.elementIndex()); | |
268 | |||
269 | 134389596 | const auto rho = [&](const auto& elemVolVars) | |
270 | { | ||
271 |
2/2✓ Branch 0 taken 85740 times.
✓ Branch 1 taken 67109058 times.
|
67194798 | if (scvf.boundary()) |
272 | 85740 | return elemVolVars[insideMassScv].density(); | |
273 | else | ||
274 | { | ||
275 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 65205530 times.
|
67109058 | const auto& outsideMomentumScv = fvGeometry.scv(scvf.outsideScvIdx()); |
276 | 69012586 | const auto& outsideMassScv = momentumCouplingContext_()[0].fvGeometry.scv(outsideMomentumScv.elementIndex()); | |
277 | // TODO distance weighting | ||
278 | 67109058 | return 0.5*(elemVolVars[insideMassScv].density() + elemVolVars[outsideMassScv].density()); | |
279 | } | ||
280 | }; | ||
281 | |||
282 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 67194798 times.
|
67194798 | return considerPreviousTimeStep ? rho(momentumCouplingContext_()[0].prevElemVolVars) |
283 | 134389596 | : rho(momentumCouplingContext_()[0].curElemVolVars); | |
284 | } | ||
285 | |||
286 | 132768324 | auto insideAndOutsideDensity(const Element<freeFlowMomentumIndex>& element, | |
287 | const FVElementGeometry<freeFlowMomentumIndex>& fvGeometry, | ||
288 | const SubControlVolumeFace<freeFlowMomentumIndex>& scvf, | ||
289 | const bool considerPreviousTimeStep = false) const | ||
290 | { | ||
291 |
1/4✗ Branch 0 not taken.
✓ Branch 1 taken 132768324 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
|
132768324 | assert(!(considerPreviousTimeStep && !isTransient_())); |
292 | 132768324 | bindCouplingContext_(Dune::index_constant<freeFlowMomentumIndex>(), element, fvGeometry.elementIndex()); | |
293 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 129051204 times.
|
132768324 | const auto& insideMomentumScv = fvGeometry.scv(scvf.insideScvIdx()); |
294 | 136485444 | const auto& insideMassScv = momentumCouplingContext_()[0].fvGeometry.scv(insideMomentumScv.elementIndex()); | |
295 | |||
296 | 265536648 | const auto result = [&](const auto& elemVolVars) | |
297 | { | ||
298 |
2/2✓ Branch 0 taken 50888 times.
✓ Branch 1 taken 132717436 times.
|
132768324 | if (scvf.boundary()) |
299 | 50888 | return std::make_pair(elemVolVars[insideMassScv].density(), elemVolVars[insideMassScv].density()); | |
300 | else | ||
301 | { | ||
302 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 129000844 times.
|
132717436 | const auto& outsideMomentumScv = fvGeometry.scv(scvf.outsideScvIdx()); |
303 | 132717436 | const auto& outsideMassScv = momentumCouplingContext_()[0].fvGeometry.scv(outsideMomentumScv.elementIndex()); | |
304 | 132717436 | return std::make_pair(elemVolVars[insideMassScv].density(), elemVolVars[outsideMassScv].density()); | |
305 | } | ||
306 | }; | ||
307 | |||
308 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 132768324 times.
|
132768324 | return considerPreviousTimeStep ? result(momentumCouplingContext_()[0].prevElemVolVars) |
309 | 265536648 | : result(momentumCouplingContext_()[0].curElemVolVars); | |
310 | } | ||
311 | |||
312 | /*! | ||
313 | * \brief Returns the density at a given sub control volume. | ||
314 | */ | ||
315 | 226036228 | Scalar density(const Element<freeFlowMomentumIndex>& element, | |
316 | const SubControlVolume<freeFlowMomentumIndex>& scv, | ||
317 | const bool considerPreviousTimeStep = false) const | ||
318 | { | ||
319 |
3/4✓ Branch 0 taken 59953376 times.
✓ Branch 1 taken 166082852 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 59953376 times.
|
226036228 | assert(!(considerPreviousTimeStep && !isTransient_())); |
320 | 226036228 | bindCouplingContext_(Dune::index_constant<freeFlowMomentumIndex>(), element, scv.elementIndex()); | |
321 | 226036228 | const auto& massScv = (*scvs(momentumCouplingContext_()[0].fvGeometry).begin()); | |
322 | |||
323 |
2/2✓ Branch 0 taken 59953376 times.
✓ Branch 1 taken 166082852 times.
|
285989604 | return considerPreviousTimeStep ? momentumCouplingContext_()[0].prevElemVolVars[massScv].density() |
324 | 166082852 | : momentumCouplingContext_()[0].curElemVolVars[massScv].density(); | |
325 | } | ||
326 | |||
327 | /*! | ||
328 | * \brief Returns the pressure at a given sub control volume face. | ||
329 | */ | ||
330 | 309689520 | Scalar effectiveViscosity(const Element<freeFlowMomentumIndex>& element, | |
331 | const FVElementGeometry<freeFlowMomentumIndex>& fvGeometry, | ||
332 | const SubControlVolumeFace<freeFlowMomentumIndex>& scvf) const | ||
333 | { | ||
334 | 309689520 | bindCouplingContext_(Dune::index_constant<freeFlowMomentumIndex>(), element, fvGeometry.elementIndex()); | |
335 | |||
336 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 303531816 times.
|
309689520 | const auto& insideMomentumScv = fvGeometry.scv(scvf.insideScvIdx()); |
337 |
2/2✓ Branch 0 taken 99584 times.
✓ Branch 1 taken 6058120 times.
|
309689520 | const auto& insideMassScv = momentumCouplingContext_()[0].fvGeometry.scv(insideMomentumScv.elementIndex()); |
338 | |||
339 |
2/2✓ Branch 0 taken 3782882 times.
✓ Branch 1 taken 305906638 times.
|
309689520 | if (scvf.boundary()) |
340 | 3782882 | return momentumCouplingContext_()[0].curElemVolVars[insideMassScv].viscosity(); | |
341 | |||
342 | 305906638 | const auto& outsideMomentumScv = fvGeometry.scv(scvf.outsideScvIdx()); | |
343 | 311964758 | const auto& outsideMassScv = momentumCouplingContext_()[0].fvGeometry.scv(outsideMomentumScv.elementIndex()); | |
344 | |||
345 | 611813276 | const auto mu = [&](const auto& elemVolVars) | |
346 | { | ||
347 | // TODO distance weighting | ||
348 | 305906638 | return 0.5*(elemVolVars[insideMassScv].viscosity() + elemVolVars[outsideMassScv].viscosity()); | |
349 | }; | ||
350 | |||
351 | 305906638 | return mu(momentumCouplingContext_()[0].curElemVolVars); | |
352 | } | ||
353 | |||
354 | /*! | ||
355 | * \brief Returns the pressure at a given sub control volume. | ||
356 | */ | ||
357 | 90344 | Scalar effectiveViscosity(const Element<freeFlowMomentumIndex>& element, | |
358 | const FVElementGeometry<freeFlowMomentumIndex>& fvGeometry, | ||
359 | const SubControlVolume<freeFlowMomentumIndex>& scv) const | ||
360 | { | ||
361 | 90344 | bindCouplingContext_(Dune::index_constant<freeFlowMomentumIndex>(), element, fvGeometry.elementIndex()); | |
362 | 90344 | const auto& insideMassScv = momentumCouplingContext_()[0].fvGeometry.scv(scv.elementIndex()); | |
363 | 90344 | return momentumCouplingContext_()[0].curElemVolVars[insideMassScv].viscosity(); | |
364 | } | ||
365 | |||
366 | /*! | ||
367 | * \brief Returns the velocity at a given sub control volume face. | ||
368 | */ | ||
369 | 141491854 | VelocityVector faceVelocity(const Element<freeFlowMassIndex>& element, | |
370 | const SubControlVolumeFace<freeFlowMassIndex>& scvf) const | ||
371 | { | ||
372 | // TODO: rethink this! Maybe we only need scvJ.dofIndex() | ||
373 | 141491854 | bindCouplingContext_(Dune::index_constant<freeFlowMassIndex>(), element, scvf.insideScvIdx()/*eIdx*/); | |
374 | |||
375 | // the TPFA scvf index corresponds to the staggered scv index (might need mapping) | ||
376 | 143595722 | const auto localMomentumScvIdx = massScvfToMomentumScvIdx_(scvf, massAndEnergyCouplingContext_()[0].fvGeometry); | |
377 | 282983708 | const auto& scvJ = massAndEnergyCouplingContext_()[0].fvGeometry.scv(localMomentumScvIdx); | |
378 | |||
379 | // create a unit normal vector oriented in positive coordinate direction | ||
380 | 141491854 | typename SubControlVolumeFace<freeFlowMassIndex>::GlobalPosition velocity; | |
381 | 141491854 | velocity[scvJ.dofAxis()] = 1.0; | |
382 | |||
383 | // create the actual velocity vector | ||
384 | 141491854 | velocity *= this->curSol(freeFlowMomentumIndex)[scvJ.dofIndex()]; | |
385 | |||
386 | 141491854 | return velocity; | |
387 | } | ||
388 | |||
389 | /*! | ||
390 | * \brief The coupling stencil of domain I, i.e. which domain J DOFs | ||
391 | * the given domain I scv's residual depends on. | ||
392 | * | ||
393 | * \param domainI the domain index of domain i | ||
394 | * \param elementI the coupled element of domain à | ||
395 | * \param scvI the sub-control volume of domain i | ||
396 | * \param domainJ the domain index of domain j | ||
397 | */ | ||
398 | template<std::size_t j> | ||
399 | const CouplingStencilType& couplingStencil(Dune::index_constant<freeFlowMomentumIndex> domainI, | ||
400 | const Element<freeFlowMomentumIndex>& elementI, | ||
401 | const SubControlVolume<freeFlowMomentumIndex>& scvI, | ||
402 | Dune::index_constant<j> domainJ) const | ||
403 | { return emptyStencil_; } | ||
404 | |||
405 | /*! | ||
406 | * \brief returns an iterable container of all indices of degrees of freedom of domain j | ||
407 | * that couple with / influence the element residual of the given element of domain i | ||
408 | * | ||
409 | * \param domainI the domain index of domain i | ||
410 | * \param elementI the coupled element of domain à | ||
411 | * \param domainJ the domain index of domain j | ||
412 | * | ||
413 | * \note The element residual definition depends on the discretization scheme of domain i | ||
414 | * box: a container of the residuals of all sub control volumes | ||
415 | * cc : the residual of the (sub) control volume | ||
416 | * fem: the residual of the element | ||
417 | * \note This function has to be implemented by all coupling managers for all combinations of i and j | ||
418 | */ | ||
419 | 2433937 | const CouplingStencilType& couplingStencil(Dune::index_constant<freeFlowMassIndex> domainI, | |
420 | const Element<freeFlowMassIndex>& elementI, | ||
421 | Dune::index_constant<freeFlowMomentumIndex> domainJ) const | ||
422 | { | ||
423 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2433937 times.
|
2433937 | const auto eIdx = this->problem(freeFlowMassIndex).gridGeometry().elementMapper().index(elementI); |
424 | 2433937 | return massAndEnergyToMomentumStencils_[eIdx]; | |
425 | } | ||
426 | |||
427 | /*! | ||
428 | * \brief returns an iterable container of all indices of degrees of freedom of domain j | ||
429 | * that couple with / influence the residual of the given sub-control volume of domain i | ||
430 | * | ||
431 | * \param domainI the domain index of domain i | ||
432 | * \param elementI the coupled element of domain à | ||
433 | * \param scvI the sub-control volume of domain i | ||
434 | * \param domainJ the domain index of domain j | ||
435 | */ | ||
436 | 9753428 | const CouplingStencilType& couplingStencil(Dune::index_constant<freeFlowMomentumIndex> domainI, | |
437 | const Element<freeFlowMomentumIndex>& elementI, | ||
438 | const SubControlVolume<freeFlowMomentumIndex>& scvI, | ||
439 | Dune::index_constant<freeFlowMassIndex> domainJ) const | ||
440 | { | ||
441 | 9753428 | return momentumToMassAndEnergyStencils_[scvI.index()]; | |
442 | } | ||
443 | |||
444 | // \} | ||
445 | |||
446 | /*! | ||
447 | * \name member functions concerning variable caching for element residual evaluations | ||
448 | */ | ||
449 | // \{ | ||
450 | |||
451 | //! \copydoc CouplingManager::updateCouplingContext | ||
452 | template<std::size_t i, std::size_t j, class LocalAssemblerI> | ||
453 | 185250256 | void updateCouplingContext(Dune::index_constant<i> domainI, | |
454 | const LocalAssemblerI& localAssemblerI, | ||
455 | Dune::index_constant<j> domainJ, | ||
456 | std::size_t dofIdxGlobalJ, | ||
457 | const PrimaryVariables<j>& priVarsJ, | ||
458 | int pvIdxJ) | ||
459 | { | ||
460 |
3/4✓ Branch 2 taken 705218 times.
✓ Branch 3 taken 456288 times.
✓ Branch 4 taken 7072 times.
✗ Branch 5 not taken.
|
185250256 | this->curSol(domainJ)[dofIdxGlobalJ][pvIdxJ] = priVarsJ[pvIdxJ]; |
461 | |||
462 | if constexpr (domainI == freeFlowMomentumIndex && domainJ == freeFlowMassIndex) | ||
463 | { | ||
464 | 32100956 | bindCouplingContext_(domainI, localAssemblerI.element()); | |
465 | |||
466 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 32100956 times.
|
32100956 | const auto& problem = this->problem(domainJ); |
467 | 32100956 | const auto& deflectedElement = problem.gridGeometry().element(dofIdxGlobalJ); | |
468 |
1/2✓ Branch 1 taken 56576 times.
✗ Branch 2 not taken.
|
32100956 | const auto elemSol = elementSolution(deflectedElement, this->curSol(domainJ), problem.gridGeometry()); |
469 | 32100956 | const auto& fvGeometry = momentumCouplingContext_()[0].fvGeometry; | |
470 | 32100956 | const auto scvIdxJ = dofIdxGlobalJ; | |
471 |
2/3✓ Branch 0 taken 468288 times.
✓ Branch 1 taken 881888 times.
✗ Branch 2 not taken.
|
32100956 | const auto& scv = fvGeometry.scv(scvIdxJ); |
472 | |||
473 | if constexpr (ElementVolumeVariables<freeFlowMassIndex>::GridVolumeVariables::cachingEnabled) | ||
474 |
2/4✓ Branch 1 taken 28288 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 28288 times.
✗ Branch 5 not taken.
|
30807356 | gridVars_(freeFlowMassIndex).curGridVolVars().volVars(scv).update(std::move(elemSol), problem, deflectedElement, scv); |
475 | else | ||
476 |
1/2✓ Branch 1 taken 28288 times.
✗ Branch 2 not taken.
|
1350176 | momentumCouplingContext_()[0].curElemVolVars[scv].update(std::move(elemSol), problem, deflectedElement, scv); |
477 | 56576 | } | |
478 | 32100956 | } | |
479 | |||
480 | // \} | ||
481 | |||
482 | /*! | ||
483 | * \brief Compute colors for multithreaded assembly | ||
484 | */ | ||
485 | void computeColorsForAssembly() | ||
486 | { | ||
487 | // use coloring of the fc staggered discretization for both domains | ||
488 | elementSets_ = computeColoring(this->problem(freeFlowMomentumIndex).gridGeometry()).sets; | ||
489 | } | ||
490 | |||
491 | /*! | ||
492 | * \brief Execute assembly kernel in parallel | ||
493 | * | ||
494 | * \param domainI the domain index of domain i | ||
495 | * \param assembleElement kernel function to execute for one element | ||
496 | */ | ||
497 | template<std::size_t i, class AssembleElementFunc> | ||
498 | void assembleMultithreaded(Dune::index_constant<i> domainI, AssembleElementFunc&& assembleElement) const | ||
499 | { | ||
500 | if (elementSets_.empty()) | ||
501 | DUNE_THROW(Dune::InvalidStateException, "Call computeColorsForAssembly before assembling in parallel!"); | ||
502 | |||
503 | // make this element loop run in parallel | ||
504 | // for this we have to color the elements so that we don't get | ||
505 | // race conditions when writing into the global matrix | ||
506 | // each color can be assembled using multiple threads | ||
507 | const auto& grid = this->problem(freeFlowMomentumIndex).gridGeometry().gridView().grid(); | ||
508 | for (const auto& elements : elementSets_) | ||
509 | { | ||
510 | Dumux::parallelFor(elements.size(), [&](const std::size_t eIdx) | ||
511 | { | ||
512 | const auto element = grid.entity(elements[eIdx]); | ||
513 | assembleElement(element); | ||
514 | }); | ||
515 | } | ||
516 | } | ||
517 | |||
518 | private: | ||
519 | 32100956 | void bindCouplingContext_(Dune::index_constant<freeFlowMomentumIndex> domainI, | |
520 | const Element<freeFlowMomentumIndex>& elementI) const | ||
521 | { | ||
522 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 32100956 times.
|
32100956 | const auto eIdx = this->problem(freeFlowMomentumIndex).gridGeometry().elementMapper().index(elementI); |
523 | 32100956 | bindCouplingContext_(domainI, elementI, eIdx); | |
524 | 32100956 | } | |
525 | |||
526 | 767880170 | void bindCouplingContext_(Dune::index_constant<freeFlowMomentumIndex> domainI, | |
527 | const Element<freeFlowMomentumIndex>& elementI, | ||
528 | const std::size_t eIdx) const | ||
529 | { | ||
530 | 767880170 | if (momentumCouplingContext_().empty()) | |
531 | { | ||
532 |
2/4✗ Branch 0 not taken.
✓ Branch 1 taken 66 times.
✓ Branch 3 taken 7 times.
✗ Branch 4 not taken.
|
66 | auto fvGeometry = localView(this->problem(freeFlowMassIndex).gridGeometry()); |
533 | 66 | fvGeometry.bind(elementI); | |
534 | |||
535 |
3/5✓ Branch 1 taken 7 times.
✓ Branch 2 taken 59 times.
✓ Branch 4 taken 7 times.
✗ Branch 5 not taken.
✗ Branch 3 not taken.
|
66 | auto curElemVolVars = localView(gridVars_(freeFlowMassIndex).curGridVolVars()); |
536 |
1/2✓ Branch 1 taken 66 times.
✗ Branch 2 not taken.
|
66 | curElemVolVars.bind(elementI, fvGeometry, this->curSol(freeFlowMassIndex)); |
537 | |||
538 |
3/4✓ Branch 0 taken 28 times.
✓ Branch 1 taken 38 times.
✓ Branch 3 taken 28 times.
✗ Branch 4 not taken.
|
104 | auto prevElemVolVars = isTransient_() ? localView(gridVars_(freeFlowMassIndex).prevGridVolVars()) |
539 |
1/2✓ Branch 1 taken 38 times.
✗ Branch 2 not taken.
|
38 | : localView(gridVars_(freeFlowMassIndex).curGridVolVars()); |
540 | |||
541 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 3 times.
|
66 | if (isTransient_()) |
542 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | prevElemVolVars.bindElement(elementI, fvGeometry, prevSol_(freeFlowMassIndex)); |
543 | |||
544 |
1/2✓ Branch 1 taken 66 times.
✗ Branch 2 not taken.
|
66 | momentumCouplingContext_().emplace_back(MomentumCouplingContext{std::move(fvGeometry), std::move(curElemVolVars), std::move(prevElemVolVars), eIdx}); |
545 | 131 | } | |
546 | 767880104 | else if (eIdx != momentumCouplingContext_()[0].eIdx) | |
547 | { | ||
548 | 2755003 | momentumCouplingContext_()[0].eIdx = eIdx; | |
549 | 5510006 | momentumCouplingContext_()[0].fvGeometry.bind(elementI); | |
550 | 2786035 | momentumCouplingContext_()[0].curElemVolVars.bind(elementI, momentumCouplingContext_()[0].fvGeometry, this->curSol(freeFlowMassIndex)); | |
551 | |||
552 |
2/2✓ Branch 0 taken 27499 times.
✓ Branch 1 taken 3533 times.
|
2755003 | if (isTransient_()) |
553 | 27499 | momentumCouplingContext_()[0].prevElemVolVars.bindElement(elementI, momentumCouplingContext_()[0].fvGeometry, prevSol_(freeFlowMassIndex)); | |
554 | } | ||
555 | 767880236 | } | |
556 | |||
557 | void bindCouplingContext_(Dune::index_constant<freeFlowMassIndex> domainI, | ||
558 | const Element<freeFlowMassIndex>& elementI) const | ||
559 | { | ||
560 | const auto eIdx = this->problem(freeFlowMassIndex).gridGeometry().elementMapper().index(elementI); | ||
561 | bindCouplingContext_(domainI, elementI, eIdx); | ||
562 | } | ||
563 | |||
564 | 141491854 | void bindCouplingContext_(Dune::index_constant<freeFlowMassIndex> domainI, | |
565 | const Element<freeFlowMassIndex>& elementI, | ||
566 | const std::size_t eIdx) const | ||
567 | { | ||
568 | 141491854 | if (massAndEnergyCouplingContext_().empty()) | |
569 | { | ||
570 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 66 times.
|
66 | const auto& gridGeometry = this->problem(freeFlowMomentumIndex).gridGeometry(); |
571 | 66 | auto fvGeometry = localView(gridGeometry); | |
572 | 66 | fvGeometry.bindElement(elementI); | |
573 | 66 | massAndEnergyCouplingContext_().emplace_back(std::move(fvGeometry), eIdx); | |
574 | } | ||
575 | 141491788 | else if (eIdx != massAndEnergyCouplingContext_()[0].eIdx) | |
576 | { | ||
577 | 26814208 | massAndEnergyCouplingContext_()[0].eIdx = eIdx; | |
578 | 26814208 | massAndEnergyCouplingContext_()[0].fvGeometry.bindElement(elementI); | |
579 | } | ||
580 | 141491854 | } | |
581 | |||
582 | /*! | ||
583 | * \brief Return a reference to the grid variables of a sub problem | ||
584 | * \param domainIdx The domain index | ||
585 | */ | ||
586 | template<std::size_t i> | ||
587 | 132 | const GridVariables<i>& gridVars_(Dune::index_constant<i> domainIdx) const | |
588 | { | ||
589 |
1/2✓ Branch 0 taken 132 times.
✗ Branch 1 not taken.
|
132 | if (std::get<i>(gridVariables_)) |
590 | 132 | return *std::get<i>(gridVariables_); | |
591 | else | ||
592 | ✗ | DUNE_THROW(Dune::InvalidStateException, "The gridVariables pointer was not set. Use setGridVariables() before calling this function"); | |
593 | } | ||
594 | |||
595 | /*! | ||
596 | * \brief Return a reference to the grid variables of a sub problem | ||
597 | * \param domainIdx The domain index | ||
598 | */ | ||
599 | template<std::size_t i> | ||
600 | 30779068 | GridVariables<i>& gridVars_(Dune::index_constant<i> domainIdx) | |
601 | { | ||
602 |
1/2✓ Branch 0 taken 30779068 times.
✗ Branch 1 not taken.
|
30779068 | if (std::get<i>(gridVariables_)) |
603 | 30779068 | return *std::get<i>(gridVariables_); | |
604 | else | ||
605 | ✗ | DUNE_THROW(Dune::InvalidStateException, "The gridVariables pointer was not set. Use setGridVariables() before calling this function"); | |
606 | } | ||
607 | |||
608 | |||
609 | 66 | void computeCouplingStencils_() | |
610 | { | ||
611 | // TODO higher order | ||
612 |
2/4✗ Branch 0 not taken.
✓ Branch 1 taken 66 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 62 times.
|
66 | const auto& momentumGridGeometry = this->problem(freeFlowMomentumIndex).gridGeometry(); |
613 | 66 | auto momentumFvGeometry = localView(momentumGridGeometry); | |
614 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 66 times.
|
66 | massAndEnergyToMomentumStencils_.clear(); |
615 | 66 | massAndEnergyToMomentumStencils_.resize(momentumGridGeometry.gridView().size(0)); | |
616 | |||
617 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 66 times.
|
66 | momentumToMassAndEnergyStencils_.clear(); |
618 | 66 | momentumToMassAndEnergyStencils_.resize(momentumGridGeometry.numScv()); | |
619 | |||
620 |
9/10✓ Branch 2 taken 340459 times.
✓ Branch 3 taken 101 times.
✓ Branch 5 taken 7 times.
✓ Branch 6 taken 12338 times.
✓ Branch 8 taken 3539 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 3536 times.
✓ Branch 11 taken 6 times.
✓ Branch 7 taken 12335 times.
✓ Branch 4 taken 100 times.
|
1065661 | for (const auto& element : elements(momentumGridGeometry.gridView())) |
621 | { | ||
622 |
2/4✓ Branch 1 taken 3536 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 3536 times.
✗ Branch 5 not taken.
|
356368 | const auto eIdx = momentumGridGeometry.elementMapper().index(element); |
623 | 368440 | momentumFvGeometry.bind(element); | |
624 |
3/3✓ Branch 0 taken 1372346 times.
✓ Branch 1 taken 398977 times.
✓ Branch 2 taken 14203 times.
|
2117693 | for (const auto& scv : scvs(momentumFvGeometry)) |
625 | { | ||
626 |
1/2✓ Branch 1 taken 63884 times.
✗ Branch 2 not taken.
|
1429158 | massAndEnergyToMomentumStencils_[eIdx].push_back(scv.dofIndex()); |
627 |
1/2✓ Branch 1 taken 63884 times.
✗ Branch 2 not taken.
|
1429158 | momentumToMassAndEnergyStencils_[scv.index()].push_back(eIdx); |
628 | |||
629 | // extend the stencil for fluids with variable viscosity and density, | ||
630 | if constexpr (FluidSystem::isCompressible(0/*phaseIdx*/)) | ||
631 | // if constexpr (FluidSystem::isCompressible(0/*phaseIdx*/) || !FluidSystem::viscosityIsConstant(0/*phaseIdx*/)) // TODO fix on master | ||
632 | { | ||
633 |
4/4✓ Branch 1 taken 65840 times.
✓ Branch 2 taken 34148 times.
✓ Branch 4 taken 99988 times.
✓ Branch 5 taken 32920 times.
|
298736 | for (const auto& scvf : scvfs(momentumFvGeometry, scv)) |
634 | { | ||
635 |
4/4✓ Branch 0 taken 65840 times.
✓ Branch 1 taken 34148 times.
✓ Branch 2 taken 63384 times.
✓ Branch 3 taken 2456 times.
|
99988 | if (scvf.isLateral() && !scvf.boundary()) |
636 | { | ||
637 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 53684 times.
|
63384 | const auto& outsideScv = momentumFvGeometry.scv(scvf.outsideScvIdx()); |
638 | 63384 | momentumToMassAndEnergyStencils_[scv.index()].push_back(outsideScv.elementIndex()); | |
639 | } | ||
640 | } | ||
641 | } | ||
642 | } | ||
643 | } | ||
644 | 66 | } | |
645 | |||
646 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 136301986 times.
|
141491854 | std::size_t massScvfToMomentumScvIdx_(const SubControlVolumeFace<freeFlowMassIndex>& massScvf, |
647 | [[maybe_unused]] const FVElementGeometry<freeFlowMomentumIndex>& momentumFVGeometry) const | ||
648 | { | ||
649 | if constexpr (ConsistentlyOrientedGrid<typename GridView<freeFlowMomentumIndex>::Grid>{}) | ||
650 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 136301986 times.
|
139387986 | return massScvf.index(); |
651 | else | ||
652 | { | ||
653 |
4/6✓ Branch 0 taken 10 times.
✓ Branch 1 taken 2103858 times.
✓ Branch 3 taken 10 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 10 times.
✗ Branch 7 not taken.
|
2103868 | static const bool makeConsistentlyOriented = getParam<bool>("Grid.MakeConsistentlyOriented", true); |
654 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2103868 times.
|
2103868 | if (!makeConsistentlyOriented) |
655 | ✗ | return massScvf.index(); | |
656 | |||
657 |
2/3✓ Branch 1 taken 4795766 times.
✗ Branch 2 not taken.
✓ Branch 0 taken 457120 times.
|
5252886 | for (const auto& momentumScv : scvs(momentumFVGeometry)) |
658 | { | ||
659 | 5252886 | typename SubControlVolumeFace<freeFlowMassIndex>::GlobalPosition momentumUnitOuterNormal(0.0); | |
660 | 5252886 | momentumUnitOuterNormal[momentumScv.dofAxis()] = momentumScv.directionSign(); | |
661 |
4/4✓ Branch 0 taken 2097084 times.
✓ Branch 1 taken 3155802 times.
✓ Branch 2 taken 2103868 times.
✓ Branch 3 taken 3149018 times.
|
12602856 | if (Dune::FloatCmp::eq<typename GridView<freeFlowMomentumIndex>::ctype>(massScvf.unitOuterNormal()*momentumUnitOuterNormal, 1.0)) |
662 | 2103868 | return momentumScv.index(); | |
663 | } | ||
664 | ✗ | DUNE_THROW(Dune::InvalidStateException, "No Momentum SCV found"); | |
665 | } | ||
666 | } | ||
667 | |||
668 | CouplingStencilType emptyStencil_; | ||
669 | std::vector<CouplingStencilType> momentumToMassAndEnergyStencils_; | ||
670 | std::vector<CouplingStencilType> massAndEnergyToMomentumStencils_; | ||
671 | |||
672 | 66 | std::vector<MomentumCouplingContext>& momentumCouplingContext_() const | |
673 |
30/33✓ Branch 0 taken 9113008 times.
✓ Branch 1 taken 231702464 times.
✓ Branch 4 taken 4005552 times.
✓ Branch 5 taken 58594777 times.
✓ Branch 9 taken 63017 times.
✓ Branch 10 taken 279860778 times.
✓ Branch 14 taken 172860124 times.
✓ Branch 15 taken 562741650 times.
✓ Branch 16 taken 18536906 times.
✓ Branch 17 taken 3533 times.
✓ Branch 18 taken 8228699 times.
✓ Branch 19 taken 481753021 times.
✓ Branch 23 taken 70534641 times.
✓ Branch 24 taken 133467422 times.
✗ Branch 27 not taken.
✓ Branch 28 taken 3716649 times.
✓ Branch 2 taken 924160 times.
✓ Branch 6 taken 79807429 times.
✓ Branch 11 taken 129609952 times.
✓ Branch 12 taken 23 times.
✓ Branch 13 taken 18942868 times.
✓ Branch 20 taken 9866588 times.
✓ Branch 25 taken 468256 times.
✓ Branch 29 taken 1947004 times.
✓ Branch 22 taken 653696 times.
✓ Branch 3 taken 2052568 times.
✓ Branch 7 taken 3 times.
✓ Branch 21 taken 857133 times.
✓ Branch 30 taken 4137472 times.
✗ Branch 33 not taken.
✓ Branch 34 taken 4 times.
✗ Branch 8 not taken.
✓ Branch 26 taken 28288 times.
|
1754781449 | { return momentumCouplingContextImpl_; } |
674 | |||
675 | 66 | std::vector<MassAndEnergyCouplingContext>& massAndEnergyCouplingContext_() const | |
676 |
8/9✓ Branch 0 taken 66 times.
✓ Branch 1 taken 141491788 times.
✓ Branch 3 taken 26814208 times.
✓ Branch 4 taken 114677580 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 136301986 times.
✓ Branch 8 taken 1921021 times.
✓ Branch 9 taken 58 times.
✓ Branch 10 taken 7 times.
|
282983840 | { return massAndEnergyCouplingContextImpl_; } |
677 | |||
678 | mutable std::vector<MassAndEnergyCouplingContext> massAndEnergyCouplingContextImpl_; | ||
679 | mutable std::vector<MomentumCouplingContext> momentumCouplingContextImpl_; | ||
680 | |||
681 | //! A tuple of std::shared_ptrs to the grid variables of the sub problems | ||
682 | GridVariablesTuple gridVariables_; | ||
683 | |||
684 | 79151078 | bool isTransient_() const | |
685 |
12/14✗ Branch 0 not taken.
✗ Branch 1 not taken.
✓ Branch 2 taken 20 times.
✓ Branch 3 taken 26 times.
✓ Branch 4 taken 54 times.
✓ Branch 5 taken 12 times.
✓ Branch 6 taken 27513 times.
✓ Branch 7 taken 3 times.
✓ Branch 8 taken 5791456 times.
✓ Branch 9 taken 3533 times.
✓ Branch 10 taken 52214920 times.
✓ Branch 11 taken 1947000 times.
✓ Branch 12 taken 18196400 times.
✓ Branch 13 taken 970200 times.
|
81875111 | { return std::get<0>(prevSolutions_) != nullptr; } |
686 | |||
687 | template<std::size_t i> | ||
688 | 27500 | const SubSolutionVector<i>& prevSol_(Dune::index_constant<i>) const | |
689 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
27500 | { return *std::get<i>(prevSolutions_); } |
690 | |||
691 | PrevSolutionVectorStorage prevSolutions_; | ||
692 | |||
693 | std::deque<std::vector<ElementSeed<freeFlowMomentumIndex>>> elementSets_; | ||
694 | }; | ||
695 | |||
696 | // multi-threading is not supported because we have only one coupling context instance and a mutable cache | ||
697 | template<class T> | ||
698 | struct CouplingManagerSupportsMultithreadedAssembly<FCStaggeredFreeFlowCouplingManager<T>> | ||
699 | : public std::false_type {}; | ||
700 | |||
701 | } // end namespace Dumux | ||
702 | |||
703 | #endif | ||
704 |