GCC Code Coverage Report


Directory: ../../../builds/dumux-repositories/
File: /builds/dumux-repositories/dumux/dumux/multidomain/facet/cellcentered/mpfa/localassembler.hh
Date: 2024-09-21 20:52:54
Exec Total Coverage
Lines: 165 192 85.9%
Functions: 44 50 88.0%
Branches: 243 366 66.4%

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 FacetCoupling
10 * \copydoc Dumux::MpfaOFacetCouplingInteractionVolumeAssembler
11 */
12 #ifndef DUMUX_MULTIDOMAIN_FACET_CC_MPFA_O_LOCAL_ASSEMBLER_HH
13 #define DUMUX_MULTIDOMAIN_FACET_CC_MPFA_O_LOCAL_ASSEMBLER_HH
14
15 #include <vector>
16
17 #include <dune/common/exceptions.hh>
18 #include <dune/common/float_cmp.hh>
19
20 #include <dumux/common/math.hh>
21 #include <dumux/common/parameters.hh>
22 #include <dumux/discretization/extrusion.hh>
23 #include <dumux/discretization/cellcentered/mpfa/methods.hh>
24 #include <dumux/discretization/cellcentered/mpfa/localassemblerbase.hh>
25 #include <dumux/discretization/cellcentered/mpfa/localassemblerhelper.hh>
26 #include <dumux/discretization/cellcentered/mpfa/computetransmissibility.hh>
27
28 namespace Dumux {
29
30 /*!
31 * \ingroup FacetCoupling
32 * \brief Specialization of the interaction volume-local
33 * assembler class for the schemes using an mpfa-o type
34 * assembly in the context of facet coupling.
35 *
36 * \tparam P The problem type
37 * \tparam EG The element finite volume geometry
38 * \tparam EV The element volume variables type
39 */
40 template< class P, class EG, class EV >
41 class MpfaOFacetCouplingInteractionVolumeAssembler
42 : public InteractionVolumeAssemblerBase< P, EG, EV >
43 {
44 using ParentType = InteractionVolumeAssemblerBase< P, EG, EV >;
45 using Helper = InteractionVolumeAssemblerHelper;
46 using Extrusion = Extrusion_t<typename EG::GridGeometry>;
47
48 template< class IV >
49 using Scalar = typename IV::Traits::MatVecTraits::FaceVector::value_type;
50
51 public:
52 //! Pull up constructor of the base class
53
6/6
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1102198 times.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 3223028 times.
✓ Branch 4 taken 2 times.
✓ Branch 5 taken 2120830 times.
18887640 using ParentType::ParentType;
54
55 /*!
56 * \brief Assembles the matrices involved in the flux expressions
57 * and the local system of equations within an interaction volume.
58 *
59 * \param handle The data handle in which the matrices are stored
60 * \param iv The interaction volume
61 * \param getT Lambda to evaluate the scv-wise tensors
62 * \param wijZeroThresh Threshold below which transmissibilities are taken to be zero.
63 * On the basis of this threshold, trivial (0 = 0) rows in the
64 * A matrix are identified and modified accordingly in order to
65 * avoid ending up with singular matrices. This can occur when the
66 * tensor is zero in some cells.
67 */
68 template< class DataHandle, class IV, class TensorFunc >
69 18010716 void assembleMatrices(DataHandle& handle, IV& iv, const TensorFunc& getT, Scalar<IV> wijZeroThresh = 0.0)
70 {
71 108064296 assembleLocalMatrices_(handle.A(), handle.AB(), handle.CA(), handle.T(), handle.omegas(), iv, getT, wijZeroThresh);
72
73 // maybe solve the local system
74
1/2
✓ Branch 0 taken 9443820 times.
✗ Branch 1 not taken.
18010716 if (iv.numUnknowns() > 0)
75 18010716 Helper::solveLocalSystem(this->fvGeometry(), handle, iv);
76 18010716 }
77
78 /*!
79 * \brief Assembles the vector of primary (cell) unknowns and (maybe)
80 * Dirichlet boundary conditions within an interaction volume.
81 *
82 * \param handle The data handle in which the vector is stored
83 * \param iv The interaction volume
84 * \param getU Lambda to obtain the desired cell/Dirichlet value from vol vars
85 */
86 template< class DataHandle, class IV, class GetU >
87 18010716 void assembleU(DataHandle& handle, const IV& iv, const GetU& getU)
88 {
89 18010716 auto& u = handle.uj();
90 18010716 Helper::resizeVector(u, iv.numKnowns());
91
92 // put the cell unknowns first ...
93 18010716 typename IV::Traits::IndexSet::LocalIndexType i = 0;
94
4/4
✓ Branch 0 taken 37002193 times.
✓ Branch 1 taken 9443820 times.
✓ Branch 2 taken 37002193 times.
✓ Branch 3 taken 9443820 times.
176609306 for (; i < iv.numScvs(); i++)
95 140587874 u[i] = getU( this->elemVolVars()[iv.localScv(i).gridScvIndex()] );
96
97 // ... then put facet unknowns ...
98
4/4
✓ Branch 0 taken 2256944 times.
✓ Branch 1 taken 9443820 times.
✓ Branch 2 taken 2256944 times.
✓ Branch 3 taken 9443820 times.
80765128 for (const auto& data : iv.interiorBoundaryData())
99 {
100 4361132 const auto& scvf = this->fvGeometry().scvf(data.scvfIndex());
101
1/2
✓ Branch 1 taken 2256944 times.
✗ Branch 2 not taken.
8722264 const auto element = this->fvGeometry().gridGeometry().element(scvf.insideScvIdx());
102
2/4
✓ Branch 1 taken 2256944 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2256944 times.
✗ Branch 5 not taken.
8722264 u[i++] = getU( this->problem().couplingManager().getLowDimVolVars(element, scvf) );
103 }
104
105 // ... then put the Dirichlet unknowns
106
4/4
✓ Branch 0 taken 516080 times.
✓ Branch 1 taken 9443820 times.
✓ Branch 2 taken 516080 times.
✓ Branch 3 taken 9443820 times.
74078224 for (const auto& data : iv.dirichletData())
107 1017680 u[i++] = getU( this->elemVolVars()[data.volVarIndex()] );
108 18010716 }
109
110 /*!
111 * \brief Assembles the gravitational flux contributions on the scvfs within an
112 * interaction volume.
113 *
114 * \param handle The data handle in which the vector is stored
115 * \param iv The interaction volume
116 * \param getRho Lambda to obtain the density from volume variables
117 */
118 template< class DataHandle, class IV, class GetRho >
119 204840 void assembleGravity(DataHandle& handle, const IV& iv, const GetRho& getRho)
120 {
121 using GridView = typename IV::Traits::GridView;
122 static constexpr int dim = GridView::dimension;
123 static constexpr int dimWorld = GridView::dimensionworld;
124 static constexpr bool isSurfaceGrid = dim < dimWorld;
125
126 // resize the gravity vectors
127 204840 auto& g = handle.g();
128 204840 auto& deltaG = handle.deltaG();
129 204840 auto& outsideG = handle.gOutside();
130 204840 Helper::resizeVector(g, iv.numFaces());
131 204840 Helper::resizeVector(deltaG, iv.numUnknowns());
132 if (isSurfaceGrid)
133 68280 Helper::resizeVector(outsideG, iv.numFaces());
134
135 //! For each face, we...
136 //! - arithmetically average the phase densities
137 //! - compute the term \f$ \alpha := \mathbf{A} \rho \ \mathbf{n}^T \mathbf{K} \mathbf{g} \f$ in each neighboring cell
138 //! - compute \f$ \alpha^* = \sum{\alpha_{outside, i}} - \alpha_{inside} \f$
139 using Scalar = typename IV::Traits::MatVecTraits::TMatrix::value_type;
140 using LocalIndexType = typename IV::Traits::IndexSet::LocalIndexType;
141
142 // xi factor for coupling conditions
143
5/8
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 204837 times.
✓ Branch 3 taken 3 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 3 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 3 times.
✗ Branch 10 not taken.
204840 static const Scalar xi = getParamFromGroup<Scalar>(this->problem().paramGroup(), "FacetCoupling.Xi", 1.0);
144
145
2/2
✓ Branch 0 taken 835380 times.
✓ Branch 1 taken 204840 times.
1040220 for (LocalIndexType faceIdx = 0; faceIdx < iv.numFaces(); ++faceIdx)
146 {
147 // gravitational acceleration on this face
148 835380 const auto& curLocalScvf = iv.localScvf(faceIdx);
149 835380 const auto& curGlobalScvf = this->fvGeometry().scvf(curLocalScvf.gridScvfIndex());
150
6/6
✓ Branch 0 taken 49896 times.
✓ Branch 1 taken 785484 times.
✓ Branch 2 taken 49896 times.
✓ Branch 3 taken 785484 times.
✓ Branch 4 taken 49896 times.
✓ Branch 5 taken 785484 times.
2506140 const auto& gravity = this->problem().spatialParams().gravity(curGlobalScvf.ipGlobal());
151 835380 const auto curIsInteriorBoundary = curLocalScvf.isOnInteriorBoundary();
152
3/4
✓ Branch 0 taken 49896 times.
✓ Branch 1 taken 785484 times.
✓ Branch 2 taken 49896 times.
✗ Branch 3 not taken.
835380 const Scalar curXiFactor = curIsInteriorBoundary ? (curGlobalScvf.boundary() ? 1.0 : xi) : 1.0;
153
154 // get permeability tensor in "positive" sub volume
155
2/2
✓ Branch 0 taken 49896 times.
✓ Branch 1 taken 785484 times.
835380 const auto& neighborScvIndices = curLocalScvf.neighboringLocalScvIndices();
156
6/6
✓ Branch 0 taken 212388 times.
✓ Branch 1 taken 622992 times.
✓ Branch 2 taken 212388 times.
✓ Branch 3 taken 622992 times.
✓ Branch 4 taken 141592 times.
✓ Branch 5 taken 415328 times.
2227680 const auto& posGlobalScv = this->fvGeometry().scv(iv.localScv(neighborScvIndices[0]).gridScvIndex());
157 835380 const auto& posVolVars = this->elemVolVars()[posGlobalScv];
158 1670760 const auto alpha_inside = posVolVars.extrusionFactor()*vtmv(curGlobalScvf.unitOuterNormal(),
159 posVolVars.permeability(),
160 gravity);
161
162
2/2
✓ Branch 0 taken 817668 times.
✓ Branch 1 taken 17712 times.
835380 const auto numOutsideFaces = !curGlobalScvf.boundary() ? curGlobalScvf.numOutsideScvs() : 0;
163 using OutsideAlphaStorage = std::conditional_t< isSurfaceGrid,
164 std::vector<Scalar>,
165 Dune::ReservedVector<Scalar, 1> >;
166
4/8
✓ Branch 1 taken 278460 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 278460 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 272556 times.
✓ Branch 7 taken 5904 times.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
1664856 OutsideAlphaStorage alpha_outside; alpha_outside.resize(numOutsideFaces);
167 2506140 std::fill(alpha_outside.begin(), alpha_outside.end(), 0.0);
168 Scalar rho;
169
170
2/2
✓ Branch 0 taken 261828 times.
✓ Branch 1 taken 16632 times.
278460 if (isSurfaceGrid && !curIsInteriorBoundary)
171
2/4
✓ Branch 1 taken 261828 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 261828 times.
✗ Branch 5 not taken.
523656 Helper::resizeVector(outsideG[faceIdx], numOutsideFaces);
172
173
2/2
✓ Branch 0 taken 831276 times.
✓ Branch 1 taken 4104 times.
835380 if (!curLocalScvf.isDirichlet())
174 {
175 831276 const auto localDofIdx = curLocalScvf.localDofIndex();
176
2/2
✓ Branch 0 taken 49896 times.
✓ Branch 1 taken 781380 times.
831276 const Scalar curOneMinusXi = curIsInteriorBoundary ? -(1.0 - xi) : 1.0;
177
178
2/2
✓ Branch 0 taken 817668 times.
✓ Branch 1 taken 13608 times.
831276 rho = getRho(posVolVars);
179
2/2
✓ Branch 0 taken 817668 times.
✓ Branch 1 taken 13608 times.
831276 deltaG[localDofIdx] = 0.0;
180
181
2/2
✓ Branch 0 taken 817668 times.
✓ Branch 1 taken 13608 times.
831276 if (!curGlobalScvf.boundary())
182 {
183
4/4
✓ Branch 0 taken 817668 times.
✓ Branch 1 taken 817668 times.
✓ Branch 2 taken 817668 times.
✓ Branch 3 taken 817668 times.
3270672 for (unsigned int idxInOutside = 0; idxInOutside < curGlobalScvf.numOutsideScvs(); ++idxInOutside)
184 {
185 // obtain outside tensor
186
2/2
✓ Branch 0 taken 209928 times.
✓ Branch 1 taken 607740 times.
817668 const auto negLocalScvIdx = neighborScvIndices[idxInOutside+1];
187
4/4
✓ Branch 0 taken 209928 times.
✓ Branch 1 taken 607740 times.
✓ Branch 2 taken 209928 times.
✓ Branch 3 taken 607740 times.
1635336 const auto& negGlobalScv = this->fvGeometry().scv(iv.localScv(negLocalScvIdx).gridScvIndex());
188 817668 const auto& negVolVars = this->elemVolVars()[negGlobalScv];
189 1090224 const auto& flipScvf = !isSurfaceGrid ? curGlobalScvf
190 272556 : this->fvGeometry().flipScvf(curGlobalScvf.index(), idxInOutside);
191
192
2/2
✓ Branch 0 taken 767772 times.
✓ Branch 1 taken 49896 times.
2453004 alpha_outside[idxInOutside] = negVolVars.extrusionFactor()*vtmv(flipScvf.unitOuterNormal(),
193 negVolVars.permeability(),
194 gravity);
195 if (isSurfaceGrid)
196 272556 alpha_outside[idxInOutside] *= -1.0;
197
198
2/2
✓ Branch 0 taken 767772 times.
✓ Branch 1 taken 49896 times.
817668 if (!curIsInteriorBoundary)
199 1535544 rho += getRho(negVolVars);
200
201 2180448 deltaG[localDofIdx] += curOneMinusXi*alpha_outside[idxInOutside];
202 }
203 }
204
205
2/2
✓ Branch 0 taken 49896 times.
✓ Branch 1 taken 781380 times.
831276 if (curIsInteriorBoundary)
206 {
207
1/2
✓ Branch 1 taken 16632 times.
✗ Branch 2 not taken.
99792 const auto posElement = this->fvGeometry().gridGeometry().element(posGlobalScv.elementIndex());
208
2/4
✓ Branch 1 taken 49896 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 49896 times.
✗ Branch 5 not taken.
99792 const auto& facetVolVars = this->problem().couplingManager().getLowDimVolVars(posElement, curGlobalScvf);
209 49896 rho += getRho(facetVolVars);
210 49896 rho /= 2.0;
211 99792 const auto alphaFacet = posVolVars.extrusionFactor()*vtmv(curGlobalScvf.unitOuterNormal(),
212 facetVolVars.permeability(),
213 gravity);
214 99792 deltaG[localDofIdx] += alphaFacet;
215 }
216 else
217 781380 rho /= numOutsideFaces + 1;
218
219 831276 deltaG[localDofIdx] -= curXiFactor*alpha_inside;
220 2493828 deltaG[localDofIdx] *= rho*Extrusion::area(this->fvGeometry(), curGlobalScvf);
221 }
222 // use average density between facet and cell density on interior Dirichlet boundaries
223
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4104 times.
4104 else if (curIsInteriorBoundary)
224 {
225 const auto posElement = this->fvGeometry().gridGeometry().element(posGlobalScv.elementIndex());
226 const auto& facetVolVars = this->problem().couplingManager().getLowDimVolVars(posElement, curGlobalScvf);
227 rho = 0.5*(getRho(facetVolVars) + getRho(posVolVars));
228 }
229 // use density resulting from Dirichlet BCs
230 else
231 8208 rho = getRho(this->elemVolVars()[curGlobalScvf.outsideScvIdx()]);
232
233 // add "inside" & "outside" alphas to gravity containers
234
4/4
✓ Branch 0 taken 261828 times.
✓ Branch 1 taken 16632 times.
✓ Branch 2 taken 261828 times.
✓ Branch 3 taken 16632 times.
2227680 g[faceIdx] = alpha_inside*rho*Extrusion::area(this->fvGeometry(), curGlobalScvf);
235
236
2/2
✓ Branch 0 taken 261828 times.
✓ Branch 1 taken 16632 times.
278460 if (isSurfaceGrid && !curIsInteriorBoundary)
237 {
238 261828 unsigned int i = 0;
239
4/4
✓ Branch 0 taken 255924 times.
✓ Branch 1 taken 261828 times.
✓ Branch 2 taken 255924 times.
✓ Branch 3 taken 261828 times.
1297332 for (const auto& alpha : alpha_outside)
240 1023696 outsideG[faceIdx][i++] = alpha*rho*Extrusion::area(this->fvGeometry(), curGlobalScvf);
241 }
242 }
243
244 // add iv-wide contributions to gravity vectors
245 409680 handle.CA().umv(deltaG, g);
246 if (isSurfaceGrid)
247 {
248 using FaceVector = typename IV::Traits::MatVecTraits::FaceVector;
249
4/10
✓ Branch 1 taken 68280 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 68280 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 68280 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 68280 times.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
273120 FaceVector AG;
250
1/2
✓ Branch 1 taken 68280 times.
✗ Branch 2 not taken.
68280 Helper::resizeVector(AG, iv.numUnknowns());
251 136560 handle.A().mv(deltaG, AG);
252
253 // compute gravitational accelerations
254
4/4
✓ Branch 0 taken 534384 times.
✓ Branch 1 taken 68280 times.
✓ Branch 2 taken 534384 times.
✓ Branch 3 taken 68280 times.
807504 for (const auto& localFaceData : iv.localFaceData())
255 {
256 // continue only for "outside" faces
257
2/2
✓ Branch 0 taken 255924 times.
✓ Branch 1 taken 278460 times.
534384 if (!localFaceData.isOutsideFace())
258 continue;
259
260 255924 const auto localScvIdx = localFaceData.ivLocalInsideScvIndex();
261 255924 const auto localScvfIdx = localFaceData.ivLocalScvfIndex();
262 255924 const auto idxInOutside = localFaceData.scvfLocalOutsideScvfIndex();
263 255924 const auto& posLocalScv = iv.localScv(localScvIdx);
264 767772 const auto& wijk = handle.omegas()[localScvfIdx][idxInOutside+1];
265
266 // add contributions from all local directions
267
2/2
✓ Branch 0 taken 511848 times.
✓ Branch 1 taken 255924 times.
767772 for (LocalIndexType localDir = 0; localDir < dim; localDir++)
268 {
269 // the scvf corresponding to this local direction in the scv
270
4/4
✓ Branch 0 taken 511176 times.
✓ Branch 1 taken 672 times.
✓ Branch 2 taken 511176 times.
✓ Branch 3 taken 672 times.
1023696 const auto& curLocalScvf = iv.localScvf(posLocalScv.localScvfIndex(localDir));
271
2/2
✓ Branch 0 taken 511176 times.
✓ Branch 1 taken 672 times.
511848 if (!curLocalScvf.isDirichlet())
272 2555880 outsideG[localScvfIdx][idxInOutside] -= wijk[localDir]*AG[curLocalScvf.localDofIndex()];
273 }
274 }
275 }
276 204840 }
277
278 private:
279 /*!
280 * \copydoc Dumux::MpfaOInteractionVolumeAssembler::assembleLocalMatrices_
281 */
282 template< class IV, class TensorFunc >
283 18010716 void assembleLocalMatrices_(typename IV::Traits::MatVecTraits::AMatrix& A,
284 typename IV::Traits::MatVecTraits::BMatrix& B,
285 typename IV::Traits::MatVecTraits::CMatrix& C,
286 typename IV::Traits::MatVecTraits::DMatrix& D,
287 typename IV::Traits::MatVecTraits::OmegaStorage& wijk,
288 IV& iv, const TensorFunc& getT,
289 Scalar<IV> wijZeroThresh)
290 {
291 using Scalar = typename IV::Traits::MatVecTraits::TMatrix::value_type;
292 using LocalIndexType = typename IV::Traits::IndexSet::LocalIndexType;
293 static constexpr int dim = IV::Traits::GridView::dimension;
294 static constexpr int dimWorld = IV::Traits::GridView::dimensionworld;
295
296 // xi factor for coupling conditions
297
5/8
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 9443802 times.
✓ Branch 3 taken 18 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 18 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 18 times.
✗ Branch 10 not taken.
18010716 static const Scalar xi = getParamFromGroup<Scalar>(this->problem().paramGroup(), "FacetCoupling.Xi", 1.0);
298
299 // On surface grids only xi = 1.0 can be used, as the coupling condition
300 // for xi != 1.0 does not generalize for surface grids where the normal
301 // vectors of the inside/outside elements have different orientations.
302 if (dim < dimWorld)
303
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 4630588 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 4630588 times.
9012956 if (Dune::FloatCmp::ne(xi, 1.0, 1e-6))
304 DUNE_THROW(Dune::InvalidStateException, "Xi != 1.0 cannot be used on surface grids");
305
306
2/6
✓ Branch 1 taken 9443820 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 9443820 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
36021432 std::vector< std::pair<LocalIndexType, LocalIndexType> > faceMarkers;
307
1/2
✓ Branch 1 taken 9443820 times.
✗ Branch 2 not taken.
18010716 Helper::resizeVector(wijk, iv.numFaces());
308
309 // if only Dirichlet faces are present in the iv,
310 // the matrices A, B & C are undefined and D = T
311
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9443820 times.
18010716 if (iv.numUnknowns() == 0)
312 {
313 // resize & reset D matrix
314 Helper::resizeMatrix(D, iv.numFaces(), iv.numKnowns()); D = 0.0;
315
316 // Loop over all the faces, in this case these are all dirichlet boundaries
317 for (LocalIndexType faceIdx = 0; faceIdx < iv.numFaces(); ++faceIdx)
318 {
319 const auto& curLocalScvf = iv.localScvf(faceIdx);
320 const auto& curGlobalScvf = this->fvGeometry().scvf(curLocalScvf.gridScvfIndex());
321 const auto& neighborScvIndices = curLocalScvf.neighboringLocalScvIndices();
322
323 // get tensor in "positive" sub volume
324 const auto& posLocalScv = iv.localScv(neighborScvIndices[0]);
325 const auto& posGlobalScv = this->fvGeometry().scv(posLocalScv.gridScvIndex());
326 const auto& posVolVars = this->elemVolVars()[posGlobalScv];
327 const auto tensor = getT(posVolVars);
328
329 // the omega factors of the "positive" sub volume
330 Helper::resizeVector(wijk[faceIdx], /*no outside scvs present*/1);
331 wijk[faceIdx][0] = computeMpfaTransmissibility<EG>(this->fvGeometry(), posLocalScv, curGlobalScvf, tensor, posVolVars.extrusionFactor());
332
333 const auto posScvLocalDofIdx = posLocalScv.localDofIndex();
334 for (LocalIndexType localDir = 0; localDir < dim; localDir++)
335 {
336 const auto& otherLocalScvf = iv.localScvf( posLocalScv.localScvfIndex(localDir) );
337 const auto otherLocalDofIdx = otherLocalScvf.localDofIndex();
338 D[faceIdx][otherLocalDofIdx] -= wijk[faceIdx][0][localDir];
339 D[faceIdx][posScvLocalDofIdx] += wijk[faceIdx][0][localDir];
340 }
341 }
342 }
343 else
344 {
345 // resize & reset matrices
346
1/2
✓ Branch 1 taken 9443820 times.
✗ Branch 2 not taken.
18010716 Helper::resizeMatrix(A, iv.numUnknowns(), iv.numUnknowns()); A = 0.0;
347
1/2
✓ Branch 1 taken 9443820 times.
✗ Branch 2 not taken.
18010716 Helper::resizeMatrix(B, iv.numUnknowns(), iv.numKnowns()); B = 0.0;
348
1/2
✓ Branch 1 taken 9443820 times.
✗ Branch 2 not taken.
18010716 Helper::resizeMatrix(C, iv.numFaces(), iv.numUnknowns()); C = 0.0;
349
1/2
✓ Branch 1 taken 9443820 times.
✗ Branch 2 not taken.
18010716 Helper::resizeMatrix(D, iv.numFaces(), iv.numKnowns()); D = 0.0;
350
351
2/2
✓ Branch 0 taken 39769901 times.
✓ Branch 1 taken 9443820 times.
93659909 for (LocalIndexType faceIdx = 0; faceIdx < iv.numFaces(); ++faceIdx)
352 {
353 75649193 const auto& curLocalScvf = iv.localScvf(faceIdx);
354 75649193 const auto& curGlobalScvf = this->fvGeometry().scvf(curLocalScvf.gridScvfIndex());
355 75649193 const auto curIsDirichlet = curLocalScvf.isDirichlet();
356 75649193 const auto curLocalDofIdx = curLocalScvf.localDofIndex();
357 75649193 const auto curIsInteriorBoundary = curLocalScvf.isOnInteriorBoundary();
358
4/4
✓ Branch 0 taken 4507084 times.
✓ Branch 1 taken 35262817 times.
✓ Branch 2 taken 4500280 times.
✓ Branch 3 taken 6804 times.
75649193 const Scalar curXiFactor = curIsInteriorBoundary ? (curGlobalScvf.boundary() ? 1.0 : xi) : 1.0;
359
360 // get tensor in "positive" sub volume
361
2/2
✓ Branch 0 taken 4507084 times.
✓ Branch 1 taken 35262817 times.
75649193 const auto& neighborScvIndices = curLocalScvf.neighboringLocalScvIndices();
362
4/4
✓ Branch 0 taken 10600654 times.
✓ Branch 1 taken 29169247 times.
✓ Branch 2 taken 5391236 times.
✓ Branch 3 taken 15014547 times.
113579380 const auto& posLocalScv = iv.localScv(neighborScvIndices[0]);
363
2/2
✓ Branch 0 taken 10600654 times.
✓ Branch 1 taken 29169247 times.
75649193 const auto& posGlobalScv = this->fvGeometry().scv(posLocalScv.gridScvIndex());
364 75649193 const auto& posVolVars = this->elemVolVars()[posGlobalScv];
365
1/2
✓ Branch 1 taken 12489912 times.
✗ Branch 2 not taken.
113579380 const auto& posElement = iv.element(neighborScvIndices[0]);
366
1/2
✓ Branch 1 taken 12489912 times.
✗ Branch 2 not taken.
75649193 const auto tensor = getT(posVolVars);
367
368 // the omega factors of the "positive" sub volume
369
3/6
✓ Branch 1 taken 19364118 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 19364118 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 19364118 times.
✗ Branch 8 not taken.
189017392 Helper::resizeVector(wijk[faceIdx], neighborScvIndices.size());
370 75649193 wijk[faceIdx][0] = computeMpfaTransmissibility<EG>(this->fvGeometry(), posLocalScv, curGlobalScvf, tensor, posVolVars.extrusionFactor());
371
372 using std::abs;
373 75649193 bool isZeroWij = false;
374
375 // go over the coordinate directions in the positive sub volume
376
2/2
✓ Branch 0 taken 79539802 times.
✓ Branch 1 taken 39769901 times.
226947579 for (unsigned int localDir = 0; localDir < dim; localDir++)
377 {
378
4/4
✓ Branch 0 taken 39769901 times.
✓ Branch 1 taken 39769901 times.
✓ Branch 2 taken 39769901 times.
✓ Branch 3 taken 39769901 times.
302596772 const auto& otherLocalScvf = iv.localScvf( posLocalScv.localScvfIndex(localDir) );
379 151298386 const auto otherLocalDofIdx = otherLocalScvf.localDofIndex();
380
381
2/2
✓ Branch 0 taken 39769901 times.
✓ Branch 1 taken 39769901 times.
151298386 if (otherLocalDofIdx == curLocalDofIdx)
382 {
383
5/10
✗ Branch 0 not taken.
✓ Branch 1 taken 39769901 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 39769901 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 39769901 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 39769901 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 20405783 times.
340526959 if (abs(wijk[faceIdx][0][localDir]) <= wijZeroThresh)
384 {
385 if (!curIsDirichlet)
386 {
387 isZeroWij = true;
388 faceMarkers.emplace_back( std::make_pair(curLocalDofIdx, faceIdx) );
389 }
390 }
391 }
392
393 // if we are not on a Dirichlet face, add entries associated with unknown face pressures
394 // i.e. in matrix C and maybe A (if current face is not a Dirichlet face)
395
2/2
✓ Branch 0 taken 78750821 times.
✓ Branch 1 taken 788981 times.
151298386 if (!otherLocalScvf.isDirichlet())
396 {
397
10/10
✓ Branch 0 taken 78227937 times.
✓ Branch 1 taken 522884 times.
✓ Branch 2 taken 78227937 times.
✓ Branch 3 taken 522884 times.
✓ Branch 4 taken 78227937 times.
✓ Branch 5 taken 522884 times.
✓ Branch 6 taken 78227937 times.
✓ Branch 7 taken 522884 times.
✓ Branch 8 taken 40153713 times.
✓ Branch 9 taken 262224 times.
674104677 C[faceIdx][otherLocalDofIdx] -= wijk[faceIdx][0][localDir];
398
2/2
✓ Branch 0 taken 78227937 times.
✓ Branch 1 taken 522884 times.
149752445 if (!curIsDirichlet)
399 669499437 A[curLocalDofIdx][otherLocalDofIdx] -= curXiFactor*wijk[faceIdx][0][localDir];
400 }
401 // the current face is a Dirichlet face and creates entries in D & maybe B
402 else
403 {
404
10/10
✓ Branch 0 taken 266097 times.
✓ Branch 1 taken 522884 times.
✓ Branch 2 taken 266097 times.
✓ Branch 3 taken 522884 times.
✓ Branch 4 taken 266097 times.
✓ Branch 5 taken 522884 times.
✓ Branch 6 taken 266097 times.
✓ Branch 7 taken 522884 times.
✓ Branch 8 taken 133405 times.
✓ Branch 9 taken 262224 times.
6949241 D[faceIdx][otherLocalDofIdx] -= wijk[faceIdx][0][localDir];
405
2/2
✓ Branch 0 taken 266097 times.
✓ Branch 1 taken 522884 times.
1545941 if (!curIsDirichlet)
406 2344001 B[curLocalDofIdx][otherLocalDofIdx] += curXiFactor*wijk[faceIdx][0][localDir];
407 }
408
409 // add entries related to pressures at the scv centers (dofs)
410 151298386 const auto posScvLocalDofIdx = posLocalScv.localDofIndex();
411
10/10
✓ Branch 0 taken 78494034 times.
✓ Branch 1 taken 1045768 times.
✓ Branch 2 taken 78494034 times.
✓ Branch 3 taken 1045768 times.
✓ Branch 4 taken 78494034 times.
✓ Branch 5 taken 1045768 times.
✓ Branch 6 taken 78494034 times.
✓ Branch 7 taken 1045768 times.
✓ Branch 8 taken 40287118 times.
✓ Branch 9 taken 524448 times.
681053918 D[faceIdx][posScvLocalDofIdx] += wijk[faceIdx][0][localDir];
412
413
2/2
✓ Branch 0 taken 78494034 times.
✓ Branch 1 taken 1045768 times.
151298386 if (!curIsDirichlet)
414 671843438 B[curLocalDofIdx][posScvLocalDofIdx] -= curXiFactor*wijk[faceIdx][0][localDir];
415 }
416
417 // handle the entries related to the coupled facet element
418
2/2
✓ Branch 0 taken 4500280 times.
✓ Branch 1 taken 35269621 times.
75649193 if (curIsInteriorBoundary && !curIsDirichlet)
419 {
420
2/4
✓ Branch 1 taken 4500280 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 4500280 times.
✗ Branch 5 not taken.
17417312 const auto facetVolVars = this->problem().couplingManager().getLowDimVolVars(posElement, curGlobalScvf);
421 8708656 const auto facetTensor = getT(facetVolVars);
422
423 // On surface grids we use the square root of the extrusion factor as approximation of the aperture
424 using std::sqrt;
425 8708656 const auto wFacet = 2.0*Extrusion::area(this->fvGeometry(), curGlobalScvf)*posVolVars.extrusionFactor()
426 26125968 *vtmv(curGlobalScvf.unitOuterNormal(), facetTensor, curGlobalScvf.unitOuterNormal())
427 8708656 / (dim < dimWorld ? sqrt(facetVolVars.extrusionFactor()) : facetVolVars.extrusionFactor());
428
429
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 4500280 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 4500280 times.
17417312 A[curLocalDofIdx][curLocalDofIdx] -= wFacet;
430
3/6
✗ Branch 0 not taken.
✓ Branch 1 taken 4500280 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 4500280 times.
✓ Branch 4 taken 4500280 times.
✗ Branch 5 not taken.
17417312 B[curLocalDofIdx][curLocalScvf.coupledFacetLocalDofIndex()] -= wFacet;
431
432 // check for zero transmissibilities (skip if inside has been zero already)
433
3/6
✓ Branch 0 taken 4500280 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 4500280 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 4500280 times.
8708656 if (!isZeroWij && abs(wFacet) <= wijZeroThresh)
434 {
435 isZeroWij = true;
436 faceMarkers.emplace_back( std::make_pair(curLocalDofIdx, faceIdx) );
437 }
438 }
439
440 // If we are on an interior face (which isn't coupled via Dirichlet Bs), add values from negative sub volume
441
3/4
✓ Branch 0 taken 38734765 times.
✓ Branch 1 taken 1035136 times.
✓ Branch 2 taken 38734765 times.
✗ Branch 3 not taken.
75649193 if (!curGlobalScvf.boundary() && !curIsDirichlet)
442 {
443 // the minus ensures the right sign of the coupling condition in the matrices
444
2/2
✓ Branch 0 taken 4500280 times.
✓ Branch 1 taken 34234485 times.
73647337 const Scalar curOneMinusXi = curIsInteriorBoundary ? -(1.0 - xi) : 1.0;
445
446 // loop over all the outside neighbors of this face and add entries
447
4/4
✓ Branch 0 taken 38734765 times.
✓ Branch 1 taken 38734765 times.
✓ Branch 2 taken 38734765 times.
✓ Branch 3 taken 38734765 times.
147294674 for (unsigned int idxInOutside = 0; idxInOutside < curGlobalScvf.numOutsideScvs(); ++idxInOutside)
448 {
449 73647337 const auto idxOnScvf = idxInOutside+1;
450
4/4
✓ Branch 0 taken 9431860 times.
✓ Branch 1 taken 29302905 times.
✓ Branch 2 taken 9431860 times.
✓ Branch 3 taken 29302905 times.
147294674 const auto& negLocalScv = iv.localScv( neighborScvIndices[idxOnScvf] );
451
2/2
✓ Branch 0 taken 9431860 times.
✓ Branch 1 taken 29302905 times.
73647337 const auto& negGlobalScv = this->fvGeometry().scv(negLocalScv.gridScvIndex());
452 73647337 const auto& negVolVars = this->elemVolVars()[negGlobalScv];
453 73647337 const auto negTensor = getT(negVolVars);
454
455 // On surface grids, use outside face for "negative" transmissibility calculation
456 73647337 const auto& scvf = dim < dimWorld ? this->fvGeometry().flipScvf(curGlobalScvf.index(), idxInOutside)
457 : curGlobalScvf;
458 73647337 wijk[faceIdx][idxOnScvf] = computeMpfaTransmissibility<EG>(this->fvGeometry(), negLocalScv, scvf, negTensor, negVolVars.extrusionFactor());
459
460 // flip sign on surface grids (since we used the "outside" normal)
461 if (dim < dimWorld)
462 36712598 wijk[faceIdx][idxOnScvf] *= -1.0;
463
464 // go over the coordinate directions in the negative sub volume
465
2/2
✓ Branch 0 taken 77469530 times.
✓ Branch 1 taken 38734765 times.
220942011 for (int localDir = 0; localDir < dim; localDir++)
466 {
467
2/2
✓ Branch 0 taken 34234485 times.
✓ Branch 1 taken 43235045 times.
147294674 const auto otherLocalScvfIdx = negLocalScv.localScvfIndex(localDir);
468
2/2
✓ Branch 0 taken 34234485 times.
✓ Branch 1 taken 43235045 times.
147294674 const auto& otherLocalScvf = iv.localScvf(otherLocalScvfIdx);
469 147294674 const auto otherLocalDofIdx = otherLocalScvf.localDofIndex();
470
471 // check for zero transmissibilities (skip if inside has been zero already)
472
3/4
✓ Branch 0 taken 34234485 times.
✓ Branch 1 taken 43235045 times.
✓ Branch 2 taken 34234485 times.
✗ Branch 3 not taken.
147294674 if (otherLocalDofIdx == curLocalDofIdx && !isZeroWij)
473
5/10
✗ Branch 0 not taken.
✓ Branch 1 taken 34234485 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 34234485 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 34234485 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 34234485 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 34234485 times.
324693405 if (abs(wijk[faceIdx][idxOnScvf][localDir]) <= wijZeroThresh)
474 faceMarkers.emplace_back( std::make_pair(curLocalDofIdx, faceIdx) );
475
476
2/2
✓ Branch 0 taken 77212743 times.
✓ Branch 1 taken 256787 times.
147294674 if (!otherLocalScvf.isDirichlet())
477 880749882 A[curLocalDofIdx][otherLocalDofIdx] += curOneMinusXi*wijk[faceIdx][idxOnScvf][localDir];
478 else
479 3018162 B[curLocalDofIdx][otherLocalDofIdx] -= curOneMinusXi*wijk[faceIdx][idxOnScvf][localDir];
480
481 // add entries to matrix B
482 883768044 B[curLocalDofIdx][negLocalScv.localDofIndex()] += curOneMinusXi*wijk[faceIdx][idxOnScvf][localDir];
483 }
484 }
485 }
486 }
487 }
488 18010716 }
489 };
490
491 } // end namespace
492
493 #endif
494