GEOS
SinglePhaseWellKernels.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_WELLS_SINGLEPHASEWELLKERNELS_HPP
21 #define GEOS_PHYSICSSOLVERS_FLUIDFLOW_WELLS_SINGLEPHASEWELLKERNELS_HPP
22 
23 #include "constitutive/fluid/singlefluid/SingleFluidFields.hpp"
24 #include "constitutive/fluid/singlefluid/SingleFluidBase.hpp"
25 #include "common/DataTypes.hpp"
26 #include "common/GEOS_RAJA_Interface.hpp"
30 #include "physicsSolvers/fluidFlow/wells/WellControls.hpp"
32 
33 namespace geos
34 {
35 
36 namespace singlePhaseWellKernels
37 {
38 
39 // tag to access well and reservoir elements in perforation rates computation
41 {
42  static constexpr integer RES = 0;
43  static constexpr integer WELL = 1;
44 };
45 
46 // tag to access the next and current well elements of a connection
47 struct ElemTag
48 {
49  static constexpr integer CURRENT = 0;
50  static constexpr integer NEXT = 1;
51 };
52 
53 // define the column offset of the derivatives
54 struct ColOffset
55 {
56  static constexpr integer DPRES = 0;
57  static constexpr integer DRATE = 1;
58 };
59 
60 // define the row offset of the residual equations
61 struct RowOffset
62 {
63  static constexpr integer CONTROL = 0;
64  static constexpr integer MASSBAL = 1;
65 };
66 
67 
68 /******************************** ControlEquationHelper ********************************/
69 
71 {
72 
75 
76  // add an epsilon to the checks to avoid control changes due to tiny pressure/rate updates
77  static constexpr real64 EPS = 1e-15;
78 
80  inline
81  static
82  void
83  switchControl( bool const isProducer,
84  WellControls::Control const & currentControl,
85  real64 const & targetBHP,
86  real64 const & targetRate,
87  real64 const & currentBHP,
88  real64 const & currentVolRate,
89  WellControls::Control & newControl );
90 
92  inline
93  static
94  void
95  compute( globalIndex const rankOffset,
96  WellControls::Control const currentControl,
97  real64 const & targetBHP,
98  real64 const & targetRate,
99  real64 const & currentBHP,
100  real64 const & dCurrentBHP_dPres,
101  real64 const & currentVolRate,
102  real64 const & dCurrentVolRate_dPres,
103  real64 const & dCurrentVolRate_dRate,
104  globalIndex const dofNumber,
105  CRSMatrixView< real64, globalIndex const > const & localMatrix,
106  arrayView1d< real64 > const & localRhs );
107 
108 };
109 
110 
111 /******************************** FluxKernel ********************************/
112 
114 {
115 
119 
120  static void
121  launch( localIndex const size,
122  globalIndex const rankOffset,
123  arrayView1d< globalIndex const > const & wellElemDofNumber,
124  arrayView1d< localIndex const > const & nextWellElemIndex,
125  arrayView1d< real64 const > const & connRate,
126  real64 const & dt,
127  CRSMatrixView< real64, globalIndex const > const & localMatrix,
128  arrayView1d< real64 > const & localRhs );
129 
130 };
131 
132 
133 /******************************** PressureRelationKernel ********************************/
134 
136 {
137 
141 
142  static localIndex
143  launch( localIndex const size,
144  globalIndex const rankOffset,
145  bool const isLocallyOwned,
146  localIndex const iwelemControl,
147  WellControls const & wellControls,
148  real64 const & timeAtEndOfStep,
149  arrayView1d< globalIndex const > const & wellElemDofNumber,
150  arrayView1d< real64 const > const & wellElemGravCoef,
151  arrayView1d< localIndex const > const & nextWellElemIndex,
152  arrayView1d< real64 const > const & wellElemPressure,
153  arrayView2d< real64 const > const & wellElemDensity,
154  arrayView2d< real64 const > const & dWellElemDensity_dPres,
155  CRSMatrixView< real64, globalIndex const > const & localMatrix,
156  arrayView1d< real64 > const & localRhs );
157 
158 };
159 
160 
161 /******************************** PerforationKernel ********************************/
162 
164 {
165 
167 
170 
171  using SingleFluidAccessors =
172  StencilMaterialAccessors< constitutive::SingleFluidBase,
173  fields::singlefluid::density,
174  fields::singlefluid::dDensity_dPressure,
175  fields::singlefluid::viscosity,
176  fields::singlefluid::dViscosity_dPressure >;
177 
185  template< typename VIEWTYPE >
187 
189  inline
190  static
191  void
192  compute( real64 const & resPressure,
193  real64 const & resDensity,
194  real64 const & dResDensity_dPres,
195  real64 const & resViscosity,
196  real64 const & dResViscosity_dPres,
197  real64 const & wellElemGravCoef,
198  real64 const & wellElemPressure,
199  real64 const & wellElemDensity,
200  real64 const & dWellElemDensity_dPres,
201  real64 const & wellElemViscosity,
202  real64 const & dWellElemViscosity_dPres,
203  real64 const & perfGravCoef,
204  real64 const & trans,
205  real64 & perfRate,
206  arraySlice1d< real64 > const & dPerfRate_dPres );
207 
208  static void
209  launch( localIndex const size,
210  ElementViewConst< arrayView1d< real64 const > > const & resPressure,
211  ElementViewConst< arrayView2d< real64 const > > const & resDensity,
212  ElementViewConst< arrayView2d< real64 const > > const & dResDensity_dPres,
213  ElementViewConst< arrayView2d< real64 const > > const & resViscosity,
214  ElementViewConst< arrayView2d< real64 const > > const & dResViscosity_dPres,
215  arrayView1d< real64 const > const & wellElemGravCoef,
216  arrayView1d< real64 const > const & wellElemPressure,
217  arrayView2d< real64 const > const & wellElemDensity,
218  arrayView2d< real64 const > const & dWellElemDensity_dPres,
219  arrayView2d< real64 const > const & wellElemViscosity,
220  arrayView2d< real64 const > const & dWellElemViscosity_dPres,
221  arrayView1d< real64 const > const & perfGravCoef,
222  arrayView1d< localIndex const > const & perfWellElemIndex,
223  arrayView1d< real64 const > const & perfTransmissibility,
224  arrayView1d< localIndex const > const & resElementRegion,
225  arrayView1d< localIndex const > const & resElementSubRegion,
226  arrayView1d< localIndex const > const & resElementIndex,
227  arrayView1d< real64 > const & perfRate,
228  arrayView2d< real64 > const & dPerfRate_dPres );
229 
230 };
231 
232 /******************************** AccumulationKernel ********************************/
233 
235 {
236 
239 
240  static void
241  launch( localIndex const size,
242  globalIndex const rankOffset,
243  arrayView1d< globalIndex const > const & wellElemDofNumber,
244  arrayView1d< integer const > const & wellElemGhostRank,
245  arrayView1d< real64 const > const & wellElemVolume,
246  arrayView2d< real64 const > const & wellElemDensity,
247  arrayView2d< real64 const > const & dWellElemDensity_dPres,
248  arrayView2d< real64 const > const & wellElemDensity_n,
249  CRSMatrixView< real64, globalIndex const > const & localMatrix,
250  arrayView1d< real64 > const & localRhs );
251 
252 };
253 
254 /******************************** PressureInitializationKernel ********************************/
255 
257 {
258 
261 
262  using SingleFluidAccessors =
263  StencilMaterialAccessors< constitutive::SingleFluidBase,
264  fields::singlefluid::density >;
265 
273  template< typename VIEWTYPE >
275 
276  static void
277  launch( localIndex const perforationSize,
278  localIndex const subRegionSize,
279  localIndex const numPerforations,
280  WellControls const & wellControls,
281  real64 const & currentTime,
282  ElementViewConst< arrayView1d< real64 const > > const & resPressure,
283  ElementViewConst< arrayView2d< real64 const > > const & resDensity,
284  arrayView1d< localIndex const > const & resElementRegion,
285  arrayView1d< localIndex const > const & resElementSubRegion,
286  arrayView1d< localIndex const > const & resElementIndex,
287  arrayView1d< real64 const > const & perfGravCoef,
288  arrayView1d< real64 const > const & wellElemGravCoef,
289  arrayView1d< real64 > const & wellElemPressure );
290 
291 };
292 
293 /******************************** RateInitializationKernel ********************************/
294 
296 {
297 
298  static void
299  launch( localIndex const subRegionSize,
300  WellControls const & wellControls,
301  real64 const & currentTime,
302  arrayView2d< real64 const > const & wellElemDens,
303  arrayView1d< real64 > const & connRate );
304 
305 };
306 
307 
308 /******************************** ResidualNormKernel ********************************/
309 
314 {
315 public:
316 
318  using Base::m_minNormalizer;
319  using Base::m_rankOffset;
320  using Base::m_localResidual;
321  using Base::m_dofNumber;
322 
323  ResidualNormKernel( globalIndex const rankOffset,
324  arrayView1d< real64 const > const & localResidual,
325  arrayView1d< globalIndex const > const & dofNumber,
327  WellElementSubRegion const & subRegion,
328  constitutive::SingleFluidBase const & fluid,
329  WellControls const & wellControls,
330  real64 const timeAtEndOfStep,
331  real64 const dt,
332  real64 const minNormalizer )
333  : Base( rankOffset,
334  localResidual,
335  dofNumber,
336  ghostRank,
337  minNormalizer ),
338  m_dt( dt ),
339  m_isLocallyOwned( subRegion.isLocallyOwned() ),
341  m_currentControl( wellControls.getControl() ),
342  m_targetBHP( wellControls.getTargetBHP( timeAtEndOfStep ) ),
343  m_targetRate( wellControls.getTargetTotalRate( timeAtEndOfStep ) ),
344  m_volume( subRegion.getElementVolume() ),
345  m_density_n( fluid.density_n() )
346  {}
347 
349  virtual void computeLinf( localIndex const iwelem,
350  LinfStackVariables & stack ) const override
351  {
352  for( localIndex idof = 0; idof < 2; ++idof )
353  {
354  real64 normalizer = 0.0;
355  if( idof == singlePhaseWellKernels::RowOffset::CONTROL )
356  {
357  // for the top well element, normalize using the current control
358  if( m_isLocallyOwned && iwelem == m_iwelemControl )
359  {
361  {
362  // this residual entry is in pressure units
363  normalizer = m_targetBHP;
364  }
366  {
367  // this residual entry is in volume / time units
368  normalizer = LvArray::math::max( LvArray::math::abs( m_targetRate ), m_minNormalizer );
369  }
370  }
371  // for the pressure difference equation, always normalize by the BHP
372  else
373  {
374  // this residual is in pressure units
375  normalizer = m_targetBHP;
376  }
377  }
378  else // SinglePhaseWell::RowOffset::MASSBAL
379  {
380  // this residual entry is in mass units
381  normalizer = m_dt * LvArray::math::abs( m_targetRate ) * m_density_n[iwelem][0];
382 
383  // to make sure that everything still works well if the rate is zero, we add this check
384  normalizer = LvArray::math::max( normalizer, m_volume[iwelem] * m_density_n[iwelem][0] );
385  }
386 
387  // we have the normalizer now, we can compute a dimensionless Linfty norm contribution
388  real64 const val = LvArray::math::abs( m_localResidual[stack.localRow + idof] ) / normalizer;
389  if( val > stack.localValue[0] )
390  {
391  stack.localValue[0] = val;
392  }
393 
394  }
395  }
396 
398  virtual void computeL2( localIndex const iwelem,
399  L2StackVariables & stack ) const override
400  {
401  GEOS_UNUSED_VAR( iwelem, stack );
402  GEOS_ERROR( "The L2 norm is not implemented for SinglePhaseWell" );
403  }
404 
405 
406 protected:
407 
409  real64 const m_dt;
410 
412  bool const m_isLocallyOwned;
413 
416 
419  real64 const m_targetBHP;
420  real64 const m_targetRate;
421 
424 
427 
428 };
429 
434 {
435 public:
436 
450  template< typename POLICY >
451  static void
452  createAndLaunch( globalIndex const rankOffset,
453  string const & dofKey,
454  arrayView1d< real64 const > const & localResidual,
455  WellElementSubRegion const & subRegion,
456  constitutive::SingleFluidBase const & fluid,
457  WellControls const & wellControls,
458  real64 const timeAtEndOfStep,
459  real64 const dt,
460  real64 const minNormalizer,
461  real64 (& residualNorm)[1] )
462  {
463  arrayView1d< globalIndex const > const dofNumber = subRegion.getReference< array1d< globalIndex > >( dofKey );
464  arrayView1d< integer const > const ghostRank = subRegion.ghostRank();
465 
466  ResidualNormKernel kernel( rankOffset, localResidual, dofNumber, ghostRank, subRegion, fluid, wellControls, timeAtEndOfStep, dt, minNormalizer );
467  ResidualNormKernel::launchLinf< POLICY >( subRegion.size(), kernel, residualNorm );
468  }
469 
470 };
471 
472 } // end namespace singlePhaseWellKernels
473 
474 } // end namespace geos
475 
476 #endif //GEOS_PHYSICSSOLVERS_FLUIDFLOW_WELLS_SINGLEPHASEWELLKERNELS_HPP
#define GEOS_HOST_DEVICE
Marks a host-device function.
Definition: GeosxMacros.hpp:49
#define GEOS_UNUSED_VAR(...)
Mark an unused variable and silence compiler warnings.
Definition: GeosxMacros.hpp:84
#define GEOS_ERROR(msg)
Raise a hard error and terminate the program.
Definition: Logger.hpp:157
typename ElementViewAccessor< VIEWTYPE >::NestedViewTypeConst ElementViewConst
The ElementViewAccessor at the ElementRegionManager level is the type resulting from ElementViewAcces...
arrayView1d< real64 const > getElementVolume() const
Get the volume of each element in this subregion.
array1d< integer > const & ghostRank()
Get the ghost information of each object.
A struct to automatically construct and store element view accessors.
A struct to automatically construct and store element view accessors.
This class describes the controls used to operate a well.
Control getControl() const
Get the control type for the well.
real64 getTargetTotalRate(real64 const &currentTime) const
Get the target total rate.
real64 getTargetBHP(real64 const &currentTime) const
Get the target bottom hole pressure value.
This class describes a collection of local well elements and perforations.
bool isLocallyOwned() const
Check if well is owned by current rank.
localIndex getTopWellElementIndex() const
Get for the top element index.
GEOS_DECLTYPE_AUTO_RETURN getReference(LOOKUP_TYPE const &lookup) const
Look up a wrapper and get reference to wrapped object.
Definition: Group.hpp:1273
localIndex size() const
Get the "size" of the group, which determines the number of elements in resizable wrappers.
Definition: Group.hpp:1315
Define the base interface for the residual calculations.
real64 const m_minNormalizer
Value used to make sure that normalizers are never zero.
arrayView1d< globalIndex const > const m_dofNumber
View on the dof numbers.
GEOS_HOST_DEVICE integer ghostRank(localIndex const i) const
Getter for the ghost rank.
arrayView1d< real64 const > const m_localResidual
View on the local residual.
static void createAndLaunch(globalIndex const rankOffset, string const &dofKey, arrayView1d< real64 const > const &localResidual, WellElementSubRegion const &subRegion, constitutive::SingleFluidBase const &fluid, WellControls const &wellControls, real64 const timeAtEndOfStep, real64 const dt, real64 const minNormalizer, real64(&residualNorm)[1])
Create a new kernel and launch.
arrayView2d< real64 const > const m_density_n
View on total density at the previous converged time step.
bool const m_isLocallyOwned
Flag indicating whether the well is locally owned or not.
arrayView1d< real64 const > const m_volume
View on the volume.
virtual GEOS_HOST_DEVICE void computeL2(localIndex const iwelem, L2StackVariables &stack) const override
Compute the local values and normalizer for the L2 norm.
virtual GEOS_HOST_DEVICE void computeLinf(localIndex const iwelem, LinfStackVariables &stack) const override
Compute the local values for the Linf norm.
localIndex const m_iwelemControl
Index of the element where the control is enforced.
WellControls::Control const m_currentControl
Controls.
ArrayView< T, 1 > arrayView1d
Alias for 1D array view.
Definition: DataTypes.hpp:180
LvArray::CRSMatrixView< T, COL_INDEX, localIndex const, LvArray::ChaiBuffer > CRSMatrixView
Alias for CRS Matrix View.
Definition: DataTypes.hpp:310
GEOS_GLOBALINDEX_TYPE globalIndex
Global index type (for indexing objects across MPI partitions).
Definition: DataTypes.hpp:88
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
ArrayView< T, 2, USD > arrayView2d
Alias for 2D array view.
Definition: DataTypes.hpp:196
Array< T, 1 > array1d
Alias for 1D array.
Definition: DataTypes.hpp:176
ElementRegionManager::ElementViewConst< VIEWTYPE > ElementViewConst
The type for element-based non-constitutive data parameters. Consists entirely of ArrayView's.
ElementRegionManager::ElementViewConst< VIEWTYPE > ElementViewConst
The type for element-based non-constitutive data parameters. Consists entirely of ArrayView's.