GEOS
FluxComputeZFormulationKernel.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 Total, S.A
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_COMPOSITIONAL_FLUXCOMPUTEZFORMULATIONKERNEL_HPP
21 #define GEOS_PHYSICSSOLVERS_FLUIDFLOW_COMPOSITIONAL_FLUXCOMPUTEZFORMULATIONKERNEL_HPP
22 
24 
25 #include "codingUtilities/Utilities.hpp"
26 #include "common/DataLayouts.hpp"
27 #include "common/DataTypes.hpp"
28 #include "common/GEOS_RAJA_Interface.hpp"
29 #include "constitutive/fluid/multifluid/MultiFluidFields.hpp"
34 #include "physicsSolvers/fluidFlow/kernels/compositional/KernelLaunchSelectors.hpp"
39 
40 namespace geos
41 {
42 
43 namespace isothermalCompositionalMultiphaseFVMKernels
44 {
45 
53 template< integer NUM_COMP, integer NUM_DOF, typename STENCILWRAPPER >
55 {
56 public:
57 
59  static constexpr integer numComp = NUM_COMP;
60 
62  static constexpr integer numDof = NUM_DOF;
63 
65  static constexpr integer numEqn = NUM_DOF-1;
66 
68  static constexpr localIndex maxNumElems = STENCILWRAPPER::maxNumPointsInFlux;
69 
71  static constexpr localIndex maxNumConns = STENCILWRAPPER::maxNumConnections;
72 
74  static constexpr localIndex maxStencilSize = STENCILWRAPPER::maxStencilSize;
75 
77  static constexpr integer numFluxSupportPoints = 2;
78 
95  globalIndex const rankOffset,
96  STENCILWRAPPER const & stencilWrapper,
97  DofNumberAccessor const & dofNumberAccessor,
98  CompFlowAccessors const & compFlowAccessors,
99  MultiFluidAccessors const & multiFluidAccessors,
100  CapPressureAccessors const & capPressureAccessors,
101  PermeabilityAccessors const & permeabilityAccessors,
102  real64 const dt,
103  CRSMatrixView< real64, globalIndex const > const & localMatrix,
104  arrayView1d< real64 > const & localRhs,
105  BitFlags< KernelFlags > kernelFlags )
106  : FluxComputeKernelBase( numPhases,
107  rankOffset,
108  dofNumberAccessor,
109  compFlowAccessors,
110  multiFluidAccessors,
111  dt,
112  localMatrix,
113  localRhs,
114  kernelFlags ),
115  m_permeability( permeabilityAccessors.get( fields::permeability::permeability {} ) ),
116  m_dPerm_dPres( permeabilityAccessors.get( fields::permeability::dPerm_dPressure {} ) ),
117  m_phaseMob( compFlowAccessors.get( fields::flow::phaseMobility {} ) ),
118  m_dPhaseMob( compFlowAccessors.get( fields::flow::dPhaseMobility {} ) ),
119  m_phaseMassDens( multiFluidAccessors.get( fields::multifluid::phaseMassDensity {} ) ),
120  m_dPhaseMassDens( multiFluidAccessors.get( fields::multifluid::dPhaseMassDensity {} ) ),
121  m_phaseCapPressure( capPressureAccessors.get( fields::cappres::phaseCapPressure {} ) ),
122  m_dPhaseCapPressure_dPhaseVolFrac( capPressureAccessors.get( fields::cappres::dPhaseCapPressure_dPhaseVolFraction {} ) ),
123  m_stencilWrapper( stencilWrapper ),
124  m_seri( stencilWrapper.getElementRegionIndices() ),
125  m_sesri( stencilWrapper.getElementSubRegionIndices() ),
126  m_sei( stencilWrapper.getElementIndices() )
127  { }
128 
134  {
135 public:
136 
143  StackVariables( localIndex const size, localIndex numElems )
144  : stencilSize( size ),
145  numConnectedElems( numElems ),
146  dofColIndices( size * numDof ),
147  localFlux( numElems * numEqn ),
148  localFluxJacobian( numElems * numEqn, size * numDof )
149  {}
150 
151  // Stencil information
152 
157 
158  // Transmissibility and derivatives
159 
164 
165  // Local degrees of freedom and local residual/jacobian
166 
169 
174  };
175 
176 
183  inline
184  localIndex stencilSize( localIndex const iconn ) const { return m_sei[iconn].size(); }
185 
192  inline
193  localIndex numPointsInFlux( localIndex const iconn ) const { return m_stencilWrapper.numPointsInFlux( iconn ); }
194 
195 
202  inline
203  void setup( localIndex const iconn,
204  StackVariables & stack ) const
205  {
206  // set degrees of freedom indices for this face
207  for( integer i = 0; i < stack.stencilSize; ++i )
208  {
209  globalIndex const offset = m_dofNumber[m_seri( iconn, i )][m_sesri( iconn, i )][m_sei( iconn, i )];
210 
211  for( integer jdof = 0; jdof < numDof; ++jdof )
212  {
213  stack.dofColIndices[i * numDof + jdof] = offset + jdof;
214  }
215  }
216  }
217 
225  template< typename FUNC = NoOpFunc >
227  inline
228  void computeFlux( localIndex const iconn,
229  StackVariables & stack,
230  FUNC && compFluxKernelOp = NoOpFunc{} ) const
231  {
232 
233  // first, compute the transmissibilities at this face
234  m_stencilWrapper.computeWeights( iconn,
236  m_dPerm_dPres,
237  stack.transmissibility,
238  stack.dTrans_dPres );
239 
240 
242  localIndex connectionIndex = 0;
243  for( k[0] = 0; k[0] < stack.numConnectedElems; ++k[0] )
244  {
245  for( k[1] = k[0] + 1; k[1] < stack.numConnectedElems; ++k[1] )
246  {
248  localIndex const seri[numFluxSupportPoints] = {m_seri( iconn, k[0] ), m_seri( iconn, k[1] )};
249  localIndex const sesri[numFluxSupportPoints] = {m_sesri( iconn, k[0] ), m_sesri( iconn, k[1] )};
250  localIndex const sei[numFluxSupportPoints] = {m_sei( iconn, k[0] ), m_sei( iconn, k[1] )};
251 
252  // clear working arrays
253  real64 compFlux[numComp]{};
254  real64 dCompFlux_dP[numFluxSupportPoints][numComp]{};
255  real64 dCompFlux_dC[numFluxSupportPoints][numComp][numComp]{};
256 
257  real64 const trans[numFluxSupportPoints] = { stack.transmissibility[connectionIndex][0],
258  stack.transmissibility[connectionIndex][1] };
259 
260  real64 const dTrans_dPres[numFluxSupportPoints] = { stack.dTrans_dPres[connectionIndex][0],
261  stack.dTrans_dPres[connectionIndex][1] };
262 
263  //***** calculation of flux *****
264  // loop over phases, compute and upwind phase flux and sum contributions to each component's flux
265  for( integer ip = 0; ip < m_numPhases; ++ip )
266  {
267  // create local work arrays
268  real64 potGrad = 0.0;
269  real64 phaseFlux = 0.0;
270  real64 dPhaseFlux_dP[numFluxSupportPoints]{};
271  real64 dPhaseFlux_dC[numFluxSupportPoints][numComp]{};
272 
273  localIndex k_up = -1;
274 
275  isothermalCompositionalMultiphaseFVMKernelUtilities::PPUPhaseFluxZFormulation::compute< numComp, numFluxSupportPoints >
276  ( m_numPhases,
277  ip,
278  m_kernelFlags.isSet( KernelFlags::CapPressure ),
279  m_kernelFlags.isSet( KernelFlags::CheckPhasePresenceInGravity ),
280  seri, sesri, sei,
281  trans,
282  dTrans_dPres,
283  m_pres,
284  m_gravCoef,
285  m_phaseMob, m_dPhaseMob,
286  m_phaseVolFrac, m_dPhaseVolFrac,
287  m_phaseCompFrac, m_dPhaseCompFrac,
288  m_phaseMassDens, m_dPhaseMassDens,
289  m_phaseCapPressure, m_dPhaseCapPressure_dPhaseVolFrac,
290  k_up,
291  potGrad,
292  phaseFlux,
293  dPhaseFlux_dP,
294  dPhaseFlux_dC,
295  compFlux,
296  dCompFlux_dP,
297  dCompFlux_dC );
298 
299  // call the lambda in the phase loop to allow the reuse of the phase fluxes and their derivatives
300  // possible use: assemble the derivatives wrt temperature, and the flux term of the energy equation for this phase
301  compFluxKernelOp( ip, k, seri, sesri, sei, connectionIndex,
302  k_up, seri[k_up], sesri[k_up], sei[k_up], potGrad,
303  phaseFlux, dPhaseFlux_dP, dPhaseFlux_dC );
304 
305  } // loop over phases
306 
308  for( integer ic = 0; ic < numComp; ++ic )
309  {
310  integer const eqIndex0 = k[0] * numEqn + ic;
311  integer const eqIndex1 = k[1] * numEqn + ic;
312 
313  stack.localFlux[eqIndex0] += m_dt * compFlux[ic];
314  stack.localFlux[eqIndex1] -= m_dt * compFlux[ic];
315 
316  for( integer ke = 0; ke < numFluxSupportPoints; ++ke )
317  {
318  localIndex const localDofIndexPres = k[ke] * numDof;
319  stack.localFluxJacobian[eqIndex0][localDofIndexPres] += m_dt * dCompFlux_dP[ke][ic];
320  stack.localFluxJacobian[eqIndex1][localDofIndexPres] -= m_dt * dCompFlux_dP[ke][ic];
321 
322  for( integer jc = 0; jc < numComp; ++jc )
323  {
324  localIndex const localDofIndexComp = localDofIndexPres + jc + 1;
325  stack.localFluxJacobian[eqIndex0][localDofIndexComp] += m_dt * dCompFlux_dC[ke][ic][jc];
326  stack.localFluxJacobian[eqIndex1][localDofIndexComp] -= m_dt * dCompFlux_dC[ke][ic][jc];
327  }
328  }
329  }
330  connectionIndex++;
331  } // loop over k[1]
332  } // loop over k[0]
333 
334  }
335 
341  template< typename FUNC = NoOpFunc >
343  inline
344  void complete( localIndex const iconn,
345  StackVariables & stack,
346  FUNC && assemblyKernelOp = NoOpFunc{} ) const
347  {
348  using namespace compositionalMultiphaseUtilities;
349 
350  if( m_kernelFlags.isSet( KernelFlags::TotalMassEquation ) )
351  {
352  // Apply equation/variable change transformation(s)
354  shiftBlockRowsAheadByOneAndReplaceFirstRowWithColumnSum( numComp, numEqn, numDof * stack.stencilSize, stack.numConnectedElems,
355  stack.localFluxJacobian, work );
356  shiftBlockElementsAheadByOneAndReplaceFirstElementWithSum( numComp, numEqn, stack.numConnectedElems,
357  stack.localFlux );
358  }
359 
360  // add contribution to residual and jacobian into:
361  // - the component mass balance equations (i = 0 to i = numComp-1)
362  // note that numDof includes derivatives wrt temperature if this class is derived in ThermalKernels
363  for( integer i = 0; i < stack.numConnectedElems; ++i )
364  {
365  if( m_ghostRank[m_seri( iconn, i )][m_sesri( iconn, i )][m_sei( iconn, i )] < 0 )
366  {
367  globalIndex const globalRow = m_dofNumber[m_seri( iconn, i )][m_sesri( iconn, i )][m_sei( iconn, i )];
368  localIndex const localRow = LvArray::integerConversion< localIndex >( globalRow - m_rankOffset );
369  GEOS_ASSERT_GE( localRow, 0 );
370  GEOS_ASSERT_GT( m_localMatrix.numRows(), localRow + numComp );
371 
372  for( integer ic = 0; ic < numComp; ++ic )
373  {
374  RAJA::atomicAdd( parallelDeviceAtomic{}, &m_localRhs[localRow + ic],
375  stack.localFlux[i * numEqn + ic] );
376  m_localMatrix.addToRowBinarySearchUnsorted< parallelDeviceAtomic >
377  ( localRow + ic,
378  stack.dofColIndices.data(),
379  stack.localFluxJacobian[i * numEqn + ic].dataIfContiguous(),
380  stack.stencilSize * numDof );
381  }
382 
383  // call the lambda to assemble additional terms, such as thermal terms
384  assemblyKernelOp( i, localRow );
385  }
386  }
387  }
388 
396  template< typename POLICY, typename KERNEL_TYPE >
397  static void
398  launch( localIndex const numConnections,
399  KERNEL_TYPE const & kernelComponent )
400  {
402  forAll< POLICY >( numConnections, [=] GEOS_HOST_DEVICE ( localIndex const iconn )
403  {
404  typename KERNEL_TYPE::StackVariables stack( kernelComponent.stencilSize( iconn ),
405  kernelComponent.numPointsInFlux( iconn ) );
406 
407  kernelComponent.setup( iconn, stack );
408  kernelComponent.computeFlux( iconn, stack );
409  kernelComponent.complete( iconn, stack );
410  } );
411  }
412 
413 protected:
414 
417  ElementViewConst< arrayView3d< real64 const > > const m_dPerm_dPres;
418 
422 
426 
430 
431  // Stencil information
432 
434  STENCILWRAPPER const m_stencilWrapper;
435 
437  typename STENCILWRAPPER::IndexContainerViewConstType const m_seri;
438  typename STENCILWRAPPER::IndexContainerViewConstType const m_sesri;
439  typename STENCILWRAPPER::IndexContainerViewConstType const m_sei;
440 
441 };
442 
447 {
448 public:
449 
466  template< typename POLICY, typename STENCILWRAPPER >
467  static void
468  createAndLaunch( integer const numComps,
469  integer const numPhases,
470  globalIndex const rankOffset,
471  string const & dofKey,
472  BitFlags< KernelFlags > kernelFlags,
473  string const & solverName,
474  ElementRegionManager const & elemManager,
475  STENCILWRAPPER const & stencilWrapper,
476  real64 const dt,
477  CRSMatrixView< real64, globalIndex const > const & localMatrix,
478  arrayView1d< real64 > const & localRhs )
479  {
480  isothermalCompositionalMultiphaseBaseKernels::internal::kernelLaunchSelectorCompSwitch( numComps, [&]( auto NC )
481  {
482  integer constexpr NUM_COMP = NC();
483  integer constexpr NUM_DOF = NC() + 1;
484 
486  elemManager.constructArrayViewAccessor< globalIndex, 1 >( dofKey );
487  dofNumberAccessor.setName( solverName + "/accessors/" + dofKey );
488 
490  typename kernelType::CompFlowAccessors compFlowAccessors( elemManager, solverName );
491  typename kernelType::MultiFluidAccessors multiFluidAccessors( elemManager, solverName );
492  typename kernelType::CapPressureAccessors capPressureAccessors( elemManager, solverName );
493  typename kernelType::PermeabilityAccessors permeabilityAccessors( elemManager, solverName );
494 
495  kernelType kernel( numPhases, rankOffset, stencilWrapper, dofNumberAccessor,
496  compFlowAccessors, multiFluidAccessors, capPressureAccessors, permeabilityAccessors,
497  dt, localMatrix, localRhs, kernelFlags );
498  kernelType::template launch< POLICY >( stencilWrapper.size(), kernel );
499  } );
500  }
501 };
502 
503 } // namespace isothermalCompositionalMultiphaseFVMKernels
504 
505 } // namespace geos
506 
507 #endif //GEOS_PHYSICSSOLVERS_FLUIDFLOW_COMPOSITIONAL_FLUXCOMPUTEZFORMULATIONKERNEL_HPP
#define GEOS_HOST_DEVICE
Marks a host-device function.
Definition: GeosxMacros.hpp:49
#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
#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.
A struct to automatically construct and store element view accessors.
A struct to automatically construct and store element view accessors.
Base class for FluxComputeKernel that holds all data not dependent on template parameters (like stenc...
ElementViewConst< arrayView2d< real64 const, compflow::USD_PHASE > > const m_phaseVolFrac
Views on phase volume fractions.
ElementViewConst< arrayView1d< globalIndex const > > const m_dofNumber
Views on dof numbers.
ElementViewConst< arrayView1d< real64 const > > const m_pres
Views on pressure.
ElementViewConst< arrayView1d< integer const > > const m_ghostRank
Views on ghost rank numbers and gravity coefficients.
ElementViewConst< arrayView4d< real64 const, constitutive::multifluid::USD_PHASE_COMP > > const m_phaseCompFrac
Views on phase component fractions.
CRSMatrixView< real64, globalIndex const > const m_localMatrix
View on the local CRS matrix.
ElementRegionManager::ElementViewConst< VIEWTYPE > ElementViewConst
The type for element-based data. Consists entirely of ArrayView's.
static void createAndLaunch(integer const numComps, integer const numPhases, globalIndex const rankOffset, string const &dofKey, BitFlags< KernelFlags > kernelFlags, 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.
ElementViewConst< arrayView2d< real64 const, compflow::USD_PHASE > > const m_phaseMob
Views on phase mobilities.
static constexpr localIndex maxNumElems
Maximum number of elements at the face.
FluxComputeZFormulationKernel(integer const numPhases, globalIndex const rankOffset, STENCILWRAPPER const &stencilWrapper, DofNumberAccessor const &dofNumberAccessor, CompFlowAccessors const &compFlowAccessors, MultiFluidAccessors const &multiFluidAccessors, CapPressureAccessors const &capPressureAccessors, PermeabilityAccessors const &permeabilityAccessors, real64 const dt, CRSMatrixView< real64, globalIndex const > const &localMatrix, arrayView1d< real64 > const &localRhs, BitFlags< KernelFlags > kernelFlags)
Constructor for the kernel interface.
static constexpr integer numEqn
Compute time value for the number of equations (all of them, except the volume balance equation)
GEOS_HOST_DEVICE void complete(localIndex const iconn, StackVariables &stack, FUNC &&assemblyKernelOp=NoOpFunc{}) const
Performs the complete phase for the kernel.
GEOS_HOST_DEVICE void setup(localIndex const iconn, StackVariables &stack) const
Performs the setup phase for the kernel.
static void launch(localIndex const numConnections, KERNEL_TYPE const &kernelComponent)
Performs the kernel launch.
static constexpr integer numComp
Compile time value for the number of components.
GEOS_HOST_DEVICE void computeFlux(localIndex const iconn, StackVariables &stack, FUNC &&compFluxKernelOp=NoOpFunc{}) const
Compute the local flux contributions to the residual and Jacobian.
GEOS_HOST_DEVICE localIndex numPointsInFlux(localIndex const iconn) const
Getter for the number of elements at this connection.
ElementViewConst< arrayView3d< real64 const, constitutive::multifluid::USD_PHASE > > const m_phaseMassDens
Views on phase mass densities.
ElementViewConst< arrayView3d< real64 const > > const m_permeability
Views on permeability.
ElementViewConst< arrayView3d< real64 const, constitutive::cappres::USD_CAPPRES > > const m_phaseCapPressure
Views on phase capillary pressure.
static constexpr integer numDof
Compute time value for the number of degrees of freedom.
STENCILWRAPPER::IndexContainerViewConstType const m_seri
Connection to element maps.
static constexpr localIndex maxStencilSize
Maximum number of points in the stencil.
static constexpr integer numFluxSupportPoints
Number of flux support points (hard-coded for TFPA)
GEOS_HOST_DEVICE localIndex stencilSize(localIndex const iconn) const
Getter for the stencil size at this connection.
static constexpr localIndex maxNumConns
Maximum number of connections at the face.
ArrayView< T, 1 > arrayView1d
Alias for 1D array view.
Definition: DataTypes.hpp:180
StackArray< T, 2, MAXSIZE > stackArray2d
Alias for 2D stack array.
Definition: DataTypes.hpp:204
LvArray::CRSMatrixView< T, COL_INDEX, localIndex const, LvArray::ChaiBuffer > CRSMatrixView
Alias for CRS Matrix View.
Definition: DataTypes.hpp:310
GEOS_GLOBALINDEX_TYPE globalIndex
Global index type (for indexing objects across MPI partitions).
Definition: DataTypes.hpp:88
StackArray< T, 1, MAXSIZE > stackArray1d
Alias for 1D stack array.
Definition: DataTypes.hpp:188
double real64
64-bit floating point type.
Definition: DataTypes.hpp:99
GEOS_LOCALINDEX_TYPE localIndex
Local index type (for indexing objects within an MPI partition).
Definition: DataTypes.hpp:85
std::int32_t integer
Signed integer type.
Definition: DataTypes.hpp:82
stackArray1d< real64, maxNumElems *numEqn > localFlux
Storage for the face local residual vector (all equations except volume balance)
stackArray2d< real64, maxNumElems *numEqn *maxStencilSize *numDof > localFluxJacobian
Storage for the face local Jacobian matrix.
real64 dTrans_dPres[maxNumConns][numFluxSupportPoints]
Derivatives of transmissibility with respect to pressure.
GEOS_HOST_DEVICE StackVariables(localIndex const size, localIndex numElems)
Constructor for the stack variables.
stackArray1d< globalIndex, maxNumElems *numDof > dofColIndices
Indices of the matrix rows/columns corresponding to the dofs in this face.