GCC Code Coverage Report


Directory: ../../../builds/dumux-repositories/
File: /builds/dumux-repositories/dumux/dumux/experimental/assembly/subdomaincvfelocalassembler.hh
Date: 2024-09-21 20:52:54
Exec Total Coverage
Lines: 74 86 86.0%
Functions: 5 13 38.5%
Branches: 79 160 49.4%

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