GEOS
RTInnerProduct.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_RTINNERPRODUCT_HPP_
21 #define GEOS_FINITEVOLUME_MIMETICINNERPRODUCTS_RTINNERPRODUCT_HPP_
22 
25 
26 namespace geos
27 {
28 namespace mimeticInnerProduct
29 {
30 
38 {
39 public:
40 
54  template< localIndex NF >
56  static void
58  arrayView1d< real64 const > const & transMultiplier,
59  ArrayOfArraysView< localIndex const > const & faceToNodes,
60  arraySlice1d< localIndex const > const & elemToFaces,
61  arraySlice1d< real64 const > const & elemCenter,
62  real64 const & elemVolume,
63  real64 const (&elemPerm)[ 3 ],
64  real64 const & lengthTolerance,
65  arraySlice2d< real64 > const & transMatrix );
66 
82  template< localIndex NF >
84  static void
86  ArrayOfArraysView< localIndex const > const & faceToNodes,
87  arraySlice1d< localIndex const > const & elemToFaces,
88  arraySlice1d< real64 const > const & elemCenter,
89  real64 const & elemVolume,
90  real64 const (&elemPerm)[ 3 ],
91  real64 const & lengthTolerance,
92  arraySlice2d< real64 > const & M );
93 };
94 
95 template< localIndex NF >
97 void
99  ArrayOfArraysView< localIndex const > const & faceToNodes,
100  arraySlice1d< localIndex const > const & elemToFaces,
101  arraySlice1d< real64 const > const & elemCenter,
102  real64 const & elemVolume,
103  real64 const (&elemPerm)[ 3 ],
104  real64 const & lengthTolerance,
105  arraySlice2d< real64 > const & M )
106 {
107  real64 const areaTolerance = lengthTolerance * lengthTolerance;
108 
109  // 1) compute C, N, face areas and the consistency term M1 = C K^{-1} C^T / V
110  real64 C[ NF ][ 3 ] = {{ 0 }};
111  real64 N[ NF ][ 3 ] = {{ 0 }};
112  real64 faceArea[ NF ] = { 0.0 };
113  real64 M1[ NF ][ NF ] = {{ 0 }};
114 
115  MimeticInnerProductHelpers::computeCellToFaceGeometry< NF >( nodePosition, faceToNodes, elemToFaces,
116  elemCenter, areaTolerance, C, N, faceArea );
117  MimeticInnerProductHelpers::computeConsistencyTerm< NF >( C, elemVolume, elemPerm, M1 );
118 
119  // 2) build Q from the K-weighted area normals N K, so I - Q Q^T projects onto ker( (N K)^T )
120  real64 q0[ NF ], q1[ NF ], q2[ NF ];
121  real64 Qmat[ NF ][ 3 ];
122  for( localIndex i = 0; i < NF; ++i )
123  {
124  q0[i] = N[i][0] * elemPerm[0];
125  q1[i] = N[i][1] * elemPerm[1];
126  q2[i] = N[i][2] * elemPerm[2];
127  }
128  MimeticInnerProductHelpers::orthonormalize< NF >( q0, q1, q2, Qmat );
129 
130  // 3) compute P = I - Q Q^T
131  real64 P[ NF ][ NF ] = {{ 0 }};
132  LvArray::tensorOps::addIdentity< NF >( P, -1.0 );
133  LvArray::tensorOps::Rij_add_AikAjk< NF, 3 >( P, Qmat );
134  LvArray::tensorOps::scale< NF, NF >( P, -1.0 );
135 
136  // 4) s = tr(M1)/(d+2), the unique RT0-matching stabilization scale on simplices (d = 3)
137  real64 const s = LvArray::tensorOps::trace< NF >( M1 ) / 5.0;
138 
139  // 5) assemble M = M1 + s P
140  for( localIndex i = 0; i < NF; ++i )
141  {
142  for( localIndex j = 0; j < NF; ++j )
143  {
144  M[i][j] = M1[i][j] + s * P[i][j];
145  }
146  }
147 }
148 
149 template< localIndex NF >
151 void
153  arrayView1d< real64 const > const & transMultiplier,
154  ArrayOfArraysView< localIndex const > const & faceToNodes,
155  arraySlice1d< localIndex const > const & elemToFaces,
156  arraySlice1d< real64 const > const & elemCenter,
157  real64 const & elemVolume,
158  real64 const (&elemPerm)[ 3 ],
159  real64 const & lengthTolerance,
160  arraySlice2d< real64 > const & transMatrix )
161 {
162  // 1) assemble M
163  computeM< NF >( nodePosition, faceToNodes, elemToFaces, elemCenter,
164  elemVolume, elemPerm, lengthTolerance, transMatrix );
165 
166  // 2) W = M^{-1} by Gauss-Jordan on the SPD local matrix
167  real64 A[ NF ][ NF ];
168  real64 W[ NF ][ NF ] = {{ 0 }};
169  for( localIndex i = 0; i < NF; ++i )
170  {
171  W[i][i] = 1.0;
172  for( localIndex j = 0; j < NF; ++j )
173  {
174  A[i][j] = transMatrix[i][j];
175  }
176  }
177  // M is symmetric positive definite: without pivoting, every pivot is bounded below by its smallest eigenvalue
178  for( localIndex k = 0; k < NF; ++k )
179  {
180  GEOS_ASSERT_GT( A[k][k], 0.0 );
181  real64 const invPivot = 1.0 / A[k][k];
182  for( localIndex j = 0; j < NF; ++j )
183  {
184  A[k][j] *= invPivot;
185  W[k][j] *= invPivot;
186  }
187  for( localIndex i = 0; i < NF; ++i )
188  {
189  if( i == k )
190  continue;
191  real64 const factor = A[i][k];
192  for( localIndex j = 0; j < NF; ++j )
193  {
194  A[i][j] -= factor * A[k][j];
195  W[i][j] -= factor * W[k][j];
196  }
197  }
198  }
199 
200  // 3) apply the face transmissibility multipliers symmetrically
201  for( localIndex i = 0; i < NF; ++i )
202  {
203  for( localIndex j = 0; j < NF; ++j )
204  {
205  transMatrix[i][j] = W[i][j] * LvArray::math::sqrt( transMultiplier[elemToFaces[i]] * transMultiplier[elemToFaces[j]] );
206  }
207  }
208 }
209 
210 } // end namespace mimeticInnerProduct
211 
212 } // end namespace geos
213 
214 #endif //GEOS_FINITEVOLUME_MIMETICINNERPRODUCTS_RTINNERPRODUCT_HPP_
#define GEOS_HOST_DEVICE
Marks a host-device function.
Definition: GeosxMacros.hpp:49
#define GEOS_ASSERT_GT(lhs, rhs)
Assert that one value compares greater than the other in debug builds.
Definition: Logger.hpp:889
static GEOS_HOST_DEVICE void computeM(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 &elemVolume, real64 const (&elemPerm)[3], real64 const &lengthTolerance, arraySlice2d< real64 > const &M)
Compute the mimetic inner product matrix M in a given element.
static GEOS_HOST_DEVICE void compute(arrayView2d< real64 const, nodes::REFERENCE_POSITION_USD > const &nodePosition, arrayView1d< real64 const > const &transMultiplier, ArrayOfArraysView< localIndex const > const &faceToNodes, arraySlice1d< localIndex const > const &elemToFaces, arraySlice1d< real64 const > const &elemCenter, real64 const &elemVolume, real64 const (&elemPerm)[3], real64 const &lengthTolerance, arraySlice2d< real64 > const &transMatrix)
In a given element, recompute the transmissibility matrix as the exact inverse of the RT inner produc...
ArrayView< T, 1 > arrayView1d
Alias for 1D array view.
Definition: DataTypes.hpp:179
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