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 // Belos: Block Linear Solvers Package
4 //
5 // Copyright 2004-2016 NTESS and the Belos contributors.
6 // SPDX-License-Identifier: BSD-3-Clause
7 // *****************************************************************************
8 // @HEADER
9 //
10 
11 #ifndef BELOS_GMRES_POLY_SOLMGR_HPP
12 #define BELOS_GMRES_POLY_SOLMGR_HPP
13 
17 
18 #include "BelosConfigDefs.hpp"
19 #include "BelosTypes.hpp"
20 
21 #include "BelosLinearProblem.hpp"
22 #include "BelosSolverManager.hpp"
23 #include "BelosGmresPolyOp.hpp"
26 #include "Teuchos_as.hpp"
27 #ifdef BELOS_TEUCHOS_TIME_MONITOR
28 #include "Teuchos_TimeMonitor.hpp"
29 #endif
30 
35 namespace Belos {
36 
38 
39 
47  GmresPolySolMgrLinearProblemFailure(const std::string& what_arg) : BelosError(what_arg)
48  {}};
49 
57  GmresPolySolMgrPolynomialFailure(const std::string& what_arg) : BelosError(what_arg)
58  {}};
59 
73 //
108 //
120 
121 template<class ScalarType, class MV, class OP>
122 class GmresPolySolMgr : public SolverManager<ScalarType,MV,OP> {
123 private:
124 
126 
130 
131 public:
132 
134 
135 
141  GmresPolySolMgr();
142 
163 
165  virtual ~GmresPolySolMgr() {};
166 
170  }
172 
174 
175 
178  const LinearProblem<ScalarType,MV,OP>& getProblem() const override {
179  return *problem_;
180  }
181 
185 
189 
206  MagnitudeType achievedTol() const override {
207  return achievedTol_;
208  }
209 
216  return Teuchos::tuple(timerPoly_);
217  }
218 
220  int getNumIters() const override {
221  return numIters_;
222  }
223 
227  bool isLOADetected() const override { return loaDetected_; }
228 
230 
232 
233 
235  void setProblem( const Teuchos::RCP<LinearProblem<ScalarType,MV,OP> > &problem ) override { problem_ = problem; }
236 
238  void setParameters( const Teuchos::RCP<Teuchos::ParameterList> &params ) override;
239 
241 
243 
252  void reset( const ResetType type ) override {
253  if ((type & Belos::Problem) && ! problem_.is_null ()) {
254  problem_->setProblem ();
256  poly_dim_ = 0; // Rebuild the GMRES polynomial
257  }
258  }
259 
261 
263 
281  ReturnType solve() override;
282 
284 
287 
289  std::string description() const override;
290 
292 
293 private:
294 
295  // Linear problem.
297 
298  // Output manager.
300 
301  // Current parameter list.
304 
305  // Default solver values.
306  static constexpr int maxDegree_default_ = 25;
307  static constexpr int verbosity_default_ = Belos::Errors;
308  static constexpr const char * label_default_ = "Belos";
309  static constexpr const char * outerSolverType_default_ = "";
310  static constexpr const char * polyType_default_ = "Arnoldi";
311  static constexpr const char * orthoType_default_ = "ICGS";
312  static constexpr bool addRoots_default_ = true;
313  static constexpr bool dampPoly_default_ = false;
314  static constexpr bool randomRHS_default_ = true;
315 
316  // Current solver values.
322  bool damp_;
323  bool addRoots_;
324  std::string polyType_;
325  std::string outerSolverType_;
326  std::string orthoType_;
327 
328  // Polynomial storage
331 
332  // Timers.
333  std::string label_;
335 
336  // Internal state variables.
337  bool isSet_;
339 
342 };
343 
344 
345 template<class ScalarType, class MV, class OP>
347  outputStream_ (Teuchos::rcpFromRef(std::cout)),
348  polyTol_ (DefaultSolverParameters::polyTol),
349  achievedTol_(MTS::zero()),
350  maxDegree_ (maxDegree_default_),
351  numIters_ (0),
352  verbosity_ (verbosity_default_),
353  hasOuterSolver_ (false),
354  randomRHS_ (randomRHS_default_),
355  damp_ (dampPoly_default_),
356  addRoots_ (addRoots_default_),
357  polyType_ (polyType_default_),
358  outerSolverType_ (outerSolverType_default_),
359  orthoType_ (orthoType_default_),
360  poly_dim_ (0),
361  label_ (label_default_),
362  isSet_ (false),
363  loaDetected_ (false)
364 {}
365 
366 
367 template<class ScalarType, class MV, class OP>
371  problem_ (problem),
372  outputStream_ (Teuchos::rcpFromRef(std::cout)),
373  polyTol_ (DefaultSolverParameters::polyTol),
374  maxDegree_ (maxDegree_default_),
375  numIters_ (0),
376  verbosity_ (verbosity_default_),
377  hasOuterSolver_ (false),
378  randomRHS_ (randomRHS_default_),
379  damp_ (dampPoly_default_),
380  addRoots_ (addRoots_default_),
381  polyType_ (polyType_default_),
382  outerSolverType_ (outerSolverType_default_),
383  orthoType_ (orthoType_default_),
384  poly_dim_ (0),
385  label_ (label_default_),
386  isSet_ (false),
387  loaDetected_ (false)
388 {
390  problem_.is_null (), std::invalid_argument,
391  "Belos::GmresPolySolMgr: The given linear problem is null. "
392  "Please call this constructor with a nonnull LinearProblem argument, "
393  "or call the constructor that does not take a LinearProblem.");
394 
395  // If the input parameter list is null, then the parameters take
396  // default values.
397  if (! pl.is_null ()) {
398  setParameters (pl);
399  }
400 }
401 
402 
403 template<class ScalarType, class MV, class OP>
406 {
407  if (validPL_.is_null ()) {
408  Teuchos::RCP<Teuchos::ParameterList> pl = Teuchos::parameterList ();
409 
410  // The static_cast is to resolve an issue with older clang versions which
411  // would cause the constexpr to link fail. With c++17 the problem is resolved.
412  pl->set("Polynomial Type", static_cast<const char *>(polyType_default_),
413  "The type of GMRES polynomial that is used as a preconditioner: Roots, Arnoldi, or Gmres.");
414  pl->set("Polynomial Tolerance", static_cast<MagnitudeType>(DefaultSolverParameters::polyTol),
415  "The relative residual tolerance that used to construct the GMRES polynomial.");
416  pl->set("Maximum Degree", static_cast<int>(maxDegree_default_),
417  "The maximum degree allowed for any GMRES polynomial.");
418  pl->set("Outer Solver", static_cast<const char *>(outerSolverType_default_),
419  "The outer solver that this polynomial is used to precondition.");
420  pl->set("Outer Solver Params", Teuchos::ParameterList(),
421  "Parameter list for the outer solver.");
422  pl->set("Verbosity", static_cast<int>(verbosity_default_),
423  "What type(s) of solver information should be outputted\n"
424  "to the output stream.");
425  pl->set("Output Stream", Teuchos::rcpFromRef(std::cout),
426  "A reference-counted pointer to the output stream where all\n"
427  "solver output is sent.");
428  pl->set("Timer Label", static_cast<const char *>(label_default_),
429  "The string to use as a prefix for the timer labels.");
430  pl->set("Orthogonalization", static_cast<const char *>(orthoType_default_),
431  "The type of orthogonalization to use to generate polynomial: DGKS, ICGS, or IMGS.");
432  pl->set("Random RHS", static_cast<bool>(randomRHS_default_),
433  "Add roots to polynomial for stability.");
434  pl->set("Add Roots", static_cast<bool>(addRoots_default_),
435  "Add roots to polynomial for stability.");
436  pl->set("Damp Poly", static_cast<bool>(dampPoly_default_),
437  "Damp polynomial for ill-conditioned problems.");
438  validPL_ = pl;
439  }
440  return validPL_;
441 }
442 
443 
444 template<class ScalarType, class MV, class OP>
447 {
448  // Create the internal parameter list if ones doesn't already exist.
449  if (params_.is_null ()) {
450  params_ = Teuchos::parameterList (*getValidParameters ());
451  }
452  else {
453  params->validateParameters (*getValidParameters (),0);
454  }
455 
456  // Check which Gmres polynomial to use
457  if (params->isParameter("Polynomial Type")) {
458  polyType_ = params->get("Polynomial Type", polyType_default_);
459  }
460 
461  // Update the outer solver in our list.
462  params_->set("Polynomial Type", polyType_);
463 
464  // Check if there is an outer solver for this Gmres Polynomial
465  if (params->isParameter("Outer Solver")) {
466  outerSolverType_ = params->get("Outer Solver", outerSolverType_default_);
467  }
468 
469  // Update the outer solver in our list.
470  params_->set("Outer Solver", outerSolverType_);
471 
472  // Check if there is a parameter list for the outer solver
473  if (params->isSublist("Outer Solver Params")) {
474  outerParams_ = Teuchos::parameterList( params->get<Teuchos::ParameterList>("Outer Solver Params") );
475  }
476 
477  // Check for maximum polynomial degree
478  if (params->isParameter("Maximum Degree")) {
479  maxDegree_ = params->get("Maximum Degree",maxDegree_default_);
480  }
481 
482  // Update parameter in our list.
483  params_->set("Maximum Degree", maxDegree_);
484 
485  // Check to see if the timer label changed.
486  if (params->isParameter("Timer Label")) {
487  std::string tempLabel = params->get("Timer Label", label_default_);
488 
489  // Update parameter in our list and solver timer
490  if (tempLabel != label_) {
491  label_ = tempLabel;
492 #ifdef BELOS_TEUCHOS_TIME_MONITOR
493  std::string polyLabel = label_ + ": GmresPolyOp creation time";
494  timerPoly_ = Teuchos::TimeMonitor::getNewCounter(polyLabel);
495 #endif
496  }
497  }
498 
499  // Update timer label
500  params_->set("Timer Label", label_);
501 
502  // Check if the orthogonalization changed.
503  if (params->isParameter("Orthogonalization")) {
504  std::string tempOrthoType = params->get("Orthogonalization",orthoType_default_);
506  // Ensure that the specified orthogonalization type is valid.
507  if (! factory.isValidName (tempOrthoType)) {
508  std::ostringstream os;
509  os << "Belos::GCRODRSolMgr: Invalid orthogonalization name \""
510  << tempOrthoType << "\". The following are valid options "
511  << "for the \"Orthogonalization\" name parameter: ";
512  factory.printValidNames (os);
513  throw std::invalid_argument (os.str());
514  }
515  if (tempOrthoType != orthoType_) {
516  orthoType_ = tempOrthoType;
517  }
518  }
519 
520  params_->set("Orthogonalization", orthoType_);
521 
522  // Check for a change in verbosity level
523  if (params->isParameter("Verbosity")) {
524  if (Teuchos::isParameterType<int>(*params,"Verbosity")) {
525  verbosity_ = params->get("Verbosity", verbosity_default_);
526  } else {
527  verbosity_ = (int)Teuchos::getParameter<Belos::MsgType>(*params,"Verbosity");
528  }
529  }
530 
531  // Update parameter in our list.
532  params_->set("Verbosity", verbosity_);
533 
534  // output stream
535  if (params->isParameter("Output Stream")) {
536  outputStream_ = Teuchos::getParameter<Teuchos::RCP<std::ostream> >(*params,"Output Stream");
537  }
538 
539  // Update parameter in our list.
540  params_->set("Output Stream", outputStream_);
541 
542  // Convergence
543  // Check for polynomial convergence tolerance
544  if (params->isParameter("Polynomial Tolerance")) {
545  if (params->isType<MagnitudeType> ("Polynomial Tolerance")) {
546  polyTol_ = params->get ("Polynomial Tolerance",
547  static_cast<MagnitudeType> (DefaultSolverParameters::polyTol));
548  }
549  else {
550  polyTol_ = params->get ("Polynomial Tolerance", DefaultSolverParameters::polyTol);
551  }
552  }
553 
554  // Update parameter in our list and residual tests.
555  params_->set("Polynomial Tolerance", polyTol_);
556 
557  // Check for maximum polynomial degree
558  if (params->isParameter("Random RHS")) {
559  randomRHS_ = params->get("Random RHS",randomRHS_default_);
560  }
561 
562  // Update parameter in our list.
563  params_->set("Random RHS", randomRHS_);
564 
565 
566  // Check for polynomial damping
567  if (params->isParameter("Damped Poly")) {
568  damp_ = params->get("Damped Poly",dampPoly_default_);
569  }
570  // Update parameter in our list.
571  params_->set("Damped Poly", damp_);
572 
573  // Check: Should we add roots for stability if needed?
574  if (params->isParameter("Add Roots")) {
575  addRoots_ = params->get("Add Roots",addRoots_default_);
576  }
577 
578  // Update parameter in our list.
579  params_->set("Add Roots", addRoots_);
580 
581  // Create the timers if we need to.
582 #ifdef BELOS_TEUCHOS_TIME_MONITOR
583  if (timerPoly_ == Teuchos::null) {
584  std::string polyLabel = label_ + ": GmresPolyOp creation time";
585  timerPoly_ = Teuchos::TimeMonitor::getNewCounter(polyLabel);
586  }
587 #endif
588 
589  // Check if we are going to perform an outer solve.
590  if (outerSolverType_ != "") {
591  hasOuterSolver_ = true;
592  }
593 
594  // Inform the solver manager that the current parameters were set.
595  isSet_ = true;
596 }
597 
598 
599 template<class ScalarType, class MV, class OP>
601 {
602  using Teuchos::RCP;
603  using Teuchos::rcp;
604  using Teuchos::rcp_const_cast;
605 
606  // Assume convergence is achieved if user does not require strict convergence.
608 
609  // Set the current parameters if they were not set before. NOTE:
610  // This may occur if the user generated the solver manager with the
611  // default constructor and then didn't set any parameters using
612  // setParameters().
613  if (! isSet_) {
614  setParameters (Teuchos::parameterList (*getValidParameters ()));
615  }
616 
618  problem_.is_null (), GmresPolySolMgrLinearProblemFailure,
619  "Belos::GmresPolySolMgr::solve: The linear problem has not been set yet, "
620  "or was set to null. Please call setProblem() with a nonnull input before "
621  "calling solve().");
622 
624  ! problem_->isProblemSet (), GmresPolySolMgrLinearProblemFailure,
625  "Belos::GmresPolySolMgr::solve: The linear problem is not ready. Please "
626  "call setProblem() on the LinearProblem object before calling solve().");
627 
628  // If the GMRES polynomial has not been constructed for this
629  // (nmatrix, preconditioner) pair, generate it.
630  if (!poly_dim_ && maxDegree_) {
631 #ifdef BELOS_TEUCHOS_TIME_MONITOR
632  Teuchos::TimeMonitor slvtimer(*timerPoly_);
633 #endif
634  poly_Op_ = Teuchos::rcp( new gmres_poly_t( problem_, params_ ) );
635  poly_dim_ = poly_Op_->polyDegree();
636 
638  "Belos::GmresPolyOp: Failed to generate polynomial that satisfied requirements.");
639  }
640 
641 
642  // Solve the linear system using the polynomial
643  if (hasOuterSolver_ && maxDegree_) {
644 
645  // Then the polynomial will be used as an operator for an outer solver.
646  // Use outer solver parameter list passed in a sublist.
648  RCP<SolverManager<ScalarType, MultiVec<ScalarType>, Operator<ScalarType> > > solver = factory.create( outerSolverType_, outerParams_ );
649  TEUCHOS_TEST_FOR_EXCEPTION( solver == Teuchos::null, std::invalid_argument,
650  "Belos::GmresPolySolMgr::solve(): Selected solver is not valid.");
651 
652  // Create a copy of the linear problem that uses the polynomial as a preconditioner.
653  // The original initial solution and right-hand side are thinly wrapped in the gmres_poly_mv_t
654  RCP<gmres_poly_mv_t> new_lhs = rcp( new gmres_poly_mv_t( problem_->getLHS() ) );
655  RCP<gmres_poly_mv_t> new_rhs = rcp( new gmres_poly_mv_t( rcp_const_cast<MV>( problem_->getRHS() ) ) );
656  RCP<gmres_poly_t> A = rcp( new gmres_poly_t( problem_ ) ); // This just performs problem_->applyOp
657  RCP<LinearProblem<ScalarType,MultiVec<ScalarType>,Operator<ScalarType> > > newProblem =
658  rcp( new LinearProblem<ScalarType,MultiVec<ScalarType>,Operator<ScalarType> >( A, new_lhs, new_rhs ) );
659  std::string solverLabel = label_ + ": Hybrid Gmres";
660  newProblem->setLabel(solverLabel);
661 
662  // If the preconditioner is left preconditioner, use Gmres poly as a left preconditioner.
663  if (problem_->getLeftPrec() != Teuchos::null)
664  newProblem->setLeftPrec( poly_Op_ );
665  else
666  newProblem->setRightPrec( poly_Op_ );
667  // Set the initial residual vector, if it has already been set in the original problem.
668  // Don't set the preconditioned residual vector, because it is not the GmresPoly preconditioned residual vector.
669  if (problem_->getInitResVec() != Teuchos::null)
670  newProblem->setInitResVec( rcp( new gmres_poly_mv_t( rcp_const_cast<MV>( problem_->getInitResVec() ) ) ) );
671  newProblem->setProblem();
672 
673  solver->setProblem( newProblem );
674 
675  ret = solver->solve();
676  numIters_ = solver->getNumIters();
677  loaDetected_ = solver->isLOADetected();
678  achievedTol_ = solver->achievedTol();
679 
680  } // if (hasOuterSolver_ && maxDegree_)
681  else if (hasOuterSolver_) {
682 
683  // There is no polynomial, just create the outer solver with the outerSolverType_ and outerParams_.
685  RCP<SolverManager<ScalarType, MV, OP> > solver = factory.create( outerSolverType_, outerParams_ );
686  TEUCHOS_TEST_FOR_EXCEPTION( solver == Teuchos::null, std::invalid_argument,
687  "Belos::GmresPolySolMgr::solve(): Selected solver is not valid.");
688 
689  solver->setProblem( problem_ );
690 
691  ret = solver->solve();
692  numIters_ = solver->getNumIters();
693  loaDetected_ = solver->isLOADetected();
694  achievedTol_ = solver->achievedTol();
695 
696  }
697  else if (maxDegree_) {
698 
699  // Apply the polynomial to the current linear system
700  poly_Op_->ApplyPoly( *problem_->getRHS(), *problem_->getLHS() );
701  achievedTol_ = MTS::one();
702 
703  }
704 
705  return ret;
706 }
707 
708 
709 template<class ScalarType, class MV, class OP>
711 {
712  std::ostringstream out;
713 
714  out << "\"Belos::GmresPolySolMgr\": {"
715  << "ScalarType: " << Teuchos::TypeNameTraits<ScalarType>::name ()
716  << ", Poly Degree: " << poly_dim_
717  << ", Poly Max Degree: " << maxDegree_
718  << ", Poly Tol: " << polyTol_;
719  out << "}";
720  return out.str ();
721 }
722 
723 } // namespace Belos
724 
725 #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)
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_
ParameterList & set(std::string const &name, T &&value, std::string const &docString="", RCP< const ParameterEntryValidator > const &validator=null)
Teuchos::RCP< Teuchos::ParameterList > params_
static const double polyTol
Relative residual tolerance for matrix polynomial construction.
Definition: BelosTypes.hpp:264
bool isParameter(const std::string &name) const
ResetType
How to reset the solver.
Definition: BelosTypes.hpp:174
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)
static constexpr bool addRoots_default_
bool isValidName(const std::string &name) const
Whether this factory recognizes the MatOrthoManager with the given name.
bool isSublist(const std::string &name) const
std::ostream & printValidNames(std::ostream &out) const
Print all recognized MatOrthoManager names to the given ostream.
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.
The GMRES polynomial can be created in conjunction with any standard preconditioner.
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:123
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.
static constexpr bool randomRHS_default_
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:28
Default parameters common to most Belos solvers.
Definition: BelosTypes.hpp:251
GmresPolySolMgr()
Empty constructor for GmresPolySolMgr. This constructor takes no arguments and sets the default value...
static constexpr bool dampPoly_default_
MagnitudeType achievedTol() const override
Tolerance achieved by the last solve() invocation.
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()
Teuchos::ScalarTraits< MagnitudeType > MTS