GCC Code Coverage Report


Directory: ../../../builds/dumux-repositories/
File: /builds/dumux-repositories/dumux/dumux/experimental/assembly/multistagefvassembler.hh
Date: 2024-05-04 19:09:25
Exec Total Coverage
Lines: 111 144 77.1%
Functions: 75 106 70.8%
Branches: 126 367 34.3%

Line Branch Exec Source
1 // -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2 // vi: set et ts=4 sw=4 sts=4:
3 //
4 // SPDX-FileCopyrightInfo: Copyright © DuMux Project contributors, see AUTHORS.md in root folder
5 // SPDX-License-Identifier: GPL-3.0-or-later
6 //
7 /*!
8 * \file
9 * \ingroup Experimental
10 * \ingroup Assembly
11 * \brief A linear system assembler (residual and Jacobian) for finite volume schemes
12 */
13 #ifndef DUMUX_EXPERIMENTAL_MULTISTAGE_FV_ASSEMBLER_HH
14 #define DUMUX_EXPERIMENTAL_MULTISTAGE_FV_ASSEMBLER_HH
15
16 #include <vector>
17 #include <deque>
18 #include <type_traits>
19 #include <memory>
20
21 #include <dune/istl/matrixindexset.hh>
22
23 #include <dumux/common/properties.hh>
24 #include <dumux/common/gridcapabilities.hh>
25 #include <dumux/common/typetraits/vector.hh>
26
27 #include <dumux/discretization/method.hh>
28 #include <dumux/linear/parallelhelpers.hh>
29 #include <dumux/linear/dunevectors.hh>
30
31 #include <dumux/assembly/coloring.hh>
32 #include <dumux/assembly/jacobianpattern.hh>
33 #include <dumux/assembly/diffmethod.hh>
34
35 #include <dumux/parallel/multithreading.hh>
36 #include <dumux/parallel/parallel_for.hh>
37
38 #include <dumux/experimental/assembly/cvfelocalassembler.hh>
39 #include <dumux/experimental/assembly/cclocalassembler.hh>
40 #include <dumux/experimental/assembly/multistagefvlocaloperator.hh>
41
42 #include <dumux/experimental/timestepping/multistagemethods.hh>
43 #include <dumux/experimental/timestepping/multistagetimestepper.hh>
44
45 namespace Dumux::Experimental::Detail {
46
47 template<class DiscretizationMethod>
48 struct LocalAssemblerChooser;
49
50 template<class DM>
51 struct LocalAssemblerChooser<DiscretizationMethods::CVFE<DM>>
52 {
53 template<class TypeTag, class Impl, DiffMethod diffMethod>
54 using type = Experimental::CVFELocalAssembler<TypeTag, Impl, diffMethod>;
55 };
56
57 template<>
58 struct LocalAssemblerChooser<DiscretizationMethods::CCMpfa>
59 {
60 template<class TypeTag, class Impl, DiffMethod diffMethod>
61 using type = Experimental::CCLocalAssembler<TypeTag, Impl, diffMethod>;
62 };
63
64 template<>
65 struct LocalAssemblerChooser<DiscretizationMethods::CCTpfa>
66 {
67 template<class TypeTag, class Impl, DiffMethod diffMethod>
68 using type = Experimental::CCLocalAssembler<TypeTag, Impl, diffMethod>;
69 };
70
71 template<class TypeTag, class Impl, DiffMethod diffMethod>
72 using LocalAssemblerChooser_t = typename LocalAssemblerChooser<
73 typename GetPropType<TypeTag, Properties::GridGeometry>::DiscretizationMethod
74 >::template type<TypeTag, Impl, diffMethod>;
75
76 } // end namespace Dumux::Detail
77
78 namespace Dumux::Experimental {
79
80 /*!
81 * \ingroup Experimental
82 * \ingroup Assembly
83 * \brief A linear system assembler (residual and Jacobian) for finite volume schemes (box, tpfa, mpfa, ...)
84 * \tparam TypeTag The TypeTag
85 * \tparam diffMethod The differentiation method to residual compute derivatives
86 */
87 template<class TypeTag, DiffMethod diffMethod>
88 class MultiStageFVAssembler
89 {
90 using GridGeo = GetPropType<TypeTag, Properties::GridGeometry>;
91 using GridView = typename GridGeo::GridView;
92 using LocalResidual = GetPropType<TypeTag, Properties::LocalResidual>;
93 using Element = typename GridView::template Codim<0>::Entity;
94 using ElementSeed = typename GridView::Grid::template Codim<0>::EntitySeed;
95
96 static constexpr bool isBox = GridGeo::discMethod == DiscretizationMethods::box;
97
98 using ThisType = MultiStageFVAssembler<TypeTag, diffMethod>;
99 using LocalAssembler = typename Detail::LocalAssemblerChooser_t<TypeTag, ThisType, diffMethod>;
100
101 public:
102 using Scalar = GetPropType<TypeTag, Properties::Scalar>;
103 using StageParams = Experimental::MultiStageParams<Scalar>;
104 using JacobianMatrix = GetPropType<TypeTag, Properties::JacobianMatrix>;
105 using SolutionVector = GetPropType<TypeTag, Properties::SolutionVector>;
106 using ResidualType = typename Dumux::Detail::NativeDuneVectorType<SolutionVector>::type;
107
108 using GridVariables = GetPropType<TypeTag, Properties::GridVariables>;
109
110 using GridGeometry = GridGeo;
111 using Problem = GetPropType<TypeTag, Properties::Problem>;
112
113 /*!
114 * \brief The constructor for instationary problems
115 * \note the grid variables might be temporarily changed during assembly (if caching is enabled)
116 * it is however guaranteed that the state after assembly will be the same as before
117 */
118 9 MultiStageFVAssembler(std::shared_ptr<const Problem> problem,
119 std::shared_ptr<const GridGeometry> gridGeometry,
120 std::shared_ptr<GridVariables> gridVariables,
121 std::shared_ptr<const Experimental::MultiStageMethod<Scalar>> msMethod,
122 const SolutionVector& prevSol)
123 : timeSteppingMethod_(msMethod)
124 , problem_(problem)
125 , gridGeometry_(gridGeometry)
126 , gridVariables_(gridVariables)
127
2/20
✓ Branch 9 taken 9 times.
✗ Branch 10 not taken.
✓ Branch 12 taken 9 times.
✗ 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.
✗ Branch 26 not taken.
✗ Branch 27 not taken.
✗ Branch 30 not taken.
✗ Branch 31 not taken.
9 , prevSol_(&prevSol)
128 {
129 9 enableMultithreading_ = SupportsColoring<typename GridGeometry::DiscretizationMethod>::value
130
3/6
✓ Branch 1 taken 9 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 9 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 9 times.
✗ Branch 8 not taken.
27 && Grid::Capabilities::supportsMultithreading(gridGeometry_->gridView())
131 && !Multithreading::isSerial()
132
2/4
✓ Branch 1 taken 9 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 9 times.
9 && getParam<bool>("Assembly.Multithreading", true);
133
134
1/2
✓ Branch 1 taken 9 times.
✗ Branch 2 not taken.
9 maybeComputeColors_();
135 9 }
136
137 /*!
138 * \brief Assembles the global Jacobian of the residual
139 * and the residual for the current solution.
140 */
141 template<class PartialReassembler = DefaultPartialReassembler>
142 2172 void assembleJacobianAndResidual(const SolutionVector& curSol, const PartialReassembler* partialReassembler = nullptr)
143 {
144 2172 resetJacobian_(partialReassembler);
145
146 2172 resetResidual_();
147 4344 spatialOperatorEvaluations_.back() = 0.0;
148 4344 temporalOperatorEvaluations_.back() = 0.0;
149
150
3/6
✗ Branch 0 not taken.
✓ Branch 1 taken 2172 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 2172 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 2172 times.
6516 if (stageParams_->size() != spatialOperatorEvaluations_.size())
151 DUNE_THROW(Dune::InvalidStateException, "Wrong number of residuals");
152
153 2172 assemble_([&](const Element& element)
154 {
155
1/4
✓ Branch 1 taken 10368 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
12652448 LocalAssembler localAssembler(*this, element, curSol);
156
1/2
✓ Branch 1 taken 5066048 times.
✗ Branch 2 not taken.
5066048 localAssembler.assembleJacobianAndResidual(
157
3/6
✓ Branch 1 taken 5066048 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 5066048 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 5066048 times.
✗ Branch 8 not taken.
15198144 *jacobian_, *residual_, *gridVariables_,
158
2/4
✓ Branch 1 taken 5066048 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 5066048 times.
✗ Branch 5 not taken.
10132096 *stageParams_,
159 temporalOperatorEvaluations_.back(),
160 spatialOperatorEvaluations_.back(),
161 5066048 constrainedDofs_,
162
1/2
✓ Branch 1 taken 5066048 times.
✗ Branch 2 not taken.
5066048 partialReassembler
163 );
164 });
165
166 // assemble the full residual for the time integration stage
167
1/2
✓ Branch 2 taken 2172 times.
✗ Branch 3 not taken.
6516 auto constantResidualComponent = (*residual_);
168 constantResidualComponent = 0.0;
169
4/4
✓ Branch 0 taken 2172 times.
✓ Branch 1 taken 2172 times.
✓ Branch 2 taken 2172 times.
✓ Branch 3 taken 2172 times.
6516 for (std::size_t k = 0; k < stageParams_->size()-1; ++k)
170 {
171
3/6
✓ Branch 0 taken 2172 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2172 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2172 times.
✗ Branch 5 not taken.
6516 if (!stageParams_->skipTemporal(k))
172 8688 constantResidualComponent.axpy(stageParams_->temporalWeight(k), temporalOperatorEvaluations_[k]);
173
6/6
✓ Branch 0 taken 2000 times.
✓ Branch 1 taken 172 times.
✓ Branch 2 taken 2000 times.
✓ Branch 3 taken 172 times.
✓ Branch 4 taken 2000 times.
✓ Branch 5 taken 172 times.
6516 if (!stageParams_->skipSpatial(k))
174 8000 constantResidualComponent.axpy(stageParams_->spatialWeight(k), spatialOperatorEvaluations_[k]);
175 }
176
177 // masked summation of constant residual component onto this stage's resiudal component
178
2/2
✓ Branch 0 taken 5068836 times.
✓ Branch 1 taken 2172 times.
5071008 for (std::size_t i = 0; i < constantResidualComponent.size(); ++i)
179
4/4
✓ Branch 0 taken 10137672 times.
✓ Branch 1 taken 5068836 times.
✓ Branch 2 taken 10137672 times.
✓ Branch 3 taken 5068836 times.
30413016 for (std::size_t ii = 0; ii < constantResidualComponent[i].size(); ++ii)
180
6/6
✓ Branch 0 taken 10135360 times.
✓ Branch 1 taken 2312 times.
✓ Branch 2 taken 10135360 times.
✓ Branch 3 taken 2312 times.
✓ Branch 4 taken 10135360 times.
✓ Branch 5 taken 2312 times.
30413016 (*residual_)[i][ii] += constrainedDofs_[i][ii] > 0.5 ? 0.0 : constantResidualComponent[i][ii];
181 2172 }
182
183 //! compute the residuals using the internal residual
184 void assembleResidual(const SolutionVector& curSol)
185 { DUNE_THROW(Dune::NotImplemented, "residual"); }
186
187 /*!
188 * \brief The version without arguments uses the default constructor to create
189 * the jacobian and residual objects in this assembler if you don't need them outside this class
190 */
191 9 void setLinearSystem()
192 {
193
2/4
✗ Branch 1 not taken.
✓ Branch 2 taken 9 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 9 times.
9 jacobian_ = std::make_shared<JacobianMatrix>();
194 18 jacobian_->setBuildMode(JacobianMatrix::random);
195
2/4
✗ Branch 1 not taken.
✓ Branch 2 taken 9 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 9 times.
9 residual_ = std::make_shared<ResidualType>();
196
197 15 setResidualSize_(*residual_);
198 9 setJacobianPattern_();
199 9 }
200
201 /*!
202 * \brief Resizes jacobian and residual and recomputes colors
203 */
204 void updateAfterGridAdaption()
205 {
206 setResidualSize_(*residual_);
207 setJacobianPattern_();
208 maybeComputeColors_();
209 }
210
211 //! Returns the number of degrees of freedom
212 std::size_t numDofs() const
213 6294 { return gridGeometry_->numDofs(); }
214
215 //! The problem
216 const Problem& problem() const
217
14/33
✓ Branch 3 taken 2 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 2 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 2 times.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✓ Branch 12 taken 2 times.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 16 not taken.
✓ Branch 17 taken 4 times.
✗ Branch 18 not taken.
✓ Branch 20 taken 4 times.
✓ Branch 21 taken 3 times.
✗ Branch 22 not taken.
✓ Branch 23 taken 4 times.
✓ Branch 24 taken 3 times.
✗ Branch 25 not taken.
✓ Branch 26 taken 4 times.
✓ Branch 27 taken 3 times.
✗ Branch 28 not taken.
✓ Branch 30 taken 3 times.
✗ Branch 31 not taken.
✓ Branch 33 taken 3 times.
✗ Branch 34 not taken.
✓ Branch 36 taken 3 times.
✗ Branch 37 not taken.
✗ Branch 43 not taken.
✗ Branch 44 not taken.
✗ Branch 46 not taken.
✗ Branch 47 not taken.
23790698 { return *problem_; }
218
219 //! The global finite volume geometry
220 const GridGeometry& gridGeometry() const
221
6/17
✓ Branch 1 taken 10000000 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 10000000 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 52224 times.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✓ Branch 12 taken 52224 times.
✗ Branch 13 not taken.
✓ Branch 15 taken 20352 times.
✗ Branch 16 not taken.
✓ Branch 18 taken 20352 times.
✗ Branch 19 not taken.
20145152 { return *gridGeometry_; }
222
223 //! The gridview
224 const GridView& gridView() const
225
4/16
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 2172 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 5066048 times.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✓ Branch 14 taken 2052 times.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
✗ Branch 18 not taken.
✓ Branch 19 taken 5019968 times.
10090240 { return gridGeometry().gridView(); }
226
227 //! The global grid variables
228 GridVariables& gridVariables()
229 4448 { return *gridVariables_; }
230
231 //! The global grid variables
232 const GridVariables& gridVariables() const
233
4/8
✓ Branch 1 taken 10072576 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 10072576 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 10072576 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 10072576 times.
✗ Branch 11 not taken.
40344064 { return *gridVariables_; }
234
235 //! The jacobian matrix
236 JacobianMatrix& jacobian()
237 8688 { return *jacobian_; }
238
239 //! The residual vector (rhs)
240 ResidualType& residual()
241
2/4
✓ Branch 3 taken 52 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 52 times.
✗ Branch 7 not taken.
4448 { return *residual_; }
242
243 //! The solution of the previous time step
244 const SolutionVector& prevSol() const
245 { return *prevSol_; }
246
247 /*!
248 * \brief Create a local residual object (used by the local assembler)
249 */
250 MultiStageFVLocalOperator<LocalResidual> localResidual() const
251
3/6
✓ Branch 1 taken 10072576 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 10072576 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 5059520 times.
✗ Branch 8 not taken.
25231552 { return { LocalResidual{problem_.get(), nullptr} }; }
252
253 /*!
254 * \brief Update the grid variables
255 */
256 void updateGridVariables(const SolutionVector &cursol)
257
2/4
✓ Branch 1 taken 2000 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2000 times.
✗ Branch 5 not taken.
4158 { gridVariables().update(cursol); }
258
259 /*!
260 * \brief Reset the gridVariables
261 */
262 void resetTimeStep(const SolutionVector &cursol)
263 { gridVariables().resetTimeStep(cursol); }
264
265 4104 void clearStages()
266 {
267 4104 spatialOperatorEvaluations_.clear();
268 4104 temporalOperatorEvaluations_.clear();
269
2/2
✓ Branch 0 taken 2052 times.
✓ Branch 1 taken 2052 times.
4104 stageParams_.reset();
270 4104 }
271
272 template<class StageParams>
273 2052 void prepareStage(SolutionVector& x, StageParams params)
274 {
275
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2052 times.
2052 stageParams_ = std::move(params);
276
1/2
✓ Branch 0 taken 2052 times.
✗ Branch 1 not taken.
2052 const auto curStage = stageParams_->size() - 1;
277
278 // in the first stage, also assemble the residual
279 // at the previous time level (stage 0 residual)
280
1/2
✓ Branch 0 taken 2052 times.
✗ Branch 1 not taken.
2052 if (curStage == 1)
281 {
282 // update time in variables?
283 6156 setProblemTime_(*problem_, stageParams_->timeAtStage(0));
284
285 2052 resetResidual_(); // residual resized and zero
286
287 2052 assert(spatialOperatorEvaluations_.size() >= 0);
288
1/2
✓ Branch 0 taken 2052 times.
✗ Branch 1 not taken.
2052 if (spatialOperatorEvaluations_.size() == 0)
289 {
290 4104 spatialOperatorEvaluations_.push_back(*residual_);
291 4104 temporalOperatorEvaluations_.push_back(*residual_);
292
293 // assemble stage 0 residuals
294 20112644 assemble_([&](const auto& element)
295 {
296
1/5
✓ Branch 1 taken 3072 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
12546080 LocalAssembler localAssembler(*this, element, *prevSol_);
297
1/4
✓ Branch 1 taken 5019968 times.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
5019968 localAssembler.localResidual().spatialWeight(1.0);
298
1/4
✓ Branch 1 taken 5019968 times.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
5019968 localAssembler.localResidual().temporalWeight(1.0);
299
3/12
✓ Branch 1 taken 5019968 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 5019968 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 5019968 times.
✗ 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.
15059904 localAssembler.assembleCurrentResidual(spatialOperatorEvaluations_.back(), temporalOperatorEvaluations_.back());
300 });
301 }
302
303 // we don't delete the first stage so it can be reused in a restarted
304 // time integration step. The evaluations are only deleted
305 // when explicitly requested by calling clearStages().
306 // So if here the vector is non-empty, we don't need to evaluate again
307 // (this should only occur if we are restarting time integration, e.g.
308 // with a different time step size)
309 else if (spatialOperatorEvaluations_.size() > 0)
310 {
311 updateGridVariables(x);
312 spatialOperatorEvaluations_.resize(1);
313 temporalOperatorEvaluations_.resize(1);
314 }
315 }
316
317 // update time in variables?
318 6156 setProblemTime_(*problem_, stageParams_->timeAtStage(curStage));
319
320 2052 resetResidual_(); // residual resized and zero
321
322
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 2052 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 2052 times.
4104 if (spatialOperatorEvaluations_.size() != curStage)
323 DUNE_THROW(Dune::InvalidStateException,
324 "Invalid state. Maybe you forgot to call clearStages()");
325
326 // allocate memory for this stage
327 4104 spatialOperatorEvaluations_.push_back(*residual_);
328 4104 temporalOperatorEvaluations_.push_back(*residual_);
329 2052 }
330
331 //! TODO get rid of this (called by Newton but shouldn't be necessary)
332 bool isStationaryProblem() const
333 { return false; }
334
335 bool isImplicit() const
336 20172032 { return timeSteppingMethod_->implicit(); }
337
338 private:
339 /*!
340 * \brief Resizes the jacobian and sets the jacobian' sparsity pattern.
341 */
342 9 void setJacobianPattern_()
343 {
344 // resize the jacobian and the residual
345 9 const auto numDofs = this->numDofs();
346 18 jacobian_->setSize(numDofs, numDofs);
347
348 // create occupation pattern of the jacobian
349
2/2
✓ Branch 2 taken 7 times.
✓ Branch 3 taken 2 times.
18 if (timeSteppingMethod_->implicit())
350
2/4
✓ Branch 3 taken 7 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 7 times.
✗ Branch 7 not taken.
14 getJacobianPattern<true>(gridGeometry()).exportIdx(*jacobian_);
351 else
352
2/4
✓ Branch 3 taken 2 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 2 times.
✗ Branch 7 not taken.
4 getJacobianPattern<false>(gridGeometry()).exportIdx(*jacobian_);
353 9 }
354
355 //! Resizes the residual
356 6174 void setResidualSize_(ResidualType& res)
357 6288 { res.resize(numDofs()); }
358
359 //! Computes the colors
360 9 void maybeComputeColors_()
361 {
362
1/2
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
9 if (enableMultithreading_)
363 18 elementSets_ = computeColoring(gridGeometry()).sets;
364 9 }
365
366 // reset the residual vector to 0.0
367 6276 void resetResidual_()
368 {
369
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6276 times.
6276 if(!residual_)
370 {
371 residual_ = std::make_shared<ResidualType>();
372 setResidualSize_(*residual_);
373 }
374
375 6276 setResidualSize_(constrainedDofs_);
376
377 12552 (*residual_) = 0.0;
378 6276 constrainedDofs_ = 0.0;
379 6276 }
380
381 // reset the Jacobian matrix to 0.0
382 template <class PartialReassembler = DefaultPartialReassembler>
383 2172 void resetJacobian_(const PartialReassembler *partialReassembler = nullptr)
384 {
385
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2172 times.
2172 if(!jacobian_)
386 {
387 jacobian_ = std::make_shared<JacobianMatrix>();
388 jacobian_->setBuildMode(JacobianMatrix::random);
389 setJacobianPattern_();
390 }
391
392
2/2
✓ Branch 0 taken 2000 times.
✓ Branch 1 taken 172 times.
2172 if (partialReassembler)
393 partialReassembler->resetJacobian(*this);
394 else
395 4344 *jacobian_ = 0.0;
396 2172 }
397
398 /*!
399 * \brief A method assembling something per element
400 * \note Handles exceptions for parallel runs
401 * \throws NumericalProblem on all processes if an exception is thrown during assembly
402 */
403 template<typename AssembleElementFunc>
404 8448 void assemble_(AssembleElementFunc&& assembleElement) const
405 {
406 // a state that will be checked on all processes
407 8448 bool succeeded = false;
408
409 // try assembling using the local assembly function
410 try
411 {
412
1/2
✓ Branch 0 taken 4224 times.
✗ Branch 1 not taken.
8448 if (enableMultithreading_)
413 {
414
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 4224 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 4224 times.
16896 assert(elementSets_.size() > 0);
415
416 // make this element loop run in parallel
417 // for this we have to color the elements so that we don't get
418 // race conditions when writing into the global matrix
419 // each color can be assembled using multiple threads
420
4/4
✓ Branch 0 taken 37508 times.
✓ Branch 1 taken 4224 times.
✓ Branch 2 taken 37508 times.
✓ Branch 3 taken 4224 times.
166928 for (const auto& elements : elementSets_)
421 {
422
1/2
✓ Branch 2 taken 37508 times.
✗ Branch 3 not taken.
20322064 Dumux::parallelFor(elements.size(), [&](const std::size_t i)
423 {
424
4/8
✗ Branch 0 not taken.
✓ Branch 1 taken 5066048 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 5066048 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 5019968 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 5019968 times.
20172032 const auto element = gridView().grid().entity(elements[i]);
425 10086016 assembleElement(element);
426 });
427 }
428 }
429 else
430 for (const auto& element : elements(gridView()))
431 assembleElement(element);
432
433 // if we get here, everything worked well on this process
434 8448 succeeded = true;
435 }
436 // throw exception if a problem occurred
437 catch (NumericalProblem &e)
438 {
439 std::cout << "rank " << gridView().comm().rank()
440 << " caught an exception while assembling:" << e.what()
441 << "\n";
442 succeeded = false;
443 }
444
445 // make sure everything worked well on all processes
446
4/8
✗ Branch 0 not taken.
✓ Branch 1 taken 4224 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 4224 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 4224 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 4224 times.
16896 if (gridView().comm().size() > 1)
447 succeeded = gridView().comm().min(succeeded);
448
449 // if not succeeded rethrow the error on all processes
450
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4224 times.
8448 if (!succeeded)
451 DUNE_THROW(NumericalProblem, "A process did not succeed in linearizing the system");
452 8448 }
453
454 // TODO make this nicer with a is_detected trait in a common location
455 template<class P>
456 void setProblemTime_(const P& p, const Scalar t)
457 4104 { setProblemTimeImpl_(p, t, 0); }
458
459 template<class P>
460 auto setProblemTimeImpl_(const P& p, const Scalar t, int) -> decltype(p.setTime(0))
461 { p.setTime(t); }
462
463 template<class P>
464 void setProblemTimeImpl_(const P& p, const Scalar t, long)
465 {}
466
467 std::shared_ptr<const Experimental::MultiStageMethod<Scalar>> timeSteppingMethod_;
468 std::vector<ResidualType> spatialOperatorEvaluations_;
469 std::vector<ResidualType> temporalOperatorEvaluations_;
470 ResidualType constrainedDofs_;
471 std::shared_ptr<const StageParams> stageParams_;
472
473 //! pointer to the problem to be solved
474 std::shared_ptr<const Problem> problem_;
475
476 //! the finite volume geometry of the grid
477 std::shared_ptr<const GridGeometry> gridGeometry_;
478
479 //! the variables container for the grid
480 std::shared_ptr<GridVariables> gridVariables_;
481
482 //! an observing pointer to the previous solution for instationary problems
483 const SolutionVector* prevSol_ = nullptr;
484
485 //! shared pointers to the jacobian matrix and residual
486 std::shared_ptr<JacobianMatrix> jacobian_;
487 std::shared_ptr<ResidualType> residual_;
488
489 //! element sets for parallel assembly
490 bool enableMultithreading_ = false;
491 std::deque<std::vector<ElementSeed>> elementSets_;
492 };
493
494 } // namespace Dumux
495
496 #endif
497