GEOS
CapillaryPressureInversionKernel.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_KERNELS_COMPOSITIONAL_CAPILLARYPRESSUREINVERSIONKERNEL_HPP
21 #define GEOS_PHYSICSSOLVERS_FLUIDFLOW_KERNELS_COMPOSITIONAL_CAPILLARYPRESSUREINVERSIONKERNEL_HPP
22 
23 #include "constitutive/capillaryPressure/InverseCapillaryPressure.hpp"
24 #include "constitutive/capillaryPressure/CapillaryPressureFields.hpp"
25 #include "codingUtilities/Utilities.hpp"
26 
27 namespace geos
28 {
29 
30 namespace isothermalCompositionalMultiphaseBaseKernels
31 {
32 
33 /******************************** CapillaryPressureInversionKernel ********************************/
37 template< typename CAP_PRESSURE = NoOpFunc >
39 {
40  template< integer numComps, integer numPhases >
41  static void launch( SortedArrayView< localIndex const > const & targetSet,
42  CAP_PRESSURE & capPressure,
43  arrayView1d< integer const > const & phaseOrder,
44  arrayView2d< real64 const > const & elementCenter,
45  TableFunction::KernelWrapper const & elevationIndexTable,
49  arrayView2d< real64, compflow::USD_COMP > const globalComponentFractions )
50  {
51  constitutive::InverseCapillaryPressure< CAP_PRESSURE > inverseCapPressureType( capPressure );
52  auto capPressureWrapper = inverseCapPressureType.createKernelWrapper();
53 
54  array2d< real64 > jFuncMultiplierArray( 1, numPhases - 1 );
55  arrayView2d< real64 const > jFuncMultiplier = jFuncMultiplierArray.toViewConst();
56  constexpr bool isJFunction = std::is_same_v< CAP_PRESSURE, constitutive::JFunctionCapillaryPressure >;
57  if constexpr ( isJFunction )
58  {
59  jFuncMultiplier = capPressure.template getField< geos::fields::cappres::jFuncMultiplier >().reference().toViewConst();
60  }
61 
62  integer const ipGas = phaseOrder[constitutive::CapillaryPressureBase::PhaseType::GAS];
63  integer const ipWater = phaseOrder[constitutive::CapillaryPressureBase::PhaseType::WATER];
64  integer const ipOil = phaseOrder[constitutive::CapillaryPressureBase::PhaseType::OIL];
65  integer phases[numPhases]{};
66  if constexpr ( numPhases == 2 )
67  {
68  if( 0 <= ipGas && 0 <= ipWater )
69  {
70  phases[0] = ipGas;
71  phases[1] = ipWater;
72  }
73  if( 0 <= ipOil && 0 <= ipWater )
74  {
75  phases[0] = ipOil;
76  phases[1] = ipWater;
77  }
78  if( 0 <= ipGas && 0 <= ipOil )
79  {
80  phases[0] = ipGas;
81  phases[1] = ipOil;
82  }
83  }
84  if constexpr ( numPhases == 3 )
85  {
86  phases[0] = ipGas;
87  phases[1] = ipOil;
88  phases[2] = ipWater;
89  }
90 
91  localIndex const numPoints = pressureValues.size( 0 );
92 
93  forAll< parallelDevicePolicy<> >( targetSet.size(), [targetSet,
94  elementCenter,
95  capPressureWrapper,
96  elevationIndexTable,
97  phases,
98  numPoints,
99  jFuncMultiplier,
100  pressureValues,
101  phaseDensityValues,
102  phaseComponentFractions,
103  globalComponentFractions] GEOS_HOST_DEVICE ( localIndex const i )
104  {
105  localIndex const k = targetSet[i];
106  real64 const elevation = elementCenter[k][2];
107 
108  real64 ea = elevationIndexTable.compute( &elevation );
109  integer const en = LvArray::math::min( static_cast< integer >(ea), numPoints - 2 );
110  ea -= en;
111 
113  StackArray< real64, 2, numPhases, compflow::LAYOUT_PHASE > targetPhaseVolumeFraction( 1, numPhases );
114  calculateCapillaryPressure< numPhases >( ea,
115  pressureValues[en][0],
116  pressureValues[en+1][0],
117  phases,
118  targetPhaseCapPressure[0][0] );
119 
120 
121  real64 constexpr initialPhaseVolumeFractionGuess = 1.0 / numPhases;
122  for( integer ip = 0; ip < numPhases; ++ip )
123  {
124  targetPhaseVolumeFraction[0][ip] = initialPhaseVolumeFractionGuess;
125  }
126 
127  localIndex const jFunctionIndex = isJFunction ? k : 0;
128  capPressureWrapper.compute( targetPhaseCapPressure[0][0],
129  jFuncMultiplier[jFunctionIndex],
130  targetPhaseVolumeFraction[0] );
131 
132  for( integer ic = 0; ic < numComps; ++ic )
133  {
134  globalComponentFractions[k][ic] = 0.0;
135  }
136  real64 totalMass = 0.0;
137  for( integer ip = 0; ip < numPhases; ++ip )
138  {
139  real64 const density0 = phaseDensityValues[en][0][ip];
140  real64 const density1 = phaseDensityValues[en+1][0][ip];
141  real64 const phaseMass = ((1.0-ea)*density0 + ea*density1) * targetPhaseVolumeFraction[0][ip];
142  for( integer ic = 0; ic < numComps; ++ic )
143  {
144  real64 const fraction0 = phaseComponentFractions[en][0][ip][ic];
145  real64 const fraction1 = phaseComponentFractions[en+1][0][ip][ic];
146  real64 const componentMass = phaseMass * ((1.0-ea)*fraction0 + ea*fraction1);
147  globalComponentFractions[k][ic] += componentMass;
148  totalMass += componentMass;
149  }
150  }
151  for( integer ic = 0; ic < numComps; ++ic )
152  {
153  globalComponentFractions[k][ic] /= totalMass;
154  }
155  } );
156  }
157 
158  template< integer numPhases >
159  static void GEOS_HOST_DEVICE calculateCapillaryPressure( real64 const alpha,
162  integer const phaseOrder[numPhases],
164  {
165  if constexpr (numPhases == 2)
166  {
167  real64 const capPressure0 = phasePressures0[phaseOrder[0]] - phasePressures0[phaseOrder[1]];
168  real64 const capPressure1 = phasePressures1[phaseOrder[0]] - phasePressures1[phaseOrder[1]];
169  phaseCapPressure[phaseOrder[1]] = (1.0-alpha)*capPressure0 + alpha*capPressure1;
170  }
171  if constexpr (numPhases == 3)
172  {
173  real64 const capPressure00 = phasePressures0[phaseOrder[1]] - phasePressures0[phaseOrder[0]];
174  real64 const capPressure01 = phasePressures1[phaseOrder[1]] - phasePressures1[phaseOrder[0]];
175  phaseCapPressure[phaseOrder[0]] = (1.0-alpha)*capPressure00 + alpha*capPressure01;
176  real64 const capPressure10 = phasePressures0[phaseOrder[1]] - phasePressures0[phaseOrder[2]];
177  real64 const capPressure11 = phasePressures1[phaseOrder[1]] - phasePressures1[phaseOrder[2]];
178  phaseCapPressure[phaseOrder[2]] = (1.0-alpha)*capPressure10 + alpha*capPressure11;
179  }
180  }
181 };
182 
183 } // namespace isothermalCompositionalMultiphaseBaseKernels
184 
185 } // namespace geos
186 
187 
188 #endif //GEOS_PHYSICSSOLVERS_FLUIDFLOW_KERNELS_COMPOSITIONAL_CAPILLARYPRESSUREINVERSIONKERNEL_HPP
#define GEOS_HOST_DEVICE
Marks a host-device function.
Definition: GeosxMacros.hpp:49
ArrayView< T, 1 > arrayView1d
Alias for 1D array view.
Definition: DataTypes.hpp:179
Array< T, 2, PERMUTATION > array2d
Alias for 2D array.
Definition: DataTypes.hpp:191
LvArray::StackArray< T, NDIM, PERMUTATION, localIndex, MAXSIZE > StackArray
Multidimensional stack-based array type. See LvArray:StackArray for details.
Definition: DataTypes.hpp:155
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
LvArray::SortedArrayView< T, localIndex, LvArray::ChaiBuffer > SortedArrayView
A sorted array view of local indices.
Definition: DataTypes.hpp:270
ArrayView< T, 4, USD > arrayView4d
Alias for 4D array view.
Definition: DataTypes.hpp:227
ArrayView< T, 2, USD > arrayView2d
Alias for 2D array view.
Definition: DataTypes.hpp:195
int integer
Signed integer type.
Definition: DataTypes.hpp:81
ArrayView< T, 3, USD > arrayView3d
Alias for 3D array view.
Definition: DataTypes.hpp:211
Kernel for the inversion of capillary pressure to saturation when we have multiphase initialisation.