Amesos2 - Direct Sparse Solver Interfaces  Version of the Day
Amesos2_SolverCore_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_SOLVERCORE_DEF_HPP
54 #define AMESOS2_SOLVERCORE_DEF_HPP
55 
56 #include "Kokkos_ArithTraits.hpp"
57 
58 #include "Amesos2_MatrixAdapter_def.hpp"
59 #include "Amesos2_MultiVecAdapter_def.hpp"
60 
61 #include "Amesos2_Util.hpp"
62 
63 #include "KokkosSparse_spmv.hpp"
64 #include "KokkosBlas.hpp"
65 
66 namespace Amesos2 {
67 
68 
69 template <template <class,class> class ConcreteSolver, class Matrix, class Vector >
71  Teuchos::RCP<const Matrix> A,
72  Teuchos::RCP<Vector> X,
73  Teuchos::RCP<const Vector> B )
74  : matrixA_(createConstMatrixAdapter<Matrix>(A))
75  , multiVecX_(X) // may be null
76  , multiVecB_(B) // may be null
77  , globalNumRows_(matrixA_->getGlobalNumRows())
78  , globalNumCols_(matrixA_->getGlobalNumCols())
79  , globalNumNonZeros_(matrixA_->getGlobalNNZ())
80  , rowIndexBase_(matrixA_->getRowIndexBase())
81  , columnIndexBase_(matrixA_->getColumnIndexBase())
82  , rank_(Teuchos::rank(*this->getComm()))
83  , root_(rank_ == 0)
84  , nprocs_(Teuchos::size(*this->getComm()))
85 {
86  TEUCHOS_TEST_FOR_EXCEPTION(
87  !matrixShapeOK(),
88  std::invalid_argument,
89  "Matrix shape inappropriate for this solver");
90 }
91 
92 
94 template <template <class,class> class ConcreteSolver, class Matrix, class Vector >
96 {
97  // Nothing
98 }
99 
100 
101 template <template <class,class> class ConcreteSolver, class Matrix, class Vector >
104 {
105 #ifdef HAVE_AMESOS2_TIMERS
106  Teuchos::TimeMonitor LocalTimer1(timers_.totalTime_);
107 #endif
108 
109  loadA(PREORDERING);
110 
111  int error_code = static_cast<solver_type*>(this)->preOrdering_impl();
112  if (error_code == EXIT_SUCCESS){
113  ++status_.numPreOrder_;
114  status_.last_phase_ = PREORDERING;
115  }
116 
117  return *this;
118 }
119 
120 
121 template <template <class,class> class ConcreteSolver, class Matrix, class Vector >
124 {
125 #ifdef HAVE_AMESOS2_TIMERS
126  Teuchos::TimeMonitor LocalTimer1(timers_.totalTime_);
127 #endif
128 
129  if( !status_.preOrderingDone() ){
130  preOrdering();
131  if( !matrix_loaded_ ) loadA(SYMBFACT);
132  } else {
133  loadA(SYMBFACT);
134  }
135 
136  int error_code = static_cast<solver_type*>(this)->symbolicFactorization_impl();
137  if (error_code == EXIT_SUCCESS){
138  ++status_.numSymbolicFact_;
139  status_.last_phase_ = SYMBFACT;
140  }
141 
142  return *this;
143 }
144 
145 
146 template <template <class,class> class ConcreteSolver, class Matrix, class Vector >
149 {
150 #ifdef HAVE_AMESOS2_TIMERS
151  Teuchos::TimeMonitor LocalTimer1(timers_.totalTime_);
152 #endif
153 
154  if( !status_.symbolicFactorizationDone() ){
155  symbolicFactorization();
156  if( !matrix_loaded_ ) loadA(NUMFACT);
157  } else {
158  loadA(NUMFACT);
159  }
160 
161  int error_code = static_cast<solver_type*>(this)->numericFactorization_impl();
162  if (error_code == EXIT_SUCCESS){
163  ++status_.numNumericFact_;
164  status_.last_phase_ = NUMFACT;
165  }
166 
167  return *this;
168 }
169 
170 
171 template <template <class,class> class ConcreteSolver, class Matrix, class Vector >
172 void
174 {
175  solve(multiVecX_.ptr(), multiVecB_.ptr());
176 }
177 
178 template <template <class,class> class ConcreteSolver, class Matrix, class Vector >
179 void
181  const Teuchos::Ptr<const Vector> B) const
182 {
183 #ifdef HAVE_AMESOS2_TIMERS
184  Teuchos::TimeMonitor LocalTimer1(timers_.totalTime_);
185 #endif
186 
187  X.assert_not_null();
188  B.assert_not_null();
189 
190  if (control_.useIterRefine_) {
191  solve_ir(X, B, control_.maxNumIterRefines_, control_.verboseIterRefine_);
192  return;
193  }
194 
195  const Teuchos::RCP<MultiVecAdapter<Vector> > x =
196  createMultiVecAdapter<Vector>(Teuchos::rcpFromPtr(X));
197  const Teuchos::RCP<const MultiVecAdapter<Vector> > b =
198  createConstMultiVecAdapter<Vector>(Teuchos::rcpFromPtr(B));
199 
200 #ifdef HAVE_AMESOS2_DEBUG
201  // Check some required properties of X and B
202  TEUCHOS_TEST_FOR_EXCEPTION
203  (x->getGlobalLength() != matrixA_->getGlobalNumCols(),
204  std::invalid_argument,
205  "MultiVector X must have length equal to the number of "
206  "global columns in A. X->getGlobalLength() = "
207  << x->getGlobalLength() << " != A->getGlobalNumCols() = "
208  << matrixA_->getGlobalNumCols() << ".");
209 
210  TEUCHOS_TEST_FOR_EXCEPTION(b->getGlobalLength() != matrixA_->getGlobalNumRows(),
211  std::invalid_argument,
212  "MultiVector B must have length equal to the number of "
213  "global rows in A");
214 
215  TEUCHOS_TEST_FOR_EXCEPTION(x->getGlobalNumVectors() != b->getGlobalNumVectors(),
216  std::invalid_argument,
217  "X and B MultiVectors must have the same number of vectors");
218 #endif // HAVE_AMESOS2_DEBUG
219 
220  if( !status_.numericFactorizationDone() ){
221  // This casting-away of constness is probably OK because this
222  // function is meant to be "logically const"
223  const_cast<type&>(*this).numericFactorization();
224  }
225 
226  int error_code = static_cast<const solver_type*>(this)->solve_impl(Teuchos::outArg(*x), Teuchos::ptrInArg(*b));
227  if (error_code == EXIT_SUCCESS){
228  ++status_.numSolve_;
229  status_.last_phase_ = SOLVE;
230  }
231 }
232 
233 template <template <class,class> class ConcreteSolver, class Matrix, class Vector >
234 void
235 SolverCore<ConcreteSolver,Matrix,Vector>::solve(Vector* X, const Vector* B) const
236 {
237  solve(Teuchos::ptr(X), Teuchos::ptr(B));
238 }
239 
240 
241 template <template <class,class> class ConcreteSolver, class Matrix, class Vector >
242 int
243 SolverCore<ConcreteSolver,Matrix,Vector>::solve_ir(const int maxNumIters, const bool verbose)
244 {
245  return solve_ir(multiVecX_.ptr(), multiVecB_.ptr(), maxNumIters, verbose);
246 }
247 
248 template <template <class,class> class ConcreteSolver, class Matrix, class Vector >
249 int
250 SolverCore<ConcreteSolver,Matrix,Vector>::solve_ir(Vector* X, const Vector* B, const int maxNumIters, const bool verbose) const
251 {
252  return solve_ir(Teuchos::ptr(X), Teuchos::ptr(B), maxNumIters, verbose);
253 }
254 
255 template <template <class,class> class ConcreteSolver, class Matrix, class Vector >
256 int
257 SolverCore<ConcreteSolver,Matrix,Vector>::solve_ir(const Teuchos::Ptr< Vector> x,
258  const Teuchos::Ptr<const Vector> b,
259  const int maxNumIters,
260  const bool verbose) const
261 {
262  using KAT = Kokkos::ArithTraits<scalar_type>;
263  using impl_scalar_type = typename KAT::val_type;
264  using magni_type = typename KAT::mag_type;
265  using host_execution_space = Kokkos::DefaultHostExecutionSpace;
266  using host_crsmat_t = KokkosSparse::CrsMatrix<impl_scalar_type, int, host_execution_space, void, int>;
267  using host_graph_t = typename host_crsmat_t::StaticCrsGraphType;
268  using host_values_t = typename host_crsmat_t::values_type::non_const_type;
269  using host_row_map_t = typename host_graph_t::row_map_type::non_const_type;
270  using host_colinds_t = typename host_graph_t::entries_type::non_const_type;
271  using host_mvector_t = Kokkos::View<impl_scalar_type **, Kokkos::LayoutLeft, host_execution_space>;
272  using host_vector_t = Kokkos::View<impl_scalar_type *, Kokkos::LayoutLeft, host_execution_space>;
273  using host_magni_view = Kokkos::View<magni_type *, Kokkos::LayoutLeft, host_execution_space>;
274 
275  const impl_scalar_type one(1.0);
276  const impl_scalar_type mone = impl_scalar_type(-one);
277  const magni_type eps = KAT::eps ();
278 
279  // get data needed for IR
280  using MVAdapter = MultiVecAdapter<Vector>;
281  Teuchos::RCP< MVAdapter> X = createMultiVecAdapter<Vector>(Teuchos::rcpFromPtr(x));
282  Teuchos::RCP<const MVAdapter> B = createConstMultiVecAdapter<Vector>(Teuchos::rcpFromPtr(b));
283 
284  auto r_ = B->clone();
285  auto e_ = X->clone();
286  auto r = r_.ptr();
287  auto e = e_.ptr();
288  Teuchos::RCP< MVAdapter> R = createMultiVecAdapter<Vector>(Teuchos::rcpFromPtr(r));
289  Teuchos::RCP< MVAdapter> E = createMultiVecAdapter<Vector>(Teuchos::rcpFromPtr(e));
290 
291  const size_t nrhs = X->getGlobalNumVectors();
292  const int nnz = this->matrixA_->getGlobalNNZ();
293  const int nrows = this->matrixA_->getGlobalNumRows();
294 
295  // get local matriix
296  host_crsmat_t crsmat;
297  host_graph_t static_graph;
298  host_row_map_t rowmap_view;
299  host_colinds_t colind_view;
300  host_values_t values_view;
301  if (this->root_) {
302  Kokkos::resize(rowmap_view, 1+nrows);
303  Kokkos::resize(colind_view, nnz);
304  Kokkos::resize(values_view, nnz);
305  } else {
306  Kokkos::resize(rowmap_view, 1);
307  Kokkos::resize(colind_view, 0);
308  Kokkos::resize(values_view, 0);
309  }
310 
311  int nnz_ret = 0;
312  Util::get_crs_helper_kokkos_view<
313  MatrixAdapter<Matrix>, host_values_t, host_colinds_t, host_row_map_t>::do_get(
314  this->matrixA_.ptr(),
315  values_view, colind_view, rowmap_view,
316  nnz_ret, ROOTED, ARBITRARY, this->rowIndexBase_);
317 
318  if (this->root_) {
319  static_graph = host_graph_t(colind_view, rowmap_view);
320  crsmat = host_crsmat_t("CrsMatrix", nrows, values_view, static_graph);
321  }
322 
323  //
324  // ** First Solve **
325  static_cast<const solver_type*>(this)->solve_impl(Teuchos::outArg(*X), Teuchos::ptrInArg(*B));
326 
327 
328  // auxiliary scalar Kokkos views
329  const int ldx = (this->root_ ? X->getGlobalLength() : 0);
330  const int ldb = (this->root_ ? B->getGlobalLength() : 0);
331  const int ldr = (this->root_ ? R->getGlobalLength() : 0);
332  const int lde = (this->root_ ? E->getGlobalLength() : 0);
333  const bool initialize_data = true;
334  const bool not_initialize_data = true;
335  host_mvector_t X_view;
336  host_mvector_t B_view;
337  host_mvector_t R_view;
338  host_mvector_t E_view;
339 
340  global_size_type rowIndexBase = this->rowIndexBase_;
341  auto Xptr = Teuchos::Ptr< MVAdapter>(X.ptr());
342  auto Bptr = Teuchos::Ptr<const MVAdapter>(B.ptr());
343  auto Rptr = Teuchos::Ptr< MVAdapter>(R.ptr());
344  auto Eptr = Teuchos::Ptr< MVAdapter>(E.ptr());
345  Util::get_1d_copy_helper_kokkos_view<MVAdapter, host_mvector_t>::
346  do_get( initialize_data, Xptr, X_view, ldx, CONTIGUOUS_AND_ROOTED, rowIndexBase);
347  Util::get_1d_copy_helper_kokkos_view<MVAdapter, host_mvector_t>::
348  do_get( initialize_data, Bptr, B_view, ldb, CONTIGUOUS_AND_ROOTED, rowIndexBase);
349  Util::get_1d_copy_helper_kokkos_view<MVAdapter, host_mvector_t>::
350  do_get(not_initialize_data, Rptr, R_view, ldr, CONTIGUOUS_AND_ROOTED, rowIndexBase);
351  Util::get_1d_copy_helper_kokkos_view<MVAdapter, host_mvector_t>::
352  do_get(not_initialize_data, Eptr, E_view, lde, CONTIGUOUS_AND_ROOTED, rowIndexBase);
353 
354 
355  host_magni_view x0norms("x0norms", nrhs);
356  host_magni_view bnorms("bnorms", nrhs);
357  host_magni_view enorms("enorms", nrhs);
358  if (this->root_) {
359  // compute initial solution norms (used for stopping criteria)
360  for (size_t j = 0; j < nrhs; j++) {
361  auto x_subview = Kokkos::subview(X_view, Kokkos::ALL(), j);
362  host_vector_t x_1d (const_cast<impl_scalar_type*>(x_subview.data()), x_subview.extent(0));
363  x0norms(j) = KokkosBlas::nrm2(x_1d);
364  }
365  if (verbose) {
366  std::cout << std::endl
367  << " SolverCore :: solve_ir (maxNumIters = " << maxNumIters
368  << ", tol = " << x0norms(0) << " * " << eps << " = " << x0norms(0)*eps
369  << ")" << std::endl;
370  }
371 
372  // compute residual norm
373  if (verbose) {
374  std::cout << " bnorm = ";
375  for (size_t j = 0; j < nrhs; j++) {
376  auto b_subview = Kokkos::subview(B_view, Kokkos::ALL(), j);
377  host_vector_t b_1d (const_cast<impl_scalar_type*>(b_subview.data()), b_subview.extent(0));
378  bnorms(j) = KokkosBlas::nrm2(b_1d);
379  std::cout << bnorms(j) << ", ";
380  }
381  std::cout << std::endl;
382  }
383  }
384 
385 
386  //
387  // ** Iterative Refinement **
388  int numIters = 0;
389  int converged = 0; // 0 = has not converged, 1 = converged
390  for (numIters = 0; numIters < maxNumIters && converged == 0; ++numIters) {
391  // r = b - Ax (on rank-0)
392  if (this->root_) {
393  Kokkos::deep_copy(R_view, B_view);
394  KokkosSparse::spmv("N", mone, crsmat, X_view, one, R_view);
395  Kokkos::fence();
396 
397  if (verbose) {
398  // compute residual norm
399  std::cout << " > " << numIters << " : norm(r,x,e) = ";
400  for (size_t j = 0; j < nrhs; j++) {
401  auto r_subview = Kokkos::subview(R_view, Kokkos::ALL(), j);
402  auto x_subview = Kokkos::subview(X_view, Kokkos::ALL(), j);
403  host_vector_t r_1d (const_cast<impl_scalar_type*>(r_subview.data()), r_subview.extent(0));
404  host_vector_t x_1d (const_cast<impl_scalar_type*>(x_subview.data()), x_subview.extent(0));
405  impl_scalar_type rnorm = KokkosBlas::nrm2(r_1d);
406  impl_scalar_type xnorm = KokkosBlas::nrm2(x_1d);
407  std::cout << rnorm << " -> " << rnorm/bnorms(j) << " " << xnorm << " " << enorms(j) << ", ";
408  }
409  std::cout << std::endl;
410  }
411  }
412 
413  // e = A^{-1} r
414  Util::put_1d_data_helper_kokkos_view<MVAdapter, host_mvector_t>::
415  do_put(Rptr, R_view, ldr, CONTIGUOUS_AND_ROOTED, rowIndexBase);
416  static_cast<const solver_type*>(this)->solve_impl(Teuchos::outArg(*E), Teuchos::ptrInArg(*R));
417  Util::get_1d_copy_helper_kokkos_view<MVAdapter, host_mvector_t>::
418  do_get(initialize_data, Eptr, E_view, lde, CONTIGUOUS_AND_ROOTED, rowIndexBase);
419 
420  // x = x + e (on rank-0)
421  if (this->root_) {
422  KokkosBlas::axpy(one, E_view, X_view);
423 
424  if (numIters < maxNumIters-1) {
425  // compute norm of corrections for "convergence" check
426  converged = 1;
427  for (size_t j = 0; j < nrhs; j++) {
428  auto e_subview = Kokkos::subview(E_view, Kokkos::ALL(), j);
429  host_vector_t e_1d (const_cast<impl_scalar_type*>(e_subview.data()), e_subview.extent(0));
430  enorms(j) = KokkosBlas::nrm2(e_1d);
431  if (enorms(j) > eps * x0norms(j)) {
432  converged = 0;
433  }
434  }
435  if (verbose && converged) {
436  std::cout << " converged " << std::endl;
437  }
438  }
439  }
440 
441  // broadcast "converged"
442  Teuchos::broadcast(*(this->matrixA_->getComm()), 0, &converged);
443  } // end of for-loop for IR iteration
444 
445  if (verbose && this->root_) {
446  // r = b - Ax
447  Kokkos::deep_copy(R_view, B_view);
448  KokkosSparse::spmv("N", mone, crsmat, X_view, one, R_view);
449  Kokkos::fence();
450  std::cout << " > final residual norm = ";
451  for (size_t j = 0; j < nrhs; j++) {
452  auto r_subview = Kokkos::subview(R_view, Kokkos::ALL(), j);
453  host_vector_t r_1d (const_cast<impl_scalar_type*>(r_subview.data()), r_subview.extent(0));
454  scalar_type rnorm = KokkosBlas::nrm2(r_1d);
455  std::cout << rnorm << " -> " << rnorm/bnorms(j) << ", ";
456  }
457  std::cout << std::endl << std::endl;
458  }
459 
460  // put X for output
461  Util::put_1d_data_helper_kokkos_view<MVAdapter, host_mvector_t>::
462  do_put(Xptr, X_view, ldx, CONTIGUOUS_AND_ROOTED, rowIndexBase);
463 
464  return numIters;
465 }
466 
467 template <template <class,class> class ConcreteSolver, class Matrix, class Vector >
468 bool
470 {
471 #ifdef HAVE_AMESOS2_TIMERS
472  Teuchos::TimeMonitor LocalTimer1(timers_.totalTime_);
473 #endif
474 
475  return( static_cast<solver_type*>(this)->matrixShapeOK_impl() );
476 }
477 
478  // The RCP should probably be to a const Matrix, but that throws a
479  // wrench in some of the traits mechanisms that aren't expecting
480  // const types
481 template <template <class,class> class ConcreteSolver, class Matrix, class Vector >
482 void
483 SolverCore<ConcreteSolver,Matrix,Vector>::setA( const Teuchos::RCP<const Matrix> a,
484  EPhase keep_phase )
485 {
486  matrixA_ = createConstMatrixAdapter(a);
487 
488 #ifdef HAVE_AMESOS2_DEBUG
489  TEUCHOS_TEST_FOR_EXCEPTION( (keep_phase != CLEAN) &&
490  (globalNumRows_ != matrixA_->getGlobalNumRows() ||
491  globalNumCols_ != matrixA_->getGlobalNumCols()),
492  std::invalid_argument,
493  "Dimensions of new matrix be the same as the old matrix if "
494  "keeping any solver phase" );
495 #endif
496 
497  status_.last_phase_ = keep_phase;
498 
499  // Reset phase counters
500  switch( status_.last_phase_ ){
501  case CLEAN:
502  status_.numPreOrder_ = 0;
503  // Intentional fallthrough.
504  case PREORDERING:
505  status_.numSymbolicFact_ = 0;
506  // Intentional fallthrough.
507  case SYMBFACT:
508  status_.numNumericFact_ = 0;
509  // Intentional fallthrough.
510  case NUMFACT: // probably won't ever happen by itself
511  status_.numSolve_ = 0;
512  // Intentional fallthrough.
513  case SOLVE: // probably won't ever happen
514  break;
515  }
516 
517  // Re-get the matrix dimensions in case they have changed
518  globalNumNonZeros_ = matrixA_->getGlobalNNZ();
519  globalNumCols_ = matrixA_->getGlobalNumCols();
520  globalNumRows_ = matrixA_->getGlobalNumRows();
521 }
522 
523 
524 template <template <class,class> class ConcreteSolver, class Matrix, class Vector >
527  const Teuchos::RCP<Teuchos::ParameterList> & parameterList )
528 {
529 #ifdef HAVE_AMESOS2_TIMERS
530  Teuchos::TimeMonitor LocalTimer1(timers_.totalTime_);
531 #endif
532 
533  if( parameterList->name() == "Amesos2" ){
534  // First, validate the parameterList
535  Teuchos::RCP<const Teuchos::ParameterList> valid_params = getValidParameters();
536  parameterList->validateParameters(*valid_params);
537 
538  // Do everything here that is for generic status and control parameters
539  control_.setControlParameters(parameterList);
540 
541  // Finally, hook to the implementation's parameter list parser
542  // First check if there is a dedicated sublist for this solver and use that if there is
543  if( parameterList->isSublist(name()) ){
544  // Have control look through the solver's parameter list to see if
545  // there is anything it recognizes (mostly the "Transpose" parameter)
546  control_.setControlParameters(Teuchos::sublist(parameterList, name()));
547 
548  static_cast<solver_type*>(this)->setParameters_impl(Teuchos::sublist(parameterList, name()));
549  }
550  }
551 
552  return *this;
553 }
554 
555 
556 template <template <class,class> class ConcreteSolver, class Matrix, class Vector >
557 Teuchos::RCP<const Teuchos::ParameterList>
559 {
560 #ifdef HAVE_AMESOS2_TIMERS
561  Teuchos::TimeMonitor LocalTimer1( timers_.totalTime_ );
562 #endif
563 
564  using Teuchos::ParameterList;
565  using Teuchos::RCP;
566  using Teuchos::rcp;
567 
568  //RCP<ParameterList> control_params = rcp(new ParameterList("Amesos2 Control"));
569  RCP<ParameterList> control_params = rcp(new ParameterList("Amesos2"));
570  control_params->set("Transpose", false, "Whether to solve with the matrix transpose");
571  control_params->set("Iterative refinement", false, "Whether to solve with iterative refinement");
572  control_params->set("Number of iterative refinements", 2, "Number of iterative refinements");
573  control_params->set("Verboes for iterative refinement", false, "Verbosity for iterative refinements");
574  // control_params->set("AddToDiag", "");
575  // control_params->set("AddZeroToDiag", false);
576  // control_params->set("MatrixProperty", "general");
577  // control_params->set("Reindex", false);
578 
579  RCP<const ParameterList>
580  solver_params = static_cast<const solver_type*>(this)->getValidParameters_impl();
581  // inject the "Transpose" parameter into the solver's valid parameters
582  Teuchos::rcp_const_cast<ParameterList>(solver_params)->set("Transpose", false,
583  "Whether to solve with the "
584  "matrix transpose");
585 
586  RCP<ParameterList> amesos2_params = rcp(new ParameterList("Amesos2"));
587  amesos2_params->setParameters(*control_params);
588  amesos2_params->set(name(), *solver_params);
589 
590  return amesos2_params;
591 }
592 
593 
594 template <template <class,class> class ConcreteSolver, class Matrix, class Vector >
595 std::string
597 {
598  std::ostringstream oss;
599  oss << name() << " solver interface";
600  return oss.str();
601 }
602 
603 
604 template <template <class,class> class ConcreteSolver, class Matrix, class Vector >
605 void
607  Teuchos::FancyOStream &out,
608  const Teuchos::EVerbosityLevel verbLevel) const
609 {
610  if( matrixA_.is_null() || (rank_ != 0) ){ return; }
611  using std::endl;
612  using std::setw;
613  using Teuchos::VERB_DEFAULT;
614  using Teuchos::VERB_NONE;
615  using Teuchos::VERB_LOW;
616  using Teuchos::VERB_MEDIUM;
617  using Teuchos::VERB_HIGH;
618  using Teuchos::VERB_EXTREME;
619  Teuchos::EVerbosityLevel vl = verbLevel;
620  if (vl == VERB_DEFAULT) vl = VERB_LOW;
621  Teuchos::RCP<const Teuchos::Comm<int> > comm = this->getComm();
622  size_t width = 1;
623  for( size_t dec = 10; dec < globalNumRows_; dec *= 10 ) {
624  ++width;
625  }
626  width = std::max<size_t>(width,size_t(11)) + 2;
627  Teuchos::OSTab tab(out);
628  // none: print nothing
629  // low: print O(1) info from node 0
630  // medium: print O(P) info, num entries per node
631  // high: print O(N) info, num entries per row
632  // extreme: print O(NNZ) info: print indices and values
633  //
634  // for medium and higher, print constituent objects at specified verbLevel
635  if( vl != VERB_NONE ) {
636  std::string p = name();
637  Util::printLine(out);
638  out << this->description() << std::endl << std::endl;
639 
640  out << p << "Matrix has " << globalNumRows_ << " rows"
641  << " and " << globalNumNonZeros_ << " nonzeros"
642  << std::endl;
643  if( vl == VERB_MEDIUM || vl == VERB_HIGH || vl == VERB_EXTREME ){
644  out << p << "Nonzero elements per row = "
645  << globalNumNonZeros_ / globalNumRows_
646  << std::endl;
647  out << p << "Percentage of nonzero elements = "
648  << 100.0 * globalNumNonZeros_ / (globalNumRows_ * globalNumCols_)
649  << std::endl;
650  }
651  if( vl == VERB_HIGH || vl == VERB_EXTREME ){
652  out << p << "Use transpose = " << control_.useTranspose_
653  << std::endl;
654  out << p << "Use iterative refinement = " << control_.useIterRefine_
655  << std::endl;
656  }
657  if ( vl == VERB_EXTREME ){
658  printTiming(out,vl);
659  }
660  Util::printLine(out);
661  }
662 }
663 
664 
665 template <template <class,class> class ConcreteSolver, class Matrix, class Vector >
666 void
668  Teuchos::FancyOStream &out,
669  const Teuchos::EVerbosityLevel verbLevel) const
670 {
671  if( matrixA_.is_null() || (rank_ != 0) ){ return; }
672 
673  double preTime = timers_.preOrderTime_.totalElapsedTime();
674  double symTime = timers_.symFactTime_.totalElapsedTime();
675  double numTime = timers_.numFactTime_.totalElapsedTime();
676  double solTime = timers_.solveTime_.totalElapsedTime();
677  double totTime = timers_.totalTime_.totalElapsedTime();
678  double overhead = totTime - (preTime + symTime + numTime + solTime);
679 
680  std::string p = name() + " : ";
681  Util::printLine(out);
682 
683  if(verbLevel != Teuchos::VERB_NONE)
684  {
685  out << p << "Time to convert matrix to implementation format = "
686  << timers_.mtxConvTime_.totalElapsedTime() << " (s)"
687  << std::endl;
688  out << p << "Time to redistribute matrix = "
689  << timers_.mtxRedistTime_.totalElapsedTime() << " (s)"
690  << std::endl;
691 
692  out << p << "Time to convert vectors to implementation format = "
693  << timers_.vecConvTime_.totalElapsedTime() << " (s)"
694  << std::endl;
695  out << p << "Time to redistribute vectors = "
696  << timers_.vecRedistTime_.totalElapsedTime() << " (s)"
697  << std::endl;
698 
699  out << p << "Number of pre-orderings = "
700  << status_.getNumPreOrder()
701  << std::endl;
702  out << p << "Time for pre-ordering = "
703  << preTime << " (s), avg = "
704  << preTime / status_.getNumPreOrder() << " (s)"
705  << std::endl;
706 
707  out << p << "Number of symbolic factorizations = "
708  << status_.getNumSymbolicFact()
709  << std::endl;
710  out << p << "Time for sym fact = "
711  << symTime << " (s), avg = "
712  << symTime / status_.getNumSymbolicFact() << " (s)"
713  << std::endl;
714 
715  out << p << "Number of numeric factorizations = "
716  << status_.getNumNumericFact()
717  << std::endl;
718  out << p << "Time for num fact = "
719  << numTime << " (s), avg = "
720  << numTime / status_.getNumNumericFact() << " (s)"
721  << std::endl;
722 
723  out << p << "Number of solve phases = "
724  << status_.getNumSolve()
725  << std::endl;
726  out << p << "Time for solve = "
727  << solTime << " (s), avg = "
728  << solTime / status_.getNumSolve() << " (s)"
729  << std::endl;
730 
731  out << p << "Total time spent in Amesos2 = "
732  << totTime << " (s)"
733  << std::endl;
734  out << p << "Total time spent in the Amesos2 interface = "
735  << overhead << " (s)"
736  << std::endl;
737  out << p << " (the above time does not include solver time)"
738  << std::endl;
739  out << p << "Amesos2 interface time / total time = "
740  << overhead / totTime
741  << std::endl;
742  Util::printLine(out);
743  }
744 }
745 
746 
747 template <template <class,class> class ConcreteSolver, class Matrix, class Vector >
748 void
750  Teuchos::ParameterList& timingParameterList) const
751 {
752  Teuchos::ParameterList temp;
753  timingParameterList = temp.setName("NULL");
754 }
755 
756 
757 template <template <class,class> class ConcreteSolver, class Matrix, class Vector >
758 std::string
760 {
761  std::string solverName = solver_type::name;
762  return solverName;
763 }
764 
765 template <template <class,class> class ConcreteSolver, class Matrix, class Vector >
766 void
768 {
769  matrix_loaded_ = static_cast<solver_type*>(this)->loadA_impl(current_phase);
770 }
771 
772 
773 } // end namespace Amesos2
774 
775 #endif // AMESOS2_SOLVERCORE_DEF_HPP
Teuchos::RCP< const Teuchos::ParameterList > getValidParameters() const override
Return a const parameter list of all of the valid parameters that this-&gt;setParameterList(...) will accept.
Definition: Amesos2_SolverCore_def.hpp:558
void solve() override
Solves (or )
Definition: Amesos2_SolverCore_def.hpp:173
Amesos2::SolverCore: A templated interface for interaction with third-party direct sparse solvers...
Definition: Amesos2_SolverCore_decl.hpp:105
~SolverCore()
Destructor.
Definition: Amesos2_SolverCore_def.hpp:95
const int size
Definition: klu2_simple.cpp:74
EPhase
Used to indicate a phase in the direct solution.
Definition: Amesos2_TypeDecl.hpp:65
super_type & setParameters(const Teuchos::RCP< Teuchos::ParameterList > &parameterList) override
Set/update internal variables and solver options.
Definition: Amesos2_SolverCore_def.hpp:526
std::string description() const override
Returns a short description of this Solver.
Definition: Amesos2_SolverCore_def.hpp:596
void setA(const Teuchos::RCP< const Matrix > a, EPhase keep_phase=CLEAN) override
Sets the matrix A of this solver.
Definition: Amesos2_SolverCore_def.hpp:483
Utility functions for Amesos2.
super_type & preOrdering() override
Pre-orders the matrix A for minimal fill-in.
Definition: Amesos2_SolverCore_def.hpp:103
void describe(Teuchos::FancyOStream &out, const Teuchos::EVerbosityLevel verbLevel=Teuchos::Describable::verbLevel_default) const override
Definition: Amesos2_SolverCore_def.hpp:606
void printTiming(Teuchos::FancyOStream &out, const Teuchos::EVerbosityLevel verbLevel) const override
Prints timing information about the current solver.
Definition: Amesos2_SolverCore_def.hpp:667
SolverCore(Teuchos::RCP< const Matrix > A, Teuchos::RCP< Vector > X, Teuchos::RCP< const Vector > B)
Initialize a Solver instance.
Definition: Amesos2_SolverCore_def.hpp:70
virtual type & numericFactorization(void)=0
Performs numeric factorization on the matrix.
bool matrixShapeOK() override
Returns true if the solver can handle this matrix shape.
Definition: Amesos2_SolverCore_def.hpp:469
void printLine(Teuchos::FancyOStream &out)
Prints a line of 70 &quot;-&quot;s on std::cout.
Definition: Amesos2_Util.cpp:119
super_type & symbolicFactorization() override
Performs symbolic factorization on the matrix A.
Definition: Amesos2_SolverCore_def.hpp:123
void loadA(EPhase current_phase)
Refresh this solver&#39;s internal data about A.
Definition: Amesos2_SolverCore_def.hpp:767
std::string name() const override
Return the name of this solver.
Definition: Amesos2_SolverCore_def.hpp:759
Interface to Amesos2 solver objects.
Definition: Amesos2_Solver_decl.hpp:78
void getTiming(Teuchos::ParameterList &timingParameterList) const override
Extracts timing information from the current solver.
Definition: Amesos2_SolverCore_def.hpp:749
super_type & numericFactorization() override
Performs numeric factorization on the matrix A.
Definition: Amesos2_SolverCore_def.hpp:148