https://mooseframework.inl.gov
PetscSupport.C
Go to the documentation of this file.
1 //* This file is part of the MOOSE framework
2 //* https://mooseframework.inl.gov
3 //*
4 //* All rights reserved, see COPYRIGHT for full restrictions
5 //* https://github.com/idaholab/moose/blob/master/COPYRIGHT
6 //*
7 //* Licensed under LGPL 2.1, please see LICENSE for details
8 //* https://www.gnu.org/licenses/lgpl-2.1.html
9 
10 #include "PetscSupport.h"
11 
12 // MOOSE includes
13 #include "MooseApp.h"
14 #include "FEProblem.h"
15 #include "DisplacedProblem.h"
16 #include "NonlinearSystem.h"
17 #include "LinearSystem.h"
18 #include "DisplacedProblem.h"
19 #include "PenetrationLocator.h"
20 #include "NearestNodeLocator.h"
21 #include "MooseTypes.h"
22 #include "MooseUtils.h"
23 #include "CommandLine.h"
24 #include "Console.h"
25 #include "MultiMooseEnum.h"
26 #include "Conversion.h"
27 #include "Executioner.h"
28 #include "MooseMesh.h"
30 #include "Convergence.h"
31 #include "ParallelParamObject.h"
32 
33 #include "libmesh/equation_systems.h"
34 #include "libmesh/linear_implicit_system.h"
35 #include "libmesh/nonlinear_implicit_system.h"
36 #include "libmesh/petsc_linear_solver.h"
37 #include "libmesh/petsc_matrix.h"
38 #include "libmesh/petsc_nonlinear_solver.h"
39 #include "libmesh/petsc_preconditioner.h"
40 #include "libmesh/petsc_vector.h"
41 #include "libmesh/sparse_matrix.h"
42 #include "libmesh/petsc_solver_exception.h"
43 #include "libmesh/simple_range.h"
44 
45 // PETSc includes
46 #include <petsc.h>
47 #include <petscsnes.h>
48 #include <petscksp.h>
49 
50 // For graph coloring
51 #include <petscmat.h>
52 #include <petscis.h>
53 #include <petscdm.h>
54 
55 // PetscDMMoose include
56 #include "PetscDMMoose.h"
57 
58 // Standard includes
59 #include <ostream>
60 #include <fstream>
61 #include <string>
62 
63 using namespace libMesh;
64 
65 void
67 {
68  PetscVector<Number> & petsc_vec = static_cast<PetscVector<Number> &>(vector);
69  LibmeshPetscCallA(vector.comm().get(), VecView(petsc_vec.vec(), 0));
70 }
71 
72 void
74 {
75  PetscMatrixBase<Number> & petsc_mat = static_cast<PetscMatrix<Number> &>(mat);
76  LibmeshPetscCallA(mat.comm().get(), MatView(petsc_mat.mat(), 0));
77 }
78 
79 void
81 {
82  PetscVector<Number> & petsc_vec =
83  static_cast<PetscVector<Number> &>(const_cast<NumericVector<Number> &>(vector));
84  LibmeshPetscCallA(vector.comm().get(), VecView(petsc_vec.vec(), 0));
85 }
86 
87 void
89 {
90  PetscMatrixBase<Number> & petsc_mat =
91  static_cast<PetscMatrix<Number> &>(const_cast<SparseMatrix<Number> &>(mat));
92  LibmeshPetscCallA(mat.comm().get(), MatView(petsc_mat.mat(), 0));
93 }
94 
95 namespace Moose
96 {
97 namespace PetscSupport
98 {
99 
100 std::string
102 {
103  switch (t)
104  {
105  case LS_BASIC:
106  return "basic";
107  case LS_DEFAULT:
108  return "default";
109  case LS_NONE:
110  return "none";
111  case LS_SHELL:
112  return "shell";
113  case LS_L2:
114  return "l2";
115  case LS_BT:
116  return "bt";
117  case LS_CP:
118  return "cp";
119  case LS_CONTACT:
120  return "contact";
121  case LS_PROJECT:
122  return "project";
123  case LS_INVALID:
124  mooseError("Invalid LineSearchType");
125  }
126  return "";
127 }
128 
129 std::string
130 stringify(const MffdType & t)
131 {
132  switch (t)
133  {
134  case MFFD_WP:
135  return "wp";
136  case MFFD_DS:
137  return "ds";
138  case MFFD_INVALID:
139  mooseError("Invalid MffdType");
140  }
141  return "";
142 }
143 
144 void
145 setSolverOptions(const SolverParams & solver_params, const MultiMooseEnum & dont_add_these_options)
146 {
147  // set PETSc options implied by a solve type
148  switch (solver_params._type)
149  {
150  case Moose::ST_PJFNK:
151  setSinglePetscOptionIfAppropriate(dont_add_these_options,
152  solver_params._prefix + "snes_mf_operator");
153  setSinglePetscOptionIfAppropriate(dont_add_these_options,
154  solver_params._prefix + "mat_mffd_type",
155  stringify(solver_params._mffd_type));
156  break;
157 
158  case Moose::ST_JFNK:
159  setSinglePetscOptionIfAppropriate(dont_add_these_options, solver_params._prefix + "snes_mf");
160  setSinglePetscOptionIfAppropriate(dont_add_these_options,
161  solver_params._prefix + "mat_mffd_type",
162  stringify(solver_params._mffd_type));
163  break;
164 
165  case Moose::ST_NEWTON:
166  break;
167 
168  case Moose::ST_FD:
169  setSinglePetscOptionIfAppropriate(dont_add_these_options, solver_params._prefix + "snes_fd");
170  break;
171 
172  case Moose::ST_LINEAR:
174  dont_add_these_options, solver_params._prefix + "snes_type", "ksponly");
175  setSinglePetscOptionIfAppropriate(dont_add_these_options,
176  solver_params._prefix + "snes_monitor_cancel");
177  break;
178  }
179 
180  Moose::LineSearchType ls_type = solver_params._line_search;
181  if (ls_type == Moose::LS_NONE)
182  ls_type = Moose::LS_BASIC;
183 
184  if (ls_type != Moose::LS_DEFAULT && ls_type != Moose::LS_CONTACT && ls_type != Moose::LS_PROJECT)
186  dont_add_these_options, solver_params._prefix + "snes_linesearch_type", stringify(ls_type));
187 }
188 
189 void
190 petscSetupDM(NonlinearSystemBase & nl, const std::string & dm_name)
191 {
192  PetscBool ismoose;
193  DM dm = LIBMESH_PETSC_NULLPTR;
194 
195  // Initialize the part of the DM package that's packaged with Moose; in the PETSc source tree this
196  // call would be in DMInitializePackage()
197  LibmeshPetscCallA(nl.comm().get(), DMMooseRegisterAll());
198  // Create and set up the DM that will consume the split options and deal with block matrices.
199  PetscNonlinearSolver<Number> * petsc_solver =
200  dynamic_cast<PetscNonlinearSolver<Number> *>(nl.nonlinearSolver());
201  const char * snes_prefix = nullptr;
202  std::string snes_prefix_str;
203  if (nl.system().prefix_with_name())
204  {
205  snes_prefix_str = nl.system().prefix();
206  snes_prefix = snes_prefix_str.c_str();
207  }
208  SNES snes = petsc_solver->snes(snes_prefix);
209  // if there exists a DMMoose object, not to recreate a new one
210  LibmeshPetscCallA(nl.comm().get(), SNESGetDM(snes, &dm));
211  if (dm)
212  {
213  LibmeshPetscCallA(nl.comm().get(), PetscObjectTypeCompare((PetscObject)dm, DMMOOSE, &ismoose));
214  if (ismoose)
215  return;
216  }
217  LibmeshPetscCallA(nl.comm().get(), DMCreateMoose(nl.comm().get(), nl, dm_name, &dm));
218  LibmeshPetscCallA(nl.comm().get(), DMSetFromOptions(dm));
219  LibmeshPetscCallA(nl.comm().get(), DMSetUp(dm));
220  LibmeshPetscCallA(nl.comm().get(), SNESSetDM(snes, dm));
221  LibmeshPetscCallA(nl.comm().get(), DMDestroy(&dm));
222  // We temporarily comment out this updating function because
223  // we lack an approach to check if the problem
224  // structure has been changed from the last iteration.
225  // The indices will be rebuilt for every timestep.
226  // TODO: figure out a way to check the structure changes of the
227  // matrix
228  // ierr = SNESSetUpdate(snes,SNESUpdateDMMoose);
229  // CHKERRABORT(nl.comm().get(),ierr);
230 }
231 
232 void
234 {
235  // commandline options always win
236  // the options from a user commandline will overwrite the existing ones if any conflicts
237  { // Get any options specified on the command-line
238  int argc;
239  char ** args;
240 
241  LibmeshPetscCallA(PETSC_COMM_WORLD, PetscGetArgs(&argc, &args));
242 #if PETSC_VERSION_LESS_THAN(3, 7, 0)
243  LibmeshPetscCallA(PETSC_COMM_WORLD, PetscOptionsInsert(&argc, &args, NULL));
244 #else
245  LibmeshPetscCallA(PETSC_COMM_WORLD,
246  PetscOptionsInsert(LIBMESH_PETSC_NULLPTR, &argc, &args, NULL));
247 #endif
248  }
249 }
250 
251 void
253 {
254  // Add any additional options specified in the input file
255  for (const auto & flag : po.flags)
256  // Need to use name method here to pass a str instead of an EnumItem because
257  // we don't care if the id attributes match
258  if (!po.dont_add_these_options.contains(flag.name()) ||
259  po.user_set_options.contains(flag.name()))
260  setSinglePetscOption(flag.rawName().c_str());
261 
262  // Add option pairs
263  for (auto & option : po.pairs)
264  if (!po.dont_add_these_options.contains(option.first) ||
265  po.user_set_options.contains(option.first))
266  setSinglePetscOption(option.first, option.second, problem);
267 
269 }
270 
271 void
273  const SolverParams & solver_params,
274  FEProblemBase * const problem)
275 {
276  PetscCallAbort(PETSC_COMM_WORLD, PetscOptionsClear(LIBMESH_PETSC_NULLPTR));
277  setSolverOptions(solver_params, po.dont_add_these_options);
278  petscSetOptionsHelper(po, problem);
279 }
280 
281 void
283  const std::vector<SolverParams> & solver_params_vec,
284  FEProblemBase * const problem)
285 {
286  PetscCallAbort(PETSC_COMM_WORLD, PetscOptionsClear(LIBMESH_PETSC_NULLPTR));
287  for (const auto & solver_params : solver_params_vec)
288  setSolverOptions(solver_params, po.dont_add_these_options);
289  petscSetOptionsHelper(po, problem);
290 }
291 
292 PetscErrorCode
294 {
296  char code[10] = {45, 45, 109, 111, 111, 115, 101};
297  const std::vector<std::string> argv = cmd_line->getArguments();
298  for (const auto & arg : argv)
299  {
300  if (arg.compare(code) == 0)
301  {
303  break;
304  }
305  }
306  PetscFunctionReturn(PETSC_SUCCESS);
307 }
308 
309 PetscErrorCode
311  PetscInt it,
312  PetscReal /*xnorm*/,
313  PetscReal /*snorm*/,
314  PetscReal /*fnorm*/,
315  SNESConvergedReason * reason,
316  void * ctx)
317 {
319  FEProblemBase & problem = *static_cast<FEProblemBase *>(ctx);
320 
321  // execute objects that may be used in convergence check
323 
324  // perform the convergence check
327  {
330  }
331  else
332  {
333  auto & convergence = problem.getConvergence(
335  status = convergence.checkConvergence(it);
336  }
337 
338  // convert convergence status to PETSc converged reason
339  switch (status)
340  {
342  *reason = SNES_CONVERGED_ITERATING;
343  break;
344 
346  *reason = SNES_CONVERGED_FNORM_ABS;
347  break;
348 
350  *reason = SNES_DIVERGED_DTOL;
351  break;
352  }
353 
354  PetscFunctionReturn(PETSC_SUCCESS);
355 }
356 
357 PetscErrorCode
359  KSP /*ksp*/, PetscInt it, PetscReal /*norm*/, KSPConvergedReason * reason, void * ctx)
360 {
362  FEProblemBase & problem = *static_cast<FEProblemBase *>(ctx);
363 
364  // execute objects that may be used in convergence check
365  // Right now, setting objects to execute on this flag would be ignored except in the
366  // linear-system-only use case.
368 
369  // perform the convergence check
371  if (problem.getFailNextSystemConvergenceCheck())
372  {
375  }
376  else
377  {
378  auto & convergence = problem.getConvergence(
379  problem.getLinearConvergenceNames()[problem.currentLinearSystem().number()]);
380  status = convergence.checkConvergence(it);
381  }
382 
383  // convert convergence status to PETSc converged reason
384  switch (status)
385  {
387  *reason = KSP_CONVERGED_ITERATING;
388  break;
389 
390  // TODO: find a KSP code that works better for this case
392  *reason = KSP_CONVERGED_RTOL_NORMAL;
393  break;
394 
396  *reason = KSP_DIVERGED_DTOL;
397  break;
398  }
399 
400  PetscFunctionReturn(PETSC_SUCCESS);
401 }
402 
403 PCSide
405 {
406  switch (pcs)
407  {
408  case Moose::PCS_LEFT:
409  return PC_LEFT;
410  case Moose::PCS_RIGHT:
411  return PC_RIGHT;
413  return PC_SYMMETRIC;
414  default:
415  mooseError("Unknown PC side requested.");
416  break;
417  }
418 }
419 
420 KSPNormType
422 {
423  switch (kspnorm)
424  {
425  case Moose::KSPN_NONE:
426  return KSP_NORM_NONE;
428  return KSP_NORM_PRECONDITIONED;
430  return KSP_NORM_UNPRECONDITIONED;
431  case Moose::KSPN_NATURAL:
432  return KSP_NORM_NATURAL;
433  case Moose::KSPN_DEFAULT:
434  return KSP_NORM_DEFAULT;
435  default:
436  mooseError("Unknown KSP norm type requested.");
437  break;
438  }
439 }
440 
441 void
443 {
444  for (const auto i : make_range(problem.numSolverSystems()))
445  {
446  SolverSystem & sys = problem.getSolverSystem(i);
447  LibmeshPetscCallA(problem.comm().get(),
448  KSPSetNormType(ksp, getPetscKSPNormType(sys.getMooseKSPNormType())));
449  }
450 }
451 
452 void
454 {
455  for (const auto i : make_range(problem.numSolverSystems()))
456  {
457  SolverSystem & sys = problem.getSolverSystem(i);
458 
459  // PETSc 3.2.x+
460  if (sys.getPCSide() != Moose::PCS_DEFAULT)
461  LibmeshPetscCallA(problem.comm().get(), KSPSetPCSide(ksp, getPetscPCSide(sys.getPCSide())));
462  }
463 }
464 
465 void
467 {
468  auto & es = problem.es();
469 
470  PetscReal rtol = es.parameters.get<Real>("linear solver tolerance");
471  PetscReal atol = es.parameters.get<Real>("linear solver absolute tolerance");
472 
473  // MOOSE defaults this to -1 for some dumb reason
474  if (atol < 0)
475  atol = 1e-50;
476 
477  PetscReal maxits = es.parameters.get<unsigned int>("linear solver maximum iterations");
478 
479  // 1e100 is because we don't use divtol currently
480  LibmeshPetscCallA(problem.comm().get(), KSPSetTolerances(ksp, rtol, atol, 1e100, maxits));
481 
482  petscSetDefaultPCSide(problem, ksp);
483 
484  petscSetDefaultKSPNormType(problem, ksp);
485 }
486 
487 void
489 {
490  // We care about both nonlinear and linear systems when setting the SNES prefix because
491  // SNESSetOptionsPrefix will also set its KSP prefix which could compete with linear system KSPs
492  for (const auto nl_index : make_range(problem.numNonlinearSystems()))
493  {
494  NonlinearSystemBase & nl = problem.getNonlinearSystemBase(nl_index);
495 
496  //
497  // prefix system matrices
498  //
499 
500  auto & lm_sys = nl.system();
501  // This check is necessary because we still have at least the system matrix lying around even
502  // when doing matrix-free, but critically even though the libmesh object(s) exist, the wrapped
503  // PETSc Mat(s) do not
504  if (problem.solverParams(nl_index)._type != Moose::ST_JFNK)
505  for (auto & [mat_name, mat] : as_range(lm_sys.matrices_begin(), lm_sys.matrices_end()))
506  {
507  libmesh_ignore(mat_name);
508  if (auto * const petsc_mat = dynamic_cast<PetscMatrixBase<Number> *>(mat.get()); petsc_mat)
509  {
510  LibmeshPetscCallA(nl.comm().get(),
511  MatSetOptionsPrefix(petsc_mat->mat(), (nl.name() + "_").c_str()));
512  // We should call this here to ensure that options from the command line are properly
513  // applied
514  LibmeshPetscCallA(nl.comm().get(), MatSetFromOptions(petsc_mat->mat()));
515  }
516  }
517 
518  //
519  // prefix SNES/KSP
520  //
521 
522  // dig out PETSc solver
523  auto * const petsc_solver = cast_ptr<PetscNonlinearSolver<Number> *>(nl.nonlinearSolver());
524  const char * snes_prefix = nullptr;
525  std::string snes_prefix_str;
526  if (nl.system().prefix_with_name())
527  {
528  snes_prefix_str = nl.system().prefix();
529  snes_prefix = snes_prefix_str.c_str();
530  }
531  SNES snes = petsc_solver->snes(snes_prefix);
532  KSP ksp;
533  LibmeshPetscCallA(nl.comm().get(), SNESGetKSP(snes, &ksp));
534 
535  LibmeshPetscCallA(nl.comm().get(), SNESSetMaxLinearSolveFailures(snes, 1000000));
536 
537  LibmeshPetscCallA(nl.comm().get(), SNESSetCheckJacobianDomainError(snes, PETSC_TRUE));
538 
539  // In 3.0.0, the context pointer must actually be used, and the
540  // final argument to KSPSetConvergenceTest() is a pointer to a
541  // routine for destroying said private data context. In this case,
542  // we use the default context provided by PETSc in addition to
543  // a few other tests.
544  {
545  LibmeshPetscCallA(
546  nl.comm().get(),
547  SNESSetConvergenceTest(snes, petscNonlinearConverged, &problem, LIBMESH_PETSC_NULLPTR));
548  }
549 
550  petscSetKSPDefaults(problem, ksp);
551  }
552 
553  for (auto sys_index : make_range(problem.numLinearSystems()))
554  {
555  // dig out PETSc solver
556  LinearSystem & lin_sys = problem.getLinearSystem(sys_index);
557  PetscLinearSolver<Number> * petsc_solver = dynamic_cast<PetscLinearSolver<Number> *>(
559  KSP ksp = petsc_solver->ksp();
560 
561  if (problem.hasLinearConvergenceObjects())
562  LibmeshPetscCallA(
563  lin_sys.comm().get(),
564  KSPSetConvergenceTest(ksp, petscLinearConverged, &problem, LIBMESH_PETSC_NULLPTR));
565 
566  // We dont set the KSP defaults here because they seem to clash with the linear solve parameters
567  // set in FEProblemBase::solveLinearSystem
568  }
569 }
570 
571 void
573 {
574  setSolveTypeFromParams(fe_problem, params);
575  setLineSearchFromParams(fe_problem, params);
576  setMFFDTypeFromParams(fe_problem, params);
577 }
578 
579 #define checkPrefix(prefix) \
580  mooseAssert(prefix[0] == '-', \
581  "Leading prefix character must be a '-'. Current prefix is '" << prefix << "'"); \
582  mooseAssert((prefix.size() == 1) || (prefix.back() == '_'), \
583  "Terminating prefix character must be a '_'. Current prefix is '" << prefix << "'"); \
584  mooseAssert(MooseUtils::isAllLowercase(prefix), "PETSc prefixes should be all lower-case")
585 
586 void
588  const std::string & prefix,
589  const ParallelParamObject & param_object)
590 {
591  const auto & params = param_object.parameters();
592  processSingletonMooseWrappedOptions(fe_problem, params);
593 
594  // The parameters contained in the Action
595  const auto & petsc_options = params.get<MultiMooseEnum>("petsc_options");
596  const auto & petsc_pair_options =
597  params.get<MooseEnumItem, std::string>("petsc_options_iname", "petsc_options_value");
598 
599  // A reference to the PetscOptions object that contains the settings that will be used in the
600  // solve
601  auto & po = fe_problem.getPetscOptions();
602 
603  // First process the single petsc options/flags
604  addPetscFlagsToPetscOptions(petsc_options, prefix, param_object, po);
605 
606  // Then process the option-value pairs
608  petsc_pair_options, fe_problem.mesh().dimension(), prefix, param_object, po);
609 }
610 
611 void
613 {
614  // Note: Options set in the Preconditioner block will override those set in the Executioner block
615  if (params.isParamValid("solve_type") && !params.isParamValid("_use_eigen_value"))
616  {
617  // Extract the solve type
618  const std::string & solve_type = params.get<MooseEnum>("solve_type");
619  for (const auto i : make_range(fe_problem.numNonlinearSystems()))
620  fe_problem.solverParams(i)._type = Moose::stringToEnum<Moose::SolveType>(solve_type);
621  }
622 }
623 
624 void
626 {
627  // Note: Options set in the Preconditioner block will override those set in the Executioner block
628  if (params.isParamValid("line_search"))
629  {
630  const auto & line_search = params.get<MooseEnum>("line_search");
631  for (const auto i : make_range(fe_problem.numNonlinearSystems()))
632  if (fe_problem.solverParams(i)._line_search == Moose::LS_INVALID || line_search != "default")
633  {
634  Moose::LineSearchType enum_line_search =
635  Moose::stringToEnum<Moose::LineSearchType>(line_search);
636  fe_problem.solverParams(i)._line_search = enum_line_search;
637  if (enum_line_search == LS_CONTACT || enum_line_search == LS_PROJECT)
638  {
639  NonlinearImplicitSystem * nl_system = dynamic_cast<NonlinearImplicitSystem *>(
640  &fe_problem.getNonlinearSystemBase(i).system());
641  if (!nl_system)
642  mooseError("You've requested a line search but you must be solving an EigenProblem. "
643  "These two things are not consistent.");
644  PetscNonlinearSolver<Real> * petsc_nonlinear_solver =
645  dynamic_cast<PetscNonlinearSolver<Real> *>(nl_system->nonlinear_solver.get());
646  if (!petsc_nonlinear_solver)
647  mooseError("Currently the MOOSE line searches all use Petsc, so you "
648  "must use Petsc as your non-linear solver.");
649  petsc_nonlinear_solver->linesearch_object =
650  std::make_unique<ComputeLineSearchObjectWrapper>(fe_problem);
651  }
652  }
653  }
654 }
655 
656 void
658 {
659  if (params.isParamValid("mffd_type"))
660  {
661  const auto & mffd_type = params.get<MooseEnum>("mffd_type");
662  for (const auto i : make_range(fe_problem.numNonlinearSystems()))
663  fe_problem.solverParams(i)._mffd_type = Moose::stringToEnum<Moose::MffdType>(mffd_type);
664  }
665 }
666 
667 template <typename T>
668 void
669 checkUserProvidedPetscOption(const T & option, const ParallelParamObject & param_object)
670 {
671  const auto & string_option = static_cast<const std::string &>(option);
672  if (string_option[0] != '-')
673  param_object.mooseError("PETSc option '", string_option, "' does not begin with '-'");
674 }
675 
676 void
678  const std::string & prefix,
679  const ParallelParamObject & param_object,
680  PetscOptions & po)
681 {
682  checkPrefix(prefix);
683 
684  // Update the PETSc single flags
685  for (const auto & option : petsc_flags)
686  {
687  checkUserProvidedPetscOption(option, param_object);
688 
689  const std::string & string_option = option.name();
690 
697  if (option == "-log_summary" || option == "-log_view")
698  mooseError("The PETSc option \"-log_summary\" or \"-log_view\" can only be used on the "
699  "command line. Please "
700  "remove it from the input file");
701 
702  // Update the stored items, but do not create duplicates
703  const std::string prefixed_option = prefix + string_option.substr(1);
704  if (!po.flags.isValueSet(prefixed_option))
705  {
706  po.flags.setAdditionalValue(prefixed_option);
707  po.user_set_options.setAdditionalValue(prefixed_option);
708  }
709  }
710 }
711 
712 void
713 setConvergedReasonFlags(FEProblemBase & fe_problem, const std::string & prefix)
714 {
715  checkPrefix(prefix);
716  libmesh_ignore(fe_problem); // avoid unused warnings for old PETSc
717 
718 #if !PETSC_VERSION_LESS_THAN(3, 14, 0)
719  // the boolean in these pairs denote whether the user has specified any of the reason flags in the
720  // input file
721  std::array<std::string, 2> reason_flags = {{"snes_converged_reason", "ksp_converged_reason"}};
722 
723  auto & po = fe_problem.getPetscOptions();
724 
725  for (const auto & reason_flag : reason_flags)
726  if (!po.flags.isValueSet(prefix + reason_flag) &&
727  (std::find_if(po.pairs.begin(),
728  po.pairs.end(),
729  [&reason_flag, &prefix](auto & pair)
730  { return pair.first == (prefix + reason_flag); }) == po.pairs.end()))
731  po.pairs.emplace_back(prefix + reason_flag, "::failed");
732 #endif
733 }
734 
735 void
737  const std::vector<std::pair<MooseEnumItem, std::string>> & petsc_pair_options,
738  const unsigned int mesh_dimension,
739  const std::string & prefix,
740  const ParallelParamObject & param_object,
741  PetscOptions & po)
742 {
743  checkPrefix(prefix);
744 
745  // Setup the name value pairs
746  bool boomeramg_found = false;
747  bool strong_threshold_found = false;
748 #if !PETSC_VERSION_LESS_THAN(3, 7, 0)
749  bool superlu_dist_found = false;
750  bool fact_pattern_found = false;
751  bool tiny_pivot_found = false;
752 #endif
753  std::string pc_description = "";
754 #if !PETSC_VERSION_LESS_THAN(3, 12, 0)
755  // If users use HMG, we would like to set
756  bool hmg_found = false;
757  bool matptap_found = false;
758  bool hmg_strong_threshold_found = false;
759 #endif
760  std::vector<std::pair<std::string, std::string>> new_options;
761 
762  for (const auto & [option_name, option_value] : petsc_pair_options)
763  {
764  checkUserProvidedPetscOption(option_name, param_object);
765 
766  new_options.clear();
767  const std::string prefixed_option_name =
768  prefix + static_cast<const std::string &>(option_name).substr(1);
769 
770  // Do not add duplicate settings
771  if (auto it =
772  MooseUtils::findPair(po.pairs, po.pairs.begin(), prefixed_option_name, MooseUtils::Any);
773  it == po.pairs.end())
774  {
775 #if !PETSC_VERSION_LESS_THAN(3, 9, 0)
776  if (option_name == "-pc_factor_mat_solver_package")
777  new_options.emplace_back(prefix + "pc_factor_mat_solver_type", option_value);
778 #else
779  if (option_name == "-pc_factor_mat_solver_type")
780  new_options.push_back(prefix + "pc_factor_mat_solver_package", option_value);
781 #endif
782 
783  // Look for a pc description
784  if (option_name == "-pc_type" || option_name == "-sub_pc_type" ||
785  option_name == "-pc_hypre_type")
786  pc_description += option_value + ' ';
787 
788 #if !PETSC_VERSION_LESS_THAN(3, 12, 0)
789  if (option_name == "-pc_type" && option_value == "hmg")
790  hmg_found = true;
791 
792  // MPIAIJ for PETSc 3.12.0: -matptap_via
793  // MAIJ for PETSc 3.12.0: -matmaijptap_via
794  // MPIAIJ for PETSc 3.13 to 3.16: -matptap_via, -matproduct_ptap_via
795  // MAIJ for PETSc 3.13 to 3.16: -matproduct_ptap_via
796  // MPIAIJ for PETSc 3.17 and higher: -matptap_via, -mat_product_algorithm
797  // MAIJ for PETSc 3.17 and higher: -mat_product_algorithm
798 #if !PETSC_VERSION_LESS_THAN(3, 17, 0)
799  if (hmg_found && (option_name == "-matptap_via" || option_name == "-matmaijptap_via" ||
800  option_name == "-matproduct_ptap_via"))
801  new_options.emplace_back(prefix + "mat_product_algorithm", option_value);
802 #elif !PETSC_VERSION_LESS_THAN(3, 13, 0)
803  if (hmg_found && (option_name == "-matptap_via" || option_name == "-matmaijptap_via"))
804  new_options.emplace_back(prefix + "matproduct_ptap_via", option_value);
805 #else
806  if (hmg_found && (option_name == "-matproduct_ptap_via"))
807  {
808  new_options.emplace_back(prefix + "matptap_via", option_value);
809  new_options.emplace_back(prefix + "matmaijptap_via", option_value);
810  }
811 #endif
812 
813  if (option_name == "-matptap_via" || option_name == "-matmaijptap_via" ||
814  option_name == "-matproduct_ptap_via" || option_name == "-mat_product_algorithm")
815  matptap_found = true;
816 
817  // For 3D problems, we need to set this 0.7
818  if (option_name == "-hmg_inner_pc_hypre_boomeramg_strong_threshold")
819  hmg_strong_threshold_found = true;
820 #endif
821  // This special case is common enough that we'd like to handle it for the user.
822  if (option_name == "-pc_hypre_type" && option_value == "boomeramg")
823  boomeramg_found = true;
824  if (option_name == "-pc_hypre_boomeramg_strong_threshold")
825  strong_threshold_found = true;
826 #if !PETSC_VERSION_LESS_THAN(3, 7, 0)
827  if ((option_name == "-pc_factor_mat_solver_package" ||
828  option_name == "-pc_factor_mat_solver_type") &&
829  option_value == "superlu_dist")
830  superlu_dist_found = true;
831  if (option_name == "-mat_superlu_dist_fact")
832  fact_pattern_found = true;
833  if (option_name == "-mat_superlu_dist_replacetinypivot")
834  tiny_pivot_found = true;
835 #endif
836 
837  if (!new_options.empty())
838  {
839  std::copy(new_options.begin(), new_options.end(), std::back_inserter(po.pairs));
840  for (const auto & option : new_options)
841  po.user_set_options.setAdditionalValue(option.first);
842  }
843  else
844  {
845  po.pairs.push_back(std::make_pair(prefixed_option_name, option_value));
846  po.user_set_options.setAdditionalValue(prefixed_option_name);
847  }
848  }
849  else
850  {
851  do
852  {
853  it->second = option_value;
854  it = MooseUtils::findPair(po.pairs, std::next(it), prefixed_option_name, MooseUtils::Any);
855  } while (it != po.pairs.end());
856  }
857  }
858 
859  // When running a 3D mesh with boomeramg, it is almost always best to supply a strong threshold
860  // value. We will provide that for the user here if they haven't supplied it themselves.
861  if (boomeramg_found && !strong_threshold_found && mesh_dimension == 3)
862  {
863  po.pairs.emplace_back(prefix + "pc_hypre_boomeramg_strong_threshold", "0.7");
864  pc_description += "strong_threshold: 0.7 (auto)";
865  }
866 
867 #if !PETSC_VERSION_LESS_THAN(3, 12, 0)
868  if (hmg_found && !hmg_strong_threshold_found && mesh_dimension == 3)
869  {
870  po.pairs.emplace_back(prefix + "hmg_inner_pc_hypre_boomeramg_strong_threshold", "0.7");
871  pc_description += "strong_threshold: 0.7 (auto)";
872  }
873 
874  // Default PETSc PtAP takes too much memory, and it is not quite useful
875  // Let us switch to use new algorithm
876  if (hmg_found && !matptap_found)
877  {
878 #if !PETSC_VERSION_LESS_THAN(3, 17, 0)
879  po.pairs.emplace_back(prefix + "mat_product_algorithm", "allatonce");
880 #elif !PETSC_VERSION_LESS_THAN(3, 13, 0)
881  po.pairs.emplace_back(prefix + "matproduct_ptap_via", "allatonce");
882 #else
883  po.pairs.emplace_back(prefix + "matptap_via", "allatonce");
884  po.pairs.emplace_back(prefix + "matmaijptap_via", "allatonce");
885 #endif
886  }
887 #endif
888 
889 #if !PETSC_VERSION_LESS_THAN(3, 7, 0)
890  // In PETSc-3.7.{0--4}, there is a bug when using superlu_dist, and we have to use
891  // SamePattern_SameRowPerm, otherwise we use whatever we have in PETSc
892  if (superlu_dist_found && !fact_pattern_found)
893  {
894  po.pairs.emplace_back(prefix + "mat_superlu_dist_fact",
895 #if PETSC_VERSION_LESS_THAN(3, 7, 5)
896  "SamePattern_SameRowPerm");
897  pc_description += "mat_superlu_dist_fact: SamePattern_SameRowPerm ";
898 #else
899  "SamePattern");
900  pc_description += "mat_superlu_dist_fact: SamePattern ";
901 #endif
902  }
903 
904  // restore this superlu option
905  if (superlu_dist_found && !tiny_pivot_found)
906  {
907  po.pairs.emplace_back(prefix + "mat_superlu_dist_replacetinypivot", "1");
908  pc_description += " mat_superlu_dist_replacetinypivot: true ";
909  }
910 #endif
911  // Set Preconditioner description
912  if (!pc_description.empty() && prefix.size() > 1)
913  po.pc_description += "[" + prefix.substr(1, prefix.size() - 2) + "]: ";
914  po.pc_description += pc_description;
915 }
916 
917 std::set<std::string>
919 {
920  return {"default", "shell", "none", "basic", "l2", "bt", "cp"};
921 }
922 
925 {
927 
928  MooseEnum solve_type("PJFNK JFNK NEWTON FD LINEAR");
929  params.addParam<MooseEnum>("solve_type",
930  solve_type,
931  "PJFNK: Preconditioned Jacobian-Free Newton Krylov "
932  "JFNK: Jacobian-Free Newton Krylov "
933  "NEWTON: Full Newton Solve "
934  "FD: Use finite differences to compute Jacobian "
935  "LINEAR: Solving a linear problem");
936 
937  MooseEnum mffd_type("wp ds", "wp");
938  params.addParam<MooseEnum>("mffd_type",
939  mffd_type,
940  "Specifies the finite differencing type for "
941  "Jacobian-free solve types. Note that the "
942  "default is wp (for Walker and Pernice).");
943 
944  params.addParam<MultiMooseEnum>(
945  "petsc_options", getCommonPetscFlags(), "Singleton PETSc options");
946  params.addParam<MultiMooseEnum>(
947  "petsc_options_iname", getCommonPetscKeys(), "Names of PETSc name/value pairs");
948  params.addParam<std::vector<std::string>>(
949  "petsc_options_value",
950  "Values of PETSc name/value pairs (must correspond with \"petsc_options_iname\"");
951  params.addParamNamesToGroup("solve_type petsc_options petsc_options_iname petsc_options_value "
952  "mffd_type",
953  "PETSc");
954 
955  return params;
956 }
957 
960 {
961  return MultiMooseEnum(
962  "-ksp_monitor_snes_lg -snes_ksp_ew -ksp_snes_ew -snes_converged_reason "
963  "-snes_ksp -snes_linesearch_monitor -snes_mf -snes_mf_operator -snes_monitor "
964  "-snes_test_display -snes_view -snes_monitor_cancel",
965  "",
966  true);
967 }
968 
971 {
972  return MultiMooseEnum(
973  "-ksp_converged_reason -ksp_gmres_modifiedgramschmidt -ksp_monitor", "", true);
974 }
975 
978 {
979  auto options = MultiMooseEnum("-dm_moose_print_embedding -dm_view", "", true);
980  options.addValidName(getCommonKSPFlags());
981  options.addValidName(getCommonSNESFlags());
982  return options;
983 }
984 
987 {
988  return MultiMooseEnum("-snes_atol -snes_linesearch_type -snes_ls -snes_max_it -snes_rtol "
989  "-snes_divergence_tolerance -snes_type",
990  "",
991  true);
992 }
993 
996 {
997  return MultiMooseEnum("-ksp_atol -ksp_gmres_restart -ksp_max_it -ksp_pc_side -ksp_rtol "
998  "-ksp_type -sub_ksp_type",
999  "",
1000  true);
1001 }
1004 {
1005  auto options = MultiMooseEnum("-mat_fd_coloring_err -mat_fd_type -mat_mffd_type "
1006  "-pc_asm_overlap -pc_factor_levels "
1007  "-pc_factor_mat_ordering_type -pc_hypre_boomeramg_grid_sweeps_all "
1008  "-pc_hypre_boomeramg_max_iter "
1009  "-pc_hypre_boomeramg_strong_threshold -pc_hypre_type -pc_type "
1010  "-sub_pc_type",
1011  "",
1012  true);
1013  options.addValidName(getCommonKSPKeys());
1014  options.addValidName(getCommonSNESKeys());
1015  return options;
1016 }
1017 
1018 bool
1020 {
1021  const PetscOptions & petsc = fe_problem.getPetscOptions();
1022 
1023  int argc;
1024  char ** args;
1025  LibmeshPetscCallA(fe_problem.comm().get(), PetscGetArgs(&argc, &args));
1026 
1027  std::vector<std::string> cml_arg;
1028  for (int i = 0; i < argc; i++)
1029  cml_arg.push_back(args[i]);
1030 
1031  if (MooseUtils::findPair(petsc.pairs, petsc.pairs.begin(), MooseUtils::Any, "vinewtonssls") ==
1032  petsc.pairs.end() &&
1033  MooseUtils::findPair(petsc.pairs, petsc.pairs.begin(), MooseUtils::Any, "vinewtonrsls") ==
1034  petsc.pairs.end() &&
1035  std::find(cml_arg.begin(), cml_arg.end(), "vinewtonssls") == cml_arg.end() &&
1036  std::find(cml_arg.begin(), cml_arg.end(), "vinewtonrsls") == cml_arg.end())
1037  return false;
1038 
1039  return true;
1040 }
1041 
1042 void
1043 setSinglePetscOption(const std::string & name,
1044  const std::string & value /*=""*/,
1045  FEProblemBase * const problem /*=nullptr*/)
1046 {
1047  static const TIMPI::Communicator comm_world(PETSC_COMM_WORLD);
1048  const TIMPI::Communicator & comm = problem ? problem->comm() : comm_world;
1049  LibmeshPetscCallA(comm.get(),
1050  PetscOptionsSetValue(LIBMESH_PETSC_NULLPTR,
1051  name.c_str(),
1052  value == "" ? LIBMESH_PETSC_NULLPTR : value.c_str()));
1053  const auto lower_case_name = MooseUtils::toLower(name);
1054  auto check_problem = [problem, &lower_case_name]()
1055  {
1056  if (!problem)
1057  mooseError(
1058  "Setting the option '",
1059  lower_case_name,
1060  "' requires passing a 'problem' parameter. Contact a developer of your application "
1061  "to have them update their code. If in doubt, reach out to the MOOSE team on Github "
1062  "discussions");
1063  };
1064 
1065  // Select vector type from user-passed PETSc options
1066  if (lower_case_name.find("-vec_type") != std::string::npos)
1067  {
1068  check_problem();
1069  for (auto & solver_system : problem->_solver_systems)
1070  {
1071  auto & lm_sys = solver_system->system();
1072  for (auto & [vec_name, vec] : as_range(lm_sys.vectors_begin(), lm_sys.vectors_end()))
1073  {
1074  libmesh_ignore(vec_name);
1075  auto * const petsc_vec = cast_ptr<PetscVector<Number> *>(vec.get());
1076  LibmeshPetscCallA(comm.get(), VecSetFromOptions(petsc_vec->vec()));
1077  }
1078  // The solution vectors aren't included in the system vectors storage
1079  auto * petsc_vec = cast_ptr<PetscVector<Number> *>(lm_sys.solution.get());
1080  LibmeshPetscCallA(comm.get(), VecSetFromOptions(petsc_vec->vec()));
1081  petsc_vec = cast_ptr<PetscVector<Number> *>(lm_sys.current_local_solution.get());
1082  LibmeshPetscCallA(comm.get(), VecSetFromOptions(petsc_vec->vec()));
1083  }
1084  }
1085  // Select matrix type from user-passed PETSc options
1086  else if (lower_case_name.find("mat_type") != std::string::npos)
1087  {
1088  check_problem();
1089 
1090  bool found_matching_prefix = false;
1091  for (const auto i : index_range(problem->_solver_systems))
1092  {
1093  const auto & solver_sys_name = problem->_solver_sys_names[i];
1094  if (lower_case_name.find("-" + MooseUtils::toLower(solver_sys_name) + "_mat_type") ==
1095  std::string::npos)
1096  continue;
1097 
1098  if (problem->solverParams(i)._type == Moose::ST_JFNK)
1099  mooseError(
1100  "Setting option '", lower_case_name, "' is incompatible with a JFNK 'solve_type'");
1101 
1102  auto & lm_sys = problem->_solver_systems[i]->system();
1103  for (auto & [mat_name, mat] : as_range(lm_sys.matrices_begin(), lm_sys.matrices_end()))
1104  {
1105  libmesh_ignore(mat_name);
1106  if (auto * const petsc_mat = dynamic_cast<PetscMatrixBase<Number> *>(mat.get()); petsc_mat)
1107  {
1108 #ifdef DEBUG
1109  const char * mat_prefix;
1110  LibmeshPetscCallA(comm.get(), MatGetOptionsPrefix(petsc_mat->mat(), &mat_prefix));
1111  mooseAssert(strcmp(mat_prefix, (solver_sys_name + "_").c_str()) == 0,
1112  "We should have prefixed these matrices previously");
1113 #endif
1114  LibmeshPetscCallA(comm.get(), MatSetFromOptions(petsc_mat->mat()));
1115  }
1116  }
1117  found_matching_prefix = true;
1118  break;
1119  }
1120 
1121  if (!found_matching_prefix)
1122  mooseError("We did not find a matching solver system name for the petsc option '",
1123  lower_case_name,
1124  "'");
1125  }
1126 }
1127 
1128 void
1129 setSinglePetscOptionIfAppropriate(const MultiMooseEnum & dont_add_these_options,
1130  const std::string & name,
1131  const std::string & value /*=""*/,
1132  FEProblemBase * const problem /*=nullptr*/)
1133 {
1134  if (!dont_add_these_options.contains(name))
1135  setSinglePetscOption(name, value, problem);
1136 }
1137 
1138 void
1139 colorAdjacencyMatrix(PetscScalar * adjacency_matrix,
1140  unsigned int size,
1141  unsigned int colors,
1142  std::vector<unsigned int> & vertex_colors,
1143  const char * coloring_algorithm)
1144 {
1145  // Mat A will be a dense matrix from the incoming data structure
1146  Mat A;
1147  LibmeshPetscCallA(PETSC_COMM_SELF, MatCreate(PETSC_COMM_SELF, &A));
1148  LibmeshPetscCallA(PETSC_COMM_SELF, MatSetSizes(A, size, size, size, size));
1149  LibmeshPetscCallA(PETSC_COMM_SELF, MatSetType(A, MATSEQDENSE));
1150  // PETSc requires a non-const data array to populate the matrix
1151  LibmeshPetscCallA(PETSC_COMM_SELF, MatSeqDenseSetPreallocation(A, adjacency_matrix));
1152  LibmeshPetscCallA(PETSC_COMM_SELF, MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY));
1153  LibmeshPetscCallA(PETSC_COMM_SELF, MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY));
1154 
1155  // Convert A to a sparse matrix
1156 #if PETSC_VERSION_LESS_THAN(3, 7, 0)
1157  LibmeshPetscCallA(PETSC_COMM_SELF, MatConvert(A, MATAIJ, MAT_REUSE_MATRIX, &A));
1158 #else
1159  LibmeshPetscCallA(PETSC_COMM_SELF, MatConvert(A, MATAIJ, MAT_INPLACE_MATRIX, &A));
1160 #endif
1161 
1162  ISColoring iscoloring;
1163  MatColoring mc;
1164  LibmeshPetscCallA(PETSC_COMM_SELF, MatColoringCreate(A, &mc));
1165  LibmeshPetscCallA(PETSC_COMM_SELF, MatColoringSetType(mc, coloring_algorithm));
1166  LibmeshPetscCallA(PETSC_COMM_SELF, MatColoringSetMaxColors(mc, static_cast<PetscInt>(colors)));
1167 
1168  // Petsc normally colors by distance two (neighbors of neighbors), we just want one
1169  LibmeshPetscCallA(PETSC_COMM_SELF, MatColoringSetDistance(mc, 1));
1170  LibmeshPetscCallA(PETSC_COMM_SELF, MatColoringSetFromOptions(mc));
1171  LibmeshPetscCallA(PETSC_COMM_SELF, MatColoringApply(mc, &iscoloring));
1172 
1173  PetscInt nn;
1174  IS * is;
1175 #if PETSC_RELEASE_LESS_THAN(3, 12, 0)
1176  LibmeshPetscCallA(PETSC_COMM_SELF, ISColoringGetIS(iscoloring, &nn, &is));
1177 #else
1178  LibmeshPetscCallA(PETSC_COMM_SELF, ISColoringGetIS(iscoloring, PETSC_USE_POINTER, &nn, &is));
1179 #endif
1180 
1181  if (nn > static_cast<PetscInt>(colors))
1182  throw std::runtime_error("Not able to color with designated number of colors");
1183 
1184  for (int i = 0; i < nn; i++)
1185  {
1186  PetscInt isize;
1187  const PetscInt * indices;
1188  LibmeshPetscCallA(PETSC_COMM_SELF, ISGetLocalSize(is[i], &isize));
1189  LibmeshPetscCallA(PETSC_COMM_SELF, ISGetIndices(is[i], &indices));
1190  for (int j = 0; j < isize; j++)
1191  {
1192  mooseAssert(indices[j] < static_cast<PetscInt>(vertex_colors.size()), "Index out of bounds");
1193  vertex_colors[indices[j]] = i;
1194  }
1195  LibmeshPetscCallA(PETSC_COMM_SELF, ISRestoreIndices(is[i], &indices));
1196  }
1197 
1198  LibmeshPetscCallA(PETSC_COMM_SELF, MatDestroy(&A));
1199  LibmeshPetscCallA(PETSC_COMM_SELF, MatColoringDestroy(&mc));
1200  LibmeshPetscCallA(PETSC_COMM_SELF, ISColoringDestroy(&iscoloring));
1201 }
1202 
1203 void
1204 dontAddPetscFlag(const std::string & flag, PetscOptions & petsc_options)
1205 {
1206  if (!petsc_options.dont_add_these_options.contains(flag))
1207  petsc_options.dont_add_these_options.setAdditionalValue(flag);
1208 }
1209 
1210 void
1212 {
1213  dontAddPetscFlag("-snes_converged_reason", fe_problem.getPetscOptions());
1214 }
1215 
1216 void
1218 {
1219  dontAddPetscFlag("-ksp_converged_reason", fe_problem.getPetscOptions());
1220 }
1221 
1222 void
1224 {
1225  auto & petsc_options = fe_problem.getPetscOptions();
1226  for (const auto & flag : getCommonKSPFlags().getNames())
1227  dontAddPetscFlag(flag, petsc_options);
1228  for (const auto & key : getCommonKSPKeys().getNames())
1229  dontAddPetscFlag(key, petsc_options);
1230 }
1231 
1232 void
1234 {
1235  auto & petsc_options = fe_problem.getPetscOptions();
1236  for (const auto & flag : getCommonSNESFlags().getNames())
1237  if (!petsc_options.dont_add_these_options.contains(flag))
1238  petsc_options.dont_add_these_options.setAdditionalValue(flag);
1239  for (const auto & key : getCommonSNESKeys().getNames())
1240  if (!petsc_options.dont_add_these_options.contains(key))
1241  petsc_options.dont_add_these_options.setAdditionalValue(key);
1242 }
1243 
1244 std::unique_ptr<PetscMatrix<Number>>
1246  Mat & mat,
1247  const std::string & binary_mat_file,
1248  const unsigned int mat_number_to_load)
1249 {
1250  LibmeshPetscCallA(comm.get(), MatCreate(comm.get(), &mat));
1251  PetscViewer matviewer;
1252  LibmeshPetscCallA(
1253  comm.get(),
1254  PetscViewerBinaryOpen(comm.get(), binary_mat_file.c_str(), FILE_MODE_READ, &matviewer));
1255  for (unsigned int i = 0; i < mat_number_to_load; ++i)
1256  LibmeshPetscCallA(comm.get(), MatLoad(mat, matviewer));
1257  LibmeshPetscCallA(comm.get(), PetscViewerDestroy(&matviewer));
1258 
1259  return std::make_unique<PetscMatrix<Number>>(mat, comm);
1260 }
1261 
1262 } // Namespace PetscSupport
1263 } // Namespace MOOSE
std::string name(const ElemQuality q)
MultiMooseEnum getCommonKSPKeys()
A helper function to produce a MultiMooseEnum with commonly used PETSc ksp option names (keys) ...
Definition: PetscSupport.C:995
MultiMooseEnum getCommonPetscKeys()
A helper function to produce a MultiMooseEnum with commonly used PETSc iname options (keys in key-val...
void resetFailNextNonlinearConvergenceCheck()
Tell the problem that the nonlinear convergence check(s) may proceed as normal.
bool isSNESVI(FEProblemBase &fe_problem)
check if SNES type is variational inequalities (VI) solver
SNES snes(const char *name=nullptr)
const std::vector< ConvergenceName > & getNonlinearConvergenceNames() const
Gets the nonlinear system convergence object name(s).
Moose::PetscSupport::PetscOptions & getPetscOptions()
Retrieve a writable reference the PETSc options (used by PetscSupport)
KSPNormType getPetscKSPNormType(Moose::MooseKSPNormType kspnorm)
Definition: PetscSupport.C:421
void addPetscOptionsFromCommandline()
Definition: PetscSupport.C:233
void setMFFDTypeFromParams(FEProblemBase &fe_problem, const InputParameters &params)
Sets the FE problem&#39;s matrix-free finite difference type from the input params.
Definition: PetscSupport.C:657
std::unique_ptr< NonlinearSolver< Number > > nonlinear_solver
Full Newton Solve.
Definition: MooseTypes.h:846
std::string toLower(const std::string &name)
Convert supplied string to lower case.
const ExecFlagType EXEC_NONLINEAR_CONVERGENCE
Definition: Moose.C:32
static void petscSetupOutput()
Output string for setting up PETSC output.
Definition: Console.C:859
std::string _prefix
Definition: SolverParams.h:35
virtual std::size_t numNonlinearSystems() const override
std::set< std::string > getPetscValidLineSearches()
Returns the valid petsc line search options as a set of strings.
Definition: PetscSupport.C:918
void petscSetupDM(NonlinearSystemBase &nl, const std::string &dm_name)
Setup the PETSc DM object.
Definition: PetscSupport.C:190
Moose::LineSearchType _line_search
Definition: SolverParams.h:20
void mooseError(Args &&... args)
Emit an error message with the given stringified, concatenated args and terminate the application...
Definition: MooseError.h:302
void setAdditionalValue(const std::string &names)
Insert operators Operator to insert (push_back) values into the enum.
const ExecFlagType EXEC_LINEAR_CONVERGENCE
Definition: Moose.C:30
std::vector< std::pair< R1, R2 > > get(const std::string &param1, const std::string &param2) const
Combine two vector parameters into a single vector of pairs.
void petscSetDefaults(FEProblemBase &problem)
Sets the default options for PETSc.
Definition: PetscSupport.C:488
libMesh::LinearImplicitSystem & linearImplicitSystem()
Return a reference to the stored linear implicit system.
Definition: LinearSystem.h:86
virtual MooseConvergenceStatus checkConvergence(unsigned int iter)=0
Returns convergence status.
MultiMooseEnum getCommonSNESFlags()
A helper function to produce a MultiMooseEnum with commonly used PETSc snes single options (flags) ...
Definition: PetscSupport.C:959
A struct for storing the various types of petsc options and values.
Definition: PetscSupport.h:39
MultiMooseEnum flags
Single value PETSc options (flags)
Definition: PetscSupport.h:51
PetscErrorCode PetscOptionItems *PetscErrorCode DM dm
PetscFunctionBegin
void setSolveTypeFromParams(FEProblemBase &fe_problem, const InputParameters &params)
Sets the FE problem&#39;s solve type from the input params.
Definition: PetscSupport.C:612
The main MOOSE class responsible for handling user-defined parameters in almost every MOOSE system...
const Parallel::Communicator & comm() const
void petscSetDefaultKSPNormType(FEProblemBase &problem, KSP ksp)
Set norm type.
Definition: PetscSupport.C:442
std::unique_ptr< PetscMatrix< Number > > createMatrixFromFile(const libMesh::Parallel::Communicator &comm, Mat &petsc_mat, const std::string &binary_mat_file, unsigned int mat_number_to_load=1)
Create a matrix from a binary file.
Solving a linear problem.
Definition: MooseTypes.h:848
void petscSetKSPDefaults(FEProblemBase &problem, KSP ksp)
Set the default options for a KSP.
Definition: PetscSupport.C:466
std::vector< std::shared_ptr< SolverSystem > > _solver_systems
Combined container to base pointer of every solver system.
std::vector< std::pair< std::string, std::string > > pairs
PETSc key-value pairs.
Definition: PetscSupport.h:48
virtual libMesh::NonlinearSolver< Number > * nonlinearSolver()=0
virtual LinearSolver< Number > * get_linear_solver() const override
The following methods are specializations for using the libMesh::Parallel::packed_range_* routines fo...
MffdType
Type of the matrix-free finite-differencing parameter.
Definition: MooseTypes.h:942
Specialization of SubProblem for solving nonlinear equations plus auxiliary equations.
bool hasLinearConvergenceObjects() const
Whether we have linear convergence objects.
InputParameters emptyInputParameters()
This class wraps provides and tracks access to command line parameters.
Definition: CommandLine.h:29
MooseKSPNormType
Norm type for converge test.
Definition: MooseTypes.h:830
Nonlinear system to be solved.
MPI_Status status
virtual const std::string & name() const
Definition: SystemBase.C:1330
PCSide getPetscPCSide(Moose::PCSideType pcs)
Definition: PetscSupport.C:404
void processSingletonMooseWrappedOptions(FEProblemBase &fe_problem, const InputParameters &params)
Process some MOOSE-wrapped PETSc options.
Definition: PetscSupport.C:572
void checkUserProvidedPetscOption(const T &option, const ParallelParamObject &param_object)
Definition: PetscSupport.C:669
bool contains(const std::string &value) const
Methods for seeing if a value is set in the MultiMooseEnum.
std::vector< SolverSystemName > _solver_sys_names
The union of nonlinear and linear system names.
virtual void execute(const ExecFlagType &exec_type)
Convenience function for performing execution of MOOSE systems.
void dontAddCommonKSPOptions(FEProblemBase &fe_problem)
Function to ensure that common KSP options are not added to the PetscOptions storage object to be lat...
PetscErrorCode petscLinearConverged(KSP, PetscInt it, PetscReal, KSPConvergedReason *reason, void *ctx)
Definition: PetscSupport.C:358
void libmesh_ignore(const Args &...)
Use whatever we have in PETSc.
Definition: MooseTypes.h:824
PetscErrorCode petscNonlinearConverged(SNES, PetscInt it, PetscReal, PetscReal, PetscReal, SNESConvergedReason *reason, void *ctx)
Definition: PetscSupport.C:310
const T & get(std::string_view) const
MultiMooseEnum getCommonPetscFlags()
A helper function to produce a MultiMooseEnum with commonly used PETSc single options (flags) ...
Definition: PetscSupport.C:977
Moose::MffdType _mffd_type
Definition: SolverParams.h:21
Real value(unsigned n, unsigned alpha, unsigned beta, Real x)
LineSearchType
Type of the line search.
Definition: MooseTypes.h:925
virtual Convergence & getConvergence(const std::string &name, const THREAD_ID tid=0) const
Gets a Convergence object.
void MooseMatView(SparseMatrix< Number > &mat)
Definition: PetscSupport.C:73
virtual unsigned int dimension() const
Returns MeshBase::mesh_dimension(), (not MeshBase::spatial_dimension()!) of the underlying libMesh me...
Definition: MooseMesh.C:2923
std::string prefix() const
Use whatever we have in PETSc.
Definition: MooseTypes.h:836
void dontAddPetscFlag(const std::string &flag, PetscOptions &petsc_options)
Function to ensure that a particular petsc option is not added to the PetscOptions storage object to ...
std::string stringify(const MffdType &t)
Definition: PetscSupport.C:130
NonlinearSystemBase & currentNonlinearSystem()
SimpleRange< IndexType > as_range(const std::pair< IndexType, IndexType > &p)
Jacobian-Free Newton Krylov.
Definition: MooseTypes.h:845
virtual libMesh::EquationSystems & es() override
void setSolverOptions(const SolverParams &solver_params, const MultiMooseEnum &dont_add_these_options)
Definition: PetscSupport.C:145
PetscErrorCode DMCreateMoose(MPI_Comm comm, NonlinearSystemBase &nl, const std::string &dm_name, DM *dm)
Create a MOOSE DM.
This is a "smart" enum class intended to replace many of the shortcomings in the C++ enum type It sho...
Definition: MooseEnum.h:33
Moose::SolveType _type
Definition: SolverParams.h:19
PetscErrorCode PetscInt const PetscInt IS * is
Use finite differences to compute Jacobian.
Definition: MooseTypes.h:847
NonlinearSystemBase & getNonlinearSystemBase(const unsigned int sys_num)
bool isValueSet(const std::string &value) const
Methods for seeing if a value is set in the MultiMooseEnum.
unsigned int number() const
Gets the number of this system.
Definition: SystemBase.C:1159
void petscSetOptions(const PetscOptions &po, const SolverParams &solver_params, FEProblemBase *const problem=nullptr)
A function for setting the PETSc options in PETSc from the options supplied to MOOSE.
Definition: PetscSupport.C:272
bool getFailNextSystemConvergenceCheck() const
Whether it will fail the next system convergence check(s), triggering failed step behavior...
LinearSystem & getLinearSystem(unsigned int sys_num)
Get non-constant reference to a linear system.
MooseConvergenceStatus
Status returned by calls to checkConvergence.
Definition: Convergence.h:33
auto findPair(C &container, It start_iterator, const M1 &first, const M2 &second)
Find a specific pair in a container matching on first, second or both pair components.
Definition: MooseUtils.h:1061
void setConvergedReasonFlags(FEProblemBase &fe_problem, const std::string &prefix)
Set flags that will instruct the user on the reason their simulation diverged from PETSc&#39;s perspectiv...
Definition: PetscSupport.C:713
void setLineSearchFromParams(FEProblemBase &fe_problem, const InputParameters &params)
Sets the FE problem&#39;s line search from the input params.
Definition: PetscSupport.C:625
void dontAddCommonSNESOptions(FEProblemBase &fe_problem)
Function to ensure that common SNES options are not added to the PetscOptions storage object to be la...
unsigned int get(unsigned int i) const
Indexing operator Operator to retrieve the id of an item from the MultiMooseEnum. ...
void setSinglePetscOption(const std::string &name, const std::string &value="", FEProblemBase *const problem=nullptr)
A wrapper function for dealing with different versions of PetscOptionsSetValue.
MultiMooseEnum getCommonKSPFlags()
A helper function to produce a MultiMooseEnum with commonly used PETSc ksp single options (flags) ...
Definition: PetscSupport.C:970
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
InputParameters getPetscValidParams()
Returns the PETSc options that are common between Executioners and Preconditioners.
Definition: PetscSupport.C:924
PetscErrorCode petscSetupOutput(CommandLine *cmd_line)
Definition: PetscSupport.C:293
std::unique_ptr< ComputeLineSearchObject > linesearch_object
Class for containing MooseEnum item information.
Definition: MooseEnumItem.h:18
void addPetscPairsToPetscOptions(const std::vector< std::pair< MooseEnumItem, std::string >> &petsc_pair_options, const unsigned int mesh_dimension, const std::string &prefix, const ParallelParamObject &param_object, PetscOptions &petsc_options)
Populate name and value pairs in a given PetscOptions object using vectors of input arguments...
Definition: PetscSupport.C:736
void petscSetOptionsHelper(const PetscOptions &po, FEProblemBase *const problem)
Definition: PetscSupport.C:252
means not set
Definition: MooseTypes.h:944
void dontAddNonlinearConvergedReason(FEProblemBase &fe_problem)
Function to ensure that -snes_converged_reason is not added to the PetscOptions storage object to be ...
void colorAdjacencyMatrix(PetscScalar *adjacency_matrix, unsigned int size, unsigned int colors, std::vector< unsigned int > &vertex_colors, const char *coloring_algorithm)
This method takes an adjacency matrix, and a desired number of colors and applies a graph coloring al...
bool getFailNextNonlinearConvergenceCheck() const
Whether it will skip further residual evaluations and fail the next nonlinear convergence check(s) ...
IntRange< T > make_range(T beg, T end)
virtual MooseMesh & mesh() override
LinearSystem & currentLinearSystem()
Get a non-constant reference to the current linear system.
void resetFailNextSystemConvergenceCheck()
Tell the problem that the system convergence check(s) may proceed as normal.
void mooseError(Args &&... args) const
Emits an error prefixed with object name and type.
PCSideType
Preconditioning side.
Definition: MooseTypes.h:819
SolverParams & solverParams(unsigned int solver_sys_num=0)
Get the solver parameters.
SolverSystem & getSolverSystem(unsigned int sys_num)
Get non-constant reference to a solver system.
MultiMooseEnum getCommonSNESKeys()
A helper function to produce a MultiMooseEnum with commonly used PETSc snes option names (keys) ...
Definition: PetscSupport.C:986
const InputParameters & parameters() const
Get the parameters of the object.
void addParam(const std::string &name, const S &value, const std::string &doc_string)
These methods add an optional parameter and a documentation string to the InputParameters object...
Linear system to be solved.
Definition: LinearSystem.h:35
void setSinglePetscOptionIfAppropriate(const MultiMooseEnum &dont_add_these_options, const std::string &name, const std::string &value="", FEProblemBase *const problem=nullptr)
Same as setSinglePetscOption, but does not set the option if it doesn&#39;t make sense for the current si...
void addPetscFlagsToPetscOptions(const MultiMooseEnum &petsc_flags, const std::string &prefix, const ParallelParamObject &param_object, PetscOptions &petsc_options)
Populate flags in a given PetscOptions object using a vector of input arguments.
Definition: PetscSupport.C:677
void dontAddLinearConvergedReason(FEProblemBase &fe_problem)
Function to ensure that -ksp_converged_reason is not added to the PetscOptions storage object to be l...
void * ctx
Preconditioned Jacobian-Free Newton Krylov.
Definition: MooseTypes.h:844
virtual std::size_t numLinearSystems() const override
MOOSE now contains C++17 code, so give a reasonable error message stating what the user can do to add...
This is a "smart" enum class intended to replace many of the shortcomings in the C++ enum type...
means not set
Definition: MooseTypes.h:927
void storePetscOptions(FEProblemBase &fe_problem, const std::string &prefix, const ParallelParamObject &param_object)
Stores the PETSc options supplied from the parameter object on the problem.
Definition: PetscSupport.C:587
std::string pc_description
Preconditioner description.
Definition: PetscSupport.h:60
static const struct MooseUtils::AnyType Any
MultiMooseEnum dont_add_these_options
Flags to explicitly not set, even if they are specified programmatically.
Definition: PetscSupport.h:54
Moose::MooseKSPNormType getMooseKSPNormType()
Get the norm in which the linear convergence is measured.
Definition: SolverSystem.h:87
void prefix_with_name(bool value)
Base class shared by both Action and MooseObject.
PetscFunctionReturn(LIBMESH_PETSC_SUCCESS)
void MooseVecView(NumericVector< Number > &vector)
Definition: PetscSupport.C:66
PetscErrorCode DMMooseRegisterAll()
virtual std::size_t numSolverSystems() const override
MultiMooseEnum user_set_options
Options that are set by the user at the input level.
Definition: PetscSupport.h:57
auto index_range(const T &sizable)
const std::vector< std::string > & getArguments()
Definition: CommandLine.h:132
Moose::PCSideType getPCSide()
Get the current preconditioner side.
Definition: SolverSystem.h:76
void petscSetDefaultPCSide(FEProblemBase &problem, KSP ksp)
Setup which side we want to apply preconditioner.
Definition: PetscSupport.C:453
const std::vector< ConvergenceName > & getLinearConvergenceNames() const
Gets the linear convergence object name(s).
void addParamNamesToGroup(const std::string &space_delim_names, const std::string group_name)
This method takes a space delimited list of parameter names and adds them to the specified group name...
bool isParamValid(const std::string &name) const
This method returns parameters that have been initialized in one fashion or another, i.e.
virtual libMesh::System & system() override
Get the reference to the libMesh system.