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"
27 
28 namespace geos
29 {
30 
31 namespace isothermalCompositionalMultiphaseBaseKernels
32 {
33 
34 /******************************** SolutionCheckKernel ********************************/
35 
41 {
42 public:
43 
45  using Base::m_rankOffset;
46  using Base::m_numComp;
47  using Base::m_dofNumber;
48  using Base::m_ghostRank;
50  using Base::m_pressure;
51  using Base::m_compDens;
52 
65  SolutionCheckKernel( integer const allowCompDensChopping,
66  integer const allowNegativePressure,
67  flowSolverUtilities::ScalingType const scalingType,
68  real64 const scalingFactor,
69  arrayView1d< real64 const > const pressure,
71  arrayView1d< real64 > pressureScalingFactor,
72  arrayView1d< real64 > compDensScalingFactor,
73  globalIndex const rankOffset,
74  integer const numComp,
75  string const dofKey,
76  ElementSubRegionBase const & subRegion,
77  arrayView1d< real64 const > const localSolution,
78  ElementsReporterCollector const & negPressureIds,
79  ElementsReporterCollector const & negDensityIds,
80  ElementsReporterCollector const & negTotalDensityIds )
81  : Base( rankOffset,
82  numComp,
83  dofKey,
84  subRegion,
85  localSolution,
86  pressure,
87  compDens,
88  pressureScalingFactor,
89  compDensScalingFactor ),
90  m_allowCompDensChopping( allowCompDensChopping ),
91  m_allowNegativePressure( allowNegativePressure ),
92  m_scalingFactor( scalingFactor ),
93  m_scalingType( scalingType ),
94  m_negPressureIds( negPressureIds ),
95  m_negDensityIds( negDensityIds ),
96  m_negTotalDensityIds( negTotalDensityIds )
97  {}
98 
103  struct KernelStats : public Base::StackVariables
104  {
106  KernelStats():
107  Base::StackVariables()
108  {}
109 
110  KernelStats( real64 _localMinVal,
111  real64 _localMinNegPres,
112  real64 _localMinNegDens,
113  real64 _localMinNegTotalDens )
114  :
115  Base::StackVariables( _localMinVal ),
116  localMinNegPres( _localMinNegPres ),
117  localMinNegDens( _localMinNegDens ),
118  localMinNegTotalDens( _localMinNegTotalDens )
119  { }
120 
121  real64 localMinNegPres;
122  real64 localMinNegDens;
123  real64 localMinNegTotalDens;
124  };
125 
130  struct StackVariables : public KernelStats
131  {
133  StackVariables():
134  KernelStats()
135  { }
136 
137  localIndex localNumNegPres; // 0 or 1
138  localIndex localNumNegDens; // 0 -> num comp
139  localIndex localNumNegTotalDens; // 0 or 1
140  };
141 
149  template< typename POLICY, typename KERNEL_TYPE >
150  static KernelStats
151  launch( localIndex const numElems,
152  KERNEL_TYPE const & kernelComponent )
153  {
154  using reducePolicy = ReducePolicy< POLICY >;
155  using atomicPolicy = AtomicPolicy< POLICY >;
156 
157  RAJA::ReduceMin< reducePolicy, integer > globalMinVal( 1 );
158 
159  RAJA::ReduceMin< reducePolicy, real64 > minPres( 0.0 );
160  RAJA::ReduceMin< reducePolicy, real64 > minDens( 0.0 );
161  RAJA::ReduceMin< reducePolicy, real64 > minTotalDens( 0.0 );
162 
163  forAll< POLICY >( numElems, [=] GEOS_HOST_DEVICE ( localIndex const ei )
164  {
165  if( kernelComponent.ghostRank( ei ) >= 0 )
166  {
167  return;
168  }
169 
170  StackVariables stack;
171  kernelComponent.setup( ei, stack );
172  kernelComponent.compute( ei, stack );
173 
174  globalMinVal.min( stack.localMinVal );
175 
176  minPres.min( stack.localMinNegPres );
177  minDens.min( stack.localMinNegDens );
178  minTotalDens.min( stack.localMinNegTotalDens );
179 
180  if( stack.localNumNegPres > 0 )
181  kernelComponent.m_negPressureIds.collectElement( atomicPolicy{}, { ei, stack.localMinNegPres } );
182 
183  if( stack.localNumNegDens > 0 )
184  kernelComponent.m_negDensityIds.collectElement( atomicPolicy{}, { ei, stack.localMinNegDens } );
185 
186  if( stack.localNumNegTotalDens > 0 )
187  kernelComponent.m_negDensityIds.collectElement( atomicPolicy{}, { ei, stack.localMinNegTotalDens } );
188  } );
189 
190  return KernelStats( globalMinVal.get(),
191  minPres.get(),
192  minDens.get(),
193  minTotalDens.get() );
194  }
195 
197  void setup( localIndex const ei,
198  StackVariables & stack ) const
199  {
200  Base::setup( ei, stack );
201 
202  stack.localMinNegPres = 0.0;
203  stack.localMinNegDens = 0.0;
204  stack.localMinNegTotalDens = 0.0;
205 
206  stack.localNumNegPres = 0;
207  stack.localNumNegDens = 0;
208  stack.localNumNegTotalDens = 0;
209  }
210 
217  void compute( localIndex const ei,
218  StackVariables & stack ) const
219  {
220  computeSolutionCheck( ei, stack );
221  }
222 
230  template< typename FUNC = NoOpFunc >
233  StackVariables & stack,
234  FUNC && kernelOp = NoOpFunc{} ) const
235  {
236  bool const localScaling = m_scalingType == flowSolverUtilities::ScalingType::Local;
237 
238  real64 const newPres = m_pressure[ei] + (localScaling ? m_pressureScalingFactor[ei] : m_scalingFactor) * m_localSolution[stack.localRow];
239  if( newPres < 0.0 && !m_allowNegativePressure )
240  stack.localMinVal = 0;
241 
242  if( newPres <= 0.0 )
243  {
244  stack.localNumNegPres += 1;
245 
246  if( newPres < stack.localMinNegPres )
247  stack.localMinNegPres = newPres;
248  }
249 
250  // if component density chopping is not allowed, the time step fails if a component density is negative
251  // otherwise, we just check that the total density is positive, and negative component densities
252  // will be chopped (i.e., set to zero) in ApplySystemSolution)
253  real64 totalDens = 0.0;
255  {
256  for( integer ic = 0; ic < m_numComp; ++ic )
257  {
258  real64 const newDens = m_compDens[ei][ic] + (localScaling ? m_compDensScalingFactor[ei] : m_scalingFactor) * m_localSolution[stack.localRow + ic + 1];
259  totalDens += newDens;
260 
261  // we invalidate timestep if new density is negative, and we report density as too low if negative or equal to zero
262  bool const isNewDensNegative = newDens < 0.0;
263  bool const isNewDensTooLow = newDens <= 0.0;
264  stack.localMinVal = isNewDensNegative ? 0 : stack.localMinVal;
265  stack.localNumNegDens += isNewDensTooLow;
266  stack.localMinNegDens = isNewDensTooLow ?
267  LvArray::math::min( stack.localMinNegDens, newDens ) :
268  stack.localMinNegDens;
269  }
270  }
271  else
272  {
273  for( integer ic = 0; ic < m_numComp; ++ic )
274  {
275  real64 const newDens = m_compDens[ei][ic] + (localScaling ? m_compDensScalingFactor[ei] : m_scalingFactor) * m_localSolution[stack.localRow + ic + 1];
276  totalDens += LvArray::math::max( newDens, 0.0 );
277 
278  // we never invalidate timestep as negatives will be chopped later in ApplySystemSolution(), and we report density as too low if
279  // negative or equal to zero
280  bool const isNewDensTooLow = newDens <= 0.0;
281  stack.localNumNegDens += isNewDensTooLow;
282  stack.localMinNegDens = isNewDensTooLow ?
283  LvArray::math::min( stack.localMinNegDens, newDens ) :
284  stack.localMinNegDens;
285  }
286  }
287  {
288  bool const isNewTotalDensTooLow = totalDens <= 0.0;
289  stack.localNumNegTotalDens += isNewTotalDensTooLow;
290  stack.localMinNegTotalDens = isNewTotalDensTooLow ?
291  LvArray::math::min( stack.localMinNegTotalDens, totalDens ) :
292  stack.localMinNegTotalDens;
293  }
294 
295  kernelOp();
296  }
297 
298 protected:
299 
302 
305 
308 
311 
312  ElementsReporterCollector const m_negPressureIds;
313 
314  ElementsReporterCollector const m_negDensityIds;
315 
316  ElementsReporterCollector const m_negTotalDensityIds;
317 
318 };
319 
324 {
325 public:
326 
338  template< typename POLICY >
340  createAndLaunch( integer const allowCompDensChopping,
341  integer const allowNegativePressure,
342  flowSolverUtilities::ScalingType const scalingType,
343  real64 const scalingFactor,
344  arrayView1d< real64 const > const pressure,
346  arrayView1d< real64 > pressureScalingFactor,
347  arrayView1d< real64 > compDensScalingFactor,
348  globalIndex const rankOffset,
349  integer const numComp,
350  string const dofKey,
351  ElementSubRegionBase & subRegion,
352  arrayView1d< real64 const > const localSolution,
353  ElementsReporterCollector const & negPressureIds,
354  ElementsReporterCollector const & negDensityIds,
355  ElementsReporterCollector const & negTotalDensityIds )
356  {
357  SolutionCheckKernel kernel( allowCompDensChopping, allowNegativePressure, scalingType, scalingFactor,
358  pressure, compDens, pressureScalingFactor, compDensScalingFactor, rankOffset,
359  numComp, dofKey, subRegion, localSolution, negPressureIds, negDensityIds,
360  negTotalDensityIds );
361  return SolutionCheckKernel::launch< POLICY >( subRegion.size(), kernel );
362  }
363 
364 };
365 
366 } // namespace isothermalCompositionalMultiphaseBaseKernels
367 
368 } // namespace geos
369 
370 
371 #endif //GEOS_PHYSICSSOLVERS_FLUIDFLOW_COMPOSITIONAL_SOLUTIONCHECKKERNEL_HPP
ScalingType
Solution scaling type.
#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, flowSolverUtilities::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.
flowSolverUtilities::ScalingType const m_scalingType
scaling type (global or local)
static KernelStats launch(localIndex const numElems, KERNEL_TYPE const &kernelComponent)
Performs the kernel launch.
SolutionCheckKernel(integer const allowCompDensChopping, integer const allowNegativePressure, flowSolverUtilities::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.
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.
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.