GEOS
DissipationFluxComputeKernel.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_DISSIPATIONFLUXCOMPUTEKERNEL_HPP
21 #define GEOS_PHYSICSSOLVERS_FLUIDFLOW_COMPOSITIONAL_DISSIPATIONFLUXCOMPUTEKERNEL_HPP
22 
25 #include "constitutive/solid/porosity/PorosityBase.hpp"
26 #include "constitutive/solid/porosity/PorosityFields.hpp"
27 
28 namespace geos
29 {
30 
31 namespace dissipationCompositionalMultiphaseFVMKernels
32 {
33 
34 static constexpr integer newtonContinuationCutoffIteration = 5;
35 static constexpr real64 initialDirectionalCoef = 100;
36 static constexpr real64 multiplierDirectionalCoef = 1000;
37 
38 /******************************** FluxComputeKernel ********************************/
39 
47 template< integer NUM_COMP, integer NUM_DOF, typename STENCILWRAPPER >
48 class FluxComputeKernel : public isothermalCompositionalMultiphaseFVMKernels::FluxComputeKernel< NUM_COMP, NUM_DOF, STENCILWRAPPER >
49 {
50 public:
51 
58  template< typename VIEWTYPE >
60 
62  using DofNumberAccessor = AbstractBase::DofNumberAccessor;
67 
68  using AbstractBase::m_dt;
69  using AbstractBase::m_gravCoef;
71 
73  using Base::numComp;
74  using Base::numDof;
75  using Base::numEqn;
78  using Base::m_dPerm_dPres;
79 
80  using DissCompFlowAccessors =
81  StencilAccessors< fields::flow::pressure_n,
82  fields::flow::globalCompDensity,
83  fields::flow::globalCompFraction,
85 
86  using PorosityAccessors =
88 
89  using Deriv = constitutive::multifluid::DerivativeOffset;
90 
114  FluxComputeKernel( integer const numPhases,
115  globalIndex const rankOffset,
116  STENCILWRAPPER const & stencilWrapper,
117  DofNumberAccessor const & dofNumberAccessor,
118  CompFlowAccessors const & compFlowAccessors,
119  DissCompFlowAccessors const & dissCompFlowAccessors,
120  MultiFluidAccessors const & multiFluidAccessors,
121  CapPressureAccessors const & capPressureAccessors,
122  PermeabilityAccessors const & permeabilityAccessors,
123  PorosityAccessors const & porosityAccessors,
124  real64 const & dt,
125  CRSMatrixView< real64, globalIndex const > const & localMatrix,
126  arrayView1d< real64 > const & localRhs,
127  BitFlags< isothermalCompositionalMultiphaseFVMKernels::KernelFlags > kernelFlags,
128  real64 const omega,
129  integer const curNewton,
130  integer const continuation,
131  integer const miscible,
132  real64 const kappamin,
133  real64 const contMultiplier )
134  : Base( numPhases,
135  rankOffset,
136  stencilWrapper,
137  dofNumberAccessor,
138  compFlowAccessors,
139  multiFluidAccessors,
140  capPressureAccessors,
141  permeabilityAccessors,
142  dt,
143  localMatrix,
144  localRhs,
145  kernelFlags ),
146  m_pres_n( dissCompFlowAccessors.get( fields::flow::pressure_n {} ) ),
147  m_porosity_n( porosityAccessors.get( fields::porosity::porosity_n {} ) ),
148  m_volume( dissCompFlowAccessors.get( fields::elementVolume {} ) ),
149  m_compFrac( dissCompFlowAccessors.get( fields::flow::globalCompFraction {} ) ),
150  m_omegaDBC( omega ),
151  m_miscibleDBC( miscible )
152  {
154  m_kappaDBC = 1.0; // default value
155 
156  if( continuation ) // if continuation is enabled
157  {
158  if( curNewton >= newtonContinuationCutoffIteration )
159  {
160  m_kappaDBC = kappamin;
161  }
162  else
163  {
164  for( int mp = 0; mp < curNewton; mp++ )
165  {
166  m_kappaDBC *= contMultiplier;
167  }
168  m_kappaDBC = std::max( m_kappaDBC, kappamin );
169  }
170  }
171  }
172 
179  void computeFlux( localIndex const iconn,
180  typename Base::StackVariables & stack ) const
181  {
182  // ***********************************************
183  // First, we call the base computeFlux to compute:
184  // 1) compFlux and its derivatives,
185  //
186  // We use the lambda below (called **inside** the phase loop of the base computeFlux) to compute dissipation terms
187  Base::computeFlux( iconn, stack, [&] ( integer const ip,
188  localIndex const (&k)[2],
189  localIndex const (&seri)[2],
190  localIndex const (&sesri)[2],
191  localIndex const (&sei)[2],
192  localIndex const connectionIndex,
193  localIndex const k_up,
194  localIndex const er_up,
195  localIndex const esr_up,
196  localIndex const ei_up,
197  real64 const & potGrad,
198  real64 const & phaseFlux,
199  real64 const (&dPhaseFlux_dP)[2],
200  real64 const (&dPhaseFlux_dC)[2][numComp] )
201  {
202  GEOS_UNUSED_VAR( k_up, potGrad, phaseFlux, dPhaseFlux_dP, dPhaseFlux_dC, er_up, esr_up, ei_up );
203 
205  real64 dissFlux[numComp]{};
206  real64 dDissFlux_dP[numFluxSupportPoints][numComp]{};
207  real64 dDissFlux_dC[numFluxSupportPoints][numComp][numComp]{};
208  real64 fluxPointCoef[numFluxSupportPoints] = {1.0, -1.0}; // for gradients
209 
210  real64 viscosityMult[3] = {1.0, 1.0, 1.0}; // for viscosity
211 
213  real64 poreVolume_n = 0.0; // Pore volume contribution
214  for( integer ke = 0; ke < numFluxSupportPoints; ++ke )
215  {
216  poreVolume_n += m_volume[seri[ke]][sesri[ke]][sei[ke]] * m_porosity_n[seri[ke]][sesri[ke]][sei[ke]][0];
217  }
218  poreVolume_n /= numFluxSupportPoints;
219 
220  // potential gradient contribution
221  // pressure
222  real64 pressure_gradient = 0;
223  for( integer ke = 0; ke < numFluxSupportPoints; ++ke )
224  pressure_gradient += fluxPointCoef[ke] * m_pres_n[seri[ke]][sesri[ke]][sei[ke]];
225 
226  real64 const potential_gradient = LvArray::math::abs( pressure_gradient );
227 
228  real64 grad_depth = 0;
229  for( integer ke = 0; ke < numFluxSupportPoints; ++ke )
230  {
231  grad_depth += fluxPointCoef[ke] * m_gravCoef[seri[ke]][sesri[ke]][sei[ke]];
232  }
233 
234  // bias towards x and y direction for miscible
235  /* The point of this "directional coefficient" was to add less dissipation flux in the direction of gravity and
236  more in all other directions. These hard-coded values of 1000 and 100 were picked by some tuning and as
237  expected are not robust. Further research/testing is needed to generalize this idea.
238  */
239  real64 directional_coef = 1.0;
240  if( m_miscibleDBC )
241  {
242  directional_coef = initialDirectionalCoef;
243  if( LvArray::math::abs( grad_depth ) > 0.0 )
244  {
245  real64 const d2 = LvArray::math::abs( grad_depth * grad_depth );
246  if( multiplierDirectionalCoef / d2 < initialDirectionalCoef )
247  directional_coef = multiplierDirectionalCoef / d2;
248  }
249  }
250 
251  // multiplier with all contributions
252  real64 const multiplier = m_kappaDBC * m_omegaDBC / poreVolume_n * m_dt * potential_gradient * directional_coef;
253 
255  for( integer ke = 0; ke < numFluxSupportPoints; ++ke )
256  {
257  real64 const coef = multiplier * viscosityMult[ip] * stack.transmissibility[connectionIndex][ke];
258  for( integer ic = 0; ic < numComp; ++ic )
259  {
260  localIndex const er = seri[ke];
261  localIndex const esr = sesri[ke];
262  localIndex const ei = sei[ke];
263 
264  // composition gradient contribution to the dissipation flux
265  dissFlux[ic] += coef * m_compFrac[er][esr][ei][ic];
266 
267  dDissFlux_dP[ke][ic] = 0; // no dependency on pressure at n+1, compFrad is global component fraction (z_c)
268 
269  for( integer jc = 0; jc < numComp; ++jc )
270  {
271  // composition gradient derivative with respect to component density contribution to the dissipation flux
272  dDissFlux_dC[ke][ic][jc] += coef * m_dCompFrac_dCompDens[er][esr][ei][ic][jc];
273  }
274  }
275  }
276 
278  for( integer ic = 0; ic < numComp; ++ic )
279  {
280  integer const eqIndex0 = k[0] * numEqn + ic;
281  integer const eqIndex1 = k[1] * numEqn + ic;
282 
283  stack.localFlux[eqIndex0] += m_dt * dissFlux[ic];
284  stack.localFlux[eqIndex1] -= m_dt * dissFlux[ic];
285 
286  for( integer ke = 0; ke < numFluxSupportPoints; ++ke )
287  {
288  localIndex const localDofIndexPres = k[ke] * numDof;
289  stack.localFluxJacobian[eqIndex0][localDofIndexPres] += m_dt * dDissFlux_dP[ke][ic];
290  stack.localFluxJacobian[eqIndex1][localDofIndexPres] -= m_dt * dDissFlux_dP[ke][ic];
291 
292  for( integer jc = 0; jc < numComp; ++jc )
293  {
294  localIndex const localDofIndexComp = localDofIndexPres + jc + 1;
295  stack.localFluxJacobian[eqIndex0][localDofIndexComp] += m_dt * dDissFlux_dC[ke][ic][jc];
296  stack.localFluxJacobian[eqIndex1][localDofIndexComp] -= m_dt * dDissFlux_dC[ke][ic][jc];
297  }
298  }
299  }
300 
301  } ); // end call to Base::computeFlux
302 
303  }
304 
305 protected:
306 
310 
313 
314  // DBC specific parameters
315  // input
316  real64 m_omegaDBC;
317  integer m_miscibleDBC;
318  // computed
319  real64 m_kappaDBC;
320 };
321 
326 {
327 public:
328 
345  template< typename POLICY, typename STENCILWRAPPER >
346  static void
347  createAndLaunch( integer const numComps,
348  integer const numPhases,
349  globalIndex const rankOffset,
350  string const & dofKey,
351  integer const hasCapPressure,
352  integer const useTotalMassEquation,
353  string const & solverName,
354  ElementRegionManager const & elemManager,
355  STENCILWRAPPER const & stencilWrapper,
356  real64 const & dt,
357  CRSMatrixView< real64, globalIndex const > const & localMatrix,
358  arrayView1d< real64 > const & localRhs,
359  real64 const omega,
360  integer const curNewton,
361  integer const continuation,
362  integer const miscible,
363  real64 const kappamin,
364  real64 const contMultiplier )
365  {
366  isothermalCompositionalMultiphaseBaseKernels::
367  internal::kernelLaunchSelectorCompSwitch( numComps, [&]( auto NC )
368  {
369  integer constexpr NUM_COMP = NC();
370  integer constexpr NUM_DOF = NC() + 1;
371 
373  elemManager.constructArrayViewAccessor< globalIndex, 1 >( dofKey );
374  dofNumberAccessor.setName( solverName + "/accessors/" + dofKey );
375 
376  BitFlags< isothermalCompositionalMultiphaseFVMKernels::KernelFlags > kernelFlags;
377  if( hasCapPressure )
378  kernelFlags.set( isothermalCompositionalMultiphaseFVMKernels::KernelFlags::CapPressure );
379  if( useTotalMassEquation )
380  kernelFlags.set( isothermalCompositionalMultiphaseFVMKernels::KernelFlags::TotalMassEquation );
381 
383  typename KERNEL_TYPE::CompFlowAccessors compFlowAccessors( elemManager, solverName );
384  typename KERNEL_TYPE::MultiFluidAccessors multiFluidAccessors( elemManager, solverName );
385  typename KERNEL_TYPE::CapPressureAccessors capPressureAccessors( elemManager, solverName );
386  typename KERNEL_TYPE::PermeabilityAccessors permeabilityAccessors( elemManager, solverName );
387  typename KERNEL_TYPE::PorosityAccessors porosityAccessors( elemManager, solverName );
388  typename KERNEL_TYPE::DissCompFlowAccessors dissCompFlowAccessors( elemManager, solverName );
389 
390  KERNEL_TYPE kernel( numPhases, rankOffset, stencilWrapper, dofNumberAccessor, compFlowAccessors, dissCompFlowAccessors,
391  multiFluidAccessors, capPressureAccessors, permeabilityAccessors, porosityAccessors,
392  dt, localMatrix, localRhs, kernelFlags, omega, curNewton, continuation, miscible, kappamin, contMultiplier );
393  KERNEL_TYPE::template launch< POLICY >( stencilWrapper.size(), kernel );
394  } );
395  }
396 };
397 
398 } // namespace DissipationCompositionalMultiphaseFVMKernels
399 
400 } // namespace geos
401 
402 
403 #endif //GEOS_PHYSICSSOLVERS_FLUIDFLOW_COMPOSITIONAL_DISSIPATIONFLUXCOMPUTEKERNEL_HPP
#define GEOS_HOST_DEVICE
Marks a host-device function.
Definition: GeosxMacros.hpp:49
#define GEOS_UNUSED_VAR(...)
Mark an unused variable and silence compiler warnings.
Definition: GeosxMacros.hpp:84
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...
A struct to automatically construct and store element view accessors.
A struct to automatically construct and store element view accessors.
static void createAndLaunch(integer const numComps, integer const numPhases, globalIndex const rankOffset, string const &dofKey, integer const hasCapPressure, integer const useTotalMassEquation, string const &solverName, ElementRegionManager const &elemManager, STENCILWRAPPER const &stencilWrapper, real64 const &dt, CRSMatrixView< real64, globalIndex const > const &localMatrix, arrayView1d< real64 > const &localRhs, real64 const omega, integer const curNewton, integer const continuation, integer const miscible, real64 const kappamin, real64 const contMultiplier)
Create a new kernel and launch.
Define the interface for the assembly kernel in charge of flux terms.
ElementRegionManager::ElementViewConst< VIEWTYPE > ElementViewConst
The type for element-based data. Consists entirely of ArrayView's.
static constexpr integer numFluxSupportPoints
Number of flux support points (hard-coded for TFPA)
static constexpr integer numEqn
Compute time value for the number of equations (all of them, except the volume balance equation)
ElementViewConst< arrayView1d< real64 const > > const m_pres_n
Views on flow properties at the previous converged time step.
GEOS_HOST_DEVICE void computeFlux(localIndex const iconn, typename Base::StackVariables &stack) const
Compute the local flux contributions to the residual and Jacobian, including dissipation.
static constexpr integer numComp
Compile time value for the number of components.
FluxComputeKernel(integer const numPhases, globalIndex const rankOffset, STENCILWRAPPER const &stencilWrapper, DofNumberAccessor const &dofNumberAccessor, CompFlowAccessors const &compFlowAccessors, DissCompFlowAccessors const &dissCompFlowAccessors, MultiFluidAccessors const &multiFluidAccessors, CapPressureAccessors const &capPressureAccessors, PermeabilityAccessors const &permeabilityAccessors, PorosityAccessors const &porosityAccessors, real64 const &dt, CRSMatrixView< real64, globalIndex const > const &localMatrix, arrayView1d< real64 > const &localRhs, BitFlags< isothermalCompositionalMultiphaseFVMKernels::KernelFlags > kernelFlags, real64 const omega, integer const curNewton, integer const continuation, integer const miscible, real64 const kappamin, real64 const contMultiplier)
Constructor for the kernel interface.
static constexpr integer numDof
Compute time value for the number of degrees of freedom.
ElementViewConst< arrayView3d< real64 const, compflow::USD_COMP_DC > > const m_dCompFrac_dCompDens
Views on derivatives of comp fractions.
Base class for FluxComputeKernel that holds all data not dependent on template parameters (like stenc...
ElementViewConst< arrayView3d< real64 const, compflow::USD_COMP_DC > > const m_dCompFrac_dCompDens
Views on derivatives of comp fractions.
Define the interface for the assembly kernel in charge of flux terms.
GEOS_HOST_DEVICE void computeFlux(localIndex const iconn, StackVariables &stack, FUNC &&compFluxKernelOp=NoOpFunc{}) const
Compute the local flux contributions to the residual and Jacobian.
static constexpr integer numFluxSupportPoints
Number of flux support points (hard-coded for TFPA)
static constexpr integer numEqn
Compute time value for the number of equations (all of them, except the volume balance equation)
static constexpr integer numComp
Compile time value for the number of components.
static constexpr integer numDof
Compute time value for the number of degrees of freedom.
ElementViewConst< arrayView3d< real64 const > > const m_permeability
Views on permeability.
ArrayView< T, 1 > arrayView1d
Alias for 1D array view.
Definition: DataTypes.hpp:180
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
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
Trait struct for elementVolume data.
Definition: MeshFields.hpp:108
Kernel variables (dof numbers, jacobian and residual) located on the stack.
stackArray2d< real64, maxNumElems *numEqn *maxStencilSize *numDof > localFluxJacobian
Storage for the face local Jacobian matrix.
stackArray1d< real64, maxNumElems *numEqn > localFlux
Storage for the face local residual vector (all equations except volume balance)
real64 transmissibility[maxNumConns][numFluxSupportPoints]
Transmissibility.