GEOS
HydrostaticPressureKernel.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 Total, S.A
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_COMPOSITIONAL_HYDROSTATICPRESSUREKERNEL_HPP
21 #define GEOS_PHYSICSSOLVERS_FLUIDFLOW_COMPOSITIONAL_HYDROSTATICPRESSUREKERNEL_HPP
22 
23 #include "common/DataLayouts.hpp"
24 #include "common/DataTypes.hpp"
25 #include "common/GEOS_RAJA_Interface.hpp"
26 #include "constitutive/fluid/multifluid/MultiFluidBase.hpp"
28 
29 namespace geos
30 {
31 
32 namespace isothermalCompositionalMultiphaseBaseKernels
33 {
34 
35 /******************************** HydrostaticPressureKernel ********************************/
36 
38 {
39 
40  // TODO: this type of constants should be centralized somewhere or provided by fluid model
41  static real64 constexpr MIN_FOR_PHASE_PRESENCE = 1e-12;
42 
43  enum class ReturnType : integer
44  {
45  FAILED_TO_CONVERGE = 0,
46  DETECTED_MULTIPHASE_FLOW = 1,
47  SUCCESS = 2
48  };
49 
50  template< typename FLUID_WRAPPER >
51  static ReturnType
52  computeHydrostaticPressure( integer const numComps,
53  integer const numPhases,
54  integer const ipInit,
55  integer const maxNumEquilIterations,
56  real64 const & equilTolerance,
57  real64 const (&gravVector)[ 3 ],
58  FLUID_WRAPPER fluidWrapper,
60  TableFunction::KernelWrapper tempTableWrapper,
61  real64 const & refElevation,
62  real64 const & refPres,
63  arraySlice1d< real64 const > const & refPhaseMassDens,
64  real64 const & newElevation,
65  real64 & newPres,
66  arraySlice1d< real64 > const & newPhaseMassDens )
67  {
68  // fluid properties at this elevation
76  StackArray< real64, 4, constitutive::MultiFluidBase::MAX_NUM_PHASES *constitutive::MultiFluidBase::MAX_NUM_COMPONENTS,
77  constitutive::multifluid::LAYOUT_PHASE_COMP > phaseCompFrac( 1, 1, numPhases, numComps );
78  real64 totalDens = 0.0;
79 
80  bool isSinglePhaseFlow = true;
81 
82  // Step 1: compute the hydrostatic pressure at the current elevation
83 
84  real64 const gravCoef = gravVector[2] * ( refElevation - newElevation );
85  real64 const temp = tempTableWrapper.compute( &newElevation );
86  for( integer ic = 0; ic < numComps; ++ic )
87  {
88  compFrac[0][ic] = compFracTableWrappers[ic].compute( &newElevation );
89  }
90 
91  // Step 2: guess the pressure with the refPhaseMassDensity
92 
93  real64 pres0 = refPres - refPhaseMassDens[ipInit] * gravCoef;
94  real64 pres1 = 0.0;
95 
96  // Step 3: compute the mass density at this elevation using the guess, and update pressure
97 
98  constitutive::MultiFluidBase::KernelWrapper::computeValues( fluidWrapper,
99  pres0,
100  temp,
101  compFrac[0],
102  phaseFrac[0][0],
103  phaseDens[0][0],
104  phaseMassDens[0][0],
105  phaseVisc[0][0],
106  phaseEnthalpy[0][0],
107  phaseInternalEnergy[0][0],
108  phaseCompFrac[0][0],
109  totalDens );
110  pres1 = refPres - 0.5 * ( refPhaseMassDens[ipInit] + phaseMassDens[0][0][ipInit] ) * gravCoef;
111 
112  // Step 4: fixed-point iteration until convergence
113 
114  bool equilHasConverged = false;
115  for( integer eqIter = 0; eqIter < maxNumEquilIterations; ++eqIter )
116  {
117 
118  // check convergence
119  equilHasConverged = ( LvArray::math::abs( pres0 - pres1 ) < equilTolerance );
120  pres0 = pres1;
121 
122  // if converged, check number of phases and move on
123  if( equilHasConverged )
124  {
125  // make sure that the fluid is single-phase, other we have to issue a warning (for now)
126  // if only one phase is mobile, we are in good shape (unfortunately it is hard to access relperm from here)
127  localIndex numberOfPhases = 0;
128  for( integer ip = 0; ip < numPhases; ++ip )
129  {
130  if( phaseFrac[0][0][ip] > MIN_FOR_PHASE_PRESENCE )
131  {
132  numberOfPhases++;
133  }
134  }
135  if( numberOfPhases > 1 )
136  {
137  isSinglePhaseFlow = false;
138  }
139 
140  break;
141  }
142 
143  // compute the mass density at this elevation using the previous pressure, and compute the new pressure
144  constitutive::MultiFluidBase::KernelWrapper::computeValues( fluidWrapper,
145  pres0,
146  temp,
147  compFrac[0],
148  phaseFrac[0][0],
149  phaseDens[0][0],
150  phaseMassDens[0][0],
151  phaseVisc[0][0],
152  phaseEnthalpy[0][0],
153  phaseInternalEnergy[0][0],
154  phaseCompFrac[0][0],
155  totalDens );
156  pres1 = refPres - 0.5 * ( refPhaseMassDens[ipInit] + phaseMassDens[0][0][ipInit] ) * gravCoef;
157  }
158 
159  // Step 5: save the hydrostatic pressure and the corresponding density
160 
161  newPres = pres1;
162  for( integer ip = 0; ip < numPhases; ++ip )
163  {
164  newPhaseMassDens[ip] = phaseMassDens[0][0][ip];
165  }
166 
167  if( !equilHasConverged )
168  {
169  return ReturnType::FAILED_TO_CONVERGE;
170  }
171  else if( !isSinglePhaseFlow )
172  {
173  return ReturnType::DETECTED_MULTIPHASE_FLOW;
174  }
175  else
176  {
177  return ReturnType::SUCCESS;
178  }
179  }
180 
181  template< typename FLUID_WRAPPER >
182  static ReturnType
183  launch( localIndex const size,
184  integer const numComps,
185  integer const numPhases,
186  integer const ipInit,
187  integer const maxNumEquilIterations,
188  real64 const equilTolerance,
189  real64 const (&gravVector)[ 3 ],
190  real64 const & minElevation,
191  real64 const & elevationIncrement,
192  real64 const & datumElevation,
193  real64 const & datumPres,
194  FLUID_WRAPPER fluidWrapper,
196  TableFunction::KernelWrapper tempTableWrapper,
197  arrayView1d< arrayView1d< real64 > const > elevationValues,
198  arrayView1d< real64 > pressureValues )
199  {
200 
201  ReturnType returnVal = ReturnType::SUCCESS;
202 
203  // Step 1: compute the phase mass densities at datum
204 
205  // datum fluid properties
206  array2d< real64, compflow::LAYOUT_COMP > datumCompFrac( 1, numComps );
207  array3d< real64, constitutive::multifluid::LAYOUT_PHASE > datumPhaseFrac( 1, 1, numPhases );
208  array3d< real64, constitutive::multifluid::LAYOUT_PHASE > datumPhaseDens( 1, 1, numPhases );
209  array3d< real64, constitutive::multifluid::LAYOUT_PHASE > datumPhaseMassDens( 1, 1, numPhases );
210  array3d< real64, constitutive::multifluid::LAYOUT_PHASE > datumPhaseVisc( 1, 1, numPhases );
211  array3d< real64, constitutive::multifluid::LAYOUT_PHASE > datumPhaseEnthalpy( 1, 1, numPhases );
212  array3d< real64, constitutive::multifluid::LAYOUT_PHASE > datumPhaseInternalEnergy( 1, 1, numPhases );
213  array4d< real64, constitutive::multifluid::LAYOUT_PHASE_COMP > datumPhaseCompFrac( 1, 1, numPhases, numComps );
214  real64 datumTotalDens = 0.0;
215 
216  real64 const datumTemp = tempTableWrapper.compute( &datumElevation );
217  for( integer ic = 0; ic < numComps; ++ic )
218  {
219  datumCompFrac[0][ic] = compFracTableWrappers[ic].compute( &datumElevation );
220  }
221  constitutive::MultiFluidBase::KernelWrapper::computeValues( fluidWrapper,
222  datumPres,
223  datumTemp,
224  datumCompFrac[0],
225  datumPhaseFrac[0][0],
226  datumPhaseDens[0][0],
227  datumPhaseMassDens[0][0],
228  datumPhaseVisc[0][0],
229  datumPhaseEnthalpy[0][0],
230  datumPhaseInternalEnergy[0][0],
231  datumPhaseCompFrac[0][0],
232  datumTotalDens );
233 
234  // Step 2: find the closest elevation to datumElevation
235 
236  forAll< parallelHostPolicy >( size, [=] ( localIndex const i )
237  {
238  real64 const elevation = minElevation + i * elevationIncrement;
239  elevationValues[0][i] = elevation;
240  } );
241  integer const iRef = LvArray::sortedArrayManipulation::find( elevationValues[0].begin(),
242  elevationValues[0].size(),
243  datumElevation );
244 
245  // Step 3: compute the mass density and pressure at the reference elevation
246 
247  array2d< real64 > phaseMassDens( pressureValues.size(), numPhases );
248  // temporary array without permutation to compile on Lassen
249  array1d< real64 > datumPhaseMassDensTmp( numPhases );
250  for( integer ip = 0; ip < numPhases; ++ip )
251  {
252  datumPhaseMassDensTmp[ip] = datumPhaseMassDens[0][0][ip];
253  }
254 
255  ReturnType const refReturnVal =
256  computeHydrostaticPressure( numComps,
257  numPhases,
258  ipInit,
259  maxNumEquilIterations,
260  equilTolerance,
261  gravVector,
262  fluidWrapper,
263  compFracTableWrappers,
264  tempTableWrapper,
265  datumElevation,
266  datumPres,
267  datumPhaseMassDensTmp,
268  elevationValues[0][iRef],
269  pressureValues[iRef],
270  phaseMassDens[iRef] );
271  if( refReturnVal == ReturnType::FAILED_TO_CONVERGE )
272  {
273  return ReturnType::FAILED_TO_CONVERGE;
274  }
275  else if( refReturnVal == ReturnType::DETECTED_MULTIPHASE_FLOW )
276  {
277  returnVal = ReturnType::DETECTED_MULTIPHASE_FLOW;
278  }
279 
280  // Step 4: for each elevation above the reference elevation, compute the pressure
281 
282  localIndex const numEntriesAboveRef = size - iRef - 1;
283  forAll< serialPolicy >( numEntriesAboveRef, [=, &returnVal] ( localIndex const i )
284  {
285  ReturnType const returnValAboveRef =
286  computeHydrostaticPressure( numComps,
287  numPhases,
288  ipInit,
289  maxNumEquilIterations,
290  equilTolerance,
291  gravVector,
292  fluidWrapper,
293  compFracTableWrappers,
294  tempTableWrapper,
295  elevationValues[0][iRef+i],
296  pressureValues[iRef+i],
297  phaseMassDens[iRef+i],
298  elevationValues[0][iRef+i+1],
299  pressureValues[iRef+i+1],
300  phaseMassDens[iRef+i+1] );
301  if( returnValAboveRef == ReturnType::FAILED_TO_CONVERGE )
302  {
303  returnVal = ReturnType::FAILED_TO_CONVERGE;
304  }
305  else if( ( returnValAboveRef == ReturnType::DETECTED_MULTIPHASE_FLOW ) &&
306  ( returnVal != ReturnType::FAILED_TO_CONVERGE ) )
307  {
308  returnVal = ReturnType::DETECTED_MULTIPHASE_FLOW;
309  }
310 
311  } );
312 
313  // Step 5: for each elevation below the reference elevation, compute the pressure
314 
315  localIndex const numEntriesBelowRef = iRef;
316  forAll< serialPolicy >( numEntriesBelowRef, [=, &returnVal] ( localIndex const i )
317  {
318  ReturnType const returnValBelowRef =
319  computeHydrostaticPressure( numComps,
320  numPhases,
321  ipInit,
322  maxNumEquilIterations,
323  equilTolerance,
324  gravVector,
325  fluidWrapper,
326  compFracTableWrappers,
327  tempTableWrapper,
328  elevationValues[0][iRef-i],
329  pressureValues[iRef-i],
330  phaseMassDens[iRef-i],
331  elevationValues[0][iRef-i-1],
332  pressureValues[iRef-i-1],
333  phaseMassDens[iRef-i-1] );
334  if( returnValBelowRef == ReturnType::FAILED_TO_CONVERGE )
335  {
336  returnVal = ReturnType::FAILED_TO_CONVERGE;
337  }
338  else if( ( returnValBelowRef == ReturnType::DETECTED_MULTIPHASE_FLOW ) &&
339  ( returnVal != ReturnType::FAILED_TO_CONVERGE ) )
340  {
341  returnVal = ReturnType::DETECTED_MULTIPHASE_FLOW;
342  }
343 
344  } );
345 
346  return returnVal;
347  }
348 
349 };
350 
351 } // namespace isothermalCompositionalMultiphaseBaseKernels
352 
353 } // namespace geos
354 
355 
356 #endif //GEOS_PHYSICSSOLVERS_FLUIDFLOW_COMPOSITIONAL_HYDROSTATICPRESSUREKERNEL_HPP
GEOS_HOST_DEVICE real64 compute(IN_ARRAY const &input) const
Interpolate in the table.
ArrayView< T, 1 > arrayView1d
Alias for 1D array view.
Definition: DataTypes.hpp:180
Array< T, 2, PERMUTATION > array2d
Alias for 2D array.
Definition: DataTypes.hpp:192
Array< T, 3, PERMUTATION > array3d
Alias for 3D array.
Definition: DataTypes.hpp:208
LvArray::StackArray< T, NDIM, PERMUTATION, localIndex, MAXSIZE > StackArray
Multidimensional stack-based array type. See LvArray:StackArray for details.
Definition: DataTypes.hpp:156
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
std::int32_t integer
Signed integer type.
Definition: DataTypes.hpp:82
Array< T, 4, PERMUTATION > array4d
Alias for 4D array.
Definition: DataTypes.hpp:224
Array< T, 1 > array1d
Alias for 1D array.
Definition: DataTypes.hpp:176