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