GEOS
FluxKernelsHelper.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_PHYSICSSOLVERS_FLUIDFLOW_SINGLEPHASE_FLUXKERNELSHELPER_HPP
21 #define GEOS_PHYSICSSOLVERS_FLUIDFLOW_SINGLEPHASE_FLUXKERNELSHELPER_HPP
22 
23 #include "common/DataTypes.hpp"
25 #include "constitutive/fluid/singlefluid/SingleFluidLayouts.hpp"
26 
27 namespace geos
28 {
29 
30 namespace singlePhaseFluxKernelsHelper
31 {
32 
39 template< typename VIEWTYPE >
41 
43 inline
44 void computeSinglePhaseFlux( localIndex const ( &seri )[2],
45  localIndex const ( &sesri )[2],
46  localIndex const ( &sei )[2],
47  real64 const ( &transmissibility )[2],
48  real64 const ( &dTrans_dPres )[2],
55  real64 & alpha,
56  real64 & mobility,
57  real64 & potGrad,
58  real64 & fluxVal,
59  real64 ( & dFlux_dP )[2],
60  real64 & dFlux_dTrans )
61 {
62  using DerivOffset = constitutive::singlefluid::DerivativeOffsetC< 0 >;
63  // average density
64  real64 densMean = 0.0;
65  real64 dDensMean_dP[2];
66 
67  for( localIndex ke = 0; ke < 2; ++ke )
68  {
69  densMean += 0.5 * dens[seri[ke]][sesri[ke]][sei[ke]][0];
70  dDensMean_dP[ke] = 0.5 * dDens[seri[ke]][sesri[ke]][sei[ke]][0][DerivOffset::dP];
71  }
72 
73  // compute potential difference
74  real64 dpotGrad_dTrans = 0.0;
75  real64 sumWeightGrav = 0.0;
76  real64 potScale = 0.0;
77  int signpotGradf[2] = {1, -1};
78 
79  for( localIndex ke = 0; ke < 2; ++ke )
80  {
81  localIndex const er = seri[ke];
82  localIndex const esr = sesri[ke];
83  localIndex const ei = sei[ke];
84 
85  real64 const pressure = pres[er][esr][ei];
86  real64 const gravD = gravCoef[er][esr][ei];
87  real64 const pot = transmissibility[ke] * ( pressure - densMean * gravD );
88 
89  potGrad += pot;
90  dpotGrad_dTrans += signpotGradf[ke] * ( pressure - densMean * gravD );
91  sumWeightGrav += transmissibility[ke] * gravD;
92 
93  potScale = fmax( potScale, fabs( pot ) );
94  }
95 
96  // compute upwinding tolerance
97  real64 constexpr upwRelTol = 1e-8;
98  real64 const upwAbsTol = fmax( potScale * upwRelTol, LvArray::NumericLimits< real64 >::epsilon );
99 
100  // decide mobility coefficients - smooth variation in [-upwAbsTol; upwAbsTol]
101  alpha = ( potGrad + upwAbsTol ) / ( 2 * upwAbsTol );
102 
103  real64 dMobility_dP[2]{};
104  if( alpha <= 0.0 || alpha >= 1.0 )
105  {
106  // happy path: single upwind direction
107  localIndex const ke = 1 - localIndex( fmax( fmin( alpha, 1.0 ), 0.0 ) );
108  mobility = mob[seri[ke]][sesri[ke]][sei[ke]];
109  dMobility_dP[ke] = dMob[seri[ke]][sesri[ke]][sei[ke]][DerivOffset::dP];
110  }
111  else
112  {
113  // sad path: weighted averaging
114  real64 const mobWeights[2] = { alpha, 1.0 - alpha };
115  for( localIndex ke = 0; ke < 2; ++ke )
116  {
117  mobility += mobWeights[ke] * mob[seri[ke]][sesri[ke]][sei[ke]];
118  dMobility_dP[ke] = mobWeights[ke] * dMob[seri[ke]][sesri[ke]][sei[ke]][DerivOffset::dP];
119  }
120  }
121 
122  // compute the final flux and derivative w.r.t transmissibility
123  fluxVal = mobility * potGrad;
124 
125  dFlux_dTrans = mobility * dpotGrad_dTrans;
126 
127  for( localIndex ke = 0; ke < 2; ++ke )
128  {
129  dFlux_dP[ke] = mobility * ( transmissibility[ke] - dDensMean_dP[ke] * sumWeightGrav )
130  + dMobility_dP[ke] * potGrad + dFlux_dTrans * dTrans_dPres[ke];
131  }
132 
133 }
134 
135 
136 template< typename ENERGYFLUX_DERIVATIVE_TYPE >
138 void computeEnthalpyFlux( localIndex const ( &seri )[2],
139  localIndex const ( &sesri )[2],
140  localIndex const ( &sei )[2],
141  real64 const ( &transmissibility )[2],
142  ElementViewConst< arrayView2d< real64 const, constitutive::singlefluid::USD_FLUID > > const & enthalpy,
143  ElementViewConst< arrayView3d< real64 const, constitutive::singlefluid::USD_FLUID_DER > > const & dEnthalpy,
144  ElementViewConst< arrayView1d< real64 const > > const & gravCoef,
147  real64 const & alpha,
148  real64 const & mobility,
149  real64 const & potGrad,
150  real64 const & massFlux,
151  real64 const & dMassFlux_dTrans,
152  real64 const ( &dMassFlux_dP )[2],
153  real64 ( & dMassFlux_dT )[2],
154  real64 & energyFlux,
155  real64 & dEnergyFlux_dTrans,
156  ENERGYFLUX_DERIVATIVE_TYPE & dEnergyFlux_dP,
157  ENERGYFLUX_DERIVATIVE_TYPE & dEnergyFlux_dT )
158 {
159  // Step 1: compute the derivatives of the mean density at the interface wrt temperature
160  using DerivOffset = constitutive::singlefluid::DerivativeOffsetC< 1 >;
161  real64 dDensMean_dT[2]{0.0, 0.0};
162 
163  for( integer ke = 0; ke < 2; ++ke )
164  {
165  real64 const dDens_dT = dDens[seri[ke]][sesri[ke]][sei[ke]][0][DerivOffset::dT];
166  dDensMean_dT[ke] = 0.5 * dDens_dT;
167  }
168 
169  // Step 2: compute the derivatives of the potential difference wrt temperature
170  //***** calculation of flux *****
171 
172  real64 dGravHead_dT[2]{0.0, 0.0};
173 
174  // compute potential difference
175  for( integer ke = 0; ke < 2; ++ke )
176  {
177  localIndex const er = seri[ke];
178  localIndex const esr = sesri[ke];
179  localIndex const ei = sei[ke];
180 
181  // compute derivative of gravity potential difference wrt temperature
182  real64 const gravD = transmissibility[ke] * gravCoef[er][esr][ei];
183 
184  for( integer i = 0; i < 2; ++i )
185  {
186  dGravHead_dT[i] += dDensMean_dT[i] * gravD;
187  }
188  }
189 
190  // Step 3: compute the derivatives of the (upwinded) compFlux wrt temperature
191  // *** upwinding ***
192 
193  // Step 3.1: compute the derivative of the mass flux wrt temperature
194  for( integer ke = 0; ke < 2; ++ke )
195  {
196  dMassFlux_dT[ke] -= dGravHead_dT[ke];
197  }
198 
199  for( integer ke = 0; ke < 2; ++ke )
200  {
201  dMassFlux_dT[ke] *= mobility;
202  }
203 
204  real64 dMob_dT[2]{};
205 
206  if( alpha <= 0.0 || alpha >= 1.0 )
207  {
208  localIndex const k_up = 1 - localIndex( fmax( fmin( alpha, 1.0 ), 0.0 ) );
209 
210  dMob_dT[k_up] = dMob[seri[k_up]][sesri[k_up]][sei[k_up]][DerivOffset::dT];
211  }
212  else
213  {
214  real64 const mobWeights[2] = { alpha, 1.0 - alpha };
215  for( integer ke = 0; ke < 2; ++ke )
216  {
217  dMob_dT[ke] = mobWeights[ke] * dMob[seri[ke]][sesri[ke]][sei[ke]][DerivOffset::dT];
218  }
219  }
220 
221  // add contribution from upstream cell mobility derivatives
222  for( integer ke = 0; ke < 2; ++ke )
223  {
224  dMassFlux_dT[ke] += dMob_dT[ke] * potGrad;
225  }
226 
227  // Step 4: compute the enthalpy flux
228  real64 enthalpyTimesMobWeight = 0.0;
229  real64 dEnthalpy_dP[2]{0.0, 0.0};
230  real64 dEnthalpy_dT[2]{0.0, 0.0};
231 
232  if( alpha <= 0.0 || alpha >= 1.0 )
233  {
234  localIndex const k_up = 1 - localIndex( fmax( fmin( alpha, 1.0 ), 0.0 ) );
235 
236  enthalpyTimesMobWeight = enthalpy[seri[k_up]][sesri[k_up]][sei[k_up]][0];
237  dEnthalpy_dP[k_up] = dEnthalpy[seri[k_up]][sesri[k_up]][sei[k_up]][0][DerivOffset::dP];
238  dEnthalpy_dT[k_up] = dEnthalpy[seri[k_up]][sesri[k_up]][sei[k_up]][0][DerivOffset::dT];
239  }
240  else
241  {
242  real64 const mobWeights[2] = { alpha, 1.0 - alpha };
243  for( integer ke = 0; ke < 2; ++ke )
244  {
245  enthalpyTimesMobWeight += mobWeights[ke] * enthalpy[seri[ke]][sesri[ke]][sei[ke]][0];
246  dEnthalpy_dP[ke] = mobWeights[ke] * dEnthalpy[seri[ke]][sesri[ke]][sei[ke]][0][DerivOffset::dP];
247  dEnthalpy_dT[ke] = mobWeights[ke] * dEnthalpy[seri[ke]][sesri[ke]][sei[ke]][0][DerivOffset::dT];
248  }
249  }
250 
251  energyFlux += massFlux * enthalpyTimesMobWeight;
252  dEnergyFlux_dTrans = enthalpyTimesMobWeight * dMassFlux_dTrans;
253 
254  for( integer ke = 0; ke < 2; ++ke )
255  {
256  dEnergyFlux_dP[ke] += dMassFlux_dP[ke] * enthalpyTimesMobWeight;
257  dEnergyFlux_dT[ke] += dMassFlux_dT[ke] * enthalpyTimesMobWeight;
258  }
259 
260  for( integer ke = 0; ke < 2; ++ke )
261  {
262  dEnergyFlux_dP[ke] += massFlux * dEnthalpy_dP[ke];
263  dEnergyFlux_dT[ke] += massFlux * dEnthalpy_dT[ke];
264  }
265 }
266 
267 
268 template< typename ENERGYFLUX_DERIVATIVE_TYPE >
270 void computeConductiveFlux( localIndex const ( &seri )[2],
271  localIndex const ( &sesri )[2],
272  localIndex const ( &sei )[2],
273  ElementViewConst< arrayView1d< real64 const > > const & temperature,
274  real64 const ( &thermalTrans )[2],
275  real64 & energyFlux,
276  ENERGYFLUX_DERIVATIVE_TYPE & dEnergyFlux_dT )
277 {
278  for( integer ke = 0; ke < 2; ++ke )
279  {
280  localIndex const er = seri[ke];
281  localIndex const esr = sesri[ke];
282  localIndex const ei = sei[ke];
283 
284  energyFlux += thermalTrans[ke] * temperature[er][esr][ei];
285  dEnergyFlux_dT[ke] += thermalTrans[ke];
286  }
287 }
288 
289 } // namespace singlePhaseFluxKernelsHelper
290 
291 } // namespace geos
292 
293 #endif //GEOS_PHYSICSSOLVERS_FLUIDFLOW_SINGLEPHASE_FLUXKERNELSHELPER_HPP
ElementRegionManager::ElementViewConst< VIEWTYPE > ElementViewConst
The type for element-based data. Consists entirely of ArrayView's.
#define GEOS_HOST_DEVICE
Marks a host-device function.
Definition: GeosxMacros.hpp:49
typename ElementViewAccessor< VIEWTYPE >::NestedViewTypeConst ElementViewConst
The ElementViewAccessor at the ElementRegionManager level is the type resulting from ElementViewAcces...
ArrayView< T, 1 > arrayView1d
Alias for 1D array view.
Definition: DataTypes.hpp:180
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
std::int32_t integer
Signed integer type.
Definition: DataTypes.hpp:82
ArrayView< T, 2, USD > arrayView2d
Alias for 2D array view.
Definition: DataTypes.hpp:196
ArrayView< T, 3, USD > arrayView3d
Alias for 3D array view.
Definition: DataTypes.hpp:212