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 Experimental | ||
10 | * \ingroup Assembly | ||
11 | * \ingroup CVFEDiscretization | ||
12 | * \ingroup MultiDomain | ||
13 | * \brief An assembler for Jacobian and residual contribution per element (CVFE methods) for multidomain problems | ||
14 | */ | ||
15 | #ifndef DUMUX_EXPERIMENTAL_SUBDOMAIN_CVFE_LOCAL_ASSEMBLER_HH | ||
16 | #define DUMUX_EXPERIMENTAL_SUBDOMAIN_CVFE_LOCAL_ASSEMBLER_HH | ||
17 | |||
18 | #include <type_traits> | ||
19 | |||
20 | #include <dune/common/reservedvector.hh> | ||
21 | #include <dune/common/indices.hh> | ||
22 | #include <dune/common/hybridutilities.hh> | ||
23 | #include <dune/grid/common/gridenums.hh> // for GhostEntity | ||
24 | #include <dune/istl/matrixindexset.hh> | ||
25 | |||
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/discretization/extrusion.hh> | ||
34 | |||
35 | #include <dumux/experimental/assembly/cvfelocalassembler.hh> | ||
36 | |||
37 | namespace Dumux::Experimental { | ||
38 | |||
39 | /*! | ||
40 | * \ingroup Experimental | ||
41 | * \ingroup Assembly | ||
42 | * \ingroup CVFEDiscretization | ||
43 | * \ingroup MultiDomain | ||
44 | * \brief A base class for all CVFE subdomain local assemblers | ||
45 | * \tparam id the id of the sub domain | ||
46 | * \tparam TypeTag the TypeTag | ||
47 | * \tparam Assembler the assembler type | ||
48 | * \tparam Implementation the actual implementation type | ||
49 | */ | ||
50 | template<std::size_t id, class TypeTag, class Assembler, class Implementation, DiffMethod dm> | ||
51 | 9472 | class SubDomainCVFELocalAssemblerBase : public Experimental::CVFELocalAssembler<TypeTag, Assembler, dm, Implementation> | |
52 | { | ||
53 | using ParentType = Experimental::CVFELocalAssembler<TypeTag, Assembler, dm, Implementation>; | ||
54 | |||
55 | using Problem = GetPropType<TypeTag, Properties::Problem>; | ||
56 | using LocalResidualValues = Dumux::NumEqVector<GetPropType<TypeTag, Properties::PrimaryVariables>>; | ||
57 | using JacobianMatrix = GetPropType<TypeTag, Properties::JacobianMatrix>; | ||
58 | using SolutionVector = typename Assembler::SolutionVector; | ||
59 | using ElementBoundaryTypes = GetPropType<TypeTag, Properties::ElementBoundaryTypes>; | ||
60 | |||
61 | using GridVariables = GetPropType<TypeTag, Properties::GridVariables>; | ||
62 | using GridVolumeVariables = typename GridVariables::GridVolumeVariables; | ||
63 | using ElementVolumeVariables = typename GridVolumeVariables::LocalView; | ||
64 | using ElementFluxVariablesCache = typename GridVariables::GridFluxVariablesCache::LocalView; | ||
65 | using Scalar = typename GridVariables::Scalar; | ||
66 | |||
67 | using GridGeometry = typename GridVariables::GridGeometry; | ||
68 | using FVElementGeometry = typename GridGeometry::LocalView; | ||
69 | using SubControlVolume = typename GridGeometry::SubControlVolume; | ||
70 | using SubControlVolumeFace = typename GridGeometry::SubControlVolumeFace; | ||
71 | using Extrusion = Extrusion_t<GridGeometry>; | ||
72 | using GridView = typename GridGeometry::GridView; | ||
73 | using Element = typename GridView::template Codim<0>::Entity; | ||
74 | |||
75 | using CouplingManager = typename Assembler::CouplingManager; | ||
76 | |||
77 | static constexpr auto numEq = GetPropType<TypeTag, Properties::ModelTraits>::numEq(); | ||
78 | |||
79 | public: | ||
80 | //! export the domain id of this sub-domain | ||
81 | static constexpr auto domainId = typename Dune::index_constant<id>(); | ||
82 | //! pull up constructor of parent class | ||
83 | using ParentType::ParentType; | ||
84 | //! export element residual vector type | ||
85 | using ElementResidualVector = typename ParentType::LocalResidual::ElementResidualVector; | ||
86 | |||
87 | // the constructor | ||
88 | 4736 | explicit SubDomainCVFELocalAssemblerBase( | |
89 | const Assembler& assembler, | ||
90 | const Element& element, | ||
91 | const SolutionVector& curSol, | ||
92 | CouplingManager& couplingManager | ||
93 | ) | ||
94 | : ParentType(assembler, | ||
95 | element, | ||
96 | curSol, | ||
97 | localView(assembler.gridGeometry(domainId)), | ||
98 |
1/2✓ Branch 1 taken 4736 times.
✗ Branch 2 not taken.
|
4736 | localView(assembler.gridVariables(domainId).curGridVolVars()), |
99 |
2/4✓ Branch 1 taken 4736 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 4736 times.
✗ Branch 5 not taken.
|
9472 | localView(assembler.gridVariables(domainId).gridFluxVarsCache()), |
100 | assembler.localResidual(domainId), | ||
101 | 9472 | (element.partitionType() == Dune::GhostEntity), | |
102 | assembler.isImplicit()) | ||
103 |
8/18✓ Branch 3 taken 4736 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 4736 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 4736 times.
✗ Branch 10 not taken.
✓ Branch 12 taken 4736 times.
✗ Branch 13 not taken.
✓ Branch 15 taken 4736 times.
✗ Branch 16 not taken.
✓ Branch 18 taken 4736 times.
✗ Branch 19 not taken.
✓ Branch 21 taken 4736 times.
✗ Branch 22 not taken.
✗ Branch 24 not taken.
✓ Branch 25 taken 4736 times.
✗ Branch 28 not taken.
✗ Branch 29 not taken.
|
4736 | , couplingManager_(couplingManager) |
104 | 4736 | {} | |
105 | |||
106 | /*! | ||
107 | * \brief Computes the derivatives with respect to the given element and adds them | ||
108 | * to the global matrix. The element residual is written into the right hand side. | ||
109 | */ | ||
110 | template<class JacobianMatrixRow, class SubResidualVector, class GridVariablesTuple, class StageParams> | ||
111 | void assembleJacobianAndResidual(JacobianMatrixRow& jacRow, SubResidualVector& res, GridVariablesTuple& gridVariables, | ||
112 | const StageParams& stageParams, SubResidualVector& temporal, SubResidualVector& spatial, | ||
113 | SubResidualVector& constrainedDofs) | ||
114 | { | ||
115 | 6912 | auto assembleCouplingBlocks = [&](const auto& residual) | |
116 | { | ||
117 | // assemble the coupling blocks | ||
118 | using namespace Dune::Hybrid; | ||
119 | 6912 | forEach(integralRange(Dune::Hybrid::size(jacRow)), [&](auto&& i) | |
120 | { | ||
121 | 3456 | if constexpr (std::decay_t<decltype(i)>{} != id) | |
122 | ✗ | this->assembleJacobianCoupling(i, jacRow, residual, gridVariables); | |
123 | }); | ||
124 | }; | ||
125 | |||
126 | // the coupled model does not support partial reassembly yet | ||
127 | 3456 | const DefaultPartialReassembler* noReassembler = nullptr; | |
128 | 6912 | ParentType::assembleJacobianAndResidual( | |
129 |
1/2✓ Branch 1 taken 3456 times.
✗ Branch 2 not taken.
|
3456 | jacRow[domainId], res, |
130 |
3/6✓ Branch 1 taken 3456 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 3456 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 3456 times.
✗ Branch 8 not taken.
|
10368 | *std::get<domainId>(gridVariables), |
131 | stageParams, temporal, spatial, | ||
132 | constrainedDofs, | ||
133 | noReassembler, | ||
134 | assembleCouplingBlocks | ||
135 | ); | ||
136 | } | ||
137 | |||
138 | /*! | ||
139 | * \brief Assemble the entries in a coupling block of the jacobian. | ||
140 | * There is no coupling block between a domain and itself. | ||
141 | */ | ||
142 | template<std::size_t otherId, class JacRow, class GridVariables> | ||
143 | ✗ | void assembleJacobianCoupling(Dune::index_constant<otherId> domainJ, JacRow& jacRow, | |
144 | const ElementResidualVector& res, GridVariables& gridVariables) | ||
145 | { | ||
146 | if constexpr (id != otherId) | ||
147 |
0/24✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
✗ Branch 21 not taken.
✗ Branch 22 not taken.
✗ Branch 24 not taken.
✗ Branch 25 not taken.
✗ Branch 27 not taken.
✗ Branch 28 not taken.
✗ Branch 30 not taken.
✗ Branch 31 not taken.
✗ Branch 33 not taken.
✗ Branch 34 not taken.
✗ Branch 36 not taken.
✗ Branch 37 not taken.
✗ Branch 39 not taken.
✗ Branch 40 not taken.
✗ Branch 42 not taken.
✗ Branch 43 not taken.
|
13824 | this->asImp_().assembleJacobianCoupling(domainJ, jacRow[domainJ], res, *std::get<domainId>(gridVariables)); |
148 | ✗ | } | |
149 | |||
150 | /*! | ||
151 | * \brief Prepares all local views necessary for local assembly. | ||
152 | */ | ||
153 | 4736 | void bindLocalViews() | |
154 | { | ||
155 | // get some references for convenience | ||
156 | 4736 | const auto& element = this->element(); | |
157 | 9472 | const auto& curSol = this->curSol(domainId); | |
158 | 9472 | auto&& fvGeometry = this->fvGeometry(); | |
159 | 4736 | auto&& curElemVolVars = this->curElemVolVars(); | |
160 | 4736 | auto&& elemFluxVarsCache = this->elemFluxVarsCache(); | |
161 | |||
162 | // bind the caches | ||
163 | 4736 | couplingManager_.bindCouplingContext(domainId, element, this->assembler()); | |
164 | 4736 | fvGeometry.bind(element); | |
165 |
3/6✗ Branch 0 not taken.
✓ Branch 1 taken 4736 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 4736 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 4736 times.
|
14208 | if (std::abs(this->localResidual().spatialWeight()) < 1e-6) |
166 | ✗ | curElemVolVars.bindElement(element, fvGeometry, curSol); | |
167 | else | ||
168 | { | ||
169 | 4736 | curElemVolVars.bind(element, fvGeometry, curSol); | |
170 | 4736 | elemFluxVarsCache.bind(element, fvGeometry, curElemVolVars); | |
171 | } | ||
172 | |||
173 | 9472 | this->elemBcTypes().update(problem(), this->element(), this->fvGeometry()); | |
174 | 4736 | } | |
175 | |||
176 | //! return reference to the underlying problem | ||
177 | template<std::size_t i = domainId> | ||
178 | ✗ | const Problem& problem(Dune::index_constant<i> dId = domainId) const | |
179 |
3/10✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✓ Branch 10 taken 2 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 2 times.
✗ Branch 14 not taken.
✓ Branch 16 taken 2 times.
✗ Branch 17 not taken.
|
155078 | { return this->assembler().problem(domainId); } |
180 | |||
181 | //! return reference to the underlying problem | ||
182 | template<std::size_t i = domainId> | ||
183 | ✗ | const auto& curSol(Dune::index_constant<i> dId = domainId) const | |
184 |
4/4✓ Branch 2 taken 2 times.
✓ Branch 3 taken 3454 times.
✓ Branch 4 taken 2 times.
✓ Branch 5 taken 3454 times.
|
16384 | { return ParentType::curSol()[dId]; } |
185 | |||
186 | //! return reference to the coupling manager | ||
187 | ✗ | CouplingManager& couplingManager() | |
188 | ✗ | { return couplingManager_; } | |
189 | |||
190 | private: | ||
191 | CouplingManager& couplingManager_; //!< the coupling manager | ||
192 | }; | ||
193 | |||
194 | /*! | ||
195 | * \ingroup Experimental | ||
196 | * \ingroup Assembly | ||
197 | * \ingroup CVFEDiscretization | ||
198 | * \ingroup MultiDomain | ||
199 | * \brief The CVFE scheme multidomain local assembler | ||
200 | * \tparam id the id of the sub domain | ||
201 | * \tparam TypeTag the TypeTag | ||
202 | * \tparam Assembler the assembler type | ||
203 | * \tparam DM the numeric differentiation method | ||
204 | */ | ||
205 | template<std::size_t id, class TypeTag, class Assembler, DiffMethod DM = DiffMethod::numeric> | ||
206 | class SubDomainCVFELocalAssembler; | ||
207 | |||
208 | /*! | ||
209 | * \ingroup Experimental | ||
210 | * \ingroup Assembly | ||
211 | * \ingroup CVFEDiscretization | ||
212 | * \ingroup MultiDomain | ||
213 | * \brief CVFE scheme multi domain local assembler using numeric differentiation | ||
214 | */ | ||
215 | template<std::size_t id, class TypeTag, class Assembler> | ||
216 | 4736 | class SubDomainCVFELocalAssembler<id, TypeTag, Assembler, DiffMethod::numeric> | |
217 | : public SubDomainCVFELocalAssemblerBase<id, TypeTag, Assembler, | ||
218 | SubDomainCVFELocalAssembler<id, TypeTag, Assembler, DiffMethod::numeric>, DiffMethod::numeric> | ||
219 | { | ||
220 | using ThisType = SubDomainCVFELocalAssembler<id, TypeTag, Assembler, DiffMethod::numeric>; | ||
221 | using ParentType = SubDomainCVFELocalAssemblerBase<id, TypeTag, Assembler, ThisType, DiffMethod::numeric>; | ||
222 | using Scalar = GetPropType<TypeTag, Properties::Scalar>; | ||
223 | using VolumeVariables = GetPropType<TypeTag, Properties::VolumeVariables>; | ||
224 | |||
225 | using ElementVolumeVariables = typename GetPropType<TypeTag, Properties::GridVolumeVariables>::LocalView; | ||
226 | using GridGeometry = GetPropType<TypeTag, Properties::GridGeometry>; | ||
227 | using FVElementGeometry = typename GridGeometry::LocalView; | ||
228 | using SubControlVolume = typename GridGeometry::SubControlVolume; | ||
229 | using GridView = typename GridGeometry::GridView; | ||
230 | using Element = typename GridView::template Codim<0>::Entity; | ||
231 | using Problem = GetPropType<TypeTag, Properties::Problem>; | ||
232 | |||
233 | static constexpr int numEq = GetPropType<TypeTag, Properties::ModelTraits>::numEq(); | ||
234 | static constexpr int dim = GridView::dimension; | ||
235 | |||
236 | static constexpr bool enableGridFluxVarsCache = GetPropType<TypeTag, Properties::GridVariables>::GridFluxVariablesCache::cachingEnabled; | ||
237 | static constexpr bool enableGridVolVarsCache = GetPropType<TypeTag, Properties::GridVariables>::GridVolumeVariables::cachingEnabled; | ||
238 | static constexpr auto domainI = Dune::index_constant<id>(); | ||
239 | |||
240 | public: | ||
241 | 4736 | using ParentType::ParentType; | |
242 | //! export element residual vector type | ||
243 | using ElementResidualVector = typename ParentType::LocalResidual::ElementResidualVector; | ||
244 | |||
245 | /*! | ||
246 | * \brief Update the coupling context for coupled models. | ||
247 | */ | ||
248 | template<class ElemSol> | ||
249 | 165888 | void maybeUpdateCouplingContext(const SubControlVolume& scv, ElemSol& elemSol, const int pvIdx) | |
250 | { | ||
251 |
1/2✓ Branch 1 taken 165888 times.
✗ Branch 2 not taken.
|
165888 | if (this->assembler().isImplicit()) |
252 | 331776 | this->couplingManager().updateCouplingContext(domainI, *this, domainI, scv.dofIndex(), elemSol[scv.localDofIndex()], pvIdx); | |
253 | 165888 | } | |
254 | |||
255 | /*! | ||
256 | * \brief Update the additional domain derivatives for coupled models. | ||
257 | */ | ||
258 | template<class JacobianMatrixDiagBlock, class GridVariables> | ||
259 | ✗ | void maybeEvalAdditionalDomainDerivatives(const ElementResidualVector& origResiduals, JacobianMatrixDiagBlock& A, GridVariables& gridVariables) | |
260 | { | ||
261 | 3456 | if (this->assembler().isImplicit()) | |
262 | this->couplingManager().evalAdditionalDomainDerivatives(domainI, *this, origResiduals, A, gridVariables); | ||
263 | ✗ | } | |
264 | |||
265 | /*! | ||
266 | * \brief Computes the derivatives with respect to the given element and adds them | ||
267 | * to the global matrix. | ||
268 | */ | ||
269 | template<std::size_t otherId, class JacobianBlock, class GridVariables> | ||
270 | 3456 | void assembleJacobianCoupling(Dune::index_constant<otherId> domainJ, JacobianBlock& A, | |
271 | const ElementResidualVector& res, GridVariables& gridVariables) | ||
272 | { | ||
273 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 3456 times.
|
3456 | if (!this->assembler().isImplicit()) |
274 | ✗ | return; | |
275 | |||
276 | //////////////////////////////////////////////////////////////////////////////////////////////////////// | ||
277 | // Calculate derivatives of all dofs in the element with respect to all dofs in the coupling stencil. // | ||
278 | //////////////////////////////////////////////////////////////////////////////////////////////////////// | ||
279 | |||
280 | // get some aliases for convenience | ||
281 | 3456 | const auto& element = this->element(); | |
282 | 3456 | const auto& fvGeometry = this->fvGeometry(); | |
283 | 3456 | auto&& curElemVolVars = this->curElemVolVars(); | |
284 | 3456 | auto&& elemFluxVarsCache = this->elemFluxVarsCache(); | |
285 | |||
286 | // convenience lambda for call to update self | ||
287 | 3456 | auto updateCoupledVariables = [&] () | |
288 | { | ||
289 | // Update ourself after the context has been modified. Depending on the | ||
290 | // type of caching, other objects might have to be updated. All ifs can be optimized away. | ||
291 | if constexpr (enableGridFluxVarsCache) | ||
292 | { | ||
293 | if constexpr (enableGridVolVarsCache) | ||
294 | this->couplingManager().updateCoupledVariables(domainI, *this, gridVariables.curGridVolVars(), gridVariables.gridFluxVarsCache()); | ||
295 | else | ||
296 | this->couplingManager().updateCoupledVariables(domainI, *this, curElemVolVars, gridVariables.gridFluxVarsCache()); | ||
297 | } | ||
298 | else | ||
299 | { | ||
300 | if constexpr (enableGridVolVarsCache) | ||
301 | this->couplingManager().updateCoupledVariables(domainI, *this, gridVariables.curGridVolVars(), elemFluxVarsCache); | ||
302 | else | ||
303 | 3456 | this->couplingManager().updateCoupledVariables(domainI, *this, curElemVolVars, elemFluxVarsCache); | |
304 | } | ||
305 | }; | ||
306 | |||
307 | // get element stencil information | ||
308 | 3456 | const auto& stencil = this->couplingManager().couplingStencil(domainI, element, domainJ); | |
309 | 3456 | const auto& curSolJ = this->curSol(domainJ); | |
310 |
2/2✓ Branch 0 taken 3456 times.
✓ Branch 1 taken 3456 times.
|
13824 | for (const auto globalJ : stencil) |
311 | { | ||
312 | // undeflected privars and privars to be deflected | ||
313 |
1/2✓ Branch 1 taken 3456 times.
✗ Branch 2 not taken.
|
3456 | const auto origPriVarsJ = curSolJ[globalJ]; |
314 | 3456 | auto priVarsJ = origPriVarsJ; | |
315 | |||
316 | // the undeflected coupling residual | ||
317 |
1/2✓ Branch 1 taken 3456 times.
✗ Branch 2 not taken.
|
3456 | const auto origResidual = this->couplingManager().evalCouplingResidual(domainI, *this, domainJ, globalJ); |
318 | |||
319 |
2/2✓ Branch 0 taken 6912 times.
✓ Branch 1 taken 3456 times.
|
10368 | for (int pvIdx = 0; pvIdx < JacobianBlock::block_type::cols; ++pvIdx) |
320 | { | ||
321 | 34560 | auto evalCouplingResidual = [&](Scalar priVar) | |
322 | { | ||
323 | 6912 | priVarsJ[pvIdx] = priVar; | |
324 | 6912 | this->couplingManager().updateCouplingContext(domainI, *this, domainJ, globalJ, priVarsJ, pvIdx); | |
325 | 6912 | updateCoupledVariables(); | |
326 | 6912 | return this->couplingManager().evalCouplingResidual(domainI, *this, domainJ, globalJ); | |
327 | }; | ||
328 | |||
329 | // derive the residuals numerically | ||
330 |
4/4✓ Branch 0 taken 2 times.
✓ Branch 1 taken 6910 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 6910 times.
|
13824 | ElementResidualVector partialDerivs(fvGeometry.numScv()); |
331 | |||
332 |
4/4✓ Branch 0 taken 2 times.
✓ Branch 1 taken 6910 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 6910 times.
|
13824 | const auto& paramGroup = this->assembler().problem(domainJ).paramGroup(); |
333 |
4/6✓ Branch 0 taken 2 times.
✓ Branch 1 taken 6910 times.
✓ Branch 3 taken 2 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 2 times.
✗ Branch 7 not taken.
|
6912 | static const int numDiffMethod = getParamFromGroup<int>(paramGroup, "Assembly.NumericDifferenceMethod"); |
334 |
4/6✓ Branch 0 taken 2 times.
✓ Branch 1 taken 6910 times.
✓ Branch 3 taken 2 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 2 times.
✗ Branch 7 not taken.
|
6912 | static const auto epsCoupl = this->couplingManager().numericEpsilon(domainJ, paramGroup); |
335 | |||
336 |
2/4✓ Branch 1 taken 6912 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 6912 times.
✗ Branch 5 not taken.
|
13824 | NumericDifferentiation::partialDerivative(evalCouplingResidual, origPriVarsJ[pvIdx], partialDerivs, origResidual, |
337 | 13824 | epsCoupl(origPriVarsJ[pvIdx], pvIdx), numDiffMethod); | |
338 | |||
339 | // update the global stiffness matrix with the current partial derivatives | ||
340 |
4/4✓ Branch 0 taken 55296 times.
✓ Branch 1 taken 6912 times.
✓ Branch 2 taken 55296 times.
✓ Branch 3 taken 6912 times.
|
69120 | for (const auto& scv : scvs(fvGeometry)) |
341 | { | ||
342 |
2/2✓ Branch 0 taken 165888 times.
✓ Branch 1 taken 55296 times.
|
221184 | for (int eqIdx = 0; eqIdx < numEq; eqIdx++) |
343 | { | ||
344 | // A[i][col][eqIdx][pvIdx] is the rate of change of | ||
345 | // the residual of equation 'eqIdx' at dof 'i' | ||
346 | // depending on the primary variable 'pvIdx' at dof | ||
347 | // 'col'. | ||
348 |
8/12✓ Branch 1 taken 165888 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 165888 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 165888 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 165888 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 145152 times.
✓ Branch 13 taken 20736 times.
✓ Branch 14 taken 145152 times.
✓ Branch 15 taken 20736 times.
|
663552 | A[scv.dofIndex()][globalJ][eqIdx][pvIdx] += partialDerivs[scv.localDofIndex()][eqIdx]; |
349 | |||
350 | // If the dof is coupled by a Dirichlet condition, | ||
351 | // set the derived value only once (i.e. overwrite existing values). | ||
352 |
4/4✓ Branch 0 taken 145152 times.
✓ Branch 1 taken 20736 times.
✓ Branch 2 taken 145152 times.
✓ Branch 3 taken 20736 times.
|
331776 | if (this->elemBcTypes().hasDirichlet()) |
353 | { | ||
354 | 145152 | const auto bcTypes = this->elemBcTypes().get(fvGeometry, scv); | |
355 |
2/4✗ Branch 0 not taken.
✓ Branch 1 taken 145152 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 145152 times.
|
290304 | if (bcTypes.isCouplingDirichlet(eqIdx)) |
356 | ✗ | A[scv.dofIndex()][globalJ][eqIdx][pvIdx] = partialDerivs[scv.localDofIndex()][eqIdx]; | |
357 |
2/2✓ Branch 0 taken 95904 times.
✓ Branch 1 taken 49248 times.
|
145152 | else if (bcTypes.isDirichlet(eqIdx)) |
358 |
2/4✓ Branch 1 taken 95904 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 95904 times.
✗ Branch 5 not taken.
|
191808 | A[scv.dofIndex()][globalJ][eqIdx][pvIdx] = 0.0; |
359 | } | ||
360 | |||
361 | // enforce internal Dirichlet constraints | ||
362 | if constexpr (Problem::enableInternalDirichletConstraints()) | ||
363 | { | ||
364 | const auto internalDirichletConstraints = this->problem().hasInternalDirichletConstraint(this->element(), scv); | ||
365 | if (internalDirichletConstraints[eqIdx]) | ||
366 | A[scv.dofIndex()][globalJ][eqIdx][pvIdx] = 0.0; | ||
367 | } | ||
368 | |||
369 | } | ||
370 | } | ||
371 | |||
372 | // restore the current element solution | ||
373 |
2/4✓ Branch 1 taken 6912 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 6912 times.
✗ Branch 5 not taken.
|
13824 | priVarsJ[pvIdx] = origPriVarsJ[pvIdx]; |
374 | |||
375 | // restore the undeflected state of the coupling context | ||
376 |
1/2✓ Branch 1 taken 6912 times.
✗ Branch 2 not taken.
|
6912 | this->couplingManager().updateCouplingContext(domainI, *this, domainJ, globalJ, priVarsJ, pvIdx); |
377 | } | ||
378 | |||
379 | // Restore original state of the flux vars cache and/or vol vars. | ||
380 | // This has to be done in case they depend on variables of domainJ before | ||
381 | // we continue with the numeric derivative w.r.t the next globalJ. Otherwise, | ||
382 | // the next "origResidual" will be incorrect. | ||
383 |
1/2✓ Branch 1 taken 3456 times.
✗ Branch 2 not taken.
|
3456 | updateCoupledVariables(); |
384 | } | ||
385 | } | ||
386 | }; | ||
387 | |||
388 | } // end namespace Dumux | ||
389 | |||
390 | #endif | ||
391 |