20 #ifndef GEOS_PHYSICSSOLVERS_MULTIPHYSICS_COUPLEDRESERVOIRANDWELLS_HPP
21 #define GEOS_PHYSICSSOLVERS_MULTIPHYSICS_COUPLEDRESERVOIRANDWELLS_HPP
25 #include "common/GEOS_RAJA_Interface.hpp"
26 #include "constitutive/fluid/multifluid/Layouts.hpp"
34 namespace coupledReservoirAndWellKernels
37 using namespace constitutive;
44 template<
integer NC,
integer IS_THERMAL >
51 static constexpr
integer resNumDOF = NC+1+IS_THERMAL;
60 using CP_Deriv = multifluid::DerivativeOffsetC< NC, IS_THERMAL >;
67 static constexpr
integer numDof = WJ_COFFSET::nDer;
70 static constexpr
integer numEqn = WJ_ROFFSET::nEqn - 2;
88 string const wellDofKey,
92 MultiFluidBase
const & fluid,
96 bool const & detectCrossflow,
97 integer & numCrossFlowPerforations,
98 BitFlags< isothermalCompositionalMultiphaseBaseKernels::KernelFlags > kernelFlags )
101 m_numPhases ( fluid.numFluidPhases()),
102 m_rankOffset( rankOffset ),
103 m_compPerfRate( perforationData->getField< fields::well::compPerforationRate >() ),
104 m_dCompPerfRate( perforationData->getField< fields::well::dCompPerforationRate >() ),
105 m_perfWellElemIndex( perforationData->getField< fields::perforation::wellElementIndex >() ),
106 m_wellElemDofNumber( subRegion.getReference<
array1d<
globalIndex > >( wellDofKey ) ),
107 m_resElemDofNumber( resDofNumber ),
108 m_resElementRegion( perforationData->getField< fields::perforation::reservoirElementRegion >() ),
109 m_resElementSubRegion( perforationData->getField< fields::perforation::reservoirElementSubRegion >() ),
110 m_resElementIndex( perforationData->getField< fields::perforation::reservoirElementIndex >() ),
111 m_localRhs( localRhs ),
112 m_localMatrix( localMatrix ),
113 m_detectCrossflow( detectCrossflow ),
114 m_numCrossFlowPerforations( numCrossFlowPerforations ),
115 m_useTotalMassEquation ( kernelFlags.isSet( isothermalCompositionalMultiphaseBaseKernels::KernelFlags::TotalMassEquation ) )
127 template<
typename FUNC = NoOpFunc >
131 FUNC && compFluxKernelOp = NoOpFunc{} )
const
134 using namespace compositionalMultiphaseUtilities;
143 localIndex const er = m_resElementRegion[iperf];
144 localIndex const esr = m_resElementSubRegion[iperf];
145 localIndex const ei = m_resElementIndex[iperf];
148 localIndex const iwelem = m_perfWellElemIndex[iperf];
149 globalIndex const resOffset = m_resElemDofNumber[er][esr][ei];
150 globalIndex const wellElemOffset = m_wellElemDofNumber[iwelem];
152 for(
integer ic = 0; ic < numComp; ++ic )
154 eqnRowIndices[TAG::RES * numComp + ic] = LvArray::integerConversion< localIndex >( resOffset - m_rankOffset ) + ic;
155 eqnRowIndices[TAG::WELL * numComp + ic] = LvArray::integerConversion< localIndex >( wellElemOffset - m_rankOffset ) + WJ_ROFFSET::MASSBAL + ic;
158 for(
integer jdof = 0; jdof < NC+1; ++jdof )
160 dofColIndices[TAG::RES * resNumDOF + jdof] = resOffset + jdof;
161 dofColIndices[TAG::WELL * resNumDOF + jdof] = wellElemOffset + WJ_COFFSET::dP + jdof;
164 if constexpr ( IS_THERMAL )
166 dofColIndices[TAG::RES * resNumDOF + NC+1 ] = resOffset + NC+1;
167 dofColIndices[TAG::WELL * resNumDOF + NC+1 ] = wellElemOffset + WJ_COFFSET::dT;
170 for(
integer ic = 0; ic < numComp; ++ic )
172 localPerf[TAG::RES * numComp + ic] = m_dt * m_compPerfRate[iperf][ic];
173 localPerf[TAG::WELL * numComp + ic] = -m_dt * m_compPerfRate[iperf][ic];
175 if( m_detectCrossflow )
177 if( m_compPerfRate[iperf][ic] > LvArray::NumericLimits< real64 >::epsilon )
179 m_numCrossFlowPerforations += 1;
182 for(
integer ke = 0; ke < 2; ++ke )
184 localIndex localDofIndexPres = ke * resNumDOF;
186 localPerfJacobian[TAG::RES * numComp + ic][localDofIndexPres] = m_dt * m_dCompPerfRate[iperf][ke][ic][CP_Deriv::dP];
187 localPerfJacobian[TAG::WELL * numComp + ic][localDofIndexPres] = -m_dt * m_dCompPerfRate[iperf][ke][ic][CP_Deriv::dP];
188 for(
integer jc = 0; jc < numComp; ++jc )
190 localIndex const localDofIndexComp = localDofIndexPres + jc + 1;
192 localPerfJacobian[TAG::RES * numComp + ic][localDofIndexComp] = m_dt * m_dCompPerfRate[iperf][ke][ic][CP_Deriv::dC+jc];
193 localPerfJacobian[TAG::WELL * numComp + ic][localDofIndexComp] = -m_dt * m_dCompPerfRate[iperf][ke][ic][CP_Deriv::dC+jc];
195 if constexpr ( IS_THERMAL )
197 localIndex localDofIndexTemp = localDofIndexPres + NC + 1;
198 localPerfJacobian[TAG::RES * numComp + ic][localDofIndexTemp] = m_dt * m_dCompPerfRate[iperf][ke][ic][CP_Deriv::dT];
199 localPerfJacobian[TAG::WELL * numComp + ic][localDofIndexTemp] = -m_dt * m_dCompPerfRate[iperf][ke][ic][CP_Deriv::dT];
204 if( m_useTotalMassEquation )
207 stackArray1d< real64, 2 * resNumDOF > work( 2 * resNumDOF );
212 for(
localIndex i = 0; i < localPerf.size(); ++i )
214 if( eqnRowIndices[i] >= 0 && eqnRowIndices[i] < m_localMatrix.numRows() )
216 m_localMatrix.addToRowBinarySearchUnsorted< parallelDeviceAtomic >( eqnRowIndices[i],
217 dofColIndices.data(),
218 localPerfJacobian[i].dataIfContiguous(),
220 RAJA::atomicAdd( parallelDeviceAtomic{}, &m_localRhs[eqnRowIndices[i]], localPerf[i] );
223 compFluxKernelOp( resOffset, wellElemOffset, dofColIndices, iwelem );
236 template<
typename POLICY,
typename KERNEL_TYPE >
239 KERNEL_TYPE
const & kernelComponent )
244 kernelComponent.computeFlux( ie );
274 bool const m_detectCrossflow;
275 integer & m_numCrossFlowPerforations;
276 integer const m_useTotalMassEquation;
299 template<
typename POLICY >
304 string const wellDofKey,
308 MultiFluidBase
const & fluid,
309 BitFlags< isothermalCompositionalMultiphaseBaseKernels::KernelFlags > kernelFlags,
310 bool const & detectCrossflow,
311 integer & numCrossFlowPerforations,
316 isothermalCompositionalMultiphaseBaseKernels::internal::kernelLaunchSelectorCompSwitch( numComps, [&](
auto NC )
318 integer constexpr NUM_COMP = NC();
321 kernelType kernel( dt, rankOffset, wellDofKey, subRegion, resDofNumber, perforationData,
322 fluid, localRhs, localMatrix, detectCrossflow, numCrossFlowPerforations, kernelFlags );
323 kernelType::template launch< POLICY >( perforationData->
size(), kernel );
335 template<
integer NC,
integer IS_THERMAL >
342 static constexpr
integer resNumDOF = NC+1+IS_THERMAL;
351 using CP_Deriv = multifluid::DerivativeOffsetC< NC, IS_THERMAL >;
356 using Base::m_localRhs;
357 using Base::m_localMatrix;
358 using Base::m_rankOffset;
363 static constexpr
integer numDof = WJ_COFFSET::nDer;
366 static constexpr
integer numEqn = WJ_ROFFSET::nEqn - 2;
385 string const wellDofKey,
389 MultiFluidBase
const & fluid,
392 bool const & detectCrossflow,
393 integer & numCrossFlowPerforations,
394 BitFlags< isothermalCompositionalMultiphaseBaseKernels::KernelFlags > kernelFlags )
405 numCrossFlowPerforations,
407 m_isProducer( isProducer ),
408 m_globalWellElementIndex( subRegion.getGlobalWellElementIndex() ),
409 m_energyPerfFlux( perforationData->getField< fields::well::energyPerforationFlux >()),
410 m_dEnergyPerfFlux( perforationData->getField< fields::well::dEnergyPerforationFlux >())
427 Base::computeFlux( iperf, [&] (
globalIndex const & resOffset,
437 if( m_globalWellElementIndex[iwelem] == 0 )
448 eqnRowIndices[TAG::RES ] = LvArray::integerConversion< localIndex >( resOffset - m_rankOffset ) + NC + 1;
449 eqnRowIndices[TAG::WELL ] = LvArray::integerConversion< localIndex >( wellElemOffset - m_rankOffset ) + WJ_ROFFSET::ENERGYBAL;
452 localPerf[TAG::RES ] = m_dt * m_energyPerfFlux[iperf];
453 localPerf[TAG::WELL ] = -m_dt * m_energyPerfFlux[iperf];
455 for(
integer ke = 0; ke < 2; ++ke )
457 localIndex localDofIndexPres = ke * resNumDOF;
458 localPerfJacobian[TAG::RES ][localDofIndexPres] = m_dt * m_dEnergyPerfFlux[iperf][ke][CP_Deriv::dP];
459 localPerfJacobian[TAG::WELL ][localDofIndexPres] = -m_dt * m_dEnergyPerfFlux[iperf][ke][CP_Deriv::dP];
462 for(
integer ic = 0; ic < numComp; ++ic )
464 localIndex const localDofIndexComp = localDofIndexPres + ic + 1;
465 localPerfJacobian[TAG::RES ][localDofIndexComp] = m_dt * m_dEnergyPerfFlux[iperf][ke][CP_Deriv::dC+ic];
466 localPerfJacobian[TAG::WELL][localDofIndexComp] = -m_dt * m_dEnergyPerfFlux[iperf][ke][CP_Deriv::dC+ic];
468 localPerfJacobian[TAG::RES ][localDofIndexPres+NC+1] = m_dt * m_dEnergyPerfFlux[iperf][ke][CP_Deriv::dT];
469 localPerfJacobian[TAG::WELL][localDofIndexPres+NC+1] = -m_dt * m_dEnergyPerfFlux[iperf][ke][CP_Deriv::dT];
473 for(
localIndex i = 0; i < localPerf.size(); ++i )
475 if( eqnRowIndices[i] >= 0 && eqnRowIndices[i] < m_localMatrix.numRows() )
477 m_localMatrix.template addToRowBinarySearchUnsorted< parallelDeviceAtomic >( eqnRowIndices[i],
478 dofColIndices.data(),
479 localPerfJacobian[i].dataIfContiguous(),
481 RAJA::atomicAdd( parallelDeviceAtomic{}, &m_localRhs[eqnRowIndices[i]], localPerf[i] );
498 template<
typename POLICY,
typename KERNEL_TYPE >
501 KERNEL_TYPE
const & kernelComponent )
506 kernelComponent.computeFlux( ie );
544 template<
typename POLICY >
550 string const wellDofKey,
554 MultiFluidBase
const & fluid,
555 BitFlags< isothermalCompositionalMultiphaseBaseKernels::KernelFlags > kernelFlags,
556 bool const & detectCrossflow,
557 integer & numCrossFlowPerforations,
562 isothermalCompositionalMultiphaseBaseKernels::internal::kernelLaunchSelectorCompSwitch( numComps, [&](
auto NC )
564 integer constexpr NUM_COMP = NC();
567 kernelType kernel( dt, isProducer, rankOffset, wellDofKey, subRegion, resDofNumber, perforationData,
568 fluid, localRhs, localMatrix, detectCrossflow, numCrossFlowPerforations, kernelFlags );
569 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, BitFlags< isothermalCompositionalMultiphaseBaseKernels::KernelFlags > kernelFlags, 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, BitFlags< isothermalCompositionalMultiphaseBaseKernels::KernelFlags > kernelFlags, 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.