GEOS
PerforationFluxKernels.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_WELLS_PERFORATIONFLUXLKERNELS_HPP
21 #define GEOS_PHYSICSSOLVERS_FLUIDFLOW_WELLS_PERFORATIONFLUXLKERNELS_HPP
22 
23 #include "codingUtilities/Utilities.hpp"
24 #include "common/DataTypes.hpp"
25 #include "common/GEOS_RAJA_Interface.hpp"
26 #include "constitutive/fluid/multifluid/MultiFluidBase.hpp"
27 #include "constitutive/fluid/multifluid/MultiFluidFields.hpp"
28 #include "constitutive/relativePermeability/RelativePermeabilityBase.hpp"
29 #include "constitutive/relativePermeability/RelativePermeabilityFields.hpp"
40 
41 
42 namespace geos
43 {
44 
45 struct NoOpStuct
46 {
47  NoOpStuct(){}
48 };
49 
50 namespace isothermalPerforationFluxKernels
51 {
52 
53 /******************************** PerforationFluxKernel ********************************/
54 
55 template< integer NC, integer NP, integer IS_THERMAL >
57 {
58 public:
60  static constexpr integer numComp = NC;
61 
63  static constexpr integer numPhase = NP;
64 
66  static constexpr integer isThermal = IS_THERMAL;
67 
69 
70  using CompFlowAccessors =
71  StencilAccessors< fields::flow::pressure,
72  fields::flow::phaseVolumeFraction,
73  fields::flow::dPhaseVolumeFraction,
74  fields::flow::dGlobalCompFraction_dGlobalCompDensity >;
75 
76  using MultiFluidAccessors =
77  StencilMaterialAccessors< constitutive::MultiFluidBase,
78  fields::multifluid::phaseDensity,
79  fields::multifluid::dPhaseDensity,
80  fields::multifluid::phaseViscosity,
81  fields::multifluid::dPhaseViscosity,
82  fields::multifluid::phaseCompFraction,
83  fields::multifluid::dPhaseCompFraction >;
84 
85  using RelPermAccessors =
86  StencilMaterialAccessors< constitutive::RelativePermeabilityBase,
87  fields::relperm::phaseRelPerm,
88  fields::relperm::dPhaseRelPerm_dPhaseVolFraction >;
89 
90 
98  template< typename VIEWTYPE >
100 
101  PerforationFluxKernel ( PerforationData * const perforationData,
102  ElementSubRegionBase const & subRegion,
103  CompFlowAccessors const & compFlowAccessors,
104  MultiFluidAccessors const & multiFluidAccessors,
105  RelPermAccessors const & relPermAccessors,
106  bool const isInjector,
107  bool const isCrossflowEnabled ):
108  m_resPres( compFlowAccessors.get( fields::flow::pressure {} )),
109  m_resPhaseVolFrac( compFlowAccessors.get( fields::flow::phaseVolumeFraction {} )),
110  m_dResPhaseVolFrac( compFlowAccessors.get( fields::flow::dPhaseVolumeFraction {} )),
111  m_dResCompFrac_dCompDens( compFlowAccessors.get( fields::flow::dGlobalCompFraction_dGlobalCompDensity {} )),
112  m_resPhaseDens( multiFluidAccessors.get( fields::multifluid::phaseDensity {} )),
113  m_dResPhaseDens( multiFluidAccessors.get( fields::multifluid::dPhaseDensity {} )),
114  m_resPhaseVisc( multiFluidAccessors.get( fields::multifluid::phaseViscosity {} )),
115  m_dResPhaseVisc( multiFluidAccessors.get( fields::multifluid::dPhaseViscosity {} )),
116  m_resPhaseCompFrac( multiFluidAccessors.get( fields::multifluid::phaseCompFraction {} )),
117  m_dResPhaseCompFrac( multiFluidAccessors.get( fields::multifluid::dPhaseCompFraction {} )),
118  m_resPhaseRelPerm( relPermAccessors.get( fields::relperm::phaseRelPerm {} )),
119  m_dResPhaseRelPerm_dPhaseVolFrac( relPermAccessors.get( fields::relperm::dPhaseRelPerm_dPhaseVolFraction {} )),
120  m_wellElemGravCoef( subRegion.getField< fields::well::gravityCoefficient >()),
121  m_wellElemPres( subRegion.getField< fields::well::pressure >()),
122  m_wellElemCompDens( subRegion.getField< fields::well::globalCompDensity >()),
123  m_wellElemTotalMassDens( subRegion.getField< fields::well::totalMassDensity >()),
124  m_dWellElemTotalMassDens( subRegion.getField< fields::well::dTotalMassDensity >()),
125  m_wellElemCompFrac( subRegion.getField< fields::well::globalCompFraction >()),
126  m_dWellElemCompFrac_dCompDens( subRegion.getField< fields::well::dGlobalCompFraction_dGlobalCompDensity >()),
127  m_perfGravCoef( perforationData->getField< fields::well::gravityCoefficient >()),
128  m_perfWellElemIndex( perforationData->getField< fields::perforation::wellElementIndex >()),
129  m_perfTrans( perforationData->getField< fields::perforation::wellTransmissibility >()),
130  m_resElementRegion( perforationData->getField< fields::perforation::reservoirElementRegion >()),
131  m_resElementSubRegion( perforationData->getField< fields::perforation::reservoirElementSubRegion >()),
132  m_resElementIndex( perforationData->getField< fields::perforation::reservoirElementIndex >()),
133  m_compPerfRate( perforationData->getField< fields::well::compPerforationRate >()),
134  m_dCompPerfRate( perforationData->getField< fields::well::dCompPerforationRate >()),
135  m_perfStatus( perforationData->getField< fields::perforation::perforationStatus >()),
136  m_isInjector( isInjector ),
137  m_isCrossflowEnabled( isCrossflowEnabled )
138  {}
139 
145  {
146 public:
147 
148  real64 m_potDiff;
149  real64 m_dPotDiff[2][constitutive::multifluid::DerivativeOffsetC< NC, IS_THERMAL >::nDer];
150 
151  };
152 
153 
155  inline
156  void initialize( localIndex const iperf, StackVariables & stack ) const
157  {
158  using CP_Deriv = constitutive::multifluid::DerivativeOffsetC< NC, IS_THERMAL >;
159  stack.m_potDiff = 0.0;
160  for( integer i = 0; i < 2; ++i )
161  {
162  for( integer ic = 0; ic < CP_Deriv::nDer; ++ic )
163  {
164  stack.m_dPotDiff[i][ic] = 0.0;
165  }
166  }
167  for( integer ic = 0; ic < NC; ++ic )
168  {
169  m_compPerfRate[iperf][ic] = 0.0;
170  for( integer ke = 0; ke < 2; ++ke )
171  {
172  for( integer jc = 0; jc < CP_Deriv::nDer; ++jc )
173  {
174  m_dCompPerfRate[iperf][ke][ic][jc] = 0.0;
175  }
176  }
177  }
178  }
180  inline
181  void computePotentialandDeriv( localIndex const iperf, localIndex const er, localIndex const esr, localIndex const ei, localIndex const iwelem, StackVariables & stack ) const
182  {
183  using CP_Deriv = constitutive::multifluid::DerivativeOffsetC< NC, IS_THERMAL >;
184  using Deriv = constitutive::multifluid::DerivativeOffset;
185  real64 dPres[2][CP_Deriv::nDer]{};
186 
187  // local working variables and arrays
188  real64 pres[2]{};
189  real64 multiplier[2]{};
190 
191  // a) get reservoir variables
192  pres[TAG::RES] = m_resPres[er][esr][ei];
193  dPres[TAG::RES][CP_Deriv::dP] = 1.0;
194  multiplier[TAG::RES] = 1.0;
195 
196  // Here in the absence of a buoyancy term we assume that the reservoir cell is perforated at its center
197  // TODO: add a buoyancy term for the reservoir side here
198 
199  // b) get well variables
200  pres[TAG::WELL] = m_wellElemPres[iwelem];
201  dPres[TAG::WELL][CP_Deriv::dP] = 1.0;
202  multiplier[TAG::WELL] = -1.0;
203 
204  real64 const gravD = ( m_perfGravCoef[iperf] - m_wellElemGravCoef[iwelem] );
205 
206  pres[TAG::WELL] += m_wellElemTotalMassDens[iwelem] * gravD;
207  // Note LHS uses CP_Deriv while RHS uses Deriv !!!
208  dPres[TAG::WELL][CP_Deriv::dP] += m_dWellElemTotalMassDens[iwelem][Deriv::dP] * gravD;
209  if constexpr ( IS_THERMAL )
210  {
211  dPres[TAG::WELL][CP_Deriv::dT] += m_dWellElemTotalMassDens[iwelem][Deriv::dT] * gravD;
212  }
213  for( integer ic = 0; ic < NC; ++ic )
214  {
215  dPres[TAG::WELL][CP_Deriv::dC+ic] += m_dWellElemTotalMassDens[iwelem][Deriv::dC+ic] * gravD;
216  }
217 
218  // compute potential difference
219  stack.m_potDiff = 0.0;
220  for( integer i = 0; i < 2; ++i )
221  {
222  stack.m_potDiff += multiplier[i] * m_perfTrans[iperf] * pres[i];
223  // LHS & RHS both use CP_Deriv
224  for( integer ic = 0; ic < CP_Deriv::nDer; ++ic )
225  {
226  stack.m_dPotDiff[i][ic] += multiplier[i] * m_perfTrans[iperf] * dPres[i][ic];
227  }
228  }
229  }
230 
232  inline
233  void computeMobilityandDeriv( localIndex const ip, localIndex const er, localIndex const esr, localIndex const ei,
234  real64 & mob, real64 (& dMob)[constitutive::multifluid::DerivativeOffsetC< NC, IS_THERMAL >::nDer] ) const
235  {
236  using CP_Deriv = constitutive::multifluid::DerivativeOffsetC< NC, IS_THERMAL >;
237  using Deriv = constitutive::multifluid::DerivativeOffset;
238 
239 
240  // viscosity
241  real64 const resVisc = m_resPhaseVisc[er][esr][ei][0][ip];
242  real64 dVisc[CP_Deriv::nDer]{};
243  dVisc[CP_Deriv::dP] = m_dResPhaseVisc[er][esr][ei][0][ip][Deriv::dP];
244  if constexpr ( IS_THERMAL )
245  {
246  dVisc[CP_Deriv::dT] = m_dResPhaseVisc[er][esr][ei][0][ip][Deriv::dT];
247  }
248 
249  applyChainRule( NC, m_dResCompFrac_dCompDens[er][esr][ei],
250  m_dResPhaseVisc[er][esr][ei][0][ip],
251  &dVisc[CP_Deriv::dC],
252  Deriv::dC );
253 
254  // relative permeability
255  real64 const resRelPerm = m_resPhaseRelPerm[er][esr][ei][0][ip];
256  real64 dRelPerm[CP_Deriv::nDer]{};
257  for( integer jp = 0; jp < NP; ++jp )
258  {
259  real64 const dResRelPerm_dS = m_dResPhaseRelPerm_dPhaseVolFrac[er][esr][ei][0][ip][jp];
260  dRelPerm[CP_Deriv::dP] += dResRelPerm_dS * m_dResPhaseVolFrac[er][esr][ei][jp][Deriv::dP];
261  if constexpr ( IS_THERMAL )
262  {
263  dRelPerm[CP_Deriv::dT] += dResRelPerm_dS * m_dResPhaseVolFrac[er][esr][ei][jp][Deriv::dT];
264  }
265  for( integer jc = 0; jc < NC; ++jc )
266  {
267  dRelPerm[CP_Deriv::dC+jc] += dResRelPerm_dS * m_dResPhaseVolFrac[er][esr][ei][jp][Deriv::dC+jc];
268  }
269  }
270  // compute mobility kr/mu
271  mob += resRelPerm / resVisc;
272  for( integer jc = 0; jc < CP_Deriv::nDer; ++jc )
273  {
274  dMob[jc] += (dRelPerm[jc] *resVisc - resRelPerm * dVisc[jc] )
275  / ( resVisc * resVisc);
276  }
277  }
278 
280  inline
281  void computeDensityMobilityandDeriv( localIndex const ip, localIndex const er, localIndex const esr, localIndex const ei,
282 
283  real64 & mob, real64 (& dMob)[constitutive::multifluid::DerivativeOffsetC< NC, IS_THERMAL >::nDer] ) const
284  {
285  using CP_Deriv = constitutive::multifluid::DerivativeOffsetC< NC, IS_THERMAL >;
286  using Deriv = constitutive::multifluid::DerivativeOffset;
287 
288  // density
289  real64 const resDens = m_resPhaseDens[er][esr][ei][0][ip];
290  real64 dDens[CP_Deriv::nDer]{};
291 
292  dDens[CP_Deriv::dP] = m_dResPhaseDens[er][esr][ei][0][ip][Deriv::dP];
293  if constexpr ( IS_THERMAL )
294  {
295  dDens[CP_Deriv::dT] = m_dResPhaseDens[er][esr][ei][0][ip][Deriv::dT];
296  }
297  applyChainRule( NC, m_dResCompFrac_dCompDens[er][esr][ei],
298  m_dResPhaseDens[er][esr][ei][0][ip],
299  &dDens[CP_Deriv::dC],
300  Deriv::dC );
301 
302  // viscosity
303  real64 const resVisc = m_resPhaseVisc[er][esr][ei][0][ip];
304  real64 dVisc[CP_Deriv::nDer]{};
305  dVisc[CP_Deriv::dP] = m_dResPhaseVisc[er][esr][ei][0][ip][Deriv::dP];
306  if constexpr ( IS_THERMAL )
307  {
308  dVisc[CP_Deriv::dT] = m_dResPhaseVisc[er][esr][ei][0][ip][Deriv::dT];
309  }
310 
311  applyChainRule( NC, m_dResCompFrac_dCompDens[er][esr][ei],
312  m_dResPhaseVisc[er][esr][ei][0][ip],
313  &dVisc[CP_Deriv::dC],
314  Deriv::dC );
315 
316  // relative permeability
317  real64 const resRelPerm = m_resPhaseRelPerm[er][esr][ei][0][ip];
318  real64 dRelPerm[CP_Deriv::nDer]{};
319  for( integer jc = 0; jc < CP_Deriv::nDer; ++jc )
320  {
321  dRelPerm[jc]=0;
322  }
323  for( integer jp = 0; jp < NP; ++jp )
324  {
325  real64 const dResRelPerm_dS = m_dResPhaseRelPerm_dPhaseVolFrac[er][esr][ei][0][ip][jp];
326  dRelPerm[CP_Deriv::dP] += dResRelPerm_dS * m_dResPhaseVolFrac[er][esr][ei][jp][Deriv::dP];
327  if constexpr ( IS_THERMAL )
328  {
329  dRelPerm[CP_Deriv::dT] += dResRelPerm_dS * m_dResPhaseVolFrac[er][esr][ei][jp][Deriv::dT];
330  }
331  for( integer jc = 0; jc < NC; ++jc )
332  {
333  dRelPerm[CP_Deriv::dC+jc] += dResRelPerm_dS * m_dResPhaseVolFrac[er][esr][ei][jp][Deriv::dC+jc];
334  }
335  }
336  // compute mobility kr/mu
337  mob = resDens * resRelPerm / resVisc;
338  for( integer jc = 0; jc < CP_Deriv::nDer; ++jc )
339  {
340  dMob[jc] = dRelPerm[jc] * resDens / resVisc
341  + mob * (dDens[jc] / resDens - dVisc[jc] / resVisc);
342  }
343  }
344 
345  template< typename FUNC = NoOpFunc >
347  inline
348  void
349  computeFlux( localIndex const iperf, localIndex const er, localIndex const esr, localIndex const ei, localIndex const iwelem, StackVariables & stack, FUNC && fluxKernelOp= NoOpFunc {} ) const
350  {
351 
352  // perf closed or inactive, return
353  if( !m_perfStatus[iperf] )
354  {
355  return;
356  }
357 
358  using Deriv = constitutive::multifluid::DerivativeOffset;
359  using CP_Deriv = constitutive::multifluid::DerivativeOffsetC< NC, IS_THERMAL >;
360 
361  // Step 2: compute potential difference and its derivatives
362  //computePotentialandDeriv( iperf, er, esr, ei, iwelem );
363 
364  // Step 3: compute mobility kr/mu and its derivatives
365  real64 mob;
366  real64 dMob[CP_Deriv::nDer]{};
367 
368  //computeDensityMobilityandDeriv( ip, er, esr, ei, mob, dMob, fluxKernelOp );
369  real64 flux = 0.0;
370  real64 dFlux[2][CP_Deriv::nDer]{};
371  real64 dCompFrac[CP_Deriv::nDer]{};
372 
373  if( stack.m_potDiff >= 0 ) // ** well is downstream **
374  {
375 
376  // loop over phases, compute and upwind phase flux
377  // and sum contributions to each component's perforation rate
378  for( integer ip = 0; ip < NP; ++ip )
379  {
380  // skip the rest of the calculation if the phase is absent
381  // or if crossflow is disabled for injectors
382  real64 const resPhaseVolFrac = m_resPhaseVolFrac[er][esr][ei][ip];
383  bool const phaseExists = (resPhaseVolFrac > 0);
384  if( !phaseExists || (m_isInjector && !m_isCrossflowEnabled) )
385  {
386  continue;
387  }
388 
389  computeDensityMobilityandDeriv( ip, er, esr, ei, mob, dMob );
390  fluxKernelOp( ip, resPhaseVolFrac, mob, dMob );
391  // compute the phase flux and derivatives using upstream cell mobility
392  flux = mob * stack.m_potDiff;
393  // Handles all dependencies
394  for( integer jc = 0; jc < CP_Deriv::nDer; ++jc )
395  {
396  dFlux[TAG::RES][jc] = dMob[jc] * stack.m_potDiff + mob * stack.m_dPotDiff[TAG::RES][jc];
397  dFlux[TAG::WELL][jc] = mob * stack.m_dPotDiff[TAG::WELL][jc];
398  }
399 
400  // increment component fluxes
401  for( integer ic = 0; ic < NC; ++ic )
402  {
403  m_compPerfRate[iperf][ic] += flux * m_resPhaseCompFrac[er][esr][ei][0][ip][ic];
404  dCompFrac[CP_Deriv::dP] = m_dResPhaseCompFrac[er][esr][ei][0][ip][ic][Deriv::dP];
405  if constexpr (IS_THERMAL)
406  {
407  dCompFrac[CP_Deriv::dT] = m_dResPhaseCompFrac[er][esr][ei][0][ip][ic][Deriv::dT];
408  }
409 
410  applyChainRule( NC,
411  m_dResCompFrac_dCompDens[er][esr][ei],
412  m_dResPhaseCompFrac[er][esr][ei][0][ip][ic],
413  &dCompFrac[CP_Deriv::dC],
414  Deriv::dC );
415 
416  for( integer jc = 0; jc < CP_Deriv::nDer; ++jc )
417  {
418  m_dCompPerfRate[iperf][TAG::RES][ic][jc] += dFlux[TAG::RES][jc] * m_resPhaseCompFrac[er][esr][ei][0][ip][ic];
419  m_dCompPerfRate[iperf][TAG::RES][ic][jc] += flux * dCompFrac[jc];
420  m_dCompPerfRate[iperf][TAG::WELL][ic][jc] += dFlux[TAG::WELL][jc] * m_resPhaseCompFrac[er][esr][ei][0][ip][ic];
421  }
422  }
423  } // end resevoir is upstream phase loop
424  }
425  else // ** well is upstream **
426  {
427  real64 resTotalMob = 0.0;
428  real64 dResTotalMob[CP_Deriv::nDer]{};
429  // we re-compute here the total mass (when useMass == 1) or molar (when useMass == 0) density
430  real64 wellElemTotalDens = 0;
431  for( integer ic = 0; ic < NC; ++ic )
432  {
433  wellElemTotalDens += m_wellElemCompDens[iwelem][ic];
434  }
435 
436  // first, compute the reservoir total mobility (excluding phase density)
437  for( integer ip = 0; ip < NP; ++ip )
438  {
439  // skip the rest of the calculation if the phase is absent
440  // or if crossflow is disabled for non-injectors aka producers
441  bool const phaseExists = (m_resPhaseVolFrac[er][esr][ei][ip] > 0);
442  if( !phaseExists || (!m_isInjector && !m_isCrossflowEnabled) )
443  {
444  continue;
445  }
446  computeMobilityandDeriv( ip, er, esr, ei, resTotalMob, dResTotalMob );
447  } // end well is upstream phase loop
448 
449  // compute a potdiff multiplier = wellElemTotalDens * resTotalMob
450  // wellElemTotalDens is a mass density if useMass == 1 and a molar density otherwise
451  real64 const mult = wellElemTotalDens * resTotalMob;
452 
453  real64 dMult[2][CP_Deriv::nDer]{};
454  dMult[TAG::WELL][CP_Deriv::dP] = 0.0;
455  if constexpr ( IS_THERMAL )
456  {
457  dMult[TAG::WELL][CP_Deriv::dT] = 0.0;
458  }
459  for( integer ic = 0; ic < NC; ++ic )
460  {
461  dMult[TAG::WELL][CP_Deriv::dC+ic] = resTotalMob;
462  }
463  for( integer jc = 0; jc < CP_Deriv::nDer; ++jc )
464  {
465  dMult[TAG::RES][jc] = wellElemTotalDens * dResTotalMob[jc];
466  }
467 
468  // compute the volumetric flux and derivatives using upstream cell mobility
469  flux = mult * stack.m_potDiff;
470  for( integer ic = 0; ic < CP_Deriv::nDer; ++ic )
471  {
472  dFlux[TAG::RES][ic] = dMult[TAG::RES][ic] * stack.m_potDiff + mult * stack.m_dPotDiff[TAG::RES][ic];
473  dFlux[TAG::WELL][ic] = dMult[TAG::WELL][ic] * stack.m_potDiff + mult * stack.m_dPotDiff[TAG::WELL][ic];
474 
475  }
476  // compute component fluxes
477  for( integer ic = 0; ic < NC; ++ic )
478  {
479  m_compPerfRate[iperf][ic] += m_wellElemCompFrac[iwelem][ic] * flux;
480  for( integer jc = 0; jc < CP_Deriv::nDer; ++jc )
481  {
482  m_dCompPerfRate[iperf][TAG::RES][ic][jc] = m_wellElemCompFrac[iwelem][ic] * dFlux[TAG::RES][jc];
483  }
484  }
485  for( integer ic = 0; ic < NC; ++ic )
486  {
487  m_dCompPerfRate[iperf][TAG::WELL][ic][CP_Deriv::dP] = m_wellElemCompFrac[iwelem][ic] * dFlux[TAG::WELL][CP_Deriv::dP];
488  if constexpr ( IS_THERMAL )
489  {
490  m_dCompPerfRate[iperf][TAG::WELL][ic][CP_Deriv::dT] = m_wellElemCompFrac[iwelem][ic] * dFlux[TAG::WELL][CP_Deriv::dT];
491  }
492  for( integer jc = 0; jc < NC; ++jc )
493  {
494  m_dCompPerfRate[iperf][TAG::WELL][ic][CP_Deriv::dC+jc] += m_wellElemCompFrac[iwelem][ic] * dFlux[TAG::WELL][CP_Deriv::dC+jc];
495  m_dCompPerfRate[iperf][TAG::WELL][ic][CP_Deriv::dC+jc] += m_dWellElemCompFrac_dCompDens[iwelem][ic][jc] * flux;
496  }
497  }
498  if constexpr ( IS_THERMAL )
499  {
500  // Cant have different dispatch functions
501  // so need to have arg list with union of upstream and downstream args, even if some are unused in one of the cases
502  fluxKernelOp( -1, -1, resTotalMob, dResTotalMob );
503  }
504  } // end upstream
505  }
513  template< typename POLICY, typename KERNEL_TYPE >
514  static void
515  launch( localIndex const numElements,
516  KERNEL_TYPE const & kernelComponent )
517  {
519  forAll< POLICY >( numElements, [=] GEOS_HOST_DEVICE ( localIndex const iperf )
520  {
521  typename KERNEL_TYPE::StackVariables stack;
522  // get the index of the reservoir elem
523  localIndex const er = kernelComponent.m_resElementRegion[iperf];
524  localIndex const esr = kernelComponent.m_resElementSubRegion[iperf];
525  localIndex const ei = kernelComponent.m_resElementIndex[iperf];
526  // get the index of the well elem
527  localIndex const iwelem = kernelComponent.m_perfWellElemIndex[iperf];
528 
529  kernelComponent.initialize( iperf, stack );
530  kernelComponent.computePotentialandDeriv( iperf, er, esr, ei, iwelem, stack );
531  kernelComponent.computeFlux( iperf, er, esr, ei, iwelem, stack );
532  } );
533  }
534 
535 
536 protected:
537  ElementViewConst< arrayView1d< real64 const > > const m_resPres;
538  ElementViewConst< arrayView2d< real64 const, compflow::USD_PHASE > > const m_resPhaseVolFrac;
539  ElementViewConst< arrayView3d< real64 const, compflow::USD_PHASE_DC > > const m_dResPhaseVolFrac;
540  ElementViewConst< arrayView3d< real64 const, compflow::USD_COMP_DC > > const m_dResCompFrac_dCompDens;
541  ElementViewConst< arrayView3d< real64 const, constitutive::multifluid::USD_PHASE > > const m_resPhaseDens;
542  ElementViewConst< arrayView4d< real64 const, constitutive::multifluid::USD_PHASE_DC > > const m_dResPhaseDens;
543  ElementViewConst< arrayView3d< real64 const, constitutive::multifluid::USD_PHASE > > const m_resPhaseVisc;
544  ElementViewConst< arrayView4d< real64 const, constitutive::multifluid::USD_PHASE_DC > > const m_dResPhaseVisc;
545  ElementViewConst< arrayView4d< real64 const, constitutive::multifluid::USD_PHASE_COMP > > const m_resPhaseCompFrac;
546  ElementViewConst< arrayView5d< real64 const, constitutive::multifluid::USD_PHASE_COMP_DC > > const m_dResPhaseCompFrac;
547  ElementViewConst< arrayView3d< real64 const, constitutive::relperm::USD_RELPERM > > const m_resPhaseRelPerm;
548  ElementViewConst< arrayView4d< real64 const, constitutive::relperm::USD_RELPERM_DS > > const m_dResPhaseRelPerm_dPhaseVolFrac;
549  arrayView1d< real64 const > const m_wellElemGravCoef;
550  arrayView1d< real64 const > const m_wellElemPres;
551  arrayView2d< real64 const, compflow::USD_COMP > const m_wellElemCompDens;
552  arrayView1d< real64 const > const m_wellElemTotalMassDens;
553  arrayView2d< real64 const, compflow::USD_FLUID_DC > const m_dWellElemTotalMassDens;
554  arrayView2d< real64 const, compflow::USD_COMP > const m_wellElemCompFrac;
555  arrayView3d< real64 const, compflow::USD_COMP_DC > const m_dWellElemCompFrac_dCompDens;
556  arrayView1d< real64 const > const m_perfGravCoef;
557  arrayView1d< localIndex const > const m_perfWellElemIndex;
558  arrayView1d< real64 const > const m_perfTrans;
559  arrayView1d< localIndex const > const m_resElementRegion;
560  arrayView1d< localIndex const > const m_resElementSubRegion;
561  arrayView1d< localIndex const > const m_resElementIndex;
562  arrayView2d< real64 > const m_compPerfRate;
563  arrayView4d< real64 > const m_dCompPerfRate;
564  arrayView3d< real64 > const m_dCompPerfRate_dPres;
565  arrayView4d< real64 > const m_dCompPerfRate_dComp;
566  arrayView1d< integer > const m_perfStatus;
567 
568  bool const m_isInjector;
569  bool const m_isCrossflowEnabled;
570 
571 };
572 
577 {
578 public:
579 
592  template< typename POLICY >
593  static void
594  createAndLaunch( integer const numComp,
595  integer const numPhases,
596  string const flowSolverName,
597  PerforationData * const perforationData,
598  ElementSubRegionBase const & subRegion,
599  ElementRegionManager const & elemManager,
600  bool const isInjector,
601  bool const isCrossflowEnabled )
602  {
603  geos::internal::kernelLaunchSelectorCompPhaseSwitch( numComp, numPhases, [&]( auto NC, auto NP )
604  {
605  integer constexpr NUM_COMP = NC();
606  integer constexpr NUM_PHASE = NP();
607  integer constexpr IS_THERMAL = 0;
608 
610  typename kernelType::CompFlowAccessors compFlowAccessors( elemManager, flowSolverName );
611  typename kernelType::MultiFluidAccessors multiFluidAccessors( elemManager, flowSolverName );
612  typename kernelType::RelPermAccessors relPermAccessors( elemManager, flowSolverName );
613 
614  kernelType kernel( perforationData, subRegion,
615  compFlowAccessors, multiFluidAccessors, relPermAccessors,
616  isInjector, isCrossflowEnabled );
617  kernelType::template launch< POLICY >( perforationData->size(), kernel );
618  } );
619  }
620 };
621 
622 } // end namespace isothermalPerforationFluxKernels
623 
624 namespace thermalPerforationFluxKernels
625 {
626 
627 using namespace constitutive;
628 
629 /******************************** PerforationFluxKernel ********************************/
630 
631 template< integer NC, integer NP, integer IS_THERMAL >
633 {
634 public:
635 
637  using Base::m_dWellElemCompFrac_dCompDens;
638  using Base::m_resPres;
639  using Base::m_resPhaseVolFrac;
640  using Base::m_dResPhaseVolFrac;
641  using Base::m_dResCompFrac_dCompDens;
642  using Base::m_resPhaseDens;
643  using Base::m_dResPhaseDens;
644  using Base::m_resPhaseVisc;
645  using Base::m_dResPhaseVisc;
646  using Base::m_resPhaseCompFrac;
647  using Base::m_dResPhaseCompFrac;
648  using Base::m_resPhaseRelPerm;
649  using Base::m_dResPhaseRelPerm_dPhaseVolFrac;
650  using Base::m_isInjector;
651  using Base::m_isCrossflowEnabled;
652  using Base::m_resElementRegion;
653  using Base::m_resElementSubRegion;
654  using Base::m_resElementIndex;
655  using Base::m_perfWellElemIndex;
656 
658  {
659 public:
663  {}
664  using Base::StackVariables::m_potDiff;
665  using Base::StackVariables::m_dPotDiff;
666  };
668  static constexpr integer numComp = NC;
669 
671  static constexpr integer numPhase = NP;
672 
674  static constexpr integer isThermal = IS_THERMAL;
675 
676  using TAG = typename Base::TAG;
679  using RelPermAccessors = typename Base::RelPermAccessors;
680 
681 
684 
686  StencilMaterialAccessors< MultiFluidBase,
687  fields::multifluid::phaseFraction,
688  fields::multifluid::dPhaseFraction,
689  fields::multifluid::phaseEnthalpy,
690  fields::multifluid::dPhaseEnthalpy >;
691 
699  template< typename VIEWTYPE >
701 
702  PerforationFluxKernel ( PerforationData * const perforationData,
703  ElementSubRegionBase & subRegion,
704  MultiFluidBase const & wellFluid,
705  CompFlowAccessors const & compFlowAccessors,
706  MultiFluidAccessors const & multiFluidAccessors,
707  RelPermAccessors const & relPermAccessors,
708  ThermalCompFlowAccessors const & thermalCompFlowAccessors,
709  ThermalMultiFluidAccessors const & thermalMultiFluidAccessors,
710  bool const isInjector,
711  bool const isCrossflowEnabled )
712  : Base( perforationData,
713  subRegion,
714  compFlowAccessors,
715  multiFluidAccessors,
716  relPermAccessors,
717  isInjector,
718  isCrossflowEnabled ),
719  m_wellElemPhaseVolFrac( subRegion.getField< fields::well::phaseVolumeFraction >() ),
720  m_dWellElemPhaseVolFrac( subRegion.getField< fields::well::dPhaseVolumeFraction >() ),
721  m_wellElemPhaseDensity( wellFluid.phaseDensity() ),
722  m_dWellElemPhaseDensity( wellFluid.dPhaseDensity()),
723  m_wellElemPhaseEnthalpy( wellFluid.phaseEnthalpy()),
724  m_dWellElemPhaseEnthalpy( wellFluid.dPhaseEnthalpy()),
725  m_energyPerfFlux( perforationData->getField< fields::well::energyPerforationFlux >() ),
726  m_dEnergyPerfFlux( perforationData->getField< fields::well::dEnergyPerforationFlux >() ),
727  m_temp( thermalCompFlowAccessors.get( fields::flow::temperature {} ) ),
728  m_resPhaseFraction( thermalMultiFluidAccessors.get( fields::multifluid::phaseFraction {} ) ),
729  m_dResPhaseFraction( thermalMultiFluidAccessors.get( fields::multifluid::dPhaseFraction {} )),
730  m_resPhaseEnthalpy( thermalMultiFluidAccessors.get( fields::multifluid::phaseEnthalpy {} ) ),
731  m_dResPhaseEnthalpy( thermalMultiFluidAccessors.get( fields::multifluid::dPhaseEnthalpy {} ) )
732  {}
733 
734  template< typename FUNC = NoOpFunc >
736  inline
737  void
738  computeFlux( localIndex const iperf, localIndex const er, localIndex const esr, localIndex const ei, localIndex const iwelem, StackVariables & stack ) const
739  {
740  using Deriv = constitutive::multifluid::DerivativeOffset;
741  using CP_Deriv =constitutive::multifluid::DerivativeOffsetC< NC, IS_THERMAL >;
742  // initialize outputs
743  m_energyPerfFlux[iperf]=0;
744  for( integer ke = 0; ke < 2; ++ke )
745  {
746  for( integer i = 0; i < CP_Deriv::nDer; ++i )
747  {
748  m_dEnergyPerfFlux[iperf][ke][i]=0;
749  }
750  }
751  if( stack.m_potDiff >= 0 ) // ** well is downstream **
752  {
753  real64 dEmob[CP_Deriv::nDer]{};
754  Base::computeFlux ( iperf, er, esr, ei, iwelem, stack, [&]( localIndex const ip, real64 const resPhaseVolFrac, real64 const mob, real64 const (&dMob)[CP_Deriv::nDer] )
755  {
756  // enthalpy
757  real64 const resEnthalpy = m_resPhaseEnthalpy[er][esr][ei][0][ip];
758  real64 dResEnthalpy[CP_Deriv::nDer]{};
759  dResEnthalpy[CP_Deriv::dP] = m_dResPhaseEnthalpy[er][esr][ei][0][ip][Deriv::dP];
760  dResEnthalpy[CP_Deriv::dT] = m_dResPhaseEnthalpy[er][esr][ei][0][ip][Deriv::dT];
761 
762  applyChainRule( NC, m_dResCompFrac_dCompDens[er][esr][ei],
763  m_dResPhaseEnthalpy[er][esr][ei][0][ip],
764  &dResEnthalpy[CP_Deriv::dC],
765  Deriv::dC );
766  for( integer jc = 0; jc < CP_Deriv::nDer; ++jc )
767  {
768  dEmob[jc] = dMob[jc] * m_resPhaseEnthalpy[er][esr][ei][0][ip] + mob * dResEnthalpy[jc];
769  }
770  real64 resPhaseMobE = mob * resEnthalpy;
771  real64 eflux = resPhaseMobE * stack.m_potDiff;
772  real64 dEFlux[2][CP_Deriv::nDer]{};
773  dEFlux[TAG::WELL][CP_Deriv::dP] = resPhaseMobE * stack.m_dPotDiff[TAG::WELL][CP_Deriv::dP];
774  dEFlux[TAG::WELL][CP_Deriv::dT] = resPhaseMobE * stack.m_dPotDiff[TAG::WELL][CP_Deriv::dT];
775  // Handles all dependencies
776  for( integer jc = 0; jc < CP_Deriv::nDer; ++jc )
777  {
778  dEFlux[TAG::RES][jc] = dEmob[jc] * stack.m_potDiff + resPhaseMobE * stack.m_dPotDiff[TAG::RES][jc];
779  m_dEnergyPerfFlux[iperf][TAG::WELL][jc] = resPhaseMobE * stack.m_dPotDiff[TAG::WELL][jc];
780  }
781  m_energyPerfFlux[iperf] += eflux;
782  // energy equation derivatives WRT res P & T
783  m_dEnergyPerfFlux[iperf][TAG::RES][CP_Deriv::dP] += dEFlux[TAG::RES][CP_Deriv::dP] * resPhaseVolFrac +
784  eflux * m_dResPhaseFraction[er][esr][ei][0][ip][Deriv::dP];
785  m_dEnergyPerfFlux[iperf][TAG::RES][CP_Deriv::dT] += dEFlux[TAG::RES][CP_Deriv::dT] * resPhaseVolFrac +
786  eflux *m_dResPhaseFraction[er][esr][ei][0][ip][Deriv::dT];
787  real64 dProp_dC[numComp]{};
788  applyChainRule( NC,
789  m_dResCompFrac_dCompDens[er][esr][ei],
790  m_dResPhaseFraction[er][esr][ei][0][ip],
791  dProp_dC,
792  Deriv::dC );
793  for( integer jc = 0; jc < NC; ++jc )
794  {
795  m_dEnergyPerfFlux[iperf][TAG::RES][CP_Deriv::dC+jc] += dEFlux[TAG::RES][CP_Deriv::dC+jc];
796  }
797  } );
798  }
799  else // ** well element is upstream **
800  {
801  Base::computeFlux ( iperf, er, esr, ei, iwelem, stack, [&]( localIndex const null1, real64 const null2, real64 const mob, real64 const (&dMob)[CP_Deriv::nDer] )
802  {
803  GEOS_UNUSED_VAR( null1 );
804  GEOS_UNUSED_VAR( null2 );
805  real64 dMult[CP_Deriv::nDer]{};
806  real64 dProp_dC[NC]{};
807  real64 totalEnthalpy=0;
808 
809  arraySlice1d< real64 const, compflow::USD_PHASE - 1 > phaseVolFrac = m_wellElemPhaseVolFrac[iwelem];
810  arraySlice2d< real64 const, compflow::USD_PHASE_DC - 1 > dPhaseVolFrac = m_dWellElemPhaseVolFrac[iwelem];
811  arraySlice1d< real64 const, constitutive::multifluid::USD_PHASE - 2 > phaseDens = m_wellElemPhaseDensity[iwelem][0];
812  arraySlice2d< real64 const, constitutive::multifluid::USD_PHASE_DC - 2 > dPhaseDens = m_dWellElemPhaseDensity[iwelem][0];
813  arraySlice1d< real64 const, constitutive::multifluid::USD_PHASE - 2 > phaseEnthalpy = m_wellElemPhaseEnthalpy[iwelem][0];
814  arraySlice2d< real64 const, constitutive::multifluid::USD_PHASE_DC - 2 > dPhaseEnthalpy = m_dWellElemPhaseEnthalpy[iwelem][0];
815  // Compute total enthalpy in the well element and its derivatives, then use it to compute energy flux and derivatives
816  for( integer iphase = 0; iphase < NP; ++iphase )
817  {
818  bool const phaseExists = (phaseVolFrac[iphase] > 0);
819  if( !phaseExists || (!m_isInjector && !m_isCrossflowEnabled) )
820  {
821  continue;
822  }
823  totalEnthalpy += phaseEnthalpy[iphase] * phaseVolFrac[iphase] * phaseDens[iphase];
824  dMult[CP_Deriv::dP] += phaseEnthalpy[iphase] * dPhaseVolFrac[iphase][Deriv::dP] * phaseDens[iphase] +
825  dPhaseEnthalpy[iphase][Deriv::dP] * phaseVolFrac[iphase] * phaseDens[iphase] +
826  phaseEnthalpy[iphase] * phaseVolFrac[iphase] * dPhaseDens[iphase][Deriv::dP];
827  dMult[CP_Deriv::dT ] += phaseEnthalpy[iphase] * dPhaseVolFrac[iphase][Deriv::dT] * phaseDens[iphase] +
828  dPhaseEnthalpy[iphase][Deriv::dT] *phaseVolFrac[iphase] * phaseDens[iphase]+
829  phaseEnthalpy[iphase] * phaseVolFrac[iphase] * dPhaseDens[iphase][Deriv::dT];
830 
831  for( integer jc = 0; jc < NC; ++jc )
832  {
833  dProp_dC[jc] += phaseVolFrac[iphase] * phaseDens[iphase] * dPhaseEnthalpy[iphase][Deriv::dC+jc]
834  + phaseVolFrac[iphase] * dPhaseDens[iphase][Deriv::dC+jc] * phaseEnthalpy[iphase];
835  dMult[CP_Deriv::dC+jc] += phaseEnthalpy[iphase] * phaseDens[iphase] * dPhaseVolFrac[iphase][Deriv::dC+jc];
836  }
837  }
838 
839  real64 dProp_dD[numComp]{};
840  applyChainRule( NC,
841  m_dWellElemCompFrac_dCompDens[iwelem],
842  dProp_dC,
843  dProp_dD,
844  0 );
845  for( integer iphase=0; iphase < NP; ++iphase )
846  {
847  for( integer jc = 0; jc < NC; ++jc )
848  {
849  dMult[CP_Deriv::dC+jc] += phaseVolFrac[iphase] * phaseDens[iphase] * dProp_dD[jc]
850  + phaseEnthalpy[iphase] * phaseVolFrac[iphase] * dProp_dD[jc];
851  }
852  }
853 
854  real64 eflux = mob * totalEnthalpy*stack.m_potDiff;
855  m_energyPerfFlux[iperf] = eflux;
856  for( integer jc = 0; jc < CP_Deriv::nDer; ++jc )
857  {
858  m_dEnergyPerfFlux[iperf][TAG::WELL][jc] = mob* dMult[jc]*stack.m_potDiff
859  + mob* totalEnthalpy * stack.m_dPotDiff[TAG::WELL][jc];
860  m_dEnergyPerfFlux[iperf][TAG::RES][jc] = dMob[jc]*totalEnthalpy*stack.m_potDiff
861  + mob* totalEnthalpy * stack.m_dPotDiff[TAG::RES][jc];
862  }
863 
864  } );
865  }
866  }
875  template< typename POLICY, typename KERNEL_TYPE >
876  static void
877  launch( localIndex const numElements,
878  KERNEL_TYPE const & kernelComponent )
879  {
881  forAll< POLICY >( numElements, [=] GEOS_HOST_DEVICE ( localIndex const iperf )
882  {
883  typename KERNEL_TYPE::StackVariables stack;
884  // get the index of the reservoir elem
885  localIndex const er = kernelComponent.m_resElementRegion[iperf];
886  localIndex const esr = kernelComponent.m_resElementSubRegion[iperf];
887  localIndex const ei = kernelComponent.m_resElementIndex[iperf];
888  // get the index of the well elem
889  localIndex const iwelem = kernelComponent.m_perfWellElemIndex[iperf];
890  kernelComponent.initialize( iperf, stack );
891  kernelComponent.computePotentialandDeriv( iperf, er, esr, ei, iwelem, stack );
892  kernelComponent.computeFlux( iperf, er, esr, ei, iwelem, stack );
893  } );
894  }
895 
896 protected:
897 
899 
901  arrayView3d< real64 const, compflow::USD_PHASE_DC > const m_dWellElemPhaseVolFrac;
902 
903  arrayView3d< real64 const, multifluid::USD_PHASE > const m_wellElemPhaseDensity;
904  arrayView4d< real64 const, multifluid::USD_PHASE_DC > const m_dWellElemPhaseDensity;
905  arrayView3d< real64 const, multifluid::USD_PHASE > const m_wellElemPhaseEnthalpy;
906  arrayView4d< real64 const, multifluid::USD_PHASE_DC > const m_dWellElemPhaseEnthalpy;
907 
910  arrayView3d< real64 > const m_dEnergyPerfFlux;
911 
914 
920 
921 
922 };
923 
928 {
929 public:
930 
944  template< typename POLICY >
945  static void
946  createAndLaunch( integer const numComp,
947  integer const numPhases,
948  string const flowSolverName,
949  PerforationData * const perforationData,
950  ElementSubRegionBase & subRegion,
951  MultiFluidBase const & fluid,
952  ElementRegionManager const & elemManager,
953  bool const isInjector,
954  bool const isCrossflowEnabled )
955  {
956  geos::internal::kernelLaunchSelectorCompPhaseSwitch( numComp, numPhases, [&]( auto NC, auto NP )
957  {
958  integer constexpr NUM_COMP = NC();
959  integer constexpr NUM_PHASE = NP();
960  integer constexpr IS_THERMAL = 1;
961 
963  typename kernelType::CompFlowAccessors compFlowAccessors( elemManager, flowSolverName );
964  typename kernelType::MultiFluidAccessors multiFluidAccessors( elemManager, flowSolverName );
965  typename kernelType::RelPermAccessors relPermAccessors( elemManager, flowSolverName );
966  typename kernelType::ThermalCompFlowAccessors thermalCompFlowAccessors( elemManager, flowSolverName );
967  typename kernelType::ThermalMultiFluidAccessors thermalMultiFluidAccessors( elemManager, flowSolverName );
968 
969  kernelType kernel( perforationData, subRegion, fluid, compFlowAccessors, multiFluidAccessors,
970  relPermAccessors, thermalCompFlowAccessors, thermalMultiFluidAccessors,
971  isInjector, isCrossflowEnabled );
972  kernelType::template launch< POLICY >( perforationData->size(), kernel );
973  } );
974  }
975 };
976 
977 } // end namespace thermalPerforationFluxKernels
978 
979 } // end namespace geos
980 
981 #endif //GEOS_PHYSICSSOLVERS_FLUIDFLOW_WELLS_PERFORATIONFLUXLKERNELS_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.
#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...
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.
localIndex size() const
Get the "size" of the group, which determines the number of elements in resizable wrappers.
Definition: Group.hpp:1315
static void createAndLaunch(integer const numComp, integer const numPhases, string const flowSolverName, PerforationData *const perforationData, ElementSubRegionBase const &subRegion, ElementRegionManager const &elemManager, bool const isInjector, bool const isCrossflowEnabled)
Create a new kernel and launch.
static constexpr integer numComp
Compile time value for the number of components.
static constexpr integer numPhase
Compile time value for the number of phases.
static constexpr integer isThermal
Compile time value for thermal option.
static void launch(localIndex const numElements, KERNEL_TYPE const &kernelComponent)
Performs the kernel launch.
ElementRegionManager::ElementViewConst< VIEWTYPE > ElementViewConst
The type for element-based non-constitutive data parameters. Consists entirely of ArrayView's.
static void createAndLaunch(integer const numComp, integer const numPhases, string const flowSolverName, PerforationData *const perforationData, ElementSubRegionBase &subRegion, MultiFluidBase const &fluid, ElementRegionManager const &elemManager, bool const isInjector, bool const isCrossflowEnabled)
Create a new kernel and launch.
arrayView1d< real64 > const m_energyPerfFlux
Views on energy flux.
arrayView2d< real64 const, compflow::USD_PHASE > const m_wellElemPhaseVolFrac
Views on well element properties.
ElementRegionManager::ElementViewConst< VIEWTYPE > ElementViewConst
The type for element-based non-constitutive data parameters. Consists entirely of ArrayView's.
ElementViewConst< arrayView3d< real64 const, multifluid::USD_PHASE > > const m_resPhaseFraction
Views on phase enthalpies.
ElementViewConst< arrayView1d< real64 const > > const m_temp
Views on temperature.
static void launch(localIndex const numElements, KERNEL_TYPE const &kernelComponent)
Performs the kernel launch.
ArrayView< T, 1 > arrayView1d
Alias for 1D array view.
Definition: DataTypes.hpp:179
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
ArrayView< T, 4, USD > arrayView4d
Alias for 4D array view.
Definition: DataTypes.hpp:227
ArrayView< T, 2, USD > arrayView2d
Alias for 2D array view.
Definition: DataTypes.hpp:195
int integer
Signed integer type.
Definition: DataTypes.hpp:81
ArrayView< T, 3, USD > arrayView3d
Alias for 3D array view.
Definition: DataTypes.hpp:211
Kernel variables (dof numbers, jacobian and residual) located on the stack.