114template <
typename VertexID,
bool TrackCompressedIdx,
bool PermitSelfConnections>
119 return this->i_.size();
122template <
typename VertexID,
bool TrackCompressedIdx,
bool PermitSelfConnections>
130template <
typename VertexID,
bool TrackCompressedIdx,
bool PermitSelfConnections>
144template <
typename VertexID,
bool TrackCompressedIdx,
bool PermitSelfConnections>
148 const Offset maxNumVertices,
149 const bool expandExistingIdxMap)
151 const auto maxRow = conns.maxRow();
153 if (maxRow.has_value() &&
154 (
static_cast<Offset
>(*maxRow) >= maxNumVertices))
156 throw std::invalid_argument {
157 "Number of vertices in input graph (" +
158 std::to_string(*maxRow) +
") "
159 "exceeds maximum graph size implied by explicit size of "
160 "adjacency matrix (" + std::to_string(maxNumVertices) +
')'
164 this->assemble(conns.rowIndices(), conns.columnIndices(),
165 maxRow.value_or(BaseVertexID{0}),
166 conns.maxCol().value_or(BaseVertexID{0}),
167 expandExistingIdxMap);
169 this->compress(maxNumVertices);
172template <
typename VertexID,
bool TrackCompressedIdx,
bool PermitSelfConnections>
177 return this->startPointers().empty()
178 ? 0 : this->startPointers().size() - 1;
181template <
typename VertexID,
bool TrackCompressedIdx,
bool PermitSelfConnections>
182typename Opm::utility::CSRGraphFromCoordinates<VertexID, TrackCompressedIdx, PermitSelfConnections>::BaseVertexID
186 return this->numRows_ - 1;
189template <
typename VertexID,
bool TrackCompressedIdx,
bool PermitSelfConnections>
190typename Opm::utility::CSRGraphFromCoordinates<VertexID, TrackCompressedIdx, PermitSelfConnections>::BaseVertexID
194 return this->numCols_ - 1;
197template <
typename VertexID,
bool TrackCompressedIdx,
bool PermitSelfConnections>
205template <
typename VertexID,
bool TrackCompressedIdx,
bool PermitSelfConnections>
213template <
typename VertexID,
bool TrackCompressedIdx,
bool PermitSelfConnections>
218 auto rowIdx = Neighbours{};
220 if (this->ia_.empty()) {
224 rowIdx.reserve(this->ia_.back());
226 auto row = BaseVertexID{};
228 const auto m = this->ia_.size() - 1;
229 for (
auto i = 0*m; i < m; ++i, ++row) {
230 const auto n = this->ia_[i + 1] - this->ia_[i + 0];
232 rowIdx.insert(rowIdx.end(), n, row);
238template <
typename VertexID,
bool TrackCompressedIdx,
bool PermitSelfConnections>
246 if constexpr (TrackCompressedIdx) {
247 this->compressedIdx_.clear();
254template <
typename VertexID,
bool TrackCompressedIdx,
bool PermitSelfConnections>
258 const Neighbours& cols,
259 const BaseVertexID maxRowIdx,
260 const BaseVertexID maxColIdx,
261 [[maybe_unused]]
const bool expandExistingIdxMap)
263 [[maybe_unused]]
auto compressedIdx = this->compressedIdx_;
264 [[maybe_unused]]
const auto numOrigNNZ = this->ja_.size();
266 auto i = this->coordinateFormatRowIndices();
267 i.insert(i.end(), rows.begin(), rows.end());
270 j.insert(j.end(), cols.begin(), cols.end());
272 const auto thisNumRows = std::max(this->numRows_, maxRowIdx + 1);
273 const auto thisNumCols = std::max(this->numCols_, maxColIdx + 1);
275 this->preparePushbackRowGrouping(thisNumRows, i);
277 this->groupAndTrackColumnIndicesByRow(i, j);
279 if constexpr (TrackCompressedIdx) {
280 if (expandExistingIdxMap) {
281 this->remapCompressedIndex(std::move(compressedIdx), numOrigNNZ);
285 this->numRows_ = thisNumRows;
286 this->numCols_ = thisNumCols;
289template <
typename VertexID,
bool TrackCompressedIdx,
bool PermitSelfConnections>
294 if (this->numRows() > maxNumVertices) {
295 throw std::invalid_argument {
296 "Number of vertices in input graph (" +
297 std::to_string(this->numRows()) +
") "
298 "exceeds maximum graph size implied by explicit size of "
299 "adjacency matrix (" + std::to_string(maxNumVertices) +
')'
303 this->sortColumnIndicesPerRow();
306 this->condenseDuplicates();
308 const auto nRows = this->startPointers().size() - 1;
309 if (nRows < maxNumVertices) {
310 this->ia_.insert(this->ia_.end(),
311 maxNumVertices - nRows,
312 this->startPointers().back());
316template <
typename VertexID,
bool TrackCompressedIdx,
bool PermitSelfConnections>
330template <
typename VertexID,
bool TrackCompressedIdx,
bool PermitSelfConnections>
337 const auto colIdx = this->ja_;
338 auto end = colIdx.begin();
342 [[maybe_unused]]
auto compressedIdx = this->compressedIdx_;
343 if constexpr (TrackCompressedIdx) {
344 this->compressedIdx_.clear();
347 const auto numRows = this->ia_.size() - 1;
348 for (
auto row = 0*numRows; row < numRows; ++row) {
351 std::advance(end, this->ia_[row + 1] - this->ia_[row + 0]);
353 const auto q = this->ja_.size();
355 this->condenseAndTrackUniqueColumnsForSingleRow(begin, end);
357 this->ia_[row + 0] = q;
360 if constexpr (TrackCompressedIdx) {
361 this->remapCompressedIndex(std::move(compressedIdx));
365 this->ia_.back() = this->ja_.size();
368template <
typename VertexID,
bool TrackCompressedIdx,
bool PermitSelfConnections>
372 const Neighbours& rowIdx)
374 assert (numRows >= 0);
376 this->ia_.assign(numRows + 1, 0);
380 for (
const auto& row : rowIdx) {
381 this->ia_[row + 1] += 1;
395 for (
typename Start::size_type i = 1, n = numRows; i <= n; ++i) {
396 this->ia_[0] += this->ia_[i];
397 this->ia_[i] = this->ia_[0] - this->ia_[i];
400 assert (this->ia_[0] == rowIdx.size());
403template <
typename VertexID,
bool TrackCompressedIdx,
bool PermitSelfConnections>
407 const Neighbours& colIdx)
409 assert (this->ia_[0] == rowIdx.size());
411 const auto nnz = rowIdx.size();
413 this->ja_.resize(nnz);
415 if constexpr (TrackCompressedIdx) {
416 this->compressedIdx_.clear();
417 this->compressedIdx_.reserve(nnz);
437 for (
auto nz = 0*nnz; nz < nnz; ++nz) {
438 const auto k = this->ia_[rowIdx[nz] + 1] ++;
440 this->ja_[k] = colIdx[nz];
442 if constexpr (TrackCompressedIdx) {
443 this->compressedIdx_.push_back(k);
450template <
typename VertexID,
bool TrackCompressedIdx,
bool PermitSelfConnections>
455 [[maybe_unused]]
auto compressedIdx = this->compressedIdx_;
458 const auto rowIdx = this->coordinateFormatRowIndices();
459 const auto colIdx = this->ja_;
461 this->preparePushbackRowGrouping(this->numCols_, colIdx);
465 this->groupAndTrackColumnIndicesByRow(colIdx, rowIdx);
468 if constexpr (TrackCompressedIdx) {
469 this->remapCompressedIndex(std::move(compressedIdx));
472 std::swap(this->numRows_, this->numCols_);
475template <
typename VertexID,
bool TrackCompressedIdx,
bool PermitSelfConnections>
479 typename Neighbours::const_iterator end)
489 while (begin != end) {
492 if constexpr (TrackCompressedIdx) {
493 this->compressedIdx_.push_back(this->ja_.size());
496 this->ja_.push_back(*begin);
499 std::find_if(begin, end, [last = this->ja_.back()]
500 (
const auto j) { return j != last; });
502 if constexpr (TrackCompressedIdx) {
504 const auto ndup = std::distance(begin, next_unique);
510 this->compressedIdx_.insert(this->compressedIdx_.end(),
512 this->compressedIdx_.back());
520template <
typename VertexID,
bool TrackCompressedIdx,
bool PermitSelfConnections>
524 [[maybe_unused]] std::optional<typename Start::size_type> numOrig)
526 if constexpr (TrackCompressedIdx) {
527 for (
auto& i : compressedIdx) {
528 i = this->compressedIdx_[i];
531 if (numOrig.has_value() && (*numOrig < this->compressedIdx_.size())) {
535 .insert(compressedIdx.end(),
536 this->compressedIdx_.begin() + *numOrig,
537 this->compressedIdx_.end());
540 this->compressedIdx_.swap(compressedIdx);
550template <
typename VertexID,
bool TrackCompressedIdx,
bool PermitSelfConnections>
553 this->uncompressed_.
clear();
557template <
typename VertexID,
bool TrackCompressedIdx,
bool PermitSelfConnections>
562 if ((v1 < 0) || (v2 < 0)) {
563 throw std::invalid_argument {
564 "Vertex IDs must be non-negative. Got (v1,v2) = ("
565 + std::to_string(v1) +
", " + std::to_string(v2)
570 if constexpr (! PermitSelfConnections) {
577 this->uncompressed_.add(v1, v2);
580template <
typename VertexID,
bool TrackCompressedIdx,
bool PermitSelfConnections>
583compress(
const Offset maxNumVertices,
const bool expandExistingIdxMap)
585 if (! this->uncompressed_.isValid()) {
586 throw std::logic_error {
587 "Cannot compress invalid connection list"
591 this->csr_.merge(this->uncompressed_, maxNumVertices, expandExistingIdxMap);
593 this->uncompressed_.clear();
596template <
typename VertexID,
bool TrackCompressedIdx,
bool PermitSelfConnections>
600 return this->csr_.numRows();
603template <
typename VertexID,
bool TrackCompressedIdx,
bool PermitSelfConnections>
607 const auto& ia = this->startPointers();
609 return ia.empty() ? 0 : ia.back();