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