MueLu Version of the Day
Loading...
Searching...
No Matches
MueLu_LWGraphBase.hpp
Go to the documentation of this file.
1// @HEADER
2// *****************************************************************************
3// MueLu: A package for multigrid based preconditioning
4//
5// Copyright 2012 NTESS and the MueLu contributors.
6// SPDX-License-Identifier: BSD-3-Clause
7// *****************************************************************************
8// @HEADER
9
10#ifndef MUELU_LWGRAPHBASE_DECL_HPP
11#define MUELU_LWGRAPHBASE_DECL_HPP
12
13#include "Kokkos_Bitset.hpp"
14#include "MueLu_ConfigDefs.hpp"
15
16#include <KokkosSparse_StaticCrsGraph.hpp>
17#include <Tpetra_KokkosCompat_ClassicNodeAPI_Wrapper.hpp>
18#include <KokkosCompat_View.hpp>
19
20#include <Xpetra_ConfigDefs.hpp> // global_size_t
21#include <Xpetra_Map_fwd.hpp>
22#include <Xpetra_CrsGraph.hpp>
23#include <Xpetra_CrsGraphFactory.hpp>
24#include <type_traits>
25
28
29#include "MueLu_Exceptions.hpp"
30
31namespace MueLu {
32
33namespace { // anonymous
34
35template <class LocalOrdinal, class RowType>
36class MaxNumRowEntriesFunctor {
37 public:
38 MaxNumRowEntriesFunctor(RowType rowPointers)
39 : rowPointers_(rowPointers) {}
40
41 KOKKOS_INLINE_FUNCTION
42 void operator()(const LocalOrdinal i, size_t& maxLength) const {
43 size_t d = rowPointers_(i + 1) - rowPointers_(i);
44
45 maxLength = (d > maxLength ? d : maxLength);
46 }
47
48 KOKKOS_INLINE_FUNCTION
49 void join(volatile size_t& dest, const volatile size_t& src) {
50 dest = (dest > src ? dest : src);
51 }
52
53 KOKKOS_INLINE_FUNCTION
54 void init(size_t& initValue) {
55 initValue = 0;
56 }
57
58 private:
59 RowType rowPointers_;
60};
61
62} // namespace
63
71template <class LocalOrdinal, class GlobalOrdinal, class Node, bool OnHost>
73 public:
76 using map_type = Xpetra::Map<LocalOrdinal, GlobalOrdinal, Node>;
77 using crs_graph_type = Xpetra::CrsGraph<LocalOrdinal, GlobalOrdinal, Node>;
78 using size_type = size_t;
79
80 using device_type = typename std::conditional<OnHost,
81 Kokkos::Device<Kokkos::Serial, Kokkos::HostSpace>,
82 typename Node::device_type>::type;
83 using execution_space = typename device_type::execution_space;
84 using memory_space = typename device_type::memory_space;
85
86 using local_graph_device_type = KokkosSparse::StaticCrsGraph<LocalOrdinal,
87 Kokkos::LayoutLeft,
88 typename Node::device_type,
89 void, size_t>;
90 using local_graph_type = typename std::conditional<OnHost, typename local_graph_device_type::host_mirror_type, local_graph_device_type>::type;
91 using boundary_nodes_type = Kokkos::View<bool*, memory_space>;
92 using row_type = typename local_graph_type::row_map_type;
93 using entries_type = typename local_graph_type::entries_type;
94 using neighbor_vertices_type = KokkosSparse::GraphRowViewConst<local_graph_type>;
95
96#undef MUELU_LWGRAPHBASE_SHORT
98
100
101
102 private:
103 void setup(const local_graph_type& graph,
104 const RCP<const map_type>& domainMap,
105 const RCP<const map_type>& importMap,
106 const std::string& objectLabel) {
107 using range_type = Kokkos::RangePolicy<local_ordinal_type, execution_space>;
108
109 graph_ = graph;
110 domainMap_ = domainMap;
111 importMap_ = importMap;
112 objectLabel_ = objectLabel;
113
114 minLocalIndex_ = domainMap_->getMinLocalIndex();
115 maxLocalIndex_ = domainMap_->getMaxLocalIndex();
116
117 MaxNumRowEntriesFunctor<LO, typename local_graph_type::row_map_type> maxNumRowEntriesFunctor(graph_.row_map);
118 Kokkos::parallel_reduce("MueLu:LocalLWGraph:LWGraph:maxnonzeros", range_type(0, graph_.numRows()), maxNumRowEntriesFunctor, maxNumRowEntries_);
119 }
120
121 public:
123 //
124 // @param[in] graph: local graph of type Kokkos::StaticCrsGraph containing CRS data
125 // @param[in] domainMap: non-overlapping (domain) map for graph. Usually provided by AmalgamationFactory stored in UnAmalgamationInfo container
126 // @param[in] importMap: overlapping map for graph. Usually provided by AmalgamationFactory stored in UnAmalgamationInfo container
127 // @param[in] objectLabel: label string
129 const RCP<const map_type>& domainMap,
130 const RCP<const map_type>& importMap,
131 const std::string& objectLabel = "") {
132 setup(graph, domainMap, importMap, objectLabel);
133 }
134
135 LWGraphBase(const RCP<const crs_graph_type>& graph,
136 const std::string& objectLabel = "") {
137 if constexpr (OnHost) {
138 // We want the graph data to live on host
139 if constexpr (std::is_same<local_graph_type,
140 typename crs_graph_type::local_graph_device_type>::value)
141 // The CrsGraph's data already lives on host.
142 setup(graph->getLocalGraphHost(), graph->getRowMap(), graph->getColMap(), objectLabel);
143 else {
144 // We deep-copy the graph to host once during construction instead of using the host mirror.
145 // This avoids issues with keeping a reference of the host mirror around.
146 auto lclGraphDevice = graph->getLocalGraphDevice();
147 auto rows = typename local_graph_type::row_map_type::non_const_type("rows", lclGraphDevice.numRows() + 1);
148 auto columns = typename local_graph_type::entries_type::non_const_type("columns", lclGraphDevice.entries.extent(0));
149 Kokkos::deep_copy(rows, lclGraphDevice.row_map);
150 Kokkos::deep_copy(columns, lclGraphDevice.entries);
151 local_graph_type lclGraph(columns, rows);
152 setup(lclGraph, graph->getRowMap(), graph->getColMap(), objectLabel);
153 }
154 } else {
155 // We want the graph data on device.
156 setup(graph->getLocalGraphDevice(), graph->getRowMap(), graph->getColMap(), objectLabel);
157 }
158 }
159
161 const entries_type& columns,
162 const RCP<const map_type>& domainMap,
163 const RCP<const map_type>& importMap,
164 const std::string& objectLabel = "") {
165 const local_graph_type graph(columns, rows);
166 setup(graph, domainMap, importMap, objectLabel);
167 }
168
169 ~LWGraphBase() = default;
171
172 const RCP<const Teuchos::Comm<int>> GetComm() const {
173 return domainMap_->getComm();
174 }
175 const RCP<const Map> GetDomainMap() const {
176 return domainMap_;
177 }
179 const RCP<const Map> GetImportMap() const {
180 return importMap_;
181 }
182
184 KOKKOS_INLINE_FUNCTION size_type GetNodeNumVertices() const {
185 return graph_.numRows();
186 }
187
189 KOKKOS_INLINE_FUNCTION size_type GetNodeNumEdges() const {
190 return graph_.row_map(GetNodeNumVertices());
191 }
192
194 Xpetra::global_size_t GetGlobalNumEdges() const {
195 Xpetra::global_size_t in = GetNodeNumEdges(), out;
196 Teuchos::reduceAll(*domainMap_->getComm(), Teuchos::REDUCE_SUM, in, Teuchos::outArg(out));
197 return out;
198 }
199
201 KOKKOS_INLINE_FUNCTION size_type getLocalMaxNumRowEntries() const {
202 return maxNumRowEntries_;
203 }
204
206 KOKKOS_INLINE_FUNCTION neighbor_vertices_type getNeighborVertices(LO i) const {
207 auto rowView = graph_.rowConst(i);
208 return rowView;
209 }
210
212 Teuchos::ArrayView<LO> getNeighborVertices_av(LO i) const {
213 return Kokkos::Compat::getArrayView(Kokkos::subview(graph_.entries,
214 Kokkos::make_pair(graph_.row_map(i),
215 graph_.row_map(i + 1))));
216 }
217
219 KOKKOS_INLINE_FUNCTION bool isLocalNeighborVertex(LO i) const {
220 return i >= minLocalIndex_ && i <= maxLocalIndex_;
221 }
222
224 KOKKOS_INLINE_FUNCTION row_type getRowPtrs() const {
225 return graph_.row_map;
226 }
227
229 KOKKOS_INLINE_FUNCTION entries_type getEntries() const {
230 return graph_.entries;
231 }
232
234 KOKKOS_INLINE_FUNCTION void SetBoundaryNodeMap(const boundary_nodes_type bndry) {
235 dirichletBoundaries_ = bndry;
236 }
237
239 KOKKOS_INLINE_FUNCTION const boundary_nodes_type GetBoundaryNodeMap() const {
241 }
242
244 std::string description() const {
245 return "LWGraphBase (" + objectLabel_ + ")";
246 }
247
249 void print(Teuchos::FancyOStream& out, const VerbLevel verbLevel = Default) const {
250 if (verbLevel & Debug) {
251 auto graph = graph_;
252 RCP<const Map> col_map = importMap_.is_null() ? domainMap_ : importMap_;
253 int mypid = col_map->getComm()->getRank();
254
255 {
256 std::ostringstream ss;
257 ss << "[pid " << mypid << "] num entries=" << graph.entries.size();
258 out << ss.str() << std::endl;
259 }
260
261 const size_t numRows = graph.numRows();
262 auto rowPtrs = graph.row_map;
263 auto columns = graph.entries;
264 auto rowPtrs_h = Kokkos::create_mirror_view(rowPtrs);
265 auto columns_h = Kokkos::create_mirror_view(columns);
266 Kokkos::deep_copy(rowPtrs_h, rowPtrs);
267 Kokkos::deep_copy(columns_h, columns);
268 for (size_t i = 0; i < numRows; ++i) {
269 std::ostringstream ss;
270 ss << "[pid " << mypid << "] row " << domainMap_->getGlobalElement(i) << ":";
271 ss << " (numEntries=" << rowPtrs_h(i + 1) - rowPtrs_h(i) << ")";
272
273 for (size_t jj = rowPtrs_h(i); jj < rowPtrs_h(i + 1); jj++) {
274 ss << " " << col_map->getGlobalElement(columns_h(jj));
275 }
276 out << ss.str() << std::endl;
277 }
278 }
279 }
280
282 return graph_;
283 }
284
285 RCP<crs_graph_type> GetCrsGraph() const {
286 RCP<crs_graph_type> graph;
287 if constexpr (std::is_same<local_graph_type,
288 typename crs_graph_type::local_graph_device_type>::value)
289 graph = Xpetra::CrsGraphFactory<LocalOrdinal, GlobalOrdinal, Node>::Build(GetDomainMap(), GetImportMap(), graph_, Teuchos::null);
290 else {
291 auto rows = typename crs_graph_type::local_graph_device_type::row_map_type::non_const_type("rows", graph_.numRows() + 1);
292 auto columns = typename crs_graph_type::local_graph_device_type::entries_type::non_const_type("columns", graph_.entries.extent(0));
293 Kokkos::deep_copy(rows, graph_.row_map);
294 Kokkos::deep_copy(columns, graph_.entries);
295 typename crs_graph_type::local_graph_device_type lclGraph(columns, rows);
296 graph = Xpetra::CrsGraphFactory<LocalOrdinal, GlobalOrdinal, Node>::Build(GetDomainMap(), GetImportMap(), lclGraph, Teuchos::null);
297 }
298 return graph;
299 }
300
301 const std::string& getObjectLabel() const {
302 return objectLabel_;
303 }
304
305 private:
308
310 RCP<const map_type> domainMap_;
311 RCP<const map_type> importMap_;
312
314 std::string objectLabel_;
315
318
322};
323
324} // namespace MueLu
325
326#define MUELU_LWGRAPHBASE_SHORT
327#endif // MUELU_LWGRAPHBASE_DECL_HPP
RowType rowPointers_
MueLu::DefaultLocalOrdinal LocalOrdinal
MueLu::DefaultGlobalOrdinal GlobalOrdinal
KOKKOS_INLINE_FUNCTION entries_type getEntries() const
Return the list entries in the local graph.
LWGraphBase(const local_graph_type &graph, const RCP< const map_type > &domainMap, const RCP< const map_type > &importMap, const std::string &objectLabel="")
LWGraph constructor.
KOKKOS_INLINE_FUNCTION row_type getRowPtrs() const
Return the row pointers of the local graph.
KOKKOS_INLINE_FUNCTION void SetBoundaryNodeMap(const boundary_nodes_type bndry)
Set boolean array indicating which rows correspond to Dirichlet boundaries.
KOKKOS_INLINE_FUNCTION size_type GetNodeNumVertices() const
Return number of graph vertices.
void setup(const local_graph_type &graph, const RCP< const map_type > &domainMap, const RCP< const map_type > &importMap, const std::string &objectLabel)
~LWGraphBase()=default
local_graph_type & getGraph() const
typename local_graph_type::entries_type entries_type
local_graph_type graph_
Underlying graph (with label)
Teuchos::ArrayView< LO > getNeighborVertices_av(LO i) const
Return the list of vertices adjacent to the vertex 'v'.
Xpetra::CrsGraph< LocalOrdinal, GlobalOrdinal, Node > crs_graph_type
Kokkos::View< bool *, memory_space > boundary_nodes_type
typename device_type::execution_space execution_space
LWGraphBase(const RCP< const crs_graph_type > &graph, const std::string &objectLabel="")
typename local_graph_type::row_map_type row_type
typename std::conditional< OnHost, Kokkos::Device< Kokkos::Serial, Kokkos::HostSpace >, typename Node::device_type >::type device_type
Xpetra::global_size_t GetGlobalNumEdges() const
Return global number of graph edges.
KOKKOS_INLINE_FUNCTION size_type getLocalMaxNumRowEntries() const
Returns the maximum number of entries across all rows/columns on this node.
typename std::conditional< OnHost, typename local_graph_device_type::host_mirror_type, local_graph_device_type >::type local_graph_type
std::string description() const
Return a simple one-line description of the Graph.
boundary_nodes_type dirichletBoundaries_
Boolean array marking Dirichlet rows.
KOKKOS_INLINE_FUNCTION const boundary_nodes_type GetBoundaryNodeMap() const
Returns map with global ids of boundary nodes.
GlobalOrdinal global_ordinal_type
KOKKOS_INLINE_FUNCTION bool isLocalNeighborVertex(LO i) const
Return true if vertex with local id 'v' is on current process.
const RCP< const Map > GetDomainMap() const
KokkosSparse::GraphRowViewConst< local_graph_type > neighbor_vertices_type
const RCP< const Teuchos::Comm< int > > GetComm() const
RCP< const map_type > importMap_
Xpetra::Map< LocalOrdinal, GlobalOrdinal, Node > map_type
RCP< const map_type > domainMap_
Graph maps.
RCP< crs_graph_type > GetCrsGraph() const
const std::string & getObjectLabel() const
void print(Teuchos::FancyOStream &out, const VerbLevel verbLevel=Default) const
Print the Graph with some verbosity level to an FancyOStream object.
LWGraphBase(const row_type &rows, const entries_type &columns, const RCP< const map_type > &domainMap, const RCP< const map_type > &importMap, const std::string &objectLabel="")
LocalOrdinal local_ordinal_type
const RCP< const Map > GetImportMap() const
Return overlapping import map (nodes).
typename device_type::memory_space memory_space
KOKKOS_INLINE_FUNCTION size_type GetNodeNumEdges() const
Return number of graph edges.
std::string objectLabel_
Name of this graph.
KokkosSparse::StaticCrsGraph< LocalOrdinal, Kokkos::LayoutLeft, typename Node::device_type, void, size_t > local_graph_device_type
KOKKOS_INLINE_FUNCTION neighbor_vertices_type getNeighborVertices(LO i) const
Return the list of vertices adjacent to the vertex 'v'.
LO minLocalIndex_
Local index boundaries (cached from domain map)
Namespace for MueLu classes and methods.
@ Debug
Print additional debugging information.