30 #include "constitutive/fluid/multifluid/MultiFluidSelector.hpp"
31 #include "constitutive/relativePermeability/RelativePermeabilitySelector.hpp"
35 using namespace constitutive;
37 namespace compositionalMultiphaseHybridFVMKernels
42 template<
integer NC,
integer NP >
47 upwindViscousCoefficient(
localIndex const (&localIds)[ 3 ],
49 ElementViewConst< arrayView3d< real64 const, multifluid::USD_PHASE > >
const & phaseDens,
50 ElementViewConst< arrayView4d< real64 const, multifluid::USD_PHASE_DC > >
const & dPhaseDens,
51 ElementViewConst< arrayView2d< real64 const, compflow::USD_PHASE > >
const & phaseMob,
52 ElementViewConst< arrayView3d< real64 const, compflow::USD_PHASE_DC > >
const & dPhaseMob,
53 ElementViewConst< arrayView3d< real64 const, compflow::USD_COMP_DC > >
const & dCompFrac_dCompDens,
54 ElementViewConst< arrayView4d< real64 const, multifluid::USD_PHASE_COMP > >
const & phaseCompFrac,
55 ElementViewConst< arrayView5d< real64 const, multifluid::USD_PHASE_COMP_DC > >
const & dPhaseCompFrac,
56 ElementViewConst< arrayView1d< globalIndex const > >
const & elemDofNumber,
57 real64 const & oneSidedVolFlux,
58 real64 ( & upwPhaseViscCoef )[ NP ][ NC ],
59 real64 ( & dUpwPhaseViscCoef_dPres )[ NP ][ NC ],
60 real64 ( & dUpwPhaseViscCoef_dCompDens )[ NP ][ NC ][ NC ],
63 using Deriv = multifluid::DerivativeOffset;
65 real64 dUpwMobRatio_dCompDens[ NC ]{};
66 real64 dUpwDensMobRatio_dCompDens[ NC ]{};
67 real64 dPhaseDens_dC[ NC ]{};
68 real64 dPhaseCompFrac_dC[ NC ]{};
71 localIndex const er = ( oneSidedVolFlux > 0 ) ? localIds[0] : neighborIds[0];
72 localIndex const esr = ( oneSidedVolFlux > 0 ) ? localIds[1] : neighborIds[1];
73 localIndex const ei = ( oneSidedVolFlux > 0 ) ? localIds[2] : neighborIds[2];
77 real64 dTotalMob_dPres = 0;
78 real64 dTotalMob_dCompDens[ NC ]{};
79 for(
integer ip = 0; ip < NP; ++ip )
81 totalMob = totalMob + phaseMob[er][esr][ei][ip];
82 dTotalMob_dPres = dTotalMob_dPres + dPhaseMob[er][esr][ei][ip][Deriv::dP];
83 for(
integer ic = 0; ic < NC; ++ic )
85 dTotalMob_dCompDens[ic] = dTotalMob_dCompDens[ic] + dPhaseMob[er][esr][ei][ip][Deriv::dC+ic];
88 real64 const totalMobInv = 1.0 / totalMob;
90 for(
integer ip = 0; ip < NP; ++ip )
93 real64 const upwMobRatio = phaseMob[er][esr][ei][ip] * totalMobInv;
94 real64 const dUpwMobRatio_dPres = ( dPhaseMob[er][esr][ei][ip][Deriv::dP] - upwMobRatio * dTotalMob_dPres )
96 for(
integer ic = 0; ic < NC; ++ic )
98 dUpwMobRatio_dCompDens[ic] = ( dPhaseMob[er][esr][ei][ip][Deriv::dC+ic] - upwMobRatio * dTotalMob_dCompDens[ic] )
104 dCompFrac_dCompDens[er][esr][ei],
105 dPhaseDens[er][esr][ei][0][ip],
108 real64 const upwDensMobRatio = phaseDens[er][esr][ei][0][ip] * upwMobRatio;
109 real64 const dUpwDensMobRatio_dPres = dPhaseDens[er][esr][ei][0][ip][Deriv::dP] * upwMobRatio
110 + phaseDens[er][esr][ei][0][ip] * dUpwMobRatio_dPres;
111 for(
integer ic = 0; ic < NC; ++ic )
113 dUpwDensMobRatio_dCompDens[ic] = dPhaseDens_dC[ic] * upwMobRatio
114 + phaseDens[er][esr][ei][0][ip] * dUpwMobRatio_dCompDens[ic];
118 for(
integer ic = 0; ic < NC; ++ic )
121 dCompFrac_dCompDens[er][esr][ei],
122 dPhaseCompFrac[er][esr][ei][0][ip][ic],
125 upwPhaseViscCoef[ip][ic] = phaseCompFrac[er][esr][ei][0][ip][ic] * upwDensMobRatio;
126 dUpwPhaseViscCoef_dPres[ip][ic] = dPhaseCompFrac[er][esr][ei][0][ip][ic][Deriv::dP] * upwDensMobRatio
127 + phaseCompFrac[er][esr][ei][0][ip][ic] * dUpwDensMobRatio_dPres;
128 for(
integer jc = 0; jc < NC; ++jc )
130 dUpwPhaseViscCoef_dCompDens[ip][ic][jc] = dPhaseCompFrac_dC[jc] * upwDensMobRatio
131 + phaseCompFrac[er][esr][ei][0][ip][ic] * dUpwDensMobRatio_dCompDens[jc];
136 upwViscDofNumber = elemDofNumber[er][esr][ei];
140 template<
integer NC,
integer NP >
145 upwindBuoyancyCoefficient(
localIndex const (&localIds)[ 3 ],
147 real64 const & transGravCoef,
148 ElementViewConst< arrayView3d< real64 const, multifluid::USD_PHASE > >
const & phaseDens,
149 ElementViewConst< arrayView4d< real64 const, multifluid::USD_PHASE_DC > >
const & dPhaseDens,
150 ElementViewConst< arrayView3d< real64 const, multifluid::USD_PHASE > >
const & phaseMassDens,
151 ElementViewConst< arrayView4d< real64 const, multifluid::USD_PHASE_DC > >
const & dPhaseMassDens,
152 ElementViewConst< arrayView2d< real64 const, compflow::USD_PHASE > >
const & phaseMob,
153 ElementViewConst< arrayView3d< real64 const, compflow::USD_PHASE_DC > >
const & dPhaseMob,
154 ElementViewConst< arrayView3d< real64 const, compflow::USD_COMP_DC > >
const & dCompFrac_dCompDens,
155 ElementViewConst< arrayView4d< real64 const, multifluid::USD_PHASE_COMP > >
const & phaseCompFrac,
156 ElementViewConst< arrayView5d< real64 const, multifluid::USD_PHASE_COMP_DC > >
const & dPhaseCompFrac,
157 real64 ( & phaseGravTerm )[ NP ][ NP-1 ],
158 real64 ( & dPhaseGravTerm_dPres )[ NP ][ NP-1 ][ 2 ],
159 real64 ( & dPhaseGravTerm_dCompDens )[ NP ][ NP-1 ][ 2 ][ NC ],
160 real64 ( & upwPhaseGravCoef )[ NP ][ NP-1 ][ NC ],
161 real64 ( & dUpwPhaseGravCoef_dPres )[ NP ][ NP-1 ][ NC ][ 2 ],
162 real64 ( & dUpwPhaseGravCoef_dCompDens )[ NP ][ NP-1 ][ NC ][ 2 ][ NC ] )
164 using Deriv = multifluid::DerivativeOffset;
167 computePhaseGravTerm( localIds,
174 dPhaseGravTerm_dPres,
175 dPhaseGravTerm_dCompDens );
179 real64 dTotalMob_dPres[ 2 ]{};
180 real64 dTotalMob_dCompDens[ 2 ][ NC ]{};
182 computeUpwindedTotalMobility( localIds,
189 dTotalMob_dCompDens );
190 real64 const totalMobInv = 1.0 / totalMob;
193 real64 dMobRatio_dPres[ 2 ]{};
194 real64 dMobRatio_dCompDens[ 2 ][ NC ]{};
195 real64 dDensMobRatio_dPres[ 2 ]{};
196 real64 dDensMobRatio_dCompDens[ 2 ][ NC ]{};
198 real64 dPhaseDens_dC[ NC ]{};
199 real64 dPhaseCompFrac_dC[ NC ]{};
201 for(
integer ip = 0; ip < NP; ++ip )
204 for(
integer jp = 0; jp < NP; ++jp )
214 setIndicesForMobilityRatioUpwinding( localIds, neighborIds,
215 phaseGravTerm[ip][k],
216 eru, esru, eiu, posu,
217 erd, esrd, eid, posd );
220 real64 const mobRatio = phaseMob[eru][esru][eiu][ip] * phaseMob[erd][esrd][eid][jp]
222 dMobRatio_dPres[posu] = ( dPhaseMob[eru][esru][eiu][ip][Deriv::dP] * phaseMob[erd][esrd][eid][jp]
223 - mobRatio * dTotalMob_dPres[posu] ) * totalMobInv;
224 dMobRatio_dPres[posd] = ( dPhaseMob[erd][esrd][eid][jp][Deriv::dP] * phaseMob[eru][esru][eiu][ip]
225 - mobRatio * dTotalMob_dPres[posd] ) * totalMobInv;
227 for(
integer ic = 0; ic < NC; ++ic )
229 dMobRatio_dCompDens[posu][ic] = ( dPhaseMob[eru][esru][eiu][ip][Deriv::dC+ic] * phaseMob[erd][esrd][eid][jp]
230 - mobRatio * dTotalMob_dCompDens[posu][ic] ) * totalMobInv;
231 dMobRatio_dCompDens[posd][ic] = ( dPhaseMob[erd][esrd][eid][jp][Deriv::dC+ic] * phaseMob[eru][esru][eiu][ip]
232 - mobRatio * dTotalMob_dCompDens[posd][ic] ) * totalMobInv;
237 dCompFrac_dCompDens[eru][esru][eiu],
238 dPhaseDens[eru][esru][eiu][0][ip],
241 real64 const densMobRatio = phaseDens[eru][esru][eiu][0][ip] * mobRatio;
242 dDensMobRatio_dPres[posu] = dPhaseDens[eru][esru][eiu][0][ip][Deriv::dP] * mobRatio
243 + phaseDens[eru][esru][eiu][0][ip] * dMobRatio_dPres[posu];
244 dDensMobRatio_dPres[posd] = phaseDens[eru][esru][eiu][0][ip] * dMobRatio_dPres[posd];
245 for(
integer ic = 0; ic < NC; ++ic )
247 dDensMobRatio_dCompDens[posu][ic] = dPhaseDens_dC[ic] * mobRatio
248 + phaseDens[eru][esru][eiu][0][ip] * dMobRatio_dCompDens[posu][ic];
249 dDensMobRatio_dCompDens[posd][ic] = phaseDens[eru][esru][eiu][0][ip] * dMobRatio_dCompDens[posd][ic];
253 for(
integer ic = 0; ic < NC; ++ic )
256 dCompFrac_dCompDens[eru][esru][eiu],
257 dPhaseCompFrac[eru][esru][eiu][0][ip][ic],
260 upwPhaseGravCoef[ip][k][ic] = phaseCompFrac[eru][esru][eiu][0][ip][ic] * densMobRatio;
261 dUpwPhaseGravCoef_dPres[ip][k][ic][posu] = dPhaseCompFrac[eru][esru][eiu][0][ip][ic][Deriv::dP] * densMobRatio
262 + phaseCompFrac[eru][esru][eiu][0][ip][ic] * dDensMobRatio_dPres[posu];
263 dUpwPhaseGravCoef_dPres[ip][k][ic][posd] = phaseCompFrac[eru][esru][eiu][0][ip][ic] * dDensMobRatio_dPres[posd];
265 for(
integer jc = 0; jc < NC; ++jc )
267 dUpwPhaseGravCoef_dCompDens[ip][k][ic][posu][jc] = dPhaseCompFrac_dC[jc] * densMobRatio
268 + phaseCompFrac[eru][esru][eiu][0][ip][ic] * dDensMobRatio_dCompDens[posu][jc];
269 dUpwPhaseGravCoef_dCompDens[ip][k][ic][posd][jc] = phaseCompFrac[eru][esru][eiu][0][ip][ic] * dDensMobRatio_dCompDens[posd][jc];
278 template<
integer NC,
integer NP >
283 computePhaseGravTerm(
localIndex const (&localIds)[ 3 ],
285 real64 const & transGravCoef,
286 ElementViewConst< arrayView3d< real64 const, multifluid::USD_PHASE > >
const & phaseMassDens,
287 ElementViewConst< arrayView4d< real64 const, multifluid::USD_PHASE_DC > >
const & dPhaseMassDens,
288 ElementViewConst< arrayView3d< real64 const, compflow::USD_COMP_DC > >
const & dCompFrac_dCompDens,
289 real64 ( & phaseGravTerm )[ NP ][ NP-1 ],
290 real64 ( & dPhaseGravTerm_dPres )[ NP ][ NP-1 ][ 2 ],
291 real64 ( & dPhaseGravTerm_dCompDens )[ NP ][ NP-1 ][ 2 ][ NC ] )
293 using Deriv = multifluid::DerivativeOffset;
302 real64 dPhaseMassDens_dCLoc[ NC ]{};
303 real64 dPhaseMassDens_dCNeighbor[ NC ]{};
304 real64 dPhaseMassDens_dC[ NC ]{};
306 for(
integer ip = 0; ip < NP; ++ip )
309 dCompFrac_dCompDens[er][esr][ei],
310 dPhaseMassDens[er][esr][ei][0][ip],
311 dPhaseMassDens_dCLoc,
314 dCompFrac_dCompDens[ern][esrn][ein],
315 dPhaseMassDens[ern][esrn][ein][0][ip],
316 dPhaseMassDens_dCNeighbor,
320 for(
integer jp = 0; jp < NP; ++jp )
327 phaseGravTerm[ip][k] = -( phaseMassDens[er][esr][ei][0][ip] + phaseMassDens[ern][esrn][ein][0][ip] );
328 phaseGravTerm[ip][k] += ( phaseMassDens[er][esr][ei][0][jp] + phaseMassDens[ern][esrn][ein][0][jp] );
329 phaseGravTerm[ip][k] *= 0.5 * transGravCoef;
331 dPhaseGravTerm_dPres[ip][k][Pos::LOCAL] = ( -dPhaseMassDens[er][esr][ei][0][ip][Deriv::dP] + dPhaseMassDens[er][esr][ei][0][jp][Deriv::dP] );
332 dPhaseGravTerm_dPres[ip][k][Pos::LOCAL] *= 0.5 * transGravCoef;
334 dPhaseGravTerm_dPres[ip][k][Pos::NEIGHBOR] = ( -dPhaseMassDens[ern][esrn][ein][0][ip][Deriv::dP] + dPhaseMassDens[ern][esrn][ein][0][jp][Deriv::dP] );
335 dPhaseGravTerm_dPres[ip][k][Pos::NEIGHBOR] *= 0.5 * transGravCoef;
337 for(
integer ic = 0; ic < NC; ++ic )
339 dPhaseGravTerm_dCompDens[ip][k][Pos::LOCAL][ic] = -0.5 * transGravCoef * dPhaseMassDens_dCLoc[ic];
340 dPhaseGravTerm_dCompDens[ip][k][Pos::NEIGHBOR][ic] = -0.5 * transGravCoef * dPhaseMassDens_dCNeighbor[ic];
343 dCompFrac_dCompDens[er][esr][ei],
344 dPhaseMassDens[er][esr][ei][0][jp],
347 for(
integer ic = 0; ic < NC; ++ic )
349 dPhaseGravTerm_dCompDens[ip][k][Pos::LOCAL][ic] += 0.5 * transGravCoef * dPhaseMassDens_dC[ic];
352 dCompFrac_dCompDens[ern][esrn][ein],
353 dPhaseMassDens[ern][esrn][ein][0][jp],
356 for(
integer ic = 0; ic < NC; ++ic )
358 dPhaseGravTerm_dCompDens[ip][k][Pos::NEIGHBOR][ic] += 0.5 * transGravCoef * dPhaseMassDens_dC[ic];
365 template<
integer NC,
integer NP >
370 computeUpwindedTotalMobility(
localIndex const (&localIds)[ 3 ],
374 real64 const (&phaseGravTerm)[ NP ][ NP-1 ],
376 real64 ( & dTotalMob_dPres )[ 2 ],
377 real64 ( & dTotalMob_dCompDens )[ 2 ][ NC ] )
379 using Deriv = multifluid::DerivativeOffset;
383 setIndicesForTotalMobilityUpwinding< NP >( localIds,
388 for(
integer ip = 0; ip < NP; ++ip )
394 totalMob = totalMob + phaseMob[er][esr][ei][ip];
395 dTotalMob_dPres[pos] = dTotalMob_dPres[pos] + dPhaseMob[er][esr][ei][pos][Deriv::dP];
396 for(
integer ic = 0; ic < NC; ++ic )
398 dTotalMob_dCompDens[pos][ic] = dTotalMob_dCompDens[pos][ic] + dPhaseMob[er][esr][ei][ip][Deriv::dC+ic];
401 if( totalMob < 1e-12 )
411 setIndicesForMobilityRatioUpwinding(
localIndex const (&localIds)[ 3 ],
423 erd = neighborIds[0];
424 esrd = neighborIds[1];
425 eid = neighborIds[2];
426 posd = Pos::NEIGHBOR;
430 eru = neighborIds[0];
431 esru = neighborIds[1];
432 eiu = neighborIds[2];
433 posu = Pos::NEIGHBOR;
441 template<
integer NP >
446 setIndicesForTotalMobilityUpwinding(
localIndex const (&localIds)[ 3 ],
448 real64 const (&gravTerm)[ NP ][ NP-1 ],
452 if constexpr ( NP == 2 )
454 if( gravTerm[0][0] > 0 )
456 totalMobIds[0][0] = localIds[0];
457 totalMobIds[0][1] = localIds[1];
458 totalMobIds[0][2] = localIds[2];
459 totalMobPos[0] = Pos::LOCAL;
460 totalMobIds[1][0] = neighborIds[0];
461 totalMobIds[1][1] = neighborIds[1];
462 totalMobIds[1][2] = neighborIds[2];
463 totalMobPos[1] = Pos::NEIGHBOR;
467 totalMobIds[0][0] = neighborIds[0];
468 totalMobIds[0][1] = neighborIds[1];
469 totalMobIds[0][2] = neighborIds[2];
470 totalMobPos[0] = Pos::NEIGHBOR;
471 totalMobIds[1][0] = localIds[0];
472 totalMobIds[1][1] = localIds[1];
473 totalMobIds[1][2] = localIds[2];
474 totalMobPos[1] = Pos::LOCAL;
477 else if constexpr ( NP == 3 )
481 for(
integer ip = 0; ip < NP; ++ip )
483 if( ( gravTerm[ip][0] >= 0 && gravTerm[ip][1] >= 0 ) ||
484 ( ( LvArray::math::abs( gravTerm[ip][0] ) >= LvArray::math::abs( gravTerm[ip][1] ) ) && gravTerm[ip][1] >= 0 ) ||
485 ( ( LvArray::math::abs( gravTerm[ip][1] ) >= LvArray::math::abs( gravTerm[ip][0] ) ) && gravTerm[ip][0] >= 0 ) )
487 totalMobIds[ip][0] = localIds[0];
488 totalMobIds[ip][1] = localIds[1];
489 totalMobIds[ip][2] = localIds[2];
490 totalMobPos[ip] = Pos::LOCAL;
494 totalMobIds[ip][0] = neighborIds[0];
495 totalMobIds[ip][1] = neighborIds[1];
496 totalMobIds[ip][2] = neighborIds[2];
497 totalMobPos[ip] = Pos::NEIGHBOR;
505 template<
integer NF,
integer NC,
integer NP >
509 AssemblerKernelHelper::
514 real64 const & elemGravCoef,
521 real64 ( & oneSidedVolFlux )[ NF ],
522 real64 ( & dOneSidedVolFlux_dPres )[ NF ],
523 real64 ( & dOneSidedVolFlux_dFacePres )[ NF ][ NF ],
524 real64 ( & dOneSidedVolFlux_dCompDens )[ NF ][ NC ] )
526 using Deriv = multifluid::DerivativeOffset;
528 real64 dPhaseMassDens_dC[ NP ][ NC ]{};
529 real64 dPresDif_dCompDens[ NC ]{};
530 real64 dPhaseGravDif_dCompDens[ NC ]{};
531 real64 dPhaseMobPotDif_dCompDens[ NC ]{};
534 for(
integer ip = 0; ip < NP; ++ip )
537 dElemCompFrac_dCompDens,
538 dElemPhaseMassDens[ip],
539 dPhaseMassDens_dC[ip],
543 for(
integer ifaceLoc = 0; ifaceLoc < NF; ++ifaceLoc )
547 for(
integer jfaceLoc = 0; jfaceLoc < NF; ++jfaceLoc )
551 real64 const ccGravCoef = elemGravCoef;
552 real64 const fGravCoef = faceGravCoef[elemToFaces[jfaceLoc]];
553 real64 const gravCoefDif = ccGravCoef - fGravCoef;
555 for(
integer ip = 0; ip < NP; ++ip )
559 real64 const ccPres = elemPres;
560 real64 const fPres = facePres[elemToFaces[jfaceLoc]];
563 real64 const presDif = ccPres - fPres;
564 real64 const dPresDif_dPres = 1;
565 real64 const dPresDif_dFacePres = -1;
566 for(
integer ic = 0; ic < NC; ++ic )
568 dPresDif_dCompDens[ic] = 0.0;
572 real64 const phaseGravDif = elemPhaseMassDens[ip] * gravCoefDif;
573 real64 const dPhaseGravDif_dPres = dElemPhaseMassDens[ip][Deriv::dP] * gravCoefDif;
576 dPhaseGravDif_dCompDens[ic] = dPhaseMassDens_dC[ip][ic] * gravCoefDif;
581 real64 const phasePotDif = presDif - phaseGravDif;
582 real64 const phaseMobPotDif = elemPhaseMob[ip] * phasePotDif;
583 real64 const dPhaseMobPotDif_dPres = dElemPhaseMob[ip][Deriv::dP] * phasePotDif
584 + elemPhaseMob[ip] * (dPresDif_dPres - dPhaseGravDif_dPres);
585 real64 const dPhaseMobPotDif_dFacePres = elemPhaseMob[ip] * dPresDif_dFacePres;
586 for(
integer ic = 0; ic < NC; ++ic )
588 dPhaseMobPotDif_dCompDens[ic] = dElemPhaseMob[ip][Deriv::dC+ic] * phasePotDif
589 + elemPhaseMob[ip] * (dPresDif_dCompDens[ic] - dPhaseGravDif_dCompDens[ic]);
593 oneSidedVolFlux[ifaceLoc] = oneSidedVolFlux[ifaceLoc]
594 + transMatrix[ifaceLoc][jfaceLoc] * phaseMobPotDif;
595 dOneSidedVolFlux_dPres[ifaceLoc] = dOneSidedVolFlux_dPres[ifaceLoc]
596 + transMatrix[ifaceLoc][jfaceLoc] * dPhaseMobPotDif_dPres;
597 dOneSidedVolFlux_dFacePres[ifaceLoc][jfaceLoc] = dOneSidedVolFlux_dFacePres[ifaceLoc][jfaceLoc]
598 + transMatrix[ifaceLoc][jfaceLoc] * dPhaseMobPotDif_dFacePres;
601 dOneSidedVolFlux_dCompDens[ifaceLoc][ic] = dOneSidedVolFlux_dCompDens[ifaceLoc][ic]
602 + transMatrix[ifaceLoc][jfaceLoc] * dPhaseMobPotDif_dCompDens[ic];
609 template<
integer NF,
integer NC,
integer NP >
613 AssemblerKernelHelper::
614 assembleFluxDivergence(
localIndex const (&localIds)[ 3 ],
624 real64 const & elemGravCoef,
625 integer const useTotalMassEquation,
637 real64 const (&oneSidedVolFlux)[ NF ],
638 real64 const (&dOneSidedVolFlux_dPres)[ NF ],
639 real64 const (&dOneSidedVolFlux_dFacePres)[ NF ][ NF ],
640 real64 const (&dOneSidedVolFlux_dCompDens)[ NF ][ NC ],
645 using namespace compositionalMultiphaseUtilities;
649 globalIndex dofColIndicesElemVars[ NDOF*(NF+1) ]{};
652 integer numNonBoundaryFaces = 0;
653 for(
integer idof = 0; idof < NDOF; ++idof )
655 dofColIndicesElemVars[idof] = elemDofNumber[localIds[0]][localIds[1]][localIds[2]] + idof;
659 real64 divMassFluxes[ NC ]{};
660 real64 dDivMassFluxes_dElemVars[ NC ][ NDOF*(NF+1) ]{};
661 real64 dDivMassFluxes_dFaceVars[ NC ][ NF ]{};
666 real64 upwPhaseViscCoef[ NP ][ NC ]{};
667 real64 dUpwPhaseViscCoef_dPres[ NP ][ NC ]{};
668 real64 dUpwPhaseViscCoef_dCompDens[ NP ][ NC ][ NC ]{};
672 real64 phaseGravTerm[ NP ][ NP-1 ]{};
673 real64 dPhaseGravTerm_dPres[ NP ][ NP-1 ][ 2 ]{};
674 real64 dPhaseGravTerm_dCompDens[ NP ][ NP-1 ][ 2 ][ NC ]{};
677 real64 upwPhaseGravCoef[ NP ][ NP-1 ][ NC ]{};
678 real64 dUpwPhaseGravCoef_dPres[ NP ][ NP-1 ][ NC ][ 2 ]{};
679 real64 dUpwPhaseGravCoef_dCompDens[ NP ][ NP-1 ][ NC ][ 2 ][ NC ]{};
682 for(
integer ifaceLoc = 0; ifaceLoc < NF; ++ifaceLoc )
686 if( isBoundaryFace[elemToFaces[ifaceLoc]] == 0 )
689 faceIndexMap[ifaceLoc] = numNonBoundaryFaces;
690 dofColIndicesFaceVars[numNonBoundaryFaces] = faceDofNumber[elemToFaces[ifaceLoc]];
691 numNonBoundaryFaces++;
695 localIndex neighborIds[ 3 ] = { localIds[0], localIds[1], localIds[2] };
696 hybridFVMKernels::CellConnectivity::isNeighborFound( localIds,
704 localIndex const neighborDofNumber = elemDofNumber[neighborIds[0]][neighborIds[1]][neighborIds[2]];
709 UpwindingHelper::upwindViscousCoefficient< NC, NP >( localIds,
719 oneSidedVolFlux[ifaceLoc],
721 dUpwPhaseViscCoef_dPres,
722 dUpwPhaseViscCoef_dCompDens,
726 assembleViscousFlux< NF, NC, NP >( ifaceLoc,
728 dOneSidedVolFlux_dPres,
729 dOneSidedVolFlux_dFacePres,
730 dOneSidedVolFlux_dCompDens,
732 dUpwPhaseViscCoef_dPres,
733 dUpwPhaseViscCoef_dCompDens,
734 elemDofNumber[localIds[0]][localIds[1]][localIds[2]],
739 dDivMassFluxes_dElemVars,
740 dDivMassFluxes_dFaceVars,
741 dofColIndicesElemVars );
746 real64 const transGravCoef = (localIds[0] != neighborIds[0] || localIds[1] != neighborIds[1] || localIds[2] != neighborIds[2])
747 * transMatrixGrav[ifaceLoc][ifaceLoc] * (elemGravCoef - mimFaceGravCoef[elemToFaces[ifaceLoc]]);
751 UpwindingHelper::upwindBuoyancyCoefficient< NC, NP >( localIds,
764 dPhaseGravTerm_dPres,
765 dPhaseGravTerm_dCompDens,
767 dUpwPhaseGravCoef_dPres,
768 dUpwPhaseGravCoef_dCompDens );
771 assembleBuoyancyFlux< NF, NC, NP >( ifaceLoc,
773 dPhaseGravTerm_dPres,
774 dPhaseGravTerm_dCompDens,
776 dUpwPhaseGravCoef_dPres,
777 dUpwPhaseGravCoef_dCompDens,
780 dDivMassFluxes_dElemVars );
785 faceIndexMap[ifaceLoc] = -1;
790 if( useTotalMassEquation > 0 )
793 real64 work[NDOF * ( NF + 1 )];
794 shiftRowsAheadByOneAndReplaceFirstRowWithColumnSum( NC, NDOF * ( NF + 1 ), dDivMassFluxes_dElemVars, work );
795 shiftRowsAheadByOneAndReplaceFirstRowWithColumnSum( NC, NF, dDivMassFluxes_dFaceVars, work );
796 shiftElementsAheadByOneAndReplaceFirstElementWithSum( NC, divMassFluxes );
802 for(
integer ic = 0; ic < NC; ++ic )
805 LvArray::integerConversion< localIndex >( elemDofNumber[localIds[0]][localIds[1]][localIds[2]] + ic - rankOffset );
811 localRhs[eqnRowLocalIndex] = localRhs[eqnRowLocalIndex] + divMassFluxes[ic];
816 real64 compactElemDerivs[ NDOF*(NF+1) ];
819 for(
integer idof = 0; idof < NDOF; ++idof )
821 compactElemDofs[idof] = dofColIndicesElemVars[idof];
822 compactElemDerivs[idof] = dDivMassFluxes_dElemVars[ic][idof];
827 for(
integer jfaceLoc = 0; jfaceLoc < NF; ++jfaceLoc )
829 if( faceIndexMap[jfaceLoc] >= 0 )
831 integer const neighborOffset = NDOF * (jfaceLoc + 1);
832 for(
integer idof = 0; idof < NDOF; ++idof )
834 compactElemDofs[compactIdx] = dofColIndicesElemVars[neighborOffset + idof];
835 compactElemDerivs[compactIdx] = dDivMassFluxes_dElemVars[ic][neighborOffset + idof];
841 localMatrix.addToRowBinarySearchUnsorted< serialAtomic >( eqnRowLocalIndex,
848 if( numNonBoundaryFaces > 0 )
850 real64 compactFaceDerivs[ NF ]{};
851 for(
integer jfaceLoc = 0; jfaceLoc < NF; ++jfaceLoc )
853 if( faceIndexMap[jfaceLoc] >= 0 )
855 compactFaceDerivs[faceIndexMap[jfaceLoc]] = dDivMassFluxes_dFaceVars[ic][jfaceLoc];
859 localMatrix.addToRowBinarySearchUnsorted< serialAtomic >( eqnRowLocalIndex,
860 &dofColIndicesFaceVars[0],
862 numNonBoundaryFaces );
867 template<
integer NF,
integer NC,
integer NP >
871 AssemblerKernelHelper::
872 assembleViscousFlux(
localIndex const ifaceLoc,
873 real64 const (&oneSidedVolFlux)[ NF ],
874 real64 const (&dOneSidedVolFlux_dPres)[ NF ],
875 real64 const (&dOneSidedVolFlux_dFacePres)[ NF ][ NF ],
876 real64 const (&dOneSidedVolFlux_dCompDens)[ NF ][ NC ],
877 real64 const (&upwPhaseViscCoef)[ NP ][ NC ],
878 real64 const (&dUpwPhaseViscCoef_dPres)[ NP ][ NC ],
879 real64 const (&dUpwPhaseViscCoef_dCompDens)[ NP ][ NC ][ NC ],
884 real64 ( & divMassFluxes )[ NC ],
885 real64 ( & dDivMassFluxes_dElemVars )[ NC ][ (NC+1)*(NF+1) ],
886 real64 ( & dDivMassFluxes_dFaceVars )[ NC ][ NF ],
887 globalIndex ( & dofColIndicesElemVars )[ (NC+1)*(NF+1) ] )
890 localIndex const elemVarsOffset = NDOF*(ifaceLoc+1);
892 for(
integer ip = 0; ip < NP; ++ip )
894 for(
integer ic = 0; ic < NC; ++ic )
899 real64 const dt_upwPhaseViscCoef = dt * upwPhaseViscCoef[ip][ic];
902 divMassFluxes[ic] = divMassFluxes[ic] + dt_upwPhaseViscCoef * oneSidedVolFlux[ifaceLoc];
905 dDivMassFluxes_dElemVars[ic][0] = dDivMassFluxes_dElemVars[ic][0]
906 + dt_upwPhaseViscCoef * dOneSidedVolFlux_dPres[ifaceLoc];
907 dDivMassFluxes_dElemVars[ic][0] = dDivMassFluxes_dElemVars[ic][0]
908 + ( elemDofNumber == upwViscDofNumber )
909 * dt * dUpwPhaseViscCoef_dPres[ip][ic] * oneSidedVolFlux[ifaceLoc];
910 for(
integer jc = 0; jc < NC; ++jc )
912 dDivMassFluxes_dElemVars[ic][jc+1] = dDivMassFluxes_dElemVars[ic][jc+1]
913 + dt_upwPhaseViscCoef * dOneSidedVolFlux_dCompDens[ifaceLoc][jc];
914 dDivMassFluxes_dElemVars[ic][jc+1] = dDivMassFluxes_dElemVars[ic][jc+1]
915 + ( elemDofNumber == upwViscDofNumber )
916 * dt * dUpwPhaseViscCoef_dCompDens[ip][ic][jc] * oneSidedVolFlux[ifaceLoc];
920 dDivMassFluxes_dElemVars[ic][elemVarsOffset] = dDivMassFluxes_dElemVars[ic][elemVarsOffset]
921 + ( elemDofNumber != upwViscDofNumber )
922 * dt * dUpwPhaseViscCoef_dPres[ip][ic] * oneSidedVolFlux[ifaceLoc];
924 for(
integer jc = 0; jc < NC; ++jc )
926 dDivMassFluxes_dElemVars[ic][elemVarsOffset+jc+1] = dDivMassFluxes_dElemVars[ic][elemVarsOffset+jc+1]
927 + ( elemDofNumber != upwViscDofNumber )
928 * dt * dUpwPhaseViscCoef_dCompDens[ip][ic][jc] * oneSidedVolFlux[ifaceLoc];
931 for(
integer jfaceLoc = 0; jfaceLoc < NF; ++jfaceLoc )
933 dDivMassFluxes_dFaceVars[ic][jfaceLoc] = dDivMassFluxes_dFaceVars[ic][jfaceLoc]
934 + dt_upwPhaseViscCoef * dOneSidedVolFlux_dFacePres[ifaceLoc][jfaceLoc];
940 for(
integer idof = 0; idof < NDOF; ++idof )
942 dofColIndicesElemVars[elemVarsOffset+idof] = neighborDofNumber + idof;
946 template<
integer NF,
integer NC,
integer NP >
950 AssemblerKernelHelper::
951 assembleBuoyancyFlux(
localIndex const ifaceLoc,
952 real64 const (&phaseGravTerm)[ NP ][ NP-1 ],
953 real64 const (&dPhaseGravTerm_dPres)[ NP ][ NP-1 ][ 2 ],
954 real64 const (&dPhaseGravTerm_dCompDens)[ NP ][ NP-1 ][ 2 ][ NC ],
955 real64 const (&upwPhaseGravCoef)[ NP ][ NP-1 ][ NC ],
956 real64 const (&dUpwPhaseGravCoef_dPres)[ NP ][ NP-1 ][ NC ][ 2 ],
957 real64 const (&dUpwPhaseGravCoef_dCompDens)[ NP ][ NP-1 ][ NC ][ 2 ][ NC ],
959 real64 ( & divMassFluxes )[ NC ],
960 real64 ( & dDivMassFluxes_dElemVars )[ NC ][ (NC+1)*(NF+1) ] )
963 localIndex const elemVarsOffset = NDOF*(ifaceLoc+1);
965 for(
integer ip = 0; ip < NP; ++ip )
967 for(
integer jp = 0; jp < NP - 1; ++jp )
969 for(
integer ic = 0; ic < NC; ++ic )
971 real64 const dt_upwPhaseGravCoef = dt * upwPhaseGravCoef[ip][jp][ic];
974 divMassFluxes[ic] = divMassFluxes[ic] + dt_upwPhaseGravCoef * phaseGravTerm[ip][jp];
977 dDivMassFluxes_dElemVars[ic][0] = dDivMassFluxes_dElemVars[ic][0]
978 + dt * dUpwPhaseGravCoef_dPres[ip][jp][ic][Pos::LOCAL] * phaseGravTerm[ip][jp];
979 dDivMassFluxes_dElemVars[ic][0] = dDivMassFluxes_dElemVars[ic][0]
980 + dt_upwPhaseGravCoef * dPhaseGravTerm_dPres[ip][jp][Pos::LOCAL];
982 for(
integer jc = 0; jc < NC; ++jc )
984 dDivMassFluxes_dElemVars[ic][jc+1] = dDivMassFluxes_dElemVars[ic][jc+1]
985 + dt * dUpwPhaseGravCoef_dCompDens[ip][jp][ic][Pos::LOCAL][jc] * phaseGravTerm[ip][jp];
986 dDivMassFluxes_dElemVars[ic][jc+1] = dDivMassFluxes_dElemVars[ic][jc+1]
987 + dt_upwPhaseGravCoef * dPhaseGravTerm_dCompDens[ip][jp][Pos::LOCAL][jc];
991 dDivMassFluxes_dElemVars[ic][elemVarsOffset] = dDivMassFluxes_dElemVars[ic][elemVarsOffset]
992 + dt * dUpwPhaseGravCoef_dPres[ip][jp][ic][Pos::NEIGHBOR] * phaseGravTerm[ip][jp];
993 dDivMassFluxes_dElemVars[ic][elemVarsOffset] = dDivMassFluxes_dElemVars[ic][elemVarsOffset]
994 + dt_upwPhaseGravCoef * dPhaseGravTerm_dPres[ip][jp][Pos::NEIGHBOR];
996 for(
integer jc = 0; jc < NC; ++jc )
998 dDivMassFluxes_dElemVars[ic][elemVarsOffset+jc+1] = dDivMassFluxes_dElemVars[ic][elemVarsOffset+jc+1]
999 + dt * dUpwPhaseGravCoef_dCompDens[ip][jp][ic][Pos::NEIGHBOR][jc] * phaseGravTerm[ip][jp];
1000 dDivMassFluxes_dElemVars[ic][elemVarsOffset+jc+1] = dDivMassFluxes_dElemVars[ic][elemVarsOffset+jc+1]
1001 + dt_upwPhaseGravCoef * dPhaseGravTerm_dCompDens[ip][jp][Pos::NEIGHBOR][jc];
1008 template<
integer NF,
integer NC >
1012 AssemblerKernelHelper::
1019 real64 const (&oneSidedVolFlux)[ NF ],
1020 real64 const (&dOneSidedVolFlux_dPres)[ NF ],
1021 real64 const (&dOneSidedVolFlux_dFacePres)[ NF ][ NF ],
1022 real64 const (&dOneSidedVolFlux_dCompDens)[ NF ][ NC ],
1026 integer constexpr NDOF = NC+1;
1029 real64 dFlux_dElemVars[ NDOF ]{};
1030 real64 dFlux_dFaceVars[ NF ]{};
1035 for(
integer idof = 0; idof < NDOF; ++idof )
1037 dofColIndicesElemVars[idof] = elemDofNumber + idof;
1041 for(
integer ifaceLoc = 0; ifaceLoc < NF; ++ifaceLoc )
1046 if( faceGhostRank[kf] >= 0 )
1052 if( isBoundaryFace[kf] > 0 )
1058 real64 const flux = oneSidedVolFlux[ifaceLoc];
1059 dFlux_dElemVars[0] = dOneSidedVolFlux_dPres[ifaceLoc];
1060 for(
integer ic = 0; ic < NC; ++ic )
1062 dFlux_dElemVars[ic+1] = dOneSidedVolFlux_dCompDens[ifaceLoc][ic];
1065 for(
integer jfaceLoc = 0; jfaceLoc < NF; ++jfaceLoc )
1067 dFlux_dFaceVars[jfaceLoc] = dOneSidedVolFlux_dFacePres[ifaceLoc][jfaceLoc];
1068 dofColIndicesFaceVars[jfaceLoc] = faceDofNumber[elemToFaces[jfaceLoc]];
1072 localIndex const eqnLocalRowIndex = LvArray::integerConversion< localIndex >( faceDofNumber[elemToFaces[ifaceLoc]] - rankOffset );
1078 RAJA::atomicAdd( parallelDeviceAtomic{}, &localRhs[eqnLocalRowIndex], flux );
1081 localMatrix.addToRowBinarySearchUnsorted< parallelDeviceAtomic >( eqnLocalRowIndex,
1082 &dofColIndicesElemVars[0],
1083 &dFlux_dElemVars[0],
1087 localMatrix.addToRowBinarySearchUnsorted< parallelDeviceAtomic >( eqnLocalRowIndex,
1088 &dofColIndicesFaceVars[0],
1089 &dFlux_dFaceVars[0],
1096 template<
integer NF,
integer NC,
integer NP >
1114 real64 const & elemGravCoef,
1115 integer const useTotalMassEquation,
1135 real64 oneSidedVolFlux[ NF ]{};
1136 real64 dOneSidedVolFlux_dPres[ NF ]{};
1137 real64 dOneSidedVolFlux_dFacePres[ NF ][ NF ]{};
1138 real64 dOneSidedVolFlux_dCompDens[ NF ][ NC ]{};
1140 localIndex const localIds[3] = { er, esr, ei };
1150 AssemblerKernelHelper::applyGradient< NF, NC, NP >( facePres,
1155 phaseMassDens[er][esr][ei][0],
1156 dPhaseMassDens[er][esr][ei][0],
1157 phaseMob[er][esr][ei],
1158 dPhaseMob[er][esr][ei],
1159 dCompFrac_dCompDens[er][esr][ei],
1162 dOneSidedVolFlux_dPres,
1163 dOneSidedVolFlux_dFacePres,
1164 dOneSidedVolFlux_dCompDens );
1169 if( elemGhostRank < 0 )
1179 AssemblerKernelHelper::assembleFluxDivergence< NF, NC, NP >( localIds,
1190 useTotalMassEquation,
1197 dCompFrac_dCompDens,
1203 dOneSidedVolFlux_dPres,
1204 dOneSidedVolFlux_dFacePres,
1205 dOneSidedVolFlux_dCompDens,
1213 AssemblerKernelHelper::assembleFaceConstraints< NF, NC >( faceDofNumber,
1217 elemDofNumber[er][esr][ei],
1220 dOneSidedVolFlux_dPres,
1221 dOneSidedVolFlux_dFacePres,
1222 dOneSidedVolFlux_dCompDens,
1229 template<
integer NF,
integer NC,
integer NP,
typename IP_TYPE >
1233 CellElementSubRegion
const & subRegion,
1234 constitutive::PermeabilityBase
const & permeabilityModel,
1235 SortedArrayView< localIndex const >
const & regionFilter,
1236 arrayView2d< real64 const, nodes::REFERENCE_POSITION_USD >
const & nodePosition,
1237 arrayView2d< localIndex const >
const & elemRegionList,
1238 arrayView2d< localIndex const >
const & elemSubRegionList,
1239 arrayView2d< localIndex const >
const & elemList,
1240 ArrayOfArraysView< localIndex const >
const & faceToNodes,
1241 arrayView1d< globalIndex const >
const & faceDofNumber,
1242 arrayView1d< integer const >
const & faceGhostRank,
1243 arrayView1d< integer const >
const & isBoundaryFace,
1244 arrayView1d< real64 const >
const & facePres,
1245 arrayView1d< real64 const >
const & faceGravCoef,
1246 arrayView1d< real64 const >
const & mimFaceGravCoef,
1247 arrayView1d< real64 const >
const & transMultiplier,
1248 ElementViewConst< arrayView2d< real64 const, compflow::USD_PHASE > >
const & phaseMob,
1249 ElementViewConst< arrayView3d< real64 const, compflow::USD_PHASE_DC > >
const & dPhaseMob,
1250 ElementViewConst< arrayView3d< real64 const, compflow::USD_COMP_DC > >
const & dCompFrac_dCompDens,
1251 ElementViewConst< arrayView3d< real64 const, multifluid::USD_PHASE > >
const & phaseDens,
1252 ElementViewConst< arrayView4d< real64 const, multifluid::USD_PHASE_DC > >
const & dPhaseDens,
1253 ElementViewConst< arrayView3d< real64 const, multifluid::USD_PHASE > >
const & phaseMassDens,
1254 ElementViewConst< arrayView4d< real64 const, multifluid::USD_PHASE_DC > >
const & dPhaseMassDens,
1255 ElementViewConst< arrayView4d< real64 const, multifluid::USD_PHASE_COMP > >
const & phaseCompFrac,
1256 ElementViewConst< arrayView5d< real64 const, multifluid::USD_PHASE_COMP_DC > >
const & dPhaseCompFrac,
1257 ElementViewConst< arrayView1d< globalIndex const > >
const & elemDofNumber,
1259 real64 const lengthTolerance,
1261 integer const useTotalMassEquation,
1262 CRSMatrixView< real64, globalIndex const >
const & localMatrix,
1263 arrayView1d< real64 >
const & localRhs )
1266 arrayView1d< integer const >
const & elemGhostRank = subRegion.ghostRank();
1269 arrayView2d< localIndex const >
const & elemToFaces = subRegion.faceList();
1272 arrayView1d< real64 const >
const & elemPres =
1273 subRegion.getReference< array1d< real64 > >( fields::flow::pressure::key() );
1276 arrayView2d< real64 const >
const & elemCenter =
1278 arrayView1d< real64 const >
const & elemVolume =
1284 arrayView3d< real64 const >
const & elemPerm = permeabilityModel.permeability();
1287 arrayView1d< real64 const >
const & elemGravCoef =
1288 subRegion.getReference< array1d< real64 > >( fields::flow::gravityCoefficient::key() );
1295 stackArray2d< real64, NF *NF > transMatrix( NF, NF );
1296 stackArray2d< real64, NF *NF > transMatrixGrav( NF, NF );
1298 real64 const perm[ 3 ] = { elemPerm[ei][0][0], elemPerm[ei][0][1], elemPerm[ei][0][2] };
1302 IP_TYPE::template compute< NF >( nodePosition,
1315 mimeticInnerProduct::TPFAInnerProduct::compute< NF >( nodePosition,
1326 compositionalMultiphaseHybridFVMKernels::AssemblerKernel::compute< NF, NC, NP >( er, esr, ei,
1340 useTotalMassEquation,
1347 dCompFrac_dCompDens,
1363 template<
integer NF,
integer NC,
integer NP,
typename IP_TYPE >
1365 DirichletFluxKernel::
1366 launch(
integer const numPhases,
1370 constitutive::PermeabilityBase
const & permeabilityModel,
1385 real64 const lengthTolerance,
1388 integer const useTotalMassEquation,
1396 using Deriv = multifluid::DerivativeOffset;
1408 auto phaseMob = compFlowAccessors.
get( fields::flow::phaseMobility{} );
1409 auto dPhaseMob = compFlowAccessors.
get( fields::flow::dPhaseMobility{} );
1410 auto dCompFrac_dCompDens = compFlowAccessors.
get( fields::flow::dGlobalCompFraction_dGlobalCompDensity{} );
1413 auto phaseMassDens = multiFluidAccessors.
get( fields::multifluid::phaseMassDensity{} );
1414 auto dPhaseMassDens = multiFluidAccessors.
get( fields::multifluid::dPhaseMassDensity{} );
1415 auto phaseCompFrac = multiFluidAccessors.
get( fields::multifluid::phaseCompFraction{} );
1416 auto dPhaseCompFrac = multiFluidAccessors.
get( fields::multifluid::dPhaseCompFraction{} );
1424 localIndex erAdj = -1, esrAdj = -1, eiAdj = -1;
1425 for(
integer ke = 0; ke < elemRegionList.size( 1 ); ++ke )
1427 if( elemRegionList[kf][ke] == er && elemSubRegionList[kf][ke] == esr )
1429 erAdj = elemRegionList[kf][ke];
1430 esrAdj = elemSubRegionList[kf][ke];
1431 eiAdj = elemList[kf][ke];
1437 if( eiAdj < 0 || elemGhostRank[eiAdj] >= 0 )
1444 real64 const perm[3] = { elemPerm[eiAdj][0][0], elemPerm[eiAdj][0][1], elemPerm[eiAdj][0][2] };
1446 IP_TYPE::template compute< NF >( nodePosition,
1458 for(
integer j = 0; j < NF; ++j )
1460 if( elemToFaces[eiAdj][j] == kf )
1473 for(
integer jfaceLoc = 0; jfaceLoc < NF; ++jfaceLoc )
1475 cellFaces[jfaceLoc] = elemToFaces[eiAdj][jfaceLoc];
1480 real64 dCompFlux_dP[NC]{};
1481 real64 dCompFlux_dC[NC][NC]{};
1482 real64 dCompFlux_dFaceP[NC][NF]{};
1486 for(
integer ip = 0; ip < numPhases; ++ip )
1488 real64 dDensMean_dC[NC]{};
1493 real64 const elemDens = phaseMassDens[erAdj][esrAdj][eiAdj][0][ip];
1494 real64 const faceDens = facePhaseMassDens[kf][ip];
1495 real64 const densMean = 0.5 * (elemDens + faceDens);
1498 dCompFrac_dCompDens[erAdj][esrAdj][eiAdj],
1499 dPhaseMassDens[erAdj][esrAdj][eiAdj][0][ip],
1503 real64 const dDensMean_dP = 0.5 * dPhaseMassDens[erAdj][esrAdj][eiAdj][0][ip][Deriv::dP];
1504 for(
integer jc = 0; jc < NC; ++jc )
1506 dDensMean_dC[jc] = 0.5 * dProp_dC[jc];
1513 for(
integer jc = 0; jc < NC; ++jc )
1519 for(
integer jfaceLoc = 0; jfaceLoc < NF; ++jfaceLoc )
1523 real64 const gravTimesDz_j = elemGravCoef[eiAdj] - faceGravCoef[kfj];
1524 real64 const Tij = transMatrix[ifaceLoc][jfaceLoc];
1525 real64 const potDif_j = elemPres[eiAdj] - facePres[kfj] - densMean * gravTimesDz_j;
1528 f += Tij * potDif_j;
1529 dF_dP += Tij * ( 1.0 - dDensMean_dP * gravTimesDz_j );
1532 dF_dFaceP[jfaceLoc] = -Tij;
1534 for(
integer jc = 0; jc < NC; ++jc )
1536 dF_dC[jc] += -Tij * dDensMean_dC[jc] * gravTimesDz_j;
1543 real64 const beta = (f > 0.0) ? 1.0 : 0.0;
1544 real64 const facePhaseMobility = facePhaseMob[kf][ip];
1545 real64 const phaseMobility = beta * phaseMob[erAdj][esrAdj][eiAdj][ip] + (1.0 - beta) * facePhaseMobility;
1546 real64 const phaseFlux = phaseMobility * f;
1547 real64 const dPhaseFlux_dP = phaseMobility * dF_dP + beta * dPhaseMob[erAdj][esrAdj][eiAdj][ip][Deriv::dP] * f;
1548 real64 dPhaseFlux_dC[NC];
1549 real64 dPhaseFlux_dFaceP[NF];
1550 for(
integer jc = 0; jc < NC; ++jc )
1552 dPhaseFlux_dC[jc] = phaseMobility * dF_dC[jc] + beta * dPhaseMob[erAdj][esrAdj][eiAdj][ip][Deriv::dC+jc] * f;
1554 for(
integer jfaceLoc = 0; jfaceLoc < NF; ++jfaceLoc )
1556 dPhaseFlux_dFaceP[jfaceLoc] = phaseMobility * dF_dFaceP[jfaceLoc];
1561 for(
integer ic = 0; ic < NC; ++ic )
1563 real64 const ycpElem = phaseCompFrac[erAdj][esrAdj][eiAdj][0][ip][ic];
1564 real64 const ycpFace = facePhaseCompFrac[kf][ip][ic];
1567 real64 const ycp = beta * ycpElem + (1.0 - beta) * ycpFace;
1569 compFlux[ic] += ycp * phaseFlux;
1572 dCompFlux_dP[ic] += dPhaseFlux_dP * ycp + beta * phaseFlux * dPhaseCompFrac[erAdj][esrAdj][eiAdj][0][ip][ic][Deriv::dP];
1577 dCompFrac_dCompDens[erAdj][esrAdj][eiAdj],
1578 dPhaseCompFrac[erAdj][esrAdj][eiAdj][0][ip][ic],
1581 for(
integer jc = 0; jc < NC; ++jc )
1585 dCompFlux_dC[ic][jc] += ycp * dPhaseFlux_dC[jc] + beta * phaseFlux * dycpElem_dC[jc];
1589 for(
integer jfaceLoc = 0; jfaceLoc < NF; ++jfaceLoc )
1591 dCompFlux_dFaceP[ic][jfaceLoc] += dPhaseFlux_dFaceP[jfaceLoc] * ycp;
1598 real64 localFluxJacobian[NC][NC+1];
1600 for(
integer ic = 0; ic < NC; ++ic )
1602 localFlux[ic] = dt * compFlux[ic];
1603 localFluxJacobian[ic][0] = dt * dCompFlux_dP[ic];
1604 for(
integer jc = 0; jc < NC; ++jc )
1606 localFluxJacobian[ic][jc+1] = dt * dCompFlux_dC[ic][jc];
1611 if( useTotalMassEquation )
1614 compositionalMultiphaseUtilities::shiftRowsAheadByOneAndReplaceFirstRowWithColumnSum( NC, NC+1, localFluxJacobian, work );
1615 compositionalMultiphaseUtilities::shiftElementsAheadByOneAndReplaceFirstElementWithSum( NC, localFlux );
1619 globalIndex const elemDof = elemDofNumber[erAdj][esrAdj][eiAdj];
1620 localIndex const localRow = LvArray::integerConversion< localIndex >( elemDof - rankOffset );
1622 for(
integer ic = 0; ic < NC; ++ic )
1624 RAJA::atomicAdd( parallelDeviceAtomic{}, &localRhs[localRow + ic], localFlux[ic] );
1627 dofColIndices[0] = elemDof;
1628 for(
integer jc = 0; jc < NC; ++jc )
1630 dofColIndices[jc+1] = elemDof + jc + 1;
1633 localMatrix.addToRowBinarySearchUnsorted< parallelDeviceAtomic >( localRow + ic,
1635 localFluxJacobian[ic],
1639 for(
integer jfaceLoc = 0; jfaceLoc < NF; ++jfaceLoc )
1644 real64 facePressureJacobian = dt * dCompFlux_dFaceP[ic][jfaceLoc];
1647 if( useTotalMassEquation && ic == 0 )
1650 facePressureJacobian = 0.0;
1651 for(
integer icc = 0; icc < NC; ++icc )
1653 facePressureJacobian += dt * dCompFlux_dFaceP[icc][jfaceLoc];
1657 localMatrix.addToRowBinarySearchUnsorted< parallelDeviceAtomic >( localRow + ic,
1659 &facePressureJacobian,
1694 template<
integer NC,
integer NP >
1706 constitutive::MultiFluidBase & fluid,
1707 constitutive::RelativePermeabilityBase & relperm,
1713 constitutiveUpdatePassThru( fluid, [&] (
auto & castedFluid )
1715 using FluidType = TYPEOFREF( castedFluid );
1716 typename FluidType::KernelWrapper fluidWrapper = castedFluid.createKernelWrapper();
1718 constitutive::constitutiveUpdatePassThru( relperm, [&] (
auto & castedRelperm )
1720 using RelPermType = TYPEOFREF( castedRelperm );
1721 typename RelPermType::KernelWrapper relPermWrapper = castedRelperm.createKernelWrapper();
1727 forAll< serialPolicy >( boundaryFaceSet.size(), [=, &facePhaseMob, &facePhaseMassDens, &facePhaseCompFrac] (
localIndex const iset )
1729 localIndex const kf = boundaryFaceSet[iset];
1732 localIndex eiAdj = -1;
1733 for( integer ke = 0; ke < elemRegionList.size( 1 ); ++ke )
1735 if( elemRegionList[kf][ke] == er && elemSubRegionList[kf][ke] == esr )
1737 eiAdj = elemList[kf][ke];
1752 constitutive::multifluid::LAYOUT_PHASE_COMP > facePhaseCompFracLocal( 1, 1, numPhases, NC );
1755 for(
integer ip = 0; ip < numPhases; ++ip )
1757 facePhaseFrac[0][0][ip] = 0.0;
1758 facePhaseDens[0][0][ip] = 0.0;
1759 facePhaseMassDensLocal[0][0][ip] = 0.0;
1760 facePhaseVisc[0][0][ip] = 0.0;
1761 facePhaseEnthalpy[0][0][ip] = 0.0;
1762 facePhaseInternalEnergy[0][0][ip] = 0.0;
1763 for(
integer ic = 0; ic < NC; ++ic )
1765 facePhaseCompFracLocal[0][0][ip][ic] = 0.0;
1769 real64 faceTotalDens = 0.0;
1772 constitutive::MultiFluidBase::KernelWrapper::computeValues( fluidWrapper,
1776 facePhaseFrac[0][0],
1777 facePhaseDens[0][0],
1778 facePhaseMassDensLocal[0][0],
1779 facePhaseVisc[0][0],
1780 facePhaseEnthalpy[0][0],
1781 facePhaseInternalEnergy[0][0],
1782 facePhaseCompFracLocal[0][0],
1789 for(
integer ip = 0; ip < numPhases; ++ip )
1792 facePhaseMassDens[kf][ip] = facePhaseMassDensLocal[0][0][ip];
1795 real64 const faceKr = facePhaseFrac[0][0][ip];
1796 real64 const mu = facePhaseVisc[0][0][ip];
1798 facePhaseMob[kf][ip] = (mu > 0 && faceTotalDens > 0) ? faceTotalDens * faceKr / mu : 0.0;
1801 for(
integer ic = 0; ic < NC; ++ic )
1803 facePhaseCompFrac[kf][ip][ic] = facePhaseCompFracLocal[0][0][ip][ic];
void evaluateBCFaceProperties(integer const numPhases, SortedArrayView< localIndex const > const &boundaryFaceSet, arrayView1d< real64 const > const &facePres, arrayView1d< real64 const > const &faceTemp, arrayView2d< real64 const, compflow::USD_COMP > const &faceCompFrac, arrayView2d< localIndex const > const &elemRegionList, arrayView2d< localIndex const > const &elemSubRegionList, arrayView2d< localIndex const > const &elemList, localIndex const er, localIndex const esr, constitutive::MultiFluidBase &fluid, constitutive::RelativePermeabilityBase &relperm, arrayView2d< real64, compflow::USD_PHASE > const &facePhaseMob, arrayView2d< real64, compflow::USD_PHASE > const &facePhaseMassDens, arrayView3d< real64, compflow::USD_PHASE_COMP > const &facePhaseCompFrac)
Evaluate constitutive properties at BC face conditions.
#define GEOS_HOST_DEVICE
Marks a host-device function.
#define GEOS_UNUSED_VAR(...)
Mark an unused variable and silence compiler warnings.
#define GEOS_DEVICE
Marks a device-only function.
#define GEOS_ASSERT_GT(lhs, rhs)
Assert that one value compares greater than the other in debug builds.
#define GEOS_ASSERT_GE(lhs, rhs)
Assert that one value compares greater than or equal to the other in debug builds.
FixedOneToManyRelation & faceList()
Get the element-to-face map.
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.
GEOS_DECLTYPE_AUTO_RETURN getReference(LOOKUP_TYPE const &lookup) const
Look up a wrapper and get reference to wrapped object.
ArrayView< T, 1 > arrayView1d
Alias for 1D array view.
StackArray< T, 2, MAXSIZE > stackArray2d
Alias for 2D stack array.
Array< T, 2, PERMUTATION > array2d
Alias for 2D array.
GEOS_GLOBALINDEX_TYPE globalIndex
Global index type (for indexing objects across MPI partitions).
LvArray::StackArray< T, NDIM, PERMUTATION, localIndex, MAXSIZE > StackArray
Multidimensional stack-based array type. See LvArray:StackArray for details.
StackArray< T, 1, MAXSIZE > stackArray1d
Alias for 1D stack array.
LvArray::ArrayOfArraysView< T, INDEX_TYPE const, CONST_SIZES, LvArray::ChaiBuffer > ArrayOfArraysView
View of array of variable-sized arrays. See LvArray::ArrayOfArraysView for details.
ArraySlice< T, 2, USD > arraySlice2d
Alias for 2D 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.
LvArray::SortedArrayView< T, localIndex, LvArray::ChaiBuffer > SortedArrayView
A sorted array view of local indices.
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.
static constexpr char const * elementVolumeString()
static constexpr char const * elementCenterString()
ElementRegionManager::ElementViewConst< VIEWTYPE > ElementViewConst
The type for element-based non-constitutive data parameters. Consists entirely of ArrayView's.
ElementRegionManager::ElementViewConst< VIEWTYPE > ElementViewConst
The type for element-based non-constitutive data parameters. Consists entirely of ArrayView's.
ElementRegionManager::ElementViewConst< VIEWTYPE > ElementViewConst
The type for element-based non-constitutive data parameters. Consists entirely of ArrayView's.