vcfvgradientcalculator.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  Copyright (C) 2010-2013 by Andreas Lauser
5 
6  This file is part of the Open Porous Media project (OPM).
7 
8  OPM is free software: you can redistribute it and/or modify
9  it under the terms of the GNU General Public License as published by
10  the Free Software Foundation, either version 2 of the License, or
11  (at your option) any later version.
12 
13  OPM is distributed in the hope that it will be useful,
14  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  GNU General Public License for more details.
17 
18  You should have received a copy of the GNU General Public License
19  along with OPM. If not, see <http://www.gnu.org/licenses/>.
20 */
26 #ifndef EWOMS_VCFV_GRADIENT_CALCULATOR_HH
27 #define EWOMS_VCFV_GRADIENT_CALCULATOR_HH
28 
29 #include "vcfvproperties.hh"
30 
32 
33 #include <dune/common/fvector.hh>
34 #include <dune/common/version.hh>
35 
36 #include <dune/geometry/type.hh>
37 #include <dune/localfunctions/lagrange/pqkfactory.hh>
38 #include <dune/common/fvector.hh>
39 
40 #include <vector>
41 
42 namespace Ewoms {
50 template<class TypeTag>
52 {
54  typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar;
55  typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView;
56  typedef typename GET_PROP_TYPE(TypeTag, ElementContext) ElementContext;
57 
58  enum { dim = GridView::dimension };
59 
60  // set the maximum number of degrees of freedom and the maximum
61  // number of flux approximation points per elements. For this, we
62  // assume cubes as the type of element with the most vertices...
63  enum { maxDof = (2 << dim) };
64  enum { maxFap = maxDof };
65 
66  typedef typename GridView::ctype CoordScalar;
67  typedef Dune::FieldVector<Scalar, dim> DimVector;
68 
69  typedef Dune::PQkLocalFiniteElementCache<CoordScalar, Scalar, dim, 1> LocalFiniteElementCache;
70  typedef typename LocalFiniteElementCache::FiniteElementType LocalFiniteElement;
71  typedef typename LocalFiniteElement::Traits::LocalBasisType::Traits LocalBasisTraits;
72  typedef typename LocalBasisTraits::JacobianType ShapeJacobian;
73 
74 public:
81  template <bool prepareValues = true, bool prepareGradients = true>
82  void prepare(const ElementContext &elemCtx, int timeIdx)
83  {
84  if (GET_PROP_VALUE(TypeTag, UseTwoPointGradients)) {
85  ParentType::template prepare<prepareValues, prepareGradients>(elemCtx, timeIdx);
86  return;
87  }
88 
89  const auto &stencil = elemCtx.stencil(timeIdx);
90 
91  const LocalFiniteElement& localFE = feCache_.get(elemCtx.element().type());
92  localFiniteElement_ = &localFE;
93 
94  // loop over all face centeres
95  for (int faceIdx = 0; faceIdx < stencil.numInteriorFaces(); ++faceIdx) {
96  const auto &localFacePos = stencil.interiorFace(faceIdx).localPos();
97 
98  // Evaluate the P1 shape functions and their gradients at all
99  // flux approximation points.
100  if (prepareValues)
101  localFE.localBasis().evaluateFunction(localFacePos, p1Value_[faceIdx]);
102 
103  if (prepareGradients) {
104  // first, get the shape function's gradient in local coordinates
105  std::vector<ShapeJacobian> localGradient;
106  localFE.localBasis().evaluateJacobian(localFacePos, localGradient);
107 
108  // convert to a gradient in global space by
109  // multiplying with the inverse transposed jacobian of
110  // the position
111  const auto &geom = elemCtx.element().geometry();
112  const auto &jacInvT =
113  geom.jacobianInverseTransposed(localFacePos);
114 
115  int numVertices = elemCtx.numDof(timeIdx);
116  for (int vertIdx = 0; vertIdx < numVertices; vertIdx++) {
117  jacInvT.mv(/*xVector=*/localGradient[vertIdx][0],
118  /*destVector=*/p1Gradient_[faceIdx][vertIdx]);
119  }
120  }
121  }
122  }
123 
124 
136  template <class QuantityCallback, class Dummy=int>
137  auto calculateValue(const ElementContext &elemCtx,
138  typename std::enable_if<!GET_PROP_VALUE(TypeTag, UseTwoPointGradients),
139  Dummy>::type fapIdx,
140  const QuantityCallback& quantityCallback) const
141  -> typename std::remove_reference<typename QuantityCallback::ResultType>::type
142  {
143  static_assert(std::is_integral<Dummy>::value,
144  "The 'Dummy' template parameter must _not_ be specified explicitly."
145  "It is only required to conditionally disable this method!");
146 
147  typedef typename std::remove_reference<typename QuantityCallback::ResultType>::type QuantityConstType;
148  typedef typename std::remove_const<QuantityConstType>::type QuantityType;
149 
150  // If the user does not want to use two-point gradients, we
151  // use P1 finite element gradients..
152  QuantityType value(0.0);
153  QuantityType tmp;
154  for (int vertIdx = 0; vertIdx < elemCtx.numDof(/*timeIdx=*/0); ++vertIdx) {
155  tmp = quantityCallback(vertIdx);
156  tmp *= p1Value_[fapIdx][vertIdx];
157  value += tmp;
158  }
159  return value;
160  }
161 
162  template <class QuantityCallback, class Dummy = int>
163  auto calculateValue(const ElementContext &elemCtx,
164  typename std::enable_if<GET_PROP_VALUE(TypeTag, UseTwoPointGradients),
165  Dummy>::type fapIdx,
166  const QuantityCallback& quantityCallback) const
167  -> decltype(ParentType::calculateValue(elemCtx, fapIdx, quantityCallback))
168  {
169  static_assert(std::is_integral<Dummy>::value,
170  "The 'Dummy' template parameter must _not_ be specified explicitly."
171  "It is only required to conditionally disable this method!");
172 
173  return ParentType::calculateValue(elemCtx, fapIdx, quantityCallback);
174  }
175 
187  template <class QuantityCallback, class EvalDimVector, class Dummy = int>
188  void calculateGradient(EvalDimVector &quantityGrad,
189  const ElementContext &elemCtx,
190  typename std::enable_if<!GET_PROP_VALUE(TypeTag, UseTwoPointGradients),
191  Dummy>::type fapIdx,
192  const QuantityCallback& quantityCallback) const
193  {
194  static_assert(std::is_integral<Dummy>::value,
195  "The 'Dummy' template parameter must _not_ be specified explicitly."
196  "It is only required to conditionally disable this method!");
197 
198  // If the user does not want two-point gradients, we use P1
199  // finite element gradients...
200  quantityGrad = 0.0;
201  for (int vertIdx = 0; vertIdx < elemCtx.numDof(/*timeIdx=*/0); ++vertIdx) {
202  Scalar dofVal = quantityCallback(vertIdx);
203 
204  auto tmp = p1Gradient_[fapIdx][vertIdx];
205  tmp *= dofVal;
206  quantityGrad += tmp;
207  }
208  }
209 
210  template <class QuantityCallback, class EvalDimVector, class Dummy=int>
211  void calculateGradient(EvalDimVector &quantityGrad,
212  const ElementContext &elemCtx,
213  typename std::enable_if<GET_PROP_VALUE(TypeTag, UseTwoPointGradients),
214  Dummy>::type fapIdx,
215  const QuantityCallback& quantityCallback) const
216  {
217  static_assert(std::is_integral<Dummy>::value,
218  "The 'Dummy' template parameter must _not_ be specified explicitly."
219  "It is only required to conditionally disable this method!");
220 
221  return ParentType::calculateGradient(quantityGrad, elemCtx, fapIdx, quantityCallback);
222  }
223 
238  template <class QuantityCallback>
239  auto calculateBoundaryValue(const ElementContext &elemCtx,
240  int fapIdx,
241  const QuantityCallback &quantityCallback)
242  -> decltype(ParentType::calculateBoundaryValue(elemCtx, fapIdx, quantityCallback))
243  { return ParentType::calculateBoundaryValue(elemCtx, fapIdx, quantityCallback); }
244 
259  template <class QuantityCallback, class EvalDimVector>
260  void calculateBoundaryGradient(EvalDimVector &quantityGrad,
261  const ElementContext &elemCtx,
262  int fapIdx,
263  const QuantityCallback &quantityCallback) const
264  { ParentType::calculateBoundaryGradient(quantityGrad, elemCtx, fapIdx, quantityCallback); }
265 
266  static LocalFiniteElementCache& localFiniteElementCache()
267  { return feCache_; }
268 
269 private:
270  static LocalFiniteElementCache feCache_;
271 
272  const LocalFiniteElement* localFiniteElement_;
273  std::vector<Dune::FieldVector<Scalar, 1>> p1Value_[maxFap];
274  DimVector p1Gradient_[maxFap][maxDof];
275 };
276 
277 template<class TypeTag>
278 typename VcfvGradientCalculator<TypeTag>::LocalFiniteElementCache
279 VcfvGradientCalculator<TypeTag>::feCache_;
280 } // namespace Ewoms
281 
282 #endif
static LocalFiniteElementCache & localFiniteElementCache()
Definition: vcfvgradientcalculator.hh:266
auto calculateValue(const ElementContext &elemCtx, typename std::enable_if< GET_PROP_VALUE(TypeTag, UseTwoPointGradients), Dummy >::type fapIdx, const QuantityCallback &quantityCallback) const -> decltype(ParentType::calculateValue(elemCtx, fapIdx, quantityCallback))
Definition: vcfvgradientcalculator.hh:163
void calculateGradient(EvalDimVector &quantityGrad, const ElementContext &elemCtx, typename std::enable_if<!GET_PROP_VALUE(TypeTag, UseTwoPointGradients), Dummy >::type fapIdx, const QuantityCallback &quantityCallback) const
Calculates the gradient of an arbitrary quantity at any flux approximation point. ...
Definition: vcfvgradientcalculator.hh:188
void calculateBoundaryGradient(EvalDimVector &quantityGrad, const ElementContext &elemCtx, int fapIdx, const QuantityCallback &quantityCallback) const
Calculates the gradient of an arbitrary quantity at any flux approximation point on the boundary...
Definition: vcfvgradientcalculator.hh:260
#define GET_PROP_VALUE(TypeTag, PropTagName)
Access the value attribute of a property for a type tag.
Definition: propertysystem.hh:468
void prepare(const ElementContext &elemCtx, int timeIdx)
Precomputes the common values to calculate gradients and values of quantities at any flux approximati...
Definition: vcfvgradientcalculator.hh:82
auto calculateValue(const ElementContext &elemCtx, typename std::enable_if<!GET_PROP_VALUE(TypeTag, UseTwoPointGradients), Dummy >::type 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: vcfvgradientcalculator.hh:137
Definition: baseauxiliarymodule.hh:35
This class calculates gradients of arbitrary quantities at flux integration points using the two-poin...
This class calculates gradients of arbitrary quantities at flux integration points for the vertex cen...
Definition: vcfvgradientcalculator.hh:51
auto calculateBoundaryValue(const ElementContext &elemCtx, int 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: vcfvgradientcalculator.hh:239
void calculateGradient(EvalDimVector &quantityGrad, const ElementContext &elemCtx, typename std::enable_if< GET_PROP_VALUE(TypeTag, UseTwoPointGradients), Dummy >::type fapIdx, const QuantityCallback &quantityCallback) const
Definition: vcfvgradientcalculator.hh:211
This class calculates gradients of arbitrary quantities at flux integration points using the two-poin...
Definition: fvbasegradientcalculator.hh:44
Declares the basic properties used by the common infrastructure of the vertex-centered finite volume ...