Teuchos::RCP<const Teuchos::ParameterList>
PardisoMKL<Matrix,Vector>::getValidParameters_impl() const
{
  using std::string;
  using Teuchos::as;
  using Teuchos::RCP;
  using Teuchos::tuple;
  using Teuchos::toString;
  using Teuchos::EnhancedNumberValidator;
  using Teuchos::setStringToIntegralParameter;
  using Teuchos::anyNumberParameterEntryValidator;
  using Teuchos::stringToIntegralParameterEntryValidator;
  typedef Teuchos::StringToIntegralParameterEntryValidator<int> STIPEV;
  Teuchos::AnyNumberParameterEntryValidator::EPreferredType preferred_int =
    Teuchos::AnyNumberParameterEntryValidator::PREFER_INT;

  static Teuchos::RCP<const Teuchos::ParameterList> valid_params;

  if( is_null(valid_params) ){
    Teuchos::RCP<Teuchos::ParameterList> pl = Teuchos::parameterList();

    // Use pardisoinit to get some default values;
    void *pt_dummy[64];
    PMKL::_INTEGER_t mtype_temp = mtype_;
    PMKL::_INTEGER_t iparm_temp[64];
    PMKL::pardisoinit(pt_dummy,
                      const_cast<PMKL::_INTEGER_t*>(&mtype_temp),
                      const_cast<PMKL::_INTEGER_t*>(iparm_temp));

    // Initialize our parameter validators, saving the string to int validators for later
    RCP<STIPEV> iparm_2_validator
      = stringToIntegralParameterEntryValidator<int>(tuple<string>("0", "2", "3"),
						     tuple<string>("The minimum degree algorithm",
								   "Nested dissection algorithm from METIS",
								   "OpenMP parallel nested dissection algorithm"),
						     tuple<int>(0, 2, 3),
						     toString(iparm_temp[1]));
    validators.insert( std::pair<int,RCP<STIPEV> >(2, iparm_2_validator) );
    
    Teuchos::RCP<EnhancedNumberValidator<int> > iparm_4_validator
      = Teuchos::rcp( new EnhancedNumberValidator<int>() );
    iparm_4_validator->setMin(0);

    RCP<STIPEV> iparm_24_validator
      = stringToIntegralParameterEntryValidator<int>(tuple<string>("0", "1"),
						     tuple<string>("PARDISO uses the previous algorithm for factorization",
								   "PARDISO uses the new two-level factorization algorithm"),
						     tuple<int>(0, 1),
						     toString(iparm_temp[23]));
    validators.insert( std::pair<int,RCP<STIPEV> >(24, iparm_24_validator) );

    RCP<STIPEV> iparm_25_validator
      = stringToIntegralParameterEntryValidator<int>(tuple<string>("0", "1"),
						     tuple<string>("PARDISO uses the parallel algorithm for the solve step",
								   "PARDISO uses the sequential forward and backward solve"),
						     tuple<int>(0, 1),
						     toString(iparm_temp[24]));
    validators.insert( std::pair<int,RCP<STIPEV> >(25, iparm_25_validator) );

    RCP<STIPEV> iparm_60_validator
      = stringToIntegralParameterEntryValidator<int>(tuple<string>("0", "2"),
						     tuple<string>("In-core PARDISO",
								   "Out-of-core PARDISO.  The OOC PARDISO can solve very "
								   "large problems by holding the matrix factors in files "
								   "on the disk. Hence the amount of RAM required by OOC "
								   "PARDISO is significantly reduced."),
						     tuple<int>(0, 2),
						     toString(iparm_temp[59]));
    validators.insert( std::pair<int,RCP<STIPEV> >(60, iparm_60_validator) );

    Teuchos::AnyNumberParameterEntryValidator::AcceptedTypes accept_int( false );
    accept_int.allowInt( true );

    pl->set("IPARM(2)" , validators[2]->getDefaultParameterName(),
	    "Fill-in reducing ordering for the input matrix", validators[2]);

    pl->set("IPARM(4)" , as<int>(iparm_temp[3]) , "Preconditioned CGS/CG",
            iparm_4_validator);

    pl->set("IPARM(8)" , as<int>(iparm_temp[8]) , "Iterative refinement step",
            anyNumberParameterEntryValidator(preferred_int, accept_int));

    pl->set("IPARM(10)", as<int>(iparm_temp[9]) , "Pivoting perturbation",
            anyNumberParameterEntryValidator(preferred_int, accept_int));

    pl->set("IPARM(18)", as<int>(iparm_temp[17]), "Report the number of non-zero elements in the factors",
            anyNumberParameterEntryValidator(preferred_int, accept_int));

    pl->set("IPARM(24)", validators[24]->getDefaultParameterName(),
	    "Parallel factorization control", validators[24]);
    
    pl->set("IPARM(25)", validators[25]->getDefaultParameterName(),
	    "Parallel forward/backward solve control", validators[25]);

    pl->set("IPARM(60)", validators[60]->getDefaultParameterName(),
	    "PARDISO mode (OOC mode)", validators[60]);

    valid_params = pl;
  }

  return valid_params;
}