GEOS
CompositionalMultiphaseWellKernels.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_COMPOSITIONALMULTIPHASEWELLKERNELS_HPP
21 #define GEOS_PHYSICSSOLVERS_FLUIDFLOW_WELLS_COMPOSITIONALMULTIPHASEWELLKERNELS_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"
32 #include "mesh/WellElementSubRegion.hpp"
41 #include "physicsSolvers/fluidFlow/wells/WellControls.hpp"
43 #include "physicsSolvers/fluidFlow/wells/WellPhaseVolumeRateConstraint.hpp"
44 
45 namespace geos
46 {
47 
48 
49 namespace compositionalMultiphaseWellKernels
50 {
51 
52 static constexpr real64 minDensForDivision = 1e-10;
53 
54 // tag to access well and reservoir elements in perforation rates computation
56 {
57  static constexpr integer RES = 0;
58  static constexpr integer WELL = 1;
59 };
60 
61 // tag to access the next and current well elements of a connection
62 struct ElemTag
63 {
64  static constexpr integer CURRENT = 0;
65  static constexpr integer NEXT = 1;
66 };
67 
68 // define the column offset of the derivatives
69 struct ColOffset
70 {
71  static constexpr integer DPRES = 0;
72  static constexpr integer DCOMP = 1;
73 };
74 
75 template< integer NC, integer IS_THERMAL >
77 
78 template< integer NC >
79 struct ColOffset_WellJac< NC, 0 >
80 {
81  static constexpr integer dP = 0;
82  static constexpr integer dC = 1;
83  static constexpr integer dQ = dC + NC;
84  static integer constexpr nDer = dQ + 1;
85 
86 };
87 
88 template< integer NC >
89 struct ColOffset_WellJac< NC, 1 >
90 {
91  static constexpr integer dP = 0;
92  static constexpr integer dC = 1;
93  static constexpr integer dQ = dC + NC;
94  static constexpr integer dT = dQ+1;
96  static integer constexpr nDer = dT + 1;
97 };
98 
99 // define the row offset of the residual equations
100 struct RowOffset
101 {
102  static constexpr integer CONTROL = 0;
103  static constexpr integer MASSBAL = 1;
104 };
105 
106 template< integer NC, integer IS_THERMAL >
108 
109 template< integer NC >
110 struct RowOffset_WellJac< NC, 0 >
111 {
112  static constexpr integer CONTROL = 0;
113  static constexpr integer MASSBAL = 1;
114  static constexpr integer VOLBAL = MASSBAL + NC;
115  static constexpr integer nEqn = VOLBAL+1;
116 };
117 
118 template< integer NC >
119 struct RowOffset_WellJac< NC, 1 >
120 {
121  static constexpr integer CONTROL = 0;
122  static constexpr integer MASSBAL = 1;
123  static constexpr integer VOLBAL = MASSBAL + NC;
124  static constexpr integer ENERGYBAL = VOLBAL+1;
125  static constexpr integer nEqn = ENERGYBAL+1;
126 
127 };
128 /******************************** ControlEquationHelper ********************************/
130 {
133 
135  inline
136  static
137  void
138  selectLimitingConstraint( bool const isProducer,
139  ConstraintTypeId const & inputControl,
140  ConstraintTypeId const & currentControl,
141  integer const phasePhaseIndex,
142  real64 const & targetBHP,
143  real64 const & targetPhaseRate,
144  real64 const & targetTotalRate,
145  real64 const & targetMassRate,
146  real64 const & currentBHP,
147  arrayView1d< real64 const > const & currentPhaseVolRate,
148  real64 const & currentTotalVolRate,
149  real64 const & currentMassRate,
150  ConstraintTypeId & newControl );
151 
152  template< integer NC, integer IS_THERMAL >
154  inline
155  static void
156  compute( globalIndex const rankOffset,
157  ConstraintTypeId const currentControl,
158  integer const targetPhaseIndex,
159  real64 const & targetBHP,
160  real64 const & targetPhaseRate,
161  real64 const & targetTotalRate,
162  real64 const & targetMassRate,
163  real64 const & currentBHP,
164  real64 const & targetValue,
165  arrayView1d< real64 const > const & dCurrentBHP,
166  arrayView1d< real64 const > const & currentPhaseVolRate,
167  arrayView2d< real64 const > const & dCurrentPhaseVolRate,
168  real64 const & currentTotalVolRate,
169  arrayView1d< real64 const > const & dCurrentTotalVolRate,
170  real64 const & massDensity,
171  globalIndex const dofNumber,
172  CRSMatrixView< real64, globalIndex const > const & localMatrix,
173  arrayView1d< real64 > const & localRhs );
174 
175 };
176 
177 /******************************** PressureRelationKernel ********************************/
178 
180 {
181  using Deriv = constitutive::multifluid::DerivativeOffset;
185 
186  template< integer NC, integer IS_THERMAL >
188  inline
189  static void
190  compute( real64 const & gravCoef,
191  real64 const & gravCoefNext,
192  real64 const & pres,
193  real64 const & presNext,
194  real64 const & totalMassDens,
195  real64 const & totalMassDensNext,
198  real64 & localPresRel,
199  real64 ( &localPresRelJacobian )[2*(NC+1+IS_THERMAL)] );
200 
201  template< integer NC, integer IS_THERMAL >
202  static void
203  launch( localIndex const size,
204  globalIndex const rankOffset,
205  arrayView1d< integer const > const elemStatus,
206  arrayView1d< globalIndex const > const & wellElemDofNumber,
207  arrayView1d< real64 const > const & wellElemGravCoef,
208  arrayView1d< localIndex const > const & nextWellElemIndex,
209  arrayView1d< real64 const > const & wellElemPressure,
210  arrayView1d< real64 const > const & wellElemTotalMassDens,
211  arrayView2d< real64 const, compflow::USD_FLUID_DC > const & dWellElemTotalMassDens,
212  bool & controlHasSwitched,
213  CRSMatrixView< real64, globalIndex const > const & localMatrix,
214  arrayView1d< real64 > const & localRhs );
215 
216 };
217 
218 /******************************** VolumeBalanceKernel ********************************/
219 
221 {
222 
225 
226  template< integer NC >
228  inline
229  static void
230  compute( integer const numPhases,
231  real64 const & volume,
234  real64 & localVolBalance,
235  real64 ( &localVolBalanceJacobian )[NC+1] );
236 
237  template< integer NC >
238  static void
239  launch( localIndex const size,
240  integer const numPhases,
241  globalIndex const rankOffset,
242  arrayView1d< globalIndex const > const & wellElemDofNumber,
243  arrayView1d< integer const > const & wellElemGhostRank,
244  arrayView2d< real64 const, compflow::USD_PHASE > const & wellElemPhaseVolFrac,
245  arrayView3d< real64 const, compflow::USD_PHASE_DC > const & dWellElemPhaseVolFrac,
246  arrayView1d< real64 const > const & wellElemVolume,
247  CRSMatrixView< real64, globalIndex const > const & localMatrix,
248  arrayView1d< real64 > const & localRhs );
249 
250 };
251 
252 /******************************** PresTempCompFracInitializationKernel ********************************/
253 
255 {
256 
257  using CompFlowAccessors =
258  StencilAccessors< fields::flow::pressure,
259  fields::flow::temperature,
260  fields::flow::globalCompDensity,
261  fields::flow::phaseVolumeFraction >;
262 
263  using MultiFluidAccessors =
264  StencilMaterialAccessors< constitutive::MultiFluidBase,
265  fields::multifluid::phaseMassDensity >;
266 
267 
275  template< typename VIEWTYPE >
277 
278  static void
279  launch( localIndex const perforationSize,
280  localIndex const subRegionSize,
281  integer const numComponents,
282  integer const numPhases,
283  WellControls const & wellControls,
284  real64 const & refWellElemGravCoef,
285  real64 const & currentTime,
291  arrayView1d< localIndex const > const & resElementRegion,
292  arrayView1d< localIndex const > const & resElementSubRegion,
293  arrayView1d< localIndex const > const & resElementIndex,
294  arrayView1d< real64 const > const & perfGravCoef,
295  arrayView1d< integer const > const & perfState,
296  arrayView1d< real64 const > const & wellElemGravCoef,
297  arrayView1d< real64 > const & wellElemPres,
298  arrayView1d< real64 > const & wellElemTemp,
299  arrayView2d< real64, compflow::USD_COMP > const & wellElemCompFrac );
300 
301 };
302 
303 /******************************** CompDensInitializationKernel ********************************/
304 
306 {
307 
308  static void
309  launch( localIndex const subRegionSize,
310  integer const numComponents,
311  arrayView2d< real64 const, compflow::USD_COMP > const & wellElemCompFrac,
313  arrayView2d< real64, compflow::USD_COMP > const & wellElemCompDens );
314 
315 };
316 
317 /******************************** RateInitializationKernel ********************************/
318 
320 {
321 
322  static void
323  launch( localIndex const subRegionSize,
324  WellControls const & wellControls,
325  real64 const & currentTime,
328  arrayView1d< real64 > const & connRate );
329 
330 };
331 
332 
333 /******************************** TotalMassDensityKernel ****************************/
334 
341 template< integer NUM_COMP, integer NUM_PHASE >
343 {
344 public:
345 
347  using Base::numComp;
348 
350  static constexpr integer numPhase = NUM_PHASE;
351 
358  constitutive::MultiFluidBase const & fluid )
359  : Base(),
360  m_phaseVolFrac( subRegion.getField< fields::well::phaseVolumeFraction >() ),
361  m_dPhaseVolFrac( subRegion.getField< fields::well::dPhaseVolumeFraction >() ),
362  m_dCompFrac_dCompDens( subRegion.getField< fields::well::dGlobalCompFraction_dGlobalCompDensity >() ),
363  m_phaseMassDens( fluid.phaseMassDensity() ),
364  m_dPhaseMassDens( fluid.dPhaseMassDensity() ),
365  m_totalMassDens( subRegion.getField< fields::well::totalMassDensity >() ),
366  m_dTotalMassDens( subRegion.getField< fields::well::dTotalMassDensity >() )
367  {}
368 
375  template< typename FUNC = NoOpFunc >
377  inline
378  void compute( localIndex const ei,
379  FUNC && totalMassDensityKernelOp = NoOpFunc{} ) const
380  {
381  using Deriv = constitutive::multifluid::DerivativeOffset;
382 
383  arraySlice1d< real64 const, compflow::USD_PHASE - 1 > phaseVolFrac = m_phaseVolFrac[ei];
384  arraySlice2d< real64 const, compflow::USD_PHASE_DC - 1 > dPhaseVolFrac = m_dPhaseVolFrac[ei];
385  arraySlice2d< real64 const, compflow::USD_COMP_DC - 1 > dCompFrac_dCompDens = m_dCompFrac_dCompDens[ei];
386  arraySlice1d< real64 const, constitutive::multifluid::USD_PHASE - 2 > phaseMassDens = m_phaseMassDens[ei][0];
387  arraySlice2d< real64 const, constitutive::multifluid::USD_PHASE_DC - 2 > dPhaseMassDens = m_dPhaseMassDens[ei][0];
388  real64 & totalMassDens = m_totalMassDens[ei];
389  arraySlice1d< real64, compflow::USD_FLUID_DC - 1 > dTotalMassDens = m_dTotalMassDens[ei];
390 
391  real64 dMassDens_dC[numComp]{};
392 
393  totalMassDens = 0.0;
394 
395  dTotalMassDens[Deriv::dP]=0.0;
396  for( integer ic = 0; ic < numComp; ++ic )
397  {
398  dTotalMassDens[Deriv::dC+ic]=0.0;
399  }
400 
401  for( integer ip = 0; ip < numPhase; ++ip )
402  {
403  totalMassDens += phaseVolFrac[ip] * phaseMassDens[ip];
404  dTotalMassDens[Deriv::dP] += dPhaseVolFrac[ip][Deriv::dP] * phaseMassDens[ip] + phaseVolFrac[ip] * dPhaseMassDens[ip][Deriv::dP];
405 
406  applyChainRule( numComp, dCompFrac_dCompDens, dPhaseMassDens[ip], dMassDens_dC, Deriv::dC );
407  for( integer ic = 0; ic < numComp; ++ic )
408  {
409  dTotalMassDens[Deriv::dC+ic] += dPhaseVolFrac[ip][Deriv::dC+ic] * phaseMassDens[ip]
410  + phaseVolFrac[ip] * dMassDens_dC[ic];
411  }
412 
413  totalMassDensityKernelOp( ip ); //, phaseVolFrac, dTotalMassDens_dPres, dTotalMassDens_dCompDens );
414  }
415 
416  }
417 
418 protected:
419 
420  // inputs
421 
426 
430 
431  // outputs
432 
436 
437 
438 };
439 
444 {
445 public:
446 
455  template< typename POLICY >
456  static void
457  createAndLaunch( integer const numComp,
458  integer const numPhase,
459  ObjectManagerBase & subRegion,
460  constitutive::MultiFluidBase const & fluid )
461  {
462  if( numPhase == 2 )
463  {
464  isothermalCompositionalMultiphaseBaseKernels::internal::kernelLaunchSelectorCompSwitch( numComp, [&] ( auto NC )
465  {
466  integer constexpr NUM_COMP = NC();
467  TotalMassDensityKernel< NUM_COMP, 2 > kernel( subRegion, fluid );
468  TotalMassDensityKernel< NUM_COMP, 2 >::template launch< POLICY >( subRegion.size(), kernel );
469  } );
470  }
471  else if( numPhase == 3 )
472  {
473  isothermalCompositionalMultiphaseBaseKernels::internal::kernelLaunchSelectorCompSwitch( numComp, [&] ( auto NC )
474  {
475  integer constexpr NUM_COMP = NC();
476  TotalMassDensityKernel< NUM_COMP, 3 > kernel( subRegion, fluid );
477  TotalMassDensityKernel< NUM_COMP, 3 >::template launch< POLICY >( subRegion.size(), kernel );
478  } );
479  }
480  }
481 };
482 
483 
484 /******************************** ResidualNormKernel ********************************/
485 
490 {
491 public:
492 
494  using Base::m_minNormalizer;
495  using Base::m_rankOffset;
496  using Base::m_localResidual;
497  using Base::m_dofNumber;
498 
499  ResidualNormKernel( globalIndex const rankOffset,
500  arrayView1d< real64 const > const & localResidual,
501  arrayView1d< globalIndex const > const & dofNumber,
503  integer const numComp,
504  integer const numDof,
505  WellElementSubRegion const & subRegion,
506  constitutive::MultiFluidBase const & fluid,
507  WellControls const & wellControls,
508  real64 const time,
509  real64 const dt,
510  real64 const minNormalizer )
511  : Base( rankOffset,
512  localResidual,
513  dofNumber,
514  ghostRank,
515  minNormalizer ),
516  m_numComp( numComp ),
517  m_numDof( numDof ),
518  m_dt( dt ),
519  m_isLocallyOwned( subRegion.isLocallyOwned() ),
521  m_isProducer( wellControls.isProducer() ),
522  m_currentControl( wellControls.getControl() ),
523  m_targetBHP( wellControls.getTargetBHP( time ) ),
524  m_volume( subRegion.getElementVolume() ),
525  m_phaseDens_n( fluid.phaseDensity_n() ),
526  m_totalDens_n( fluid.totalDensity_n() )
527  {
528  // Note this assumes that there is only one rate constraint
529  // This is a normalizer for the balance equations. The normalizaer should be the current rate not the constraint value!!
530  // This is one of the reasons for restricting constraint type for a production well
531  // Another pr will remove fix this (so the cause for difference results is isolated to one change)
532  auto const * rateConstraint = wellControls.getRateConstraints().front();
533  if( rateConstraint != nullptr )
534  {
535  m_constraintValue = rateConstraint->getConstraintValue( time );
536  }
537  if( m_isProducer )
538  {
540  }
541  else
542  {
543  m_targetPhaseIndex = -1;
544  }
545  }
546 
548  virtual void computeLinf( localIndex const iwelem,
549  LinfStackVariables & stack ) const override
550  {
552 
553  real64 normalizer = 0.0;
554  for( integer idof = 0; idof < m_numDof; ++idof )
555  {
556 
557  // Step 1: compute a normalizer for the control or pressure equation
558 
559  // for the control equation, we distinguish two cases
560  if( idof == ROFFSET::CONTROL )
561  {
562 
563  // for the top well element, normalize using the current control
564  if( m_isLocallyOwned && iwelem == m_iwelemControl )
565  {
567  {
568  // the residual entry is in pressure units
569  normalizer = m_targetBHP;
570  }
572  {
573  // the residual entry is in volume / time units
574  normalizer = LvArray::math::max( LvArray::math::abs( m_constraintValue ), m_minNormalizer );
575  }
577  {
578  // the residual entry is in volume / time units
579  normalizer = LvArray::math::max( LvArray::math::abs( m_constraintValue ), m_minNormalizer );
580  }
582  {
583  // the residual entry is in volume / time units
584  normalizer = LvArray::math::max( LvArray::math::abs( m_constraintValue ), m_minNormalizer );
585  }
586  }
587  // for the pressure difference equation, always normalize by the BHP
588  else
589  {
590  normalizer = m_targetBHP;
591  }
592  }
593  // Step 2: compute a normalizer for the mass balance equations
594  else if( idof >= ROFFSET::MASSBAL && idof < ROFFSET::MASSBAL + m_numComp )
595  {
596  if( m_isProducer ) // only PHASEVOLRATE is supported for now
597  {
598  // the residual is in mass units
599  normalizer = m_dt * LvArray::math::abs( m_constraintValue ) * m_phaseDens_n[iwelem][0][m_targetPhaseIndex];
600  }
601  else // Type::INJECTOR, only TOTALVOLRATE is supported for now
602  {
604  {
605  normalizer = m_dt * LvArray::math::abs( m_constraintValue );
606  }
607  else
608  {
609  // the residual is in mass units
610  normalizer = m_dt * LvArray::math::abs( m_constraintValue ) * m_totalDens_n[iwelem][0];
611  }
612 
613  }
614 
615  // to make sure that everything still works well if the rate is zero, we add this check
616  normalizer = LvArray::math::max( normalizer, m_volume[iwelem] * m_totalDens_n[iwelem][0] );
617  }
618  // Step 3: compute a normalizer for the volume balance equations
619  else if( idof == ROFFSET::MASSBAL + m_numComp )
620  {
621  if( m_isProducer ) // only PHASEVOLRATE is supported for now
622  {
623  // the residual is in volume units
624  normalizer = m_dt * LvArray::math::abs( m_constraintValue );
625  }
626  else // Type::INJECTOR, only TOTALVOLRATE is supported for now
627  {
629  {
630  normalizer = m_dt * LvArray::math::abs( m_constraintValue/ m_totalDens_n[iwelem][0] );
631  }
632  else
633  {
634  normalizer = m_dt * LvArray::math::abs( m_constraintValue );
635  }
636 
637  }
638 
639  }
640 
641  // to make sure that everything still works well if the rate is zero, we add this check
642  normalizer = LvArray::math::max( normalizer, m_volume[iwelem] );
643 
644  // Step 4: compute the contribution to the residual
645  real64 const val = LvArray::math::abs( m_localResidual[stack.localRow + idof] ) / normalizer;
646  if( val > stack.localValue[0] )
647  {
648  stack.localValue[0] = val;
649  }
650  }
651  }
652 
654  virtual void computeL2( localIndex const iwelem,
655  L2StackVariables & stack ) const override
656  {
657  GEOS_UNUSED_VAR( iwelem, stack );
658  GEOS_ERROR( "The L2 norm is not implemented for CompositionalMultiphaseWell" );
659  }
660 
661 
662 protected:
663 
666 
669 
672 
674  real64 const m_dt;
675 
677  bool const m_isLocallyOwned;
678 
681 
683  bool const m_isProducer;
684 
687  real64 m_constraintValue;
688  real64 m_targetBHP;
689 
690 
693 
697 
698 };
699 
704 {
705 public:
706 
722  template< typename POLICY >
723  static void
724  createAndLaunch( integer const numComp,
725  integer const numDof,
726  globalIndex const rankOffset,
727  string const & dofKey,
728  arrayView1d< real64 const > const & localResidual,
729  WellElementSubRegion const & subRegion,
730  constitutive::MultiFluidBase const & fluid,
731  WellControls const & wellControls,
732  real64 const time,
733  real64 const dt,
734  real64 const minNormalizer,
735  real64 (& residualNorm)[1] )
736  {
737  arrayView1d< globalIndex const > const dofNumber = subRegion.getReference< array1d< globalIndex > >( dofKey );
738  arrayView1d< integer const > const ghostRank = subRegion.ghostRank();
739 
740  ResidualNormKernel kernel( rankOffset, localResidual, dofNumber, ghostRank,
741  numComp, numDof, subRegion, fluid, wellControls, time, dt, minNormalizer );
742  ResidualNormKernel::launchLinf< POLICY >( subRegion.size(), kernel, residualNorm );
743  }
744 
745 };
746 
747 /******************************** SolutionScalingKernel ********************************/
748 
753 {
754 public:
755 
769  template< typename POLICY >
771  createAndLaunch( real64 const maxRelativePresChange,
772  real64 const maxAbsolutePresChange,
773  real64 const maxCompFracChange,
774  real64 const maxRelativeCompDensChange,
775  globalIndex const rankOffset,
776  integer const numComp,
777  string const dofKey,
778  ElementSubRegionBase & subRegion,
779  arrayView1d< real64 const > const localSolution )
780  {
781  arrayView1d< real64 const > const pressure =
782  subRegion.getField< fields::well::pressure >();
784  subRegion.getField< fields::well::globalCompDensity >();
785  arrayView1d< real64 > pressureScalingFactor =
786  subRegion.getField< fields::well::pressureScalingFactor >();
787  arrayView1d< real64 > compDensScalingFactor =
788  subRegion.getField< fields::well::globalCompDensityScalingFactor >();
789  isothermalCompositionalMultiphaseBaseKernels::
790  SolutionScalingKernel kernel( maxRelativePresChange, maxAbsolutePresChange, maxCompFracChange, maxRelativeCompDensChange, rankOffset,
791  numComp, dofKey, subRegion, localSolution, pressure, compDens, pressureScalingFactor, compDensScalingFactor );
792  return isothermalCompositionalMultiphaseBaseKernels::
793  SolutionScalingKernel::
794  launch< POLICY >( subRegion.size(), kernel );
795  }
796 
797 };
798 
799 /******************************** ElementBasedAssemblyKernel ********************************/
800 
807 template< integer NUM_COMP, integer IS_THERMAL >
809 {
810 public:
813 
814  // Well jacobian column and row indicies
815  using FLUID_PROP_COFFSET = constitutive::multifluid::DerivativeOffsetC< NUM_COMP, IS_THERMAL >;
819  static constexpr integer numComp = NUM_COMP;
820 
822  static constexpr integer numDof = NUM_COMP + 1 + IS_THERMAL;
823 
825  static constexpr integer numEqn = NUM_COMP + 1 + IS_THERMAL;
826 
827 
840  integer const thermalEffectsEnabled,
841  integer const isProducer,
842  globalIndex const rankOffset,
843  string const dofKey,
844  WellElementSubRegion const & subRegion,
845  constitutive::MultiFluidBase const & fluid,
846  CRSMatrixView< real64, globalIndex const > const & localMatrix,
847  arrayView1d< real64 > const & localRhs,
848  BitFlags< isothermalCompositionalMultiphaseBaseKernels::KernelFlags > const kernelFlags )
849  : m_numPhases( numPhases ),
850  m_thermalEffectsEnabled( thermalEffectsEnabled ),
851  m_isProducer( isProducer ),
852  m_rankOffset( rankOffset ),
853  m_iwelemControl( subRegion.getTopWellElementIndex() ),
854  m_dofNumber( subRegion.getReference< array1d< globalIndex > >( dofKey ) ),
855  m_elemGhostRank( subRegion.ghostRank() ),
856  m_elemStatus( subRegion.getLocalWellElementStatus() ),
857  m_volume( subRegion.getElementVolume() ),
858  m_dCompFrac_dCompDens( subRegion.getField< fields::flow::dGlobalCompFraction_dGlobalCompDensity >() ),
859  m_phaseVolFrac_n( subRegion.getField< fields::flow::phaseVolumeFraction_n >() ),
860  m_phaseVolFrac( subRegion.getField< fields::flow::phaseVolumeFraction >() ),
861  m_dPhaseVolFrac( subRegion.getField< fields::flow::dPhaseVolumeFraction >() ),
862  m_phaseDens_n( fluid.phaseDensity_n() ),
863  m_phaseDens( fluid.phaseDensity() ),
864  m_dPhaseDens( fluid.dPhaseDensity() ),
865  m_phaseCompFrac_n( fluid.phaseCompFraction_n() ),
866  m_phaseCompFrac( fluid.phaseCompFraction() ),
867  m_dPhaseCompFrac( fluid.dPhaseCompFraction() ),
868  m_compDens( subRegion.getField< fields::flow::globalCompDensity >() ),
869  m_compDens_n( subRegion.getField< fields::flow::globalCompDensity_n >() ),
870  m_localMatrix( localMatrix ),
871  m_localRhs( localRhs ),
872  m_kernelFlags( kernelFlags )
873  {}
874 
880  {
881 public:
882 
883  // volume information (used by both accumulation and volume balance)
884  real64 volume = 0.0;
885 
886  // Residual information
887 
890 
892  globalIndex dofIndices[numDof]{}; // NC compdens + P + thermal
893  globalIndex eqnRowIndices[numDof]{};
894  globalIndex dofColIndices[numDof]{};
895 
898 
901 
902  };
903 
910  bool skipElement( localIndex const ei ) const
911  {
912  return ( m_elemGhostRank( ei ) >= 0 || m_elemStatus[ei]==WellElementSubRegion::WellElemStatus::CLOSED );
913  }
914 
921  void setup( localIndex const ei,
922  StackVariables & stack ) const
923  {
924  // initialize the volume
925  stack.volume = m_volume[ei];
926 
927  // Note row/col indices needed to be consistent with layout of stack.localJacobian
928  // Setup row equation indices for this element ( mass + vol + thermal if valid)
929 
930  // 1) Mass Balance
931  for( integer ic = 0; ic < numComp; ++ic )
932  {
933  stack.eqnRowIndices[ic] = m_dofNumber[ei] + WJ_ROFFSET::MASSBAL + ic - m_rankOffset;
934  }
935 // 2) Volume Balance
936  stack.eqnRowIndices[numComp] = m_dofNumber[ei] + WJ_ROFFSET::VOLBAL - m_rankOffset;
937  // 3) Energy Balance
938  if constexpr ( IS_THERMAL )
939  {
940  stack.eqnRowIndices[numComp+1] = m_dofNumber[ei] + WJ_ROFFSET::ENERGYBAL - m_rankOffset;
941  }
942  // Setup equation column indices for this element ( P + COMPDENS + THERMAL if valid)
943  stack.dofColIndices[0] = m_dofNumber[ei] + WJ_COFFSET::dP;
944  for( integer ic = 0; ic < numComp; ++ic )
945  {
946  stack.dofColIndices[ic+1] = m_dofNumber[ei] + WJ_COFFSET::dC+ic;
947  }
948  if constexpr ( IS_THERMAL )
949  {
950  stack.dofColIndices[numComp+1] = m_dofNumber[ei] + WJ_COFFSET::dT;
951  }
952  for( integer jc = 0; jc < numEqn; ++jc )
953  {
954  stack.localResidual[jc] = 0.0;
955  for( integer ic = 0; ic < numDof; ++ic )
956  {
957  stack.localJacobian[jc][ic] = 0.0;
958  }
959  }
960  }
968  template< typename FUNC = NoOpFunc >
971  StackVariables & stack,
972  FUNC && phaseAmountKernelOp = NoOpFunc{} ) const
973  {
974 
975  using Deriv = constitutive::multifluid::DerivativeOffset;
976 
977  // construct the slices for variables accessed multiple times
978  arraySlice2d< real64 const, compflow::USD_COMP_DC - 1 > dCompFrac_dCompDens = m_dCompFrac_dCompDens[ei];
979 
980  arraySlice1d< real64 const, compflow::USD_PHASE - 1 > phaseVolFrac_n = m_phaseVolFrac_n[ei];
981  arraySlice1d< real64 const, compflow::USD_PHASE - 1 > phaseVolFrac = m_phaseVolFrac[ei];
982  arraySlice2d< real64 const, compflow::USD_PHASE_DC - 1 > dPhaseVolFrac = m_dPhaseVolFrac[ei];
983 
984  arraySlice1d< real64 const, constitutive::multifluid::USD_PHASE - 2 > phaseDens_n = m_phaseDens_n[ei][0];
985  arraySlice1d< real64 const, constitutive::multifluid::USD_PHASE - 2 > phaseDens = m_phaseDens[ei][0];
986  arraySlice2d< real64 const, constitutive::multifluid::USD_PHASE_DC - 2 > dPhaseDens = m_dPhaseDens[ei][0];
987 
988  arraySlice2d< real64 const, constitutive::multifluid::USD_PHASE_COMP - 2 > phaseCompFrac_n = m_phaseCompFrac_n[ei][0];
989  arraySlice2d< real64 const, constitutive::multifluid::USD_PHASE_COMP - 2 > phaseCompFrac = m_phaseCompFrac[ei][0];
990  arraySlice3d< real64 const, constitutive::multifluid::USD_PHASE_COMP_DC - 2 > dPhaseCompFrac = m_dPhaseCompFrac[ei][0];
991 
992  // temporary work arrays
993  real64 dPhaseAmount[FLUID_PROP_COFFSET::nDer]{};
994  real64 dPhaseAmount_dC[numComp]{};
995  real64 dPhaseCompFrac_dC[numComp]{};
996 
997  // sum contributions to component accumulation from each phase
998  for( integer ip = 0; ip < m_numPhases; ++ip )
999  {
1000  real64 const phaseAmount = stack.volume * phaseVolFrac[ip] * phaseDens[ip];
1001  real64 const phaseAmount_n = stack.volume * phaseVolFrac_n[ip] * phaseDens_n[ip];
1002 
1003  dPhaseAmount[FLUID_PROP_COFFSET::dP]=stack.volume * ( dPhaseVolFrac[ip][Deriv::dP] * phaseDens[ip]
1004  + phaseVolFrac[ip] * dPhaseDens[ip][Deriv::dP] );
1005 
1006  // assemble density dependence
1007  applyChainRule( numComp, dCompFrac_dCompDens, dPhaseDens[ip], dPhaseAmount_dC, Deriv::dC );
1008  applyChainRule( numComp, dCompFrac_dCompDens, dPhaseDens[ip], &dPhaseAmount[FLUID_PROP_COFFSET::dC], Deriv::dC );
1009  for( integer jc = 0; jc < numComp; ++jc )
1010  {
1011  dPhaseAmount_dC[jc] = dPhaseAmount_dC[jc] * phaseVolFrac[ip]
1012  + phaseDens[ip] * dPhaseVolFrac[ip][Deriv::dC+jc];
1013  dPhaseAmount_dC[jc] *= stack.volume;
1014  dPhaseAmount[FLUID_PROP_COFFSET::dC+jc] = dPhaseAmount[FLUID_PROP_COFFSET::dC+jc] * phaseVolFrac[ip]
1015  + phaseDens[ip] * dPhaseVolFrac[ip][Deriv::dC+jc];
1016  dPhaseAmount[FLUID_PROP_COFFSET::dC+jc] *= stack.volume;
1017  }
1018  // ic - index of component whose conservation equation is assembled
1019  // (i.e. row number in local matrix)
1020  for( integer ic = 0; ic < numComp; ++ic )
1021  {
1022  real64 const phaseCompAmount = phaseAmount * phaseCompFrac[ip][ic];
1023  real64 const phaseCompAmount_n = phaseAmount_n * phaseCompFrac_n[ip][ic];
1024 
1025  real64 const dPhaseCompAmount_dP = dPhaseAmount[FLUID_PROP_COFFSET::dP] * phaseCompFrac[ip][ic]
1026  + phaseAmount * dPhaseCompFrac[ip][ic][Deriv::dP];
1027 
1028  stack.localResidual[ic] += phaseCompAmount - phaseCompAmount_n;
1029  stack.localJacobian[ic][0] += dPhaseCompAmount_dP;
1030 
1031  // jc - index of component w.r.t. whose compositional var the derivative is being taken
1032  // (i.e. col number in local matrix)
1033 
1034  // assemble phase composition dependence
1035  applyChainRule( numComp, dCompFrac_dCompDens, dPhaseCompFrac[ip][ic], dPhaseCompFrac_dC, Deriv::dC );
1036  for( integer jc = 0; jc < numComp; ++jc )
1037  {
1038  real64 const dPhaseCompAmount_dC = dPhaseCompFrac_dC[jc] * phaseAmount
1039  + phaseCompFrac[ip][ic] * dPhaseAmount[FLUID_PROP_COFFSET::dC+jc];
1040 
1041  stack.localJacobian[ic][jc + 1] += dPhaseCompAmount_dC;
1042  }
1043  }
1044  if constexpr ( IS_THERMAL )
1045  {
1046  dPhaseAmount[FLUID_PROP_COFFSET::dT] = stack.volume * (dPhaseVolFrac[ip][Deriv::dT] * phaseDens[ip] + phaseVolFrac[ip] * dPhaseDens[ip][Deriv::dT] );
1047  for( integer ic = 0; ic < numComp; ++ic )
1048  {
1049  // assemble the derivatives of the component mass balance equations with respect to temperature
1050  stack.localJacobian[ic][numComp+1] += dPhaseAmount[FLUID_PROP_COFFSET::dT] * phaseCompFrac[ip][ic]
1051  + phaseAmount * dPhaseCompFrac[ip][ic][Deriv::dT];
1052  }
1053  }
1054  // call the lambda in the phase loop to allow the reuse of the phase amounts and their derivatives
1055  // possible use: assemble accumulation term of the energy equation for this phase
1056  phaseAmountKernelOp( ip, phaseAmount, phaseAmount_n, dPhaseAmount );
1057 
1058  }
1059 
1060  // check zero diagonal (works only in debug)
1061  /*
1062  for( integer ic = 0; ic < numComp; ++ic )
1063  {
1064  GEOS_ASSERT_MSG ( LvArray::math::abs( stack.localJacobian[ic][ic] ) > minDensForDivision,
1065  GEOS_FMT( "Zero diagonal in Jacobian: equation {}, value = {}", ic, stack.localJacobian[ic][ic] ) );
1066  }
1067  */
1068  }
1069 
1070 
1081  StackVariables & stack ) const
1082  {
1083  using Deriv = constitutive::multifluid::DerivativeOffset;
1084 
1085  arraySlice1d< real64 const, compflow::USD_PHASE - 1 > phaseVolFrac = m_phaseVolFrac[ei];
1086  arraySlice2d< real64 const, compflow::USD_PHASE_DC - 1 > dPhaseVolFrac = m_dPhaseVolFrac[ei];
1087 
1088  real64 oneMinusPhaseVolFracSum = 1.0;
1089 
1090  // sum contributions to component accumulation from each phase
1091 // Note localJacobian stores equation balances in order of component/vol/enerqy
1092  // These are mapped to solver orderings with indicies setup in stack variables
1093  for( integer ip = 0; ip < m_numPhases; ++ip )
1094  {
1095  oneMinusPhaseVolFracSum -= phaseVolFrac[ip];
1096  stack.localJacobian[numComp][0] -= dPhaseVolFrac[ip][Deriv::dP];
1097 
1098  for( integer jc = 0; jc < numComp; ++jc )
1099  {
1100  stack.localJacobian[numComp][jc+1] -= dPhaseVolFrac[ip][Deriv::dC+jc];
1101  }
1102 
1103  if constexpr ( IS_THERMAL)
1104  {
1105  stack.localJacobian[numComp][numComp+1] -= dPhaseVolFrac[ip][Deriv::dT];
1106  }
1107 
1108  }
1109  // scale saturation-based volume balance by pore volume (for better scaling w.r.t. other equations)
1110  stack.localResidual[numComp] = stack.volume * oneMinusPhaseVolFracSum;
1111  for( integer idof = 0; idof < numComp+1+IS_THERMAL; ++idof )
1112  {
1113  stack.localJacobian[numComp][idof] *= stack.volume;
1114  }
1115  }
1116 
1123  void complete( localIndex const ei, //GEOS_UNUSED_PARAM( ei ),
1124  StackVariables & stack ) const
1125  {
1126  using namespace compositionalMultiphaseUtilities;
1127 
1128  integer const numRows = numComp+1+ IS_THERMAL;
1129 
1130  if constexpr ( IS_THERMAL)
1131  {
1133  {
1134  for( integer i=0; i < numComp+1+IS_THERMAL; i++ )
1135  {
1136  stack.localJacobian[numRows-1][i] = 0.0;
1137  }
1138  // constant Temperature
1139  for( integer i=0; i < numComp+1+IS_THERMAL; i++ )
1140  stack.localJacobian[i][numRows-1] = 0.0;
1141  stack.localJacobian[numRows-1][numRows-1] = 1.0;
1142 
1143  stack.localResidual[numRows-1]=0.0;
1144  }
1145  else if( ei == m_iwelemControl && !m_isProducer )
1146  {
1147  // For top segment energy balance eqn replaced with T(n+1) - T = 0
1148  // No other energy balance derivatives
1149  // Assumption is global index == 0 is top segment with fixed temp BC
1150 
1151  for( integer i=0; i < numComp+1+IS_THERMAL; i++ )
1152  {
1153  stack.localJacobian[numRows-1][i] = 0.0;
1154  }
1155  // constant Temperature
1156  for( integer i=0; i < numComp+1+IS_THERMAL; i++ )
1157  stack.localJacobian[i][numRows-1] = 0.0;
1158  stack.localJacobian[numRows-1][numRows-1] = 1.0;
1159 
1160  stack.localResidual[numRows-1]=0.0;
1161  }
1162  }
1163 
1164  if( m_kernelFlags.isSet( isothermalCompositionalMultiphaseBaseKernels::KernelFlags::TotalMassEquation ) )
1165  {
1166  // apply equation/variable change transformation to the component mass balance equations
1167  real64 work[numComp + 1 + IS_THERMAL]{};
1168  shiftRowsAheadByOneAndReplaceFirstRowWithColumnSum( numComp, numComp+1+ IS_THERMAL, stack.localJacobian, work );
1169  shiftElementsAheadByOneAndReplaceFirstElementWithSum( numComp, stack.localResidual );
1170  }
1171 
1172  // add contribution to residual and jacobian into:
1173  // - the component mass balance equations (i = 0 to i = numComp-1)
1174  // - the volume balance equations (i = numComp)
1175  // note that numDof includes derivatives wrt temperature if this class is derived in ThermalKernels
1176 
1177  for( integer i = 0; i < numRows; ++i )
1178  {
1179  m_localRhs[stack.eqnRowIndices[i]] += stack.localResidual[i];
1180  m_localMatrix.addToRow< serialAtomic >( stack.eqnRowIndices[i],
1181  stack.dofColIndices,
1182  stack.localJacobian[i],
1183  numComp+1+ IS_THERMAL );
1184  }
1185 
1186  }
1187 
1195  template< typename POLICY, typename KERNEL_TYPE >
1196  static void
1197  launch( localIndex const numElems,
1198  KERNEL_TYPE const & kernelComponent )
1199  {
1201  forAll< POLICY >( numElems, [=] GEOS_HOST_DEVICE ( localIndex const ei )
1202  {
1203  if( kernelComponent.skipElement( ei ) )
1204  {
1205  return;
1206  }
1207 
1208  typename KERNEL_TYPE::StackVariables stack;
1209 
1210  kernelComponent.setup( ei, stack );
1211  kernelComponent.computeAccumulation( ei, stack );
1212  kernelComponent.computeVolumeBalance( ei, stack );
1213  kernelComponent.complete( ei, stack );
1214  } );
1215  }
1216 
1217 protected:
1218 
1221 
1226 
1229 
1232 
1235 
1238 
1241 
1244 
1247  arrayView2d< real64 const > const m_porosity;
1248  arrayView2d< real64 const > const m_dPoro_dPres;
1249 
1252 
1257 
1262 
1267 
1268  // Views on component densities
1271 
1276 
1277  BitFlags< isothermalCompositionalMultiphaseBaseKernels::KernelFlags > const m_kernelFlags;
1278 };
1279 
1280 
1285 {
1286 public:
1299  template< typename POLICY >
1300  static void
1301  createAndLaunch( localIndex const numComps,
1302  localIndex const numPhases,
1303  integer const & thermalEffectsEnabled,
1304  integer const isProducer,
1305  globalIndex const rankOffset,
1306  BitFlags< isothermalCompositionalMultiphaseBaseKernels::KernelFlags > kernelFlags,
1307  string const dofKey,
1308  WellElementSubRegion const & subRegion,
1309  constitutive::MultiFluidBase const & fluid,
1310  CRSMatrixView< real64, globalIndex const > const & localMatrix,
1311  arrayView1d< real64 > const & localRhs )
1312  {
1313  geos::internal::kernelLaunchSelectorCompThermSwitch( numComps, 0, [&]( auto NC, auto IS_THERMAL )
1314  {
1315  localIndex constexpr NUM_COMP = NC();
1316 
1317  integer constexpr istherm = IS_THERMAL();
1318 
1320  kernel( numPhases, thermalEffectsEnabled, isProducer, rankOffset, dofKey, subRegion, fluid, localMatrix, localRhs, kernelFlags );
1322  launch< POLICY, ElementBasedAssemblyKernel< NUM_COMP, istherm > >( subRegion.size(), kernel );
1323  } );
1324  }
1325 };
1334 template< integer NC, integer IS_THERMAL >
1336 {
1337 public:
1338 
1342 
1343  using FLUID_PROP_COFFSET = constitutive::multifluid::DerivativeOffsetC< NC, IS_THERMAL >;
1346 
1347  using CP_Deriv = constitutive::multifluid::DerivativeOffsetC< NC, IS_THERMAL >;
1349  static constexpr integer numComp = NC;
1350 
1352  static constexpr integer numDof = WJ_COFFSET::nDer;
1353 
1355  static constexpr integer numEqn = NC;
1356 
1357  static constexpr integer maxNumElems = 2;
1358  static constexpr integer maxStencilSize = 2;
1374  globalIndex const rankOffset,
1375  string const wellDofKey,
1376  WellControls const & wellControls,
1377  WellElementSubRegion const & subRegion,
1378  CRSMatrixView< real64, globalIndex const > const & localMatrix,
1379  arrayView1d< real64 > const & localRhs,
1380  BitFlags< isothermalCompositionalMultiphaseBaseKernels::KernelFlags > kernelFlags )
1381  :
1382  m_dt( dt ),
1383  m_rankOffset( rankOffset ),
1384  m_wellElemDofNumber ( subRegion.getReference< array1d< globalIndex > >( wellDofKey ) ),
1385  m_nextWellElemIndex ( subRegion.getReference< array1d< localIndex > >( WellElementSubRegion::viewKeyStruct::nextWellElementIndexString()) ),
1386  m_elemStatus( subRegion.getLocalWellElementStatus() ),
1387  m_connRate ( subRegion.getField< fields::well::connectionRate >() ),
1388  m_wellElemCompFrac ( subRegion.getField< fields::well::globalCompFraction >() ),
1389  m_dWellElemCompFrac_dCompDens ( subRegion.getField< fields::well::dGlobalCompFraction_dGlobalCompDensity >() ),
1390  m_localMatrix( localMatrix ),
1391  m_localRhs ( localRhs ),
1392  m_useTotalMassEquation ( kernelFlags.isSet( isothermalCompositionalMultiphaseBaseKernels::KernelFlags::TotalMassEquation ) ),
1393  m_isProducer ( wellControls.isProducer() ),
1394  m_injection ( wellControls.getInjectionStream() )
1395  {}
1396 
1398  {
1399 public:
1400 
1408  : stencilSize( size ),
1409  numConnectedElems( 2 ),
1410  dofColIndices( size * numDof )
1411  {}
1412 
1413  // Stencil information
1414  localIndex const stencilSize;
1417 
1418 
1419  // edge indexes
1420  localIndex iwelemUp;
1421  localIndex iwelemNext;
1422  localIndex iwelemCurrent;
1423  globalIndex offsetUp;
1424  globalIndex offsetCurrent;
1425  globalIndex offsetNext;
1426  // Local degrees of freedom and local residual/jacobian
1427 
1430 
1437  };
1438 
1439 
1441  bool skipElement( localIndex const ei ) const
1442  {
1443  return ( m_elemStatus[ei]==WellElementSubRegion::WellElemStatus::CLOSED );
1444  }
1445 
1452  inline
1453  void setup( localIndex const iconn,
1454  StackVariables & stack ) const
1455  {
1456  stack.numConnectedElems=2;
1457  if( m_nextWellElemIndex[iconn] <0 )
1458  {
1459  stack.numConnectedElems = 1;
1460  }
1461 
1462  stack.localFlux.resize( stack.numConnectedElems*numEqn );
1463  stack.localFluxJacobian.resize( stack.numConnectedElems * numEqn, stack.stencilSize * numDof );
1464  stack.localFluxJacobian_dQ.resize( stack.numConnectedElems * numEqn, 1 );
1465 
1466  }
1467 
1474  inline
1475  void complete( localIndex const iconn,
1476  StackVariables & stack ) const
1477  {
1478  GEOS_UNUSED_VAR( iconn );
1479  using namespace compositionalMultiphaseUtilities;
1480  if( stack.numConnectedElems ==1 )
1481  {
1482  // Setup Jacobian global row indicies
1483  // equations for COMPONENT + ENERGY balances
1484  globalIndex oneSidedEqnRowIndices[numEqn]{};
1485  for( integer ic = 0; ic < NC; ++ic )
1486  {
1487  oneSidedEqnRowIndices[ic] = stack.offsetUp + WJ_ROFFSET::MASSBAL + ic - m_rankOffset;
1488  }
1489 
1490  // Setup Jacobian global col indicies ( Mapping from local jac order to well jac order)
1491  globalIndex oneSidedDofColIndices_dPresCompTempUp[CP_Deriv::nDer]{};
1492  globalIndex oneSidedDofColIndices_dRate = stack.offsetCurrent + WJ_COFFSET::dQ;
1493  // Note localFluxJacobian cols are stored using CP_Deriv order (dP dC or dP dT dC)
1494  int ioff=0;
1495  oneSidedDofColIndices_dPresCompTempUp[ioff++] = stack.offsetUp + WJ_COFFSET::dP;
1496 
1497  if constexpr ( IS_THERMAL )
1498  {
1499  oneSidedDofColIndices_dPresCompTempUp[ioff++] = stack.offsetUp + WJ_COFFSET::dT;
1500  }
1501  for( integer jdof = 0; jdof < NC; ++jdof )
1502  {
1503  oneSidedDofColIndices_dPresCompTempUp[ioff++] = stack.offsetUp + WJ_COFFSET::dC+ jdof;
1504  }
1505  if( m_useTotalMassEquation > 0 )
1506  {
1507  // Apply equation/variable change transformation(s)
1508  real64 work[CP_Deriv::nDer]{};
1509  shiftRowsAheadByOneAndReplaceFirstRowWithColumnSum( numEqn, 1, stack.localFluxJacobian_dQ, work );
1510  shiftRowsAheadByOneAndReplaceFirstRowWithColumnSum( numEqn, CP_Deriv::nDer, stack.localFluxJacobian, work );
1511  shiftElementsAheadByOneAndReplaceFirstElementWithSum( numEqn, stack.localFlux );
1512  }
1513  for( integer i = 0; i < numEqn; ++i )
1514  {
1515  if( oneSidedEqnRowIndices[i] >= 0 && oneSidedEqnRowIndices[i] < m_localMatrix.numRows() )
1516  {
1517  m_localMatrix.addToRow< parallelDeviceAtomic >( oneSidedEqnRowIndices[i],
1518  &oneSidedDofColIndices_dRate,
1519  stack.localFluxJacobian_dQ[i],
1520  1 );
1521  m_localMatrix.addToRowBinarySearchUnsorted< parallelDeviceAtomic >( oneSidedEqnRowIndices[i],
1522  oneSidedDofColIndices_dPresCompTempUp,
1523  stack.localFluxJacobian[i],
1524  CP_Deriv::nDer );
1525  RAJA::atomicAdd( parallelDeviceAtomic{}, &m_localRhs[oneSidedEqnRowIndices[i]], stack.localFlux[i] );
1526  }
1527  }
1528  }
1529  else
1530  {
1531  // Setup Jacobian global row indicies
1532  // equations for COMPONENT + ENERGY balances
1533  globalIndex eqnRowIndices[2*numEqn]{};
1534 
1535  for( integer ic = 0; ic < NC; ++ic )
1536  {
1537  // mass balance equations for all components
1538  eqnRowIndices[TAG::NEXT *numEqn+ic] = stack.offsetNext + WJ_ROFFSET::MASSBAL + ic - m_rankOffset;
1539  eqnRowIndices[TAG::CURRENT *numEqn+ic] = stack.offsetCurrent + WJ_ROFFSET::MASSBAL + ic - m_rankOffset;
1540  }
1541 
1542  // Setup Jacobian global col indicies ( Mapping from local jac order to well jac order)
1543  globalIndex dofColIndices_dPresCompUp[CP_Deriv::nDer]{};
1544  globalIndex dofColIndices_dRate = stack.offsetCurrent + WJ_COFFSET::dQ;
1545 
1546  int ioff=0;
1547  // Indice storage order reflects local jac col storage order CP::Deriv order P T DENS
1548  dofColIndices_dPresCompUp[ioff++] = stack.offsetUp + WJ_COFFSET::dP;
1549 
1550  if constexpr ( IS_THERMAL )
1551  {
1552  dofColIndices_dPresCompUp[ioff++] = stack.offsetUp + WJ_COFFSET::dT;
1553  }
1554  for( integer jdof = 0; jdof < NC; ++jdof )
1555  {
1556  dofColIndices_dPresCompUp[ioff++] = stack.offsetUp + WJ_COFFSET::dC+ jdof;
1557  }
1558 
1559 
1560  if( m_useTotalMassEquation > 0 )
1561  {
1562  // Apply equation/variable change transformation(s)
1563  real64 work[CP_Deriv::nDer]{};
1564  shiftBlockRowsAheadByOneAndReplaceFirstRowWithColumnSum( numEqn, numEqn, 1, 2, stack.localFluxJacobian_dQ, work );
1565  shiftBlockRowsAheadByOneAndReplaceFirstRowWithColumnSum( numEqn, numEqn, CP_Deriv::nDer, 2, stack.localFluxJacobian, work );
1566  shiftBlockElementsAheadByOneAndReplaceFirstElementWithSum( numEqn, numEqn, 2, stack.localFlux );
1567  }
1568  // Note this updates diag and offdiag
1569  for( integer i = 0; i < 2*NC; ++i )
1570  {
1571  if( eqnRowIndices[i] >= 0 && eqnRowIndices[i] < m_localMatrix.numRows() )
1572  {
1573  m_localMatrix.addToRow< parallelDeviceAtomic >( eqnRowIndices[i],
1574  &dofColIndices_dRate,
1575  stack.localFluxJacobian_dQ[i],
1576  1 );
1577  m_localMatrix.addToRowBinarySearchUnsorted< parallelDeviceAtomic >( eqnRowIndices[i],
1578  dofColIndices_dPresCompUp,
1579  stack.localFluxJacobian[i],
1580  CP_Deriv::nDer );
1581  RAJA::atomicAdd( parallelDeviceAtomic{}, &m_localRhs[eqnRowIndices[i]], stack.localFlux[i] );
1582 
1583  }
1584  }
1585  }
1586  }
1587 
1589  inline
1590  void
1591  computeExit( real64 const & dt,
1592  real64 const ( &compFlux )[NC ],
1593  StackVariables & stack,
1594  real64 ( & dCompFlux)[NC][numDof] ) const
1595  {
1596  for( integer ic = 0; ic < NC; ++ic )
1597  {
1598  stack.localFlux[ic] = -dt * compFlux[ic];
1599  // derivative with respect to rate
1600  stack.localFluxJacobian_dQ[ic][0] = -dt * dCompFlux[ic][WJ_COFFSET::dQ];
1601  // derivative with respect to upstream pressure
1602  stack.localFluxJacobian[ic][CP_Deriv::dP] = -dt * dCompFlux[ic][WJ_COFFSET::dP];
1603  // derivatives with respect to upstream component densities
1604  for( integer jdof = 0; jdof < NC; ++jdof )
1605  {
1606  stack.localFluxJacobian[ic][CP_Deriv::dC+jdof] = -dt * dCompFlux[ic][WJ_COFFSET::dC+jdof];
1607  }
1608  if constexpr ( IS_THERMAL )
1609  {
1610  stack.localFluxJacobian[ic][CP_Deriv::dT] = -dt * dCompFlux[ic][WJ_COFFSET::dT];
1611  }
1612  }
1613  }
1614 
1616  inline
1617  void
1618  compute( real64 const & dt,
1619  real64 const ( &compFlux )[NC ],
1620  StackVariables & stack,
1621  real64 ( & dCompFlux)[(NC )][numDof] ) const
1622  {
1623  // flux terms
1624  for( integer ic = 0; ic < NC; ++ic )
1625  {
1626  stack.localFlux[TAG::NEXT * NC +ic] = dt * compFlux[ic];
1627  stack.localFlux[TAG::CURRENT * NC +ic] = -dt * compFlux[ic];
1628  // derivative with respect to rate
1629  stack.localFluxJacobian_dQ[TAG::NEXT * NC+ ic][0] = dt * dCompFlux[ic][WJ_COFFSET::dQ];
1630  stack.localFluxJacobian_dQ[TAG::CURRENT * NC + +ic][0] = -dt * dCompFlux[ic][WJ_COFFSET::dQ];
1631 
1632  // derivative with respect to upstream pressure
1633  stack.localFluxJacobian[TAG::NEXT * NC +ic][CP_Deriv::dP] = dt * dCompFlux[ic][WJ_COFFSET::dP];
1634  stack.localFluxJacobian[TAG::CURRENT * NC+ ic][CP_Deriv::dP] = -dt * dCompFlux[ic][WJ_COFFSET::dP];
1635 
1636  if constexpr ( IS_THERMAL )
1637  {
1638  stack.localFluxJacobian[TAG::NEXT * NC +ic][CP_Deriv::dT] = dt * dCompFlux[ic][WJ_COFFSET::dT];
1639  stack.localFluxJacobian[TAG::CURRENT * NC +ic][CP_Deriv::dT] = -dt * dCompFlux[ic][WJ_COFFSET::dT];
1640  }
1641 
1642  // derivatives with respect to upstream component densities
1643  for( integer jdof = 0; jdof < NC; ++jdof )
1644  {
1645  stack.localFluxJacobian[TAG::NEXT * NC +ic][CP_Deriv::dC+jdof] = dt * dCompFlux[ic][WJ_COFFSET::dC+jdof];
1646  stack.localFluxJacobian[TAG::CURRENT * NC +ic][CP_Deriv::dC+jdof] = -dt * dCompFlux[ic][WJ_COFFSET::dC+jdof];
1647  }
1648  }
1649  }
1650 
1658  template< typename FUNC = NoOpFunc >
1660  inline
1661  void computeFlux( localIndex const iwelem,
1662  StackVariables & stack,
1663  FUNC && compFluxKernelOp = NoOpFunc{} ) const
1664  {
1665 
1666  using namespace compositionalMultiphaseUtilities;
1667 
1668  // create local work arrays
1669  real64 compFracUp[NC]{};
1670  real64 compFlux[NC]{};
1671  real64 dComp[NC][NC];
1672  real64 dCompFlux[NC][numDof]{};
1673  for( integer ic = 0; ic < NC; ++ic )
1674  {
1675  for( integer jc = 0; jc < NC; ++jc )
1676  {
1677  dComp[ic][jc]=0.0;
1678  }
1679  }
1680  // Step 1) decide the upwind well element
1681 
1682  /* currentConnRate < 0 flow from iwelem to iwelemNext
1683  * currentConnRate > 0 flow from iwelemNext to iwelem
1684  * With this convention, currentConnRate < 0 at the last connection for a producer
1685  * currentConnRate > 0 at the last connection for a injector
1686  */
1687 
1688  localIndex iwelemNext = m_nextWellElemIndex[iwelem];
1689 
1690  // Current element is open and next element is closed => no dependency on next segment
1691  if( iwelemNext >= 0 )
1692  {
1693  if( m_elemStatus[iwelemNext]==WellElementSubRegion::WellElemStatus::CLOSED )
1694  {
1695  iwelemNext = -1;
1696  }
1697  }
1698 
1699  real64 const currentConnRate = m_connRate[iwelem];
1700  localIndex iwelemUp = -1;
1701  if( iwelemNext < 0 && !m_isProducer ) // exit connection, injector
1702  {
1703  // we still need to define iwelemUp for Jacobian assembly
1704  iwelemUp = iwelem;
1705 
1706  // just copy the injection stream into compFrac
1707  for( integer ic = 0; ic < NC; ++ic )
1708  {
1709  compFracUp[ic] = m_injection[ic];
1710  for( integer jc = 0; jc < NC; ++jc )
1711  {
1712  dComp[ic][jc] = m_dWellElemCompFrac_dCompDens[iwelemUp][ic][jc];
1713  }
1714  for( integer jc = 0; jc < NC; ++jc )
1715  {
1716  dCompFlux[ic][WJ_COFFSET::dC+jc] = 0.0;
1717  }
1718  }
1719  }
1720  else
1721  {
1722  // first set iwelemUp to the upstream cell
1723  if( ( iwelemNext < 0 && m_isProducer ) // exit connection, producer
1724  || currentConnRate < 0 ) // not an exit connection, iwelem is upstream
1725  {
1726  iwelemUp = iwelem;
1727  }
1728  else // not an exit connection, iwelemNext is upstream
1729  {
1730  iwelemUp = iwelemNext;
1731  }
1732 
1733  // copy the vars of iwelemUp into compFrac
1734  for( integer ic = 0; ic < NC; ++ic )
1735  {
1736  compFracUp[ic] = m_wellElemCompFrac[iwelemUp][ic];
1737  for( integer jc = 0; jc < NC; ++jc )
1738  {
1739  dCompFlux[ic][WJ_COFFSET::dC+jc] = m_dWellElemCompFrac_dCompDens[iwelemUp][ic][jc];
1740  dComp[ic][jc] = m_dWellElemCompFrac_dCompDens[iwelemUp][ic][jc];
1741  }
1742  }
1743  }
1744 
1745  // Step 2) compute upstream transport coefficient
1746 
1747  for( integer ic = 0; ic < NC; ++ic )
1748  {
1749  compFlux[ic] = compFracUp[ic] * currentConnRate;
1750  dCompFlux[ic][WJ_COFFSET::dQ] = compFracUp[ic];
1751  // none of these quantities depend on pressure
1752  dCompFlux[ic][WJ_COFFSET::dP] = 0.0;
1753  if constexpr ( IS_THERMAL )
1754  {
1755  dCompFlux[ic][WJ_COFFSET::dT] = 0.0;
1756  }
1757  for( integer jc = 0; jc < NC; ++jc )
1758  {
1759  dCompFlux[ic][WJ_COFFSET::dC+jc] = dCompFlux[ic][WJ_COFFSET::dC+jc] * currentConnRate;
1760  }
1761  }
1762 
1763  stack.offsetUp = m_wellElemDofNumber[iwelemUp];
1764  stack.iwelemUp = iwelemUp;
1765  stack.offsetCurrent = m_wellElemDofNumber[iwelem];
1766  stack.iwelemCurrent= iwelem;
1767 
1768 
1769  if( iwelemNext < 0 ) // exit connection
1770  {
1771  // for this case, we only need NC mass conservation equations
1772  computeExit ( m_dt,
1773  compFlux,
1774  stack,
1775  dCompFlux );
1776 
1777  }
1778  else // not an exit connection
1779  {
1780  compute( m_dt,
1781  compFlux,
1782  stack,
1783  dCompFlux
1784  );
1785  stack.offsetNext = m_wellElemDofNumber[iwelemNext];
1786  }
1787  stack.iwelemNext = iwelemNext;
1788  compFluxKernelOp( iwelemNext, iwelemUp, currentConnRate, dComp );
1789  }
1790 
1791 
1799  template< typename POLICY, typename KERNEL_TYPE >
1800  static void
1801  launch( localIndex const numElements,
1802  KERNEL_TYPE const & kernelComponent )
1803  {
1805  forAll< POLICY >( numElements, [=] GEOS_HOST_DEVICE ( localIndex const ie )
1806  {
1807  typename KERNEL_TYPE::StackVariables stack( 1 );
1808  if( kernelComponent.skipElement( ie ))
1809  {
1810  return;
1811  }
1812  kernelComponent.setup( ie, stack );
1813  kernelComponent.computeFlux( ie, stack );
1814  kernelComponent.complete( ie, stack );
1815  } );
1816  }
1817 
1818 protected:
1820  real64 const m_dt;
1823 
1828 
1831 
1834 
1835 
1840 
1845 
1848 
1850  bool const m_isProducer;
1851 
1854 
1855 
1856 };
1857 
1862 {
1863 public:
1864 
1878  template< typename POLICY >
1879  static void
1880  createAndLaunch( integer const numComps,
1881  real64 const dt,
1882  globalIndex const rankOffset,
1883  BitFlags< isothermalCompositionalMultiphaseBaseKernels::KernelFlags > kernelFlags,
1884  string const dofKey,
1885  WellControls const & wellControls,
1886  WellElementSubRegion const & subRegion,
1887  CRSMatrixView< real64, globalIndex const > const & localMatrix,
1888  arrayView1d< real64 > const & localRhs )
1889  {
1890  isothermalCompositionalMultiphaseBaseKernels::internal::kernelLaunchSelectorCompSwitch( numComps, [&]( auto NC )
1891  {
1892  integer constexpr NUM_COMP = NC();
1893 
1894  using kernelType = FaceBasedAssemblyKernel< NUM_COMP, 0 >;
1895  kernelType kernel( dt, rankOffset, dofKey, wellControls, subRegion, localMatrix, localRhs, kernelFlags );
1896  kernelType::template launch< POLICY >( subRegion.size(), kernel );
1897  } );
1898  }
1899 };
1900 } // end namespace compositionalMultiphaseWellKernels
1901 
1902 } // end namespace geos
1903 
1904 #endif //GEOS_PHYSICSSOLVERS_FLUIDFLOW_WELLS_COMPOSITIONALMULTIPHASEWELLKERNELS_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_ERROR(...)
Raise a hard error and terminate the program.
Definition: Logger.hpp:226
#define GEOS_MARK_FUNCTION
Mark function with both Caliper and NVTX if enabled.
typename ElementViewAccessor< VIEWTYPE >::NestedViewTypeConst ElementViewConst
The ElementViewAccessor at the ElementRegionManager level is the type resulting from ElementViewAcces...
arrayView1d< real64 const > getElementVolume() const
Get the volume of each element in this subregion.
The ObjectManagerBase is the base object of all object managers in the mesh data hierachy.
array1d< integer > const & ghostRank()
Get the ghost information of each object.
GEOS_DECLTYPE_AUTO_RETURN getField() const
Get a view to the field associated with a trait from this ObjectManagerBase.
A struct to automatically construct and store element view accessors.
A struct to automatically construct and store element view accessors.
This class describes the controls used to operate a well.
This class describes a collection of local well elements and perforations.
bool isLocallyOwned() const
Check if well is owned by current rank.
localIndex getTopWellElementIndex() const
Get for the top element index.
static void createAndLaunch(localIndex const numComps, localIndex const numPhases, integer const &thermalEffectsEnabled, integer const isProducer, globalIndex const rankOffset, BitFlags< isothermalCompositionalMultiphaseBaseKernels::KernelFlags > kernelFlags, string const dofKey, WellElementSubRegion const &subRegion, constitutive::MultiFluidBase const &fluid, 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 accumulation and volume balance.
static constexpr integer numEqn
Compute time value for the number of equations mass bal + vol bal + energy bal.
arrayView1d< globalIndex const > const m_dofNumber
View on the dof numbers.
arrayView3d< real64 const, constitutive::multifluid::USD_PHASE > const m_phaseDens_n
Views on the phase densities.
bool const m_thermalEffectsEnabled
Flag indicating whether thermal effects are enabled.
GEOS_HOST_DEVICE void computeAccumulation(localIndex const ei, StackVariables &stack, FUNC &&phaseAmountKernelOp=NoOpFunc{}) const
Compute the local accumulation contributions to the residual and Jacobian.
ElementBasedAssemblyKernel(localIndex const numPhases, integer const thermalEffectsEnabled, integer const isProducer, globalIndex const rankOffset, string const dofKey, WellElementSubRegion const &subRegion, constitutive::MultiFluidBase const &fluid, CRSMatrixView< real64, globalIndex const > const &localMatrix, arrayView1d< real64 > const &localRhs, BitFlags< isothermalCompositionalMultiphaseBaseKernels::KernelFlags > const kernelFlags)
Constructor.
GEOS_HOST_DEVICE bool skipElement(localIndex const ei) const
Getter for the element.
arrayView4d< real64 const, constitutive::multifluid::USD_PHASE_COMP > const m_phaseCompFrac_n
Views on the phase component fraction.
arrayView3d< real64 const, compflow::USD_COMP_DC > const m_dCompFrac_dCompDens
Views on the derivatives of comp fractions wrt component density.
arrayView1d< real64 const > const m_volume
View on the element volumes.
GEOS_HOST_DEVICE void complete(localIndex const ei, StackVariables &stack) const
Performs the complete phase for the kernel.
static constexpr integer numComp
Compile time value for the number of components.
static void launch(localIndex const numElems, KERNEL_TYPE const &kernelComponent)
Performs the kernel launch.
arrayView2d< real64 const, compflow::USD_PHASE > const m_phaseVolFrac_n
Views on the phase volume fractions.
static constexpr integer numDof
Number of Dof's set in this kernal - no dQ in accum.
GEOS_HOST_DEVICE void computeVolumeBalance(localIndex const ei, StackVariables &stack) const
Compute the local volume balance contributions to the residual and Jacobian.
CRSMatrixView< real64, globalIndex const > const m_localMatrix
View on the local CRS matrix.
arrayView1d< integer const > const m_elemGhostRank
View on the ghost ranks.
localIndex const m_iwelemControl
Index of the element where the control is enforced.
GEOS_HOST_DEVICE void setup(localIndex const ei, StackVariables &stack) const
Performs the setup phase for the kernel.
static void createAndLaunch(integer const numComps, real64 const dt, globalIndex const rankOffset, BitFlags< isothermalCompositionalMultiphaseBaseKernels::KernelFlags > kernelFlags, string const dofKey, WellControls const &wellControls, WellElementSubRegion const &subRegion, 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.
arrayView1d< globalIndex const > const m_wellElemDofNumber
Reference to the degree-of-freedom numbers.
arrayView1d< real64 const > const m_injection
Injection stream composition.
GEOS_HOST_DEVICE void setup(localIndex const iconn, StackVariables &stack) const
Performs the setup phase for the kernel.
GEOS_HOST_DEVICE void computeFlux(localIndex const iwelem, StackVariables &stack, FUNC &&compFluxKernelOp=NoOpFunc{}) const
Compute the local flux contributions to the residual and Jacobian.
GEOS_HOST_DEVICE void complete(localIndex const iconn, StackVariables &stack) const
Performs the setup phase for the kernel.
integer const m_rankOffset
Rank offset for calculating row/col Jacobian indices.
arrayView1d< localIndex const > const m_nextWellElemIndex
Next element index, needed since iterating over element nodes, not edges.
arrayView2d< real64 const, compflow::USD_COMP > const m_wellElemCompFrac
Element component fraction.
static void launch(localIndex const numElements, KERNEL_TYPE const &kernelComponent)
Performs the kernel launch.
FaceBasedAssemblyKernel(real64 const dt, globalIndex const rankOffset, string const wellDofKey, WellControls const &wellControls, WellElementSubRegion const &subRegion, CRSMatrixView< real64, globalIndex const > const &localMatrix, arrayView1d< real64 > const &localRhs, BitFlags< isothermalCompositionalMultiphaseBaseKernels::KernelFlags > kernelFlags)
Constructor for the kernel interface.
arrayView1d< integer const > const m_elemStatus
View on the well status.
CRSMatrixView< real64, globalIndex const > const m_localMatrix
View on the local CRS matrix.
arrayView3d< real64 const, compflow::USD_COMP_DC > const m_dWellElemCompFrac_dCompDens
Element component fraction derivatives.
static void createAndLaunch(integer const numComp, integer const numDof, globalIndex const rankOffset, string const &dofKey, arrayView1d< real64 const > const &localResidual, WellElementSubRegion const &subRegion, constitutive::MultiFluidBase const &fluid, WellControls const &wellControls, real64 const time, real64 const dt, real64 const minNormalizer, real64(&residualNorm)[1])
Create a new kernel and launch.
virtual GEOS_HOST_DEVICE void computeLinf(localIndex const iwelem, LinfStackVariables &stack) const override
Compute the local values for the Linf norm.
bool const m_isLocallyOwned
Flag indicating whether the well is locally owned or not.
arrayView3d< real64 const, constitutive::multifluid::USD_PHASE > const m_phaseDens_n
View on phase/total density at the previous converged time step.
localIndex const m_iwelemControl
Index of the element where the control is enforced.
virtual GEOS_HOST_DEVICE void computeL2(localIndex const iwelem, L2StackVariables &stack) const override
Compute the local values and normalizer for the L2 norm.
bool const m_isProducer
Flag indicating whether the well is a producer or an injector.
static isothermalCompositionalMultiphaseBaseKernels::SolutionScalingKernel::StackVariables createAndLaunch(real64 const maxRelativePresChange, real64 const maxAbsolutePresChange, real64 const maxCompFracChange, real64 const maxRelativeCompDensChange, globalIndex const rankOffset, integer const numComp, string const dofKey, ElementSubRegionBase &subRegion, arrayView1d< real64 const > const localSolution)
Create a new kernel and launch.
static void 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 total mass density.
GEOS_HOST_DEVICE void compute(localIndex const ei, FUNC &&totalMassDensityKernelOp=NoOpFunc{}) const
Compute the total mass density in an element.
static constexpr integer numPhase
Compile time value for the number of phases.
arrayView3d< real64 const, constitutive::multifluid::USD_PHASE > m_phaseMassDens
Views on phase mass densities.
arrayView2d< real64 const, compflow::USD_PHASE > m_phaseVolFrac
Views on phase volume fractions.
static constexpr integer numComp
Compile time value for the number of components.
TotalMassDensityKernel(ObjectManagerBase &subRegion, constitutive::MultiFluidBase const &fluid)
Constructor.
GEOS_DECLTYPE_AUTO_RETURN getReference(LOOKUP_TYPE const &lookup) const
Look up a wrapper and get reference to wrapped object.
Definition: Group.hpp:1273
localIndex size() const
Get the "size" of the group, which determines the number of elements in resizable wrappers.
Definition: Group.hpp:1315
Define the base interface for the property update kernels.
static constexpr integer numComp
Compile time value for the number of components.
Define the base interface for the residual calculations.
real64 const m_minNormalizer
Value used to make sure that normalizers are never zero.
arrayView1d< globalIndex const > const m_dofNumber
View on the dof numbers.
GEOS_HOST_DEVICE integer ghostRank(localIndex const i) const
Getter for the ghost rank.
arrayView1d< real64 const > const m_localResidual
View on the local residual.
ConstraintTypeId getControl() const
Get the control type for the well.
bool isProducer() const
Is the well a producer?
stdVector< WellConstraintBase const * > getRateConstraints() const
Gets a list of rate constraints.
real64 getTargetBHP(real64 const &targetTime, const ConstraintSourceId source=ConstraintSourceId::USER) const
Returns the target bottom hole pressure value.
integer getConstraintPhaseIndex() const
Const accessor for the phase constraint index.
ArrayView< T, 1 > arrayView1d
Alias for 1D array view.
Definition: DataTypes.hpp:179
StackArray< T, 2, MAXSIZE > stackArray2d
Alias for 2D stack array.
Definition: DataTypes.hpp:203
GEOS_GLOBALINDEX_TYPE globalIndex
Global index type (for indexing objects across MPI partitions).
Definition: DataTypes.hpp:87
StackArray< T, 1, MAXSIZE > stackArray1d
Alias for 1D stack array.
Definition: DataTypes.hpp:187
ArraySlice< T, 2, USD > arraySlice2d
Alias for 2D array slice.
Definition: DataTypes.hpp:199
ArraySlice< T, 3, USD > arraySlice3d
Alias for 3D array slice.
Definition: DataTypes.hpp:215
ArrayView< T, 5, USD > arrayView5d
Alias for 5D array view.
Definition: DataTypes.hpp:243
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
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
Array< T, 1 > array1d
Alias for 1D array.
Definition: DataTypes.hpp:175
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.
Kernel variables (dof numbers, jacobian and residual) located on the stack.
real64 localJacobian[numEqn][numDof]
C-array storage for the element local Jacobian matrix (all equations except constraint and momentum)
globalIndex dofIndices[numDof]
Indices of the matrix rows/columns corresponding to the dofs in this element.
real64 localResidual[numEqn]
C-array storage for the element local residual vector (all equations except constraint and momentum)
stackArray2d< real64, maxNumElems *numEqn *maxStencilSize *CP_Deriv::nDer > localFluxJacobian
Storage for the face local Jacobian matrix dC dP dT.
GEOS_HOST_DEVICE StackVariables(localIndex const size)
Constructor for the stack variables.
stackArray2d< real64, maxNumElems *numEqn *maxStencilSize > localFluxJacobian_dQ
Storage for the face local Jacobian matrix dQ only.
stackArray1d< globalIndex, maxNumElems *numDof > dofColIndices
Indices of the matrix rows/columns corresponding to the dofs in this face.
stackArray1d< real64, maxNumElems *numEqn > localFlux
Storage for the face local residual vector (all mass bal equations)
ElementRegionManager::ElementViewConst< VIEWTYPE > ElementViewConst
The type for element-based non-constitutive data parameters. Consists entirely of ArrayView's.