Amesos2 - Direct Sparse Solver Interfaces  Version of the Day
Amesos2_EpetraMultiVecAdapter_def.hpp
Go to the documentation of this file.
1 // @HEADER
2 //
3 // ***********************************************************************
4 //
5 // Amesos2: Templated Direct Sparse Solver Package
6 // Copyright 2011 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 Michael A. Heroux (maherou@sandia.gov)
39 //
40 // ***********************************************************************
41 //
42 // @HEADER
43 
53 #ifndef AMESOS2_EPETRA_MULTIVEC_ADAPTER_DEF_HPP
54 #define AMESOS2_EPETRA_MULTIVEC_ADAPTER_DEF_HPP
55 
56 #include <Teuchos_as.hpp>
57 
58 #include <Epetra_SerialComm.h>
59 #ifdef HAVE_MPI
60 #include <Epetra_MpiComm.h>
61 #endif
62 #include <Epetra_LocalMap.h>
63 #include <Epetra_Import.h>
64 #include <Epetra_Export.h>
65 
67 #include "Amesos2_Util.hpp"
68 
69 namespace Amesos2 {
70 
72  : mv_(adapter.mv_)
73  , mv_map_(adapter.mv_map_)
74 { }
75 
76 MultiVecAdapter<Epetra_MultiVector>::MultiVecAdapter(const Teuchos::RCP<multivec_t>& m)
77  : mv_(m)
78 {
79  mv_map_ = Teuchos::rcpFromRef(mv_->Map());
80 }
81 
82 
84 {
85  return !mv_->DistributedGlobal();
86 }
87 
89 {
90  return mv_->DistributedGlobal();
91 }
92 
93 
94 const Teuchos::RCP<const Teuchos::Comm<int> >
96 {
97  return Util::to_teuchos_comm(Teuchos::rcpFromRef(mv_->Comm()));
98 }
99 
100 
102 {
103  return Teuchos::as<size_t>(mv_->MyLength());
104 }
105 
106 
108 {
109  return Teuchos::as<size_t>(mv_->NumVectors());
110 }
111 
112 
115 {
116  return Teuchos::as<global_size_t>(mv_->GlobalLength());
117 }
118 
119 
121 {
122  return Teuchos::as<size_t>(mv_->NumVectors());
123 }
124 
125 
127 {
128  return Teuchos::as<size_t>(mv_->Stride());
129 }
130 
131 
133 {
134  return mv_->ConstantStride();
135 }
136 
137 
138 Teuchos::RCP<const Tpetra::Vector<MultiVecAdapter<Epetra_MultiVector>::scalar_t,
143 {
144  using Teuchos::RCP;
145  using Teuchos::rcp;
146  using Teuchos::ArrayRCP;
147  using Tpetra::MultiVector;
148 
149  typedef scalar_t st;
150  typedef local_ordinal_t lot;
151  typedef global_ordinal_t got;
152  typedef node_t nt;
153 
154  RCP<MultiVector<st,lot,got,nt> > vector = rcp(new MultiVector<st,lot,got,nt>(this->getMap(),1));
155 
156  // Copy vector contents into Tpetra multi-vector
157  ArrayRCP<st> it = vector->getDataNonConst(0);
158  double* vector_data = mv_->operator[](Teuchos::as<int>(j)); // values from j^th vector
159  Tpetra::global_size_t size = vector->getGlobalLength();
160 
161  for( Tpetra::global_size_t i = 0; i < size; ++i ){
162  *it = vector_data[i];
163  }
164 
165  return vector->getVector(j);
166 }
167 
168 
169 // Implementation is essentially the same as getVector()
170 Teuchos::RCP<Tpetra::Vector<MultiVecAdapter<Epetra_MultiVector>::scalar_t,
175 {
176  using Teuchos::RCP;
177  using Teuchos::rcp;
178  using Teuchos::ArrayRCP;
179  using Tpetra::MultiVector;
180 
181  typedef scalar_t st;
182  typedef local_ordinal_t lot;
183  typedef global_ordinal_t got;
184  typedef node_t nt;
185 
186  RCP<MultiVector<st,lot,got,nt> > vector = rcp(new MultiVector<st,lot,got,nt>(this->getMap(),1));
187 
188  // Copy vector contents into Tpetra multi-vector
189  ArrayRCP<st> it = vector->getDataNonConst(0);
190  double* vector_data = mv_->operator[](Teuchos::as<int>(j)); // values from j^th vector
191  Tpetra::global_size_t size = vector->getGlobalLength();
192 
193  for( Tpetra::global_size_t i = 0; i < size; ++i ){
194  *it = vector_data[i];
195  }
196 
197  return vector->getVectorNonConst(j);
198 }
199 
200 
202 {
203  TEUCHOS_TEST_FOR_EXCEPTION( this->getGlobalNumVectors() != 1,
204  std::invalid_argument,
205  "Amesos2_EpetraMultiVectorAdapter: getMVPointer_impl should only be called for case with a single vector and single MPI process" );
206 
207  double* vector_data = mv_->operator[](Teuchos::as<int>(0)); // raw pointer to data from 0^th vector
208  return vector_data;
209 }
210 
211 
213  const Teuchos::ArrayView<MultiVecAdapter<Epetra_MultiVector>::scalar_t>& av,
214  size_t lda,
215  Teuchos::Ptr<
219  EDistribution /* distribution */) const
220 {
221  using Teuchos::rcpFromPtr;
222  using Teuchos::as;
223 
224  const size_t num_vecs = getGlobalNumVectors();
225 
226 #ifdef HAVE_AMESOS2_DEBUG
227  const size_t requested_vector_length = distribution_map->getNodeNumElements();
228  TEUCHOS_TEST_FOR_EXCEPTION( lda < requested_vector_length,
229  std::invalid_argument,
230  "Given stride is not large enough for local vector length" );
231  TEUCHOS_TEST_FOR_EXCEPTION( as<size_t>(av.size()) < (num_vecs-1) * lda + requested_vector_length,
232  std::invalid_argument,
233  "MultiVector storage not large enough given leading dimension "
234  "and number of vectors" );
235 #endif
236 
237  // Optimization for ROOTED and single MPI process
238  if ( num_vecs == 1 && mv_->Comm().MyPID() == 0 && mv_->Comm().NumProc() == 1 ) {
239  mv_->ExtractCopy(av.getRawPtr(), lda);
240  }
241  else {
242  Epetra_Map e_dist_map
243  = *Util::tpetra_map_to_epetra_map<local_ordinal_t,
244  global_ordinal_t,
245  global_size_t,
246  node_t>(*distribution_map);
247 
248  multivec_t redist_mv(e_dist_map, as<int>(num_vecs));
249  const Epetra_Import importer(e_dist_map, *mv_map_); // Note, target/source order is reversed in Tpetra
250  redist_mv.Import(*mv_, importer, Insert);
251 
252  // Finally, do copy
253  redist_mv.ExtractCopy(av.getRawPtr(), lda);
254  }
255 
256 }
257 
258 
259 Teuchos::ArrayRCP<MultiVecAdapter<Epetra_MultiVector>::scalar_t>
261 {
262  ((void) local);
263  // TEUCHOS_TEST_FOR_EXCEPTION( !this->isConstantStride(),
264  // std::logic_error,
265  // "get1dViewNonConst() : can only get 1d view if stride is constant");
266 
267  // if( local ){
268  // TEUCHOS_TEST_FOR_EXCEPTION(
269  // true,
270  // std::logic_error,
271  // "Amesos2::MultiVecAdapter<Epetra_MultiVector> : 1D views not yet supported for local-local Epetra multi-vectors");
272 
273  // // localize();
274  // // /* Use the global element list returned by
275  // // * mv_->getMap()->getNodeElementList() to get a subCopy of mv_ which we
276  // // * assign to l_l_mv_, then return get1dViewNonConst() of l_l_mv_
277  // // */
278  // // l_l_mv_ = Teuchos::null;
279 
280  // // Teuchos::Array<GlobalOrdinal> nodeElements_go(mv_->Map().NumMyElements());
281  // // mv_->Map().MyGlobalElements(nodeElements_go.getRawPtr());
282  // // Teuchos::Array<size_t> nodeElements_st(nodeElements_go.size());
283 
284  // // // Convert the node element to a list of size_t type objects
285  // // typename Teuchos::ArrayView<const GlobalOrdinal>::iterator it_go;
286  // // Teuchos::Array<size_t>::iterator it_st = nodeElements_st.begin();
287  // // for( it_go = nodeElements_go.begin(); it_go != nodeElements_go.end(); ++it_go ){
288  // // *(it_st++) = Teuchos::as<size_t>(*it_go);
289  // // }
290 
291  // // l_l_mv_ = l_mv_->subViewNonConst(nodeElements_st);
292 
293  // // return(l_l_mv_->get1dViewNonConst());
294  // } else {
295  // scalar_t* values;
296  // int lda;
297 
298  // if( !isLocal() ){
299  // this->localize();
300  // l_mv_->ExtractView(&values, &lda);
301  // } else {
302  // mv_->ExtractView(&values, &lda);
303  // }
304 
305  // TEUCHOS_TEST_FOR_EXCEPTION( lda != Teuchos::as<int>(this->getStride()),
306  // std::logic_error,
307  // "Stride reported during extraction not consistent with what multivector reports");
308 
309  // return Teuchos::arcp(values,0,lda*this->getGlobalNumVectors(),false);
310  // }
311  return Teuchos::null;
312 }
313 
314 
315 void
317  const Teuchos::ArrayView<const MultiVecAdapter<Epetra_MultiVector>::scalar_t>& new_data,
318  size_t lda,
319  Teuchos::Ptr<
323  EDistribution /* distribution */)
324 {
325  using Teuchos::rcpFromPtr;
326  using Teuchos::as;
327 
328  const size_t num_vecs = getGlobalNumVectors();
329  // TODO: check that the following const_cast is safe
330  double* data_ptr = const_cast<double*>(new_data.getRawPtr());
331 
332  // Optimization for ROOTED and single MPI process
333  if ( num_vecs == 1 && mv_->Comm().MyPID() == 0 && mv_->Comm().NumProc() == 1 ) {
334  // First, functioning impl
335  //const multivec_t source_mv(Copy, *mv_map_, data_ptr, as<int>(lda), as<int>(num_vecs));
336  //const Epetra_Import importer(*mv_map_, *mv_map_); //trivial - map does not change
337  //mv_->Import(source_mv, importer, Insert);
338  // Element-wise copy rather than using importer
339  auto vector = mv_->Pointers();
340  for ( size_t i = 0; i < lda; ++i ) {
341  vector[0][i] = data_ptr[i];
342  }
343  }
344  else {
345  const Epetra_BlockMap e_source_map
346  = *Util::tpetra_map_to_epetra_map<local_ordinal_t,global_ordinal_t,global_size_t,node_t>(*source_map);
347  const multivec_t source_mv(Copy, e_source_map, data_ptr, as<int>(lda), as<int>(num_vecs));
348  const Epetra_Import importer(*mv_map_, e_source_map);
349 
350  mv_->Import(source_mv, importer, Insert);
351  }
352 }
353 
354 
356 {
357  std::ostringstream oss;
358  oss << "Amesos2 adapter wrapping: Epetra_MultiVector";
359  return oss.str();
360 }
361 
362 
364  Teuchos::FancyOStream& os,
365  const Teuchos::EVerbosityLevel verbLevel) const
366 {
367  // TODO: implement!
368  if(verbLevel != Teuchos::VERB_NONE)
369  {
370  os << "TODO: implement! ";
371  }
372 }
373 
374 
375 Teuchos::RCP<const Tpetra::Map<MultiVecAdapter<Epetra_MultiVector>::local_ordinal_t,
379 {
380  return Util::epetra_map_to_tpetra_map<local_ordinal_t,global_ordinal_t,global_size_t,node_t>(*mv_map_);
381 }
382 
383 
385 = "Amesos2 adapter for Epetra_MultiVector";
386 
387 
388 } // end namespace Amesos2
389 
390 #endif // AMESOS2_EPETRA_MULTIVEC_ADAPTER_DEF_HPP
Utility functions for Amesos2.
const RCP< const Teuchos::Comm< int > > to_teuchos_comm(RCP< const Epetra_Comm > c)
Transform an Epetra_Comm object into a Teuchos::Comm object.
Amesos2::MultiVecAdapter specialization for the Epetra_MultiVector class.
RCP< Epetra_Map > tpetra_map_to_epetra_map(const Tpetra::Map< LO, GO, Node > &map)
Transform a Tpetra::Map object into an Epetra_Map.
Definition: Amesos2_Util.hpp:766
EDistribution
Definition: Amesos2_TypeDecl.hpp:123
A templated MultiVector class adapter for Amesos2.
Definition: Amesos2_MultiVecAdapter_decl.hpp:176