20 #ifndef GEOS_PHYSICSSOLVERS_FLUIDFLOW_WELLS_COMPOSITIONALMULTIPHASEWELLKERNELS_HPP
21 #define GEOS_PHYSICSSOLVERS_FLUIDFLOW_WELLS_COMPOSITIONALMULTIPHASEWELLKERNELS_HPP
23 #include "codingUtilities/Utilities.hpp"
25 #include "common/GEOS_RAJA_Interface.hpp"
26 #include "constitutive/fluid/multifluid/MultiFluidBase.hpp"
27 #include "constitutive/fluid/multifluid/MultiFluidFields.hpp"
28 #include "constitutive/relativePermeability/RelativePermeabilityBase.hpp"
29 #include "constitutive/relativePermeability/RelativePermeabilityFields.hpp"
36 #include "physicsSolvers/fluidFlow/kernels/compositional/AccumulationKernel.hpp"
41 #include "physicsSolvers/fluidFlow/wells/WellControls.hpp"
48 namespace compositionalMultiphaseWellKernels
51 static constexpr
real64 minDensForDivision = 1e-10;
56 static constexpr
integer RES = 0;
57 static constexpr
integer WELL = 1;
63 static constexpr
integer CURRENT = 0;
64 static constexpr
integer NEXT = 1;
70 static constexpr
integer DPRES = 0;
71 static constexpr
integer DCOMP = 1;
74 template<
integer NC,
integer IS_THERMAL >
77 template<
integer NC >
80 static constexpr
integer dP = 0;
81 static constexpr
integer dC = 1;
82 static constexpr
integer dQ = dC + NC;
83 static integer constexpr nDer = dQ + 1;
87 template<
integer NC >
90 static constexpr
integer dP = 0;
91 static constexpr
integer dC = 1;
92 static constexpr
integer dQ = dC + NC;
93 static constexpr
integer dT = dQ+1;
101 static constexpr
integer CONTROL = 0;
102 static constexpr
integer MASSBAL = 1;
105 template<
integer NC,
integer IS_THERMAL >
108 template<
integer NC >
111 static constexpr
integer CONTROL = 0;
112 static constexpr
integer MASSBAL = 1;
113 static constexpr
integer VOLBAL = MASSBAL + NC;
114 static constexpr
integer nEqn = VOLBAL+1;
117 template<
integer NC >
120 static constexpr
integer CONTROL = 0;
121 static constexpr
integer MASSBAL = 1;
122 static constexpr
integer VOLBAL = MASSBAL + NC;
123 static constexpr
integer ENERGYBAL = VOLBAL+1;
124 static constexpr
integer nEqn = ENERGYBAL+1;
137 switchControl(
bool const isProducer,
141 real64 const & targetPhaseRate,
142 real64 const & targetTotalRate,
143 real64 const & targetMassRate,
144 real64 const & currentBHP,
146 real64 const & currentTotalVolRate,
149 template<
integer NC,
integer IS_THERMAL >
155 integer const targetPhaseIndex,
157 real64 const & targetPhaseRate,
158 real64 const & targetTotalRate,
159 real64 const & targetMassRate,
160 real64 const & currentBHP,
164 real64 const & currentTotalVolRate,
166 real64 const & massDensity,
177 using Deriv = constitutive::multifluid::DerivativeOffset;
182 template<
integer NC,
integer IS_THERMAL >
186 compute(
real64 const & gravCoef,
187 real64 const & gravCoefNext,
190 real64 const & totalMassDens,
191 real64 const & totalMassDensNext,
195 real64 ( &localPresRelJacobian )[2*(NC+1+IS_THERMAL)] );
197 template<
integer NC,
integer IS_THERMAL >
201 bool const isLocallyOwned,
203 integer const targetPhaseIndex,
205 real64 const & timeAtEndOfStep,
212 bool & controlHasSwitched,
226 template<
integer NC >
230 compute(
integer const numPhases,
235 real64 ( &localVolBalanceJacobian )[NC+1] );
237 template<
integer NC >
259 fields::flow::temperature,
260 fields::flow::globalCompDensity,
261 fields::flow::phaseVolumeFraction >;
265 fields::multifluid::phaseMassDensity >;
275 template<
typename VIEWTYPE >
285 real64 const & currentTime,
323 integer const targetPhaseIndex,
325 real64 const & currentTime,
341 template<
integer NUM_COMP,
integer NUM_PHASE >
358 constitutive::MultiFluidBase
const & fluid )
360 m_phaseVolFrac( subRegion.getField< fields::well::phaseVolumeFraction >() ),
361 m_dPhaseVolFrac( subRegion.getField< fields::well::dPhaseVolumeFraction >() ),
362 m_dCompFrac_dCompDens( subRegion.getField< fields::well::dGlobalCompFraction_dGlobalCompDensity >() ),
364 m_dPhaseMassDens( fluid.dPhaseMassDensity() ),
365 m_totalMassDens( subRegion.getField< fields::well::totalMassDensity >() ),
366 m_dTotalMassDens( subRegion.getField< fields::well::dTotalMassDensity >() )
375 template<
typename FUNC = NoOpFunc >
379 FUNC && totalMassDensityKernelOp = NoOpFunc{} )
const
381 using Deriv = constitutive::multifluid::DerivativeOffset;
384 arraySlice2d<
real64 const, compflow::USD_PHASE_DC - 1 > dPhaseVolFrac = m_dPhaseVolFrac[ei];
385 arraySlice2d<
real64 const, compflow::USD_COMP_DC - 1 > dCompFrac_dCompDens = m_dCompFrac_dCompDens[ei];
387 arraySlice2d<
real64 const, constitutive::multifluid::USD_PHASE_DC - 2 > dPhaseMassDens = m_dPhaseMassDens[ei][0];
389 arraySlice1d<
real64, compflow::USD_FLUID_DC - 1 > dTotalMassDens = m_dTotalMassDens[ei];
395 dTotalMassDens[Deriv::dP]=0.0;
398 dTotalMassDens[Deriv::dC+ic]=0.0;
403 totalMassDens += phaseVolFrac[ip] * phaseMassDens[ip];
404 dTotalMassDens[Deriv::dP] += dPhaseVolFrac[ip][Deriv::dP] * phaseMassDens[ip] + phaseVolFrac[ip] * dPhaseMassDens[ip][Deriv::dP];
406 applyChainRule(
numComp, dCompFrac_dCompDens, dPhaseMassDens[ip], dMassDens_dC, Deriv::dC );
409 dTotalMassDens[Deriv::dC+ic] += dPhaseVolFrac[ip][Deriv::dC+ic] * phaseMassDens[ip]
410 + phaseVolFrac[ip] * dMassDens_dC[ic];
413 totalMassDensityKernelOp( ip );
455 template<
typename POLICY >
460 constitutive::MultiFluidBase
const & fluid )
464 isothermalCompositionalMultiphaseBaseKernels::internal::kernelLaunchSelectorCompSwitch( numComp, [&] (
auto NC )
466 integer constexpr NUM_COMP = NC();
471 else if( numPhase == 3 )
473 isothermalCompositionalMultiphaseBaseKernels::internal::kernelLaunchSelectorCompSwitch( numComp, [&] (
auto NC )
475 integer constexpr NUM_COMP = NC();
505 integer const targetPhaseIndex,
507 constitutive::MultiFluidBase
const & fluid,
509 real64 const timeAtEndOfStep,
511 real64 const minNormalizer )
525 m_targetBHP( wellControls.
getTargetBHP( timeAtEndOfStep ) ),
531 m_totalDens_n( fluid.totalDensity_n() )
536 LinfStackVariables & stack )
const override
547 if( idof == ROFFSET::CONTROL )
556 normalizer = m_targetBHP;
561 normalizer = LvArray::math::max( LvArray::math::abs( m_targetTotalRate ),
m_minNormalizer );
566 normalizer = LvArray::math::max( LvArray::math::abs( m_targetPhaseRate ),
m_minNormalizer );
571 normalizer = LvArray::math::max( LvArray::math::abs( m_targetMassRate ),
m_minNormalizer );
577 normalizer = m_targetBHP;
581 else if( idof >= ROFFSET::MASSBAL && idof < ROFFSET::MASSBAL +
m_numComp )
592 normalizer =
m_dt * LvArray::math::abs( m_targetMassRate );
597 normalizer =
m_dt * LvArray::math::abs( m_targetTotalRate ) * m_totalDens_n[iwelem][0];
603 normalizer = LvArray::math::max( normalizer,
m_volume[iwelem] * m_totalDens_n[iwelem][0] );
606 else if( idof == ROFFSET::MASSBAL +
m_numComp )
611 normalizer =
m_dt * LvArray::math::abs( m_targetPhaseRate );
617 normalizer =
m_dt * LvArray::math::abs( m_targetMassRate/ m_totalDens_n[iwelem][0] );
621 normalizer =
m_dt * LvArray::math::abs( m_targetTotalRate );
629 normalizer = LvArray::math::max( normalizer,
m_volume[iwelem] );
633 if( val > stack.localValue[0] )
635 stack.localValue[0] = val;
642 L2StackVariables & stack )
const override
645 GEOS_ERROR(
"The L2 norm is not implemented for CompositionalMultiphaseWell" );
675 real64 const m_targetTotalRate;
676 real64 const m_targetPhaseRate;
677 real64 const m_targetMassRate;
711 template<
typename POLICY >
715 integer const targetPhaseIndex,
717 string const & dofKey,
720 constitutive::MultiFluidBase
const & fluid,
722 real64 const timeAtEndOfStep,
724 real64 const minNormalizer,
725 real64 (& residualNorm)[1] )
731 numComp, numDof, targetPhaseIndex, subRegion, fluid, wellControls, timeAtEndOfStep, dt, minNormalizer );
732 ResidualNormKernel::launchLinf< POLICY >( subRegion.
size(), kernel, residualNorm );
759 template<
typename POLICY >
762 real64 const maxAbsolutePresChange,
763 real64 const maxCompFracChange,
764 real64 const maxRelativeCompDensChange,
772 subRegion.
getField< fields::well::pressure >();
774 subRegion.
getField< fields::well::globalCompDensity >();
776 subRegion.
getField< fields::well::pressureScalingFactor >();
778 subRegion.
getField< fields::well::globalCompDensityScalingFactor >();
779 isothermalCompositionalMultiphaseBaseKernels::
780 SolutionScalingKernel kernel( maxRelativePresChange, maxAbsolutePresChange, maxCompFracChange, maxRelativeCompDensChange, rankOffset,
781 numComp, dofKey, subRegion, localSolution, pressure, compDens, pressureScalingFactor, compDensScalingFactor );
782 return isothermalCompositionalMultiphaseBaseKernels::
783 SolutionScalingKernel::
784 launch< POLICY >( subRegion.
size(), kernel );
809 template<
typename POLICY >
813 real64 const scalingFactor,
825 isothermalCompositionalMultiphaseBaseKernels::
826 SolutionCheckKernel kernel( allowCompDensChopping, 0, scalingType, scalingFactor,
827 pressure, compDens, pressureScalingFactor, compDensScalingFactor, rankOffset,
828 numComp, dofKey, subRegion, localSolution );
829 return isothermalCompositionalMultiphaseBaseKernels::
830 SolutionCheckKernel::
831 launch< POLICY >( subRegion.
size(), kernel );
844 template<
integer NUM_COMP,
integer IS_THERMAL >
853 using FLUID_PROP_COFFSET = constitutive::multifluid::DerivativeOffsetC< NUM_COMP, IS_THERMAL >;
882 constitutive::MultiFluidBase
const & fluid,
885 BitFlags< isothermalCompositionalMultiphaseBaseKernels::KernelFlags >
const kernelFlags )
892 m_volume( subRegion.getElementVolume() ),
893 m_dCompFrac_dCompDens( subRegion.getField< fields::flow::dGlobalCompFraction_dGlobalCompDensity >() ),
894 m_phaseVolFrac_n( subRegion.getField< fields::flow::phaseVolumeFraction_n >() ),
895 m_phaseVolFrac( subRegion.getField< fields::flow::phaseVolumeFraction >() ),
896 m_dPhaseVolFrac( subRegion.getField< fields::flow::dPhaseVolumeFraction >() ),
898 m_phaseDens( fluid.phaseDensity() ),
899 m_dPhaseDens( fluid.dPhaseDensity() ),
901 m_phaseCompFrac( fluid.phaseCompFraction() ),
902 m_dPhaseCompFrac( fluid.dPhaseCompFraction() ),
903 m_compDens( subRegion.getField< fields::flow::globalCompDensity >() ),
904 m_compDens_n( subRegion.getField< fields::flow::globalCompDensity_n >() ),
907 m_kernelFlags( kernelFlags )
972 if constexpr ( IS_THERMAL )
977 stack.dofColIndices[0] =
m_dofNumber[ei] + WJ_COFFSET::dP;
980 stack.dofColIndices[ic+1] =
m_dofNumber[ei] + WJ_COFFSET::dC+ic;
982 if constexpr ( IS_THERMAL )
1006 template<
typename FUNC = NoOpFunc >
1010 FUNC && phaseAmountKernelOp = NoOpFunc{} )
const
1013 using Deriv = constitutive::multifluid::DerivativeOffset;
1019 arraySlice1d<
real64 const, compflow::USD_PHASE - 1 > phaseVolFrac = m_phaseVolFrac[ei];
1020 arraySlice2d<
real64 const, compflow::USD_PHASE_DC - 1 > dPhaseVolFrac = m_dPhaseVolFrac[ei];
1023 arraySlice1d<
real64 const, constitutive::multifluid::USD_PHASE - 2 > phaseDens = m_phaseDens[ei][0];
1024 arraySlice2d<
real64 const, constitutive::multifluid::USD_PHASE_DC - 2 > dPhaseDens = m_dPhaseDens[ei][0];
1027 arraySlice2d<
real64 const, constitutive::multifluid::USD_PHASE_COMP - 2 > phaseCompFrac = m_phaseCompFrac[ei][0];
1028 arraySlice3d<
real64 const, constitutive::multifluid::USD_PHASE_COMP_DC - 2 > dPhaseCompFrac = m_dPhaseCompFrac[ei][0];
1031 real64 dPhaseAmount[FLUID_PROP_COFFSET::nDer]{};
1038 real64 const phaseAmount = stack.volume * phaseVolFrac[ip] * phaseDens[ip];
1039 real64 const phaseAmount_n = stack.volume * phaseVolFrac_n[ip] * phaseDens_n[ip];
1041 real64 const dPhaseAmount_dP = stack.volume * ( dPhaseVolFrac[ip][Deriv::dP] * phaseDens[ip]
1042 + phaseVolFrac[ip] * dPhaseDens[ip][Deriv::dP] );
1043 dPhaseAmount[FLUID_PROP_COFFSET::dP]=stack.volume * ( dPhaseVolFrac[ip][Deriv::dP] * phaseDens[ip]
1044 + phaseVolFrac[ip] * dPhaseDens[ip][Deriv::dP] );
1047 applyChainRule(
numComp, dCompFrac_dCompDens, dPhaseDens[ip], dPhaseAmount_dC, Deriv::dC );
1048 applyChainRule(
numComp, dCompFrac_dCompDens, dPhaseDens[ip], &dPhaseAmount[FLUID_PROP_COFFSET::dC], Deriv::dC );
1051 dPhaseAmount_dC[jc] = dPhaseAmount_dC[jc] * phaseVolFrac[ip]
1052 + phaseDens[ip] * dPhaseVolFrac[ip][Deriv::dC+jc];
1053 dPhaseAmount_dC[jc] *= stack.volume;
1054 dPhaseAmount[FLUID_PROP_COFFSET::dC+jc] = dPhaseAmount[FLUID_PROP_COFFSET::dC+jc] * phaseVolFrac[ip]
1055 + phaseDens[ip] * dPhaseVolFrac[ip][Deriv::dC+jc];
1056 dPhaseAmount[FLUID_PROP_COFFSET::dC+jc] *= stack.volume;
1061 assert( fabs( dPhaseAmount[FLUID_PROP_COFFSET::dC+ic] -dPhaseAmount_dC[ic] ) < FLT_EPSILON );
1068 real64 const phaseCompAmount = phaseAmount * phaseCompFrac[ip][ic];
1069 real64 const phaseCompAmount_n = phaseAmount_n * phaseCompFrac_n[ip][ic];
1071 real64 const dPhaseCompAmount_dP = dPhaseAmount_dP * phaseCompFrac[ip][ic]
1072 + phaseAmount * dPhaseCompFrac[ip][ic][Deriv::dP];
1074 stack.
localResidual[ic] += phaseCompAmount - phaseCompAmount_n;
1081 applyChainRule(
numComp, dCompFrac_dCompDens, dPhaseCompFrac[ip][ic], dPhaseCompFrac_dC, Deriv::dC );
1084 real64 const dPhaseCompAmount_dC = dPhaseCompFrac_dC[jc] * phaseAmount
1085 + phaseCompFrac[ip][ic] * dPhaseAmount[FLUID_PROP_COFFSET::dC+jc];
1090 if constexpr ( IS_THERMAL )
1092 dPhaseAmount[FLUID_PROP_COFFSET::dT] = stack.volume * (dPhaseVolFrac[ip][Deriv::dT] * phaseDens[ip] + phaseVolFrac[ip] * dPhaseDens[ip][Deriv::dT] );
1096 stack.
localJacobian[ic][
numComp+1] += dPhaseAmount[FLUID_PROP_COFFSET::dT] * phaseCompFrac[ip][ic]
1097 + phaseAmount * dPhaseCompFrac[ip][ic][Deriv::dT];
1102 phaseAmountKernelOp( ip, phaseAmount, phaseAmount_n, dPhaseAmount );
1129 using Deriv = constitutive::multifluid::DerivativeOffset;
1131 arraySlice1d<
real64 const, compflow::USD_PHASE - 1 > phaseVolFrac = m_phaseVolFrac[ei];
1132 arraySlice2d<
real64 const, compflow::USD_PHASE_DC - 1 > dPhaseVolFrac = m_dPhaseVolFrac[ei];
1134 real64 oneMinusPhaseVolFracSum = 1.0;
1141 oneMinusPhaseVolFracSum -= phaseVolFrac[ip];
1149 if constexpr ( IS_THERMAL)
1173 using namespace compositionalMultiphaseUtilities;
1177 if constexpr ( IS_THERMAL)
1198 if( m_kernelFlags.isSet( isothermalCompositionalMultiphaseBaseKernels::KernelFlags::TotalMassEquation ) )
1211 for(
integer i = 0; i < numRows; ++i )
1214 m_localMatrix.addToRow< serialAtomic >( stack.eqnRowIndices[i],
1215 stack.dofColIndices,
1229 template<
typename POLICY,
typename KERNEL_TYPE >
1232 KERNEL_TYPE
const & kernelComponent )
1238 if( kernelComponent.elemGhostRank( ei ) >= 0 )
1243 typename KERNEL_TYPE::StackVariables stack;
1245 kernelComponent.setup( ei, stack );
1246 kernelComponent.computeAccumulation( ei, stack );
1247 kernelComponent.computeVolumeBalance( ei, stack );
1248 kernelComponent.complete( ei, stack );
1307 BitFlags< isothermalCompositionalMultiphaseBaseKernels::KernelFlags >
const m_kernelFlags;
1329 template<
typename POLICY >
1335 integer const useTotalMassEquation,
1336 string const dofKey,
1338 constitutive::MultiFluidBase
const & fluid,
1342 geos::internal::kernelLaunchSelectorCompThermSwitch( numComps, 0, [&](
auto NC,
auto IS_THERMAL )
1346 integer constexpr istherm = IS_THERMAL();
1348 BitFlags< isothermalCompositionalMultiphaseBaseKernels::KernelFlags > kernelFlags;
1349 if( useTotalMassEquation )
1350 kernelFlags.set( isothermalCompositionalMultiphaseBaseKernels::KernelFlags::TotalMassEquation );
1353 kernel( numPhases, isProducer, rankOffset, dofKey, subRegion, fluid, localMatrix, localRhs, kernelFlags );
1355 launch< POLICY, ElementBasedAssemblyKernel< NUM_COMP, istherm > >( subRegion.
size(), kernel );
1367 template<
integer NC,
integer IS_THERMAL >
1376 using FLUID_PROP_COFFSET = constitutive::multifluid::DerivativeOffsetC< NC, IS_THERMAL >;
1380 using CP_Deriv = constitutive::multifluid::DerivativeOffsetC< NC, IS_THERMAL >;
1390 static constexpr
integer maxNumElems = 2;
1391 static constexpr
integer maxStencilSize = 2;
1408 string const wellDofKey,
1413 BitFlags< isothermalCompositionalMultiphaseBaseKernels::KernelFlags > kernelFlags )
1417 m_wellElemDofNumber ( subRegion.getReference<
array1d<
globalIndex > >( wellDofKey ) ),
1419 m_connRate ( subRegion.getField< fields::well::mixtureConnectionRate >() ),
1420 m_wellElemCompFrac ( subRegion.getField< fields::well::globalCompFraction >() ),
1421 m_dWellElemCompFrac_dCompDens ( subRegion.getField< fields::well::dGlobalCompFraction_dGlobalCompDensity >() ),
1424 m_useTotalMassEquation ( kernelFlags.isSet( isothermalCompositionalMultiphaseBaseKernels::KernelFlags::TotalMassEquation ) ),
1426 m_injection ( wellControls.getInjectionStream() )
1440 : stencilSize( size ),
1441 numConnectedElems( 2 ),
1442 dofColIndices( size *
numDof )
1482 if( m_nextWellElemIndex[iconn] <0 )
1503 using namespace compositionalMultiphaseUtilities;
1509 for(
integer ic = 0; ic < NC; ++ic )
1511 oneSidedEqnRowIndices[ic] = stack.offsetUp + WJ_ROFFSET::MASSBAL + ic -
m_rankOffset;
1515 globalIndex oneSidedDofColIndices_dPresCompTempUp[CP_Deriv::nDer]{};
1516 globalIndex oneSidedDofColIndices_dRate = stack.offsetCurrent + WJ_COFFSET::dQ;
1519 oneSidedDofColIndices_dPresCompTempUp[ioff++] = stack.offsetUp + WJ_COFFSET::dP;
1521 if constexpr ( IS_THERMAL )
1523 oneSidedDofColIndices_dPresCompTempUp[ioff++] = stack.offsetUp + WJ_COFFSET::dT;
1525 for(
integer jdof = 0; jdof < NC; ++jdof )
1527 oneSidedDofColIndices_dPresCompTempUp[ioff++] = stack.offsetUp + WJ_COFFSET::dC+ jdof;
1529 if( m_useTotalMassEquation > 0 )
1532 real64 work[CP_Deriv::nDer]{};
1535 shiftElementsAheadByOneAndReplaceFirstElementWithSum(
numEqn, stack.
localFlux );
1539 if( oneSidedEqnRowIndices[i] >= 0 && oneSidedEqnRowIndices[i] <
m_localMatrix.numRows() )
1541 m_localMatrix.addToRow< parallelDeviceAtomic >( oneSidedEqnRowIndices[i],
1542 &oneSidedDofColIndices_dRate,
1545 m_localMatrix.addToRowBinarySearchUnsorted< parallelDeviceAtomic >( oneSidedEqnRowIndices[i],
1546 oneSidedDofColIndices_dPresCompTempUp,
1549 RAJA::atomicAdd( parallelDeviceAtomic{}, &
m_localRhs[oneSidedEqnRowIndices[i]], stack.
localFlux[i] );
1559 for(
integer ic = 0; ic < NC; ++ic )
1562 eqnRowIndices[TAG::NEXT *
numEqn+ic] = stack.offsetNext + WJ_ROFFSET::MASSBAL + ic -
m_rankOffset;
1563 eqnRowIndices[TAG::CURRENT *
numEqn+ic] = stack.offsetCurrent + WJ_ROFFSET::MASSBAL + ic -
m_rankOffset;
1567 globalIndex dofColIndices_dPresCompUp[CP_Deriv::nDer]{};
1568 globalIndex dofColIndices_dRate = stack.offsetCurrent + WJ_COFFSET::dQ;
1572 dofColIndices_dPresCompUp[ioff++] = stack.offsetUp + WJ_COFFSET::dP;
1574 if constexpr ( IS_THERMAL )
1576 dofColIndices_dPresCompUp[ioff++] = stack.offsetUp + WJ_COFFSET::dT;
1578 for(
integer jdof = 0; jdof < NC; ++jdof )
1580 dofColIndices_dPresCompUp[ioff++] = stack.offsetUp + WJ_COFFSET::dC+ jdof;
1584 if( m_useTotalMassEquation > 0 )
1587 real64 work[CP_Deriv::nDer]{};
1593 for(
integer i = 0; i < 2*NC; ++i )
1595 if( eqnRowIndices[i] >= 0 && eqnRowIndices[i] <
m_localMatrix.numRows() )
1597 m_localMatrix.addToRow< parallelDeviceAtomic >( eqnRowIndices[i],
1598 &dofColIndices_dRate,
1601 m_localMatrix.addToRowBinarySearchUnsorted< parallelDeviceAtomic >( eqnRowIndices[i],
1602 dofColIndices_dPresCompUp,
1605 RAJA::atomicAdd( parallelDeviceAtomic{}, &
m_localRhs[eqnRowIndices[i]], stack.
localFlux[i] );
1615 computeExit(
real64 const & dt,
1616 real64 const ( &compFlux )[NC ],
1617 StackVariables & stack,
1620 for(
integer ic = 0; ic < NC; ++ic )
1622 stack.localFlux[ic] = -dt * compFlux[ic];
1624 stack.localFluxJacobian_dQ[ic][0] = -dt * dCompFlux[ic][WJ_COFFSET::dQ];
1626 stack.localFluxJacobian[ic][CP_Deriv::dP] = -dt * dCompFlux[ic][WJ_COFFSET::dP];
1628 for(
integer jdof = 0; jdof < NC; ++jdof )
1630 stack.localFluxJacobian[ic][CP_Deriv::dC+jdof] = -dt * dCompFlux[ic][WJ_COFFSET::dC+jdof];
1632 if constexpr ( IS_THERMAL )
1634 stack.localFluxJacobian[ic][CP_Deriv::dT] = -dt * dCompFlux[ic][WJ_COFFSET::dT];
1642 compute(
real64 const & dt,
1643 real64 const ( &compFlux )[NC ],
1644 StackVariables & stack,
1648 for(
integer ic = 0; ic < NC; ++ic )
1650 stack.localFlux[TAG::NEXT * NC +ic] = dt * compFlux[ic];
1651 stack.localFlux[TAG::CURRENT * NC +ic] = -dt * compFlux[ic];
1653 stack.localFluxJacobian_dQ[TAG::NEXT * NC+ ic][0] = dt * dCompFlux[ic][WJ_COFFSET::dQ];
1654 stack.localFluxJacobian_dQ[TAG::CURRENT * NC + +ic][0] = -dt * dCompFlux[ic][WJ_COFFSET::dQ];
1657 stack.localFluxJacobian[TAG::NEXT * NC +ic][CP_Deriv::dP] = dt * dCompFlux[ic][WJ_COFFSET::dP];
1658 stack.localFluxJacobian[TAG::CURRENT * NC+ ic][CP_Deriv::dP] = -dt * dCompFlux[ic][WJ_COFFSET::dP];
1660 if constexpr ( IS_THERMAL )
1662 stack.localFluxJacobian[TAG::NEXT * NC +ic][CP_Deriv::dT] = dt * dCompFlux[ic][WJ_COFFSET::dT];
1663 stack.localFluxJacobian[TAG::CURRENT * NC +ic][CP_Deriv::dT] = -dt * dCompFlux[ic][WJ_COFFSET::dT];
1667 for(
integer jdof = 0; jdof < NC; ++jdof )
1669 stack.localFluxJacobian[TAG::NEXT * NC +ic][CP_Deriv::dC+jdof] = dt * dCompFlux[ic][WJ_COFFSET::dC+jdof];
1670 stack.localFluxJacobian[TAG::CURRENT * NC +ic][CP_Deriv::dC+jdof] = -dt * dCompFlux[ic][WJ_COFFSET::dC+jdof];
1682 template<
typename FUNC = NoOpFunc >
1687 FUNC && compFluxKernelOp = NoOpFunc{} )
const
1690 using namespace compositionalMultiphaseUtilities;
1697 for(
integer ic = 0; ic < NC; ++ic )
1699 for(
integer jc = 0; jc < NC; ++jc )
1712 localIndex const iwelemNext = m_nextWellElemIndex[iwelem];
1713 real64 const currentConnRate = m_connRate[iwelem];
1722 for(
integer ic = 0; ic < NC; ++ic )
1724 compFracUp[ic] = m_injection[ic];
1725 for(
integer jc = 0; jc < NC; ++jc )
1727 dComp[ic][jc] = m_dWellElemCompFrac_dCompDens[iwelemUp][ic][jc];
1729 for(
integer jc = 0; jc < NC; ++jc )
1731 dCompFlux[ic][WJ_COFFSET::dC+jc] = 0.0;
1739 || currentConnRate < 0 )
1745 iwelemUp = iwelemNext;
1749 for(
integer ic = 0; ic < NC; ++ic )
1751 compFracUp[ic] = m_wellElemCompFrac[iwelemUp][ic];
1752 for(
integer jc = 0; jc < NC; ++jc )
1754 dCompFlux[ic][WJ_COFFSET::dC+jc] = m_dWellElemCompFrac_dCompDens[iwelemUp][ic][jc];
1755 dComp[ic][jc] = m_dWellElemCompFrac_dCompDens[iwelemUp][ic][jc];
1762 for(
integer ic = 0; ic < NC; ++ic )
1764 compFlux[ic] = compFracUp[ic] * currentConnRate;
1765 dCompFlux[ic][WJ_COFFSET::dQ] = compFracUp[ic];
1767 dCompFlux[ic][WJ_COFFSET::dP] = 0.0;
1768 if constexpr ( IS_THERMAL )
1770 dCompFlux[ic][WJ_COFFSET::dT] = 0.0;
1772 for(
integer jc = 0; jc < NC; ++jc )
1774 dCompFlux[ic][WJ_COFFSET::dC+jc] = dCompFlux[ic][WJ_COFFSET::dC+jc] * currentConnRate;
1778 stack.offsetUp = m_wellElemDofNumber[iwelemUp];
1779 stack.iwelemUp = iwelemUp;
1780 stack.offsetCurrent = m_wellElemDofNumber[iwelem];
1781 stack.iwelemCurrent= iwelem;
1784 if( iwelemNext < 0 )
1800 stack.offsetNext = m_wellElemDofNumber[iwelemNext];
1802 stack.iwelemNext = iwelemNext;
1803 compFluxKernelOp( iwelemNext, iwelemUp, currentConnRate, dComp );
1814 template<
typename POLICY,
typename KERNEL_TYPE >
1817 KERNEL_TYPE
const & kernelComponent )
1822 typename KERNEL_TYPE::StackVariables stack( 1 );
1824 kernelComponent.setup( ie, stack );
1825 kernelComponent.computeFlux( ie, stack );
1826 kernelComponent.complete( ie, stack );
1887 template<
typename POLICY >
1892 integer const useTotalMassEquation,
1893 string const dofKey,
1899 isothermalCompositionalMultiphaseBaseKernels::internal::kernelLaunchSelectorCompSwitch( numComps, [&](
auto NC )
1901 integer constexpr NUM_COMP = NC();
1904 BitFlags< isothermalCompositionalMultiphaseBaseKernels::KernelFlags > kernelFlags;
1905 if( useTotalMassEquation )
1906 kernelFlags.set( isothermalCompositionalMultiphaseBaseKernels::KernelFlags::TotalMassEquation );
1911 kernelType kernel( dt, rankOffset, dofKey, wellControls, subRegion, localMatrix, localRhs, kernelFlags );
1912 kernelType::template launch< POLICY >( subRegion.
size(), kernel );
#define GEOS_HOST_DEVICE
Marks a host-device function.
#define GEOS_UNUSED_VAR(...)
Mark an unused variable and silence compiler warnings.
#define GEOS_ERROR(msg)
Raise a hard error and terminate the program.
#define GEOS_MARK_FUNCTION
Mark function with both Caliper and NVTX if enabled.
ScalingType
Solution scaling type.
typename ElementViewAccessor< VIEWTYPE >::NestedViewTypeConst ElementViewConst
The ElementViewAccessor at the ElementRegionManager level is the type resulting from ElementViewAcces...
arrayView1d< real64 const > getElementVolume() const
Get the volume of each element in this subregion.
The ObjectManagerBase is the base object of all object managers in the mesh data hierachy.
array1d< integer > const & ghostRank()
Get the ghost information of each object.
GEOS_DECLTYPE_AUTO_RETURN getField() const
Get a view to the field associated with a trait from this ObjectManagerBase.
A struct to automatically construct and store element view accessors.
A struct to automatically construct and store element view accessors.
This class describes the controls used to operate a well.
bool isProducer() const
Is the well a producer?
Control getControl() const
Get the control type for the well.
real64 getTargetPhaseRate(real64 const ¤tTime) const
Get the target phase rate.
real64 getTargetTotalRate(real64 const ¤tTime) const
Get the target total rate.
real64 getTargetMassRate(real64 const ¤tTime) const
Get the target mass rate.
real64 getTargetBHP(real64 const ¤tTime) const
Get the target bottom hole pressure value.
This class describes a collection of local well elements and perforations.
bool isLocallyOwned() const
Check if well is owned by current rank.
localIndex getTopWellElementIndex() const
Get for the top element index.
static void createAndLaunch(localIndex const numComps, localIndex const numPhases, integer const isProducer, globalIndex const rankOffset, integer const useTotalMassEquation, string const dofKey, WellElementSubRegion const &subRegion, constitutive::MultiFluidBase const &fluid, CRSMatrixView< real64, globalIndex const > const &localMatrix, arrayView1d< real64 > const &localRhs)
Create a new kernel and launch.
Define the interface for the assembly kernel in charge of accumulation and volume balance.
static constexpr integer numEqn
Compute time value for the number of equations mass bal + vol bal + energy bal.
ElementBasedAssemblyKernel(localIndex const numPhases, integer const isProducer, globalIndex const rankOffset, string const dofKey, WellElementSubRegion const &subRegion, constitutive::MultiFluidBase const &fluid, CRSMatrixView< real64, globalIndex const > const &localMatrix, arrayView1d< real64 > const &localRhs, BitFlags< isothermalCompositionalMultiphaseBaseKernels::KernelFlags > const kernelFlags)
Constructor.
arrayView1d< globalIndex const > const m_dofNumber
View on the dof numbers.
arrayView3d< real64 const, constitutive::multifluid::USD_PHASE > const m_phaseDens_n
Views on the phase densities.
GEOS_HOST_DEVICE void computeAccumulation(localIndex const ei, StackVariables &stack, FUNC &&phaseAmountKernelOp=NoOpFunc{}) const
Compute the local accumulation contributions to the residual and Jacobian.
arrayView4d< real64 const, constitutive::multifluid::USD_PHASE_COMP > const m_phaseCompFrac_n
Views on the phase component fraction.
GEOS_HOST_DEVICE integer elemGhostRank(localIndex const ei) const
Getter for the ghost rank of an element.
arrayView3d< real64 const, compflow::USD_COMP_DC > const m_dCompFrac_dCompDens
Views on the derivatives of comp fractions wrt component density.
arrayView1d< real64 const > const m_volume
View on the element volumes.
GEOS_HOST_DEVICE void complete(localIndex const ei, StackVariables &stack) const
Performs the complete phase for the kernel.
static constexpr integer numComp
Compile time value for the number of components.
globalIndex const m_rankOffset
Offset for my MPI rank.
integer const m_isProducer
Well type.
static void launch(localIndex const numElems, KERNEL_TYPE const &kernelComponent)
Performs the kernel launch.
arrayView2d< real64 const, compflow::USD_PHASE > const m_phaseVolFrac_n
Views on the phase volume fractions.
static constexpr integer numDof
Number of Dof's set in this kernal - no dQ in accum.
GEOS_HOST_DEVICE void computeVolumeBalance(localIndex const ei, StackVariables &stack) const
Compute the local volume balance contributions to the residual and Jacobian.
CRSMatrixView< real64, globalIndex const > const m_localMatrix
View on the local CRS matrix.
integer const m_numPhases
Number of fluid phases.
arrayView1d< integer const > const m_elemGhostRank
View on the ghost ranks.
localIndex const m_iwelemControl
Index of the element where the control is enforced.
arrayView1d< real64 > const m_localRhs
View on the local RHS.
GEOS_HOST_DEVICE void setup(localIndex const ei, StackVariables &stack) const
Performs the setup phase for the kernel.
arrayView2d< real64 const > const m_porosity_n
Views on the porosity.
static void createAndLaunch(integer const numComps, real64 const dt, globalIndex const rankOffset, integer const useTotalMassEquation, string const dofKey, WellControls const &wellControls, WellElementSubRegion const &subRegion, CRSMatrixView< real64, globalIndex const > const &localMatrix, arrayView1d< real64 > const &localRhs)
Create a new kernel and launch.
Define the interface for the assembly kernel in charge of flux terms.
arrayView1d< globalIndex const > const m_wellElemDofNumber
Reference to the degree-of-freedom numbers.
arrayView1d< real64 const > const m_injection
Injection stream composition.
arrayView1d< real64 > const m_localRhs
View on the local RHS.
GEOS_HOST_DEVICE void setup(localIndex const iconn, StackVariables &stack) const
Performs the setup phase for the kernel.
GEOS_HOST_DEVICE void computeFlux(localIndex const iwelem, StackVariables &stack, FUNC &&compFluxKernelOp=NoOpFunc{}) const
Compute the local flux contributions to the residual and Jacobian.
integer const m_useTotalMassEquation
Kernel option flag.
GEOS_HOST_DEVICE void complete(localIndex const iconn, StackVariables &stack) const
Performs the setup phase for the kernel.
integer const m_rankOffset
Rank offset for calculating row/col Jacobian indices.
arrayView1d< localIndex const > const m_nextWellElemIndex
Next element index, needed since iterating over element nodes, not edges.
arrayView2d< real64 const, compflow::USD_COMP > const m_wellElemCompFrac
Element component fraction.
real64 const m_dt
Time step size.
static void launch(localIndex const numElements, KERNEL_TYPE const &kernelComponent)
Performs the kernel launch.
FaceBasedAssemblyKernel(real64 const dt, globalIndex const rankOffset, string const wellDofKey, WellControls const &wellControls, WellElementSubRegion const &subRegion, CRSMatrixView< real64, globalIndex const > const &localMatrix, arrayView1d< real64 > const &localRhs, BitFlags< isothermalCompositionalMultiphaseBaseKernels::KernelFlags > kernelFlags)
Constructor for the kernel interface.
arrayView1d< real64 const > const m_connRate
Connection rate.
CRSMatrixView< real64, globalIndex const > const m_localMatrix
View on the local CRS matrix.
arrayView3d< real64 const, compflow::USD_COMP_DC > const m_dWellElemCompFrac_dCompDens
Element component fraction derivatives.
bool const m_isProducer
Well type.
static void createAndLaunch(integer const numComp, integer const numDof, integer const targetPhaseIndex, globalIndex const rankOffset, string const &dofKey, arrayView1d< real64 const > const &localResidual, WellElementSubRegion const &subRegion, constitutive::MultiFluidBase const &fluid, WellControls const &wellControls, real64 const timeAtEndOfStep, real64 const dt, real64 const minNormalizer, real64(&residualNorm)[1])
Create a new kernel and launch.
virtual GEOS_HOST_DEVICE void computeLinf(localIndex const iwelem, LinfStackVariables &stack) const override
Compute the local values for the Linf norm.
bool const m_isLocallyOwned
Flag indicating whether the well is locally owned or not.
integer const m_numComp
Number of fluid components.
arrayView3d< real64 const, constitutive::multifluid::USD_PHASE > const m_phaseDens_n
View on phase/total density at the previous converged time step.
arrayView1d< real64 const > const m_volume
View on the volume.
integer const m_targetPhaseIndex
Index of the target phase.
integer const m_numDof
Number of dof per well element.
WellControls::Control const m_currentControl
Controls.
real64 const m_dt
Time step size.
localIndex const m_iwelemControl
Index of the element where the control is enforced.
virtual GEOS_HOST_DEVICE void computeL2(localIndex const iwelem, L2StackVariables &stack) const override
Compute the local values and normalizer for the L2 norm.
bool const m_isProducer
Flag indicating whether the well is a producer or an injector.
static isothermalCompositionalMultiphaseBaseKernels::SolutionCheckKernel::StackVariables createAndLaunch(integer const allowCompDensChopping, CompositionalMultiphaseFVM::ScalingType const scalingType, real64 const scalingFactor, arrayView1d< real64 const > const pressure, arrayView2d< real64 const, compflow::USD_COMP > const compDens, arrayView1d< real64 > pressureScalingFactor, arrayView1d< real64 > compDensScalingFactor, globalIndex const rankOffset, integer const numComp, string const dofKey, ElementSubRegionBase &subRegion, arrayView1d< real64 const > const localSolution)
Create a new kernel and launch.
static isothermalCompositionalMultiphaseBaseKernels::SolutionScalingKernel::StackVariables createAndLaunch(real64 const maxRelativePresChange, real64 const maxAbsolutePresChange, real64 const maxCompFracChange, real64 const maxRelativeCompDensChange, globalIndex const rankOffset, integer const numComp, string const dofKey, ElementSubRegionBase &subRegion, arrayView1d< real64 const > const localSolution)
Create a new kernel and launch.
static void createAndLaunch(integer const numComp, integer const numPhase, ObjectManagerBase &subRegion, constitutive::MultiFluidBase const &fluid)
Create a new kernel and launch.
Define the interface for the property kernel in charge of computing the total mass density.
arrayView1d< real64 > m_totalMassDens
Views on total mass densities.
GEOS_HOST_DEVICE void compute(localIndex const ei, FUNC &&totalMassDensityKernelOp=NoOpFunc{}) const
Compute the total mass density in an element.
static constexpr integer numPhase
Compile time value for the number of phases.
arrayView3d< real64 const, constitutive::multifluid::USD_PHASE > m_phaseMassDens
Views on phase mass densities.
arrayView2d< real64 const, compflow::USD_PHASE > m_phaseVolFrac
Views on phase volume fractions.
static constexpr integer numComp
Compile time value for the number of components.
TotalMassDensityKernel(ObjectManagerBase &subRegion, constitutive::MultiFluidBase const &fluid)
Constructor.
GEOS_DECLTYPE_AUTO_RETURN getReference(LOOKUP_TYPE const &lookup) const
Look up a wrapper and get reference to wrapped object.
localIndex size() const
Get the "size" of the group, which determines the number of elements in resizable wrappers.
Define the base interface for the property update kernels.
static constexpr integer numComp
Compile time value for the number of components.
Define the base interface for the residual calculations.
real64 const m_minNormalizer
Value used to make sure that normalizers are never zero.
arrayView1d< globalIndex const > const m_dofNumber
View on the dof numbers.
GEOS_HOST_DEVICE integer ghostRank(localIndex const i) const
Getter for the ghost rank.
globalIndex const m_rankOffset
Offset for my MPI rank.
arrayView1d< real64 const > const m_localResidual
View on the local residual.
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.
ArraySlice< T, 2, USD > arraySlice2d
Alias for 2D array slice.
ArraySlice< T, 3, USD > arraySlice3d
Alias for 3D array slice.
ArrayView< T, 5, USD > arrayView5d
Alias for 5D array view.
double real64
64-bit floating point type.
GEOS_LOCALINDEX_TYPE localIndex
Local index type (for indexing objects within an MPI partition).
ArraySlice< T, 1, USD > arraySlice1d
Alias for 1D array slice.
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.
Kernel variables (dof numbers, jacobian and residual) located on the stack.
real64 localJacobian[numEqn][numDof]
C-array storage for the element local Jacobian matrix (all equations except constraint and momentum)
globalIndex dofIndices[numDof]
Indices of the matrix rows/columns corresponding to the dofs in this element.
localIndex localRow
Index of the local row corresponding to this element.
real64 localResidual[numEqn]
C-array storage for the element local residual vector (all equations except constraint and momentum)
stackArray2d< real64, maxNumElems *numEqn *maxStencilSize *CP_Deriv::nDer > localFluxJacobian
Storage for the face local Jacobian matrix dC dP dT.
GEOS_HOST_DEVICE StackVariables(localIndex const size)
Constructor for the stack variables.
stackArray2d< real64, maxNumElems *numEqn *maxStencilSize > localFluxJacobian_dQ
Storage for the face local Jacobian matrix dQ only.
stackArray1d< globalIndex, maxNumElems *numDof > dofColIndices
Indices of the matrix rows/columns corresponding to the dofs in this face.
stackArray1d< real64, maxNumElems *numEqn > localFlux
Storage for the face local residual vector (all mass bal equations)
localIndex numConnectedElems
Number of elements connected at a given connection.
ElementRegionManager::ElementViewConst< VIEWTYPE > ElementViewConst
The type for element-based non-constitutive data parameters. Consists entirely of ArrayView's.
Kernel variables located on the stack.
Kernel variables located on the stack.