Zoltan2
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
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>
19 #include <Zoltan2_InputTraits.hpp>
21 #include <fstream>
22 
23 namespace Zoltan2 {
24 
25 //template<typename Adapter>
26 //class PartitioningSolution;
27 
38 };
39 
50 public:
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 
68 template <typename User>
69  class BaseAdapter : public BaseAdapterRoot {
70 
71 public:
72  using lno_t = typename InputTraits<User>::lno_t;
73  using gno_t = typename InputTraits<User>::gno_t;
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::HostMirror;
83 
84  using IdsDeviceView = Kokkos::View<gno_t *, device_t>;
85  using IdsHostView = typename IdsDeviceView::HostMirror;
86 
87  using ConstOffsetsDeviceView = Kokkos::View<const offset_t *, device_t>;
88  using ConstOffsetsHostView = typename ConstOffsetsDeviceView::HostMirror;
89 
90  using OffsetsDeviceView = Kokkos::View<offset_t *, device_t>;
91  using OffsetsHostView = typename OffsetsDeviceView::HostMirror;
92 
93  using ConstScalarsDeviceView = Kokkos::View<const scalar_t *, device_t>;
94  using ConstScalarsHostView = typename ConstScalarsDeviceView::HostMirror;
95 
96  using ScalarsDeviceView = Kokkos::View<scalar_t *, device_t>;
97  using ScalarsHostView = typename ScalarsDeviceView::HostMirror;
98 
99  using ConstWeightsDeviceView1D = Kokkos::View<const scalar_t *, device_t>;
100  using ConstWeightsHostView1D = typename ConstWeightsDeviceView1D::HostMirror;
101 
102  using WeightsDeviceView1D = Kokkos::View<scalar_t *, device_t>;
103  using WeightsHostView1D = typename WeightsDeviceView1D::HostMirror;
104 
105  using ConstWeightsDeviceView = Kokkos::View<const scalar_t **, device_t>;
106  using ConstWeightsHostView = typename ConstWeightsDeviceView::HostMirror;
107 
108  using WeightsDeviceView = Kokkos::View<scalar_t **, device_t>;
109  using WeightsHostView = typename WeightsDeviceView::HostMirror;
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>(
200  "wgts", getLocalNumIDs(), getNumWeightsPerID());
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 
290 protected:
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 
302 template <typename User>
303 class AdapterWithCoords : public BaseAdapter<User>
304 {
305 public:
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::HostMirror;
313 
314 public:
315  virtual void getCoordinatesView(const scalar_t *&coords, int &stride,
316  int coordDim) const = 0;
317  virtual void getCoordinatesKokkosView(CoordsDeviceView &elements) const = 0;
318 
319  virtual void getCoordinatesHostView(CoordsHostView &) const {
321  }
322  virtual void getCoordinatesDeviceView(CoordsDeviceView &elements) const {
324  }
325 };
326 
327 // Forward declare
328 template <typename User>
330 
331 template <typename User, typename UserCoord=User>
333 {
334 public:
335  virtual void setCoordinateInput(VectorAdapter<UserCoord> *coordData) = 0;
336  virtual VectorAdapter<UserCoord> *getCoordinateInput() const = 0;
337 };
338 
339 template <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
Kokkos::View< const scalar_t *, device_t > ConstWeightsDeviceView1D
virtual int getNumWeightsPerID() const
Returns the number of weights per object. Number of weights per object should be zero or greater...
virtual VectorAdapter< UserCoord > * getCoordinateInput() const =0
virtual void getPartsDeviceView(Kokkos::View< part_t *, device_t > &inputPart) const
virtual void getIDsView(const gno_t *&ids) const
Provide a pointer to this process&#39; identifiers.
typename InputTraits< UserCoord >::scalar_t scalar_t
typename Kokkos::HostSpace::memory_space host_t
Kokkos::View< scalar_t *, device_t > WeightsDeviceView1D
Kokkos::View< scalar_t **, Kokkos::LayoutLeft, device_t > CoordsDeviceView
default_part_t part_t
The data type to represent part numbers.
default_offset_t offset_t
The data type to represent offsets.
virtual void getIDsDeviceView(ConstIdsDeviceView &deviceIds) const
Provide a Kokkos view (Device side) to this process&#39; identifiers.
#define Z2_THROW_NOT_IMPLEMENTED
virtual void setCoordinateInput(VectorAdapter< UserCoord > *coordData)=0
typename node_t::device_type device_t
typename ScalarsDeviceView::HostMirror ScalarsHostView
Defines the PartitioningSolution class.
typename InputTraits< UserCoord >::part_t part_t
Kokkos::View< const gno_t *, device_t > ConstIdsDeviceView
typename ConstScalarsDeviceView::HostMirror ConstScalarsHostView
virtual void getWeightsDeviceView(WeightsDeviceView1D &deviceWgts, int idx=0) const
Provide a Kokkos view (Device side) of the weights.
virtual void getWeightsView(const scalar_t *&wgt, int &stride, int idx=0) const
Provide pointer to a weight array with stride.
virtual void getIDsKokkosView(ConstIdsDeviceView &ids) const
Provide a Kokkos view to this process&#39; identifiers.
typename IdsDeviceView::HostMirror IdsHostView
typename WeightsDeviceView::HostMirror WeightsHostView
Kokkos::View< const scalar_t *, device_t > ConstScalarsDeviceView
typename InputTraits< UserCoord >::node_t node_t
typename CoordsDeviceView::HostMirror CoordsHostView
virtual void getWeightsKokkosView(Kokkos::View< scalar_t **, device_t > &wgt) const
Provide kokkos view of weights.
virtual ~BaseAdapterRoot()=default
A PartitioningSolution is a solution to a partitioning problem.
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...
typename ConstOffsetsDeviceView::HostMirror ConstOffsetsHostView
typename InputTraits< UserCoord >::gno_t gno_t
typename ConstIdsDeviceView::HostMirror ConstIdsHostView
void generateWeightFileOnly(const char *fileprefix, const Teuchos::Comm< int > &comm) const
default_lno_t lno_t
The ordinal type (e.g., int, long, int64_t) that represents local counts and local indices...
BaseAdapterType
An enum to identify general types of adapters.
identifier data, just a list of IDs
VectorAdapter defines the interface for vector input.
typename ConstWeightsDeviceView1D::HostMirror ConstWeightsHostView1D
BaseAdapter defines methods required by all Adapters.
Kokkos::View< gno_t *, device_t > IdsDeviceView
Traits for application input objects.
default_gno_t gno_t
The ordinal type (e.g., int, long, int64_t) that can represent global counts and identifiers.
virtual void getPartsHostView(Kokkos::View< part_t *, host_t > &inputPart) const
Kokkos::View< offset_t *, device_t > OffsetsDeviceView
default_node_t node_t
The Kokkos node type. This is only meaningful for users of Tpetra objects.
typename InputTraits< UserCoord >::offset_t offset_t
typename WeightsDeviceView1D::HostMirror WeightsHostView1D
virtual void getWeightsHostView(WeightsHostView &hostWgts) const
Provide a Kokkos view (Host side) of the weights.
void applyPartitioningSolution(const User &in, User *&out, const PartitioningSolution< Adapter > &solution) const
Apply a PartitioningSolution to an input.
virtual size_t getLocalNumIDs() const =0
Returns the number of objects on this process.
typename ConstWeightsDeviceView::HostMirror ConstWeightsHostView
virtual void getCoordinatesHostView(CoordsHostView &) const
Gathering definitions used in software development.
virtual void getCoordinatesDeviceView(CoordsDeviceView &elements) const
Kokkos::View< const scalar_t **, device_t > ConstWeightsDeviceView
Kokkos::View< scalar_t **, device_t > WeightsDeviceView
typename OffsetsDeviceView::HostMirror OffsetsHostView
Kokkos::View< scalar_t *, device_t > ScalarsDeviceView
virtual void getCoordinatesKokkosView(CoordsDeviceView &elements) const =0
virtual void getWeightsHostView(WeightsHostView1D &hostWgts, int idx=0) const
Provide a Kokkos view (Host side) of the weights.
virtual void getWeightsDeviceView(WeightsDeviceView &deviceWgts) const
Provide a Kokkos view (Device side) of the weights.
Kokkos::View< const offset_t *, device_t > ConstOffsetsDeviceView
typename InputTraits< UserCoord >::lno_t lno_t
default_scalar_t scalar_t
The data type for weights and coordinates.
virtual void getCoordinatesView(const scalar_t *&coords, int &stride, int coordDim) const =0
virtual enum BaseAdapterType adapterType() const =0
Returns the type of adapter.
virtual void getIDsHostView(ConstIdsHostView &hostIds) const
Provide a Kokkos view (Host side) to this process&#39; identifiers.