GCC Code Coverage Report


Directory: ../../../builds/dumux-repositories/
File: dumux/dumux/multidomain/fvassembler.hh
Date: 2025-04-12 19:19:20
Exec Total Coverage
Lines: 198 203 97.5%
Functions: 2767 3285 84.2%
Branches: 299 667 44.8%

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-FileCopyrightText: 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 MultiDomain
10 * \ingroup Assembly
11 * \brief A linear system assembler (residual and Jacobian) for finite volume schemes
12 * with multiple domains
13 */
14 #ifndef DUMUX_MULTIDOMAIN_FV_ASSEMBLER_HH
15 #define DUMUX_MULTIDOMAIN_FV_ASSEMBLER_HH
16
17 #include <type_traits>
18 #include <tuple>
19
20 #include <dune/common/hybridutilities.hh>
21 #include <dune/istl/matrixindexset.hh>
22
23 #include <dumux/common/exceptions.hh>
24 #include <dumux/common/properties.hh>
25 #include <dumux/common/timeloop.hh>
26 #include <dumux/common/typetraits/utility.hh>
27 #include <dumux/common/typetraits/periodic.hh>
28 #include <dumux/common/gridcapabilities.hh>
29 #include <dumux/discretization/method.hh>
30 #include <dumux/assembly/diffmethod.hh>
31 #include <dumux/assembly/jacobianpattern.hh>
32 #include <dumux/linear/parallelhelpers.hh>
33 #include <dumux/parallel/multithreading.hh>
34
35 #include "couplingjacobianpattern.hh"
36 #include "subdomaincclocalassembler.hh"
37 #include "subdomaincvfelocalassembler.hh"
38 #include "subdomainstaggeredlocalassembler.hh"
39 #include "subdomainfclocalassembler.hh"
40 #include "assemblerview.hh"
41
42 #include <dumux/discretization/method.hh>
43
44 namespace Dumux {
45
46 namespace Grid::Capabilities {
47
48 namespace Detail {
49 // helper for multi-domain models
50 template<class T, std::size_t... I>
51
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 bool allGridsSupportsMultithreadingImpl(const T& gridGeometries, std::index_sequence<I...>)
52 {
53
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 26 times.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
26 return (... && supportsMultithreading(std::get<I>(gridGeometries)->gridView()));
54 }
55 } // end namespace Detail
56
57 // helper for multi-domain models (all grids have to support multithreading)
58 template<class... GG>
59 26 bool allGridsSupportsMultithreading(const std::tuple<GG...>& gridGeometries)
60 {
61 1 return Detail::allGridsSupportsMultithreadingImpl<std::tuple<GG...>>(gridGeometries, std::make_index_sequence<sizeof...(GG)>());
62 }
63
64 } // end namespace Grid::Capabilities
65
66 /*!
67 * \ingroup MultiDomain
68 * \ingroup Assembly
69 * \brief trait that is specialized for coupling manager supporting multithreaded assembly
70 */
71 template<class CM>
72 struct CouplingManagerSupportsMultithreadedAssembly : public std::false_type
73 {};
74
75 /*!
76 * \ingroup MultiDomain
77 * \ingroup Assembly
78 * \brief A linear system assembler (residual and Jacobian) for finite volume schemes (box, tpfa, mpfa, ...)
79 * with multiple domains
80 * \tparam MDTraits the multidimensional traits
81 * \tparam diffMethod the differentiation method to residual compute derivatives
82 * \tparam useImplicitAssembly if to use an implicit or explicit time discretization
83 */
84 template<class MDTraits, class CMType, DiffMethod diffMethod, bool useImplicitAssembly = true>
85 class MultiDomainFVAssembler
86 {
87 template<std::size_t id>
88 using SubDomainTypeTag = typename MDTraits::template SubDomain<id>::TypeTag;
89
90 public:
91 using Traits = MDTraits;
92
93 using Scalar = typename MDTraits::Scalar;
94
95 template<std::size_t id>
96 using LocalResidual = typename MDTraits::template SubDomain<id>::LocalResidual;
97
98 template<std::size_t id>
99 using GridVariables = typename MDTraits::template SubDomain<id>::GridVariables;
100
101 template<std::size_t id>
102 using GridGeometry = typename MDTraits::template SubDomain<id>::GridGeometry;
103
104 template<std::size_t id>
105 using Problem = typename MDTraits::template SubDomain<id>::Problem;
106
107 using JacobianMatrix = typename MDTraits::JacobianMatrix;
108 using SolutionVector = typename MDTraits::SolutionVector;
109 using ResidualType = typename MDTraits::ResidualVector;
110
111 using CouplingManager = CMType;
112
113 /*!
114 * \brief Returns true if the assembler considers implicit assembly.
115 */
116 static constexpr bool isImplicit()
117 { return useImplicitAssembly; }
118
119 private:
120
121 using ProblemTuple = typename MDTraits::template TupleOfSharedPtrConst<Problem>;
122 using GridGeometryTuple = typename MDTraits::template TupleOfSharedPtrConst<GridGeometry>;
123 using GridVariablesTuple = typename MDTraits::template TupleOfSharedPtr<GridVariables>;
124
125 using TimeLoop = TimeLoopBase<Scalar>;
126 using ThisType = MultiDomainFVAssembler<MDTraits, CouplingManager, diffMethod, isImplicit()>;
127
128 template<std::size_t id>
129 using SubDomainAssemblerView = MultiDomainAssemblerSubDomainView<ThisType, id>;
130
131 template<class DiscretizationMethod, std::size_t id>
132 struct SubDomainAssemblerType;
133
134 template<std::size_t id>
135 struct SubDomainAssemblerType<DiscretizationMethods::CCTpfa, id>
136 {
137 using type = SubDomainCCLocalAssembler<id, SubDomainTypeTag<id>, SubDomainAssemblerView<id>, diffMethod, isImplicit()>;
138 };
139
140 template<std::size_t id>
141 struct SubDomainAssemblerType<DiscretizationMethods::CCMpfa, id>
142 {
143 using type = SubDomainCCLocalAssembler<id, SubDomainTypeTag<id>, SubDomainAssemblerView<id>, diffMethod, isImplicit()>;
144 };
145
146 template<std::size_t id, class DM>
147 struct SubDomainAssemblerType<DiscretizationMethods::CVFE<DM>, id>
148 {
149 using type = SubDomainCVFELocalAssembler<id, SubDomainTypeTag<id>, SubDomainAssemblerView<id>, diffMethod, isImplicit()>;
150 };
151
152 template<std::size_t id>
153 struct SubDomainAssemblerType<DiscretizationMethods::Staggered, id>
154 {
155 using type = SubDomainStaggeredLocalAssembler<id, SubDomainTypeTag<id>, SubDomainAssemblerView<id>, diffMethod, isImplicit()>;
156 };
157
158 template<std::size_t id>
159 struct SubDomainAssemblerType<DiscretizationMethods::FCStaggered, id>
160 {
161 using type = SubDomainFaceCenteredLocalAssembler<id, SubDomainTypeTag<id>, SubDomainAssemblerView<id>, diffMethod, isImplicit()>;
162 };
163
164 template<std::size_t id>
165 using SubDomainAssembler = typename SubDomainAssemblerType<typename GridGeometry<id>::DiscretizationMethod, id>::type;
166
167 public:
168
169
170 /*!
171 * \brief The constructor for stationary problems
172 * \note the grid variables might be temporarily changed during assembly (if caching is enabled)
173 * it is however guaranteed that the state after assembly will be the same as before
174 */
175 129 MultiDomainFVAssembler(ProblemTuple problem,
176 GridGeometryTuple gridGeometry,
177 GridVariablesTuple gridVariables,
178 std::shared_ptr<CouplingManager> couplingManager)
179 129 : couplingManager_(couplingManager)
180
1/2
✓ Branch 1 taken 129 times.
✗ Branch 2 not taken.
129 , problemTuple_(std::move(problem))
181 129 , gridGeometryTuple_(std::move(gridGeometry))
182 129 , gridVariablesTuple_(std::move(gridVariables))
183
1/2
✓ Branch 1 taken 129 times.
✗ Branch 2 not taken.
129 , timeLoop_()
184 129 , isStationaryProblem_(true)
185
1/2
✓ Branch 1 taken 129 times.
✗ Branch 2 not taken.
129 , warningIssued_(false)
186 {
187 static_assert(isImplicit(), "Explicit assembler for stationary problem doesn't make sense!");
188
1/2
✓ Branch 1 taken 129 times.
✗ Branch 2 not taken.
129 std::cout << "Instantiated assembler for a stationary problem." << std::endl;
189
190 129 enableMultithreading_ = CouplingManagerSupportsMultithreadedAssembly<CouplingManager>::value
191
1/2
✓ Branch 1 taken 21 times.
✗ Branch 2 not taken.
21 && Grid::Capabilities::allGridsSupportsMultithreading(gridGeometryTuple_)
192 && !Multithreading::isSerial()
193
1/2
✓ Branch 1 taken 21 times.
✗ Branch 2 not taken.
21 && getParam<bool>("Assembly.Multithreading", true);
194
195 129 maybeComputeColors_();
196 21 }
197
198 /*!
199 * \brief The constructor for instationary problems
200 * \note the grid variables might be temporarily changed during assembly (if caching is enabled)
201 * it is however guaranteed that the state after assembly will be the same as before
202 */
203 92 MultiDomainFVAssembler(ProblemTuple problem,
204 GridGeometryTuple gridGeometry,
205 GridVariablesTuple gridVariables,
206 std::shared_ptr<CouplingManager> couplingManager,
207 std::shared_ptr<const TimeLoop> timeLoop,
208 const SolutionVector& prevSol)
209 92 : couplingManager_(couplingManager)
210 92 , problemTuple_(std::move(problem))
211 92 , gridGeometryTuple_(std::move(gridGeometry))
212 92 , gridVariablesTuple_(std::move(gridVariables))
213 92 , timeLoop_(timeLoop)
214 92 , prevSol_(&prevSol)
215 92 , isStationaryProblem_(false)
216
1/2
✓ Branch 1 taken 92 times.
✗ Branch 2 not taken.
92 , warningIssued_(false)
217 {
218
1/2
✓ Branch 1 taken 92 times.
✗ Branch 2 not taken.
92 std::cout << "Instantiated assembler for an instationary problem." << std::endl;
219
220 92 enableMultithreading_ = CouplingManagerSupportsMultithreadedAssembly<CouplingManager>::value
221
1/2
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
5 && Grid::Capabilities::allGridsSupportsMultithreading(gridGeometryTuple_)
222 && !Multithreading::isSerial()
223
4/7
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 4 times.
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✓ Branch 6 taken 1 times.
✗ Branch 2 not taken.
5 && getParam<bool>("Assembly.Multithreading", true);
224
225 92 maybeComputeColors_();
226 5 }
227
228 /*!
229 * \brief Assembles the global Jacobian of the residual
230 * and the residual for the current solution.
231 */
232 10582 void assembleJacobianAndResidual(const SolutionVector& curSol)
233 {
234 10582 checkAssemblerState_();
235 10582 resetJacobian_();
236 10582 resetResidual_();
237
238 using namespace Dune::Hybrid;
239 80786 forEach(std::make_index_sequence<JacobianMatrix::N()>(), [&](const auto domainId)
240 {
241 19061 auto& jacRow = (*jacobian_)[domainId];
242 19061 auto& subRes = (*residual_)[domainId];
243 38122 this->assembleJacobianAndResidual_(domainId, jacRow, subRes, curSol);
244
245 38122 const auto gridGeometry = std::get<domainId>(gridGeometryTuple_);
246
8/10
✓ Branch 1 taken 287 times.
✓ Branch 2 taken 6612 times.
✓ Branch 3 taken 942 times.
✓ Branch 4 taken 1694 times.
✓ Branch 6 taken 1500 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 500 times.
✗ Branch 9 not taken.
✓ Branch 0 taken 7285 times.
✓ Branch 5 taken 241 times.
19061 enforcePeriodicConstraints_(domainId, jacRow, subRes, *gridGeometry, curSol[domainId]);
247 17141 });
248 10582 }
249
250 //! compute the residuals using the internal residual
251 1510 void assembleResidual(const SolutionVector& curSol)
252 {
253
1/8
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 1 taken 99 times.
✗ Branch 2 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
1510 resetResidual_();
254
1/8
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 1 taken 99 times.
✗ Branch 2 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
1510 assembleResidual(*residual_, curSol);
255 99 }
256
257 //! assemble a residual r
258 1510 void assembleResidual(ResidualType& r, const SolutionVector& curSol)
259 {
260 1510 r = 0.0;
261
262 1510 checkAssemblerState_();
263
264 // update the grid variables for the case of active caching
265 1510 updateGridVariables(curSol);
266
267 using namespace Dune::Hybrid;
268 6038 forEach(integralRange(Dune::Hybrid::size(r)), [&](const auto domainId)
269 {
270 1510 auto& subRes = r[domainId];
271 4528 this->assembleResidual_(domainId, subRes, curSol);
272 });
273 1509 }
274
275 /*!
276 * \brief Tells the assembler which jacobian and residual to use.
277 * This also resizes the containers to the required sizes and sets the
278 * sparsity pattern of the jacobian matrix.
279 */
280 3 void setLinearSystem(std::shared_ptr<JacobianMatrix> A,
281 std::shared_ptr<ResidualType> r)
282 {
283 3 jacobian_ = A;
284 3 residual_ = r;
285
286 3 setJacobianBuildMode(*jacobian_);
287 3 setJacobianPattern_(*jacobian_);
288 3 setResidualSize_(*residual_);
289 3 }
290
291 /*!
292 * \brief The version without arguments uses the default constructor to create
293 * the jacobian and residual objects in this assembler if you don't need them outside this class
294 */
295 204 void setLinearSystem()
296 {
297
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 197 times.
211 jacobian_ = std::make_shared<JacobianMatrix>();
298
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 197 times.
211 residual_ = std::make_shared<ResidualType>();
299
300 204 setJacobianBuildMode(*jacobian_);
301 244 setJacobianPattern_(*jacobian_);
302 244 setResidualSize_(*residual_);
303 204 }
304
305 /*!
306 * \brief Sets the jacobian build mode
307 */
308 228 void setJacobianBuildMode(JacobianMatrix& jac) const
309 {
310 using namespace Dune::Hybrid;
311 456 forEach(std::make_index_sequence<JacobianMatrix::N()>(), [&](const auto i)
312 {
313
1/2
✓ Branch 0 taken 1112 times.
✗ Branch 1 not taken.
2640 forEach(jac[i], [&](auto& jacBlock)
314 {
315 using BlockType = std::decay_t<decltype(jacBlock)>;
316
6/12
✓ Branch 0 taken 422 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 411 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 166 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 74 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 25 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 14 times.
✗ Branch 11 not taken.
1112 if (jacBlock.buildMode() == BlockType::BuildMode::unknown)
317 1112 jacBlock.setBuildMode(BlockType::BuildMode::random);
318 else if (jacBlock.buildMode() != BlockType::BuildMode::random)
319
0/120
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✗ Branch 22 not taken.
✗ Branch 23 not taken.
✗ Branch 25 not taken.
✗ Branch 26 not taken.
✗ Branch 28 not taken.
✗ Branch 29 not taken.
✗ Branch 35 not taken.
✗ Branch 36 not taken.
✗ Branch 38 not taken.
✗ Branch 39 not taken.
✗ Branch 41 not taken.
✗ Branch 42 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.
✗ Branch 53 not taken.
✗ Branch 54 not taken.
✗ Branch 56 not taken.
✗ Branch 57 not taken.
✗ Branch 59 not taken.
✗ Branch 60 not taken.
✗ Branch 62 not taken.
✗ Branch 63 not taken.
✗ Branch 69 not taken.
✗ Branch 70 not taken.
✗ Branch 72 not taken.
✗ Branch 73 not taken.
✗ Branch 75 not taken.
✗ Branch 76 not taken.
✗ Branch 78 not taken.
✗ Branch 79 not taken.
✗ Branch 81 not taken.
✗ Branch 82 not taken.
✗ Branch 84 not taken.
✗ Branch 85 not taken.
✗ Branch 87 not taken.
✗ Branch 88 not taken.
✗ Branch 90 not taken.
✗ Branch 91 not taken.
✗ Branch 93 not taken.
✗ Branch 94 not taken.
✗ Branch 96 not taken.
✗ Branch 97 not taken.
✗ Branch 103 not taken.
✗ Branch 104 not taken.
✗ Branch 106 not taken.
✗ Branch 107 not taken.
✗ Branch 109 not taken.
✗ Branch 110 not taken.
✗ Branch 112 not taken.
✗ Branch 113 not taken.
✗ Branch 115 not taken.
✗ Branch 116 not taken.
✗ Branch 118 not taken.
✗ Branch 119 not taken.
✗ Branch 121 not taken.
✗ Branch 122 not taken.
✗ Branch 124 not taken.
✗ Branch 125 not taken.
✗ Branch 127 not taken.
✗ Branch 128 not taken.
✗ Branch 130 not taken.
✗ Branch 131 not taken.
✗ Branch 137 not taken.
✗ Branch 138 not taken.
✗ Branch 140 not taken.
✗ Branch 141 not taken.
✗ Branch 143 not taken.
✗ Branch 144 not taken.
✗ Branch 146 not taken.
✗ Branch 147 not taken.
✗ Branch 149 not taken.
✗ Branch 150 not taken.
✗ Branch 152 not taken.
✗ Branch 153 not taken.
✗ Branch 155 not taken.
✗ Branch 156 not taken.
✗ Branch 158 not taken.
✗ Branch 159 not taken.
✗ Branch 161 not taken.
✗ Branch 162 not taken.
✗ Branch 164 not taken.
✗ Branch 165 not taken.
✗ Branch 171 not taken.
✗ Branch 172 not taken.
✗ Branch 174 not taken.
✗ Branch 175 not taken.
✗ Branch 177 not taken.
✗ Branch 178 not taken.
✗ Branch 180 not taken.
✗ Branch 181 not taken.
✗ Branch 183 not taken.
✗ Branch 184 not taken.
✗ Branch 186 not taken.
✗ Branch 187 not taken.
✗ Branch 189 not taken.
✗ Branch 190 not taken.
✗ Branch 192 not taken.
✗ Branch 193 not taken.
✗ Branch 195 not taken.
✗ Branch 196 not taken.
✗ Branch 198 not taken.
✗ Branch 199 not taken.
1112 DUNE_THROW(Dune::NotImplemented, "Only BCRS matrices with random build mode are supported at the moment");
320 });
321 });
322 }
323
324 /*!
325 * \brief Resizes jacobian and residual and recomputes colors
326 */
327 void updateAfterGridAdaption()
328 {
329 setJacobianPattern_(*jacobian_);
330 setResidualSize_(*residual_);
331 maybeComputeColors_();
332 }
333
334 /*!
335 * \brief Updates the grid variables with the given solution
336 */
337 10222 void updateGridVariables(const SolutionVector& curSol)
338 {
339 using namespace Dune::Hybrid;
340
3/6
✓ Branch 4 taken 1058 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1057 times.
✗ Branch 8 not taken.
✓ Branch 1 taken 19 times.
✗ Branch 2 not taken.
9285 forEach(integralRange(Dune::Hybrid::size(gridVariablesTuple_)), [&](const auto domainId)
341 13254 { this->gridVariables(domainId).update(curSol[domainId]); });
342 }
343
344 /*!
345 * \brief Resets the grid variables to the last time step
346 */
347 19 void resetTimeStep(const SolutionVector& curSol)
348 {
349 using namespace Dune::Hybrid;
350
3/7
✓ Branch 1 taken 15 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 4 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 4 times.
✗ Branch 8 not taken.
✗ Branch 0 not taken.
19 forEach(integralRange(Dune::Hybrid::size(gridVariablesTuple_)), [&](const auto domainId)
351 23 { this->gridVariables(domainId).resetTimeStep(curSol[domainId]); });
352 }
353
354 //! the number of dof locations of domain i
355 template<std::size_t i>
356 496 std::size_t numDofs(Dune::index_constant<i> domainId) const
357 465 { return std::get<domainId>(gridGeometryTuple_)->numDofs(); }
358
359 //! the problem of domain i
360 template<std::size_t i>
361 282850612 const auto& problem(Dune::index_constant<i> domainId) const
362
49/53
✓ Branch 0 taken 531288 times.
✓ Branch 1 taken 52178551 times.
✓ Branch 2 taken 21002 times.
✓ Branch 3 taken 10337995 times.
✓ Branch 4 taken 6911314 times.
✓ Branch 5 taken 6821857 times.
✓ Branch 6 taken 1638936 times.
✓ Branch 7 taken 60450441 times.
✓ Branch 9 taken 8569479 times.
✓ Branch 10 taken 6152 times.
✓ Branch 12 taken 5507658 times.
✓ Branch 13 taken 1502570 times.
✓ Branch 15 taken 20538027 times.
✓ Branch 16 taken 46 times.
✓ Branch 18 taken 10030774 times.
✓ Branch 19 taken 15 times.
✓ Branch 21 taken 1308544 times.
✓ Branch 22 taken 17 times.
✓ Branch 24 taken 712274 times.
✓ Branch 25 taken 858512 times.
✓ Branch 29 taken 2441133 times.
✓ Branch 30 taken 542894 times.
✓ Branch 32 taken 39153 times.
✓ Branch 33 taken 790179 times.
✓ Branch 11 taken 2769786 times.
✓ Branch 14 taken 481885 times.
✓ Branch 20 taken 4290217 times.
✓ Branch 23 taken 325726 times.
✓ Branch 17 taken 67 times.
✓ Branch 26 taken 5234901 times.
✓ Branch 28 taken 646167 times.
✓ Branch 31 taken 574669 times.
✓ Branch 8 taken 1100258 times.
✓ Branch 27 taken 1381617 times.
✓ Branch 36 taken 4 times.
✓ Branch 37 taken 374003 times.
✓ Branch 39 taken 3 times.
✓ Branch 40 taken 374005 times.
✓ Branch 34 taken 1 times.
✓ Branch 41 taken 39042 times.
✓ Branch 43 taken 4 times.
✓ Branch 44 taken 1 times.
✓ Branch 35 taken 15 times.
✓ Branch 38 taken 39056 times.
✓ Branch 42 taken 1 times.
✓ Branch 45 taken 1 times.
✓ Branch 47 taken 1 times.
✗ Branch 48 not taken.
✗ Branch 46 not taken.
✓ Branch 50 taken 1 times.
✗ Branch 51 not taken.
✓ Branch 53 taken 1 times.
✗ Branch 54 not taken.
697442943 { return *std::get<domainId>(problemTuple_); }
363
364 //! the finite volume grid geometry of domain i
365 template<std::size_t i>
366 39062556 const auto& gridGeometry(Dune::index_constant<i> domainId) const
367
8/12
✓ Branch 1 taken 7468405 times.
✓ Branch 2 taken 193914 times.
✓ Branch 4 taken 24428846 times.
✓ Branch 5 taken 851040 times.
✗ Branch 3 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 773889 times.
✓ Branch 8 taken 39040 times.
✓ Branch 9 taken 150000 times.
✗ Branch 10 not taken.
✓ Branch 12 taken 2892000 times.
✗ Branch 13 not taken.
37540948 { return *std::get<domainId>(gridGeometryTuple_); }
368
369 //! the grid view of domain i
370 template<std::size_t i>
371
9/16
✓ Branch 1 taken 1370 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 807 times.
✓ Branch 5 taken 5679 times.
✓ Branch 6 taken 7 times.
✓ Branch 7 taken 8089 times.
✓ Branch 9 taken 910 times.
✗ Branch 10 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✗ Branch 0 not taken.
✓ Branch 3 taken 1371 times.
✓ Branch 8 taken 7 times.
✓ Branch 11 taken 910 times.
21496 const auto& gridView(Dune::index_constant<i> domainId) const
372
26/46
✓ Branch 1 taken 131 times.
✓ Branch 2 taken 1239 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 131 times.
✓ Branch 6 taken 1240 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 1371 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 146 times.
✗ Branch 14 not taken.
✓ Branch 15 taken 1283 times.
✓ Branch 16 taken 2 times.
✓ Branch 17 taken 5201 times.
✓ Branch 19 taken 1168 times.
✓ Branch 20 taken 4380 times.
✓ Branch 22 taken 1283 times.
✓ Branch 23 taken 171 times.
✓ Branch 24 taken 1500 times.
✓ Branch 25 taken 5259 times.
✓ Branch 27 taken 169 times.
✓ Branch 28 taken 6628 times.
✗ Branch 29 not taken.
✓ Branch 30 taken 162 times.
✗ Branch 32 not taken.
✓ Branch 33 taken 748 times.
✓ Branch 35 taken 162 times.
✓ Branch 36 taken 748 times.
✗ Branch 37 not taken.
✓ Branch 38 taken 162 times.
✗ Branch 40 not taken.
✓ Branch 41 taken 748 times.
✗ Branch 10 not taken.
✓ Branch 18 taken 138 times.
✗ Branch 26 not taken.
✗ Branch 31 not taken.
✗ Branch 21 not taken.
✓ Branch 13 taken 823 times.
✗ Branch 5 not taken.
✗ Branch 34 not taken.
✗ Branch 39 not taken.
✗ Branch 42 not taken.
✗ Branch 43 not taken.
✓ Branch 44 taken 748 times.
✗ Branch 46 not taken.
✗ Branch 47 not taken.
42993 { return gridGeometry(domainId).gridView(); }
373
374 //! the grid variables of domain i
375 template<std::size_t i>
376 41857293 GridVariables<i>& gridVariables(Dune::index_constant<i> domainId)
377
15/23
✓ Branch 1 taken 894377 times.
✓ Branch 2 taken 5308770 times.
✓ Branch 4 taken 2539442 times.
✓ Branch 5 taken 21462027 times.
✓ Branch 7 taken 833114 times.
✓ Branch 8 taken 201045 times.
✓ Branch 10 taken 668890 times.
✓ Branch 11 taken 352352 times.
✓ Branch 13 taken 1171704 times.
✗ Branch 14 not taken.
✓ Branch 16 taken 100012 times.
✗ Branch 17 not taken.
✓ Branch 19 taken 100264 times.
✗ Branch 20 not taken.
✓ Branch 22 taken 105781 times.
✗ Branch 23 not taken.
✓ Branch 3 taken 362500 times.
✓ Branch 6 taken 989000 times.
✗ Branch 9 not taken.
✗ Branch 12 not taken.
✗ Branch 15 not taken.
✓ Branch 25 taken 1928000 times.
✗ Branch 26 not taken.
40550189 { return *std::get<domainId>(gridVariablesTuple_); }
378
379 //! the grid variables of domain i
380 template<std::size_t i>
381 500 const GridVariables<i>& gridVariables(Dune::index_constant<i> domainId) const
382
2/4
✓ Branch 1 taken 200 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 200 times.
✗ Branch 5 not taken.
500 { return *std::get<domainId>(gridVariablesTuple_); }
383
384 //! the coupling manager
385 const CouplingManager& couplingManager() const
386 { return *couplingManager_; }
387
388 //! the full Jacobian matrix
389 7572 JacobianMatrix& jacobian()
390
2/6
✗ Branch 0 not taken.
✓ Branch 1 taken 6642 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 13 times.
✗ Branch 2 not taken.
✗ Branch 5 not taken.
15123 { return *jacobian_; }
391
392 //! the full residual vector
393 11506 ResidualType& residual()
394
5/19
✓ Branch 5 taken 15 times.
✗ Branch 6 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✓ Branch 11 taken 6 times.
✓ Branch 12 taken 1 times.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✗ Branch 17 not taken.
✗ Branch 18 not taken.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
✓ Branch 3 taken 2404 times.
✗ Branch 4 not taken.
✗ Branch 7 not taken.
✗ Branch 10 not taken.
✓ Branch 1 taken 119 times.
✗ Branch 2 not taken.
✗ Branch 13 not taken.
11506 { return *residual_; }
395
396 //! the solution of the previous time step
397 5138804 const SolutionVector& prevSol() const
398
6/10
✓ Branch 4 taken 264000 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 100000 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 100000 times.
✗ Branch 11 not taken.
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
✓ Branch 6 taken 100000 times.
✓ Branch 9 taken 617000 times.
5845108 { return *prevSol_; }
399
400 /*!
401 * \brief Set time loop for instationary problems
402 * \note calling this turns this into a stationary assembler
403 */
404 void setTimeManager(std::shared_ptr<const TimeLoop> timeLoop)
405 { timeLoop_ = timeLoop; isStationaryProblem_ = !(static_cast<bool>(timeLoop)); }
406
407 /*!
408 * \brief Sets the solution from which to start the time integration. Has to be
409 * called prior to assembly for time-dependent problems.
410 */
411 void setPreviousSolution(const SolutionVector& u)
412 { prevSol_ = &u; }
413
414 /*!
415 * \brief Whether we are assembling a stationary or instationary problem
416 */
417 381113927 bool isStationaryProblem() const
418
18/22
✓ Branch 0 taken 58579817 times.
✓ Branch 1 taken 3640910 times.
✓ Branch 2 taken 158890249 times.
✓ Branch 3 taken 14579631 times.
✓ Branch 4 taken 30769995 times.
✓ Branch 5 taken 26049376 times.
✓ Branch 6 taken 33405966 times.
✓ Branch 7 taken 25166614 times.
✓ Branch 8 taken 2757828 times.
✓ Branch 9 taken 6142431 times.
✓ Branch 10 taken 192855 times.
✓ Branch 11 taken 12587902 times.
✓ Branch 12 taken 2892000 times.
✓ Branch 13 taken 388353 times.
✗ Branch 14 not taken.
✓ Branch 15 taken 150000 times.
✗ Branch 16 not taken.
✓ Branch 17 taken 2892000 times.
✗ Branch 18 not taken.
✓ Branch 19 taken 100000 times.
✗ Branch 20 not taken.
✓ Branch 21 taken 1928000 times.
381113927 { return isStationaryProblem_; }
419
420 /*!
421 * \brief Create a local residual object (used by the local assembler)
422 */
423 template<std::size_t i>
424 39183619 LocalResidual<i> localResidual(Dune::index_constant<i> domainId) const
425
7/15
✓ Branch 1 taken 7662908 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 24465960 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1627330 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 150618 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 163489 times.
✗ Branch 14 not taken.
✓ Branch 16 taken 2892000 times.
✗ Branch 17 not taken.
✓ Branch 19 taken 300 times.
✗ Branch 20 not taken.
✗ Branch 6 not taken.
38750335 { return LocalResidual<i>(std::get<domainId>(problemTuple_).get(), timeLoop_.get()); }
426
427 protected:
428 //! the coupling manager coupling the sub domains
429 std::shared_ptr<CouplingManager> couplingManager_;
430
431 private:
432 /*!
433 * \brief Sets the jacobian sparsity pattern.
434 */
435 234 void setJacobianPattern_(JacobianMatrix& jac) const
436 {
437 using namespace Dune::Hybrid;
438 1754 forEach(std::make_index_sequence<JacobianMatrix::N()>(), [&](const auto domainI)
439 {
440 4816 forEach(integralRange(Dune::Hybrid::size(jac[domainI])), [&](const auto domainJ)
441 {
442 1981 const auto pattern = this->getJacobianPattern_(domainI, domainJ);
443
9/18
✓ Branch 1 taken 225 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 225 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 225 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 225 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 43 times.
✗ Branch 14 not taken.
✓ Branch 16 taken 43 times.
✗ Branch 17 not taken.
✓ Branch 19 taken 42 times.
✗ Branch 20 not taken.
✓ Branch 22 taken 42 times.
✗ Branch 23 not taken.
✓ Branch 25 taken 40 times.
✗ Branch 26 not taken.
1110 pattern.exportIdx(jac[domainI][domainJ]);
444 1112 });
445 });
446 194 }
447
448 /*!
449 * \brief Resizes the residual
450 */
451 232 void setResidualSize_(ResidualType& res) const
452 {
453 using namespace Dune::Hybrid;
454 1876 forEach(integralRange(Dune::Hybrid::size(res)), [&](const auto domainId)
455 465 { res[domainId].resize(this->numDofs(domainId)); });
456 159 }
457
458 // reset the residual vector to 0.0
459 12092 void resetResidual_()
460 {
461
2/2
✓ Branch 0 taken 21 times.
✓ Branch 1 taken 10561 times.
12092 if(!residual_)
462 {
463
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 21 times.
21 residual_ = std::make_shared<ResidualType>();
464 21 setResidualSize_(*residual_);
465 }
466
467 12092 (*residual_) = 0.0;
468 12092 }
469
470 // reset the jacobian vector to 0.0
471 10582 void resetJacobian_()
472 {
473
2/2
✓ Branch 0 taken 21 times.
✓ Branch 1 taken 9051 times.
10582 if(!jacobian_)
474 {
475
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 21 times.
21 jacobian_ = std::make_shared<JacobianMatrix>();
476 21 setJacobianBuildMode(*jacobian_);
477 21 setJacobianPattern_(*jacobian_);
478 }
479
480 10582 (*jacobian_) = 0.0;
481 10582 }
482
483 //! Computes the colors
484 221 void maybeComputeColors_()
485 {
486 if constexpr (CouplingManagerSupportsMultithreadedAssembly<CouplingManager>::value)
487
1/2
✓ Branch 0 taken 26 times.
✗ Branch 1 not taken.
26 if (enableMultithreading_)
488
1/2
✓ Branch 1 taken 26 times.
✗ Branch 2 not taken.
26 couplingManager_->computeColorsForAssembly();
489 }
490
491 // check if the assembler is in a correct state for assembly
492 12092 void checkAssemblerState_() const
493 {
494
3/4
✓ Branch 0 taken 10226 times.
✓ Branch 1 taken 356 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 10226 times.
12092 if (!isStationaryProblem_ && !prevSol_)
495 DUNE_THROW(Dune::InvalidStateException, "Assembling instationary problem but previous solution was not set!");
496
497
3/4
✓ Branch 0 taken 356 times.
✓ Branch 1 taken 10226 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 356 times.
12092 if (isStationaryProblem_ && prevSol_)
498 DUNE_THROW(Dune::InvalidStateException, "Assembling stationary problem but a previous solution was set."
499 << " Did you forget to set the timeLoop to make this problem instationary?");
500 12092 }
501
502 template<std::size_t i, class JacRow, class SubRes>
503 19061 void assembleJacobianAndResidual_(Dune::index_constant<i> domainId, JacRow& jacRow, SubRes& subRes,
504 const SolutionVector& curSol)
505 {
506 97841685 assemble_(domainId, [&](const auto& element)
507 {
508
1/2
✓ Branch 1 taken 40 times.
✗ Branch 2 not taken.
24455656 MultiDomainAssemblerSubDomainView view{*this, domainId};
509
1/2
✓ Branch 1 taken 40 times.
✗ Branch 2 not taken.
24455656 SubDomainAssembler<i> subDomainAssembler(view, element, curSol, *couplingManager_);
510
10/13
✓ Branch 1 taken 5354528 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 261096 times.
✓ Branch 4 taken 13577648 times.
✓ Branch 6 taken 518162 times.
✓ Branch 7 taken 492181 times.
✓ Branch 8 taken 754509 times.
✓ Branch 9 taken 57708 times.
✓ Branch 5 taken 1319082 times.
✓ Branch 10 taken 1928000 times.
✓ Branch 13 taken 964000 times.
✗ Branch 14 not taken.
✗ Branch 11 not taken.
27176800 subDomainAssembler.assembleJacobianAndResidual(jacRow, subRes, gridVariablesTuple_);
511 24455656 });
512 }
513
514 template<std::size_t i, class SubRes>
515 1509 void assembleResidual_(Dune::index_constant<i> domainId, SubRes& subRes,
516 const SolutionVector& curSol)
517 {
518 58251476 assemble_(domainId, [&](const auto& element)
519 {
520 14562492 MultiDomainAssemblerSubDomainView view{*this, domainId};
521 14562492 SubDomainAssembler<i> subDomainAssembler(view, element, curSol, *couplingManager_);
522
3/6
✓ Branch 1 taken 2773386 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 11789105 times.
✓ Branch 5 taken 1 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
14562492 subDomainAssembler.assembleResidual(subRes);
523 14562491 });
524 }
525
526 /*!
527 * \brief A method assembling something per element
528 * \note Handles exceptions for parallel runs
529 * \throws NumericalProblem on all processes if an exception is thrown during assembly
530 */
531 template<std::size_t i, class AssembleElementFunc>
532 44160 void assemble_(Dune::index_constant<i> domainId, AssembleElementFunc&& assembleElement) const
533 {
534 // a state that will be checked on all processes
535
1/2
✓ Branch 1 taken 16590 times.
✗ Branch 2 not taken.
44160 bool succeeded = false;
536
537 // try assembling using the local assembly function
538 try
539 {
540 if constexpr (CouplingManagerSupportsMultithreadedAssembly<CouplingManager>::value)
541 {
542
1/2
✓ Branch 0 taken 584 times.
✗ Branch 1 not taken.
1168 if (enableMultithreading_)
543 {
544
1/2
✓ Branch 1 taken 584 times.
✗ Branch 2 not taken.
1168 couplingManager_->assembleMultithreaded(
545 domainId, std::forward<AssembleElementFunc>(assembleElement)
546 );
547 1168 return;
548 }
549 }
550
551 // fallback for coupling managers that don't support multithreaded assembly (yet)
552 // or if multithreaded assembly is disabled
553 // let the local assembler add the element contributions
554
12/13
✓ Branch 1 taken 16590 times.
✓ Branch 2 taken 2962815 times.
✓ Branch 4 taken 29341154 times.
✓ Branch 5 taken 4 times.
✓ Branch 7 taken 27206912 times.
✓ Branch 8 taken 50713 times.
✓ Branch 10 taken 3789113 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 3789085 times.
✓ Branch 13 taken 2346 times.
✓ Branch 3 taken 5278 times.
✓ Branch 6 taken 2069606 times.
✓ Branch 9 taken 326348 times.
144365246 for (const auto& element : elements(gridView(domainId)))
555
2/2
✓ Branch 1 taken 36076810 times.
✓ Branch 2 taken 1 times.
72153622 assembleElement(element);
556
557 // if we get here, everything worked well on this process
558 42990 succeeded = true;
559 }
560 // throw exception if a problem occurred
561
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
2 catch (NumericalProblem &e)
562 {
563
2/5
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
✗ Branch 2 not taken.
2 std::cout << "rank " << gridView(domainId).comm().rank()
564 2 << " caught an exception while assembling:" << e.what()
565
4/8
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 8 taken 1 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 1 times.
✗ Branch 12 not taken.
2 << "\n";
566 2 succeeded = false;
567 }
568
569 // make sure everything worked well on all processes
570
3/4
✗ Branch 0 not taken.
✓ Branch 1 taken 19150 times.
✓ Branch 2 taken 2346 times.
✓ Branch 3 taken 13982 times.
42992 if (gridView(domainId).comm().size() > 1)
571 succeeded = gridView(domainId).comm().min(succeeded);
572
573 // if not succeeded rethrow the error on all processes
574
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 21495 times.
42992 if (!succeeded)
575
11/22
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 1 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 1 times.
✗ Branch 14 not taken.
✓ Branch 16 taken 1 times.
✗ Branch 17 not taken.
✓ Branch 19 taken 1 times.
✗ Branch 20 not taken.
✓ Branch 22 taken 1 times.
✗ Branch 23 not taken.
✓ Branch 25 taken 1 times.
✗ Branch 26 not taken.
✓ Branch 28 taken 1 times.
✗ Branch 29 not taken.
✓ Branch 32 taken 1 times.
✗ Branch 33 not taken.
8 DUNE_THROW(NumericalProblem, "A process did not succeed in linearizing the system");
576 42990 }
577
578 // get diagonal block pattern
579 template<std::size_t i, std::size_t j, typename std::enable_if_t<(i==j), int> = 0>
580 548 Dune::MatrixIndexSet getJacobianPattern_(Dune::index_constant<i> domainI,
581 Dune::index_constant<j> domainJ) const
582 {
583 548 const auto& gg = gridGeometry(domainI);
584 548 auto pattern = getJacobianPattern<isImplicit()>(gg);
585
4/8
✓ Branch 1 taken 252 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 200 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 42 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 2 times.
✗ Branch 11 not taken.
548 couplingManager_->extendJacobianPattern(domainI, pattern);
586 115 return pattern;
587 }
588
589 // get coupling block pattern
590 template<std::size_t i, std::size_t j, typename std::enable_if_t<(i!=j), int> = 0>
591
2/4
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
616 Dune::MatrixIndexSet getJacobianPattern_(Dune::index_constant<i> domainI,
592 Dune::index_constant<j> domainJ) const
593 {
594
2/4
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
536 return getCouplingJacobianPattern<isImplicit()>(*couplingManager_,
595 domainI, gridGeometry(domainI),
596
2/4
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
616 domainJ, gridGeometry(domainJ));
597 }
598
599 // build periodic constraints into the system matrix
600 template<std::size_t i, class JacRow, class Res, class GG, class Sol>
601 2255 void enforcePeriodicConstraints_(Dune::index_constant<i> domainI, JacRow& jacRow, Res& res, const GG& gridGeometry, const Sol& curSol)
602 {
603 if constexpr (Detail::hasPeriodicDofMap<GG>())
604 {
605
2/2
✓ Branch 0 taken 644 times.
✓ Branch 1 taken 1715 times.
2899 for (const auto& m : gridGeometry.periodicDofMap())
606 {
607
2/2
✓ Branch 0 taken 322 times.
✓ Branch 1 taken 322 times.
644 if (m.first < m.second)
608 {
609 322 auto& jac = jacRow[domainI];
610
611 // add the second row to the first
612 322 res[m.first] += res[m.second];
613
614 322 const auto end = jac[m.second].end();
615
2/2
✓ Branch 0 taken 2838 times.
✓ Branch 1 taken 322 times.
3160 for (auto it = jac[m.second].begin(); it != end; ++it)
616 2838 jac[m.first][it.index()] += (*it);
617
618
619 // enforce the solution of the first periodic DOF to the second one
620 322 res[m.second] = curSol[m.second] - curSol[m.first];
621
622 // set derivatives accordingly in jacobian, i.e. id for m.second and -id for m.first
623 auto setMatrixBlock = [] (auto& matrixBlock, double diagValue)
624 {
625
0/4
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
644 for (int eIdx = 0; eIdx < matrixBlock.N(); ++eIdx)
626 644 matrixBlock[eIdx][eIdx] = diagValue;
627 };
628
629
3/4
✗ Branch 0 not taken.
✓ Branch 1 taken 3160 times.
✓ Branch 2 taken 2838 times.
✓ Branch 3 taken 322 times.
3160 for (auto it = jac[m.second].begin(); it != end; ++it)
630 {
631 2838 auto& matrixBlock = *it;
632
2/2
✓ Branch 0 taken 322 times.
✓ Branch 1 taken 2516 times.
2838 matrixBlock = 0.0;
633
634 assert(matrixBlock.N() == matrixBlock.M());
635
2/2
✓ Branch 0 taken 322 times.
✓ Branch 1 taken 2516 times.
2838 if(it.index() == m.second)
636 2838 setMatrixBlock(matrixBlock, 1.0);
637
638
2/2
✓ Branch 0 taken 322 times.
✓ Branch 1 taken 2516 times.
2838 if(it.index() == m.first)
639 2838 setMatrixBlock(matrixBlock, -1.0);
640
641 }
642
643 using namespace Dune::Hybrid;
644 322 forEach(makeIncompleteIntegerSequence<JacRow::size(), domainI>(), [&](const auto couplingDomainId)
645 {
646 322 auto& jacCoupling = jacRow[couplingDomainId];
647
648
3/8
✗ Branch 0 not taken.
✓ Branch 1 taken 644 times.
✓ Branch 2 taken 322 times.
✓ Branch 3 taken 322 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
644 for (auto it = jacCoupling[m.second].begin(); it != jacCoupling[m.second].end(); ++it)
649 322 jacCoupling[m.first][it.index()] += (*it);
650
651
2/4
✓ Branch 0 taken 322 times.
✓ Branch 1 taken 322 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
644 for (auto it = jacCoupling[m.second].begin(); it != jacCoupling[m.second].end(); ++it)
652 322 (*it) = 0.0;
653 });
654 }
655 }
656 }
657 2255 }
658
659 //! pointer to the problem to be solved
660 ProblemTuple problemTuple_;
661
662 //! the finite volume geometry of the grid
663 GridGeometryTuple gridGeometryTuple_;
664
665 //! the variables container for the grid
666 GridVariablesTuple gridVariablesTuple_;
667
668 //! the time loop for instationary problem assembly
669 std::shared_ptr<const TimeLoop> timeLoop_;
670
671 //! an observing pointer to the previous solution for instationary problems
672 const SolutionVector* prevSol_ = nullptr;
673
674 //! if this assembler is assembling an instationary problem
675 bool isStationaryProblem_;
676
677 //! shared pointers to the jacobian matrix and residual
678 std::shared_ptr<JacobianMatrix> jacobian_;
679 std::shared_ptr<ResidualType> residual_;
680
681 //! Issue a warning if the calculation is used in parallel with overlap. This could be a static local variable if it wasn't for g++7 yielding a linker error.
682 mutable bool warningIssued_;
683
684 //! if multithreaded assembly is enabled
685 bool enableMultithreading_ = false;
686 };
687
688 } // end namespace Dumux
689
690 #endif
691