opm-simulators
fvbasegradientcalculator.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_FV_BASE_GRADIENT_CALCULATOR_HH
29 #define EWOMS_FV_BASE_GRADIENT_CALCULATOR_HH
30 
31 #include <dune/common/fvector.hh>
32 
35 
36 #include <cmath>
37 #include <type_traits>
38 
39 namespace Opm {
40 
41 template<class TypeTag>
43 
50 template<class TypeTag>
52 {
58 
59  enum { dim = GridView::dimension };
60  enum { dimWorld = GridView::dimensionworld };
61 
62  // maximum number of flux approximation points. to calculate this,
63  // we assume that the geometry with the most points is a cube.
64  enum { maxFap = 2 << dim };
65 
66  using DimVector = Dune::FieldVector<Scalar, dimWorld>;
67  using EvalDimVector = Dune::FieldVector<Evaluation, dimWorld>;
68 
69 public:
74  static void registerParameters()
75  {}
76 
84  template <bool prepareValues = true, bool prepareGradients = true>
85  void prepare(const ElementContext&, unsigned)
86  { /* nothing to do */ }
87 
99  template <class QuantityCallback>
100  auto calculateScalarValue(const ElementContext& elemCtx,
101  unsigned fapIdx,
102  const QuantityCallback& quantityCallback) const
103  -> std::remove_reference_t<decltype(quantityCallback.operator()(0))>
104  {
105  using RawReturnType = decltype(quantityCallback.operator()(0));
106  using ReturnType = std::remove_const_t<std::remove_reference_t<RawReturnType>>;
107 
108  Scalar interiorDistance;
109  Scalar exteriorDistance;
110  computeDistances_(interiorDistance, exteriorDistance, elemCtx, fapIdx);
111 
112  const auto& face = elemCtx.stencil(/*timeIdx=*/0).interiorFace(fapIdx);
113  const auto i = face.interiorIndex();
114  const auto j = face.exteriorIndex();
115  const auto focusDofIdx = elemCtx.focusDofIndex();
116 
117  // use the average weighted by distance...
118  ReturnType value;
119  if (i == focusDofIdx) {
120  value = quantityCallback(i) * interiorDistance;
121  } else {
122  value = getValue(quantityCallback(i)) * interiorDistance;
123  }
124 
125  if (j == focusDofIdx) {
126  value += quantityCallback(j) * exteriorDistance;
127  }
128  else {
129  value += getValue(quantityCallback(j)) * exteriorDistance;
130  }
131 
132  value /= interiorDistance + exteriorDistance;
133 
134  return value;
135  }
136 
148  template <class QuantityCallback>
149  auto calculateVectorValue(const ElementContext& elemCtx,
150  unsigned fapIdx,
151  const QuantityCallback& quantityCallback) const
152  -> std::remove_reference_t<decltype(quantityCallback.operator()(0))>
153  {
154  using RawReturnType = decltype(quantityCallback.operator()(0));
155  using ReturnType = std::remove_const_t<std::remove_reference_t<RawReturnType>>;
156 
157  Scalar interiorDistance;
158  Scalar exteriorDistance;
159  computeDistances_(interiorDistance, exteriorDistance, elemCtx, fapIdx);
160 
161  const auto& face = elemCtx.stencil(/*timeIdx=*/0).interiorFace(fapIdx);
162  const auto i = face.interiorIndex();
163  const auto j = face.exteriorIndex();
164  const auto focusDofIdx = elemCtx.focusDofIndex();
165 
166  // use the average weighted by distance...
167  ReturnType value;
168  if (i == focusDofIdx) {
169  value = quantityCallback(i);
170  for (int k = 0; k < value.size(); ++k) {
171  value[k] *= interiorDistance;
172  }
173  }
174  else {
175  const auto& dofVal = getValue(quantityCallback(i));
176  for (int k = 0; k < dofVal.size(); ++k) {
177  value[k] = getValue(dofVal[k]) * interiorDistance;
178  }
179  }
180 
181  if (j == focusDofIdx) {
182  const auto& dofVal = quantityCallback(j);
183  for (int k = 0; k < dofVal.size(); ++k) {
184  value[k] += dofVal[k] * exteriorDistance;
185  }
186  }
187  else {
188  const auto& dofVal = quantityCallback(j);
189  for (int k = 0; k < dofVal.size(); ++k) {
190  value[k] += getValue(dofVal[k]) * exteriorDistance;
191  }
192  }
193 
194  const Scalar totDistance = interiorDistance + exteriorDistance;
195  for (int k = 0; k < value.size(); ++k) {
196  value[k] /= totDistance;
197  }
198 
199  return value;
200  }
201 
214  template <class QuantityCallback>
215  void calculateGradient(EvalDimVector& quantityGrad,
216  const ElementContext& elemCtx,
217  unsigned fapIdx,
218  const QuantityCallback& quantityCallback) const
219  {
220  const auto& stencil = elemCtx.stencil(/*timeIdx=*/0);
221  const auto& face = stencil.interiorFace(fapIdx);
222 
223  const auto i = face.interiorIndex();
224  const auto j = face.exteriorIndex();
225  const auto focusIdx = elemCtx.focusDofIndex();
226 
227  const auto& interiorPos = stencil.subControlVolume(i).globalPos();
228  const auto& exteriorPos = stencil.subControlVolume(j).globalPos();
229 
230  Evaluation deltay;
231  if (i == focusIdx) {
232  deltay = getValue(quantityCallback(j)) - quantityCallback(i);
233  }
234  else if (j == focusIdx) {
235  deltay = quantityCallback(j) - getValue(quantityCallback(i));
236  }
237  else {
238  deltay = getValue(quantityCallback(j)) - getValue(quantityCallback(i));
239  }
240 
241  Scalar distSquared = 0.0;
242  for (unsigned dimIdx = 0; dimIdx < dimWorld; ++dimIdx) {
243  const Scalar tmp = exteriorPos[dimIdx] - interiorPos[dimIdx];
244  distSquared += tmp * tmp;
245  }
246 
247  // divide the gradient by the squared distance between the centers of the
248  // sub-control volumes: the gradient is the normalized directional vector between
249  // the two centers times the ratio of the difference of the values and their
250  // distance, i.e., d/abs(d) * delta y / abs(d) = d*delta y / abs(d)^2.
251  for (unsigned dimIdx = 0; dimIdx < dimWorld; ++dimIdx) {
252  const Scalar tmp = exteriorPos[dimIdx] - interiorPos[dimIdx];
253  quantityGrad[dimIdx] = deltay *( tmp / distSquared);
254  }
255  }
256 
271  template <class QuantityCallback>
272  auto calculateBoundaryValue(const ElementContext&,
273  unsigned,
274  const QuantityCallback& quantityCallback)
275  -> decltype(quantityCallback.boundaryValue())
276  { return quantityCallback.boundaryValue(); }
277 
293  template <class QuantityCallback>
294  void calculateBoundaryGradient(EvalDimVector& quantityGrad,
295  const ElementContext& elemCtx,
296  unsigned faceIdx,
297  const QuantityCallback& quantityCallback) const
298  {
299  const auto& stencil = elemCtx.stencil(/*timeIdx=*/0);
300  const auto& face = stencil.boundaryFace(faceIdx);
301 
302  Evaluation deltay;
303  if (face.interiorIndex() == elemCtx.focusDofIndex()) {
304  deltay = quantityCallback.boundaryValue() - quantityCallback(face.interiorIndex());
305  }
306  else {
307  deltay = getValue(quantityCallback.boundaryValue()) -
308  getValue(quantityCallback(face.interiorIndex()));
309  }
310 
311  const auto& boundaryFacePos = face.integrationPos();
312  const auto& interiorPos = stencil.subControlVolume(face.interiorIndex()).center();
313 
314  Scalar distSquared = 0;
315  for (unsigned dimIdx = 0; dimIdx < dimWorld; ++dimIdx) {
316  const Scalar tmp = boundaryFacePos[dimIdx] - interiorPos[dimIdx];
317  distSquared += tmp * tmp;
318  }
319 
320  // divide the gradient by the squared distance between the center of the
321  // sub-control and the center of the boundary face: the gradient is the
322  // normalized directional vector between the two centers times the ratio of the
323  // difference of the values and their distance, i.e., d/abs(d) * deltay / abs(d)
324  // = d*deltay / abs(d)^2.
325  for (unsigned dimIdx = 0; dimIdx < dimWorld; ++dimIdx) {
326  const Scalar tmp = boundaryFacePos[dimIdx] - interiorPos[dimIdx];
327  quantityGrad[dimIdx] = deltay * (tmp / distSquared);
328  }
329  }
330 
331 private:
332  void computeDistances_(Scalar& interiorDistance,
333  Scalar& exteriorDistance,
334  const ElementContext& elemCtx,
335  unsigned fapIdx) const
336  {
337  const auto& stencil = elemCtx.stencil(/*timeIdx=*/0);
338  const auto& face = stencil.interiorFace(fapIdx);
339 
340  // calculate the distances of the position of the interior and of the exterior
341  // finite volume to the position of the integration point.
342  const auto& normal = face.normal();
343  const auto i = face.interiorIndex();
344  const auto j = face.exteriorIndex();
345  const auto& interiorPos = stencil.subControlVolume(i).globalPos();
346  const auto& exteriorPos = stencil.subControlVolume(j).globalPos();
347  const auto& integrationPos = face.integrationPos();
348 
349  interiorDistance = 0.0;
350  exteriorDistance = 0.0;
351  for (unsigned dimIdx = 0; dimIdx < dimWorld; ++dimIdx) {
352  interiorDistance += (interiorPos[dimIdx] - integrationPos[dimIdx]) * normal[dimIdx];
353  exteriorDistance += (exteriorPos[dimIdx] - integrationPos[dimIdx]) * normal[dimIdx];
354  }
355 
356  interiorDistance = std::sqrt(std::abs(interiorDistance));
357  exteriorDistance = std::sqrt(std::abs(exteriorDistance));
358  }
359 };
360 
361 } // namespace Opm
362 
363 #endif
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:215
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:233
This class calculates gradients of arbitrary quantities at flux integration points using the two-poin...
Definition: fvbasegradientcalculator.hh:51
The base class for the element-centered finite-volume discretization scheme.
Definition: fvbasegradientcalculator.hh:42
auto calculateVectorValue(const ElementContext &elemCtx, unsigned fapIdx, const QuantityCallback &quantityCallback) const -> std::remove_reference_t< decltype(quantityCallback.operator()(0))>
Calculates the value of an arbitrary vectorial quantity at any interior flux approximation point...
Definition: fvbasegradientcalculator.hh:149
static void registerParameters()
Register all run-time parameters for the gradient calculator of the base class of the discretization...
Definition: fvbasegradientcalculator.hh:74
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:272
This file contains a set of helper functions used by VFPProd / VFPInj.
Definition: blackoilbioeffectsmodules.hh:45
auto calculateScalarValue(const ElementContext &elemCtx, unsigned fapIdx, const QuantityCallback &quantityCallback) const -> std::remove_reference_t< decltype(quantityCallback.operator()(0))>
Calculates the value of an arbitrary scalar quantity at any interior flux approximation point...
Definition: fvbasegradientcalculator.hh:100
Declare the properties used by the infrastructure code of the finite volume discretizations.
void prepare(const ElementContext &, unsigned)
Precomputes the common values to calculate gradients and values of quantities at every interior flux ...
Definition: fvbasegradientcalculator.hh:85
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:294
Defines a type tags and some fundamental properties all models.