MueLu  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
MueLu_LWGraphBase.hpp
Go to the documentation of this file.
1 // @HEADER
2 //
3 // ***********************************************************************
4 //
5 // MueLu: A package for multigrid based preconditioning
6 // Copyright 2012 Sandia Corporation
7 //
8 // Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
9 // the U.S. Government retains certain rights in this software.
10 //
11 // Redistribution and use in source and binary forms, with or without
12 // modification, are permitted provided that the following conditions are
13 // met:
14 //
15 // 1. Redistributions of source code must retain the above copyright
16 // notice, this list of conditions and the following disclaimer.
17 //
18 // 2. Redistributions in binary form must reproduce the above copyright
19 // notice, this list of conditions and the following disclaimer in the
20 // documentation and/or other materials provided with the distribution.
21 //
22 // 3. Neither the name of the Corporation nor the names of the
23 // contributors may be used to endorse or promote products derived from
24 // this software without specific prior written permission.
25 //
26 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
27 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
30 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
31 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
32 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
33 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
34 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
35 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
36 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37 //
38 // Questions? Contact
39 // Jonathan Hu (jhu@sandia.gov)
40 // Andrey Prokopenko (aprokop@sandia.gov)
41 // Ray Tuminaro (rstumin@sandia.gov)
42 //
43 // ***********************************************************************
44 //
45 // @HEADER
46 #ifndef MUELU_LWGRAPHBASE_DECL_HPP
47 #define MUELU_LWGRAPHBASE_DECL_HPP
48 
49 #include "Kokkos_Bitset.hpp"
50 #include "MueLu_ConfigDefs.hpp"
51 
52 #include <Kokkos_StaticCrsGraph.hpp>
53 #include <Tpetra_KokkosCompat_ClassicNodeAPI_Wrapper.hpp>
54 #include <KokkosCompat_View.hpp>
55 
56 #include <Xpetra_ConfigDefs.hpp> // global_size_t
57 #include <Xpetra_Map_fwd.hpp>
58 #include <Xpetra_CrsGraph.hpp>
60 #include <type_traits>
61 
62 #include "MueLu_VerbosityLevel.hpp"
64 
65 #include "MueLu_Exceptions.hpp"
66 
67 namespace MueLu {
68 
69 namespace { // anonymous
70 
71 template <class LocalOrdinal, class RowType>
72 class MaxNumRowEntriesFunctor {
73  public:
74  MaxNumRowEntriesFunctor(RowType rowPointers)
75  : rowPointers_(rowPointers) {}
76 
77  KOKKOS_INLINE_FUNCTION
78  void operator()(const LocalOrdinal i, size_t& maxLength) const {
79  size_t d = rowPointers_(i + 1) - rowPointers_(i);
80 
81  maxLength = (d > maxLength ? d : maxLength);
82  }
83 
84  KOKKOS_INLINE_FUNCTION
85  void join(volatile size_t& dest, const volatile size_t& src) {
86  dest = (dest > src ? dest : src);
87  }
88 
89  KOKKOS_INLINE_FUNCTION
90  void init(size_t& initValue) {
91  initValue = 0;
92  }
93 
94  private:
95  RowType rowPointers_;
96 };
97 
98 } // namespace
99 
107 template <class LocalOrdinal, class GlobalOrdinal, class Node, bool OnHost>
108 class LWGraphBase {
109  public:
114  using size_type = size_t;
115 
116  using device_type = typename std::conditional<OnHost,
117  Kokkos::Device<Kokkos::Serial, Kokkos::HostSpace>,
118  typename Node::device_type>::type;
119  using execution_space = typename device_type::execution_space;
120  using memory_space = typename device_type::memory_space;
121 
122  using local_graph_device_type = Kokkos::StaticCrsGraph<LocalOrdinal,
123  Kokkos::LayoutLeft,
124  typename Node::device_type,
125  void, size_t>;
126  using local_graph_type = typename std::conditional<OnHost, typename local_graph_device_type::HostMirror, local_graph_device_type>::type;
127  using boundary_nodes_type = Kokkos::View<bool*, memory_space>;
128  using row_type = typename local_graph_type::row_map_type;
129  using entries_type = typename local_graph_type::entries_type;
130  using neighbor_vertices_type = Kokkos::GraphRowViewConst<local_graph_type>;
131 
132 #undef MUELU_LWGRAPHBASE_SHORT
134 
136 
137 
138  private:
139  void setup(const local_graph_type& graph,
140  const RCP<const map_type>& domainMap,
141  const RCP<const map_type>& importMap,
142  const std::string& objectLabel) {
143  using range_type = Kokkos::RangePolicy<local_ordinal_type, execution_space>;
144 
145  graph_ = graph;
146  domainMap_ = domainMap;
147  importMap_ = importMap;
148  objectLabel_ = objectLabel;
149 
152 
153  MaxNumRowEntriesFunctor<LO, typename local_graph_type::row_map_type> maxNumRowEntriesFunctor(graph_.row_map);
154  Kokkos::parallel_reduce("MueLu:LocalLWGraph:LWGraph:maxnonzeros", range_type(0, graph_.numRows()), maxNumRowEntriesFunctor, maxNumRowEntries_);
155  }
156 
157  public:
159  //
160  // @param[in] graph: local graph of type Kokkos::StaticCrsGraph containing CRS data
161  // @param[in] domainMap: non-overlapping (domain) map for graph. Usually provided by AmalgamationFactory stored in UnAmalgamationInfo container
162  // @param[in] importMap: overlapping map for graph. Usually provided by AmalgamationFactory stored in UnAmalgamationInfo container
163  // @param[in] objectLabel: label string
165  const RCP<const map_type>& domainMap,
166  const RCP<const map_type>& importMap,
167  const std::string& objectLabel = "") {
168  setup(graph, domainMap, importMap, objectLabel);
169  }
170 
172  const std::string& objectLabel = "") {
173  if constexpr (OnHost) {
174  // We want the graph data to live on host
175  if constexpr (std::is_same<local_graph_type,
176  typename crs_graph_type::local_graph_type>::value)
177  // The CrsGraph's data already lives on host.
178  setup(graph->getLocalGraphHost(), graph->getRowMap(), graph->getColMap(), objectLabel);
179  else {
180  // We deep-copy the graph to host once during construction instead of using the host mirror.
181  // This avoids issues with keeping a reference of the host mirror around.
182  auto lclGraphDevice = graph->getLocalGraphDevice();
183  auto rows = typename local_graph_type::row_map_type::non_const_type("rows", lclGraphDevice.numRows() + 1);
184  auto columns = typename local_graph_type::entries_type::non_const_type("columns", lclGraphDevice.entries.extent(0));
185  Kokkos::deep_copy(rows, lclGraphDevice.row_map);
186  Kokkos::deep_copy(columns, lclGraphDevice.entries);
187  local_graph_type lclGraph(columns, rows);
188  setup(lclGraph, graph->getRowMap(), graph->getColMap(), objectLabel);
189  }
190  } else {
191  // We want the graph data on device.
192  setup(graph->getLocalGraphDevice(), graph->getRowMap(), graph->getColMap(), objectLabel);
193  }
194  }
195 
197  const entries_type& columns,
198  const RCP<const map_type>& domainMap,
199  const RCP<const map_type>& importMap,
200  const std::string& objectLabel = "") {
201  const local_graph_type graph(columns, rows);
202  setup(graph, domainMap, importMap, objectLabel);
203  }
204 
205  ~LWGraphBase() = default;
207 
209  return domainMap_->getComm();
210  }
211  const RCP<const Map> GetDomainMap() const {
212  return domainMap_;
213  }
215  const RCP<const Map> GetImportMap() const {
216  return importMap_;
217  }
218 
220  KOKKOS_INLINE_FUNCTION size_type GetNodeNumVertices() const {
221  return graph_.numRows();
222  }
223 
225  KOKKOS_INLINE_FUNCTION size_type GetNodeNumEdges() const {
226  return graph_.row_map(GetNodeNumVertices());
227  }
228 
232  Teuchos::reduceAll(*domainMap_->getComm(), Teuchos::REDUCE_SUM, in, Teuchos::outArg(out));
233  return out;
234  }
235 
237  KOKKOS_INLINE_FUNCTION size_type getLocalMaxNumRowEntries() const {
238  return maxNumRowEntries_;
239  }
240 
242  KOKKOS_INLINE_FUNCTION neighbor_vertices_type getNeighborVertices(LO i) const {
243  auto rowView = graph_.rowConst(i);
244  return rowView;
245  }
246 
249  return Kokkos::Compat::getArrayView(Kokkos::subview(graph_.entries,
250  Kokkos::make_pair(graph_.row_map(i),
251  graph_.row_map(i + 1))));
252  }
253 
255  KOKKOS_INLINE_FUNCTION bool isLocalNeighborVertex(LO i) const {
256  return i >= minLocalIndex_ && i <= maxLocalIndex_;
257  }
258 
260  KOKKOS_INLINE_FUNCTION row_type getRowPtrs() const {
261  return graph_.row_map;
262  }
263 
265  KOKKOS_INLINE_FUNCTION entries_type getEntries() const {
266  return graph_.entries;
267  }
268 
270  KOKKOS_INLINE_FUNCTION void SetBoundaryNodeMap(const boundary_nodes_type bndry) {
271  dirichletBoundaries_ = bndry;
272  }
273 
275  KOKKOS_INLINE_FUNCTION const boundary_nodes_type GetBoundaryNodeMap() const {
276  return dirichletBoundaries_;
277  }
278 
280  std::string description() const {
281  return "LWGraphBase (" + objectLabel_ + ")";
282  }
283 
285  void print(Teuchos::FancyOStream& out, const VerbLevel verbLevel = Default) const {
286  if (verbLevel & Debug) {
287  auto graph = graph_;
289  int mypid = col_map->getComm()->getRank();
290 
291  {
292  std::ostringstream ss;
293  ss << "[pid " << mypid << "] num entries=" << graph.entries.size();
294  out << ss.str() << std::endl;
295  }
296 
297  const size_t numRows = graph.numRows();
298  auto rowPtrs = graph.row_map;
299  auto columns = graph.entries;
300  auto rowPtrs_h = Kokkos::create_mirror_view(rowPtrs);
301  auto columns_h = Kokkos::create_mirror_view(columns);
302  Kokkos::deep_copy(rowPtrs_h, rowPtrs);
303  Kokkos::deep_copy(columns_h, columns);
304  for (size_t i = 0; i < numRows; ++i) {
305  std::ostringstream ss;
306  ss << "[pid " << mypid << "] row " << domainMap_->getGlobalElement(i) << ":";
307  ss << " (numEntries=" << rowPtrs_h(i + 1) - rowPtrs_h(i) << ")";
308 
309  for (size_t jj = rowPtrs_h(i); jj < rowPtrs_h(i + 1); jj++) {
310  ss << " " << col_map->getGlobalElement(columns_h(jj));
311  }
312  out << ss.str() << std::endl;
313  }
314  }
315  }
316 
318  return graph_;
319  }
320 
322  RCP<crs_graph_type> graph;
323  if constexpr (std::is_same<local_graph_type,
324  typename crs_graph_type::local_graph_type>::value)
326  else {
327  auto rows = typename crs_graph_type::local_graph_type::row_map_type::non_const_type("rows", graph_.numRows() + 1);
328  auto columns = typename crs_graph_type::local_graph_type::entries_type::non_const_type("columns", graph_.entries.extent(0));
329  Kokkos::deep_copy(rows, graph_.row_map);
330  Kokkos::deep_copy(columns, graph_.entries);
331  typename crs_graph_type::local_graph_type lclGraph(columns, rows);
333  }
334  return graph;
335  }
336 
337  private:
340 
344 
346  std::string objectLabel_;
347 
350 
354 };
355 
356 } // namespace MueLu
357 
358 #define MUELU_LWGRAPHBASE_SHORT
359 #endif // MUELU_LWGRAPHBASE_DECL_HPP
local_graph_type & getGraph() const
void setup(const local_graph_type &graph, const RCP< const map_type > &domainMap, const RCP< const map_type > &importMap, const std::string &objectLabel)
virtual Teuchos::RCP< const Teuchos::Comm< int > > getComm() const =0
MueLu::DefaultLocalOrdinal LocalOrdinal
virtual LocalOrdinal getMinLocalIndex() const =0
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.
void print(Teuchos::FancyOStream &out, const VerbLevel verbLevel=Default) const
Print the Graph with some verbosity level to an FancyOStream object.
RCP< const map_type > importMap_
typename std::conditional< OnHost, typename local_graph_device_type::HostMirror, local_graph_device_type >::type local_graph_type
RowType rowPointers_
RCP< crs_graph_type > GetCrsGraph() const
static Teuchos::RCP< CrsGraph< LocalOrdinal, GlobalOrdinal, Node > > Build(const Teuchos::RCP< const Map< LocalOrdinal, GlobalOrdinal, Node > > &map, size_t NumVectors, ProfileType pftype=DynamicProfile)
std::string description() const
Return a simple one-line description of the Graph.
Print additional debugging information.
LocalOrdinal LO
KOKKOS_INLINE_FUNCTION size_type GetNodeNumVertices() const
Return number of graph vertices.
KOKKOS_INLINE_FUNCTION size_type GetNodeNumEdges() const
Return number of graph edges.
KOKKOS_INLINE_FUNCTION const boundary_nodes_type GetBoundaryNodeMap() const
Returns map with global ids of boundary nodes.
KOKKOS_INLINE_FUNCTION size_type getLocalMaxNumRowEntries() const
Returns the maximum number of entries across all rows/columns on this node.
Kokkos::GraphRowViewConst< local_graph_type > neighbor_vertices_type
MueLu::DefaultGlobalOrdinal GlobalOrdinal
local_graph_type graph_
Underlying graph (with label)
KOKKOS_INLINE_FUNCTION entries_type getEntries() const
Return the list entries in the local graph.
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="")
KOKKOS_INLINE_FUNCTION bool isLocalNeighborVertex(LO i) const
Return true if vertex with local id &#39;v&#39; is on current process.
virtual GlobalOrdinal getGlobalElement(LocalOrdinal localIndex) const =0
Kokkos::StaticCrsGraph< LocalOrdinal, Kokkos::LayoutLeft, typename Node::device_type, void, size_t > local_graph_device_type
virtual LocalOrdinal getMaxLocalIndex() const =0
size_t global_size_t
KOKKOS_INLINE_FUNCTION neighbor_vertices_type getNeighborVertices(LO i) const
Return the list of vertices adjacent to the vertex &#39;v&#39;.
const RCP< const Map > GetImportMap() const
Return overlapping import map (nodes).
boundary_nodes_type dirichletBoundaries_
Boolean array marking Dirichlet rows.
Xpetra::global_size_t GetGlobalNumEdges() const
Return global number of graph edges.
const RCP< const Map > GetDomainMap() const
Teuchos::ArrayView< LO > getNeighborVertices_av(LO i) const
Return the list of vertices adjacent to the vertex &#39;v&#39;.
virtual RCP< const Map< LocalOrdinal, GlobalOrdinal, Node > > getRowMap() const =0
LWGraphBase(const local_graph_type &graph, const RCP< const map_type > &domainMap, const RCP< const map_type > &importMap, const std::string &objectLabel="")
LWGraph constructor.
RCP< const map_type > domainMap_
Graph maps.
typename std::conditional< OnHost, Kokkos::Device< Kokkos::Serial, Kokkos::HostSpace >, typename Node::device_type >::type device_type
std::string objectLabel_
Name of this graph.
const RCP< const Teuchos::Comm< int > > GetComm() const
LO minLocalIndex_
Local index boundaries (cached from domain map)
LWGraphBase(const RCP< const crs_graph_type > &graph, const std::string &objectLabel="")
~LWGraphBase()=default
bool is_null() const
virtual RCP< const Map< LocalOrdinal, GlobalOrdinal, Node > > getColMap() const =0