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