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 |