Beispiel #1
0
void
petscSetOptions(FEProblem & problem)
{
  // Reference to the options stored in FEPRoblem
  PetscOptions & petsc = problem.getPetscOptions();

  if (petsc.inames.size() != petsc.values.size())
    mooseError("PETSc names and options are not the same length");

  PetscOptionsClear();

  { // Get any options specified on the command-line
    int argc;
    char ** args;

    PetscGetArgs(&argc, &args);
    PetscOptionsInsert(&argc, &args, NULL);
  }

  setSolverOptions(problem.solverParams());

  // Add any additional options specified in the input file
  for (MooseEnumIterator it = petsc.flags.begin(); it != petsc.flags.end(); ++it)
    PetscOptionsSetValue(it->c_str(), PETSC_NULL);
  for (unsigned int i=0; i<petsc.inames.size(); ++i)
    PetscOptionsSetValue(petsc.inames[i].c_str(), petsc.values[i].c_str());

  SolverParams& solver_params = problem.solverParams();
  if (solver_params._type != Moose::ST_JFNK  &&
      solver_params._type != Moose::ST_FD &&
      !problem.getNonlinearSystem().haveFiniteDifferencedPreconditioner() &&
      problem.getNonlinearSystem().haveDecomposition())
  {
    // Set up DM only if have a decomposition. Additionally, turn DM OFF if not using FD-based solvers,
    // (both -snes_mf and -snes_fd) and FDP. This is all rather crufty, but what's a good generic rule here?
    // In principle at least, splits should be able to work with ST_FD (-snes_fd) and FDP (a coloring-based
    // version of -snes_fd), but one has to be careful about the initialization order so as not to override
    // SNESComputeJacobianDefaultColor() set up by FDP, for instance.  However, it's unlikely that splits
    // will be used when running an FD solver (debugging).
    problem.getNonlinearSystem().setupDecomposition();
    petscSetupDM(problem.getNonlinearSystem());
  } else {
    // Otherwise turn off the decomposition
    std::vector<std::string> nosplits;
    problem.getNonlinearSystem().setDecomposition(nosplits);
  }

}
Beispiel #2
0
void
CreateExecutionerAction::storeCommonExecutionerParams(FEProblem & fe_problem, InputParameters & params)
{
  // Note: Options set in the Preconditioner block will override those set in the Executioner block
  if (params.isParamValid("solve_type"))
  {
    // Extract the solve type
    const std::string & solve_type = params.get<MooseEnum>("solve_type");
    fe_problem.solverParams()._type = Moose::stringToEnum<Moose::SolveType>(solve_type);
  }

  MooseEnum line_search = params.get<MooseEnum>("line_search");
  if (fe_problem.solverParams()._line_search == Moose::LS_INVALID || line_search != "default")
    fe_problem.solverParams()._line_search = Moose::stringToEnum<Moose::LineSearchType>(line_search);

#ifdef LIBMESH_HAVE_PETSC
  MultiMooseEnum           petsc_options       = params.get<MultiMooseEnum>("petsc_options");
  std::vector<std::string> petsc_options_iname = params.get<std::vector<std::string> >("petsc_options_iname");
  std::vector<std::string> petsc_options_value = params.get<std::vector<std::string> >("petsc_options_value");

  fe_problem.storePetscOptions(petsc_options, petsc_options_iname, petsc_options_value);
#endif //LIBMESH_HAVE_PETSC
}
Beispiel #3
0
void
petscSetOptions(FEProblem & problem)
{
  // Reference to the options stored in FEPRoblem
  PetscOptions & petsc = problem.getPetscOptions();

  if (petsc.inames.size() != petsc.values.size())
    mooseError("PETSc names and options are not the same length");

#if PETSC_VERSION_LESS_THAN(3,7,0)
  PetscOptionsClear();
#else
  PetscOptionsClear(PETSC_NULL);
#endif

  setSolverOptions(problem.solverParams());

  // Add any additional options specified in the input file
  for (const auto & flag : petsc.flags)
    setSinglePetscOption(flag.c_str());
  for (unsigned int i=0; i<petsc.inames.size(); ++i)
    setSinglePetscOption(petsc.inames[i], petsc.values[i]);

  // set up DM which is required if use a field split preconditioner
  if (problem.getNonlinearSystem().haveFieldSplitPreconditioner())
    petscSetupDM(problem.getNonlinearSystem());

  // commandline options always win
  // the options from a user commandline will overwrite the existing ones if any conflicts
  { // Get any options specified on the command-line
    int argc;
    char ** args;

    PetscGetArgs(&argc, &args);
#if PETSC_VERSION_LESS_THAN(3,7,0)
    PetscOptionsInsert(&argc, &args, NULL);
#else
    PetscOptionsInsert(PETSC_NULL, &argc, &args, NULL);
#endif
  }
}
Beispiel #4
0
std::string
outputExecutionInformation(MooseApp & app, FEProblem & problem)
{

  std::stringstream oss;
  oss << std::left;

  Executioner * exec = app.getExecutioner();

  oss << "Execution Information:\n"
      << std::setw(console_field_width) << "  Executioner: " << demangle(typeid(*exec).name()) << '\n';

  std::string time_stepper = exec->getTimeStepperName();
  if (time_stepper != "")
    oss << std::setw(console_field_width) << "  TimeStepper: " << time_stepper << '\n';

  oss << std::setw(console_field_width) << "  Solver Mode: " << Moose::stringify<Moose::SolveType>(problem.solverParams()._type) << '\n';

  const std::string & pc_desc = problem.getPetscOptions().pc_description;
  if (!pc_desc.empty())
    oss << std::setw(console_field_width) << "  Preconditioner: " << pc_desc << '\n';
  oss << '\n';

  return oss.str();
}
Beispiel #5
0
void
storePetscOptions(FEProblem & fe_problem, const InputParameters & params)
{
  // Note: Options set in the Preconditioner block will override those set in the Executioner block
  if (params.isParamValid("solve_type"))
  {
    // Extract the solve type
    const std::string & solve_type = params.get<MooseEnum>("solve_type");
    fe_problem.solverParams()._type = Moose::stringToEnum<Moose::SolveType>(solve_type);
  }

  if (params.isParamValid("line_search"))
  {
      MooseEnum line_search = params.get<MooseEnum>("line_search");
      if (fe_problem.solverParams()._line_search == Moose::LS_INVALID || line_search != "default")
        fe_problem.solverParams()._line_search = Moose::stringToEnum<Moose::LineSearchType>(line_search);
  }

  // The parameters contained in the Action
  const MultiMooseEnum & petsc_options = params.get<MultiMooseEnum>("petsc_options");
  const MultiMooseEnum & petsc_options_inames = params.get<MultiMooseEnum>("petsc_options_iname");
  const std::vector<std::string> & petsc_options_values = params.get<std::vector<std::string> >("petsc_options_value");

  // A reference to the PetscOptions object that contains the settings that will be used in the solve
  Moose::PetscSupport::PetscOptions & po = fe_problem.getPetscOptions();

  // Update the PETSc single flags
  for (const auto & option : petsc_options)
  {
    /**
     * "-log_summary" cannot be used in the input file. This option needs to be set when PETSc is initialized
     * which happens before the parser is even created.  We'll throw an error if somebody attempts to add this option later.
     */
    if (option == "-log_summary")
      mooseError("The PETSc option \"-log_summary\" can only be used on the command line.  Please remove it from the input file");

    // Warn about superseded PETSc options (Note: -snes is not a REAL option, but people used it in their input files)
    else
    {
      std::string help_string;
      if (option == "-snes" || option == "-snes_mf" || option == "-snes_mf_operator")
        help_string = "Please set the solver type through \"solve_type\".";
      else if (option == "-ksp_monitor")
        help_string = "Please use \"Outputs/print_linear_residuals=true\"";

      if (help_string != "")
        mooseWarning("The PETSc option " << option << " should not be used directly in a MOOSE input file. " << help_string);
    }

    // Update the stored items, but do not create duplicates
    if (find(po.flags.begin(), po.flags.end(), option) == po.flags.end())
      po.flags.push_back(option);
  }

  // Check that the name value pairs are sized correctly
  if (petsc_options_inames.size() != petsc_options_values.size())
    mooseError("PETSc names and options are not the same length");

  // Setup the name value pairs
  bool boomeramg_found = false;
  bool strong_threshold_found = false;
  std::string pc_description = "";
  for (unsigned int i = 0; i < petsc_options_inames.size(); i++)
  {
    // Do not add duplicate settings
    if (find(po.inames.begin(), po.inames.end(), petsc_options_inames[i]) == po.inames.end())
    {
      po.inames.push_back(petsc_options_inames[i]);
      po.values.push_back(petsc_options_values[i]);

      // Look for a pc description
      if (petsc_options_inames[i] == "-pc_type" || petsc_options_inames[i] == "-pc_sub_type" || petsc_options_inames[i] == "-pc_hypre_type")
        pc_description += petsc_options_values[i] + ' ';

      // This special case is common enough that we'd like to handle it for the user.
      if (petsc_options_inames[i] == "-pc_hypre_type" && petsc_options_values[i] == "boomeramg")
        boomeramg_found = true;
      if (petsc_options_inames[i] == "-pc_hypre_boomeramg_strong_threshold")
        strong_threshold_found = true;
    }
    else
    {
      for (unsigned int j = 0; j < po.inames.size(); j++)
        if (po.inames[j] == petsc_options_inames[i])
          po.values[j] = petsc_options_values[i];
    }
  }


  // When running a 3D mesh with boomeramg, it is almost always best to supply a strong threshold value
  // We will provide that for the user here if they haven't supplied it themselves.
  if (boomeramg_found && !strong_threshold_found && fe_problem.mesh().dimension() == 3)
  {
    po.inames.push_back("-pc_hypre_boomeramg_strong_threshold");
    po.values.push_back("0.7");
    pc_description += "strong_threshold: 0.7 (auto)";
  }

  // Set Preconditioner description
  po.pc_description = pc_description;
}