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 Newton | ||
10 | * \brief This class provides the infrastructure to write the | ||
11 | * convergence behaviour of the newton method into a VTK file. | ||
12 | */ | ||
13 | #ifndef DUMUX_NEWTON_CONVERGENCE_WRITER_HH | ||
14 | #define DUMUX_NEWTON_CONVERGENCE_WRITER_HH | ||
15 | |||
16 | #include <string> | ||
17 | |||
18 | #include <dune/grid/io/file/vtk/vtksequencewriter.hh> | ||
19 | #include <dumux/discretization/method.hh> | ||
20 | |||
21 | namespace Dumux { | ||
22 | |||
23 | /*! | ||
24 | * \ingroup Newton | ||
25 | * \brief A convergence writer interface | ||
26 | * Provide an interface that show the minimal requirements a convergence write passed to a newton method has to fulfill | ||
27 | * \note This is used together with a Newton solver, see documentation of the Newton solver for | ||
28 | * more information on how to use this class. | ||
29 | */ | ||
30 | template <class SolutionVector, class ResidualVector> | ||
31 | 4 | struct ConvergenceWriterInterface | |
32 | { | ||
33 | virtual ~ConvergenceWriterInterface() = default; | ||
34 | |||
35 | ✗ | virtual void write(const SolutionVector &uLastIter, const ResidualVector &deltaU, const ResidualVector &residual) {} | |
36 | }; | ||
37 | |||
38 | /*! | ||
39 | * \ingroup Newton | ||
40 | * \brief Writes the intermediate solutions for every Newton iteration | ||
41 | * \note This is used together with a Newton solver, see documentation of the Newton solver for | ||
42 | * more information on how to use this class. | ||
43 | */ | ||
44 | template <class GridGeometry, class SolutionVector, class ResidualVector> | ||
45 | class NewtonConvergenceWriter : public ConvergenceWriterInterface<SolutionVector, ResidualVector> | ||
46 | { | ||
47 | using GridView = typename GridGeometry::GridView; | ||
48 | static constexpr auto numEq = SolutionVector::block_type::dimension; | ||
49 | using Scalar = typename SolutionVector::block_type::value_type; | ||
50 | |||
51 | static_assert(GridGeometry::discMethod != DiscretizationMethods::staggered, | ||
52 | "This convergence writer does not work for the staggered method, use the StaggeredNewtonConvergenceWriter instead"); | ||
53 | public: | ||
54 | /*! | ||
55 | * \brief Constructor | ||
56 | * \param gridGeometry The finite-volume grid geometry | ||
57 | * \param name Base name of the vtk output | ||
58 | */ | ||
59 | 4 | NewtonConvergenceWriter(const GridGeometry& gridGeometry, | |
60 | const std::string& name = "newton_convergence") | ||
61 | 4 | : gridGeometry_(gridGeometry) | |
62 |
3/6✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 4 times.
✗ Branch 6 not taken.
✓ Branch 9 taken 4 times.
✗ Branch 10 not taken.
|
8 | , writer_(gridGeometry.gridView(), name, "", "") |
63 | { | ||
64 |
1/2✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
|
4 | resize(); |
65 | |||
66 | if (GridGeometry::discMethod == DiscretizationMethods::box) | ||
67 | { | ||
68 |
2/2✓ Branch 0 taken 6 times.
✓ Branch 1 taken 2 times.
|
8 | for (int eqIdx = 0; eqIdx < numEq; ++eqIdx) |
69 | { | ||
70 |
2/4✓ Branch 2 taken 6 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 6 times.
✗ Branch 6 not taken.
|
18 | writer_.addVertexData(x_[eqIdx], "x_" + std::to_string(eqIdx)); |
71 |
2/4✓ Branch 2 taken 6 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 6 times.
✗ Branch 6 not taken.
|
18 | writer_.addVertexData(delta_[eqIdx], "delta_" + std::to_string(eqIdx)); |
72 |
2/4✓ Branch 2 taken 6 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 6 times.
✗ Branch 6 not taken.
|
18 | writer_.addVertexData(def_[eqIdx], "defect_" + std::to_string(eqIdx)); |
73 | } | ||
74 | } | ||
75 | else | ||
76 | { | ||
77 |
2/2✓ Branch 0 taken 6 times.
✓ Branch 1 taken 2 times.
|
8 | for (int eqIdx = 0; eqIdx < numEq; ++eqIdx) |
78 | { | ||
79 |
2/4✓ Branch 2 taken 6 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 6 times.
✗ Branch 6 not taken.
|
18 | writer_.addCellData(x_[eqIdx], "x_" + std::to_string(eqIdx)); |
80 |
2/4✓ Branch 2 taken 6 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 6 times.
✗ Branch 6 not taken.
|
18 | writer_.addCellData(delta_[eqIdx], "delta_" + std::to_string(eqIdx)); |
81 |
2/4✓ Branch 2 taken 6 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 6 times.
✗ Branch 6 not taken.
|
18 | writer_.addCellData(def_[eqIdx], "defect_" + std::to_string(eqIdx)); |
82 | } | ||
83 | } | ||
84 | 4 | } | |
85 | |||
86 | //! Resizes the output fields. This has to be called whenever the grid changes | ||
87 | 4 | void resize() | |
88 | { | ||
89 | 4 | const auto numDofs = gridGeometry_.numDofs(); | |
90 | |||
91 | // resize the output fields | ||
92 |
2/2✓ Branch 0 taken 12 times.
✓ Branch 1 taken 4 times.
|
16 | for (int eqIdx = 0; eqIdx < numEq; ++eqIdx) |
93 | { | ||
94 | 12 | def_[eqIdx].resize(numDofs); | |
95 | 12 | delta_[eqIdx].resize(numDofs); | |
96 | 12 | x_[eqIdx].resize(numDofs); | |
97 | } | ||
98 | 4 | } | |
99 | |||
100 | //! Reset the convergence writer for a possible next Newton step | ||
101 | //! You may set a different id in case you don't want the output to be overwritten by the next step | ||
102 | 31 | void reset(std::size_t newId = 0UL) | |
103 |
1/2✓ Branch 1 taken 31 times.
✗ Branch 2 not taken.
|
31 | { id_ = newId; iteration_ = 0UL; } |
104 | |||
105 | 135 | void write(const SolutionVector& uLastIter, | |
106 | const ResidualVector& deltaU, | ||
107 | const ResidualVector& residual) override | ||
108 | { | ||
109 |
2/4✓ Branch 0 taken 135 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 135 times.
✗ Branch 3 not taken.
|
135 | assert(uLastIter.size() == deltaU.size() && uLastIter.size() == residual.size()); |
110 | |||
111 |
2/2✓ Branch 0 taken 68329 times.
✓ Branch 1 taken 135 times.
|
68464 | for (std::size_t dofIdxGlobal = 0; dofIdxGlobal < deltaU.size(); ++dofIdxGlobal) |
112 | { | ||
113 |
2/2✓ Branch 0 taken 204987 times.
✓ Branch 1 taken 68329 times.
|
273316 | for (int eqIdx = 0; eqIdx < numEq; ++eqIdx) |
114 | { | ||
115 | 204987 | x_[eqIdx][dofIdxGlobal] = uLastIter[dofIdxGlobal][eqIdx]; | |
116 | 204987 | delta_[eqIdx][dofIdxGlobal] = - deltaU[dofIdxGlobal][eqIdx]; | |
117 | 204987 | def_[eqIdx][dofIdxGlobal] = residual[dofIdxGlobal][eqIdx]; | |
118 | } | ||
119 | } | ||
120 | |||
121 | 135 | writer_.write(static_cast<double>(id_) + static_cast<double>(iteration_)/1000); | |
122 | 135 | ++iteration_; | |
123 | 135 | } | |
124 | |||
125 | private: | ||
126 | std::size_t id_ = 0UL; | ||
127 | std::size_t iteration_ = 0UL; | ||
128 | |||
129 | const GridGeometry& gridGeometry_; | ||
130 | |||
131 | Dune::VTKSequenceWriter<GridView> writer_; | ||
132 | |||
133 | std::array<std::vector<Scalar>, numEq> def_; | ||
134 | std::array<std::vector<Scalar>, numEq> delta_; | ||
135 | std::array<std::vector<Scalar>, numEq> x_; | ||
136 | }; | ||
137 | |||
138 | } // end namespace Dumux | ||
139 | |||
140 | #endif | ||
141 |