Skip to content

Commit 978f06b

Browse files
authored
Merge branch 'main' into dokken/blocked_real_space
2 parents e427d17 + 32b4c90 commit 978f06b

1 file changed

Lines changed: 34 additions & 13 deletions

File tree

cpp/dolfinx/la/SparsityPattern.cpp

Lines changed: 34 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -302,7 +302,7 @@ void SparsityPattern::finalize()
302302
auto it = std::ranges::lower_bound(src0, owner);
303303
assert(it != src0.end() and *it == owner);
304304
return static_cast<int>(
305-
std::distance(src0.begin(), it));
305+
std::ranges::distance(src0.begin(), it));
306306
});
307307

308308
// Compute size of data to send to each process
@@ -428,33 +428,54 @@ void SparsityPattern::finalize()
428428
// Reserve the exact pre-dedup edge count
429429
_edges.reserve(cache_cols.size() + recv_cols_bucketed.size());
430430

431-
// Sort and remove duplicates per row, building CSR offsets as we
432-
// go. Offsets are int64_t to avoid overflow.
431+
// De-duplicate each row's raw (unsorted, repeats included) column
432+
// list with a generation-stamped marker: last_seen[col] == i means
433+
// col has already been recorded for row i. Rows are visited exactly
434+
// once in increasing order, so the row index itself is the stamp --
435+
// no reset between rows needed. This turns per-row de-duplication
436+
// from O(m log m) (sort the raw, repeat-laden list) into
437+
// O(m + k log k), where k <= m is the de-duplicated count: sorting
438+
// only ever runs over the much smaller de-duplicated list.
439+
const std::int32_t num_cols0
440+
= local_size1 + static_cast<std::int32_t>(_col_ghosts.size());
441+
std::vector<std::int32_t> last_seen(num_cols0, -1);
442+
443+
// Build CSR offsets as we go. Offsets are int64_t to avoid overflow.
433444
_off_diagonal_offsets.resize(num_rows0);
434445
_offsets.reserve(num_rows0 + 1);
435446
_offsets.push_back(0);
436447
std::vector<std::int32_t> row;
437448
for (std::int32_t i = 0; i < num_rows0; ++i)
438449
{
439450
row.clear();
440-
row.insert(row.end(), cache_cols.begin() + cache_offsets[i],
441-
cache_cols.begin() + cache_offsets[i + 1]);
451+
for (std::int64_t k = cache_offsets[i]; k < cache_offsets[i + 1]; ++k)
452+
{
453+
if (std::int32_t c = cache_cols[k]; last_seen[c] != i)
454+
{
455+
last_seen[c] = i;
456+
row.push_back(c);
457+
}
458+
}
442459
if (i < local_size0)
443460
{
444-
row.insert(row.end(), recv_cols_bucketed.begin() + recv_offsets[i],
445-
recv_cols_bucketed.begin() + recv_offsets[i + 1]);
461+
for (std::int64_t k = recv_offsets[i]; k < recv_offsets[i + 1]; ++k)
462+
{
463+
if (std::int32_t c = recv_cols_bucketed[k]; last_seen[c] != i)
464+
{
465+
last_seen[c] = i;
466+
row.push_back(c);
467+
}
468+
}
446469
}
447470

448471
std::ranges::sort(row);
449-
auto it_end = std::ranges::unique(row).begin();
450472

451473
// Find position of first "off-diagonal" column
452-
_off_diagonal_offsets[i] = std::distance(
453-
row.begin(),
454-
std::ranges::lower_bound(row.begin(), it_end, local_size1));
474+
_off_diagonal_offsets[i] = std::ranges::distance(
475+
row.begin(), std::ranges::lower_bound(row, local_size1));
455476

456-
_edges.insert(_edges.end(), row.begin(), it_end);
457-
_offsets.push_back(_offsets.back() + std::distance(row.begin(), it_end));
477+
_edges.insert(_edges.end(), row.begin(), row.end());
478+
_offsets.push_back(_offsets.back() + row.size());
458479
}
459480

460481
_edges.shrink_to_fit();

0 commit comments

Comments
 (0)