Zoltan2
Loading...
Searching...
No Matches
Zoltan2_Adapter.hpp
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
14#ifndef _ZOLTAN2_ADAPTER_HPP_
15#define _ZOLTAN2_ADAPTER_HPP_
16
17#include <Kokkos_Core.hpp>
18#include <Zoltan2_Standards.hpp>
21#include <fstream>
22
23namespace Zoltan2 {
24
25//template<typename Adapter>
26//class PartitioningSolution;
27
39
50public:
51 virtual ~BaseAdapterRoot() = default; // required virtual declaration
52
58 virtual size_t getLocalNumIDs() const = 0;
59
65 virtual int getNumWeightsPerID() const { return 0; };
66};
67
68template <typename User>
70
71public:
78 using host_t = typename Kokkos::HostSpace::memory_space;
79 using device_t = typename node_t::device_type;
80
81 using ConstIdsDeviceView = Kokkos::View<const gno_t *, device_t>;
82 using ConstIdsHostView = typename ConstIdsDeviceView::host_mirror_type;
83
84 using IdsDeviceView = Kokkos::View<gno_t *, device_t>;
85 using IdsHostView = typename IdsDeviceView::host_mirror_type;
86
87 using ConstOffsetsDeviceView = Kokkos::View<const offset_t *, device_t>;
88 using ConstOffsetsHostView = typename ConstOffsetsDeviceView::host_mirror_type;
89
90 using OffsetsDeviceView = Kokkos::View<offset_t *, device_t>;
91 using OffsetsHostView = typename OffsetsDeviceView::host_mirror_type;
92
93 using ConstScalarsDeviceView = Kokkos::View<const scalar_t *, device_t>;
94 using ConstScalarsHostView = typename ConstScalarsDeviceView::host_mirror_type;
95
96 using ScalarsDeviceView = Kokkos::View<scalar_t *, device_t>;
97 using ScalarsHostView = typename ScalarsDeviceView::host_mirror_type;
98
99 using ConstWeightsDeviceView1D = Kokkos::View<const scalar_t *, device_t>;
100 using ConstWeightsHostView1D = typename ConstWeightsDeviceView1D::host_mirror_type;
101
102 using WeightsDeviceView1D = Kokkos::View<scalar_t *, device_t>;
103 using WeightsHostView1D = typename WeightsDeviceView1D::host_mirror_type;
104
105 using ConstWeightsDeviceView = Kokkos::View<const scalar_t **, device_t>;
106 using ConstWeightsHostView = typename ConstWeightsDeviceView::host_mirror_type;
107
108 using WeightsDeviceView = Kokkos::View<scalar_t **, device_t>;
109 using WeightsHostView = typename WeightsDeviceView::host_mirror_type;
110
113 virtual enum BaseAdapterType adapterType() const = 0;
114
120 virtual void getIDsView(const gno_t *&ids) const {
121 // If adapter does not define getIDsView, getIDsKokkosView is called.
122 // If adapter does not define getIDsKokkosView, getIDsView is called.
123 // Allows forward and backwards compatibility.
124 ConstIdsDeviceView kokkosIds;
125 getIDsKokkosView(kokkosIds);
126 //deep_copy(?)
127 ids = kokkosIds.data();
128 }
129
135 virtual void getIDsKokkosView(ConstIdsDeviceView &ids) const {
136 // If adapter does not define getIDsView, getIDsKokkosView is called.
137 // If adapter does not define getIDsKokkosView, getIDsView is called.
138 // Allows forward and backwards compatibility.
139 const gno_t * ptr_ids;
140 getIDsView(ptr_ids);
141
142 auto non_const_ids = IdsDeviceView("ptr_ids", getLocalNumIDs());
143 auto host_ids = Kokkos::create_mirror_view(non_const_ids);
144 for(size_t i = 0; i < this->getLocalNumIDs(); ++i) {
145 host_ids(i) = ptr_ids[i];
146 }
147 Kokkos::deep_copy(non_const_ids, host_ids);
148 ids = non_const_ids;
149 }
150
155 virtual void getIDsHostView(ConstIdsHostView& hostIds) const {
157 }
158
163 virtual void getIDsDeviceView(ConstIdsDeviceView &deviceIds) const {
165 }
166
168 // * \param wgt on return a pointer to the weights for this idx
169 // * \param stride on return, the value such that
170 // * the \t nth weight should be found at <tt> wgt[n*stride] </tt>.
171 // * \param idx the weight index, zero or greater
172 // * This function or getWeightsKokkosView must be implemented in
173 // * derived adapter if getNumWeightsPerID > 0.
174 // * This function should not be called if getNumWeightsPerID is zero.
175 // */
176 virtual void getWeightsView(const scalar_t *&wgt, int &stride,
177 int idx = 0) const {
178 // If adapter does not define getWeightsView, getWeightsKokkosView is called.
179 // If adapter does not define getWeightsKokkosView, getWeightsView is called.
180 // Allows forward and backwards compatibility.
181 Kokkos::View<scalar_t **, device_t> kokkos_wgts_2d;
182 getWeightsKokkosView(kokkos_wgts_2d);
183 Kokkos::View<scalar_t *, device_t> kokkos_wgts;
184 wgt = Kokkos::subview(kokkos_wgts_2d, Kokkos::ALL, idx).data();
185 stride = 1;
186 }
187
189 // * \param wgt on return a Kokkos view of the weights for this idx
190 // * This function or getWeightsView must be implemented in
191 // * derived adapter if getNumWeightsPerID > 0.
192 // * This function should not be called if getNumWeightsPerID is zero.
193 // */
194 virtual void getWeightsKokkosView(Kokkos::View<scalar_t **,
195 device_t> & wgt) const {
196 // If adapter does not define getWeightsKokkosView, getWeightsView is called.
197 // If adapter does not define getWeightsView, getWeightsKokkosView is called.
198 // Allows forward and backwards compatibility.
199 wgt = Kokkos::View<scalar_t **, device_t>(
201 auto host_wgt = Kokkos::create_mirror_view(wgt);
202 for(int j = 0; j < this->getNumWeightsPerID(); ++j) {
203 const scalar_t * ptr_wgts;
204 int stride;
205 getWeightsView(ptr_wgts, stride, j);
206 size_t i = 0;
207 for(size_t n = 0; n < this->getLocalNumIDs() * stride; n += stride) {
208 host_wgt(i++,j) = ptr_wgts[n];
209 }
210 }
211 Kokkos::deep_copy(wgt, host_wgt);
212 }
213
218 virtual void getWeightsHostView(WeightsHostView1D& hostWgts, int idx = 0) const {
220 }
221
225 virtual void getWeightsHostView(WeightsHostView& hostWgts) const {
227 }
228
233 virtual void getWeightsDeviceView(WeightsDeviceView1D& deviceWgts, int idx = 0) const {
235 }
236
240 virtual void getWeightsDeviceView(WeightsDeviceView& deviceWgts) const {
242 }
243
253 virtual void getPartsView(const part_t *&inputPart) const {
254 // Default behavior: return NULL for inputPart array;
255 // assume input part == rank
256 inputPart = NULL;
257 }
258
259 virtual void getPartsHostView(Kokkos::View<part_t*, host_t> &inputPart) const {
261 }
262
263 virtual void getPartsDeviceView(Kokkos::View<part_t*, device_t> &inputPart) const {
265 }
266
284 template <typename Adapter>
285 void applyPartitioningSolution(const User &in, User *&out,
286 const PartitioningSolution<Adapter> &solution) const {
288 }
289
290protected:
291
292 // Write Chaco-formatted graph and assign files echoing adapter input
293 // This routine is serial and may be slow; use it only for debugging
294 // This function does not write edge info to the graph file, as the
295 // BaseAdapter does not know about edge info; it writes
296 // only the Chaco header and vertex weights (if applicable).
297 void generateWeightFileOnly(const char* fileprefix,
298 const Teuchos::Comm<int> &comm) const;
299
300};
301
302template <typename User>
303class AdapterWithCoords : public BaseAdapter<User>
304{
305public:
308 using host_t = typename Kokkos::HostSpace::memory_space;
309
310 // Coordinates in MJ are LayoutLeft since Tpetra Multivector gives LayoutLeft
311 using CoordsDeviceView = Kokkos::View<scalar_t **, Kokkos::LayoutLeft, device_t>;
312 using CoordsHostView = typename CoordsDeviceView::host_mirror_type;
313
314public:
315 virtual void getCoordinatesView(const scalar_t *&coords, int &stride,
316 int coordDim) const = 0;
317 virtual void getCoordinatesKokkosView(CoordsDeviceView &elements) const = 0;
318
322 virtual void getCoordinatesDeviceView(CoordsDeviceView &elements) const {
324 }
325};
326
327// Forward declare
328template <typename User>
329class VectorAdapter;
330
331template <typename User, typename UserCoord=User>
333{
334public:
335 virtual void setCoordinateInput(VectorAdapter<UserCoord> *coordData) = 0;
337};
338
339template <typename User>
341 const char *fileprefix,
342 const Teuchos::Comm<int> &comm
343) const
344{
345 int np = comm.getSize();
346 int me = comm.getRank();
347
348 size_t nLocalIDs = this->getLocalNumIDs();
349
350 // Write .graph file: header and weights only (no edges)
351 // Adapters with edges have to implement their own generateFiles function
352 // to provide edge info.
353 {
354 // append suffix to filename
355 std::string filenamestr = fileprefix;
356 filenamestr = filenamestr + ".graph";
357 const char *filename = filenamestr.c_str();
358
359 size_t nGlobalIDs;
360 Teuchos::reduceAll(comm, Teuchos::REDUCE_SUM, 1, &nLocalIDs, &nGlobalIDs);
361
362 int nWgts = this->getNumWeightsPerID();
363
364 for (int p = 0; p < np; p++) {
365
366 // Is it this processor's turn to write to files?
367 if (me == p) {
368
369 std::ofstream fp;
370
371 if (me == 0) {
372 // open file for writing
373 fp.open(filename, std::ios::out);
374 // write Chaco header info
375 // this function assumes no edges
376 fp << nGlobalIDs << " " << 0 << " "
377 << (nWgts ? "010" : "000") << " "
378 << (nWgts > 1 ? std::to_string(nWgts) : " ") << std::endl;
379 }
380 else {
381 // open file for appending
382 fp.open(filename, std::ios::app);
383 }
384
385 if (nWgts) {
386
387 // get weight data
388 const scalar_t **wgts = new const scalar_t *[nWgts];
389 int *strides = new int[nWgts];
390 for (int n = 0; n < nWgts; n++)
391 getWeightsView(wgts[n], strides[n], n);
392
393 // write weights to file
394 for (size_t i = 0; i < nLocalIDs; i++) {
395 for (int n = 0; n < nWgts; n++)
396 fp << wgts[n][i*strides[n]] << " ";
397 fp << "\n";
398 }
399
400 delete [] strides;
401 delete [] wgts;
402 }
403
404 fp.close();
405 }
406
407 comm.barrier();
408 }
409 }
410
411 // write assignments file
412 {
413 std::string filenamestr = fileprefix;
414 filenamestr = filenamestr + ".assign";
415 const char *filename = filenamestr.c_str();
416
417 for (int p = 0; p < np; p++) {
418
419 // Is it this processor's turn to write to files?
420 if (me == p) {
421
422 std::ofstream fp;
423
424 if (me == 0) {
425 // open file for writing
426 fp.open(filename, std::ios::out);
427 }
428 else {
429 // open file for appending
430 fp.open(filename, std::ios::app);
431 }
432
433 const part_t *parts;
434 this->getPartsView(parts);
435
436 for (size_t i = 0; i < nLocalIDs; i++) {
437 fp << (parts != NULL ? parts[i] : me) << "\n";
438 }
439 fp.close();
440 }
441
442 comm.barrier();
443 }
444 }
445}
446
447} //namespace Zoltan2
448
449#endif
typename node_t::device_type device_t
#define Z2_THROW_NOT_IMPLEMENTED
Traits for application input objects.
Defines the PartitioningSolution class.
Gathering definitions used in software development.
virtual VectorAdapter< UserCoord > * getCoordinateInput() const =0
virtual void setCoordinateInput(VectorAdapter< UserCoord > *coordData)=0
virtual void getCoordinatesView(const scalar_t *&coords, int &stride, int coordDim) const =0
virtual void getCoordinatesDeviceView(CoordsDeviceView &elements) const
typename BaseAdapter< User >::node_t::device_type device_t
Kokkos::View< scalar_t **, Kokkos::LayoutLeft, device_t > CoordsDeviceView
typename BaseAdapter< User >::scalar_t scalar_t
virtual void getCoordinatesKokkosView(CoordsDeviceView &elements) const =0
typename Kokkos::HostSpace::memory_space host_t
typename CoordsDeviceView::host_mirror_type CoordsHostView
virtual void getCoordinatesHostView(CoordsHostView &) const
BaseAdapter defines methods required by all Adapters.
virtual ~BaseAdapterRoot()=default
virtual int getNumWeightsPerID() const
Returns the number of weights per object. Number of weights per object should be zero or greater....
virtual size_t getLocalNumIDs() const =0
Returns the number of objects on this process.
virtual void getWeightsHostView(WeightsHostView &hostWgts) const
Provide a Kokkos view (Host side) of the weights.
typename InputTraits< User >::node_t node_t
Kokkos::View< const scalar_t **, device_t > ConstWeightsDeviceView
Kokkos::View< const scalar_t *, device_t > ConstWeightsDeviceView1D
typename IdsDeviceView::host_mirror_type IdsHostView
typename InputTraits< User >::lno_t lno_t
virtual void getPartsHostView(Kokkos::View< part_t *, host_t > &inputPart) const
Kokkos::View< const offset_t *, device_t > ConstOffsetsDeviceView
void generateWeightFileOnly(const char *fileprefix, const Teuchos::Comm< int > &comm) const
Kokkos::View< const scalar_t *, device_t > ConstScalarsDeviceView
virtual void getIDsView(const gno_t *&ids) const
Provide a pointer to this process' identifiers.
Kokkos::View< const gno_t *, device_t > ConstIdsDeviceView
virtual void getWeightsHostView(WeightsHostView1D &hostWgts, int idx=0) const
Provide pointer to a weight array with stride.
typename ConstScalarsDeviceView::host_mirror_type ConstScalarsHostView
typename ConstWeightsDeviceView1D::host_mirror_type ConstWeightsHostView1D
typename OffsetsDeviceView::host_mirror_type OffsetsHostView
virtual void getPartsView(const part_t *&inputPart) const
Provide pointer to an array containing the input part assignment for each ID. The input part informat...
virtual void getIDsKokkosView(ConstIdsDeviceView &ids) const
Provide a Kokkos view to this process' identifiers.
typename InputTraits< User >::scalar_t scalar_t
typename ConstIdsDeviceView::host_mirror_type ConstIdsHostView
typename InputTraits< User >::gno_t gno_t
typename ConstWeightsDeviceView::host_mirror_type ConstWeightsHostView
virtual void getPartsDeviceView(Kokkos::View< part_t *, device_t > &inputPart) const
typename WeightsDeviceView1D::host_mirror_type WeightsHostView1D
typename Kokkos::HostSpace::memory_space host_t
typename WeightsDeviceView::host_mirror_type WeightsHostView
Kokkos::View< scalar_t *, device_t > ScalarsDeviceView
Kokkos::View< scalar_t *, device_t > WeightsDeviceView1D
virtual enum BaseAdapterType adapterType() const =0
Returns the type of adapter.
typename ConstOffsetsDeviceView::host_mirror_type ConstOffsetsHostView
Kokkos::View< gno_t *, device_t > IdsDeviceView
typename InputTraits< User >::offset_t offset_t
virtual void getWeightsDeviceView(WeightsDeviceView1D &deviceWgts, int idx=0) const
Provide a Kokkos view (Device side) of the weights.
void applyPartitioningSolution(const User &in, User *&out, const PartitioningSolution< Adapter > &solution) const
Apply a PartitioningSolution to an input.
typename InputTraits< User >::part_t part_t
typename ScalarsDeviceView::host_mirror_type ScalarsHostView
Kokkos::View< offset_t *, device_t > OffsetsDeviceView
virtual void getIDsHostView(ConstIdsHostView &hostIds) const
Provide a Kokkos view (Host side) to this process' identifiers.
virtual void getWeightsDeviceView(WeightsDeviceView &deviceWgts) const
Provide a Kokkos view (Device side) of the weights.
Kokkos::View< scalar_t **, device_t > WeightsDeviceView
typename node_t::device_type device_t
virtual void getIDsDeviceView(ConstIdsDeviceView &deviceIds) const
Provide a Kokkos view (Device side) to this process' identifiers.
A PartitioningSolution is a solution to a partitioning problem.
VectorAdapter defines the interface for vector input.
Created by mbenlioglu on Aug 31, 2020.
BaseAdapterType
An enum to identify general types of adapters.
@ VectorAdapterType
vector data
@ InvalidAdapterType
unused value
@ GraphAdapterType
graph data
@ MatrixAdapterType
matrix data
@ MeshAdapterType
mesh data
@ IdentifierAdapterType
identifier data, just a list of IDs
default_offset_t offset_t
The data type to represent offsets.
default_gno_t gno_t
The ordinal type (e.g., int, long, int64_t) that can represent global counts and identifiers.
default_node_t node_t
The Kokkos node type. This is only meaningful for users of Tpetra objects.
default_lno_t lno_t
The ordinal type (e.g., int, long, int64_t) that represents local counts and local indices.
default_part_t part_t
The data type to represent part numbers.
default_scalar_t scalar_t
The data type for weights and coordinates.