Zoltan2
Zoltan2_Adapter.hpp
Go to the documentation of this file.
1 // @HEADER
2 //
3 // ***********************************************************************
4 //
5 // Zoltan2: A package of combinatorial algorithms for scientific computing
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 Karen Devine (kddevin@sandia.gov)
39 // Erik Boman (egboman@sandia.gov)
40 // Siva Rajamanickam (srajama@sandia.gov)
41 //
42 // ***********************************************************************
43 //
44 // @HEADER
45 
50 #ifndef _ZOLTAN2_ADAPTER_HPP_
51 #define _ZOLTAN2_ADAPTER_HPP_
52 
53 #include <Kokkos_Core.hpp>
54 #include <Zoltan2_Standards.hpp>
55 #include <Zoltan2_InputTraits.hpp>
57 
58 namespace Zoltan2 {
59 
70 };
71 
82 public:
83  virtual ~BaseAdapterRoot() {}; // required virtual declaration
84 
90  virtual size_t getLocalNumIDs() const = 0;
91 
97  virtual int getNumWeightsPerID() const { return 0; };
98 };
99 
100 template <typename User>
101  class BaseAdapter : public BaseAdapterRoot {
102 
103 public:
104  typedef typename InputTraits<User>::lno_t lno_t;
105  typedef typename InputTraits<User>::gno_t gno_t;
110 
113  virtual enum BaseAdapterType adapterType() const = 0;
114 
117  virtual ~BaseAdapter() {};
118 
123  virtual void getIDsView(const gno_t *&ids) const {
124  // If adapter does not define getIDsView, getIDsKokkosView is called.
125  // If adapter does not define getIDsKokkosView, getIDsView is called.
126  // Allows forward and backwards compatibility.
127  Kokkos::View<const gno_t *, typename node_t::device_type> kokkosIds;
128  getIDsKokkosView(kokkosIds);
129  ids = kokkosIds.data();
130  }
131 
136  virtual void getIDsKokkosView(Kokkos::View<const gno_t *,
137  typename node_t::device_type> &ids) const {
138  // If adapter does not define getIDsView, getIDsKokkosView is called.
139  // If adapter does not define getIDsKokkosView, getIDsView is called.
140  // Allows forward and backwards compatibility.
141  const gno_t * ptr_ids;
142  getIDsView(ptr_ids);
143  typedef Kokkos::View<gno_t *, typename node_t::device_type> view_t;
144  view_t non_const_ids = view_t("ptr_ids", getLocalNumIDs());
145  typename view_t::HostMirror host_ids = Kokkos::create_mirror_view(non_const_ids);
146  for(size_t i = 0; i < this->getLocalNumIDs(); ++i) {
147  host_ids(i) = ptr_ids[i];
148  }
149  Kokkos::deep_copy(non_const_ids, host_ids);
150  ids = non_const_ids;
151  }
152 
154  // * \param wgt on return a pointer to the weights for this idx
155  // * \param stride on return, the value such that
156  // * the \t nth weight should be found at <tt> wgt[n*stride] </tt>.
157  // * \param idx the weight index, zero or greater
158  // * This function or getWeightsKokkosView must be implemented in
159  // * derived adapter if getNumWeightsPerID > 0.
160  // * This function should not be called if getNumWeightsPerID is zero.
161  // */
162  virtual void getWeightsView(const scalar_t *&wgt, int &stride,
163  int idx = 0) const {
164  // If adapter does not define getWeightsView, getWeightsKokkosView is called.
165  // If adapter does not define getWeightsKokkosView, getWeightsView is called.
166  // Allows forward and backwards compatibility.
167  Kokkos::View<scalar_t **, typename node_t::device_type> kokkos_wgts_2d;
168  getWeightsKokkosView(kokkos_wgts_2d);
169  Kokkos::View<scalar_t *, typename node_t::device_type> kokkos_wgts;
170  wgt = Kokkos::subview(kokkos_wgts_2d, Kokkos::ALL, idx).data();
171  stride = 1;
172  }
173 
175  // * \param wgt on return a Kokkos view of the weights for this idx
176  // * This function or getWeightsView must be implemented in
177  // * derived adapter if getNumWeightsPerID > 0.
178  // * This function should not be called if getNumWeightsPerID is zero.
179  // */
180  virtual void getWeightsKokkosView(Kokkos::View<scalar_t **,
181  typename node_t::device_type> & wgt) const {
182  // If adapter does not define getWeightsKokkosView, getWeightsView is called.
183  // If adapter does not define getWeightsView, getWeightsKokkosView is called.
184  // Allows forward and backwards compatibility.
185  wgt = Kokkos::View<scalar_t **, typename node_t::device_type>(
186  "wgts", getLocalNumIDs(), getNumWeightsPerID());
187  typename Kokkos::View<scalar_t **, typename node_t::device_type>::HostMirror
188  host_wgt = Kokkos::create_mirror_view(wgt);
189  for(int j = 0; j < this->getNumWeightsPerID(); ++j) {
190  const scalar_t * ptr_wgts;
191  int stride;
192  getWeightsView(ptr_wgts, stride, j);
193  size_t i = 0;
194  for(size_t n = 0; n < this->getLocalNumIDs() * stride; n += stride) {
195  host_wgt(i++,j) = ptr_wgts[n];
196  }
197  }
198  Kokkos::deep_copy(wgt, host_wgt);
199  }
200 
210  void getPartsView(const part_t *&inputPart) const {
211  // Default behavior: return NULL for inputPart array;
212  // assume input part == rank
213  inputPart = NULL;
214  }
215 
233  template <typename Adapter>
234  void applyPartitioningSolution(const User &in, User *&out,
235  const PartitioningSolution<Adapter> &solution) const {
237  }
238 
239 protected:
240 
241  // Write Chaco-formatted graph and assign files echoing adapter input
242  // This routine is serial and may be slow; use it only for debugging
243  // This function does not write edge info to the graph file, as the
244  // BaseAdapter does not know about edge info; it writes
245  // only the Chaco header and vertex weights (if applicable).
246  void generateWeightFileOnly(const char* fileprefix,
247  const Teuchos::Comm<int> &comm) const;
248 
249 };
250 
251 template <typename User>
253  const char *fileprefix,
254  const Teuchos::Comm<int> &comm
255 ) const
256 {
257  int np = comm.getSize();
258  int me = comm.getRank();
259 
260  size_t nLocalIDs = this->getLocalNumIDs();
261 
262  // Write .graph file: header and weights only (no edges)
263  // Adapters with edges have to implement their own generateFiles function
264  // to provide edge info.
265  {
266  // append suffix to filename
267  std::string filenamestr = fileprefix;
268  filenamestr = filenamestr + ".graph";
269  const char *filename = filenamestr.c_str();
270 
271  size_t nGlobalIDs;
272  Teuchos::reduceAll(comm, Teuchos::REDUCE_SUM, 1, &nLocalIDs, &nGlobalIDs);
273 
274  int nWgts = this->getNumWeightsPerID();
275 
276  for (int p = 0; p < np; p++) {
277 
278  // Is it this processor's turn to write to files?
279  if (me == p) {
280 
281  std::ofstream fp;
282 
283  if (me == 0) {
284  // open file for writing
285  fp.open(filename, std::ios::out);
286  // write Chaco header info
287  // this function assumes no edges
288  fp << nGlobalIDs << " " << 0 << " "
289  << (nWgts ? "010" : "000") << " "
290  << (nWgts > 1 ? std::to_string(nWgts) : " ") << std::endl;
291  }
292  else {
293  // open file for appending
294  fp.open(filename, std::ios::app);
295  }
296 
297  if (nWgts) {
298 
299  // get weight data
300  const scalar_t **wgts = new const scalar_t *[nWgts];
301  int *strides = new int[nWgts];
302  for (int n = 0; n < nWgts; n++)
303  getWeightsView(wgts[n], strides[n], n);
304 
305  // write weights to file
306  for (size_t i = 0; i < nLocalIDs; i++) {
307  for (int n = 0; n < nWgts; n++)
308  fp << wgts[n][i*strides[n]] << " ";
309  fp << "\n";
310  }
311 
312  delete [] strides;
313  delete [] wgts;
314  }
315 
316  fp.close();
317  }
318 
319  comm.barrier();
320  }
321  }
322 
323  // write assignments file
324  {
325  std::string filenamestr = fileprefix;
326  filenamestr = filenamestr + ".assign";
327  const char *filename = filenamestr.c_str();
328 
329  for (int p = 0; p < np; p++) {
330 
331  // Is it this processor's turn to write to files?
332  if (me == p) {
333 
334  std::ofstream fp;
335 
336  if (me == 0) {
337  // open file for writing
338  fp.open(filename, std::ios::out);
339  }
340  else {
341  // open file for appending
342  fp.open(filename, std::ios::app);
343  }
344 
345  const part_t *parts;
346  this->getPartsView(parts);
347 
348  for (size_t i = 0; i < nLocalIDs; i++) {
349  fp << (parts != NULL ? parts[i] : me) << "\n";
350  }
351  fp.close();
352  }
353 
354  comm.barrier();
355  }
356  }
357 }
358 
359 } //namespace Zoltan2
360 
361 #endif
#define Z2_THROW_NOT_IMPLEMENTED
Traits for application input objects.
Defines the PartitioningSolution class.
Gathering definitions used in software development.
BaseAdapter defines methods required by all Adapters.
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.
InputTraits< User >::node_t node_t
void getPartsView(const part_t *&inputPart) const
Provide pointer to a weight array with stride.
InputTraits< User >::offset_t offset_t
InputTraits< User >::part_t part_t
InputTraits< User >::scalar_t scalar_t
void generateWeightFileOnly(const char *fileprefix, const Teuchos::Comm< int > &comm) const
virtual void getIDsView(const gno_t *&ids) const
Provide a pointer to this process' identifiers.
InputTraits< User >::lno_t lno_t
virtual ~BaseAdapter()
Destructor.
virtual void getIDsKokkosView(Kokkos::View< const gno_t *, typename node_t::device_type > &ids) const
Provide a Kokkos view to this process' identifiers.
virtual enum BaseAdapterType adapterType() const =0
Returns the type of adapter.
void applyPartitioningSolution(const User &in, User *&out, const PartitioningSolution< Adapter > &solution) const
Apply a PartitioningSolution to an input.
InputTraits< User >::gno_t gno_t
A PartitioningSolution is a solution to a partitioning problem.
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.