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(); }
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); } }
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 } }
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; }