GEOS
SimpleInnerProduct.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_SIMPLEINNERPRODUCT_HPP_
21 #define GEOS_FINITEVOLUME_MIMETICINNERPRODUCTS_SIMPLEINNERPRODUCT_HPP_
22 
26 
27 namespace geos
28 {
29 namespace mimeticInnerProduct
30 {
31 
38 {
39 public:
40 
55  template< localIndex NF >
57  static void
59  arrayView1d< real64 const > const & transMultiplier,
60  ArrayOfArraysView< localIndex const > const & faceToNodes,
61  arraySlice1d< localIndex const > const & elemToFaces,
62  arraySlice1d< real64 const > const & elemCenter,
63  real64 const & elemVolume,
64  real64 const (&elemPerm)[ 3 ],
65  real64 const & lengthTolerance,
66  arraySlice2d< real64 > const & transMatrix );
67 
81  template< localIndex NF >
83  static void
85  ArrayOfArraysView< localIndex const > const & faceToNodes,
86  arraySlice1d< localIndex const > const & elemToFaces,
87  arraySlice1d< real64 const > const & elemCenter,
88  real64 const & elemVolume,
89  real64 const (&elemPerm)[ 3 ],
90  real64 const & lengthTolerance,
91  arraySlice2d< real64 > const & M );
92 };
93 
94 template< localIndex NF >
96 void
98  arrayView1d< real64 const > const & transMultiplier,
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 & transMatrix )
106 {
107  real64 const areaTolerance = lengthTolerance * lengthTolerance;
108  real64 const weightToleranceInv = 1e30 / lengthTolerance;
109 
110  real64 cellToFaceMat[ NF ][ 3 ] = {{ 0 }};
111  real64 normalsMat[ NF ][ 3 ] = {{ 0 }};
112  real64 permMat[ 3 ][ 3 ] = {{ 0 }};
113 
114  real64 work_dimByNumFaces[ 3 ][ NF ] = {{ 0 }};
115  real64 worka_numFacesByNumFaces[ NF ][ NF ] = {{ 0 }};
116  real64 workb_numFacesByNumFaces[ NF ][ NF ] = {{ 0 }};
117  real64 workc_numFacesByNumFaces[ NF ][ NF ] = {{ 0 }};
118 
119  real64 tpTransInv[ NF ] = { 0.0 };
120 
121  real64 q0[ NF ], q1[ NF ], q2[ NF ];
122  real64 faceArea[ NF ];
123 
124 
125  // 0) assemble full coefficient tensor from principal axis/components
126  MimeticInnerProductHelpers::makeFullTensor( elemPerm, permMat );
127 
128  // 1) fill the matrices cellToFaceMat and normalsMat row by row
129  for( localIndex ifaceLoc = 0; ifaceLoc < NF; ++ifaceLoc )
130  {
131  real64 faceCenter[ 3 ], faceNormal[ 3 ], cellToFaceVec[ 3 ];
132  // compute the face geometry data: center, normal, vector from cell center to face center
133  faceArea[ ifaceLoc ] =
134  computationalGeometry::centroid_3DPolygon( faceToNodes[elemToFaces[ifaceLoc]],
135  nodePosition,
136  faceCenter,
137  faceNormal,
138  areaTolerance );
139 
140  MimeticInnerProductHelpers::computeCellToFacetVector( cellToFaceVec, faceCenter, elemCenter );
141  MimeticInnerProductHelpers::orientNormalOutward( cellToFaceVec, faceNormal );
142 
143  q0[ ifaceLoc ] = faceArea[ ifaceLoc ] * cellToFaceVec[ 0 ];
144  q1[ ifaceLoc ] = faceArea[ ifaceLoc ] * cellToFaceVec[ 1 ];
145  q2[ ifaceLoc ] = faceArea[ ifaceLoc ] * cellToFaceVec[ 2 ];
146 
147  // the two-point transmissibility is computed to computed here because it is needed
148  // in the implementation of the transmissibility multiplier (see below)
149  // TODO: see what it would take to bring the (harmonically averaged) two-point trans here
150  real64 diagEntry = 0.0;
151  MimeticInnerProductHelpers::computeInvTPFATransWithMultiplier< NF >( elemPerm,
152  faceNormal,
153  faceArea[ifaceLoc],
154  transMultiplier[elemToFaces[ifaceLoc]],
155  weightToleranceInv,
156  cellToFaceVec,
157  diagEntry );
158  tpTransInv[ifaceLoc] = diagEntry;
159 
160  LvArray::tensorOps::scale< 3 >( faceNormal, faceArea[ ifaceLoc ] );
161  normalsMat[ ifaceLoc ][ 0 ] = faceNormal[ 0 ];
162  normalsMat[ ifaceLoc ][ 1 ] = faceNormal[ 1 ];
163  normalsMat[ ifaceLoc ][ 2 ] = faceNormal[ 2 ];
164 
165  }
166 
167  // 2) compute the stabilization coefficient
168  real64 const tParam = 2 * LvArray::tensorOps::trace< 3 >( permMat );
169 
170  // 3) compute N K N'
171  LvArray::tensorOps::Rij_eq_AikBjk< 3, NF, 3 >( work_dimByNumFaces,
172  permMat,
173  normalsMat );
174  LvArray::tensorOps::Rij_eq_AikBkj< NF, NF, 3 >( transMatrix,
175  normalsMat,
176  work_dimByNumFaces );
177 
178  // 4) compute the orthonormalization of the matrix cellToFaceVec
179  MimeticInnerProductHelpers::orthonormalize< NF >( q0, q1, q2, cellToFaceMat );
180 
181  // 5) compute P_Q = I - QQ'
182  // note: we compute -P_Q here
183  LvArray::tensorOps::addIdentity< NF >( worka_numFacesByNumFaces, -1 );
184  LvArray::tensorOps::Rij_add_AikAjk< NF, 3 >( worka_numFacesByNumFaces,
185  cellToFaceMat );
186 
187  // 6) compute D P_Q D where D = diag( faceArea )
188  // 7) compute T = ( N K N' + t D P_Q D ) / elemVolume
189  for( localIndex i = 0; i < NF; ++i )
190  {
191  workb_numFacesByNumFaces[ i ][ i ] = faceArea[ i ];
192  }
193 
194  LvArray::tensorOps::Rij_eq_AikBkj< NF, NF, NF >( workc_numFacesByNumFaces,
195  workb_numFacesByNumFaces,
196  worka_numFacesByNumFaces );
197 
198 
199  LvArray::tensorOps::scale< NF, NF >( transMatrix, 1 / elemVolume );
200  LvArray::tensorOps::scale< NF, NF >( workc_numFacesByNumFaces, -tParam / elemVolume );
201  LvArray::tensorOps::Rij_add_AikBkj< NF, NF, NF >( transMatrix,
202  workc_numFacesByNumFaces,
203  workb_numFacesByNumFaces );
204 
205  // 7) incorporate the transmissbility multipliers
206  // Ref: Nilsen, H. M., J. R. Natvig, and K.-A Lie.,
207  // "Accurate modeling of faults by multipoint, mimetic, and mixed methods." SPEJ
208 
209  if( !isZero( LvArray::tensorOps::l2NormSquared< NF >( tpTransInv ) ) )
210  {
211  MimeticInnerProductHelpers::computeTransMatrixWithMultipliers< NF >( tpTransInv,
212  transMatrix );
213  }
214 
215 }
216 
217 template< localIndex NF >
219 void
221  ArrayOfArraysView< localIndex const > const & faceToNodes,
222  arraySlice1d< localIndex const > const & elemToFaces,
223  arraySlice1d< real64 const > const & elemCenter,
224  real64 const & elemVolume,
225  real64 const (&elemPerm)[ 3 ],
226  real64 const & lengthTolerance,
227  arraySlice2d< real64 > const & M )
228 {
229  real64 const areaTolerance = lengthTolerance * lengthTolerance;
230 
231  // 1) Compute C, N, A and the consistency part C K^{-1} C^T / volume
232  real64 C[ NF ][ 3 ] = {{ 0 }};
233  real64 N[ NF ][ 3 ] = {{ 0 }};
234  real64 A[ NF ] = { 0.0 };
235  real64 CKCt[ NF ][ NF ] = {{0}};
236 
237  MimeticInnerProductHelpers::computeCellToFaceGeometry< NF >( nodePosition, faceToNodes, elemToFaces,
238  elemCenter, areaTolerance, C, N, A );
239  MimeticInnerProductHelpers::computeConsistencyTerm< NF >( C, elemVolume, elemPerm, CKCt );
240 
241  // 3) Q = orth(N / A)
242  real64 q0[ NF ], q1[ NF ], q2[ NF ];
243  real64 Qmat[ NF ][ 3 ];
244  for( localIndex i = 0; i < NF; ++i )
245  {
246  q0[i] = N[i][0] / A[i];
247  q1[i] = N[i][1] / A[i];
248  q2[i] = N[i][2] / A[i];
249  }
250 
251  MimeticInnerProductHelpers::orthonormalize< NF >( q0, q1, q2, Qmat );
252 
253  // 4) M = CKCt + (v / t) * A^{-1} * ( I - Q Q^T ) * A^{-1}
254  real64 invA[NF];
255  for( localIndex i = 0; i < NF; ++i )
256  {
257  invA[i] = real64( 1 ) / A[i];
258  }
259 
260  // scale = elemVolume / tParam, where tParam = 2 * trace(K)
261  real64 const tParam = real64( 2 ) * (elemPerm[0] + elemPerm[1] + elemPerm[2]);
262  real64 const scale = elemVolume / tParam;
263 
264  for( localIndex i = 0; i < NF; ++i )
265  {
266  real64 const invAiScaled = scale * invA[i];
267 
268  real64 const qi0 = Qmat[i][0];
269  real64 const qi1 = Qmat[i][1];
270  real64 const qi2 = Qmat[i][2];
271 
272  for( localIndex j = i; j < NF; ++j )
273  {
274  // qdot = (Q Q^T)_{ij} = sum_k Qik * Qjk, with k in [0,2]
275  real64 const qdot = qi0*Qmat[j][0] + qi1*Qmat[j][1] + qi2*Qmat[j][2];
276 
277  real64 const u = (i == j ? real64( 1 ) : real64( 0 )) - qdot;
278 
279  real64 const mij = CKCt[i][j] + (invAiScaled * invA[j]) * u;
280 
281  M[i][j] = mij;
282  M[j][i] = mij; // symmetry fill
283  }
284  }
285 }
286 
287 
288 } // end namespace mimeticInnerProduct
289 
290 } // end namespace geos
291 
292 
293 #endif //GEOS_FINITEVOLUME_MIMETICINNERPRODUCTS_SIMPLEINNERPRODUCT_HPP_
#define GEOS_HOST_DEVICE
Marks a host-device function.
Definition: GeosxMacros.hpp:49
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 using the Simple inner product.
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 in a cell using the Simple inner product.
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
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 computeCellToFacetVector(real64(&cellToFacetVec)[3], real64 const (&facetCenter)[3], arraySlice1d< real64 const > const &cellCenter)
Compute the vector from cell center to facet center.