GEOS
MimeticInnerProductHelpers.hpp
Go to the documentation of this file.
1 /*
2  * ------------------------------------------------------------------------------------------------------------
3  * SPDX-License-Identifier: LGPL-2.1-only
4  *
5  * Copyright (c) 2016-2024 Lawrence Livermore National Security LLC
6  * Copyright (c) 2018-2024 TotalEnergies
7  * Copyright (c) 2018-2024 The Board of Trustees of the Leland Stanford Junior University
8  * Copyright (c) 2023-2024 Chevron
9  * Copyright (c) 2019- GEOS/GEOSX Contributors
10  * All rights reserved
11  *
12  * See top level LICENSE, COPYRIGHT, CONTRIBUTORS, NOTICE, and ACKNOWLEDGEMENTS files for details.
13  * ------------------------------------------------------------------------------------------------------------
14  */
15 
20 #ifndef GEOS_FINITEVOLUME_MIMETICINNERPRODUCTS_MIMETICINNERPRODUCTHELPERS_HPP
21 #define GEOS_FINITEVOLUME_MIMETICINNERPRODUCTS_MIMETICINNERPRODUCTHELPERS_HPP
22 
24 
25 namespace geos
26 {
27 namespace mimeticInnerProduct
28 {
29 
35 {
36 
43  static
44  void makeFullTensor( real64 const (&values)[ 3 ],
45  real64 (& result)[ 3 ][ 3 ] )
46  {
47  LvArray::tensorOps::fill< 3, 3 >( result, 0.0 );
48  result[ 0 ][ 0 ] = values[ 0 ];
49  result[ 1 ][ 1 ] = values[ 1 ];
50  result[ 2 ][ 2 ] = values[ 2 ];
51  }
52 
60  static
61  void computeCellToFacetVector( real64 (& cellToFacetVec)[ 3 ],
62  real64 const (&facetCenter)[ 3 ],
63  arraySlice1d< real64 const > const & cellCenter )
64  {
65  LvArray::tensorOps::copy< 3 >( cellToFacetVec, facetCenter );
66  LvArray::tensorOps::subtract< 3 >( cellToFacetVec, cellCenter );
67  }
68 
75  static
76  void orientNormalOutward( real64 const (&cellToFacetVec)[ 3 ],
77  real64 (& faceNormal)[ 3 ] )
78  {
79  if( LvArray::tensorOps::AiBi< 3 >( cellToFacetVec, faceNormal ) < 0.0 )
80  {
81  LvArray::tensorOps::scale< 3 >( faceNormal, -1.0 );
82  }
83  }
84 
98  template< localIndex NF >
100  static
102  ArrayOfArraysView< localIndex const > const & faceToNodes,
103  arraySlice1d< localIndex const > const & elemToFaces,
104  arraySlice1d< real64 const > const & elemCenter,
105  real64 const & areaTolerance,
106  real64 (& C)[ NF ][ 3 ],
107  real64 (& N)[ NF ][ 3 ],
108  real64 (& faceArea)[ NF ] )
109  {
110  for( localIndex ifaceLoc = 0; ifaceLoc < NF; ++ifaceLoc )
111  {
112  real64 faceCenter[ 3 ], faceNormal[ 3 ], cellToFaceVec[ 3 ];
113 
114  faceArea[ifaceLoc] =
115  computationalGeometry::centroid_3DPolygon( faceToNodes[elemToFaces[ifaceLoc]],
116  nodePosition,
117  faceCenter,
118  faceNormal,
119  areaTolerance );
120 
121  computeCellToFacetVector( cellToFaceVec, faceCenter, elemCenter );
122  orientNormalOutward( cellToFaceVec, faceNormal );
123 
124  for( int d = 0; d < 3; ++d )
125  {
126  C[ifaceLoc][d] = cellToFaceVec[d];
127  N[ifaceLoc][d] = faceArea[ifaceLoc] * faceNormal[d];
128  }
129  }
130  }
131 
140  template< localIndex NF >
142  static
143  void computeConsistencyTerm( real64 const (&C)[ NF ][ 3 ],
144  real64 const & elemVolume,
145  real64 const (&elemPerm)[ 3 ],
146  real64 (& CKCt)[ NF ][ NF ] )
147  {
148  // Kinv assumes diagonal K
149  real64 Kinv[ 3 ][ 3 ] = {{ 0 }};
150  for( int d = 0; d < 3; ++d )
151  {
152  Kinv[d][d] = 1.0 / elemPerm[d];
153  }
154 
155  real64 work[ 3 ][ NF ] = {{ 0 }};
156  LvArray::tensorOps::Rij_eq_AikBjk< 3, NF, 3 >( work, Kinv, C );
157  LvArray::tensorOps::Rij_eq_AikBkj< NF, NF, 3 >( CKCt, C, work );
158  LvArray::tensorOps::scale< NF, NF >( CKCt, 1.0 / elemVolume );
159  }
160 
169  template< localIndex NF >
171  static
172  void orthonormalize( real64 (& q0)[ NF ],
173  real64 (& q1)[ NF ],
174  real64 (& q2)[ NF ],
175  real64 (& cellToFaceMat)[ NF ][ 3 ] )
176  {
177  // modified Gram-Schmidt algorithm
178 
179  // q0
180  LvArray::tensorOps::scale< NF >( q0, 1.0/LvArray::tensorOps::l2Norm< NF >( q0 ) );
181 
182  // q1
183  real64 const q0Dotq1 = LvArray::tensorOps::AiBi< NF >( q0, q1 );
184  LvArray::tensorOps::scaledAdd< NF >( q1, q0, -q0Dotq1 );
185  LvArray::tensorOps::scale< NF >( q1, 1.0/LvArray::tensorOps::l2Norm< NF >( q1 ) );
186 
187  // q2
188  real64 const q0Dotq2 = LvArray::tensorOps::AiBi< NF >( q0, q2 );
189  LvArray::tensorOps::scaledAdd< NF >( q2, q0, -q0Dotq2 );
190  real64 const q1Dotq2 = LvArray::tensorOps::AiBi< NF >( q1, q2 );
191  LvArray::tensorOps::scaledAdd< NF >( q2, q1, -q1Dotq2 );
192  LvArray::tensorOps::scale< NF >( q2, 1.0/LvArray::tensorOps::l2Norm< NF >( q2 ) );
193 
194  for( localIndex i = 0; i < NF; ++i )
195  {
196  cellToFaceMat[ i ][ 0 ] = q0[ i ];
197  cellToFaceMat[ i ][ 1 ] = q1[ i ];
198  cellToFaceMat[ i ][ 2 ] = q2[ i ];
199  }
200  }
201 
213  template< localIndex NF >
215  static void
216  computeInvTPFATransWithMultiplier( real64 const (&elemPerm)[ 3 ],
217  real64 const (&faceNormal)[ 3 ],
218  real64 const & faceArea,
219  real64 const & transMult,
220  real64 const & weightToleranceInv,
221  real64 (& cellToFaceVec)[ 3 ],
222  real64 & tpTransInv )
223  {
224  real64 const c2fDistance = LvArray::tensorOps::normalize< 3 >( cellToFaceVec );
225  real64 const mult = transMult;
226  tpTransInv = c2fDistance / faceArea;
227 
228  real64 faceConormal[ 3 ] = { 0.0 };
229  LvArray::tensorOps::hadamardProduct< 3 >( faceConormal, elemPerm, faceNormal );
230  real64 halfWeight = LvArray::tensorOps::AiBi< 3 >( cellToFaceVec, faceConormal );
231  if( halfWeight < 0.0 )
232  {
233  LvArray::tensorOps::hadamardProduct< 3 >( faceConormal, elemPerm, cellToFaceVec );
234  halfWeight = LvArray::tensorOps::AiBi< 3 >( cellToFaceVec, faceConormal );
235  }
236  tpTransInv /= halfWeight;
237  tpTransInv = LvArray::math::min( tpTransInv, weightToleranceInv );
238  tpTransInv *= ( 1.0 - mult ) / mult;
239  }
240 
241 
248  template< localIndex NF >
250  static void
251  computeTransMatrixWithMultipliers( real64 const (&tpTransInv)[ NF ],
252  arraySlice2d< real64 > const & transMatrix )
253  {
254  // the inverse of the pertubed inverse is computed using the Sherman-Morrison formula
255  for( localIndex k = 0; k < NF; ++k )
256  {
257  real64 const mult = LvArray::math::sqrt( tpTransInv[k] );
258  real64 Tmult[ NF ] = { 0.0 };
259  for( localIndex i = 0; i < NF; ++i )
260  {
261  Tmult[i] = transMatrix[k][i] * mult;
262  }
263 
264  real64 const invDenom = 1.0 / ( 1.0 + Tmult[k] * mult );
265  for( localIndex i = 0; i < NF; ++i )
266  {
267  for( localIndex j = 0; j < NF; ++j )
268  {
269  transMatrix[i][j] -= Tmult[i]*Tmult[j]*invDenom;
270  }
271  }
272  }
273  }
274 
275 };
276 
277 } // namespace mimeticInnerProduct
278 
279 } // namespace geos
280 
281 #endif //GEOS_FINITEVOLUME_MIMETICINNERPRODUCTS_MIMETICINNERPRODUCTHELPERS_HPP
#define GEOS_HOST_DEVICE
Marks a host-device function.
Definition: GeosxMacros.hpp:49
LvArray::ArrayOfArraysView< T, INDEX_TYPE const, CONST_SIZES, LvArray::ChaiBuffer > ArrayOfArraysView
View of array of variable-sized arrays. See LvArray::ArrayOfArraysView for details.
Definition: DataTypes.hpp:285
ArraySlice< T, 2, USD > arraySlice2d
Alias for 2D array slice.
Definition: DataTypes.hpp:199
double real64
64-bit floating point type.
Definition: DataTypes.hpp:98
GEOS_LOCALINDEX_TYPE localIndex
Local index type (for indexing objects within an MPI partition).
Definition: DataTypes.hpp:84
ArraySlice< T, 1, USD > arraySlice1d
Alias for 1D array slice.
Definition: DataTypes.hpp:183
ArrayView< T, 2, USD > arrayView2d
Alias for 2D array view.
Definition: DataTypes.hpp:195
Helper struct handling inner product for hybrid finite volume schemes.
static GEOS_HOST_DEVICE void computeInvTPFATransWithMultiplier(real64 const (&elemPerm)[3], real64 const (&faceNormal)[3], real64 const &faceArea, real64 const &transMult, real64 const &weightToleranceInv, real64(&cellToFaceVec)[3], real64 &tpTransInv)
For a given face, compute the TPFA entry incorporating the multiplier.
static GEOS_HOST_DEVICE void makeFullTensor(real64 const (&values)[3], real64(&result)[3][3])
Create a full tensor from an array.
static GEOS_HOST_DEVICE void orientNormalOutward(real64 const (&cellToFacetVec)[3], real64(&faceNormal)[3])
Ensure the facet normal points outward from the cell.
static GEOS_HOST_DEVICE void computeCellToFaceGeometry(arrayView2d< real64 const, nodes::REFERENCE_POSITION_USD > const &nodePosition, ArrayOfArraysView< localIndex const > const &faceToNodes, arraySlice1d< localIndex const > const &elemToFaces, arraySlice1d< real64 const > const &elemCenter, real64 const &areaTolerance, real64(&C)[NF][3], real64(&N)[NF][3], real64(&faceArea)[NF])
In a given element, compute the cell-to-face vectors C, the outward area-weighted face normals N,...
static GEOS_HOST_DEVICE void computeCellToFacetVector(real64(&cellToFacetVec)[3], real64 const (&facetCenter)[3], arraySlice1d< real64 const > const &cellCenter)
Compute the vector from cell center to facet center.
static GEOS_HOST_DEVICE void computeTransMatrixWithMultipliers(real64 const (&tpTransInv)[NF], arraySlice2d< real64 > const &transMatrix)
Incorporate the transmissibility multiplier into the transmissibility matrix.
static GEOS_HOST_DEVICE void orthonormalize(real64(&q0)[NF], real64(&q1)[NF], real64(&q2)[NF], real64(&cellToFaceMat)[NF][3])
Orthonormalize a set of three vectors.
static GEOS_HOST_DEVICE void computeConsistencyTerm(real64 const (&C)[NF][3], real64 const &elemVolume, real64 const (&elemPerm)[3], real64(&CKCt)[NF][NF])
Compute the consistency term CKCt = C K^{-1} C^T / elemVolume of the inner product matrix.