GCC Code Coverage Report


Directory: ../../../builds/dumux-repositories/
File: /builds/dumux-repositories/dumux/dumux/multidomain/subdomaincvfelocalassembler.hh
Date: 2024-05-04 19:09:25
Exec Total Coverage
Lines: 93 105 88.6%
Functions: 131 444 29.5%
Branches: 169 376 44.9%

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-FileCopyrightInfo: 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 Assembly
10 * \ingroup CVFEDiscretization
11 * \ingroup MultiDomain
12 * \brief An assembler for Jacobian and residual contribution per element (CVFE methods) for multidomain problems
13 */
14 #ifndef DUMUX_MULTIDOMAIN_SUBDOMAIN_CVFE_LOCAL_ASSEMBLER_HH
15 #define DUMUX_MULTIDOMAIN_SUBDOMAIN_CVFE_LOCAL_ASSEMBLER_HH
16
17 #include <type_traits>
18
19 #include <dune/common/reservedvector.hh>
20 #include <dune/common/indices.hh>
21 #include <dune/common/hybridutilities.hh>
22 #include <dune/grid/common/gridenums.hh> // for GhostEntity
23 #include <dune/istl/matrixindexset.hh>
24
25 #include <dumux/common/reservedblockvector.hh>
26 #include <dumux/common/properties.hh>
27 #include <dumux/common/parameters.hh>
28 #include <dumux/common/numericdifferentiation.hh>
29 #include <dumux/common/numeqvector.hh>
30 #include <dumux/assembly/numericepsilon.hh>
31 #include <dumux/assembly/diffmethod.hh>
32 #include <dumux/assembly/cvfelocalassembler.hh>
33 #include <dumux/discretization/extrusion.hh>
34
35 namespace Dumux {
36
37 /*!
38 * \ingroup Assembly
39 * \ingroup CVFEDiscretization
40 * \ingroup MultiDomain
41 * \brief A base class for all CVFE subdomain local assemblers
42 * \tparam id the id of the sub domain
43 * \tparam TypeTag the TypeTag
44 * \tparam Assembler the assembler type
45 * \tparam Implementation the actual implementation type
46 * \tparam implicit Specifies whether the time discretization is implicit or not not (i.e. explicit)
47 */
48 template<std::size_t id, class TypeTag, class Assembler, class Implementation, DiffMethod dm, bool implicit>
49 6964146 class SubDomainCVFELocalAssemblerBase : public CVFELocalAssembler<TypeTag, Assembler, dm, implicit, Implementation>
50 {
51 using ParentType = CVFELocalAssembler<TypeTag, Assembler, dm, implicit, Implementation>;
52
53 using Problem = GetPropType<TypeTag, Properties::Problem>;
54 using LocalResidualValues = Dumux::NumEqVector<GetPropType<TypeTag, Properties::PrimaryVariables>>;
55 using JacobianMatrix = GetPropType<TypeTag, Properties::JacobianMatrix>;
56 using SolutionVector = typename Assembler::SolutionVector;
57 using ElementBoundaryTypes = GetPropType<TypeTag, Properties::ElementBoundaryTypes>;
58
59 using GridVariables = GetPropType<TypeTag, Properties::GridVariables>;
60 using GridVolumeVariables = typename GridVariables::GridVolumeVariables;
61 using ElementVolumeVariables = typename GridVolumeVariables::LocalView;
62 using ElementFluxVariablesCache = typename GridVariables::GridFluxVariablesCache::LocalView;
63 using Scalar = typename GridVariables::Scalar;
64
65 using GridGeometry = typename GridVariables::GridGeometry;
66 using FVElementGeometry = typename GridGeometry::LocalView;
67 using SubControlVolume = typename GridGeometry::SubControlVolume;
68 using SubControlVolumeFace = typename GridGeometry::SubControlVolumeFace;
69 using Extrusion = Extrusion_t<GridGeometry>;
70 using GridView = typename GridGeometry::GridView;
71 using Element = typename GridView::template Codim<0>::Entity;
72
73 using CouplingManager = typename Assembler::CouplingManager;
74
75 static constexpr auto numEq = GetPropType<TypeTag, Properties::ModelTraits>::numEq();
76
77 public:
78 //! export the domain id of this sub-domain
79 static constexpr auto domainId = typename Dune::index_constant<id>();
80 //! pull up constructor of parent class
81 using ParentType::ParentType;
82 //! export element residual vector type
83 using ElementResidualVector = typename ParentType::LocalResidual::ElementResidualVector;
84
85 // the constructor
86 5875411 explicit SubDomainCVFELocalAssemblerBase(
87 const Assembler& assembler,
88 const Element& element,
89 const SolutionVector& curSol,
90 CouplingManager& couplingManager
91 )
92 : ParentType(assembler,
93 element,
94 curSol,
95 localView(assembler.gridGeometry(domainId)),
96
2/4
✓ Branch 1 taken 1295090 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 40 times.
✗ Branch 5 not taken.
14145835 localView(assembler.gridVariables(domainId).curGridVolVars()),
97
3/6
✓ Branch 1 taken 1295090 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 40 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 40 times.
✗ Branch 8 not taken.
14886995 localView(assembler.gridVariables(domainId).prevGridVolVars()),
98
4/8
✓ Branch 1 taken 1295090 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 40 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 40 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 40 times.
✗ Branch 11 not taken.
15628155 localView(assembler.gridVariables(domainId).gridFluxVarsCache()),
99 assembler.localResidual(domainId),
100 11614763 (element.partitionType() == Dune::GhostEntity))
101
26/44
✓ Branch 0 taken 1412574 times.
✓ Branch 1 taken 68041 times.
✓ Branch 2 taken 1239836 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 68041 times.
✓ Branch 5 taken 1239836 times.
✓ Branch 6 taken 712307 times.
✓ Branch 7 taken 55254 times.
✓ Branch 8 taken 1252623 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 55254 times.
✓ Branch 11 taken 1239836 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 55234 times.
✓ Branch 14 taken 1239816 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 55234 times.
✓ Branch 17 taken 1239816 times.
✗ Branch 18 not taken.
✓ Branch 19 taken 55234 times.
✓ Branch 20 taken 1239816 times.
✗ Branch 21 not taken.
✓ Branch 22 taken 55234 times.
✓ Branch 23 taken 1239816 times.
✗ Branch 24 not taken.
✓ Branch 25 taken 55234 times.
✓ Branch 26 taken 1239816 times.
✗ Branch 27 not taken.
✓ Branch 28 taken 55234 times.
✓ Branch 29 taken 1239816 times.
✗ Branch 30 not taken.
✓ Branch 31 taken 55234 times.
✗ Branch 32 not taken.
✓ Branch 33 taken 1239816 times.
✗ Branch 34 not taken.
✓ Branch 35 taken 1295050 times.
✗ Branch 36 not taken.
✓ Branch 37 taken 55234 times.
✗ Branch 38 not taken.
✗ Branch 39 not taken.
✗ Branch 40 not taken.
✗ Branch 41 not taken.
✗ Branch 42 not taken.
✗ Branch 43 not taken.
7235721 , couplingManager_(couplingManager)
102 5875371 {}
103
104 /*!
105 * \brief Computes the derivatives with respect to the given element and adds them
106 * to the global matrix. The element residual is written into the right hand side.
107 */
108 template<class JacobianMatrixRow, class SubResidualVector, class GridVariablesTuple>
109 void assembleJacobianAndResidual(JacobianMatrixRow& jacRow, SubResidualVector& res, GridVariablesTuple& gridVariables)
110 {
111 4893652 auto assembleCouplingBlocks = [&](const auto& residual)
112 {
113 // assemble the coupling blocks
114 using namespace Dune::Hybrid;
115 1432826 forEach(integralRange(Dune::Hybrid::size(jacRow)), [&](auto&& i)
116 {
117 2446826 if constexpr (std::decay_t<decltype(i)>{} != id)
118
0/6
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
1424727 this->assembleJacobianCoupling(i, jacRow, residual, gridVariables);
119 });
120 };
121
122 // the coupled model does not support partial reassembly yet
123 2446826 const DefaultPartialReassembler* noReassembler = nullptr;
124
16/32
✓ Branch 1 taken 859507 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 859507 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 859507 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 859507 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 565611 times.
✗ Branch 14 not taken.
✓ Branch 16 taken 565611 times.
✗ Branch 17 not taken.
✓ Branch 19 taken 565611 times.
✗ Branch 20 not taken.
✓ Branch 22 taken 565611 times.
✗ Branch 23 not taken.
✓ Branch 25 taken 57708 times.
✗ Branch 26 not taken.
✓ Branch 28 taken 57708 times.
✗ Branch 29 not taken.
✓ Branch 31 taken 57708 times.
✗ Branch 32 not taken.
✓ Branch 34 taken 57708 times.
✗ Branch 35 not taken.
✓ Branch 37 taken 964000 times.
✗ Branch 38 not taken.
✓ Branch 40 taken 964000 times.
✗ Branch 41 not taken.
✓ Branch 43 taken 964000 times.
✗ Branch 44 not taken.
✓ Branch 46 taken 964000 times.
✗ Branch 47 not taken.
9787304 ParentType::assembleJacobianAndResidual(jacRow[domainId], res, *std::get<domainId>(gridVariables), noReassembler, assembleCouplingBlocks);
125 }
126
127 /*!
128 * \brief Assemble the entries in a coupling block of the jacobian.
129 * There is no coupling block between a domain and itself.
130 */
131 template<std::size_t otherId, class JacRow, class GridVariables,
132 typename std::enable_if_t<(otherId == id), int> = 0>
133 void assembleJacobianCoupling(Dune::index_constant<otherId> domainJ, JacRow& jacRow,
134 const ElementResidualVector& res, GridVariables& gridVariables)
135 {}
136
137 /*!
138 * \brief Assemble the entries in a coupling block of the jacobian.
139 */
140 template<std::size_t otherId, class JacRow, class GridVariables,
141 typename std::enable_if_t<(otherId != id), int> = 0>
142 void assembleJacobianCoupling(Dune::index_constant<otherId> domainJ, JacRow& jacRow,
143 const ElementResidualVector& res, GridVariables& gridVariables)
144 {
145
0/79
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
✗ Branch 22 not taken.
✗ Branch 23 not taken.
✗ Branch 24 not taken.
✗ Branch 25 not taken.
✗ Branch 26 not taken.
✗ Branch 27 not taken.
✗ Branch 28 not taken.
✗ Branch 29 not taken.
✗ Branch 30 not taken.
✗ Branch 31 not taken.
✗ Branch 32 not taken.
✗ Branch 33 not taken.
✗ Branch 34 not taken.
✗ Branch 35 not taken.
✗ Branch 36 not taken.
✗ Branch 37 not taken.
✗ Branch 38 not taken.
✗ Branch 39 not taken.
✗ Branch 40 not taken.
✗ Branch 42 not taken.
✗ Branch 43 not taken.
✗ Branch 45 not taken.
✗ Branch 46 not taken.
✗ Branch 48 not taken.
✗ Branch 49 not taken.
✗ Branch 50 not taken.
✗ Branch 51 not taken.
✗ Branch 52 not taken.
✗ Branch 53 not taken.
✗ Branch 54 not taken.
✗ Branch 55 not taken.
✗ Branch 56 not taken.
✗ Branch 58 not taken.
✗ Branch 59 not taken.
✗ Branch 61 not taken.
✗ Branch 62 not taken.
✗ Branch 64 not taken.
✗ Branch 65 not taken.
✗ Branch 66 not taken.
✗ Branch 67 not taken.
✗ Branch 68 not taken.
✗ Branch 69 not taken.
✗ Branch 70 not taken.
✗ Branch 71 not taken.
✗ Branch 72 not taken.
✗ Branch 73 not taken.
✗ Branch 74 not taken.
✗ Branch 75 not taken.
✗ Branch 76 not taken.
✗ Branch 77 not taken.
✗ Branch 78 not taken.
✗ Branch 79 not taken.
✗ Branch 80 not taken.
✗ Branch 81 not taken.
✗ Branch 82 not taken.
✗ Branch 83 not taken.
✗ Branch 84 not taken.
✗ Branch 86 not taken.
✗ Branch 87 not taken.
9754908 this->asImp_().assembleJacobianCoupling(domainJ, jacRow[domainJ], res, *std::get<domainId>(gridVariables));
146 }
147
148 /*!
149 * \brief Evaluates the local source term for an element and given element volume variables
150 */
151 218701 ElementResidualVector evalLocalSourceResidual(const Element& element, const ElementVolumeVariables& elemVolVars) const
152 {
153 // initialize the residual vector for all scvs in this element
154 656103 ElementResidualVector residual(this->fvGeometry().numScv());
155
156 // evaluate the volume terms (storage + source terms)
157 // forward to the local residual specialized for the discretization methods
158
4/4
✓ Branch 0 taken 694440 times.
✓ Branch 1 taken 142542 times.
✓ Branch 2 taken 545808 times.
✓ Branch 3 taken 68226 times.
2074471 for (const auto& scv : scvs(this->fvGeometry()))
159 {
160 857816 const auto& curVolVars = elemVolVars[scv];
161 1418368 auto source = this->localResidual().computeSource(problem(), element, this->fvGeometry(), elemVolVars, scv);
162 1715632 source *= -Extrusion::volume(this->fvGeometry(), scv)*curVolVars.extrusionFactor();
163 1715632 residual[scv.localDofIndex()] = std::move(source);
164 }
165
166 218701 return residual;
167 }
168
169 /*!
170 * \brief Evaluates the local source term depending on time discretization scheme
171 */
172 ElementResidualVector evalLocalSourceResidual(const Element& neighbor) const
173 285084 { return this->evalLocalSourceResidual(neighbor, implicit ? this->curElemVolVars() : this->prevElemVolVars()); }
174
175 /*!
176 * \brief Prepares all local views necessary for local assembly.
177 */
178 5882290 void bindLocalViews()
179 {
180 // get some references for convenience
181 5882290 const auto& element = this->element();
182 11764580 const auto& curSol = this->curSol(domainId);
183 11764580 auto&& fvGeometry = this->fvGeometry();
184 5882290 auto&& curElemVolVars = this->curElemVolVars();
185 5882290 auto&& elemFluxVarsCache = this->elemFluxVarsCache();
186
187 // bind the caches
188 5882290 couplingManager_.bindCouplingContext(domainId, element, this->assembler());
189 5882290 fvGeometry.bind(element);
190
191 if constexpr (implicit)
192 {
193 3854290 curElemVolVars.bind(element, fvGeometry, curSol);
194 3854290 elemFluxVarsCache.bind(element, fvGeometry, curElemVolVars);
195
4/4
✓ Branch 0 taken 873254 times.
✓ Branch 1 taken 1594819 times.
✓ Branch 2 taken 873254 times.
✓ Branch 3 taken 1594819 times.
7708580 if (!this->assembler().isStationaryProblem())
196 4160816 this->prevElemVolVars().bindElement(element, fvGeometry, this->assembler().prevSol()[domainId]);
197 }
198 else
199 {
200 2028000 auto& prevElemVolVars = this->prevElemVolVars();
201 4056000 const auto& prevSol = this->assembler().prevSol()[domainId];
202
203 2028000 curElemVolVars.bindElement(element, fvGeometry, curSol);
204 2028000 prevElemVolVars.bind(element, fvGeometry, prevSol);
205 2028000 elemFluxVarsCache.bind(element, fvGeometry, prevElemVolVars);
206 }
207
208 11764580 this->elemBcTypes().update(problem(), this->element(), this->fvGeometry());
209 5882290 }
210
211 //! return reference to the underlying problem
212 template<std::size_t i = domainId>
213 const Problem& problem(Dune::index_constant<i> dId = domainId) const
214
31/48
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✓ Branch 2 taken 12676 times.
✓ Branch 3 taken 12743 times.
✓ Branch 4 taken 1319 times.
✓ Branch 5 taken 23 times.
✓ Branch 6 taken 8 times.
✓ Branch 7 taken 4 times.
✓ Branch 8 taken 26 times.
✓ Branch 9 taken 10 times.
✓ Branch 10 taken 3 times.
✓ Branch 11 taken 25 times.
✓ Branch 12 taken 4 times.
✓ Branch 13 taken 4 times.
✓ Branch 14 taken 7 times.
✓ Branch 15 taken 22 times.
✓ Branch 16 taken 5 times.
✓ Branch 17 taken 2 times.
✓ Branch 18 taken 24 times.
✓ Branch 19 taken 6 times.
✗ Branch 20 not taken.
✓ Branch 21 taken 23 times.
✓ Branch 22 taken 3 times.
✗ Branch 23 not taken.
✓ Branch 24 taken 4 times.
✓ Branch 25 taken 3 times.
✗ Branch 26 not taken.
✗ Branch 27 not taken.
✓ Branch 28 taken 2 times.
✗ Branch 29 not taken.
✗ Branch 30 not taken.
✓ Branch 31 taken 1 times.
✗ Branch 32 not taken.
✓ Branch 33 taken 1 times.
✗ Branch 34 not taken.
✓ Branch 36 taken 1 times.
✗ Branch 37 not taken.
✓ Branch 38 taken 1 times.
✓ Branch 39 taken 1 times.
✗ Branch 40 not taken.
✓ Branch 41 taken 1 times.
✗ Branch 42 not taken.
✓ Branch 46 taken 1 times.
✗ Branch 47 not taken.
✓ Branch 49 taken 1 times.
✗ Branch 50 not taken.
✗ Branch 57 not taken.
✗ Branch 58 not taken.
18358684 { return this->assembler().problem(domainId); }
215
216 //! return reference to the underlying problem
217 template<std::size_t i = domainId>
218 const auto& curSol(Dune::index_constant<i> dId = domainId) const
219
3/6
✗ Branch 0 not taken.
✓ Branch 1 taken 1795 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 10531 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 8736 times.
11857798 { return ParentType::curSol()[dId]; }
220
221 //! return reference to the coupling manager
222 CouplingManager& couplingManager()
223 { return couplingManager_; }
224
225 private:
226 CouplingManager& couplingManager_; //!< the coupling manager
227 };
228
229 /*!
230 * \ingroup Assembly
231 * \ingroup CVFEDiscretization
232 * \ingroup MultiDomain
233 * \brief The CVFE scheme multidomain local assembler
234 * \tparam id the id of the sub domain
235 * \tparam TypeTag the TypeTag
236 * \tparam Assembler the assembler type
237 * \tparam DM the numeric differentiation method
238 * \tparam implicit whether the assembler is explicit or implicit in time
239 */
240 template<std::size_t id, class TypeTag, class Assembler, DiffMethod DM = DiffMethod::numeric, bool implicit = true>
241 class SubDomainCVFELocalAssembler;
242
243 /*!
244 * \ingroup Assembly
245 * \ingroup CVFEDiscretization
246 * \ingroup MultiDomain
247 * \brief CVFE scheme multi domain local assembler using numeric differentiation and implicit time discretization
248 */
249 template<std::size_t id, class TypeTag, class Assembler>
250
4/16
✓ Branch 0 taken 500514 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 452090 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✓ Branch 8 taken 261056 times.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✓ Branch 12 taken 261056 times.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
3942789 class SubDomainCVFELocalAssembler<id, TypeTag, Assembler, DiffMethod::numeric, /*implicit=*/true>
251 : public SubDomainCVFELocalAssemblerBase<id, TypeTag, Assembler,
252 SubDomainCVFELocalAssembler<id, TypeTag, Assembler, DiffMethod::numeric, true>, DiffMethod::numeric, true >
253 {
254 using ThisType = SubDomainCVFELocalAssembler<id, TypeTag, Assembler, DiffMethod::numeric, /*implicit=*/true>;
255 using ParentType = SubDomainCVFELocalAssemblerBase<id, TypeTag, Assembler, ThisType, DiffMethod::numeric, /*implicit=*/true>;
256 using Scalar = GetPropType<TypeTag, Properties::Scalar>;
257 using VolumeVariables = GetPropType<TypeTag, Properties::VolumeVariables>;
258
259 using ElementVolumeVariables = typename GetPropType<TypeTag, Properties::GridVolumeVariables>::LocalView;
260 using GridGeometry = GetPropType<TypeTag, Properties::GridGeometry>;
261 using FVElementGeometry = typename GridGeometry::LocalView;
262 using SubControlVolume = typename GridGeometry::SubControlVolume;
263 using GridView = typename GridGeometry::GridView;
264 using Element = typename GridView::template Codim<0>::Entity;
265 using Problem = GetPropType<TypeTag, Properties::Problem>;
266
267 static constexpr int numEq = GetPropType<TypeTag, Properties::ModelTraits>::numEq();
268 static constexpr int dim = GridView::dimension;
269
270 static constexpr bool enableGridFluxVarsCache = GetPropType<TypeTag, Properties::GridVariables>::GridFluxVariablesCache::cachingEnabled;
271 static constexpr bool enableGridVolVarsCache = GetPropType<TypeTag, Properties::GridVariables>::GridVolumeVariables::cachingEnabled;
272 static constexpr auto domainI = Dune::index_constant<id>();
273
274 public:
275
2/4
✓ Branch 1 taken 40 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 40 times.
✗ Branch 5 not taken.
2468113 using ParentType::ParentType;
276 //! export element residual vector type
277 using ElementResidualVector = typename ParentType::LocalResidual::ElementResidualVector;
278
279 /*!
280 * \brief Update the coupling context for coupled models.
281 */
282 template<class ElemSol>
283 92 void maybeUpdateCouplingContext(const SubControlVolume& scv, ElemSol& elemSol, const int pvIdx)
284 {
285
6/10
✗ Branch 0 not taken.
✓ Branch 1 taken 37792 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 80 times.
✓ Branch 4 taken 37712 times.
✓ Branch 5 taken 80 times.
✓ Branch 9 taken 18528 times.
✗ Branch 10 not taken.
✓ Branch 12 taken 18528 times.
✗ Branch 13 not taken.
50897172 this->couplingManager().updateCouplingContext(domainI, *this, domainI, scv.dofIndex(), elemSol[scv.localDofIndex()], pvIdx);
286 92 }
287
288 /*!
289 * \brief Update the additional domain derivatives for coupled models.
290 */
291 template<class JacobianMatrixDiagBlock, class GridVariables>
292 void maybeEvalAdditionalDomainDerivatives(const ElementResidualVector& origResiduals, JacobianMatrixDiagBlock& A, GridVariables& gridVariables)
293 {
294 1432826 this->couplingManager().evalAdditionalDomainDerivatives(domainI, *this, origResiduals, A, gridVariables);
295 }
296
297 /*!
298 * \brief Computes the derivatives with respect to the given element and adds them
299 * to the global matrix.
300 */
301 template<std::size_t otherId, class JacobianBlock, class GridVariables>
302 2313152 void assembleJacobianCoupling(Dune::index_constant<otherId> domainJ, JacobianBlock& A,
303 const ElementResidualVector& res, GridVariables& gridVariables)
304 {
305 ////////////////////////////////////////////////////////////////////////////////////////////////////////
306 // Calculate derivatives of all dofs in the element with respect to all dofs in the coupling stencil. //
307 ////////////////////////////////////////////////////////////////////////////////////////////////////////
308
309 // get some aliases for convenience
310 2313152 const auto& element = this->element();
311 2313152 const auto& fvGeometry = this->fvGeometry();
312 2313152 auto&& curElemVolVars = this->curElemVolVars();
313 2313152 auto&& elemFluxVarsCache = this->elemFluxVarsCache();
314
315 // convenience lambda for call to update self
316 11542875 auto updateCoupledVariables = [&] ()
317 {
318 // Update ourself after the context has been modified. Depending on the
319 // type of caching, other objects might have to be updated. All ifs can be optimized away.
320 if constexpr (enableGridFluxVarsCache)
321 {
322 if constexpr (enableGridVolVarsCache)
323 8322665 this->couplingManager().updateCoupledVariables(domainI, *this, gridVariables.curGridVolVars(), gridVariables.gridFluxVarsCache());
324 else
325 this->couplingManager().updateCoupledVariables(domainI, *this, curElemVolVars, gridVariables.gridFluxVarsCache());
326 }
327 else
328 {
329 if constexpr (enableGridVolVarsCache)
330 this->couplingManager().updateCoupledVariables(domainI, *this, gridVariables.curGridVolVars(), elemFluxVarsCache);
331 else
332 907358 this->couplingManager().updateCoupledVariables(domainI, *this, curElemVolVars, elemFluxVarsCache);
333 }
334 };
335
336 // get element stencil information
337 2313152 const auto& stencil = this->couplingManager().couplingStencil(domainI, element, domainJ);
338 2313152 const auto& curSolJ = this->curSol(domainJ);
339
4/4
✓ Branch 0 taken 2716822 times.
✓ Branch 1 taken 1440925 times.
✓ Branch 2 taken 2716522 times.
✓ Branch 3 taken 1440625 times.
12522663 for (const auto globalJ : stencil)
340 {
341 // undeflected privars and privars to be deflected
342
1/3
✗ Branch 0 not taken.
✓ Branch 1 taken 2716822 times.
✗ Branch 2 not taken.
5103491 const auto origPriVarsJ = curSolJ[globalJ];
343 5103491 auto priVarsJ = origPriVarsJ;
344
345 // the undeflected coupling residual
346
1/3
✗ Branch 0 not taken.
✓ Branch 1 taken 2716822 times.
✗ Branch 2 not taken.
5103491 const auto origResidual = this->couplingManager().evalCouplingResidual(domainI, *this, domainJ, globalJ);
347
348
2/2
✓ Branch 0 taken 4126832 times.
✓ Branch 1 taken 2716822 times.
13027002 for (int pvIdx = 0; pvIdx < JacobianBlock::block_type::cols; ++pvIdx)
349 {
350 21843476 auto evalCouplingResidual = [&](Scalar priVar)
351 {
352 3492464 priVarsJ[pvIdx] = priVar;
353 4126832 this->couplingManager().updateCouplingContext(domainI, *this, domainJ, globalJ, priVarsJ, pvIdx);
354
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 33 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 33 times.
4124528 updateCoupledVariables();
355
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 33 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 33 times.
4126832 return this->couplingManager().evalCouplingResidual(domainI, *this, domainJ, globalJ);
356 };
357
358 // derive the residuals numerically
359
4/4
✓ Branch 0 taken 47 times.
✓ Branch 1 taken 1625181 times.
✓ Branch 2 taken 47 times.
✓ Branch 3 taken 1625181 times.
15847022 ElementResidualVector partialDerivs(fvGeometry.numScv());
360
361
4/4
✓ Branch 0 taken 76 times.
✓ Branch 1 taken 4126756 times.
✓ Branch 2 taken 76 times.
✓ Branch 3 taken 4126756 times.
15847022 const auto& paramGroup = this->assembler().problem(domainJ).paramGroup();
362
5/6
✓ Branch 0 taken 76 times.
✓ Branch 1 taken 4126756 times.
✓ Branch 3 taken 75 times.
✓ Branch 4 taken 1 times.
✓ Branch 6 taken 75 times.
✗ Branch 7 not taken.
7923511 static const int numDiffMethod = getParamFromGroup<int>(paramGroup, "Assembly.NumericDifferenceMethod");
363
4/6
✓ Branch 0 taken 75 times.
✓ Branch 1 taken 4126757 times.
✓ Branch 3 taken 75 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 75 times.
✗ Branch 7 not taken.
7923511 static const auto epsCoupl = this->couplingManager().numericEpsilon(domainJ, paramGroup);
364
365
2/4
✓ Branch 1 taken 4126832 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2779368 times.
✗ Branch 5 not taken.
13482247 NumericDifferentiation::partialDerivative(evalCouplingResidual, origPriVarsJ[pvIdx], partialDerivs, origResidual,
366 13482247 epsCoupl(origPriVarsJ[pvIdx], pvIdx), numDiffMethod);
367
368 // update the global stiffness matrix with the current partial derivatives
369
4/4
✓ Branch 0 taken 14597642 times.
✓ Branch 1 taken 4126832 times.
✓ Branch 2 taken 13987086 times.
✓ Branch 3 taken 3821554 times.
43649800 for (const auto& scv : scvs(fvGeometry))
370 {
371
2/2
✓ Branch 0 taken 19893030 times.
✓ Branch 1 taken 14597642 times.
65565872 for (int eqIdx = 0; eqIdx < numEq; eqIdx++)
372 {
373 // A[i][col][eqIdx][pvIdx] is the rate of change of
374 // the residual of equation 'eqIdx' at dof 'i'
375 // depending on the primary variable 'pvIdx' at dof
376 // 'col'.
377
9/13
✓ Branch 1 taken 19893030 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 19893030 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 19893030 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 9425632 times.
✓ Branch 10 taken 10467398 times.
✓ Branch 11 taken 8540432 times.
✓ Branch 12 taken 837596 times.
✓ Branch 13 taken 9627962 times.
✗ Branch 14 not taken.
✓ Branch 15 taken 648240 times.
132680968 A[scv.dofIndex()][globalJ][eqIdx][pvIdx] += partialDerivs[scv.localDofIndex()][eqIdx];
378
379 // If the dof is coupled by a Dirichlet condition,
380 // set the derived value only once (i.e. overwrite existing values).
381
4/4
✓ Branch 0 taken 10096924 times.
✓ Branch 1 taken 9796106 times.
✓ Branch 2 taken 10096924 times.
✓ Branch 3 taken 9796106 times.
75526188 if (this->elemBcTypes().hasDirichlet())
382 {
383 2710328 const auto bcTypes = this->elemBcTypes().get(fvGeometry, scv);
384
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 724236 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 724236 times.
2711192 if (bcTypes.isCouplingDirichlet(eqIdx))
385 A[scv.dofIndex()][globalJ][eqIdx][pvIdx] = partialDerivs[scv.localDofIndex()][eqIdx];
386
2/2
✓ Branch 0 taken 306422 times.
✓ Branch 1 taken 417814 times.
1355596 else if (bcTypes.isDirichlet(eqIdx))
387
2/4
✓ Branch 1 taken 306422 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 306422 times.
✗ Branch 5 not taken.
1178436 A[scv.dofIndex()][globalJ][eqIdx][pvIdx] = 0.0;
388 }
389
390 // enforce internal Dirichlet constraints
391 if constexpr (Problem::enableInternalDirichletConstraints())
392 {
393
2/4
✓ Branch 1 taken 115200 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 115200 times.
✗ Branch 5 not taken.
460800 const auto internalDirichletConstraints = this->problem().hasInternalDirichletConstraint(this->element(), scv);
394
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 115200 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 115200 times.
460800 if (internalDirichletConstraints[eqIdx])
395 A[scv.dofIndex()][globalJ][eqIdx][pvIdx] = 0.0;
396 }
397
398 }
399 }
400
401 // restore the current element solution
402
2/4
✓ Branch 1 taken 340524 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 340524 times.
✗ Branch 5 not taken.
13482247 priVarsJ[pvIdx] = origPriVarsJ[pvIdx];
403
404 // restore the undeflected state of the coupling context
405
1/2
✓ Branch 1 taken 1539436 times.
✗ Branch 2 not taken.
12952559 this->couplingManager().updateCouplingContext(domainI, *this, domainJ, globalJ, priVarsJ, pvIdx);
406 }
407
408 // Restore original state of the flux vars cache and/or vol vars.
409 // This has to be done in case they depend on variables of domainJ before
410 // we continue with the numeric derivative w.r.t the next globalJ. Otherwise,
411 // the next "origResidual" will be incorrect.
412
1/2
✓ Branch 1 taken 300 times.
✗ Branch 2 not taken.
5103491 updateCoupledVariables();
413 }
414 2313152 }
415 };
416
417 /*!
418 * \ingroup Assembly
419 * \ingroup CVFEDiscretization
420 * \ingroup MultiDomain
421 * \brief CVFE scheme multi domain local assembler using numeric differentiation and explicit time discretization
422 */
423 template<std::size_t id, class TypeTag, class Assembler>
424 1014000 class SubDomainCVFELocalAssembler<id, TypeTag, Assembler, DiffMethod::numeric, /*implicit=*/false>
425 : public SubDomainCVFELocalAssemblerBase<id, TypeTag, Assembler,
426 SubDomainCVFELocalAssembler<id, TypeTag, Assembler, DiffMethod::numeric, false>, DiffMethod::numeric, false >
427 {
428 using ThisType = SubDomainCVFELocalAssembler<id, TypeTag, Assembler, DiffMethod::numeric, /*implicit=*/false>;
429 using ParentType = SubDomainCVFELocalAssemblerBase<id, TypeTag, Assembler, ThisType, DiffMethod::numeric, /*implicit=*/false>;
430
431 public:
432 1014000 using ParentType::ParentType;
433 //! export element residual vector type
434 using ElementResidualVector = typename ParentType::LocalResidual::ElementResidualVector;
435
436 /*!
437 * \brief Computes the coupling derivatives with respect to the given element and adds them
438 * to the global matrix.
439 * \note Since the coupling can only enter sources or fluxes and these are evaluated on
440 * the old time level (explicit scheme), the coupling blocks are empty.
441 */
442 template<std::size_t otherId, class JacobianBlock, class GridVariables>
443 void assembleJacobianCoupling(Dune::index_constant<otherId> domainJ, JacobianBlock& A,
444 const ElementResidualVector& res, GridVariables& gridVariables)
445 {}
446 };
447
448 } // end namespace Dumux
449
450 #endif
451