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 {
45  static void assembleConstraintEquation( real64 const & time_n,
46  WellControls & wellControls,
47  BHPConstraint & constraint,
48  WellElementSubRegion const & subRegion,
49  string const & wellDofKey,
50  localIndex const & rankOffset,
52  arrayView1d< real64 > const & localRhs )
53  {
54  // subRegion data
55  localIndex const iwelemRef = subRegion.getTopWellElementIndex();
56  arrayView1d< globalIndex const > const & wellElemDofNumber = subRegion.getReference< array1d< globalIndex > >( wellDofKey );
57  arrayView1d< real64 const > const & pres = subRegion.getField< fields::well::pressure >();
58 
59  constitutive::SingleFluidBase & fluidSeparator = wellControls.getSingleFluidSeparator();
60  arrayView2d< real64 const, constitutive::singlefluid::USD_FLUID > const & density = fluidSeparator.density();
61  arrayView3d< real64 const, constitutive::singlefluid::USD_FLUID_DER > const & dDensity = fluidSeparator.dDensity();
62 
63  arrayView1d< real64 const > const wellElemGravCoef = subRegion.getField< fields::well::gravityCoefficient >();
64 
65  // setup row/column indices for constraint equation
68  using Deriv = constitutive::singlefluid::DerivativeOffsetC< IS_THERMAL >;
69 
70  localIndex const eqnRowIndex = wellElemDofNumber[iwelemRef] + ROFFSET_WJ::CONTROL - rankOffset;
71  globalIndex dofColIndices[COFFSET_WJ::nDer]{};
72  for( integer i = 0; i < COFFSET_WJ::nDer; ++i )
73  {
74  dofColIndices[ i ] = wellElemDofNumber[iwelemRef] + i;
75  }
76  // constraint data
77  real64 const & targetBHP = constraint.getConstraintValue( time_n );
78  real64 const & refGravCoef = constraint.getReferenceGravityCoef();
79 
80  // current constraint value
81  real64 const & currentBHP =
82  wellControls.getReference< real64 >( SinglePhaseWell::viewKeyStruct::currentBHPString() );
83 
84  // residual
85  real64 controlEqn = currentBHP - targetBHP;
86 
87  // setup Jacobian terms
88  real64 dControlEqn[2+IS_THERMAL]{};
89 
90  // bring everything back to host, capture the scalars by reference
91  forAll< serialPolicy >( 1, [pres,
92  density,
93  dDensity,
94  wellElemGravCoef,
95  &dControlEqn,
96  &iwelemRef,
97  &refGravCoef] ( localIndex const )
98  {
99  real64 const diffGravCoef = refGravCoef - wellElemGravCoef[iwelemRef];
100  dControlEqn[COFFSET_WJ::dP] = 1.0 + dDensity[iwelemRef][0][Deriv::dP] *diffGravCoef;
101  if constexpr ( IS_THERMAL )
102  {
103  dControlEqn[COFFSET_WJ::dT] = dDensity[iwelemRef][0][Deriv::dT] * diffGravCoef;
104  }
105  } );
106 
107  // add solver matrices
108  localRhs[eqnRowIndex] += controlEqn;
109  localMatrix.addToRowBinarySearchUnsorted< serialAtomic >( eqnRowIndex,
110  dofColIndices,
111  dControlEqn,
112  COFFSET_WJ::nDer );
113  }
114  template< template< typename U > class T, typename U=VolumeRateConstraint >
115  static void assembleConstraintEquation( real64 const & time_n,
116  WellControls & wellControls,
117  T< VolumeRateConstraint > & constraint,
118  WellElementSubRegion const & subRegion,
119  string const & wellDofKey,
120  localIndex const & rankOffset,
121  CRSMatrixView< real64, globalIndex const > const & localMatrix,
122  arrayView1d< real64 > const & localRhs )
123  {
124  // subRegion data
125 
126  localIndex const iwelemRef = subRegion.getTopWellElementIndex();
127  arrayView1d< globalIndex const > const & wellElemDofNumber = subRegion.getReference< array1d< globalIndex > >( wellDofKey );
128 
129 
130  // setup row/column indices for constraint equation
133  using Deriv = constitutive::singlefluid::DerivativeOffsetC< IS_THERMAL >;
134 
135  localIndex const eqnRowIndex = wellElemDofNumber[iwelemRef] + ROFFSET_WJ::CONTROL - rankOffset;
136  globalIndex dofColIndices[COFFSET_WJ::nDer]{};
137  for( integer i = 0; i < COFFSET_WJ::nDer; ++i )
138  {
139  dofColIndices[ i ] = wellElemDofNumber[iwelemRef] + i;
140  }
141 
142  // fluid data
143  constitutive::SingleFluidBase & fluidSeparator = wellControls.getSingleFluidSeparator();
144  arrayView2d< real64 const, constitutive::singlefluid::USD_FLUID > const & density = fluidSeparator.density();
145  arrayView3d< real64 const, constitutive::singlefluid::USD_FLUID_DER > const & dDensity = fluidSeparator.dDensity();
146 
147  // constraint data
148  real64 const & targetVolRate = constraint.getConstraintValue( time_n );
149 
150  // current constraint value
151  real64 & currentVolRate =
152  wellControls.getReference< real64 >( SinglePhaseWell::viewKeyStruct::currentVolRateString() );
153 
154  integer const useSurfaceConditions = wellControls.useSurfaceConditions();
155 
156  // residual
157  real64 controlEqn = currentVolRate - targetVolRate;
158 
159  // setup Jacobian terms
160  real64 dControlEqn[2+IS_THERMAL]{};
161 
162  // bring everything back to host, capture the scalars by reference
163  forAll< serialPolicy >( 1, [currentVolRate,
164  density,
165  dDensity,
166  &dControlEqn,
167  &useSurfaceConditions,
168  &iwelemRef] ( localIndex const )
169  {
170  // compute the inverse of the total density and derivatives
171  real64 const densInv = 1.0 / density[iwelemRef][0];
172 
173  dControlEqn[COFFSET_WJ::dP] = -( useSurfaceConditions == 0 ) * dDensity[iwelemRef][0][Deriv::dP] * currentVolRate * densInv;
174  dControlEqn[COFFSET_WJ::dQ] = densInv;
175  if constexpr ( IS_THERMAL )
176  {
177  dControlEqn[COFFSET_WJ::dT] = -( useSurfaceConditions == 0 ) * dDensity[iwelemRef][0][Deriv::dT] * currentVolRate * densInv;
178  }
179 
180  } );
181 
182  // add solver matrices
183  localRhs[eqnRowIndex] += controlEqn;
184  localMatrix.addToRowBinarySearchUnsorted< serialAtomic >( eqnRowIndex,
185  dofColIndices,
186  dControlEqn,
187  COFFSET_WJ::nDer );
188  }
189 };
190 
191 } // end namespace wellConstraintKernels
192 
193 } // end namespace geos
194 
195 #endif //GEOS_PHYSICSSOLVERS_FLUIDFLOW_WELLS_WELLCONSTRAINTKERNELS_HPP
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.
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.
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:1275
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