GEOS
ImmiscibleMultiphaseKernels.hpp
Go to the documentation of this file.
1 /*
2  * ------------------------------------------------------------------------------------------------------------
3  * SPDX-License-Identifier: LGPL-2.1-only
4  *
5  * Copyright (c) 2016-2024 Lawrence Livermore National Security LLC
6  * Copyright (c) 2018-2024 TotalEnergies
7  * Copyright (c) 2018-2024 The Board of Trustees of the Leland Stanford Junior University
8  * Copyright (c) 2023-2024 Chevron
9  * Copyright (c) 2019- GEOS/GEOSX Contributors
10  * All rights reserved
11  *
12  * See top level LICENSE, COPYRIGHT, CONTRIBUTORS, NOTICE, and ACKNOWLEDGEMENTS files for details.
13  * ------------------------------------------------------------------------------------------------------------
14  */
15 
20 #ifndef GEOS_PHYSICSSOLVERS_FLUIDFLOW_MULTIPHASEKERNELS_HPP
21 #define GEOS_PHYSICSSOLVERS_FLUIDFLOW_MULTIPHASEKERNELS_HPP
22 
23 #include "codingUtilities/Utilities.hpp"
24 #include "common/DataLayouts.hpp"
25 #include "common/DataTypes.hpp"
26 #include "common/GEOS_RAJA_Interface.hpp"
27 #include "constitutive/fluid/twophaseimmisciblefluid/TwoPhaseImmiscibleFluid.hpp"
28 #include "constitutive/solid/CoupledSolidBase.hpp"
29 #include "constitutive/fluid/twophaseimmisciblefluid/TwoPhaseImmiscibleFluidFields.hpp"
30 #include "constitutive/capillaryPressure/CapillaryPressureFields.hpp"
31 #include "constitutive/capillaryPressure/CapillaryPressureBase.hpp"
32 #include "constitutive/permeability/PermeabilityBase.hpp"
33 #include "constitutive/permeability/PermeabilityFields.hpp"
34 #include "constitutive/relativePermeability/RelativePermeabilityBase.hpp"
35 #include "constitutive/relativePermeability/RelativePermeabilityFields.hpp"
42 #include "physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlowFields.hpp"
45 #include "physicsSolvers/fluidFlow/kernels/immiscibleMultiphase/KernelLaunchSelectors.hpp"
46 
47 namespace geos
48 {
49 namespace immiscibleMultiphaseKernels
50 {
51 using namespace constitutive;
52 
53 
54 /******************************** FluxComputeKernelBase ********************************/
55 
61 {
62 public:
63 
70  template< typename VIEWTYPE >
72 
74 
77  fields::flow::pressure,
78  fields::flow::gravityCoefficient,
79  fields::immiscibleMultiphaseFlow::phaseVolumeFraction,
80  fields::immiscibleMultiphaseFlow::phaseMobility,
81  fields::immiscibleMultiphaseFlow::dPhaseMobility >;
82 
84  StencilMaterialAccessors< constitutive::TwoPhaseImmiscibleFluid,
85  fields::twophaseimmisciblefluid::phaseDensity,
86  fields::twophaseimmisciblefluid::dPhaseDensity >;
87 
88  using CapPressureAccessors =
89  StencilMaterialAccessors< CapillaryPressureBase,
90  fields::cappres::phaseCapPressure,
91  fields::cappres::dPhaseCapPressure_dPhaseVolFraction >;
92 
93  using PermeabilityAccessors =
94  StencilMaterialAccessors< PermeabilityBase,
95  fields::permeability::permeability,
96  fields::permeability::dPerm_dPressure >;
97 
99 
115  FluxComputeKernelBase( integer const numPhases,
116  globalIndex const rankOffset,
117  DofNumberAccessor const & dofNumberAccessor,
118  ImmiscibleMultiphaseFlowAccessors const & multiPhaseFlowAccessors,
119  MultiphaseFluidAccessors const & fluidAccessors,
120  CapPressureAccessors const & capPressureAccessors,
121  PermeabilityAccessors const & permeabilityAccessors,
122  real64 const & dt,
123  CRSMatrixView< real64, globalIndex const > const & localMatrix,
124  arrayView1d< real64 > const & localRhs,
125  integer const hasCapPressure,
126  integer const useTotalMassEquation,
127  integer const checkPhasePresenceInGravity )
128  : m_numPhases ( numPhases ),
129  m_rankOffset( rankOffset ),
130  m_dt( dt ),
131  m_dofNumber( dofNumberAccessor.toNestedViewConst() ),
132  m_permeability( permeabilityAccessors.get( fields::permeability::permeability {} ) ),
133  m_dPerm_dPres( permeabilityAccessors.get( fields::permeability::dPerm_dPressure {} ) ),
134  m_ghostRank( multiPhaseFlowAccessors.get( fields::ghostRank {} ) ),
135  m_gravCoef( multiPhaseFlowAccessors.get( fields::flow::gravityCoefficient {} ) ),
136  m_pres( multiPhaseFlowAccessors.get( fields::flow::pressure {} ) ),
137  m_phaseVolFrac( multiPhaseFlowAccessors.get( fields::immiscibleMultiphaseFlow::phaseVolumeFraction {} ) ),
138  m_mob( multiPhaseFlowAccessors.get( fields::immiscibleMultiphaseFlow::phaseMobility {} ) ),
139  m_dMob( multiPhaseFlowAccessors.get( fields::immiscibleMultiphaseFlow::dPhaseMobility {} ) ),
140  m_dens( fluidAccessors.get( fields::twophaseimmisciblefluid::phaseDensity {} ) ),
141  m_dDens_dPres( fluidAccessors.get( fields::twophaseimmisciblefluid::dPhaseDensity {} ) ),
142  m_phaseCapPressure( capPressureAccessors.get( fields::cappres::phaseCapPressure {} ) ),
143  m_dPhaseCapPressure_dPhaseVolFrac( capPressureAccessors.get( fields::cappres::dPhaseCapPressure_dPhaseVolFraction {} ) ),
144  m_localMatrix( localMatrix ),
145  m_localRhs( localRhs ),
146  m_hasCapPressure ( hasCapPressure ),
147  m_useTotalMassEquation ( useTotalMassEquation ),
148  m_checkPhasePresenceInGravity ( checkPhasePresenceInGravity )
149  {}
150 
151 protected:
152 
155 
158 
160  real64 const m_dt;
161 
164 
168 
172 
173  // Primary and secondary variables
177 
181 
185 
188  ElementViewConst< arrayView4d< real64 const, cappres::USD_CAPPRES_DS > > const m_dPhaseCapPressure_dPhaseVolFrac;
189 
190  // Residual and jacobian
191 
196 
197  // Flags
198  integer const m_hasCapPressure;
199  integer const m_useTotalMassEquation;
200  integer const m_checkPhasePresenceInGravity;
201 };
202 
203 /***************************************** */
204 
211 template< integer NUM_EQN, integer NUM_DOF, typename STENCILWRAPPER >
213 {
214 public:
215 
217  static constexpr integer numDof = NUM_DOF;
218 
220  static constexpr integer numEqn = NUM_EQN;
221 
223  static constexpr localIndex maxNumElems = STENCILWRAPPER::maxNumPointsInFlux;
224 
226  static constexpr localIndex maxNumConns = STENCILWRAPPER::maxNumConnections;
227 
229  static constexpr localIndex maxStencilSize = STENCILWRAPPER::maxStencilSize;
230 
247  FluxComputeKernel( integer const numPhases,
248  globalIndex const rankOffset,
249  STENCILWRAPPER const & stencilWrapper,
250  DofNumberAccessor const & dofNumberAccessor,
251  ImmiscibleMultiphaseFlowAccessors const & multiPhaseFlowAccessors,
252  MultiphaseFluidAccessors const & fluidAccessors,
253  CapPressureAccessors const & capPressureAccessors,
254  PermeabilityAccessors const & permeabilityAccessors,
255  real64 const & dt,
256  CRSMatrixView< real64, globalIndex const > const & localMatrix,
257  arrayView1d< real64 > const & localRhs,
258  integer const hasCapPressure,
259  integer const useTotalMassEquation,
260  integer const checkPhasePresenceInGravity )
261  : FluxComputeKernelBase( numPhases,
262  rankOffset,
263  dofNumberAccessor,
264  multiPhaseFlowAccessors,
265  fluidAccessors,
266  capPressureAccessors,
267  permeabilityAccessors,
268  dt,
269  localMatrix,
270  localRhs,
271  hasCapPressure,
272  useTotalMassEquation,
273  checkPhasePresenceInGravity ),
274  m_stencilWrapper( stencilWrapper ),
275  m_seri( stencilWrapper.getElementRegionIndices() ),
276  m_sesri( stencilWrapper.getElementSubRegionIndices() ),
277  m_sei( stencilWrapper.getElementIndices() )
278  {}
279 
285  {
286 public:
287 
294  StackVariables( localIndex const size, localIndex numElems )
295  : stencilSize( size ),
296  numFluxElems( numElems ),
297  dofColIndices( size * numDof ),
298  localFlux( numElems * numEqn ),
299  localFluxJacobian( numElems * numEqn, size * numDof )
300  {}
301 
302  // Stencil information
303 
306 
309 
310  // Transmissibility and derivatives
311 
313  real64 transmissibility[maxNumConns][2]{};
315  real64 dTrans_dPres[maxNumConns][2]{};
316 
317  // Local degrees of freedom and local residual/jacobian
318 
321 
326  };
327 
334  localIndex stencilSize( localIndex const iconn ) const
335  { return m_sei[iconn].size(); }
336 
343  localIndex numPointsInFlux( localIndex const iconn ) const
344  { return m_stencilWrapper.numPointsInFlux( iconn ); }
345 
353  void setup( localIndex const iconn,
354  StackVariables & stack ) const
355  {
356  // set degrees of freedom indices for this face
357  for( integer i = 0; i < stack.stencilSize; ++i )
358  {
359  globalIndex const offset = m_dofNumber[m_seri( iconn, i )][m_sesri( iconn, i )][m_sei( iconn, i )];
360 
361  for( integer jdof = 0; jdof < numDof; ++jdof )
362  {
363  stack.dofColIndices[i * numDof + jdof] = offset + jdof;
364  }
365  }
366  }
367 
375  template< typename FUNC = NoOpFunc > // should change to multiphase
377  void computeFlux( localIndex const iconn,
378  StackVariables & stack,
379  FUNC && kernelOp = NoOpFunc{} ) const
380  {
381  // first, compute the transmissibilities at this face // get k and dk/dP from global arrays
382  // and place in stack
383  m_stencilWrapper.computeWeights( iconn,
384  m_permeability,
385  m_dPerm_dPres,
386  stack.transmissibility,
387  stack.dTrans_dPres );
388 
389  localIndex k[2];
390  localIndex connectionIndex = 0;
391 
392  for( k[0] = 0; k[0] < stack.numFluxElems; ++k[0] )
393  {
394  for( k[1] = k[0] + 1; k[1] < stack.numFluxElems; ++k[1] )
395  {
396  // clear working arrays
397  real64 densMean[numEqn]{};
398  real64 dDensMean_dP[numEqn][2]{};
399 
400  real64 presGrad[numEqn]{};
401  real64 dPresGrad_dP[numEqn][2]{};
402 
403  real64 gravHead[numEqn]{};
404  real64 dGravHead_dP[numEqn][2]{};
405 
406  real64 capGrad[numEqn]{};
407  real64 dCapGrad_dP[numEqn][2]{};
408  real64 dCapGrad_dS[numEqn][2]{};
409 
410  real64 fluxVal[numEqn]{};
411  real64 dFlux_dP[numEqn][2]{};
412  real64 dFlux_dS[numEqn][2]{};
413 
414  real64 mobility[numEqn]{};
415  real64 dMob_dP[numEqn][2]{};
416  real64 dMob_dS[numEqn][2]{};
417 
418  real64 const trans[2] = { stack.transmissibility[connectionIndex][0], stack.transmissibility[connectionIndex][1] };
419  real64 const dTrans_dP[2] = { stack.dTrans_dPres[connectionIndex][0], stack.dTrans_dPres[connectionIndex][1] };
420 
421  // cell indices
422  localIndex const seri[2] = {m_seri( iconn, k[0] ), m_seri( iconn, k[1] )};
423  localIndex const sesri[2] = {m_sesri( iconn, k[0] ), m_sesri( iconn, k[1] )};
424  localIndex const sei[2] = {m_sei( iconn, k[0] ), m_sei( iconn, k[1] )};
425 
426  // loop over phases
427  for( integer ip = 0; ip < m_numPhases; ++ip )
428  {
429  // calculate quantities on primary connected cells
430  integer denom = 0;
431  for( integer ke = 0; ke < 2; ++ke )
432  {
433  // density
434  bool const phaseExists = (m_phaseVolFrac[seri[ke]][sesri[ke]][sei[ke]][ip] > 0);
435  if( m_checkPhasePresenceInGravity && !phaseExists )
436  {
437  continue;
438  }
439 
440  real64 const density = m_dens[seri[ke]][sesri[ke]][sei[ke]][0][ip]; // r = rho1 || rho2
441  real64 const dDens_dP = m_dDens_dPres[seri[ke]][sesri[ke]][sei[ke]][0][ip][Deriv::dP]; // dr/dP = dr1/dP1 || dr2/dP
442 
443  // average density and derivatives
444  densMean[ip] += density; // rho = (rho1 + rho2)
445  dDensMean_dP[ip][ke] = dDens_dP; // drho/dP = { (dr1/dP1) , (dr2/dP2) }
446 
447  denom++;
448  }
449 
450  if( denom > 1 )
451  {
452  densMean[ip] /= denom; // rho = (rho1 + rho2) / denom
453  for( integer ke = 0; ke < 2; ++ke )
454  {
455  dDensMean_dP[ip][ke] /= denom; // drho/dP = { (dr1/dP1) / denom , (dr2/dP2) / denom }
456  }
457  }
458 
459  //***** calculation of flux *****
460 
461  // compute potential difference
462  real64 potScale = 0.0;
463  real64 dPresGrad_dTrans = 0.0;
464  real64 dGravHead_dTrans = 0.0;
465  real64 dCapGrad_dTrans = 0.0;
466  constexpr int signPotDiff[2] = {1, -1};
467 
468  for( integer ke = 0; ke < 2; ++ke )
469  {
470  localIndex const er = seri[ke];
471  localIndex const esr = sesri[ke];
472  localIndex const ei = sei[ke];
473 
474  real64 const pressure = m_pres[er][esr][ei]; // P = P1 || P2
475  presGrad[ip] += trans[ke] * pressure; // DPv = T (P1 - P2)
476  dPresGrad_dTrans += signPotDiff[ke] * pressure; // dDPv/dT = (P1 - P2)
477  dPresGrad_dP[ip][ke] = trans[ke]; // dDPv/dP = { T , -T }
478 
479  real64 const gravD = trans[ke] * m_gravCoef[er][esr][ei]; // D = T g z1 || -T g z2
480  real64 pot = trans[ke] * pressure - densMean[ip] * gravD; // Phi = T P1 - rho T g z1 || -T P2 + rho T g z2
481 
482  gravHead[ip] += densMean[ip] * gravD; // DPg = rho (T g z1 - T g z2) = T rho g (z1 - z2)
483  dGravHead_dTrans += signPotDiff[ke] * densMean[ip] * m_gravCoef[er][esr][ei]; // dDPg/dT = rho g z1 - rho g z2 = rho g (z1 - z2)
484 
485  for( integer i = 0; i < 2; ++i )
486  {
487  dGravHead_dP[ip][i] += dDensMean_dP[ip][i] * gravD; // dDPg/dP = {drho/dP1 * T g (z1 - z2) , drho/dP2 * T g (z1 - z2)}
488  }
489 
490  if( m_hasCapPressure ) // check sign convention
491  {
492  real64 const capPres = m_phaseCapPressure[er][esr][ei][0][ip]; // Pc = Pc1 || Pc2
493  dCapGrad_dTrans -= signPotDiff[ke] * capPres; // dDPc/dT = (-Pc1 + Pc2)
494  pot -= trans[ke] * capPres; // Phi = T P1 - rho T g z1 - T Pc1 || -T P2 + rho T g z2 + T
495  // Pc2
496  capGrad[ip] -= trans[ke] * capPres; // DPc = T (-Pc1 + Pc2)
497  }
498 
499  potScale = fmax( potScale, fabs( pot ) ); // maxPhi = Phi1 > Phi2 ? Phi1 : Phi2
500  }
501 
502  for( integer ke = 0; ke < 2; ++ke )
503  {
504  dPresGrad_dP[ip][ke] += dTrans_dP[ke] * dPresGrad_dTrans; // dDPv/dP = { T + dT/dP1 * (P1 - P2) , -T + dT/dP2 * (P1 - P2)}
505  dGravHead_dP[ip][ke] += dTrans_dP[ke] * dGravHead_dTrans; // dDPg/dP = { drho/dP1 * T g (z1 - z2) + dT/dP1 * rho g (z1 - z2) ,
506  // drho/dP2 * T g (z1 - z2) + dT/dP2 * rho g (z1 - z2) }
507  if( m_hasCapPressure )
508  {
509  real64 const dCapPres_dS = m_dPhaseCapPressure_dPhaseVolFrac[seri[ke]][sesri[ke]][sei[ke]][0][ip][ip]; // dPc/dS = dPc1/dS1 ||
510  // dPc2/dS2
511  dCapGrad_dP[ip][ke] += dTrans_dP[ke] * dCapGrad_dTrans; // dDPc/dP = { dT/dP1 *
512  // (-Pc1 + Pc2) ,
513  // dT/dP2 *
514  // (-Pc1 + Pc2) }
515  dCapGrad_dS[ip][ke] -= trans[ke] * dCapPres_dS; // dDPc/dS = { -T *
516  // dPc1/dS1 , T *
517  // dPc2/dS2 }
518  }
519  }
520 
521  // *** upwinding ***
522 
523  // compute potential gradient
524  real64 potGrad = presGrad[ip] - gravHead[ip]; // DPhi = T (P1 - P2) - T rho g (z1 - z2)
525  if( m_hasCapPressure )
526  {
527  potGrad += capGrad[ip]; // DPhi = T (P1 - P2) - T rho g (z1 - z2) + T (-Pc1 + Pc2)
528  }
529 
530  // compute upwinding tolerance
531  real64 constexpr upwRelTol = 1e-8;
532  real64 const upwAbsTol = fmax( potScale * upwRelTol, LvArray::NumericLimits< real64 >::epsilon ); // abstol = maxPhi * tol > eps ?
533  // maxPhi * tol : eps
534 
535  // decide mobility coefficients - smooth variation in [-upwAbsTol; upwAbsTol]
536  real64 const alpha = ( potGrad + upwAbsTol ) / ( 2 * upwAbsTol ); // alpha = (DPhi + abstol) / abstol / 2
537 
538  // choose upstream cell
539  if( alpha <= 0.0 || alpha >= 1.0 ) // no smoothing needed
540  {
541  localIndex const k_up = 1 - localIndex( fmax( fmin( alpha, 1.0 ), 0.0 ) ); // 1 upwind -> k_up = 0 || 2 upwind -> k_up = 1
542 
543  mobility[ip] = m_mob[seri[k_up]][sesri[k_up]][sei[k_up]][ip]; // M = Mupstream
544  dMob_dP[ip][k_up] = m_dMob[seri[k_up]][sesri[k_up]][sei[k_up]][ip][Deriv::dP]; // dM/dP = {dM/dP1 , 0} OR {0 , dM/dP2}
545  dMob_dS[ip][k_up] = m_dMob[seri[k_up]][sesri[k_up]][sei[k_up]][ip][Deriv::dS]; // dM/dS = {dM/dS1 , 0} OR {0 , dM/dS2}
546  }
547  else // perform smoothing
548  {
549  real64 const mobWeights[2] = { alpha, 1.0 - alpha };
550  for( integer ke = 0; ke < 2; ++ke )
551  {
552  mobility[ip] += mobWeights[ke] * m_mob[seri[ke]][sesri[ke]][sei[ke]][ip]; // M = alpha * M1 + (1 - alpha) * M2
553  dMob_dP[ip][ke] = mobWeights[ke] * m_dMob[seri[ke]][sesri[ke]][sei[ke]][ip][Deriv::dP]; // dM/dP = {alpha * dM1/dP1 , (1 -
554  // alpha) * dM2/dP2}
555  dMob_dS[ip][ke] = mobWeights[ke] * m_dMob[seri[ke]][sesri[ke]][sei[ke]][ip][Deriv::dS]; // dM/dP = {alpha * dM1/dS1 , (1 -
556  // alpha) * dM2/dS2}
557  }
558  }
559 
560  // pressure gradient depends on all points in the stencil
561  for( integer ke = 0; ke < 2; ++ke )
562  {
563  dFlux_dP[ip][ke] += dPresGrad_dP[ip][ke]; // dF/dP = { T + dT/dP1 * (P1 - P2) ,
564  // -T + dT/dP2 * (P1 - P2) }
565  }
566 
567  // gravitational head depends only on the two cells connected (same as mean density)
568  for( integer ke = 0; ke < 2; ++ke )
569  {
570  dFlux_dP[ip][ke] -= dGravHead_dP[ip][ke]; // dF/dP = { T + dT/dP1 * (P1 - P2) - drho/dP1 * T g (z1 - z2) - dT/dP1 * rho g (z1 -
571  // z2) ,
572  // -T + dT/dP2 * (P1 - P2) - drho/dP2 * T g (z1 - z2) - dT/dP2 * rho g (z1 -
573  // z2) }
574  }
575 
576  // capillary pressure contribution
577  if( m_hasCapPressure )
578  {
579  for( integer ke = 0; ke < 2; ++ke )
580  {
581  dFlux_dP[ip][ke] += dCapGrad_dP[ip][ke]; // dF/dP = { T + dT/dP1 * (P1 - P2) - drho/dP1 * T g (z1 - z2) - dT/dP1 * rho g (z1
582  // - z2) + dT/dP1 * (-Pc1 + Pc2) ,
583  // -T + dT/dP2 * (P1 - P2) - drho/dP2 * T g (z1 - z2) - dT/dP2 * rho g (z1
584  // - z2) + dT/dP2 * (-Pc1 + Pc2) }
585 
586  dFlux_dS[ip][ke] += dCapGrad_dS[ip][ke]; // dF/dS = { T * -dPc/dS1 , T * dPc/dS2 }
587  }
588  }
589 
590  // compute the flux and derivatives using upstream cell mobility
591  fluxVal[ip] = mobility[ip] * potGrad; // F = M * DPhi
592 
593  for( integer ke = 0; ke < 2; ++ke )
594  {
595  dFlux_dP[ip][ke] *= mobility[ip]; // dF/dP = { M [ T + dT/dP1 * (P1 - P2) - drho/dP1 * T g (z1 - z2) - dT/dP1 * rho g (z1 -
596  // z2) + dT/dP1 * (-Pc1 + Pc2)] ,
597  // M [-T + dT/dP2 * (P1 - P2) - drho/dP2 * T g (z1 - z2) - dT/dP2 * rho g (z1 -
598  // z2) + dT/dP2 * (-Pc1 + Pc2)] }
599 
600  dFlux_dS[ip][ke] *= mobility[ip]; // dF/dS = { M [T * -dPc/dS1] , M [T * dPc/dS2] }
601  }
602 
603  // add contribution from upstream cell mobility derivatives
604  for( integer ke = 0; ke < 2; ++ke )
605  {
606  dFlux_dP[ip][ke] += dMob_dP[ip][ke] * potGrad; // dF/dP = { M [ T + dT/dP1 * (P1 - P2) - drho1/dP * T g (z1 - z2) - dT/dP1 *
607  // rho g (z1 - z2) + dT/dP1 * (-Pc1 + Pc2)] + dM/dP1 * DPhi ,
608  // M [-T + dT/dP2 * (P1 - P2) - drho2/dP * T g (z1 - z2) - dT/dP2 *
609  // rho g (z1 - z2) + dT/dP2 * (-Pc1 + Pc2)] + dM/dP2 * DPhi }
610 
611  dFlux_dS[ip][ke] += dMob_dS[ip][ke] * potGrad; // dF/dS = { M [T * -dPc/dS1] + dM/dS1 * DPhi , M [T * dPc/dS2] + dM/dS2 * DPhi
612  // }
613  }
614 
615  // populate local flux vector and derivatives
616  stack.localFlux[k[0]*numEqn + ip] += m_dt * fluxVal[ip];
617  stack.localFlux[k[1]*numEqn + ip] -= m_dt * fluxVal[ip];
618 
619  for( integer ke = 0; ke < 2; ++ke )
620  {
621  // pressure
622  localIndex const localDofIndexPres = k[ke] * numDof;
623  stack.localFluxJacobian[k[0]*numEqn + ip][localDofIndexPres] += m_dt * dFlux_dP[ip][ke];
624  stack.localFluxJacobian[k[1]*numEqn + ip][localDofIndexPres] -= m_dt * dFlux_dP[ip][ke];
625 
626  // saturation (hard-coded for 2-phase currently)
627  localIndex const localDofIndexSat = k[ke] * numDof + 1;
628  stack.localFluxJacobian[k[0]*numEqn + ip][localDofIndexSat] += m_dt * dFlux_dS[ip][ke];
629  stack.localFluxJacobian[k[1]*numEqn + ip][localDofIndexSat] -= m_dt * dFlux_dS[ip][ke];
630  }
631 
632  // Customize the kernel with this lambda
633  kernelOp( k, seri, sesri, sei, connectionIndex, alpha, mobility, potGrad, fluxVal, dFlux_dP, dFlux_dS ); // Not sure what this
634  // does
635 
636  } // loop over phases
637 
638  connectionIndex++;
639  }
640  } // loop over connection elements
641  }
642 
648  template< typename FUNC = NoOpFunc > // should change to multiphase
650  void complete( localIndex const iconn,
651  StackVariables & stack,
652  FUNC && kernelOp = NoOpFunc{} ) const
653  {
654  using namespace compositionalMultiphaseUtilities;
655 
656  if( m_useTotalMassEquation )
657  {
658  // Apply equation/variable change transformation(s)
660  shiftBlockRowsAheadByOneAndReplaceFirstRowWithColumnSum( m_numPhases, numEqn, numDof * stack.stencilSize, stack.numFluxElems,
661  stack.localFluxJacobian, work );
662  shiftBlockElementsAheadByOneAndReplaceFirstElementWithSum( m_numPhases, numEqn, stack.numFluxElems,
663  stack.localFlux );
664  }
665 
666  // add contribution to residual and jacobian into:
667  // - the mass balance equation
668  // note that numDof includes derivatives wrt temperature if this class is derived in ThermalKernels
669  for( integer i = 0; i < stack.numFluxElems; ++i )
670  {
671  if( m_ghostRank[m_seri( iconn, i )][m_sesri( iconn, i )][m_sei( iconn, i )] < 0 )
672  {
673  globalIndex const globalRow = m_dofNumber[m_seri( iconn, i )][m_sesri( iconn, i )][m_sei( iconn, i )];
674  localIndex const localRow = LvArray::integerConversion< localIndex >( globalRow - m_rankOffset );
675  GEOS_ASSERT_GE( localRow, 0 );
676 
677  GEOS_ASSERT_GT( m_localMatrix.numRows(), localRow + numEqn - 1 );
678 
679  for( integer ic = 0; ic < numEqn; ++ic )
680  {
681  RAJA::atomicAdd( parallelDeviceAtomic{}, &m_localRhs[localRow + ic],
682  stack.localFlux[i * numEqn + ic] );
683  m_localMatrix.addToRowBinarySearchUnsorted< parallelDeviceAtomic >
684  ( localRow + ic,
685  stack.dofColIndices.data(),
686  stack.localFluxJacobian[i * numEqn + ic].dataIfContiguous(),
687  stack.stencilSize * numDof );
688  }
689 
690  // call the lambda to assemble additional terms, such as thermal terms
691  kernelOp( i, localRow );
692  }
693  }
694  }
695 
703  template< typename POLICY, typename KERNEL_TYPE >
704  static void
705  launch( localIndex const numConnections,
706  KERNEL_TYPE const & kernelComponent )
707  {
709 
710  forAll< POLICY >( numConnections, [=] GEOS_HOST_DEVICE ( localIndex const iconn )
711  {
712  typename KERNEL_TYPE::StackVariables stack( kernelComponent.stencilSize( iconn ),
713  kernelComponent.numPointsInFlux( iconn ) );
714 
715  kernelComponent.setup( iconn, stack );
716  kernelComponent.computeFlux( iconn, stack );
717  kernelComponent.complete( iconn, stack );
718  } );
719  }
720 
721 protected:
722 
723  // Stencil information
724 
726  STENCILWRAPPER const m_stencilWrapper;
727 
729  typename STENCILWRAPPER::IndexContainerViewConstType const m_seri;
730  typename STENCILWRAPPER::IndexContainerViewConstType const m_sesri;
731  typename STENCILWRAPPER::IndexContainerViewConstType const m_sei;
732 };
733 
734 
735 /****************************************** */
736 
741 {
742 public:
743 
757  template< typename POLICY, typename STENCILWRAPPER >
758  static void
759  createAndLaunch( integer const numPhases,
760  globalIndex const rankOffset,
761  string const & dofKey,
762  integer const hasCapPressure,
763  integer const useTotalMassEquation,
764  integer const checkPhasePresenceInGravity,
765  string const & solverName,
766  ElementRegionManager const & elemManager,
767  STENCILWRAPPER const & stencilWrapper,
768  real64 const & dt,
769  CRSMatrixView< real64, globalIndex const > const & localMatrix,
770  arrayView1d< real64 > const & localRhs )
771  {
772  integer constexpr NUM_EQN = 2;
773  integer constexpr NUM_DOF = 2;
774 
776  elemManager.constructArrayViewAccessor< globalIndex, 1 >( dofKey );
777  dofNumberAccessor.setName( solverName + "/accessors/" + dofKey );
778 
780  typename kernelType::ImmiscibleMultiphaseFlowAccessors flowAccessors( elemManager, solverName );
781  typename kernelType::MultiphaseFluidAccessors fluidAccessors( elemManager, solverName );
782  typename kernelType::CapPressureAccessors capPressureAccessors( elemManager, solverName );
783  typename kernelType::PermeabilityAccessors permAccessors( elemManager, solverName );
784 
785  kernelType kernel( numPhases, rankOffset, stencilWrapper, dofNumberAccessor,
786  flowAccessors, fluidAccessors, capPressureAccessors, permAccessors,
787  dt, localMatrix, localRhs, hasCapPressure, useTotalMassEquation,
788  checkPhasePresenceInGravity );
789  kernelType::template launch< POLICY >( stencilWrapper.size(), kernel );
790  }
791 };
792 
793 
794 /******************************** AccumulationKernel ********************************/
795 
796 enum class KernelFlags
797 {
798  TotalMassEquation = 1 << 0, // 1
799 
801  // Flag2 = 1 << 1, // 2
802  // Flag3 = 1 << 2, // 4
803  // Flag4 = 1 << 3, // 8
804  // Flag5 = 1 << 4, // 16
805  // Flag6 = 1 << 5, // 32
806  // Flag7 = 1 << 6, // 64
807  // Flag8 = 1 << 7 //128
808 };
816 template< integer NUM_EQN, integer NUM_DOF >
818 {
819 public:
820 
823 
825  static constexpr integer numDof = NUM_DOF;
826 
828  static constexpr integer numEqn = NUM_EQN;
829 
842  AccumulationKernel( localIndex const numPhases,
843  globalIndex const rankOffset,
844  string const dofKey,
845  ElementSubRegionBase const & subRegion,
846  constitutive::TwoPhaseImmiscibleFluid const & fluid,
847  constitutive::CoupledSolidBase const & solid,
848  CRSMatrixView< real64, globalIndex const > const & localMatrix,
849  arrayView1d< real64 > const & localRhs,
850  BitFlags< KernelFlags > const kernelFlags )
851  : m_numPhases( numPhases ),
852  m_rankOffset( rankOffset ),
853  m_dofNumber( subRegion.getReference< array1d< globalIndex > >( dofKey ) ),
854  m_elemGhostRank( subRegion.ghostRank() ),
855  m_volume( subRegion.getElementVolume() ),
856  m_porosity( solid.getPorosity() ),
857  m_dPoro_dPres( solid.getDporosity_dPressure() ),
858  m_phaseVolFrac( subRegion.getField< fields::immiscibleMultiphaseFlow::phaseVolumeFraction >() ),
859  m_phaseDens( fluid.phaseDensity() ),
860  m_dPhaseDens( fluid.dPhaseDensity() ),
861  m_phaseMass_n( subRegion.template getField< fields::immiscibleMultiphaseFlow::phaseMass_n >() ),
862  m_localMatrix( localMatrix ),
863  m_localRhs( localRhs ),
864  m_kernelFlags( kernelFlags )
865  {}
866 
872  {
873 public:
874 
875  // Pore volume information (used by both accumulation)
876 
878  real64 poreVolume = 0.0;
879 
881  real64 dPoreVolume_dPres = 0.0;
882 
883  // Residual information
884 
886  localIndex localRow = -1;
887 
889  globalIndex dofIndices[numDof]{};
890 
892  real64 localResidual[numEqn]{};
893 
895  real64 localJacobian[numEqn][numDof]{};
896 
897  };
898 
905  integer elemGhostRank( localIndex const ei ) const
906  { return m_elemGhostRank( ei ); }
907 
908 
915  void setup( localIndex const ei,
916  StackVariables & stack ) const
917  {
918  // initialize the pore volume
919  stack.poreVolume = m_volume[ei] * m_porosity[ei][0];
920  stack.dPoreVolume_dPres = m_volume[ei] * m_dPoro_dPres[ei][0];
921 
922  // set row index and degrees of freedom indices for this element
923  stack.localRow = m_dofNumber[ei] - m_rankOffset;
924  for( integer idof = 0; idof < numDof; ++idof )
925  {
926  stack.dofIndices[idof] = m_dofNumber[ei] + idof;
927  }
928  }
929 
937  StackVariables & stack ) const
938  {
939  constexpr int sign[2] = {1, -1};
940  // ip - index of phase/component whose conservation equation is assembled
941  // (i.e. row number in local matrix)
942  for( integer ip = 0; ip < m_numPhases; ++ip )
943  {
944  real64 const phaseMass = stack.poreVolume * m_phaseVolFrac[ei][ip] * m_phaseDens[ei][0][ip];
945  real64 const phaseMass_n = m_phaseMass_n[ei][ip];
946 
947  stack.localResidual[ip] += phaseMass - phaseMass_n;
948 
949  real64 const dPhaseMass_dP = stack.dPoreVolume_dPres * m_phaseVolFrac[ei][ip] * m_phaseDens[ei][0][ip]
950  + stack.poreVolume * m_phaseVolFrac[ei][ip] * m_dPhaseDens[ei][0][ip][0];
951  stack.localJacobian[ip][0] += dPhaseMass_dP;
952 
953  real64 const dPhaseMass_dS = stack.poreVolume * m_phaseDens[ei][0][ip];
954  stack.localJacobian[ip][1] += sign[ip] * dPhaseMass_dS;
955  }
956  }
957 
965  StackVariables & stack ) const
966  {
967  using namespace compositionalMultiphaseUtilities;
968 
969  if( m_kernelFlags.isSet( KernelFlags::TotalMassEquation ) )
970  {
971  // apply equation/variable change transformation to the component mass balance equations
972  real64 work[numDof]{};
973  shiftRowsAheadByOneAndReplaceFirstRowWithColumnSum( m_numPhases, numDof, stack.localJacobian, work );
974  shiftElementsAheadByOneAndReplaceFirstElementWithSum( m_numPhases, stack.localResidual );
975  }
976 
977  // add contribution to residual and jacobian into:
978  // - the component mass balance equations (i = 0 to i = numPhase - 1)
979  // note that numDof includes derivatives wrt temperature if this class is derived in ThermalKernels
980  integer const numRows = m_numPhases;
981  for( integer i = 0; i < numRows; ++i )
982  {
983  m_localRhs[stack.localRow + i] += stack.localResidual[i];
984  m_localMatrix.addToRow< serialAtomic >( stack.localRow + i,
985  stack.dofIndices,
986  stack.localJacobian[i],
987  numDof );
988  }
989  }
990 
998  template< typename POLICY, typename KERNEL_TYPE >
999  static void
1000  launch( localIndex const numElems,
1001  KERNEL_TYPE const & kernelComponent )
1002  {
1004 
1005  forAll< POLICY >( numElems, [=] GEOS_HOST_DEVICE ( localIndex const ei )
1006  {
1007  if( kernelComponent.elemGhostRank( ei ) >= 0 )
1008  {
1009  return;
1010  }
1011 
1012  typename KERNEL_TYPE::StackVariables stack;
1013 
1014  kernelComponent.setup( ei, stack );
1015  kernelComponent.computeAccumulation( ei, stack );
1016  kernelComponent.complete( ei, stack );
1017  } );
1018  }
1019 
1020 protected:
1021 
1024 
1027 
1030 
1033 
1036  arrayView2d< real64 const > const m_dPoro_dPres;
1037 
1040 
1044 
1045  // View on component amount (mass) from previous time step
1047 
1052 
1053  BitFlags< KernelFlags > const m_kernelFlags;
1054 };
1055 
1060 {
1061 public:
1062 
1076  template< typename POLICY >
1077  static void
1078  createAndLaunch( integer const numPhases,
1079  globalIndex const rankOffset,
1080  integer const useTotalMassEquation,
1081  string const dofKey,
1082  ElementSubRegionBase const & subRegion,
1083  constitutive::TwoPhaseImmiscibleFluid const & fluid,
1084  constitutive::CoupledSolidBase const & solid,
1085  CRSMatrixView< real64, globalIndex const > const & localMatrix,
1086  arrayView1d< real64 > const & localRhs )
1087  {
1088 
1089  geos::immiscibleMultiphaseKernels::kernelLaunchSelectorPhaseSwitch( numPhases, [&] ( auto NP )
1090  {
1091  integer constexpr NUM_EQN = NP();
1092  integer constexpr NUM_DOF = NP();
1093 
1094  BitFlags< KernelFlags > kernelFlags;
1095  if( useTotalMassEquation )
1096  kernelFlags.set( KernelFlags::TotalMassEquation );
1097 
1098  AccumulationKernel< NUM_EQN, NUM_DOF > kernel( numPhases, rankOffset, dofKey, subRegion,
1099  fluid, solid, localMatrix, localRhs, kernelFlags );
1100  AccumulationKernel< NUM_EQN, NUM_DOF >::template launch< POLICY >( subRegion.size(), kernel );
1101  } );
1102  }
1103 
1104 };
1105 
1106 
1107 
1108 /******************************** PhaseMobilityKernel ********************************/
1109 
1115 template< integer NUM_PHASE >
1117 {
1118 public:
1119 
1120  //using Base = MultiphaseFluidAccessors::PropertyKernelBase< NUM_COMP >;
1121 
1123  static constexpr integer numPhase = NUM_PHASE;
1124 
1132  TwoPhaseImmiscibleFluid const & fluid,
1133  RelativePermeabilityBase const & relperm )
1134  :
1135  m_phaseDens( fluid.phaseDensity() ),
1136  m_dPhaseDens( fluid.dPhaseDensity() ),
1137  m_phaseVisc( fluid.phaseViscosity() ),
1138  m_dPhaseVisc( fluid.dPhaseViscosity() ),
1139  m_phaseRelPerm( relperm.phaseRelPerm() ),
1140  m_dPhaseRelPerm_dPhaseVolFrac( relperm.dPhaseRelPerm_dPhaseVolFraction() ),
1141  m_phaseMob( subRegion.getField< fields::immiscibleMultiphaseFlow::phaseMobility >() ),
1142  m_dPhaseMob( subRegion.getField< fields::immiscibleMultiphaseFlow::dPhaseMobility >() )
1143  {}
1144 
1152  template< typename POLICY, typename KERNEL_TYPE >
1153  static void
1154  launch( localIndex const numElems,
1155  KERNEL_TYPE const & kernelComponent )
1156  {
1157  forAll< POLICY >( numElems, [=] GEOS_HOST_DEVICE ( localIndex const ei )
1158  {
1159  kernelComponent.compute( ei );
1160  } );
1161  }
1162 
1169  template< typename FUNC = NoOpFunc >
1171  void compute( localIndex const ei,
1172  FUNC && phaseMobilityKernelOp = NoOpFunc{} ) const
1173  {
1174  using Deriv = immiscibleFlow::DerivativeOffset;
1175 
1176  arraySlice1d< real64, immiscibleFlow::USD_PHASE - 1 > const phaseMob = m_phaseMob[ei];
1177  arraySlice2d< real64, immiscibleFlow::USD_PHASE_DS - 1 > const dPhaseMob = m_dPhaseMob[ei];
1178  constexpr int sign[2] = {1, -1};
1179 
1180  for( integer ip = 0; ip < numPhase; ++ip )
1181  {
1182  real64 const density = m_phaseDens[ei][0][ip];
1183  real64 const dDens_dP = m_dPhaseDens[ei][0][ip][Deriv::dP];
1184  real64 const viscosity = m_phaseVisc[ei][0][ip];
1185  real64 const dVisc_dP = m_dPhaseVisc[ei][0][ip][Deriv::dP];
1186 
1187  real64 const relPerm = m_phaseRelPerm[ei][0][ip];
1188 
1189  real64 const mobility = relPerm * density / viscosity;
1190 
1191  phaseMob[ip] = mobility;
1192  dPhaseMob[ip][Deriv::dP] = mobility * (dDens_dP / density - dVisc_dP / viscosity);
1193 
1194  // for( integer jp = 0; jp < numPhase-1; ++jp )
1195  // {
1196  // Derivative matrix is currently diagonal. Implementation below handles missing off-diagonal entry.
1197  real64 const dRelPerm_dS = sign[ip] * m_dPhaseRelPerm_dPhaseVolFrac[ei][0][ip][ip];
1198  dPhaseMob[ip][Deriv::dS] = dRelPerm_dS * density / viscosity;
1199  // }
1200 
1201 
1202  // call the lambda in the phase loop to allow the reuse of the relperm, density, viscosity, and mobility
1203  // possible use: assemble the derivatives wrt temperature
1204  phaseMobilityKernelOp( ip, phaseMob[ip], dPhaseMob[ip] );
1205  }
1206  }
1207 
1208 protected:
1209 
1210  // inputs
1211 
1215 
1216  //arrayView2d< real64 const, immiscibleFlow::USD_PHASE > m_phaseDens;
1217  //arrayView2d< real64 const, immiscibleFlow::USD_PHASE > m_dPhaseDens;
1218 
1222  //arrayView2d< real64 const, immiscibleFlow::USD_PHASE > m_phaseVisc;
1223  //arrayView2d< real64 const, immiscibleFlow::USD_PHASE > m_dPhaseVisc;
1224 
1227  arrayView4d< real64 const, relperm::USD_RELPERM_DS > m_dPhaseRelPerm_dPhaseVolFrac;
1228 
1229  // outputs
1230 
1234 };
1235 
1240 {
1241 public:
1242 
1250  template< typename POLICY >
1251  static void
1252  createAndLaunch( integer const numPhase,
1253  ObjectManagerBase & subRegion,
1254  TwoPhaseImmiscibleFluid const & fluid,
1255  RelativePermeabilityBase const & relperm )
1256  {
1257  if( numPhase == 2 )
1258  {
1259  PhaseMobilityKernel< 2 > kernel( subRegion, fluid, relperm );
1260  PhaseMobilityKernel< 2 >::template launch< POLICY >( subRegion.size(), kernel );
1261  }
1262  }
1263 };
1264 
1265 
1267 {
1268  template< typename POLICY, typename FLUID_WRAPPER >
1269  static void
1270  launch( localIndex const size,
1271  FLUID_WRAPPER const & fluidWrapper,
1272  arrayView1d< real64 const > const & pres )
1273  {
1274  forAll< POLICY >( size, [=] GEOS_HOST_DEVICE ( localIndex const k )
1275  {
1276  for( localIndex q = 0; q < fluidWrapper.numGauss(); ++q )
1277  {
1278  fluidWrapper.update( k, q, pres[k] );
1279  }
1280  } );
1281  }
1282 };
1283 
1284 //******************************** ResidualNormKernel ********************************/
1285 
1293 static constexpr integer numNorm = 1;
1294 
1296 {
1297 public:
1298 
1299 
1301  using Base::m_minNormalizer;
1302  using Base::m_rankOffset;
1303  using Base::m_localResidual;
1304  using Base::m_dofNumber;
1305 
1306  ResidualNormKernel( globalIndex const rankOffset,
1307  arrayView1d< real64 const > const & localResidual,
1308  arrayView1d< globalIndex const > const & dofNumber,
1309  arrayView1d< localIndex const > const & ghostRank,
1310  integer const numPhases,
1311  ElementSubRegionBase const & subRegion,
1312  constitutive::CoupledSolidBase const & solid,
1313  real64 const minNormalizer )
1314  : Base( rankOffset,
1315  localResidual,
1316  dofNumber,
1317  ghostRank,
1318  minNormalizer ),
1319  m_numPhases( numPhases ),
1320  m_volume( subRegion.getElementVolume() ),
1321  m_porosity_n( solid.getPorosity_n() ),
1322  m_phaseMass_n( subRegion.template getField< fields::immiscibleMultiphaseFlow::phaseMass_n >() )
1323  {}
1324 
1326  virtual void computeLinf( localIndex const ei,
1327  LinfStackVariables & stack ) const override
1328  {
1329  real64 massNormalizer = 0;
1330  for( integer idof = 0; idof < m_numPhases; ++idof )
1331  {
1332  massNormalizer += LvArray::math::max( m_minNormalizer, m_phaseMass_n[ei][idof] );
1333  }
1334 
1335  for( integer idof = 0; idof < m_numPhases; ++idof )
1336  {
1337  real64 const valMass = LvArray::math::abs( m_localResidual[stack.localRow + idof] ) / massNormalizer;
1338  if( valMass > stack.localValue[0] )
1339  {
1340  stack.localValue[0] = valMass;
1341  }
1342  }
1343 
1344  // for( integer idof = 0; idof < m_numPhases; ++idof )
1345  // {
1346  // real64 const massNormalizer = LvArray::math::max( m_minNormalizer, m_phaseMass_n[ei][idof] );
1347  // real64 const valMass = LvArray::math::abs( m_localResidual[stack.localRow + idof] ) / massNormalizer;
1348  // if( valMass > stack.localValue[0] )
1349  // {
1350  // stack.localValue[0] = valMass;
1351  // }
1352  // }
1353 
1354  }
1355 
1357  virtual void computeL2( localIndex const ei,
1358  L2StackVariables & stack ) const override
1359  {
1360  for( integer idof = 0; idof < m_numPhases; ++idof )
1361  {
1362  real64 const massNormalizer = LvArray::math::max( m_minNormalizer, m_phaseMass_n[ei][idof] );
1363  stack.localValue[0] += m_localResidual[stack.localRow + idof] * m_localResidual[stack.localRow + idof];
1364  stack.localNormalizer[0] += massNormalizer;
1365  }
1366  }
1367 
1368 
1369 protected:
1370 
1373 
1376 
1381 };
1382 
1387 {
1388 public:
1389 
1403  template< typename POLICY >
1404  static void
1406  integer const numPhases,
1407  globalIndex const rankOffset,
1408  string const dofKey,
1409  arrayView1d< real64 const > const & localResidual,
1410  ElementSubRegionBase const & subRegion,
1411  constitutive::CoupledSolidBase const & solid,
1412  real64 const minNormalizer,
1413  real64 (& residualNorm)[1],
1414  real64 (& residualNormalizer)[1] )
1415  {
1416  arrayView1d< globalIndex const > const dofNumber = subRegion.getReference< array1d< globalIndex > >( dofKey );
1417  arrayView1d< integer const > const ghostRank = subRegion.ghostRank();
1418 
1419  ResidualNormKernel kernel( rankOffset, localResidual, dofNumber, ghostRank, numPhases, subRegion, solid, minNormalizer );
1420  if( normType == physicsSolverBaseKernels::NormType::Linf )
1421  {
1422  ResidualNormKernel::launchLinf< POLICY >( subRegion.size(), kernel, residualNorm );
1423  }
1424  else // L2 norm
1425  {
1426  ResidualNormKernel::launchL2< POLICY >( subRegion.size(), kernel, residualNorm, residualNormalizer );
1427  }
1428  }
1429 
1430 };
1431 
1432 
1433 
1434 } // namespace immiscible multiphasekernels
1435 
1436 
1437 } // namespace geos
1438 
1439 #endif //GEOS_PHYSICSSOLVERS_FLUIDFLOW_MULTIPHASEKERNELS_HPP
#define GEOS_HOST_DEVICE
Marks a host-device function.
Definition: GeosxMacros.hpp:49
#define GEOS_UNUSED_PARAM(X)
Mark an unused argument and silence compiler warnings.
Definition: GeosxMacros.hpp:72
static constexpr integer numNorm
Compile time value for the number of norms to compute.
#define GEOS_ASSERT_GT(lhs, rhs)
Assert that one value compares greater than the other in debug builds.
Definition: Logger.hpp:440
#define GEOS_ASSERT_GE(lhs, rhs)
Assert that one value compares greater than or equal to the other in debug builds.
Definition: Logger.hpp:455
NormType
Type of norm used to check convergence TODO: find a way to put this inside the class.
#define GEOS_MARK_FUNCTION
Mark function with both Caliper and NVTX if enabled.
The ElementRegionManager class provides an interface to ObjectManagerBase in order to manage ElementR...
ElementViewAccessor< ArrayView< T const, NDIM, getUSD< PERM > > > constructArrayViewAccessor(string const &name, string const &neighborName=string()) const
This is a function to construct a ElementViewAccessor to access array data registered on the mesh.
array1d< array1d< VIEWTYPE > > ElementViewAccessor
The ElementViewAccessor at the ElementRegionManager level is an array of array of VIEWTYPE.
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.
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.
Definition: Group.hpp:1275
localIndex size() const
Get the "size" of the group, which determines the number of elements in resizable wrappers.
Definition: Group.hpp:1317
static void createAndLaunch(integer const numPhases, globalIndex const rankOffset, integer const useTotalMassEquation, string const dofKey, ElementSubRegionBase const &subRegion, constitutive::TwoPhaseImmiscibleFluid const &fluid, constitutive::CoupledSolidBase const &solid, 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.
GEOS_HOST_DEVICE void complete(localIndex const GEOS_UNUSED_PARAM(ei), StackVariables &stack) const
Performs the complete phase for the kernel.
arrayView1d< real64 const > const m_volume
View on the element volumes.
AccumulationKernel(localIndex const numPhases, globalIndex const rankOffset, string const dofKey, ElementSubRegionBase const &subRegion, constitutive::TwoPhaseImmiscibleFluid const &fluid, constitutive::CoupledSolidBase const &solid, CRSMatrixView< real64, globalIndex const > const &localMatrix, arrayView1d< real64 > const &localRhs, BitFlags< KernelFlags > const kernelFlags)
Constructor.
static void launch(localIndex const numElems, KERNEL_TYPE const &kernelComponent)
Performs the kernel launch.
arrayView1d< globalIndex const > const m_dofNumber
View on the dof numbers.
arrayView1d< integer const > const m_elemGhostRank
View on the ghost ranks.
arrayView2d< real64 const > const m_porosity
Views on the porosity.
arrayView2d< real64 const, immiscibleFlow::USD_PHASE > const m_phaseVolFrac
Views on the phase volume fractions.
CRSMatrixView< real64, globalIndex const > const m_localMatrix
View on the local CRS matrix.
GEOS_HOST_DEVICE integer elemGhostRank(localIndex const ei) const
Getter for the ghost rank of an element.
arrayView1d< real64 > const m_localRhs
View on the local RHS.
arrayView3d< real64 const, constitutive::multifluid::USD_PHASE > const m_phaseDens
Views on the phase densities.
GEOS_HOST_DEVICE void computeAccumulation(localIndex const ei, StackVariables &stack) const
Compute the local accumulation contributions to the residual and Jacobian.
GEOS_HOST_DEVICE void setup(localIndex const ei, StackVariables &stack) const
Performs the setup phase for the kernel.
Base class for FluxComputeKernel that holds all data not dependent on template parameters (like stenc...
ElementViewConst< arrayView3d< real64 const > > m_permeability
Views on permeability.
FluxComputeKernelBase(integer const numPhases, globalIndex const rankOffset, DofNumberAccessor const &dofNumberAccessor, ImmiscibleMultiphaseFlowAccessors const &multiPhaseFlowAccessors, MultiphaseFluidAccessors const &fluidAccessors, CapPressureAccessors const &capPressureAccessors, PermeabilityAccessors const &permeabilityAccessors, real64 const &dt, CRSMatrixView< real64, globalIndex const > const &localMatrix, arrayView1d< real64 > const &localRhs, integer const hasCapPressure, integer const useTotalMassEquation, integer const checkPhasePresenceInGravity)
Constructor for the kernel interface.
ElementViewConst< arrayView1d< integer const > > const m_ghostRank
Views on ghost rank numbers and gravity coefficients.
ElementRegionManager::ElementViewConst< VIEWTYPE > ElementViewConst
The type for element-based data. Consists entirely of ArrayView's.
ElementViewConst< arrayView1d< real64 const > > const m_pres
Views on pressure and phase volume fraction.
ElementViewConst< arrayView2d< real64 const, immiscibleFlow::USD_PHASE > > const m_mob
Views on fluid mobility.
ElementViewConst< arrayView1d< globalIndex const > > const m_dofNumber
Views on dof numbers.
arrayView1d< real64 > const m_localRhs
View on the local RHS.
CRSMatrixView< real64, globalIndex const > const m_localMatrix
View on the local CRS matrix.
ElementViewConst< arrayView3d< real64 const, constitutive::multifluid::USD_PHASE > > const m_dens
Views on fluid density.
ElementViewConst< arrayView3d< real64 const, cappres::USD_CAPPRES > > const m_phaseCapPressure
Views on capillary pressure.
static void createAndLaunch(integer const numPhases, globalIndex const rankOffset, string const &dofKey, integer const hasCapPressure, integer const useTotalMassEquation, integer const checkPhasePresenceInGravity, string const &solverName, ElementRegionManager const &elemManager, STENCILWRAPPER const &stencilWrapper, real64 const &dt, 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.
GEOS_HOST_DEVICE void complete(localIndex const iconn, StackVariables &stack, FUNC &&kernelOp=NoOpFunc{}) const
Performs the complete phase for the kernel.
GEOS_HOST_DEVICE void computeFlux(localIndex const iconn, StackVariables &stack, FUNC &&kernelOp=NoOpFunc{}) const
Compute the local flux contributions to the residual and Jacobian.
STENCILWRAPPER const m_stencilWrapper
Reference to the stencil wrapper.
static void launch(localIndex const numConnections, KERNEL_TYPE const &kernelComponent)
Performs the kernel launch.
GEOS_HOST_DEVICE localIndex numPointsInFlux(localIndex const iconn) const
Getter for the number of elements at this connection.
FluxComputeKernel(integer const numPhases, globalIndex const rankOffset, STENCILWRAPPER const &stencilWrapper, DofNumberAccessor const &dofNumberAccessor, ImmiscibleMultiphaseFlowAccessors const &multiPhaseFlowAccessors, MultiphaseFluidAccessors const &fluidAccessors, CapPressureAccessors const &capPressureAccessors, PermeabilityAccessors const &permeabilityAccessors, real64 const &dt, CRSMatrixView< real64, globalIndex const > const &localMatrix, arrayView1d< real64 > const &localRhs, integer const hasCapPressure, integer const useTotalMassEquation, integer const checkPhasePresenceInGravity)
Constructor for the kernel interface.
GEOS_HOST_DEVICE localIndex stencilSize(localIndex const iconn) const
Getter for the stencil size at this connection.
GEOS_HOST_DEVICE void setup(localIndex const iconn, StackVariables &stack) const
Performs the setup phase for the kernel.
STENCILWRAPPER::IndexContainerViewConstType const m_seri
Connection to element maps.
static void createAndLaunch(integer const numPhase, ObjectManagerBase &subRegion, TwoPhaseImmiscibleFluid const &fluid, RelativePermeabilityBase const &relperm)
Create a new kernel and launch.
Define the interface for the property kernel in charge of computing the phase mobilities.
arrayView3d< real64 const, relperm::USD_RELPERM > m_phaseRelPerm
Views on the phase relative permeabilities.
PhaseMobilityKernel(ObjectManagerBase &subRegion, TwoPhaseImmiscibleFluid const &fluid, RelativePermeabilityBase const &relperm)
Constructor.
arrayView2d< real64, immiscibleFlow::USD_PHASE > m_phaseMob
Views on the phase mobilities.
arrayView3d< real64 const, constitutive::multifluid::USD_PHASE > m_phaseVisc
Views on the phase viscosities.
GEOS_HOST_DEVICE void compute(localIndex const ei, FUNC &&phaseMobilityKernelOp=NoOpFunc{}) const
Compute the phase mobilities in an element.
arrayView3d< real64 const, constitutive::multifluid::USD_PHASE > m_phaseDens
Views on the phase densities.
static void launch(localIndex const numElems, KERNEL_TYPE const &kernelComponent)
Performs the kernel launch.
static void createAndLaunch(physicsSolverBaseKernels::NormType const normType, integer const numPhases, globalIndex const rankOffset, string const dofKey, arrayView1d< real64 const > const &localResidual, ElementSubRegionBase const &subRegion, constitutive::CoupledSolidBase const &solid, real64 const minNormalizer, real64(&residualNorm)[1], real64(&residualNormalizer)[1])
Create a new kernel and launch.
Define the interface for the property kernel in charge of computing the residual norm.
arrayView1d< real64 const > const m_volume
View on the volume.
virtual GEOS_HOST_DEVICE void computeLinf(localIndex const ei, LinfStackVariables &stack) const override
Compute the local values for the Linf norm.
virtual GEOS_HOST_DEVICE void computeL2(localIndex const ei, L2StackVariables &stack) const override
Compute the local values and normalizer for the L2 norm.
arrayView2d< real64 const, immiscibleFlow::USD_PHASE > const m_phaseMass_n
View on mass at the previous converged time step.
arrayView2d< real64 const > const m_porosity_n
View on porosity at the previous converged time step.
Define the base interface for the residual calculations.
ArrayView< T, 1 > arrayView1d
Alias for 1D array view.
Definition: DataTypes.hpp:188
StackArray< T, 2, MAXSIZE > stackArray2d
Alias for 2D stack array.
Definition: DataTypes.hpp:212
LvArray::CRSMatrixView< T, COL_INDEX, localIndex const, LvArray::ChaiBuffer > CRSMatrixView
Alias for CRS Matrix View.
Definition: DataTypes.hpp:318
GEOS_GLOBALINDEX_TYPE globalIndex
Global index type (for indexing objects across MPI partitions).
Definition: DataTypes.hpp:87
StackArray< T, 1, MAXSIZE > stackArray1d
Alias for 1D stack array.
Definition: DataTypes.hpp:196
ArraySlice< T, 2, USD > arraySlice2d
Alias for 2D array slice.
Definition: DataTypes.hpp:208
double real64
64-bit floating point type.
Definition: DataTypes.hpp:98
GEOS_LOCALINDEX_TYPE localIndex
Local index type (for indexing objects within an MPI partition).
Definition: DataTypes.hpp:84
ArraySlice< T, 1, USD > arraySlice1d
Alias for 1D array slice.
Definition: DataTypes.hpp:192
std::int32_t integer
Signed integer type.
Definition: DataTypes.hpp:81
ArrayView< T, 4, USD > arrayView4d
Alias for 4D array view.
Definition: DataTypes.hpp:236
ArrayView< T, 2, USD > arrayView2d
Alias for 2D array view.
Definition: DataTypes.hpp:204
Array< T, 1 > array1d
Alias for 1D array.
Definition: DataTypes.hpp:184
ArrayView< T, 3, USD > arrayView3d
Alias for 3D array view.
Definition: DataTypes.hpp:220
Trait struct for ghostRank data.
Definition: MeshFields.hpp:100
indices of pressure and saturation derivatives
Kernel variables (dof numbers, jacobian and residual) located on the stack.
real64 dPoreVolume_dPres
Derivative of pore volume with respect to pressure.
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 volume balance)
real64 localJacobian[numEqn][numDof]
C-array storage for the element local Jacobian matrix (all equations except volume balance,...
Kernel variables (dof numbers, jacobian and residual) located on the stack.
GEOS_HOST_DEVICE StackVariables(localIndex const size, localIndex numElems)
Constructor for the stack variables.
stackArray2d< real64, maxNumElems *numEqn *maxStencilSize *numDof > localFluxJacobian
Storage for the face local Jacobian matrix.
localIndex const numFluxElems
Number of elements for a given connection.
stackArray1d< globalIndex, maxNumElems *numDof > dofColIndices
Indices of the matrix rows/columns corresponding to the dofs in this face.
real64 dTrans_dPres[maxNumConns][2]
Derivatives of transmissibility with respect to pressure.
stackArray1d< real64, maxNumElems *numEqn > localFlux
Storage for the face local residual vector (all equations except volume balance)