MueLu  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
MueLu_AggregationStructuredAlgorithm_kokkos_def.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_AGGREGATIONSTRUCTUREDALGORITHM_KOKKOS_DEF_HPP
47 #define MUELU_AGGREGATIONSTRUCTUREDALGORITHM_KOKKOS_DEF_HPP
48 
49 #include <Teuchos_Comm.hpp>
50 #include <Teuchos_CommHelpers.hpp>
51 
52 #include <Xpetra_MapFactory.hpp>
53 #include <Xpetra_Map.hpp>
55 #include <Xpetra_CrsGraph.hpp>
56 
57 #include "MueLu_Exceptions.hpp"
58 #include "MueLu_Monitor.hpp"
59 
60 #include "MueLu_LWGraph_kokkos.hpp"
61 #include "MueLu_Aggregates.hpp"
62 #include "MueLu_IndexManager_kokkos.hpp"
64 
65 namespace MueLu {
66 
67 template <class LocalOrdinal, class GlobalOrdinal, class Node>
69  BuildAggregates(const Teuchos::ParameterList& /* params */, const LWGraph_kokkos& graph,
70  Aggregates& aggregates,
71  Kokkos::View<unsigned*, device_type>& aggStat,
72  LO& numNonAggregatedNodes) const {
73  Monitor m(*this, "BuildAggregates");
74 
76  if (const char* dbg = std::getenv("MUELU_STRUCTUREDALGORITHM_DEBUG")) {
77  out = Teuchos::fancyOStream(Teuchos::rcpFromRef(std::cout));
78  out->setShowAllFrontMatter(false).setShowProcRank(true);
79  } else {
80  out = Teuchos::getFancyOStream(rcp(new Teuchos::oblackholestream()));
81  }
82 
83  RCP<IndexManager_kokkos> geoData = aggregates.GetIndexManagerKokkos();
84  const LO numLocalFineNodes = geoData->getNumLocalFineNodes();
85  const LO numCoarseNodes = geoData->getNumCoarseNodes();
86  LOVectorView vertex2AggId = aggregates.GetVertex2AggId()->getDeviceLocalView(Xpetra::Access::ReadWrite);
87  LOVectorView procWinner = aggregates.GetProcWinner()->getDeviceLocalView(Xpetra::Access::ReadWrite);
88 
89  *out << "Loop over fine nodes and assign them to an aggregate and a rank" << std::endl;
90  LO numAggregatedNodes;
91  fillAggregatesFunctor fillAggregates(geoData,
92  graph.GetComm()->getRank(),
93  aggStat,
94  vertex2AggId,
95  procWinner);
96  Kokkos::parallel_reduce("StructuredAggregation: fill aggregates data",
97  Kokkos::RangePolicy<execution_space>(0, numLocalFineNodes),
98  fillAggregates,
99  numAggregatedNodes);
100 
101  *out << "numCoarseNodes= " << numCoarseNodes
102  << ", numAggregatedNodes= " << numAggregatedNodes << std::endl;
103  numNonAggregatedNodes = numNonAggregatedNodes - numAggregatedNodes;
104 
105 } // BuildAggregates()
106 
107 template <class LocalOrdinal, class GlobalOrdinal, class Node>
109  BuildGraph(const LWGraph_kokkos& graph, RCP<IndexManager_kokkos>& geoData, const LO dofsPerNode,
110  RCP<CrsGraph>& myGraph) const {
111  Monitor m(*this, "BuildGraphP");
112 
114  if (const char* dbg = std::getenv("MUELU_STRUCTUREDALGORITHM_DEBUG")) {
115  out = Teuchos::fancyOStream(Teuchos::rcpFromRef(std::cout));
116  out->setShowAllFrontMatter(false).setShowProcRank(true);
117  } else {
118  out = Teuchos::getFancyOStream(rcp(new Teuchos::oblackholestream()));
119  }
120 
121  // Compute the number of coarse points needed to interpolate quantities to a fine point
122  int numInterpolationPoints = 0;
123  if (geoData->getInterpolationOrder() == 0) {
124  numInterpolationPoints = 1;
125  } else if (geoData->getInterpolationOrder() == 1) {
126  // Compute 2^numDimensions using bit logic to avoid round-off errors from std::pow()
127  numInterpolationPoints = 1 << geoData->getNumDimensions();
128  }
129  *out << "numInterpolationPoints=" << numInterpolationPoints << std::endl;
130 
131  const LO numLocalFineNodes = geoData->getNumLocalFineNodes();
132  const LO numCoarseNodes = geoData->getNumCoarseNodes();
133  const LO numNnzEntries = dofsPerNode * (numCoarseNodes + numInterpolationPoints * (numLocalFineNodes - numCoarseNodes));
134 
135  non_const_row_map_type rowPtr("Prolongator graph, rowPtr", dofsPerNode * (numLocalFineNodes + 1));
136  entries_type colIndex("Prolongator graph, colIndices", numNnzEntries);
137 
138  *out << "Compute prolongatorGraph data" << std::endl;
139  if (geoData->getInterpolationOrder() == 0) {
140  computeGraphDataConstantFunctor computeGraphData(geoData,
141  numCoarseNodes,
142  dofsPerNode,
143  geoData->getCoarseningRates(),
144  geoData->getCoarseningEndRates(),
145  geoData->getLocalFineNodesPerDir(),
146  rowPtr,
147  colIndex);
148  Kokkos::parallel_for("Structured Aggregation: compute loca graph data",
149  Kokkos::RangePolicy<execution_space>(0, numLocalFineNodes),
150  computeGraphData);
151  } else if (geoData->getInterpolationOrder() == 1) {
152  // Note, lbv 2018-11-08: in the piece-wise linear case I am computing the rowPtr
153  // using a parallel scan, it might be possible to do something faster than that
154  // by including this calculation in computeGraphDataLinearFunctor but at the moment
155  // all the ideas I have include a bunch of if statements which I would like to avoid.
156  computeGraphRowPtrFunctor computeGraphRowPtr(geoData,
157  dofsPerNode,
158  numInterpolationPoints,
159  numLocalFineNodes,
160  geoData->getCoarseningRates(),
161  geoData->getLocalFineNodesPerDir(),
162  rowPtr);
163  Kokkos::parallel_scan("Structured Aggregation: compute rowPtr for prolongator graph",
164  Kokkos::RangePolicy<execution_space>(0, numLocalFineNodes + 1),
165  computeGraphRowPtr);
166 
167  computeGraphDataLinearFunctor computeGraphData(geoData,
168  geoData->getNumDimensions(),
169  numCoarseNodes,
170  dofsPerNode,
171  numInterpolationPoints,
172  geoData->getCoarseningRates(),
173  geoData->getCoarseningEndRates(),
174  geoData->getLocalFineNodesPerDir(),
175  geoData->getCoarseNodesPerDir(),
176  rowPtr,
177  colIndex);
178  Kokkos::parallel_for("Structured Aggregation: compute loca graph data",
179  Kokkos::RangePolicy<execution_space>(0, numLocalFineNodes),
180  computeGraphData);
181  }
182 
183  local_graph_type myLocalGraph(colIndex, rowPtr);
184 
185  // Compute graph's colMap and domainMap
186  RCP<Map> colMap, domainMap;
187  *out << "Compute domain and column maps of the CrsGraph" << std::endl;
188  colMap = MapFactory::Build(graph.GetDomainMap()->lib(),
190  numCoarseNodes,
191  graph.GetDomainMap()->getIndexBase(),
192  graph.GetDomainMap()->getComm());
193  domainMap = colMap;
194 
195  myGraph = CrsGraphFactory::Build(myLocalGraph, graph.GetDomainMap(), colMap,
196  colMap, graph.GetDomainMap());
197 
198 } // BuildGraph()
199 
200 template <class LocalOrdinal, class GlobalOrdinal, class Node>
203  const int myRank,
204  Kokkos::View<unsigned*, device_type> aggStat,
205  LOVectorView vertex2AggID,
206  LOVectorView procWinner)
207  : geoData_(*geoData)
208  , myRank_(myRank)
209  , aggStat_(aggStat)
210  , vertex2AggID_(vertex2AggID)
211  , procWinner_(procWinner) {}
212 
213 template <class LocalOrdinal, class GlobalOrdinal, class Node>
215  fillAggregatesFunctor::operator()(const LO nodeIdx, LO& lNumAggregatedNodes) const {
216  // Compute coarse ID associated with fine LID
217  LO rem, rate;
218  LO coarseNodeCoarseLID;
219  LO nodeFineTuple[3], coarseIdx[3];
220  auto coarseRate = geoData_.getCoarseningRates();
221  auto endRate = geoData_.getCoarseningEndRates();
222  auto lFineNodesPerDir = geoData_.getLocalFineNodesPerDir();
223  // Compute coarse ID associated with fine LID
224  geoData_.getFineLID2FineTuple(nodeIdx, nodeFineTuple);
225 
226  for (int dim = 0; dim < 3; ++dim) {
227  coarseIdx[dim] = nodeFineTuple[dim] / coarseRate(dim);
228  rem = nodeFineTuple[dim] % coarseRate(dim);
229  rate = (nodeFineTuple[dim] < lFineNodesPerDir(dim) - endRate(dim)) ? coarseRate(dim) : endRate(dim);
230  if (rem > (rate / 2)) {
231  ++coarseIdx[dim];
232  }
233  }
234 
235  geoData_.getCoarseTuple2CoarseLID(coarseIdx[0], coarseIdx[1], coarseIdx[2],
236  coarseNodeCoarseLID);
237 
238  vertex2AggID_(nodeIdx, 0) = coarseNodeCoarseLID;
239  procWinner_(nodeIdx, 0) = myRank_;
240  aggStat_(nodeIdx) = AGGREGATED;
241  ++lNumAggregatedNodes;
242 
243 } // fillAggregatesFunctor::operator()
244 
245 template <class LocalOrdinal, class GlobalOrdinal, class Node>
249  const LO NumGhostedNodes,
250  const LO dofsPerNode,
251  constIntTupleView coarseRate,
252  constIntTupleView endRate,
253  constLOTupleView lFineNodesPerDir,
254  non_const_row_map_type rowPtr,
255  entries_type colIndex)
256  : geoData_(*geoData)
257  , numGhostedNodes_(NumGhostedNodes)
258  , dofsPerNode_(dofsPerNode)
259  , coarseRate_(coarseRate)
260  , endRate_(endRate)
261  , lFineNodesPerDir_(lFineNodesPerDir)
262  , rowPtr_(rowPtr)
263  , colIndex_(colIndex) {
264 } // computeGraphDataConstantFunctor()
265 
266 template <class LocalOrdinal, class GlobalOrdinal, class Node>
269  LO nodeFineTuple[3] = {0, 0, 0};
270  LO nodeCoarseTuple[3] = {0, 0, 0};
271 
272  // Compute ghosted tuple associated with fine LID
273  geoData_.getFineLID2FineTuple(nodeIdx, nodeFineTuple);
274 
275  // Compute coarse tuple associated with fine point
276  // then overwrite it with tuple associated with aggregate
277  LO rem, rate, coarseNodeCoarseLID;
278  for (int dim = 0; dim < 3; ++dim) {
279  nodeCoarseTuple[dim] = nodeFineTuple[dim] / coarseRate_(dim);
280  rem = nodeFineTuple[dim] % coarseRate_(dim);
281  if (nodeFineTuple[dim] < (lFineNodesPerDir_(dim) - endRate_(dim))) {
282  rate = coarseRate_(dim);
283  } else {
284  rate = endRate_(dim);
285  }
286  if (rem > (rate / 2)) {
287  ++nodeCoarseTuple[dim];
288  }
289  }
290 
291  // get LID associted with aggregate
292  geoData_.getCoarseTuple2CoarseLID(nodeCoarseTuple[0], nodeCoarseTuple[1], nodeCoarseTuple[2],
293  coarseNodeCoarseLID);
294 
295  // store data into CrsGraph taking care of multiple dofs case
296  for (LO dof = 0; dof < dofsPerNode_; ++dof) {
297  rowPtr_(nodeIdx * dofsPerNode_ + dof + 1) = nodeIdx * dofsPerNode_ + dof + 1;
298  colIndex_(nodeIdx * dofsPerNode_ + dof) = coarseNodeCoarseLID * dofsPerNode_ + dof;
299  }
300 
301 } // computeGraphDataConstantFunctor::operator()
302 
303 template <class LocalOrdinal, class GlobalOrdinal, class Node>
306  const LO dofsPerNode,
307  const int numInterpolationPoints,
308  const LO numLocalRows,
309  constIntTupleView coarseRate,
310  constLOTupleView lFineNodesPerDir,
311  non_const_row_map_type rowPtr)
312  : geoData_(*geoData)
313  , dofsPerNode_(dofsPerNode)
314  , numInterpolationPoints_(numInterpolationPoints)
315  , numLocalRows_(numLocalRows)
316  , coarseRate_(coarseRate)
317  , lFineNodesPerDir_(lFineNodesPerDir)
318  , rowPtr_(rowPtr) {}
319 
320 template <class LocalOrdinal, class GlobalOrdinal, class Node>
322  computeGraphRowPtrFunctor::operator()(const LO rowIdx, GO& update, const bool final) const {
323  if (final) {
324  // Kokkos uses a multipass algorithm to implement scan.
325  // Only update the array on the final pass. Updating the
326  // array before changing 'update' means that we do an
327  // exclusive scan. Update the array after for an inclusive
328  // scan.
329  rowPtr_(rowIdx) = update;
330  }
331  if (rowIdx < numLocalRows_) {
332  LO nodeIdx = rowIdx / dofsPerNode_;
333  bool allCoarse = true;
334  LO nodeFineTuple[3] = {0, 0, 0};
335  geoData_.getFineLID2FineTuple(nodeIdx, nodeFineTuple);
336  for (int dim = 0; dim < 3; ++dim) {
337  const LO rem = nodeFineTuple[dim] % coarseRate_(dim);
338 
339  // Check if Fine node lies on Coarse Node
340  allCoarse = (allCoarse && ((rem == 0) || (nodeFineTuple[dim] == lFineNodesPerDir_(dim) - 1)));
341  }
342  update += (allCoarse ? 1 : numInterpolationPoints_);
343  }
344 } // computeGraphRowPtrFunctor::operator()
345 
346 template <class LocalOrdinal, class GlobalOrdinal, class Node>
349  const int numDimensions,
350  const LO numGhostedNodes,
351  const LO dofsPerNode,
352  const int numInterpolationPoints,
353  constIntTupleView coarseRate,
354  constIntTupleView endRate,
355  constLOTupleView lFineNodesPerDir,
356  constLOTupleView ghostedNodesPerDir,
357  non_const_row_map_type rowPtr,
358  entries_type colIndex)
359  : geoData_(*geoData)
360  , numDimensions_(numDimensions)
361  , numGhostedNodes_(numGhostedNodes)
362  , dofsPerNode_(dofsPerNode)
363  , numInterpolationPoints_(numInterpolationPoints)
364  , coarseRate_(coarseRate)
365  , endRate_(endRate)
366  , lFineNodesPerDir_(lFineNodesPerDir)
367  , ghostedNodesPerDir_(ghostedNodesPerDir)
368  , rowPtr_(rowPtr)
369  , colIndex_(colIndex) {
370 } // computeGraphDataLinearFunctor()
371 
372 template <class LocalOrdinal, class GlobalOrdinal, class Node>
375  LO nodeFineTuple[3] = {0, 0, 0};
376  LO nodeCoarseTuple[3] = {0, 0, 0};
377 
378  // Compute coarse ID associated with fine LID
379  geoData_.getFineLID2FineTuple(nodeIdx, nodeFineTuple);
380 
381  LO coarseNodeCoarseLID;
382  bool allCoarse = false;
383  for (int dim = 0; dim < 3; ++dim) {
384  nodeCoarseTuple[dim] = nodeFineTuple[dim] / coarseRate_(dim);
385  }
386  if (rowPtr_(nodeIdx + 1) == rowPtr_(nodeIdx) + 1) {
387  allCoarse = true;
388  }
389 
390  geoData_.getCoarseTuple2CoarseLID(nodeCoarseTuple[0], nodeCoarseTuple[1], nodeCoarseTuple[2],
391  coarseNodeCoarseLID);
392 
393  if (allCoarse) {
394  // Fine node lies on Coarse node, easy case, we only need the LID of the coarse node.
395  for (LO dof = 0; dof < dofsPerNode_; ++dof) {
396  colIndex_(rowPtr_(nodeIdx * dofsPerNode_ + dof)) = coarseNodeCoarseLID * dofsPerNode_ + dof;
397  }
398  } else {
399  for (int dim = 0; dim < numDimensions_; ++dim) {
400  if (nodeCoarseTuple[dim] == ghostedNodesPerDir_(dim) - 1) {
401  --nodeCoarseTuple[dim];
402  }
403  }
404  // Compute Coarse Node LID
405  // Note lbv 10-06-2018: it is likely benefitial to remove the two if statments and somehow
406  // find out the number of dimensions before calling the opertor() of the functor.
407  for (LO dof = 0; dof < dofsPerNode_; ++dof) {
408  geoData_.getCoarseTuple2CoarseLID(nodeCoarseTuple[0], nodeCoarseTuple[1], nodeCoarseTuple[2], colIndex_(rowPtr_(nodeIdx * dofsPerNode_ + dof) + 0));
409  geoData_.getCoarseTuple2CoarseLID(nodeCoarseTuple[0] + 1, nodeCoarseTuple[1], nodeCoarseTuple[2], colIndex_(rowPtr_(nodeIdx * dofsPerNode_ + dof) + 1));
410  if (numDimensions_ > 1) {
411  geoData_.getCoarseTuple2CoarseLID(nodeCoarseTuple[0], nodeCoarseTuple[1] + 1, nodeCoarseTuple[2], colIndex_(rowPtr_(nodeIdx * dofsPerNode_ + dof) + 2));
412  geoData_.getCoarseTuple2CoarseLID(nodeCoarseTuple[0] + 1, nodeCoarseTuple[1] + 1, nodeCoarseTuple[2], colIndex_(rowPtr_(nodeIdx * dofsPerNode_ + dof) + 3));
413  if (numDimensions_ > 2) {
414  geoData_.getCoarseTuple2CoarseLID(nodeCoarseTuple[0], nodeCoarseTuple[1], nodeCoarseTuple[2] + 1, colIndex_(rowPtr_(nodeIdx * dofsPerNode_ + dof) + 4));
415  geoData_.getCoarseTuple2CoarseLID(nodeCoarseTuple[0] + 1, nodeCoarseTuple[1], nodeCoarseTuple[2] + 1, colIndex_(rowPtr_(nodeIdx * dofsPerNode_ + dof) + 5));
416  geoData_.getCoarseTuple2CoarseLID(nodeCoarseTuple[0], nodeCoarseTuple[1] + 1, nodeCoarseTuple[2] + 1, colIndex_(rowPtr_(nodeIdx * dofsPerNode_ + dof) + 6));
417  geoData_.getCoarseTuple2CoarseLID(nodeCoarseTuple[0] + 1, nodeCoarseTuple[1] + 1, nodeCoarseTuple[2] + 1, colIndex_(rowPtr_(nodeIdx * dofsPerNode_ + dof) + 7));
418  }
419  }
420  }
421  }
422 } // computeGraphDataLinearFunctor::operator()
423 
424 } // namespace MueLu
425 
426 #endif /* MUELU_AGGREGATIONSTRUCTUREDALGORITHM_DEF_HPP_ */
fillAggregatesFunctor(RCP< IndexManager_kokkos > geoData, const int myRank, Kokkos::View< unsigned *, device_type > aggStat, LOVectorView vertex2AggID, LOVectorView procWinner)
typename local_graph_type::row_map_type::non_const_type non_const_row_map_type
Lightweight MueLu representation of a compressed row storage graph.
decltype(std::declval< LOVector >().getDeviceLocalView(Xpetra::Access::ReadWrite)) LOVectorView
const RCP< LOVector > & GetProcWinner() const
Returns constant vector that maps local node IDs to owning processor IDs.
Container class for aggregation information.
basic_FancyOStream & setShowProcRank(const bool showProcRank)
GlobalOrdinal GO
KOKKOS_INLINE_FUNCTION intTupleView getCoarseningEndRates() const
KOKKOS_INLINE_FUNCTION intTupleView getCoarseningRates() const
LocalOrdinal LO
computeGraphRowPtrFunctor(RCP< IndexManager_kokkos > geoData, const LO dofsPerNode, const int numInterpolationPoints, const LO numLocalRows, constIntTupleView coarseRate, constLOTupleView lFineNodesPerDir, non_const_row_map_type rowPtr)
TEUCHOS_DEPRECATED RCP< T > rcp(T *p, Dealloc_T dealloc, bool owns_mem)
typename Kokkos::View< const LO[3], device_type > constLOTupleView
basic_FancyOStream & setShowAllFrontMatter(const bool showAllFrontMatter)
const RCP< LOMultiVector > & GetVertex2AggId() const
Returns constant vector that maps local node IDs to local aggregates IDs.
KOKKOS_INLINE_FUNCTION void operator()(const LO rowIdx, GO &update, const bool final) const
computeGraphDataLinearFunctor(RCP< IndexManager_kokkos > geoData, const int numDimensions, const LO numGhostedNodes, const LO dofsPerNode, const int numInterpolationPoints, constIntTupleView coarseRate, constIntTupleView endRate, constLOTupleView lFineNodesPerDir, constLOTupleView ghostedNodesPerDir, non_const_row_map_type rowPtr, entries_type colIndex)
Timer to be used in non-factories.
const RCP< const Map > GetDomainMap() const
KOKKOS_INLINE_FUNCTION void operator()(const LO nodeIdx, LO &lNumAggregatedNodes) const
void BuildAggregates(const Teuchos::ParameterList &params, const LWGraph_kokkos &graph, Aggregates &aggregates, Kokkos::View< unsigned *, device_type > &aggStat, LO &numNonAggregatedNodes) const
Build aggregates object.
KOKKOS_INLINE_FUNCTION LOTupleView getCoarseNodesPerDir() const
KOKKOS_INLINE_FUNCTION LOTupleView getLocalFineNodesPerDir() const
computeGraphDataConstantFunctor(RCP< IndexManager_kokkos > geoData, const LO numGhostedNodes, const LO dofsPerNode, constIntTupleView coarseRate, constIntTupleView endRate, constLOTupleView lFineNodesPerDir, non_const_row_map_type rowPtr, entries_type colIndex)
typename Kokkos::View< const int[3], device_type > constIntTupleView
const RCP< const Teuchos::Comm< int > > GetComm() const
void BuildGraph(const LWGraph_kokkos &graph, RCP< IndexManager_kokkos > &geoData, const LO dofsPerNode, RCP< CrsGraph > &myGraph) const
Build a CrsGraph instead of aggregates.
RCP< IndexManager_kokkos > & GetIndexManagerKokkos()
Get the index manager used by structured aggregation algorithms. This has to be done by the aggregati...