version 3.8
localassemblerhelper.hh
Go to the documentation of this file.
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//
14#ifndef DUMUX_DISCRETIZATION_CC_MPFA_LOCAL_ASSEMBLER_HELPER_HH
15#define DUMUX_DISCRETIZATION_CC_MPFA_LOCAL_ASSEMBLER_HELPER_HH
16
17#include <algorithm>
18#include <vector>
19#include <cassert>
20#include <utility>
21#include <type_traits>
22
24
25namespace Dumux {
26
34{
35 // Helper structs to detect if matrix has resize function
36 struct HasMatrixResize
37 {
38 template<class M>
39 auto operator()(const M& m) -> decltype(std::declval<M>().resize(0, 0))
40 {}
41 };
42
43 // Helper structs to detect if vector has resize function
44 struct HasVectorResize
45 {
46 template<class V>
47 auto operator()(const V& v) -> decltype(std::declval<V>().resize(0))
48 {}
49 };
50
51 template<class Matrix>
52 static constexpr auto matrixHasResizeFunction()
53 { return decltype( isValid(HasMatrixResize())(std::declval<Matrix>()) )::value; }
54
55 template<class Vector>
56 static constexpr auto vectorHasResizeFunction()
57 { return decltype( isValid(HasVectorResize())(std::declval<Vector>()) )::value; }
58
59public:
69 template< class FVElementGeometry, class DataHandle, class IV >
70 static void solveLocalSystem(const FVElementGeometry& fvGeometry,
71 DataHandle& handle,
72 IV& iv)
73 {
74 assert(iv.numUnknowns() > 0);
75
76 // T = C*(A^-1)*B + D
77 handle.A().invert();
78 handle.CA().rightmultiply(handle.A());
79 handle.T() += multiplyMatrices(handle.CA(), handle.AB());
80 handle.AB().leftmultiply(handle.A());
81
82 // On surface grids, compute the "outside" transmissibilities
83 using GridView = typename IV::Traits::GridView;
84 static constexpr int dim = GridView::dimension;
85 static constexpr int dimWorld = GridView::dimensionworld;
86 if (dim < dimWorld)
87 {
88 // bring outside tij container to the right size
89 auto& tijOut = handle.tijOutside();
90 tijOut.resize(iv.numFaces());
91 using LocalIndexType = typename IV::Traits::IndexSet::LocalIndexType;
92 for (LocalIndexType fIdx = 0; fIdx < iv.numFaces(); ++fIdx)
93 {
94 const auto& curGlobalScvf = fvGeometry.scvf(iv.localScvf(fIdx).gridScvfIndex());
95 const auto numOutsideFaces = curGlobalScvf.boundary() ? 0 : curGlobalScvf.numOutsideScvs();
96 // resize each face entry to the right number of outside faces
97 tijOut[fIdx].resize(numOutsideFaces);
98 std::for_each(tijOut[fIdx].begin(),
99 tijOut[fIdx].end(),
100 [&](auto& v) { resizeVector(v, iv.numKnowns()); });
101 }
102
103 // compute outside transmissibilities
104 for (const auto& localFaceData : iv.localFaceData())
105 {
106 // continue only for "outside" faces
107 if (!localFaceData.isOutsideFace())
108 continue;
109
110 const auto scvIdx = localFaceData.ivLocalInsideScvIndex();
111 const auto scvfIdx = localFaceData.ivLocalScvfIndex();
112 const auto idxInOut = localFaceData.scvfLocalOutsideScvfIndex();
113
114 const auto& wijk = handle.omegas()[scvfIdx][idxInOut+1];
115 auto& tij = tijOut[scvfIdx][idxInOut];
116
117 tij = 0.0;
118 for (unsigned int dir = 0; dir < dim; dir++)
119 {
120 // the scvf corresponding to this local direction in the scv
121 const auto& scvf = iv.localScvf(iv.localScv(scvIdx).localScvfIndex(dir));
122
123 // on interior faces the coefficients of the AB matrix come into play
124 if (!scvf.isDirichlet())
125 {
126 auto tmp = handle.AB()[scvf.localDofIndex()];
127 tmp *= wijk[dir];
128 tij -= tmp;
129 }
130 else
131 tij[scvf.localDofIndex()] -= wijk[dir];
132
133 // add entry from the scv unknown
134 tij[scvIdx] += wijk[dir];
135 }
136 }
137 }
138 }
139
147 template< class DataHandle, class IV >
148 static typename IV::Traits::MatVecTraits::FaceVector
149 assembleFaceUnkowns(const DataHandle& handle, const IV& iv)
150 {
151 typename IV::Traits::MatVecTraits::FaceVector u;
152 resizeVector(u, iv.numFaces());
153
154 handle.AB().mv(handle.uj(), u);
155
156 // maybe add gravity terms
157 if (handle.deltaG().size() == iv.numUnknowns())
158 handle.A().umv(handle.deltaG(), u);
159
160 return u;
161 }
162
171 template< class DataHandle, class IV >
172 static std::vector< typename IV::Traits::LocalScvType::GlobalCoordinate >
173 assembleScvGradients(const DataHandle& handle, const IV& iv)
174 {
175 const auto u = assembleFaceUnkowns(handle, iv);
176
177 using LocalScv = typename IV::Traits::LocalScvType;
178 using Gradient = typename LocalScv::GlobalCoordinate;
179
180 std::vector<Gradient> result; result.reserve(iv.numScvs());
181 for (unsigned int scvIdx = 0; scvIdx < iv.numScvs(); ++scvIdx)
182 {
183 const auto& scv = iv.localScv(scvIdx);
184
185 Gradient gradU(0.0);
186 for (unsigned int dir = 0; dir < LocalScv::myDimension; ++dir)
187 {
188 auto nu = scv.nu(dir);
189
190 // obtain face pressure
191 const auto& scvf = iv.localScvf( scv.localScvfIndex(dir) );
192 const auto faceU = !scvf.isDirichlet() ? u[scvf.localDofIndex()]
193 : handle.uj()[scvf.localDofIndex()];
194
195 nu *= faceU - handle.uj()[scv.localDofIndex()];
196 gradU += nu;
197 }
198
199 gradU /= scv.detX();
200 result.emplace_back( std::move(gradU) );
201 }
202
203 return result;
204 }
205
207 template< class Matrix,
208 class size_type,
209 std::enable_if_t<matrixHasResizeFunction<Matrix>(), int> = 0 >
210 static void resizeMatrix(Matrix& M, size_type rows, size_type cols)
211 {
212 M.resize(rows, cols);
213 }
214
216 template< class Matrix,
217 class size_type,
218 std::enable_if_t<!matrixHasResizeFunction<Matrix>(), int> = 0 >
219 static void resizeMatrix(Matrix& M, size_type rows, size_type cols)
220 {}
221
223 template< class Vector,
224 class size_type,
225 std::enable_if_t<vectorHasResizeFunction<Vector>(), int> = 0 >
226 static void resizeVector(Vector& v, size_type size)
227 {
228 v.resize(size);
229 }
230
232 template< class Vector,
233 class size_type,
234 std::enable_if_t<!vectorHasResizeFunction<Vector>(), int> = 0 >
235 static void resizeVector(Vector& v, size_type rows)
236 {}
237};
238
239} // end namespace Dumux
240
241#endif
A class that contains helper functions as well as functionality which is common to different mpfa sch...
Definition: localassemblerhelper.hh:34
static void resizeVector(Vector &v, size_type rows)
resizes a vector to the given size (specialization for static vector type - do nothing)
Definition: localassemblerhelper.hh:235
static void solveLocalSystem(const FVElementGeometry &fvGeometry, DataHandle &handle, IV &iv)
Solves a previously assembled iv-local system of equations and stores the resulting transmissibilitie...
Definition: localassemblerhelper.hh:70
static std::vector< typename IV::Traits::LocalScvType::GlobalCoordinate > assembleScvGradients(const DataHandle &handle, const IV &iv)
Assembles the solution gradients in the sub-control volumes within an interaction volume.
Definition: localassemblerhelper.hh:173
static void resizeMatrix(Matrix &M, size_type rows, size_type cols)
resizes a matrix to the given sizes (specialization for dynamic matrix type)
Definition: localassemblerhelper.hh:210
static void resizeVector(Vector &v, size_type size)
resizes a vector to the given size (specialization for dynamic matrix type)
Definition: localassemblerhelper.hh:226
static IV::Traits::MatVecTraits::FaceVector assembleFaceUnkowns(const DataHandle &handle, const IV &iv)
Assembles the vector of face unknowns within an interaction volume.
Definition: localassemblerhelper.hh:149
Dune::DynamicMatrix< Scalar > multiplyMatrices(const Dune::DynamicMatrix< Scalar > &M1, const Dune::DynamicMatrix< Scalar > &M2)
Multiply two dynamic matrices.
Definition: math.hh:722
constexpr auto isValid(const Expression &t)
A function that creates a test functor to do class member introspection at compile time.
Definition: isvalid.hh:81
A helper function for class member function introspection.
Definition: adapt.hh:17