GEOSX
CellElementStencilTPFA.hpp
Go to the documentation of this file.
1 /*
2  * ------------------------------------------------------------------------------------------------------------
3  * SPDX-License-Identifier: LGPL-2.1-only
4  *
5  * Copyright (c) 2018-2020 Lawrence Livermore National Security LLC
6  * Copyright (c) 2018-2020 The Board of Trustees of the Leland Stanford Junior University
7  * Copyright (c) 2018-2020 TotalEnergies
8  * Copyright (c) 2019- GEOSX Contributors
9  * All rights reserved
10  *
11  * See top level LICENSE, COPYRIGHT, CONTRIBUTORS, NOTICE, and ACKNOWLEDGEMENTS files for details.
12  * ------------------------------------------------------------------------------------------------------------
13  */
14 
19 #ifndef GEOS_FINITEVOLUME_CELLELEMENTSTENCILTPFA_HPP_
20 #define GEOS_FINITEVOLUME_CELLELEMENTSTENCILTPFA_HPP_
21 
22 #include "StencilBase.hpp"
23 
24 namespace geos
25 {
26 
30 class CellElementStencilTPFAWrapper : public StencilWrapperBase< TwoPointStencilTraits >
31 {
32 public:
33 
35  template< typename VIEWTYPE >
37 
49  CellElementStencilTPFAWrapper( IndexContainerType const & elementRegionIndices,
50  IndexContainerType const & elementSubRegionIndices,
51  IndexContainerType const & elementIndices,
52  WeightContainerType const & weights,
53  arrayView2d< real64 > const & faceNormal,
54  arrayView3d< real64 > const & cellToFaceVec,
55  arrayView1d< real64 > const & transMultiplier,
56  arrayView1d< real64 > const & geometricStabilizationCoef );
57 
67  void computeWeights( localIndex const iconn,
68  CoefficientAccessor< arrayView3d< real64 const > > const & coefficient,
69  CoefficientAccessor< arrayView3d< real64 const > > const & dCoeff_dVar,
70  real64 ( &weight )[1][2],
71  real64 ( &dWeight_dVar )[1][2] ) const;
72 
82  void computeWeights( localIndex iconn,
83  real64 ( &weight )[1][2],
84  real64 ( &dWeight_dVar )[1][2] ) const;
85 
93  real64 ( &stabilizationWeight )[1][2] ) const;
94 
99  localIndex size() const
100  {
101  return m_elementRegionIndices.size( 0 );
102  }
103 
111  localIndex stencilSize( localIndex const index ) const
112  {
113  GEOS_UNUSED_VAR( index );
114  return maxStencilSize;
115  }
116 
124  localIndex numPointsInFlux( localIndex const index ) const
125  {
126  GEOS_UNUSED_VAR( index );
127  return maxNumPointsInFlux;
128  }
129 
130 private:
131 
132  arrayView2d< real64 > m_faceNormal;
133  arrayView3d< real64 > m_cellToFaceVec;
134  arrayView1d< real64 > m_transMultiplier;
135  arrayView1d< real64 > m_geometricStabilizationCoef;
136 };
137 
138 
144 class CellElementStencilTPFA final : public StencilBase< TwoPointStencilTraits, CellElementStencilTPFA >
145 {
146 public:
147 
152 
153  virtual void add( localIndex const numPts,
154  localIndex const * const elementRegionIndices,
155  localIndex const * const elementSubRegionIndices,
156  localIndex const * const elementIndices,
157  real64 const * const weights,
158  localIndex const connectorIndex ) override;
159 
167  void addVectors( real64 const & transMultiplier,
168  real64 const & geometricStabilizationCoef,
169  real64 const (&faceNormal)[3],
170  real64 const (&cellToFaceVec)[2][3] );
171 
176  virtual localIndex size() const override
177  { return m_elementRegionIndices.size( 0 ); }
178 
183  virtual void reserve( localIndex const size ) override;
184 
190  constexpr localIndex stencilSize( localIndex index ) const
191  {
192  GEOS_UNUSED_VAR( index );
193  return maxStencilSize;
194  }
195 
198 
204 
205 private:
206 
207  array2d< real64 > m_faceNormal;
208  array3d< real64 > m_cellToFaceVec;
209  array1d< real64 > m_transMultiplier;
210  array1d< real64 > m_geometricStabilizationCoef;
211 };
212 
214 inline void
216  computeWeights( localIndex const iconn,
217  CoefficientAccessor< arrayView3d< real64 const > > const & coefficient,
218  CoefficientAccessor< arrayView3d< real64 const > > const & dCoeff_dVar,
219  real64 (& weight)[1][2],
220  real64 (& dWeight_dVar )[1][2] ) const
221 {
222  real64 halfWeight[2];
223  real64 dHalfWeight_dVar[2];
224 
225  // real64 const tolerance = 1e-30 * lengthTolerance; // TODO: choice of constant based on physics?
226 
227  for( localIndex i = 0; i < 2; ++i )
228  {
229  localIndex const er = m_elementRegionIndices[iconn][i];
230  localIndex const esr = m_elementSubRegionIndices[iconn][i];
231  localIndex const ei = m_elementIndices[iconn][i];
232 
233  halfWeight[i] = m_weights[iconn][i];
234  dHalfWeight_dVar[i] = m_weights[iconn][i];
235 
236  // Proper computation
237  real64 faceNormal[3];
238  LvArray::tensorOps::copy< 3 >( faceNormal, m_faceNormal[iconn] );
239  if( LvArray::tensorOps::AiBi< 3 >( m_cellToFaceVec[iconn][i], faceNormal ) < 0.0 )
240  {
241  LvArray::tensorOps::scale< 3 >( faceNormal, -1 );
242  }
243 
244  real64 faceConormal[3];
245  real64 dFaceConormal_dVar[3];
246  LvArray::tensorOps::hadamardProduct< 3 >( faceConormal, coefficient[er][esr][ei][0], faceNormal );
247  LvArray::tensorOps::hadamardProduct< 3 >( dFaceConormal_dVar, dCoeff_dVar[er][esr][ei][0], faceNormal );
248  halfWeight[i] *= LvArray::tensorOps::AiBi< 3 >( m_cellToFaceVec[iconn][i], faceConormal );
249  dHalfWeight_dVar[i] *= LvArray::tensorOps::AiBi< 3 >( m_cellToFaceVec[iconn][i], dFaceConormal_dVar );
250 
251  // correct negative weight issue arising from non-K-orthogonal grids
252  if( halfWeight[i] < 0.0 )
253  {
254  LvArray::tensorOps::hadamardProduct< 3 >( faceConormal,
255  coefficient[er][esr][ei][0],
256  m_cellToFaceVec[iconn][i] );
257  LvArray::tensorOps::hadamardProduct< 3 >( dFaceConormal_dVar,
258  dCoeff_dVar[er][esr][ei][0],
259  m_cellToFaceVec[iconn][i] );
260  halfWeight[i] = m_weights[iconn][i];
261  dHalfWeight_dVar[i] = m_weights[iconn][i];
262  halfWeight[i] *= LvArray::tensorOps::AiBi< 3 >( m_cellToFaceVec[iconn][i], faceConormal );
263  dHalfWeight_dVar[i] *= LvArray::tensorOps::AiBi< 3 >( m_cellToFaceVec[iconn][i], dFaceConormal_dVar );
264  }
265  }
266 
267  // Do harmonic and arithmetic averaging
268  real64 const product = halfWeight[0]*halfWeight[1];
269  real64 const sum = halfWeight[0]+halfWeight[1];
270 
271  real64 const harmonicWeight = sum > 0 ? product / sum : 0.0;
272  real64 const arithmeticWeight = sum / 2;
273 
274  real64 dHarmonicWeight_dVar[2];
275  real64 dArithmeticWeight_dVar[2];
276 
277  dHarmonicWeight_dVar[0] = sum > 0 ? (dHalfWeight_dVar[0]*sum*halfWeight[1] - dHalfWeight_dVar[0]*halfWeight[0]*halfWeight[1]) / ( sum*sum ) : 0.0;
278  dHarmonicWeight_dVar[1] = sum > 0 ? (dHalfWeight_dVar[1]*sum*halfWeight[0] - dHalfWeight_dVar[1]*halfWeight[1]*halfWeight[0]) / ( sum*sum ) : 0.0;
279 
280  dArithmeticWeight_dVar[0] = dHalfWeight_dVar[0] / 2;
281  dArithmeticWeight_dVar[1] = dHalfWeight_dVar[1] / 2;
282 
283  real64 const meanPermCoeff = 1.0; //TODO make it a member if it is really necessary
284 
285  real64 const value = meanPermCoeff * harmonicWeight + (1 - meanPermCoeff) * arithmeticWeight;
286  for( localIndex ke = 0; ke < 2; ++ke )
287  {
288  weight[0][ke] = m_transMultiplier[iconn] * value * (ke == 0 ? 1 : -1);
289 
290  real64 const dValue_dVar = meanPermCoeff * dHarmonicWeight_dVar[ke] + (1 - meanPermCoeff) * dArithmeticWeight_dVar[ke];
291  dWeight_dVar[0][ke] = m_transMultiplier[iconn] * dValue_dVar;
292  }
293 }
294 
296 inline void
299  real64 (& weight)[1][2],
300  real64 (& dWeight_dVar )[1][2] ) const
301 {
302  real64 halfWeight[2];
303 
304  // real64 const tolerance = 1e-30 * lengthTolerance; // TODO: choice of constant based on physics?
305 
306  for( localIndex i =0; i<2; i++ )
307  {
308  halfWeight[i] = m_weights[iconn][i];
309 
310  // Proper computation
311  real64 faceNormal[3];
312 
313  LvArray::tensorOps::copy< 3 >( faceNormal, m_faceNormal[iconn] );
314 
315  if( LvArray::tensorOps::AiBi< 3 >( m_cellToFaceVec[iconn][i], faceNormal ) < 0.0 )
316  {
317  LvArray::tensorOps::scale< 3 >( faceNormal, -1 );
318  }
319 
320  halfWeight[i] *= LvArray::tensorOps::AiBi< 3 >( m_cellToFaceVec[iconn][i], faceNormal );
321 
322  // correct negative weight issue arising from non-K-orthogonal grids
323  if( halfWeight[i] < 0.0 )
324  {
325  halfWeight[i] = m_weights[iconn][i];
326  halfWeight[i] *= LvArray::tensorOps::AiBi< 3 >( m_cellToFaceVec[iconn][i], m_cellToFaceVec[iconn][i] );
327  }
328  }
329 
330  // Do harmonic and arithmetic averaging
331  real64 const product = halfWeight[0]*halfWeight[1];
332  real64 const sum = halfWeight[0]+halfWeight[1];
333 
334  real64 const harmonicWeight = sum > 0 ? product / sum : 0.0;
335  real64 const arithmeticWeight = sum / 2;
336 
337  real64 const meanPermCoeff = 1.0; //TODO make it a member if it is really necessary
338 
339  real64 const value = meanPermCoeff * harmonicWeight + (1 - meanPermCoeff) * arithmeticWeight;
340  for( localIndex ke = 0; ke < 2; ++ke )
341  {
342  weight[0][ke] = m_transMultiplier[iconn] * value * (ke == 0 ? 1 : -1);
343  }
344 
345  dWeight_dVar[0][0] = 0.0;
346  dWeight_dVar[0][1] = 0.0;
347 }
348 
350 inline void
353  real64 ( & stabilizationWeight )[1][2] ) const
354 {
355  stabilizationWeight[0][0] = m_geometricStabilizationCoef[iconn];
356  stabilizationWeight[0][1] = -m_geometricStabilizationCoef[iconn];
357 }
358 
359 
360 } /* namespace geos */
361 
362 #endif /* GEOS_FINITEVOLUME_CELLELEMENTSTENCILTPFA_HPP_ */
#define GEOS_HOST_DEVICE
Marks a host-device function.
Definition: GeosxMacros.hpp:48
#define GEOS_UNUSED_VAR(...)
Mark an unused variable and silence compiler warnings.
Definition: GeosxMacros.hpp:83
#define GEOS_FORCE_INLINE
Marks a function or lambda for inlining.
Definition: GeosxMacros.hpp:50
virtual void add(localIndex const numPts, localIndex const *const elementRegionIndices, localIndex const *const elementSubRegionIndices, localIndex const *const elementIndices, real64 const *const weights, localIndex const connectorIndex) override
Add an entry to the stencil.
virtual localIndex size() const override
Return the stencil size.
constexpr localIndex stencilSize(localIndex index) const
Give the number of points in a stencil entry.
void addVectors(real64 const &transMultiplier, real64 const &geometricStabilizationCoef, real64 const (&faceNormal)[3], real64 const (&cellToFaceVec)[2][3])
Add the vectors need to compute the transmissiblity to the Stencil.
KernelWrapper createKernelWrapper() const
Create an update kernel wrapper.
CellElementStencilTPFA()
Default constructor.
virtual void reserve(localIndex const size) override
Reserve the size of the stencil.
ElementRegionManager::ElementViewConst< VIEWTYPE > CoefficientAccessor
Coefficient view accessory type.
GEOS_HOST_DEVICE GEOS_FORCE_INLINE localIndex stencilSize(localIndex const index) const
Give the number of points in a stencil entry.
GEOS_HOST_DEVICE void computeWeights(localIndex const iconn, CoefficientAccessor< arrayView3d< real64 const > > const &coefficient, CoefficientAccessor< arrayView3d< real64 const > > const &dCoeff_dVar, real64(&weight)[1][2], real64(&dWeight_dVar)[1][2]) const
Compute weights and derivatives w.r.t to one variable.
localIndex size() const
Give the number of stencil entries.
CellElementStencilTPFAWrapper(IndexContainerType const &elementRegionIndices, IndexContainerType const &elementSubRegionIndices, IndexContainerType const &elementIndices, WeightContainerType const &weights, arrayView2d< real64 > const &faceNormal, arrayView3d< real64 > const &cellToFaceVec, arrayView1d< real64 > const &transMultiplier, arrayView1d< real64 > const &geometricStabilizationCoef)
Constructor.
GEOS_HOST_DEVICE GEOS_FORCE_INLINE localIndex numPointsInFlux(localIndex const index) const
Give the number of points between which the flux is.
GEOS_HOST_DEVICE void computeStabilizationWeights(localIndex iconn, real64(&stabilizationWeight)[1][2]) const
Compute the stabilization weights.
typename ElementViewAccessor< VIEWTYPE >::NestedViewTypeConst ElementViewConst
The ElementViewAccessor at the ElementRegionManager level is the type resulting from ElementViewAcces...
Provides management of the interior stencil points when using Two-Point flux approximation.
TRAITS::IndexContainerType m_elementRegionIndices
The container for the element region indices for each point in each stencil.
TRAITS::IndexContainerViewConstType m_elementRegionIndices
The container for the element region indices for each point in each stencil.
TRAITS::IndexContainerViewConstType m_elementSubRegionIndices
The container for the element sub region indices for each point in each stencil.
TRAITS::WeightContainerViewType m_weights
The container for the weights for each point in each stencil.
TRAITS::IndexContainerViewConstType m_elementIndices
The container for the element indices for each point in each stencil.
ArrayView< T, 1 > arrayView1d
Alias for 1D array view.
Definition: DataTypes.hpp:220
Array< T, 2, PERMUTATION > array2d
Alias for 2D array.
Definition: DataTypes.hpp:232
Array< T, 3, PERMUTATION > array3d
Alias for 3D array.
Definition: DataTypes.hpp:248
double real64
64-bit floating point type.
Definition: DataTypes.hpp:139
ArrayView< T, 2, USD > arrayView2d
Alias for 2D array view.
Definition: DataTypes.hpp:236
GEOSX_LOCALINDEX_TYPE localIndex
Local index type (for indexing objects within an MPI partition).
Definition: DataTypes.hpp:125
Array< T, 1 > array1d
Alias for 1D array.
Definition: DataTypes.hpp:216
ArrayView< T, 3, USD > arrayView3d
Alias for 3D array view.
Definition: DataTypes.hpp:252
CONTAINER< localIndex > IndexContainerType
The array type that will be used to store the indices of the stencil contributors.
Definition: StencilBase.hpp:43
static constexpr localIndex maxStencilSize
Maximum number of points in a stencil.
Definition: StencilBase.hpp:61
CONTAINER< real64 > WeightContainerType
The array type that is used to store the weights of the stencil contributors.
Definition: StencilBase.hpp:49
static constexpr localIndex maxNumPointsInFlux
Maximum number of points the flux.
Definition: StencilBase.hpp:58