/*
Copyright 2016 SINTEF ICT, Applied Mathematics.
Copyright 2016 Statoil ASA.
Copyright 2022 Equinor ASA
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 .
*/
#ifndef OPM_OUTPUT_DATA_INTERREGFLOWMAP_HPP
#define OPM_OUTPUT_DATA_INTERREGFLOWMAP_HPP
#include
#include
#include
#include
#include
#include
#include
/// \file
///
/// Facility for converting collection of region ID pairs into a sparse
/// (CSR) adjacency matrix representation of a graph. Supports O(nnz)
/// compression and, if applicable, accumulation of weight values for
/// repeated entity pairs.
namespace Opm { namespace data {
/// Form CSR adjacency matrix representation of inter-region flow rate
/// graph provided as a list of connections between regions.
class InterRegFlowMap
{
private:
/// Representation of neighbouring regions.
using Neighbours = std::vector;
/// Offset into neighbour array.
using Offset = Neighbours::size_type;
/// CSR start pointers.
using Start = std::vector;
/// Linear flow rate buffer.
using RateBuffer = std::vector;
/// Internal view of flows between regions.
using Window = InterRegFlow;
public:
/// Client view of flows between specified region pair.
using ReadOnlyWindow = InterRegFlow::const_iterator>;
/// Client type through which to define a single inter-region connection.
using FlowRates = Window::FlowRates;
/// Client type through which to identify a component flow of a
/// single inter-region connection.
using Component = Window::Component;
/// Add flow rate connection between regions.
///
/// \param[in] r1 Primary (source) zero-based region index. Used as
/// row index.
///
/// \param[in] r2 Secondary (sink) zero-based region index. Used as
/// column index.
///
/// \param[in] rates Flow rates associated to single connection.
///
/// If both region IDs are the same then this function does nothing.
void addConnection(const int r1, const int r2, const FlowRates& rates);
/// Form CSR adjacency matrix representation of input graph from
/// connections established in previous calls to addConnection().
///
/// \param[in] numRegions Number of rows in resulting CSR matrix.
/// If prior calls to addConnection() supply source entity IDs
/// (row indices) greater than or equal to \p numRows, then
/// method compress() will throw \code std::invalid_argument
/// \endcode.
void compress(const std::size_t numRegions);
/// Retrieve number of rows (source entities) in input graph.
/// Corresponds to value of argument passed to compress(). Valid
/// only after calling compress().
Offset numRegions() const;
/// Retrieve accumulated inter-region flow rates for identified pair
/// of regions.
///
/// \param[in] r1 Primary (source) zero-based region index. Used as
/// row index.
///
/// \param[in] r2 Secondary (sink) zero-based region index. Used as
/// column index.
///
/// \return View of accumulated inter-region flow rates and
/// associated flow direction sign. \code std::nullopt \endcode
/// if no such rates exist.
std::optional>
getInterRegFlows(const int r1, const int r2) const;
// MessageBufferType API should be similar to Dune::MessageBufferIF
template
void write(MessageBufferType& buffer) const
{
this->connections_.write(buffer);
this->writeVector(this->rates_, buffer);
}
// MessageBufferType API should be similar to Dune::MessageBufferIF
template
void read(MessageBufferType& buffer)
{
this->connections_.read(buffer);
auto rates = RateBuffer{};
this->readVector(buffer, rates);
this->appendRates(rates);
}
/// Clear all internal buffers, but preserve allocated capacity.
void clear();
private:
// VertexID = int, TrackCompressedIdx = true.
using Graph = utility::CSRGraphFromCoordinates;
Graph connections_{};
RateBuffer rates_{};
template
void writeVector(const std::vector& vec,
MessageBufferType& buffer) const
{
const auto n = vec.size();
buffer.write(n);
for (const auto& x : vec) {
buffer.write(x);
}
}
template
void readVector(MessageBufferType& buffer,
std::vector& vec)
{
auto n = 0 * vec.size();
buffer.read(n);
vec.resize(n);
for (auto& x : vec) {
buffer.read(x);
}
}
template
void appendRates(const Rates& rates)
{
this->rates_.insert(this->rates_.end(), rates.begin(), rates.end());
}
};
}} // namespace Opm::data
#endif // OPM_OUTPUT_DATA_INTERREGFLOWMAP_HPP