GCC Code Coverage Report


Directory: ../../../builds/dumux-repositories/
File: /builds/dumux-repositories/dumux/dumux/assembly/cvfelocalassembler.hh
Date: 2024-09-21 20:52:54
Exec Total Coverage
Lines: 192 201 95.5%
Functions: 754 1684 44.8%
Branches: 213 528 40.3%

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 * \brief An assembler for Jacobian and residual contribution per element (CVFE methods)
12 */
13 #ifndef DUMUX_CVFE_LOCAL_ASSEMBLER_HH
14 #define DUMUX_CVFE_LOCAL_ASSEMBLER_HH
15
16 #include <dune/common/exceptions.hh>
17 #include <dune/common/hybridutilities.hh>
18 #include <dune/common/reservedvector.hh>
19 #include <dune/grid/common/gridenums.hh>
20 #include <dune/istl/matrixindexset.hh>
21 #include <dune/istl/bvector.hh>
22
23 #include <dumux/common/properties.hh>
24 #include <dumux/common/parameters.hh>
25 #include <dumux/common/numericdifferentiation.hh>
26
27 #include <dumux/assembly/numericepsilon.hh>
28 #include <dumux/assembly/diffmethod.hh>
29 #include <dumux/assembly/fvlocalassemblerbase.hh>
30 #include <dumux/assembly/partialreassembler.hh>
31 #include <dumux/assembly/entitycolor.hh>
32
33 #include <dumux/discretization/cvfe/elementsolution.hh>
34
35 #include "volvardeflectionhelper_.hh"
36
37 namespace Dumux {
38
39 #ifndef DOXYGEN
40 namespace Detail::CVFE {
41
42 struct NoOperator
43 {
44 template<class... Args>
45 constexpr void operator()(Args&&...) const {}
46 };
47
48 template<class X, class Y>
49 using Impl = std::conditional_t<!std::is_same_v<X, void>, X, Y>;
50
51 } // end namespace Detail
52 #endif // DOXYGEN
53
54 /*!
55 * \ingroup Assembly
56 * \ingroup CVFEDiscretization
57 * \brief A base class for all local CVFE assemblers
58 * \tparam TypeTag The TypeTag
59 * \tparam Assembler The assembler type
60 * \tparam Implementation The actual implementation
61 * \tparam implicit Specifies whether the time discretization is implicit or not not (i.e. explicit)
62 */
63 template<class TypeTag, class Assembler, class Implementation, bool implicit>
64 19557523 class CVFELocalAssemblerBase : public FVLocalAssemblerBase<TypeTag, Assembler, Implementation, implicit>
65 {
66 using ParentType = FVLocalAssemblerBase<TypeTag, Assembler, Implementation, implicit>;
67 using JacobianMatrix = GetPropType<TypeTag, Properties::JacobianMatrix>;
68 using GridVariables = GetPropType<TypeTag, Properties::GridVariables>;
69 using ElementVolumeVariables = typename GridVariables::GridVolumeVariables::LocalView;
70 using SolutionVector = typename Assembler::SolutionVector;
71
72 static constexpr int numEq = GetPropType<TypeTag, Properties::ModelTraits>::numEq();
73 static constexpr int dim = GetPropType<TypeTag, Properties::GridGeometry>::GridView::dimension;
74
75 public:
76
77 18422503 using ParentType::ParentType;
78
79 13279760 void bindLocalViews()
80 {
81 13279760 ParentType::bindLocalViews();
82 53119040 this->elemBcTypes().update(this->asImp_().problem(), this->element(), this->fvGeometry());
83 13279760 }
84
85
86 /*!
87 * \brief Computes the derivatives with respect to the given element and adds them
88 * to the global matrix. The element residual is written into the right hand side.
89 */
90 template <class ResidualVector, class PartialReassembler = DefaultPartialReassembler, class CouplingFunction = Detail::CVFE::NoOperator>
91 16234847 void assembleJacobianAndResidual(JacobianMatrix& jac, ResidualVector& res, GridVariables& gridVariables,
92 const PartialReassembler* partialReassembler = nullptr,
93 const CouplingFunction& maybeAssembleCouplingBlocks = {})
94 {
95 16234847 this->asImp_().bindLocalViews();
96 64939388 const auto eIdxGlobal = this->asImp_().problem().gridGeometry().elementMapper().index(this->element());
97 if (partialReassembler
98
6/6
✓ Branch 0 taken 452312 times.
✓ Branch 1 taken 10355219 times.
✓ Branch 2 taken 101612 times.
✓ Branch 3 taken 350700 times.
✓ Branch 4 taken 101612 times.
✓ Branch 5 taken 350700 times.
11899795 && partialReassembler->elementColor(eIdxGlobal) == EntityColor::green)
99 {
100
0/2
✗ Branch 0 not taken.
✗ Branch 1 not taken.
101612 const auto residual = this->asImp_().evalLocalResidual(); // forward to the internal implementation
101
4/4
✓ Branch 0 taken 406448 times.
✓ Branch 1 taken 101612 times.
✓ Branch 2 taken 406448 times.
✓ Branch 3 taken 101612 times.
1117732 for (const auto& scv : scvs(this->fvGeometry()))
102 1625792 res[scv.dofIndex()] += residual[scv.localDofIndex()];
103
104 // assemble the coupling blocks for coupled models (does nothing if not coupled)
105 maybeAssembleCouplingBlocks(residual);
106 }
107
2/2
✓ Branch 0 taken 13151258 times.
✓ Branch 1 taken 69504 times.
16133235 else if (!this->elementIsGhost())
108 {
109 16063731 const auto residual = this->asImp_().assembleJacobianAndResidualImpl(jac, gridVariables, partialReassembler); // forward to the internal implementation
110
4/4
✓ Branch 0 taken 44447146 times.
✓ Branch 1 taken 13151258 times.
✓ Branch 2 taken 41790590 times.
✓ Branch 3 taken 11822980 times.
148781945 for (const auto& scv : scvs(this->fvGeometry()))
111 210914728 res[scv.dofIndex()] += residual[scv.localDofIndex()];
112
113 // assemble the coupling blocks for coupled models (does nothing if not coupled)
114 4180191 maybeAssembleCouplingBlocks(residual);
115 }
116 else
117 {
118 // Treatment of ghost elements
119 69504 assert(this->elementIsGhost());
120
121 // handle dofs per codimension
122
2/4
✓ Branch 1 taken 69504 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 69504 times.
✗ Branch 5 not taken.
139008 const auto& gridGeometry = this->asImp_().problem().gridGeometry();
123
1/2
✓ Branch 1 taken 69504 times.
✗ Branch 2 not taken.
434304 Dune::Hybrid::forEach(std::make_integer_sequence<int, dim>{}, [&](auto d)
124 {
125 139008 constexpr int codim = dim - d;
126 414144 const auto& localCoeffs = gridGeometry.feCache().get(this->element().type()).localCoefficients();
127
8/24
✓ Branch 0 taken 272592 times.
✓ Branch 1 taken 72696 times.
✓ Branch 2 taken 273948 times.
✓ Branch 3 taken 68148 times.
✓ Branch 4 taken 277140 times.
✓ Branch 5 taken 69504 times.
✓ Branch 6 taken 272592 times.
✓ Branch 7 taken 68148 times.
✗ 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.
693288 for (int idx = 0; idx < localCoeffs.size(); ++idx)
128 {
129 554280 const auto& localKey = localCoeffs.localKey(idx);
130
131 // skip if we are not handling this codim right now
132
8/24
✓ Branch 0 taken 4548 times.
✓ Branch 1 taken 272592 times.
✓ Branch 2 taken 4548 times.
✓ Branch 3 taken 272592 times.
✓ Branch 4 taken 272592 times.
✓ Branch 5 taken 4548 times.
✓ Branch 6 taken 272592 times.
✓ Branch 7 taken 4548 times.
✗ 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.
1108560 if (localKey.codim() != codim)
133 414792 continue;
134
135 // do not change the non-ghost entities
136
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 16 not taken.
✗ Branch 17 not taken.
690888 auto entity = this->element().template subEntity<codim>(localKey.subEntity());
137
11/47
✓ Branch 0 taken 1356 times.
✓ Branch 1 taken 3192 times.
✓ Branch 2 taken 1356 times.
✓ Branch 3 taken 3192 times.
✓ Branch 4 taken 133416 times.
✓ Branch 5 taken 133416 times.
✓ Branch 6 taken 133416 times.
✓ Branch 7 taken 133416 times.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✓ Branch 11 taken 5760 times.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✓ Branch 14 taken 2880 times.
✓ Branch 15 taken 2880 times.
✗ 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 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 37 not taken.
✗ Branch 38 not taken.
✗ Branch 39 not taken.
✗ Branch 40 not taken.
✗ Branch 42 not taken.
✗ Branch 43 not taken.
✗ Branch 44 not taken.
✗ Branch 45 not taken.
✗ Branch 47 not taken.
✗ Branch 48 not taken.
✗ Branch 50 not taken.
✗ Branch 51 not taken.
411912 if (entity.partitionType() == Dune::InteriorEntity || entity.partitionType() == Dune::BorderEntity)
138
0/8
✗ 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.
137652 continue;
139
140 // WARNING: this only works if the mapping from codim+subEntity to
141 // global dofIndex is unique (on dof per entity of this codim).
142 // For more general mappings, we should use a proper local-global mapping here.
143 // For example through dune-functions.
144
0/22
✗ 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.
✗ 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.
278976 const auto dofIndex = gridGeometry.dofMapper().index(entity);
145
146 // this might be a vector-valued dof
147 using BlockType = typename JacobianMatrix::block_type;
148
4/23
✓ Branch 1 taken 3192 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 3192 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 133416 times.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✓ Branch 10 taken 133416 times.
✗ 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.
278976 BlockType &J = jac[dofIndex][dofIndex];
149
4/12
✓ Branch 0 taken 6384 times.
✓ Branch 1 taken 3192 times.
✓ Branch 2 taken 332712 times.
✓ Branch 3 taken 136296 times.
✗ 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.
478584 for (int j = 0; j < BlockType::rows; ++j)
150 1010088 J[j][j] = 1.0;
151
152 // set residual for the ghost dof
153
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.
418464 res[dofIndex] = 0;
154 }
155 });
156 }
157
158 21245331 auto applyDirichlet = [&] (const auto& scvI,
159 const auto& dirichletValues,
160 const auto eqIdx,
161 1670160 const auto pvIdx)
162 {
163 10728280 res[scvI.dofIndex()][eqIdx] = this->curElemVolVars()[scvI].priVars()[pvIdx] - dirichletValues[pvIdx];
164
165 1670160 auto& row = jac[scvI.dofIndex()];
166
12/24
✗ Branch 0 not taken.
✓ Branch 1 taken 12384365 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 12384365 times.
✓ Branch 4 taken 10878895 times.
✓ Branch 5 taken 1505470 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 1463013 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 1463013 times.
✓ Branch 10 taken 1304531 times.
✓ Branch 11 taken 158482 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 65276 times.
✗ Branch 14 not taken.
✓ Branch 15 taken 65276 times.
✓ Branch 16 taken 59068 times.
✓ Branch 17 taken 6208 times.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
✗ Branch 22 not taken.
✗ Branch 23 not taken.
26155148 for (auto col = row.begin(); col != row.end(); ++col)
167 35319801 row[col.index()][eqIdx] = 0.0;
168
169 3340320 jac[scvI.dofIndex()][scvI.dofIndex()][eqIdx][pvIdx] = 1.0;
170
171 // if a periodic dof has Dirichlet values also apply the same Dirichlet values to the other dof
172
4/6
✓ Branch 3 taken 4 times.
✓ Branch 4 taken 815896 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 62354 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 944 times.
4782912 if (this->asImp_().problem().gridGeometry().dofOnPeriodicBoundary(scvI.dofIndex()))
173 {
174 12 const auto periodicDof = this->asImp_().problem().gridGeometry().periodicallyMappedDof(scvI.dofIndex());
175 8 res[periodicDof][eqIdx] = this->asImp_().curSol()[periodicDof][pvIdx] - dirichletValues[pvIdx];
176
177 4 auto& rowP = jac[periodicDof];
178
4/18
✗ Branch 0 not taken.
✓ Branch 1 taken 30 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 30 times.
✓ Branch 4 taken 26 times.
✓ Branch 5 taken 4 times.
✗ 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.
56 for (auto col = rowP.begin(); col != rowP.end(); ++col)
179 52 rowP[col.index()][eqIdx] = 0.0;
180
181 4 rowP[periodicDof][eqIdx][pvIdx] = 1.0;
182 }
183 };
184
185 32469694 this->asImp_().enforceDirichletConstraints(applyDirichlet);
186 16234847 }
187
188 /*!
189 * \brief Computes the derivatives with respect to the given element and adds them
190 * to the global matrix.
191 */
192 1136 void assembleJacobian(JacobianMatrix& jac, GridVariables& gridVariables)
193 {
194 1136 this->asImp_().bindLocalViews();
195 1136 this->asImp_().assembleJacobianAndResidualImpl(jac, gridVariables); // forward to the internal implementation
196
197 1472 auto applyDirichlet = [&] (const auto& scvI,
198 const auto& dirichletValues,
199 const auto eqIdx,
200 340 const auto pvIdx)
201 {
202 336 auto& row = jac[scvI.dofIndex()];
203
4/12
✗ Branch 0 not taken.
✓ Branch 1 taken 2416 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 2416 times.
✓ Branch 4 taken 2080 times.
✓ Branch 5 taken 336 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
4496 for (auto col = row.begin(); col != row.end(); ++col)
204 4160 row[col.index()][eqIdx] = 0.0;
205
206 672 jac[scvI.dofIndex()][scvI.dofIndex()][eqIdx][pvIdx] = 1.0;
207 };
208
209 2272 this->asImp_().enforceDirichletConstraints(applyDirichlet);
210 1136 }
211
212 /*!
213 * \brief Assemble the residual only
214 */
215 template <class ResidualVector>
216 2636587 void assembleResidual(ResidualVector& res)
217 {
218 2636587 this->asImp_().bindLocalViews();
219
0/2
✗ Branch 0 not taken.
✗ Branch 1 not taken.
2636587 const auto residual = this->evalLocalResidual();
220
221
4/4
✓ Branch 0 taken 8476682 times.
✓ Branch 1 taken 2172371 times.
✓ Branch 2 taken 8476682 times.
✓ Branch 3 taken 2172371 times.
28462109 for (const auto& scv : scvs(this->fvGeometry()))
222 41104696 res[scv.dofIndex()] += residual[scv.localDofIndex()];
223
224 2636587 auto applyDirichlet = [&] (const auto& scvI,
225 const auto& dirichletValues,
226 const auto eqIdx,
227 const auto pvIdx)
228 {
229 901790 res[scvI.dofIndex()][eqIdx] = this->curElemVolVars()[scvI].priVars()[pvIdx] - dirichletValues[pvIdx];
230 };
231
232 5273174 this->asImp_().enforceDirichletConstraints(applyDirichlet);
233 2636587 }
234
235 //! Enforce Dirichlet constraints
236 template<typename ApplyFunction>
237 void enforceDirichletConstraints(const ApplyFunction& applyDirichlet)
238 {
239 // enforce Dirichlet boundary conditions
240 15495881 this->asImp_().evalDirichletBoundaries(applyDirichlet);
241 // take care of internal Dirichlet constraints (if enabled)
242 13611247 this->asImp_().enforceInternalDirichletConstraints(applyDirichlet);
243 }
244
245 /*!
246 * \brief Evaluates Dirichlet boundaries
247 */
248 template< typename ApplyDirichletFunctionType >
249 30974278 void evalDirichletBoundaries(ApplyDirichletFunctionType applyDirichlet)
250 {
251 // enforce Dirichlet boundaries by overwriting partial derivatives with 1 or 0
252 // and set the residual to (privar - dirichletvalue)
253
4/4
✓ Branch 0 taken 540031 times.
✓ Branch 1 taken 14955850 times.
✓ Branch 2 taken 540031 times.
✓ Branch 3 taken 14955850 times.
61948556 if (this->elemBcTypes().hasDirichlet())
254 {
255
4/4
✓ Branch 0 taken 1853527 times.
✓ Branch 1 taken 540031 times.
✓ Branch 2 taken 1597153 times.
✓ Branch 3 taken 411844 times.
6930002 for (const auto& scvI : scvs(this->fvGeometry()))
256 {
257 11084982 const auto bcTypes = this->elemBcTypes().get(this->fvGeometry(), scvI);
258
4/4
✓ Branch 0 taken 889757 times.
✓ Branch 1 taken 963770 times.
✓ Branch 2 taken 889757 times.
✓ Branch 3 taken 963770 times.
7389988 if (bcTypes.hasDirichlet())
259 {
260
4/4
✓ Branch 0 taken 188499 times.
✓ Branch 1 taken 151905 times.
✓ Branch 2 taken 188499 times.
✓ Branch 3 taken 151905 times.
3365130 const auto dirichletValues = this->asImp_().problem().dirichlet(this->element(), scvI);
261
262 // set the Dirichlet conditions in residual and jacobian
263
3/3
✓ Branch 0 taken 1514863 times.
✓ Branch 1 taken 1043435 times.
✓ Branch 2 taken 155511 times.
5415762 for (int eqIdx = 0; eqIdx < numEq; ++eqIdx)
264 {
265
2/2
✓ Branch 0 taken 24454 times.
✓ Branch 1 taken 1799598 times.
3642176 if (bcTypes.isDirichlet(eqIdx))
266 {
267
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1799598 times.
3593268 const auto pvIdx = bcTypes.eqToDirichletIndex(eqIdx);
268
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1799598 times.
3593268 assert(0 <= pvIdx && pvIdx < numEq);
269 3593268 applyDirichlet(scvI, dirichletValues, eqIdx, pvIdx);
270 }
271 }
272 }
273 }
274 }
275 30974278 }
276
277 /*!
278 * \brief Update the coupling context for coupled models.
279 * \note This does nothing per default (not a coupled model).
280 */
281 template<class... Args>
282 void maybeUpdateCouplingContext(Args&&...) {}
283
284 /*!
285 * \brief Update the additional domain derivatives for coupled models.
286 * \note This does nothing per default (not a coupled model).
287 */
288 template<class... Args>
289 void maybeEvalAdditionalDomainDerivatives(Args&&...) {}
290 };
291
292 /*!
293 * \ingroup Assembly
294 * \ingroup CVFEDiscretization
295 * \brief An assembler for Jacobian and residual contribution per element (CVFE methods)
296 * \tparam TypeTag The TypeTag
297 * \tparam diffMethod The differentiation method to residual compute derivatives
298 * \tparam implicit Specifies whether the time discretization is implicit or not not (i.e. explicit)
299 * \tparam Implementation via CRTP
300 */
301 template<class TypeTag, class Assembler, DiffMethod diffMethod = DiffMethod::numeric, bool implicit = true, class Implementation = void>
302 class CVFELocalAssembler;
303
304 /*!
305 * \ingroup Assembly
306 * \ingroup CVFEDiscretization
307 * \brief Control volume finite element local assembler using numeric differentiation and implicit time discretization
308 */
309 template<class TypeTag, class Assembler, class Implementation>
310
4/16
✓ Branch 0 taken 2189632 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 397794 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✓ Branch 8 taken 232108 times.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✓ Branch 12 taken 232108 times.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
16273926 class CVFELocalAssembler<TypeTag, Assembler, DiffMethod::numeric, /*implicit=*/true, Implementation>
311 : public CVFELocalAssemblerBase<TypeTag, Assembler,
312 Detail::CVFE::Impl<Implementation, CVFELocalAssembler<TypeTag, Assembler, DiffMethod::numeric, true, Implementation>>,
313 true>
314 {
315 using ThisType = CVFELocalAssembler<TypeTag, Assembler, DiffMethod::numeric, true, Implementation>;
316 using ParentType = CVFELocalAssemblerBase<TypeTag, Assembler, Detail::CVFE::Impl<Implementation, ThisType>, true>;
317 using Scalar = GetPropType<TypeTag, Properties::Scalar>;
318 using GridVariables = GetPropType<TypeTag, Properties::GridVariables>;
319 using VolumeVariables = GetPropType<TypeTag, Properties::VolumeVariables>;
320 using JacobianMatrix = GetPropType<TypeTag, Properties::JacobianMatrix>;
321
322 static constexpr int numEq = GetPropType<TypeTag, Properties::ModelTraits>::numEq();
323 static constexpr int dim = GetPropType<TypeTag, Properties::GridGeometry>::GridView::dimension;
324
325 static constexpr bool enableGridFluxVarsCache
326 = GridVariables::GridFluxVariablesCache::cachingEnabled;
327 static constexpr bool solutionDependentFluxVarsCache
328 = GridVariables::GridFluxVariablesCache::FluxVariablesCache::isSolDependent;
329
330 public:
331
332 using LocalResidual = typename ParentType::LocalResidual;
333 using ElementResidualVector = typename LocalResidual::ElementResidualVector;
334
7/17
✓ Branch 1 taken 935347 times.
✓ Branch 2 taken 10149625 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 930165 times.
✓ Branch 5 taken 20800 times.
✓ Branch 6 taken 807816 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 8736 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 7708 times.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
15435668 using ParentType::ParentType;
335
336 /*!
337 * \brief Computes the derivatives with respect to the given element and adds them
338 * to the global matrix.
339 *
340 * \return The element residual at the current solution.
341 */
342 template <class PartialReassembler = DefaultPartialReassembler>
343 11887637 ElementResidualVector assembleJacobianAndResidualImpl(JacobianMatrix& A, GridVariables& gridVariables,
344 const PartialReassembler* partialReassembler = nullptr)
345 {
346 // get some aliases for convenience
347 11887637 const auto& element = this->element();
348
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 44241 times.
11887637 const auto& fvGeometry = this->fvGeometry();
349
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 443 times.
11887637 const auto& curSol = this->asImp_().curSol();
350
351
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 44241 times.
11887637 auto&& curElemVolVars = this->curElemVolVars();
352
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 44241 times.
11887637 auto&& elemFluxVarsCache = this->elemFluxVarsCache();
353
354 // get the vector of the actual element residuals
355
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 44241 times.
11887637 const auto origResiduals = this->evalLocalResidual();
356
357 //////////////////////////////////////////////////////////////////////////////////////////////////
358 // //
359 // Calculate derivatives of all dofs in stencil with respect to the dofs in the element. In the //
360 // neighboring elements we do so by computing the derivatives of the fluxes which depend on the //
361 // actual element. In the actual element we evaluate the derivative of the entire residual. //
362 // //
363 //////////////////////////////////////////////////////////////////////////////////////////////////
364
365 // if all volvars in the stencil have to be updated or if it's enough to only update the
366 // volVars for the scv whose associated dof has been deflected
367
6/8
✓ Branch 0 taken 211 times.
✓ Branch 1 taken 9988953 times.
✓ Branch 3 taken 154 times.
✓ Branch 4 taken 57 times.
✓ Branch 6 taken 154 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 142 times.
✗ Branch 10 not taken.
11887637 static const bool updateAllVolVars = getParamFromGroup<bool>(
368
2/4
✓ Branch 1 taken 154 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 12 times.
✗ Branch 5 not taken.
501 this->asImp_().problem().paramGroup(), "Assembly.BoxVolVarsDependOnAllElementDofs", false
369 );
370
371 // create the element solution
372 19705337 auto elemSol = elementSolution(element, curSol, fvGeometry.gridGeometry());
373
374 // create the vector storing the partial derivatives
375 23775274 ElementResidualVector partialDerivs(fvGeometry.numScv());
376
377 27594705 Detail::VolVarsDeflectionHelper deflectionHelper(
378 [&] (const auto& scv) -> VolumeVariables& {
379 689388072 return this->getVolVarAccess(gridVariables.curGridVolVars(), curElemVolVars, scv);
380 },
381 fvGeometry,
382 updateAllVolVars
383 );
384
385 // calculation of the derivatives
386
4/4
✓ Branch 0 taken 35428924 times.
✓ Branch 1 taken 9989164 times.
✓ Branch 2 taken 34983634 times.
✓ Branch 3 taken 9766519 times.
64493734 for (const auto& scv : scvs(fvGeometry))
387 {
388 // dof index and corresponding actual pri vars
389 40718460 const auto dofIdx = scv.dofIndex();
390
1/2
✓ Branch 0 taken 21240562 times.
✗ Branch 1 not taken.
40718460 deflectionHelper.setCurrent(scv);
391
392 // calculate derivatives w.r.t to the privars at the dof at hand
393
2/2
✓ Branch 0 taken 82861526 times.
✓ Branch 1 taken 35428924 times.
130983018 for (int pvIdx = 0; pvIdx < numEq; pvIdx++)
394 {
395 90264558 partialDerivs = 0.0;
396
397 548253554 auto evalResiduals = [&](Scalar priVar)
398 {
399 // update the volume variables and compute element residual
400 177009348 elemSol[scv.localDofIndex()][pvIdx] = priVar;
401 183173084 deflectionHelper.deflect(elemSol, scv, this->asImp_().problem());
402 if constexpr (solutionDependentFluxVarsCache)
403 {
404 3126982 elemFluxVarsCache.update(element, fvGeometry, curElemVolVars);
405 if constexpr (enableGridFluxVarsCache)
406 gridVariables.gridFluxVarsCache().updateElement(element, fvGeometry, curElemVolVars);
407 }
408
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 80 times.
175163576 this->asImp_().maybeUpdateCouplingContext(scv, elemSol, pvIdx);
409
3/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1660354 times.
✓ Branch 2 taken 17472 times.
✓ Branch 3 taken 615360 times.
91586542 return this->evalLocalResidual();
410 };
411
412 // derive the residuals numerically
413
7/10
✓ Branch 0 taken 212 times.
✓ Branch 1 taken 82861314 times.
✓ Branch 3 taken 154 times.
✓ Branch 4 taken 58 times.
✓ Branch 6 taken 154 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 154 times.
✗ Branch 10 not taken.
✓ Branch 12 taken 154 times.
✗ Branch 13 not taken.
90264558 static const NumericEpsilon<Scalar, numEq> eps_{this->asImp_().problem().paramGroup()};
414
7/10
✓ Branch 0 taken 343 times.
✓ Branch 1 taken 82861183 times.
✓ Branch 3 taken 154 times.
✓ Branch 4 taken 189 times.
✓ Branch 6 taken 154 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 154 times.
✗ Branch 10 not taken.
✓ Branch 12 taken 154 times.
✗ Branch 13 not taken.
90264558 static const int numDiffMethod = getParamFromGroup<int>(this->asImp_().problem().paramGroup(), "Assembly.NumericDifferenceMethod");
415
3/6
✓ Branch 1 taken 82861526 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 82861526 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 80201234 times.
✗ Branch 8 not taken.
264606002 NumericDifferentiation::partialDerivative(evalResiduals, elemSol[scv.localDofIndex()][pvIdx], partialDerivs, origResiduals,
416 264606002 eps_(elemSol[scv.localDofIndex()][pvIdx], pvIdx), numDiffMethod);
417
418 // update the global stiffness matrix with the current partial derivatives
419
4/4
✓ Branch 0 taken 308026178 times.
✓ Branch 1 taken 82861526 times.
✓ Branch 2 taken 306023734 times.
✓ Branch 3 taken 81860304 times.
510971512 for (const auto& scvJ : scvs(fvGeometry))
420 {
421 // don't add derivatives for green dofs
422 if (!partialReassembler
423
6/6
✓ Branch 0 taken 11222400 times.
✓ Branch 1 taken 280193638 times.
✓ Branch 2 taken 10849688 times.
✓ Branch 3 taken 372712 times.
✓ Branch 4 taken 10849688 times.
✓ Branch 5 taken 372712 times.
295785094 || partialReassembler->dofColor(scvJ.dofIndex()) != EntityColor::green)
424 {
425
2/2
✓ Branch 0 taken 810148982 times.
✓ Branch 1 taken 307653466 times.
1189633248 for (int eqIdx = 0; eqIdx < numEq; eqIdx++)
426 {
427 // A[i][col][eqIdx][pvIdx] is the rate of change of
428 // the residual of equation 'eqIdx' at dof 'i'
429 // depending on the primary variable 'pvIdx' at dof
430 // 'col'.
431
4/8
✓ Branch 1 taken 810148982 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 810148982 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 810148982 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 797798140 times.
✗ Branch 11 not taken.
3403686778 A[scvJ.dofIndex()][dofIdx][eqIdx][pvIdx] += partialDerivs[scvJ.localDofIndex()][eqIdx];
432 }
433 }
434 }
435
436 // restore the original state of the scv's volume variables
437 90264558 deflectionHelper.restore(scv);
438
439 // restore the original element solution
440
4/8
✓ Branch 1 taken 3246 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 3246 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 2400 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 2400 times.
✗ Branch 11 not taken.
348682888 elemSol[scv.localDofIndex()][pvIdx] = curSol[scv.dofIndex()][pvIdx];
441
1/2
✓ Branch 1 taken 3246 times.
✗ Branch 2 not taken.
98240916 this->asImp_().maybeUpdateCouplingContext(scv, elemSol, pvIdx);
442 }
443 }
444
445 // restore original state of the flux vars cache in case of global caching.
446 // In the case of local caching this is obsolete because the elemFluxVarsCache used here goes out of scope after this.
447 if constexpr (enableGridFluxVarsCache)
448 3214759 gridVariables.gridFluxVarsCache().updateElement(element, fvGeometry, curElemVolVars);
449
450 // evaluate additional derivatives that might arise from the coupling (no-op if not coupled)
451 11887637 this->asImp_().maybeEvalAdditionalDomainDerivatives(origResiduals, A, gridVariables);
452
453 11887637 return origResiduals;
454 }
455
456 }; // implicit CVFEAssembler with numeric Jacobian
457
458 /*!
459 * \ingroup Assembly
460 * \ingroup CVFEDiscretization
461 * \brief Control volume finite element local assembler using numeric differentiation and explicit time discretization
462 */
463 template<class TypeTag, class Assembler, class Implementation>
464 1014000 class CVFELocalAssembler<TypeTag, Assembler, DiffMethod::numeric, /*implicit=*/false, Implementation>
465 : public CVFELocalAssemblerBase<TypeTag, Assembler,
466 Detail::CVFE::Impl<Implementation, CVFELocalAssembler<TypeTag, Assembler, DiffMethod::numeric, false, Implementation>>,
467 false>
468 {
469 using ThisType = CVFELocalAssembler<TypeTag, Assembler, DiffMethod::numeric, false, Implementation>;
470 using ParentType = CVFELocalAssemblerBase<TypeTag, Assembler, Detail::CVFE::Impl<Implementation, ThisType>, false>;
471 using Scalar = GetPropType<TypeTag, Properties::Scalar>;
472 using GridVariables = GetPropType<TypeTag, Properties::GridVariables>;
473 using VolumeVariables = GetPropType<TypeTag, Properties::VolumeVariables>;
474 using JacobianMatrix = GetPropType<TypeTag, Properties::JacobianMatrix>;
475
476 static constexpr int numEq = GetPropType<TypeTag, Properties::ModelTraits>::numEq();
477 static constexpr int dim = GetPropType<TypeTag, Properties::GridGeometry>::GridView::dimension;
478
479 public:
480
481 using LocalResidual = typename ParentType::LocalResidual;
482 using ElementResidualVector = typename LocalResidual::ElementResidualVector;
483
2/4
✓ Branch 1 taken 50000 times.
✗ Branch 2 not taken.
✓ Branch 6 taken 964000 times.
✗ Branch 7 not taken.
1014000 using ParentType::ParentType;
484
485 /*!
486 * \brief Computes the derivatives with respect to the given element and adds them
487 * to the global matrix.
488 *
489 * \return The element residual at the current solution.
490 */
491 template <class PartialReassembler = DefaultPartialReassembler>
492 1014000 ElementResidualVector assembleJacobianAndResidualImpl(JacobianMatrix& A, GridVariables& gridVariables,
493 const PartialReassembler* partialReassembler = nullptr)
494 {
495 1014000 if (partialReassembler)
496 DUNE_THROW(Dune::NotImplemented, "partial reassembly for explicit time discretization");
497
498 // get some aliases for convenience
499 1014000 const auto& element = this->element();
500 1014000 const auto& fvGeometry = this->fvGeometry();
501 1014000 const auto& curSol = this->asImp_().curSol();
502 1014000 auto&& curElemVolVars = this->curElemVolVars();
503
504 // get the vecor of the actual element residuals
505 1014000 const auto origResiduals = this->evalLocalResidual();
506 1014000 const auto origStorageResiduals = this->evalLocalStorageResidual();
507
508 //////////////////////////////////////////////////////////////////////////////////////////////////
509 // //
510 // Calculate derivatives of all dofs in stencil with respect to the dofs in the element. In the //
511 // neighboring elements we do so by computing the derivatives of the fluxes which depend on the //
512 // actual element. In the actual element we evaluate the derivative of the entire residual. //
513 // //
514 //////////////////////////////////////////////////////////////////////////////////////////////////
515
516 // create the element solution
517 1064000 auto elemSol = elementSolution(element, curSol, fvGeometry.gridGeometry());
518
519 // create the vector storing the partial derivatives
520 2028000 ElementResidualVector partialDerivs(fvGeometry.numScv());
521
522 // calculation of the derivatives
523 5020000 for (const auto& scv : scvs(fvGeometry))
524 {
525 // dof index and corresponding actual pri vars
526 2992000 const auto dofIdx = scv.dofIndex();
527 5984000 auto& curVolVars = this->getVolVarAccess(gridVariables.curGridVolVars(), curElemVolVars, scv);
528 2992000 const VolumeVariables origVolVars(curVolVars);
529
530 // calculate derivatives w.r.t to the privars at the dof at hand
531 5984000 for (int pvIdx = 0; pvIdx < numEq; pvIdx++)
532 {
533 2992000 partialDerivs = 0.0;
534
535 14960000 auto evalStorage = [&](Scalar priVar)
536 {
537 // auto partialDerivsTmp = partialDerivs;
538 2992000 elemSol[scv.localDofIndex()][pvIdx] = priVar;
539 5984000 curVolVars.update(elemSol, this->asImp_().problem(), element, scv);
540 2992000 return this->evalLocalStorageResidual();
541 };
542
543 // derive the residuals numerically
544 2992000 static const NumericEpsilon<Scalar, numEq> eps_{this->asImp_().problem().paramGroup()};
545 2992000 static const int numDiffMethod = getParamFromGroup<int>(this->asImp_().problem().paramGroup(), "Assembly.NumericDifferenceMethod");
546 5984000 NumericDifferentiation::partialDerivative(evalStorage, elemSol[scv.localDofIndex()][pvIdx], partialDerivs, origStorageResiduals,
547 5984000 eps_(elemSol[scv.localDofIndex()][pvIdx], pvIdx), numDiffMethod);
548
549 // update the global stiffness matrix with the current partial derivatives
550 5984000 for (int eqIdx = 0; eqIdx < numEq; eqIdx++)
551 {
552 // A[i][col][eqIdx][pvIdx] is the rate of change of
553 // the residual of equation 'eqIdx' at dof 'i'
554 // depending on the primary variable 'pvIdx' at dof
555 // 'col'.
556 8976000 A[dofIdx][dofIdx][eqIdx][pvIdx] += partialDerivs[scv.localDofIndex()][eqIdx];
557 }
558
559 // restore the original state of the scv's volume variables
560 2992000 curVolVars = origVolVars;
561
562 // restore the original element solution
563 8976000 elemSol[scv.localDofIndex()][pvIdx] = curSol[scv.dofIndex()][pvIdx];
564 // TODO additional dof dependencies
565 }
566 }
567
568 1014000 return origResiduals;
569 }
570 }; // explicit CVFEAssembler with numeric Jacobian
571
572 /*!
573 * \ingroup Assembly
574 * \ingroup CVFEDiscretization
575 * \brief Control volume finite element local assembler using analytic differentiation and implicit time discretization
576 */
577 template<class TypeTag, class Assembler, class Implementation>
578
2/8
✓ Branch 0 taken 500000 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 5000 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
1259597 class CVFELocalAssembler<TypeTag, Assembler, DiffMethod::analytic, /*implicit=*/true, Implementation>
579 : public CVFELocalAssemblerBase<TypeTag, Assembler,
580 Detail::CVFE::Impl<Implementation, CVFELocalAssembler<TypeTag, Assembler, DiffMethod::analytic, true, Implementation>>,
581 true>
582 {
583 using ThisType = CVFELocalAssembler<TypeTag, Assembler, DiffMethod::analytic, true, Implementation>;
584 using ParentType = CVFELocalAssemblerBase<TypeTag, Assembler, Detail::CVFE::Impl<Implementation, ThisType>, true>;
585 using GridVariables = GetPropType<TypeTag, Properties::GridVariables>;
586 using JacobianMatrix = GetPropType<TypeTag, Properties::JacobianMatrix>;
587
588 public:
589
590 using LocalResidual = typename ParentType::LocalResidual;
591 using ElementResidualVector = typename LocalResidual::ElementResidualVector;
592
2/8
✓ Branch 2 taken 728769 times.
✗ Branch 3 not taken.
✓ Branch 6 taken 25828 times.
✗ Branch 7 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
754597 using ParentType::ParentType;
593
594 /*!
595 * \brief Computes the derivatives with respect to the given element and adds them
596 * to the global matrix.
597 *
598 * \return The element residual at the current solution.
599 */
600 template <class PartialReassembler = DefaultPartialReassembler>
601 253869 ElementResidualVector assembleJacobianAndResidualImpl(JacobianMatrix& A, GridVariables& gridVariables,
602 const PartialReassembler* partialReassembler = nullptr)
603 {
604
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 253869 times.
253869 if (partialReassembler)
605 DUNE_THROW(Dune::NotImplemented, "partial reassembly for analytic differentiation");
606
607 // get some aliases for convenience
608 253869 const auto& element = this->element();
609
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 135105 times.
253869 const auto& fvGeometry = this->fvGeometry();
610
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 135105 times.
253869 const auto& problem = this->asImp_().problem();
611
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 135105 times.
253869 const auto& curElemVolVars = this->curElemVolVars();
612
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 135105 times.
253869 const auto& elemFluxVarsCache = this->elemFluxVarsCache();
613
614 // get the vecor of the actual element residuals
615
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 135105 times.
253869 const auto origResiduals = this->evalLocalResidual();
616
617 //////////////////////////////////////////////////////////////////////////////////////////////////
618 // //
619 // Calculate derivatives of all dofs in stencil with respect to the dofs in the element. In the //
620 // neighboring elements we do so by computing the derivatives of the fluxes which depend on the //
621 // actual element. In the actual element we evaluate the derivative of the entire residual. //
622 // //
623 //////////////////////////////////////////////////////////////////////////////////////////////////
624
625 // calculation of the source and storage derivatives
626
4/4
✓ Branch 0 taken 745266 times.
✓ Branch 1 taken 253869 times.
✓ Branch 2 taken 744056 times.
✓ Branch 3 taken 253264 times.
1881404 for (const auto& scv : scvs(fvGeometry))
627 {
628 // dof index and corresponding actual pri vars
629 745266 const auto dofIdx = scv.dofIndex();
630
2/2
✓ Branch 0 taken 611000 times.
✓ Branch 1 taken 134266 times.
745266 const auto& volVars = curElemVolVars[scv];
631
632 // derivative of this scv residual w.r.t the d.o.f. of the same scv (because of mass lumping)
633 // only if the problem is instationary we add derivative of storage term
634 // TODO if e.g. porosity depends on all dofs in the element, we would have off-diagonal matrix entries!?
635
2/2
✓ Branch 0 taken 611000 times.
✓ Branch 1 taken 134266 times.
745266 if (!this->assembler().isStationaryProblem())
636 1833000 this->localResidual().addStorageDerivatives(A[dofIdx][dofIdx],
637 problem,
638 element,
639 fvGeometry,
640 volVars,
641 scv);
642
643 // derivative of this scv residual w.r.t the d.o.f. of the same scv (because of mass lumping)
644 // add source term derivatives
645 2235798 this->localResidual().addSourceDerivatives(A[dofIdx][dofIdx],
646 problem,
647 element,
648 fvGeometry,
649 volVars,
650 scv);
651 }
652
653 // localJacobian[scvIdx][otherScvIdx][eqIdx][priVarIdx] of the fluxes
654
4/4
✓ Branch 0 taken 636519 times.
✓ Branch 1 taken 253869 times.
✓ Branch 2 taken 635914 times.
✓ Branch 3 taken 253264 times.
1144257 for (const auto& scvf : scvfs(fvGeometry))
655 {
656
2/2
✓ Branch 0 taken 609556 times.
✓ Branch 1 taken 26358 times.
636519 if (!scvf.boundary())
657 {
658 // add flux term derivatives
659 1220322 this->localResidual().addFluxDerivatives(A,
660 problem,
661 element,
662 fvGeometry,
663 curElemVolVars,
664 elemFluxVarsCache,
665 scvf);
666 }
667
668 // the boundary gets special treatment to simplify
669 // for the user
670 else
671 {
672 52716 const auto& insideScv = fvGeometry.scv(scvf.insideScvIdx());
673 79074 if (this->elemBcTypes().get(fvGeometry, insideScv).hasNeumann())
674 {
675 // add flux term derivatives
676 this->localResidual().addRobinFluxDerivatives(A[insideScv.dofIndex()],
677 problem,
678 element,
679 fvGeometry,
680 curElemVolVars,
681 elemFluxVarsCache,
682 scvf);
683 }
684 }
685 }
686
687 253869 return origResiduals;
688 }
689
690 }; // implicit CVFEAssembler with analytic Jacobian
691
692 /*!
693 * \ingroup Assembly
694 * \ingroup CVFEDiscretization
695 * \brief Control volume finite element local assembler using analytic differentiation and explicit time discretization
696 */
697 template<class TypeTag, class Assembler, class Implementation>
698
2/8
✓ Branch 0 taken 500000 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 5000 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
1010000 class CVFELocalAssembler<TypeTag, Assembler, DiffMethod::analytic, /*implicit=*/false, Implementation>
699 : public CVFELocalAssemblerBase<TypeTag, Assembler,
700 Detail::CVFE::Impl<Implementation, CVFELocalAssembler<TypeTag, Assembler, DiffMethod::analytic, false, Implementation>>,
701 false>
702 {
703 using ThisType = CVFELocalAssembler<TypeTag, Assembler, DiffMethod::analytic, false, Implementation>;
704 using ParentType = CVFELocalAssemblerBase<TypeTag, Assembler, Detail::CVFE::Impl<Implementation, ThisType>, false>;
705 using GridVariables = GetPropType<TypeTag, Properties::GridVariables>;
706 using JacobianMatrix = GetPropType<TypeTag, Properties::JacobianMatrix>;
707
708 public:
709
710 using LocalResidual = typename ParentType::LocalResidual;
711 using ElementResidualVector = typename LocalResidual::ElementResidualVector;
712
2/4
✓ Branch 2 taken 500000 times.
✗ Branch 3 not taken.
✓ Branch 6 taken 5000 times.
✗ Branch 7 not taken.
505000 using ParentType::ParentType;
713
714 /*!
715 * \brief Computes the derivatives with respect to the given element and adds them
716 * to the global matrix.
717 *
718 * \return The element residual at the current solution.
719 */
720 template <class PartialReassembler = DefaultPartialReassembler>
721 5000 ElementResidualVector assembleJacobianAndResidualImpl(JacobianMatrix& A, GridVariables& gridVariables,
722 const PartialReassembler* partialReassembler = nullptr)
723 {
724
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5000 times.
5000 if (partialReassembler)
725 DUNE_THROW(Dune::NotImplemented, "partial reassembly for explicit time discretization");
726
727 // get some aliases for convenience
728 5000 const auto& element = this->element();
729 5000 const auto& fvGeometry = this->fvGeometry();
730 5000 const auto& problem = this->asImp_().problem();
731 5000 const auto& curElemVolVars = this->curElemVolVars();
732
733 // get the vecor of the actual element residuals
734 5000 const auto origResiduals = this->evalLocalResidual();
735
736 //////////////////////////////////////////////////////////////////////////////////////////////////
737 // //
738 // Calculate derivatives of all dofs in stencil with respect to the dofs in the element. In the //
739 // neighboring elements we do so by computing the derivatives of the fluxes which depend on the //
740 // actual element. In the actual element we evaluate the derivative of the entire residual. //
741 // //
742 //////////////////////////////////////////////////////////////////////////////////////////////////
743
744 // calculation of the source and storage derivatives
745
4/4
✓ Branch 0 taken 20000 times.
✓ Branch 1 taken 5000 times.
✓ Branch 2 taken 20000 times.
✓ Branch 3 taken 5000 times.
30000 for (const auto& scv : scvs(fvGeometry))
746 {
747 // dof index and corresponding actual pri vars
748 20000 const auto dofIdx = scv.dofIndex();
749 20000 const auto& volVars = curElemVolVars[scv];
750
751 // derivative of this scv residual w.r.t the d.o.f. of the same scv (because of mass lumping)
752 // only if the problem is instationary we add derivative of storage term
753 60000 this->localResidual().addStorageDerivatives(A[dofIdx][dofIdx],
754 problem,
755 element,
756 fvGeometry,
757 volVars,
758 scv);
759 }
760
761 5000 return origResiduals;
762 }
763
764 }; // explicit CVFEAssembler with analytic Jacobian
765
766 } // end namespace Dumux
767
768 #endif
769