Amesos2 - Direct Sparse Solver Interfaces Version of the Day
Amesos2_KLU2_def.hpp
Go to the documentation of this file.
1// @HEADER
2// *****************************************************************************
3// Amesos2: Templated Direct Sparse Solver Package
4//
5// Copyright 2011 NTESS and the Amesos2 contributors.
6// SPDX-License-Identifier: BSD-3-Clause
7// *****************************************************************************
8// @HEADER
9
18#ifndef AMESOS2_KLU2_DEF_HPP
19#define AMESOS2_KLU2_DEF_HPP
20
21#include <Teuchos_Tuple.hpp>
22#include <Teuchos_ParameterList.hpp>
23#include <Teuchos_StandardParameterEntryValidators.hpp>
24
26#include "Amesos2_KLU2_decl.hpp"
27
28namespace Amesos2 {
29
30
31template <class Matrix, class Vector>
33 Teuchos::RCP<const Matrix> A,
34 Teuchos::RCP<Vector> X,
35 Teuchos::RCP<const Vector> B )
36 : SolverCore<Amesos2::KLU2,Matrix,Vector>(A, X, B)
37 , transFlag_(0)
38 , is_contiguous_(true)
39 , use_gather_(true)
40 , debug_level_(0)
41{
42 ::KLU2::klu_defaults<klu2_dtype, local_ordinal_type> (&(data_.common_)) ;
43 data_.symbolic_ = NULL;
44 data_.numeric_ = NULL;
45
46 // Override some default options
47 // TODO: use data_ here to init
48}
49
50
51template <class Matrix, class Vector>
53{
54 /* Free KLU2 data_types
55 * - Matrices
56 * - Vectors
57 * - Other data
58 */
59 if (data_.symbolic_ != NULL)
60 ::KLU2::klu_free_symbolic<klu2_dtype, local_ordinal_type>
61 (&(data_.symbolic_), &(data_.common_)) ;
62 if (data_.numeric_ != NULL)
63 ::KLU2::klu_free_numeric<klu2_dtype, local_ordinal_type>
64 (&(data_.numeric_), &(data_.common_)) ;
65
66 // Storage is initialized in numericFactorization_impl()
67 //if ( data_.A.Store != NULL ){
68 // destoy
69 //}
70
71 // only root allocated these SuperMatrices.
72 //if ( data_.L.Store != NULL ){ // will only be true for this->root_
73 // destroy ..
74 //}
75}
76
77template <class Matrix, class Vector>
78bool
80 return (this->root_ && (this->matrixA_->getComm()->getSize() == 1) && is_contiguous_);
81}
82
83template<class Matrix, class Vector>
84int
86{
87 /* TODO: Define what it means for KLU2
88 */
89#ifdef HAVE_AMESOS2_TIMERS
90 Teuchos::TimeMonitor preOrderTimer(this->timers_.preOrderTime_);
91#endif
92
93 return(0);
94}
95
96
97template <class Matrix, class Vector>
98int
100{
101 if (data_.symbolic_ != NULL) {
102 ::KLU2::klu_free_symbolic<klu2_dtype, local_ordinal_type>
103 (&(data_.symbolic_), &(data_.common_)) ;
104 }
105
106 if ( single_proc_optimization() ) {
107 host_ordinal_type_array host_row_ptr_view;
108 host_ordinal_type_array host_cols_view;
109 this->matrixA_->returnRowPtr_kokkos_view(host_row_ptr_view);
110 this->matrixA_->returnColInd_kokkos_view(host_cols_view);
111 data_.symbolic_ = ::KLU2::klu_analyze<klu2_dtype, local_ordinal_type>
112 ((local_ordinal_type)this->globalNumCols_, host_row_ptr_view.data(),
113 host_cols_view.data(), &(data_.common_)) ;
114 }
115 else
116 {
117 data_.symbolic_ = ::KLU2::klu_analyze<klu2_dtype, local_ordinal_type>
118 ((local_ordinal_type)this->globalNumCols_, host_col_ptr_view_.data(),
119 host_rows_view_.data(), &(data_.common_)) ;
120
121 } //end single_process_optim_check = false
122
123 return(0);
124}
125
126
127template <class Matrix, class Vector>
128int
130{
131 using Teuchos::as;
132
133 // Cleanup old L and U matrices if we are not reusing a symbolic
134 // factorization. Stores and other data will be allocated in gstrf.
135 // Only rank 0 has valid pointers, TODO: for KLU2
136
137 int info = 0;
138 if ( this->root_ ) {
139
140 { // Do factorization
141#ifdef HAVE_AMESOS2_TIMERS
142 Teuchos::TimeMonitor numFactTimer(this->timers_.numFactTime_);
143#endif
144
145 if (data_.numeric_ != NULL) {
146 ::KLU2::klu_free_numeric<klu2_dtype, local_ordinal_type>
147 (&(data_.numeric_), &(data_.common_));
148 }
149
150 if ( single_proc_optimization() ) {
151 host_ordinal_type_array host_row_ptr_view;
152 host_ordinal_type_array host_cols_view;
153 this->matrixA_->returnRowPtr_kokkos_view(host_row_ptr_view);
154 this->matrixA_->returnColInd_kokkos_view(host_cols_view);
155 this->matrixA_->returnValues_kokkos_view(host_nzvals_view_);
156 klu2_dtype * pValues = function_map::convert_scalar(host_nzvals_view_.data());
157 data_.numeric_ = ::KLU2::klu_factor<klu2_dtype, local_ordinal_type>
158 (host_row_ptr_view.data(), host_cols_view.data(), pValues,
159 data_.symbolic_, &(data_.common_));
160 }
161 else {
162 klu2_dtype * pValues = function_map::convert_scalar(host_nzvals_view_.data());
163 data_.numeric_ = ::KLU2::klu_factor<klu2_dtype, local_ordinal_type>
164 (host_col_ptr_view_.data(), host_rows_view_.data(), pValues,
165 data_.symbolic_, &(data_.common_));
166 } //end single_process_optim_check = false
167
168 // To have a test which confirms a throw, we need MPI to throw on all the
169 // ranks. So we delay and broadcast first. Others throws in Amesos2 which
170 // happen on just the root rank would also have the same problem if we
171 // tested them but we decided to fix just this one for the present. This
172 // is the only error/throw we currently have a unit test for.
173 if(data_.numeric_ == nullptr) {
174 info = 1;
175 if(debug_level_ > 0) {
176 std::cout << " ** Amesos2::KLU2::numericFactorization failed with status = ";
177 if(data_.common_.status == KLU_OK)
178 std::cout << "KLU_OK **\n";
179 else if (data_.common_.status == KLU_SINGULAR)
180 std::cout << "KLU_SINGULAR **\n";
181 else if (data_.common_.status == KLU_OUT_OF_MEMORY)
182 std::cout << "KLU_OUT_OF_MEMORY **\n";
183 else if (data_.common_.status == KLU_INVALID)
184 std::cout << "KLU_INVALID **\n";
185 else if (data_.common_.status == KLU_TOO_LARGE)
186 std::cout << "KLU_TOO_LARGE **\n";
187 }
188 }
189
190 // This is set after numeric factorization complete as pivoting can be used;
191 // In this case, a discrepancy between symbolic and numeric nnz total can occur.
192 if(info == 0) { // skip if error code so we don't segfault - will throw
193 this->setNnzLU( as<size_t>((data_.numeric_)->lnz) + as<size_t>((data_.numeric_)->unz) );
194 }
195 } // end scope
196
197 } // end this->root_
198
199 /* All processes should have the same error code */
200 Teuchos::broadcast(*(this->matrixA_->getComm()), 0, &info);
201
202 TEUCHOS_TEST_FOR_EXCEPTION(info > 0, std::runtime_error,
203 "KLU2 numeric factorization failed(info="+std::to_string(info)+")");
204
205 return(info);
206}
207
208template <class Matrix, class Vector>
209int
211 const Teuchos::Ptr<MultiVecAdapter<Vector> > X,
212 const Teuchos::Ptr<const MultiVecAdapter<Vector> > B) const
213{
214 using Teuchos::as;
215 int ierr = 0; // returned error code
216
217 const global_size_type ld_rhs = this->root_ ? X->getGlobalLength() : 0;
218 const size_t nrhs = X->getGlobalNumVectors();
219 if (debug_level_ > 0) {
220 if (this->root_) std::cout << "\n == Amesos2_KLU2::solve_impl ==" << std::endl;
221 if (debug_level_ == 1) {
222 B->description();
223 } else {
224 Teuchos::RCP<Teuchos::FancyOStream> fancy = Teuchos::fancyOStream(Teuchos::rcpFromRef(std::cout));
225 if (!is_null(B->getMap())) B->getMap()->describe(*fancy, Teuchos::VERB_EXTREME);
226 std::cout << std::endl;
227 B->describe(*fancy, Teuchos::VERB_EXTREME);
228 }
229 }
230
231 bool bDidAssignX;
232 bool bDidAssignB;
233 bool use_gather = use_gather_; // user param
234 use_gather = (use_gather && this->matrixA_->getComm()->getSize() > 1); // only with multiple MPIs
235 use_gather = (use_gather && (std::is_same<vector_scalar_type, float>::value ||
236 std::is_same<vector_scalar_type, double>::value)); // only for double or float vectors
237 {
238#ifdef HAVE_AMESOS2_TIMERS
239 Teuchos::TimeMonitor mvConvTimer(this->timers_.vecConvTime_);
240#endif
241 const bool initialize_data = true;
242 const bool do_not_initialize_data = false;
243 if ( single_proc_optimization() && nrhs == 1 ) {
244 // no map creation
245 bDidAssignB = Util::get_1d_copy_helper_kokkos_view<MultiVecAdapter<Vector>,
246 host_solve_array_t>::do_get(initialize_data, B, bValues_, as<size_t>(ld_rhs));
247
248 bDidAssignX = Util::get_1d_copy_helper_kokkos_view<MultiVecAdapter<Vector>,
249 host_solve_array_t>::do_get(do_not_initialize_data, X, xValues_, as<size_t>(ld_rhs));
250 }
251 else {
252 if (use_gather) {
253 int rval = B->gather(bValues_, this->perm_g2l, this->recvCountRows, this->recvDisplRows,
254 (is_contiguous_ == true) ? ROOTED : CONTIGUOUS_AND_ROOTED);
255 if (rval == 0) {
256 X->gather(xValues_, this->perm_g2l, this->recvCountRows, this->recvDisplRows,
257 (is_contiguous_ == true) ? ROOTED : CONTIGUOUS_AND_ROOTED);
258 bDidAssignB = true; // TODO : find when we can avoid deep-copy
259 bDidAssignX = false; // TODO : find when we can avoid scatter
260 } else {
261 use_gather = false;
262 }
263 }
264 if (!use_gather) {
265 const EDistribution dist = (is_contiguous_ == true) ? ROOTED : CONTIGUOUS_AND_ROOTED;
266 if (distributionMap_.is_null()) {
267 typedef MultiVecAdapter<Vector> MVA;
268 distributionMap_ = Util::getDistributionMap<
269 typename MVA::local_ordinal_t, typename MVA::global_ordinal_t,
270 typename MVA::global_size_t, typename MVA::node_t>(
271 dist, B->getGlobalLength(), B->getComm(),
272 this->rowIndexBase_, B->getMap());
273 }
274 auto distMapPtr = Teuchos::ptrInArg(*distributionMap_);
275 bDidAssignB = Util::get_1d_copy_helper_kokkos_view<MultiVecAdapter<Vector>,
276 host_solve_array_t>::do_get(initialize_data, B, bValues_,
277 as<size_t>(ld_rhs), distMapPtr, dist);
278 // see Amesos2_Tacho_def.hpp for an explanation of why we 'get' X
279 bDidAssignX = Util::get_1d_copy_helper_kokkos_view<MultiVecAdapter<Vector>,
280 host_solve_array_t>::do_get(do_not_initialize_data, X, xValues_,
281 as<size_t>(ld_rhs), distMapPtr, dist);
282 }
283
284 // klu_tsolve is going to put the solution x into the input b.
285 // Copy b to x then solve in x.
286 // We do not want to solve in b, then copy to x, because if b was assigned
287 // then the solve will change b permanently and mess up the next test cycle.
288 // However if b was actually a copy (bDidAssignB = false) then we can avoid
289 // this deep_copy and just assign xValues_ = bValues_.
290 if(bDidAssignB) {
291 Kokkos::deep_copy(xValues_, bValues_); // need deep_copy or solve will change adapter's b memory which should never happen
292 }
293 else {
294 xValues_ = bValues_; // safe because bValues_ does not point straight to adapter's memory space
295 }
296 }
297 }
298
299 klu2_dtype * pxValues = function_map::convert_scalar(xValues_.data());
300 klu2_dtype * pbValues = function_map::convert_scalar(bValues_.data());
301
302 // can be null for non root
303 if( this->root_) {
304 TEUCHOS_TEST_FOR_EXCEPTION(pbValues == nullptr,
305 std::runtime_error, "Amesos2 Runtime Error: b_vector returned null ");
306
307 TEUCHOS_TEST_FOR_EXCEPTION(pxValues == nullptr,
308 std::runtime_error, "Amesos2 Runtime Error: x_vector returned null ");
309 }
310
311 if ( single_proc_optimization() && nrhs == 1 ) {
312#ifdef HAVE_AMESOS2_TIMERS
313 Teuchos::TimeMonitor solveTimer(this->timers_.solveTime_);
314#endif
315
316 // For this case, Crs matrix raw pointers were used, so the non-transpose default solve
317 // is actually the transpose solve as klu_solve expects Ccs matrix pointers
318 // Thus, if the transFlag_ is true, the non-transpose solve should be used
319 if (transFlag_ == 0)
320 {
321 ::KLU2::klu_tsolve2<klu2_dtype, local_ordinal_type>
322 (data_.symbolic_, data_.numeric_,
323 (local_ordinal_type)this->globalNumCols_,
324 (local_ordinal_type)nrhs,
325 pbValues, pxValues, &(data_.common_)) ;
326 }
327 else {
328 ::KLU2::klu_solve2<klu2_dtype, local_ordinal_type>
329 (data_.symbolic_, data_.numeric_,
330 (local_ordinal_type)this->globalNumCols_,
331 (local_ordinal_type)nrhs,
332 pbValues, pxValues, &(data_.common_)) ;
333 }
334
335 /* All processes should have the same error code */
336 // Teuchos::broadcast(*(this->getComm()), 0, &ierr);
337
338 } // end single_process_optim_check && nrhs == 1
339 else // single proc optimizations but nrhs > 1,
340 // or distributed over processes case
341 {
342 if ( this->root_ ) {
343#ifdef HAVE_AMESOS2_TIMERS
344 Teuchos::TimeMonitor solveTimer(this->timers_.solveTime_);
345#endif
346 if (transFlag_ == 0)
347 {
348 // For this case, Crs matrix raw pointers were used, so the non-transpose default solve
349 // is actually the transpose solve as klu_solve expects Ccs matrix pointers
350 // Thus, if the transFlag_ is true, the non-transpose solve should be used
351 if ( single_proc_optimization() ) {
352 ::KLU2::klu_tsolve<klu2_dtype, local_ordinal_type>
353 (data_.symbolic_, data_.numeric_,
354 (local_ordinal_type)this->globalNumCols_,
355 (local_ordinal_type)nrhs,
356 pxValues, &(data_.common_)) ;
357 }
358 else {
359 ::KLU2::klu_solve<klu2_dtype, local_ordinal_type>
360 (data_.symbolic_, data_.numeric_,
361 (local_ordinal_type)this->globalNumCols_,
362 (local_ordinal_type)nrhs,
363 pxValues, &(data_.common_)) ;
364 }
365 }
366 else
367 {
368 // For this case, Crs matrix raw pointers were used, so the non-transpose default solve
369 // is actually the transpose solve as klu_solve expects Ccs matrix pointers
370 // Thus, if the transFlag_ is true, the non- transpose solve should be used
371 if ( single_proc_optimization() ) {
372 ::KLU2::klu_solve<klu2_dtype, local_ordinal_type>
373 (data_.symbolic_, data_.numeric_,
374 (local_ordinal_type)this->globalNumCols_,
375 (local_ordinal_type)nrhs,
376 pxValues, &(data_.common_)) ;
377 }
378 else {
379 ::KLU2::klu_tsolve<klu2_dtype, local_ordinal_type>
380 (data_.symbolic_, data_.numeric_,
381 (local_ordinal_type)this->globalNumCols_,
382 (local_ordinal_type)nrhs,
383 pxValues, &(data_.common_)) ;
384 }
385 }
386 } // end root_
387 } //end else
388
389 // if bDidAssignX, then we solved straight to the adapter's X memory space without
390 // requiring additional memory allocation, so the x data is already in place.
391 // TODO: should we check bDidAssignB?
392 if(!bDidAssignX) {
393#ifdef HAVE_AMESOS2_TIMERS
394 Teuchos::TimeMonitor redistTimer( this->timers_.vecRedistTime_ );
395#endif
396 if (use_gather) {
397 int rval = X->scatter(xValues_, this->perm_g2l, this->recvCountRows, this->recvDisplRows,
398 (is_contiguous_ == true) ? ROOTED : CONTIGUOUS_AND_ROOTED);
399 if (rval != 0) use_gather = false;
400 }
401 if (!use_gather) {
402 const EDistribution dist = (is_contiguous_ == true) ? ROOTED : CONTIGUOUS_AND_ROOTED;
403 if (!distributionMap_.is_null()) {
404 Util::put_1d_data_helper_kokkos_view<
405 MultiVecAdapter<Vector>,host_solve_array_t>::do_put(X, xValues_,
406 as<size_t>(ld_rhs), Teuchos::ptrInArg(*distributionMap_), dist);
407 } else {
408 Util::put_1d_data_helper_kokkos_view<
409 MultiVecAdapter<Vector>,host_solve_array_t>::do_put(X, xValues_,
410 as<size_t>(ld_rhs), dist, this->rowIndexBase_);
411 }
412 }
413 }
414 if (debug_level_ > 0) {
415 if (debug_level_ == 1) {
416 X->description();
417 } else {
418 Teuchos::RCP<Teuchos::FancyOStream> fancy = Teuchos::fancyOStream(Teuchos::rcpFromRef(std::cout));
419 if (!is_null(X->getMap())) X->getMap()->describe(*fancy, Teuchos::VERB_EXTREME);
420 std::cout << std::endl;
421 X->describe(*fancy, Teuchos::VERB_EXTREME);
422 }
423 }
424 return(ierr);
425}
426
427
428template <class Matrix, class Vector>
429bool
431{
432 // The KLU2 factorization routines can handle square as well as
433 // rectangular matrices, but KLU2 can only apply the solve routines to
434 // square matrices, so we check the matrix for squareness.
435 return( this->matrixA_->getGlobalNumRows() == this->matrixA_->getGlobalNumCols() );
436}
437
438
439template <class Matrix, class Vector>
440void
441KLU2<Matrix,Vector>::setParameters_impl(const Teuchos::RCP<Teuchos::ParameterList> & parameterList )
442{
443 using Teuchos::RCP;
444 using Teuchos::getIntegralValue;
445 using Teuchos::ParameterEntryValidator;
446
447 RCP<const Teuchos::ParameterList> valid_params = getValidParameters_impl();
448
449 transFlag_ = this->control_.useTranspose_ ? 1: 0;
450 // The KLU2 transpose option can override the Amesos2 option
451 if( parameterList->isParameter("Trans") ){
452 RCP<const ParameterEntryValidator> trans_validator = valid_params->getEntry("Trans").validator();
453 parameterList->getEntry("Trans").setValidator(trans_validator);
454
455 transFlag_ = getIntegralValue<int>(*parameterList, "Trans");
456 }
457
458 if( parameterList->isParameter("IsContiguous") ){
459 is_contiguous_ = parameterList->get<bool>("IsContiguous");
460 }
461 if( parameterList->isParameter("UseCustomGather") ){
462 use_gather_ = parameterList->get<bool>("UseCustomGather");
463 }
464
465 if( parameterList->isParameter("DebugLevel") ){
466 debug_level_ = parameterList->get<int>("DebugLevel");
467 }
468}
469
470
471template <class Matrix, class Vector>
472Teuchos::RCP<const Teuchos::ParameterList>
474{
475 using std::string;
476 using Teuchos::tuple;
477 using Teuchos::ParameterList;
478 using Teuchos::setStringToIntegralParameter;
479
480 static Teuchos::RCP<const Teuchos::ParameterList> valid_params;
481
482 if( is_null(valid_params) )
483 {
484 Teuchos::RCP<Teuchos::ParameterList> pl = Teuchos::parameterList();
485
486 pl->set("Equil", true, "Whether to equilibrate the system before solve, does nothing now");
487 pl->set("IsContiguous", true, "Whether GIDs contiguous");
488 pl->set("UseCustomGather", true, "Whether to use new matrix-gather routine");
489 pl->set("DebugLevel", 0, "Debug message level (0 for no message, and >0 for more message");
490
491 setStringToIntegralParameter<int>("Trans", "NOTRANS",
492 "Solve for the transpose system or not",
493 tuple<string>("NOTRANS","TRANS","CONJ"),
494 tuple<string>("Solve with transpose",
495 "Do not solve with transpose",
496 "Solve with the conjugate transpose"),
497 tuple<int>(0, 1, 2),
498 pl.getRawPtr());
499 valid_params = pl;
500 }
501
502 return valid_params;
503}
504
505
506template <class Matrix, class Vector>
507bool
509{
510 using Teuchos::as;
511#ifdef HAVE_AMESOS2_TIMERS
512 Teuchos::TimeMonitor convTimer(this->timers_.mtxConvTime_);
513#endif
514
515 if(current_phase == SOLVE)return(false);
516 if (debug_level_ > 0 && current_phase == NUMFACT) {
517 if (this->root_) {
518 std::cout << "\n == Amesos2_KLU2::loadA_impl";
519 if (current_phase == PREORDERING) std::cout << "(PreOrder)";
520 if (current_phase == SYMBFACT) std::cout << "(SymFact)";
521 if (current_phase == NUMFACT) std::cout << "(NumFact)";
522 std::cout << " ==" << std::endl;
523 }
524 Teuchos::RCP<Teuchos::FancyOStream> fancy = Teuchos::fancyOStream(Teuchos::rcpFromRef(std::cout));
525 this->matrixA_->describe(*fancy, (debug_level_ == 1 ? Teuchos::VERB_LOW : Teuchos::VERB_EXTREME));
526 }
527
528 if ( single_proc_optimization() ) {
529 // Do nothing in this case - Crs raw pointers will be used
530 }
531 else
532 {
533 // Only the root image needs storage allocated
534 if( this->root_ ) {
535 if (host_nzvals_view_.extent(0) != this->globalNumNonZeros_)
536 Kokkos::resize(host_nzvals_view_, this->globalNumNonZeros_);
537 if (host_rows_view_.extent(0) != this->globalNumNonZeros_)
538 Kokkos::resize(host_rows_view_, this->globalNumNonZeros_);
539 if (host_col_ptr_view_.extent(0) != (this->globalNumRows_ + 1))
540 Kokkos::resize(host_col_ptr_view_, this->globalNumRows_ + 1);
541 }
542 local_ordinal_type nnz_ret = -1;
543 bool use_gather = use_gather_; // user param
544 use_gather = (use_gather && this->matrixA_->getComm()->getSize() > 1); // only with multiple MPIs
545 use_gather = (use_gather && (std::is_same<scalar_type, float>::value || std::is_same<scalar_type, double>::value)); // only for double or float
546 {
547#ifdef HAVE_AMESOS2_TIMERS
548 Teuchos::TimeMonitor mtxRedistTimer( this->timers_.mtxRedistTime_ );
549#endif
550 if (use_gather) {
551 bool column_major = true;
552 if (!is_contiguous_) {
553 auto contig_mat = this->matrixA_->reindex(this->contig_rowmap_, this->contig_colmap_, current_phase);
554 nnz_ret = contig_mat->gather(host_nzvals_view_, host_rows_view_, host_col_ptr_view_, this->perm_g2l, this->recvCountRows, this->recvDisplRows, this->recvCounts, this->recvDispls,
555 this->transpose_map, this->nzvals_t, column_major, current_phase);
556 } else {
557 nnz_ret = this->matrixA_->gather(host_nzvals_view_, host_rows_view_, host_col_ptr_view_, this->perm_g2l, this->recvCountRows, this->recvDisplRows, this->recvCounts, this->recvDispls,
558 this->transpose_map, this->nzvals_t, column_major, current_phase);
559 }
560 // gather failed (e.g., not implemened for KokkosCrsMatrix)
561 // in case of the failure, it falls back to the original "do_get"
562 if (nnz_ret < 0) use_gather = false;
563 }
564 if (!use_gather) {
566 MatrixAdapter<Matrix>,host_value_type_array,host_ordinal_type_array,host_ordinal_type_array>
567 ::do_get(this->matrixA_.ptr(), host_nzvals_view_, host_rows_view_, host_col_ptr_view_, nnz_ret,
568 (is_contiguous_ == true) ? ROOTED : CONTIGUOUS_AND_ROOTED,
569 ARBITRARY,
570 this->rowIndexBase_);
571 }
572 }
573
574 // gather return the total nnz_ret on every MPI process
575 if (use_gather || this->root_) {
576 TEUCHOS_TEST_FOR_EXCEPTION( nnz_ret != as<local_ordinal_type>(this->globalNumNonZeros_),
577 std::runtime_error,
578 "Amesos2_KLU2 loadA_impl: Did not get the expected number of non-zero vals("
579 +std::to_string(nnz_ret)+" vs "+std::to_string(this->globalNumNonZeros_)+")");
580 }
581 } //end else single_process_optim_check = false
582
583 return true;
584}
585
586
587template <class Matrix, class Vector>
588void
589KLU2<Matrix,Vector>::describe_impl(Teuchos::FancyOStream &out,
590 const Teuchos::EVerbosityLevel verbLevel) const
591{
592 out << " KLU2 current parameters:" << std::endl;
593 out << " > Trans = " << transFlag_ << std::endl;
594 out << " > IsContiguous = " << (is_contiguous_ ? "YES" : "NO") << std::endl;
595 out << " > UseCustomGather = " << (use_gather_ ? "YES" : "NO") << std::endl;
596 out << " > DebugLevel = " << debug_level_ << std::endl;
597 out << std::endl;
598}
599
600
601template<class Matrix, class Vector>
602const char* KLU2<Matrix,Vector>::name = "KLU2";
603
604
605} // end namespace Amesos2
606
607#endif // AMESOS2_KLU2_DEF_HPP
Amesos2 KLU2 declarations.
EDistribution
Definition Amesos2_TypeDecl.hpp:89
@ ROOTED
Definition Amesos2_TypeDecl.hpp:93
@ CONTIGUOUS_AND_ROOTED
Definition Amesos2_TypeDecl.hpp:94
@ ARBITRARY
Definition Amesos2_TypeDecl.hpp:109
Amesos2 interface to the KLU2 package.
Definition Amesos2_KLU2_decl.hpp:39
KLU2(Teuchos::RCP< const Matrix > A, Teuchos::RCP< Vector > X, Teuchos::RCP< const Vector > B)
Initialize from Teuchos::RCP.
Definition Amesos2_KLU2_def.hpp:32
Teuchos::RCP< const Teuchos::ParameterList > getValidParameters_impl() const
Definition Amesos2_KLU2_def.hpp:473
bool single_proc_optimization() const
can we optimize size_type and ordinal_type for straight pass through, also check that is_contiguous_ ...
Definition Amesos2_KLU2_def.hpp:79
bool matrixShapeOK_impl() const
Determines whether the shape of the matrix is OK for this solver.
Definition Amesos2_KLU2_def.hpp:430
int symbolicFactorization_impl()
Perform symbolic factorization of the matrix using KLU2.
Definition Amesos2_KLU2_def.hpp:99
int preOrdering_impl()
Performs pre-ordering on the matrix to increase efficiency.
Definition Amesos2_KLU2_def.hpp:85
void describe_impl(Teuchos::FancyOStream &out, const Teuchos::EVerbosityLevel verbLevel) const
Prints the status information about the current solver with some level of verbosity.
Definition Amesos2_KLU2_def.hpp:589
int solve_impl(const Teuchos::Ptr< MultiVecAdapter< Vector > > X, const Teuchos::Ptr< const MultiVecAdapter< Vector > > B) const
KLU2 specific solve.
Definition Amesos2_KLU2_def.hpp:210
~KLU2()
Destructor.
Definition Amesos2_KLU2_def.hpp:52
bool loadA_impl(EPhase current_phase)
Reads matrix data into internal structures.
Definition Amesos2_KLU2_def.hpp:508
int numericFactorization_impl()
KLU2 specific numeric factorization.
Definition Amesos2_KLU2_def.hpp:129
void setParameters_impl(const Teuchos::RCP< Teuchos::ParameterList > &parameterList)
Definition Amesos2_KLU2_def.hpp:441
A Matrix adapter interface for Amesos2.
Definition Amesos2_MatrixAdapter_decl.hpp:42
Amesos2::SolverCore: A templated interface for interaction with third-party direct sparse solvers.
Definition Amesos2_SolverCore_decl.hpp:72
EPhase
Used to indicate a phase in the direct solution.
Definition Amesos2_TypeDecl.hpp:31
A templated MultiVector class adapter for Amesos2.
Definition Amesos2_MultiVecAdapter_decl.hpp:142
A generic helper class for getting a CCS representation of a Matrix.
Definition Amesos2_Util.hpp:589