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 
68 };
69 
70 template< localIndex NF >
72 void
74  arrayView1d< real64 const > const & transMultiplier,
75  ArrayOfArraysView< localIndex const > const & faceToNodes,
76  arraySlice1d< localIndex const > const & elemToFaces,
77  arraySlice1d< real64 const > const & elemCenter,
78  real64 const & elemVolume,
79  real64 const (&elemPerm)[ 3 ],
80  real64 const & lengthTolerance,
81  arraySlice2d< real64 > const & transMatrix )
82 {
83  real64 const areaTolerance = lengthTolerance * lengthTolerance;
84  real64 const weightToleranceInv = 1e30 / lengthTolerance;
85 
86  real64 cellToFaceMat[ NF ][ 3 ] = {{ 0 }};
87  real64 normalsMat[ NF ][ 3 ] = {{ 0 }};
88  real64 permMat[ 3 ][ 3 ] = {{ 0 }};
89 
90  real64 work_dimByNumFaces[ 3 ][ NF ] = {{ 0 }};
91  real64 worka_numFacesByNumFaces[ NF ][ NF ] = {{ 0 }};
92  real64 workb_numFacesByNumFaces[ NF ][ NF ] = {{ 0 }};
93  real64 workc_numFacesByNumFaces[ NF ][ NF ] = {{ 0 }};
94 
95  real64 tpTransInv[ NF ] = { 0.0 };
96 
97  real64 q0[ NF ], q1[ NF ], q2[ NF ];
98  real64 faceArea[ NF ];
99 
100 
101  // 0) assemble full coefficient tensor from principal axis/components
102  MimeticInnerProductHelpers::makeFullTensor( elemPerm, permMat );
103 
104  // 1) fill the matrices cellToFaceMat and normalsMat row by row
105  for( localIndex ifaceLoc = 0; ifaceLoc < NF; ++ifaceLoc )
106  {
107  real64 faceCenter[ 3 ], faceNormal[ 3 ], cellToFaceVec[ 3 ];
108  // compute the face geometry data: center, normal, vector from cell center to face center
109  faceArea[ ifaceLoc ] =
110  computationalGeometry::centroid_3DPolygon( faceToNodes[elemToFaces[ifaceLoc]],
111  nodePosition,
112  faceCenter,
113  faceNormal,
114  areaTolerance );
115 
116  LvArray::tensorOps::copy< 3 >( cellToFaceVec, faceCenter );
117  LvArray::tensorOps::subtract< 3 >( cellToFaceVec, elemCenter );
118 
119  q0[ ifaceLoc ] = faceArea[ ifaceLoc ] * cellToFaceVec[ 0 ];
120  q1[ ifaceLoc ] = faceArea[ ifaceLoc ] * cellToFaceVec[ 1 ];
121  q2[ ifaceLoc ] = faceArea[ ifaceLoc ] * cellToFaceVec[ 2 ];
122 
123  if( LvArray::tensorOps::AiBi< 3 >( cellToFaceVec, faceNormal ) < 0.0 )
124  {
125  LvArray::tensorOps::scale< 3 >( faceNormal, -1 );
126  }
127 
128  // the two-point transmissibility is computed to computed here because it is needed
129  // in the implementation of the transmissibility multiplier (see below)
130  // TODO: see what it would take to bring the (harmonically averaged) two-point trans here
131  real64 diagEntry = 0.0;
132  MimeticInnerProductHelpers::computeInvTPFATransWithMultiplier< NF >( elemPerm,
133  faceNormal,
134  faceArea[ifaceLoc],
135  transMultiplier[elemToFaces[ifaceLoc]],
136  weightToleranceInv,
137  cellToFaceVec,
138  diagEntry );
139  tpTransInv[ifaceLoc] = diagEntry;
140 
141  LvArray::tensorOps::scale< 3 >( faceNormal, faceArea[ ifaceLoc ] );
142  normalsMat[ ifaceLoc ][ 0 ] = faceNormal[ 0 ];
143  normalsMat[ ifaceLoc ][ 1 ] = faceNormal[ 1 ];
144  normalsMat[ ifaceLoc ][ 2 ] = faceNormal[ 2 ];
145 
146  }
147 
148  // 2) compute the stabilization coefficient
149  real64 const tParam = 2 * LvArray::tensorOps::trace< 3 >( permMat );
150 
151  // 3) compute N K N'
152  LvArray::tensorOps::Rij_eq_AikBjk< 3, NF, 3 >( work_dimByNumFaces,
153  permMat,
154  normalsMat );
155  LvArray::tensorOps::Rij_eq_AikBkj< NF, NF, 3 >( transMatrix,
156  normalsMat,
157  work_dimByNumFaces );
158 
159  // 4) compute the orthonormalization of the matrix cellToFaceVec
160  MimeticInnerProductHelpers::orthonormalize< NF >( q0, q1, q2, cellToFaceMat );
161 
162  // 5) compute P_Q = I - QQ'
163  // note: we compute -P_Q here
164  LvArray::tensorOps::addIdentity< NF >( worka_numFacesByNumFaces, -1 );
165  LvArray::tensorOps::Rij_add_AikAjk< NF, 3 >( worka_numFacesByNumFaces,
166  cellToFaceMat );
167 
168  // 6) compute D P_Q D where D = diag( faceArea )
169  // 7) compute T = ( N K N' + t D P_Q D ) / elemVolume
170  for( localIndex i = 0; i < NF; ++i )
171  {
172  workb_numFacesByNumFaces[ i ][ i ] = faceArea[ i ];
173  }
174 
175  LvArray::tensorOps::Rij_eq_AikBkj< NF, NF, NF >( workc_numFacesByNumFaces,
176  workb_numFacesByNumFaces,
177  worka_numFacesByNumFaces );
178 
179 
180  LvArray::tensorOps::scale< NF, NF >( transMatrix, 1 / elemVolume );
181  LvArray::tensorOps::scale< NF, NF >( workc_numFacesByNumFaces, -tParam / elemVolume );
182  LvArray::tensorOps::Rij_add_AikBkj< NF, NF, NF >( transMatrix,
183  workc_numFacesByNumFaces,
184  workb_numFacesByNumFaces );
185 
186  // 7) incorporate the transmissbility multipliers
187  // Ref: Nilsen, H. M., J. R. Natvig, and K.-A Lie.,
188  // "Accurate modeling of faults by multipoint, mimetic, and mixed methods." SPEJ
189 
190  if( !isZero( LvArray::tensorOps::l2NormSquared< NF >( tpTransInv ) ) )
191  {
192  MimeticInnerProductHelpers::computeTransMatrixWithMultipliers< NF >( tpTransInv,
193  transMatrix );
194  }
195 
196 }
197 
198 } // end namespace mimeticInnerProduct
199 
200 } // end namespace geos
201 
202 
203 #endif //GEOS_FINITEVOLUME_MIMETICINNERPRODUCTS_SIMPLEINNERPRODUCT_HPP_
#define GEOS_HOST_DEVICE
Marks a host-device function.
Definition: GeosxMacros.hpp:49
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:180
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:286
ArraySlice< T, 2, USD > arraySlice2d
Alias for 2D array slice.
Definition: DataTypes.hpp:200
double real64
64-bit floating point type.
Definition: DataTypes.hpp:99
GEOS_LOCALINDEX_TYPE localIndex
Local index type (for indexing objects within an MPI partition).
Definition: DataTypes.hpp:85
ArraySlice< T, 1, USD > arraySlice1d
Alias for 1D array slice.
Definition: DataTypes.hpp:184
ArrayView< T, 2, USD > arrayView2d
Alias for 2D array view.
Definition: DataTypes.hpp:196
static GEOS_HOST_DEVICE void makeFullTensor(real64 const (&values)[3], real64(&result)[3][3])
Create a full tensor from an array.