GCC Code Coverage Report


Directory: ../../../builds/dumux-repositories/
File: /builds/dumux-repositories/dumux/dumux/linear/helmholtzoperator.hh
Date: 2024-05-04 19:09:25
Exec Total Coverage
Lines: 40 52 76.9%
Functions: 5 13 38.5%
Branches: 35 92 38.0%

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 Linear
10 * \brief Scalar Helmholtz operator to be used as a solver component
11 */
12 #ifndef DUMUX_LINEAR_HELMHOLTZ_OPERATOR_HH
13 #define DUMUX_LINEAR_HELMHOLTZ_OPERATOR_HH
14
15 #include <dumux/common/math.hh>
16 #include <dumux/common/properties.hh>
17 #include <dumux/common/numeqvector.hh>
18 #include <dumux/discretization/cellcentered/tpfa/computetransmissibility.hh>
19 #include <dumux/common/boundarytypes.hh>
20 #include <dumux/common/fvproblem.hh>
21 #include <dumux/assembly/fvassembler.hh>
22
23 namespace Dumux::Detail::HelmholtzOperator {
24
25 template <class Traits>
26 360000 class HelmholtzModelVolumeVariables
27 {
28 using Scalar = typename Traits::PrimaryVariables::value_type;
29 public:
30 using PrimaryVariables = typename Traits::PrimaryVariables;
31
32 template<class ElementSolution, class Problem, class Element, class SubControlVolume>
33 void update(const ElementSolution& elemSol, const Problem&, const Element&, const SubControlVolume& scv)
34 360000 { priVars_ = elemSol[scv.indexInElement()]; }
35
36 5740800 Scalar priVar(const int pvIdx) const { return priVars_[pvIdx]; }
37 const PrimaryVariables& priVars() const { return priVars_; }
38 Scalar extrusionFactor() const { return 1.0; }
39
40 private:
41 PrimaryVariables priVars_;
42 };
43
44 template<class TypeTag>
45 class HelmholtzModelLocalResidual
46 : public GetPropType<TypeTag, Properties::BaseLocalResidual>
47 {
48 using ParentType = GetPropType<TypeTag, Properties::BaseLocalResidual>;
49 using Scalar = GetPropType<TypeTag, Properties::Scalar>;
50 using Problem = GetPropType<TypeTag, Properties::Problem>;
51 using NumEqVector = Dumux::NumEqVector<GetPropType<TypeTag, Properties::PrimaryVariables>>;
52 using VolumeVariables = typename GetPropType<TypeTag, Properties::GridVolumeVariables>::VolumeVariables;
53 using ElementVolumeVariables = typename GetPropType<TypeTag, Properties::GridVolumeVariables>::LocalView;
54 using ElementFluxVariablesCache = typename GetPropType<TypeTag, Properties::GridFluxVariablesCache>::LocalView;
55 using GridGeometry = GetPropType<TypeTag, Properties::GridGeometry>;
56 using FVElementGeometry = typename GridGeometry::LocalView;
57 using SubControlVolume = typename FVElementGeometry::SubControlVolume;
58 using SubControlVolumeFace = typename FVElementGeometry::SubControlVolumeFace;
59 using GridView = typename GridGeometry::GridView;
60 using Element = typename GridView::template Codim<0>::Entity;
61 static constexpr int dimWorld = GridView::dimensionworld;
62 public:
63
2/4
✓ Branch 1 taken 180000 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 180000 times.
✗ Branch 5 not taken.
360000 using ParentType::ParentType;
64
65 NumEqVector computeStorage(const Problem&,
66 const SubControlVolume&,
67 const VolumeVariables&) const
68 { return NumEqVector(0.0); }
69
70 2870400 NumEqVector computeFlux(const Problem& problem,
71 const Element&, const FVElementGeometry& fvGeometry,
72 const ElementVolumeVariables& elemVolVars,
73 const SubControlVolumeFace& scvf,
74 const ElementFluxVariablesCache& elemFluxVarsCache) const
75 {
76 2870400 NumEqVector flux(0.0);
77
78 // CVFE schemes
79 if constexpr (GridGeometry::discMethod == DiscretizationMethods::box
80 || GridGeometry::discMethod == DiscretizationMethods::fcdiamond
81 || GridGeometry::discMethod == DiscretizationMethods::pq1bubble)
82 {
83 const auto& fluxVarCache = elemFluxVarsCache[scvf];
84 Dune::FieldVector<Scalar, dimWorld> gradConcentration(0.0);
85 for (const auto& scv : scvs(fvGeometry))
86 {
87 const auto& volVars = elemVolVars[scv];
88 gradConcentration.axpy(volVars.concentration(), fluxVarCache.gradN(scv.indexInElement()));
89 }
90
91 NumEqVector flux;
92 flux[0] = -1.0*vtmv(scvf.unitOuterNormal(), problem.a(), gradConcentration)*scvf.area();
93 }
94
95 // CCTpfa
96 else if constexpr (GridGeometry::discMethod == DiscretizationMethods::cctpfa)
97 {
98 5740800 const auto& insideScv = fvGeometry.scv(scvf.insideScvIdx());
99 2870400 const auto& insideV = elemVolVars[insideScv];
100 5740800 const auto& outsideV = elemVolVars[scvf.outsideScvIdx()];
101 2870400 const auto ti = computeTpfaTransmissibility(
102 fvGeometry, scvf, insideScv, problem.a(), insideV.extrusionFactor()
103 );
104
105 2870400 const auto tij = [&]{
106
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2870400 times.
2870400 if (scvf.boundary())
107 return scvf.area()*ti;
108 else
109 {
110 5740800 const auto& outsideScv = fvGeometry.scv(scvf.outsideScvIdx());
111 8611200 const Scalar tj = -computeTpfaTransmissibility(
112 2870400 fvGeometry, scvf, outsideScv, problem.a(), outsideV.extrusionFactor()
113 );
114
115 2870400 return scvf.area()*(ti * tj)/(ti + tj);
116 }
117 2870400 }();
118
119 5740800 const auto u = insideV.priVar(0);
120 5740800 const auto v = outsideV.priVar(0);
121 2870400 flux[0] = tij*(u - v);
122 }
123 else
124 DUNE_THROW(Dune::NotImplemented, "Discretization method " << GridGeometry::discMethod);
125
126 2870400 return flux;
127 }
128
129 NumEqVector computeSource(const Problem& problem,
130 const Element&, const FVElementGeometry&,
131 const ElementVolumeVariables& elemVolVars,
132 const SubControlVolume& scv) const
133 {
134 NumEqVector source(0.0);
135 source[0] = -problem.b()*elemVolVars[scv].priVar(0);
136 return source;
137 }
138 };
139
140 template<class TypeTag>
141 2 class HelmholtzModelHomogeneousNeumannProblem : public FVProblem<TypeTag>
142 {
143 using ParentType = FVProblem<TypeTag>;
144 using GridGeometry = GetPropType<TypeTag, Properties::GridGeometry>;
145 using Scalar = GetPropType<TypeTag, Properties::Scalar>;
146 using BoundaryTypes = Dumux::BoundaryTypes<GetPropType<TypeTag, Properties::ModelTraits>::numEq()>;
147 public:
148 2 HelmholtzModelHomogeneousNeumannProblem(std::shared_ptr<const GridGeometry> gridGeometry, Scalar a, Scalar b)
149 : ParentType(gridGeometry)
150
5/14
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
✓ Branch 8 taken 2 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 2 times.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✓ Branch 13 taken 2 times.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
6 , a_(a), b_(b)
151 2 {}
152
153 template<class GlobalPosition>
154 BoundaryTypes boundaryTypesAtPos(const GlobalPosition& globalPos) const
155
4/8
✗ Branch 0 not taken.
✓ Branch 1 taken 4800 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 4800 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 4800 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 4800 times.
19200 { BoundaryTypes values; values.setAllNeumann(); return values; }
156
157 Scalar a() const { return a_; }
158 Scalar b() const { return b_; }
159 private:
160 Scalar a_, b_;
161 };
162
163 template<class G, class D, class S>
164 struct Policy
165 {
166 using Scalar = S;
167 using Grid = G;
168 using Discretization = D;
169 };
170
171 template<class P>
172 struct TTag {
173 using InheritsFrom = std::tuple<typename P::Discretization>;
174 };
175
176 } // end namespace Dumux::Detail::HelmholtzOperator
177
178 namespace Dumux::Properties {
179
180 //! Set the default type of scalar values to double
181 template<class TypeTag, class P>
182 struct Scalar<TypeTag, Dumux::Detail::HelmholtzOperator::TTag<P>>
183 { using type = typename P::Scalar; };
184
185 //! Set the default primary variable vector to a vector of size of number of equations
186 template<class TypeTag, class P>
187 struct PrimaryVariables<TypeTag, Dumux::Detail::HelmholtzOperator::TTag<P>>
188 {
189 using type = Dune::FieldVector<
190 GetPropType<TypeTag, Properties::Scalar>,
191 GetPropType<TypeTag, Properties::ModelTraits>::numEq()
192 >;
193 };
194
195 template<class TypeTag, class P>
196 struct ModelTraits<TypeTag, Dumux::Detail::HelmholtzOperator::TTag<P>>
197 {
198 struct Traits { static constexpr int numEq() { return 1; } };
199 using type = Traits;
200 };
201
202 template<class TypeTag, class P>
203 struct LocalResidual<TypeTag, Dumux::Detail::HelmholtzOperator::TTag<P>>
204 { using type = Dumux::Detail::HelmholtzOperator::HelmholtzModelLocalResidual<TypeTag>; };
205
206 template<class TypeTag, class P>
207 struct Problem<TypeTag, Dumux::Detail::HelmholtzOperator::TTag<P>>
208 { using type = Dumux::Detail::HelmholtzOperator::HelmholtzModelHomogeneousNeumannProblem<TypeTag>; };
209
210 template<class TypeTag, class P>
211 struct VolumeVariables<TypeTag, Dumux::Detail::HelmholtzOperator::TTag<P>>
212 {
213 struct Traits { using PrimaryVariables = GetPropType<TypeTag, Properties::PrimaryVariables>; };
214 using type = Dumux::Detail::HelmholtzOperator::HelmholtzModelVolumeVariables<Traits>;
215 };
216
217 template<class TypeTag, class P>
218 struct EnableGridVolumeVariablesCache<TypeTag, Dumux::Detail::HelmholtzOperator::TTag<P>>
219 { static constexpr bool value = true; };
220
221 template<class TypeTag, class P>
222 struct EnableGridFluxVariablesCache<TypeTag, Dumux::Detail::HelmholtzOperator::TTag<P>>
223 { static constexpr bool value = true; };
224
225 template<class TypeTag, class P>
226 struct EnableGridGeometryCache<TypeTag, Dumux::Detail::HelmholtzOperator::TTag<P>>
227 { static constexpr bool value = true; };
228
229 template<class TypeTag, class P>
230 struct Grid<TypeTag, Dumux::Detail::HelmholtzOperator::TTag<P>>
231 { using type = typename P::Grid; };
232
233 } // end namespace Dumux::Properties
234
235 namespace Dumux {
236
237 /*!
238 * \brief make a Helmholtz matrix operator (aΔ + bI)
239 * \tparam Discretization the discretization model type tag
240 * \param gridView the gridView on which to assemble the discrete operator
241 * \param a the weight for the Laplacian
242 * \param b the weight for the mass matrix
243 *
244 * For example: a=-1.0 and b=0.0 will yield a negative Laplacian operator
245 * For example: a=0.0 and b=1.0 will yield the mass matrix
246 * For example: a=1.0 and b=1.0 will yield the unweighted Helmholtz operator
247 *
248 * Useful as a preconditioner component or for testing solvers
249 */
250 template<class Discretization, class GridView, class Scalar>
251 2 auto makeHelmholtzMatrix(const GridView& gridView, const Scalar a = 1.0, const Scalar b = 1.0)
252 {
253 using TypeTag = Detail::HelmholtzOperator::TTag<
254 Detail::HelmholtzOperator::Policy<typename GridView::Grid, Discretization, Scalar>
255 >;
256 using GridGeometry = GetPropType<TypeTag, Properties::GridGeometry>;
257
0/2
✗ Branch 1 not taken.
✗ Branch 2 not taken.
2 auto gridGeometry = std::make_shared<GridGeometry>(gridView);
258
259 using Problem = GetPropType<TypeTag, Properties::Problem>;
260
2/6
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
4 auto problem = std::make_shared<Problem>(gridGeometry, a, b);
261
262 using SolutionVector = GetPropType<TypeTag, Properties::SolutionVector>;
263 using GridVariables = GetPropType<TypeTag, Properties::GridVariables>;
264
2/6
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
4 auto gridVariables = std::make_shared<GridVariables>(problem, gridGeometry);
265
4/10
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 2 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 2 times.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
6 SolutionVector x(gridGeometry->numDofs());
266
2/4
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
4 gridVariables->init(x);
267
268 using Assembler = FVAssembler<TypeTag, DiffMethod::numeric>;
269
2/6
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
4 auto assembler = std::make_shared<Assembler>(problem, gridGeometry, gridVariables);
270 using A = typename Assembler::JacobianMatrix;
271 using V = typename Assembler::ResidualType;
272
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
2 auto jacobian = std::make_shared<A>();
273
3/6
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
✗ Branch 6 not taken.
6 auto residual = std::make_shared<V>();
274
3/12
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 2 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 2 times.
✗ 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.
6 assembler->setLinearSystem(jacobian, residual);
275
2/4
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
4 assembler->assembleJacobian(x);
276 2 return jacobian;
277 };
278
279 /*!
280 * \brief make a Laplace matrix operator aΔ
281 */
282 template<class Discretization, class GridView, class Scalar>
283 auto makeLaplaceMatrix(const GridView& gridView, const Scalar a = 1.0)
284 { return createHelmholtzMatrix(gridView, a, 0.0); };
285
286 template<class LinearOperator, class Discretization, class GridView, class Scalar>
287 1 std::shared_ptr<LinearOperator> makeHelmholtzLinearOperator(const GridView& gridView, const Scalar a, const Scalar b)
288
2/6
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 1 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
1 { return std::make_shared<LinearOperator>(makeHelmholtzMatrix<Discretization>(gridView, a, b)); }
289
290 template<class LinearOperator, class Discretization, class GridView, class Comm, class Scalar>
291 std::shared_ptr<LinearOperator> makeHelmholtzLinearOperator(const GridView& gridView, const Comm& comm, const Scalar a, const Scalar b)
292 { return std::make_shared<LinearOperator>(makeHelmholtzMatrix<Discretization>(gridView, a, b), comm); }
293
294 template<class LinearOperator, class Discretization, class GridView, class Scalar>
295 std::shared_ptr<LinearOperator> makeLaplaceLinearOperator(const GridView& gridView, const Scalar a)
296 { return std::make_shared<LinearOperator>(makeLaplaceMatrix<Discretization>(gridView, a)); }
297
298 template<class LinearOperator, class Discretization, class GridView, class Comm, class Scalar>
299 std::shared_ptr<LinearOperator> makeLaplaceLinearOperator(const GridView& gridView, const Comm& comm, const Scalar a)
300 { return std::make_shared<LinearOperator>(makeLaplaceMatrix<Discretization>(gridView, a), comm); }
301
302 } // end namespace Dumux
303
304 #endif
305