GCC Code Coverage Report


Directory: ../../../builds/dumux-repositories/
File: dumux/dumux/multidomain/subdomaincvfelocalassembler.hh
Date: 2025-05-03 19:19:02
Exec Total Coverage
Lines: 101 103 98.1%
Functions: 149 152 98.0%
Branches: 106 178 59.6%

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