GCC Code Coverage Report


Directory: ../../../builds/dumux-repositories/
File: /builds/dumux-repositories/dumux/dumux/assembly/cvfelocalassembler.hh
Date: 2024-05-04 19:09:25
Exec Total Coverage
Lines: 192 201 95.5%
Functions: 748 1669 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 19901396 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 18770472 using ParentType::ParentType;
78
79 13280353 void bindLocalViews()
80 {
81 13280353 ParentType::bindLocalViews();
82 53121412 this->elemBcTypes().update(this->asImp_().problem(), this->element(), this->fvGeometry());
83 13280353 }
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 16380180 void assembleJacobianAndResidual(JacobianMatrix& jac, ResidualVector& res, GridVariables& gridVariables,
92 const PartialReassembler* partialReassembler = nullptr,
93 const CouplingFunction& maybeAssembleCouplingBlocks = {})
94 {
95 16380180 this->asImp_().bindLocalViews();
96 65520720 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 10355812 times.
✓ Branch 2 taken 101612 times.
✓ Branch 3 taken 350700 times.
✓ Branch 4 taken 101612 times.
✓ Branch 5 taken 350700 times.
11900388 && 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 13238497 times.
✓ Branch 1 taken 69702 times.
16278568 else if (!this->elementIsGhost())
108 {
109 16208866 const auto residual = this->asImp_().assembleJacobianAndResidualImpl(jac, gridVariables, partialReassembler); // forward to the internal implementation
110
4/4
✓ Branch 0 taken 44723806 times.
✓ Branch 1 taken 13238497 times.
✓ Branch 2 taken 42067250 times.
✓ Branch 3 taken 11910219 times.
150175942 for (const auto& scv : scvs(this->fvGeometry()))
111 212831912 res[scv.dofIndex()] += residual[scv.localDofIndex()];
112
113 // assemble the coupling blocks for coupled models (does nothing if not coupled)
114 4324931 maybeAssembleCouplingBlocks(residual);
115 }
116 else
117 {
118 // Treatment of ghost elements
119 69702 assert(this->elementIsGhost());
120
121 // handle dofs per codimension
122
2/4
✓ Branch 1 taken 69702 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 69702 times.
✗ Branch 5 not taken.
139404 const auto& gridGeometry = this->asImp_().problem().gridGeometry();
123
1/2
✓ Branch 1 taken 69702 times.
✗ Branch 2 not taken.
435492 Dune::Hybrid::forEach(std::make_integer_sequence<int, dim>{}, [&](auto d)
124 {
125 139404 constexpr int codim = dim - d;
126 415332 const auto& localCoeffs = gridGeometry.feCache().get(this->element().type()).localCoefficients();
127
8/24
✓ Branch 0 taken 273384 times.
✓ Branch 1 taken 72894 times.
✓ Branch 2 taken 274740 times.
✓ Branch 3 taken 68346 times.
✓ Branch 4 taken 277932 times.
✓ Branch 5 taken 69702 times.
✓ Branch 6 taken 273384 times.
✓ Branch 7 taken 68346 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.
695268 for (int idx = 0; idx < localCoeffs.size(); ++idx)
128 {
129 555864 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 273384 times.
✓ Branch 2 taken 4548 times.
✓ Branch 3 taken 273384 times.
✓ Branch 4 taken 273384 times.
✓ Branch 5 taken 4548 times.
✓ Branch 6 taken 273384 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.
1111728 if (localKey.codim() != codim)
133 415980 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.
692868 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 133812 times.
✓ Branch 5 taken 133812 times.
✓ Branch 6 taken 133812 times.
✓ Branch 7 taken 133812 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.
413100 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.
138048 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.
279768 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 133812 times.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✓ Branch 10 taken 133812 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.
279768 BlockType &J = jac[dofIndex][dofIndex];
149
4/12
✓ Branch 0 taken 6384 times.
✓ Branch 1 taken 3192 times.
✓ Branch 2 taken 333900 times.
✓ Branch 3 taken 136692 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.
480168 for (int j = 0; j < BlockType::rows; ++j)
150 1013652 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.
419652 res[dofIndex] = 0;
154 }
155 });
156 }
157
158 21422350 auto applyDirichlet = [&] (const auto& scvI,
159 const auto& dirichletValues,
160 const auto eqIdx,
161 1680722 const auto pvIdx)
162 {
163 10796635 res[scvI.dofIndex()][eqIdx] = this->curElemVolVars()[scvI].priVars()[pvIdx] - dirichletValues[pvIdx];
164
165 1680722 auto& row = jac[scvI.dofIndex()];
166
12/24
✗ Branch 0 not taken.
✓ Branch 1 taken 12426267 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 12426267 times.
✓ Branch 4 taken 10914079 times.
✓ Branch 5 taken 1512188 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 1497657 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 1497657 times.
✓ Branch 10 taken 1335331 times.
✓ Branch 11 taken 162326 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.
26297678 for (auto col = row.begin(); col != row.end(); ++col)
167 35517753 row[col.index()][eqIdx] = 0.0;
168
169 3361444 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 822614 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 66198 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 944 times.
4814598 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 32760360 this->asImp_().enforceDirichletConstraints(applyDirichlet);
186 16380180 }
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 2781327 void assembleResidual(ResidualVector& res)
217 {
218 2781327 this->asImp_().bindLocalViews();
219
0/2
✗ Branch 0 not taken.
✗ Branch 1 not taken.
2781327 const auto residual = this->evalLocalResidual();
220
221
4/4
✓ Branch 0 taken 8766162 times.
✓ Branch 1 taken 2259215 times.
✓ Branch 2 taken 8766162 times.
✓ Branch 3 taken 2259215 times.
29880561 for (const auto& scv : scvs(this->fvGeometry()))
222 43073160 res[scv.dofIndex()] += residual[scv.localDofIndex()];
223
224 2781327 auto applyDirichlet = [&] (const auto& scvI,
225 const auto& dirichletValues,
226 const auto eqIdx,
227 const auto pvIdx)
228 {
229 937672 res[scvI.dofIndex()][eqIdx] = this->curElemVolVars()[scvI].priVars()[pvIdx] - dirichletValues[pvIdx];
230 };
231
232 5562654 this->asImp_().enforceDirichletConstraints(applyDirichlet);
233 2781327 }
234
235 //! Enforce Dirichlet constraints
236 template<typename ApplyFunction>
237 void enforceDirichletConstraints(const ApplyFunction& applyDirichlet)
238 {
239 // enforce Dirichlet boundary conditions
240 15670162 this->asImp_().evalDirichletBoundaries(applyDirichlet);
241 // take care of internal Dirichlet constraints (if enabled)
242 13698684 this->asImp_().enforceInternalDirichletConstraints(applyDirichlet);
243 }
244
245 /*!
246 * \brief Evaluates Dirichlet boundaries
247 */
248 template< typename ApplyDirichletFunctionType >
249 31322840 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 544565 times.
✓ Branch 1 taken 15125597 times.
✓ Branch 2 taken 544565 times.
✓ Branch 3 taken 15125597 times.
62645680 if (this->elemBcTypes().hasDirichlet())
254 {
255
4/4
✓ Branch 0 taken 1870201 times.
✓ Branch 1 taken 544565 times.
✓ Branch 2 taken 1613827 times.
✓ Branch 3 taken 416378 times.
6990554 for (const auto& scvI : scvs(this->fvGeometry()))
256 {
257 11185026 const auto bcTypes = this->elemBcTypes().get(this->fvGeometry(), scvI);
258
4/4
✓ Branch 0 taken 896135 times.
✓ Branch 1 taken 974066 times.
✓ Branch 2 taken 896135 times.
✓ Branch 3 taken 974066 times.
7456684 if (bcTypes.hasDirichlet())
259 {
260
4/4
✓ Branch 0 taken 188355 times.
✓ Branch 1 taken 151761 times.
✓ Branch 2 taken 188355 times.
✓ Branch 3 taken 151761 times.
3390642 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 1531319 times.
✓ Branch 1 taken 1049301 times.
✓ Branch 2 taken 155255 times.
5459894 for (int eqIdx = 0; eqIdx < numEq; ++eqIdx)
264 {
265
2/2
✓ Branch 0 taken 24454 times.
✓ Branch 1 taken 1815286 times.
3673552 if (bcTypes.isDirichlet(eqIdx))
266 {
267
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1815286 times.
3624644 const auto pvIdx = bcTypes.eqToDirichletIndex(eqIdx);
268
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1815286 times.
3624644 assert(0 <= pvIdx && pvIdx < numEq);
269 3624644 applyDirichlet(scvI, dirichletValues, eqIdx, pvIdx);
270 }
271 }
272 }
273 }
274 }
275 31322840 }
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 2243432 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 455690 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.
16617799 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 10150218 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.
15783637 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 11974876 ElementResidualVector assembleJacobianAndResidualImpl(JacobianMatrix& A, GridVariables& gridVariables,
344 const PartialReassembler* partialReassembler = nullptr)
345 {
346 // get some aliases for convenience
347 11974876 const auto& element = this->element();
348
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 44241 times.
11974876 const auto& fvGeometry = this->fvGeometry();
349
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 443 times.
11974876 const auto& curSol = this->asImp_().curSol();
350
351
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 44241 times.
11974876 auto&& curElemVolVars = this->curElemVolVars();
352
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 44241 times.
11974876 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.
11974876 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 183 times.
✓ Branch 1 taken 10018324 times.
✓ Branch 3 taken 155 times.
✓ Branch 4 taken 28 times.
✓ Branch 6 taken 155 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 142 times.
✗ Branch 10 not taken.
11974876 static const bool updateAllVolVars = getParamFromGroup<bool>(
368
2/4
✓ Branch 1 taken 155 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 13 times.
✗ Branch 5 not taken.
510 this->asImp_().problem().paramGroup(), "Assembly.BoxVolVarsDependOnAllElementDofs", false
369 );
370
371 // create the element solution
372 19879815 auto elemSol = elementSolution(element, curSol, fvGeometry.gridGeometry());
373
374 // create the vector storing the partial derivatives
375 23949752 ElementResidualVector partialDerivs(fvGeometry.numScv());
376
377 28405644 Detail::VolVarsDeflectionHelper deflectionHelper(
378 [&] (const auto& scv) -> VolumeVariables& {
379 693575748 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 35502948 times.
✓ Branch 1 taken 10018507 times.
✓ Branch 2 taken 35057658 times.
✓ Branch 3 taken 9795862 times.
64944872 for (const auto& scv : scvs(fvGeometry))
387 {
388 // dof index and corresponding actual pri vars
389 40995120 const auto dofIdx = scv.dofIndex();
390
1/2
✓ Branch 0 taken 21330970 times.
✗ Branch 1 not taken.
40995120 deflectionHelper.setCurrent(scv);
391
392 // calculate derivatives w.r.t to the privars at the dof at hand
393
2/2
✓ Branch 0 taken 83102714 times.
✓ Branch 1 taken 35502948 times.
131819294 for (int pvIdx = 0; pvIdx < numEq; pvIdx++)
394 {
395 90824174 partialDerivs = 0.0;
396
397 551611250 auto evalResiduals = [&](Scalar priVar)
398 {
399 // update the volume variables and compute element residual
400 178041736 elemSol[scv.localDofIndex()][pvIdx] = priVar;
401 184292316 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.
175790692 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.
92146158 return this->evalLocalResidual();
410 };
411
412 // derive the residuals numerically
413
7/10
✓ Branch 0 taken 211 times.
✓ Branch 1 taken 83102503 times.
✓ Branch 3 taken 155 times.
✓ Branch 4 taken 56 times.
✓ Branch 6 taken 155 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 155 times.
✗ Branch 10 not taken.
✓ Branch 12 taken 155 times.
✗ Branch 13 not taken.
90824174 static const NumericEpsilon<Scalar, numEq> eps_{this->asImp_().problem().paramGroup()};
414
7/10
✓ Branch 0 taken 296 times.
✓ Branch 1 taken 83102418 times.
✓ Branch 3 taken 155 times.
✓ Branch 4 taken 141 times.
✓ Branch 6 taken 155 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 155 times.
✗ Branch 10 not taken.
✓ Branch 12 taken 155 times.
✗ Branch 13 not taken.
90824174 static const int numDiffMethod = getParamFromGroup<int>(this->asImp_().problem().paramGroup(), "Assembly.NumericDifferenceMethod");
415
3/6
✓ Branch 1 taken 83102714 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 83102714 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 80442422 times.
✗ Branch 8 not taken.
266198006 NumericDifferentiation::partialDerivative(evalResiduals, elemSol[scv.localDofIndex()][pvIdx], partialDerivs, origResiduals,
416 266198006 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 308759642 times.
✓ Branch 1 taken 83102714 times.
✓ Branch 2 taken 306757198 times.
✓ Branch 3 taken 82101492 times.
514011076 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 280406038 times.
✓ Branch 2 taken 10849688 times.
✓ Branch 3 taken 372712 times.
✓ Branch 4 taken 10849688 times.
✓ Branch 5 taken 372712 times.
295997494 || partialReassembler->dofColor(scvJ.dofIndex()) != EntityColor::green)
424 {
425
2/2
✓ Branch 0 taken 813230870 times.
✓ Branch 1 taken 308386930 times.
1196748672 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 813230870 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 813230870 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 813230870 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 800880028 times.
✗ Branch 11 not taken.
3424206614 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 90824174 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.
350747664 elemSol[scv.localDofIndex()][pvIdx] = curSol[scv.dofIndex()][pvIdx];
441
1/2
✓ Branch 1 taken 3246 times.
✗ Branch 2 not taken.
99292648 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 3297507 gridVariables.gridFluxVarsCache().updateElement(element, fvGeometry, curElemVolVars);
449
450 // evaluate additional derivatives that might arise from the coupling (no-op if not coupled)
451 11974876 this->asImp_().maybeEvalAdditionalDomainDerivatives(origResiduals, A, gridVariables);
452
453 11974876 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