mirror of
https://github.com/OPM/opm-simulators.git
synced 2024-12-30 11:06:55 -06:00
d1d22668ea
The initial use case is calculating the phase-filled pore-volume weighted average of the fluid mass densities per PVT region. This value goes into calculating depth-corrected per-cell phase pressure values such as the BPPO and BPPG summary vectors. This class manages a single linear array which separately tracks the averages' numerators and denominators as running sums per region and region set. We pick this data structure to simplify the cross-rank reduction needed in MPI parallel runs. Client code is expected to add individual per-cell and per-phase contributions using the addCell() member function and then call the accumulateParallel() member to affect the cross-rank reduction. The averages will then be available through the fieldValue() and value() member functions. As a further view towards the initial use case, we track two different types of average per phase--one for the phase-filled volume and one for the pore-volume filled volume. The latter is the average we would get for the case of the phase saturation being one throughout the region. This alternative value is the fallback option for the case of the phase saturation being identically zero throughout the region.
354 lines
15 KiB
C++
354 lines
15 KiB
C++
// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
|
// vi: set et ts=4 sw=4 sts=4:
|
|
/*
|
|
Copyright 2024 Equinor AS
|
|
|
|
This file is part of the Open Porous Media project (OPM).
|
|
|
|
OPM is free software: you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation, either version 3 of the License, or
|
|
(at your option) any later version.
|
|
|
|
OPM is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with OPM. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#ifndef OPM_REGION_PHASE_POREVOL_AVERAGE_MODULE_HPP
|
|
#define OPM_REGION_PHASE_POREVOL_AVERAGE_MODULE_HPP
|
|
|
|
#include <opm/simulators/utils/ParallelCommunication.hpp>
|
|
|
|
#include <cstddef>
|
|
#include <functional>
|
|
#include <string>
|
|
#include <string_view>
|
|
#include <vector>
|
|
|
|
namespace Opm {
|
|
|
|
/// Facility for calculating volume-weighted average function values
|
|
/// over user-defined regions in parallel. Defaults to phase-filled
|
|
/// pore-volume averages, but falls back to simple pore-volume averages
|
|
/// if the saturation is identically zero in a region--i.e., calculates
|
|
/// what the average value would be if the phase fully occupied the
|
|
/// available pore-volume in this case.
|
|
class RegionPhasePoreVolAverage
|
|
{
|
|
public:
|
|
/// Minimal characteristics of a cell from a simulation grid.
|
|
struct CellValue
|
|
{
|
|
/// Function value
|
|
double value { 0.0 };
|
|
|
|
/// Phase saturation
|
|
double sat { 0.0 };
|
|
|
|
/// Reservoir condition pore-volume
|
|
double porv { 0.0 };
|
|
};
|
|
|
|
/// Compile-time disambiguation type for phases.
|
|
struct Phase
|
|
{
|
|
/// Phase index
|
|
unsigned int ix;
|
|
};
|
|
|
|
/// Compile-time disambiguation type for regions.
|
|
struct Region
|
|
{
|
|
/// Region index
|
|
unsigned int ix;
|
|
};
|
|
|
|
/// Call-back function type for accessing region arrays--typically the FIP* arrays.
|
|
using RegionArrayAccessor = std::function<const std::vector<int>&(const std::string&)>;
|
|
|
|
/// Constructor.
|
|
///
|
|
/// \param[in] comm Grid level global communicator.
|
|
///
|
|
/// \param[in] numPhases Number of phases for which to calculate
|
|
/// average values.
|
|
///
|
|
/// \param[in] regionNames List of region sets. Typically contains
|
|
/// one or more of the FIP* array names and, possibly, the PVTNUM
|
|
/// region set as well.
|
|
///
|
|
/// \param[in] getRegionArray Call-back function for accessing
|
|
/// region definition from region set names.
|
|
explicit RegionPhasePoreVolAverage(const Parallel::Communication& comm,
|
|
std::size_t numPhases,
|
|
const std::vector<std::string>& regionNames,
|
|
RegionArrayAccessor getRegionArray);
|
|
|
|
/// Retrieve field-level average function value for specific phase.
|
|
///
|
|
/// \param[in] p Phase for which to retrieve the field-level average
|
|
/// function value.
|
|
///
|
|
/// \return Field-level average function value for phase \p p.
|
|
double fieldValue(const Phase& p) const;
|
|
|
|
/// Retrieve region-level average function value for specific phase
|
|
/// in specific region of named region set.
|
|
///
|
|
/// \param[in] rset Named region set--e.g., "FIPNUM".
|
|
///
|
|
/// \param[in] p Phase for which to retrieve the region-level average
|
|
/// function value.
|
|
///
|
|
/// \param[in] r Region ID for which to retrieve the region-level
|
|
/// average function value.
|
|
///
|
|
/// \return Region-level average function value.
|
|
double value(std::string_view rset, const Phase& p, const Region& r) const;
|
|
|
|
/// Clear internal arrays in preparation of accumulating
|
|
/// region-level averages from per-cell contributions.
|
|
void prepareAccumulation();
|
|
|
|
/// Incorporate contributions from a single cell.
|
|
///
|
|
/// \param[in] activeCell Per-rank active cell ID--typically one of
|
|
/// the rank's interior cells.
|
|
///
|
|
/// \param[in] p Phase for which to incorporate the per-cell contribution.
|
|
///
|
|
/// \param[in] cv Single cell function value contribution.
|
|
void addCell(std::size_t activeCell, const Phase& p, const CellValue& cv);
|
|
|
|
/// Accumulate region-level average values across MPI ranks.
|
|
///
|
|
/// Typically the last step in calculating the region-level average
|
|
/// values. It is typically an error to call this function multiple
|
|
/// times without an intervening call to \c prepareAccumulation().
|
|
void accumulateParallel();
|
|
|
|
private:
|
|
/// Index type for value array.
|
|
using Ix = std::vector<double>::size_type;
|
|
|
|
/// Kinds of weighting functions.
|
|
enum AvgType {
|
|
SatPV, //< Weighted by phase-filled pore-volume.
|
|
PV, //< Weighted by total pore-volume (s=1).
|
|
|
|
// ---- Must be last enumerator ----
|
|
NumTypes, //< Number of averge types.
|
|
};
|
|
|
|
/// Elements/items collected per average type.
|
|
enum Element {
|
|
Value, //< Running sum of weighted function values.
|
|
Weight, //< Running sum of weights.
|
|
|
|
// ---- Must be last enumerator ----
|
|
NumElem, //< Number of items/elements per average type.
|
|
};
|
|
|
|
/// MPI communication object.
|
|
std::reference_wrapper<const Parallel::Communication> comm_;
|
|
|
|
/// Number of phases for which to accumulate function value averages.
|
|
std::size_t np_{};
|
|
|
|
/// Named region sets.
|
|
std::vector<std::string> rsetNames_{};
|
|
|
|
/// Call-back function for accessing region set arrays.
|
|
RegionArrayAccessor getRegionArray_;
|
|
|
|
/// Start pointers for average values of each named region set. In
|
|
/// particular, \code rsStart_[i] \endcode identifies the offset
|
|
/// into \c x_ of the first average type of the first phase of the
|
|
/// first region in region set \code rsetNames_[i] \endcode.
|
|
std::vector<Ix> rsStart_{};
|
|
|
|
/// All elements--i.e., running sums--that go into calculating the
|
|
/// field- and region-level weighted function averages per phase.
|
|
/// We store all elements in a single linear array, and track
|
|
/// numerators and denominators in separate elements, in order to
|
|
/// simplify cross-rank reduction in parallel simulation runs. See
|
|
/// accumulateParallel() for details on this reduction process.
|
|
///
|
|
/// There are \c np_ base entries for each region in each region set
|
|
/// (+ FIELD). Each base entry has \code AvgType::NumTypes \endcode
|
|
/// different average types, and each average type comprises \code
|
|
/// Element::NumElem \endcode separate elements in \c x_.
|
|
///
|
|
/// You should typically access this array through the value() and
|
|
/// weight() member functions, and the start index to both of those
|
|
/// should be the return value from fieldStartIx() or rsetStartIx().
|
|
std::vector<double> x_{};
|
|
|
|
/// Compute final average value for a single region and phase.
|
|
///
|
|
/// Prefers the average value weighted by phase-filled pore-volume,
|
|
/// but falls back to average value weighted by total pore-volume if
|
|
/// saturation is identically zero throughout the region.
|
|
///
|
|
/// \param[in] start Offset into linearised value array (\c x_)
|
|
/// corresponding to the first average value type of a particular
|
|
/// phase in a particular region. Usually calculated by
|
|
/// fieldStartIx() or rsetStartIx().
|
|
///
|
|
/// \return Weighted average function value.
|
|
double averageValueWithFallback(Ix start) const;
|
|
|
|
/// Compute average function value for a single region and phase.
|
|
///
|
|
/// \param[in] start Offset into linearised value array (\c x_)
|
|
/// corresponding to the first average value type of a particular
|
|
/// phase in a particular region. Usually calculated by
|
|
/// fieldStartIx() or rsetStartIx().
|
|
///
|
|
/// \param[in] type Which kind of average value to compute.
|
|
///
|
|
/// \return Weighted average function value.
|
|
double averageValue(Ix start, AvgType type) const;
|
|
|
|
/// Compute linearised value array offset for field-level average
|
|
/// function values of a single phase.
|
|
///
|
|
/// \param[in] phase Phase index for which to compute array offset.
|
|
///
|
|
/// \return Value array offset for field-level averages of \p phase.
|
|
Ix fieldStartIx(unsigned int phase) const;
|
|
|
|
/// Compute linearised value array offset for region-level average
|
|
/// function values of a single phase.
|
|
///
|
|
/// \param[in] rset Enumerated region set.
|
|
///
|
|
/// \param[in] region Region index within \p rset.
|
|
///
|
|
/// \param[in] phase Phase index for which to compute array offset.
|
|
///
|
|
/// \return Value array offset for region-level averages of \p phase.
|
|
Ix rsetStartIx(std::size_t rset, int region, unsigned int phase) const;
|
|
|
|
/// Compute linearised value array offset for average function
|
|
/// values of a single phase.
|
|
///
|
|
/// \param[in] offset Field or region base offset.
|
|
///
|
|
/// \param[in] phase Phase index for which to compute array offset.
|
|
///
|
|
/// \return Value array offset for weighted averages of \p phase.
|
|
Ix startIx(std::size_t offset, unsigned int phase) const;
|
|
|
|
/// Compute region ID of single active cell within particular region
|
|
/// set.
|
|
///
|
|
/// \param[in] rset Enumerated region set.
|
|
///
|
|
/// \param[in] activeCell Per-rank active cell ID--typically one of
|
|
/// the rank's interior cells.
|
|
///
|
|
/// \return Region ID of \p activeCell within \p rset.
|
|
int regionIndex(std::size_t rset, std::size_t activeCell) const;
|
|
|
|
/// Incorporate per-cell contribution into all average function types.
|
|
///
|
|
/// \param[in] start Offset into linearised value array (\c x_)
|
|
/// corresponding to the first average value type of a particular
|
|
/// phase in a particular region. Usually calculated by
|
|
/// fieldStartIx() or rsetStartIx().
|
|
///
|
|
/// \param[in] cv Single cell function value contribution.
|
|
void add(Ix start, const CellValue& cv);
|
|
|
|
/// Incorporate per-cell contribution into specific function type.
|
|
///
|
|
/// \param[in] start Offset into linearised value array (\c x_)
|
|
/// corresponding to the first average value type of a particular
|
|
/// phase in a particular region. Usually calculated by
|
|
/// fieldStartIx() or rsetStartIx().
|
|
///
|
|
/// \param[in] type Which kind of average value to accumulate.
|
|
///
|
|
/// \param[in] x Function value.
|
|
///
|
|
/// \param[in] w Function weight.
|
|
void add(Ix start, AvgType type, double x, double w);
|
|
|
|
/// Mutable access to value item of specific average value type
|
|
///
|
|
/// \param[in] start Offset into linearised value array (\c x_)
|
|
/// corresponding to the first average value type of a particular
|
|
/// phase in a particular region. Usually calculated by
|
|
/// fieldStartIx() or rsetStartIx().
|
|
///
|
|
/// \param[in] type Which kind of average value to accumulate.
|
|
///
|
|
/// \return Reference to mutable element of linearised value array
|
|
/// corresponding to the running sum of function values.
|
|
double& value(Ix start, AvgType type);
|
|
|
|
/// Mutable access to weight item of specific average value type
|
|
///
|
|
/// \param[in] start Offset into linearised value array (\c x_)
|
|
/// corresponding to the first average value type of a particular
|
|
/// phase in a particular region. Usually calculated by
|
|
/// fieldStartIx() or rsetStartIx().
|
|
///
|
|
/// \param[in] type Which kind of average value to accumulate.
|
|
///
|
|
/// \return Reference to mutable element of linearised value array
|
|
/// corresponding to the running sum of function weights.
|
|
double& weight(Ix start, AvgType type);
|
|
|
|
/// Read-only access to value item of specific average value type
|
|
///
|
|
/// \param[in] start Offset into linearised value array (\c x_)
|
|
/// corresponding to the first average value type of a particular
|
|
/// phase in a particular region. Usually calculated by
|
|
/// fieldStartIx() or rsetStartIx().
|
|
///
|
|
/// \param[in] type Which kind of average value to accumulate.
|
|
///
|
|
/// \return Running sum of function value.
|
|
double value(Ix start, AvgType type) const;
|
|
|
|
/// Read-only access to weight item of specific average value type
|
|
///
|
|
/// \param[in] start Offset into linearised value array (\c x_)
|
|
/// corresponding to the first average value type of a particular
|
|
/// phase in a particular region. Usually calculated by
|
|
/// fieldStartIx() or rsetStartIx().
|
|
///
|
|
/// \param[in] type Which kind of average value to accumulate.
|
|
///
|
|
/// \return Running sum of function weights.
|
|
double weight(Ix start, AvgType type) const;
|
|
|
|
/// Compute value array index of particular item of particular
|
|
/// average value
|
|
///
|
|
/// \param[in] start Offset into linearised value array (\c x_)
|
|
/// corresponding to the first average value type of a particular
|
|
/// phase in a particular region. Usually calculated by
|
|
/// fieldStartIx() or rsetStartIx().
|
|
///
|
|
/// \param[in] type Which kind of average value to reference.
|
|
///
|
|
/// \param[in] element Which running sum element to reference for
|
|
/// this particular average value.
|
|
///
|
|
/// \return Index into linearised value array \c x_ corresponding to
|
|
/// this particular element of this particular average function
|
|
/// type.
|
|
Ix valueArrayIndex(Ix start, AvgType type, Element element) const;
|
|
};
|
|
} // namespace Opm
|
|
|
|
#endif // OPM_REGION_PHASE_POREVOL_AVERAGE_MODULE_HPP
|