Implement arbitrary region statistics#3037
Conversation
|
Great idea. Can we make it work with '' define boxes too ? |
| GEOS_HOST_DEVICE | ||
| static constexpr real64 safeInverse( real64 const val ) | ||
| { | ||
| return (val < LvArray::NumericLimits< real64 >::epsilon) ? 0.0 : 1.0 / val; | ||
| } |
There was a problem hiding this comment.
Could this be exposed in a header that is commonly used for calculations? I think safe-dividing could be useful to everyone. :)
| regData[Statistics::CELL_COUNT] = MpiWrapper::sum( regData[Statistics::CELL_COUNT] ); | ||
| regData[Statistics::STATIC_PORE_VOLUME] = MpiWrapper::sum( regData[Statistics::STATIC_PORE_VOLUME] ); | ||
| regData[Statistics::PORE_VOLUME] = MpiWrapper::sum( regData[Statistics::PORE_VOLUME] ); | ||
|
|
||
| regData[Statistics::MINIMUM_PRESSURE] = MpiWrapper::min( regData[Statistics::MINIMUM_PRESSURE] ); | ||
| regData[Statistics::MAXIMUM_PRESSURE] = MpiWrapper::max( regData[Statistics::MAXIMUM_PRESSURE] ); | ||
| regData[Statistics::MINIMUM_TEMPERATURE] = MpiWrapper::min( regData[Statistics::MINIMUM_TEMPERATURE] ); | ||
| regData[Statistics::MAXIMUM_TEMPERATURE] = MpiWrapper::max( regData[Statistics::MAXIMUM_TEMPERATURE] ); | ||
|
|
||
| regData[Statistics::AVERAGE_PRESSURE] = MpiWrapper::sum( regData[Statistics::AVERAGE_PRESSURE] ); | ||
| regData[Statistics::AVERAGE_TEMPERATURE] = MpiWrapper::sum( regData[Statistics::AVERAGE_TEMPERATURE] ); | ||
|
|
||
| for( integer propIndex = Statistics::PHASE_PORE_VOLUME; propIndex < Statistics::END; ++propIndex ) | ||
| { | ||
| regData[propIndex] = MpiWrapper::sum( regData[propIndex] ); | ||
| } |
There was a problem hiding this comment.
I don't know the impact, but I'm wondering if this kind of repeated reductions should & could be grouped to be optimized.
|
|
||
| registerWrapper( viewKeyStruct::propertyNamesString(), &m_propertyNames ). | ||
| setInputFlag( InputFlags::OPTIONAL ). | ||
| setDescription( "The list of names of properties to report" ); |
There was a problem hiding this comment.
| setDescription( "The list of names of properties to report" ); | |
| setDescription( "The list of names of properties to report. If leaved empty, all available properties are selected." ); |
| m_propertyNameTypes.emplace_back( PropertyNameType::Pressure ); | ||
| m_propertyNameTypes.emplace_back( PropertyNameType::Temperature ); | ||
| m_propertyNameTypes.emplace_back( PropertyNameType::StaticPoreVolume ); | ||
| m_propertyNameTypes.emplace_back( PropertyNameType::PoreVolume ); | ||
| m_propertyNameTypes.emplace_back( PropertyNameType::PhaseVolumeFraction ); | ||
| m_propertyNameTypes.emplace_back( PropertyNameType::PhasePoreVolume ); | ||
| m_propertyNameTypes.emplace_back( PropertyNameType::PhaseMass ); | ||
| m_propertyNameTypes.emplace_back( PropertyNameType::PhaseDensity ); | ||
| m_propertyNameTypes.emplace_back( PropertyNameType::PhaseViscosity ); | ||
| m_propertyNameTypes.emplace_back( PropertyNameType::PhaseComponentMass ); | ||
| m_propertyNameTypes.emplace_back( PropertyNameType::ComponentMass ); |
There was a problem hiding this comment.
In order to automatically iterate over enum labels :
| m_propertyNameTypes.emplace_back( PropertyNameType::Pressure ); | |
| m_propertyNameTypes.emplace_back( PropertyNameType::Temperature ); | |
| m_propertyNameTypes.emplace_back( PropertyNameType::StaticPoreVolume ); | |
| m_propertyNameTypes.emplace_back( PropertyNameType::PoreVolume ); | |
| m_propertyNameTypes.emplace_back( PropertyNameType::PhaseVolumeFraction ); | |
| m_propertyNameTypes.emplace_back( PropertyNameType::PhasePoreVolume ); | |
| m_propertyNameTypes.emplace_back( PropertyNameType::PhaseMass ); | |
| m_propertyNameTypes.emplace_back( PropertyNameType::PhaseDensity ); | |
| m_propertyNameTypes.emplace_back( PropertyNameType::PhaseViscosity ); | |
| m_propertyNameTypes.emplace_back( PropertyNameType::PhaseComponentMass ); | |
| m_propertyNameTypes.emplace_back( PropertyNameType::ComponentMass ); | |
| constexpr auto labelCount = EnumStrings< PropertyNameType >::count; | |
| for( integer i = 0; i < labelCount; ++i ) | |
| { | |
| m_propertyNameTypes.emplace_back( i ); | |
| } |
... we could add a getEnumStringsCount( ENUM const ) in the ENUM_STRINGS() macro :
inline constexpr size_t getEnumStringsCount( ENUM const ) \
{ \
constexpr char const * arr[] { __VA_ARGS__ }; \
constexpr auto s = std::end( arr ) - std::begin( arr ); \
return s; \
} \
... and a constexpr count in EnumStrings :
inline static constexpr size_t count = getEnumStringsCount( enum_type{} );
| std::ofstream outputFile( m_outputDir + "/" + viewKeyStruct::fileNameString() + ".csv" ); | ||
|
|
||
| writeArray( outputFile, propNames ); | ||
| writeArray( outputFile, propUnits ); | ||
| writeArray( outputFile, regNames ); | ||
| writeArray( outputFile, phaseNames ); | ||
| writeArray( outputFile, compNames ); | ||
|
|
||
| outputFile.close(); |
| string const massUnit = useMass ? "kg" : "mol"; | ||
| string const densityUnit = useMass ? "kg/m^3" : "mol/m^3"; |
There was a problem hiding this comment.
| string const massUnit = useMass ? "kg" : "mol"; | |
| string const densityUnit = useMass ? "kg/m^3" : "mol/m^3"; | |
| string const massUnit = getSymbol( useMass ? units::Unit::Mass : units::Unit::Mole ); | |
| string const densityUnit = getSymbol( useMass ? units::Unit::MassRate : units::Unit::MoleRate ); |
| struct RegionMultiphaseStatistics::Statistics | ||
| { | ||
| static constexpr integer MAX_NUM_PHASE = 3; | ||
| static constexpr integer MAX_NUM_COMPS = 5; | ||
| /// Indices for properties | ||
| static constexpr integer CELL_COUNT = 0; | ||
| static constexpr integer STATIC_PORE_VOLUME = 1; | ||
| static constexpr integer PORE_VOLUME = 2; |
There was a problem hiding this comment.
Here, what do you think of grouping the indices in a C Enum?
| struct RegionMultiphaseStatistics::Statistics | |
| { | |
| static constexpr integer MAX_NUM_PHASE = 3; | |
| static constexpr integer MAX_NUM_COMPS = 5; | |
| /// Indices for properties | |
| static constexpr integer CELL_COUNT = 0; | |
| static constexpr integer STATIC_PORE_VOLUME = 1; | |
| static constexpr integer PORE_VOLUME = 2; | |
| struct RegionMultiphaseStatistics::Statistics | |
| { | |
| static constexpr integer MAX_NUM_PHASE = 3; | |
| static constexpr integer MAX_NUM_COMPS = 5; | |
| enum PropIds : integer { | |
| CELL_COUNT, | |
| STATIC_PORE_VOLUME, | |
| PORE_VOLUME, | |
| // [...] | |
| END | |
| }; |
| GEOS_HOST_DEVICE Statistics( Statistics const & rhs ) | ||
| { | ||
| for( integer i = 0; i < END; i++ ) | ||
| { | ||
| m_data[i] = rhs.m_data[i]; | ||
| } | ||
| } | ||
|
|
||
| GEOS_HOST_DEVICE Statistics const & operator=( Statistics const & rhs ) | ||
| { | ||
| for( integer i = 0; i < END; i++ ) | ||
| { | ||
| m_data[i] = rhs.m_data[i]; | ||
| } | ||
| return *this; | ||
| } | ||
|
|
||
| Statistics( Statistics && rhs ) | ||
| { | ||
| std::swap( m_data, rhs.m_data ); | ||
| } |
| RAJA::ReduceSum< ReducePolicy< POLICY >, Statistics > sumStats( RAJA::operators::plus< Statistics >::identity() ); | ||
| RAJA::ReduceMin< ReducePolicy< POLICY >, Statistics > minStats( RAJA::operators::minimum< Statistics >::identity() ); |
There was a problem hiding this comment.
Is it possible to declare a RAJA::ReduceSum< ReducePolicy< POLICY >, real64[] >?
| } ); | ||
|
|
||
| // Create the csv file if requires | ||
| if( 0 < getLogLevel() && 0 < m_writeCSV && MpiWrapper::commRank() == 0 ) |
There was a problem hiding this comment.
Why this condition is different to the one below? (in RegionMultiphaseStatistics::computeRegionStatistics()).
|
Superceded by #4005 |
The purpose of this PR is to allow the user to report region statistics for arbitrary cell regions (cell collections) that are not linked to the simulation (solvers or constitutive models).
The idea is that the user will create a task similar to
CompositionalMultiphaseStatistics. With that they can specify the properties to report and then target this with an event.In this example, there are 3 non-overlapping regions named
PLATFORM_A,PLATFORM_B1andPLATFORM_B2not linked to the simulation and the user wants statistics for pressure, pore volume and volume fraction in these regions. The 3 regions are identified by an attribute and these are assigned values 13, 28 and 3 respectively. The creation of the task will create a fieldNameREGION.STATISTICS_regionfor each grid cell. The user can use this field to load a property and mark the cells belonging to each region. For example