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), \
585  "PETSc prefixes should be all lower-case. What are you, a crazy person?")
586 
587 void
589  const std::string & prefix,
590  const ParallelParamObject & param_object)
591 {
592  const auto & params = param_object.parameters();
593  processSingletonMooseWrappedOptions(fe_problem, params);
594 
595  // The parameters contained in the Action
596  const auto & petsc_options = params.get<MultiMooseEnum>("petsc_options");
597  const auto & petsc_pair_options =
598  params.get<MooseEnumItem, std::string>("petsc_options_iname", "petsc_options_value");
599 
600  // A reference to the PetscOptions object that contains the settings that will be used in the
601  // solve
602  auto & po = fe_problem.getPetscOptions();
603 
604  // First process the single petsc options/flags
605  addPetscFlagsToPetscOptions(petsc_options, prefix, param_object, po);
606 
607  // Then process the option-value pairs
609  petsc_pair_options, fe_problem.mesh().dimension(), prefix, param_object, po);
610 }
611 
612 void
614 {
615  // Note: Options set in the Preconditioner block will override those set in the Executioner block
616  if (params.isParamValid("solve_type") && !params.isParamValid("_use_eigen_value"))
617  {
618  // Extract the solve type
619  const std::string & solve_type = params.get<MooseEnum>("solve_type");
620  for (const auto i : make_range(fe_problem.numNonlinearSystems()))
621  fe_problem.solverParams(i)._type = Moose::stringToEnum<Moose::SolveType>(solve_type);
622  }
623 }
624 
625 void
627 {
628  // Note: Options set in the Preconditioner block will override those set in the Executioner block
629  if (params.isParamValid("line_search"))
630  {
631  const auto & line_search = params.get<MooseEnum>("line_search");
632  for (const auto i : make_range(fe_problem.numNonlinearSystems()))
633  if (fe_problem.solverParams(i)._line_search == Moose::LS_INVALID || line_search != "default")
634  {
635  Moose::LineSearchType enum_line_search =
636  Moose::stringToEnum<Moose::LineSearchType>(line_search);
637  fe_problem.solverParams(i)._line_search = enum_line_search;
638  if (enum_line_search == LS_CONTACT || enum_line_search == LS_PROJECT)
639  {
640  NonlinearImplicitSystem * nl_system = dynamic_cast<NonlinearImplicitSystem *>(
641  &fe_problem.getNonlinearSystemBase(i).system());
642  if (!nl_system)
643  mooseError("You've requested a line search but you must be solving an EigenProblem. "
644  "These two things are not consistent.");
645  PetscNonlinearSolver<Real> * petsc_nonlinear_solver =
646  dynamic_cast<PetscNonlinearSolver<Real> *>(nl_system->nonlinear_solver.get());
647  if (!petsc_nonlinear_solver)
648  mooseError("Currently the MOOSE line searches all use Petsc, so you "
649  "must use Petsc as your non-linear solver.");
650  petsc_nonlinear_solver->linesearch_object =
651  std::make_unique<ComputeLineSearchObjectWrapper>(fe_problem);
652  }
653  }
654  }
655 }
656 
657 void
659 {
660  if (params.isParamValid("mffd_type"))
661  {
662  const auto & mffd_type = params.get<MooseEnum>("mffd_type");
663  for (const auto i : make_range(fe_problem.numNonlinearSystems()))
664  fe_problem.solverParams(i)._mffd_type = Moose::stringToEnum<Moose::MffdType>(mffd_type);
665  }
666 }
667 
668 template <typename T>
669 void
670 checkUserProvidedPetscOption(const T & option, const ParallelParamObject & param_object)
671 {
672  const auto & string_option = static_cast<const std::string &>(option);
673  if (string_option[0] != '-')
674  param_object.mooseError("PETSc option '", string_option, "' does not begin with '-'");
675 }
676 
677 void
679  const std::string & prefix,
680  const ParallelParamObject & param_object,
681  PetscOptions & po)
682 {
683  checkPrefix(prefix);
684 
685  // Update the PETSc single flags
686  for (const auto & option : petsc_flags)
687  {
688  checkUserProvidedPetscOption(option, param_object);
689 
690  const std::string & string_option = option.name();
691 
698  if (option == "-log_summary" || option == "-log_view")
699  mooseError("The PETSc option \"-log_summary\" or \"-log_view\" can only be used on the "
700  "command line. Please "
701  "remove it from the input file");
702 
703  // Update the stored items, but do not create duplicates
704  const std::string prefixed_option = prefix + string_option.substr(1);
705  if (!po.flags.isValueSet(prefixed_option))
706  {
707  po.flags.setAdditionalValue(prefixed_option);
708  po.user_set_options.setAdditionalValue(prefixed_option);
709  }
710  }
711 }
712 
713 void
714 setConvergedReasonFlags(FEProblemBase & fe_problem, const std::string & prefix)
715 {
716  checkPrefix(prefix);
717  libmesh_ignore(fe_problem); // avoid unused warnings for old PETSc
718 
719 #if !PETSC_VERSION_LESS_THAN(3, 14, 0)
720  // the boolean in these pairs denote whether the user has specified any of the reason flags in the
721  // input file
722  std::array<std::string, 2> reason_flags = {{"snes_converged_reason", "ksp_converged_reason"}};
723 
724  auto & po = fe_problem.getPetscOptions();
725 
726  for (const auto & reason_flag : reason_flags)
727  if (!po.flags.isValueSet(prefix + reason_flag) &&
728  (std::find_if(po.pairs.begin(),
729  po.pairs.end(),
730  [&reason_flag, &prefix](auto & pair)
731  { return pair.first == (prefix + reason_flag); }) == po.pairs.end()))
732  po.pairs.emplace_back(prefix + reason_flag, "::failed");
733 #endif
734 }
735 
736 void
738  const std::vector<std::pair<MooseEnumItem, std::string>> & petsc_pair_options,
739  const unsigned int mesh_dimension,
740  const std::string & prefix,
741  const ParallelParamObject & param_object,
742  PetscOptions & po)
743 {
744  checkPrefix(prefix);
745 
746  // Setup the name value pairs
747  bool boomeramg_found = false;
748  bool strong_threshold_found = false;
749 #if !PETSC_VERSION_LESS_THAN(3, 7, 0)
750  bool superlu_dist_found = false;
751  bool fact_pattern_found = false;
752  bool tiny_pivot_found = false;
753 #endif
754  std::string pc_description = "";
755 #if !PETSC_VERSION_LESS_THAN(3, 12, 0)
756  // If users use HMG, we would like to set
757  bool hmg_found = false;
758  bool matptap_found = false;
759  bool hmg_strong_threshold_found = false;
760 #endif
761  std::vector<std::pair<std::string, std::string>> new_options;
762 
763  for (const auto & [option_name, option_value] : petsc_pair_options)
764  {
765  checkUserProvidedPetscOption(option_name, param_object);
766 
767  new_options.clear();
768  const std::string prefixed_option_name =
769  prefix + static_cast<const std::string &>(option_name).substr(1);
770 
771  // Do not add duplicate settings
772  if (auto it =
773  MooseUtils::findPair(po.pairs, po.pairs.begin(), prefixed_option_name, MooseUtils::Any);
774  it == po.pairs.end())
775  {
776 #if !PETSC_VERSION_LESS_THAN(3, 9, 0)
777  if (option_name == "-pc_factor_mat_solver_package")
778  new_options.emplace_back(prefix + "pc_factor_mat_solver_type", option_value);
779 #else
780  if (option_name == "-pc_factor_mat_solver_type")
781  new_options.push_back(prefix + "pc_factor_mat_solver_package", option_value);
782 #endif
783 
784  // Look for a pc description
785  if (option_name == "-pc_type" || option_name == "-sub_pc_type" ||
786  option_name == "-pc_hypre_type")
787  pc_description += option_value + ' ';
788 
789 #if !PETSC_VERSION_LESS_THAN(3, 12, 0)
790  if (option_name == "-pc_type" && option_value == "hmg")
791  hmg_found = true;
792 
793  // MPIAIJ for PETSc 3.12.0: -matptap_via
794  // MAIJ for PETSc 3.12.0: -matmaijptap_via
795  // MPIAIJ for PETSc 3.13 to 3.16: -matptap_via, -matproduct_ptap_via
796  // MAIJ for PETSc 3.13 to 3.16: -matproduct_ptap_via
797  // MPIAIJ for PETSc 3.17 and higher: -matptap_via, -mat_product_algorithm
798  // MAIJ for PETSc 3.17 and higher: -mat_product_algorithm
799 #if !PETSC_VERSION_LESS_THAN(3, 17, 0)
800  if (hmg_found && (option_name == "-matptap_via" || option_name == "-matmaijptap_via" ||
801  option_name == "-matproduct_ptap_via"))
802  new_options.emplace_back(prefix + "mat_product_algorithm", option_value);
803 #elif !PETSC_VERSION_LESS_THAN(3, 13, 0)
804  if (hmg_found && (option_name == "-matptap_via" || option_name == "-matmaijptap_via"))
805  new_options.emplace_back(prefix + "matproduct_ptap_via", option_value);
806 #else
807  if (hmg_found && (option_name == "-matproduct_ptap_via"))
808  {
809  new_options.emplace_back(prefix + "matptap_via", option_value);
810  new_options.emplace_back(prefix + "matmaijptap_via", option_value);
811  }
812 #endif
813 
814  if (option_name == "-matptap_via" || option_name == "-matmaijptap_via" ||
815  option_name == "-matproduct_ptap_via" || option_name == "-mat_product_algorithm")
816  matptap_found = true;
817 
818  // For 3D problems, we need to set this 0.7
819  if (option_name == "-hmg_inner_pc_hypre_boomeramg_strong_threshold")
820  hmg_strong_threshold_found = true;
821 #endif
822  // This special case is common enough that we'd like to handle it for the user.
823  if (option_name == "-pc_hypre_type" && option_value == "boomeramg")
824  boomeramg_found = true;
825  if (option_name == "-pc_hypre_boomeramg_strong_threshold")
826  strong_threshold_found = true;
827 #if !PETSC_VERSION_LESS_THAN(3, 7, 0)
828  if ((option_name == "-pc_factor_mat_solver_package" ||
829  option_name == "-pc_factor_mat_solver_type") &&
830  option_value == "superlu_dist")
831  superlu_dist_found = true;
832  if (option_name == "-mat_superlu_dist_fact")
833  fact_pattern_found = true;
834  if (option_name == "-mat_superlu_dist_replacetinypivot")
835  tiny_pivot_found = true;
836 #endif
837 
838  if (!new_options.empty())
839  {
840  std::copy(new_options.begin(), new_options.end(), std::back_inserter(po.pairs));
841  for (const auto & option : new_options)
842  po.user_set_options.setAdditionalValue(option.first);
843  }
844  else
845  {
846  po.pairs.push_back(std::make_pair(prefixed_option_name, option_value));
847  po.user_set_options.setAdditionalValue(prefixed_option_name);
848  }
849  }
850  else
851  {
852  do
853  {
854  it->second = option_value;
855  it = MooseUtils::findPair(po.pairs, std::next(it), prefixed_option_name, MooseUtils::Any);
856  } while (it != po.pairs.end());
857  }
858  }
859 
860  // When running a 3D mesh with boomeramg, it is almost always best to supply a strong threshold
861  // value. We will provide that for the user here if they haven't supplied it themselves.
862  if (boomeramg_found && !strong_threshold_found && mesh_dimension == 3)
863  {
864  po.pairs.emplace_back(prefix + "pc_hypre_boomeramg_strong_threshold", "0.7");
865  pc_description += "strong_threshold: 0.7 (auto)";
866  }
867 
868 #if !PETSC_VERSION_LESS_THAN(3, 12, 0)
869  if (hmg_found && !hmg_strong_threshold_found && mesh_dimension == 3)
870  {
871  po.pairs.emplace_back(prefix + "hmg_inner_pc_hypre_boomeramg_strong_threshold", "0.7");
872  pc_description += "strong_threshold: 0.7 (auto)";
873  }
874 
875  // Default PETSc PtAP takes too much memory, and it is not quite useful
876  // Let us switch to use new algorithm
877  if (hmg_found && !matptap_found)
878  {
879 #if !PETSC_VERSION_LESS_THAN(3, 17, 0)
880  po.pairs.emplace_back(prefix + "mat_product_algorithm", "allatonce");
881 #elif !PETSC_VERSION_LESS_THAN(3, 13, 0)
882  po.pairs.emplace_back(prefix + "matproduct_ptap_via", "allatonce");
883 #else
884  po.pairs.emplace_back(prefix + "matptap_via", "allatonce");
885  po.pairs.emplace_back(prefix + "matmaijptap_via", "allatonce");
886 #endif
887  }
888 #endif
889 
890 #if !PETSC_VERSION_LESS_THAN(3, 7, 0)
891  // In PETSc-3.7.{0--4}, there is a bug when using superlu_dist, and we have to use
892  // SamePattern_SameRowPerm, otherwise we use whatever we have in PETSc
893  if (superlu_dist_found && !fact_pattern_found)
894  {
895  po.pairs.emplace_back(prefix + "mat_superlu_dist_fact",
896 #if PETSC_VERSION_LESS_THAN(3, 7, 5)
897  "SamePattern_SameRowPerm");
898  pc_description += "mat_superlu_dist_fact: SamePattern_SameRowPerm ";
899 #else
900  "SamePattern");
901  pc_description += "mat_superlu_dist_fact: SamePattern ";
902 #endif
903  }
904 
905  // restore this superlu option
906  if (superlu_dist_found && !tiny_pivot_found)
907  {
908  po.pairs.emplace_back(prefix + "mat_superlu_dist_replacetinypivot", "1");
909  pc_description += " mat_superlu_dist_replacetinypivot: true ";
910  }
911 #endif
912  // Set Preconditioner description
913  if (!pc_description.empty() && prefix.size() > 1)
914  po.pc_description += "[" + prefix.substr(1, prefix.size() - 2) + "]: ";
915  po.pc_description += pc_description;
916 }
917 
918 std::set<std::string>
920 {
921  return {"default", "shell", "none", "basic", "l2", "bt", "cp"};
922 }
923 
926 {
928 
929  MooseEnum solve_type("PJFNK JFNK NEWTON FD LINEAR");
930  params.addParam<MooseEnum>("solve_type",
931  solve_type,
932  "PJFNK: Preconditioned Jacobian-Free Newton Krylov "
933  "JFNK: Jacobian-Free Newton Krylov "
934  "NEWTON: Full Newton Solve "
935  "FD: Use finite differences to compute Jacobian "
936  "LINEAR: Solving a linear problem");
937 
938  MooseEnum mffd_type("wp ds", "wp");
939  params.addParam<MooseEnum>("mffd_type",
940  mffd_type,
941  "Specifies the finite differencing type for "
942  "Jacobian-free solve types. Note that the "
943  "default is wp (for Walker and Pernice).");
944 
945  params.addParam<MultiMooseEnum>(
946  "petsc_options", getCommonPetscFlags(), "Singleton PETSc options");
947  params.addParam<MultiMooseEnum>(
948  "petsc_options_iname", getCommonPetscKeys(), "Names of PETSc name/value pairs");
949  params.addParam<std::vector<std::string>>(
950  "petsc_options_value",
951  "Values of PETSc name/value pairs (must correspond with \"petsc_options_iname\"");
952  params.addParamNamesToGroup("solve_type petsc_options petsc_options_iname petsc_options_value "
953  "mffd_type",
954  "PETSc");
955 
956  return params;
957 }
958 
961 {
962  return MultiMooseEnum(
963  "-ksp_monitor_snes_lg -snes_ksp_ew -ksp_snes_ew -snes_converged_reason "
964  "-snes_ksp -snes_linesearch_monitor -snes_mf -snes_mf_operator -snes_monitor "
965  "-snes_test_display -snes_view -snes_monitor_cancel",
966  "",
967  true);
968 }
969 
972 {
973  return MultiMooseEnum(
974  "-ksp_converged_reason -ksp_gmres_modifiedgramschmidt -ksp_monitor", "", true);
975 }
976 
979 {
980  auto options = MultiMooseEnum("-dm_moose_print_embedding -dm_view", "", true);
981  options.addValidName(getCommonKSPFlags());
982  options.addValidName(getCommonSNESFlags());
983  return options;
984 }
985 
988 {
989  return MultiMooseEnum("-snes_atol -snes_linesearch_type -snes_ls -snes_max_it -snes_rtol "
990  "-snes_divergence_tolerance -snes_type",
991  "",
992  true);
993 }
994 
997 {
998  return MultiMooseEnum("-ksp_atol -ksp_gmres_restart -ksp_max_it -ksp_pc_side -ksp_rtol "
999  "-ksp_type -sub_ksp_type",
1000  "",
1001  true);
1002 }
1005 {
1006  auto options = MultiMooseEnum("-mat_fd_coloring_err -mat_fd_type -mat_mffd_type "
1007  "-pc_asm_overlap -pc_factor_levels "
1008  "-pc_factor_mat_ordering_type -pc_hypre_boomeramg_grid_sweeps_all "
1009  "-pc_hypre_boomeramg_max_iter "
1010  "-pc_hypre_boomeramg_strong_threshold -pc_hypre_type -pc_type "
1011  "-sub_pc_type",
1012  "",
1013  true);
1014  options.addValidName(getCommonKSPKeys());
1015  options.addValidName(getCommonSNESKeys());
1016  return options;
1017 }
1018 
1019 bool
1021 {
1022  const PetscOptions & petsc = fe_problem.getPetscOptions();
1023 
1024  int argc;
1025  char ** args;
1026  LibmeshPetscCallA(fe_problem.comm().get(), PetscGetArgs(&argc, &args));
1027 
1028  std::vector<std::string> cml_arg;
1029  for (int i = 0; i < argc; i++)
1030  cml_arg.push_back(args[i]);
1031 
1032  if (MooseUtils::findPair(petsc.pairs, petsc.pairs.begin(), MooseUtils::Any, "vinewtonssls") ==
1033  petsc.pairs.end() &&
1034  MooseUtils::findPair(petsc.pairs, petsc.pairs.begin(), MooseUtils::Any, "vinewtonrsls") ==
1035  petsc.pairs.end() &&
1036  std::find(cml_arg.begin(), cml_arg.end(), "vinewtonssls") == cml_arg.end() &&
1037  std::find(cml_arg.begin(), cml_arg.end(), "vinewtonrsls") == cml_arg.end())
1038  return false;
1039 
1040  return true;
1041 }
1042 
1043 void
1044 setSinglePetscOption(const std::string & name,
1045  const std::string & value /*=""*/,
1046  FEProblemBase * const problem /*=nullptr*/)
1047 {
1048  static const TIMPI::Communicator comm_world(PETSC_COMM_WORLD);
1049  const TIMPI::Communicator & comm = problem ? problem->comm() : comm_world;
1050  LibmeshPetscCallA(comm.get(),
1051  PetscOptionsSetValue(LIBMESH_PETSC_NULLPTR,
1052  name.c_str(),
1053  value == "" ? LIBMESH_PETSC_NULLPTR : value.c_str()));
1054  const auto lower_case_name = MooseUtils::toLower(name);
1055  auto check_problem = [problem, &lower_case_name]()
1056  {
1057  if (!problem)
1058  mooseError(
1059  "Setting the option '",
1060  lower_case_name,
1061  "' requires passing a 'problem' parameter. Contact a developer of your application "
1062  "to have them update their code. If in doubt, reach out to the MOOSE team on Github "
1063  "discussions");
1064  };
1065 
1066  // Select vector type from user-passed PETSc options
1067  if (lower_case_name.find("-vec_type") != std::string::npos)
1068  {
1069  check_problem();
1070  for (auto & solver_system : problem->_solver_systems)
1071  {
1072  auto & lm_sys = solver_system->system();
1073  for (auto & [vec_name, vec] : as_range(lm_sys.vectors_begin(), lm_sys.vectors_end()))
1074  {
1075  libmesh_ignore(vec_name);
1076  auto * const petsc_vec = cast_ptr<PetscVector<Number> *>(vec.get());
1077  LibmeshPetscCallA(comm.get(), VecSetFromOptions(petsc_vec->vec()));
1078  }
1079  // The solution vectors aren't included in the system vectors storage
1080  auto * petsc_vec = cast_ptr<PetscVector<Number> *>(lm_sys.solution.get());
1081  LibmeshPetscCallA(comm.get(), VecSetFromOptions(petsc_vec->vec()));
1082  petsc_vec = cast_ptr<PetscVector<Number> *>(lm_sys.current_local_solution.get());
1083  LibmeshPetscCallA(comm.get(), VecSetFromOptions(petsc_vec->vec()));
1084  }
1085  }
1086  // Select matrix type from user-passed PETSc options
1087  else if (lower_case_name.find("mat_type") != std::string::npos)
1088  {
1089  check_problem();
1090 
1091  bool found_matching_prefix = false;
1092  for (const auto i : index_range(problem->_solver_systems))
1093  {
1094  const auto & solver_sys_name = problem->_solver_sys_names[i];
1095  if (lower_case_name.find("-" + MooseUtils::toLower(solver_sys_name) + "_mat_type") ==
1096  std::string::npos)
1097  continue;
1098 
1099  if (problem->solverParams(i)._type == Moose::ST_JFNK)
1100  mooseError(
1101  "Setting option '", lower_case_name, "' is incompatible with a JFNK 'solve_type'");
1102 
1103  auto & lm_sys = problem->_solver_systems[i]->system();
1104  for (auto & [mat_name, mat] : as_range(lm_sys.matrices_begin(), lm_sys.matrices_end()))
1105  {
1106  libmesh_ignore(mat_name);
1107  if (auto * const petsc_mat = dynamic_cast<PetscMatrixBase<Number> *>(mat.get()); petsc_mat)
1108  {
1109 #ifdef DEBUG
1110  const char * mat_prefix;
1111  LibmeshPetscCallA(comm.get(), MatGetOptionsPrefix(petsc_mat->mat(), &mat_prefix));
1112  mooseAssert(strcmp(mat_prefix, (solver_sys_name + "_").c_str()) == 0,
1113  "We should have prefixed these matrices previously");
1114 #endif
1115  LibmeshPetscCallA(comm.get(), MatSetFromOptions(petsc_mat->mat()));
1116  }
1117  }
1118  found_matching_prefix = true;
1119  break;
1120  }
1121 
1122  if (!found_matching_prefix)
1123  mooseError("We did not find a matching solver system name for the petsc option '",
1124  lower_case_name,
1125  "'");
1126  }
1127 }
1128 
1129 void
1130 setSinglePetscOptionIfAppropriate(const MultiMooseEnum & dont_add_these_options,
1131  const std::string & name,
1132  const std::string & value /*=""*/,
1133  FEProblemBase * const problem /*=nullptr*/)
1134 {
1135  if (!dont_add_these_options.contains(name))
1136  setSinglePetscOption(name, value, problem);
1137 }
1138 
1139 void
1140 colorAdjacencyMatrix(PetscScalar * adjacency_matrix,
1141  unsigned int size,
1142  unsigned int colors,
1143  std::vector<unsigned int> & vertex_colors,
1144  const char * coloring_algorithm)
1145 {
1146  // Mat A will be a dense matrix from the incoming data structure
1147  Mat A;
1148  LibmeshPetscCallA(PETSC_COMM_SELF, MatCreate(PETSC_COMM_SELF, &A));
1149  LibmeshPetscCallA(PETSC_COMM_SELF, MatSetSizes(A, size, size, size, size));
1150  LibmeshPetscCallA(PETSC_COMM_SELF, MatSetType(A, MATSEQDENSE));
1151  // PETSc requires a non-const data array to populate the matrix
1152  LibmeshPetscCallA(PETSC_COMM_SELF, MatSeqDenseSetPreallocation(A, adjacency_matrix));
1153  LibmeshPetscCallA(PETSC_COMM_SELF, MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY));
1154  LibmeshPetscCallA(PETSC_COMM_SELF, MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY));
1155 
1156  // Convert A to a sparse matrix
1157 #if PETSC_VERSION_LESS_THAN(3, 7, 0)
1158  LibmeshPetscCallA(PETSC_COMM_SELF, MatConvert(A, MATAIJ, MAT_REUSE_MATRIX, &A));
1159 #else
1160  LibmeshPetscCallA(PETSC_COMM_SELF, MatConvert(A, MATAIJ, MAT_INPLACE_MATRIX, &A));
1161 #endif
1162 
1163  ISColoring iscoloring;
1164  MatColoring mc;
1165  LibmeshPetscCallA(PETSC_COMM_SELF, MatColoringCreate(A, &mc));
1166  LibmeshPetscCallA(PETSC_COMM_SELF, MatColoringSetType(mc, coloring_algorithm));
1167  LibmeshPetscCallA(PETSC_COMM_SELF, MatColoringSetMaxColors(mc, static_cast<PetscInt>(colors)));
1168 
1169  // Petsc normally colors by distance two (neighbors of neighbors), we just want one
1170  LibmeshPetscCallA(PETSC_COMM_SELF, MatColoringSetDistance(mc, 1));
1171  LibmeshPetscCallA(PETSC_COMM_SELF, MatColoringSetFromOptions(mc));
1172  LibmeshPetscCallA(PETSC_COMM_SELF, MatColoringApply(mc, &iscoloring));
1173 
1174  PetscInt nn;
1175  IS * is;
1176 #if PETSC_RELEASE_LESS_THAN(3, 12, 0)
1177  LibmeshPetscCallA(PETSC_COMM_SELF, ISColoringGetIS(iscoloring, &nn, &is));
1178 #else
1179  LibmeshPetscCallA(PETSC_COMM_SELF, ISColoringGetIS(iscoloring, PETSC_USE_POINTER, &nn, &is));
1180 #endif
1181 
1182  if (nn > static_cast<PetscInt>(colors))
1183  throw std::runtime_error("Not able to color with designated number of colors");
1184 
1185  for (int i = 0; i < nn; i++)
1186  {
1187  PetscInt isize;
1188  const PetscInt * indices;
1189  LibmeshPetscCallA(PETSC_COMM_SELF, ISGetLocalSize(is[i], &isize));
1190  LibmeshPetscCallA(PETSC_COMM_SELF, ISGetIndices(is[i], &indices));
1191  for (int j = 0; j < isize; j++)
1192  {
1193  mooseAssert(indices[j] < static_cast<PetscInt>(vertex_colors.size()), "Index out of bounds");
1194  vertex_colors[indices[j]] = i;
1195  }
1196  LibmeshPetscCallA(PETSC_COMM_SELF, ISRestoreIndices(is[i], &indices));
1197  }
1198 
1199  LibmeshPetscCallA(PETSC_COMM_SELF, MatDestroy(&A));
1200  LibmeshPetscCallA(PETSC_COMM_SELF, MatColoringDestroy(&mc));
1201  LibmeshPetscCallA(PETSC_COMM_SELF, ISColoringDestroy(&iscoloring));
1202 }
1203 
1204 void
1205 dontAddPetscFlag(const std::string & flag, PetscOptions & petsc_options)
1206 {
1207  if (!petsc_options.dont_add_these_options.contains(flag))
1208  petsc_options.dont_add_these_options.setAdditionalValue(flag);
1209 }
1210 
1211 void
1213 {
1214  dontAddPetscFlag("-snes_converged_reason", fe_problem.getPetscOptions());
1215 }
1216 
1217 void
1219 {
1220  dontAddPetscFlag("-ksp_converged_reason", fe_problem.getPetscOptions());
1221 }
1222 
1223 void
1225 {
1226  auto & petsc_options = fe_problem.getPetscOptions();
1227  for (const auto & flag : getCommonKSPFlags().getNames())
1228  dontAddPetscFlag(flag, petsc_options);
1229  for (const auto & key : getCommonKSPKeys().getNames())
1230  dontAddPetscFlag(key, petsc_options);
1231 }
1232 
1233 void
1235 {
1236  auto & petsc_options = fe_problem.getPetscOptions();
1237  for (const auto & flag : getCommonSNESFlags().getNames())
1238  if (!petsc_options.dont_add_these_options.contains(flag))
1239  petsc_options.dont_add_these_options.setAdditionalValue(flag);
1240  for (const auto & key : getCommonSNESKeys().getNames())
1241  if (!petsc_options.dont_add_these_options.contains(key))
1242  petsc_options.dont_add_these_options.setAdditionalValue(key);
1243 }
1244 
1245 std::unique_ptr<PetscMatrix<Number>>
1247  Mat & mat,
1248  const std::string & binary_mat_file,
1249  const unsigned int mat_number_to_load)
1250 {
1251  LibmeshPetscCallA(comm.get(), MatCreate(comm.get(), &mat));
1252  PetscViewer matviewer;
1253  LibmeshPetscCallA(
1254  comm.get(),
1255  PetscViewerBinaryOpen(comm.get(), binary_mat_file.c_str(), FILE_MODE_READ, &matviewer));
1256  for (unsigned int i = 0; i < mat_number_to_load; ++i)
1257  LibmeshPetscCallA(comm.get(), MatLoad(mat, matviewer));
1258  LibmeshPetscCallA(comm.get(), PetscViewerDestroy(&matviewer));
1259 
1260  return std::make_unique<PetscMatrix<Number>>(mat, comm);
1261 }
1262 
1263 } // Namespace PetscSupport
1264 } // 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:996
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:658
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:855
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:919
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:960
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:613
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:670
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:978
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:714
void setLineSearchFromParams(FEProblemBase &fe_problem, const InputParameters &params)
Sets the FE problem&#39;s line search from the input params.
Definition: PetscSupport.C:626
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:971
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:925
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:737
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:987
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:678
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:588
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.