Tpetra parallel linear algebra  Version of the Day
Tpetra_CrsGraphTransposer_def.hpp
1 // @HEADER
2 // ***********************************************************************
3 //
4 // Tpetra: Templated Linear Algebra Services Package
5 // Copyright (2008) Sandia Corporation
6 //
7 // Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
8 // the U.S. Government retains certain rights in this software.
9 //
10 // Redistribution and use in source and binary forms, with or without
11 // modification, are permitted provided that the following conditions are
12 // met:
13 //
14 // 1. Redistributions of source code must retain the above copyright
15 // notice, this list of conditions and the following disclaimer.
16 //
17 // 2. Redistributions in binary form must reproduce the above copyright
18 // notice, this list of conditions and the following disclaimer in the
19 // documentation and/or other materials provided with the distribution.
20 //
21 // 3. Neither the name of the Corporation nor the names of the
22 // contributors may be used to endorse or promote products derived from
23 // this software without specific prior written permission.
24 //
25 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
26 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
28 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
29 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
30 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
31 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
32 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
33 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
34 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
35 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 //
37 // Questions? Contact Michael A. Heroux (maherou@sandia.gov)
38 //
39 // ************************************************************************
40 // @HEADER
41 
42 #ifndef TPETRA_CRSGRAPHTRANSPOSER_DEF_HPP
43 #define TPETRA_CRSGRAPHTRANSPOSER_DEF_HPP
44 
45 #include "Tpetra_CrsGraph.hpp"
46 #include "Tpetra_Export.hpp"
48 #include "Tpetra_Details_makeColMap.hpp"
50 #include "Teuchos_ParameterList.hpp"
51 #include "Teuchos_TimeMonitor.hpp"
52 #include "KokkosKernels_SparseUtils.hpp"
53 #include "KokkosKernels_Handle.hpp"
54 #include "KokkosSparse_spadd.hpp"
55 
56 namespace Tpetra {
57 
58  template<typename GO,
59  typename LocalIndicesType,
60  typename GlobalIndicesType,
61  typename ColMapType>
62  struct ConvertLocalToGlobalFunctor
63  {
64  ConvertLocalToGlobalFunctor(
65  const LocalIndicesType& colindsOrig_,
66  const GlobalIndicesType& colindsConverted_,
67  const ColMapType& colmap_) :
68  colindsOrig (colindsOrig_),
69  colindsConverted (colindsConverted_),
70  colmap (colmap_)
71  {}
72  KOKKOS_INLINE_FUNCTION void
73  operator() (const GO i) const
74  {
75  colindsConverted(i) = colmap.getGlobalElement(colindsOrig(i));
76  }
77  LocalIndicesType colindsOrig;
78  GlobalIndicesType colindsConverted;
79  ColMapType colmap;
80  };
81 
82  template<class LO, class GO, class LOView, class GOView, class LocalMap>
83  struct ConvertGlobalToLocalFunctor
84  {
85  ConvertGlobalToLocalFunctor(LOView& lids_, const GOView& gids_, const LocalMap localColMap_)
86  : lids(lids_), gids(gids_), localColMap(localColMap_)
87  {}
88 
89  KOKKOS_FUNCTION void operator() (const GO i) const
90  {
91  lids(i) = localColMap.getLocalElement(gids(i));
92  }
93 
94  LOView lids;
95  const GOView gids;
96  const LocalMap localColMap;
97  };
98 
99 
100  template <typename size_type, typename ordinal_type,
101  typename ArowptrsT, typename BrowptrsT, typename CrowptrsT,
102  typename AcolindsT, typename BcolindsT, typename CcolindsT>
103  struct SortedNumericIndicesOnlyFunctor {
104 
105  SortedNumericIndicesOnlyFunctor(const ArowptrsT& Arowptrs_,
106  const BrowptrsT& Browptrs_,
107  const CrowptrsT& Crowptrs_,
108  const AcolindsT& Acolinds_,
109  const BcolindsT& Bcolinds_,
110  const CcolindsT& Ccolinds_)
111  : Arowptrs(Arowptrs_),
112  Browptrs(Browptrs_),
113  Crowptrs(Crowptrs_),
114  Acolinds(Acolinds_),
115  Bcolinds(Bcolinds_),
116  Ccolinds(Ccolinds_) {}
117 
118  KOKKOS_INLINE_FUNCTION void operator()(const ordinal_type i) const
119  {
120  const ordinal_type ORDINAL_MAX = Kokkos::ArithTraits<ordinal_type>::max();
121 
122  // count the union of nonzeros in Arow and Brow
123  size_type ai = 0;
124  size_type bi = 0;
125  size_type Arowstart = Arowptrs(i);
126  size_type Arowlen = Arowptrs(i + 1) - Arowstart;
127  size_type Browstart = Browptrs(i);
128  size_type Browlen = Browptrs(i + 1) - Browstart;
129  ordinal_type Acol = (Arowlen == 0) ? ORDINAL_MAX : Acolinds(Arowstart);
130  ordinal_type Bcol = (Browlen == 0) ? ORDINAL_MAX : Bcolinds(Browstart);
131  size_type Coffset = Crowptrs(i);
132  while (Acol != ORDINAL_MAX || Bcol != ORDINAL_MAX)
133  {
134  ordinal_type Ccol = (Acol < Bcol) ? Acol : Bcol;
135  while(Acol == Ccol)
136  {
137  ai++;
138  if(ai == Arowlen)
139  Acol = ORDINAL_MAX;
140  else
141  Acol = Acolinds(Arowstart + ai);
142  }
143  while(Bcol == Ccol)
144  {
145  bi++;
146  if(bi == Browlen)
147  Bcol = ORDINAL_MAX;
148  else
149  Bcol = Bcolinds(Browstart + bi);
150  }
151  Ccolinds(Coffset) = Ccol;
152  Coffset++;
153  }
154  }
155 
156  const ArowptrsT Arowptrs;
157  const BrowptrsT Browptrs;
158  const CrowptrsT Crowptrs;
159  const AcolindsT Acolinds;
160  const BcolindsT Bcolinds;
161  CcolindsT Ccolinds;
162  };
163 
164  template <typename size_type, typename ordinal_type,
165  typename ArowptrsT, typename BrowptrsT, typename CrowptrsT,
166  typename AcolindsT, typename BcolindsT, typename CcolindsT>
167  struct UnsortedNumericIndicesOnlyFunctor {
168 
169  UnsortedNumericIndicesOnlyFunctor(
170  const ArowptrsT Arowptrs_, const BrowptrsT Browptrs_, const CrowptrsT Crowptrs_,
171  const AcolindsT Acolinds_, const BcolindsT Bcolinds_, CcolindsT Ccolinds_,
172  const CcolindsT Apos_, const CcolindsT Bpos_)
173  : Arowptrs(Arowptrs_),
174  Browptrs(Browptrs_),
175  Crowptrs(Crowptrs_),
176  Acolinds(Acolinds_),
177  Bcolinds(Bcolinds_),
178  Ccolinds(Ccolinds_),
179  Apos(Apos_),
180  Bpos(Bpos_) {}
181 
182  KOKKOS_INLINE_FUNCTION void operator()(const ordinal_type i) const {
183  size_type CrowStart = Crowptrs(i);
184  size_type ArowStart = Arowptrs(i);
185  size_type ArowEnd = Arowptrs(i + 1);
186  size_type BrowStart = Browptrs(i);
187  size_type BrowEnd = Browptrs(i + 1);
188  // add in A entries, while setting C colinds
189  for (size_type j = ArowStart; j < ArowEnd; j++) {
190  Ccolinds(CrowStart + Apos(j)) = Acolinds(j);
191  }
192  // add in B entries, while setting C colinds
193  for (size_type j = BrowStart; j < BrowEnd; j++) {
194  Ccolinds(CrowStart + Bpos(j)) = Bcolinds(j);
195  }
196  }
197  const ArowptrsT Arowptrs;
198  const BrowptrsT Browptrs;
199  const CrowptrsT Crowptrs;
200  const AcolindsT Acolinds;
201  const BcolindsT Bcolinds;
202  CcolindsT Ccolinds;
203  const CcolindsT Apos;
204  const CcolindsT Bpos;
205  };
206 
207 
208  template<class LocalOrdinal,
209  class GlobalOrdinal,
210  class Node>
212  CrsGraphTransposer (const Teuchos::RCP<const crs_graph_type>& origGraph,
213  const std::string& label)
214  : origGraph_ (origGraph), label_ (label)
215  {}
216 
217  template<class LocalOrdinal,
218  class GlobalOrdinal,
219  class Node>
220  Teuchos::RCP<CrsGraph<LocalOrdinal, GlobalOrdinal, Node> >
222  symmetrize (const Teuchos::RCP<Teuchos::ParameterList> &params)
223  {
224  using Teuchos::RCP;
225  using device_type = typename Node::device_type;
226  using execution_space = typename device_type::execution_space;
227  using range_type = Kokkos::RangePolicy<execution_space, size_t>;
228  using local_graph_device_type = typename crs_graph_type::local_graph_device_type;
229  using impl_scalar_type = ::Tpetra::Details::DefaultTypes::scalar_type;
230  using row_ptrs_array = typename local_graph_device_type::row_map_type::non_const_type ;
231  using col_inds_array = typename local_graph_device_type::entries_type::non_const_type;
232  using local_map_type = typename map_type::local_map_type;
233  using global_col_inds_array = typename Kokkos::View<GlobalOrdinal*, device_type>;
234 
235  auto graph = origGraph_;
236  auto domain_map = graph->getDomainMap();
237  auto range_map = graph->getRangeMap();
238  auto row_map = graph->getRowMap();
239  auto col_map = graph->getColMap();
240  RCP<const map_type> col_map_sym;
241  RCP<const Import<LocalOrdinal,GlobalOrdinal,Node> > importer;
242 
243  TEUCHOS_ASSERT(domain_map->isSameAs(*range_map));
244  TEUCHOS_ASSERT(domain_map->isSameAs(*row_map));
245 
246  // Do the transpose
247  RCP<crs_graph_type> graphT = createTranspose (params);
248 
249  auto col_map_T = graphT->getColMap();
250  TEUCHOS_ASSERT(!col_map_T.is_null());
251  TEUCHOS_ASSERT(domain_map->isSameAs(*graphT->getDomainMap()));
252 
253  bool graphSorted = graph->isSorted();
254  bool graphTSorted = graphT->isSorted();
255  bool sorted = graphSorted && graphTSorted;
256  bool matchingColMaps = col_map->isSameAs(*col_map_T);
257 
258  auto lclGraph = graph->getLocalGraphDevice();
259  auto lclGraphT = graphT->getLocalGraphDevice();
260 
261  using KKH_LO = KokkosKernels::Experimental::KokkosKernelsHandle<size_t, LocalOrdinal, impl_scalar_type,
262  typename Node::execution_space, typename Node::memory_space, typename Node::memory_space>;
263  using KKH_GO = KokkosKernels::Experimental::KokkosKernelsHandle<size_t, GlobalOrdinal, impl_scalar_type,
264  typename Node::execution_space, typename Node::memory_space, typename Node::memory_space>;
265 
266  auto rowptrs = lclGraph.row_map;
267  auto rowptrsT = lclGraphT.row_map;
268  auto colinds = lclGraph.entries;
269  auto colindsT = lclGraphT.entries;
270 
271  auto nrows = rowptrs.extent(0) - 1;
272  auto rowptrsSym = row_ptrs_array(Kokkos::ViewAllocateWithoutInitializing("row ptrs sym"), nrows + 1);
273 
274  col_inds_array colindsSym;
275 
276  if(!matchingColMaps) {
277  // convert indices of local graph to GlobalOrdinal
278  auto lclColmap = col_map->getLocalMap();
279  global_col_inds_array colindsConverted(Kokkos::ViewAllocateWithoutInitializing("colinds (converted)"), colinds.extent(0));
280  ConvertLocalToGlobalFunctor<GlobalOrdinal, col_inds_array, global_col_inds_array, local_map_type> convert(colinds, colindsConverted, lclColmap);
281  Kokkos::parallel_for("colInds (converted)", range_type(0, colinds.extent(0)), convert);
282 
283  // convert indices of local graphT to GlobalOrdinal
284  auto lclColmapT = col_map_T->getLocalMap();
285  global_col_inds_array colindsTConverted(Kokkos::ViewAllocateWithoutInitializing("colindsT (converted)"), colindsT.extent(0));
286  ConvertLocalToGlobalFunctor<GlobalOrdinal, col_inds_array, global_col_inds_array, local_map_type> convertT(colindsT, colindsTConverted, lclColmapT);
287  Kokkos::parallel_for("colIndsT (converted)", range_type(0, colindsT.extent(0)), convertT);
288 
289  // sum graph and graphT in GlobalOrdinal
290  KKH_GO handle;
291  handle.create_spadd_handle(false);
292  auto addHandle = handle.get_spadd_handle();
293 
294  global_col_inds_array globalColindsSym;
295 
296  KokkosSparse::Experimental::spadd_symbolic
297  <KKH_GO, typename row_ptrs_array::const_type, typename global_col_inds_array::const_type, typename row_ptrs_array::const_type, typename global_col_inds_array::const_type, row_ptrs_array, global_col_inds_array>
298  (&handle, rowptrs, colindsConverted, rowptrsT, colindsTConverted, rowptrsSym);
299  globalColindsSym = global_col_inds_array(Kokkos::ViewAllocateWithoutInitializing("global colinds sym"), addHandle->get_c_nnz());
300 
301  UnsortedNumericIndicesOnlyFunctor<
302  size_t, GlobalOrdinal,
303  typename row_ptrs_array::const_type, typename row_ptrs_array::const_type, row_ptrs_array,
304  typename global_col_inds_array::const_type, typename global_col_inds_array::const_type, global_col_inds_array>
305  unsortedNumeric(rowptrs, rowptrsT, rowptrsSym,
306  colindsConverted, colindsTConverted, globalColindsSym,
307  addHandle->get_a_pos(), addHandle->get_b_pos());
308  Kokkos::parallel_for("KokkosSparse::SpAdd:Numeric::InputNotSorted",
309  range_type(0, nrows), unsortedNumeric);
310 
311  // build column map for graphSym
312  Tpetra::Details::makeColMap<LocalOrdinal, GlobalOrdinal, Node>
313  (col_map_sym, domain_map, globalColindsSym);
314 
315  // convert indices of local graphSym to LocalOrdinal
316  auto lclColmapSym = col_map_sym->getLocalMap();
317  colindsSym = col_inds_array("colindsSym", globalColindsSym.extent(0));
318  ConvertGlobalToLocalFunctor<LocalOrdinal, GlobalOrdinal, col_inds_array, global_col_inds_array, typename map_type::local_map_type> convertSym(colindsSym, globalColindsSym, lclColmapSym);
319  Kokkos::parallel_for(range_type(0, globalColindsSym.extent(0)), convertSym);
320 
321  } else {
322 
323  // sum graph and graphT in LocalOrdinal
324  KKH_LO handle;
325  handle.create_spadd_handle(sorted);
326  auto addHandle = handle.get_spadd_handle();
327 
328  KokkosSparse::Experimental::spadd_symbolic
329  <KKH_LO,
330  typename row_ptrs_array::const_type, typename col_inds_array::const_type,
331  typename row_ptrs_array::const_type, typename col_inds_array::const_type,
332  row_ptrs_array, col_inds_array>
333  (&handle, rowptrs, colinds, rowptrsT, colindsT, rowptrsSym);
334  colindsSym = col_inds_array(Kokkos::ViewAllocateWithoutInitializing("C colinds"), addHandle->get_c_nnz());
335 
336  if (sorted) {
337  SortedNumericIndicesOnlyFunctor<
338  size_t, LocalOrdinal,
339  typename row_ptrs_array::const_type, typename row_ptrs_array::const_type, row_ptrs_array,
340  typename col_inds_array::const_type, typename col_inds_array::const_type, col_inds_array>
341  sortedNumeric(rowptrs, rowptrsT, rowptrsSym,
342  colinds, colindsT, colindsSym);
343  Kokkos::parallel_for("KokkosSparse::SpAdd:Numeric::InputSorted",
344  range_type(0, nrows), sortedNumeric);
345 
346  } else {
347  UnsortedNumericIndicesOnlyFunctor<
348  size_t, LocalOrdinal,
349  typename row_ptrs_array::const_type, typename row_ptrs_array::const_type, row_ptrs_array,
350  typename col_inds_array::const_type, typename col_inds_array::const_type, col_inds_array>
351  unsortedNumeric(rowptrs, rowptrsT, rowptrsSym,
352  colinds, colindsT, colindsSym,
353  addHandle->get_a_pos(), addHandle->get_b_pos());
354  Kokkos::parallel_for("KokkosSparse::SpAdd:Numeric::InputNotSorted",
355  range_type(0, nrows), unsortedNumeric);
356  }
357 
358  // column map for graphSym is graph's column map
359  col_map_sym = col_map;
360  importer = graph->getImporter();
361  }
362 
363  bool sort = true;
364  if (sort)
365  KokkosKernels::Impl::sort_crs_graph<execution_space, row_ptrs_array, col_inds_array>(rowptrsSym, colindsSym);
366 
367  local_graph_device_type lclGraphSym = local_graph_device_type(colindsSym, rowptrsSym);
368 
369  RCP<Teuchos::ParameterList> graphParams = Teuchos::null;
370  if(!sort) {
371  graphParams = rcp(new Teuchos::ParameterList);
372  graphParams->set("sorted", false);
373  }
374 
375  return rcp (new crs_graph_type (lclGraphSym,
376  row_map,
377  col_map_sym,
378  domain_map,
379  range_map,
380  importer,
381  Teuchos::null,
382  graphParams));
383  }
384 
385  template<class LocalOrdinal,
386  class GlobalOrdinal,
387  class Node>
388  Teuchos::RCP<CrsGraph<LocalOrdinal, GlobalOrdinal, Node> >
390  createTranspose (const Teuchos::RCP<Teuchos::ParameterList> &params)
391  {
392  using Teuchos::RCP;
393  // Do the local transpose
394  RCP<crs_graph_type> transGraphWithSharedRows = createTransposeLocal (params);
395 
396 #ifdef HAVE_TPETRA_MMM_TIMINGS
397  const std::string prefix = std::string ("Tpetra ") + label_ + ": ";
398  using Teuchos::TimeMonitor;
399  TimeMonitor MM (*TimeMonitor::getNewTimer (prefix + "Transpose TAFC"));
400 #endif
401 
402  // If transGraphWithSharedRows has an exporter, that's what we
403  // want. If it doesn't, the rows aren't actually shared, and we're
404  // done!
405  using export_type = Export<LocalOrdinal, GlobalOrdinal, Node>;
406  RCP<const export_type> exporter =
407  transGraphWithSharedRows->getExporter ();
408  if (exporter.is_null ()) {
409  return transGraphWithSharedRows;
410  }
411  else {
412  Teuchos::ParameterList labelList;
413 #ifdef HAVE_TPETRA_MMM_TIMINGS
414  labelList.set("Timer Label", label_);
415 #endif
416  if(! params.is_null ()) {
417  const char paramName[] = "compute global constants";
418  labelList.set (paramName, params->get (paramName, true));
419  }
420  // Use the Export object to do a fused Export and fillComplete.
421  // This always sorts the local graph after communication, so
422  // no need to set "sorted = false" in parameters.
423  return exportAndFillCompleteCrsGraph<crs_graph_type>
424  (transGraphWithSharedRows, *exporter, Teuchos::null,
425  Teuchos::null, Teuchos::rcpFromRef (labelList));
426  }
427  }
428 
429  template<class LocalOrdinal,
430  class GlobalOrdinal,
431  class Node>
432  Teuchos::RCP<CrsGraph<LocalOrdinal, GlobalOrdinal, Node> >
434  createTransposeLocal (const Teuchos::RCP<Teuchos::ParameterList> &params)
435  {
436  using Teuchos::RCP;
437  using Teuchos::rcp;
438  using Teuchos::rcp_dynamic_cast;
439  using LO = LocalOrdinal;
440  using GO = GlobalOrdinal;
441  using import_type = Tpetra::Import<LO, GO, Node>;
442  using export_type = Tpetra::Export<LO, GO, Node>;
443 
444 #ifdef HAVE_TPETRA_MMM_TIMINGS
445  std::string prefix = std::string("Tpetra ") + label_ + ": ";
446  using Teuchos::TimeMonitor;
447  TimeMonitor MM (*TimeMonitor::getNewTimer (prefix + "Transpose Local"));
448 #endif
449 
450  const bool sort = [&] () {
451  constexpr bool sortDefault = true; // see #4607 discussion
452  const char sortParamName[] = "sort";
453  return params.get () == nullptr ? sortDefault :
454  params->get (sortParamName, sortDefault);
455  } ();
456 
457  using local_graph_device_type = typename crs_graph_type::local_graph_device_type;
458  local_graph_device_type lclGraph = origGraph_->getLocalGraphDevice ();
459 
460  //Allocate views and call the other version of transpose_graph
461  using c_rowmap_t = typename local_graph_device_type::row_map_type;
462  using c_entries_t = typename local_graph_device_type::entries_type;
463  using rowmap_t = typename local_graph_device_type::row_map_type::non_const_type;
464  using entries_t = typename local_graph_device_type::entries_type::non_const_type;
465  LocalOrdinal numCols = origGraph_->getColMap()->getNodeNumElements();
466  rowmap_t lclGraphT_rowmap("Transpose rowmap", numCols + 1);
467  entries_t lclGraphT_entries(
468  Kokkos::ViewAllocateWithoutInitializing("Transpose entries"), lclGraph.entries.extent(0));
469  KokkosKernels::Impl::transpose_graph<
470  c_rowmap_t, c_entries_t,
471  rowmap_t, entries_t,
472  rowmap_t, typename local_graph_device_type::execution_space>(
473  lclGraph.numRows(), numCols,
474  lclGraph.row_map, lclGraph.entries,
475  lclGraphT_rowmap, lclGraphT_entries);
476 
477  if (sort)
478  KokkosKernels::Impl::sort_crs_graph<
479  typename local_graph_device_type::execution_space,
480  rowmap_t, entries_t>(
481  lclGraphT_rowmap,
482  lclGraphT_entries);
483 
484  //And construct the transpose local_graph_device_type
485  local_graph_device_type lclGraphT = local_graph_device_type(lclGraphT_entries, lclGraphT_rowmap);
486 
487  // Prebuild the importers and exporters the no-communication way,
488  // flipping the importers and exporters around.
489  const auto origExport = origGraph_->getExporter ();
490  RCP<const import_type> myImport = origExport.is_null () ?
491  Teuchos::null : rcp (new import_type (*origExport));
492  const auto origImport = origGraph_->getImporter ();
493  RCP<const export_type> myExport = origImport.is_null () ?
494  Teuchos::null : rcp (new export_type (*origImport));
495 
496  RCP<Teuchos::ParameterList> graphParams = Teuchos::null;
497  if(!sort) {
498  graphParams = rcp(new Teuchos::ParameterList);
499  graphParams->set("sorted", false);
500  }
501 
502  return rcp (new crs_graph_type (lclGraphT,
503  origGraph_->getColMap (),
504  origGraph_->getRowMap (),
505  origGraph_->getRangeMap (),
506  origGraph_->getDomainMap (),
507  myImport, myExport, graphParams));
508  }
509 
510  //
511  // Explicit instantiation macro
512  //
513  // Must be expanded from within the Tpetra namespace!
514  //
515 
516 #define TPETRA_CRSGRAPHTRANSPOSER_INSTANT(LO,GO,NODE) \
517  template class CrsGraphTransposer< LO , GO , NODE >;
518 
519 } // namespace Tpetra
520 
521 #endif
Declare and define the functions Tpetra::Details::computeOffsetsFromCounts and Tpetra::computeOffsets...
Declaration and definition of functions for sorting "short" arrays of keys and corresponding values.
CrsGraphTransposer(const Teuchos::RCP< const crs_graph_type > &origGraph, const std::string &label=std::string())
Constructor that takes the graph to transpose.
Teuchos::RCP< crs_graph_type > createTransposeLocal(const Teuchos::RCP< Teuchos::ParameterList > &params=Teuchos::null)
Compute and return the transpose of the graph given to the constructor.
Teuchos::RCP< crs_graph_type > createTranspose(const Teuchos::RCP< Teuchos::ParameterList > &params=Teuchos::null)
Compute and return the transpose of the graph given to the constructor.
Teuchos::RCP< crs_graph_type > symmetrize(const Teuchos::RCP< Teuchos::ParameterList > &params=Teuchos::null)
Compute and return graph+graph^T of the graph given to the constructor.
A distributed graph accessed by rows (adjacency lists) and stored sparsely.
Kokkos::StaticCrsGraph< local_ordinal_type, Kokkos::LayoutLeft, device_type, void, size_t > local_graph_device_type
The type of the part of the sparse graph on each MPI process.
"Local" part of Map suitable for Kokkos kernels.
Communication plan for data redistribution from a (possibly) multiply-owned to a uniquely-owned distr...
Communication plan for data redistribution from a uniquely-owned to a (possibly) multiply-owned distr...
Namespace Tpetra contains the class and methods constituting the Tpetra library.
void sort(View &view, const size_t &size)
Convenience wrapper for std::sort for host-accessible views.