GEOS
SinglePhaseWellConstraintKernels.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_WELLS_SINGLEPHASEWELLCONSTRAINTKERNELS_HPP
21 #define GEOS_PHYSICSSOLVERS_FLUIDFLOW_WELLS_SINGLEPHASEWELLCONSTRAINTKERNELS_HPP
22 
23 #include "codingUtilities/Utilities.hpp"
24 #include "constitutive/fluid/singlefluid/SingleFluidBase.hpp"
25 #include "constitutive/fluid/singlefluid/SingleFluidFields.hpp"
26 
27 
28 #include "physicsSolvers/fluidFlow/wells/WellControls.hpp"
29 #include "physicsSolvers/fluidFlow/wells/WellBHPConstraints.hpp"
30 #include "physicsSolvers/fluidFlow/wells/WellVolumeRateConstraint.hpp"
31 
32 
33 namespace geos
34 {
35 
36 namespace singlePhaseWellConstraintKernels
37 {
38 
39 /******************************** ControlEquationHelper ********************************/
40 
41 
42 template< integer IS_THERMAL >
44 {
46  static void setTemperatureDerivative( real64 * const dControlEqn,
47  real64 const value )
48  {
49  if constexpr ( IS_THERMAL )
50  {
52  }
53  }
54 
55  template< BHPConstraintTypeId I >
56  static void assembleConstraintEquation( real64 const & time_n,
57  WellControls & wellControls,
58  BHPConstraint< I > & constraint,
59  WellElementSubRegion const & subRegion,
60  string const & wellDofKey,
61  localIndex const & rankOffset,
63  arrayView1d< real64 > const & localRhs )
64  {
65  // subRegion data
66  localIndex const iwelemRef = subRegion.getTopWellElementIndex();
67  arrayView1d< globalIndex const > const wellElemDofNumber = subRegion.getReference< array1d< globalIndex > >( wellDofKey );
68 
69  constitutive::SingleFluidBase & fluidSeparator = wellControls.getSingleFluidSeparator();
70  arrayView3d< real64 const, constitutive::singlefluid::USD_FLUID_DER > const dDensity = fluidSeparator.dDensity();
71 
72  arrayView1d< real64 const > const wellElemGravCoef = subRegion.getField< fields::well::gravityCoefficient >();
73 
74  // setup row/column indices for constraint equation
77  using Deriv = constitutive::singlefluid::DerivativeOffsetC< IS_THERMAL >;
78 
79  // constraint data
80  real64 const targetBHP = constraint.getConstraintValue( time_n );
81  real64 const refGravCoef = constraint.getReferenceGravityCoef();
82 
83  // current constraint value
84  real64 const currentBHP =
85  wellControls.getReference< real64 >( SinglePhaseWell::viewKeyStruct::currentBHPString() );
86 
87  // The separator is updated on the host. Copy its small set of scalar
88  // derivatives into the device closure and keep the matrix and RHS on device.
89  real64 const dDensity_dP = dDensity[iwelemRef][0][Deriv::dP];
90  real64 dDensity_dT = 0.0;
91  if constexpr ( IS_THERMAL )
92  {
93  dDensity_dT = dDensity[iwelemRef][0][Deriv::dT];
94  }
95 
96  forAll< parallelDevicePolicy<> >( 1, [=] GEOS_HOST_DEVICE ( localIndex const )
97  {
98  globalIndex const dofNumber = wellElemDofNumber[iwelemRef];
99  localIndex const eqnRowIndex = LvArray::integerConversion< localIndex >( dofNumber + ROFFSET_WJ::CONTROL - rankOffset );
100  globalIndex dofColIndices[COFFSET_WJ::nDer]{};
101  for( integer i = 0; i < COFFSET_WJ::nDer; ++i )
102  {
103  dofColIndices[ i ] = dofNumber + i;
104  }
105 
106  real64 const diffGravCoef = refGravCoef - wellElemGravCoef[iwelemRef];
107  real64 dControlEqn[2+IS_THERMAL]{};
108  dControlEqn[COFFSET_WJ::dP] = 1.0 + dDensity_dP * diffGravCoef;
109  setTemperatureDerivative( dControlEqn, dDensity_dT * diffGravCoef );
110 
111  RAJA::atomicAdd( parallelDeviceAtomic{}, &localRhs[eqnRowIndex], currentBHP - targetBHP );
112  localMatrix.addToRowBinarySearchUnsorted< parallelDeviceAtomic >( eqnRowIndex,
113  dofColIndices,
114  dControlEqn,
115  COFFSET_WJ::nDer );
116  } );
117  }
118  template< template< typename U > class T, typename U=VolumeRateConstraint >
119  static void assembleConstraintEquation( real64 const & time_n,
120  WellControls & wellControls,
121  T< VolumeRateConstraint > & constraint,
122  WellElementSubRegion const & subRegion,
123  string const & wellDofKey,
124  localIndex const & rankOffset,
125  CRSMatrixView< real64, globalIndex const > const & localMatrix,
126  arrayView1d< real64 > const & localRhs )
127  {
128  // subRegion data
129 
130  localIndex const iwelemRef = subRegion.getTopWellElementIndex();
131  arrayView1d< globalIndex const > const wellElemDofNumber = subRegion.getReference< array1d< globalIndex > >( wellDofKey );
132 
133  // setup row/column indices for constraint equation
136  using Deriv = constitutive::singlefluid::DerivativeOffsetC< IS_THERMAL >;
137 
138  // fluid data
139  constitutive::SingleFluidBase & fluidSeparator = wellControls.getSingleFluidSeparator();
140  arrayView2d< real64 const, constitutive::singlefluid::USD_FLUID > const density = fluidSeparator.density();
141  arrayView3d< real64 const, constitutive::singlefluid::USD_FLUID_DER > const dDensity = fluidSeparator.dDensity();
142 
143  // constraint data
144  real64 const targetVolRate = constraint.getConstraintValue( time_n );
145 
146  // current constraint value
147  real64 const currentVolRate =
148  wellControls.getReference< real64 >( WellControls::viewKeyStruct::currentVolRateString() );
149 
150  integer const useSurfaceConditions = wellControls.useSurfaceConditions();
151 
152  // The separator is updated on the host. Copy its small set of scalar
153  // properties into the device closure and keep the matrix and RHS on device.
154  real64 const densityRef = density[iwelemRef][0];
155  real64 const dDensity_dP = dDensity[iwelemRef][0][Deriv::dP];
156  real64 dDensity_dT = 0.0;
157  if constexpr ( IS_THERMAL )
158  {
159  dDensity_dT = dDensity[iwelemRef][0][Deriv::dT];
160  }
161 
162  forAll< parallelDevicePolicy<> >( 1, [=] GEOS_HOST_DEVICE ( localIndex const )
163  {
164  globalIndex const dofNumber = wellElemDofNumber[iwelemRef];
165  localIndex const eqnRowIndex = LvArray::integerConversion< localIndex >( dofNumber + ROFFSET_WJ::CONTROL - rankOffset );
166  globalIndex dofColIndices[COFFSET_WJ::nDer]{};
167  for( integer i = 0; i < COFFSET_WJ::nDer; ++i )
168  {
169  dofColIndices[ i ] = dofNumber + i;
170  }
171 
172  real64 const densInv = 1.0 / densityRef;
173  real64 dControlEqn[2+IS_THERMAL]{};
174  dControlEqn[COFFSET_WJ::dP] = -( useSurfaceConditions == 0 ) * dDensity_dP * currentVolRate * densInv;
175  dControlEqn[COFFSET_WJ::dQ] = densInv;
176  setTemperatureDerivative( dControlEqn,
177  -( useSurfaceConditions == 0 ) * dDensity_dT * currentVolRate * densInv );
178 
179  RAJA::atomicAdd( parallelDeviceAtomic{}, &localRhs[eqnRowIndex], currentVolRate - targetVolRate );
180  localMatrix.addToRowBinarySearchUnsorted< parallelDeviceAtomic >( eqnRowIndex,
181  dofColIndices,
182  dControlEqn,
183  COFFSET_WJ::nDer );
184  } );
185  }
186 };
187 
188 } // end namespace wellConstraintKernels
189 
190 } // end namespace geos
191 
192 #endif //GEOS_PHYSICSSOLVERS_FLUIDFLOW_WELLS_WELLCONSTRAINTKERNELS_HPP
#define GEOS_HOST_DEVICE
Marks a host-device function.
Definition: GeosxMacros.hpp:49
This class describes a minimum pressure constraint used to control a injection well.
real64 getReferenceGravityCoef() const
Getter for the reference gravity coefficient.
GEOS_DECLTYPE_AUTO_RETURN getField() const
Get a view to the field associated with a trait from this ObjectManagerBase.
This class describes a volume rate constraint used to control a well.
real64 getConstraintValue(real64 const &currentTime) const
Get the target bottom hole pressure value.
This class describes the controls used to operate a well.
This class describes a collection of local well elements and perforations.
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
integer useSurfaceConditions() const
Getter for the flag specifying whether we check rates at surface or reservoir conditions.
constitutive::SingleFluidBase & getSingleFluidSeparator()
Getter for single fluid separator.
ArrayView< T, 1 > arrayView1d
Alias for 1D array view.
Definition: DataTypes.hpp:179
GEOS_GLOBALINDEX_TYPE globalIndex
Global index type (for indexing objects across MPI partitions).
Definition: DataTypes.hpp:87
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
LvArray::CRSMatrixView< T, COL_INDEX, INDEX_TYPE const, LvArray::ChaiBuffer > CRSMatrixView
Alias for CRS Matrix View.
Definition: DataTypes.hpp:309
ArrayView< T, 2, USD > arrayView2d
Alias for 2D array view.
Definition: DataTypes.hpp:195
int integer
Signed integer type.
Definition: DataTypes.hpp:81
Array< T, 1 > array1d
Alias for 1D array.
Definition: DataTypes.hpp:175
ArrayView< T, 3, USD > arrayView3d
Alias for 3D array view.
Definition: DataTypes.hpp:211