Zoltan2
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
TpetraRowGraphInputKokkos.cpp
Go to the documentation of this file.
1 // @HEADER
2 // *****************************************************************************
3 // Zoltan2: A package of combinatorial algorithms for scientific computing
4 //
5 // Copyright 2012 NTESS and the Zoltan2 contributors.
6 // SPDX-License-Identifier: BSD-3-Clause
7 // *****************************************************************************
8 // @HEADER
9 
10 //
11 // Basic testing of Zoltan2::TpetraRowGraphAdapter
17 #include <Zoltan2_InputTraits.hpp>
18 #include <Zoltan2_TestHelpers.hpp>
21 
22 #include <Teuchos_Comm.hpp>
23 #include <Teuchos_CommHelpers.hpp>
24 #include <Teuchos_DefaultComm.hpp>
25 #include <Teuchos_RCP.hpp>
26 #include <cstdlib>
27 #include <stdexcept>
28 
29 using Teuchos::Comm;
30 using Teuchos::RCP;
31 using Teuchos::rcp;
32 using Teuchos::rcp_const_cast;
33 using Teuchos::rcp_dynamic_cast;
34 
35 using ztcrsgraph_t = Tpetra::CrsGraph<zlno_t, zgno_t, znode_t>;
36 using ztrowgraph_t = Tpetra::RowGraph<zlno_t, zgno_t, znode_t>;
38 using device_t = typename node_t::device_type;
41 using execspace_t =
42  typename rowAdapter_t::ConstWeightsHostView1D::execution_space;
43 
44 template <typename offset_t>
45 void printGraph(RCP<const Comm<int>> &comm, zlno_t nvtx, const zgno_t *vtxIds,
46  const offset_t *offsets, const zgno_t *edgeIds) {
47  int rank = comm->getRank();
48  int nprocs = comm->getSize();
49  comm->barrier();
50  for (int p = 0; p < nprocs; p++) {
51  if (p == rank) {
52  std::cout << rank << ":" << std::endl;
53  for (zlno_t i = 0; i < nvtx; i++) {
54  std::cout << " vertex " << vtxIds[i] << ": ";
55  for (offset_t j = offsets[i]; j < offsets[i + 1]; j++) {
56  std::cout << edgeIds[j] << " ";
57  }
58  std::cout << std::endl;
59  }
60  std::cout.flush();
61  }
62  comm->barrier();
63  }
64  comm->barrier();
65 }
66 
67 template <typename adapter_t, typename graph_t>
68 void TestGraphIds(adapter_t &ia, graph_t &graph) {
69 
70  using idsHost_t = typename adapter_t::ConstIdsHostView;
71  using offsetsHost_t = typename adapter_t::ConstOffsetsHostView;
72  using localInds_t =
73  typename adapter_t::user_t::nonconst_local_inds_host_view_type;
74 
75  const auto nvtx = graph.getLocalNumRows();
76  const auto nedges = graph.getLocalNumEntries();
77  const auto maxNumEntries = graph.getLocalMaxNumRowEntries();
78 
79  typename adapter_t::Base::ConstIdsHostView adjIdsHost_("adjIdsHost_", nedges);
80  typename adapter_t::Base::ConstOffsetsHostView offsHost_("offsHost_",
81  nvtx + 1);
82 
83  localInds_t nbors("nbors", maxNumEntries);
84 
85  for (size_t v = 0; v < nvtx; v++) {
86  size_t numColInds = 0;
87  graph.getLocalRowCopy(v, nbors, numColInds);
88 
89  offsHost_(v + 1) = offsHost_(v) + numColInds;
90  for (size_t e = offsHost_(v), i = 0; e < offsHost_(v + 1); e++) {
91  adjIdsHost_(e) = graph.getColMap()->getGlobalElement(nbors(i++));
92  }
93  }
94 
95  idsHost_t vtxIdsHost;
96  ia.getVertexIDsHostView(vtxIdsHost);
97 
98  const auto graphIDS = graph.getRowMap()->getLocalElementList();
99 
100  Z2_TEST_COMPARE_ARRAYS(graphIDS, vtxIdsHost);
101 
102  idsHost_t adjIdsHost;
103  offsetsHost_t offsetsHost;
104  ia.getEdgesHostView(offsetsHost, adjIdsHost);
105 
106  Z2_TEST_COMPARE_ARRAYS(adjIdsHost_, adjIdsHost);
107  Z2_TEST_COMPARE_ARRAYS(offsHost_, offsetsHost);
108 }
109 
110 template <typename adapter_t, typename graph_t>
111 void verifyInputAdapter(adapter_t &ia, graph_t &graph) {
112  using idsDevice_t = typename adapter_t::ConstIdsDeviceView;
113  using idsHost_t = typename adapter_t::ConstIdsHostView;
114  using offsetsDevice_t = typename adapter_t::ConstOffsetsDeviceView;
115  using offsetsHost_t = typename adapter_t::ConstOffsetsHostView;
116  using weightsDevice_t = typename adapter_t::WeightsDeviceView1D;
117  using weightsHost_t = typename adapter_t::WeightsHostView1D;
118 
119  const auto nVtx = ia.getLocalNumIDs();
120 
121  Z2_TEST_EQUALITY(ia.getLocalNumVertices(), graph.getLocalNumRows());
122  Z2_TEST_EQUALITY(ia.getLocalNumEdges(), graph.getLocalNumEntries());
123 
127 
128  idsDevice_t vtxIdsDevice;
129  ia.getVertexIDsDeviceView(vtxIdsDevice);
130  idsHost_t vtxIdsHost;
131  ia.getVertexIDsHostView(vtxIdsHost);
132 
133  Z2_TEST_DEVICE_HOST_VIEWS(vtxIdsDevice, vtxIdsHost);
134 
138 
139  idsDevice_t adjIdsDevice;
140  offsetsDevice_t offsetsDevice;
141 
142  ia.getEdgesDeviceView(offsetsDevice, adjIdsDevice);
143 
144  idsHost_t adjIdsHost;
145  offsetsHost_t offsetsHost;
146  ia.getEdgesHostView(offsetsHost, adjIdsHost);
147 
148  Z2_TEST_DEVICE_HOST_VIEWS(adjIdsDevice, adjIdsHost);
149  Z2_TEST_DEVICE_HOST_VIEWS(offsetsDevice, offsetsHost);
150 
154  Z2_TEST_THROW(ia.setVertexWeightsDevice(
155  typename adapter_t::ConstWeightsDeviceView1D{}, 50),
156  std::runtime_error);
157 
158  weightsDevice_t wgts0("wgts0", nVtx);
159  Kokkos::parallel_for(
160  nVtx, KOKKOS_LAMBDA(const int idx) { wgts0(idx) = idx * 2; });
161  Kokkos::fence();
162 
163  Z2_TEST_NOTHROW(ia.setVertexWeightsDevice(wgts0, 0));
164 
165  // Don't reuse the same View, since we don't copy the values,
166  // we just assign the View (increase use count)
167  weightsDevice_t wgts1("wgts1", nVtx);
168  Kokkos::parallel_for(
169  nVtx, KOKKOS_LAMBDA(const int idx) { wgts1(idx) = idx * 3; });
170 
171  Z2_TEST_NOTHROW(ia.setVertexWeightsDevice(wgts1, 1));
172 
176  {
177  weightsDevice_t weightsDevice;
178  Z2_TEST_NOTHROW(ia.getVertexWeightsDeviceView(weightsDevice, 0));
179 
180  weightsHost_t weightsHost;
181  Z2_TEST_NOTHROW(ia.getVertexWeightsHostView(weightsHost, 0));
182 
183  Z2_TEST_DEVICE_HOST_VIEWS(weightsDevice, weightsHost);
184 
185  Z2_TEST_DEVICE_HOST_VIEWS(wgts0, weightsHost);
186  }
187  {
188  weightsDevice_t weightsDevice;
189  Z2_TEST_NOTHROW(ia.getVertexWeightsDeviceView(weightsDevice, 1));
190 
191  weightsHost_t weightsHost;
192  Z2_TEST_NOTHROW(ia.getVertexWeightsHostView(weightsHost, 1));
193 
194  Z2_TEST_DEVICE_HOST_VIEWS(weightsDevice, weightsHost);
195 
196  Z2_TEST_DEVICE_HOST_VIEWS(wgts1, weightsHost);
197  }
198  {
199  weightsDevice_t wgtsDevice;
200  Z2_TEST_THROW(ia.getVertexWeightsDeviceView(wgtsDevice, 2),
201  std::runtime_error);
202 
203  weightsHost_t wgtsHost;
204  Z2_TEST_THROW(ia.getVertexWeightsHostView(wgtsHost, 2), std::runtime_error);
205  }
206 
207  TestGraphIds(ia, graph);
208 }
209 
210 int main(int narg, char *arg[]) {
212  using rowPart_t = rowAdapter_t::part_t;
213 
215  using crsPart_t = crsAdapter_t::part_t;
216 
217  Tpetra::ScopeGuard tscope(&narg, &arg);
218  const auto comm = Tpetra::getDefaultComm();
219 
220  try {
221  Teuchos::ParameterList params;
222  params.set("input file", "simple");
223  params.set("file type", "Chaco");
224 
225  auto uinput = rcp(new UserInputForTests(params, comm));
226 
227  // Input crs graph and row graph cast from it.
228  const auto crsGraph = uinput->getUITpetraCrsGraph();
229  const auto rowGraph = rcp_dynamic_cast<ztrowgraph_t>(crsGraph);
230 
231  const auto nvtx = rowGraph->getLocalNumRows();
232 
233  // To test migration in the input adapter we need a Solution object.
234  const auto env = rcp(new Zoltan2::Environment(comm));
235 
236  const int nWeights = 2;
237 
239  // User object is Tpetra::CrsGraph
241  {
242  PrintFromRoot("Input adapter for Tpetra::CrsGraph");
243 
244  auto tpetraCrsGraphInput = rcp(new crsAdapter_t(crsGraph, nWeights));
245 
246  verifyInputAdapter(*tpetraCrsGraphInput, *crsGraph);
247 
248  ztcrsgraph_t *mMigrate = NULL;
249  crsPart_t *p = new crsPart_t[nvtx];
250  memset(p, 0, sizeof(crsPart_t) * nvtx);
251  ArrayRCP<crsPart_t> solnParts(p, 0, nvtx, true);
252 
253  crsSoln_t solution(env, comm, nWeights);
254  solution.setParts(solnParts);
255  tpetraCrsGraphInput->applyPartitioningSolution(*crsGraph, mMigrate,
256  solution);
257  const auto newG = rcp(mMigrate);
258 
259  auto cnewG = rcp_const_cast<const ztcrsgraph_t>(newG);
260  auto newInput = rcp(new crsAdapter_t(cnewG, nWeights));
261 
262  PrintFromRoot("Input adapter for Tpetra::RowGraph migrated to proc 0");
263 
264  verifyInputAdapter(*newInput, *newG);
265  }
266 
268  // User object is Tpetra::RowGraph
270  {
271  PrintFromRoot("Input adapter for Tpetra::RowGraph");
272 
273  auto tpetraRowGraphInput = rcp(new rowAdapter_t(rowGraph, nWeights));
274 
275  verifyInputAdapter(*tpetraRowGraphInput, *crsGraph);
276 
277  rowPart_t *p = new rowPart_t[nvtx];
278  memset(p, 0, sizeof(rowPart_t) * nvtx);
279  ArrayRCP<rowPart_t> solnParts(p, 0, nvtx, true);
280 
281  rowSoln_t solution(env, comm, nWeights);
282  solution.setParts(solnParts);
283 
284  ztrowgraph_t *mMigrate = NULL;
285  tpetraRowGraphInput->applyPartitioningSolution(*crsGraph, mMigrate,
286  solution);
287  const auto newG = rcp(mMigrate);
288 
289  auto cnewG = rcp_const_cast<const ztrowgraph_t>(newG);
290  auto newInput = rcp(new rowAdapter_t(cnewG, nWeights));
291 
292  PrintFromRoot("Input adapter for Tpetra::RowGraph migrated to proc 0");
293 
294  verifyInputAdapter(*newInput, *newG);
295  }
296  } catch (std::exception &e) {
297  std::cout << e.what() << std::endl;
298  return EXIT_FAILURE;
299  }
300 
301  PrintFromRoot("PASS");
302 }
void verifyInputAdapter(adapter_t &ia, matrix_t &matrix)
void TestGraphIds(adapter_t &ia, graph_t &graph)
void PrintFromRoot(const std::string &message)
typename crsAdapter_t::ConstWeightsHostView1D::execution_space execspace_t
Defines TpetraRowGraphAdapter class.
typename node_t::device_type device_t
Defines TpetraCrsGraphAdapter class.
Provides access for Zoltan2 to Tpetra::CrsMatrix data.
typename Zoltan2::InputTraits< ztcrsmatrix_t >::node_t node_t
Provides access for Zoltan2 to Tpetra::CrsGraph data.
int main(int narg, char **arg)
Definition: coloring1.cpp:164
common code used by tests
typename InputTraits< User >::part_t part_t
#define Z2_TEST_COMPARE_ARRAYS(val1, val2)
void printGraph(RCP< const Comm< int > > &comm, zlno_t nvtx, const zgno_t *vtxIds, const offset_t *offsets, const zgno_t *edgeIds)
Tpetra::RowGraph< zlno_t, zgno_t, znode_t > ztrowgraph_t
A PartitioningSolution is a solution to a partitioning problem.
#define Z2_TEST_DEVICE_HOST_VIEWS(deviceView, hostView)
#define Z2_TEST_EQUALITY(val1, val2)
Tpetra::CrsGraph< zlno_t, zgno_t, znode_t > ztcrsgraph_t
Traits for application input objects.
The user parameters, debug, timing and memory profiling output objects, and error checking methods...
Zoltan2::TpetraCrsMatrixAdapter< ztcrsmatrix_t > crsAdapter_t
Tpetra::Map::local_ordinal_type zlno_t
default_node_t node_t
The Kokkos node type. This is only meaningful for users of Tpetra objects.
#define Z2_TEST_THROW(code, ExceptType)
Tpetra::Map::global_ordinal_type zgno_t
#define Z2_TEST_NOTHROW(code)
Zoltan2::TpetraRowGraphAdapter< ztrowgraph_t > rowAdapter_t
Provides access for Zoltan2 to Tpetra::RowGraph data.