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