GCC Code Coverage Report


Directory: ../../../builds/dumux-repositories/
File: /builds/dumux-repositories/dumux/dumux/discretization/cellcentered/mpfa/localassemblerbase.hh
Date: 2024-05-04 19:09:25
Exec Total Coverage
Lines: 62 65 95.4%
Functions: 12 104 11.5%
Branches: 68 82 82.9%

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 CCMpfaDiscretization
10 * \brief Defines the general interface of classes used for the assembly
11 * of the local systems of equations involved in the transmissibility
12 * computation in mpfa schemes.
13 */
14 #ifndef DUMUX_DISCRETIZATION_CC_MPFA_LOCAL_ASSEMBLER_BASE_HH
15 #define DUMUX_DISCRETIZATION_CC_MPFA_LOCAL_ASSEMBLER_BASE_HH
16
17 #include <algorithm>
18 #include <vector>
19 #include <type_traits>
20
21 #include <dune/common/exceptions.hh>
22 #include <dune/common/reservedvector.hh>
23
24 #include <dumux/common/typetraits/isvalid.hh>
25 #include <dumux/discretization/extrusion.hh>
26 #include "localassemblerhelper.hh"
27
28 namespace Dumux {
29
30 /*!
31 * \ingroup CCMpfaDiscretization
32 * \brief Defines the general interface of the local assembler
33 * classes for the assembly of the interaction volume-local
34 * transmissibility matrix. Specializations have to be provided
35 * for the available interaction volume implementations. these
36 * should derive from this base class.
37 *
38 * \tparam P The problem type
39 * \tparam EG The element finite volume geometry
40 * \tparam EV The element volume variables type
41 */
42 template< class P, class EG, class EV >
43 class InteractionVolumeAssemblerBase
44 : public InteractionVolumeAssemblerHelper
45 {
46 using Problem = P;
47 using FVElementGeometry = EG;
48 using ElementVolumeVariables = EV;
49 using Extrusion = Extrusion_t<typename EG::GridGeometry>;
50 using Helper = InteractionVolumeAssemblerHelper;
51
52 template< class IV >
53 using Scalar = typename IV::Traits::MatVecTraits::FaceVector::value_type;
54
55 public:
56 /*!
57 * \brief The constructor.
58 * Sets pointers to the objects required for a subsequent call to assemble().
59 *
60 * \param problem The problem to be solved (boundary/initial conditions etc.)
61 * \param fvGeometry The local view on the finite volume grid geometry
62 * \param elemVolVars The local view on the primary/secondary variables
63 */
64 76855392 InteractionVolumeAssemblerBase(const Problem& problem,
65 const FVElementGeometry& fvGeometry,
66 const ElementVolumeVariables& elemVolVars)
67 {
68 76855392 problemPtr_ = &problem;
69 76855392 fvGeometryPtr_ = &fvGeometry;
70
5/5
✓ Branch 0 taken 398496 times.
✓ Branch 1 taken 48547560 times.
✓ Branch 2 taken 5272536 times.
✓ Branch 3 taken 12065201 times.
✓ Branch 4 taken 53662 times.
76855392 elemVolVarsPtr_ = &elemVolVars;
71 }
72
73 // return functions to the local views & problem
74 const Problem& problem() const { return *problemPtr_; }
75 const FVElementGeometry& fvGeometry() const { return *fvGeometryPtr_; }
76 const ElementVolumeVariables& elemVolVars() const { return *elemVolVarsPtr_; }
77
78 /*!
79 * \brief Assembles the matrices involved in the flux
80 * expressions and the local system of equations
81 * within an mpfa interaction volume.
82 *
83 * \tparam DataHandle The data handle
84 * \tparam IV The interaction volume type implementation
85 * \tparam TensorFunc Lambda to obtain the tensor w.r.t.
86 * which the local system is to be solved
87 *
88 * \param handle The data handle in which the matrices are stored
89 * \param iv The interaction volume
90 * \param getT Lambda to evaluate the scv-wise tensors
91 * \param wijZeroThresh the zero threshold wij
92 */
93 template< class DataHandle, class IV, class TensorFunc >
94 void assembleMatrices(DataHandle& handle, IV& iv, const TensorFunc& getT, Scalar<IV> wijZeroThresh = 0.0)
95 {
96 DUNE_THROW(Dune::NotImplemented, "Implementation does not provide an assembleMatrices() function");
97 }
98
99 /*!
100 * \brief Assembles the vector of primary (cell) unknowns and (maybe)
101 * Dirichlet boundary conditions within an interaction volume.
102 *
103 * \tparam IV The interaction volume type implementation
104 * \tparam GetU Lambda to obtain the cell unknowns from grid indices
105 *
106 * \param handle The data handle in which the vector is stored
107 * \param iv The interaction volume
108 * \param getU Lambda to obtain the desired cell/Dirichlet value from vol vars
109 */
110 template< class DataHandle, class IV, class GetU >
111 void assembleU(DataHandle& handle, const IV& iv, const GetU& getU)
112 {
113 DUNE_THROW(Dune::NotImplemented, "Implementation does not provide an assemble() function for the cell/Dirichlet unknowns");
114 }
115
116 /*!
117 * \brief Assembles the gravitational flux contributions on the scvfs within an
118 * interaction volume.
119 *
120 * \param handle The data handle in which the vector is stored
121 * \param iv The interaction volume
122 * \param getRho Lambda to obtain the density from volume variables
123 */
124 template< class DataHandle, class IV, class GetRho >
125 47073922 void assembleGravity(DataHandle& handle, const IV& iv, const GetRho& getRho)
126 {
127 using GridView = typename IV::Traits::GridView;
128 static constexpr int dim = GridView::dimension;
129 static constexpr int dimWorld = GridView::dimensionworld;
130 static constexpr bool isSurfaceGrid = dim < dimWorld;
131
132 // resize the gravity vectors
133 47073922 auto& g = handle.g();
134 47073922 auto& deltaG = handle.deltaG();
135 47073922 auto& outsideG = handle.gOutside();
136 47073922 Helper::resizeVector(g, iv.numFaces());
137 47073922 Helper::resizeVector(deltaG, iv.numUnknowns());
138 if (isSurfaceGrid)
139 13660904 Helper::resizeVector(outsideG, iv.numFaces());
140
141 //! For each face, we...
142 //! - arithmetically average the phase densities
143 //! - compute the term \f$ \alpha := \mathbf{A} \rho \ \mathbf{n}^T \mathbf{K} \mathbf{g} \f$ in each neighboring cell
144 //! - compute \f$ \alpha^* = \sum{\alpha_{outside, i}} - \alpha_{inside} \f$
145 using Scalar = typename IV::Traits::MatVecTraits::TMatrix::value_type;
146 using LocalIndexType = typename IV::Traits::IndexSet::LocalIndexType;
147
148
3/3
✓ Branch 0 taken 131235760 times.
✓ Branch 1 taken 114971294 times.
✓ Branch 2 taken 13660904 times.
262437668 for (LocalIndexType faceIdx = 0; faceIdx < iv.numFaces(); ++faceIdx)
149 {
150 // gravitational acceleration on this face
151 215363746 const auto& curLocalScvf = iv.localScvf(faceIdx);
152 215363746 const auto& curGlobalScvf = fvGeometry().scvf(curLocalScvf.gridScvfIndex());
153
6/6
✓ Branch 0 taken 3766636 times.
✓ Branch 1 taken 10754072 times.
✓ Branch 2 taken 3766636 times.
✓ Branch 3 taken 10754072 times.
✓ Branch 4 taken 3766636 times.
✓ Branch 5 taken 10754072 times.
646091238 const auto& gravity = problem().spatialParams().gravity(curGlobalScvf.ipGlobal());
154
155 // get permeability tensor in "positive" sub volume
156 215363746 const auto& neighborScvIndices = curLocalScvf.neighboringLocalScvIndices();
157
6/6
✓ Branch 0 taken 3766636 times.
✓ Branch 1 taken 10754072 times.
✓ Branch 2 taken 3766636 times.
✓ Branch 3 taken 10754072 times.
✓ Branch 4 taken 3766636 times.
✓ Branch 5 taken 10754072 times.
564008012 const auto& posGlobalScv = fvGeometry().scv(iv.localScv(neighborScvIndices[0]).gridScvIndex());
158 215363746 const auto& posVolVars = elemVolVars()[posGlobalScv];
159 430727492 const auto alpha_inside = posVolVars.extrusionFactor()*vtmv(curGlobalScvf.unitOuterNormal(),
160 posVolVars.permeability(),
161 gravity);
162
163
2/2
✓ Branch 0 taken 208155190 times.
✓ Branch 1 taken 5163796 times.
215363746 const auto numOutsideFaces = !curGlobalScvf.boundary() ? curGlobalScvf.numOutsideScvs() : 0;
164 using OutsideAlphaStorage = std::conditional_t< isSurfaceGrid,
165 std::vector<Scalar>,
166 Dune::ReservedVector<Scalar, 1> >;
167
4/8
✓ Branch 1 taken 82083226 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 82083226 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 79292974 times.
✓ Branch 7 taken 2790252 times.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
458823172 OutsideAlphaStorage alpha_outside; alpha_outside.resize(numOutsideFaces);
168 646091238 std::fill(alpha_outside.begin(), alpha_outside.end(), 0.0);
169 Scalar rho;
170
171 if (isSurfaceGrid)
172
2/4
✓ Branch 1 taken 82083226 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 82083226 times.
✗ Branch 5 not taken.
164166452 Helper::resizeVector(outsideG[faceIdx], numOutsideFaces);
173
174
2/2
✓ Branch 0 taken 212397602 times.
✓ Branch 1 taken 921384 times.
215363746 if (!curLocalScvf.isDirichlet())
175 {
176 214421034 const auto localDofIdx = curLocalScvf.localDofIndex();
177
178
2/2
✓ Branch 0 taken 208155190 times.
✓ Branch 1 taken 4242412 times.
214421034 rho = getRho(posVolVars);
179
2/2
✓ Branch 0 taken 208155190 times.
✓ Branch 1 taken 4242412 times.
214421034 deltaG[localDofIdx] = 0.0;
180
181
2/2
✓ Branch 0 taken 208155190 times.
✓ Branch 1 taken 4242412 times.
214421034 if (!curGlobalScvf.boundary())
182 {
183
4/4
✓ Branch 0 taken 209412694 times.
✓ Branch 1 taken 208155190 times.
✓ Branch 2 taken 209412694 times.
✓ Branch 3 taken 208155190 times.
842885496 for (unsigned int idxInOutside = 0; idxInOutside < curGlobalScvf.numOutsideScvs(); ++idxInOutside)
184 {
185 // obtain outside tensor
186
2/2
✓ Branch 0 taken 3609148 times.
✓ Branch 1 taken 10593856 times.
211350126 const auto negLocalScvIdx = neighborScvIndices[idxInOutside+1];
187
4/4
✓ Branch 0 taken 3609148 times.
✓ Branch 1 taken 10593856 times.
✓ Branch 2 taken 3609148 times.
✓ Branch 3 taken 10593856 times.
422700252 const auto& negGlobalScv = fvGeometry().scv(iv.localScv(negLocalScvIdx).gridScvIndex());
188 211350126 const auto& negVolVars = elemVolVars()[negGlobalScv];
189 291900604 const auto& flipScvf = !isSurfaceGrid ? curGlobalScvf
190 80550478 : fvGeometry().flipScvf(curGlobalScvf.index(), idxInOutside);
191
192 634050378 alpha_outside[idxInOutside] = negVolVars.extrusionFactor()*vtmv(flipScvf.unitOuterNormal(),
193 negVolVars.permeability(),
194 gravity);
195 if (isSurfaceGrid)
196 80550478 alpha_outside[idxInOutside] *= -1.0;
197
198 211350126 rho += getRho(negVolVars);
199 553499900 deltaG[localDofIdx] += alpha_outside[idxInOutside];
200 }
201 }
202
203 214421034 rho /= numOutsideFaces + 1;
204 214421034 deltaG[localDofIdx] -= alpha_inside;
205 643263102 deltaG[localDofIdx] *= rho*Extrusion::area(fvGeometry(), curGlobalScvf);
206 }
207 // use density resulting from Dirichlet BCs
208 else
209 1885424 rho = getRho(elemVolVars()[curGlobalScvf.outsideScvIdx()]);
210
211 // add "inside" & "outside" alphas to gravity containers
212 564008012 g[faceIdx] = alpha_inside*rho*Extrusion::area(fvGeometry(), curGlobalScvf);
213
214 if (isSurfaceGrid)
215 {
216 82083226 unsigned int i = 0;
217
4/4
✓ Branch 0 taken 80550478 times.
✓ Branch 1 taken 82083226 times.
✓ Branch 2 taken 80550478 times.
✓ Branch 3 taken 82083226 times.
407350634 for (const auto& alpha : alpha_outside)
218 322201912 outsideG[faceIdx][i++] = alpha*rho*Extrusion::area(fvGeometry(), curGlobalScvf);
219 }
220 }
221
222 // add iv-wide contributions to gravity vectors
223 94147844 handle.CA().umv(deltaG, g);
224 if (isSurfaceGrid)
225 {
226 using FaceVector = typename IV::Traits::MatVecTraits::FaceVector;
227
4/10
✓ Branch 1 taken 13660904 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 13660904 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 13660904 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 13660904 times.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
54643616 FaceVector AG;
228
2/4
✓ Branch 1 taken 13660904 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 13660904 times.
✗ Branch 5 not taken.
27321808 Helper::resizeVector(AG, iv.numUnknowns());
229 27321808 handle.A().mv(deltaG, AG);
230
231 // compute gravitational accelerations
232
4/4
✓ Branch 0 taken 162633704 times.
✓ Branch 1 taken 13660904 times.
✓ Branch 2 taken 162633704 times.
✓ Branch 3 taken 13660904 times.
217277320 for (const auto& localFaceData : iv.localFaceData())
233 {
234 // continue only for "outside" faces
235
2/2
✓ Branch 0 taken 80550478 times.
✓ Branch 1 taken 82083226 times.
162633704 if (!localFaceData.isOutsideFace())
236 continue;
237
238 80550478 const auto localScvIdx = localFaceData.ivLocalInsideScvIndex();
239 80550478 const auto localScvfIdx = localFaceData.ivLocalScvfIndex();
240 80550478 const auto idxInOutside = localFaceData.scvfLocalOutsideScvfIndex();
241 161100956 const auto& posLocalScv = iv.localScv(localScvIdx);
242 241651434 const auto& wijk = handle.omegas()[localScvfIdx][idxInOutside+1];
243
244 // add contributions from all local directions
245
2/2
✓ Branch 0 taken 161100956 times.
✓ Branch 1 taken 80550478 times.
241651434 for (LocalIndexType localDir = 0; localDir < dim; localDir++)
246 {
247 // the scvf corresponding to this local direction in the scv
248
2/2
✓ Branch 1 taken 160815176 times.
✓ Branch 2 taken 285780 times.
161100956 const auto& curLocalScvf = iv.localScvf(posLocalScv.localScvfIndex(localDir));
249
2/2
✓ Branch 0 taken 160815176 times.
✓ Branch 1 taken 285780 times.
161100956 if (!curLocalScvf.isDirichlet())
250 804075880 outsideG[localScvfIdx][idxInOutside] -= wijk[localDir]*AG[curLocalScvf.localDofIndex()];
251 }
252 }
253 }
254 47073922 }
255
256 private:
257 // pointers to the data required for assembly
258 const Problem* problemPtr_;
259 const FVElementGeometry* fvGeometryPtr_;
260 const ElementVolumeVariables* elemVolVarsPtr_;
261 };
262
263 } // end namespace Dumux
264
265 #endif
266