GEOS
StatisticsAggregatorBaseHelpers.hpp
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 
16 #include "mesh/MeshBody.hpp"
18 
19 #include "LvArray/src/math.hpp"
20 #include "common/DataTypes.hpp"
21 #include "common/format/Format.hpp"
23 #include "common/logger/Logger.hpp"
25 #include "dataRepository/Group.hpp"
27 #include "mesh/ElementRegionBase.hpp"
30 #include "mesh/MeshLevel.hpp"
31 
32 namespace geos
33 {
34 
35 namespace internal
36 {
37 
43 inline bool isStatisticsRegion( ElementRegionBase const & region )
44 {
45  // we only process cell and surface regions (wells are skipped)
46  return dynamic_cast< CellElementRegion const * >( &region ) != nullptr ||
47  dynamic_cast< SurfaceElementRegion const * >( &region ) != nullptr;
48 }
49 
50 } // namespace internal
51 
52 inline RegionStatisticsBase::RegionStatisticsBase( string const & targetName,
53  dataRepository::Group * const parent,
54  string_view setName,
55  bool const dataOutputEnabled ):
56  dataRepository::Group( targetName, parent ),
57  m_time( std::numeric_limits< double >::lowest() ),
58  m_setName( setName )
59 {
60  Group::setRestartFlags( dataOutputEnabled ?
63 
64  // TODO : registerWrappers to store results in HDF5 (but need repairing of 1D HDF5 outputs)
65 }
66 
67 template< typename Impl >
69  dataRepository::Group & meshBodies,
70  bool const dataOutputEnabled ):
71  m_ownerDataContext( ownerDataContext ),
72  m_dataOutputEnabled( dataOutputEnabled ),
73  m_meshBodies( meshBodies ),
74  m_isAnySetsIntersecting( false )
75 {}
76 
77 template< typename Impl >
78 std::set< string >
80  string_array const & regionNames )
81 {
82  std::set< string > foundSetNames;
83 
84  mesh.getElemManager().forElementRegions< ElementRegionBase >( regionNames,
85  [&] ( localIndex &,
86  ElementRegionBase const & region )
87  {
88  if( !internal::isStatisticsRegion( region ) )
89  return;
90 
91  region.forElementSubRegions< ElementSubRegionBase >( [&] ( ElementSubRegionBase const & subRegion ) {
92  dataRepository::Group const & sets = subRegion.sets();
93  sets.forWrappers< SetType >( [&] ( dataRepository::Wrapper< SetType > const & set )
94  {
95  foundSetNames.emplace( set.getName() );
96  } );
97  } );
98  } );
99 
100  return foundSetNames;
101 }
102 
103 template< typename Impl >
104 void
106 {
107  solver.forDiscretizationOnMeshTargets( m_meshBodies, [&] ( string const & meshBodyName,
108  MeshLevel & mesh,
109  string_array const & regionNames )
110  {
111  // getting the container of all requesters statistics groups (can be already initialized)
112  dataRepository::Group * meshStatsGroup = mesh.getGroupPointer( string( ViewKeys::statisticsString()) );
113  if( meshStatsGroup == nullptr )
114  meshStatsGroup = &mesh.registerGroup( string( ViewKeys::statisticsString() ) );
115 
116  // registering the container of instance statistics groups (must be unique for this instance)
117  string const & ownerName = getOwnerName();
118  GEOS_ERROR_IF_NE_MSG( meshStatsGroup->hasGroup( ownerName ), false,
119  GEOS_FMT( "A statistics aggregator have already been requested for '{}'.",
120  ownerName ),
121  m_ownerDataContext );
122  meshStatsGroup->registerGroup( ownerName );
123 
124  MeshBody const & body = m_meshBodies.getGroup< MeshBody >( meshBodyName );
125 
127  std::set< string > foundSetNames = getMeshLevelPartialSetNames( mesh, regionNames );
128 
129  { // remembering the path of this discretization
130  DiscretizationSetPath const path {
131  /* .m_meshBody = */ body.getIndexInParent(),
132  /* .m_meshLevel = */ mesh.getIndexInParent(),
133  /* .m_setNames = */ string_array( foundSetNames.begin(), foundSetNames.end()),
134  /* .m_regionNames = */ regionNames,
135  /* .m_setsCompound = */ {},
136  };
137  m_discretizationsPaths.emplace_back( path );
138  }
139  } );
140 }
141 
142 template< typename Impl >
143 void
145  string_array const & setNames )
146 {
147  m_setNames.insert( setNames.begin(), setNames.end() );
148  if( m_setNames.empty())
149  m_setNames.emplace( "all" );
150 
151  bool regionFound = false;
152  bool subRegionFound = false;
153  std::set< string > confirmedSets;
154 
155  for( auto & path : m_discretizationsPaths )
156  {
157  MeshLevel & mesh = getMeshLevel( path );
158  ElementRegionManager & elemManager = mesh.getElemManager();
159  dataRepository::Group & statisticsGroup = getInstanceStatisticsGroup( mesh );
160  StatsGroupType & meshStats = registerStatsFunc( statisticsGroup, string( ViewKeys::setsStatisticsString() ),
161  "", m_dataOutputEnabled );
162  SetsCompound meshSetsCompounds;
163  bool isAnySetIntersects = false;
164 
165  // registering all stats Group in the dataRepository for each set
166  for( string const & setName : m_setNames )
167  {
168  StatsGroupType & meshSetStats = registerStatsFunc( meshStats, setName,
169  setName, m_dataOutputEnabled );
170 
171  for( size_t regionId = 0; regionId < path.m_regionNames.size(); ++regionId )
172  {
173  ElementRegionBase & region = elemManager.getRegion< ElementRegionBase >( path.m_regionNames[regionId] );
174  if( internal::isStatisticsRegion( region ) )
175  {
176  StatsGroupType & setRegionStats = registerStatsFunc( meshSetStats, region.getName(),
177  setName, m_dataOutputEnabled );
178  stdMap< string, SetType > & regionSetsCompounds = meshSetsCompounds.get_inserted( region.getName() );
179  regionFound = true;
180 
181  region.forElementSubRegions< ElementSubRegionBase >( [&] ( ElementSubRegionBase & subRegion )
182  {
183  registerStatsFunc( setRegionStats, subRegion.getName(),
184  setName, false );
185  subRegionFound = true;
186 
187  auto const * const subRegionSetWrapper = subRegion.sets().getWrapperPointer< SetType >( setName );
188  if( subRegionSetWrapper != nullptr )
189  {
190  if( !subRegionSetWrapper->reference().empty() )
191  confirmedSets.emplace( setName );
192 
193  // Insert the set elements ids in the mesh-level compound. If doubles are found, sets intersect.
194  SetViewType const & subRegionSet = subRegionSetWrapper->reference();
195  arrayView1d< integer const > const elemGhostRank = subRegion.ghostRank();
196  SetType & subRegionSetsCompound = regionSetsCompounds.get_inserted( subRegion.getName() );
197  for( localIndex setIter = 0; setIter < subRegionSet.size(); ++setIter )
198  {
199  localIndex elemId = subRegionSet[setIter];
200  if( elemGhostRank[elemId] < 0 )
201  {
202  if( !subRegionSetsCompound.insert( elemId ) )
203  isAnySetIntersects = true;
204  }
205  }
206  }
207  } );
208  }
209  }
210  }
211 
212  // if needed, registering stats Group in the dataRepository for the compound set
213  isAnySetIntersects = (bool)( MpiWrapper::max( (unsigned char)( isAnySetIntersects ) ) );
214  if( isAnySetIntersects )
215  {
216  string_view setName = ViewKeys::compoundSetNameString();
217  StatsGroupType & meshSetStats = registerStatsFunc( meshStats, string( setName ),
218  setName, false );
219  for( size_t regionId = 0; regionId < path.m_regionNames.size(); ++regionId )
220  {
221  ElementRegionBase & region = elemManager.getRegion< ElementRegionBase >( path.m_regionNames[regionId] );
222  if( internal::isStatisticsRegion( region ) )
223  {
224  StatsGroupType & setRegionStats = registerStatsFunc( meshSetStats, region.getName(),
225  setName, false );
226 
227  region.forElementSubRegions< ElementSubRegionBase >( [&] ( ElementSubRegionBase & subRegion )
228  {
229  registerStatsFunc( setRegionStats, subRegion.getName(),
230  setName, false );
231 
232  path.m_setsCompound
233  .get_inserted( region.getName())
234  .insert( meshSetsCompounds
235  .at( region.getName() )
236  .extract( subRegion.getName() ) );
237  } );
238  }
239  }
240  }
241  }
242 
243  m_regionStatsState.m_isEnabled = true;
244  m_regionStatsState.m_isDirty = true;
245 
246  GEOS_ERROR_IF( regionFound == 0 || subRegionFound == 0,
247  GEOS_FMT( "{}: Missing region for computing statistics:\n- {} regions,\n- {} sub-regions.",
248  getOwnerName(),
249  regionFound ? "found" : "no",
250  subRegionFound ? "found" : "no" ),
251  m_ownerDataContext );
252 
253  // at this point, m_setNames content is element sets user *requests*: they are the same on every ranks,
254  // but we don't know yet if any of these set is missing or empty (=> confirmedSets).
255  std::set< string > notFoundSets;
256  for( string const & requestedSetName : m_setNames )
257  {
258  if( MpiWrapper::max( confirmedSets.count( requestedSetName ) ) == 0 )
259  notFoundSets.emplace( requestedSetName );
260  }
261  if( MpiWrapper::commRank() == 0 )
262  GEOS_ERROR_IF( !notFoundSets.empty(),
263  GEOS_FMT( "During retrieval of statistics element sets, the following set(s) could not be "
264  "found or does not contain any element:\n- {}",
265  stringutilities::join( notFoundSets, "\n- " ) ),
266  m_ownerDataContext );
267 }
268 
269 template< typename Impl >
270 MeshLevel &
272 {
273  MeshBody & body = m_meshBodies.getGroup< MeshBody >( path.m_meshBody );
274  MeshLevel & mesh = body.getMeshLevel( path.m_meshLevel );
275  return mesh;
276 }
277 
278 template< typename Impl >
281 {
282  // considering everything is initialized, or else, crash gracefully
283  dataRepository::Group & meshStatsGroup = mesh.getGroup( string( ViewKeys::statisticsString() ) );
284  dataRepository::Group & instanceStatisticsGroup = meshStatsGroup.getGroup( getOwnerName() );
285  return instanceStatisticsGroup;
286 }
287 
288 template< typename Impl >
289 typename StatsAggregatorBase< Impl >::StatsGroupType &
291 getMeshLevelStatistics( MeshLevel & mesh ) const
292 {
293  // considering everything is initialized, or else, crash gracefully
294  dataRepository::Group & instanceStatisticsGroup = getInstanceStatisticsGroup( mesh );
295  return instanceStatisticsGroup.getGroup< StatsGroupType >( string( ViewKeys::setsStatisticsString()) );
296 }
297 
298 template< typename Impl >
299 typename StatsAggregatorBase< Impl >::StatsGroupType &
301  string_view requestedSetName ) const
302 {
303  // considering mesh-level stats structure is initialized, or else, crash gracefully
304  StatsGroupType & meshStats = getMeshLevelStatistics( mesh );
305  string const setName = string( requestedSetName.empty() ? "all" : requestedSetName );
306  StatsGroupType * const stats = meshStats.template getGroupPointer< StatsGroupType >( setName );
307  GEOS_THROW_IF( stats == nullptr,
308  GEOS_FMT( "Element set '{}' statistics data structure not found, has the set been requested?\nRequested element sets:\n- {}",
309  setName, stringutilities::join( m_setNames, "\n- " ) ),
310  InputError, m_ownerDataContext );
311  return *stats;
312 }
313 
314 template< typename Impl >
315 typename StatsAggregatorBase< Impl >::StatsGroupType &
317 {
318  // considering mesh-level stats structure is initialized, or else, crash gracefully
319  StatsGroupType & meshStats = getMeshLevelStatistics( mesh );
320  string const setName = string( ViewKeys::compoundSetNameString() );
321  StatsGroupType * const stats = meshStats.template getGroupPointer< StatsGroupType >( setName );
322  GEOS_THROW_IF( stats == nullptr,
323  GEOS_FMT( "Compound element set data structure not found ({}), is the aggregator initialized? Was the compound needed?\nRequested element sets:\n- {}",
324  setName, stringutilities::join( m_setNames, "\n- " ) ),
325  InputError, m_ownerDataContext );
326  return *stats;
327 }
328 
329 template< typename Impl >
330 bool
331 StatsAggregatorBase< Impl >::isCompoundSetStatistics( StatsGroupType const & setStats ) const
332 {
333  return setStats.getSetName() == ViewKeys::compoundSetNameString();
334 }
335 
336 template< typename Impl >
337 typename StatsAggregatorBase< Impl >::StatsGroupType &
339  string_view regionName,
340  string_view setName ) const
341 {
342  StatsGroupType & setStats = getSetStatistics( mesh, setName );
343  StatsGroupType * const stats = setStats.template getGroupPointer< StatsGroupType >( string( regionName ) );
344  GEOS_THROW_IF( stats == nullptr,
345  GEOS_FMT( "Region '{}' not found to get region statistics, is it a target of the reservoir solver?\n"
346  "Available target regions:\n- {}",
347  regionName, stringutilities::join( setStats.getSubGroupsNames(), "\n- " ) ),
348  InputError, m_ownerDataContext );
349  return *stats;
350 }
351 
352 template< typename Impl >
353 void
355 {
356  for( auto const & path : m_discretizationsPaths )
357  {
358  MeshLevel & mesh = getMeshLevel( path );
359  StatsGroupType & meshLevelStats = getMeshLevelStatistics( mesh );
360 
361  func( mesh, meshLevelStats );
362  }
363 }
364 
365 template< typename Impl >
366 void
368  StatsGroupType & meshLevelStats,
369  bool enableCompoundSet,
370  RegionStatsFunc< MeshLevelSet > const & func ) const
371 {
372  meshLevelStats.template forSubGroups< StatsGroupType >( [&] ( StatsGroupType & setStats )
373  {
374  if( enableCompoundSet || setStats.getSetName() != ViewKeys::compoundSetNameString() )
375  {
376  MeshLevelSet meshSet {
377  /* .mesh = */ mesh,
378  /* .setName = */ setStats.getTargetName(),
379  };
380 
381  func( meshSet, setStats );
382  }
383  } );
384 }
385 
386 template< typename Impl >
387 void
389  StatsGroupType & setStats,
390  RegionStatsFunc< ElementRegionBase & > const & func ) const
391 {
392  ElementRegionManager & elemManager = meshSet.mesh.getElemManager();
393  setStats.template forSubGroups< StatsGroupType >( [&] ( StatsGroupType & setRegionStats )
394  {
395  string_view regionName = setRegionStats.getTargetName();
396  ElementRegionBase & region = elemManager.getRegion< ElementRegionBase >( string( regionName ) );
397  if( internal::isStatisticsRegion( region ) ) // we only process cell and surface regions (wells are skipped)
398  func( region, setRegionStats );
399  } );
400 }
401 
402 template< typename Impl >
403 void
405  StatsGroupType & setRegionStats,
406  RegionStatsFunc< ElementSubRegionBase & > const & func ) const
407 {
408  setRegionStats.template forSubGroups< StatsGroupType >( [&] ( StatsGroupType & subRegionStatistics )
409  {
410  string_view subRegionName = subRegionStatistics.getTargetName();
411  ElementSubRegionBase & subRegion = setRegion.getSubRegion< ElementSubRegionBase >( string( subRegionName ) );
412 
413  func( subRegion, subRegionStatistics );
414  } );
415 }
416 
417 template< typename Impl >
418 bool
419 StatsAggregatorBase< Impl >::isComputed( real64 const timeRequest, StatsGroupType const & stats )
420 {
421  real64 const timePrecisionScale = LvArray::math::max( LvArray::math::abs( timeRequest ),
422  LvArray::math::abs( stats.m_time ) );
423  static constexpr real64 timeRelTol = 1.0e-12;
424 
425  return
426  !m_regionStatsState.m_isDirty &&
427  LvArray::math::abs( timeRequest - stats.m_time ) < timeRelTol * timePrecisionScale;
428 }
429 
430 template< typename Impl >
431 void
433 {
434  m_regionStatsState.m_isDirty = true;
435 }
436 
437 template< typename Impl >
438 bool
440 {
442 
443  m_warnings.clear();
444 
445  for( auto const & path : m_discretizationsPaths )
446  {
447  MeshLevel & mesh = getMeshLevel( path );
448  StatsGroupType & meshLevelStats = getMeshLevelStatistics( mesh );
449  bool const isSetsCompoundEnabled = !path.m_setsCompound.empty();
450 
451  // computation of sub region stats for each selected set
452  initStats( meshLevelStats, timeRequest );
453  forRegionStatistics( mesh, meshLevelStats, true,
454  [&, timeRequest] ( MeshLevelSet meshSet, StatsGroupType & setStats )
455  {
456  initStats( setStats, timeRequest );
457  forRegionStatistics( meshSet, setStats,
458  [&, timeRequest] ( ElementRegionBase & region, StatsGroupType & regionStats )
459  {
460  initStats( regionStats, timeRequest );
461  forRegionStatistics( region, regionStats,
462  [&, timeRequest] ( ElementSubRegionBase & subRegion, StatsGroupType & subRegionStats )
463  {
464  initStats( subRegionStats, timeRequest );
465 
466  SetType const & targetSet = meshSet.setName == ViewKeys::compoundSetNameString() ?
467  path.m_setsCompound.at( region.getName() ).at( subRegion.getName() ) :
468  subRegion.sets().getReference< SetType >( string( meshSet.setName ) );
469  computeSubRegionRankStats( subRegion, subRegionStats, targetSet );
470  } );
471  } );
472  } );
473 
474  // aggregation of computations from the sub regions
475  forRegionStatistics( mesh, meshLevelStats, true,
476  [&] ( MeshLevelSet meshSet, StatsGroupType & setStats )
477  {
478  forRegionStatistics( meshSet, setStats,
479  [&] ( ElementRegionBase & region, StatsGroupType & regionStats )
480  {
481  forRegionStatistics( region, regionStats,
482  [&] ( ElementSubRegionBase &, StatsGroupType & subRegionStats )
483  {
484  aggregateStats( regionStats, subRegionStats );
485  // sub-region stats finalization is disabled, it does not seem useful
486  // mpiAggregateStats( subRegionStats );
487  // postAggregateStats( subRegionStats );
488  } );
489 
490  aggregateStats( setStats, regionStats );
491 
492  mpiAggregateStats( regionStats );
493  postAggregateStats( regionStats );
494  } );
495 
496  // if there is no compound set, we can simply aggregate each set statistics to the mesh-level statistics.
497  // if there is one, we will only take into account the statistics of the compound set.
498  if( !isSetsCompoundEnabled || isCompoundSetStatistics( setStats ) )
499  {
500  aggregateStats( meshLevelStats, setStats );
501  }
502 
503  mpiAggregateStats( setStats );
504  postAggregateStats( setStats );
505  } );
506 
507  mpiAggregateStats( meshLevelStats );
508  postAggregateStats( meshLevelStats );
509  }
510 
511  m_regionStatsState.m_isDirty = false;
512 
513  return true;
514 }
515 
516 } /* namespace geos */
#define GEOS_ERROR_IF(COND,...)
Conditionally raise a hard error and terminate the program.
Definition: Logger.hpp:211
#define GEOS_ERROR_IF_NE_MSG(lhs, rhs,...)
Raise a hard error if two values are not equal.
Definition: Logger.hpp:442
#define GEOS_THROW_IF(COND, MSG,...)
Conditionally raise a hard error and terminate the program.
Definition: Logger.hpp:289
#define GEOS_MARK_FUNCTION
Mark function with both Caliper and NVTX if enabled.
The ElementRegionBase is the base class to manage the data stored at the element level.
void forElementSubRegions(LAMBDA &&lambda) const
Apply a lambda to all subregions.
SUBREGIONTYPE const & getSubRegion(KEY_TYPE const &key) const
Get a reference to a subregion.
The ElementRegionManager class provides an interface to ObjectManagerBase in order to manage ElementR...
void forElementRegions(LAMBDA &&lambda)
This function is used to launch kernel function over all the element regions with region type = Eleme...
T const & getRegion(KEY_TYPE const &key) const
Get a element region.
The class is used to manage mesh body.
Definition: MeshBody.hpp:36
MeshLevel & getMeshLevel(T const &level) const
Get a reference to a MeshLevel.
Definition: MeshBody.hpp:100
Class facilitating the representation of a multi-level discretization of a MeshBody.
Definition: MeshLevel.hpp:42
ElementRegionManager const & getElemManager() const
Get the element region manager.
Definition: MeshLevel.hpp:207
Group & sets()
Get the group holding the object sets.
RegionStatisticsBase(string const &targetName, dataRepository::Group *const parent, string_view setName, bool dataOutputEnabled)
Construct a new Region Statistics Base object.
Reponsible of computing physical statistics over the grid, registering the result in the data reposit...
dataRepository::Group & getInstanceStatisticsGroup(MeshLevel &mesh) const
Get the Instance Statistics Group for the given mesh-level.
void initStatisticsAggregation(SolverType &solver)
Enable the computation of any statistics, explores the data structure to collect them.
StatsGroupType & getMeshLevelStatistics(MeshLevel &mesh) const
StatsAggregatorBase(dataRepository::DataContext const &ownerDataContext, dataRepository::Group &meshBodies, bool statsOutputEnabled)
Construct a new Stats Aggregator object.
void enableRegionStatisticsAggregation(RegionStatsRegisterFunc &&registerStatsFunc, string_array const &setNames)
Enable the computation of region statistics, initialize data structure to collect them....
StatsGroupType & getRegionStatistics(MeshLevel &mesh, string_view regionName, string_view setName="") const
std::function< void(OwnerType, StatsGroupType &) > RegionStatsFunc
Standard function signature for any functor that applies on statistics group instances (StatsGroupTyp...
MeshLevel & getMeshLevel(DiscretizationSetPath const &path) const
StatsGroupType & getSetStatistics(MeshLevel &mesh, string_view setName="") const
static std::set< string > getMeshLevelPartialSetNames(MeshLevel const &mesh, string_array const &regionNames)
TODO.
StatsGroupType & getCompoundSetStatistics(MeshLevel &mesh) const
bool isCompoundSetStatistics(StatsGroupType const &stats) const
std::function< StatsGroupType &(dataRepository::Group &, string const &, string_view, bool) > RegionStatsRegisterFunc
A functor that can be used to register a statistics Group instance. Parameters:
void forRegionStatistics(RegionStatsFunc< MeshLevel & > const &functor) const
Execute the given functor on each mesh-level (discretization) available for this instance.
T * getGroupPointer(KEY const &key)
Return a pointer to a sub-group of the current Group.
Definition: Group.hpp:299
localIndex getIndexInParent() const
Get the group's index within its parent group.
Definition: Group.hpp:1391
T & registerGroup(string const &name, std::unique_ptr< T > newObject)
Register a new Group as a sub-group of current Group.
Definition: Group.hpp:200
void setRestartFlags(RestartFlags flags)
Set flags that control restart output of this group.
Definition: Group.hpp:1428
string const & getName() const
Get group name.
Definition: Group.hpp:1329
GEOS_DECLTYPE_AUTO_RETURN getReference(LOOKUP_TYPE const &lookup) const
Look up a wrapper and get reference to wrapped object.
Definition: Group.hpp:1273
T & getGroup(KEY const &key)
Return a reference to a sub-group of the current Group.
Definition: Group.hpp:318
bool hasGroup(string const &name) const
Check whether a sub-group exists.
Definition: Group.hpp:405
void forWrappers(LAMBDA &&lambda)
Apply the given functor to wrappers.
Definition: Group.hpp:637
@ WRITE_AND_READ
Write and read from restart.
@ NO_WRITE
Do not write into restart.
ArrayView< T, 1 > arrayView1d
Alias for 1D array view.
Definition: DataTypes.hpp:179
stdVector< string > string_array
A 1-dimensional array of geos::string types.
Definition: DataTypes.hpp:361
std::string string
String type.
Definition: DataTypes.hpp:90
std::set< T > set
A set of local indices.
Definition: DataTypes.hpp:262
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
internal::StdMapWrapper< std::map< Key, T, Compare, Allocator >, USE_STD_CONTAINER_BOUNDS_CHECKING > stdMap
std::string_view string_view
String type.
Definition: DataTypes.hpp:93
Exception class used to report errors in user input.
static T max(T const &value, MPI_Comm comm=MPI_COMM_GEOS)
Convenience function for a MPI_Allreduce using a MPI_MAX operation.
localIndex m_meshLevel
The id of the mesh level in the mesh body.
localIndex m_meshBody
The id of the mesh body in the "meshBodies" Group.
Allow to reference a set in a given MeshLevel structure.