OGS
ComputeSparsityPattern.cpp File Reference
#include "ComputeSparsityPattern.h"
#include <numeric>
#include <range/v3/algorithm/sort.hpp>
#include <range/v3/algorithm/unique.hpp>
#include <range/v3/range/conversion.hpp>
#include <range/v3/view/transform.hpp>
#include "LocalToGlobalIndexMap.h"
#include "MeshLib/NodeAdjacencyTable.h"
#include "MeshLib/NodePartitionedMesh.h"
Include dependency graph for ComputeSparsityPattern.cpp:

Go to the source code of this file.

Namespaces

namespace  NumLib

Functions

GlobalSparsityPattern computeSparsityPatternPETSc (NumLib::LocalToGlobalIndexMap const &dof_table, MeshLib::Mesh const &mesh)
GlobalSparsityPattern NumLib::computeSparsityPattern (LocalToGlobalIndexMap const &dof_table, MeshLib::Mesh const &mesh)
 Computes a sparsity pattern for the given inputs.

Function Documentation

◆ computeSparsityPatternPETSc()

GlobalSparsityPattern computeSparsityPatternPETSc ( NumLib::LocalToGlobalIndexMap const & dof_table,
MeshLib::Mesh const & mesh )

Definition at line 18 of file ComputeSparsityPattern.cpp.

20{
21 assert(dynamic_cast<MeshLib::NodePartitionedMesh const*>(&mesh));
22
23 MeshLib::NodeAdjacencyTable const node_adjacency_table(mesh);
24
25 // getGlobalIndices() returns raw PETSc global indices:
26 // idx >= 0 — owned by this rank, actual PETSc global row/col index
27 // idx < 0 — ghost node on this rank (owned by another rank);
28 // the actual global index is stored negated
29 auto const global_idcs =
31 ranges::views::transform([&](auto&& l)
32 { return dof_table.getGlobalIndices(l); }) |
33 ranges::to<std::vector>();
34
35 auto const n_local =
36 static_cast<GlobalIndexType>(dof_table.dofSizeWithoutGhosts());
37
38 // Each rank owns a contiguous range of global indices; global_start is the
39 // first index owned here, obtained by an exclusive prefix-sum of the local
40 // sizes. It maps a global row index to the corresponding local row index.
41 //
42 // MPIU_INT is not an MPI standard datatype but a PETSc macro (defined in
43 // petscsys.h) that expands to the MPI datatype matching the width of
44 // PetscInt, i.e. MPI_INT or MPI_INT64_T depending on the PETSc
45 // configuration. It is used rather than the BaseLib::MPI wrappers because
46 // BaseLib::MPI::mpiType() has no mapping for a 64-bit PetscInt and would
47 // silently pick the wrong datatype.
48 GlobalIndexType global_start = 0;
49 MPI_Exscan(&n_local, &global_start, 1, MPIU_INT, MPI_SUM, PETSC_COMM_WORLD);
50 // Total global DOF count needed to decode the special ghost encoding where
51 // global index 0 is stored as -num_global_dof.
52 GlobalIndexType num_global_dof = 0;
53 MPI_Allreduce(&n_local, &num_global_dof, 1, MPIU_INT, MPI_SUM,
54 PETSC_COMM_WORLD);
55
56 // Collect all (row, col) pairs into per-local-row lists of global column
57 // indices; they are sorted and deduplicated below.
58 //
59 // A row holds only a few dozen columns, so a flat vector plus one
60 // sort/unique per row is used instead of std::set: appending is a
61 // contiguous write without a per-element node allocation, and the sort
62 // is on data that already sits in cache. The result is the same -- sorted
63 // and unique -- as std::set gives, which is what the CSR pattern needs.
64 std::vector<std::vector<GlobalIndexType>> col_lists(n_local);
65
66 // Decode a raw PETSc global index (possibly negative ghost encoding) to the
67 // actual non-negative global index.
68 auto const decode_col = [&](GlobalIndexType const raw) -> GlobalIndexType
69 {
70 if (raw >= 0)
71 {
72 return raw;
73 }
74 // Ghost encoding: actual index k is stored as -k, except k==0 which is
75 // stored as -num_global_dof.
76 return (-raw == num_global_dof) ? 0 : -raw;
77 };
78
79 // Collect a (row, col) pair into the per-row column set.
80 // row >= 0 (non-negative) — owned by this rank
81 // row < 0 — ghost row, not owned here → skip
82 auto const collect =
83 [&](GlobalIndexType const row, GlobalIndexType const col)
84 {
85 if (row < 0)
86 {
87 return;
88 }
89 // A non-negative raw index is owned by this rank, and an owned index
90 // lies in this rank's contiguous range [global_start, global_start +
91 // n_local), so the local row is always in range here.
92 GlobalIndexType const local_row = row - global_start;
93 assert(local_row >= 0 && local_row < n_local);
94 col_lists[local_row].push_back(decode_col(col));
95 };
96
97 // Standard mesh-adjacency contribution.
98 // Note: getAdjacentNodes() already includes node n itself (the adjacency
99 // table is built from all element nodes, including self), so there is no
100 // need for a separate self-node loop.
101 for (std::size_t n = 0; n < mesh.getNumberOfNodes(); ++n)
102 {
103 auto const& adj_nodes = node_adjacency_table.getAdjacentNodes(n);
104 for (auto const row_idx : global_idcs[n])
105 {
106 for (auto const adj : adj_nodes)
107 {
108 for (auto const col_idx : global_idcs[adj])
109 {
110 collect(row_idx, col_idx);
111 }
112 }
113 }
114 }
115
116 // Sort and deduplicate each row, so that col_idx ends up sorted within each
117 // row as PETScSparsityPattern documents.
118 std::size_t number_of_nonzeros = 0;
119 for (auto& cols : col_lists)
120 {
121 ranges::sort(cols);
122 cols.erase(ranges::unique(cols), cols.end());
123 number_of_nonzeros += cols.size();
124 }
125
126 // Build the CSR sparsity pattern from the collected column lists.
127 GlobalSparsityPattern sparsity_pattern;
128 sparsity_pattern.row_ptr.resize(n_local + 1);
129 sparsity_pattern.row_ptr[0] = 0;
130 sparsity_pattern.col_idx.reserve(number_of_nonzeros);
131
132 for (GlobalIndexType local_row = 0; local_row < n_local; ++local_row)
133 {
134 auto const& cols = col_lists[local_row];
135 sparsity_pattern.col_idx.insert(sparsity_pattern.col_idx.end(),
136 cols.begin(), cols.end());
137 sparsity_pattern.row_ptr[local_row + 1] =
138 sparsity_pattern.row_ptr[local_row] +
139 static_cast<GlobalIndexType>(cols.size());
140 }
141
142 return sparsity_pattern;
143}
MathLib::PETScSparsityPattern GlobalSparsityPattern
GlobalMatrix::IndexType GlobalIndexType
auto meshLocations(Mesh const &mesh, MeshItemType const item_type)
Definition Mesh.h:234
std::vector< PetscInt > col_idx
Global column indices, sorted within each local row.
std::vector< PetscInt > row_ptr
CSR row pointers (length n_local_rows + 1).

References MathLib::PETScSparsityPattern::col_idx, NumLib::LocalToGlobalIndexMap::dofSizeWithoutGhosts(), MeshLib::NodeAdjacencyTable::getAdjacentNodes(), NumLib::LocalToGlobalIndexMap::getGlobalIndices(), MeshLib::Mesh::getNumberOfNodes(), MeshLib::views::meshLocations(), MeshLib::Node, and MathLib::PETScSparsityPattern::row_ptr.

Referenced by NumLib::computeSparsityPattern().