Zoltan2
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
Zoltan2_XpetraMultiVectorAdapter.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_XPETRAMULTIVECTORADAPTER_HPP_
15 #define _ZOLTAN2_XPETRAMULTIVECTORADAPTER_HPP_
16 
17 #include <Zoltan2_XpetraTraits.hpp>
19 #include <Zoltan2_StridedData.hpp>
21 
22 #if defined(HAVE_ZOLTAN2_EPETRA) && defined(HAVE_XPETRA_EPETRA)
23 #include <Xpetra_EpetraMultiVector.hpp>
24 #endif
25 #include <Xpetra_TpetraMultiVector.hpp>
26 
27 namespace Zoltan2 {
28 
46 template <typename User>
47  class XpetraMultiVectorAdapter : public VectorAdapter<User> {
48 public:
49 
50 #ifndef DOXYGEN_SHOULD_SKIP_THIS
51  typedef typename InputTraits<User>::scalar_t scalar_t;
52  typedef typename InputTraits<User>::lno_t lno_t;
53  typedef typename InputTraits<User>::gno_t gno_t;
54  typedef typename InputTraits<User>::part_t part_t;
55  typedef typename InputTraits<User>::node_t node_t;
56  typedef User user_t;
57  typedef User userCoord_t;
58 
59  typedef Xpetra::MultiVector<scalar_t, lno_t, gno_t, node_t> x_mvector_t;
60  typedef Xpetra::TpetraMultiVector<
61  scalar_t, lno_t, gno_t, node_t> xt_mvector_t;
62 #endif
63 
79  XpetraMultiVectorAdapter(const RCP<const User> &invector,
80  std::vector<const scalar_t *> &weights, std::vector<int> &weightStrides);
81 
87  XpetraMultiVectorAdapter(const RCP<const User> &invector);
88 
89 
91  // The Adapter interface.
93 
94  size_t getLocalNumIDs() const { return vector_->getLocalLength();}
95 
96  void getIDsView(const gno_t *&ids) const
97  {
98  ids = map_->getLocalElementList().getRawPtr();
99  }
100 
102  Kokkos::View<const gno_t *, typename node_t::device_type> &ids) const {
103  if (map_->lib() == Xpetra::UseTpetra) {
104  using device_type = typename node_t::device_type;
105  const xt_mvector_t *tvector =
106  dynamic_cast<const xt_mvector_t *>(vector_.get());
107  // MJ can be running Host, CudaSpace, or CudaUVMSpace while Map now
108  // internally never stores CudaUVMSpace so we may need a conversion.
109  // However Map stores both Host and CudaSpace so this could be improved
110  // if device_type was CudaSpace. Then we could add a new accessor to
111  // Map such as getMyGlobalIndicesDevice() which could be direct assigned
112  // here. Since Tpetra is still UVM dependent that is not going to happen
113  // yet so just leaving this as Host to device_type conversion for now.
114  ids = Kokkos::create_mirror_view_and_copy(device_type(),
115  tvector->getTpetra_MultiVector()->getMap()->getMyGlobalIndices());
116  }
117  else if (map_->lib() == Xpetra::UseEpetra) {
118 #if defined(HAVE_ZOLTAN2_EPETRA) && defined(HAVE_XPETRA_EPETRA)
119  // this will call getIDsView to get raw ptr and create a view from it
121 #else
122  throw std::logic_error("Epetra requested, but Trilinos is not "
123  "built with Epetra");
124 #endif
125  }
126  else {
127  throw std::logic_error("getIDsKokkosView called but not on Tpetra or Epetra!");
128  }
129  }
130 
131  int getNumWeightsPerID() const { return numWeights_;}
132 
133  void getWeightsView(const scalar_t *&weights, int &stride, int idx) const
134  {
135  if(idx<0 || idx >= numWeights_)
136  {
137  std::ostringstream emsg;
138  emsg << __FILE__ << ":" << __LINE__
139  << " Invalid weight index " << idx << std::endl;
140  throw std::runtime_error(emsg.str());
141  }
142 
143  size_t length;
144  weights_[idx].getStridedList(length, weights, stride);
145  }
146 
147  void getWeightsKokkos2dView(Kokkos::View<scalar_t **,
148  typename node_t::device_type> &wgt) const {
149  typedef Kokkos::View<scalar_t**, typename node_t::device_type> view_t;
150  wgt = view_t("wgts", vector_->getLocalLength(), numWeights_);
151  typename view_t::HostMirror host_wgt = Kokkos::create_mirror_view(wgt);
152  for(int idx = 0; idx < numWeights_; ++idx) {
153  const scalar_t * weights;
154  size_t length;
155  int stride;
156  weights_[idx].getStridedList(length, weights, stride);
157  size_t fill_index = 0;
158  for(size_t n = 0; n < length; n += stride) {
159  host_wgt(fill_index++,idx) = weights[n];
160  }
161  }
162  Kokkos::deep_copy(wgt, host_wgt);
163  }
164 
166  // The VectorAdapter interface.
168 
169  int getNumEntriesPerID() const {return vector_->getNumVectors();}
170 
171  void getEntriesView(const scalar_t *&elements, int &stride, int idx=0) const;
172 
174  // coordinates in MJ are LayoutLeft since Tpetra Multivector gives LayoutLeft
175  Kokkos::View<scalar_t **, Kokkos::LayoutLeft,
176  typename node_t::device_type> & elements) const;
177 
178  template <typename Adapter>
179  void applyPartitioningSolution(const User &in, User *&out,
180  const PartitioningSolution<Adapter> &solution) const;
181 
182  template <typename Adapter>
183  void applyPartitioningSolution(const User &in, RCP<User> &out,
184  const PartitioningSolution<Adapter> &solution) const;
185 
186 private:
187 
188  RCP<const User> invector_;
189  RCP<const x_mvector_t> vector_;
190  RCP<const Xpetra::Map<lno_t, gno_t, node_t> > map_;
191 
192  int numWeights_;
193  ArrayRCP<StridedData<lno_t, scalar_t> > weights_;
194 };
195 
197 // Definitions
199 
200 template <typename User>
202  const RCP<const User> &invector,
203  std::vector<const scalar_t *> &weights, std::vector<int> &weightStrides):
204  invector_(invector), vector_(), map_(),
205  numWeights_(weights.size()), weights_(weights.size())
206 {
207  typedef StridedData<lno_t, scalar_t> input_t;
208 
209  try {
210  RCP<x_mvector_t> tmp =
211  XpetraTraits<User>::convertToXpetra(rcp_const_cast<User>(invector));
212  vector_ = rcp_const_cast<const x_mvector_t>(tmp);
213  }
215 
216  map_ = vector_->getMap();
217 
218  size_t length = vector_->getLocalLength();
219 
220  if (length > 0 && numWeights_ > 0){
221  int stride = 1;
222  for (int w=0; w < numWeights_; w++){
223  if (weightStrides.size())
224  stride = weightStrides[w];
225  ArrayRCP<const scalar_t> wgtV(weights[w], 0, stride*length, false);
226  weights_[w] = input_t(wgtV, stride);
227  }
228  }
229 }
230 
231 
233 template <typename User>
235  const RCP<const User> &invector):
236  invector_(invector), vector_(), map_(),
237  numWeights_(0), weights_()
238 {
239  try {
240  RCP<x_mvector_t> tmp =
241  XpetraTraits<User>::convertToXpetra(rcp_const_cast<User>(invector));
242  vector_ = rcp_const_cast<const x_mvector_t>(tmp);
243  }
245 
246  map_ = vector_->getMap();
247 }
248 
250 template <typename User>
252  const scalar_t *&elements, int &stride, int idx) const
253 {
254  size_t vecsize;
255  stride = 1;
256  elements = NULL;
257  if (map_->lib() == Xpetra::UseTpetra){
258  const xt_mvector_t *tvector =
259  dynamic_cast<const xt_mvector_t *>(vector_.get());
260 
261  vecsize = tvector->getLocalLength();
262  if (vecsize > 0){
263  ArrayRCP<const scalar_t> data = tvector->getData(idx);
264  elements = data.get();
265  }
266  }
267  else if (map_->lib() == Xpetra::UseEpetra){
268 #if defined(HAVE_ZOLTAN2_EPETRA) && defined(HAVE_XPETRA_EPETRA)
269  typedef Xpetra::EpetraMultiVectorT<gno_t,node_t> xe_mvector_t;
270  const xe_mvector_t *evector =
271  dynamic_cast<const xe_mvector_t *>(vector_.get());
272 
273  vecsize = evector->getLocalLength();
274  if (vecsize > 0){
275  ArrayRCP<const double> data = evector->getData(idx);
276 
277  // Cast so this will compile when scalar_t is not double,
278  // a case when this code should never execute.
279  elements = reinterpret_cast<const scalar_t *>(data.get());
280  }
281 #else
282  throw std::logic_error("Epetra requested, but Trilinos is not "
283  "built with Epetra");
284 #endif
285  }
286  else{
287  throw std::logic_error("invalid underlying lib");
288  }
289 }
290 
292 template <typename User>
294  // coordinates in MJ are LayoutLeft since Tpetra Multivector gives LayoutLeft
295  Kokkos::View<scalar_t **, Kokkos::LayoutLeft, typename node_t::device_type> & elements) const
296 {
297  if (map_->lib() == Xpetra::UseTpetra){
298  const xt_mvector_t *tvector =
299  dynamic_cast<const xt_mvector_t *>(vector_.get());
300  // coordinates in MJ are LayoutLeft since Tpetra Multivector gives LayoutLeft
301  Kokkos::View<scalar_t **, Kokkos::LayoutLeft, typename node_t::device_type> view2d =
302  tvector->getTpetra_MultiVector()->template getLocalView<typename node_t::device_type>(Tpetra::Access::ReadWrite);
303  elements = view2d;
304  // CMS/KDD: Look at this stuff right here. Compare against a non-cuda build OR, look at core/driver/driverinputs/kuberry/kuberry.coords
305  // Ca try changing the kuberry.xml to use "input adapter" "BasicVector" rather than "XpetraMultiVector"
306 
307  }
308  else if (map_->lib() == Xpetra::UseEpetra){
309 #if defined(HAVE_ZOLTAN2_EPETRA) && defined(HAVE_XPETRA_EPETRA)
310  typedef Xpetra::EpetraMultiVectorT<gno_t,node_t> xe_mvector_t;
311  const xe_mvector_t *evector =
312  dynamic_cast<const xe_mvector_t *>(vector_.get());
313  elements =
314  Kokkos::View<scalar_t **, Kokkos::LayoutLeft, typename node_t::device_type>
315  ("elements", evector->getLocalLength(), evector->getNumVectors());
316  if(evector->getLocalLength() > 0) {
317  for(size_t idx = 0; idx < evector->getNumVectors(); ++idx) {
318  const scalar_t * ptr;
319  int stride;
320  getEntriesView(ptr, stride, idx);
321  for(size_t n = 0; n < evector->getLocalLength(); ++n) {
322  elements(n, idx) = ptr[n];
323  }
324  }
325  }
326 #else
327  throw std::logic_error("Epetra requested, but Trilinos is not "
328  "built with Epetra");
329 #endif
330  }
331  else {
332  throw std::logic_error("getEntriesKokkosView called but not using Tpetra or Epetra!");
333  }
334 }
335 
337 template <typename User>
338  template <typename Adapter>
340  const User &in, User *&out,
341  const PartitioningSolution<Adapter> &solution) const
342 {
343  // Get an import list (rows to be received)
344  size_t numNewRows;
345  ArrayRCP<gno_t> importList;
346  try{
347  numNewRows = Zoltan2::getImportList<Adapter,
349  (solution, this, importList);
350  }
352 
353  // Move the rows, creating a new vector.
354  RCP<User> outPtr = XpetraTraits<User>::doMigration(in, numNewRows,
355  importList.getRawPtr());
356  out = outPtr.get();
357  outPtr.release();
358 }
359 
361 template <typename User>
362  template <typename Adapter>
364  const User &in, RCP<User> &out,
365  const PartitioningSolution<Adapter> &solution) const
366 {
367  // Get an import list (rows to be received)
368  size_t numNewRows;
369  ArrayRCP<gno_t> importList;
370  try{
371  numNewRows = Zoltan2::getImportList<Adapter,
373  (solution, this, importList);
374  }
376 
377  // Move the rows, creating a new vector.
378  out = XpetraTraits<User>::doMigration(in, numNewRows,
379  importList.getRawPtr());
380 }
381 
382 } //namespace Zoltan2
383 
384 #endif
Helper functions for Partitioning Problems.
#define Z2_FORWARD_EXCEPTIONS
Forward an exception back through call stack.
static ArrayRCP< ArrayRCP< zscalar_t > > weights
default_part_t part_t
The data type to represent part numbers.
map_t::global_ordinal_type gno_t
Definition: mapRemotes.cpp:27
XpetraMultiVectorAdapter(const RCP< const User > &invector, std::vector< const scalar_t * > &weights, std::vector< int > &weightStrides)
Constructor.
Defines the VectorAdapter interface.
static RCP< User > doMigration(const User &from, size_t numLocalRows, const gno_t *myNewRows)
Migrate the object Given a user object and a new row distribution, create and return a new user objec...
typename Zoltan2::InputTraits< ztcrsmatrix_t >::node_t node_t
Traits of Xpetra classes, including migration method.
typename InputTraits< User >::part_t part_t
void getIDsKokkosView(Kokkos::View< const gno_t *, typename node_t::device_type > &ids) const
static RCP< User > convertToXpetra(const RCP< User > &a)
Convert the object to its Xpetra wrapped version.
size_t getImportList(const PartitioningSolution< SolutionAdapter > &solution, const DataAdapter *const data, ArrayRCP< typename DataAdapter::gno_t > &imports)
From a PartitioningSolution, get a list of IDs to be imported. Assumes part numbers in PartitioningSo...
virtual void getIDsKokkosView(ConstIdsDeviceView &ids) const
Provide a Kokkos view to this process&#39; identifiers.
int getNumEntriesPerID() const
Return the number of vectors.
typename InputTraits< User >::node_t node_t
A PartitioningSolution is a solution to a partitioning problem.
typename InputTraits< User >::gno_t gno_t
void applyPartitioningSolution(const User &in, User *&out, const PartitioningSolution< Adapter > &solution) const
default_lno_t lno_t
The ordinal type (e.g., int, long, int64_t) that represents local counts and local indices...
VectorAdapter defines the interface for vector input.
The StridedData class manages lists of weights or coordinates.
void getEntriesView(const scalar_t *&elements, int &stride, int idx=0) const
Provide a pointer to the elements of the specified vector.
int getNumWeightsPerID() const
Returns the number of weights per object. Number of weights per object should be zero or greater...
An adapter for Xpetra::MultiVector.
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.
void getWeightsKokkos2dView(Kokkos::View< scalar_t **, typename node_t::device_type > &wgt) const
size_t getLocalNumIDs() const
Returns the number of objects on this process.
typename BaseAdapter< User >::scalar_t scalar_t
typename InputTraits< User >::lno_t lno_t
default_scalar_t scalar_t
The data type for weights and coordinates.
void getWeightsView(const scalar_t *&weights, int &stride, int idx) const
Provide pointer to a weight array with stride.
void getEntriesKokkosView(Kokkos::View< scalar_t **, Kokkos::LayoutLeft, typename node_t::device_type > &elements) const
This file defines the StridedData class.
Zoltan2::BasicUserTypes< zscalar_t, zlno_t, zgno_t > user_t
Definition: Metric.cpp:39