GEOSX
BdVLMInnerProduct.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_BDVLMINNERPRODUCT_HPP_
20 #define GEOS_FINITEVOLUME_MIMETICINNERPRODUCTS_BDVLMINNERPRODUCT_HPP_
21 
25 
26 namespace geos
27 {
28 namespace mimeticInnerProduct
29 {
30 
37 {
38 public:
39 
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  GEOS_UNUSED_VAR( elemVolume );
84  real64 const areaTolerance = lengthTolerance * lengthTolerance;
85  real64 const weightToleranceInv = 1e30 / lengthTolerance;
86 
87  real64 cellToFaceMat[ NF ][ 3 ] = {{ 0 }};
88  real64 normalsMat[ NF ][ 3 ] = {{ 0 }};
89  real64 permMat[ 3 ][ 3 ] = {{ 0 }};
90  real64 faceAreaMat[ NF ][ NF ] = {{ 0 }};
91 
92  real64 work_dimByDim[ 3 ][ 3 ] = {{ 0 }};
93  real64 work_numFacesByDim[ NF ][ 3 ] = {{ 0 }};
94  real64 work_dimByNumFaces[ 3 ][ NF ] = {{ 0 }};
95  real64 work_numFacesByNumFaces[ NF ][ NF ] = {{ 0 }};
96 
97  real64 tpTransInv[ NF ] = { 0.0 };
98 
99  // 0) assemble full coefficient tensor from principal axis/components
100  MimeticInnerProductHelpers::makeFullTensor( elemPerm, permMat );
101 
102  // 1) fill the matrices cellToFaceMat and normalsMat row by row
103  for( localIndex ifaceLoc = 0; ifaceLoc < NF; ++ifaceLoc )
104  {
105  real64 faceCenter[ 3 ], faceNormal[ 3 ], cellToFaceVec[ 3 ];
106  // compute the face geometry data: center, normal, vector from cell center to face center
107  faceAreaMat[ ifaceLoc ][ ifaceLoc ] =
108  computationalGeometry::centroid_3DPolygon( faceToNodes[elemToFaces[ifaceLoc]],
109  nodePosition,
110  faceCenter,
111  faceNormal,
112  areaTolerance );
113 
114  LvArray::tensorOps::copy< 3 >( cellToFaceVec, faceCenter );
115  LvArray::tensorOps::subtract< 3 >( cellToFaceVec, elemCenter );
116 
117  cellToFaceMat[ ifaceLoc ][0] = faceAreaMat[ ifaceLoc ][ ifaceLoc ] * cellToFaceVec[ 0 ];
118  cellToFaceMat[ ifaceLoc ][1] = faceAreaMat[ ifaceLoc ][ ifaceLoc ] * cellToFaceVec[ 1 ];
119  cellToFaceMat[ ifaceLoc ][2] = faceAreaMat[ ifaceLoc ][ ifaceLoc ] * cellToFaceVec[ 2 ];
120 
121  if( LvArray::tensorOps::AiBi< 3 >( cellToFaceVec, faceNormal ) < 0.0 )
122  {
123  LvArray::tensorOps::scale< 3 >( faceNormal, -1 );
124  }
125 
126  // the two-point transmissibility is computed to computed here because it is needed
127  // in the implementation of the transmissibility multiplier (see below)
128  // TODO: see what it would take to bring the (harmonically averaged) two-point trans here
129  real64 diagEntry = 0.0;
130  MimeticInnerProductHelpers::computeInvTPFATransWithMultiplier< NF >( elemPerm,
131  faceNormal,
132  faceAreaMat[ifaceLoc][ifaceLoc],
133  transMultiplier[elemToFaces[ifaceLoc]],
134  weightToleranceInv,
135  cellToFaceVec,
136  diagEntry );
137  tpTransInv[ifaceLoc] = diagEntry;
138 
139  normalsMat[ ifaceLoc ][ 0 ] = faceNormal[ 0 ];
140  normalsMat[ ifaceLoc ][ 1 ] = faceNormal[ 1 ];
141  normalsMat[ ifaceLoc ][ 2 ] = faceNormal[ 2 ];
142 
143  }
144 
145  // 2) compute N of Beirao da Veiga, Lipnikov, Manzini
146  LvArray::tensorOps::Rij_eq_AikBkj< NF, 3, 3 >( work_numFacesByDim,
147  normalsMat,
148  permMat );
149 
150  // 3) compute ( N^T R )^-1 of Beirao da Veiga, Lipnikov, Manzini
151  LvArray::tensorOps::Rij_eq_AkiBkj< 3, 3, NF >( work_dimByDim,
152  work_numFacesByDim,
153  cellToFaceMat );
154  LvArray::tensorOps::invert< 3 >( work_dimByDim );
155 
156  // 4) compute N ( N^T R )^-1 N^T
157  LvArray::tensorOps::Rij_eq_AikBjk< 3, NF, 3 >( work_dimByNumFaces,
158  work_dimByDim,
159  work_numFacesByDim );
160  LvArray::tensorOps::Rij_eq_AikBkj< NF, NF, 3 >( transMatrix,
161  work_numFacesByDim,
162  work_dimByNumFaces );
163 
164  // 5) compute the stabilization coefficient \tilde{ \lambda }
165  real64 const stabCoef = 2.0 / NF * LvArray::tensorOps::trace< NF >( transMatrix );
166 
167  // at this point we have N ( N^T R )^-1 N^T and \tilde{ \lambda }
168  // we have to compute I - R ( R^T R )^-1 R^T and sum
169 
170  // 6) compute ( R^T R )^-1
171  LvArray::tensorOps::Rij_eq_AkiAkj< 3, NF >( work_dimByDim,
172  cellToFaceMat );
173  LvArray::tensorOps::invert< 3 >( work_dimByDim );
174 
175  // 7) compute I - R ( R^T R )^-1 R^T
176  LvArray::tensorOps::addIdentity< NF >( work_numFacesByNumFaces, -1 );
177  LvArray::tensorOps::Rij_eq_AikBjk< 3, NF, 3 >( work_dimByNumFaces,
178  work_dimByDim,
179  cellToFaceMat );
180  LvArray::tensorOps::Rij_add_AikBkj< NF, NF, 3 >( work_numFacesByNumFaces,
181  cellToFaceMat,
182  work_dimByNumFaces );
183 
184  // 8) compute N ( N^T R )^-1 N^T + \tilde{ \lambda } * (I - R ( R^T R )^-1 R^T)
185  LvArray::tensorOps::scaledAdd< NF, NF >( transMatrix, work_numFacesByNumFaces, -stabCoef );
186 
187 
188  // 9) this IP was designed for velocities,
189  // so we have to pre- and post-multiply by faceAreaMat to get an IP for fluxes
190  LvArray::tensorOps::Rij_eq_AikBkj< NF, NF, NF >( work_numFacesByNumFaces,
191  transMatrix,
192  faceAreaMat );
193  LvArray::tensorOps::Rij_eq_AikBkj< NF, NF, NF >( transMatrix,
194  faceAreaMat,
195  work_numFacesByNumFaces );
196 
197  // 10) incorporate the transmissbility multipliers
198  // Ref: Nilsen, H. M., J. R. Natvig, and K.-A Lie.,
199  // "Accurate modeling of faults by multipoint, mimetic, and mixed methods." SPEJ
200 
201  if( !isZero( LvArray::tensorOps::l2NormSquared< NF >( tpTransInv ) ) )
202  {
203  MimeticInnerProductHelpers::computeTransMatrixWithMultipliers< NF >( tpTransInv,
204  transMatrix );
205  }
206 
207 }
208 
209 } // end namespace mimeticInnerProduct
210 
211 } // end namespace geos
212 
213 
214 #endif //GEOS_FINITEVOLUME_MIMETICINNERPRODUCTS_BDVLMINNERPRODUCT_HPP_
#define GEOS_HOST_DEVICE
Marks a host-device function.
Definition: GeosxMacros.hpp:48
#define GEOS_UNUSED_VAR(...)
Mark an unused variable and silence compiler warnings.
Definition: GeosxMacros.hpp:83
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 inner product of Beirao...
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.