GEOS
SolutionScalingKernel.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_SOLUTIONSCALINGKERNEL_HPP
21 #define GEOS_PHYSICSSOLVERS_FLUIDFLOW_COMPOSITIONAL_SOLUTIONSCALINGKERNEL_HPP
22 
24 #include "physicsSolvers/fluidFlow/kernels/compositional/AccumulationKernel.hpp"
26 
27 namespace geos
28 {
29 
30 namespace isothermalCompositionalMultiphaseBaseKernels
31 {
32 
33 /******************************** SolutionScalingKernel ********************************/
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;
52  using Base::m_compDensScalingFactor;
53 
70  SolutionScalingKernel( real64 const maxRelativePresChange,
71  real64 const maxAbsolutePresChange,
72  real64 const maxCompFracChange,
73  real64 const maxRelativeCompDensChange,
74  globalIndex const rankOffset,
75  integer const numComp,
76  string const dofKey,
77  ElementSubRegionBase const & subRegion,
78  arrayView1d< real64 const > const localSolution,
79  arrayView1d< real64 const > const pressure,
81  arrayView1d< real64 > pressureScalingFactor,
82  arrayView1d< real64 > compDensScalingFactor )
83  : Base( rankOffset,
84  numComp,
85  dofKey,
86  subRegion,
87  localSolution,
88  pressure,
89  compDens,
90  pressureScalingFactor,
91  compDensScalingFactor ),
92  m_maxRelativePresChange( maxRelativePresChange ),
93  m_maxAbsolutePresChange( maxAbsolutePresChange ),
94  m_maxCompFracChange( maxCompFracChange ),
95  m_maxRelativeCompDensChange( maxRelativeCompDensChange )
96  {}
97 
102  struct StackVariables : public Base::StackVariables
103  {
106  { }
107 
108  StackVariables( real64 _localMinVal,
109  real64 _localMaxDeltaPres,
110  localIndex _localMaxDeltaPresLoc,
111  real64 _localMaxDeltaTemp,
112  localIndex _localMaxDeltaTempLoc,
113  real64 _localMaxDeltaCompDens,
114  localIndex _localMaxDeltaCompDensLoc,
115  real64 _localMinPresScalingFactor,
116  real64 _localMinTempScalingFactor,
117  real64 _localMinCompDensScalingFactor )
118  :
119  Base::StackVariables( _localMinVal ),
120  localMaxDeltaPres( _localMaxDeltaPres ),
121  localMaxDeltaPresLoc( _localMaxDeltaPresLoc ),
122  localMaxDeltaTemp( _localMaxDeltaTemp ),
123  localMaxDeltaTempLoc( _localMaxDeltaTempLoc ),
124  localMaxDeltaCompDens( _localMaxDeltaCompDens ),
125  localMaxDeltaCompDensLoc( _localMaxDeltaCompDensLoc ),
126  localMinPresScalingFactor( _localMinPresScalingFactor ),
127  localMinTempScalingFactor( _localMinTempScalingFactor ),
128  localMinCompDensScalingFactor( _localMinCompDensScalingFactor )
129  { }
130 
131  real64 localMaxDeltaPres;
132  localIndex localMaxDeltaPresLoc;
133  real64 localMaxDeltaTemp;
134  localIndex localMaxDeltaTempLoc;
135  real64 localMaxDeltaCompDens;
136  localIndex localMaxDeltaCompDensLoc;
137 
138  real64 localMinPresScalingFactor;
139  real64 localMinTempScalingFactor;
140  real64 localMinCompDensScalingFactor;
141 
142  };
143 
151  template< typename POLICY, typename KERNEL_TYPE >
152  static StackVariables
153  launch( localIndex const numElems,
154  KERNEL_TYPE const & kernelComponent )
155  {
156  RAJA::ReduceMin< ReducePolicy< POLICY >, real64 > globalScalingFactor( 1.0 );
157 
158  RAJA::ReduceMaxLoc< ReducePolicy< POLICY >, real64 > maxDeltaPres( std::numeric_limits< real64 >::min(), -1 );
159  RAJA::ReduceMaxLoc< ReducePolicy< POLICY >, real64 > maxDeltaTemp( std::numeric_limits< real64 >::min(), -1 );
160  RAJA::ReduceMaxLoc< ReducePolicy< POLICY >, real64 > maxDeltaCompDens( std::numeric_limits< real64 >::min(), -1 );
161 
162  RAJA::ReduceMin< ReducePolicy< POLICY >, real64 > minPresScalingFactor( 1.0 );
163  RAJA::ReduceMin< ReducePolicy< POLICY >, real64 > minTempScalingFactor( 1.0 );
164  RAJA::ReduceMin< ReducePolicy< POLICY >, real64 > minCompDensScalingFactor( 1.0 );
165 
166  forAll< POLICY >( numElems, [=] GEOS_HOST_DEVICE ( localIndex const ei )
167  {
168  if( kernelComponent.ghostRank( ei ) >= 0 )
169  {
170  return;
171  }
172 
173  StackVariables stack;
174  kernelComponent.setup( ei, stack );
175  kernelComponent.compute( ei, stack );
176 
177  globalScalingFactor.min( stack.localMinVal );
178 
179  maxDeltaPres.maxloc( stack.localMaxDeltaPres, ei );
180  maxDeltaTemp.maxloc( stack.localMaxDeltaTemp, ei );
181  maxDeltaCompDens.maxloc( stack.localMaxDeltaCompDens, ei );
182 
183  minPresScalingFactor.min( stack.localMinPresScalingFactor );
184  minTempScalingFactor.min( stack.localMinTempScalingFactor );
185  minCompDensScalingFactor.min( stack.localMinCompDensScalingFactor );
186  } );
187 
188  return StackVariables( globalScalingFactor.get(),
189  maxDeltaPres.get(),
190  maxDeltaPres.getLoc(),
191  maxDeltaTemp.get(),
192  maxDeltaTemp.getLoc(),
193  maxDeltaCompDens.get(),
194  maxDeltaCompDens.getLoc(),
195  minPresScalingFactor.get(),
196  minTempScalingFactor.get(),
197  minCompDensScalingFactor.get() );
198  }
199 
201  void setup( localIndex const ei,
202  StackVariables & stack ) const
203  {
204  Base::setup( ei, stack );
205 
206  stack.localMaxDeltaPres = 0.0;
207  stack.localMaxDeltaPresLoc = -1;
208  stack.localMaxDeltaTemp = 0.0;
209  stack.localMaxDeltaTempLoc = -1;
210  stack.localMaxDeltaCompDens = 0.0;
211  stack.localMaxDeltaCompDensLoc =-1;
212 
213  stack.localMinPresScalingFactor = 1.0;
214  stack.localMinTempScalingFactor = 1.0;
215  stack.localMinCompDensScalingFactor = 1.0;
216  }
217 
224  void compute( localIndex const ei,
225  StackVariables & stack ) const
226  {
227  computeScalingFactor( ei, stack );
228  }
229 
237  template< typename FUNC = NoOpFunc >
240  StackVariables & stack,
241  FUNC && kernelOp = NoOpFunc{} ) const
242  {
243  real64 constexpr eps = minDensForDivision;
244 
245  // compute the change in pressure
246  real64 const pres = m_pressure[ei];
247  real64 const absPresChange = LvArray::math::abs( m_localSolution[stack.localRow] );
248  if( stack.localMaxDeltaPres < absPresChange )
249  {
250  stack.localMaxDeltaPres = absPresChange;
251  }
252 
253  // compute pressure scaling factor
254  real64 presScalingFactor = 1.0;
255  // when enabled, absolute change scaling has a priority over relative change
256  if( m_maxAbsolutePresChange > 0.0 ) // maxAbsolutePresChange <= 0.0 means that absolute scaling is disabled
257  {
258  if( absPresChange > m_maxAbsolutePresChange )
259  {
260  presScalingFactor = m_maxAbsolutePresChange / absPresChange;
261  }
262  }
263  else if( pres > eps )
264  {
265  real64 const relativePresChange = absPresChange / pres;
266  if( relativePresChange > m_maxRelativePresChange )
267  {
268  presScalingFactor = m_maxRelativePresChange / relativePresChange;
269  }
270  }
271  m_pressureScalingFactor[ei] = presScalingFactor;
272  if( stack.localMinVal > presScalingFactor )
273  {
274  stack.localMinVal = presScalingFactor;
275  }
276  if( stack.localMinPresScalingFactor > presScalingFactor )
277  {
278  stack.localMinPresScalingFactor = presScalingFactor;
279  }
280 
281  real64 prevTotalDens = 0;
282  for( integer ic = 0; ic < m_numComp; ++ic )
283  {
284  prevTotalDens += m_compDens[ei][ic];
285  }
286 
287  m_compDensScalingFactor[ei] = 1.0;
288 
289  // compute the change in component densities and component fractions
290  for( integer ic = 0; ic < m_numComp; ++ic )
291  {
292  // compute scaling factor based on relative change in component densities
293  real64 const absCompDensChange = LvArray::math::abs( m_localSolution[stack.localRow + ic + 1] );
294  if( stack.localMaxDeltaCompDens < absCompDensChange )
295  {
296  stack.localMaxDeltaCompDens = absCompDensChange;
297  }
298 
299  // This actually checks the change in component fraction, using a lagged total density
300  // Indeed we can rewrite the following check as:
301  // | prevCompDens / prevTotalDens - newCompDens / prevTotalDens | > maxCompFracChange
302  // Note that the total density in the second term is lagged (i.e, we use prevTotalDens)
303  // because I found it more robust than using directly newTotalDens (which can vary also
304  // wildly when the compDens change is large)
305  real64 const maxAbsCompDensChange = m_maxCompFracChange * prevTotalDens;
306  if( absCompDensChange > maxAbsCompDensChange && absCompDensChange > eps )
307  {
308  real64 const compScalingFactor = maxAbsCompDensChange / absCompDensChange;
309  m_compDensScalingFactor[ei] = LvArray::math::min( m_compDensScalingFactor[ei], compScalingFactor );
310  if( stack.localMinVal > compScalingFactor )
311  {
312  stack.localMinVal = compScalingFactor;
313  }
314  if( stack.localMinCompDensScalingFactor > compScalingFactor )
315  {
316  stack.localMinCompDensScalingFactor = compScalingFactor;
317  }
318  }
319 
320  // switch from relative to absolute when value is < 1.0
321  real64 const maxRelCompDensChange = m_maxRelativeCompDensChange * LvArray::math::max( m_compDens[ei][ic], 1.0 );
322  if( absCompDensChange > maxRelCompDensChange && absCompDensChange > eps )
323  {
324  real64 const compScalingFactor = maxRelCompDensChange / absCompDensChange;
325  m_compDensScalingFactor[ei] = LvArray::math::min( m_compDensScalingFactor[ei], compScalingFactor );
326  if( stack.localMinVal > compScalingFactor )
327  {
328  stack.localMinVal = compScalingFactor;
329  }
330  if( stack.localMinCompDensScalingFactor > compScalingFactor )
331  {
332  stack.localMinCompDensScalingFactor = compScalingFactor;
333  }
334  }
335  }
336 
337  // compute the scaling factor for other vars, such as temperature
338  kernelOp();
339  }
340 
341 protected:
342 
345  real64 const m_maxAbsolutePresChange;
346  real64 const m_maxCompFracChange;
347  real64 const m_maxRelativeCompDensChange;
348 
349 };
350 
355 {
356 public:
357 
358  /*
359  * @brief Create and launch the kernel computing the scaling factor
360  * @tparam POLICY the kernel policy
361  * @param[in] maxRelativePresChange the max allowed relative pressure change
362  * @param[in] maxAbsolutePresChange the max allowed absolute pressure change
363  * @param[in] maxCompFracChange the max allowed comp fraction change
364  * @param[in] maxRelativeCompDensChange the max allowed comp density change
365  * @param[in] rankOffset the rank offset
366  * @param[in] numComp the number of components
367  * @param[in] dofKey the dof key to get dof numbers
368  * @param[in] subRegion the subRegion
369  * @param[in] localSolution the Newton update
370  * @return the scaling factor
371  */
372  template< typename POLICY >
374  createAndLaunch( real64 const maxRelativePresChange,
375  real64 const maxAbsolutePresChange,
376  real64 const maxCompFracChange,
377  real64 const maxRelativeCompDensChange,
378  arrayView1d< real64 const > const pressure,
380  arrayView1d< real64 > pressureScalingFactor,
381  arrayView1d< real64 > compDensScalingFactor,
382  globalIndex const rankOffset,
383  integer const numComp,
384  string const dofKey,
385  ElementSubRegionBase & subRegion,
386  arrayView1d< real64 const > const localSolution )
387  {
388  SolutionScalingKernel kernel( maxRelativePresChange, maxAbsolutePresChange, maxCompFracChange, maxRelativeCompDensChange, rankOffset,
389  numComp, dofKey, subRegion, localSolution, pressure, compDens, pressureScalingFactor, compDensScalingFactor );
390  return SolutionScalingKernel::launch< POLICY >( subRegion.size(), kernel );
391  }
392 };
393 
394 } // namespace isothermalCompositionalMultiphaseBaseKernels
395 
396 } // namespace geos
397 
398 
399 #endif //GEOS_PHYSICSSOLVERS_FLUIDFLOW_COMPOSITIONAL_SOLUTIONSCALINGKERNEL_HPP
#define GEOS_HOST_DEVICE
Marks a host-device function.
Definition: GeosxMacros.hpp:49
localIndex size() const
Get the "size" of the group, which determines the number of elements in resizable wrappers.
Definition: Group.hpp:1315
GEOS_HOST_DEVICE void setup(localIndex const ei, StackVariables &stack) const
Performs the setup phase for the kernel.
static StackVariables launch(localIndex const numElems, KERNEL_TYPE const &kernelComponent)
Performs the kernel launch.
GEOS_HOST_DEVICE void computeScalingFactor(localIndex const ei, StackVariables &stack, FUNC &&kernelOp=NoOpFunc{}) const
Compute the local value of the scaling factor.
SolutionScalingKernel(real64 const maxRelativePresChange, real64 const maxAbsolutePresChange, real64 const maxCompFracChange, real64 const maxRelativeCompDensChange, globalIndex const rankOffset, integer const numComp, string const dofKey, ElementSubRegionBase const &subRegion, arrayView1d< real64 const > const localSolution, arrayView1d< real64 const > const pressure, arrayView2d< real64 const, compflow::USD_COMP > const compDens, arrayView1d< real64 > pressureScalingFactor, arrayView1d< real64 > compDensScalingFactor)
Create a new kernel instance.
GEOS_HOST_DEVICE void compute(localIndex const ei, StackVariables &stack) const
Compute the local value.
real64 const m_maxRelativePresChange
Max allowed changes in primary variables.
ArrayView< T, 1 > arrayView1d
Alias for 1D array view.
Definition: DataTypes.hpp:180
GEOS_GLOBALINDEX_TYPE globalIndex
Global index type (for indexing objects across MPI partitions).
Definition: DataTypes.hpp:88
double real64
64-bit floating point type.
Definition: DataTypes.hpp:99
GEOS_LOCALINDEX_TYPE localIndex
Local index type (for indexing objects within an MPI partition).
Definition: DataTypes.hpp:85
std::int32_t integer
Signed integer type.
Definition: DataTypes.hpp:82
ArrayView< T, 2, USD > arrayView2d
Alias for 2D array view.
Definition: DataTypes.hpp:196