GEOS
ThermalDirichletFluxComputeKernel_impl.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_COMPOSITIONAL_THERMALDIRICHLETFLUXCOMPUTEKERNEL_IMPL_HPP
21 #define GEOS_PHYSICSSOLVERS_FLUIDFLOW_COMPOSITIONAL_THERMALDIRICHLETFLUXCOMPUTEKERNEL_IMPL_HPP
22 
25 
26 namespace geos
27 {
28 namespace thermalCompositionalMultiphaseFVMKernels
29 {
30 
31 template< typename FLUIDWRAPPER, typename POLICY, integer NUM_COMP, integer NUM_DOF >
33 DirichletFluxComputeKernel( integer const numPhases,
34  globalIndex const rankOffset,
35  FaceManager const & faceManager,
36  BoundaryStencilWrapper const & stencilWrapper,
37  FLUIDWRAPPER const & fluidWrapper,
38  DofNumberAccessor const & dofNumberAccessor,
39  CompFlowAccessors const & compFlowAccessors,
40  ThermalCompFlowAccessors const & thermalCompFlowAccessors,
41  MultiFluidAccessors const & multiFluidAccessors,
42  ThermalMultiFluidAccessors const & thermalMultiFluidAccessors,
43  CapPressureAccessors const & capPressureAccessors,
44  PermeabilityAccessors const & permeabilityAccessors,
45  ThermalConductivityAccessors const & thermalConductivityAccessors,
46  real64 const dt,
48  arrayView1d< real64 > const & localRhs,
49  BitFlags< isothermalCompositionalMultiphaseFVMKernels::KernelFlags > kernelFlags )
50  : Base( numPhases,
51  rankOffset,
52  faceManager,
53  stencilWrapper,
54  fluidWrapper,
55  dofNumberAccessor,
56  compFlowAccessors,
57  multiFluidAccessors,
58  capPressureAccessors,
59  permeabilityAccessors,
60  dt,
61  localMatrix,
62  localRhs,
63  kernelFlags ),
64  m_temp( thermalCompFlowAccessors.get( fields::flow::temperature {} ) ),
65  m_phaseEnthalpy( thermalMultiFluidAccessors.get( fields::multifluid::phaseEnthalpy {} ) ),
66  m_dPhaseEnthalpy( thermalMultiFluidAccessors.get( fields::multifluid::dPhaseEnthalpy {} ) ),
67  m_thermalConductivity( thermalConductivityAccessors.get( fields::thermalconductivity::effectiveConductivity {} ) )
68 {}
69 
70 template< typename FLUIDWRAPPER, typename POLICY, integer NUM_COMP, integer NUM_DOF >
72 launchKernel( localIndex const numConnections )
73 {
74  this->template launch< POLICY >( numConnections, *this );
75 }
76 
77 template< typename FLUIDWRAPPER, typename POLICY, integer NUM_COMP, integer NUM_DOF >
80 computeFlux( localIndex const iconn,
81  StackVariables & stack ) const
82 {
83  using Order = BoundaryStencil::Order;
84  using Deriv = constitutive::multifluid::DerivativeOffset;
85 
86  // ***********************************************
87  // First, we call the base computeFlux to compute:
88  // 1) compFlux and its derivatives (including derivatives wrt temperature),
89  // 2) enthalpy part of energyFlux and its derivatives (including derivatives wrt temperature)
90  //
91  // Computing dCompFlux_dT and the enthalpy flux requires quantities already computed in the base computeFlux,
92  // such as potGrad, phaseFlux, and the indices of the upwind cell
93  // We use the lambda below (called **inside** the phase loop of the base computeFlux) to access these variables
94  Base::computeFlux( iconn, stack, [&] ( integer const ip,
95  localIndex const er,
96  localIndex const esr,
97  localIndex const ei,
98  localIndex const kf,
99  real64 const f, // potGrad times trans
100  real64 const facePhaseMob,
103  real64 const phaseFlux,
104  real64 const dPhaseFlux_dP,
105  real64 const (&dPhaseFlux_dC)[numComp] )
106  {
107  // We are in the loop over phases, ip provides the current phase index.
108 
109  // Step 1: compute the derivatives of the mean density at the interface wrt temperature
110 
111  real64 const dDensMean_dT = 0.5 * m_dPhaseMassDens[er][esr][ei][0][ip][Deriv::dT];
112 
113  // Step 2: compute the derivatives of the phase potential difference wrt temperature
114  //***** calculation of flux *****
115 
116  real64 const dF_dT = -stack.transmissibility * dDensMean_dT * ( m_gravCoef[er][esr][ei] - m_faceGravCoef[kf] );
117 
118  // Step 3: compute the derivatives of the (upwinded) compFlux wrt temperature
119  // *** upwinding ***
120 
121  // note: the upwinding is done in the base class, which is in charge of
122  // computing the following quantities: potGrad, phaseFlux
123  // It is easier to hard-code the if/else because it is difficult to address elem and face variables in a uniform way
124 
125  if( f >= 0 ) // the element is upstream
126  {
127 
128  // Step 3.1.a: compute the derivative of phase flux wrt temperature
129  real64 const dPhaseFlux_dT = m_phaseMob[er][esr][ei][ip] * dF_dT + m_dPhaseMob[er][esr][ei][ip][Deriv::dT] * f;
130 
131  // Step 3.2.a: compute the derivative of component flux wrt temperature
132 
133  // slice some constitutive arrays to avoid too much indexing in component loop
134  arraySlice1d< real64 const, constitutive::multifluid::USD_PHASE_COMP - 3 > phaseCompFracSub =
135  m_phaseCompFrac[er][esr][ei][0][ip];
136  arraySlice2d< real64 const, constitutive::multifluid::USD_PHASE_COMP_DC - 3 > dPhaseCompFracSub =
137  m_dPhaseCompFrac[er][esr][ei][0][ip];
138 
139  for( integer ic = 0; ic < numComp; ++ic )
140  {
141  real64 const ycp = phaseCompFracSub[ic];
142  stack.dCompFlux_dT[ic] += dPhaseFlux_dT * ycp + phaseFlux * dPhaseCompFracSub[ic][Deriv::dT];
143  }
144 
145  // Step 3.3.a: compute the enthalpy flux
146 
147  real64 const enthalpy = m_phaseEnthalpy[er][esr][ei][0][ip];
148  stack.energyFlux += phaseFlux * enthalpy;
149  stack.dEnergyFlux_dP += dPhaseFlux_dP * enthalpy + phaseFlux * m_dPhaseEnthalpy[er][esr][ei][0][ip][Deriv::dP];
150  stack.dEnergyFlux_dT += dPhaseFlux_dT * enthalpy + phaseFlux * m_dPhaseEnthalpy[er][esr][ei][0][ip][Deriv::dT];
151 
152  real64 dProp_dC[numComp]{};
153  applyChainRule( numComp,
154  m_dCompFrac_dCompDens[er][esr][ei],
155  m_dPhaseEnthalpy[er][esr][ei][0][ip],
156  dProp_dC,
157  Deriv::dC );
158  for( integer jc = 0; jc < numComp; ++jc )
159  {
160  stack.dEnergyFlux_dC[jc] += dPhaseFlux_dC[jc] * enthalpy + phaseFlux * dProp_dC[jc];
161  }
162 
163  }
164  else // the face is upstream
165  {
166 
167  // Step 3.1.b: compute the derivative of phase flux wrt temperature
168  real64 const dPhaseFlux_dT = facePhaseMob * dF_dT;
169 
170  // Step 3.2.b: compute the derivative of component flux wrt temperature
171 
172  for( integer ic = 0; ic < numComp; ++ic )
173  {
174  real64 const ycp = facePhaseCompFrac[ip][ic];
175  stack.dCompFlux_dT[ic] += dPhaseFlux_dT * ycp;
176  }
177 
178  // Step 3.3.b: compute the enthalpy flux
179 
180  real64 const enthalpy = facePhaseEnthalpy[ip];
181  stack.energyFlux += phaseFlux * enthalpy;
182  stack.dEnergyFlux_dP += dPhaseFlux_dP * enthalpy;
183  stack.dEnergyFlux_dT += dPhaseFlux_dT * enthalpy;
184  for( integer jc = 0; jc < numComp; ++jc )
185  {
186  stack.dEnergyFlux_dC[jc] += dPhaseFlux_dC[jc] * enthalpy;
187  }
188 
189  }
190 
191  } );
192 
193  // *****************************************************
194  // Computation of the conduction term in the energy flux
195  // Note that the phase enthalpy term in the energy was computed above
196  // Note that this term is computed using an explicit treatment of conductivity for now
197 
198  // Step 1: compute the thermal transmissibilities at this face
199  // Below, the thermal conductivity used to compute (explicitly) the thermal conducivity
200  // To avoid modifying the signature of the "computeWeights" function for now, we pass m_thermalConductivity twice
201  // TODO: modify computeWeights to accomodate explicit coefficients
202  real64 thermalTrans = 0.0;
203  real64 dThermalTrans_dPerm[3]{}; // not used
204  m_stencilWrapper.computeWeights( iconn,
205  m_thermalConductivity,
206  thermalTrans,
207  dThermalTrans_dPerm );
208 
209  // Step 2: compute temperature difference at the interface
210  stack.energyFlux += thermalTrans
211  * ( m_temp[m_seri( iconn, Order::ELEM )][m_sesri( iconn, Order::ELEM )][m_sei( iconn, Order::ELEM )] - m_faceTemp[m_sei( iconn, Order::FACE )] );
212  stack.dEnergyFlux_dT += thermalTrans;
213 
214 
215  // **********************************************************************************
216  // At this point, we have computed the energyFlux and the compFlux for all components
217  // We have to do two things here:
218  // 1) Add dCompFlux_dTemp to the localFluxJacobian of the component mass balance equations
219  // 2) Add energyFlux and its derivatives to the localFlux(Jacobian) of the energy balance equation
220 
221  // Step 1: add dCompFlux_dTemp to localFluxJacobian
222  for( integer ic = 0; ic < numComp; ++ic )
223  {
224  stack.localFluxJacobian[ic][numDof-1] = m_dt * stack.dCompFlux_dT[ic];
225  }
226 
227  // Step 2: add energyFlux and its derivatives to localFlux and localFluxJacobian
228  integer const localRowIndexEnergy = numEqn-1;
229  stack.localFlux[localRowIndexEnergy] = m_dt * stack.energyFlux;
230 
231  stack.localFluxJacobian[localRowIndexEnergy][0] = m_dt * stack.dEnergyFlux_dP;
232  stack.localFluxJacobian[localRowIndexEnergy][numDof-1] = m_dt * stack.dEnergyFlux_dT;
233  for( integer jc = 0; jc < numComp; ++jc )
234  {
235  stack.localFluxJacobian[localRowIndexEnergy][jc+1] = m_dt * stack.dEnergyFlux_dC[jc];
236  }
237 }
238 
239 template< typename FLUIDWRAPPER, typename POLICY, integer NUM_COMP, integer NUM_DOF >
242 complete( localIndex const iconn,
243  StackVariables & stack ) const
244 {
245  // Call Case::complete to assemble the component mass balance equations (i = 0 to i = numDof-2)
246  // In the lambda, add contribution to residual and jacobian into the energy balance equation
247  Base::complete( iconn, stack, [&] ( localIndex const localRow )
248  {
249  // beware, there is volume balance eqn in m_localRhs and m_localMatrix!
250  RAJA::atomicAdd( parallelDeviceAtomic{}, &AbstractBase::m_localRhs[localRow + numEqn], stack.localFlux[numEqn-1] );
251  AbstractBase::m_localMatrix.addToRowBinarySearchUnsorted< parallelDeviceAtomic >
252  ( localRow + numEqn,
253  stack.dofColIndices,
254  stack.localFluxJacobian[numEqn-1],
255  numDof );
256  } );
257 }
258 
259 } // namespace thermalCompositionalMultiphaseFVMKernels
260 } // namespace geos
261 
262 #endif //GEOS_PHYSICSSOLVERS_FLUIDFLOW_COMPOSITIONAL_THERMALDIRICHLETFLUXCOMPUTEKERNEL_IMPL_HPP
#define GEOS_HOST_DEVICE
Marks a host-device function.
Definition: GeosxMacros.hpp:49
The FaceManager class provides an interface to ObjectManagerBase in order to manage face data.
Definition: FaceManager.hpp:44
A struct to automatically construct and store element view accessors.
A struct to automatically construct and store element view accessors.
Define the interface for the assembly kernel in charge of Dirichlet face flux terms.
void launchKernel(localIndex const numConnections)
Launch the kernel for a given number of connections.
GEOS_HOST_DEVICE void complete(localIndex const iconn, StackVariables &stack) const
Performs the complete phase for the kernel.
DirichletFluxComputeKernel(integer const numPhases, globalIndex const rankOffset, FaceManager const &faceManager, BoundaryStencilWrapper const &stencilWrapper, FLUIDWRAPPER const &fluidWrapper, DofNumberAccessor const &dofNumberAccessor, CompFlowAccessors const &compFlowAccessors, ThermalCompFlowAccessors const &thermalCompFlowAccessors, MultiFluidAccessors const &multiFluidAccessors, ThermalMultiFluidAccessors const &thermalMultiFluidAccessors, CapPressureAccessors const &capPressureAccessors, PermeabilityAccessors const &permeabilityAccessors, ThermalConductivityAccessors const &thermalConductivityAccessors, real64 const dt, CRSMatrixView< real64, globalIndex const > const &localMatrix, arrayView1d< real64 > const &localRhs, BitFlags< isothermalCompositionalMultiphaseFVMKernels::KernelFlags > kernelFlags)
Constructor for the kernel interface.
GEOS_HOST_DEVICE void computeFlux(localIndex const iconn, StackVariables &stack) const
Compute the local flux contributions to the residual and Jacobian.
ArrayView< T, 1 > arrayView1d
Alias for 1D array view.
Definition: DataTypes.hpp:179
GEOS_GLOBALINDEX_TYPE globalIndex
Global index type (for indexing objects across MPI partitions).
Definition: DataTypes.hpp:87
ArraySlice< T, 2, USD > arraySlice2d
Alias for 2D array slice.
Definition: DataTypes.hpp:199
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:183
LvArray::CRSMatrixView< T, COL_INDEX, INDEX_TYPE const, LvArray::ChaiBuffer > CRSMatrixView
Alias for CRS Matrix View.
Definition: DataTypes.hpp:309
int integer
Signed integer type.
Definition: DataTypes.hpp:81
Defines the order of element/face in the stencil.
globalIndex dofColIndices[numDof]
Indices of the matrix rows/columns corresponding to the dofs in this face.