GEOS
SolutionCheckKernel.hpp
Go to the documentation of this file.
1 /*
2  * ------------------------------------------------------------------------------------------------------------
3  * SPDX-License-Identifier: LGPL-2.1-only
4  *
5  * Copyright (c) 2016-2024 Lawrence Livermore National Security LLC
6  * Copyright (c) 2018-2024 TotalEnergies
7  * Copyright (c) 2018-2024 The Board of Trustees of the Leland Stanford Junior University
8  * Copyright (c) 2023-2024 Chevron
9  * Copyright (c) 2019- GEOS/GEOSX Contributors
10  * All rights reserved
11  *
12  * See top level LICENSE, COPYRIGHT, CONTRIBUTORS, NOTICE, and ACKNOWLEDGEMENTS files for details.
13  * ------------------------------------------------------------------------------------------------------------
14  */
15 
20 #ifndef GEOS_PHYSICSSOLVERS_FLUIDFLOW_COMPOSITIONAL_SOLUTIONCHECKKERNEL_HPP
21 #define GEOS_PHYSICSSOLVERS_FLUIDFLOW_COMPOSITIONAL_SOLUTIONCHECKKERNEL_HPP
22 
23 #include "LvArray/src/math.hpp"
26 
27 namespace geos
28 {
29 
30 namespace isothermalCompositionalMultiphaseBaseKernels
31 {
32 
33 /******************************** SolutionCheckKernel ********************************/
34 
40 {
41 public:
42 
44  using Base::m_rankOffset;
45  using Base::m_numComp;
46  using Base::m_dofNumber;
47  using Base::m_ghostRank;
49  using Base::m_pressure;
50  using Base::m_compDens;
51 
64  SolutionCheckKernel( integer const allowCompDensChopping,
65  integer const allowNegativePressure,
67  real64 const scalingFactor,
68  arrayView1d< real64 const > const pressure,
70  arrayView1d< real64 > pressureScalingFactor,
71  arrayView1d< real64 > compDensScalingFactor,
72  globalIndex const rankOffset,
73  integer const numComp,
74  string const dofKey,
75  ElementSubRegionBase const & subRegion,
76  arrayView1d< real64 const > const localSolution,
77  ElementsReporterCollector const & negPressureIds,
78  ElementsReporterCollector const & negDensityIds,
79  ElementsReporterCollector const & negTotalDensityIds )
80  : Base( rankOffset,
81  numComp,
82  dofKey,
83  subRegion,
84  localSolution,
85  pressure,
86  compDens,
87  pressureScalingFactor,
88  compDensScalingFactor ),
89  m_allowCompDensChopping( allowCompDensChopping ),
90  m_allowNegativePressure( allowNegativePressure ),
91  m_scalingFactor( scalingFactor ),
92  m_scalingType( scalingType ),
93  m_negPressureIds( negPressureIds ),
94  m_negDensityIds( negDensityIds ),
95  m_negTotalDensityIds( negTotalDensityIds )
96  {}
97 
102  struct KernelStats : public Base::StackVariables
103  {
105  KernelStats():
106  Base::StackVariables()
107  {}
108 
109  KernelStats( real64 _localMinVal,
110  real64 _localMinNegPres,
111  real64 _localMinNegDens,
112  real64 _localMinNegTotalDens )
113  :
114  Base::StackVariables( _localMinVal ),
115  localMinNegPres( _localMinNegPres ),
116  localMinNegDens( _localMinNegDens ),
117  localMinNegTotalDens( _localMinNegTotalDens )
118  { }
119 
120  real64 localMinNegPres;
121  real64 localMinNegDens;
122  real64 localMinNegTotalDens;
123  };
124 
129  struct StackVariables : public KernelStats
130  {
132  StackVariables():
133  KernelStats()
134  { }
135 
136  localIndex localNumNegPres; // 0 or 1
137  localIndex localNumNegDens; // 0 -> num comp
138  localIndex localNumNegTotalDens; // 0 or 1
139  };
140 
148  template< typename POLICY, typename KERNEL_TYPE >
149  static KernelStats
150  launch( localIndex const numElems,
151  KERNEL_TYPE const & kernelComponent )
152  {
153  using reducePolicy = ReducePolicy< POLICY >;
154  using atomicPolicy = AtomicPolicy< POLICY >;
155 
156  RAJA::ReduceMin< reducePolicy, integer > globalMinVal( 1 );
157 
158  RAJA::ReduceMin< reducePolicy, real64 > minPres( 0.0 );
159  RAJA::ReduceMin< reducePolicy, real64 > minDens( 0.0 );
160  RAJA::ReduceMin< reducePolicy, real64 > minTotalDens( 0.0 );
161 
162  forAll< POLICY >( numElems, [=] GEOS_HOST_DEVICE ( localIndex const ei )
163  {
164  if( kernelComponent.ghostRank( ei ) >= 0 )
165  {
166  return;
167  }
168 
169  StackVariables stack;
170  kernelComponent.setup( ei, stack );
171  kernelComponent.compute( ei, stack );
172 
173  globalMinVal.min( stack.localMinVal );
174 
175  minPres.min( stack.localMinNegPres );
176  minDens.min( stack.localMinNegDens );
177  minTotalDens.min( stack.localMinNegTotalDens );
178 
179  if( stack.localNumNegPres > 0 )
180  kernelComponent.m_negPressureIds.collectElement( atomicPolicy{}, { ei, stack.localMinNegPres } );
181 
182  if( stack.localNumNegDens > 0 )
183  kernelComponent.m_negDensityIds.collectElement( atomicPolicy{}, { ei, stack.localMinNegDens } );
184 
185  if( stack.localNumNegTotalDens > 0 )
186  kernelComponent.m_negDensityIds.collectElement( atomicPolicy{}, { ei, stack.localMinNegTotalDens } );
187  } );
188 
189  return KernelStats( globalMinVal.get(),
190  minPres.get(),
191  minDens.get(),
192  minTotalDens.get() );
193  }
194 
196  void setup( localIndex const ei,
197  StackVariables & stack ) const
198  {
199  Base::setup( ei, stack );
200 
201  stack.localMinNegPres = 0.0;
202  stack.localMinNegDens = 0.0;
203  stack.localMinNegTotalDens = 0.0;
204 
205  stack.localNumNegPres = 0;
206  stack.localNumNegDens = 0;
207  stack.localNumNegTotalDens = 0;
208  }
209 
216  void compute( localIndex const ei,
217  StackVariables & stack ) const
218  {
219  computeSolutionCheck( ei, stack );
220  }
221 
229  template< typename FUNC = NoOpFunc >
232  StackVariables & stack,
233  FUNC && kernelOp = NoOpFunc{} ) const
234  {
235  bool const localScaling = m_scalingType == compositionalMultiphaseUtilities::ScalingType::Local;
236 
237  real64 const newPres = m_pressure[ei] + (localScaling ? m_pressureScalingFactor[ei] : m_scalingFactor) * m_localSolution[stack.localRow];
238  if( newPres < 0.0 && !m_allowNegativePressure )
239  stack.localMinVal = 0;
240 
241  if( newPres <= 0.0 )
242  {
243  stack.localNumNegPres += 1;
244 
245  if( newPres < stack.localMinNegPres )
246  stack.localMinNegPres = newPres;
247  }
248 
249  // if component density chopping is not allowed, the time step fails if a component density is negative
250  // otherwise, we just check that the total density is positive, and negative component densities
251  // will be chopped (i.e., set to zero) in ApplySystemSolution)
252  real64 totalDens = 0.0;
254  {
255  for( integer ic = 0; ic < m_numComp; ++ic )
256  {
257  real64 const newDens = m_compDens[ei][ic] + (localScaling ? m_compDensScalingFactor[ei] : m_scalingFactor) * m_localSolution[stack.localRow + ic + 1];
258  totalDens += newDens;
259 
260  // we invalidate timestep if new density is negative, and we report density as too low if negative or equal to zero
261  bool const isNewDensNegative = newDens < 0.0;
262  bool const isNewDensTooLow = newDens <= 0.0;
263  stack.localMinVal = isNewDensNegative ? 0 : stack.localMinVal;
264  stack.localNumNegDens += isNewDensTooLow;
265  stack.localMinNegDens = isNewDensTooLow ?
266  LvArray::math::min( stack.localMinNegDens, newDens ) :
267  stack.localMinNegDens;
268  }
269  }
270  else
271  {
272  for( integer ic = 0; ic < m_numComp; ++ic )
273  {
274  real64 const newDens = m_compDens[ei][ic] + (localScaling ? m_compDensScalingFactor[ei] : m_scalingFactor) * m_localSolution[stack.localRow + ic + 1];
275  totalDens += LvArray::math::max( newDens, 0.0 );
276 
277  // we never invalidate timestep as negatives will be chopped later in ApplySystemSolution(), and we report density as too low if
278  // negative or equal to zero
279  bool const isNewDensTooLow = newDens <= 0.0;
280  stack.localNumNegDens += isNewDensTooLow;
281  stack.localMinNegDens = isNewDensTooLow ?
282  LvArray::math::min( stack.localMinNegDens, newDens ) :
283  stack.localMinNegDens;
284  }
285  }
286  {
287  bool const isNewTotalDensTooLow = totalDens <= 0.0;
288  stack.localNumNegTotalDens += isNewTotalDensTooLow;
289  stack.localMinNegTotalDens = isNewTotalDensTooLow ?
290  LvArray::math::min( stack.localMinNegTotalDens, totalDens ) :
291  stack.localMinNegTotalDens;
292  }
293 
294  kernelOp();
295  }
296 
297 protected:
298 
301 
304 
307 
310 
311  ElementsReporterCollector const m_negPressureIds;
312 
313  ElementsReporterCollector const m_negDensityIds;
314 
315  ElementsReporterCollector const m_negTotalDensityIds;
316 
317 };
318 
323 {
324 public:
325 
337  template< typename POLICY >
339  createAndLaunch( integer const allowCompDensChopping,
340  integer const allowNegativePressure,
342  real64 const scalingFactor,
343  arrayView1d< real64 const > const pressure,
345  arrayView1d< real64 > pressureScalingFactor,
346  arrayView1d< real64 > compDensScalingFactor,
347  globalIndex const rankOffset,
348  integer const numComp,
349  string const dofKey,
350  ElementSubRegionBase & subRegion,
351  arrayView1d< real64 const > const localSolution,
352  ElementsReporterCollector const & negPressureIds,
353  ElementsReporterCollector const & negDensityIds,
354  ElementsReporterCollector const & negTotalDensityIds )
355  {
356  SolutionCheckKernel kernel( allowCompDensChopping, allowNegativePressure, scalingType, scalingFactor,
357  pressure, compDens, pressureScalingFactor, compDensScalingFactor, rankOffset,
358  numComp, dofKey, subRegion, localSolution, negPressureIds, negDensityIds,
359  negTotalDensityIds );
360  return SolutionCheckKernel::launch< POLICY >( subRegion.size(), kernel );
361  }
362 
363 };
364 
365 } // namespace isothermalCompositionalMultiphaseBaseKernels
366 
367 } // namespace geos
368 
369 
370 #endif //GEOS_PHYSICSSOLVERS_FLUIDFLOW_COMPOSITIONAL_SOLUTIONCHECKKERNEL_HPP
ScalingType
Solution scaling type, used in CompositionalMultiphaseFVM.
#define GEOS_HOST_DEVICE
Marks a host-device function.
Definition: GeosxMacros.hpp:49
Collects and reports elements ids and data using an atomic counter. This class provides functionality...
localIndex size() const
Get the "size" of the group, which determines the number of elements in resizable wrappers.
Definition: Group.hpp:1315
static SolutionCheckKernel::KernelStats createAndLaunch(integer const allowCompDensChopping, integer const allowNegativePressure, compositionalMultiphaseUtilities::ScalingType const scalingType, real64 const scalingFactor, arrayView1d< real64 const > const pressure, arrayView2d< real64 const, compflow::USD_COMP > const compDens, arrayView1d< real64 > pressureScalingFactor, arrayView1d< real64 > compDensScalingFactor, globalIndex const rankOffset, integer const numComp, string const dofKey, ElementSubRegionBase &subRegion, arrayView1d< real64 const > const localSolution, ElementsReporterCollector const &negPressureIds, ElementsReporterCollector const &negDensityIds, ElementsReporterCollector const &negTotalDensityIds)
Create a new kernel and launch.
SolutionCheckKernel(integer const allowCompDensChopping, integer const allowNegativePressure, compositionalMultiphaseUtilities::ScalingType const scalingType, real64 const scalingFactor, arrayView1d< real64 const > const pressure, arrayView2d< real64 const, compflow::USD_COMP > const compDens, arrayView1d< real64 > pressureScalingFactor, arrayView1d< real64 > compDensScalingFactor, globalIndex const rankOffset, integer const numComp, string const dofKey, ElementSubRegionBase const &subRegion, arrayView1d< real64 const > const localSolution, ElementsReporterCollector const &negPressureIds, ElementsReporterCollector const &negDensityIds, ElementsReporterCollector const &negTotalDensityIds)
Create a new kernel instance.
static KernelStats launch(localIndex const numElems, KERNEL_TYPE const &kernelComponent)
Performs the kernel launch.
GEOS_HOST_DEVICE void computeSolutionCheck(localIndex const ei, StackVariables &stack, FUNC &&kernelOp=NoOpFunc{}) const
Compute the local value of the check.
integer const m_allowNegativePressure
flag to allow negative pressure values
GEOS_HOST_DEVICE void compute(localIndex const ei, StackVariables &stack) const
Compute the local value.
compositionalMultiphaseUtilities::ScalingType const m_scalingType
scaling type (global or local)
integer const m_allowCompDensChopping
flag to allow the component density chopping
GEOS_HOST_DEVICE void setup(localIndex const ei, StackVariables &stack) const
Performs the setup phase for the kernel.
ArrayView< T, 1 > arrayView1d
Alias for 1D array view.
Definition: DataTypes.hpp:179
GEOS_GLOBALINDEX_TYPE globalIndex
Global index type (for indexing objects across MPI partitions).
Definition: DataTypes.hpp:87
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
ArrayView< T, 2, USD > arrayView2d
Alias for 2D array view.
Definition: DataTypes.hpp:195
int integer
Signed integer type.
Definition: DataTypes.hpp:81
Kernel variables (dof numbers, jacobian and residual) located on the stack.