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"
32 #include "mesh/WellElementSubRegion.hpp"
41 #include "physicsSolvers/fluidFlow/wells/WellControls.hpp"
43 #include "physicsSolvers/fluidFlow/wells/WellPhaseVolumeRateConstraint.hpp"
49 namespace compositionalMultiphaseWellKernels
52 static constexpr
real64 minDensForDivision = 1e-10;
57 static constexpr
integer RES = 0;
58 static constexpr
integer WELL = 1;
64 static constexpr
integer CURRENT = 0;
65 static constexpr
integer NEXT = 1;
71 static constexpr
integer DPRES = 0;
72 static constexpr
integer DCOMP = 1;
75 template<
integer NC,
integer IS_THERMAL >
78 template<
integer NC >
81 static constexpr
integer dP = 0;
82 static constexpr
integer dC = 1;
83 static constexpr
integer dQ = dC + NC;
84 static integer constexpr nDer = dQ + 1;
88 template<
integer NC >
91 static constexpr
integer dP = 0;
92 static constexpr
integer dC = 1;
93 static constexpr
integer dQ = dC + NC;
94 static constexpr
integer dT = dQ+1;
102 static constexpr
integer CONTROL = 0;
103 static constexpr
integer MASSBAL = 1;
106 template<
integer NC,
integer IS_THERMAL >
109 template<
integer NC >
112 static constexpr
integer CONTROL = 0;
113 static constexpr
integer MASSBAL = 1;
114 static constexpr
integer VOLBAL = MASSBAL + NC;
115 static constexpr
integer nEqn = VOLBAL+1;
118 template<
integer NC >
121 static constexpr
integer CONTROL = 0;
122 static constexpr
integer MASSBAL = 1;
123 static constexpr
integer VOLBAL = MASSBAL + NC;
124 static constexpr
integer ENERGYBAL = VOLBAL+1;
125 static constexpr
integer nEqn = ENERGYBAL+1;
138 selectLimitingConstraint(
bool const isProducer,
143 real64 const & targetPhaseRate,
144 real64 const & targetTotalRate,
145 real64 const & targetMassRate,
146 real64 const & currentBHP,
148 real64 const & currentTotalVolRate,
149 real64 const & currentMassRate,
152 template<
integer NC,
integer IS_THERMAL >
158 integer const targetPhaseIndex,
160 real64 const & targetPhaseRate,
161 real64 const & targetTotalRate,
162 real64 const & targetMassRate,
163 real64 const & currentBHP,
164 real64 const & targetValue,
168 real64 const & currentTotalVolRate,
170 real64 const & massDensity,
181 using Deriv = constitutive::multifluid::DerivativeOffset;
186 template<
integer NC,
integer IS_THERMAL >
190 compute(
real64 const & gravCoef,
191 real64 const & gravCoefNext,
194 real64 const & totalMassDens,
195 real64 const & totalMassDensNext,
199 real64 ( &localPresRelJacobian )[2*(NC+1+IS_THERMAL)] );
201 template<
integer NC,
integer IS_THERMAL >
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 >
284 real64 const & refWellElemGravCoef,
285 real64 const & currentTime,
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();
506 constitutive::MultiFluidBase
const & fluid,
510 real64 const minNormalizer )
526 m_totalDens_n( fluid.totalDensity_n() )
533 if( rateConstraint !=
nullptr )
535 m_constraintValue = rateConstraint->getConstraintValue( time );
549 LinfStackVariables & stack )
const override
560 if( idof == ROFFSET::CONTROL )
569 normalizer = m_targetBHP;
574 normalizer = LvArray::math::max( LvArray::math::abs( m_constraintValue ),
m_minNormalizer );
579 normalizer = LvArray::math::max( LvArray::math::abs( m_constraintValue ),
m_minNormalizer );
584 normalizer = LvArray::math::max( LvArray::math::abs( m_constraintValue ),
m_minNormalizer );
590 normalizer = m_targetBHP;
594 else if( idof >= ROFFSET::MASSBAL && idof < ROFFSET::MASSBAL +
m_numComp )
605 normalizer =
m_dt * LvArray::math::abs( m_constraintValue );
610 normalizer =
m_dt * LvArray::math::abs( m_constraintValue ) * m_totalDens_n[iwelem][0];
616 normalizer = LvArray::math::max( normalizer,
m_volume[iwelem] * m_totalDens_n[iwelem][0] );
619 else if( idof == ROFFSET::MASSBAL +
m_numComp )
624 normalizer =
m_dt * LvArray::math::abs( m_constraintValue );
630 normalizer =
m_dt * LvArray::math::abs( m_constraintValue/ m_totalDens_n[iwelem][0] );
634 normalizer =
m_dt * LvArray::math::abs( m_constraintValue );
642 normalizer = LvArray::math::max( normalizer,
m_volume[iwelem] );
646 if( val > stack.localValue[0] )
648 stack.localValue[0] = val;
655 L2StackVariables & stack )
const override
658 GEOS_ERROR(
"The L2 norm is not implemented for CompositionalMultiphaseWell" );
722 template<
typename POLICY >
727 string const & dofKey,
730 constitutive::MultiFluidBase
const & fluid,
734 real64 const minNormalizer,
735 real64 (& residualNorm)[1] )
741 numComp, numDof, subRegion, fluid, wellControls, time, dt, minNormalizer );
742 ResidualNormKernel::launchLinf< POLICY >( subRegion.
size(), kernel, residualNorm );
769 template<
typename POLICY >
772 real64 const maxAbsolutePresChange,
773 real64 const maxCompFracChange,
774 real64 const maxRelativeCompDensChange,
782 subRegion.
getField< fields::well::pressure >();
784 subRegion.
getField< fields::well::globalCompDensity >();
786 subRegion.
getField< fields::well::pressureScalingFactor >();
788 subRegion.
getField< fields::well::globalCompDensityScalingFactor >();
789 isothermalCompositionalMultiphaseBaseKernels::
790 SolutionScalingKernel kernel( maxRelativePresChange, maxAbsolutePresChange, maxCompFracChange, maxRelativeCompDensChange, rankOffset,
791 numComp, dofKey, subRegion, localSolution, pressure, compDens, pressureScalingFactor, compDensScalingFactor );
792 return isothermalCompositionalMultiphaseBaseKernels::
793 SolutionScalingKernel::
794 launch< POLICY >( subRegion.
size(), kernel );
807 template<
integer NUM_COMP,
integer IS_THERMAL >
815 using FLUID_PROP_COFFSET = constitutive::multifluid::DerivativeOffsetC< NUM_COMP, IS_THERMAL >;
840 integer const thermalEffectsEnabled,
845 constitutive::MultiFluidBase
const & fluid,
848 BitFlags< isothermalCompositionalMultiphaseBaseKernels::KernelFlags >
const kernelFlags )
857 m_volume( subRegion.getElementVolume() ),
858 m_dCompFrac_dCompDens( subRegion.getField< fields::flow::dGlobalCompFraction_dGlobalCompDensity >() ),
859 m_phaseVolFrac_n( subRegion.getField< fields::flow::phaseVolumeFraction_n >() ),
860 m_phaseVolFrac( subRegion.getField< fields::flow::phaseVolumeFraction >() ),
861 m_dPhaseVolFrac( subRegion.getField< fields::flow::dPhaseVolumeFraction >() ),
863 m_phaseDens( fluid.phaseDensity() ),
864 m_dPhaseDens( fluid.dPhaseDensity() ),
866 m_phaseCompFrac( fluid.phaseCompFraction() ),
867 m_dPhaseCompFrac( fluid.dPhaseCompFraction() ),
868 m_compDens( subRegion.getField< fields::flow::globalCompDensity >() ),
869 m_compDens_n( subRegion.getField< fields::flow::globalCompDensity_n >() ),
872 m_kernelFlags( kernelFlags )
938 if constexpr ( IS_THERMAL )
943 stack.dofColIndices[0] =
m_dofNumber[ei] + WJ_COFFSET::dP;
946 stack.dofColIndices[ic+1] =
m_dofNumber[ei] + WJ_COFFSET::dC+ic;
948 if constexpr ( IS_THERMAL )
968 template<
typename FUNC = NoOpFunc >
972 FUNC && phaseAmountKernelOp = NoOpFunc{} )
const
975 using Deriv = constitutive::multifluid::DerivativeOffset;
981 arraySlice1d<
real64 const, compflow::USD_PHASE - 1 > phaseVolFrac = m_phaseVolFrac[ei];
982 arraySlice2d<
real64 const, compflow::USD_PHASE_DC - 1 > dPhaseVolFrac = m_dPhaseVolFrac[ei];
985 arraySlice1d<
real64 const, constitutive::multifluid::USD_PHASE - 2 > phaseDens = m_phaseDens[ei][0];
986 arraySlice2d<
real64 const, constitutive::multifluid::USD_PHASE_DC - 2 > dPhaseDens = m_dPhaseDens[ei][0];
989 arraySlice2d<
real64 const, constitutive::multifluid::USD_PHASE_COMP - 2 > phaseCompFrac = m_phaseCompFrac[ei][0];
990 arraySlice3d<
real64 const, constitutive::multifluid::USD_PHASE_COMP_DC - 2 > dPhaseCompFrac = m_dPhaseCompFrac[ei][0];
993 real64 dPhaseAmount[FLUID_PROP_COFFSET::nDer]{};
1000 real64 const phaseAmount = stack.volume * phaseVolFrac[ip] * phaseDens[ip];
1001 real64 const phaseAmount_n = stack.volume * phaseVolFrac_n[ip] * phaseDens_n[ip];
1003 dPhaseAmount[FLUID_PROP_COFFSET::dP]=stack.volume * ( dPhaseVolFrac[ip][Deriv::dP] * phaseDens[ip]
1004 + phaseVolFrac[ip] * dPhaseDens[ip][Deriv::dP] );
1007 applyChainRule(
numComp, dCompFrac_dCompDens, dPhaseDens[ip], dPhaseAmount_dC, Deriv::dC );
1008 applyChainRule(
numComp, dCompFrac_dCompDens, dPhaseDens[ip], &dPhaseAmount[FLUID_PROP_COFFSET::dC], Deriv::dC );
1011 dPhaseAmount_dC[jc] = dPhaseAmount_dC[jc] * phaseVolFrac[ip]
1012 + phaseDens[ip] * dPhaseVolFrac[ip][Deriv::dC+jc];
1013 dPhaseAmount_dC[jc] *= stack.volume;
1014 dPhaseAmount[FLUID_PROP_COFFSET::dC+jc] = dPhaseAmount[FLUID_PROP_COFFSET::dC+jc] * phaseVolFrac[ip]
1015 + phaseDens[ip] * dPhaseVolFrac[ip][Deriv::dC+jc];
1016 dPhaseAmount[FLUID_PROP_COFFSET::dC+jc] *= stack.volume;
1022 real64 const phaseCompAmount = phaseAmount * phaseCompFrac[ip][ic];
1023 real64 const phaseCompAmount_n = phaseAmount_n * phaseCompFrac_n[ip][ic];
1025 real64 const dPhaseCompAmount_dP = dPhaseAmount[FLUID_PROP_COFFSET::dP] * phaseCompFrac[ip][ic]
1026 + phaseAmount * dPhaseCompFrac[ip][ic][Deriv::dP];
1028 stack.
localResidual[ic] += phaseCompAmount - phaseCompAmount_n;
1035 applyChainRule(
numComp, dCompFrac_dCompDens, dPhaseCompFrac[ip][ic], dPhaseCompFrac_dC, Deriv::dC );
1038 real64 const dPhaseCompAmount_dC = dPhaseCompFrac_dC[jc] * phaseAmount
1039 + phaseCompFrac[ip][ic] * dPhaseAmount[FLUID_PROP_COFFSET::dC+jc];
1044 if constexpr ( IS_THERMAL )
1046 dPhaseAmount[FLUID_PROP_COFFSET::dT] = stack.volume * (dPhaseVolFrac[ip][Deriv::dT] * phaseDens[ip] + phaseVolFrac[ip] * dPhaseDens[ip][Deriv::dT] );
1050 stack.
localJacobian[ic][
numComp+1] += dPhaseAmount[FLUID_PROP_COFFSET::dT] * phaseCompFrac[ip][ic]
1051 + phaseAmount * dPhaseCompFrac[ip][ic][Deriv::dT];
1056 phaseAmountKernelOp( ip, phaseAmount, phaseAmount_n, dPhaseAmount );
1083 using Deriv = constitutive::multifluid::DerivativeOffset;
1085 arraySlice1d<
real64 const, compflow::USD_PHASE - 1 > phaseVolFrac = m_phaseVolFrac[ei];
1086 arraySlice2d<
real64 const, compflow::USD_PHASE_DC - 1 > dPhaseVolFrac = m_dPhaseVolFrac[ei];
1088 real64 oneMinusPhaseVolFracSum = 1.0;
1095 oneMinusPhaseVolFracSum -= phaseVolFrac[ip];
1103 if constexpr ( IS_THERMAL)
1126 using namespace compositionalMultiphaseUtilities;
1130 if constexpr ( IS_THERMAL)
1164 if( m_kernelFlags.isSet( isothermalCompositionalMultiphaseBaseKernels::KernelFlags::TotalMassEquation ) )
1177 for(
integer i = 0; i < numRows; ++i )
1180 m_localMatrix.addToRow< serialAtomic >( stack.eqnRowIndices[i],
1181 stack.dofColIndices,
1195 template<
typename POLICY,
typename KERNEL_TYPE >
1198 KERNEL_TYPE
const & kernelComponent )
1203 if( kernelComponent.skipElement( ei ) )
1208 typename KERNEL_TYPE::StackVariables stack;
1210 kernelComponent.setup( ei, stack );
1211 kernelComponent.computeAccumulation( ei, stack );
1212 kernelComponent.computeVolumeBalance( ei, stack );
1213 kernelComponent.complete( ei, stack );
1277 BitFlags< isothermalCompositionalMultiphaseBaseKernels::KernelFlags >
const m_kernelFlags;
1299 template<
typename POLICY >
1303 integer const & thermalEffectsEnabled,
1306 BitFlags< isothermalCompositionalMultiphaseBaseKernels::KernelFlags > kernelFlags,
1307 string const dofKey,
1309 constitutive::MultiFluidBase
const & fluid,
1313 geos::internal::kernelLaunchSelectorCompThermSwitch( numComps, 0, [&](
auto NC,
auto IS_THERMAL )
1317 integer constexpr istherm = IS_THERMAL();
1320 kernel( numPhases, thermalEffectsEnabled, isProducer, rankOffset, dofKey, subRegion, fluid, localMatrix, localRhs, kernelFlags );
1322 launch< POLICY, ElementBasedAssemblyKernel< NUM_COMP, istherm > >( subRegion.
size(), kernel );
1334 template<
integer NC,
integer IS_THERMAL >
1343 using FLUID_PROP_COFFSET = constitutive::multifluid::DerivativeOffsetC< NC, IS_THERMAL >;
1347 using CP_Deriv = constitutive::multifluid::DerivativeOffsetC< NC, IS_THERMAL >;
1357 static constexpr
integer maxNumElems = 2;
1358 static constexpr
integer maxStencilSize = 2;
1375 string const wellDofKey,
1380 BitFlags< isothermalCompositionalMultiphaseBaseKernels::KernelFlags > kernelFlags )
1384 m_wellElemDofNumber ( subRegion.getReference<
array1d<
globalIndex > >( wellDofKey ) ),
1387 m_connRate ( subRegion.getField< fields::well::connectionRate >() ),
1388 m_wellElemCompFrac ( subRegion.getField< fields::well::globalCompFraction >() ),
1389 m_dWellElemCompFrac_dCompDens ( subRegion.getField< fields::well::dGlobalCompFraction_dGlobalCompDensity >() ),
1392 m_useTotalMassEquation ( kernelFlags.isSet( isothermalCompositionalMultiphaseBaseKernels::KernelFlags::TotalMassEquation ) ),
1394 m_injection ( wellControls.getInjectionStream() )
1408 : stencilSize( size ),
1409 numConnectedElems( 2 ),
1410 dofColIndices( size *
numDof )
1443 return (
m_elemStatus[ei]==WellElementSubRegion::WellElemStatus::CLOSED );
1457 if( m_nextWellElemIndex[iconn] <0 )
1479 using namespace compositionalMultiphaseUtilities;
1485 for(
integer ic = 0; ic < NC; ++ic )
1487 oneSidedEqnRowIndices[ic] = stack.offsetUp + WJ_ROFFSET::MASSBAL + ic -
m_rankOffset;
1491 globalIndex oneSidedDofColIndices_dPresCompTempUp[CP_Deriv::nDer]{};
1492 globalIndex oneSidedDofColIndices_dRate = stack.offsetCurrent + WJ_COFFSET::dQ;
1495 oneSidedDofColIndices_dPresCompTempUp[ioff++] = stack.offsetUp + WJ_COFFSET::dP;
1497 if constexpr ( IS_THERMAL )
1499 oneSidedDofColIndices_dPresCompTempUp[ioff++] = stack.offsetUp + WJ_COFFSET::dT;
1501 for(
integer jdof = 0; jdof < NC; ++jdof )
1503 oneSidedDofColIndices_dPresCompTempUp[ioff++] = stack.offsetUp + WJ_COFFSET::dC+ jdof;
1505 if( m_useTotalMassEquation > 0 )
1508 real64 work[CP_Deriv::nDer]{};
1511 shiftElementsAheadByOneAndReplaceFirstElementWithSum(
numEqn, stack.
localFlux );
1515 if( oneSidedEqnRowIndices[i] >= 0 && oneSidedEqnRowIndices[i] <
m_localMatrix.numRows() )
1517 m_localMatrix.addToRow< parallelDeviceAtomic >( oneSidedEqnRowIndices[i],
1518 &oneSidedDofColIndices_dRate,
1521 m_localMatrix.addToRowBinarySearchUnsorted< parallelDeviceAtomic >( oneSidedEqnRowIndices[i],
1522 oneSidedDofColIndices_dPresCompTempUp,
1525 RAJA::atomicAdd( parallelDeviceAtomic{}, &
m_localRhs[oneSidedEqnRowIndices[i]], stack.
localFlux[i] );
1535 for(
integer ic = 0; ic < NC; ++ic )
1538 eqnRowIndices[TAG::NEXT *
numEqn+ic] = stack.offsetNext + WJ_ROFFSET::MASSBAL + ic -
m_rankOffset;
1539 eqnRowIndices[TAG::CURRENT *
numEqn+ic] = stack.offsetCurrent + WJ_ROFFSET::MASSBAL + ic -
m_rankOffset;
1543 globalIndex dofColIndices_dPresCompUp[CP_Deriv::nDer]{};
1544 globalIndex dofColIndices_dRate = stack.offsetCurrent + WJ_COFFSET::dQ;
1548 dofColIndices_dPresCompUp[ioff++] = stack.offsetUp + WJ_COFFSET::dP;
1550 if constexpr ( IS_THERMAL )
1552 dofColIndices_dPresCompUp[ioff++] = stack.offsetUp + WJ_COFFSET::dT;
1554 for(
integer jdof = 0; jdof < NC; ++jdof )
1556 dofColIndices_dPresCompUp[ioff++] = stack.offsetUp + WJ_COFFSET::dC+ jdof;
1560 if( m_useTotalMassEquation > 0 )
1563 real64 work[CP_Deriv::nDer]{};
1569 for(
integer i = 0; i < 2*NC; ++i )
1571 if( eqnRowIndices[i] >= 0 && eqnRowIndices[i] <
m_localMatrix.numRows() )
1573 m_localMatrix.addToRow< parallelDeviceAtomic >( eqnRowIndices[i],
1574 &dofColIndices_dRate,
1577 m_localMatrix.addToRowBinarySearchUnsorted< parallelDeviceAtomic >( eqnRowIndices[i],
1578 dofColIndices_dPresCompUp,
1581 RAJA::atomicAdd( parallelDeviceAtomic{}, &
m_localRhs[eqnRowIndices[i]], stack.
localFlux[i] );
1591 computeExit(
real64 const & dt,
1592 real64 const ( &compFlux )[NC ],
1596 for(
integer ic = 0; ic < NC; ++ic )
1598 stack.localFlux[ic] = -dt * compFlux[ic];
1600 stack.localFluxJacobian_dQ[ic][0] = -dt * dCompFlux[ic][WJ_COFFSET::dQ];
1602 stack.localFluxJacobian[ic][CP_Deriv::dP] = -dt * dCompFlux[ic][WJ_COFFSET::dP];
1604 for(
integer jdof = 0; jdof < NC; ++jdof )
1606 stack.localFluxJacobian[ic][CP_Deriv::dC+jdof] = -dt * dCompFlux[ic][WJ_COFFSET::dC+jdof];
1608 if constexpr ( IS_THERMAL )
1610 stack.localFluxJacobian[ic][CP_Deriv::dT] = -dt * dCompFlux[ic][WJ_COFFSET::dT];
1618 compute(
real64 const & dt,
1619 real64 const ( &compFlux )[NC ],
1624 for(
integer ic = 0; ic < NC; ++ic )
1626 stack.localFlux[TAG::NEXT * NC +ic] = dt * compFlux[ic];
1627 stack.localFlux[TAG::CURRENT * NC +ic] = -dt * compFlux[ic];
1629 stack.localFluxJacobian_dQ[TAG::NEXT * NC+ ic][0] = dt * dCompFlux[ic][WJ_COFFSET::dQ];
1630 stack.localFluxJacobian_dQ[TAG::CURRENT * NC + +ic][0] = -dt * dCompFlux[ic][WJ_COFFSET::dQ];
1633 stack.localFluxJacobian[TAG::NEXT * NC +ic][CP_Deriv::dP] = dt * dCompFlux[ic][WJ_COFFSET::dP];
1634 stack.localFluxJacobian[TAG::CURRENT * NC+ ic][CP_Deriv::dP] = -dt * dCompFlux[ic][WJ_COFFSET::dP];
1636 if constexpr ( IS_THERMAL )
1638 stack.localFluxJacobian[TAG::NEXT * NC +ic][CP_Deriv::dT] = dt * dCompFlux[ic][WJ_COFFSET::dT];
1639 stack.localFluxJacobian[TAG::CURRENT * NC +ic][CP_Deriv::dT] = -dt * dCompFlux[ic][WJ_COFFSET::dT];
1643 for(
integer jdof = 0; jdof < NC; ++jdof )
1645 stack.localFluxJacobian[TAG::NEXT * NC +ic][CP_Deriv::dC+jdof] = dt * dCompFlux[ic][WJ_COFFSET::dC+jdof];
1646 stack.localFluxJacobian[TAG::CURRENT * NC +ic][CP_Deriv::dC+jdof] = -dt * dCompFlux[ic][WJ_COFFSET::dC+jdof];
1658 template<
typename FUNC = NoOpFunc >
1663 FUNC && compFluxKernelOp = NoOpFunc{} )
const
1666 using namespace compositionalMultiphaseUtilities;
1673 for(
integer ic = 0; ic < NC; ++ic )
1675 for(
integer jc = 0; jc < NC; ++jc )
1688 localIndex iwelemNext = m_nextWellElemIndex[iwelem];
1691 if( iwelemNext >= 0 )
1693 if(
m_elemStatus[iwelemNext]==WellElementSubRegion::WellElemStatus::CLOSED )
1699 real64 const currentConnRate = m_connRate[iwelem];
1707 for(
integer ic = 0; ic < NC; ++ic )
1709 compFracUp[ic] = m_injection[ic];
1710 for(
integer jc = 0; jc < NC; ++jc )
1712 dComp[ic][jc] = m_dWellElemCompFrac_dCompDens[iwelemUp][ic][jc];
1714 for(
integer jc = 0; jc < NC; ++jc )
1716 dCompFlux[ic][WJ_COFFSET::dC+jc] = 0.0;
1724 || currentConnRate < 0 )
1730 iwelemUp = iwelemNext;
1734 for(
integer ic = 0; ic < NC; ++ic )
1736 compFracUp[ic] = m_wellElemCompFrac[iwelemUp][ic];
1737 for(
integer jc = 0; jc < NC; ++jc )
1739 dCompFlux[ic][WJ_COFFSET::dC+jc] = m_dWellElemCompFrac_dCompDens[iwelemUp][ic][jc];
1740 dComp[ic][jc] = m_dWellElemCompFrac_dCompDens[iwelemUp][ic][jc];
1747 for(
integer ic = 0; ic < NC; ++ic )
1749 compFlux[ic] = compFracUp[ic] * currentConnRate;
1750 dCompFlux[ic][WJ_COFFSET::dQ] = compFracUp[ic];
1752 dCompFlux[ic][WJ_COFFSET::dP] = 0.0;
1753 if constexpr ( IS_THERMAL )
1755 dCompFlux[ic][WJ_COFFSET::dT] = 0.0;
1757 for(
integer jc = 0; jc < NC; ++jc )
1759 dCompFlux[ic][WJ_COFFSET::dC+jc] = dCompFlux[ic][WJ_COFFSET::dC+jc] * currentConnRate;
1763 stack.offsetUp = m_wellElemDofNumber[iwelemUp];
1764 stack.iwelemUp = iwelemUp;
1765 stack.offsetCurrent = m_wellElemDofNumber[iwelem];
1766 stack.iwelemCurrent= iwelem;
1769 if( iwelemNext < 0 )
1785 stack.offsetNext = m_wellElemDofNumber[iwelemNext];
1787 stack.iwelemNext = iwelemNext;
1788 compFluxKernelOp( iwelemNext, iwelemUp, currentConnRate, dComp );
1799 template<
typename POLICY,
typename KERNEL_TYPE >
1802 KERNEL_TYPE
const & kernelComponent )
1807 typename KERNEL_TYPE::StackVariables stack( 1 );
1808 if( kernelComponent.skipElement( ie ))
1812 kernelComponent.setup( ie, stack );
1813 kernelComponent.computeFlux( ie, stack );
1814 kernelComponent.complete( ie, stack );
1878 template<
typename POLICY >
1883 BitFlags< isothermalCompositionalMultiphaseBaseKernels::KernelFlags > kernelFlags,
1884 string const dofKey,
1890 isothermalCompositionalMultiphaseBaseKernels::internal::kernelLaunchSelectorCompSwitch( numComps, [&](
auto NC )
1892 integer constexpr NUM_COMP = NC();
1895 kernelType kernel( dt, rankOffset, dofKey, wellControls, subRegion, localMatrix, localRhs, kernelFlags );
1896 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(...)
Raise a hard error and terminate the program.
#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...
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.
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 &thermalEffectsEnabled, integer const isProducer, globalIndex const rankOffset, BitFlags< isothermalCompositionalMultiphaseBaseKernels::KernelFlags > kernelFlags, 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.
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.
bool const m_thermalEffectsEnabled
Flag indicating whether thermal effects are enabled.
GEOS_HOST_DEVICE void computeAccumulation(localIndex const ei, StackVariables &stack, FUNC &&phaseAmountKernelOp=NoOpFunc{}) const
Compute the local accumulation contributions to the residual and Jacobian.
ElementBasedAssemblyKernel(localIndex const numPhases, integer const thermalEffectsEnabled, 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.
GEOS_HOST_DEVICE bool skipElement(localIndex const ei) const
Getter for the element.
arrayView4d< real64 const, constitutive::multifluid::USD_PHASE_COMP > const m_phaseCompFrac_n
Views on the phase component fraction.
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.
arrayView1d< integer const > const m_elemStatus
View on the well status.
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, BitFlags< isothermalCompositionalMultiphaseBaseKernels::KernelFlags > kernelFlags, 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< integer const > const m_elemStatus
View on the well status.
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, globalIndex const rankOffset, string const &dofKey, arrayView1d< real64 const > const &localResidual, WellElementSubRegion const &subRegion, constitutive::MultiFluidBase const &fluid, WellControls const &wellControls, real64 const time, real64 const dt, real64 const minNormalizer, real64(&residualNorm)[1])
Create a new kernel and launch.
integer m_targetPhaseIndex
Index of the target phase.
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.
ConstraintTypeId const m_currentControl
Controls.
arrayView1d< real64 const > const m_volume
View on the volume.
integer const m_numDof
Number of dof per well element.
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::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.
ConstraintTypeId getControl() const
Get the control type for the well.
bool isProducer() const
Is the well a producer?
stdVector< WellConstraintBase const * > getRateConstraints() const
Gets a list of rate constraints.
real64 getTargetBHP(real64 const &targetTime, const ConstraintSourceId source=ConstraintSourceId::USER) const
Returns the target bottom hole pressure value.
integer getConstraintPhaseIndex() const
Const accessor for the phase constraint index.
ArrayView< T, 1 > arrayView1d
Alias for 1D array view.
StackArray< T, 2, MAXSIZE > stackArray2d
Alias for 2D stack array.
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.
LvArray::CRSMatrixView< T, COL_INDEX, INDEX_TYPE const, LvArray::ChaiBuffer > CRSMatrixView
Alias for CRS Matrix View.
ArrayView< T, 4, USD > arrayView4d
Alias for 4D array view.
ArrayView< T, 2, USD > arrayView2d
Alias for 2D array view.
int integer
Signed integer type.
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.
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.