42 #ifndef TPETRA_CRSGRAPHTRANSPOSER_DEF_HPP
43 #define TPETRA_CRSGRAPHTRANSPOSER_DEF_HPP
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 "KokkosSparse_Utils.hpp"
53 #include "KokkosKernels_Handle.hpp"
54 #include "KokkosSparse_spadd.hpp"
59 typename LocalIndicesType,
60 typename GlobalIndicesType,
62 struct ConvertLocalToGlobalFunctor
64 ConvertLocalToGlobalFunctor(
65 const LocalIndicesType& colindsOrig_,
66 const GlobalIndicesType& colindsConverted_,
67 const ColMapType& colmap_) :
68 colindsOrig (colindsOrig_),
69 colindsConverted (colindsConverted_),
72 KOKKOS_INLINE_FUNCTION
void
73 operator() (
const GO i)
const
75 colindsConverted(i) = colmap.getGlobalElement(colindsOrig(i));
77 LocalIndicesType colindsOrig;
78 GlobalIndicesType colindsConverted;
82 template<
class LO,
class GO,
class LOView,
class GOView,
class LocalMap>
83 struct ConvertGlobalToLocalFunctor
85 ConvertGlobalToLocalFunctor(LOView& lids_,
const GOView& gids_,
const LocalMap localColMap_)
86 : lids(lids_), gids(gids_), localColMap(localColMap_)
89 KOKKOS_FUNCTION
void operator() (
const GO i)
const
91 lids(i) = localColMap.getLocalElement(gids(i));
96 const LocalMap localColMap;
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 {
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_),
116 Ccolinds(Ccolinds_) {}
118 KOKKOS_INLINE_FUNCTION
void operator()(
const ordinal_type i)
const
120 const ordinal_type ORDINAL_MAX = Kokkos::ArithTraits<ordinal_type>::max();
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)
134 ordinal_type Ccol = (Acol < Bcol) ? Acol : Bcol;
141 Acol = Acolinds(Arowstart + ai);
149 Bcol = Bcolinds(Browstart + bi);
151 Ccolinds(Coffset) = Ccol;
156 const ArowptrsT Arowptrs;
157 const BrowptrsT Browptrs;
158 const CrowptrsT Crowptrs;
159 const AcolindsT Acolinds;
160 const BcolindsT Bcolinds;
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 {
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_),
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);
189 for (size_type j = ArowStart; j < ArowEnd; j++) {
190 Ccolinds(CrowStart + Apos(j)) = Acolinds(j);
193 for (size_type j = BrowStart; j < BrowEnd; j++) {
194 Ccolinds(CrowStart + Bpos(j)) = Bcolinds(j);
197 const ArowptrsT Arowptrs;
198 const BrowptrsT Browptrs;
199 const CrowptrsT Crowptrs;
200 const AcolindsT Acolinds;
201 const BcolindsT Bcolinds;
203 const CcolindsT Apos;
204 const CcolindsT Bpos;
208 template<
class LocalOrdinal,
213 const std::string& label)
214 : origGraph_ (origGraph), label_ (label)
217 template<
class LocalOrdinal,
220 Teuchos::RCP<CrsGraph<LocalOrdinal, GlobalOrdinal, Node> >
222 symmetrize (
const Teuchos::RCP<Teuchos::ParameterList> ¶ms)
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>;
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;
233 using global_col_inds_array =
typename Kokkos::View<GlobalOrdinal*, device_type>;
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;
243 TEUCHOS_ASSERT(domain_map->isSameAs(*range_map));
244 TEUCHOS_ASSERT(domain_map->isSameAs(*row_map));
247 RCP<crs_graph_type> graphT = createTranspose (params);
249 auto col_map_T = graphT->getColMap();
250 TEUCHOS_ASSERT(!col_map_T.is_null());
251 TEUCHOS_ASSERT(domain_map->isSameAs(*graphT->getDomainMap()));
253 bool graphSorted = graph->isSorted();
254 bool graphTSorted = graphT->isSorted();
255 bool sorted = graphSorted && graphTSorted;
256 bool matchingColMaps = col_map->isSameAs(*col_map_T);
258 auto lclGraph = graph->getLocalGraphDevice();
259 auto lclGraphT = graphT->getLocalGraphDevice();
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>;
266 auto rowptrs = lclGraph.row_map;
267 auto rowptrsT = lclGraphT.row_map;
268 auto colinds = lclGraph.entries;
269 auto colindsT = lclGraphT.entries;
271 auto nrows = rowptrs.extent(0) - 1;
272 auto rowptrsSym = row_ptrs_array(Kokkos::ViewAllocateWithoutInitializing(
"row ptrs sym"), nrows + 1);
274 col_inds_array colindsSym;
276 if(!matchingColMaps) {
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);
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);
291 handle.create_spadd_handle(
false);
292 auto addHandle = handle.get_spadd_handle();
294 global_col_inds_array globalColindsSym;
296 KokkosSparse::Experimental::spadd_symbolic
298 #
if KOKKOSKERNELS_VERSION >= 40299
299 nrows, graph->getGlobalNumCols(),
301 rowptrs, colindsConverted, rowptrsT, colindsTConverted, rowptrsSym);
302 globalColindsSym = global_col_inds_array(Kokkos::ViewAllocateWithoutInitializing(
"global colinds sym"), addHandle->get_c_nnz());
304 UnsortedNumericIndicesOnlyFunctor<
305 size_t, GlobalOrdinal,
306 typename row_ptrs_array::const_type,
typename row_ptrs_array::const_type, row_ptrs_array,
307 typename global_col_inds_array::const_type,
typename global_col_inds_array::const_type, global_col_inds_array>
308 unsortedNumeric(rowptrs, rowptrsT, rowptrsSym,
309 colindsConverted, colindsTConverted, globalColindsSym,
310 addHandle->get_a_pos(), addHandle->get_b_pos());
311 Kokkos::parallel_for(
"KokkosSparse::SpAdd:Numeric::InputNotSorted",
312 range_type(0, nrows), unsortedNumeric);
315 Tpetra::Details::makeColMap<LocalOrdinal, GlobalOrdinal, Node>
316 (col_map_sym, domain_map, globalColindsSym);
319 auto lclColmapSym = col_map_sym->getLocalMap();
320 colindsSym = col_inds_array(
"colindsSym", globalColindsSym.extent(0));
321 ConvertGlobalToLocalFunctor<LocalOrdinal, GlobalOrdinal, col_inds_array, global_col_inds_array, typename map_type::local_map_type> convertSym(colindsSym, globalColindsSym, lclColmapSym);
322 Kokkos::parallel_for(range_type(0, globalColindsSym.extent(0)), convertSym);
328 handle.create_spadd_handle(sorted);
329 auto addHandle = handle.get_spadd_handle();
331 KokkosSparse::Experimental::spadd_symbolic
333 #
if KOKKOSKERNELS_VERSION >= 40299
334 nrows, graph->getGlobalNumCols(),
336 rowptrs, colinds, rowptrsT, colindsT, rowptrsSym);
337 colindsSym = col_inds_array(Kokkos::ViewAllocateWithoutInitializing(
"C colinds"), addHandle->get_c_nnz());
340 SortedNumericIndicesOnlyFunctor<
341 size_t, LocalOrdinal,
342 typename row_ptrs_array::const_type,
typename row_ptrs_array::const_type, row_ptrs_array,
343 typename col_inds_array::const_type,
typename col_inds_array::const_type, col_inds_array>
344 sortedNumeric(rowptrs, rowptrsT, rowptrsSym,
345 colinds, colindsT, colindsSym);
346 Kokkos::parallel_for(
"KokkosSparse::SpAdd:Numeric::InputSorted",
347 range_type(0, nrows), sortedNumeric);
350 UnsortedNumericIndicesOnlyFunctor<
351 size_t, LocalOrdinal,
352 typename row_ptrs_array::const_type,
typename row_ptrs_array::const_type, row_ptrs_array,
353 typename col_inds_array::const_type,
typename col_inds_array::const_type, col_inds_array>
354 unsortedNumeric(rowptrs, rowptrsT, rowptrsSym,
355 colinds, colindsT, colindsSym,
356 addHandle->get_a_pos(), addHandle->get_b_pos());
357 Kokkos::parallel_for(
"KokkosSparse::SpAdd:Numeric::InputNotSorted",
358 range_type(0, nrows), unsortedNumeric);
362 col_map_sym = col_map;
363 importer = graph->getImporter();
368 KokkosSparse::sort_crs_graph<execution_space, row_ptrs_array, col_inds_array>(rowptrsSym, colindsSym);
370 local_graph_device_type lclGraphSym = local_graph_device_type(colindsSym, rowptrsSym);
372 RCP<Teuchos::ParameterList> graphParams = Teuchos::null;
374 graphParams = rcp(
new Teuchos::ParameterList);
375 graphParams->set(
"sorted",
false);
388 template<
class LocalOrdinal,
391 Teuchos::RCP<CrsGraph<LocalOrdinal, GlobalOrdinal, Node> >
397 RCP<crs_graph_type> transGraphWithSharedRows = createTransposeLocal (params);
399 #ifdef HAVE_TPETRA_MMM_TIMINGS
400 const std::string prefix = std::string (
"Tpetra ") + label_ +
": ";
401 using Teuchos::TimeMonitor;
402 TimeMonitor MM (*TimeMonitor::getNewTimer (prefix +
"Transpose TAFC"));
409 RCP<const export_type> exporter =
410 transGraphWithSharedRows->getExporter ();
411 if (exporter.is_null ()) {
412 return transGraphWithSharedRows;
415 Teuchos::ParameterList labelList;
416 #ifdef HAVE_TPETRA_MMM_TIMINGS
417 labelList.set(
"Timer Label", label_);
419 if(! params.is_null ()) {
420 const char paramName[] =
"compute global constants";
421 labelList.set (paramName, params->get (paramName,
true));
426 return exportAndFillCompleteCrsGraph<crs_graph_type>
427 (transGraphWithSharedRows, *exporter, Teuchos::null,
428 Teuchos::null, Teuchos::rcpFromRef (labelList));
432 template<
class LocalOrdinal,
435 Teuchos::RCP<CrsGraph<LocalOrdinal, GlobalOrdinal, Node> >
441 using Teuchos::rcp_dynamic_cast;
442 using LO = LocalOrdinal;
443 using GO = GlobalOrdinal;
447 #ifdef HAVE_TPETRA_MMM_TIMINGS
448 std::string prefix = std::string(
"Tpetra ") + label_ +
": ";
449 using Teuchos::TimeMonitor;
450 TimeMonitor MM (*TimeMonitor::getNewTimer (prefix +
"Transpose Local"));
453 const bool sort = [&] () {
454 constexpr
bool sortDefault =
true;
455 const char sortParamName[] =
"sort";
456 return params.get () ==
nullptr ? sortDefault :
457 params->get (sortParamName, sortDefault);
461 local_graph_device_type lclGraph = origGraph_->getLocalGraphDevice ();
464 using c_rowmap_t =
typename local_graph_device_type::row_map_type;
465 using c_entries_t =
typename local_graph_device_type::entries_type;
466 using rowmap_t =
typename local_graph_device_type::row_map_type::non_const_type;
467 using entries_t =
typename local_graph_device_type::entries_type::non_const_type;
468 LocalOrdinal numCols = origGraph_->getColMap()->getLocalNumElements();
469 rowmap_t lclGraphT_rowmap(
"Transpose rowmap", numCols + 1);
470 entries_t lclGraphT_entries(
471 Kokkos::ViewAllocateWithoutInitializing(
"Transpose entries"), lclGraph.entries.extent(0));
472 KokkosSparse::Impl::transpose_graph<
473 c_rowmap_t, c_entries_t,
475 rowmap_t,
typename local_graph_device_type::execution_space>(
476 lclGraph.numRows(), numCols,
477 lclGraph.row_map, lclGraph.entries,
478 lclGraphT_rowmap, lclGraphT_entries);
481 KokkosSparse::sort_crs_graph<
482 typename local_graph_device_type::execution_space,
483 rowmap_t, entries_t>(
488 local_graph_device_type lclGraphT = local_graph_device_type(lclGraphT_entries, lclGraphT_rowmap);
492 const auto origExport = origGraph_->getExporter ();
493 RCP<const import_type> myImport = origExport.is_null () ?
494 Teuchos::null : rcp (
new import_type (*origExport));
495 const auto origImport = origGraph_->getImporter ();
496 RCP<const export_type> myExport = origImport.is_null () ?
497 Teuchos::null : rcp (
new export_type (*origImport));
499 RCP<Teuchos::ParameterList> graphParams = Teuchos::null;
501 graphParams = rcp(
new Teuchos::ParameterList);
502 graphParams->set(
"sorted",
false);
506 origGraph_->getColMap (),
507 origGraph_->getRowMap (),
508 origGraph_->getRangeMap (),
509 origGraph_->getDomainMap (),
510 myImport, myExport, graphParams));
519 #define TPETRA_CRSGRAPHTRANSPOSER_INSTANT(LO,GO,NODE) \
520 template class CrsGraphTransposer< LO , GO , NODE >;
Communication plan for data redistribution from a uniquely-owned to a (possibly) multiply-owned distr...
Declaration and definition of functions for sorting "short" arrays of keys and corresponding values...
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.
Teuchos::RCP< crs_graph_type > createTransposeLocal(const Teuchos::RCP< Teuchos::ParameterList > ¶ms=Teuchos::null)
Compute and return the transpose of the graph given to the constructor.
"Local" part of Map suitable for Kokkos kernels.
void sort(View &view, const size_t &size)
Convenience wrapper for std::sort for host-accessible views.
CrsGraphTransposer(const Teuchos::RCP< const crs_graph_type > &origGraph, const std::string &label=std::string())
Constructor that takes the graph to transpose.
Declare and define the functions Tpetra::Details::computeOffsetsFromCounts and Tpetra::computeOffsets...
Communication plan for data redistribution from a (possibly) multiply-owned to a uniquely-owned distr...
Teuchos::RCP< crs_graph_type > createTranspose(const Teuchos::RCP< Teuchos::ParameterList > ¶ms=Teuchos::null)
Compute and return the transpose of the graph given to the constructor.
A distributed graph accessed by rows (adjacency lists) and stored sparsely.
Teuchos::RCP< crs_graph_type > symmetrize(const Teuchos::RCP< Teuchos::ParameterList > ¶ms=Teuchos::null)
Compute and return graph+graph^T of the graph given to the constructor.