GEOS
PhaseVolumeFractionKernel.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_PHASEVOLUMEFRACTIONKERNEL_HPP
21 #define GEOS_PHYSICSSOLVERS_FLUIDFLOW_COMPOSITIONAL_PHASEVOLUMEFRACTIONKERNEL_HPP
22 
24 
25 namespace geos
26 {
27 
28 namespace isothermalCompositionalMultiphaseBaseKernels
29 {
30 
31 /******************************** PhaseVolumeFractionKernel ********************************/
32 
39 template< integer NUM_COMP, integer NUM_PHASE >
41 {
42 public:
43 
45  using Base::numComp;
46 
48  static constexpr integer numPhase = NUM_PHASE;
49 
56  constitutive::MultiFluidBase const & fluid )
57  : Base(),
58  m_phaseVolFrac( subRegion.getField< fields::flow::phaseVolumeFraction >() ),
59  m_dPhaseVolFrac( subRegion.getField< fields::flow::dPhaseVolumeFraction >() ),
60  m_compDens( subRegion.getField< fields::flow::globalCompDensity >() ),
61  m_dCompFrac_dCompDens( subRegion.getField< fields::flow::dGlobalCompFraction_dGlobalCompDensity >() ),
62  m_phaseFrac( fluid.phaseFraction() ),
63  m_dPhaseFrac( fluid.dPhaseFraction() ),
64  m_phaseDens( fluid.phaseDensity() ),
65  m_dPhaseDens( fluid.dPhaseDensity() )
66  {}
67 
74  template< typename FUNC = NoOpFunc >
77  FUNC && phaseVolFractionKernelOp = NoOpFunc{} ) const
78  {
79  using Deriv = constitutive::multifluid::DerivativeOffset;
80 
81  arraySlice1d< real64 const, compflow::USD_COMP - 1 > const compDens = m_compDens[ei];
82  arraySlice2d< real64 const, compflow::USD_COMP_DC - 1 > const dCompFrac_dCompDens = m_dCompFrac_dCompDens[ei];
83  arraySlice1d< real64 const, constitutive::multifluid::USD_PHASE - 2 > const phaseDens = m_phaseDens[ei][0];
84  arraySlice2d< real64 const, constitutive::multifluid::USD_PHASE_DC - 2 > const dPhaseDens = m_dPhaseDens[ei][0];
85  arraySlice1d< real64 const, constitutive::multifluid::USD_PHASE - 2 > const phaseFrac = m_phaseFrac[ei][0];
86  arraySlice2d< real64 const, constitutive::multifluid::USD_PHASE_DC - 2 > const dPhaseFrac = m_dPhaseFrac[ei][0];
87  arraySlice1d< real64, compflow::USD_PHASE - 1 > const phaseVolFrac = m_phaseVolFrac[ei];
88  arraySlice2d< real64, compflow::USD_PHASE_DC - 1 > const dPhaseVolFrac = m_dPhaseVolFrac[ei];
89 
90  real64 work[numComp]{};
91 
92  // compute total density from component partial densities
93  real64 totalDensity = 0.0;
94  real64 const dTotalDens_dCompDens = 1.0;
95  for( integer ic = 0; ic < numComp; ++ic )
96  {
97  totalDensity += compDens[ic];
98  }
99 
100  real64 maxDeltaPhaseVolFrac = 0.0;
101 
102  for( integer ip = 0; ip < numPhase; ++ip )
103  {
104 
105  // set the saturation to zero if the phase is absent
106  bool const phaseExists = (phaseFrac[ip] > 0);
107  if( !phaseExists )
108  {
109  phaseVolFrac[ip] = 0.;
110  for( integer jc = 0; jc < numComp+2; ++jc )
111  {
112  dPhaseVolFrac[ip][jc] = 0.;
113  }
114  continue;
115  }
116 
117  // Expression for volume fractions: S_p = (nu_p / rho_p) * rho_t
118  real64 const phaseDensInv = 1.0 / phaseDens[ip];
119 
120  // store old saturation to compute change later
121  real64 const satOld = phaseVolFrac[ip];
122 
123  // compute saturation and derivatives except multiplying by the total density
124  phaseVolFrac[ip] = phaseFrac[ip] * phaseDensInv;
125 
126  dPhaseVolFrac[ip][Deriv::dP] =
127  (dPhaseFrac[ip][Deriv::dP] - phaseVolFrac[ip] * dPhaseDens[ip][Deriv::dP]) * phaseDensInv;
128 
129  for( integer jc = 0; jc < numComp; ++jc )
130  {
131  dPhaseVolFrac[ip][Deriv::dC+jc] =
132  (dPhaseFrac[ip][Deriv::dC+jc] - phaseVolFrac[ip] * dPhaseDens[ip][Deriv::dC+jc]) * phaseDensInv;
133  }
134 
135  // apply chain rule to convert derivatives from global component fractions to densities
136  applyChainRuleInPlace( numComp, dCompFrac_dCompDens, dPhaseVolFrac[ip], work, Deriv::dC );
137 
138  // call the lambda in the phase loop to allow the reuse of the phaseVolFrac and totalDensity
139  // possible use: assemble the derivatives wrt temperature
140  phaseVolFractionKernelOp( ip, phaseVolFrac[ip], phaseDensInv, totalDensity );
141 
142  // now finalize the computation by multiplying by total density
143  for( integer jc = 0; jc < numComp; ++jc )
144  {
145  dPhaseVolFrac[ip][Deriv::dC+jc] *= totalDensity;
146  dPhaseVolFrac[ip][Deriv::dC+jc] += phaseVolFrac[ip] * dTotalDens_dCompDens;
147  }
148 
149  phaseVolFrac[ip] *= totalDensity;
150  dPhaseVolFrac[ip][Deriv::dP] *= totalDensity;
151 
152  real64 const deltaPhaseVolFrac = LvArray::math::abs( phaseVolFrac[ip] - satOld );
153  if( maxDeltaPhaseVolFrac < deltaPhaseVolFrac )
154  {
155  maxDeltaPhaseVolFrac = deltaPhaseVolFrac;
156  }
157  }
158  return maxDeltaPhaseVolFrac;
159  }
160 
168  template< typename POLICY, typename KERNEL_TYPE >
169  static real64
170  launch( localIndex const numElems,
171  KERNEL_TYPE const & kernelComponent )
172  {
173  RAJA::ReduceMax< ReducePolicy< POLICY >, real64 > maxDeltaPhaseVolFrac( 0.0 );
174  forAll< POLICY >( numElems, [=] GEOS_HOST_DEVICE ( localIndex const ei )
175  {
176  real64 const deltaPhaseVolFrac = kernelComponent.compute( ei );
177  maxDeltaPhaseVolFrac.max( deltaPhaseVolFrac );
178  } );
179  return maxDeltaPhaseVolFrac.get();
180  }
181 
182 protected:
183 
184  // outputs
185 
189 
190  // inputs
191 
195 
199 
203 
204 };
205 
210 {
211 public:
212 
221  template< typename POLICY >
222  static real64
223  createAndLaunch( integer const numComp,
224  integer const numPhase,
225  ObjectManagerBase & subRegion,
226  constitutive::MultiFluidBase const & fluid )
227  {
228  real64 maxDeltaPhaseVolFrac = 0.0;
229  if( numPhase == 2 )
230  {
231  internal::kernelLaunchSelectorCompSwitch( numComp, [&] ( auto NC )
232  {
233  integer constexpr NUM_COMP = NC();
234  PhaseVolumeFractionKernel< NUM_COMP, 2 > kernel( subRegion, fluid );
235  maxDeltaPhaseVolFrac = PhaseVolumeFractionKernel< NUM_COMP, 2 >::template launch< POLICY >( subRegion.size(), kernel );
236  } );
237  }
238  else if( numPhase == 3 )
239  {
240  internal::kernelLaunchSelectorCompSwitch( numComp, [&] ( auto NC )
241  {
242  integer constexpr NUM_COMP = NC();
243  PhaseVolumeFractionKernel< NUM_COMP, 3 > kernel( subRegion, fluid );
244  maxDeltaPhaseVolFrac = PhaseVolumeFractionKernel< NUM_COMP, 3 >::template launch< POLICY >( subRegion.size(), kernel );
245  } );
246  }
247  return maxDeltaPhaseVolFrac;
248  }
249 };
250 
251 } // namespace isothermalCompositionalMultiphaseBaseKernels
252 
253 } // namespace geos
254 
255 
256 #endif //GEOS_PHYSICSSOLVERS_FLUIDFLOW_COMPOSITIONAL_PHASEVOLUMEFRACTIONKERNEL_HPP
#define GEOS_HOST_DEVICE
Marks a host-device function.
Definition: GeosxMacros.hpp:49
The ObjectManagerBase is the base object of all object managers in the mesh data hierachy.
localIndex size() const
Get the "size" of the group, which determines the number of elements in resizable wrappers.
Definition: Group.hpp:1315
static real64 createAndLaunch(integer const numComp, integer const numPhase, ObjectManagerBase &subRegion, constitutive::MultiFluidBase const &fluid)
Create a new kernel and launch.
Define the interface for the property kernel in charge of computing the phase volume fractions.
arrayView3d< real64 const, constitutive::multifluid::USD_PHASE > m_phaseDens
Views on phase densities.
static real64 launch(localIndex const numElems, KERNEL_TYPE const &kernelComponent)
Performs the kernel launch.
static constexpr integer numPhase
Compile time value for the number of phases.
arrayView3d< real64 const, constitutive::multifluid::USD_PHASE > m_phaseFrac
Views on phase fractions.
PhaseVolumeFractionKernel(ObjectManagerBase &subRegion, constitutive::MultiFluidBase const &fluid)
Constructor.
GEOS_HOST_DEVICE real64 compute(localIndex const ei, FUNC &&phaseVolFractionKernelOp=NoOpFunc{}) const
Compute the phase volume fractions in an element.
arrayView2d< real64, compflow::USD_PHASE > m_phaseVolFrac
Views on phase volume fractions.
static constexpr integer numComp
Compile time value for the number of components.
arrayView2d< real64 const, compflow::USD_COMP > m_compDens
Views on component densities.
Define the base interface for the property update kernels.
static constexpr integer numComp
Compile time value for the number of components.
ArraySlice< T, 2, USD > arraySlice2d
Alias for 2D array slice.
Definition: DataTypes.hpp:200
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
ArraySlice< T, 1, USD > arraySlice1d
Alias for 1D array slice.
Definition: DataTypes.hpp:184
std::int32_t integer
Signed integer type.
Definition: DataTypes.hpp:82
ArrayView< T, 4, USD > arrayView4d
Alias for 4D array view.
Definition: DataTypes.hpp:228
ArrayView< T, 2, USD > arrayView2d
Alias for 2D array view.
Definition: DataTypes.hpp:196
ArrayView< T, 3, USD > arrayView3d
Alias for 3D array view.
Definition: DataTypes.hpp:212