Belos Package Browser (Single Doxygen Collection)  Development
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
BelosGmresPolySolMgr.hpp
Go to the documentation of this file.
1 //@HEADER
2 // ************************************************************************
3 //
4 // Belos: Block Linear Solvers Package
5 // Copyright 2004 Sandia Corporation
6 //
7 // Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
8 // the U.S. Government retains certain rights in this software.
9 //
10 // Redistribution and use in source and binary forms, with or without
11 // modification, are permitted provided that the following conditions are
12 // met:
13 //
14 // 1. Redistributions of source code must retain the above copyright
15 // notice, this list of conditions and the following disclaimer.
16 //
17 // 2. Redistributions in binary form must reproduce the above copyright
18 // notice, this list of conditions and the following disclaimer in the
19 // documentation and/or other materials provided with the distribution.
20 //
21 // 3. Neither the name of the Corporation nor the names of the
22 // contributors may be used to endorse or promote products derived from
23 // this software without specific prior written permission.
24 //
25 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
26 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
28 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
29 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
30 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
31 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
32 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
33 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
34 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
35 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 //
37 // Questions? Contact Michael A. Heroux (maherou@sandia.gov)
38 //
39 // ************************************************************************
40 //@HEADER
41 
42 #ifndef BELOS_GMRES_POLY_SOLMGR_HPP
43 #define BELOS_GMRES_POLY_SOLMGR_HPP
44 
48 
49 #include "BelosConfigDefs.hpp"
50 #include "BelosTypes.hpp"
51 
52 #include "BelosLinearProblem.hpp"
53 #include "BelosSolverManager.hpp"
54 #include "BelosGmresPolyOp.hpp"
56 #include "Teuchos_as.hpp"
57 #ifdef BELOS_TEUCHOS_TIME_MONITOR
58 #include "Teuchos_TimeMonitor.hpp"
59 #endif
60 
61 
62 namespace Belos {
63 
65 
66 
74  GmresPolySolMgrLinearProblemFailure(const std::string& what_arg) : BelosError(what_arg)
75  {}};
76 
84  GmresPolySolMgrPolynomialFailure(const std::string& what_arg) : BelosError(what_arg)
85  {}};
86 
132 
133 template<class ScalarType, class MV, class OP>
134 class GmresPolySolMgr : public SolverManager<ScalarType,MV,OP> {
135 private:
136 
142 
143 public:
144 
146 
147 
153  GmresPolySolMgr();
154 
166 
168  virtual ~GmresPolySolMgr() {};
169 
173  }
175 
177 
178 
181  const LinearProblem<ScalarType,MV,OP>& getProblem() const override {
182  return *problem_;
183  }
184 
188 
192 
199  return Teuchos::tuple(timerPoly_);
200  }
201 
203  int getNumIters() const override {
204  return numIters_;
205  }
206 
210  bool isLOADetected() const override { return loaDetected_; }
211 
213 
215 
216 
218  void setProblem( const Teuchos::RCP<LinearProblem<ScalarType,MV,OP> > &problem ) override { problem_ = problem; }
219 
221  void setParameters( const Teuchos::RCP<Teuchos::ParameterList> &params ) override;
222 
224 
226 
235  void reset( const ResetType type ) override {
236  if ((type & Belos::Problem) && ! problem_.is_null ()) {
237  problem_->setProblem ();
239  poly_dim_ = 0; // Rebuild the GMRES polynomial
240  }
241  }
242 
244 
246 
264  ReturnType solve() override;
265 
267 
270 
272  std::string description() const override;
273 
275 
276 private:
277 
278  // Linear problem.
280 
281  // Output manager.
283 
284  // Current parameter list.
287 
288  // Default solver values.
289  static constexpr int maxDegree_default_ = 25;
290  static constexpr int verbosity_default_ = Belos::Errors;
291  static constexpr const char * label_default_ = "Belos";
292  static constexpr const char * outerSolverType_default_ = "";
293  static constexpr const char * polyType_default_ = "Arnoldi";
294  static constexpr const char * orthoType_default_ = "DGKS";
295  static constexpr std::ostream * outputStream_default_ = &std::cout;
296 
297  // Current solver values.
303  std::string polyType_;
304  std::string outerSolverType_;
305  std::string orthoType_;
306 
307  // Polynomial storage
310 
311  // Timers.
312  std::string label_;
314 
315  // Internal state variables.
316  bool isSet_;
318 
321 };
322 
323 
324 template<class ScalarType, class MV, class OP>
326  outputStream_ (Teuchos::rcp(outputStream_default_,false)),
327  polyTol_ (DefaultSolverParameters::polyTol),
328  maxDegree_ (maxDegree_default_),
329  numIters_ (0),
330  verbosity_ (verbosity_default_),
331  hasOuterSolver_ (false),
332  randomRHS_ (true),
333  polyType_ (polyType_default_),
334  outerSolverType_ (outerSolverType_default_),
335  orthoType_ (orthoType_default_),
336  poly_dim_ (0),
337  label_ (label_default_),
338  isSet_ (false),
339  loaDetected_ (false)
340 {}
341 
342 
343 template<class ScalarType, class MV, class OP>
347  problem_ (problem),
348  outputStream_ (Teuchos::rcp(outputStream_default_,false)),
349  polyTol_ (DefaultSolverParameters::polyTol),
350  maxDegree_ (maxDegree_default_),
351  numIters_ (0),
352  verbosity_ (verbosity_default_),
353  hasOuterSolver_ (false),
354  randomRHS_ (true),
355  polyType_ (polyType_default_),
356  outerSolverType_ (outerSolverType_default_),
357  orthoType_ (orthoType_default_),
358  poly_dim_ (0),
359  label_ (label_default_),
360  isSet_ (false),
361  loaDetected_ (false)
362 {
364  problem_.is_null (), std::invalid_argument,
365  "Belos::GmresPolySolMgr: The given linear problem is null. "
366  "Please call this constructor with a nonnull LinearProblem argument, "
367  "or call the constructor that does not take a LinearProblem.");
368 
369  // If the input parameter list is null, then the parameters take
370  // default values.
371  if (! pl.is_null ()) {
372  setParameters (pl);
373  }
374 }
375 
376 
377 template<class ScalarType, class MV, class OP>
380 {
381  if (validPL_.is_null ()) {
382  Teuchos::RCP<Teuchos::ParameterList> pl = Teuchos::parameterList ();
383 
384  // The static_cast is to resolve an issue with older clang versions which
385  // would cause the constexpr to link fail. With c++17 the problem is resolved.
386  pl->set("Polynomial Type", static_cast<const char *>(polyType_default_),
387  "The type of GMRES polynomial that is used as a preconditioner.");
388  pl->set("Polynomial Tolerance", static_cast<MagnitudeType>(DefaultSolverParameters::polyTol),
389  "The relative residual tolerance that used to construct the GMRES polynomial.");
390  pl->set("Maximum Degree", static_cast<int>(maxDegree_default_),
391  "The maximum degree allowed for any GMRES polynomial.");
392  pl->set("Outer Solver", static_cast<const char *>(outerSolverType_default_),
393  "The outer solver that this polynomial is used to precondition.");
394  pl->set("Verbosity", static_cast<int>(verbosity_default_),
395  "What type(s) of solver information should be outputted\n"
396  "to the output stream.");
397  pl->set("Output Stream", Teuchos::rcp(outputStream_default_,false),
398  "A reference-counted pointer to the output stream where all\n"
399  "solver output is sent.");
400  pl->set("Timer Label", static_cast<const char *>(label_default_),
401  "The string to use as a prefix for the timer labels.");
402  pl->set("Orthogonalization", static_cast<const char *>(orthoType_default_),
403  "The type of orthogonalization to use to generate polynomial: DGKS, ICGS, or IMGS.");
404  validPL_ = pl;
405  }
406  return validPL_;
407 }
408 
409 
410 template<class ScalarType, class MV, class OP>
413 {
414  // Create the internal parameter list if ones doesn't already exist.
415  if (params_.is_null ()) {
416  params_ = Teuchos::parameterList (*getValidParameters ());
417  }
418  else {
419  params->validateParameters (*getValidParameters ());
420  }
421 
422  // Check which Gmres polynomial to use
423  if (params->isParameter("Polynomial Type")) {
424  polyType_ = params->get("Polynomial Type", polyType_default_);
425  }
426 
427  // Update the outer solver in our list.
428  params_->set("Polynomial Type", polyType_);
429 
430  // Check if there is an outer solver for this Gmres Polynomial
431  if (params->isParameter("Outer Solver")) {
432  outerSolverType_ = params->get("Outer Solver", outerSolverType_default_);
433  }
434 
435  // Update the outer solver in our list.
436  params_->set("Outer Solver", outerSolverType_);
437 
438  // Check if there is a parameter list for the outer solver
439  if (params->isSublist("Outer Solver Params")) {
440  outerParams_ = Teuchos::parameterList( params->get<Teuchos::ParameterList>("Outer Solver Params") );
441  }
442 
443  // Check for maximum polynomial degree
444  if (params->isParameter("Maximum Degree")) {
445  maxDegree_ = params->get("Maximum Degree",maxDegree_default_);
446  }
447 
448  // Update parameter in our list.
449  params_->set("Maximum Degree", maxDegree_);
450 
451  // Check to see if the timer label changed.
452  if (params->isParameter("Timer Label")) {
453  std::string tempLabel = params->get("Timer Label", label_default_);
454 
455  // Update parameter in our list and solver timer
456  if (tempLabel != label_) {
457  label_ = tempLabel;
458 #ifdef BELOS_TEUCHOS_TIME_MONITOR
459  std::string polyLabel = label_ + ": GmresPolyOp creation time";
460  timerPoly_ = Teuchos::TimeMonitor::getNewCounter(polyLabel);
461 #endif
462  }
463  }
464 
465  // Update timer label
466  params_->set("Timer Label", label_);
467 
468  // Check if the orthogonalization changed.
469  if (params->isParameter("Orthogonalization")) {
470  std::string tempOrthoType = params->get("Orthogonalization",orthoType_default_);
471  TEUCHOS_TEST_FOR_EXCEPTION( tempOrthoType != "DGKS" && tempOrthoType != "ICGS" && tempOrthoType != "IMGS",
472  std::invalid_argument,
473  "Belos::GmresPolySolMgr: \"Orthogonalization\" must be either \"DGKS\", \"ICGS\", or \"IMGS\".");
474  if (tempOrthoType != orthoType_) {
475  orthoType_ = tempOrthoType;
476  }
477  }
478 
479  params_->set("Orthogonalization", orthoType_);
480 
481  // Check for a change in verbosity level
482  if (params->isParameter("Verbosity")) {
483  if (Teuchos::isParameterType<int>(*params,"Verbosity")) {
484  verbosity_ = params->get("Verbosity", verbosity_default_);
485  } else {
486  verbosity_ = (int)Teuchos::getParameter<Belos::MsgType>(*params,"Verbosity");
487  }
488  }
489 
490  // Update parameter in our list.
491  params_->set("Verbosity", verbosity_);
492 
493  // output stream
494  if (params->isParameter("Output Stream")) {
495  outputStream_ = Teuchos::getParameter<Teuchos::RCP<std::ostream> >(*params,"Output Stream");
496  }
497 
498  // Update parameter in our list.
499  params_->set("Output Stream", outputStream_);
500 
501  // Convergence
502  // Check for polynomial convergence tolerance
503  if (params->isParameter("Polynomial Tolerance")) {
504  if (params->isType<MagnitudeType> ("Polynomial Tolerance")) {
505  polyTol_ = params->get ("Polynomial Tolerance",
506  static_cast<MagnitudeType> (DefaultSolverParameters::polyTol));
507  }
508  else {
509  polyTol_ = params->get ("Polynomial Tolerance", DefaultSolverParameters::polyTol);
510  }
511  }
512 
513  // Update parameter in our list and residual tests.
514  params_->set("Polynomial Tolerance", polyTol_);
515 
516  // Check for maximum polynomial degree
517  if (params->isParameter("Random RHS")) {
518  randomRHS_ = params->get("Random RHS",true);
519  }
520 
521  // Update parameter in our list.
522  params_->set("Random RHS", randomRHS_);
523 
524  // Create the timers if we need to.
525 #ifdef BELOS_TEUCHOS_TIME_MONITOR
526  if (timerPoly_ == Teuchos::null) {
527  std::string polyLabel = label_ + ": GmresPolyOp creation time";
528  timerPoly_ = Teuchos::TimeMonitor::getNewCounter(polyLabel);
529  }
530 #endif
531 
532  // Check if we are going to perform an outer solve.
533  if (outerSolverType_ != "") {
534  hasOuterSolver_ = true;
535  }
536 
537  // Inform the solver manager that the current parameters were set.
538  isSet_ = true;
539 }
540 
541 
542 template<class ScalarType, class MV, class OP>
544 {
545  using Teuchos::RCP;
546  using Teuchos::rcp;
547  using Teuchos::rcp_const_cast;
548 
549  // Assume convergence is achieved if user does not require strict convergence.
551 
552  // Set the current parameters if they were not set before. NOTE:
553  // This may occur if the user generated the solver manager with the
554  // default constructor and then didn't set any parameters using
555  // setParameters().
556  if (! isSet_) {
557  setParameters (Teuchos::parameterList (*getValidParameters ()));
558  }
559 
561  problem_.is_null (), GmresPolySolMgrLinearProblemFailure,
562  "Belos::GmresPolySolMgr::solve: The linear problem has not been set yet, "
563  "or was set to null. Please call setProblem() with a nonnull input before "
564  "calling solve().");
565 
567  ! problem_->isProblemSet (), GmresPolySolMgrLinearProblemFailure,
568  "Belos::GmresPolySolMgr::solve: The linear problem is not ready. Please "
569  "call setProblem() on the LinearProblem object before calling solve().");
570 
571  // If the GMRES polynomial has not been constructed for this
572  // (nmatrix, preconditioner) pair, generate it.
573  if (!poly_dim_ && maxDegree_) {
574 #ifdef BELOS_TEUCHOS_TIME_MONITOR
575  Teuchos::TimeMonitor slvtimer(*timerPoly_);
576 #endif
577  poly_Op_ = Teuchos::rcp( new gmres_poly_t( problem_, params_ ) );
578  poly_dim_ = poly_Op_->polyDegree();
579 
581  "Belos::GmresPolyOp: Failed to generate polynomial that satisfied requirements.");
582  }
583 
584 
585  // Solve the linear system using the polynomial
586  if (hasOuterSolver_ && maxDegree_) {
587 
588  // Then the polynomial will be used as an operator for an outer solver.
589  // Use outer solver parameter list passed in a sublist.
591  RCP<SolverManager<ScalarType, MultiVec<ScalarType>, Operator<ScalarType> > > solver = factory.create( outerSolverType_, outerParams_ );
592  TEUCHOS_TEST_FOR_EXCEPTION( solver == Teuchos::null, std::invalid_argument,
593  "Belos::GmresPolySolMgr::solve(): Selected solver is not valid.");
594 
595  // Create a copy of the linear problem that uses the polynomial as a preconditioner.
596  // The original initial solution and right-hand side are thinly wrapped in the gmres_poly_mv_t
597  RCP<gmres_poly_mv_t> new_lhs = rcp( new gmres_poly_mv_t( problem_->getLHS() ) );
598  RCP<gmres_poly_mv_t> new_rhs = rcp( new gmres_poly_mv_t( rcp_const_cast<MV>( problem_->getRHS() ) ) );
599  RCP<gmres_poly_t> A = rcp( new gmres_poly_t( problem_ ) ); // This just performs problem_->applyOp
600  RCP<LinearProblem<ScalarType,MultiVec<ScalarType>,Operator<ScalarType> > > newProblem =
601  rcp( new LinearProblem<ScalarType,MultiVec<ScalarType>,Operator<ScalarType> >( A, new_lhs, new_rhs ) );
602  std::string solverLabel = label_ + ": Hybrid Gmres";
603  newProblem->setLabel(solverLabel);
604 
605  // If the preconditioner is left preconditioner, use Gmres poly as a left preconditioner.
606  if (problem_->getLeftPrec() != Teuchos::null)
607  newProblem->setLeftPrec( poly_Op_ );
608  else
609  newProblem->setRightPrec( poly_Op_ );
610  // Set the initial residual vector, if it has already been set in the original problem.
611  // Don't set the preconditioned residual vector, because it is not the GmresPoly preconditioned residual vector.
612  if (problem_->getInitResVec() != Teuchos::null)
613  newProblem->setInitResVec( rcp( new gmres_poly_mv_t( rcp_const_cast<MV>( problem_->getInitResVec() ) ) ) );
614  newProblem->setProblem();
615 
616  solver->setProblem( newProblem );
617 
618  ret = solver->solve();
619  numIters_ = solver->getNumIters();
620  loaDetected_ = solver->isLOADetected();
621 
622  } // if (hasOuterSolver_ && maxDegree_)
623  else if (hasOuterSolver_) {
624 
625  // There is no polynomial, just create the outer solver with the outerSolverType_ and outerParams_.
627  RCP<SolverManager<ScalarType, MV, OP> > solver = factory.create( outerSolverType_, outerParams_ );
628  TEUCHOS_TEST_FOR_EXCEPTION( solver == Teuchos::null, std::invalid_argument,
629  "Belos::GmresPolySolMgr::solve(): Selected solver is not valid.");
630 
631  solver->setProblem( problem_ );
632 
633  ret = solver->solve();
634  numIters_ = solver->getNumIters();
635  loaDetected_ = solver->isLOADetected();
636 
637  }
638  else if (maxDegree_) {
639 
640  // Apply the polynomial to the current linear system
641  poly_Op_->ApplyPoly( *problem_->getRHS(), *problem_->getLHS() );
642 
643  }
644 
645  return ret;
646 }
647 
648 
649 template<class ScalarType, class MV, class OP>
651 {
652  std::ostringstream out;
653 
654  out << "\"Belos::GmresPolySolMgr\": {"
655  << "ScalarType: " << Teuchos::TypeNameTraits<ScalarType>::name ()
656  << ", Poly Degree: " << poly_dim_
657  << ", Poly Max Degree: " << maxDegree_
658  << ", Poly Tol: " << polyTol_;
659  out << "}";
660  return out.str ();
661 }
662 
663 } // namespace Belos
664 
665 #endif // BELOS_GMRES_POLY_SOLMGR_HPP
Teuchos::RCP< const Teuchos::ParameterList > getCurrentParameters() const override
Get a parameter list containing the current parameters for this object.
Collection of types and exceptions used within the Belos solvers.
Belos::GmresPolyOp< ScalarType, MV, OP > gmres_poly_t
Teuchos::RCP< gmres_poly_t > poly_Op_
Teuchos::RCP< const Teuchos::ParameterList > validPL_
Cached default (valid) parameters.
ReturnType solve() override
This method performs possibly repeated calls to the underlying linear solver&#39;s iterate() routine unti...
virtual ~GmresPolySolMgr()
Destructor.
Defines the GMRES polynomial operator hybrid-GMRES iterative linear solver.
Belos::GmresPolyMv< ScalarType, MV > gmres_poly_mv_t
bool isLOADetected() const override
Return whether a loss of accuracy was detected by this solver during the most current solve...
static constexpr const char * label_default_
T & get(ParameterList &l, const std::string &name)
ParameterList & set(std::string const &name, T const &value, std::string const &docString="", RCP< const ParameterEntryValidator > const &validator=null)
Teuchos::Array< Teuchos::RCP< Teuchos::Time > > getTimers() const
Return the timers for this object.
static RCP< Time > getNewCounter(const std::string &name)
static constexpr int maxDegree_default_
#define TEUCHOS_TEST_FOR_EXCEPTION(throw_exception_test, Exception, msg)
Teuchos::RCP< Teuchos::ParameterList > outerParams_
Teuchos::RCP< Teuchos::ParameterList > params_
static const double polyTol
Relative residual tolerance for matrix polynomial construction.
Definition: BelosTypes.hpp:304
Traits class which defines basic operations on multivectors.
bool isParameter(const std::string &name) const
static constexpr std::ostream * outputStream_default_
ResetType
How to reset the solver.
Definition: BelosTypes.hpp:206
Alternative run-time polymorphic interface for operators.
GmresPolySolMgrLinearProblemFailure is thrown when the linear problem is not setup (i...
TEUCHOS_DEPRECATED RCP< T > rcp(T *p, Dealloc_T dealloc, bool owns_mem)
Pure virtual base class which describes the basic interface for a solver manager. ...
bool is_null(const RCP< T > &p)
Teuchos::ScalarTraits< ScalarType > STS
bool isSublist(const std::string &name) const
const LinearProblem< ScalarType, MV, OP > & getProblem() const override
Get current linear problem being solved for in this object.
A linear system to solve, and its associated information.
Class which describes the linear problem to be solved by the iterative solver.
void setProblem(const Teuchos::RCP< LinearProblem< ScalarType, MV, OP > > &problem) override
Set the linear problem that needs to be solved.
MultiVecTraits< ScalarType, MV > MVT
Hybrid block GMRES iterative linear solver.
static constexpr const char * orthoType_default_
int getNumIters() const override
Get the iteration count for the most recent call to solve().
ReturnType
Whether the Belos solve converged for all linear systems.
Definition: BelosTypes.hpp:155
The Belos::SolverManager is a templated virtual base class that defines the basic interface that any ...
Belos&#39;s class for applying the GMRES polynomial operator that is used by the hybrid-GMRES linear solv...
void reset(const ResetType type) override
Reset the solver.
Teuchos::RCP< Teuchos::Time > timerPoly_
void validateParameters(ParameterList const &validParamList, int const depth=1000, EValidateUsed const validateUsed=VALIDATE_USED_ENABLED, EValidateDefaults const validateDefaults=VALIDATE_DEFAULTS_ENABLED) const
std::string description() const override
Method to return description of the hybrid block GMRES solver manager.
GmresPolySolMgrPolynomialFailure is thrown when their is a problem generating the GMRES polynomial fo...
virtual Teuchos::RCP< solver_base_type > create(const std::string &solverName, const Teuchos::RCP< Teuchos::ParameterList > &solverParams)
Create, configure, and return the specified solver.
GmresPolySolMgrPolynomialFailure(const std::string &what_arg)
void setParameters(const Teuchos::RCP< Teuchos::ParameterList > &params) override
Set the parameters the solver manager should use to solve the linear problem.
bool isType(const std::string &name) const
Teuchos::ScalarTraits< ScalarType >::magnitudeType MagnitudeType
Teuchos::RCP< const Teuchos::ParameterList > getValidParameters() const override
Get a parameter list containing the valid parameters for this object.
static constexpr const char * outerSolverType_default_
Interface for multivectors used by Belos&#39; linear solvers.
Teuchos::RCP< std::ostream > outputStream_
Parent class to all Belos exceptions.
Definition: BelosTypes.hpp:60
Default parameters common to most Belos solvers.
Definition: BelosTypes.hpp:291
GmresPolySolMgr()
Empty constructor for GmresPolySolMgr. This constructor takes no arguments and sets the default value...
Belos header file which uses auto-configuration information to include necessary C++ headers...
static constexpr int verbosity_default_
Teuchos::RCP< SolverManager< ScalarType, MV, OP > > clone() const override
clone for Inverted Injection (DII)
typename::Belos::Impl::SolverFactorySelector< SC, MV, OP >::type SolverFactory
GmresPolySolMgrLinearProblemFailure(const std::string &what_arg)
static constexpr const char * polyType_default_
Teuchos::RCP< LinearProblem< ScalarType, MV, OP > > problem_
static std::string name()