GEOS
StatisticsKernel.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_STATISTICSKERNEL_HPP
21 #define GEOS_PHYSICSSOLVERS_FLUIDFLOW_COMPOSITIONAL_STATISTICSKERNEL_HPP
22 
23 #include "common/DataLayouts.hpp"
24 #include "common/DataTypes.hpp"
25 #include "common/GEOS_RAJA_Interface.hpp"
26 #include "constitutive/relativePermeability/Layouts.hpp"
27 
28 
29 namespace geos
30 {
31 
32 namespace isothermalCompositionalMultiphaseBaseKernels
33 {
34 
35 /******************************** StatisticsKernel ********************************/
36 
38 {
39  template< typename POLICY >
40  static void
41  saveDeltaPressure( localIndex const size,
42  arrayView1d< real64 const > const & pres,
43  arrayView1d< real64 const > const & initPres,
44  arrayView1d< real64 > const & deltaPres )
45  {
46  forAll< parallelDevicePolicy<> >( size, [=] GEOS_HOST_DEVICE ( localIndex const ei )
47  {
48  deltaPres[ei] = pres[ei] - initPres[ei];
49  } );
50  }
51 
52  template< typename POLICY >
53  static void
54  launch( SortedArrayView< localIndex const > const & targetSet,
55  integer const numComps,
56  integer const numPhases,
57  real64 const relpermThreshold,
58  arrayView1d< integer const > const & elemGhostRank,
59  arrayView1d< real64 const > const & volume,
60  arrayView1d< real64 const > const & pres,
61  arrayView1d< real64 const > const & deltaPres,
62  arrayView1d< real64 const > const & temp,
63  arrayView1d< real64 const > const & refPorosity,
64  arrayView2d< real64 const > const & porosity,
70  globalIndex & elemCount,
71  real64 & minPres,
72  real64 & avgPresNumerator,
73  real64 & maxPres,
74  real64 & minDeltaPres,
75  real64 & maxDeltaPres,
76  real64 & minTemp,
77  real64 & avgTempNumerator,
78  real64 & maxTemp,
79  real64 & totalUncompactedPoreVol,
80  arrayView1d< real64 > const & phaseDynamicPoreVol,
81  arrayView1d< real64 > const & phaseMass,
82  arrayView1d< real64 > const & trappedPhaseMass,
83  arrayView1d< real64 > const & immobilePhaseMass,
84  arrayView2d< real64 > const & dissolvedComponentMass )
85  {
86  RAJA::ReduceSum< parallelDeviceReduce, localIndex > subRegionElemCount( 0 );
87  RAJA::ReduceMin< parallelDeviceReduce, real64 > subRegionMinPres( LvArray::NumericLimits< real64 >::max );
88  RAJA::ReduceSum< parallelDeviceReduce, real64 > subRegionAvgPresNumerator( 0.0 );
89  RAJA::ReduceMax< parallelDeviceReduce, real64 > subRegionMaxPres( -LvArray::NumericLimits< real64 >::max );
90  RAJA::ReduceMin< parallelDeviceReduce, real64 > subRegionMinDeltaPres( LvArray::NumericLimits< real64 >::max );
91  RAJA::ReduceMax< parallelDeviceReduce, real64 > subRegionMaxDeltaPres( -LvArray::NumericLimits< real64 >::max );
92  RAJA::ReduceMin< parallelDeviceReduce, real64 > subRegionMinTemp( LvArray::NumericLimits< real64 >::max );
93  RAJA::ReduceSum< parallelDeviceReduce, real64 > subRegionAvgTempNumerator( 0.0 );
94  RAJA::ReduceMax< parallelDeviceReduce, real64 > subRegionMaxTemp( 0.0 );
95  RAJA::ReduceSum< parallelDeviceReduce, real64 > subRegionTotalUncompactedPoreVol( 0.0 );
96 
97  // For this arrays phaseDynamicPoreVol, phaseMass, dissolvedComponentMass,
98  // using an array of ReduceSum leads to a formal parameter overflow in CUDA.
99  // As a workaround, we use a slice with RAJA::atomicAdd instead
100 
101  forAll< parallelDevicePolicy<> >( targetSet.size(),
102  [targetSet,
103  numComps,
104  numPhases,
105  relpermThreshold,
106  elemGhostRank,
107  volume,
108  refPorosity,
109  porosity,
110  pres,
111  deltaPres,
112  temp,
113  phaseDensity,
114  phaseVolFrac,
115  phaseTrappedVolFrac,
116  phaseRelperm,
117  phaseCompFraction,
118  subRegionElemCount,
119  subRegionMinPres,
120  subRegionAvgPresNumerator,
121  subRegionMaxPres,
122  subRegionMinDeltaPres,
123  subRegionMaxDeltaPres,
124  subRegionMinTemp,
125  subRegionAvgTempNumerator,
126  subRegionMaxTemp,
127  subRegionTotalUncompactedPoreVol,
128  phaseDynamicPoreVol,
129  phaseMass,
130  trappedPhaseMass,
131  immobilePhaseMass,
132  dissolvedComponentMass] GEOS_HOST_DEVICE ( localIndex const setElemId )
133  {
134  localIndex ei = targetSet[setElemId];
135 
136  if( elemGhostRank[ei] >= 0 )
137  return;
138 
139  // To match our "reference", we have to use reference porosity here, not the actual porosity when we compute averages
140  real64 const uncompactedPoreVol = volume[ei] * refPorosity[ei];
141  real64 const dynamicPoreVol = volume[ei] * porosity[ei][0];
142 
143  subRegionElemCount += 1;
144 
145  subRegionMinPres.min( pres[ei] );
146  subRegionAvgPresNumerator += uncompactedPoreVol * pres[ei];
147  subRegionMaxPres.max( pres[ei] );
148 
149  subRegionMaxDeltaPres.max( deltaPres[ei] );
150  subRegionMinDeltaPres.min( deltaPres[ei] );
151 
152  subRegionMinTemp.min( temp[ei] );
153  subRegionAvgTempNumerator += uncompactedPoreVol * temp[ei];
154  subRegionMaxTemp.max( temp[ei] );
155  subRegionTotalUncompactedPoreVol += uncompactedPoreVol;
156  for( integer ip = 0; ip < numPhases; ++ip )
157  {
158  real64 const elemPhaseVolume = dynamicPoreVol * phaseVolFrac[ei][ip];
159  real64 const elemPhaseMass = phaseDensity[ei][0][ip] * elemPhaseVolume;
160  real64 const elemTrappedPhaseMass = phaseDensity[ei][0][ip] * dynamicPoreVol * phaseTrappedVolFrac[ei][0][ip];
161  // RAJA::atomicAdd used here because we do not use ReduceSum here (for the reason explained above)
162  RAJA::atomicAdd( parallelDeviceAtomic{}, &phaseDynamicPoreVol[ip], elemPhaseVolume );
163  RAJA::atomicAdd( parallelDeviceAtomic{}, &phaseMass[ip], elemPhaseMass );
164  RAJA::atomicAdd( parallelDeviceAtomic{}, &trappedPhaseMass[ip], elemTrappedPhaseMass );
165  if( phaseRelperm[ei][0][ip] < relpermThreshold )
166  {
167  RAJA::atomicAdd( parallelDeviceAtomic{}, &immobilePhaseMass[ip], elemPhaseMass );
168  }
169  for( integer ic = 0; ic < numComps; ++ic )
170  {
171  // RAJA::atomicAdd used here because we do not use ReduceSum here (for the reason explained above)
172  RAJA::atomicAdd( parallelDeviceAtomic{}, &dissolvedComponentMass[ip][ic], phaseCompFraction[ei][0][ip][ic] * elemPhaseMass );
173  }
174  }
175 
176  } );
177 
178  elemCount = globalIndex( subRegionElemCount.get() );
179 
180  minPres = subRegionMinPres.get();
181  avgPresNumerator = subRegionAvgPresNumerator.get();
182  maxPres = subRegionMaxPres.get();
183  minDeltaPres = subRegionMinDeltaPres.get();
184  maxDeltaPres = subRegionMaxDeltaPres.get();
185 
186  minTemp = subRegionMinTemp.get();
187  avgTempNumerator = subRegionAvgTempNumerator.get();
188  maxTemp = subRegionMaxTemp.get();
189 
190  totalUncompactedPoreVol = subRegionTotalUncompactedPoreVol.get();
191 
192  // dummy loop to bring data back to the CPU
193  forAll< serialPolicy >( 1, [phaseDynamicPoreVol, phaseMass, trappedPhaseMass, immobilePhaseMass, dissolvedComponentMass] ( localIndex const )
194  {
195  GEOS_UNUSED_VAR( phaseDynamicPoreVol, phaseMass, trappedPhaseMass, immobilePhaseMass, dissolvedComponentMass );
196  } );
197  }
198 };
199 
200 } // namespace isothermalCompositionalMultiphaseBaseKernels
201 
202 } // namespace geos
203 
204 
205 #endif //GEOS_PHYSICSSOLVERS_FLUIDFLOW_COMPOSITIONAL_STATISTICSKERNEL_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.
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
LvArray::SortedArrayView< T, localIndex, LvArray::ChaiBuffer > SortedArrayView
A sorted array view of local indices.
Definition: DataTypes.hpp:270
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
ArrayView< T, 3, USD > arrayView3d
Alias for 3D array view.
Definition: DataTypes.hpp:211