19 #ifndef GEOS_PHYSICSSOLVERS_MULTIPHYSICS_COUPLEDRESERVOIRANDWELLS_HPP
20 #define GEOS_PHYSICSSOLVERS_MULTIPHYSICS_COUPLEDRESERVOIRANDWELLS_HPP
24 #include "common/GEOS_RAJA_Interface.hpp"
25 #include "constitutive/fluid/multifluid/Layouts.hpp"
33 namespace coupledReservoirAndWellKernels
36 using namespace constitutive;
43 template<
integer NC,
integer IS_THERMAL >
50 static constexpr
integer resNumDOF = NC+1+IS_THERMAL;
59 using CP_Deriv = multifluid::DerivativeOffsetC< NC, IS_THERMAL >;
66 static constexpr
integer numDof = WJ_COFFSET::nDer;
69 static constexpr
integer numEqn = WJ_ROFFSET::nEqn - 2;
87 string const wellDofKey,
91 MultiFluidBase
const & fluid,
95 bool const & detectCrossflow,
96 integer & numCrossFlowPerforations,
97 BitFlags< isothermalCompositionalMultiphaseBaseKernels::KernelFlags > kernelFlags )
100 m_numPhases ( fluid.numFluidPhases()),
101 m_rankOffset( rankOffset ),
102 m_compPerfRate( perforationData->getField< fields::well::compPerforationRate >() ),
103 m_dCompPerfRate( perforationData->getField< fields::well::dCompPerforationRate >() ),
104 m_perfWellElemIndex( perforationData->getField< fields::perforation::wellElementIndex >() ),
105 m_wellElemDofNumber( subRegion.getReference<
array1d<
globalIndex > >( wellDofKey ) ),
106 m_resElemDofNumber( resDofNumber ),
107 m_resElementRegion( perforationData->getField< fields::perforation::reservoirElementRegion >() ),
108 m_resElementSubRegion( perforationData->getField< fields::perforation::reservoirElementSubRegion >() ),
109 m_resElementIndex( perforationData->getField< fields::perforation::reservoirElementIndex >() ),
110 m_localRhs( localRhs ),
111 m_localMatrix( localMatrix ),
112 m_detectCrossflow( detectCrossflow ),
113 m_numCrossFlowPerforations( numCrossFlowPerforations ),
114 m_useTotalMassEquation ( kernelFlags.isSet( isothermalCompositionalMultiphaseBaseKernels::KernelFlags::TotalMassEquation ) )
126 template<
typename FUNC = NoOpFunc >
130 FUNC && compFluxKernelOp = NoOpFunc{} )
const
133 using namespace compositionalMultiphaseUtilities;
142 localIndex const er = m_resElementRegion[iperf];
143 localIndex const esr = m_resElementSubRegion[iperf];
144 localIndex const ei = m_resElementIndex[iperf];
147 localIndex const iwelem = m_perfWellElemIndex[iperf];
148 globalIndex const resOffset = m_resElemDofNumber[er][esr][ei];
149 globalIndex const wellElemOffset = m_wellElemDofNumber[iwelem];
151 for(
integer ic = 0; ic < numComp; ++ic )
153 eqnRowIndices[TAG::RES * numComp + ic] = LvArray::integerConversion< localIndex >( resOffset - m_rankOffset ) + ic;
154 eqnRowIndices[TAG::WELL * numComp + ic] = LvArray::integerConversion< localIndex >( wellElemOffset - m_rankOffset ) + WJ_ROFFSET::MASSBAL + ic;
157 for(
integer jdof = 0; jdof < NC+1; ++jdof )
159 dofColIndices[TAG::RES * resNumDOF + jdof] = resOffset + jdof;
160 dofColIndices[TAG::WELL * resNumDOF + jdof] = wellElemOffset + WJ_COFFSET::dP + jdof;
163 if constexpr ( IS_THERMAL )
165 dofColIndices[TAG::RES * resNumDOF + NC+1 ] = resOffset + NC+1;
166 dofColIndices[TAG::WELL * resNumDOF + NC+1 ] = wellElemOffset + WJ_COFFSET::dT;
169 for(
integer ic = 0; ic < numComp; ++ic )
171 localPerf[TAG::RES * numComp + ic] = m_dt * m_compPerfRate[iperf][ic];
172 localPerf[TAG::WELL * numComp + ic] = -m_dt * m_compPerfRate[iperf][ic];
174 if( m_detectCrossflow )
176 if( m_compPerfRate[iperf][ic] > LvArray::NumericLimits< real64 >::epsilon )
178 m_numCrossFlowPerforations += 1;
181 for(
integer ke = 0; ke < 2; ++ke )
183 localIndex localDofIndexPres = ke * resNumDOF;
185 localPerfJacobian[TAG::RES * numComp + ic][localDofIndexPres] = m_dt * m_dCompPerfRate[iperf][ke][ic][CP_Deriv::dP];
186 localPerfJacobian[TAG::WELL * numComp + ic][localDofIndexPres] = -m_dt * m_dCompPerfRate[iperf][ke][ic][CP_Deriv::dP];
187 for(
integer jc = 0; jc < numComp; ++jc )
189 localIndex const localDofIndexComp = localDofIndexPres + jc + 1;
191 localPerfJacobian[TAG::RES * numComp + ic][localDofIndexComp] = m_dt * m_dCompPerfRate[iperf][ke][ic][CP_Deriv::dC+jc];
192 localPerfJacobian[TAG::WELL * numComp + ic][localDofIndexComp] = -m_dt * m_dCompPerfRate[iperf][ke][ic][CP_Deriv::dC+jc];
194 if constexpr ( IS_THERMAL )
196 localIndex localDofIndexTemp = localDofIndexPres + NC + 1;
197 localPerfJacobian[TAG::RES * numComp + ic][localDofIndexTemp] = m_dt * m_dCompPerfRate[iperf][ke][ic][CP_Deriv::dT];
198 localPerfJacobian[TAG::WELL * numComp + ic][localDofIndexTemp] = -m_dt * m_dCompPerfRate[iperf][ke][ic][CP_Deriv::dT];
203 if( m_useTotalMassEquation )
206 stackArray1d< real64, 2 * resNumDOF > work( 2 * resNumDOF );
211 for(
localIndex i = 0; i < localPerf.size(); ++i )
213 if( eqnRowIndices[i] >= 0 && eqnRowIndices[i] < m_localMatrix.numRows() )
215 m_localMatrix.addToRowBinarySearchUnsorted< parallelDeviceAtomic >( eqnRowIndices[i],
216 dofColIndices.data(),
217 localPerfJacobian[i].dataIfContiguous(),
219 RAJA::atomicAdd( parallelDeviceAtomic{}, &m_localRhs[eqnRowIndices[i]], localPerf[i] );
222 compFluxKernelOp( resOffset, wellElemOffset, dofColIndices, iwelem );
235 template<
typename POLICY,
typename KERNEL_TYPE >
238 KERNEL_TYPE
const & kernelComponent )
243 kernelComponent.computeFlux( ie );
273 bool const m_detectCrossflow;
274 integer & m_numCrossFlowPerforations;
275 integer const m_useTotalMassEquation;
298 template<
typename POLICY >
303 string const wellDofKey,
307 MultiFluidBase
const & fluid,
308 integer const & useTotalMassEquation,
309 bool const & detectCrossflow,
310 integer & numCrossFlowPerforations,
315 isothermalCompositionalMultiphaseBaseKernels::internal::kernelLaunchSelectorCompSwitch( numComps, [&](
auto NC )
317 integer constexpr NUM_COMP = NC();
320 BitFlags< isothermalCompositionalMultiphaseBaseKernels::KernelFlags > kernelFlags;
321 if( useTotalMassEquation )
322 kernelFlags.set( isothermalCompositionalMultiphaseBaseKernels::KernelFlags::TotalMassEquation );
328 kernelType kernel( dt, rankOffset, wellDofKey, subRegion, resDofNumber, perforationData, fluid, localRhs, localMatrix, detectCrossflow, numCrossFlowPerforations, kernelFlags );
329 kernelType::template launch< POLICY >( perforationData->
size(), kernel );
341 template<
integer NC,
integer IS_THERMAL >
348 static constexpr
integer resNumDOF = NC+1+IS_THERMAL;
357 using CP_Deriv = multifluid::DerivativeOffsetC< NC, IS_THERMAL >;
362 using Base::m_localRhs;
363 using Base::m_localMatrix;
364 using Base::m_rankOffset;
369 static constexpr
integer numDof = WJ_COFFSET::nDer;
372 static constexpr
integer numEqn = WJ_ROFFSET::nEqn - 2;
391 string const wellDofKey,
395 MultiFluidBase
const & fluid,
398 bool const & detectCrossflow,
399 integer & numCrossFlowPerforations,
400 BitFlags< isothermalCompositionalMultiphaseBaseKernels::KernelFlags > kernelFlags )
411 numCrossFlowPerforations,
413 m_isProducer( isProducer ),
414 m_globalWellElementIndex( subRegion.getGlobalWellElementIndex() ),
415 m_energyPerfFlux( perforationData->getField< fields::well::energyPerforationFlux >()),
416 m_dEnergyPerfFlux( perforationData->getField< fields::well::dEnergyPerforationFlux >())
433 Base::computeFlux( iperf, [&] (
globalIndex const & resOffset,
443 if( m_globalWellElementIndex[iwelem] == 0 )
454 eqnRowIndices[TAG::RES ] = LvArray::integerConversion< localIndex >( resOffset - m_rankOffset ) + NC + 1;
455 eqnRowIndices[TAG::WELL ] = LvArray::integerConversion< localIndex >( wellElemOffset - m_rankOffset ) + WJ_ROFFSET::ENERGYBAL;
458 localPerf[TAG::RES ] = m_dt * m_energyPerfFlux[iperf];
459 localPerf[TAG::WELL ] = -m_dt * m_energyPerfFlux[iperf];
461 for(
integer ke = 0; ke < 2; ++ke )
463 localIndex localDofIndexPres = ke * resNumDOF;
464 localPerfJacobian[TAG::RES ][localDofIndexPres] = m_dt * m_dEnergyPerfFlux[iperf][ke][CP_Deriv::dP];
465 localPerfJacobian[TAG::WELL ][localDofIndexPres] = -m_dt * m_dEnergyPerfFlux[iperf][ke][CP_Deriv::dP];
468 for(
integer ic = 0; ic < numComp; ++ic )
470 localIndex const localDofIndexComp = localDofIndexPres + ic + 1;
471 localPerfJacobian[TAG::RES ][localDofIndexComp] = m_dt * m_dEnergyPerfFlux[iperf][ke][CP_Deriv::dC+ic];
472 localPerfJacobian[TAG::WELL][localDofIndexComp] = -m_dt * m_dEnergyPerfFlux[iperf][ke][CP_Deriv::dC+ic];
474 localPerfJacobian[TAG::RES ][localDofIndexPres+NC+1] = m_dt * m_dEnergyPerfFlux[iperf][ke][CP_Deriv::dT];
475 localPerfJacobian[TAG::WELL][localDofIndexPres+NC+1] = -m_dt * m_dEnergyPerfFlux[iperf][ke][CP_Deriv::dT];
479 for(
localIndex i = 0; i < localPerf.size(); ++i )
481 if( eqnRowIndices[i] >= 0 && eqnRowIndices[i] < m_localMatrix.numRows() )
483 m_localMatrix.template addToRowBinarySearchUnsorted< parallelDeviceAtomic >( eqnRowIndices[i],
484 dofColIndices.data(),
485 localPerfJacobian[i].dataIfContiguous(),
487 RAJA::atomicAdd( parallelDeviceAtomic{}, &m_localRhs[eqnRowIndices[i]], localPerf[i] );
504 template<
typename POLICY,
typename KERNEL_TYPE >
507 KERNEL_TYPE
const & kernelComponent )
512 kernelComponent.computeFlux( ie );
550 template<
typename POLICY >
556 string const wellDofKey,
560 MultiFluidBase
const & fluid,
561 integer const & useTotalMassEquation,
562 bool const & detectCrossflow,
563 integer & numCrossFlowPerforations,
568 isothermalCompositionalMultiphaseBaseKernels::internal::kernelLaunchSelectorCompSwitch( numComps, [&](
auto NC )
570 integer constexpr NUM_COMP = NC();
573 BitFlags< isothermalCompositionalMultiphaseBaseKernels::KernelFlags > kernelFlags;
574 if( useTotalMassEquation )
575 kernelFlags.set( isothermalCompositionalMultiphaseBaseKernels::KernelFlags::TotalMassEquation );
581 kernelType kernel( dt, isProducer, rankOffset, wellDofKey, subRegion, resDofNumber, perforationData, fluid, localRhs, localMatrix, detectCrossflow, numCrossFlowPerforations, kernelFlags );
582 kernelType::template launch< POLICY >( perforationData->
size(), kernel );
GEOS_HOST_DEVICE void shiftBlockRowsAheadByOneAndReplaceFirstRowWithColumnSum(integer const numRowsToShift, integer const numRowsInBlock, integer const numColsInBlock, integer const numBlocks, MATRIX &&mat, VEC &&work)
In each block, shift the elements from 0 to numRowsToShift-1, shifts all rows one position ahead and ...
GEOS_HOST_DEVICE void shiftBlockElementsAheadByOneAndReplaceFirstElementWithSum(integer const numRowsToShift, integer const numRowsInBlock, integer const numBlocks, VEC &&v)
In each block, shift the elements from 0 to numRowsToShift-1 one position ahead and replaces the firs...
#define GEOS_HOST_DEVICE
Marks a host-device function.
#define GEOS_MARK_FUNCTION
Mark function with both Caliper and NVTX if enabled.
typename ElementViewAccessor< VIEWTYPE >::NestedViewTypeConst ElementViewConst
The ElementViewAccessor at the ElementRegionManager level is the type resulting from ElementViewAcces...
This class describes a collection of local well elements and perforations.
static void createAndLaunch(integer const numComps, real64 const dt, globalIndex const rankOffset, string const wellDofKey, WellElementSubRegion const &subRegion, ElementRegionManager::ElementViewConst< arrayView1d< globalIndex const > > const resDofNumber, PerforationData const *const perforationData, MultiFluidBase const &fluid, integer const &useTotalMassEquation, bool const &detectCrossflow, integer &numCrossFlowPerforations, arrayView1d< real64 > const &localRhs, CRSMatrixView< real64, globalIndex const > const &localMatrix)
Create a new kernel and launch.
integer const m_numPhases
Number of phases.
GEOS_HOST_DEVICE void computeFlux(localIndex const iperf, FUNC &&compFluxKernelOp=NoOpFunc{}) const
Compute the local flux contributions to the residual and Jacobian.
IsothermalCompositionalMultiPhaseFluxKernel(real64 const dt, globalIndex const rankOffset, string const wellDofKey, WellElementSubRegion const &subRegion, ElementRegionManager::ElementViewConst< arrayView1d< globalIndex const > > const resDofNumber, PerforationData const *const perforationData, MultiFluidBase const &fluid, arrayView1d< real64 > const &localRhs, CRSMatrixView< real64, globalIndex const > const &localMatrix, bool const &detectCrossflow, integer &numCrossFlowPerforations, BitFlags< isothermalCompositionalMultiphaseBaseKernels::KernelFlags > kernelFlags)
Constructor for the kernel interface.
real64 const m_dt
Time step size.
static void launch(localIndex const numElements, KERNEL_TYPE const &kernelComponent)
Performs the kernel launch.
static void createAndLaunch(integer const numComps, integer const isProducer, real64 const dt, globalIndex const rankOffset, string const wellDofKey, WellElementSubRegion const &subRegion, ElementRegionManager::ElementViewConst< arrayView1d< globalIndex const > > const resDofNumber, PerforationData const *const perforationData, MultiFluidBase const &fluid, integer const &useTotalMassEquation, bool const &detectCrossflow, integer &numCrossFlowPerforations, arrayView1d< real64 > const &localRhs, CRSMatrixView< real64, globalIndex const > const &localMatrix)
Create a new kernel and launch.
GEOS_HOST_DEVICE void computeFlux(localIndex const iperf) const
Compute the local flux contributions to the residual and Jacobian.
ThermalCompositionalMultiPhaseFluxKernel(real64 const dt, integer const isProducer, globalIndex const rankOffset, string const wellDofKey, WellElementSubRegion const &subRegion, ElementRegionManager::ElementViewConst< arrayView1d< globalIndex const > > const resDofNumber, PerforationData const *const perforationData, MultiFluidBase const &fluid, arrayView1d< real64 > const &localRhs, CRSMatrixView< real64, globalIndex const > const &localMatrix, bool const &detectCrossflow, integer &numCrossFlowPerforations, BitFlags< isothermalCompositionalMultiphaseBaseKernels::KernelFlags > kernelFlags)
Constructor for the kernel interface.
arrayView1d< real64 const > const m_energyPerfFlux
Views on energy flux.
static void launch(localIndex const numElements, KERNEL_TYPE const &kernelComponent)
Performs the kernel launch.
integer const m_isProducer
Well type.
arrayView1d< globalIndex const > m_globalWellElementIndex
Global index of local element.
localIndex size() const
Get the "size" of the group, which determines the number of elements in resizable wrappers.
ArrayView< T, 1 > arrayView1d
Alias for 1D array view.
StackArray< T, 2, MAXSIZE > stackArray2d
Alias for 2D stack array.
LvArray::CRSMatrixView< T, COL_INDEX, localIndex const, LvArray::ChaiBuffer > CRSMatrixView
Alias for CRS Matrix View.
GEOS_GLOBALINDEX_TYPE globalIndex
Global index type (for indexing objects across MPI partitions).
StackArray< T, 1, MAXSIZE > stackArray1d
Alias for 1D stack array.
double real64
64-bit floating point type.
GEOS_LOCALINDEX_TYPE localIndex
Local index type (for indexing objects within an MPI partition).
std::int32_t integer
Signed integer type.
ArrayView< T, 4, USD > arrayView4d
Alias for 4D array view.
ArrayView< T, 2, USD > arrayView2d
Alias for 2D array view.
Array< T, 1 > array1d
Alias for 1D array.
ArrayView< T, 3, USD > arrayView3d
Alias for 3D array view.