Amesos2 - Direct Sparse Solver Interfaces  Version of the Day
Amesos2_Tacho_def.hpp
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 Sivasankaran Rajamanickam (srajama@sandia.gov)
39 //
40 // ***********************************************************************
41 //
42 // @HEADER
43 
44 #ifndef AMESOS2_TACHO_DEF_HPP
45 #define AMESOS2_TACHO_DEF_HPP
46 
47 #include <Teuchos_Tuple.hpp>
48 #include <Teuchos_ParameterList.hpp>
49 #include <Teuchos_StandardParameterEntryValidators.hpp>
50 
52 #include "Amesos2_Tacho_decl.hpp"
53 #include "Amesos2_Util.hpp"
54 
55 namespace Amesos2 {
56 
57 template <class Matrix, class Vector>
59  Teuchos::RCP<const Matrix> A,
60  Teuchos::RCP<Vector> X,
61  Teuchos::RCP<const Vector> B )
62  : SolverCore<Amesos2::TachoSolver,Matrix,Vector>(A, X, B)
63  , nzvals_() // initialize to empty arrays
64  , colind_()
65  , rowptr_()
66 {
67 }
68 
69 
70 template <class Matrix, class Vector>
72 {
73 }
74 
75 template <class Matrix, class Vector>
76 std::string
78 {
79  std::ostringstream oss;
80  oss << "Tacho solver interface";
81  return oss.str();
82 }
83 
84 template<class Matrix, class Vector>
85 int
87 {
88  return(0);
89 }
90 
91 template <class Matrix, class Vector>
92 int
94 {
95  int status = 0;
96 
97  size_type_array row_ptr;
98  ordinal_type_array cols;
99 
100  if ( this->root_ ) {
101  if(do_optimization()) {
102  // in the optimized case we read the values directly from the matrix
103  typedef typename MatrixAdapter<Matrix>::spmtx_ptr_t row_ptr_t;
104  typedef typename MatrixAdapter<Matrix>::spmtx_idx_t col_ind_t;
105  row_ptr_t sp_rowptr = this->matrixA_->returnRowPtr();
106  TEUCHOS_TEST_FOR_EXCEPTION(sp_rowptr == nullptr,
107  std::runtime_error, "Amesos2 Runtime Error: sp_rowptr returned null");
108  col_ind_t sp_colind = this->matrixA_->returnColInd();
109  TEUCHOS_TEST_FOR_EXCEPTION(sp_colind == nullptr,
110  std::runtime_error, "Amesos2 Runtime Error: sp_colind returned null");
111 
112  /*
113  A couple of things to resolve/discuss here:
114 
115  (1) Do we want to try and do a direct view when the types match?
116  If we do, then we need something that compiles for non-matching.
117  I think that forces us to have a force cast - something like below.
118 
119  (2) Is this a problem for complex? Basker prevents optimization for
120  complex but I wasn't sure if that necessary.
121 
122  (3) Can I safely read the size and index types directly without using
123  std::remove_pointer to determine the regular type.
124 
125  */
126 
127  if(std::is_same<size_type, typename std::remove_pointer<row_ptr_t>::type>::value) {
128  // This line is used when types match exactly, but we need compilation when they don't
129  // match, hence the cast - not sure if there is a better way to do this.
130  row_ptr = size_type_array((size_type*)sp_rowptr, this->globalNumRows_ + 1);
131  }
132  else {
133  row_ptr = size_type_array("r", this->globalNumRows_ + 1);
134  for(global_size_type n = 0; n < this->globalNumRows_ + 1; ++n) {
135  row_ptr(n) = static_cast<size_type>(sp_rowptr[n]);
136  }
137  }
138 
139  if(std::is_same<ordinal_type, typename std::remove_pointer<col_ind_t>::type>::value) {
140  // cast is so that things compile when this line is not used - same issues as above.
141  cols = ordinal_type_array((ordinal_type*)sp_colind, this->globalNumNonZeros_);
142  }
143  else {
144  cols = ordinal_type_array("c", this->globalNumNonZeros_);
145  for(global_size_type n = 0; n < this->globalNumNonZeros_; ++n) {
146  cols(n) = static_cast<ordinal_type>(sp_colind[n]);
147  }
148  }
149  }
150  else
151  {
152  // Non optimized case used the arrays set up in loadA_impl
153  row_ptr = size_type_array(this->rowptr_.getRawPtr(), this->globalNumRows_ + 1);
154  cols = ordinal_type_array(this->colind_.getRawPtr(), this->globalNumNonZeros_);
155  }
156 
157  // TODO: Confirm param options
158  // data_.solver.setMaxNumberOfSuperblocks(data_.max_num_superblocks);
159  data_.solver.analyze(this->globalNumCols_, row_ptr, cols);
160  }
161 
162  return status;
163 }
164 
165 
166 template <class Matrix, class Vector>
167 int
169 {
170  int status = 0;
171 
172  if ( this->root_ ) {
173  value_type_array values;
174 
175  if(do_optimization()) {
176  // in the optimized case we read the values directly from the matrix
177  typename MatrixAdapter<Matrix>::spmtx_vals_t sp_values = this->matrixA_->returnValues();
178  TEUCHOS_TEST_FOR_EXCEPTION(sp_values == nullptr,
179  std::runtime_error, "Amesos2 Runtime Error: sp_values returned null");
180  // this type should always be ok for float/double because Tacho solver
181  // is templated to value_type to guarantee a match here.
182  values = value_type_array(sp_values, this->globalNumNonZeros_);
183  }
184  else
185  {
186  // Non optimized case used the arrays set up in loadA_impl
187  values = value_type_array(this->nzvals_.getRawPtr(), this->globalNumNonZeros_);
188  }
189 
190  data_.solver.factorize(values);
191  }
192 
193  return status;
194 }
195 
196 template <class Matrix, class Vector>
197 int
199  const Teuchos::Ptr<const MultiVecAdapter<Vector> > B) const
200 {
201  using Teuchos::as;
202 
203  const global_size_type ld_rhs = this->root_ ? X->getGlobalLength() : 0;
204  const size_t nrhs = X->getGlobalNumVectors();
205 
206  const size_t val_store_size = as<size_t>(ld_rhs * nrhs);
207  Teuchos::Array<tacho_type> xValues(val_store_size);
208  Teuchos::Array<tacho_type> bValues(val_store_size);
209 
210  { // Get values from RHS B
211 #ifdef HAVE_AMESOS2_TIMERS
212  Teuchos::TimeMonitor mvConvTimer(this->timers_.vecConvTime_);
213  Teuchos::TimeMonitor redistTimer(this->timers_.vecRedistTime_);
214 #endif
216  tacho_type>::do_get(B, bValues(),
217  as<size_t>(ld_rhs),
218  ROOTED, this->rowIndexBase_);
219  }
220 
221  int ierr = 0; // returned error code
222 
223  if ( this->root_ ) { // Do solve!
224 #ifdef HAVE_AMESOS2_TIMER
225  Teuchos::TimeMonitor solveTimer(this->timers_.solveTime_);
226 #endif
227  // Bump up the workspace size if needed
228  if (workspace_.extent(0) < this->globalNumRows_ || workspace_.extent(1) < nrhs) {
229  workspace_ = solve_array_t("t", this->globalNumRows_, nrhs);
230  }
231 
232  solve_array_t x(xValues.getRawPtr(), this->globalNumRows_, nrhs);
233  solve_array_t b(bValues.getRawPtr(), this->globalNumRows_, nrhs);
234 
235  data_.solver.solve(x, b, workspace_);
236 
237  int status = 0; // TODO: determine what error handling will be
238  if(status != 0) {
239  ierr = status;
240  }
241  }
242 
243  /* All processes should have the same error code */
244  Teuchos::broadcast(*(this->getComm()), 0, &ierr);
245 
246  TEUCHOS_TEST_FOR_EXCEPTION( ierr != 0, std::runtime_error,
247  "tacho_solve has error code: " << ierr );
248 
249  /* Update X's global values */
250  {
251 #ifdef HAVE_AMESOS2_TIMERS
252  Teuchos::TimeMonitor redistTimer(this->timers_.vecRedistTime_);
253 #endif
254 
256  MultiVecAdapter<Vector>,tacho_type>::do_put(X, xValues(),
257  as<size_t>(ld_rhs),
258  ROOTED, this->rowIndexBase_);
259  }
260 
261  return(ierr);
262 }
263 
264 
265 template <class Matrix, class Vector>
266 bool
268 {
269  // Tacho can only apply the solve routines to square matrices
270  return( this->matrixA_->getGlobalNumRows() == this->matrixA_->getGlobalNumCols() );
271 }
272 
273 
274 template <class Matrix, class Vector>
275 void
276 TachoSolver<Matrix,Vector>::setParameters_impl(const Teuchos::RCP<Teuchos::ParameterList> & parameterList )
277 {
278  RCP<const Teuchos::ParameterList> valid_params = getValidParameters_impl();
279 
280  // TODO: Confirm param options
281  // data_.num_kokkos_threads = parameterList->get<int>("kokkos-threads", 1);
282  // data_.max_num_superblocks = parameterList->get<int>("max-num-superblocks", 4);
283 }
284 
285 
286 template <class Matrix, class Vector>
287 Teuchos::RCP<const Teuchos::ParameterList>
289 {
290  static Teuchos::RCP<const Teuchos::ParameterList> valid_params;
291 
292  if( is_null(valid_params) ){
293  Teuchos::RCP<Teuchos::ParameterList> pl = Teuchos::parameterList();
294 
295  // TODO: Confirm param options
296  // pl->set("kokkos-threads", 1, "Number of threads");
297  // pl->set("max-num-superblocks", 4, "Max number of superblocks");
298 
299  valid_params = pl;
300  }
301 
302  return valid_params;
303 }
304 
305 template <class Matrix, class Vector>
306 bool
308  return (this->root_ && (this->matrixA_->getComm()->getSize() == 1));
309 }
310 
311 template <class Matrix, class Vector>
312 bool
314 {
315  if(current_phase == SOLVE) {
316  return(false);
317  }
318 
319  if(!do_optimization()) {
320 #ifdef HAVE_AMESOS2_TIMERS
321  Teuchos::TimeMonitor convTimer(this->timers_.mtxConvTime_);
322 #endif
323 
324  // Only the root image needs storage allocated
325  if( this->root_ ) {
326  nzvals_.resize(this->globalNumNonZeros_);
327  colind_.resize(this->globalNumNonZeros_);
328  rowptr_.resize(this->globalNumRows_ + 1);
329  }
330 
331  size_type nnz_ret = 0;
332  {
333  #ifdef HAVE_AMESOS2_TIMERS
334  Teuchos::TimeMonitor mtxRedistTimer( this->timers_.mtxRedistTime_ );
335  #endif
336 
337  TEUCHOS_TEST_FOR_EXCEPTION( this->rowIndexBase_ != this->columnIndexBase_,
338  std::runtime_error,
339  "Row and column maps have different indexbase ");
340 
342  MatrixAdapter<Matrix>,tacho_type,ordinal_type,size_type>::do_get(
343  this->matrixA_.ptr(),
344  nzvals_(), colind_(),
345  rowptr_(), nnz_ret,
346  ROOTED, ARBITRARY,
347  this->columnIndexBase_);
348  }
349  }
350 
351  return true;
352 }
353 
354 
355 template<class Matrix, class Vector>
356 const char* TachoSolver<Matrix,Vector>::name = "Tacho";
357 
358 
359 } // end namespace Amesos2
360 
361 #endif // AMESOS2_TACHO_DEF_HPP
Amesos2::SolverCore: A templated interface for interaction with third-party direct sparse solvers...
Definition: Amesos2_SolverCore_decl.hpp:105
EPhase
Used to indicate a phase in the direct solution.
Definition: Amesos2_TypeDecl.hpp:65
Amesos2 interface to the Tacho package.
Definition: Amesos2_Tacho_decl.hpp:65
Similar to get_ccs_helper , but used to get a CRS representation of the given matrix.
Definition: Amesos2_Util.hpp:665
int symbolicFactorization_impl()
Perform symbolic factorization of the matrix using Tacho.
Definition: Amesos2_Tacho_def.hpp:93
std::string description() const
Returns a short description of this Solver.
Definition: Amesos2_Tacho_def.hpp:77
Helper class for getting 1-D copies of multivectors.
Definition: Amesos2_MultiVecAdapter_decl.hpp:266
Utility functions for Amesos2.
bool matrixShapeOK_impl() const
Determines whether the shape of the matrix is OK for this solver.
Definition: Amesos2_Tacho_def.hpp:267
int numericFactorization_impl()
Tacho specific numeric factorization.
Definition: Amesos2_Tacho_def.hpp:168
int preOrdering_impl()
Performs pre-ordering on the matrix to increase efficiency.
Definition: Amesos2_Tacho_def.hpp:86
A Matrix adapter interface for Amesos2.
Definition: Amesos2_MatrixAdapter_decl.hpp:76
Teuchos::RCP< const Teuchos::ParameterList > getValidParameters_impl() const
Definition: Amesos2_Tacho_def.hpp:288
int solve_impl(const Teuchos::Ptr< MultiVecAdapter< Vector > > X, const Teuchos::Ptr< const MultiVecAdapter< Vector > > B) const
Tacho specific solve.
Definition: Amesos2_Tacho_def.hpp:198
TachoSolver(Teuchos::RCP< const Matrix > A, Teuchos::RCP< Vector > X, Teuchos::RCP< const Vector > B)
Initialize from Teuchos::RCP.
Definition: Amesos2_Tacho_def.hpp:58
bool loadA_impl(EPhase current_phase)
Reads matrix data into internal structures.
Definition: Amesos2_Tacho_def.hpp:313
bool do_optimization() const
can we optimize size_type and ordinal_type for straight pass through
Definition: Amesos2_Tacho_def.hpp:307
Helper class for putting 1-D data arrays into multivectors.
Definition: Amesos2_MultiVecAdapter_decl.hpp:322
A templated MultiVector class adapter for Amesos2.
Definition: Amesos2_MultiVecAdapter_decl.hpp:176
~TachoSolver()
Destructor.
Definition: Amesos2_Tacho_def.hpp:71