p1fegradientcalculator.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 This file is part of the Open Porous Media project (OPM).
5
6 OPM is free software: you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation, either version 2 of the License, or
9 (at your option) any later version.
10
11 OPM is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with OPM. If not, see <http://www.gnu.org/licenses/>.
18
19 Consult the COPYING file in the top-level source directory of this
20 module for the precise wording of the license and the list of
21 copyright holders.
22*/
28#ifndef EWOMS_P1FE_GRADIENT_CALCULATOR_HH
29#define EWOMS_P1FE_GRADIENT_CALCULATOR_HH
30
31#include "vcfvproperties.hh"
32
34
35#include <dune/common/fvector.hh>
36#include <dune/common/version.hh>
37
38#include <dune/geometry/type.hh>
39
40#if HAVE_DUNE_LOCALFUNCTIONS
41#include <dune/localfunctions/lagrange/pqkfactory.hh>
42#endif // HAVE_DUNE_LOCALFUNCTIONS
43
44#include <dune/common/fvector.hh>
45
46#include <vector>
47
48namespace Opm {
58template<class TypeTag>
60{
66
67 enum { dim = GridView::dimension };
68
69 // set the maximum number of degrees of freedom and the maximum
70 // number of flux approximation points per elements. For this, we
71 // assume cubes as the type of element with the most vertices...
72 enum { maxDof = (2 << dim) };
73 enum { maxFap = maxDof };
74
75 using CoordScalar = typename GridView::ctype;
76 using DimVector = Dune::FieldVector<Scalar, dim>;
77
78#if HAVE_DUNE_LOCALFUNCTIONS
79 using LocalFiniteElementCache = Dune::PQkLocalFiniteElementCache<CoordScalar, Scalar, dim, 1>;
80 using LocalFiniteElement = typename LocalFiniteElementCache::FiniteElementType;
81 using LocalBasisTraits = typename LocalFiniteElement::Traits::LocalBasisType::Traits;
82 using ShapeJacobian = typename LocalBasisTraits::JacobianType;
83#endif // HAVE_DUNE_LOCALFUNCTIONS
84
85public:
92 template <bool prepareValues = true, bool prepareGradients = true>
93 void prepare([[maybe_unused]] const ElementContext& elemCtx,
94 [[maybe_unused]] unsigned timeIdx)
95 {
96 if (getPropValue<TypeTag, Properties::UseP1FiniteElementGradients>()) {
97#if !HAVE_DUNE_LOCALFUNCTIONS
98 // The dune-localfunctions module is required for P1 finite element gradients
99 throw std::logic_error("The dune-localfunctions module is required in oder to use"
100 " finite element gradients");
101#else
102 const auto& stencil = elemCtx.stencil(timeIdx);
103
104 const LocalFiniteElement& localFE = feCache_.get(elemCtx.element().type());
105 localFiniteElement_ = &localFE;
106
107 // loop over all face centeres
108 for (unsigned faceIdx = 0; faceIdx < stencil.numInteriorFaces(); ++faceIdx) {
109 const auto& localFacePos = stencil.interiorFace(faceIdx).localPos();
110
111 // Evaluate the P1 shape functions and their gradients at all
112 // flux approximation points.
113 if (prepareValues)
114 localFE.localBasis().evaluateFunction(localFacePos, p1Value_[faceIdx]);
115
116 if (prepareGradients) {
117 // first, get the shape function's gradient in local coordinates
118 std::vector<ShapeJacobian> localGradient;
119 localFE.localBasis().evaluateJacobian(localFacePos, localGradient);
120
121 // convert to a gradient in global space by
122 // multiplying with the inverse transposed jacobian of
123 // the position
124 const auto& geom = elemCtx.element().geometry();
125 const auto& jacInvT =
126 geom.jacobianInverseTransposed(localFacePos);
127
128 size_t numVertices = elemCtx.numDof(timeIdx);
129 for (unsigned vertIdx = 0; vertIdx < numVertices; vertIdx++) {
130 jacInvT.mv(/*xVector=*/localGradient[vertIdx][0],
131 /*destVector=*/p1Gradient_[faceIdx][vertIdx]);
132 }
133 }
134 }
135#endif
136 }
137 else
138 ParentType::template prepare<prepareValues, prepareGradients>(elemCtx, timeIdx);
139 }
140
152 template <class QuantityCallback>
153 auto calculateScalarValue([[maybe_unused]] const ElementContext& elemCtx,
154 [[maybe_unused]] unsigned fapIdx,
155 [[maybe_unused]] const QuantityCallback& quantityCallback) const
156 -> typename std::remove_reference<typename QuantityCallback::ResultType>::type
157 {
158 if (getPropValue<TypeTag, Properties::UseP1FiniteElementGradients>()) {
159#if !HAVE_DUNE_LOCALFUNCTIONS
160 // The dune-localfunctions module is required for P1 finite element gradients
161 throw std::logic_error("The dune-localfunctions module is required in oder to use"
162 " finite element gradients");
163#else
164 using QuantityConstType = typename std::remove_reference<typename QuantityCallback::ResultType>::type;
165 using QuantityType = typename std::remove_const<QuantityConstType>::type;
166 using Toolbox = MathToolbox<QuantityType>;
167
168 // If the user does not want to use two-point gradients, we
169 // use P1 finite element gradients..
170 QuantityType value(0.0);
171 for (unsigned vertIdx = 0; vertIdx < elemCtx.numDof(/*timeIdx=*/0); ++vertIdx) {
172 if (std::is_same<QuantityType, Scalar>::value ||
173 elemCtx.focusDofIndex() == vertIdx)
174 value += quantityCallback(vertIdx)*p1Value_[fapIdx][vertIdx];
175 else
176 value += Toolbox::value(quantityCallback(vertIdx))*p1Value_[fapIdx][vertIdx];
177 }
178
179 return value;
180#endif
181 }
182 else
183 return ParentType::calculateScalarValue(elemCtx, fapIdx, quantityCallback);
184 }
185
197 template <class QuantityCallback>
198 auto calculateVectorValue([[maybe_unused]] const ElementContext& elemCtx,
199 [[maybe_unused]] unsigned fapIdx,
200 [[maybe_unused]] const QuantityCallback& quantityCallback) const
201 -> typename std::remove_reference<typename QuantityCallback::ResultType>::type
202 {
203 if (getPropValue<TypeTag, Properties::UseP1FiniteElementGradients>()) {
204#if !HAVE_DUNE_LOCALFUNCTIONS
205 // The dune-localfunctions module is required for P1 finite element gradients
206 throw std::logic_error("The dune-localfunctions module is required in oder to use"
207 " finite element gradients");
208#else
209 using QuantityConstType = typename std::remove_reference<typename QuantityCallback::ResultType>::type;
210 using QuantityType = typename std::remove_const<QuantityConstType>::type;
211
212 using RawFieldType = decltype(std::declval<QuantityType>()[0]);
213 using FieldType = typename std::remove_const<typename std::remove_reference<RawFieldType>::type>::type;
214
215 using Toolbox = MathToolbox<FieldType>;
216
217 // If the user does not want to use two-point gradients, we
218 // use P1 finite element gradients..
219 QuantityType value(0.0);
220 for (unsigned vertIdx = 0; vertIdx < elemCtx.numDof(/*timeIdx=*/0); ++vertIdx) {
221 if (std::is_same<QuantityType, Scalar>::value ||
222 elemCtx.focusDofIndex() == vertIdx)
223 {
224 const auto& tmp = quantityCallback(vertIdx);
225 for (unsigned k = 0; k < tmp.size(); ++k)
226 value[k] += tmp[k]*p1Value_[fapIdx][vertIdx];
227 }
228 else {
229 const auto& tmp = quantityCallback(vertIdx);
230 for (unsigned k = 0; k < tmp.size(); ++k)
231 value[k] += Toolbox::value(tmp[k])*p1Value_[fapIdx][vertIdx];
232 }
233 }
234
235 return value;
236#endif
237 }
238 else
239 return ParentType::calculateVectorValue(elemCtx, fapIdx, quantityCallback);
240 }
241
253 template <class QuantityCallback, class EvalDimVector>
254 void calculateGradient([[maybe_unused]] EvalDimVector& quantityGrad,
255 [[maybe_unused]] const ElementContext& elemCtx,
256 [[maybe_unused]] unsigned fapIdx,
257 [[maybe_unused]] const QuantityCallback& quantityCallback) const
258 {
259 if (getPropValue<TypeTag, Properties::UseP1FiniteElementGradients>()) {
260#if !HAVE_DUNE_LOCALFUNCTIONS
261 // The dune-localfunctions module is required for P1 finite element gradients
262 throw std::logic_error("The dune-localfunctions module is required in oder to use"
263 " finite element gradients");
264#else
265 using QuantityConstType = typename std::remove_reference<typename QuantityCallback::ResultType>::type;
266 using QuantityType = typename std::remove_const<QuantityConstType>::type;
267
268 // If the user does not want two-point gradients, we use P1 finite element
269 // gradients...
270 quantityGrad = 0.0;
271 for (unsigned vertIdx = 0; vertIdx < elemCtx.numDof(/*timeIdx=*/0); ++vertIdx) {
272 if (std::is_same<QuantityType, Scalar>::value ||
273 elemCtx.focusDofIndex() == vertIdx)
274 {
275 const auto& dofVal = quantityCallback(vertIdx);
276 const auto& tmp = p1Gradient_[fapIdx][vertIdx];
277 for (int dimIdx = 0; dimIdx < dim; ++ dimIdx)
278 quantityGrad[dimIdx] += dofVal*tmp[dimIdx];
279 }
280 else {
281 const auto& dofVal = quantityCallback(vertIdx);
282 const auto& tmp = p1Gradient_[fapIdx][vertIdx];
283 for (int dimIdx = 0; dimIdx < dim; ++ dimIdx)
284 quantityGrad[dimIdx] += scalarValue(dofVal)*tmp[dimIdx];
285 }
286 }
287#endif
288 }
289 else
290 ParentType::calculateGradient(quantityGrad, elemCtx, fapIdx, quantityCallback);
291 }
292
307 template <class QuantityCallback>
308 auto calculateBoundaryValue(const ElementContext& elemCtx,
309 unsigned fapIdx,
310 const QuantityCallback& quantityCallback)
311 -> decltype(ParentType::calculateBoundaryValue(elemCtx, fapIdx, quantityCallback))
312 { return ParentType::calculateBoundaryValue(elemCtx, fapIdx, quantityCallback); }
313
328 template <class QuantityCallback, class EvalDimVector>
329 void calculateBoundaryGradient(EvalDimVector& quantityGrad,
330 const ElementContext& elemCtx,
331 unsigned fapIdx,
332 const QuantityCallback& quantityCallback) const
333 { ParentType::calculateBoundaryGradient(quantityGrad, elemCtx, fapIdx, quantityCallback); }
334
335#if HAVE_DUNE_LOCALFUNCTIONS
336 static LocalFiniteElementCache& localFiniteElementCache()
337 { return feCache_; }
338#endif
339
340private:
341#if HAVE_DUNE_LOCALFUNCTIONS
342 static LocalFiniteElementCache feCache_;
343
344 const LocalFiniteElement* localFiniteElement_;
345 std::vector<Dune::FieldVector<Scalar, 1>> p1Value_[maxFap];
346 DimVector p1Gradient_[maxFap][maxDof];
347#endif // HAVE_DUNE_LOCALFUNCTIONS
348};
349
350#if HAVE_DUNE_LOCALFUNCTIONS
351template<class TypeTag>
352typename P1FeGradientCalculator<TypeTag>::LocalFiniteElementCache
353P1FeGradientCalculator<TypeTag>::feCache_;
354#endif
355} // namespace Opm
356
357#endif
This class calculates gradients of arbitrary quantities at flux integration points using the two-poin...
Definition: fvbasegradientcalculator.hh:47
void calculateBoundaryGradient(EvalDimVector &quantityGrad, const ElementContext &elemCtx, unsigned faceIdx, const QuantityCallback &quantityCallback) const
Calculates the gradient of an arbitrary quantity at any flux approximation point on the boundary.
Definition: fvbasegradientcalculator.hh:284
void calculateGradient(EvalDimVector &quantityGrad, const ElementContext &elemCtx, unsigned fapIdx, const QuantityCallback &quantityCallback) const
Calculates the gradient of an arbitrary quantity at any flux approximation point.
Definition: fvbasegradientcalculator.hh:201
auto calculateScalarValue(const ElementContext &elemCtx, unsigned fapIdx, const QuantityCallback &quantityCallback) const -> typename std::remove_reference< decltype(quantityCallback.operator()(0))>::type
Calculates the value of an arbitrary scalar quantity at any interior flux approximation point.
Definition: fvbasegradientcalculator.hh:95
auto calculateBoundaryValue(const ElementContext &, unsigned, const QuantityCallback &quantityCallback) -> decltype(quantityCallback.boundaryValue())
Calculates the value of an arbitrary quantity at any flux approximation point on the grid boundary.
Definition: fvbasegradientcalculator.hh:263
auto calculateVectorValue(const ElementContext &elemCtx, unsigned fapIdx, const QuantityCallback &quantityCallback) const -> typename std::remove_reference< decltype(quantityCallback.operator()(0))>::type
Calculates the value of an arbitrary vectorial quantity at any interior flux approximation point.
Definition: fvbasegradientcalculator.hh:141
This class calculates gradients of arbitrary quantities at flux integration points using first order ...
Definition: p1fegradientcalculator.hh:60
auto calculateScalarValue(const ElementContext &elemCtx, unsigned fapIdx, const QuantityCallback &quantityCallback) const -> typename std::remove_reference< typename QuantityCallback::ResultType >::type
Calculates the value of an arbitrary quantity at any interior flux approximation point.
Definition: p1fegradientcalculator.hh:153
auto calculateVectorValue(const ElementContext &elemCtx, unsigned fapIdx, const QuantityCallback &quantityCallback) const -> typename std::remove_reference< typename QuantityCallback::ResultType >::type
Calculates the value of an arbitrary quantity at any interior flux approximation point.
Definition: p1fegradientcalculator.hh:198
void calculateBoundaryGradient(EvalDimVector &quantityGrad, const ElementContext &elemCtx, unsigned fapIdx, const QuantityCallback &quantityCallback) const
Calculates the gradient of an arbitrary quantity at any flux approximation point on the boundary.
Definition: p1fegradientcalculator.hh:329
auto calculateBoundaryValue(const ElementContext &elemCtx, unsigned fapIdx, const QuantityCallback &quantityCallback) -> decltype(ParentType::calculateBoundaryValue(elemCtx, fapIdx, quantityCallback))
Calculates the value of an arbitrary quantity at any flux approximation point on the grid boundary.
Definition: p1fegradientcalculator.hh:308
void prepare(const ElementContext &elemCtx, unsigned timeIdx)
Precomputes the common values to calculate gradients and values of quantities at any flux approximati...
Definition: p1fegradientcalculator.hh:93
void calculateGradient(EvalDimVector &quantityGrad, const ElementContext &elemCtx, unsigned fapIdx, const QuantityCallback &quantityCallback) const
Calculates the gradient of an arbitrary quantity at any flux approximation point.
Definition: p1fegradientcalculator.hh:254
Definition: blackoilboundaryratevector.hh:37
typename Properties::Detail::GetPropImpl< TypeTag, Property >::type::type GetPropType
get the type alias defined in the property (equivalent to old macro GET_PROP_TYPE(....
Definition: propertysystem.hh:242
Declares the basic properties used by the common infrastructure of the vertex-centered finite volume ...