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 "Amesos2_MatrixAdapter_def.hpp"
57#include "Amesos2_MultiVecAdapter_def.hpp"
58
59#include "Amesos2_Util.hpp"
60
61
62namespace Amesos2 {
63
64
65template <template <class,class> class ConcreteSolver, class Matrix, class Vector >
67 Teuchos::RCP<const Matrix> A,
68 Teuchos::RCP<Vector> X,
69 Teuchos::RCP<const Vector> B )
70 : matrixA_(createConstMatrixAdapter<Matrix>(A))
71 , multiVecX_(X) // may be null
72 , multiVecB_(B) // may be null
73 , globalNumRows_(matrixA_->getGlobalNumRows())
74 , globalNumCols_(matrixA_->getGlobalNumCols())
75 , globalNumNonZeros_(matrixA_->getGlobalNNZ())
76 , rowIndexBase_(matrixA_->getRowIndexBase())
77 , columnIndexBase_(matrixA_->getColumnIndexBase())
78 , rank_(Teuchos::rank(*this->getComm()))
79 , root_(rank_ == 0)
80 , nprocs_(Teuchos::size(*this->getComm()))
81{
82 TEUCHOS_TEST_FOR_EXCEPTION(
84 std::invalid_argument,
85 "Matrix shape inappropriate for this solver");
86}
87
88
90template <template <class,class> class ConcreteSolver, class Matrix, class Vector >
92{
93 // Nothing
94}
95
96
97template <template <class,class> class ConcreteSolver, class Matrix, class Vector >
100{
101#ifdef HAVE_AMESOS2_TIMERS
102 Teuchos::TimeMonitor LocalTimer1(timers_.totalTime_);
103#endif
104
105 loadA(PREORDERING);
106
107 static_cast<solver_type*>(this)->preOrdering_impl();
108 ++status_.numPreOrder_;
109 status_.last_phase_ = PREORDERING;
110
111 return *this;
112}
113
114
115template <template <class,class> class ConcreteSolver, class Matrix, class Vector >
118{
119#ifdef HAVE_AMESOS2_TIMERS
120 Teuchos::TimeMonitor LocalTimer1(timers_.totalTime_);
121#endif
122
123 if( !status_.preOrderingDone() ){
124 preOrdering();
125 if( !matrix_loaded_ ) loadA(SYMBFACT);
126 } else {
127 loadA(SYMBFACT);
128 }
129
130 static_cast<solver_type*>(this)->symbolicFactorization_impl();
131 ++status_.numSymbolicFact_;
132 status_.last_phase_ = SYMBFACT;
133
134 return *this;
135}
136
137
138template <template <class,class> class ConcreteSolver, class Matrix, class Vector >
141{
142#ifdef HAVE_AMESOS2_TIMERS
143 Teuchos::TimeMonitor LocalTimer1(timers_.totalTime_);
144#endif
145
146 if( !status_.symbolicFactorizationDone() ){
147 symbolicFactorization();
148 if( !matrix_loaded_ ) loadA(NUMFACT);
149 } else {
150 loadA(NUMFACT);
151 }
152
153 static_cast<solver_type*>(this)->numericFactorization_impl();
154 ++status_.numNumericFact_;
155 status_.last_phase_ = NUMFACT;
156
157 return *this;
158}
159
160
161template <template <class,class> class ConcreteSolver, class Matrix, class Vector >
162void
164{
165 solve(multiVecX_.ptr(), multiVecB_.ptr());
167
168template <template <class,class> class ConcreteSolver, class Matrix, class Vector >
169void
171 const Teuchos::Ptr<const Vector> B) const
172{
173#ifdef HAVE_AMESOS2_TIMERS
174 Teuchos::TimeMonitor LocalTimer1(timers_.totalTime_);
175#endif
176
177 X.assert_not_null();
178 B.assert_not_null();
179
180 const Teuchos::RCP<MultiVecAdapter<Vector> > x =
181 createMultiVecAdapter<Vector>(Teuchos::rcpFromPtr(X));
182 const Teuchos::RCP<const MultiVecAdapter<Vector> > b =
183 createConstMultiVecAdapter<Vector>(Teuchos::rcpFromPtr(B));
184
185#ifdef HAVE_AMESOS2_DEBUG
186 // Check some required properties of X and B
187 TEUCHOS_TEST_FOR_EXCEPTION
188 (x->getGlobalLength() != matrixA_->getGlobalNumCols(),
189 std::invalid_argument,
190 "MultiVector X must have length equal to the number of "
191 "global columns in A. X->getGlobalLength() = "
192 << x->getGlobalLength() << " != A->getGlobalNumCols() = "
193 << matrixA_->getGlobalNumCols() << ".");
194
195 TEUCHOS_TEST_FOR_EXCEPTION(b->getGlobalLength() != matrixA_->getGlobalNumRows(),
196 std::invalid_argument,
197 "MultiVector B must have length equal to the number of "
198 "global rows in A");
199
200 TEUCHOS_TEST_FOR_EXCEPTION(x->getGlobalNumVectors() != b->getGlobalNumVectors(),
201 std::invalid_argument,
202 "X and B MultiVectors must have the same number of vectors");
203#endif // HAVE_AMESOS2_DEBUG
204
205 if( !status_.numericFactorizationDone() ){
206 // This casting-away of constness is probably OK because this
207 // function is meant to be "logically const"
208 const_cast<type&>(*this).numericFactorization();
209 }
210
211 static_cast<const solver_type*>(this)->solve_impl(Teuchos::outArg(*x), Teuchos::ptrInArg(*b));
212 ++status_.numSolve_;
213 status_.last_phase_ = SOLVE;
214}
215
216template <template <class,class> class ConcreteSolver, class Matrix, class Vector >
217void
218SolverCore<ConcreteSolver,Matrix,Vector>::solve(Vector* X, const Vector* B) const
219{
220 solve(Teuchos::ptr(X), Teuchos::ptr(B));
221}
222
223template <template <class,class> class ConcreteSolver, class Matrix, class Vector >
224bool
226{
227#ifdef HAVE_AMESOS2_TIMERS
228 Teuchos::TimeMonitor LocalTimer1(timers_.totalTime_);
229#endif
230
231 return( static_cast<solver_type*>(this)->matrixShapeOK_impl() );
232}
233
234 // The RCP should probably be to a const Matrix, but that throws a
235 // wrench in some of the traits mechanisms that aren't expecting
236 // const types
237template <template <class,class> class ConcreteSolver, class Matrix, class Vector >
238void
239SolverCore<ConcreteSolver,Matrix,Vector>::setA( const Teuchos::RCP<const Matrix> a,
240 EPhase keep_phase )
241{
242 matrixA_ = createConstMatrixAdapter(a);
243
244#ifdef HAVE_AMESOS2_DEBUG
245 TEUCHOS_TEST_FOR_EXCEPTION( (keep_phase != CLEAN) &&
246 (globalNumRows_ != matrixA_->getGlobalNumRows() ||
247 globalNumCols_ != matrixA_->getGlobalNumCols()),
248 std::invalid_argument,
249 "Dimensions of new matrix be the same as the old matrix if "
250 "keeping any solver phase" );
251#endif
252
253 status_.last_phase_ = keep_phase;
254
255 // Reset phase counters
256 switch( status_.last_phase_ ){
257 case CLEAN:
258 status_.numPreOrder_ = 0;
259 // Intentional fallthrough.
260 case PREORDERING:
261 status_.numSymbolicFact_ = 0;
262 // Intentional fallthrough.
263 case SYMBFACT:
264 status_.numNumericFact_ = 0;
265 // Intentional fallthrough.
266 case NUMFACT: // probably won't ever happen by itself
267 status_.numSolve_ = 0;
268 // Intentional fallthrough.
269 case SOLVE: // probably won't ever happen
270 break;
271 }
272
273 // Re-get the matrix dimensions in case they have changed
274 globalNumNonZeros_ = matrixA_->getGlobalNNZ();
275 globalNumCols_ = matrixA_->getGlobalNumCols();
276 globalNumRows_ = matrixA_->getGlobalNumRows();
277}
278
279
280template <template <class,class> class ConcreteSolver, class Matrix, class Vector >
281Solver<Matrix,Vector>&
283 const Teuchos::RCP<Teuchos::ParameterList> & parameterList )
284{
285#ifdef HAVE_AMESOS2_TIMERS
286 Teuchos::TimeMonitor LocalTimer1(timers_.totalTime_);
287#endif
288
289 if( parameterList->name() == "Amesos2" ){
290 // First, validate the parameterList
291 Teuchos::RCP<const Teuchos::ParameterList> valid_params = getValidParameters();
292 parameterList->validateParameters(*valid_params);
293
294 // Do everything here that is for generic status and control parameters
295 control_.setControlParameters(parameterList);
296
297 // Finally, hook to the implementation's parameter list parser
298 // First check if there is a dedicated sublist for this solver and use that if there is
299 if( parameterList->isSublist(name()) ){
300 // Have control look through the solver's parameter list to see if
301 // there is anything it recognizes (mostly the "Transpose" parameter)
302 control_.setControlParameters(Teuchos::sublist(parameterList, name()));
303
304 static_cast<solver_type*>(this)->setParameters_impl(Teuchos::sublist(parameterList, name()));
305 }
306 }
307
308 return *this;
309}
310
311
312template <template <class,class> class ConcreteSolver, class Matrix, class Vector >
313Teuchos::RCP<const Teuchos::ParameterList>
316#ifdef HAVE_AMESOS2_TIMERS
317 Teuchos::TimeMonitor LocalTimer1( timers_.totalTime_ );
318#endif
319
320 using Teuchos::ParameterList;
321 using Teuchos::RCP;
322 using Teuchos::rcp;
323
324 RCP<ParameterList> control_params = rcp(new ParameterList("Amesos2 Control"));
325 control_params->set("Transpose", false, "Whether to solve with the matrix transpose");
326 // control_params->set("AddToDiag", "");
327 // control_params->set("AddZeroToDiag", false);
328 // control_params->set("MatrixProperty", "general");
329 // control_params->set("Reindex", false);
330
331 RCP<const ParameterList>
332 solver_params = static_cast<const solver_type*>(this)->getValidParameters_impl();
333 // inject the "Transpose" parameter into the solver's valid parameters
334 Teuchos::rcp_const_cast<ParameterList>(solver_params)->set("Transpose", false,
335 "Whether to solve with the "
336 "matrix transpose");
337
338 RCP<ParameterList> amesos2_params = rcp(new ParameterList("Amesos2"));
339 amesos2_params->setParameters(*control_params);
340 amesos2_params->set(name(), *solver_params);
341
342 return amesos2_params;
343}
344
345
346template <template <class,class> class ConcreteSolver, class Matrix, class Vector >
347std::string
349{
350 std::ostringstream oss;
351 oss << name() << " solver interface";
352 return oss.str();
353}
354
355
356template <template <class,class> class ConcreteSolver, class Matrix, class Vector >
357void
359 Teuchos::FancyOStream &out,
360 const Teuchos::EVerbosityLevel verbLevel) const
361{
362 if( matrixA_.is_null() || (rank_ != 0) ){ return; }
363 using std::endl;
364 using std::setw;
365 using Teuchos::VERB_DEFAULT;
366 using Teuchos::VERB_NONE;
367 using Teuchos::VERB_LOW;
368 using Teuchos::VERB_MEDIUM;
369 using Teuchos::VERB_HIGH;
370 using Teuchos::VERB_EXTREME;
371 Teuchos::EVerbosityLevel vl = verbLevel;
372 if (vl == VERB_DEFAULT) vl = VERB_LOW;
373 Teuchos::RCP<const Teuchos::Comm<int> > comm = this->getComm();
374 size_t width = 1;
375 for( size_t dec = 10; dec < globalNumRows_; dec *= 10 ) {
376 ++width;
377 }
378 width = std::max<size_t>(width,size_t(11)) + 2;
379 Teuchos::OSTab tab(out);
380 // none: print nothing
381 // low: print O(1) info from node 0
382 // medium: print O(P) info, num entries per node
383 // high: print O(N) info, num entries per row
384 // extreme: print O(NNZ) info: print indices and values
385 //
386 // for medium and higher, print constituent objects at specified verbLevel
387 if( vl != VERB_NONE ) {
388 std::string p = name();
389 Util::printLine(out);
390 out << this->description() << std::endl << std::endl;
391
392 out << p << "Matrix has " << globalNumRows_ << "rows"
393 << " and " << globalNumNonZeros_ << "nonzeros"
394 << std::endl;
395 if( vl == VERB_MEDIUM || vl == VERB_HIGH || vl == VERB_EXTREME ){
396 out << p << "Nonzero elements per row = "
397 << globalNumNonZeros_ / globalNumRows_
398 << std::endl;
399 out << p << "Percentage of nonzero elements = "
400 << 100.0 * globalNumNonZeros_ / (globalNumRows_ * globalNumCols_)
401 << std::endl;
402 }
403 if( vl == VERB_HIGH || vl == VERB_EXTREME ){
404 out << p << "Use transpose = " << control_.useTranspose_
405 << std::endl;
406 }
407 if ( vl == VERB_EXTREME ){
408 printTiming(out,vl);
409 }
410 Util::printLine(out);
411 }
412}
413
415template <template <class,class> class ConcreteSolver, class Matrix, class Vector >
416void
418 Teuchos::FancyOStream &out,
419 const Teuchos::EVerbosityLevel verbLevel) const
420{
421 if( matrixA_.is_null() || (rank_ != 0) ){ return; }
422
423 double preTime = timers_.preOrderTime_.totalElapsedTime();
424 double symTime = timers_.symFactTime_.totalElapsedTime();
425 double numTime = timers_.numFactTime_.totalElapsedTime();
426 double solTime = timers_.solveTime_.totalElapsedTime();
427 double totTime = timers_.totalTime_.totalElapsedTime();
428 double overhead = totTime - (preTime + symTime + numTime + solTime);
429
430 std::string p = name() + " : ";
431 Util::printLine(out);
432
433 if(verbLevel != Teuchos::VERB_NONE)
434 {
435 out << p << "Time to convert matrix to implementation format = "
436 << timers_.mtxConvTime_.totalElapsedTime() << " (s)"
437 << std::endl;
438 out << p << "Time to redistribute matrix = "
439 << timers_.mtxRedistTime_.totalElapsedTime() << " (s)"
440 << std::endl;
442 out << p << "Time to convert vectors to implementation format = "
443 << timers_.vecConvTime_.totalElapsedTime() << " (s)"
444 << std::endl;
445 out << p << "Time to redistribute vectors = "
446 << timers_.vecRedistTime_.totalElapsedTime() << " (s)"
447 << std::endl;
448
449 out << p << "Number of pre-orderings = "
450 << status_.getNumPreOrder()
451 << std::endl;
452 out << p << "Time for pre-ordering = "
453 << preTime << " (s), avg = "
454 << preTime / status_.getNumPreOrder() << " (s)"
455 << std::endl;
456
457 out << p << "Number of symbolic factorizations = "
458 << status_.getNumSymbolicFact()
459 << std::endl;
460 out << p << "Time for sym fact = "
461 << symTime << " (s), avg = "
462 << symTime / status_.getNumSymbolicFact() << " (s)"
463 << std::endl;
464
465 out << p << "Number of numeric factorizations = "
466 << status_.getNumNumericFact()
467 << std::endl;
468 out << p << "Time for num fact = "
469 << numTime << " (s), avg = "
470 << numTime / status_.getNumNumericFact() << " (s)"
471 << std::endl;
472
473 out << p << "Number of solve phases = "
474 << status_.getNumSolve()
475 << std::endl;
476 out << p << "Time for solve = "
477 << solTime << " (s), avg = "
478 << solTime / status_.getNumSolve() << " (s)"
479 << std::endl;
480
481 out << p << "Total time spent in Amesos2 = "
482 << totTime << " (s)"
483 << std::endl;
484 out << p << "Total time spent in the Amesos2 interface = "
485 << overhead << " (s)"
486 << std::endl;
487 out << p << " (the above time does not include solver time)"
488 << std::endl;
489 out << p << "Amesos2 interface time / total time = "
490 << overhead / totTime
491 << std::endl;
492 Util::printLine(out);
493 }
494}
495
496
497template <template <class,class> class ConcreteSolver, class Matrix, class Vector >
498void
500 Teuchos::ParameterList& timingParameterList) const
501{
502 Teuchos::ParameterList temp;
503 timingParameterList = temp.setName("NULL");
504}
505
506
507template <template <class,class> class ConcreteSolver, class Matrix, class Vector >
508std::string
510{
511 std::string solverName = solver_type::name;
512 return solverName;
513}
514
515template <template <class,class> class ConcreteSolver, class Matrix, class Vector >
516void
518{
519 matrix_loaded_ = static_cast<solver_type*>(this)->loadA_impl(current_phase);
520}
521
522
523} // end namespace Amesos2
524
525#endif // AMESOS2_SOLVERCORE_DEF_HPP
Utility functions for Amesos2.
Amesos2 interface to the Baker package.
Definition: Amesos2_Basker_decl.hpp:74
void describe(Teuchos::FancyOStream &out, const Teuchos::EVerbosityLevel verbLevel=Teuchos::Describable::verbLevel_default) const
Definition: Amesos2_SolverCore_def.hpp:358
super_type & numericFactorization()
Performs numeric factorization on the matrix A.
Definition: Amesos2_SolverCore_def.hpp:140
void printTiming(Teuchos::FancyOStream &out, const Teuchos::EVerbosityLevel verbLevel) const
Prints timing information about the current solver.
Definition: Amesos2_SolverCore_def.hpp:417
std::string description() const
Returns a short description of this Solver.
Definition: Amesos2_SolverCore_def.hpp:348
SolverCore(Teuchos::RCP< const Matrix > A, Teuchos::RCP< Vector > X, Teuchos::RCP< const Vector > B)
Initialize a Solver instance.
Definition: Amesos2_SolverCore_def.hpp:66
super_type & setParameters(const Teuchos::RCP< Teuchos::ParameterList > &parameterList)
Set/update internal variables and solver options.
Definition: Amesos2_SolverCore_def.hpp:282
void getTiming(Teuchos::ParameterList &timingParameterList) const
Extracts timing information from the current solver.
Definition: Amesos2_SolverCore_def.hpp:499
Teuchos::RCP< const Teuchos::ParameterList > getValidParameters() const
Return a const parameter list of all of the valid parameters that this->setParameterList(....
Definition: Amesos2_SolverCore_def.hpp:314
std::string name() const
Return the name of this solver.
Definition: Amesos2_SolverCore_def.hpp:509
void setA(const Teuchos::RCP< const Matrix > a, EPhase keep_phase=CLEAN)
Sets the matrix A of this solver.
Definition: Amesos2_SolverCore_def.hpp:239
void loadA(EPhase current_phase)
Refresh this solver's internal data about A.
Definition: Amesos2_SolverCore_def.hpp:517
~SolverCore()
Destructor.
Definition: Amesos2_SolverCore_def.hpp:91
void solve()
Solves (or )
Definition: Amesos2_SolverCore_def.hpp:163
bool matrixShapeOK()
Returns true if the solver can handle this matrix shape.
Definition: Amesos2_SolverCore_def.hpp:225
super_type & symbolicFactorization()
Performs symbolic factorization on the matrix A.
Definition: Amesos2_SolverCore_def.hpp:117
super_type & preOrdering()
Pre-orders the matrix A for minimal fill-in.
Definition: Amesos2_SolverCore_def.hpp:99
Interface to Amesos2 solver objects.
Definition: Amesos2_Solver_decl.hpp:78
virtual type & numericFactorization(void)=0
Performs numeric factorization on the matrix.
EPhase
Used to indicate a phase in the direct solution.
Definition: Amesos2_TypeDecl.hpp:65
void printLine(Teuchos::FancyOStream &out)
Prints a line of 70 "-"s on std::cout.
Definition: Amesos2_Util.cpp:119