Stokhos Package Browser (Single Doxygen Collection)  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
Stokhos_Tpetra_Utilities_MP_Vector.hpp
Go to the documentation of this file.
1 // @HEADER
2 // *****************************************************************************
3 // Stokhos Package
4 //
5 // Copyright 2009 NTESS and the Stokhos contributors.
6 // SPDX-License-Identifier: BSD-3-Clause
7 // *****************************************************************************
8 // @HEADER
9 
10 #ifndef STOKHOS_TPETRA_UTILITIES_MP_VECTOR_HPP
11 #define STOKHOS_TPETRA_UTILITIES_MP_VECTOR_HPP
12 
14 #include "Tpetra_Map.hpp"
15 #include "Tpetra_MultiVector.hpp"
16 #include "Tpetra_CrsGraph.hpp"
17 #include "Tpetra_CrsMatrix.hpp"
18 
19 namespace Stokhos {
20 
21  // Create a flattened map for a map representing a distribution for an
22  // embedded scalar type
23  template <typename LocalOrdinal, typename GlobalOrdinal, typename Node>
25  create_flat_map(const Tpetra::Map<LocalOrdinal,GlobalOrdinal,Node>& map,
26  const LocalOrdinal block_size) {
27  using Tpetra::global_size_t;
28  using Teuchos::ArrayView;
29  using Teuchos::Array;
30  using Teuchos::RCP;
31  using Teuchos::rcp;
32 
33  typedef Tpetra::Map<LocalOrdinal,GlobalOrdinal,Node> Map;
34 
35  // Get map info
36  const global_size_t num_global_entries = map.getGlobalNumElements();
37  const size_t num_local_entries = map.getLocalNumElements();
38  const GlobalOrdinal index_base = map.getIndexBase();
39  ArrayView<const GlobalOrdinal> element_list =
40  map.getLocalElementList();
41 
42  // Create new elements
43  const global_size_t flat_num_global_entries = num_global_entries*block_size;
44  const size_t flat_num_local_entries = num_local_entries * block_size;
45  const GlobalOrdinal flat_index_base = index_base;
46  Array<GlobalOrdinal> flat_element_list(flat_num_local_entries);
47  for (size_t i=0; i<num_local_entries; ++i)
48  for (LocalOrdinal j=0; j<block_size; ++j)
49  flat_element_list[i*block_size+j] = element_list[i]*block_size+j;
50 
51  // Create new map
52  RCP<Map> flat_map =
53  rcp(new Map(flat_num_global_entries, flat_element_list(),
54  flat_index_base, map.getComm()));
55 
56  return flat_map;
57  }
58 
59  // Create a flattened graph for a graph from a matrix with the
60  // MP::Vector scalar type (each block is an identity matrix)
61  // If flat_domain_map and/or flat_range_map are null, they will be computed,
62  // otherwise they will be used as-is.
63  template <typename LocalOrdinal, typename GlobalOrdinal, typename Node>
66  const Tpetra::CrsGraph<LocalOrdinal,GlobalOrdinal,Node >& graph,
67  Teuchos::RCP<const Tpetra::Map<LocalOrdinal,GlobalOrdinal,Node > >& flat_domain_map,
68  Teuchos::RCP<const Tpetra::Map<LocalOrdinal,GlobalOrdinal,Node > >& flat_range_map,
69  const LocalOrdinal block_size) {
70  using Teuchos::ArrayRCP;
71  using Teuchos::RCP;
72  using Teuchos::rcp;
73 
74  typedef Tpetra::Map<LocalOrdinal,GlobalOrdinal,Node> Map;
75  typedef Tpetra::CrsGraph<LocalOrdinal,GlobalOrdinal,Node> Graph;
76  typedef typename Graph::local_graph_device_type::row_map_type::non_const_type RowPtrs;
77  typedef typename Graph::local_graph_device_type::entries_type::non_const_type LocalIndices;
78 
79  // Build domain map if necessary
80  if (flat_domain_map == Teuchos::null)
81  flat_domain_map = create_flat_map(*(graph.getDomainMap()), block_size);
82 
83  // Build range map if necessary
84  if (flat_range_map == Teuchos::null)
85  flat_range_map = create_flat_map(*(graph.getRangeMap()), block_size);
86 
87  // Build column map
88  RCP<const Map> flat_col_map =
89  create_flat_map(*(graph.getColMap()), block_size);
90 
91  // Build row map if necessary
92  // Check if range_map == row_map, then we can use flat_range_map
93  // as the flattened row map
94  RCP<const Map> flat_row_map;
95  if (graph.getRangeMap() == graph.getRowMap())
96  flat_row_map = flat_range_map;
97  else
98  flat_row_map = create_flat_map(*(graph.getRowMap()), block_size);
99 
100  // Build flattened row offsets and column indices
101  auto row_offsets = graph.getLocalRowPtrsHost();
102  auto col_indices = graph.getLocalIndicesHost();
103  const size_t num_row = graph.getLocalNumRows();
104  const size_t num_col_indices = col_indices.size();
105  RowPtrs flat_row_offsets("row_ptrs", num_row*block_size+1);
106  LocalIndices flat_col_indices("col_indices", num_col_indices * block_size);
107  auto flat_row_offsets_host = Kokkos::create_mirror_view(flat_row_offsets);
108  auto flat_col_indices_host = Kokkos::create_mirror_view(flat_col_indices);
109  for (size_t row=0; row<num_row; ++row) {
110  const size_t row_beg = row_offsets[row];
111  const size_t row_end = row_offsets[row+1];
112  const size_t num_col = row_end - row_beg;
113  for (LocalOrdinal j=0; j<block_size; ++j) {
114  const size_t flat_row = row*block_size + j;
115  const size_t flat_row_beg = row_beg*block_size + j*num_col;
116  flat_row_offsets_host[flat_row] = flat_row_beg;
117  for (size_t entry=0; entry<num_col; ++entry) {
118  const LocalOrdinal col = col_indices[row_beg+entry];
119  const LocalOrdinal flat_col = col*block_size + j;
120  flat_col_indices_host[flat_row_beg+entry] = flat_col;
121  }
122  }
123  }
124  flat_row_offsets_host[num_row*block_size] = num_col_indices*block_size;
125  Kokkos::deep_copy(flat_row_offsets, flat_row_offsets_host);
126  Kokkos::deep_copy(flat_col_indices, flat_col_indices_host);
127 
128  // Build flattened graph
129  RCP<Graph> flat_graph =
130  rcp(new Graph(flat_row_map, flat_col_map,
131  flat_row_offsets, flat_col_indices));
132  flat_graph->fillComplete(flat_domain_map, flat_range_map);
133 
134  return flat_graph;
135  }
136 
137  // Create a flattened vector by unrolling the MP::Vector scalar type. The
138  // returned vector is a view of the original
139  template <typename Storage, typename LocalOrdinal, typename GlobalOrdinal, typename Node>
142  const Tpetra::MultiVector<Sacado::MP::Vector<Storage>, LocalOrdinal, GlobalOrdinal, Node>& vec,
143  const Teuchos::RCP<const Tpetra::Map<LocalOrdinal, GlobalOrdinal, Node>>& flat_map
144  ) {
145  using BaseScalar = typename Storage::value_type;
146  using FlatVector = Tpetra::MultiVector<BaseScalar, LocalOrdinal, GlobalOrdinal, Node>;
147 
148  // Create flattenend view using reshaping conversion copy constructor
149  typename FlatVector::wrapped_dual_view_type flat_vals(vec.getWrappedDualView());
150 
151  // Create flat vector
152  return Teuchos::make_rcp<FlatVector>(flat_map, flat_vals);
153  }
154 
155  // This version creates the map if necessary
156  template <typename Storage, typename LocalOrdinal, typename GlobalOrdinal, typename Node>
159  const Tpetra::MultiVector<Sacado::MP::Vector<Storage>, LocalOrdinal, GlobalOrdinal, Node>& vec,
160  Teuchos::RCP<const Tpetra::Map<LocalOrdinal, GlobalOrdinal, Node>>& flat_map
161  ) {
162  if (flat_map == Teuchos::null) {
163  const LocalOrdinal mp_size = Storage::static_size;
164  flat_map = create_flat_map(*(vec.getMap()), mp_size);
165  }
167  return create_flat_vector_view(vec, const_flat_map);
168  }
169 
170  template <typename Storage, typename LocalOrdinal, typename GlobalOrdinal, typename Node>
173  const Tpetra::Vector<Sacado::MP::Vector<Storage>, LocalOrdinal, GlobalOrdinal, Node>& vec,
174  const Teuchos::RCP<const Tpetra::Map<LocalOrdinal, GlobalOrdinal, Node>>& flat_map
175  ) {
177  static_cast<const Tpetra::MultiVector<Sacado::MP::Vector<Storage>, LocalOrdinal, GlobalOrdinal, Node>&>(vec),
178  flat_map
179  )->getVectorNonConst(0);
180  }
181 
182  template <typename Storage, typename LocalOrdinal, typename GlobalOrdinal, typename Node>
185  const Tpetra::Vector<Sacado::MP::Vector<Storage>, LocalOrdinal, GlobalOrdinal, Node>& vec,
186  Teuchos::RCP<const Tpetra::Map<LocalOrdinal, GlobalOrdinal, Node>>& flat_map
187  ) {
188  if (flat_map == Teuchos::null) {
189  const LocalOrdinal mp_size = Storage::static_size;
190  flat_map = create_flat_map(*(vec.getMap()), mp_size);
191  }
193  return create_flat_vector_view(vec, const_flat_map);
194  }
195 
196  // Create a flattened matrix by unrolling the MP::Vector scalar type. The
197  // returned matrix is NOT a view of the original (and can't be)
198  template <typename Storage, typename LocalOrdinal, typename GlobalOrdinal,
199  typename Node>
200  Teuchos::RCP< Tpetra::CrsMatrix<typename Storage::value_type,
203  const Tpetra::CrsMatrix<Sacado::MP::Vector<Storage>,
205  const Teuchos::RCP<const Tpetra::CrsGraph<LocalOrdinal,GlobalOrdinal,Node> >& flat_graph,
206  const LocalOrdinal block_size) {
207  using Teuchos::ArrayView;
208  using Teuchos::Array;
209  using Teuchos::RCP;
210  using Teuchos::rcp;
211 
213  typedef typename Storage::value_type BaseScalar;
214  typedef Tpetra::CrsMatrix<Scalar,LocalOrdinal,GlobalOrdinal,Node> Matrix;
215  typedef Tpetra::CrsMatrix<BaseScalar,LocalOrdinal,GlobalOrdinal,Node> FlatMatrix;
216 
217  // Create flat matrix
218  RCP<FlatMatrix> flat_mat = rcp(new FlatMatrix(flat_graph));
219 
220  // Set values
221  const size_t num_rows = mat.getLocalNumRows();
222  const size_t max_cols = mat.getLocalMaxNumRowEntries();
223  typename Matrix::local_inds_host_view_type indices, flat_indices;
224  typename Matrix::values_host_view_type values;
225  Array<BaseScalar> flat_values(max_cols);
226  for (size_t row=0; row<num_rows; ++row) {
227  mat.getLocalRowView(row, indices, values);
228  const size_t num_col = mat.getNumEntriesInLocalRow(row);
229  for (LocalOrdinal i=0; i<block_size; ++i) {
230  const LocalOrdinal flat_row = row*block_size + i;
231  for (size_t j=0; j<num_col; ++j)
232  flat_values[j] = values[j].coeff(i);
233  flat_graph->getLocalRowView(flat_row, flat_indices);
234  flat_mat->replaceLocalValues(flat_row, Kokkos::Compat::getConstArrayView(flat_indices),
235  flat_values(0, num_col));
236  }
237  }
238  flat_mat->fillComplete(flat_graph->getDomainMap(),
239  flat_graph->getRangeMap());
240 
241  return flat_mat;
242  }
243 
244 } // namespace Stokhos
245 
246 #endif // STOKHOS_TPETRA_UTILITIES_MP_VECTOR_HPP
Teuchos::RCP< Tpetra::CrsMatrix< typename Storage::value_type, LocalOrdinal, GlobalOrdinal, Node > > create_flat_matrix(const Tpetra::CrsMatrix< Sacado::UQ::PCE< Storage >, LocalOrdinal, GlobalOrdinal, Node > &mat, const Teuchos::RCP< const Tpetra::CrsGraph< LocalOrdinal, GlobalOrdinal, Node > > &flat_graph, const Teuchos::RCP< const Tpetra::CrsGraph< LocalOrdinal, GlobalOrdinal, Node > > &cijk_graph, const CijkType &cijk_dev)
Stokhos::StandardStorage< int, double > Storage
Teuchos::RCP< const Tpetra::MultiVector< typename Storage::value_type, LocalOrdinal, GlobalOrdinal, Node > > create_flat_vector_view(const Tpetra::MultiVector< Sacado::UQ::PCE< Storage >, LocalOrdinal, GlobalOrdinal, Node > &vec, const Teuchos::RCP< const Tpetra::Map< LocalOrdinal, GlobalOrdinal, Node > > &flat_map)
TEUCHOS_DEPRECATED RCP< T > rcp(T *p, Dealloc_T dealloc, bool owns_mem)
Teuchos::RCP< Tpetra::CrsGraph< LocalOrdinal, GlobalOrdinal, Node > > create_flat_mp_graph(const Tpetra::CrsGraph< LocalOrdinal, GlobalOrdinal, Node > &graph, Teuchos::RCP< const Tpetra::Map< LocalOrdinal, GlobalOrdinal, Node > > &flat_domain_map, Teuchos::RCP< const Tpetra::Map< LocalOrdinal, GlobalOrdinal, Node > > &flat_range_map, const LocalOrdinal block_size)
void deep_copy(const Stokhos::CrsMatrix< ValueType, DstDevice, Layout > &dst, const Stokhos::CrsMatrix< ValueType, SrcDevice, Layout > &src)
Tpetra::KokkosClassic::DefaultNode::DefaultNodeType Node
Teuchos::RCP< Tpetra::Map< LocalOrdinal, GlobalOrdinal, Node > > create_flat_map(const Tpetra::Map< LocalOrdinal, GlobalOrdinal, Node > &map, const LocalOrdinal block_size)
Stokhos::CrsMatrix< ValueType, Device, Layout >::HostMirror create_mirror_view(const Stokhos::CrsMatrix< ValueType, Device, Layout > &A)