https://mooseframework.inl.gov
FEProblemBase.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 #ifdef MOOSE_KOKKOS_ENABLED
12 #endif
13 
14 #include "FEProblemBase.h"
15 #include "AuxiliarySystem.h"
17 #include "MooseEnum.h"
18 #include "Factory.h"
19 #include "MooseUtils.h"
20 #include "DisplacedProblem.h"
21 #include "SystemBase.h"
22 #include "MaterialData.h"
28 #include "ComputeIndicatorThread.h"
29 #include "ComputeMarkerThread.h"
33 #include "MaxQpsThread.h"
34 #include "ActionWarehouse.h"
35 #include "Conversion.h"
36 #include "Material.h"
37 #include "FunctorMaterial.h"
38 #include "ConstantIC.h"
39 #include "Parser.h"
40 #include "ElementH1Error.h"
41 #include "Function.h"
42 #include "Convergence.h"
43 #include "NonlinearSystem.h"
44 #include "LinearSystem.h"
45 #include "SolverSystem.h"
46 #include "Distribution.h"
47 #include "Sampler.h"
48 #include "PetscSupport.h"
49 #include "RandomInterface.h"
50 #include "RandomData.h"
51 #include "MooseEigenSystem.h"
52 #include "MooseParsedFunction.h"
53 #include "MeshChangedInterface.h"
54 #include "MeshDisplacedInterface.h"
56 #include "ScalarInitialCondition.h"
58 #include "ElementPostprocessor.h"
59 #include "NodalPostprocessor.h"
60 #include "SidePostprocessor.h"
62 #include "InterfacePostprocessor.h"
63 #include "GeneralPostprocessor.h"
69 #include "Positions.h"
70 #include "Indicator.h"
71 #include "Marker.h"
72 #include "MultiApp.h"
73 #include "MultiAppTransfer.h"
74 #include "TransientMultiApp.h"
75 #include "ElementUserObject.h"
76 #include "DomainUserObject.h"
77 #include "NodalUserObject.h"
78 #include "SideUserObject.h"
79 #include "InternalSideUserObject.h"
80 #include "InterfaceUserObject.h"
81 #include "GeneralUserObject.h"
84 #include "Transfer.h"
85 #include "MultiAppTransfer.h"
86 #include "MultiMooseEnum.h"
87 #include "Predictor.h"
88 #include "Assembly.h"
89 #include "Control.h"
90 #include "XFEMInterface.h"
91 #include "ConsoleUtils.h"
92 #include "NonlocalKernel.h"
93 #include "NonlocalIntegratedBC.h"
94 #include "ShapeElementUserObject.h"
95 #include "ShapeSideUserObject.h"
96 #include "MooseVariableFE.h"
97 #include "MooseVariableScalar.h"
99 #include "TimeIntegrator.h"
100 #include "LineSearch.h"
102 #include "MaxVarNDofsPerElem.h"
103 #include "MaxVarNDofsPerNode.h"
104 #include "FVKernel.h"
105 #include "LinearFVKernel.h"
106 #include "FVTimeKernel.h"
107 #include "MooseVariableFV.h"
108 #include "MooseLinearVariableFV.h"
109 #include "FVBoundaryCondition.h"
111 #include "FVInterfaceKernel.h"
112 #include "Reporter.h"
113 #include "ADUtils.h"
114 #include "Executioner.h"
115 #include "VariadicTable.h"
118 #include "NodalBCBase.h"
119 #include "MortarUserObject.h"
120 #include "MortarUserObjectThread.h"
121 #include "RedistributeProperties.h"
122 #include "Checkpoint.h"
123 
124 #include "libmesh/exodusII_io.h"
125 #include "libmesh/quadrature.h"
126 #include "libmesh/coupling_matrix.h"
127 #include "libmesh/nonlinear_solver.h"
128 #include "libmesh/sparse_matrix.h"
129 #include "libmesh/string_to_enum.h"
130 #include "libmesh/fe_interface.h"
131 #include "libmesh/enum_norm_type.h"
132 #include "libmesh/petsc_solver_exception.h"
133 
134 #include "metaphysicl/dualnumber.h"
135 
136 using namespace libMesh;
137 
138 // Anonymous namespace for helper function
139 namespace
140 {
144 bool
145 sortMooseVariables(const MooseVariableFEBase * a, const MooseVariableFEBase * b)
146 {
147  return a->number() < b->number();
148 }
149 } // namespace
150 
152 
155 {
157  params.addParam<unsigned int>("null_space_dimension", 0, "The dimension of the nullspace");
158  params.addParam<unsigned int>(
159  "transpose_null_space_dimension", 0, "The dimension of the transpose nullspace");
160  params.addParam<unsigned int>(
161  "near_null_space_dimension", 0, "The dimension of the near nullspace");
162  params.addParam<bool>("solve",
163  true,
164  "Whether or not to actually solve the Nonlinear system. "
165  "This is handy in the case that all you want to do is "
166  "execute AuxKernels, Transfers, etc. without actually "
167  "solving anything");
168  params.addParam<bool>("use_nonlinear",
169  true,
170  "Determines whether to use a Nonlinear vs a "
171  "Eigenvalue system (Automatically determined based "
172  "on executioner)");
173  params.addParam<bool>("error_on_jacobian_nonzero_reallocation",
174  "This causes PETSc to error if it had to reallocate memory in the Jacobian "
175  "matrix due to not having enough nonzeros");
176  params.addParam<bool>("ignore_zeros_in_jacobian",
177  false,
178  "Do not explicitly store zero values in "
179  "the Jacobian matrix if true");
180  params.addParam<bool>("force_restart",
181  false,
182  "EXPERIMENTAL: If true, a sub_app may use a "
183  "restart file instead of using of using the master "
184  "backup file");
185  params.addDeprecatedParam<bool>("skip_additional_restart_data",
186  false,
187  "True to skip additional data in equation system for restart.",
188  "This parameter is no longer used, as we do not load additional "
189  "vectors by default with restart");
190  params.addParam<bool>("skip_nl_system_check",
191  false,
192  "True to skip the NonlinearSystem check for work to do (e.g. Make sure "
193  "that there are variables to solve for).");
194  params.addParam<bool>("allow_initial_conditions_with_restart",
195  false,
196  "True to allow the user to specify initial conditions when restarting. "
197  "Initial conditions can override any restarted field");
198 
199  auto coverage_check_description = [](std::string scope, std::string list_param_name)
200  {
201  return "Controls, if and how a " + scope +
202  " subdomain coverage check is performed. "
203  "With 'TRUE' or 'ON' all subdomains are checked (the default). Setting 'FALSE' or 'OFF' "
204  "will disable the check for all subdomains. "
205  "To exclude a predefined set of subdomains 'SKIP_LIST' is to "
206  "be used, while the subdomains to skip are to be defined in the parameter '" +
207  list_param_name +
208  "'. To limit the check to a list of subdomains, 'ONLY_LIST' is to "
209  "be used (again, using the parameter '" +
210  list_param_name + "').";
211  };
212 
213  params.addParam<std::vector<SubdomainName>>(
214  "block",
215  {"ANY_BLOCK_ID"},
216  "List of subdomains for kernel coverage and material coverage checks. Setting this parameter "
217  "is equivalent to setting 'kernel_coverage_block_list' and 'material_coverage_block_list' as "
218  "well as using 'ONLY_LIST' as the coverage check mode.");
219 
220  MooseEnum kernel_coverage_check_modes("FALSE TRUE OFF ON SKIP_LIST ONLY_LIST", "TRUE");
221  params.addParam<MooseEnum>("kernel_coverage_check",
222  kernel_coverage_check_modes,
223  coverage_check_description("kernel", "kernel_coverage_block_list"));
224  params.addParam<std::vector<SubdomainName>>(
225  "kernel_coverage_block_list",
226  {},
227  "List of subdomains for kernel coverage check. The meaning of this list is controlled by the "
228  "parameter 'kernel_coverage_check' (whether this is the list of subdomains to be checked, "
229  "not to be checked or not taken into account).");
230  params.addParam<bool>(
231  "boundary_restricted_node_integrity_check",
232  true,
233  "Set to false to disable checking of boundary restricted nodal object variable dependencies, "
234  "e.g. are the variable dependencies defined on the selected boundaries?");
235  params.addParam<bool>("boundary_restricted_elem_integrity_check",
236  true,
237  "Set to false to disable checking of boundary restricted elemental object "
238  "variable dependencies, e.g. are the variable dependencies defined on the "
239  "selected boundaries?");
240  MooseEnum material_coverage_check_modes("FALSE TRUE OFF ON SKIP_LIST ONLY_LIST", "TRUE");
241  params.addParam<MooseEnum>(
242  "material_coverage_check",
243  material_coverage_check_modes,
244  coverage_check_description("material", "material_coverage_block_list"));
245  params.addParam<std::vector<SubdomainName>>(
246  "material_coverage_block_list",
247  {},
248  "List of subdomains for material coverage check. The meaning of this list is controlled by "
249  "the parameter 'material_coverage_check' (whether this is the list of subdomains to be "
250  "checked, not to be checked or not taken into account).");
251 
252  params.addParam<bool>("fv_bcs_integrity_check",
253  true,
254  "Set to false to disable checking of overlapping Dirichlet and Flux BCs "
255  "and/or multiple DirichletBCs per sideset");
256 
257  params.addParam<bool>(
258  "material_dependency_check", true, "Set to false to disable material dependency check");
259  params.addParam<bool>("parallel_barrier_messaging",
260  false,
261  "Displays messaging from parallel "
262  "barrier notifications when executing "
263  "or transferring to/from Multiapps "
264  "(default: false)");
265 
266  MooseEnum verbosity("false true extra", "false");
267  params.addParam<MooseEnum>("verbose_setup",
268  verbosity,
269  "Set to 'true' to have the problem report on any object created. Set "
270  "to 'extra' to also display all parameters.");
271  params.addParam<bool>("verbose_multiapps",
272  false,
273  "Set to True to enable verbose screen printing related to MultiApps");
274  params.addParam<bool>(
275  "verbose_restore",
276  false,
277  "Set to True to enable verbose screen printing related to solution restoration");
278 
279  params.addParam<FileNameNoExtension>("restart_file_base",
280  "File base name used for restart (e.g. "
281  "<path>/<filebase> or <path>/LATEST to "
282  "grab the latest file available)");
283 
284  params.addParam<std::vector<std::vector<TagName>>>(
285  "extra_tag_vectors",
286  {},
287  "Extra vectors to add to the system that can be filled by objects which compute residuals "
288  "and Jacobians (Kernels, BCs, etc.) by setting tags on them. The outer index is for which "
289  "nonlinear system the extra tag vectors should be added for");
290 
291  params.addParam<std::vector<std::vector<TagName>>>(
292  "not_zeroed_tag_vectors",
293  {},
294  "Extra vector tags which the sytem will not zero when other vector tags are zeroed. "
295  "The outer index is for which nonlinear system the extra tag vectors should be added for");
296 
297  params.addParam<std::vector<std::vector<TagName>>>(
298  "extra_tag_matrices",
299  {},
300  "Extra matrices to add to the system that can be filled "
301  "by objects which compute residuals and Jacobians "
302  "(Kernels, BCs, etc.) by setting tags on them. The outer index is for which "
303  "nonlinear system the extra tag vectors should be added for");
304 
305  params.addParam<std::vector<TagName>>(
306  "extra_tag_solutions",
307  {},
308  "Extra solution vectors to add to the system that can be used by "
309  "objects for coupling variable values stored in them.");
310 
311  params.addParam<bool>("previous_nl_solution_required",
312  false,
313  "True to indicate that this calculation requires a solution vector for "
314  "storing the previous nonlinear iteration.");
315 
316  params.addParam<std::vector<NonlinearSystemName>>(
317  "nl_sys_names", std::vector<NonlinearSystemName>{"nl0"}, "The nonlinear system names");
318 
319  params.addParam<std::vector<LinearSystemName>>("linear_sys_names", {}, "The linear system names");
320 
321  params.addParam<bool>("check_uo_aux_state",
322  false,
323  "True to turn on a check that no state presents during the evaluation of "
324  "user objects and aux kernels");
325 
326  params.addPrivateParam<MooseMesh *>("mesh");
327 
328  params.declareControllable("solve");
329 
330  params.addParam<bool>(
331  "allow_invalid_solution",
332  false,
333  "Set to true to allow convergence even though the solution has been marked as 'invalid'");
334  params.addParam<bool>("show_invalid_solution_console",
335  true,
336  "Set to true to show the invalid solution occurance summary in console");
337  params.addParam<bool>("immediately_print_invalid_solution",
338  false,
339  "Whether or not to report invalid solution warnings at the time the "
340  "warning is produced instead of after the calculation");
341 
342  params.addParam<bool>(
343  "identify_variable_groups_in_nl",
344  true,
345  "Whether to identify variable groups in nonlinear systems. This affects dof ordering");
346 
347  params.addParam<bool>(
348  "regard_general_exceptions_as_errors",
349  false,
350  "If we catch an exception during residual/Jacobian evaluaton for which we don't have "
351  "specific handling, immediately error instead of allowing the time step to be cut");
352 
353  params.addParam<bool>("use_hash_table_matrix_assembly",
354  false,
355  "Whether to assemble matrices using hash tables instead of preallocating "
356  "matrix memory. This can be a good option if the sparsity pattern changes "
357  "throughout the course of the simulation.");
358  params.addParam<bool>(
359  "restore_original_nonzero_pattern",
360  "Whether we should reset matrix memory for every Jacobian evaluation. This option is useful "
361  "if the sparsity pattern is constantly changing and you are using hash table assembly or if "
362  "you wish to continually restore the matrix to the originally preallocated sparsity pattern "
363  "computed by relationship managers.");
364 
365  params.addParamNamesToGroup(
366  "skip_nl_system_check kernel_coverage_check kernel_coverage_block_list "
367  "boundary_restricted_node_integrity_check "
368  "boundary_restricted_elem_integrity_check material_coverage_check "
369  "material_coverage_block_list fv_bcs_integrity_check "
370  "material_dependency_check check_uo_aux_state error_on_jacobian_nonzero_reallocation",
371  "Simulation checks");
372  params.addParamNamesToGroup("use_nonlinear previous_nl_solution_required nl_sys_names "
373  "ignore_zeros_in_jacobian identify_variable_groups_in_nl "
374  "use_hash_table_matrix_assembly restore_original_nonzero_pattern",
375  "Nonlinear system(s)");
376  params.addParamNamesToGroup(
377  "restart_file_base force_restart allow_initial_conditions_with_restart", "Restart");
378  params.addParamNamesToGroup(
379  "verbose_setup verbose_multiapps verbose_restore parallel_barrier_messaging", "Verbosity");
380  params.addParamNamesToGroup(
381  "null_space_dimension transpose_null_space_dimension near_null_space_dimension",
382  "Null space removal");
383  params.addParamNamesToGroup(
384  "extra_tag_vectors extra_tag_matrices extra_tag_solutions not_zeroed_tag_vectors",
385  "Contribution to tagged field data");
386  params.addParamNamesToGroup(
387  "allow_invalid_solution show_invalid_solution_console immediately_print_invalid_solution",
388  "Solution validity control");
389 
390  return params;
391 }
392 
394  : SubProblem(parameters),
395  Restartable(this, "FEProblemBase"),
396  _mesh(*getCheckedPointerParam<MooseMesh *>("mesh")),
397  _req(declareManagedRestartableDataWithContext<RestartableEquationSystems>(
398  "equation_systems", nullptr, _mesh)),
399  _initialized(false),
400  _solve(getParam<bool>("solve")),
401  _transient(false),
402  _time(declareRestartableData<Real>("time")),
403  _time_old(declareRestartableData<Real>("time_old")),
404  _t_step(declareRecoverableData<int>("t_step")),
405  _dt(declareRestartableData<Real>("dt")),
406  _dt_old(declareRestartableData<Real>("dt_old")),
407  _need_to_add_default_nonlinear_convergence(false),
408  _need_to_add_default_multiapp_fixed_point_convergence(false),
409  _need_to_add_default_steady_state_convergence(false),
410  _linear_sys_names(getParam<std::vector<LinearSystemName>>("linear_sys_names")),
411  _num_linear_sys(_linear_sys_names.size()),
412  _linear_systems(_num_linear_sys, nullptr),
413  _current_linear_sys(nullptr),
414  _using_default_nl(!isParamSetByUser("nl_sys_names")),
415  _nl_sys_names(!_using_default_nl || (_using_default_nl && !_linear_sys_names.size())
416  ? getParam<std::vector<NonlinearSystemName>>("nl_sys_names")
417  : std::vector<NonlinearSystemName>()),
418  _num_nl_sys(_nl_sys_names.size()),
419  _nl(_num_nl_sys, nullptr),
420  _current_nl_sys(nullptr),
421  _solver_systems(_num_nl_sys + _num_linear_sys, nullptr),
422  _aux(nullptr),
423  _coupling(Moose::COUPLING_DIAG),
424 #ifdef MOOSE_KOKKOS_ENABLED
425  _kokkos_assembly(*this),
426 #endif
427  _mesh_divisions(/*threaded=*/true),
428  _material_props(declareRestartableDataWithContext<MaterialPropertyStorage>(
429  "material_props", &_mesh, _material_prop_registry, *this)),
430  _bnd_material_props(declareRestartableDataWithContext<MaterialPropertyStorage>(
431  "bnd_material_props", &_mesh, _material_prop_registry, *this)),
432  _neighbor_material_props(declareRestartableDataWithContext<MaterialPropertyStorage>(
433  "neighbor_material_props", &_mesh, _material_prop_registry, *this)),
434 #ifdef MOOSE_KOKKOS_ENABLED
435  _kokkos_material_props(
436  declareRestartableDataWithContext<Moose::Kokkos::MaterialPropertyStorage>(
437  "kokkos_material_props", &_mesh, _material_prop_registry, *this)),
438  _kokkos_bnd_material_props(
439  declareRestartableDataWithContext<Moose::Kokkos::MaterialPropertyStorage>(
440  "kokkos_bnd_material_props", &_mesh, _material_prop_registry, *this)),
441  _kokkos_neighbor_material_props(
442  declareRestartableDataWithContext<Moose::Kokkos::MaterialPropertyStorage>(
443  "kokkos_neighbor_material_props", &_mesh, _material_prop_registry, *this)),
444 #endif
445  _reporter_data(_app),
446  // TODO: delete the following line after apps have been updated to not call getUserObjects
447  _all_user_objects(_app.getExecuteOnEnum()),
448  _multi_apps(_app.getExecuteOnEnum()),
449  _transient_multi_apps(_app.getExecuteOnEnum()),
450  _transfers(_app.getExecuteOnEnum(), /*threaded=*/false),
451  _to_multi_app_transfers(_app.getExecuteOnEnum(), /*threaded=*/false),
452  _from_multi_app_transfers(_app.getExecuteOnEnum(), /*threaded=*/false),
453  _between_multi_app_transfers(_app.getExecuteOnEnum(), /*threaded=*/false),
454 #ifdef LIBMESH_ENABLE_AMR
455  _adaptivity(*this),
456  _cycles_completed(0),
457 #endif
458  _displaced_mesh(nullptr),
459  _geometric_search_data(*this, _mesh),
460  _mortar_data(*this),
461  _reinit_displaced_elem(false),
462  _reinit_displaced_face(false),
463  _reinit_displaced_neighbor(false),
464  _input_file_saved(false),
465  _has_dampers(false),
466  _has_constraints(false),
467  _snesmf_reuse_base(true),
468  _skip_exception_check(false),
469  _snesmf_reuse_base_set_by_user(false),
470  _has_initialized_stateful(false),
471  _const_jacobian(false),
472  _has_jacobian(false),
473  _needs_old_newton_iter(false),
474  _previous_nl_solution_required(getParam<bool>("previous_nl_solution_required")),
475  _has_nonlocal_coupling(false),
476  _calculate_jacobian_in_uo(false),
477  _kernel_coverage_check(
478  getParam<MooseEnum>("kernel_coverage_check").getEnum<CoverageCheckMode>()),
479  _kernel_coverage_blocks(getParam<std::vector<SubdomainName>>("kernel_coverage_block_list")),
480  _boundary_restricted_node_integrity_check(
481  getParam<bool>("boundary_restricted_node_integrity_check")),
482  _boundary_restricted_elem_integrity_check(
483  getParam<bool>("boundary_restricted_elem_integrity_check")),
484  _material_coverage_check(
485  getParam<MooseEnum>("material_coverage_check").getEnum<CoverageCheckMode>()),
486  _material_coverage_blocks(getParam<std::vector<SubdomainName>>("material_coverage_block_list")),
487  _fv_bcs_integrity_check(getParam<bool>("fv_bcs_integrity_check")),
488  _material_dependency_check(getParam<bool>("material_dependency_check")),
489  _uo_aux_state_check(getParam<bool>("check_uo_aux_state")),
490  _max_qps(std::numeric_limits<unsigned int>::max()),
491  _max_scalar_order(INVALID_ORDER),
492  _has_time_integrator(false),
493  _has_exception(false),
494  _parallel_barrier_messaging(getParam<bool>("parallel_barrier_messaging")),
495  _verbose_setup(getParam<MooseEnum>("verbose_setup")),
496  _verbose_multiapps(getParam<bool>("verbose_multiapps")),
497  _verbose_restore(getParam<bool>("verbose_restore")),
498  _current_execute_on_flag(EXEC_NONE),
499  _control_warehouse(_app.getExecuteOnEnum(), /*threaded=*/false),
500  _is_petsc_options_inserted(false),
501  _line_search(nullptr),
502  _using_ad_mat_props(false),
503  _current_ic_state(0),
504  _use_hash_table_matrix_assembly(getParam<bool>("use_hash_table_matrix_assembly")),
505  _error_on_jacobian_nonzero_reallocation(
506  isParamValid("error_on_jacobian_nonzero_reallocation")
507  ? getParam<bool>("error_on_jacobian_nonzero_reallocation")
508  : _app.errorOnJacobianNonzeroReallocation()),
509  _restore_original_nonzero_pattern(isParamValid("restore_original_nonzero_pattern")
510  ? getParam<bool>("restore_original_nonzero_pattern")
511  : _use_hash_table_matrix_assembly),
512  _ignore_zeros_in_jacobian(getParam<bool>("ignore_zeros_in_jacobian")),
513  _preserve_matrix_sparsity_pattern(true),
514  _force_restart(getParam<bool>("force_restart")),
515  _allow_ics_during_restart(getParam<bool>("allow_initial_conditions_with_restart")),
516  _skip_nl_system_check(getParam<bool>("skip_nl_system_check")),
517  _fail_next_system_convergence_check(false),
518  _allow_invalid_solution(getParam<bool>("allow_invalid_solution")),
519  _show_invalid_solution_console(getParam<bool>("show_invalid_solution_console")),
520  _immediately_print_invalid_solution(getParam<bool>("immediately_print_invalid_solution")),
521  _started_initial_setup(false),
522  _has_internal_edge_residual_objects(false),
523  _u_dot_requested(false),
524  _u_dotdot_requested(false),
525  _u_dot_old_requested(false),
526  _u_dotdot_old_requested(false),
527  _has_mortar(false),
528  _num_grid_steps(0),
529  _print_execution_on(),
530  _identify_variable_groups_in_nl(getParam<bool>("identify_variable_groups_in_nl")),
531  _regard_general_exceptions_as_errors(getParam<bool>("regard_general_exceptions_as_errors")),
532  _requires_nonlocal_coupling(false)
533 {
534  auto checkCoverageCheckConflict =
535  [this](const std::string & coverage_check,
536  const CoverageCheckMode & coverage_check_mode,
537  const std::vector<SubdomainName> & coverage_blocks) -> void
538  {
539  if (coverage_check_mode != CoverageCheckMode::FALSE &&
540  coverage_check_mode != CoverageCheckMode::OFF)
541  if (coverage_blocks.size() > 1)
542  if (std::find(coverage_blocks.begin(), coverage_blocks.end(), "ANY_BLOCK_ID") !=
543  coverage_blocks.end())
544  paramError(coverage_check,
545  "The list of blocks used for ",
546  coverage_check,
547  " cannot contain 'ANY_BLOCK_ID' along with other blocks. ");
548  };
549 
550  checkCoverageCheckConflict(
551  "kernel_coverage_check", _kernel_coverage_check, _kernel_coverage_blocks);
552  checkCoverageCheckConflict(
553  "material_coverage_check", _material_coverage_check, _material_coverage_blocks);
554 
555  // Initialize static do_derivatives member. We initialize this to true so that all the
556  // default AD things that we setup early in the simulation actually get their derivative
557  // vectors initalized. We will toggle this to false when doing residual evaluations
558  ADReal::do_derivatives = true;
559 
560  // Disable refinement/coarsening in EquationSystems::reinit because we already do this ourselves
562 
564  // Default constructor fine for nonlinear because it will be populated later by framework
565  // executioner/solve object parameters
566  _solver_params.resize(_num_nl_sys);
567  for (const auto i : index_range(_nl_sys_names))
568  {
569  const auto & name = _nl_sys_names[i];
572  _solver_sys_names.push_back(name);
573  }
574 
575  for (const auto i : index_range(_linear_sys_names))
576  {
577  const auto & name = _linear_sys_names[i];
580  _solver_sys_names.push_back(name);
581  // Unlike for nonlinear these are basically dummy parameters
583  }
584 
585  _nonlocal_cm.resize(numSolverSystems());
586  _cm.resize(numSolverSystems());
587 
588  _time = 0.0;
589  _time_old = 0.0;
590  _t_step = 0;
591  _dt = 0;
592  _dt_old = _dt;
593 
594  unsigned int n_threads = libMesh::n_threads();
595 
596  _real_zero.resize(n_threads, 0.);
597  _scalar_zero.resize(n_threads);
598  _zero.resize(n_threads);
599  _phi_zero.resize(n_threads);
600  _ad_zero.resize(n_threads);
601  _grad_zero.resize(n_threads);
602  _ad_grad_zero.resize(n_threads);
603  _grad_phi_zero.resize(n_threads);
604  _second_zero.resize(n_threads);
605  _ad_second_zero.resize(n_threads);
606  _second_phi_zero.resize(n_threads);
607  _point_zero.resize(n_threads);
608  _vector_zero.resize(n_threads);
611 
613 
617 
618  es().parameters.set<FEProblemBase *>("_fe_problem_base") = this;
619 
620  if (isParamValid("restart_file_base"))
621  {
622  std::string restart_file_base = getParam<FileNameNoExtension>("restart_file_base");
623 
624  // This check reverts to old behavior of providing "restart_file_base=" to mean
625  // don't restart... BISON currently relies on this. It could probably be removed.
626  // The new MooseUtils::convertLatestCheckpoint will error out if a checkpoint file
627  // is not found, which I think makes sense. Which means, without this, if you
628  // set "restart_file_base=", you'll get a "No checkpoint file found" error
629  if (restart_file_base.size())
630  {
631  restart_file_base = MooseUtils::convertLatestCheckpoint(restart_file_base);
632  setRestartFile(restart_file_base);
633  }
634  }
635 
636  // // Generally speaking, the mesh is prepared for use, and consequently remote elements are deleted
637  // // well before our Problem(s) are constructed. Historically, in MooseMesh we have a bunch of
638  // // needs_prepare type flags that make it so we never call prepare_for_use (and consequently
639  // // delete_remote_elements) again. So the below line, historically, has had no impact. HOWEVER:
640  // // I've added some code in SetupMeshCompleteAction for deleting remote elements post
641  // // EquationSystems::init. If I execute that code without default ghosting, then I get > 40 MOOSE
642  // // test failures, so we clearly have some simulations that are not yet covered properly by
643  // // relationship managers. Until that is resolved, I am going to retain default geometric ghosting
644  // if (!_default_ghosting)
645  // _mesh.getMesh().remove_ghosting_functor(_mesh.getMesh().default_ghosting());
646 
647 #if !PETSC_RELEASE_LESS_THAN(3, 12, 0)
648  // Main app should hold the default database to handle system petsc options
649  if (!_app.isUltimateMaster())
650  LibmeshPetscCall(PetscOptionsCreate(&_petsc_option_data_base));
651 #endif
652 
653  if (!_solve)
654  {
655  // If we are not solving, we do not care about seeing unused petsc options
656  Moose::PetscSupport::setSinglePetscOption("-options_left", "0");
657  // We don't want petscSetOptions being called in solve and clearing the option that was just set
659  }
660 }
661 
662 const MooseMesh &
663 FEProblemBase::mesh(bool use_displaced) const
664 {
665  if (use_displaced && !_displaced_problem)
666  mooseWarning("Displaced mesh was requested but the displaced problem does not exist. "
667  "Regular mesh will be returned");
668  return ((use_displaced && _displaced_problem) ? _displaced_problem->mesh() : mesh());
669 }
670 
671 void
673 {
674  // add vectors and their tags to system
675  auto & vectors = getParam<std::vector<std::vector<TagName>>>("extra_tag_vectors");
676  for (const auto sys_num : index_range(vectors))
677  for (auto & vector : vectors[sys_num])
678  {
679  auto tag = addVectorTag(vector);
680  _solver_systems[sys_num]->addVector(tag, false, libMesh::GHOSTED);
681  }
682 
683  auto & not_zeroed_vectors = getParam<std::vector<std::vector<TagName>>>("not_zeroed_tag_vectors");
684  for (const auto sys_num : index_range(not_zeroed_vectors))
685  for (auto & vector : not_zeroed_vectors[sys_num])
686  {
687  auto tag = addVectorTag(vector);
688  _solver_systems[sys_num]->addVector(tag, false, GHOSTED);
690  }
691 }
692 
693 void
695 {
696  auto & matrices = getParam<std::vector<std::vector<TagName>>>("extra_tag_matrices");
697  for (const auto sys_num : index_range(matrices))
698  for (auto & matrix : matrices[sys_num])
699  {
700  auto tag = addMatrixTag(matrix);
701  _solver_systems[sys_num]->addMatrix(tag);
702  }
703 
704  for (auto & sys : _solver_systems)
705  sys->sizeVariableMatrixData();
706  _aux->sizeVariableMatrixData();
707 }
708 
709 void
711 {
712  for (auto & vector : getParam<std::vector<TagName>>("extra_tag_solutions"))
713  {
714  auto tag = addVectorTag(vector, Moose::VECTOR_TAG_SOLUTION);
715  for (auto & sys : _solver_systems)
716  sys->addVector(tag, false, libMesh::GHOSTED);
717  _aux->addVector(tag, false, libMesh::GHOSTED);
718  }
719 
721  {
722  // We'll populate the zeroth state of the nonlinear iterations with the current solution for
723  // ease of use in doing things like copying solutions backwards. We're just storing pointers in
724  // the solution states containers so populating the zeroth state does not cost us the memory of
725  // a new vector
727  }
728 
730  for (auto & sys : _solver_systems)
731  sys->associateVectorToTag(*sys->system().current_local_solution.get(), tag);
732  _aux->associateVectorToTag(*_aux->system().current_local_solution.get(), tag);
733 }
734 
735 void
737 {
738  for (auto & sys : _solver_systems)
739  sys->needSolutionState(state, iteration_type);
740  _aux->needSolutionState(state, iteration_type);
741 }
742 
743 void
744 FEProblemBase::newAssemblyArray(std::vector<std::shared_ptr<SolverSystem>> & solver_systems)
745 {
746  unsigned int n_threads = libMesh::n_threads();
747 
748  _assembly.resize(n_threads);
749  for (const auto i : make_range(n_threads))
750  {
751  _assembly[i].resize(solver_systems.size());
752  for (const auto j : index_range(solver_systems))
753  _assembly[i][j] = std::make_unique<Assembly>(*solver_systems[j], i);
754  }
755 }
756 
757 void
759  std::vector<std::shared_ptr<NonlinearSystemBase>> & nls)
760 {
761  TIME_SECTION("initNullSpaceVectors", 5, "Initializing Null Space Vectors");
762 
763  unsigned int dimNullSpace = parameters.get<unsigned int>("null_space_dimension");
764  unsigned int dimTransposeNullSpace =
765  parameters.get<unsigned int>("transpose_null_space_dimension");
766  unsigned int dimNearNullSpace = parameters.get<unsigned int>("near_null_space_dimension");
767  for (unsigned int i = 0; i < dimNullSpace; ++i)
768  {
769  std::ostringstream oss;
770  oss << "_" << i;
771  // do not project, since this will be recomputed, but make it ghosted, since the near nullspace
772  // builder might march over all nodes
773  for (auto & nl : nls)
774  nl->addVector("NullSpace" + oss.str(), false, libMesh::GHOSTED);
775  }
776  _subspace_dim["NullSpace"] = dimNullSpace;
777  for (unsigned int i = 0; i < dimTransposeNullSpace; ++i)
778  {
779  std::ostringstream oss;
780  oss << "_" << i;
781  // do not project, since this will be recomputed, but make it ghosted, since the near nullspace
782  // builder might march over all nodes
783  for (auto & nl : nls)
784  nl->addVector("TransposeNullSpace" + oss.str(), false, libMesh::GHOSTED);
785  }
786  _subspace_dim["TransposeNullSpace"] = dimTransposeNullSpace;
787  for (unsigned int i = 0; i < dimNearNullSpace; ++i)
788  {
789  std::ostringstream oss;
790  oss << "_" << i;
791  // do not project, since this will be recomputed, but make it ghosted, since the near-nullspace
792  // builder might march over all semilocal nodes
793  for (auto & nl : nls)
794  nl->addVector("NearNullSpace" + oss.str(), false, libMesh::GHOSTED);
795  }
796  _subspace_dim["NearNullSpace"] = dimNearNullSpace;
797 }
798 
800 {
801  // Flush the Console stream, the underlying call to Console::mooseConsole
802  // relies on a call to Output::checkInterval that has references to
803  // _time, etc. If it is not flushed here memory problems arise if you have
804  // an unflushed stream and start destructing things.
805  _console << std::flush;
806 
807  unsigned int n_threads = libMesh::n_threads();
808  for (unsigned int i = 0; i < n_threads; i++)
809  {
810  _zero[i].release();
811  _phi_zero[i].release();
812  _scalar_zero[i].release();
813  _grad_zero[i].release();
814  _grad_phi_zero[i].release();
815  _second_zero[i].release();
816  _second_phi_zero[i].release();
817  _vector_zero[i].release();
818  _vector_curl_zero[i].release();
819  _ad_zero[i].release();
820  _ad_grad_zero[i].release();
821  _ad_second_zero[i].release();
822  }
823 
824 #if !PETSC_RELEASE_LESS_THAN(3, 12, 0)
825  if (!_app.isUltimateMaster())
826  {
827  auto ierr = PetscOptionsDestroy(&_petsc_option_data_base);
828  // Don't throw on destruction
829  CHKERRABORT(this->comm().get(), ierr);
830  }
831 #endif
832 }
833 
834 void
835 FEProblemBase::setCoordSystem(const std::vector<SubdomainName> & blocks,
836  const MultiMooseEnum & coord_sys)
837 {
838  TIME_SECTION("setCoordSystem", 5, "Setting Coordinate System");
839  _mesh.setCoordSystem(blocks, coord_sys);
840 }
841 
842 void
844 {
845  _mesh.setAxisymmetricCoordAxis(rz_coord_axis);
846 }
847 
848 const ConstElemRange &
850 {
852  {
853  std::vector<const DofMap *> dof_maps(es().n_systems());
854  for (const auto i : make_range(es().n_systems()))
855  {
856  const auto & sys = es().get_system(i);
857  dof_maps[i] = &sys.get_dof_map();
858  }
860  std::make_unique<ConstElemRange>(_mesh.getMesh().multi_evaluable_elements_begin(dof_maps),
861  _mesh.getMesh().multi_evaluable_elements_end(dof_maps));
862  }
864 }
865 
866 const ConstElemRange &
868 {
870  {
871  std::vector<const DofMap *> dof_maps(_nl.size());
872  for (const auto i : index_range(dof_maps))
873  dof_maps[i] = &_nl[i]->dofMap();
875  std::make_unique<ConstElemRange>(_mesh.getMesh().multi_evaluable_elements_begin(dof_maps),
876  _mesh.getMesh().multi_evaluable_elements_end(dof_maps));
877  }
878 
880 }
881 
882 void
884 {
885  TIME_SECTION("initialSetup", 2, "Performing Initial Setup");
886 
888 
890  mooseError("Checkpoint recovery and restart and exodus restart are all mutually exclusive.");
891 
893  mooseWarning("MOOSE may fail to catch an exception when the \"skip_exception_check\" parameter "
894  "is used. If you receive a terse MPI error during execution, remove this "
895  "parameter and rerun your simulation");
896 
897  // set state flag indicating that we are in or beyond initialSetup.
898  // This can be used to throw errors in methods that _must_ be called at construction time.
899  _started_initial_setup = true;
901 
902  // Setup the solution states (current, old, etc) in each system based on
903  // its default and the states requested of each of its variables
904  for (const auto i : index_range(_solver_systems))
905  {
906  _solver_systems[i]->initSolutionState();
907  if (getDisplacedProblem())
908  getDisplacedProblem()->solverSys(i).initSolutionState();
909  }
910  _aux->initSolutionState();
911  if (getDisplacedProblem())
912  getDisplacedProblem()->auxSys().initSolutionState();
913 
914  // always execute to get the max number of DoF per element and node needed to initialize phi_zero
915  // variables
916  dof_id_type global_max_var_n_dofs_per_elem = 0;
917  for (const auto i : index_range(_solver_systems))
918  {
919  auto & sys = *_solver_systems[i];
920  dof_id_type max_var_n_dofs_per_elem;
921  dof_id_type max_var_n_dofs_per_node;
922  {
923  TIME_SECTION("computingMaxDofs", 3, "Computing Max Dofs Per Element");
924 
925  MaxVarNDofsPerElem mvndpe(*this, sys);
926  Threads::parallel_reduce(*_mesh.getActiveLocalElementRange(), mvndpe);
927  max_var_n_dofs_per_elem = mvndpe.max();
928  _communicator.max(max_var_n_dofs_per_elem);
929 
930  MaxVarNDofsPerNode mvndpn(*this, sys);
931  Threads::parallel_reduce(*_mesh.getLocalNodeRange(), mvndpn);
932  max_var_n_dofs_per_node = mvndpn.max();
933  _communicator.max(max_var_n_dofs_per_node);
934  global_max_var_n_dofs_per_elem =
935  std::max(global_max_var_n_dofs_per_elem, max_var_n_dofs_per_elem);
936  }
937 
938  {
939  TIME_SECTION("assignMaxDofs", 5, "Assigning Maximum Dofs Per Elem");
940 
941  sys.assignMaxVarNDofsPerElem(max_var_n_dofs_per_elem);
943  if (displaced_problem)
944  displaced_problem->solverSys(i).assignMaxVarNDofsPerElem(max_var_n_dofs_per_elem);
945 
946  sys.assignMaxVarNDofsPerNode(max_var_n_dofs_per_node);
947  if (displaced_problem)
948  displaced_problem->solverSys(i).assignMaxVarNDofsPerNode(max_var_n_dofs_per_node);
949  }
950  }
951 
952  {
953  TIME_SECTION("resizingVarValues", 5, "Resizing Variable Values");
954 
955  for (unsigned int tid = 0; tid < libMesh::n_threads(); ++tid)
956  {
957  _phi_zero[tid].resize(global_max_var_n_dofs_per_elem, std::vector<Real>(getMaxQps(), 0.));
958  _grad_phi_zero[tid].resize(global_max_var_n_dofs_per_elem,
959  std::vector<RealGradient>(getMaxQps(), RealGradient(0.)));
960  _second_phi_zero[tid].resize(global_max_var_n_dofs_per_elem,
961  std::vector<RealTensor>(getMaxQps(), RealTensor(0.)));
962  }
963  }
964 
965  // Set up stateful material property redistribution, if we suspect
966  // it may be necessary later.
968 
970  {
971  // Only load all of the vectors if we're recovering
973 
974  // This forces stateful material property loading to be an exact one-to-one match
975  if (_app.isRecovering())
976  {
978  props->setRecovering();
979 
980 #ifdef MOOSE_KOKKOS_ENABLED
981  for (auto props :
983  props->setRecovering();
984 #endif
985  }
986 
987  TIME_SECTION("restore", 3, "Restoring from backup");
988 
989  // We could have a cached backup when this app is a sub-app and has been given a Backup
990  if (!_app.hasInitialBackup())
992  else
994 
1000  if (_app.isRestarting())
1001  {
1002  if (_app.hasStartTime())
1004  else
1005  _time_old = _time;
1006  }
1007  }
1008  else
1009  {
1011 
1012  if (reader)
1013  {
1014  TIME_SECTION("copyingFromExodus", 3, "Copying Variables From Exodus");
1015 
1016  for (auto & sys : _solver_systems)
1017  sys->copyVars(*reader);
1018  _aux->copyVars(*reader);
1019  }
1020  else
1021  {
1022  if (_solver_systems[0]->hasVarCopy() || _aux->hasVarCopy())
1023  mooseError("Need Exodus reader to restart variables but the reader is not available\n"
1024  "Use either FileMesh with an Exodus mesh file or FileMeshGenerator with an "
1025  "Exodus mesh file and with use_for_exodus_restart equal to true");
1026  }
1027  }
1028 
1029  // Perform output related setups
1031 
1032  // Flush all output to _console that occur during construction and initialization of objects
1034 
1035  // Build Refinement and Coarsening maps for stateful material projections if necessary
1036  if ((_adaptivity.isOn() || _num_grid_steps) &&
1039  {
1041  mooseError("Stateful neighbor material properties do not work with mesh adaptivity");
1042 
1044  }
1045 
1046  if (!_app.isRecovering())
1047  {
1054  {
1055  if (!_app.isUltimateMaster())
1056  mooseError(
1057  "Doing extra refinements when restarting is NOT supported for sub-apps of a MultiApp");
1058 
1060  }
1061  }
1062 
1063  unsigned int n_threads = libMesh::n_threads();
1064 
1065  // Convergence initial setup
1066  {
1067  TIME_SECTION("convergenceInitialSetup", 5, "Initializing Convergence objects");
1068 
1069  for (THREAD_ID tid = 0; tid < n_threads; tid++)
1071  }
1072 
1073  // UserObject initialSetup
1074  std::set<std::string> depend_objects_ic = _ics.getDependObjects();
1075  std::set<std::string> depend_objects_aux = _aux->getDependObjects();
1076 
1077  // This replaces all prior updateDependObjects calls on the old user object warehouses.
1078  TheWarehouse::Query uo_query = theWarehouse().query().condition<AttribSystem>("UserObject");
1079  std::vector<UserObject *> userobjs;
1080  uo_query.queryInto(userobjs);
1082  theWarehouse(), getAuxiliarySystem(), _app.getExecuteOnEnum(), userobjs, depend_objects_ic);
1083 
1084  std::map<int, std::vector<UserObject *>> group_userobjs;
1085  for (auto obj : userobjs)
1086  group_userobjs[obj->getParam<int>("execution_order_group")].push_back(obj);
1087 
1088  for (auto & [group, objs] : group_userobjs)
1089  for (auto obj : objs)
1090  obj->initialSetup();
1091 
1092  // check if jacobian calculation is done in userobject
1093  for (THREAD_ID tid = 0; tid < n_threads; ++tid)
1095 
1096  // Check whether nonlocal couling is required or not
1100 
1101  {
1102  TIME_SECTION("initializingFunctions", 5, "Initializing Functions");
1103 
1104  // Call the initialSetup methods for functions
1105  for (THREAD_ID tid = 0; tid < n_threads; tid++)
1106  {
1107  reinitScalars(tid); // initialize scalars so they are properly sized for use as input into
1108  // ParsedFunctions
1109  _functions.initialSetup(tid);
1110  }
1111  }
1112 
1113  {
1114  TIME_SECTION("initializingRandomObjects", 5, "Initializing Random Objects");
1115 
1116  // Random interface objects
1117  for (const auto & it : _random_data_objects)
1118  it.second->updateSeeds(EXEC_INITIAL);
1119  }
1120 
1121  if (!_app.isRecovering())
1122  {
1124 
1125  {
1126  TIME_SECTION("ICinitialSetup", 5, "Setting Up Initial Conditions");
1127 
1128  for (THREAD_ID tid = 0; tid < n_threads; tid++)
1129  _ics.initialSetup(tid);
1130 
1132  }
1133 
1134  projectSolution();
1135  }
1136 
1137  // Materials
1139  {
1140  TIME_SECTION("materialInitialSetup", 3, "Setting Up Materials");
1141 
1142  for (THREAD_ID tid = 0; tid < n_threads; tid++)
1143  {
1144  // Sort the Material objects, these will be actually computed by MOOSE in reinit methods.
1145  _materials.sort(tid);
1147 
1148  // Call initialSetup on all material objects
1150 
1151  // Discrete materials may insert additional dependencies on materials during the initial
1152  // setup. Therefore we resolve the dependencies once more, now with the additional
1153  // dependencies due to discrete materials.
1155  {
1156  _materials.sort(tid);
1158  }
1159  }
1160 
1161 #ifdef MOOSE_KOKKOS_ENABLED
1162  _kokkos_materials.sort(0, true);
1163 #endif
1164 
1165  {
1166  TIME_SECTION("computingInitialStatefulProps", 3, "Computing Initial Material Values");
1167 
1169 
1173 #ifdef MOOSE_KOKKOS_ENABLED
1178 #endif
1179  }
1180  }
1181 
1182  // setRestartInPlace() is set because the property maps have now been setup and we can
1183  // dataLoad() them directly in place
1184  // setRecovering() is set because from now on we require a one-to-one mapping of
1185  // stateful properties because we shouldn't be declaring any more
1187  {
1188  props->setRestartInPlace();
1189  props->setRecovering();
1190  }
1191 
1192  for (THREAD_ID tid = 0; tid < n_threads; tid++)
1193  {
1196  _markers.sort(tid);
1197  _markers.initialSetup(tid);
1198  }
1199 
1200 #ifdef LIBMESH_ENABLE_AMR
1201 
1202  if (!_app.isRecovering())
1203  {
1204  unsigned int n = adaptivity().getInitialSteps();
1205  if (n && !_app.isUltimateMaster() && _app.isRestarting())
1206  mooseError("Cannot perform initial adaptivity during restart on sub-apps of a MultiApp!");
1207 
1208  initialAdaptMesh();
1209  }
1210 
1211 #endif // LIBMESH_ENABLE_AMR
1212 
1213  if (!_app.isRecovering() && !_app.isRestarting())
1214  {
1215  // During initial setup the solution is copied to the older solution states (old, older, etc)
1217 
1218  // Check if there are old state initial conditions
1219  auto ics = _ics.getActiveObjects();
1220  auto fv_ics = _fv_ics.getActiveObjects();
1221  auto scalar_ics = _scalar_ics.getActiveObjects();
1222  unsigned short ic_state_max = 0;
1223 
1224  auto findMax = [&ic_state_max](const auto & obj_list)
1225  {
1226  for (auto ic : obj_list.getActiveObjects())
1227  ic_state_max = std::max(ic_state_max, ic->getState());
1228  };
1229  findMax(_ics);
1230  findMax(_fv_ics);
1231  findMax(_scalar_ics);
1232 
1233  // if there are old state ICs, compute them and write to old states accordingly
1234  if (ic_state_max > 0)
1235  {
1236  // state 0 copy (we'll overwrite current state when evaluating ICs and need to restore it once
1237  // we're done with the old/older state ICs)
1238  std::vector<std::unique_ptr<NumericVector<Real>>> state0_sys_buffers(_solver_systems.size());
1239  std::unique_ptr<NumericVector<Real>> state0_aux_buffer;
1240 
1241  // save state 0
1242  for (const auto i : index_range(_solver_systems))
1243  state0_sys_buffers[i] = _solver_systems[i]->solutionState(0).clone();
1244 
1245  state0_aux_buffer = _aux->solutionState(0).clone();
1246 
1247  // compute old state ICs
1248  for (_current_ic_state = 1; _current_ic_state <= ic_state_max; _current_ic_state++)
1249  {
1250  projectSolution();
1251 
1252  for (auto & sys : _solver_systems)
1253  sys->solutionState(_current_ic_state) = sys->solutionState(0);
1254 
1255  _aux->solutionState(_current_ic_state) = _aux->solutionState(0);
1256  }
1257  _current_ic_state = 0;
1258 
1259  // recover state 0
1260  for (const auto i : index_range(_solver_systems))
1261  {
1262  _solver_systems[i]->solutionState(0) = *state0_sys_buffers[i];
1263  _solver_systems[i]->solutionState(0).close();
1264  _solver_systems[i]->update();
1265  }
1266  _aux->solutionState(0) = *state0_aux_buffer;
1267  _aux->solutionState(0).close();
1268  _aux->update();
1269  }
1270  }
1271 
1272  if (!_app.isRecovering())
1273  {
1274  if (haveXFEM())
1275  updateMeshXFEM();
1276  }
1277 
1278  // Call initialSetup on the solver systems
1279  for (auto & sys : _solver_systems)
1280  sys->initialSetup();
1281 
1282  // Auxilary variable initialSetup calls
1283  _aux->initialSetup();
1284 
1285  if (_displaced_problem)
1286  // initialSetup for displaced systems
1287  _displaced_problem->initialSetup();
1288 
1289  for (auto & sys : _solver_systems)
1290  sys->setSolution(*(sys->system().current_local_solution.get()));
1291 
1292  // Update the nearest node searches (has to be called after the problem is all set up)
1293  // We do this here because this sets up the Element's DoFs to ghost
1295 
1297  if (_displaced_mesh)
1299 
1300  // We need to move the mesh in order to build a map between mortar secondary and primary
1301  // interfaces. This map will then be used by the AgumentSparsityOnInterface ghosting functor to
1302  // know which dofs we need ghosted when we call EquationSystems::reinit
1304  {
1305  _displaced_problem->updateMesh();
1306  // if displacements were applied to the mesh, the mortar mesh should be updated too
1307  updateMortarMesh();
1308  }
1309 
1310  // Possibly reinit one more time to get ghosting correct
1312 
1313  if (_displaced_mesh)
1314  _displaced_problem->updateMesh();
1315 
1316  updateGeomSearch(); // Call all of the rest of the geometric searches
1317 
1318  for (auto & sys : _solver_systems)
1319  {
1320  const auto & tis = sys->getTimeIntegrators();
1321 
1322  {
1323  TIME_SECTION("timeIntegratorInitialSetup", 5, "Initializing Time Integrator");
1324  for (auto & ti : tis)
1325  ti->initialSetup();
1326  }
1327  }
1328 
1329  // HUGE NOTE: MultiApp initialSetup() MUST... I repeat MUST be _after_ main-app restartable data
1330  // has been restored
1331 
1332  // Call initialSetup on the MultiApps
1333  if (_multi_apps.hasObjects())
1334  {
1335  TIME_SECTION("initialSetupMultiApps", 2, "Initializing MultiApps", false);
1337  }
1338 
1339  // Call initialSetup on the transfers
1340  {
1341  TIME_SECTION("initialSetupTransfers", 2, "Initializing Transfers");
1342 
1344 
1345  // Call initialSetup on the MultiAppTransfers to be executed on TO_MULTIAPP
1346  const auto & to_multi_app_objects = _to_multi_app_transfers.getActiveObjects();
1347  for (const auto & transfer : to_multi_app_objects)
1348  {
1349  transfer->setCurrentDirection(Transfer::DIRECTION::TO_MULTIAPP);
1350  transfer->initialSetup();
1351  }
1352 
1353  // Call initialSetup on the MultiAppTransfers to be executed on FROM_MULTIAPP
1354  const auto & from_multi_app_objects = _from_multi_app_transfers.getActiveObjects();
1355  for (const auto & transfer : from_multi_app_objects)
1356  {
1357  transfer->setCurrentDirection(Transfer::DIRECTION::FROM_MULTIAPP);
1358  transfer->initialSetup();
1359  }
1360 
1361  // Call initialSetup on the MultiAppTransfers to be executed on BETWEEN_MULTIAPP
1362  const auto & between_multi_app_objects = _between_multi_app_transfers.getActiveObjects();
1363  for (const auto & transfer : between_multi_app_objects)
1364  {
1365  transfer->setCurrentDirection(Transfer::DIRECTION::BETWEEN_MULTIAPP);
1366  transfer->initialSetup();
1367  }
1368  }
1369 
1371  {
1372  TIME_SECTION("BoundaryRestrictedNodeIntegrityCheck", 5);
1373 
1374  // check that variables are defined along boundaries of boundary restricted nodal objects
1375  ConstBndNodeRange & bnd_nodes = *mesh().getBoundaryNodeRange();
1376  BoundaryNodeIntegrityCheckThread bnict(*this, uo_query);
1377  Threads::parallel_reduce(bnd_nodes, bnict);
1378 
1379  // Nodal bcs aren't threaded
1380  const auto & node_to_elem_map = _mesh.nodeToActiveSemilocalElemMap();
1381  for (const auto & bnode : bnd_nodes)
1382  {
1383  const auto boundary_id = bnode->_bnd_id;
1384  const Node * const node = bnode->_node;
1385 
1386  if (node->processor_id() != this->processor_id())
1387  continue;
1388 
1389  // Only check vertices. Variables may not be defined on non-vertex nodes (think first order
1390  // Lagrange on a second order mesh) and user-code can often handle that
1391  const Elem * const an_elem =
1392  _mesh.getMesh().elem_ptr(libmesh_map_find(node_to_elem_map, node->id()).front());
1393  if (!an_elem->is_vertex(an_elem->get_node_index(node)))
1394  continue;
1395 
1396  const auto & bnd_name = _mesh.getBoundaryName(boundary_id);
1397 
1398  for (auto & nl : _nl)
1399  {
1400  const auto & nodal_bcs = nl->getNodalBCWarehouse();
1401  if (!nodal_bcs.hasBoundaryObjects(boundary_id, 0))
1402  continue;
1403 
1404  const auto & bnd_objects = nodal_bcs.getBoundaryObjects(boundary_id, 0);
1405  for (const auto & bnd_object : bnd_objects)
1406  // Skip if this object uses geometric search because coupled variables may be defined on
1407  // paired boundaries instead of the boundary this node is on
1408  if (!bnd_object->requiresGeometricSearch() &&
1409  bnd_object->checkVariableBoundaryIntegrity())
1410  {
1411  std::set<MooseVariableFieldBase *> vars_to_omit = {
1412  &static_cast<MooseVariableFieldBase &>(
1413  const_cast<MooseVariableBase &>(bnd_object->variable()))};
1414 
1416  *bnd_object, bnd_object->checkAllVariables(*node, vars_to_omit), bnd_name);
1417  }
1418  }
1419  }
1420  }
1421 
1423  {
1424  TIME_SECTION("BoundaryRestrictedElemIntegrityCheck", 5);
1425 
1426  // check that variables are defined along boundaries of boundary restricted elemental objects
1427  ConstBndElemRange & bnd_elems = *mesh().getBoundaryElementRange();
1428  BoundaryElemIntegrityCheckThread beict(*this, uo_query);
1429  Threads::parallel_reduce(bnd_elems, beict);
1430  }
1431 
1432  if (!_app.isRecovering())
1433  {
1435 
1437  if (!converged)
1438  mooseError("failed to converge initial MultiApp");
1439 
1440  // We'll backup the Multiapp here
1442 
1443  for (THREAD_ID tid = 0; tid < n_threads; tid++)
1444  reinitScalars(tid);
1445 
1447 
1448  // The FEProblemBase::execute method doesn't call all the systems on EXEC_INITIAL, but it does
1449  // set/unset the current flag. Therefore, this resets the current flag to EXEC_INITIAL so that
1450  // subsequent calls (e.g., executeControls) have the proper flag.
1452  }
1453 
1454  // Here we will initialize the stateful properties once more since they may have been updated
1455  // during initialSetup by calls to computeProperties.
1456  //
1457  // It's really bad that we don't allow this during restart. It means that we can't add new
1458  // stateful materials
1459  // during restart. This is only happening because this _has_ to be below initial userobject
1460  // execution.
1461  // Otherwise this could be done up above... _before_ restoring restartable data... which would
1462  // allow you to have
1463  // this happen during restart. I honestly have no idea why this has to happen after initial user
1464  // object computation.
1465  // THAT is something we should fix... so I've opened this ticket: #5804
1466  if (!_app.isRecovering() && !_app.isRestarting())
1467  {
1470  {
1471  TIME_SECTION("computeMaterials", 2, "Computing Initial Material Properties");
1472 
1474  }
1475 #ifdef MOOSE_KOKKOS_ENABLED
1479  {
1480  TIME_SECTION("computeMaterials", 2, "Computing Initial Material Properties");
1481 
1483  }
1484 #endif
1485  }
1486 
1487  // Control Logic
1489 
1490  // Scalar variables need to reinited for the initial conditions to be available for output
1491  for (unsigned int tid = 0; tid < n_threads; tid++)
1492  reinitScalars(tid);
1493 
1494  if (_displaced_mesh)
1495  _displaced_problem->syncSolutions();
1496 
1497  // Writes all calls to _console from initialSetup() methods
1499 
1501  {
1503  for (THREAD_ID tid = 0; tid < n_threads; ++tid)
1504  for (auto & assembly : _assembly[tid])
1506  }
1507 
1508  {
1509  TIME_SECTION("lineSearchInitialSetup", 5, "Initializing Line Search");
1510 
1511  if (_line_search)
1512  _line_search->initialSetup();
1513  }
1514 
1515  // Perform Reporter get/declare check
1517 
1518  // We do this late to allow objects to get late restartable data
1521 
1523 }
1524 
1525 void
1527 {
1528  for (const auto & pp : _reporter_data.getPostprocessorNames())
1529  if (hasScalarVariable(pp))
1530  mooseError("Postprocessor \"" + pp +
1531  "\" has the same name as a scalar variable in the system.");
1532 }
1533 
1534 void
1536 {
1538 
1539  if (_t_step > 1 && _num_grid_steps)
1540  {
1541  libMesh::MeshRefinement mesh_refinement(_mesh);
1542  std::unique_ptr<libMesh::MeshRefinement> displaced_mesh_refinement(nullptr);
1543  if (_displaced_mesh)
1544  displaced_mesh_refinement = std::make_unique<libMesh::MeshRefinement>(*_displaced_mesh);
1545 
1546  for (MooseIndex(_num_grid_steps) i = 0; i < _num_grid_steps; ++i)
1547  {
1548  if (_displaced_problem)
1549  // If the DisplacedProblem is active, undisplace the DisplacedMesh in preparation for
1550  // refinement. We can't safely refine the DisplacedMesh directly, since the Hilbert keys
1551  // computed on the inconsistenly-displaced Mesh are different on different processors,
1552  // leading to inconsistent Hilbert keys. We must do this before the undisplaced Mesh is
1553  // coarsensed, so that the element and node numbering is still consistent. We also have to
1554  // make sure this is done during every step of coarsening otherwise different partitions
1555  // will be generated for the reference and displaced meshes (even for replicated)
1556  _displaced_problem->undisplaceMesh();
1557 
1558  mesh_refinement.uniformly_coarsen();
1559  if (_displaced_mesh)
1560  displaced_mesh_refinement->uniformly_coarsen();
1561 
1562  // Mark this as an intermediate change because we do not yet want to reinit_systems. E.g. we
1563  // need things to happen in the following order for the undisplaced problem:
1564  // u1) EquationSystems::reinit_solutions. This will restrict the solution vectors and then
1565  // contract the mesh
1566  // u2) MooseMesh::meshChanged. This will update the node/side lists and other
1567  // things which needs to happen after the contraction
1568  // u3) GeometricSearchData::reinit. Once the node/side lists are updated we can perform our
1569  // geometric searches which will aid in determining sparsity patterns
1570  //
1571  // We do these things for the displaced problem (if it exists)
1572  // d1) EquationSystems::reinit. Restrict the displaced problem vector copies and then contract
1573  // the mesh. It's safe to do a full reinit with the displaced because there are no
1574  // matrices that sparsity pattern calculations will be conducted for
1575  // d2) MooseMesh::meshChanged. This will update the node/side lists and other
1576  // things which needs to happen after the contraction
1577  // d3) UpdateDisplacedMeshThread::operator(). Re-displace the mesh using the *displaced*
1578  // solution vector copy because we don't know the state of the reference solution vector.
1579  // It's safe to use the displaced copy because we are outside of a non-linear solve,
1580  // and there is no concern about differences between solution and current_local_solution
1581  // d4) GeometricSearchData::reinit. With the node/side lists updated and the mesh
1582  // re-displaced, we can perform our geometric searches, which will aid in determining the
1583  // sparsity pattern of the matrix held by the libMesh::ImplicitSystem held by the
1584  // NonlinearSystem held by this
1585  meshChanged(
1586  /*intermediate_change=*/true, /*contract_mesh=*/true, /*clean_refinement_flags=*/true);
1587  }
1588 
1589  // u4) Now that all the geometric searches have been done (both undisplaced and displaced),
1590  // we're ready to update the sparsity pattern
1591  es().reinit_systems();
1592  }
1593 
1594  if (_line_search)
1595  _line_search->timestepSetup();
1596 
1597  // Random interface objects
1598  for (const auto & it : _random_data_objects)
1599  it.second->updateSeeds(EXEC_TIMESTEP_BEGIN);
1600 
1601  unsigned int n_threads = libMesh::n_threads();
1602  for (THREAD_ID tid = 0; tid < n_threads; tid++)
1603  {
1606  }
1607 
1608  _aux->timestepSetup();
1609  for (auto & sys : _solver_systems)
1610  sys->timestepSetup();
1611 
1612  if (_displaced_problem)
1613  // timestepSetup for displaced systems
1614  _displaced_problem->timestepSetup();
1615 
1616  for (THREAD_ID tid = 0; tid < n_threads; tid++)
1617  {
1620  _markers.timestepSetup(tid);
1621  }
1622 
1623  std::vector<UserObject *> userobjs;
1624  theWarehouse().query().condition<AttribSystem>("UserObject").queryIntoUnsorted(userobjs);
1625  for (auto obj : userobjs)
1626  obj->timestepSetup();
1627 
1628  // Timestep setup of output objects
1630 
1633  _has_nonlocal_coupling = true;
1634 }
1635 
1636 unsigned int
1638 {
1640  mooseError("Max QPS uninitialized");
1641  return _max_qps;
1642 }
1643 
1644 Order
1646 {
1647  return _max_scalar_order;
1648 }
1649 
1650 void
1652 {
1653  TIME_SECTION("checkNonlocalCoupling", 5, "Checking Nonlocal Coupling");
1654 
1655  for (THREAD_ID tid = 0; tid < libMesh::n_threads(); tid++)
1656  for (auto & nl : _nl)
1657  {
1658  const auto & all_kernels = nl->getKernelWarehouse();
1659  const auto & kernels = all_kernels.getObjects(tid);
1660  for (const auto & kernel : kernels)
1661  {
1662  std::shared_ptr<NonlocalKernel> nonlocal_kernel =
1664  if (nonlocal_kernel)
1665  {
1668  _nonlocal_kernels.addObject(kernel, tid);
1669  }
1670  }
1671  const MooseObjectWarehouse<IntegratedBCBase> & all_integrated_bcs =
1672  nl->getIntegratedBCWarehouse();
1673  const auto & integrated_bcs = all_integrated_bcs.getObjects(tid);
1674  for (const auto & integrated_bc : integrated_bcs)
1675  {
1676  std::shared_ptr<NonlocalIntegratedBC> nonlocal_integrated_bc =
1678  if (nonlocal_integrated_bc)
1679  {
1682  _nonlocal_integrated_bcs.addObject(integrated_bc, tid);
1683  }
1684  }
1685  }
1686 }
1687 
1688 void
1690 {
1691  std::set<const MooseVariableFEBase *> uo_jacobian_moose_vars;
1692  {
1693  std::vector<ShapeElementUserObject *> objs;
1694  theWarehouse()
1695  .query()
1697  .condition<AttribThread>(tid)
1698  .queryInto(objs);
1699 
1700  for (const auto & uo : objs)
1701  {
1702  _calculate_jacobian_in_uo = uo->computeJacobianFlag();
1703  const auto & mv_deps = uo->jacobianMooseVariables();
1704  uo_jacobian_moose_vars.insert(mv_deps.begin(), mv_deps.end());
1705  }
1706  }
1707  {
1708  std::vector<ShapeSideUserObject *> objs;
1709  theWarehouse()
1710  .query()
1712  .condition<AttribThread>(tid)
1713  .queryInto(objs);
1714  for (const auto & uo : objs)
1715  {
1716  _calculate_jacobian_in_uo = uo->computeJacobianFlag();
1717  const auto & mv_deps = uo->jacobianMooseVariables();
1718  uo_jacobian_moose_vars.insert(mv_deps.begin(), mv_deps.end());
1719  }
1720  }
1721 
1722  _uo_jacobian_moose_vars[tid].assign(uo_jacobian_moose_vars.begin(), uo_jacobian_moose_vars.end());
1723  std::sort(
1724  _uo_jacobian_moose_vars[tid].begin(), _uo_jacobian_moose_vars[tid].end(), sortMooseVariables);
1725 }
1726 
1727 void
1728 FEProblemBase::setVariableAllDoFMap(const std::vector<const MooseVariableFEBase *> & moose_vars)
1729 {
1730  for (unsigned int i = 0; i < moose_vars.size(); ++i)
1731  {
1732  VariableName var_name = moose_vars[i]->name();
1733  auto & sys = _solver_systems[moose_vars[i]->sys().number()];
1734  sys->setVariableGlobalDoFs(var_name);
1735  _var_dof_map[var_name] = sys->getVariableGlobalDoFs();
1736  }
1737 }
1738 
1739 void
1740 FEProblemBase::prepare(const Elem * elem, const THREAD_ID tid)
1741 {
1742  for (const auto i : index_range(_solver_systems))
1743  {
1744  _assembly[tid][i]->reinit(elem);
1745  _solver_systems[i]->prepare(tid);
1746 
1747  if (i < _num_nl_sys)
1748  {
1749  // This method is called outside of residual/Jacobian callbacks during initial condition
1750  // evaluation
1752  _assembly[tid][i]->prepareJacobianBlock();
1753  _assembly[tid][i]->prepareResidual();
1755  _assembly[tid][i]->prepareNonlocal();
1756  }
1757  }
1758  _aux->prepare(tid);
1759 
1760  if (_displaced_problem &&
1761  // _reinit_displaced_neighbor applies to interface type objects which will do computations
1762  // based on both elem and neighbor. Consequently, despite what you might think by its name, we
1763  // must make sure we prepare the displaced elem
1765  {
1766  _displaced_problem->prepare(_displaced_mesh->elemPtr(elem->id()), tid);
1768  _displaced_problem->prepareNonlocal(tid);
1769  }
1770 }
1771 
1772 void
1774 {
1775  for (auto & nl : _nl)
1776  nl->prepareFace(tid, true);
1777  _aux->prepareFace(tid, false);
1778 
1780  _displaced_problem->prepareFace(_displaced_mesh->elemPtr(elem->id()), tid);
1781 }
1782 
1783 void
1784 FEProblemBase::prepare(const Elem * elem,
1785  unsigned int ivar,
1786  unsigned int jvar,
1787  const std::vector<dof_id_type> & dof_indices,
1788  const THREAD_ID tid)
1789 {
1790  for (const auto i : index_range(_nl))
1791  {
1792  _assembly[tid][i]->reinit(elem);
1793  _nl[i]->prepare(tid);
1794  }
1795 
1796  _aux->prepare(tid);
1797  const auto current_nl_sys_num = _current_nl_sys->number();
1798  _assembly[tid][current_nl_sys_num]->prepareBlock(ivar, jvar, dof_indices);
1800  if (_nonlocal_cm[current_nl_sys_num](ivar, jvar) != 0)
1801  {
1802  MooseVariableFEBase & jv = _current_nl_sys->getVariable(tid, jvar);
1803  _assembly[tid][current_nl_sys_num]->prepareBlockNonlocal(
1804  ivar, jvar, dof_indices, jv.allDofIndices());
1805  }
1806 
1808  {
1809  _displaced_problem->prepare(_displaced_mesh->elemPtr(elem->id()), ivar, jvar, dof_indices, tid);
1811  if (_nonlocal_cm[current_nl_sys_num](ivar, jvar) != 0)
1812  {
1813  MooseVariableFEBase & jv = _current_nl_sys->getVariable(tid, jvar);
1814  _displaced_problem->prepareBlockNonlocal(ivar, jvar, dof_indices, jv.allDofIndices(), tid);
1815  }
1816  }
1817 }
1818 
1819 void
1821 {
1822  SubdomainID did = elem->subdomain_id();
1823  for (const auto i : index_range(_solver_systems))
1824  {
1825  _assembly[tid][i]->setCurrentSubdomainID(did);
1826  if (_displaced_problem &&
1828  _displaced_problem->assembly(tid, i).setCurrentSubdomainID(did);
1829  }
1830 }
1831 
1832 void
1833 FEProblemBase::setNeighborSubdomainID(const Elem * elem, unsigned int side, const THREAD_ID tid)
1834 {
1835  SubdomainID did = elem->neighbor_ptr(side)->subdomain_id();
1836  for (const auto i : index_range(_nl))
1837  {
1838  _assembly[tid][i]->setCurrentNeighborSubdomainID(did);
1839  if (_displaced_problem &&
1841  _displaced_problem->assembly(tid, i).setCurrentNeighborSubdomainID(did);
1842  }
1843 }
1844 
1845 void
1846 FEProblemBase::setNeighborSubdomainID(const Elem * elem, const THREAD_ID tid)
1847 {
1848  SubdomainID did = elem->subdomain_id();
1849  for (const auto i : index_range(_nl))
1850  {
1851  _assembly[tid][i]->setCurrentNeighborSubdomainID(did);
1852  if (_displaced_problem &&
1854  _displaced_problem->assembly(tid, i).setCurrentNeighborSubdomainID(did);
1855  }
1856 }
1857 
1858 void
1860 {
1861  _assembly[tid][_current_nl_sys->number()]->prepare();
1863  _assembly[tid][_current_nl_sys->number()]->prepareNonlocal();
1864 
1866  {
1867  _displaced_problem->prepareAssembly(tid);
1869  _displaced_problem->prepareNonlocal(tid);
1870  }
1871 }
1872 
1873 void
1875 {
1876  _assembly[tid][_current_nl_sys->number()]->addResidual(Assembly::GlobalDataKey{},
1878 
1879  if (_displaced_problem)
1880  _displaced_problem->addResidual(tid);
1881 }
1882 
1883 void
1885 {
1886  _assembly[tid][_current_nl_sys->number()]->addResidualNeighbor(Assembly::GlobalDataKey{},
1888 
1889  if (_displaced_problem)
1890  _displaced_problem->addResidualNeighbor(tid);
1891 }
1892 
1893 void
1895 {
1896  _assembly[tid][_current_nl_sys->number()]->addResidualLower(Assembly::GlobalDataKey{},
1898 
1899  if (_displaced_problem)
1900  _displaced_problem->addResidualLower(tid);
1901 }
1902 
1903 void
1905 {
1906  _assembly[tid][_current_nl_sys->number()]->addResidualScalar(Assembly::GlobalDataKey{},
1908 }
1909 
1910 void
1912 {
1914  if (_displaced_problem)
1915  _displaced_problem->cacheResidual(tid);
1916 }
1917 
1918 void
1920 {
1922  if (_displaced_problem)
1923  _displaced_problem->cacheResidualNeighbor(tid);
1924 }
1925 
1926 void
1928 {
1930  if (_displaced_problem)
1931  _displaced_problem->addCachedResidual(tid);
1932 }
1933 
1934 void
1936 {
1938  _assembly[tid][_current_nl_sys->number()]->addCachedResidualDirectly(
1940 
1942  _assembly[tid][_current_nl_sys->number()]->addCachedResidualDirectly(
1944 
1945  // We do this because by adding the cached residual directly, we cannot ensure that all of the
1946  // cached residuals are emptied after only the two add calls above
1947  _assembly[tid][_current_nl_sys->number()]->clearCachedResiduals(Assembly::GlobalDataKey{});
1948 
1949  if (_displaced_problem)
1950  _displaced_problem->addCachedResidualDirectly(residual, tid);
1951 }
1952 
1953 void
1955 {
1956  _assembly[tid][_current_nl_sys->number()]->setResidual(
1957  residual,
1959  getVectorTag(_nl[_current_nl_sys->number()]->residualVectorTag()));
1960  if (_displaced_problem)
1961  _displaced_problem->setResidual(residual, tid);
1962 }
1963 
1964 void
1966 {
1967  _assembly[tid][_current_nl_sys->number()]->setResidualNeighbor(
1969  if (_displaced_problem)
1970  _displaced_problem->setResidualNeighbor(residual, tid);
1971 }
1972 
1973 void
1975 {
1976  _assembly[tid][_current_nl_sys->number()]->addJacobian(Assembly::GlobalDataKey{});
1978  _assembly[tid][_current_nl_sys->number()]->addJacobianNonlocal(Assembly::GlobalDataKey{});
1979  if (_displaced_problem)
1980  {
1981  _displaced_problem->addJacobian(tid);
1983  _displaced_problem->addJacobianNonlocal(tid);
1984  }
1985 }
1986 
1987 void
1989 {
1990  _assembly[tid][_current_nl_sys->number()]->addJacobianNeighbor(Assembly::GlobalDataKey{});
1991  if (_displaced_problem)
1992  _displaced_problem->addJacobianNeighbor(tid);
1993 }
1994 
1995 void
1997 {
1998  _assembly[tid][_current_nl_sys->number()]->addJacobianNeighborLowerD(Assembly::GlobalDataKey{});
1999  if (_displaced_problem)
2000  _displaced_problem->addJacobianNeighborLowerD(tid);
2001 }
2002 
2003 void
2005 {
2006  _assembly[tid][_current_nl_sys->number()]->addJacobianLowerD(Assembly::GlobalDataKey{});
2007  if (_displaced_problem)
2008  _displaced_problem->addJacobianLowerD(tid);
2009 }
2010 
2011 void
2013 {
2014  _assembly[tid][_current_nl_sys->number()]->addJacobianScalar(Assembly::GlobalDataKey{});
2015 }
2016 
2017 void
2018 FEProblemBase::addJacobianOffDiagScalar(unsigned int ivar, const THREAD_ID tid /* = 0*/)
2019 {
2020  _assembly[tid][_current_nl_sys->number()]->addJacobianOffDiagScalar(ivar,
2022 }
2023 
2024 void
2026 {
2028  if (_displaced_problem)
2029  _displaced_problem->cacheJacobian(tid);
2030 }
2031 
2032 void
2034 {
2036  if (_displaced_problem)
2037  _displaced_problem->cacheJacobianNeighbor(tid);
2038 }
2039 
2040 void
2042 {
2044  if (_displaced_problem)
2045  _displaced_problem->addCachedJacobian(tid);
2046 }
2047 
2048 void
2050  unsigned int ivar,
2051  unsigned int jvar,
2052  const DofMap & dof_map,
2053  std::vector<dof_id_type> & dof_indices,
2054  const std::set<TagID> & tags,
2055  const THREAD_ID tid)
2056 {
2057  _assembly[tid][_current_nl_sys->number()]->addJacobianBlockTags(
2058  jacobian, ivar, jvar, dof_map, dof_indices, Assembly::GlobalDataKey{}, tags);
2059 
2061  if (_nonlocal_cm[_current_nl_sys->number()](ivar, jvar) != 0)
2062  {
2063  MooseVariableFEBase & jv = _current_nl_sys->getVariable(tid, jvar);
2064  _assembly[tid][_current_nl_sys->number()]->addJacobianBlockNonlocalTags(
2065  jacobian,
2066  ivar,
2067  jvar,
2068  dof_map,
2069  dof_indices,
2070  jv.allDofIndices(),
2072  tags);
2073  }
2074 
2075  if (_displaced_problem)
2076  {
2077  _displaced_problem->addJacobianBlockTags(jacobian, ivar, jvar, dof_map, dof_indices, tags, tid);
2079  if (_nonlocal_cm[_current_nl_sys->number()](ivar, jvar) != 0)
2080  {
2081  MooseVariableFEBase & jv = _current_nl_sys->getVariable(tid, jvar);
2082  _displaced_problem->addJacobianBlockNonlocal(
2083  jacobian, ivar, jvar, dof_map, dof_indices, jv.allDofIndices(), tags, tid);
2084  }
2085  }
2086 }
2087 
2088 void
2090  unsigned int ivar,
2091  unsigned int jvar,
2092  const DofMap & dof_map,
2093  std::vector<dof_id_type> & dof_indices,
2094  std::vector<dof_id_type> & neighbor_dof_indices,
2095  const std::set<TagID> & tags,
2096  const THREAD_ID tid)
2097 {
2098  _assembly[tid][_current_nl_sys->number()]->addJacobianNeighborTags(jacobian,
2099  ivar,
2100  jvar,
2101  dof_map,
2102  dof_indices,
2103  neighbor_dof_indices,
2105  tags);
2106  if (_displaced_problem)
2107  _displaced_problem->addJacobianNeighbor(
2108  jacobian, ivar, jvar, dof_map, dof_indices, neighbor_dof_indices, tags, tid);
2109 }
2110 
2111 void
2112 FEProblemBase::prepareShapes(unsigned int var, const THREAD_ID tid)
2113 {
2114  _assembly[tid][_current_nl_sys->number()]->copyShapes(var);
2115 }
2116 
2117 void
2118 FEProblemBase::prepareFaceShapes(unsigned int var, const THREAD_ID tid)
2119 {
2120  _assembly[tid][_current_nl_sys->number()]->copyFaceShapes(var);
2121 }
2122 
2123 void
2125 {
2126  _assembly[tid][_current_nl_sys->number()]->copyNeighborShapes(var);
2127 }
2128 
2129 void
2131 {
2132  if (_mesh.elemPtr(elem_id)->processor_id() != processor_id())
2133  _ghosted_elems.insert(elem_id);
2134 }
2135 
2136 void
2138 {
2139  _mesh.addGhostedBoundary(boundary_id);
2140  if (_displaced_problem)
2141  _displaced_mesh->addGhostedBoundary(boundary_id);
2142 }
2143 
2144 void
2146 {
2147  TIME_SECTION("ghostGhostedBoundaries", 3, "Ghosting Ghosted Boundaries");
2148 
2150 
2151  if (_displaced_problem)
2153 }
2154 
2155 void
2156 FEProblemBase::sizeZeroes(unsigned int /*size*/, const THREAD_ID /*tid*/)
2157 {
2158  mooseDoOnce(mooseWarning(
2159  "This function is deprecated and no longer performs any function. Please do not call it."));
2160 }
2161 
2162 bool
2164 {
2165  std::vector<Point> & points = _dirac_kernel_info.getPoints()[elem].first;
2166 
2167  unsigned int n_points = points.size();
2168 
2169  if (n_points)
2170  {
2171  if (n_points > _max_qps)
2172  {
2173  _max_qps = n_points;
2174 
2179  unsigned int max_qpts = getMaxQps();
2180  for (unsigned int tid = 0; tid < libMesh::n_threads(); ++tid)
2181  {
2182  // the highest available order in libMesh is 43
2183  _scalar_zero[tid].resize(FORTYTHIRD, 0);
2184  _zero[tid].resize(max_qpts, 0);
2185  _grad_zero[tid].resize(max_qpts, RealGradient(0.));
2186  _second_zero[tid].resize(max_qpts, RealTensor(0.));
2187  _vector_zero[tid].resize(max_qpts, RealGradient(0.));
2188  _vector_curl_zero[tid].resize(max_qpts, RealGradient(0.));
2189  }
2190  }
2191 
2192  for (const auto i : index_range(_nl))
2193  {
2194  _assembly[tid][i]->reinitAtPhysical(elem, points);
2195  _nl[i]->prepare(tid);
2196  }
2197  _aux->prepare(tid);
2198 
2199  reinitElem(elem, tid);
2200  }
2201 
2202  _assembly[tid][_current_nl_sys->number()]->prepare();
2204  _assembly[tid][_current_nl_sys->number()]->prepareNonlocal();
2205 
2206  bool have_points = n_points > 0;
2208  {
2209  have_points |= _displaced_problem->reinitDirac(_displaced_mesh->elemPtr(elem->id()), tid);
2211  _displaced_problem->prepareNonlocal(tid);
2212  }
2213 
2214  return have_points;
2215 }
2216 
2217 void
2218 FEProblemBase::reinitElem(const Elem * elem, const THREAD_ID tid)
2219 {
2220  for (auto & sys : _solver_systems)
2221  sys->reinitElem(elem, tid);
2222  _aux->reinitElem(elem, tid);
2223 
2225  _displaced_problem->reinitElem(_displaced_mesh->elemPtr(elem->id()), tid);
2226 }
2227 
2228 void
2230  const std::vector<Point> & phys_points_in_elem,
2231  const THREAD_ID tid)
2232 {
2233  mooseAssert(_mesh.queryElemPtr(elem->id()) == elem,
2234  "Are you calling this method with a displaced mesh element?");
2235 
2236  for (const auto i : index_range(_solver_systems))
2237  {
2238  _assembly[tid][i]->reinitAtPhysical(elem, phys_points_in_elem);
2239  _solver_systems[i]->prepare(tid);
2240  _assembly[tid][i]->prepare();
2242  _assembly[tid][i]->prepareNonlocal();
2243  }
2244  _aux->prepare(tid);
2245 
2246  reinitElem(elem, tid);
2247 }
2248 
2249 void
2250 FEProblemBase::reinitElemFace(const Elem * const elem,
2251  const unsigned int side,
2252  const BoundaryID,
2253  const THREAD_ID tid)
2254 {
2256  "reinitElemFace with a BoundaryID argument is deprecated because the boundary id was never "
2257  "used. Please call reinitElemFace without the BoundaryID argument instead");
2258 
2259  reinitElemFace(elem, side, tid);
2260 }
2261 
2262 void
2263 FEProblemBase::reinitElemFace(const Elem * const elem, const unsigned int side, const THREAD_ID tid)
2264 {
2265  for (const auto i : index_range(_solver_systems))
2266  {
2267  _assembly[tid][i]->reinit(elem, side);
2268  _solver_systems[i]->reinitElemFace(elem, side, tid);
2269  }
2270  _aux->reinitElemFace(elem, side, tid);
2271 
2273  _displaced_problem->reinitElemFace(_displaced_mesh->elemPtr(elem->id()), side, tid);
2274 }
2275 
2276 void
2278  const THREAD_ID tid,
2279  const std::vector<Point> * const pts,
2280  const std::vector<Real> * const weights)
2281 {
2282  SubProblem::reinitLowerDElem(lower_d_elem, tid, pts, weights);
2283 
2285  _displaced_problem->reinitLowerDElem(
2286  _displaced_mesh->elemPtr(lower_d_elem->id()), tid, pts, weights);
2287 }
2288 
2289 void
2290 FEProblemBase::reinitNode(const Node * node, const THREAD_ID tid)
2291 {
2293  _displaced_problem->reinitNode(&_displaced_mesh->nodeRef(node->id()), tid);
2294 
2295  for (const auto i : index_range(_nl))
2296  {
2297  _assembly[tid][i]->reinit(node);
2298  _nl[i]->reinitNode(node, tid);
2299  }
2300  _aux->reinitNode(node, tid);
2301 }
2302 
2303 void
2304 FEProblemBase::reinitNodeFace(const Node * node, BoundaryID bnd_id, const THREAD_ID tid)
2305 {
2307  _displaced_problem->reinitNodeFace(&_displaced_mesh->nodeRef(node->id()), bnd_id, tid);
2308 
2309  for (const auto i : index_range(_nl))
2310  {
2311  _assembly[tid][i]->reinit(node);
2312  _nl[i]->reinitNodeFace(node, bnd_id, tid);
2313  }
2314  _aux->reinitNodeFace(node, bnd_id, tid);
2315 }
2316 
2317 void
2318 FEProblemBase::reinitNodes(const std::vector<dof_id_type> & nodes, const THREAD_ID tid)
2319 {
2321  _displaced_problem->reinitNodes(nodes, tid);
2322 
2323  for (auto & nl : _nl)
2324  nl->reinitNodes(nodes, tid);
2325  _aux->reinitNodes(nodes, tid);
2326 }
2327 
2328 void
2329 FEProblemBase::reinitNodesNeighbor(const std::vector<dof_id_type> & nodes, const THREAD_ID tid)
2330 {
2332  _displaced_problem->reinitNodesNeighbor(nodes, tid);
2333 
2334  for (auto & nl : _nl)
2335  nl->reinitNodesNeighbor(nodes, tid);
2336  _aux->reinitNodesNeighbor(nodes, tid);
2337 }
2338 
2339 void
2340 FEProblemBase::reinitScalars(const THREAD_ID tid, bool reinit_for_derivative_reordering /*=false*/)
2341 {
2342  TIME_SECTION("reinitScalars", 3, "Reinitializing Scalar Variables");
2343 
2345  _displaced_problem->reinitScalars(tid, reinit_for_derivative_reordering);
2346 
2347  for (auto & nl : _nl)
2348  nl->reinitScalars(tid, reinit_for_derivative_reordering);
2349  _aux->reinitScalars(tid, reinit_for_derivative_reordering);
2350 
2351  // This is called outside of residual/Jacobian call-backs
2352  for (auto & assembly : _assembly[tid])
2354 }
2355 
2356 void
2358 {
2359  _assembly[tid][_current_nl_sys->number()]->prepareOffDiagScalar();
2360  if (_displaced_problem)
2361  _displaced_problem->reinitOffDiagScalars(tid);
2362 }
2363 
2364 void
2365 FEProblemBase::reinitNeighbor(const Elem * elem, unsigned int side, const THREAD_ID tid)
2366 {
2367  setNeighborSubdomainID(elem, side, tid);
2368 
2369  const Elem * neighbor = elem->neighbor_ptr(side);
2370  unsigned int neighbor_side = neighbor->which_neighbor_am_i(elem);
2371 
2372  for (const auto i : index_range(_nl))
2373  {
2374  _assembly[tid][i]->reinitElemAndNeighbor(elem, side, neighbor, neighbor_side);
2375  _nl[i]->prepareNeighbor(tid);
2376  // Called during stateful material property evaluation outside of solve
2377  _assembly[tid][i]->prepareNeighbor();
2378  }
2379  _aux->prepareNeighbor(tid);
2380 
2381  for (auto & nl : _nl)
2382  {
2383  nl->reinitElemFace(elem, side, tid);
2384  nl->reinitNeighborFace(neighbor, neighbor_side, tid);
2385  }
2386  _aux->reinitElemFace(elem, side, tid);
2387  _aux->reinitNeighborFace(neighbor, neighbor_side, tid);
2388 
2390  {
2391  // There are cases like for cohesive zone modeling without significant sliding where we cannot
2392  // use FEInterface::inverse_map in Assembly::reinitElemAndNeighbor in the displaced problem
2393  // because the physical points coming from the element don't actually lie on the neighbor.
2394  // Moreover, what's the point of doing another physical point inversion in other cases? We only
2395  // care about the reference points which we can just take from the undisplaced computation
2396  const auto & displaced_ref_pts = _assembly[tid][0]->qRuleNeighbor()->get_points();
2397 
2398  _displaced_problem->reinitNeighbor(
2399  _displaced_mesh->elemPtr(elem->id()), side, tid, &displaced_ref_pts);
2400  }
2401 }
2402 
2403 void
2405  unsigned int side,
2406  const THREAD_ID tid)
2407 {
2408  reinitNeighbor(elem, side, tid);
2409 
2410  const Elem * lower_d_elem = _mesh.getLowerDElem(elem, side);
2411  if (lower_d_elem && _mesh.interiorLowerDBlocks().count(lower_d_elem->subdomain_id()) > 0)
2412  reinitLowerDElem(lower_d_elem, tid);
2413  else
2414  {
2415  // with mesh refinement, lower-dimensional element might be defined on neighbor side
2416  auto & neighbor = _assembly[tid][0]->neighbor();
2417  auto & neighbor_side = _assembly[tid][0]->neighborSide();
2418  const Elem * lower_d_elem_neighbor = _mesh.getLowerDElem(neighbor, neighbor_side);
2419  if (lower_d_elem_neighbor &&
2420  _mesh.interiorLowerDBlocks().count(lower_d_elem_neighbor->subdomain_id()) > 0)
2421  {
2422  auto qps = _assembly[tid][0]->qPointsFaceNeighbor().stdVector();
2423  std::vector<Point> reference_points;
2424  FEMap::inverse_map(
2425  lower_d_elem_neighbor->dim(), lower_d_elem_neighbor, qps, reference_points);
2426  reinitLowerDElem(lower_d_elem_neighbor, tid, &reference_points);
2427  }
2428  }
2429 
2431  _displaced_problem->reinitElemNeighborAndLowerD(
2432  _displaced_mesh->elemPtr(elem->id()), side, tid);
2433 }
2434 
2435 void
2436 FEProblemBase::reinitNeighborPhys(const Elem * neighbor,
2437  unsigned int neighbor_side,
2438  const std::vector<Point> & physical_points,
2439  const THREAD_ID tid)
2440 {
2441  mooseAssert(_mesh.queryElemPtr(neighbor->id()) == neighbor,
2442  "Are you calling this method with a displaced mesh element?");
2443 
2444  for (const auto i : index_range(_nl))
2445  {
2446  // Reinits shape the functions at the physical points
2447  _assembly[tid][i]->reinitNeighborAtPhysical(neighbor, neighbor_side, physical_points);
2448 
2449  // Sets the neighbor dof indices
2450  _nl[i]->prepareNeighbor(tid);
2451  }
2452  _aux->prepareNeighbor(tid);
2453 
2454  // Resizes Re and Ke
2455  _assembly[tid][_current_nl_sys->number()]->prepareNeighbor();
2456 
2457  // Compute the values of each variable at the points
2458  for (auto & nl : _nl)
2459  nl->reinitNeighborFace(neighbor, neighbor_side, tid);
2460  _aux->reinitNeighborFace(neighbor, neighbor_side, tid);
2461 }
2462 
2463 void
2464 FEProblemBase::reinitNeighborPhys(const Elem * neighbor,
2465  const std::vector<Point> & physical_points,
2466  const THREAD_ID tid)
2467 {
2468  mooseAssert(_mesh.queryElemPtr(neighbor->id()) == neighbor,
2469  "Are you calling this method with a displaced mesh element?");
2470 
2471  for (const auto i : index_range(_nl))
2472  {
2473  // Reinits shape the functions at the physical points
2474  _assembly[tid][i]->reinitNeighborAtPhysical(neighbor, physical_points);
2475 
2476  // Sets the neighbor dof indices
2477  _nl[i]->prepareNeighbor(tid);
2478  }
2479  _aux->prepareNeighbor(tid);
2480 
2481  // Resizes Re and Ke
2482  _assembly[tid][_current_nl_sys->number()]->prepareNeighbor();
2483 
2484  // Compute the values of each variable at the points
2485  for (auto & nl : _nl)
2486  nl->reinitNeighbor(neighbor, tid);
2487  _aux->reinitNeighbor(neighbor, tid);
2488 }
2489 
2490 void
2491 FEProblemBase::getDiracElements(std::set<const Elem *> & elems)
2492 {
2493  // First add in the undisplaced elements
2494  elems = _dirac_kernel_info.getElements();
2495 
2496  if (_displaced_problem)
2497  {
2498  std::set<const Elem *> displaced_elements;
2499  _displaced_problem->getDiracElements(displaced_elements);
2500 
2501  { // Use the ids from the displaced elements to get the undisplaced elements
2502  // and add them to the list
2503  for (const auto & elem : displaced_elements)
2504  elems.insert(_mesh.elemPtr(elem->id()));
2505  }
2506  }
2507 }
2508 
2509 void
2511 {
2513 
2514  if (_displaced_problem)
2515  _displaced_problem->clearDiracInfo();
2516 }
2517 
2518 void
2520 {
2521  _all_materials.subdomainSetup(subdomain, tid);
2522  // Call the subdomain methods of the output system, these are not threaded so only call it once
2523  if (tid == 0)
2525 
2526  for (auto & nl : _nl)
2527  nl->subdomainSetup(subdomain, tid);
2528 
2529  // FIXME: call displaced_problem->subdomainSetup() ?
2530  // When adding possibility with materials being evaluated on displaced mesh
2531 }
2532 
2533 void
2535 {
2536  _all_materials.neighborSubdomainSetup(subdomain, tid);
2537 }
2538 
2539 void
2540 FEProblemBase::addFunction(const std::string & type,
2541  const std::string & name,
2542  InputParameters & parameters)
2543 {
2544  parallel_object_only();
2545 
2546  parameters.set<SubProblem *>("_subproblem") = this;
2547 
2548  for (THREAD_ID tid = 0; tid < libMesh::n_threads(); tid++)
2549  {
2550  std::shared_ptr<Function> func = _factory.create<Function>(type, name, parameters, tid);
2551  logAdd("Function", name, type, parameters);
2552  _functions.addObject(func, tid);
2553 
2554  if (auto * const functor = dynamic_cast<Moose::FunctorBase<Real> *>(func.get()))
2555  {
2556  this->addFunctor(name, *functor, tid);
2557  if (_displaced_problem)
2558  _displaced_problem->addFunctor(name, *functor, tid);
2559  }
2560  else
2561  mooseError("Unrecognized function functor type");
2562  }
2563 }
2564 
2565 void
2566 FEProblemBase::addConvergence(const std::string & type,
2567  const std::string & name,
2568  InputParameters & parameters)
2569 {
2570  parallel_object_only();
2571 
2572  for (THREAD_ID tid = 0; tid < libMesh::n_threads(); tid++)
2573  {
2574  std::shared_ptr<Convergence> conv = _factory.create<Convergence>(type, name, parameters, tid);
2575  _convergences.addObject(conv, tid);
2576  }
2577 }
2578 
2579 void
2581 {
2582  const std::string class_name = "DefaultNonlinearConvergence";
2583  InputParameters params = _factory.getValidParams(class_name);
2584  params.applyParameters(params_to_apply);
2585  params.applyParameters(parameters());
2586  params.set<bool>("added_as_default") = true;
2587  for (const auto & conv_name : getNonlinearConvergenceNames())
2588  addConvergence(class_name, conv_name, params);
2589 }
2590 
2591 void
2593 {
2594  const std::string class_name = "DefaultMultiAppFixedPointConvergence";
2595  InputParameters params = _factory.getValidParams(class_name);
2596  params.applyParameters(params_to_apply);
2597  params.applyParameters(parameters());
2598  params.set<bool>("added_as_default") = true;
2600 }
2601 
2602 void
2604 {
2605  const std::string class_name = "DefaultSteadyStateConvergence";
2606  InputParameters params = _factory.getValidParams(class_name);
2607  params.applyParameters(params_to_apply);
2608  params.applyParameters(parameters());
2609  params.set<bool>("added_as_default") = true;
2610  addConvergence(class_name, getSteadyStateConvergenceName(), params);
2611 }
2612 
2613 bool
2614 FEProblemBase::hasFunction(const std::string & name, const THREAD_ID tid)
2615 {
2616  return _functions.hasActiveObject(name, tid);
2617 }
2618 
2619 Function &
2620 FEProblemBase::getFunction(const std::string & name, const THREAD_ID tid)
2621 {
2622  // This thread lock is necessary since this method will create functions
2623  // for all threads if one is missing.
2624  Threads::spin_mutex::scoped_lock lock(get_function_mutex);
2625 
2626  if (!hasFunction(name, tid))
2627  {
2628  // If we didn't find a function, it might be a default function, attempt to construct one now
2629  std::istringstream ss(name);
2630  Real real_value;
2631 
2632  // First see if it's just a constant. If it is, build a ConstantFunction
2633  if (ss >> real_value && ss.eof())
2634  {
2635  InputParameters params = _factory.getValidParams("ConstantFunction");
2636  params.set<Real>("value") = real_value;
2637  addFunction("ConstantFunction", ss.str(), params);
2638  }
2639  else
2640  {
2642  std::string vars = "x,y,z,t,NaN,pi,e";
2643  if (fp.Parse(name, vars) == -1) // -1 for success
2644  {
2645  // It parsed ok, so build a MooseParsedFunction
2646  InputParameters params = _factory.getValidParams("ParsedFunction");
2647  params.set<std::string>("expression") = name;
2648  addFunction("ParsedFunction", name, params);
2649  }
2650  }
2651 
2652  // Try once more
2653  if (!hasFunction(name, tid))
2654  mooseError("Unable to find function " + name);
2655  }
2656 
2657  auto * const ret = dynamic_cast<Function *>(_functions.getActiveObject(name, tid).get());
2658  if (!ret)
2659  mooseError("No function named ", name, " of appropriate type");
2660 
2661  return *ret;
2662 }
2663 
2664 bool
2665 FEProblemBase::hasConvergence(const std::string & name, const THREAD_ID tid) const
2666 {
2667  return _convergences.hasActiveObject(name, tid);
2668 }
2669 
2670 Convergence &
2671 FEProblemBase::getConvergence(const std::string & name, const THREAD_ID tid) const
2672 {
2673  auto * const ret = dynamic_cast<Convergence *>(_convergences.getActiveObject(name, tid).get());
2674  if (!ret)
2675  mooseError("The Convergence object '", name, "' does not exist.");
2676 
2677  return *ret;
2678 }
2679 
2680 const std::vector<std::shared_ptr<Convergence>> &
2682 {
2683  return _convergences.getActiveObjects(tid);
2684 }
2685 
2686 void
2687 FEProblemBase::addMeshDivision(const std::string & type,
2688  const std::string & name,
2689  InputParameters & parameters)
2690 {
2691  parallel_object_only();
2692  parameters.set<FEProblemBase *>("_fe_problem_base") = this;
2693  parameters.set<SubProblem *>("_subproblem") = this;
2694  for (THREAD_ID tid = 0; tid < libMesh::n_threads(); tid++)
2695  {
2696  std::shared_ptr<MeshDivision> func = _factory.create<MeshDivision>(type, name, parameters, tid);
2697  _mesh_divisions.addObject(func, tid);
2698  }
2699 }
2700 
2701 MeshDivision &
2702 FEProblemBase::getMeshDivision(const std::string & name, const THREAD_ID tid) const
2703 {
2704  auto * const ret = dynamic_cast<MeshDivision *>(_mesh_divisions.getActiveObject(name, tid).get());
2705  if (!ret)
2706  mooseError("No MeshDivision object named ", name, " of appropriate type");
2707  return *ret;
2708 }
2709 
2710 void
2712 {
2713  _line_search->lineSearch();
2714 }
2715 
2717 FEProblemBase::getNonlinearSystem(const unsigned int sys_num)
2718 {
2719  mooseDeprecated("FEProblemBase::getNonlinearSystem() is deprecated, please use "
2720  "FEProblemBase::getNonlinearSystemBase() \n");
2721 
2722  mooseAssert(sys_num < _nl.size(), "System number greater than the number of nonlinear systems");
2723  auto nl_sys = std::dynamic_pointer_cast<NonlinearSystem>(_nl[sys_num]);
2724 
2725  if (!nl_sys)
2726  mooseError("This is not a NonlinearSystem");
2727 
2728  return *nl_sys;
2729 }
2730 
2731 void
2732 FEProblemBase::addDistribution(const std::string & type,
2733  const std::string & name,
2734  InputParameters & parameters)
2735 {
2736  parameters.set<std::string>("type") = type;
2737  addObject<Distribution>(type, name, parameters, /* threaded = */ false);
2738 }
2739 
2740 Distribution &
2741 FEProblemBase::getDistribution(const std::string & name)
2742 {
2743  std::vector<Distribution *> objs;
2744  theWarehouse()
2745  .query()
2746  .condition<AttribSystem>("Distribution")
2747  .condition<AttribName>(name)
2748  .queryInto(objs);
2749  if (objs.empty())
2750  mooseError("Unable to find Distribution with name '" + name + "'");
2751  return *(objs[0]);
2752 }
2753 
2754 void
2755 FEProblemBase::addSampler(const std::string & type,
2756  const std::string & name,
2757  InputParameters & parameters)
2758 {
2759  const auto samplers = addObject<Sampler>(type, name, parameters);
2760  for (auto & sampler : samplers)
2761  sampler->init();
2762 }
2763 
2764 Sampler &
2765 FEProblemBase::getSampler(const std::string & name, const THREAD_ID tid)
2766 {
2767  std::vector<Sampler *> objs;
2768  theWarehouse()
2769  .query()
2770  .condition<AttribSystem>("Sampler")
2771  .condition<AttribThread>(tid)
2772  .condition<AttribName>(name)
2773  .queryInto(objs);
2774  if (objs.empty())
2775  mooseError(
2776  "Unable to find Sampler with name '" + name +
2777  "', if you are attempting to access this object in the constructor of another object then "
2778  "the object being retrieved must occur prior to the caller within the input file.");
2779  return *(objs[0]);
2780 }
2781 
2782 bool
2783 FEProblemBase::duplicateVariableCheck(const std::string & var_name,
2784  const FEType & type,
2785  bool is_aux,
2786  const std::set<SubdomainID> * const active_subdomains)
2787 {
2788  std::set<SubdomainID> subdomainIDs;
2789  if (active_subdomains->size() == 0)
2790  {
2791  const auto subdomains = _mesh.meshSubdomains();
2792  subdomainIDs.insert(subdomains.begin(), subdomains.end());
2793  }
2794  else
2795  subdomainIDs.insert(active_subdomains->begin(), active_subdomains->end());
2796 
2797  for (auto & sys : _solver_systems)
2798  {
2799  SystemBase * curr_sys_ptr = sys.get();
2800  SystemBase * other_sys_ptr = _aux.get();
2801  std::string error_prefix = "";
2802  if (is_aux)
2803  {
2804  curr_sys_ptr = _aux.get();
2805  other_sys_ptr = sys.get();
2806  error_prefix = "aux";
2807  }
2808 
2809  if (other_sys_ptr->hasVariable(var_name))
2810  mooseError("Cannot have an auxiliary variable and a solver variable with the same name: ",
2811  var_name);
2812 
2813  if (curr_sys_ptr->hasVariable(var_name))
2814  {
2815  const Variable & var =
2816  curr_sys_ptr->system().variable(curr_sys_ptr->system().variable_number(var_name));
2817 
2818  // variable type
2819  if (var.type() != type)
2820  {
2821  const auto stringifyType = [](FEType t)
2822  { return Moose::stringify(t.family) + " of order " + Moose::stringify(t.order); };
2823 
2824  mooseError("Mismatching types are specified for ",
2825  error_prefix,
2826  "variable with name '",
2827  var_name,
2828  "': '",
2829  stringifyType(var.type()),
2830  "' and '",
2831  stringifyType(type),
2832  "'");
2833  }
2834 
2835  // block-restriction
2836  if (!(active_subdomains->size() == 0 && var.active_subdomains().size() == 0))
2837  {
2838  const auto varActiveSubdomains = var.active_subdomains();
2839  std::set<SubdomainID> varSubdomainIDs;
2840  if (varActiveSubdomains.size() == 0)
2841  {
2842  const auto subdomains = _mesh.meshSubdomains();
2843  varSubdomainIDs.insert(subdomains.begin(), subdomains.end());
2844  }
2845  else
2846  varSubdomainIDs.insert(varActiveSubdomains.begin(), varActiveSubdomains.end());
2847 
2848  // Is subdomainIDs a subset of varSubdomainIDs? With this we allow the case that the newly
2849  // requested block restriction is only a subset of the existing one.
2850  const auto isSubset = std::includes(varSubdomainIDs.begin(),
2851  varSubdomainIDs.end(),
2852  subdomainIDs.begin(),
2853  subdomainIDs.end());
2854 
2855  if (!isSubset)
2856  {
2857  // helper function: make a string from a set of subdomain ids
2858  const auto stringifySubdomains = [this](std::set<SubdomainID> subdomainIDs)
2859  {
2860  std::stringstream s;
2861  for (auto const i : subdomainIDs)
2862  {
2863  // do we need to insert a comma?
2864  if (s.tellp() != 0)
2865  s << ", ";
2866 
2867  // insert subdomain name and id -or- only the id (if no name is given)
2868  const auto subdomainName = _mesh.getSubdomainName(i);
2869  if (subdomainName.empty())
2870  s << i;
2871  else
2872  s << subdomainName << " (" << i << ")";
2873  }
2874  return s.str();
2875  };
2876 
2877  const std::string msg = "Mismatching block-restrictions are specified for " +
2878  error_prefix + "variable with name '" + var_name + "': {" +
2879  stringifySubdomains(varSubdomainIDs) + "} and {" +
2880  stringifySubdomains(subdomainIDs) + "}";
2881 
2882  mooseError(msg);
2883  }
2884  }
2885 
2886  return true;
2887  }
2888  }
2889 
2890  return false;
2891 }
2892 
2893 void
2894 FEProblemBase::addVariable(const std::string & var_type,
2895  const std::string & var_name,
2896  InputParameters & params)
2897 {
2898  parallel_object_only();
2899 
2900  const auto order = Utility::string_to_enum<Order>(params.get<MooseEnum>("order"));
2901  const auto family = Utility::string_to_enum<FEFamily>(params.get<MooseEnum>("family"));
2902  const auto fe_type = FEType(order, family);
2903 
2904  const auto active_subdomains_vector =
2905  _mesh.getSubdomainIDs(params.get<std::vector<SubdomainName>>("block"));
2906  const std::set<SubdomainID> active_subdomains(active_subdomains_vector.begin(),
2907  active_subdomains_vector.end());
2908 
2909  if (duplicateVariableCheck(var_name, fe_type, /* is_aux = */ false, &active_subdomains))
2910  return;
2911 
2912  params.set<FEProblemBase *>("_fe_problem_base") = this;
2913  params.set<Moose::VarKindType>("_var_kind") = Moose::VarKindType::VAR_SOLVER;
2914  SolverSystemName sys_name = params.get<SolverSystemName>("solver_sys");
2915 
2916  const auto solver_system_number = solverSysNum(sys_name);
2917  logAdd("Variable", var_name, var_type, params);
2918  _solver_systems[solver_system_number]->addVariable(var_type, var_name, params);
2919  if (_displaced_problem)
2920  // MooseObjects need to be unique so change the name here
2921  _displaced_problem->addVariable(var_type, var_name, params, solver_system_number);
2922 
2923  _solver_var_to_sys_num[var_name] = solver_system_number;
2924 
2925  markFamilyPRefinement(params);
2926 }
2927 
2928 std::pair<bool, unsigned int>
2929 FEProblemBase::determineSolverSystem(const std::string & var_name,
2930  const bool error_if_not_found) const
2931 {
2932  auto map_it = _solver_var_to_sys_num.find(var_name);
2933  const bool var_in_sys = map_it != _solver_var_to_sys_num.end();
2934  if (var_in_sys)
2935  mooseAssert(_solver_systems[map_it->second]->hasVariable(var_name) ||
2936  _solver_systems[map_it->second]->hasScalarVariable(var_name),
2937  "If the variable is in our FEProblem solver system map, then it must be in the "
2938  "solver system we expect");
2939  else if (error_if_not_found)
2940  {
2941  if (_aux->hasVariable(var_name) || _aux->hasScalarVariable(var_name))
2942  mooseError("No solver variable named ",
2943  var_name,
2944  " found. Did you specify an auxiliary variable when you meant to specify a "
2945  "solver variable?");
2946  else
2947  mooseError("Unknown variable '",
2948  var_name,
2949  "'. It does not exist in the solver system(s) or auxiliary system");
2950  }
2951 
2952  return std::make_pair(var_in_sys, var_in_sys ? map_it->second : libMesh::invalid_uint);
2953 }
2954 
2955 void
2957  const std::string & name,
2958  InputParameters & parameters,
2959  const unsigned int nl_sys_num,
2960  const std::string & base_name,
2961  bool & reinit_displaced)
2962 {
2963  if (_displaced_problem && parameters.get<bool>("use_displaced_mesh"))
2964  {
2965  parameters.set<SubProblem *>("_subproblem") = _displaced_problem.get();
2966  parameters.set<SystemBase *>("_sys") = &_displaced_problem->solverSys(nl_sys_num);
2967  reinit_displaced = true;
2968  }
2969  else
2970  {
2971  if (_displaced_problem == nullptr && parameters.get<bool>("use_displaced_mesh"))
2972  {
2973  // We allow Kernels to request that they use_displaced_mesh,
2974  // but then be overridden when no displacements variables are
2975  // provided in the Mesh block. If that happened, update the value
2976  // of use_displaced_mesh appropriately for this Kernel.
2977  if (parameters.have_parameter<bool>("use_displaced_mesh"))
2978  parameters.set<bool>("use_displaced_mesh") = false;
2979  }
2980 
2981  parameters.set<SubProblem *>("_subproblem") = this;
2982  parameters.set<SystemBase *>("_sys") = _nl[nl_sys_num].get();
2983  }
2984 
2985  logAdd(base_name, name, ro_name, parameters);
2986 }
2987 
2988 void
2989 FEProblemBase::setAuxKernelParamsAndLog(const std::string & ak_name,
2990  const std::string & name,
2991  InputParameters & parameters,
2992  const std::string & base_name)
2993 {
2994  if (_displaced_problem && parameters.get<bool>("use_displaced_mesh"))
2995  {
2996  parameters.set<SubProblem *>("_subproblem") = _displaced_problem.get();
2997  parameters.set<SystemBase *>("_sys") = &_displaced_problem->auxSys();
2998  parameters.set<SystemBase *>("_nl_sys") = &_displaced_problem->solverSys(0);
2999  if (!parameters.get<std::vector<BoundaryName>>("boundary").empty())
3000  _reinit_displaced_face = true;
3001  else
3002  _reinit_displaced_elem = true;
3003  }
3004  else
3005  {
3006  if (_displaced_problem == nullptr && parameters.get<bool>("use_displaced_mesh"))
3007  {
3008  // We allow AuxKernels to request that they use_displaced_mesh,
3009  // but then be overridden when no displacements variables are
3010  // provided in the Mesh block. If that happened, update the value
3011  // of use_displaced_mesh appropriately for this AuxKernel.
3012  if (parameters.have_parameter<bool>("use_displaced_mesh"))
3013  parameters.set<bool>("use_displaced_mesh") = false;
3014  }
3015 
3016  parameters.set<SubProblem *>("_subproblem") = this;
3017  parameters.set<SystemBase *>("_sys") = _aux.get();
3018  parameters.set<SystemBase *>("_nl_sys") = _solver_systems[0].get();
3019  }
3020 
3021  logAdd(base_name, name, ak_name, parameters);
3022 }
3023 
3024 void
3025 FEProblemBase::addKernel(const std::string & kernel_name,
3026  const std::string & name,
3027  InputParameters & parameters)
3028 {
3029  parallel_object_only();
3030  const auto nl_sys_num = determineSolverSystem(parameters.varName("variable", name), true).second;
3031  if (!isSolverSystemNonlinear(nl_sys_num))
3032  mooseError("You are trying to add a Kernel to a linear variable/system, which is not "
3033  "supported at the moment!");
3035  kernel_name, name, parameters, nl_sys_num, "Kernel", _reinit_displaced_elem);
3036 
3037  _nl[nl_sys_num]->addKernel(kernel_name, name, parameters);
3038 }
3039 
3040 void
3041 FEProblemBase::addHDGKernel(const std::string & kernel_name,
3042  const std::string & name,
3043  InputParameters & parameters)
3044 {
3045  parallel_object_only();
3046  const auto nl_sys_num = determineSolverSystem(parameters.varName("variable", name), true).second;
3047  if (!isSolverSystemNonlinear(nl_sys_num))
3048  mooseError("You are trying to add a HDGKernel to a linear variable/system, which is not "
3049  "supported at the moment!");
3051  kernel_name, name, parameters, nl_sys_num, "HDGKernel", _reinit_displaced_elem);
3052 
3053  _nl[nl_sys_num]->addHDGKernel(kernel_name, name, parameters);
3054 }
3055 
3056 void
3057 FEProblemBase::addNodalKernel(const std::string & kernel_name,
3058  const std::string & name,
3059  InputParameters & parameters)
3060 {
3061  parallel_object_only();
3062 
3063  const auto nl_sys_num = determineSolverSystem(parameters.varName("variable", name), true).second;
3064  if (_displaced_problem && parameters.get<bool>("use_displaced_mesh"))
3065  {
3066  parameters.set<SubProblem *>("_subproblem") = _displaced_problem.get();
3067  parameters.set<SystemBase *>("_sys") = &_displaced_problem->solverSys(nl_sys_num);
3068  _reinit_displaced_elem = true;
3069  }
3070  else
3071  {
3072  if (_displaced_problem == nullptr && parameters.get<bool>("use_displaced_mesh"))
3073  {
3074  // We allow NodalKernels to request that they use_displaced_mesh,
3075  // but then be overridden when no displacements variables are
3076  // provided in the Mesh block. If that happened, update the value
3077  // of use_displaced_mesh appropriately for this NodalKernel.
3078  if (parameters.have_parameter<bool>("use_displaced_mesh"))
3079  parameters.set<bool>("use_displaced_mesh") = false;
3080  }
3081 
3082  parameters.set<SubProblem *>("_subproblem") = this;
3083  parameters.set<SystemBase *>("_sys") = _nl[nl_sys_num].get();
3084  }
3085  logAdd("NodalKernel", name, kernel_name, parameters);
3086  _nl[nl_sys_num]->addNodalKernel(kernel_name, name, parameters);
3087 }
3088 
3089 void
3090 FEProblemBase::addScalarKernel(const std::string & kernel_name,
3091  const std::string & name,
3092  InputParameters & parameters)
3093 {
3094  parallel_object_only();
3095 
3096  const auto nl_sys_num = determineSolverSystem(parameters.varName("variable", name), true).second;
3097  if (!isSolverSystemNonlinear(nl_sys_num))
3098  mooseError("You are trying to add a ScalarKernel to a linear variable/system, which is not "
3099  "supported at the moment!");
3100 
3101  if (_displaced_problem && parameters.get<bool>("use_displaced_mesh"))
3102  {
3103  parameters.set<SubProblem *>("_subproblem") = _displaced_problem.get();
3104  parameters.set<SystemBase *>("_sys") = &_displaced_problem->solverSys(nl_sys_num);
3105  }
3106  else
3107  {
3108  if (_displaced_problem == nullptr && parameters.get<bool>("use_displaced_mesh"))
3109  {
3110  // We allow ScalarKernels to request that they use_displaced_mesh,
3111  // but then be overridden when no displacements variables are
3112  // provided in the Mesh block. If that happened, update the value
3113  // of use_displaced_mesh appropriately for this ScalarKernel.
3114  if (parameters.have_parameter<bool>("use_displaced_mesh"))
3115  parameters.set<bool>("use_displaced_mesh") = false;
3116  }
3117 
3118  parameters.set<SubProblem *>("_subproblem") = this;
3119  parameters.set<SystemBase *>("_sys") = _nl[nl_sys_num].get();
3120  }
3121 
3122  logAdd("ScalarKernel", name, kernel_name, parameters);
3123  _nl[nl_sys_num]->addScalarKernel(kernel_name, name, parameters);
3124 }
3125 
3126 void
3127 FEProblemBase::addBoundaryCondition(const std::string & bc_name,
3128  const std::string & name,
3129  InputParameters & parameters)
3130 {
3131  parallel_object_only();
3132 
3133  const auto nl_sys_num = determineSolverSystem(parameters.varName("variable", name), true).second;
3134  if (!isSolverSystemNonlinear(nl_sys_num))
3135  mooseError(
3136  "You are trying to add a BoundaryCondition to a linear variable/system, which is not "
3137  "supported at the moment!");
3138 
3140  bc_name, name, parameters, nl_sys_num, "BoundaryCondition", _reinit_displaced_face);
3141  _nl[nl_sys_num]->addBoundaryCondition(bc_name, name, parameters);
3142 }
3143 
3144 void
3145 FEProblemBase::addConstraint(const std::string & c_name,
3146  const std::string & name,
3147  InputParameters & parameters)
3148 {
3149  parallel_object_only();
3150 
3151  _has_constraints = true;
3152 
3153  auto determine_var_param_name = [&parameters, this]()
3154  {
3155  if (parameters.isParamValid("variable"))
3156  return "variable";
3157  else
3158  {
3159  // must be a mortar constraint
3160  const bool has_secondary_var = parameters.isParamValid("secondary_variable");
3161  const bool has_primary_var = parameters.isParamValid("primary_variable");
3162  if (!has_secondary_var && !has_primary_var)
3163  mooseError(
3164  "Either a 'secondary_variable' or 'primary_variable' parameter must be supplied for '",
3166  "'");
3167  return has_secondary_var ? "secondary_variable" : "primary_variable";
3168  }
3169  };
3170 
3171  const auto nl_sys_num =
3172  determineSolverSystem(parameters.varName(determine_var_param_name(), name), true).second;
3173  if (!isSolverSystemNonlinear(nl_sys_num))
3174  mooseError("You are trying to add a Constraint to a linear variable/system, which is not "
3175  "supported at the moment!");
3176 
3177  if (_displaced_problem && parameters.get<bool>("use_displaced_mesh"))
3178  {
3179  parameters.set<SubProblem *>("_subproblem") = _displaced_problem.get();
3180  parameters.set<SystemBase *>("_sys") = &_displaced_problem->solverSys(nl_sys_num);
3181  _reinit_displaced_face = true;
3182  }
3183  else
3184  {
3185  // It might _want_ to use a displaced mesh... but we're not so set it to false
3186  if (parameters.have_parameter<bool>("use_displaced_mesh"))
3187  parameters.set<bool>("use_displaced_mesh") = false;
3188 
3189  parameters.set<SubProblem *>("_subproblem") = this;
3190  parameters.set<SystemBase *>("_sys") = _nl[nl_sys_num].get();
3191  }
3192 
3193  logAdd("Constraint", name, c_name, parameters);
3194  _nl[nl_sys_num]->addConstraint(c_name, name, parameters);
3195 }
3196 
3197 void
3198 FEProblemBase::addAuxVariable(const std::string & var_type,
3199  const std::string & var_name,
3200  InputParameters & params)
3201 {
3202  parallel_object_only();
3203 
3204  const auto order = Utility::string_to_enum<Order>(params.get<MooseEnum>("order"));
3205  const auto family = Utility::string_to_enum<FEFamily>(params.get<MooseEnum>("family"));
3206  const auto fe_type = FEType(order, family);
3207 
3208  const auto active_subdomains_vector =
3209  _mesh.getSubdomainIDs(params.get<std::vector<SubdomainName>>("block"));
3210  const std::set<SubdomainID> active_subdomains(active_subdomains_vector.begin(),
3211  active_subdomains_vector.end());
3212 
3213  if (duplicateVariableCheck(var_name, fe_type, /* is_aux = */ true, &active_subdomains))
3214  return;
3215 
3216  params.set<FEProblemBase *>("_fe_problem_base") = this;
3218 
3219  logAdd("AuxVariable", var_name, var_type, params);
3220  _aux->addVariable(var_type, var_name, params);
3221  if (_displaced_problem)
3222  // MooseObjects need to be unique so change the name here
3223  _displaced_problem->addAuxVariable(var_type, var_name, params);
3224 
3225  markFamilyPRefinement(params);
3226 }
3227 
3228 void
3229 FEProblemBase::addAuxVariable(const std::string & var_name,
3230  const FEType & type,
3231  const std::set<SubdomainID> * const active_subdomains)
3232 {
3233  parallel_object_only();
3234 
3235  mooseDeprecated("Please use the addAuxVariable(var_type, var_name, params) API instead");
3236 
3237  if (duplicateVariableCheck(var_name, type, /* is_aux = */ true, active_subdomains))
3238  return;
3239 
3240  std::string var_type;
3241  if (type == FEType(0, MONOMIAL))
3242  var_type = "MooseVariableConstMonomial";
3243  else if (type.family == SCALAR)
3244  var_type = "MooseVariableScalar";
3245  else if (FEInterface::field_type(type) == TYPE_VECTOR)
3246  var_type = "VectorMooseVariable";
3247  else
3248  var_type = "MooseVariable";
3249 
3250  InputParameters params = _factory.getValidParams(var_type);
3251  params.set<FEProblemBase *>("_fe_problem_base") = this;
3253  params.set<MooseEnum>("order") = type.order.get_order();
3254  params.set<MooseEnum>("family") = Moose::stringify(type.family);
3255 
3256  if (active_subdomains)
3257  for (const SubdomainID & id : *active_subdomains)
3258  params.set<std::vector<SubdomainName>>("block").push_back(Moose::stringify(id));
3259 
3260  logAdd("AuxVariable", var_name, var_type, params);
3261  _aux->addVariable(var_type, var_name, params);
3262  if (_displaced_problem)
3263  _displaced_problem->addAuxVariable("MooseVariable", var_name, params);
3264 
3265  markFamilyPRefinement(params);
3266 }
3267 
3268 void
3269 FEProblemBase::addAuxArrayVariable(const std::string & var_name,
3270  const FEType & type,
3271  unsigned int components,
3272  const std::set<SubdomainID> * const active_subdomains)
3273 {
3274  parallel_object_only();
3275 
3276  mooseDeprecated("Please use the addAuxVariable(var_type, var_name, params) API instead");
3277 
3278  if (duplicateVariableCheck(var_name, type, /* is_aux = */ true, active_subdomains))
3279  return;
3280 
3281  InputParameters params = _factory.getValidParams("ArrayMooseVariable");
3282  params.set<FEProblemBase *>("_fe_problem_base") = this;
3284  params.set<MooseEnum>("order") = type.order.get_order();
3285  params.set<MooseEnum>("family") = Moose::stringify(type.family);
3286  params.set<unsigned int>("components") = components;
3287 
3288  if (active_subdomains)
3289  for (const SubdomainID & id : *active_subdomains)
3290  params.set<std::vector<SubdomainName>>("block").push_back(Moose::stringify(id));
3291 
3292  logAdd("Variable", var_name, "ArrayMooseVariable", params);
3293  _aux->addVariable("ArrayMooseVariable", var_name, params);
3294  if (_displaced_problem)
3295  _displaced_problem->addAuxVariable("ArrayMooseVariable", var_name, params);
3296 
3297  markFamilyPRefinement(params);
3298 }
3299 
3300 void
3301 FEProblemBase::addAuxScalarVariable(const std::string & var_name,
3302  Order order,
3303  Real /*scale_factor*/,
3304  const std::set<SubdomainID> * const active_subdomains)
3305 {
3306  parallel_object_only();
3307 
3308  mooseDeprecated("Please use the addAuxVariable(var_type, var_name, params) API instead");
3309 
3310  if (order > _max_scalar_order)
3311  _max_scalar_order = order;
3312 
3313  FEType type(order, SCALAR);
3314  if (duplicateVariableCheck(var_name, type, /* is_aux = */ true, active_subdomains))
3315  return;
3316 
3317  InputParameters params = _factory.getValidParams("MooseVariableScalar");
3318  params.set<FEProblemBase *>("_fe_problem_base") = this;
3320 
3321  params.set<MooseEnum>("order") = type.order.get_order();
3322  params.set<MooseEnum>("family") = "SCALAR";
3323  params.set<std::vector<Real>>("scaling") = {1};
3324  if (active_subdomains)
3325  for (const SubdomainID & id : *active_subdomains)
3326  params.set<std::vector<SubdomainName>>("block").push_back(Moose::stringify(id));
3327 
3328  logAdd("ScalarVariable", var_name, "MooseVariableScalar", params);
3329  _aux->addVariable("MooseVariableScalar", var_name, params);
3330  if (_displaced_problem)
3331  _displaced_problem->addAuxVariable("MooseVariableScalar", var_name, params);
3332 }
3333 
3334 void
3335 FEProblemBase::addAuxKernel(const std::string & kernel_name,
3336  const std::string & name,
3337  InputParameters & parameters)
3338 {
3339  parallel_object_only();
3340 
3341  setAuxKernelParamsAndLog(kernel_name, name, parameters, "AuxKernel");
3342 
3343  _aux->addKernel(kernel_name, name, parameters);
3344 }
3345 
3346 void
3347 FEProblemBase::addAuxScalarKernel(const std::string & kernel_name,
3348  const std::string & name,
3349  InputParameters & parameters)
3350 {
3351  parallel_object_only();
3352 
3353  if (_displaced_problem && parameters.get<bool>("use_displaced_mesh"))
3354  {
3355  parameters.set<SubProblem *>("_subproblem") = _displaced_problem.get();
3356  parameters.set<SystemBase *>("_sys") = &_displaced_problem->auxSys();
3357  }
3358  else
3359  {
3360  if (_displaced_problem == nullptr && parameters.get<bool>("use_displaced_mesh"))
3361  {
3362  // We allow AuxScalarKernels to request that they use_displaced_mesh,
3363  // but then be overridden when no displacements variables are
3364  // provided in the Mesh block. If that happened, update the value
3365  // of use_displaced_mesh appropriately for this AuxScalarKernel.
3366  if (parameters.have_parameter<bool>("use_displaced_mesh"))
3367  parameters.set<bool>("use_displaced_mesh") = false;
3368  }
3369 
3370  parameters.set<SubProblem *>("_subproblem") = this;
3371  parameters.set<SystemBase *>("_sys") = _aux.get();
3372  }
3373 
3374  logAdd("AuxScalarKernel", name, kernel_name, parameters);
3375  _aux->addScalarKernel(kernel_name, name, parameters);
3376 }
3377 
3378 void
3379 FEProblemBase::addDiracKernel(const std::string & kernel_name,
3380  const std::string & name,
3381  InputParameters & parameters)
3382 {
3383  parallel_object_only();
3384 
3385  const auto nl_sys_num = determineSolverSystem(parameters.varName("variable", name), true).second;
3386  if (!isSolverSystemNonlinear(nl_sys_num))
3387  mooseError("You are trying to add a DiracKernel to a linear variable/system, which is not "
3388  "supported at the moment!");
3389 
3390  if (_displaced_problem && parameters.get<bool>("use_displaced_mesh"))
3391  {
3392  parameters.set<SubProblem *>("_subproblem") = _displaced_problem.get();
3393  parameters.set<SystemBase *>("_sys") = &_displaced_problem->solverSys(nl_sys_num);
3394  _reinit_displaced_elem = true;
3395  }
3396  else
3397  {
3398  if (_displaced_problem == nullptr && parameters.get<bool>("use_displaced_mesh"))
3399  {
3400  // We allow DiracKernels to request that they use_displaced_mesh,
3401  // but then be overridden when no displacements variables are
3402  // provided in the Mesh block. If that happened, update the value
3403  // of use_displaced_mesh appropriately for this DiracKernel.
3404  if (parameters.have_parameter<bool>("use_displaced_mesh"))
3405  parameters.set<bool>("use_displaced_mesh") = false;
3406  }
3407 
3408  parameters.set<SubProblem *>("_subproblem") = this;
3409  parameters.set<SystemBase *>("_sys") = _nl[nl_sys_num].get();
3410  }
3411 
3412  logAdd("DiracKernel", name, kernel_name, parameters);
3413  _nl[nl_sys_num]->addDiracKernel(kernel_name, name, parameters);
3414 }
3415 
3416 // DGKernels ////
3417 
3418 void
3419 FEProblemBase::addDGKernel(const std::string & dg_kernel_name,
3420  const std::string & name,
3421  InputParameters & parameters)
3422 {
3423  parallel_object_only();
3424 
3425  const auto nl_sys_num = determineSolverSystem(parameters.varName("variable", name), true).second;
3426  if (!isSolverSystemNonlinear(nl_sys_num))
3427  mooseError("You are trying to add a DGKernel to a linear variable/system, which is not "
3428  "supported at the moment!");
3429 
3430  if (_displaced_problem && parameters.get<bool>("use_displaced_mesh"))
3431  {
3432  parameters.set<SubProblem *>("_subproblem") = _displaced_problem.get();
3433  parameters.set<SystemBase *>("_sys") = &_displaced_problem->solverSys(nl_sys_num);
3435  }
3436  else
3437  {
3438  if (_displaced_problem == nullptr && parameters.get<bool>("use_displaced_mesh"))
3439  {
3440  // We allow DGKernels to request that they use_displaced_mesh,
3441  // but then be overridden when no displacements variables are
3442  // provided in the Mesh block. If that happened, update the value
3443  // of use_displaced_mesh appropriately for this DGKernel.
3444  if (parameters.have_parameter<bool>("use_displaced_mesh"))
3445  parameters.set<bool>("use_displaced_mesh") = false;
3446  }
3447 
3448  parameters.set<SubProblem *>("_subproblem") = this;
3449  parameters.set<SystemBase *>("_sys") = _nl[nl_sys_num].get();
3450  }
3451 
3452  logAdd("DGKernel", name, dg_kernel_name, parameters);
3453  _nl[nl_sys_num]->addDGKernel(dg_kernel_name, name, parameters);
3454 
3456 }
3457 
3458 void
3459 FEProblemBase::addFVKernel(const std::string & fv_kernel_name,
3460  const std::string & name,
3461  InputParameters & parameters)
3462 {
3463  if (_displaced_problem && parameters.get<bool>("use_displaced_mesh"))
3464  // FVElementalKernels are computed in the historically finite element threaded loops. They rely
3465  // on Assembly data like _current_elem. When we call reinit on the FEProblemBase we will only
3466  // reinit the DisplacedProblem and its associated Assembly objects if we mark this boolean as
3467  // true
3468  _reinit_displaced_elem = true;
3469  addObject<FVKernel>(fv_kernel_name, name, parameters);
3470 }
3471 
3472 void
3473 FEProblemBase::addFVBC(const std::string & fv_bc_name,
3474  const std::string & name,
3475  InputParameters & parameters)
3476 {
3477  addObject<FVBoundaryCondition>(fv_bc_name, name, parameters);
3478 }
3479 
3480 void
3481 FEProblemBase::addFVInterfaceKernel(const std::string & fv_ik_name,
3482  const std::string & name,
3483  InputParameters & parameters)
3484 {
3487  addObject<FVInterfaceKernel>(
3488  fv_ik_name, name, parameters, /*threaded=*/true, /*variable_param_name=*/"variable1");
3489 }
3490 
3491 void
3492 FEProblemBase::addLinearFVKernel(const std::string & kernel_name,
3493  const std::string & name,
3494  InputParameters & parameters)
3495 {
3496  addObject<LinearFVKernel>(kernel_name, name, parameters);
3497 }
3498 
3499 void
3500 FEProblemBase::addLinearFVBC(const std::string & bc_name,
3501  const std::string & name,
3502  InputParameters & parameters)
3503 {
3504  addObject<LinearFVBoundaryCondition>(bc_name, name, parameters);
3505 }
3506 
3507 // InterfaceKernels ////
3508 
3509 void
3510 FEProblemBase::addInterfaceKernel(const std::string & interface_kernel_name,
3511  const std::string & name,
3512  InputParameters & parameters)
3513 {
3514  parallel_object_only();
3515 
3516  const auto nl_sys_num = determineSolverSystem(parameters.varName("variable", name), true).second;
3517  if (!isSolverSystemNonlinear(nl_sys_num))
3518  mooseError("You are trying to add a InterfaceKernel to a linear variable/system, which is not "
3519  "supported at the moment!");
3520 
3521  if (_displaced_problem && parameters.get<bool>("use_displaced_mesh"))
3522  {
3523  parameters.set<SubProblem *>("_subproblem") = _displaced_problem.get();
3524  parameters.set<SystemBase *>("_sys") = &_displaced_problem->solverSys(nl_sys_num);
3526  }
3527  else
3528  {
3529  if (_displaced_problem == nullptr && parameters.get<bool>("use_displaced_mesh"))
3530  {
3531  // We allow InterfaceKernels to request that they use_displaced_mesh,
3532  // but then be overridden when no displacements variables are
3533  // provided in the Mesh block. If that happened, update the value
3534  // of use_displaced_mesh appropriately for this InterfaceKernel.
3535  if (parameters.have_parameter<bool>("use_displaced_mesh"))
3536  parameters.set<bool>("use_displaced_mesh") = false;
3537  }
3538 
3539  parameters.set<SubProblem *>("_subproblem") = this;
3540  parameters.set<SystemBase *>("_sys") = _nl[nl_sys_num].get();
3541  }
3542 
3543  logAdd("InterfaceKernel", name, interface_kernel_name, parameters);
3544  _nl[nl_sys_num]->addInterfaceKernel(interface_kernel_name, name, parameters);
3545 
3547 }
3548 
3549 void
3550 FEProblemBase::checkICRestartError(const std::string & ic_name,
3551  const std::string & name,
3552  const VariableName & var_name)
3553 {
3555  {
3556  std::string restart_method = "";
3557  if (_app.isRestarting())
3558  restart_method =
3559  "a checkpoint restart, by IC object '" + ic_name + "' for variable '" + name + "'";
3560  else if (_app.getExReaderForRestart())
3561  {
3562  std::vector<std::string> restarted_vars = _app.getExReaderForRestart()->get_elem_var_names();
3563  const auto nodal_vars = _app.getExReaderForRestart()->get_nodal_var_names();
3564  const auto global_vars = _app.getExReaderForRestart()->get_global_var_names();
3565  restarted_vars.insert(restarted_vars.end(), nodal_vars.begin(), nodal_vars.end());
3566  restarted_vars.insert(restarted_vars.end(), global_vars.begin(), global_vars.end());
3567 
3568  if (std::find(restarted_vars.begin(), restarted_vars.end(), var_name) != restarted_vars.end())
3569  restart_method = "an Exodus restart, by IC object '" + ic_name + "' for variable '" + name +
3570  "' that is also being restarted";
3571  }
3572  if (!restart_method.empty())
3573  mooseError(
3574  "Initial conditions have been specified during ",
3575  restart_method,
3576  ".\nThis is only allowed if you specify 'allow_initial_conditions_with_restart' to "
3577  "the [Problem], as initial conditions can override restarted fields");
3578  }
3579 }
3580 
3581 void
3582 FEProblemBase::addInitialCondition(const std::string & ic_name,
3583  const std::string & name,
3584  InputParameters & parameters)
3585 {
3586  parallel_object_only();
3587 
3588  // before we start to mess with the initial condition, we need to check parameters for errors.
3590  const std::string & var_name = parameters.get<VariableName>("variable");
3591 
3592  // Forbid initial conditions on a restarted problem, as they would override the restart
3593  checkICRestartError(ic_name, name, var_name);
3594 
3595  parameters.set<SubProblem *>("_subproblem") = this;
3596 
3597  // field IC
3598  if (hasVariable(var_name))
3599  {
3600  for (THREAD_ID tid = 0; tid < libMesh::n_threads(); ++tid)
3601  {
3604  parameters.set<SystemBase *>("_sys") = &var.sys();
3605  std::shared_ptr<InitialConditionBase> ic;
3606  if (dynamic_cast<MooseVariable *>(&var))
3607  ic = _factory.create<InitialCondition>(ic_name, name, parameters, tid);
3608  else if (dynamic_cast<VectorMooseVariable *>(&var))
3609  ic = _factory.create<VectorInitialCondition>(ic_name, name, parameters, tid);
3610  else if (dynamic_cast<ArrayMooseVariable *>(&var))
3611  ic = _factory.create<ArrayInitialCondition>(ic_name, name, parameters, tid);
3612  else if (dynamic_cast<MooseVariableFVReal *>(&var))
3613  ic = _factory.create<InitialCondition>(ic_name, name, parameters, tid);
3614  else if (dynamic_cast<MooseLinearVariableFVReal *>(&var))
3615  ic = _factory.create<InitialCondition>(ic_name, name, parameters, tid);
3616  else
3617  mooseError("Your FE variable in initial condition ",
3618  name,
3619  " must be either of scalar or vector type");
3620  logAdd("IC", name, ic_name, parameters);
3621  _ics.addObject(ic, tid);
3622  }
3623  }
3624 
3625  // scalar IC
3626  else if (hasScalarVariable(var_name))
3627  {
3628  MooseVariableScalar & var = getScalarVariable(0, var_name);
3629  parameters.set<SystemBase *>("_sys") = &var.sys();
3630  std::shared_ptr<ScalarInitialCondition> ic =
3632  logAdd("ScalarIC", name, ic_name, parameters);
3633  _scalar_ics.addObject(ic);
3634  }
3635 
3636  else
3637  mooseError(
3638  "Variable '", var_name, "' requested in initial condition '", name, "' does not exist.");
3639 }
3640 
3641 void
3642 FEProblemBase::addFVInitialCondition(const std::string & ic_name,
3643  const std::string & name,
3644  InputParameters & parameters)
3645 {
3646  parallel_object_only();
3647 
3648  // before we start to mess with the initial condition, we need to check parameters for errors.
3650  const std::string & var_name = parameters.get<VariableName>("variable");
3651 
3652  // Forbid initial conditions on a restarted problem, as they would override the restart
3653  checkICRestartError(ic_name, name, var_name);
3654 
3655  parameters.set<SubProblem *>("_subproblem") = this;
3656 
3657  // field IC
3658  if (hasVariable(var_name))
3659  {
3660  for (THREAD_ID tid = 0; tid < libMesh::n_threads(); ++tid)
3661  {
3662  auto & var = getVariable(
3664  parameters.set<SystemBase *>("_sys") = &var.sys();
3665  std::shared_ptr<FVInitialConditionBase> ic;
3666  if (var.isFV())
3667  ic = _factory.create<FVInitialCondition>(ic_name, name, parameters, tid);
3668  else
3669  mooseError(
3670  "Your variable for an FVInitialCondition needs to be an a finite volume variable!");
3671  _fv_ics.addObject(ic, tid);
3672  }
3673  }
3674  else
3675  mooseError("Variable '",
3676  var_name,
3677  "' requested in finite volume initial condition '",
3678  name,
3679  "' does not exist.");
3680 }
3681 
3682 void
3684 {
3685  TIME_SECTION("projectSolution", 2, "Projecting Initial Solutions")
3686 
3687  FloatingPointExceptionGuard fpe_guard(_app);
3688 
3690  ComputeInitialConditionThread cic(*this);
3691  Threads::parallel_reduce(elem_range, cic);
3692 
3693  if (haveFV())
3694  {
3696  ElemInfoRange elem_info_range(_mesh.ownedElemInfoBegin(), _mesh.ownedElemInfoEnd());
3697 
3698  ComputeFVInitialConditionThread cfvic(*this);
3699  Threads::parallel_reduce(elem_info_range, cfvic);
3700  }
3701 
3702  // Need to close the solution vector here so that boundary ICs take precendence
3703  for (auto & nl : _nl)
3704  nl->solution().close();
3705  _aux->solution().close();
3706 
3707  // now run boundary-restricted initial conditions
3708  ConstBndNodeRange & bnd_nodes = *_mesh.getBoundaryNodeRange();
3710  Threads::parallel_reduce(bnd_nodes, cbic);
3711 
3712  for (auto & nl : _nl)
3713  nl->solution().close();
3714  _aux->solution().close();
3715 
3716  // Also, load values into the SCALAR dofs
3717  // Note: We assume that all SCALAR dofs are on the
3718  // processor with highest ID
3719  if (processor_id() == (n_processors() - 1) && _scalar_ics.hasActiveObjects())
3720  {
3721  const auto & ics = _scalar_ics.getActiveObjects();
3722  for (const auto & ic : ics)
3723  {
3724  MooseVariableScalar & var = ic->variable();
3725  var.reinit();
3726 
3727  DenseVector<Number> vals(var.order());
3728  ic->compute(vals);
3729 
3730  const unsigned int n_scalar_dofs = var.dofIndices().size();
3731  for (unsigned int i = 0; i < n_scalar_dofs; i++)
3732  {
3733  const auto global_index = var.dofIndices()[i];
3734  var.sys().solution().set(global_index, vals(i));
3735  var.setValue(i, vals(i));
3736  }
3737  }
3738  }
3739 
3740  for (auto & sys : _solver_systems)
3741  {
3742  sys->solution().close();
3743  sys->solution().localize(*sys->system().current_local_solution, sys->dofMap().get_send_list());
3744  }
3745 
3746  _aux->solution().close();
3747  _aux->solution().localize(*_aux->sys().current_local_solution, _aux->dofMap().get_send_list());
3748 }
3749 
3750 void
3752  ConstElemRange & elem_range,
3753  ConstBndNodeRange & bnd_nodes,
3754  const std::optional<std::set<VariableName>> & target_vars)
3755 {
3756  if (target_vars)
3757  {
3758  ComputeInitialConditionThread cic(*this, &(*target_vars));
3759  Threads::parallel_reduce(elem_range, cic);
3760  }
3761  else
3762  {
3763  ComputeInitialConditionThread cic(*this);
3764  Threads::parallel_reduce(elem_range, cic);
3765  }
3766 
3767  // Need to close the solution vector here so that boundary ICs take precendence
3768  for (auto & nl : _nl)
3769  nl->solution().close();
3770  _aux->solution().close();
3771 
3772  if (target_vars)
3773  {
3774  ComputeBoundaryInitialConditionThread cbic(*this, &(*target_vars));
3775  Threads::parallel_reduce(bnd_nodes, cbic);
3776  }
3777  else
3778  {
3780  Threads::parallel_reduce(bnd_nodes, cbic);
3781  }
3782 
3783  for (auto & nl : _nl)
3784  nl->solution().close();
3785  _aux->solution().close();
3786 
3787  // Also, load values into the SCALAR dofs
3788  // Note: We assume that all SCALAR dofs are on the
3789  // processor with highest ID
3790  if (processor_id() == (n_processors() - 1) && _scalar_ics.hasActiveObjects())
3791  {
3792  const auto & ics = _scalar_ics.getActiveObjects();
3793  for (const auto & ic : ics)
3794  {
3795  MooseVariableScalar & var = ic->variable();
3796 
3797  if (target_vars && !target_vars->count(var.name()))
3798  continue;
3799 
3800  var.reinit();
3801 
3802  DenseVector<Number> vals(var.order());
3803  ic->compute(vals);
3804 
3805  const unsigned int n_scalar_dofs = var.dofIndices().size();
3806  for (unsigned int i = 0; i < n_scalar_dofs; i++)
3807  {
3808  const auto global_index = var.dofIndices()[i];
3809  var.sys().solution().set(global_index, vals(i));
3810  var.setValue(i, vals(i));
3811  }
3812  }
3813  }
3814 
3815  for (auto & nl : _nl)
3816  {
3817  nl->solution().close();
3818  nl->solution().localize(*nl->system().current_local_solution, nl->dofMap().get_send_list());
3819  }
3820 
3821  _aux->solution().close();
3822  _aux->solution().localize(*_aux->sys().current_local_solution, _aux->dofMap().get_send_list());
3823 }
3824 
3825 void
3827  Number (*func)(const Point &,
3828  const libMesh::Parameters &,
3829  const std::string &,
3830  const std::string &),
3831  Gradient (*func_grad)(const Point &,
3832  const libMesh::Parameters &,
3833  const std::string &,
3834  const std::string &),
3835  const libMesh::Parameters & params,
3836  const VariableName & target_var)
3837 {
3838  mooseAssert(!Threads::in_threads,
3839  "We're performing a projection based on data from just the thread 0 variable, so any "
3840  "modifications to the variable solution must have been thread joined already");
3841 
3842  const auto & var = getStandardVariable(0, target_var);
3843  const auto var_num = var.number();
3844  const auto sn = systemNumForVariable(target_var);
3845  auto & sys = getSystemBase(sn);
3846 
3847  // Let libmesh handle the projection
3848  System & libmesh_sys = getSystem(target_var);
3849  auto temp_vec = libmesh_sys.current_local_solution->zero_clone();
3850  libmesh_sys.project_vector(func, func_grad, params, *temp_vec);
3851  temp_vec->close();
3852 
3853  // Get the dof indices to copy
3854  DofMap & dof_map = sys.dofMap();
3855  std::set<dof_id_type> dof_indices;
3856  std::vector<dof_id_type> elem_dof_indices;
3857 
3858  for (const auto & elem : elem_range)
3859  {
3860  dof_map.dof_indices(elem, elem_dof_indices, var_num);
3861  dof_indices.insert(elem_dof_indices.begin(), elem_dof_indices.end());
3862  }
3863  std::vector<dof_id_type> dof_indices_v(dof_indices.begin(), dof_indices.end());
3864 
3865  // Copy the projected values into the solution vector
3866  std::vector<Real> dof_vals;
3867  temp_vec->get(dof_indices_v, dof_vals);
3868  mooseAssert(sys.solution().closed(),
3869  "The solution should be closed before mapping our projection");
3870  sys.solution().insert(dof_vals, dof_indices_v);
3871  sys.solution().close();
3872  sys.solution().localize(*libmesh_sys.current_local_solution, sys.dofMap().get_send_list());
3873 }
3874 
3875 std::shared_ptr<MaterialBase>
3878  const THREAD_ID tid,
3879  bool no_warn)
3880 {
3881  switch (type)
3882  {
3884  name += "_neighbor";
3885  break;
3887  name += "_face";
3888  break;
3889  default:
3890  break;
3891  }
3892 
3893  std::shared_ptr<MaterialBase> material = _all_materials[type].getActiveObject(name, tid);
3894  if (!no_warn && material->getParam<bool>("compute") && type == Moose::BLOCK_MATERIAL_DATA)
3895  mooseWarning("You are retrieving a Material object (",
3896  material->name(),
3897  "), but its compute flag is set to true. This indicates that MOOSE is "
3898  "computing this property which may not be desired and produce un-expected "
3899  "results.");
3900 
3901  return material;
3902 }
3903 
3904 MaterialData &
3906  const THREAD_ID tid,
3907  const MooseObject * object) const
3908 {
3909  switch (type)
3910  {
3912  if (object)
3913  _material_props.addConsumer(type, object);
3914  return _material_props.getMaterialData(tid);
3916  if (object)
3922  if (object)
3925  }
3926 
3927  mooseError("FEProblemBase::getMaterialData(): Invalid MaterialDataType ", type);
3928 }
3929 
3930 const std::set<const MooseObject *> &
3932 {
3933  switch (type)
3934  {
3943  }
3944 
3945  mooseError("FEProblemBase::getMaterialPropertyStorageConsumers(): Invalid MaterialDataType ",
3946  type);
3947 }
3948 
3949 void
3951 {
3952  if (_ignore_zeros_in_jacobian && preserve)
3953  paramWarning(
3954  "ignore_zeros_in_jacobian",
3955  "We likely cannot preserve the sparsity pattern if ignoring zeros in the Jacobian, which "
3956  "leads to removing those entries from the Jacobian sparsity pattern");
3958 }
3959 
3960 bool
3962 {
3963  return allowInvalidSolution() || // invalid solutions are always allowed
3964  !_app.solutionInvalidity().hasInvalidSolutionError(); // if not allowed, check for errors
3965 }
3966 
3967 void
3968 FEProblemBase::addFunctorMaterial(const std::string & functor_material_name,
3969  const std::string & name,
3970  InputParameters & parameters)
3971 {
3972  parallel_object_only();
3973 
3974  auto add_functor_materials = [&](const auto & parameters, const auto & name)
3975  {
3976  for (THREAD_ID tid = 0; tid < libMesh::n_threads(); tid++)
3977  {
3978  // Create the general Block/Boundary MaterialBase object
3979  std::shared_ptr<MaterialBase> material =
3980  _factory.create<MaterialBase>(functor_material_name, name, parameters, tid);
3981  logAdd("FunctorMaterial", name, functor_material_name, parameters);
3982  _all_materials.addObject(material, tid);
3983  _materials.addObject(material, tid);
3984  }
3985  };
3986 
3987  parameters.set<SubProblem *>("_subproblem") = this;
3988  add_functor_materials(parameters, name);
3989  if (_displaced_problem)
3990  {
3991  auto disp_params = parameters;
3992  disp_params.set<SubProblem *>("_subproblem") = _displaced_problem.get();
3993  add_functor_materials(disp_params, name + "_displaced");
3994  }
3995 }
3996 
3997 void
3998 FEProblemBase::addMaterial(const std::string & mat_name,
3999  const std::string & name,
4000  InputParameters & parameters)
4001 {
4002  addMaterialHelper({&_materials}, mat_name, name, parameters);
4003 }
4004 
4005 void
4006 FEProblemBase::addInterfaceMaterial(const std::string & mat_name,
4007  const std::string & name,
4008  InputParameters & parameters)
4009 {
4011 }
4012 
4013 void
4014 FEProblemBase::addMaterialHelper(std::vector<MaterialWarehouse *> warehouses,
4015  const std::string & mat_name,
4016  const std::string & name,
4017  InputParameters & parameters)
4018 {
4019  parallel_object_only();
4020 
4021  if (_displaced_problem && parameters.get<bool>("use_displaced_mesh"))
4022  {
4023  parameters.set<SubProblem *>("_subproblem") = _displaced_problem.get();
4025  }
4026  else
4027  {
4028  if (_displaced_problem == nullptr && parameters.get<bool>("use_displaced_mesh"))
4029  {
4030  // We allow Materials to request that they use_displaced_mesh,
4031  // but then be overridden when no displacements variables are
4032  // provided in the Mesh block. If that happened, update the value
4033  // of use_displaced_mesh appropriately for this Material.
4034  if (parameters.have_parameter<bool>("use_displaced_mesh"))
4035  parameters.set<bool>("use_displaced_mesh") = false;
4036  }
4037 
4038  parameters.set<SubProblem *>("_subproblem") = this;
4039  }
4040 
4041  for (THREAD_ID tid = 0; tid < libMesh::n_threads(); tid++)
4042  {
4043  // Create the general Block/Boundary MaterialBase object
4044  std::shared_ptr<MaterialBase> material =
4045  _factory.create<MaterialBase>(mat_name, name, parameters, tid);
4046  logAdd("Material", name, mat_name, parameters);
4047  bool discrete = !material->getParam<bool>("compute");
4048 
4049  // If the object is boundary restricted or if it is a functor material we do not create the
4050  // neighbor and face objects
4051  if (material->boundaryRestricted() || dynamic_cast<FunctorMaterial *>(material.get()))
4052  {
4053  _all_materials.addObject(material, tid);
4054  if (discrete)
4055  _discrete_materials.addObject(material, tid);
4056  else
4057  for (auto && warehouse : warehouses)
4058  warehouse->addObject(material, tid);
4059  }
4060 
4061  // Non-boundary restricted require face and neighbor objects
4062  else
4063  {
4064  // TODO: we only need to do this if we have needs for face materials (e.g.
4065  // FV, DG, etc.) - but currently we always do it. Figure out how to fix
4066  // this.
4067 
4068  // The name of the object being created, this is changed multiple times as objects are
4069  // created below
4070  std::string object_name;
4071 
4072  // Create a copy of the supplied parameters to the setting for "_material_data_type" isn't
4073  // used from a previous tid loop
4074  InputParameters current_parameters = parameters;
4075 
4076  // face material
4077  current_parameters.set<Moose::MaterialDataType>("_material_data_type") =
4079  object_name = name + "_face";
4080  std::shared_ptr<MaterialBase> face_material =
4081  _factory.create<MaterialBase>(mat_name, object_name, current_parameters, tid);
4082 
4083  // neighbor material
4084  current_parameters.set<Moose::MaterialDataType>("_material_data_type") =
4086  current_parameters.set<bool>("_neighbor") = true;
4087  object_name = name + "_neighbor";
4088  std::shared_ptr<MaterialBase> neighbor_material =
4089  _factory.create<MaterialBase>(mat_name, object_name, current_parameters, tid);
4090 
4091  // Store the material objects
4092  _all_materials.addObjects(material, neighbor_material, face_material, tid);
4093 
4094  if (discrete)
4095  _discrete_materials.addObjects(material, neighbor_material, face_material, tid);
4096  else
4097  for (auto && warehouse : warehouses)
4098  warehouse->addObjects(material, neighbor_material, face_material, tid);
4099 
4100  // Names of all controllable parameters for this Material object
4101  const std::string & base = parameters.getBase();
4102  MooseObjectParameterName name(MooseObjectName(base, material->name()), "*");
4103  const auto param_names =
4105 
4106  // Connect parameters of the primary Material object to those on the face and neighbor
4107  // objects
4108  for (const auto & p_name : param_names)
4109  {
4110  MooseObjectParameterName primary_name(MooseObjectName(base, material->name()),
4111  p_name.parameter());
4112  MooseObjectParameterName face_name(MooseObjectName(base, face_material->name()),
4113  p_name.parameter());
4114  MooseObjectParameterName neighbor_name(MooseObjectName(base, neighbor_material->name()),
4115  p_name.parameter());
4117  primary_name, face_name, false);
4119  primary_name, neighbor_name, false);
4120  }
4121  }
4122  }
4123 }
4124 
4125 void
4126 FEProblemBase::prepareMaterials(const std::unordered_set<unsigned int> & consumer_needed_mat_props,
4127  const SubdomainID blk_id,
4128  const THREAD_ID tid)
4129 {
4130  std::set<MooseVariableFEBase *> needed_moose_vars;
4131  std::unordered_set<unsigned int> needed_mat_props;
4132 
4133  if (_all_materials.hasActiveBlockObjects(blk_id, tid))
4134  {
4135  _all_materials.updateVariableDependency(needed_moose_vars, tid);
4136  _all_materials.updateBlockMatPropDependency(blk_id, needed_mat_props, tid);
4137  }
4138 
4139  const auto & ids = _mesh.getSubdomainBoundaryIds(blk_id);
4140  for (const auto id : ids)
4141  {
4142  _materials.updateBoundaryVariableDependency(id, needed_moose_vars, tid);
4143  _materials.updateBoundaryMatPropDependency(id, needed_mat_props, tid);
4144  }
4145 
4146  const auto & current_active_elemental_moose_variables = getActiveElementalMooseVariables(tid);
4147  needed_moose_vars.insert(current_active_elemental_moose_variables.begin(),
4148  current_active_elemental_moose_variables.end());
4149 
4150  needed_mat_props.insert(consumer_needed_mat_props.begin(), consumer_needed_mat_props.end());
4151 
4152  setActiveElementalMooseVariables(needed_moose_vars, tid);
4153  setActiveMaterialProperties(needed_mat_props, tid);
4154 }
4155 
4156 void
4157 FEProblemBase::reinitMaterials(SubdomainID blk_id, const THREAD_ID tid, bool swap_stateful)
4158 {
4159  if (hasActiveMaterialProperties(tid))
4160  {
4161  auto && elem = _assembly[tid][0]->elem();
4162  unsigned int n_points = _assembly[tid][0]->qRule()->n_points();
4163 
4164  auto & material_data = _material_props.getMaterialData(tid);
4165  material_data.resize(n_points);
4166 
4167  // Only swap if requested
4168  if (swap_stateful)
4169  material_data.swap(*elem);
4170 
4171  if (_discrete_materials.hasActiveBlockObjects(blk_id, tid))
4172  material_data.reset(_discrete_materials.getActiveBlockObjects(blk_id, tid));
4173 
4174  if (_materials.hasActiveBlockObjects(blk_id, tid))
4175  material_data.reinit(_materials.getActiveBlockObjects(blk_id, tid));
4176  }
4177 }
4178 
4179 void
4181  const THREAD_ID tid,
4182  const bool swap_stateful,
4183  const std::deque<MaterialBase *> * const reinit_mats)
4184 {
4185  // we reinit more often than needed here because we dont have a way to check whether
4186  // we need to compute the face materials on a particular (possibly external) face
4187  if (hasActiveMaterialProperties(tid))
4188  {
4189  auto && elem = _assembly[tid][0]->elem();
4190  unsigned int side = _assembly[tid][0]->side();
4191  unsigned int n_points = _assembly[tid][0]->qRuleFace()->n_points();
4192 
4193  auto & bnd_material_data = _bnd_material_props.getMaterialData(tid);
4194  bnd_material_data.resize(n_points);
4195 
4196  if (swap_stateful && !bnd_material_data.isSwapped())
4197  bnd_material_data.swap(*elem, side);
4198 
4199  if (_discrete_materials[Moose::FACE_MATERIAL_DATA].hasActiveBlockObjects(blk_id, tid))
4200  bnd_material_data.reset(
4201  _discrete_materials[Moose::FACE_MATERIAL_DATA].getActiveBlockObjects(blk_id, tid));
4202 
4203  if (reinit_mats)
4204  bnd_material_data.reinit(*reinit_mats);
4205  else if (_materials[Moose::FACE_MATERIAL_DATA].hasActiveBlockObjects(blk_id, tid))
4206  bnd_material_data.reinit(
4207  _materials[Moose::FACE_MATERIAL_DATA].getActiveBlockObjects(blk_id, tid));
4208  }
4209 }
4210 
4211 void
4213  const SubdomainID blk_id,
4214  const THREAD_ID tid,
4215  const bool swap_stateful,
4216  const std::deque<MaterialBase *> * const reinit_mats)
4217 {
4218  if (hasActiveMaterialProperties(tid) && (needBoundaryMaterialOnSide(boundary_id, tid) ||
4219  needInterfaceMaterialOnSide(boundary_id, tid) ||
4220  needInternalNeighborSideMaterial(blk_id, tid)))
4221  {
4222  const auto * const elem = _assembly[tid][0]->elem();
4223  unsigned int side = _assembly[tid][0]->side();
4224  unsigned int n_points = _assembly[tid][0]->qRuleFace()->n_points();
4225 
4226  auto & bnd_material_data = _bnd_material_props.getMaterialData(tid);
4227  bnd_material_data.resize(n_points);
4228 
4229  if (swap_stateful && !bnd_material_data.isSwapped())
4230  bnd_material_data.swap(*elem, side);
4231 
4232  if (_discrete_materials[Moose::FACE_MATERIAL_DATA].hasActiveBlockObjects(blk_id, tid))
4233  bnd_material_data.reset(
4234  _discrete_materials[Moose::FACE_MATERIAL_DATA].getActiveBlockObjects(blk_id, tid));
4235 
4236  if (reinit_mats)
4237  bnd_material_data.reinit(*reinit_mats);
4238  else if (_materials[Moose::FACE_MATERIAL_DATA].hasActiveBlockObjects(blk_id, tid))
4239  bnd_material_data.reinit(
4240  _materials[Moose::FACE_MATERIAL_DATA].getActiveBlockObjects(blk_id, tid));
4241  }
4242 }
4243 
4244 void
4246  const BoundaryID boundary_id,
4247  const SubdomainID blk_id,
4248  const THREAD_ID tid,
4249  const bool swap_stateful,
4250  const std::deque<MaterialBase *> * const reinit_mats)
4251 {
4252  // Since objects don't declare whether they need the face or neighbor (side) material properties,
4253  // we use the same criteria for skipping material property computations as for face material
4254  // properties This could be a future optimization.
4255  if (hasActiveMaterialProperties(tid) && (needBoundaryMaterialOnSide(boundary_id, tid) ||
4256  needInterfaceMaterialOnSide(boundary_id, tid) ||
4257  needInternalNeighborSideMaterial(blk_id, tid)))
4258  reinitMaterialsNeighbor(blk_id, tid, swap_stateful, reinit_mats);
4259 }
4260 
4261 void
4263  const THREAD_ID tid,
4264  const bool swap_stateful,
4265  const std::deque<MaterialBase *> * const reinit_mats)
4266 {
4267  if (hasActiveMaterialProperties(tid))
4268  {
4269  // NOTE: this will not work with h-adaptivity
4270  // lindsayad: why not?
4271 
4272  const Elem * neighbor = _assembly[tid][0]->neighbor();
4273  unsigned int neighbor_side = neighbor->which_neighbor_am_i(_assembly[tid][0]->elem());
4274 
4275  mooseAssert(neighbor, "neighbor should be non-null");
4276  mooseAssert(blk_id == neighbor->subdomain_id(),
4277  "The provided blk_id " << blk_id << " and neighbor subdomain ID "
4278  << neighbor->subdomain_id() << " do not match.");
4279 
4280  unsigned int n_points = _assembly[tid][0]->qRuleNeighbor()->n_points();
4281 
4282  auto & neighbor_material_data = _neighbor_material_props.getMaterialData(tid);
4283  neighbor_material_data.resize(n_points);
4284 
4285  // Only swap if requested
4286  if (swap_stateful)
4287  neighbor_material_data.swap(*neighbor, neighbor_side);
4288 
4289  if (_discrete_materials[Moose::NEIGHBOR_MATERIAL_DATA].hasActiveBlockObjects(blk_id, tid))
4290  neighbor_material_data.reset(
4291  _discrete_materials[Moose::NEIGHBOR_MATERIAL_DATA].getActiveBlockObjects(blk_id, tid));
4292 
4293  if (reinit_mats)
4294  neighbor_material_data.reinit(*reinit_mats);
4295  else if (_materials[Moose::NEIGHBOR_MATERIAL_DATA].hasActiveBlockObjects(blk_id, tid))
4296  neighbor_material_data.reinit(
4297  _materials[Moose::NEIGHBOR_MATERIAL_DATA].getActiveBlockObjects(blk_id, tid));
4298  }
4299 }
4300 
4301 void
4303  const THREAD_ID tid,
4304  const bool swap_stateful,
4305  const std::deque<MaterialBase *> * const reinit_mats)
4306 {
4307  if (hasActiveMaterialProperties(tid) && needBoundaryMaterialOnSide(boundary_id, tid))
4308  {
4309  auto && elem = _assembly[tid][0]->elem();
4310  unsigned int side = _assembly[tid][0]->side();
4311  unsigned int n_points = _assembly[tid][0]->qRuleFace()->n_points();
4312 
4313  auto & bnd_material_data = _bnd_material_props.getMaterialData(tid);
4314  bnd_material_data.resize(n_points);
4315 
4316  if (swap_stateful && !bnd_material_data.isSwapped())
4317  bnd_material_data.swap(*elem, side);
4318 
4319  if (_discrete_materials.hasActiveBoundaryObjects(boundary_id, tid))
4320  bnd_material_data.reset(_discrete_materials.getActiveBoundaryObjects(boundary_id, tid));
4321 
4322  if (reinit_mats)
4323  bnd_material_data.reinit(*reinit_mats);
4324  else if (_materials.hasActiveBoundaryObjects(boundary_id, tid))
4325  bnd_material_data.reinit(_materials.getActiveBoundaryObjects(boundary_id, tid));
4326  }
4327 }
4328 
4329 void
4331  const THREAD_ID tid,
4332  bool swap_stateful)
4333 {
4334  if (hasActiveMaterialProperties(tid) && needInterfaceMaterialOnSide(boundary_id, tid))
4335  {
4336  const Elem * const & elem = _assembly[tid][0]->elem();
4337  unsigned int side = _assembly[tid][0]->side();
4338  unsigned int n_points = _assembly[tid][0]->qRuleFace()->n_points();
4339 
4340  auto & bnd_material_data = _bnd_material_props.getMaterialData(tid);
4341  bnd_material_data.resize(n_points);
4342 
4343  if (swap_stateful && !bnd_material_data.isSwapped())
4344  bnd_material_data.swap(*elem, side);
4345 
4346  if (_interface_materials.hasActiveBoundaryObjects(boundary_id, tid))
4347  bnd_material_data.reinit(_interface_materials.getActiveBoundaryObjects(boundary_id, tid));
4348  }
4349 }
4350 
4351 void
4353 {
4354  auto && elem = _assembly[tid][0]->elem();
4356 }
4357 
4358 void
4360 {
4361  auto && elem = _assembly[tid][0]->elem();
4362  unsigned int side = _assembly[tid][0]->side();
4363  _bnd_material_props.getMaterialData(tid).swapBack(*elem, side);
4364 }
4365 
4366 void
4368 {
4369  // NOTE: this will not work with h-adaptivity
4370  const Elem * neighbor = _assembly[tid][0]->neighbor();
4371  unsigned int neighbor_side =
4372  neighbor ? neighbor->which_neighbor_am_i(_assembly[tid][0]->elem()) : libMesh::invalid_uint;
4373 
4374  if (!neighbor)
4375  {
4376  if (haveFV())
4377  {
4378  // If neighbor is null, then we're on the neighbor side of a mesh boundary, e.g. we're off
4379  // the mesh in ghost-land. If we're using the finite volume method, then variable values and
4380  // consequently material properties have well-defined values in this ghost region outside of
4381  // the mesh and we really do want to reinit our neighbor materials in this case. Since we're
4382  // off in ghost land it's safe to do swaps with `MaterialPropertyStorage` using the elem and
4383  // elem_side keys
4384  neighbor = _assembly[tid][0]->elem();
4385  neighbor_side = _assembly[tid][0]->side();
4386  mooseAssert(neighbor, "We should have an appropriate value for elem coming from Assembly");
4387  }
4388  else
4389  mooseError("neighbor is null in Assembly!");
4390  }
4391 
4392  _neighbor_material_props.getMaterialData(tid).swapBack(*neighbor, neighbor_side);
4393 }
4394 
4395 void
4396 FEProblemBase::logAdd(const std::string & system,
4397  const std::string & name,
4398  const std::string & type,
4399  const InputParameters & params) const
4400 {
4401  if (_verbose_setup != "false")
4402  _console << "[DBG] Adding " << system << " '" << name << "' of type " << type << std::endl;
4403  if (_verbose_setup == "extra")
4404  _console << params << std::endl;
4405 }
4406 
4407 void
4409  const std::string & object_name,
4410  const std::string & var_param_name)
4411 {
4412  // Due to objects like SolutionUserObject which manipulate libmesh objects
4413  // and variables directly at the back end, we need a default option here
4414  // which is going to be the pointer to the first solver system within this
4415  // problem
4416  unsigned int sys_num = 0;
4417  if (parameters.isParamValid(var_param_name))
4418  {
4419  const auto variable_name = parameters.varName(var_param_name, object_name);
4420  if (this->hasVariable(variable_name) || this->hasScalarVariable(variable_name))
4421  sys_num = getSystem(variable_name).number();
4422  }
4423  if (parameters.isParamValid("solver_sys"))
4424  {
4425  const auto var_sys_num = sys_num;
4426  sys_num = getSystemBase(parameters.get<SolverSystemName>("solver_sys")).number();
4427  if (sys_num != var_sys_num && parameters.isParamValid(var_param_name))
4428  mooseError("We dont support setting 'variable' to a variable that is not set to the same "
4429  "system as the 'solver_sys' parameter");
4430  }
4431 
4432  if (_displaced_problem && parameters.have_parameter<bool>("use_displaced_mesh") &&
4433  parameters.get<bool>("use_displaced_mesh"))
4434  {
4435  parameters.set<SubProblem *>("_subproblem") = _displaced_problem.get();
4436  if (sys_num == _aux->number())
4437  parameters.set<SystemBase *>("_sys") = &_displaced_problem->systemBaseAuxiliary();
4438  else
4439  parameters.set<SystemBase *>("_sys") = &_displaced_problem->solverSys(sys_num);
4440  }
4441  else
4442  {
4443  // The object requested use_displaced_mesh, but it was overridden
4444  // due to there being no displacements variables in the [Mesh] block.
4445  // If that happened, update the value of use_displaced_mesh appropriately.
4446  if (!_displaced_problem && parameters.have_parameter<bool>("use_displaced_mesh") &&
4447  parameters.get<bool>("use_displaced_mesh"))
4448  parameters.set<bool>("use_displaced_mesh") = false;
4449 
4450  parameters.set<SubProblem *>("_subproblem") = this;
4451 
4452  if (sys_num == _aux->number())
4453  parameters.set<SystemBase *>("_sys") = _aux.get();
4454  else
4455  parameters.set<SystemBase *>("_sys") = _solver_systems[sys_num].get();
4456  }
4457 }
4458 
4459 void
4460 FEProblemBase::addPostprocessor(const std::string & pp_name,
4461  const std::string & name,
4462  InputParameters & parameters)
4463 {
4464  // Check for name collision
4465  if (hasUserObject(name))
4466  mooseError("A ",
4468  " already exists. You may not add a Postprocessor by the same name.");
4469 
4470  addUserObject(pp_name, name, parameters);
4471 }
4472 
4473 void
4474 FEProblemBase::addVectorPostprocessor(const std::string & pp_name,
4475  const std::string & name,
4476  InputParameters & parameters)
4477 {
4478  // Check for name collision
4479  if (hasUserObject(name))
4480  mooseError("A ",
4482  " already exists. You may not add a VectorPostprocessor by the same name.");
4483 
4484  addUserObject(pp_name, name, parameters);
4485 }
4486 
4487 void
4488 FEProblemBase::addReporter(const std::string & type,
4489  const std::string & name,
4490  InputParameters & parameters)
4491 {
4492  // Check for name collision
4493  if (hasUserObject(name))
4494  mooseError("A ",
4496  " already exists. You may not add a Reporter by the same name.");
4497 
4499 }
4500 
4501 std::vector<std::shared_ptr<UserObject>>
4502 FEProblemBase::addUserObject(const std::string & user_object_name,
4503  const std::string & name,
4504  InputParameters & parameters)
4505 {
4506  parallel_object_only();
4507 
4508  std::vector<std::shared_ptr<UserObject>> uos;
4509 
4510  // Add the _subproblem and _sys parameters depending on use_displaced_mesh
4512 
4513  for (const auto tid : make_range(libMesh::n_threads()))
4514  {
4515  // Create the UserObject
4516  std::shared_ptr<UserObject> user_object =
4517  _factory.create<UserObject>(user_object_name, name, parameters, tid);
4518  logAdd("UserObject", name, user_object_name, parameters);
4519  uos.push_back(user_object);
4520 
4521  if (tid != 0)
4522  user_object->setPrimaryThreadCopy(uos[0].get());
4523 
4524  // TODO: delete this line after apps have been updated to not call getUserObjects
4525  _all_user_objects.addObject(user_object, tid);
4526 
4527  theWarehouse().add(user_object);
4528 
4529  // Attempt to create all the possible UserObject types
4530  auto euo = std::dynamic_pointer_cast<ElementUserObject>(user_object);
4531  auto suo = std::dynamic_pointer_cast<SideUserObject>(user_object);
4532  auto isuo = std::dynamic_pointer_cast<InternalSideUserObject>(user_object);
4533  auto iuo = std::dynamic_pointer_cast<InterfaceUserObjectBase>(user_object);
4534  auto nuo = std::dynamic_pointer_cast<NodalUserObject>(user_object);
4535  auto duo = std::dynamic_pointer_cast<DomainUserObject>(user_object);
4536  auto guo = std::dynamic_pointer_cast<GeneralUserObject>(user_object);
4537  auto tguo = std::dynamic_pointer_cast<ThreadedGeneralUserObject>(user_object);
4538  auto muo = std::dynamic_pointer_cast<MortarUserObject>(user_object);
4539 
4540  // Account for displaced mesh use
4541  if (_displaced_problem && parameters.get<bool>("use_displaced_mesh"))
4542  {
4543  // Whether to re-init or not depends on the attributes of the base classes.
4544  // For example, InterfaceUOBase has "_current_side_elem" and "_neighbor_elem"
4545  // so it needs to reinit on displaced neighbors and faces
4546  // _reinit_displaced_elem -> _current_elem will be reinited
4547  // _reinit_displaced_face -> _current_elem, lowerD if any and _current_side_elem to be
4548  // reinited _reinit_displaced_neighbor -> _current_elem, lowerD if any and _current_neighbor
4549  // to be reinited Note that as soon as you use materials on the displaced mesh, all three get
4550  // turned on.
4551  if (euo || nuo || duo)
4552  _reinit_displaced_elem = true;
4553  if (suo || duo || isuo || iuo)
4554  _reinit_displaced_face = true;
4555  if (iuo || duo || isuo)
4557  }
4558 
4559  // These objects only require one thread
4560  if ((guo && !tguo) || muo)
4561  break;
4562  }
4563 
4564  // Add as a Functor if it is one. We usually need to add the user object from thread 0 as the
4565  // registered functor for all threads because when user objects are thread joined, generally only
4566  // the primary thread copy ends up with all the data
4567  for (const auto tid : make_range(libMesh::n_threads()))
4568  {
4569  const decltype(uos)::size_type uo_index = uos.front()->needThreadedCopy() ? tid : 0;
4570  if (const auto functor = dynamic_cast<Moose::FunctorBase<Real> *>(uos[uo_index].get()))
4571  {
4572  this->addFunctor(name, *functor, tid);
4573  if (_displaced_problem)
4574  _displaced_problem->addFunctor(name, *functor, tid);
4575  }
4576  }
4577 
4578  return uos;
4579 }
4580 
4581 const UserObject &
4582 FEProblemBase::getUserObjectBase(const std::string & name, const THREAD_ID tid /* = 0 */) const
4583 {
4584  std::vector<UserObject *> objs;
4585  theWarehouse()
4586  .query()
4587  .condition<AttribSystem>("UserObject")
4588  .condition<AttribThread>(tid)
4589  .condition<AttribName>(name)
4590  .queryInto(objs);
4591  if (objs.empty())
4592  mooseError("Unable to find user object with name '" + name + "'");
4593  mooseAssert(objs.size() == 1, "Should only find one UO");
4594  return *(objs[0]);
4595 }
4596 
4597 const Positions &
4598 FEProblemBase::getPositionsObject(const std::string & name) const
4599 {
4600  std::vector<Positions *> objs;
4601  theWarehouse()
4602  .query()
4603  .condition<AttribSystem>("UserObject")
4604  .condition<AttribName>(name)
4605  .queryInto(objs);
4606  if (objs.empty())
4607  mooseError("Unable to find Positions object with name '" + name + "'");
4608  mooseAssert(objs.size() == 1, "Should only find one Positions");
4609  return *(objs[0]);
4610 }
4611 
4612 bool
4613 FEProblemBase::hasUserObject(const std::string & name) const
4614 {
4615  std::vector<UserObject *> objs;
4616  theWarehouse()
4617  .query()
4618  .condition<AttribSystem>("UserObject")
4619  .condition<AttribThread>(0)
4620  .condition<AttribName>(name)
4621  .queryInto(objs);
4622  return !objs.empty();
4623 }
4624 
4625 bool
4626 FEProblemBase::hasPostprocessorValueByName(const PostprocessorName & name) const
4627 {
4629 }
4630 
4631 const PostprocessorValue &
4632 FEProblemBase::getPostprocessorValueByName(const PostprocessorName & name,
4633  std::size_t t_index) const
4634 {
4636  t_index);
4637 }
4638 
4639 void
4640 FEProblemBase::setPostprocessorValueByName(const PostprocessorName & name,
4641  const PostprocessorValue & value,
4642  std::size_t t_index)
4643 {
4645  PostprocessorReporterName(name), value, t_index);
4646 }
4647 
4648 bool
4649 FEProblemBase::hasPostprocessor(const std::string & name) const
4650 {
4651  mooseDeprecated("FEProblemBase::hasPostprocssor is being removed; use "
4652  "hasPostprocessorValueByName instead.");
4654 }
4655 
4658  const std::string & vector_name,
4659  std::size_t t_index) const
4660 {
4662  VectorPostprocessorReporterName(object_name, vector_name), t_index);
4663 }
4664 
4665 void
4667  const std::string & vector_name,
4668  const VectorPostprocessorValue & value,
4669  std::size_t t_index)
4670 {
4672  VectorPostprocessorReporterName(object_name, vector_name), value, t_index);
4673 }
4674 
4675 const VectorPostprocessor &
4677  const THREAD_ID tid) const
4678 {
4679  return getUserObject<VectorPostprocessor>(object_name, tid);
4680 }
4681 
4682 void
4684 {
4685  for (const auto & it : _multi_apps)
4686  {
4687  const auto & objects = it.second.getActiveObjects();
4688  for (const auto & obj : objects)
4689  obj->parentOutputPositionChanged();
4690  }
4691 }
4692 
4693 void
4695 {
4697  computeMarkers();
4698 }
4699 
4700 void
4702 {
4703  // Initialize indicator aux variable fields
4705  {
4706  TIME_SECTION("computeIndicators", 1, "Computing Indicators");
4707 
4708  // Internal side indicators may lead to creating a much larger sparsity pattern than dictated by
4709  // the actual finite element scheme (e.g. CFEM)
4710  const auto old_do_derivatives = ADReal::do_derivatives;
4711  ADReal::do_derivatives = false;
4712 
4713  std::vector<std::string> fields;
4714 
4715  // Indicator Fields
4716  const auto & indicators = _indicators.getActiveObjects();
4717  for (const auto & indicator : indicators)
4718  fields.push_back(indicator->name());
4719 
4720  // InternalSideIndicator Fields
4721  const auto & internal_indicators = _internal_side_indicators.getActiveObjects();
4722  for (const auto & internal_indicator : internal_indicators)
4723  fields.push_back(internal_indicator->name());
4724 
4725  _aux->zeroVariables(fields);
4726 
4727  // compute Indicators
4728  ComputeIndicatorThread cit(*this);
4729  Threads::parallel_reduce(*_mesh.getActiveLocalElementRange(), cit);
4730  _aux->solution().close();
4731  _aux->update();
4732 
4733  ComputeIndicatorThread finalize_cit(*this, true);
4734  Threads::parallel_reduce(*_mesh.getActiveLocalElementRange(), finalize_cit);
4735  _aux->solution().close();
4736  _aux->update();
4737 
4738  ADReal::do_derivatives = old_do_derivatives;
4739  }
4740 }
4741 
4742 void
4744 {
4745  if (_markers.hasActiveObjects())
4746  {
4747  TIME_SECTION("computeMarkers", 1, "Computing Markers");
4748 
4749  std::vector<std::string> fields;
4750 
4751  // Marker Fields
4752  const auto & markers = _markers.getActiveObjects();
4753  for (const auto & marker : markers)
4754  fields.push_back(marker->name());
4755 
4756  _aux->zeroVariables(fields);
4757 
4759 
4760  for (THREAD_ID tid = 0; tid < libMesh::n_threads(); ++tid)
4761  {
4762  const auto & markers = _markers.getActiveObjects(tid);
4763  for (const auto & marker : markers)
4764  marker->markerSetup();
4765  }
4766 
4767  ComputeMarkerThread cmt(*this);
4768  Threads::parallel_reduce(*_mesh.getActiveLocalElementRange(), cmt);
4769 
4770  _aux->solution().close();
4771  _aux->update();
4772  }
4773 }
4774 
4775 const ExecFlagType &
4777 {
4778  return _current_execute_on_flag;
4779 }
4780 
4781 void
4783 {
4784  _current_execute_on_flag = flag;
4785 }
4786 
4787 void
4789 {
4790 }
4791 
4792 void
4794 {
4795  SubProblem::customSetup(exec_type);
4796 
4797  if (_line_search)
4798  _line_search->customSetup(exec_type);
4799 
4800  unsigned int n_threads = libMesh::n_threads();
4801  for (THREAD_ID tid = 0; tid < n_threads; tid++)
4802  {
4803  _all_materials.customSetup(exec_type, tid);
4804  _functions.customSetup(exec_type, tid);
4805  }
4806 
4807  _aux->customSetup(exec_type);
4808  for (auto & nl : _nl)
4809  nl->customSetup(exec_type);
4810 
4811  if (_displaced_problem)
4812  _displaced_problem->customSetup(exec_type);
4813 
4814  for (THREAD_ID tid = 0; tid < n_threads; tid++)
4815  {
4816  _internal_side_indicators.customSetup(exec_type, tid);
4817  _indicators.customSetup(exec_type, tid);
4818  _markers.customSetup(exec_type, tid);
4819  }
4820 
4821  std::vector<UserObject *> userobjs;
4822  theWarehouse().query().condition<AttribSystem>("UserObject").queryIntoUnsorted(userobjs);
4823  for (auto obj : userobjs)
4824  obj->customSetup(exec_type);
4825 
4826  _app.getOutputWarehouse().customSetup(exec_type);
4827 }
4828 
4829 void
4831 {
4832  // Set the current flag
4833  setCurrentExecuteOnFlag(exec_type);
4834 
4835  if (exec_type != EXEC_INITIAL)
4836  executeControls(exec_type);
4837 
4838  // intentially call this after executing controls because the setups may rely on the controls
4839  // FIXME: we skip the following flags because they have dedicated setup functions in
4840  // SetupInterface and it may not be appropriate to call them here.
4841  if (!(exec_type == EXEC_INITIAL || exec_type == EXEC_TIMESTEP_BEGIN ||
4842  exec_type == EXEC_SUBDOMAIN || exec_type == EXEC_NONLINEAR || exec_type == EXEC_LINEAR))
4843  customSetup(exec_type);
4844 
4845  // Samplers; EXEC_INITIAL is not called because the Sampler::init() method that is called after
4846  // construction makes the first Sampler::execute() call. This ensures that the random number
4847  // generator object is the correct state prior to any other object (e.g., Transfers) attempts to
4848  // extract data from the Sampler. That is, if the Sampler::execute() call is delayed to here
4849  // then it is not in the correct state for other objects.
4850  if (exec_type != EXEC_INITIAL)
4851  executeSamplers(exec_type);
4852 
4853  // Pre-aux UserObjects
4854  computeUserObjects(exec_type, Moose::PRE_AUX);
4855 
4856  // Systems (includes system time derivative and aux kernel calculations)
4857  computeSystems(exec_type);
4858  // With the auxiliary system solution computed, sync the displaced problem auxiliary solution
4859  // before computation of post-aux user objects. The undisplaced auxiliary system current local
4860  // solution is updated (via System::update) within the AuxiliarySystem class's variable
4861  // computation methods (e.g. computeElementalVarsHelper, computeNodalVarsHelper), so it is safe to
4862  // use it here
4863  if (_displaced_problem)
4864  _displaced_problem->syncAuxSolution(*getAuxiliarySystem().currentSolution());
4865 
4866  // Post-aux UserObjects
4867  computeUserObjects(exec_type, Moose::POST_AUX);
4868 
4869  // Return the current flag to None
4871 
4873  {
4874  // we will only check aux variables and postprocessors
4875  // checking more reporter data can be added in the future if needed
4876  std::unique_ptr<NumericVector<Number>> x = _aux->currentSolution()->clone();
4878 
4879  // call THIS execute one more time for checking the possible states
4880  _checking_uo_aux_state = true;
4881  FEProblemBase::execute(exec_type);
4882  _checking_uo_aux_state = false;
4883 
4884  const Real check_tol = 1e-8;
4885 
4886  const Real xnorm = x->l2_norm();
4887  *x -= *_aux->currentSolution();
4888  if (x->l2_norm() > check_tol * xnorm)
4889  {
4890  const auto & sys = _aux->system();
4891  const unsigned int n_vars = sys.n_vars();
4892  std::multimap<Real, std::string, std::greater<Real>> ordered_map;
4893  for (const auto i : make_range(n_vars))
4894  {
4895  const Real vnorm = sys.calculate_norm(*x, i, DISCRETE_L2);
4896  ordered_map.emplace(vnorm, sys.variable_name(i));
4897  }
4898 
4899  std::ostringstream oss;
4900  for (const auto & [error_norm, var_name] : ordered_map)
4901  oss << " {" << var_name << ", " << error_norm << "},\n";
4902 
4903  mooseError("Aux kernels, user objects appear to have states for aux variables on ",
4904  exec_type,
4905  ".\nVariable error norms in descending order:\n",
4906  oss.str());
4907  }
4908 
4910  if (pp_values.size() != new_pp_values.size())
4911  mooseError("Second execution for uo/aux state check should not change the number of "
4912  "real reporter values");
4913 
4914  const Real ppnorm = pp_values.l2_norm();
4915  pp_values -= new_pp_values;
4916  if (pp_values.l2_norm() > check_tol * ppnorm)
4917  {
4918  const auto pp_names = getReporterData().getAllRealReporterFullNames();
4919  std::multimap<Real, std::string, std::greater<Real>> ordered_map;
4920  for (const auto i : index_range(pp_names))
4921  ordered_map.emplace(std::abs(pp_values(i)), pp_names[i]);
4922 
4923  std::ostringstream oss;
4924  for (const auto & [error_norm, pp_name] : ordered_map)
4925  oss << " {" << pp_name << ", " << error_norm << "},\n";
4926 
4927  mooseError("Aux kernels, user objects appear to have states for real reporter values on ",
4928  exec_type,
4929  ".\nErrors of real reporter values in descending order:\n",
4930  oss.str());
4931  }
4932  }
4933 }
4934 
4935 // Finalize, threadJoin, and update PP values of Elemental/Nodal/Side/InternalSideUserObjects
4936 void
4938 {
4939  std::vector<UserObject *> objs;
4940  query.queryInto(objs);
4941  if (!isgen)
4942  {
4943  // join all threaded user objects (i.e. not regular general user objects) to the primary
4944  // thread
4945  for (auto obj : objs)
4946  if (obj->primaryThreadCopy())
4947  obj->primaryThreadCopy()->threadJoin(*obj);
4948  }
4949 
4950  query.condition<AttribThread>(0).queryInto(objs);
4951 
4952  // finalize objects and retrieve/store any postprocessor values
4953  for (auto obj : objs)
4954  {
4955  if (isgen && dynamic_cast<ThreadedGeneralUserObject *>(obj))
4956  continue;
4957  if (isgen)
4958  {
4959  // general user objects are not run in their own threaded loop object - so run them here
4960  if (shouldPrintExecution(0))
4961  _console << "[DBG] Initializing, executing & finalizing general UO '" << obj->name()
4962  << "' on " << _current_execute_on_flag.name() << std::endl;
4963  obj->initialize();
4964  obj->execute();
4965  }
4966 
4967  obj->finalize();
4968 
4969  // These have to be stored piecemeal (with every call to this function) because general
4970  // postprocessors (which run last after other userobjects have been completed) might depend on
4971  // them being stored. This wouldn't be a problem if all userobjects satisfied the dependency
4972  // resolver interface and could be sorted appropriately with the general userobjects, but they
4973  // don't.
4974  auto pp = dynamic_cast<const Postprocessor *>(obj);
4975  if (pp)
4976  {
4977  _reporter_data.finalize(obj->name());
4978  setPostprocessorValueByName(obj->name(), pp->getValue());
4979  }
4980 
4981  auto vpp = dynamic_cast<VectorPostprocessor *>(obj);
4982  if (vpp)
4983  _reporter_data.finalize(obj->name());
4984 
4985  // Update Reporter data
4986  auto reporter = dynamic_cast<Reporter *>(obj);
4987  if (reporter)
4988  _reporter_data.finalize(obj->name());
4989  }
4990 }
4991 
4992 void
4994  const Moose::AuxGroup & group,
4995  const std::string & name)
4996 {
4997  const auto old_exec_flag = _current_execute_on_flag;
5000  .query()
5001  .condition<AttribSystem>("UserObject")
5002  .condition<AttribExecOns>(type)
5003  .condition<AttribName>(name);
5005  _current_execute_on_flag = old_exec_flag;
5006 }
5007 
5008 void
5010 {
5012  theWarehouse().query().condition<AttribSystem>("UserObject").condition<AttribExecOns>(type);
5014 }
5015 
5016 void
5018  const Moose::AuxGroup & group,
5019  TheWarehouse::Query & primary_query)
5020 {
5021  try
5022  {
5023  TIME_SECTION("computeUserObjects", 1, "Computing User Objects");
5024 
5025  // Add group to query
5026  if (group == Moose::PRE_IC)
5027  primary_query.condition<AttribPreIC>(true);
5028  else if (group == Moose::PRE_AUX)
5029  primary_query.condition<AttribPreAux>(type);
5030  else if (group == Moose::POST_AUX)
5031  primary_query.condition<AttribPostAux>(type);
5032 
5033  // query everything first to obtain a list of execution groups
5034  std::vector<UserObject *> uos;
5035  primary_query.clone().queryIntoUnsorted(uos);
5036  std::set<int> execution_groups;
5037  for (const auto & uo : uos)
5038  execution_groups.insert(uo->getParam<int>("execution_order_group"));
5039 
5040  // iterate over execution order groups
5041  for (const auto execution_group : execution_groups)
5042  {
5043  auto query = primary_query.clone().condition<AttribExecutionOrderGroup>(execution_group);
5044 
5045  std::vector<GeneralUserObject *> genobjs;
5046  query.clone().condition<AttribInterfaces>(Interfaces::GeneralUserObject).queryInto(genobjs);
5047 
5048  std::vector<UserObject *> userobjs;
5049  query.clone()
5054  .queryInto(userobjs);
5055 
5056  std::vector<UserObject *> tgobjs;
5057  query.clone()
5059  .queryInto(tgobjs);
5060 
5061  std::vector<UserObject *> nodal;
5062  query.clone().condition<AttribInterfaces>(Interfaces::NodalUserObject).queryInto(nodal);
5063 
5064  std::vector<MortarUserObject *> mortar;
5065  query.clone().condition<AttribInterfaces>(Interfaces::MortarUserObject).queryInto(mortar);
5066 
5067  if (userobjs.empty() && genobjs.empty() && tgobjs.empty() && nodal.empty() && mortar.empty())
5068  continue;
5069 
5070  // Start the timer here since we have at least one active user object
5071  std::string compute_uo_tag = "computeUserObjects(" + Moose::stringify(type) + ")";
5072 
5073  // Perform Residual/Jacobian setups
5074  if (type == EXEC_LINEAR)
5075  {
5076  for (auto obj : userobjs)
5077  obj->residualSetup();
5078  for (auto obj : nodal)
5079  obj->residualSetup();
5080  for (auto obj : mortar)
5081  obj->residualSetup();
5082  for (auto obj : tgobjs)
5083  obj->residualSetup();
5084  for (auto obj : genobjs)
5085  obj->residualSetup();
5086  }
5087  else if (type == EXEC_NONLINEAR)
5088  {
5089  for (auto obj : userobjs)
5090  obj->jacobianSetup();
5091  for (auto obj : nodal)
5092  obj->jacobianSetup();
5093  for (auto obj : mortar)
5094  obj->jacobianSetup();
5095  for (auto obj : tgobjs)
5096  obj->jacobianSetup();
5097  for (auto obj : genobjs)
5098  obj->jacobianSetup();
5099  }
5100 
5101  for (auto obj : userobjs)
5102  obj->initialize();
5103 
5104  // Execute Side/InternalSide/Interface/Elemental/DomainUserObjects
5105  if (!userobjs.empty())
5106  {
5107  // non-nodal user objects have to be run separately before the nodal user objects run
5108  // because some nodal user objects (NodalNormal related) depend on elemental user objects
5109  // :-(
5110  ComputeUserObjectsThread cppt(*this, query);
5111  Threads::parallel_reduce(*_mesh.getActiveLocalElementRange(), cppt);
5112 
5113  // There is one instance in rattlesnake where an elemental user object's finalize depends
5114  // on a side user object having been finalized first :-(
5121  }
5122 
5123  // if any userobject may have written to variables we need to close the aux solution
5124  for (const auto & uo : userobjs)
5125  if (auto euo = dynamic_cast<const ElementUserObject *>(uo);
5126  euo && euo->hasWritableCoupledVariables())
5127  {
5128  _aux->solution().close();
5129  _aux->system().update();
5130  break;
5131  }
5132 
5133  // Execute NodalUserObjects
5134  // BISON has an axial reloc elemental user object that has a finalize func that depends on a
5135  // nodal user object's prev value. So we can't initialize this until after elemental objects
5136  // have been finalized :-(
5137  for (auto obj : nodal)
5138  obj->initialize();
5139  if (query.clone().condition<AttribInterfaces>(Interfaces::NodalUserObject).count() > 0)
5140  {
5141  ComputeNodalUserObjectsThread cnppt(*this, query);
5142  Threads::parallel_reduce(*_mesh.getLocalNodeRange(), cnppt);
5144  }
5145 
5146  // if any userobject may have written to variables we need to close the aux solution
5147  for (const auto & uo : nodal)
5148  if (auto nuo = dynamic_cast<const NodalUserObject *>(uo);
5149  nuo && nuo->hasWritableCoupledVariables())
5150  {
5151  _aux->solution().close();
5152  _aux->system().update();
5153  break;
5154  }
5155 
5156  // Execute MortarUserObjects
5157  {
5158  for (auto obj : mortar)
5159  obj->initialize();
5160  if (!mortar.empty())
5161  {
5162  auto create_and_run_mortar_functors = [this, type, &mortar](const bool displaced)
5163  {
5164  // go over mortar interfaces and construct functors
5165  const auto & mortar_interfaces = getMortarInterfaces(displaced);
5166  for (const auto & mortar_interface : mortar_interfaces)
5167  {
5168  const auto primary_secondary_boundary_pair = mortar_interface.first;
5169  auto mortar_uos_to_execute =
5170  getMortarUserObjects(primary_secondary_boundary_pair.first,
5171  primary_secondary_boundary_pair.second,
5172  displaced,
5173  mortar);
5174  const auto & mortar_generation_object = mortar_interface.second;
5175 
5176  auto * const subproblem = displaced
5177  ? static_cast<SubProblem *>(_displaced_problem.get())
5178  : static_cast<SubProblem *>(this);
5179  MortarUserObjectThread muot(mortar_uos_to_execute,
5180  mortar_generation_object,
5181  *subproblem,
5182  *this,
5183  displaced,
5184  subproblem->assembly(0, 0));
5185 
5186  muot();
5187  }
5188  };
5189 
5190  create_and_run_mortar_functors(false);
5191  if (_displaced_problem)
5192  create_and_run_mortar_functors(true);
5193  }
5194  for (auto obj : mortar)
5195  obj->finalize();
5196  }
5197 
5198  // Execute threaded general user objects
5199  for (auto obj : tgobjs)
5200  obj->initialize();
5201  std::vector<GeneralUserObject *> tguos_zero;
5202  query.clone()
5203  .condition<AttribThread>(0)
5204  .condition<AttribInterfaces>(Interfaces::ThreadedGeneralUserObject)
5205  .queryInto(tguos_zero);
5206  for (auto obj : tguos_zero)
5207  {
5208  std::vector<GeneralUserObject *> tguos;
5209  auto q = query.clone()
5210  .condition<AttribName>(obj->name())
5211  .condition<AttribInterfaces>(Interfaces::ThreadedGeneralUserObject);
5212  q.queryInto(tguos);
5213 
5215  Threads::parallel_reduce(GeneralUserObjectRange(tguos.begin(), tguos.end()), ctguot);
5216  joinAndFinalize(q);
5217  }
5218 
5219  // Execute general user objects
5221  true);
5222  }
5223  }
5224  catch (...)
5225  {
5226  handleException("computeUserObjectsInternal");
5227  }
5228 }
5229 
5230 void
5232 {
5233  if (_control_warehouse[exec_type].hasActiveObjects())
5234  {
5235  TIME_SECTION("executeControls", 1, "Executing Controls");
5236 
5238 
5239  auto controls_wh = _control_warehouse[exec_type];
5240  // Add all of the dependencies into the resolver and sort them
5241  for (const auto & it : controls_wh.getActiveObjects())
5242  {
5243  // Make sure an item with no dependencies comes out too!
5244  resolver.addItem(it);
5245 
5246  std::vector<std::string> & dependent_controls = it->getDependencies();
5247  for (const auto & depend_name : dependent_controls)
5248  {
5249  if (controls_wh.hasActiveObject(depend_name))
5250  {
5251  auto dep_control = controls_wh.getActiveObject(depend_name);
5252  resolver.addEdge(dep_control, it);
5253  }
5254  else
5255  mooseError("The Control \"",
5256  depend_name,
5257  "\" was not created, did you make a "
5258  "spelling mistake or forget to include it "
5259  "in your input file?");
5260  }
5261  }
5262 
5263  const auto & ordered_controls = resolver.getSortedValues();
5264 
5265  if (!ordered_controls.empty())
5266  {
5267  _control_warehouse.setup(exec_type);
5268  // Run the controls in the proper order
5269  for (const auto & control : ordered_controls)
5270  control->execute();
5271  }
5272  }
5273 }
5274 
5275 void
5277 {
5278  // TODO: This should be done in a threaded loop, but this should be super quick so for now
5279  // do a serial loop.
5280  for (THREAD_ID tid = 0; tid < libMesh::n_threads(); ++tid)
5281  {
5282  std::vector<Sampler *> objects;
5283  theWarehouse()
5284  .query()
5285  .condition<AttribSystem>("Sampler")
5286  .condition<AttribThread>(tid)
5287  .condition<AttribExecOns>(exec_type)
5288  .queryInto(objects);
5289 
5290  if (!objects.empty())
5291  {
5292  TIME_SECTION("executeSamplers", 1, "Executing Samplers");
5293  FEProblemBase::objectSetupHelper<Sampler>(objects, exec_type);
5294  FEProblemBase::objectExecuteHelper<Sampler>(objects);
5295  }
5296  }
5297 }
5298 
5299 void
5301 {
5302  TIME_SECTION("updateActiveObjects", 5, "Updating Active Objects");
5303 
5304  for (THREAD_ID tid = 0; tid < libMesh::n_threads(); ++tid)
5305  {
5306  for (auto & nl : _nl)
5307  nl->updateActive(tid);
5308  _aux->updateActive(tid);
5311  _markers.updateActive(tid);
5313  _materials.updateActive(tid);
5315  }
5316 
5324 
5325 #ifdef MOOSE_KOKKOS_ENABLED
5327 #endif
5328 }
5329 
5330 void
5332 {
5333  //<< "Object " << a->name() << " -> " << b->name() << std::endl;
5334 }
5335 
5336 void
5338 {
5339  TIME_SECTION("reinitBecauseOfGhostingOrNewGeomObjects",
5340  3,
5341  "Reinitializing Because of Geometric Search Objects");
5342 
5343  // Need to see if _any_ processor has ghosted elems or geometry objects.
5344  bool needs_reinit = !_ghosted_elems.empty();
5345  needs_reinit = needs_reinit || !_geometric_search_data._nearest_node_locators.empty() ||
5346  (_mortar_data.hasObjects() && mortar_changed);
5347  needs_reinit =
5348  needs_reinit || (_displaced_problem &&
5349  (!_displaced_problem->geomSearchData()._nearest_node_locators.empty() ||
5350  (_mortar_data.hasDisplacedObjects() && mortar_changed)));
5351  _communicator.max(needs_reinit);
5352 
5353  if (needs_reinit)
5354  {
5355  // Call reinit to get the ghosted vectors correct now that some geometric search has been done
5356  es().reinit();
5357 
5358  if (_displaced_mesh)
5359  _displaced_problem->es().reinit();
5360  }
5361 }
5362 
5363 void
5364 FEProblemBase::addDamper(const std::string & damper_name,
5365  const std::string & name,
5366  InputParameters & parameters)
5367 {
5368  parallel_object_only();
5369 
5370  const auto nl_sys_num =
5371  parameters.isParamValid("variable")
5372  ? determineSolverSystem(parameters.varName("variable", name), true).second
5373  : (unsigned int)0;
5374 
5375  if (!isSolverSystemNonlinear(nl_sys_num))
5376  mooseError("You are trying to add a DGKernel to a linear variable/system, which is not "
5377  "supported at the moment!");
5378 
5379  parameters.set<SubProblem *>("_subproblem") = this;
5380  parameters.set<SystemBase *>("_sys") = _nl[nl_sys_num].get();
5381 
5382  _has_dampers = true;
5383  logAdd("Damper", name, damper_name, parameters);
5384  _nl[nl_sys_num]->addDamper(damper_name, name, parameters);
5385 }
5386 
5387 void
5389 {
5390  for (auto & nl : _nl)
5391  nl->setupDampers();
5392 }
5393 
5394 void
5395 FEProblemBase::addIndicator(const std::string & indicator_name,
5396  const std::string & name,
5397  InputParameters & parameters)
5398 {
5399  parallel_object_only();
5400 
5401  if (_displaced_problem && parameters.get<bool>("use_displaced_mesh"))
5402  {
5403  parameters.set<SubProblem *>("_subproblem") = _displaced_problem.get();
5404  parameters.set<SystemBase *>("_sys") = &_displaced_problem->auxSys();
5405  _reinit_displaced_elem = true;
5406  }
5407  else
5408  {
5409  if (_displaced_problem == nullptr && parameters.get<bool>("use_displaced_mesh"))
5410  {
5411  // We allow Indicators to request that they use_displaced_mesh,
5412  // but then be overridden when no displacements variables are
5413  // provided in the Mesh block. If that happened, update the value
5414  // of use_displaced_mesh appropriately for this Indicator.
5415  if (parameters.have_parameter<bool>("use_displaced_mesh"))
5416  parameters.set<bool>("use_displaced_mesh") = false;
5417  }
5418 
5419  parameters.set<SubProblem *>("_subproblem") = this;
5420  parameters.set<SystemBase *>("_sys") = _aux.get();
5421  }
5422 
5423  for (THREAD_ID tid = 0; tid < libMesh::n_threads(); tid++)
5424  {
5425  std::shared_ptr<Indicator> indicator =
5426  _factory.create<Indicator>(indicator_name, name, parameters, tid);
5427  logAdd("Indicator", name, indicator_name, parameters);
5428  std::shared_ptr<InternalSideIndicatorBase> isi =
5430  if (isi)
5432  else
5433  _indicators.addObject(indicator, tid);
5434  }
5435 }
5436 
5437 void
5438 FEProblemBase::addMarker(const std::string & marker_name,
5439  const std::string & name,
5440  InputParameters & parameters)
5441 {
5442  parallel_object_only();
5443 
5444  if (_displaced_problem && parameters.get<bool>("use_displaced_mesh"))
5445  {
5446  parameters.set<SubProblem *>("_subproblem") = _displaced_problem.get();
5447  parameters.set<SystemBase *>("_sys") = &_displaced_problem->auxSys();
5448  _reinit_displaced_elem = true;
5449  }
5450  else
5451  {
5452  if (_displaced_problem == nullptr && parameters.get<bool>("use_displaced_mesh"))
5453  {
5454  // We allow Markers to request that they use_displaced_mesh,
5455  // but then be overridden when no displacements variables are
5456  // provided in the Mesh block. If that happened, update the value
5457  // of use_displaced_mesh appropriately for this Marker.
5458  if (parameters.have_parameter<bool>("use_displaced_mesh"))
5459  parameters.set<bool>("use_displaced_mesh") = false;
5460  }
5461 
5462  parameters.set<SubProblem *>("_subproblem") = this;
5463  parameters.set<SystemBase *>("_sys") = _aux.get();
5464  }
5465 
5466  for (THREAD_ID tid = 0; tid < libMesh::n_threads(); tid++)
5467  {
5468  std::shared_ptr<Marker> marker = _factory.create<Marker>(marker_name, name, parameters, tid);
5469  logAdd("Marker", name, marker_name, parameters);
5470  _markers.addObject(marker, tid);
5471  }
5472 }
5473 
5474 void
5475 FEProblemBase::addMultiApp(const std::string & multi_app_name,
5476  const std::string & name,
5477  InputParameters & parameters)
5478 {
5479  parallel_object_only();
5480 
5481  parameters.set<MPI_Comm>("_mpi_comm") = _communicator.get();
5482 
5483  if (_displaced_problem && parameters.get<bool>("use_displaced_mesh"))
5484  {
5485  parameters.set<SubProblem *>("_subproblem") = _displaced_problem.get();
5486  parameters.set<SystemBase *>("_sys") = &_displaced_problem->auxSys();
5487  _reinit_displaced_elem = true;
5488  }
5489  else
5490  {
5491  if (_displaced_problem == nullptr && parameters.get<bool>("use_displaced_mesh"))
5492  {
5493  // We allow MultiApps to request that they use_displaced_mesh,
5494  // but then be overridden when no displacements variables are
5495  // provided in the Mesh block. If that happened, update the value
5496  // of use_displaced_mesh appropriately for this MultiApp.
5497  if (parameters.have_parameter<bool>("use_displaced_mesh"))
5498  parameters.set<bool>("use_displaced_mesh") = false;
5499  }
5500 
5501  parameters.set<SubProblem *>("_subproblem") = this;
5502  parameters.set<SystemBase *>("_sys") = _aux.get();
5503  }
5504 
5505  std::shared_ptr<MultiApp> multi_app = _factory.create<MultiApp>(multi_app_name, name, parameters);
5506  logAdd("MultiApp", name, multi_app_name, parameters);
5507  multi_app->setupPositions();
5508 
5509  _multi_apps.addObject(multi_app);
5510 
5511  // Store TransientMultiApp objects in another container, this is needed for calling computeDT
5512  std::shared_ptr<TransientMultiApp> trans_multi_app =
5514  if (trans_multi_app)
5515  _transient_multi_apps.addObject(trans_multi_app);
5516 }
5517 
5518 bool
5520 {
5521  return _multi_apps[type].hasActiveObjects();
5522 }
5523 
5524 bool
5525 FEProblemBase::hasMultiApp(const std::string & multi_app_name) const
5526 {
5527  return _multi_apps.hasActiveObject(multi_app_name);
5528 }
5529 
5530 std::shared_ptr<MultiApp>
5531 FEProblemBase::getMultiApp(const std::string & multi_app_name) const
5532 {
5533  return _multi_apps.getObject(multi_app_name);
5534 }
5535 
5536 void
5538 {
5539  bool to_multiapp = direction == MultiAppTransfer::TO_MULTIAPP;
5540  bool from_multiapp = direction == MultiAppTransfer::FROM_MULTIAPP;
5541  std::string string_direction;
5542  if (to_multiapp)
5543  string_direction = " To ";
5544  else if (from_multiapp)
5545  string_direction = " From ";
5546  else
5547  string_direction = " Between ";
5548 
5549  const MooseObjectWarehouse<Transfer> & wh = to_multiapp ? _to_multi_app_transfers[type]
5550  : from_multiapp ? _from_multi_app_transfers[type]
5552 
5553  if (wh.hasActiveObjects())
5554  {
5555  TIME_SECTION("execMultiAppTransfers", 1, "Executing Transfers");
5556 
5557  const auto & transfers = wh.getActiveObjects();
5558 
5559  if (_verbose_multiapps)
5560  {
5561  _console << COLOR_CYAN << "\nTransfers on " << Moose::stringify(type) << string_direction
5562  << "MultiApps" << COLOR_DEFAULT << ":" << std::endl;
5563 
5565  {"Name", "Type", "From", "To"});
5566 
5567  // Build Table of Transfer Info
5568  for (const auto & transfer : transfers)
5569  {
5570  auto multiapp_transfer = dynamic_cast<MultiAppTransfer *>(transfer.get());
5571 
5572  table.addRow(multiapp_transfer->name(),
5573  multiapp_transfer->type(),
5574  multiapp_transfer->getFromName(),
5575  multiapp_transfer->getToName());
5576  }
5577 
5578  // Print it
5579  table.print(_console);
5580  }
5581 
5582  for (const auto & transfer : transfers)
5583  {
5584  transfer->setCurrentDirection(direction);
5585  transfer->execute();
5586  }
5587 
5589 
5590  if (_verbose_multiapps)
5591  _console << COLOR_CYAN << "Transfers on " << Moose::stringify(type) << " Are Finished\n"
5592  << COLOR_DEFAULT << std::endl;
5593  }
5594  else if (_multi_apps[type].getActiveObjects().size())
5595  {
5596  if (_verbose_multiapps)
5597  _console << COLOR_CYAN << "\nNo Transfers on " << Moose::stringify(type) << string_direction
5598  << "MultiApps\n"
5599  << COLOR_DEFAULT << std::endl;
5600  }
5601 }
5602 
5603 std::vector<std::shared_ptr<Transfer>>
5605 {
5606  if (direction == MultiAppTransfer::TO_MULTIAPP)
5608  else if (direction == MultiAppTransfer::FROM_MULTIAPP)
5610  else
5612 }
5613 
5614 std::vector<std::shared_ptr<Transfer>>
5616 {
5617  if (direction == MultiAppTransfer::TO_MULTIAPP)
5619  else if (direction == MultiAppTransfer::FROM_MULTIAPP)
5621  else
5623 }
5624 
5627 {
5628  if (direction == MultiAppTransfer::TO_MULTIAPP)
5629  return _to_multi_app_transfers;
5630  else if (direction == MultiAppTransfer::FROM_MULTIAPP)
5632  else
5634 }
5635 
5636 bool
5638 {
5639  // Active MultiApps
5640  const std::vector<MooseSharedPointer<MultiApp>> & multi_apps =
5642 
5643  // Do anything that needs to be done to Apps before transfers
5644  for (const auto & multi_app : multi_apps)
5645  multi_app->preTransfer(_dt, _time);
5646 
5647  // Execute Transfers _to_ MultiApps
5649 
5650  // Execute Transfers _between_ Multiapps
5652 
5653  // Execute MultiApps
5654  if (multi_apps.size())
5655  {
5656  TIME_SECTION("execMultiApps", 1, "Executing MultiApps", false);
5657 
5658  if (_verbose_multiapps)
5659  _console << COLOR_CYAN << "\nExecuting MultiApps on " << Moose::stringify(type)
5660  << COLOR_DEFAULT << std::endl;
5661 
5662  bool success = true;
5663 
5664  for (const auto & multi_app : multi_apps)
5665  {
5666  success = multi_app->solveStep(_dt, _time, auto_advance);
5667  // no need to finish executing the subapps if one fails
5668  if (!success)
5669  break;
5670  }
5671 
5673 
5674  _communicator.min(success);
5675 
5676  if (!success)
5677  return false;
5678 
5679  if (_verbose_multiapps)
5680  _console << COLOR_CYAN << "Finished Executing MultiApps on " << Moose::stringify(type) << "\n"
5681  << COLOR_DEFAULT << std::endl;
5682  }
5683 
5684  // Execute Transfers _from_ MultiApps
5686 
5687  // If we made it here then everything passed
5688  return true;
5689 }
5690 
5691 void
5693 {
5694  const auto & multi_apps = _multi_apps.getActiveObjects();
5695 
5696  for (const auto & multi_app : multi_apps)
5697  multi_app->finalize();
5698 }
5699 
5700 void
5702 {
5703  const auto & multi_apps = _multi_apps.getActiveObjects();
5704 
5705  for (const auto & multi_app : multi_apps)
5706  multi_app->postExecute();
5707 }
5708 
5709 void
5711 {
5712  const auto & multi_apps = _multi_apps[type].getActiveObjects();
5713 
5714  if (multi_apps.size())
5715  for (const auto & multi_app : multi_apps)
5716  multi_app->incrementTStep(_time);
5717 }
5718 
5719 void
5720 FEProblemBase::finishMultiAppStep(ExecFlagType type, bool recurse_through_multiapp_levels)
5721 {
5722  const auto & multi_apps = _multi_apps[type].getActiveObjects();
5723 
5724  if (multi_apps.size())
5725  {
5726  if (_verbose_multiapps)
5727  _console << COLOR_CYAN << "\nAdvancing MultiApps on " << type.name() << COLOR_DEFAULT
5728  << std::endl;
5729 
5730  for (const auto & multi_app : multi_apps)
5731  multi_app->finishStep(recurse_through_multiapp_levels);
5732 
5734 
5735  if (_verbose_multiapps)
5736  _console << COLOR_CYAN << "Finished Advancing MultiApps on " << type.name() << "\n"
5737  << COLOR_DEFAULT << std::endl;
5738  }
5739 }
5740 
5741 void
5743 {
5744  const auto & multi_apps = _multi_apps[type].getActiveObjects();
5745 
5746  if (multi_apps.size())
5747  {
5748  TIME_SECTION("backupMultiApps", 5, "Backing Up MultiApp");
5749 
5750  if (_verbose_multiapps)
5751  _console << COLOR_CYAN << "\nBacking Up MultiApps on " << type.name() << COLOR_DEFAULT
5752  << std::endl;
5753 
5754  for (const auto & multi_app : multi_apps)
5755  multi_app->backup();
5756 
5758 
5759  if (_verbose_multiapps)
5760  _console << COLOR_CYAN << "Finished Backing Up MultiApps on " << type.name() << "\n"
5761  << COLOR_DEFAULT << std::endl;
5762  }
5763 }
5764 
5765 void
5767 {
5768  const auto & multi_apps = _multi_apps[type].getActiveObjects();
5769 
5770  if (multi_apps.size())
5771  {
5772  if (_verbose_multiapps)
5773  {
5774  if (force)
5775  _console << COLOR_CYAN << "\nRestoring Multiapps on " << type.name()
5776  << " because of solve failure!" << COLOR_DEFAULT << std::endl;
5777  else
5778  _console << COLOR_CYAN << "\nRestoring MultiApps on " << type.name() << COLOR_DEFAULT
5779  << std::endl;
5780  }
5781 
5782  for (const auto & multi_app : multi_apps)
5783  multi_app->restore(force);
5784 
5786 
5787  if (_verbose_multiapps)
5788  _console << COLOR_CYAN << "Finished Restoring MultiApps on " << type.name() << "\n"
5789  << COLOR_DEFAULT << std::endl;
5790  }
5791 }
5792 
5793 Real
5795 {
5796  const auto & multi_apps = _transient_multi_apps[type].getActiveObjects();
5797 
5798  Real smallest_dt = std::numeric_limits<Real>::max();
5799 
5800  for (const auto & multi_app : multi_apps)
5801  smallest_dt = std::min(smallest_dt, multi_app->computeDT());
5802 
5803  return smallest_dt;
5804 }
5805 
5806 void
5808 {
5809  if (_transfers[type].hasActiveObjects())
5810  {
5811  TIME_SECTION("execTransfers", 3, "Executing Transfers");
5812 
5813  const auto & transfers = _transfers[type].getActiveObjects();
5814 
5815  for (const auto & transfer : transfers)
5816  transfer->execute();
5817  }
5818 }
5819 
5820 void
5821 FEProblemBase::addTransfer(const std::string & transfer_name,
5822  const std::string & name,
5823  InputParameters & parameters)
5824 {
5825  parallel_object_only();
5826 
5827  if (_displaced_problem && parameters.get<bool>("use_displaced_mesh"))
5828  {
5829  parameters.set<SubProblem *>("_subproblem") = _displaced_problem.get();
5830  parameters.set<SystemBase *>("_sys") = &_displaced_problem->auxSys();
5831  _reinit_displaced_elem = true;
5832  }
5833  else
5834  {
5835  if (_displaced_problem == nullptr && parameters.get<bool>("use_displaced_mesh"))
5836  {
5837  // We allow Transfers to request that they use_displaced_mesh,
5838  // but then be overridden when no displacements variables are
5839  // provided in the Mesh block. If that happened, update the value
5840  // of use_displaced_mesh appropriately for this Transfer.
5841  if (parameters.have_parameter<bool>("use_displaced_mesh"))
5842  parameters.set<bool>("use_displaced_mesh") = false;
5843  }
5844 
5845  parameters.set<SubProblem *>("_subproblem") = this;
5846  parameters.set<SystemBase *>("_sys") = _aux.get();
5847  }
5848 
5849  // Handle the "SAME_AS_MULTIAPP" execute option. The get method is used to test for the
5850  // flag so the set by user flag is not reset, calling set with the true flag causes the set
5851  // by user status to be reset, which should only be done if the EXEC_SAME_AS_MULTIAPP is
5852  // being applied to the object.
5854  {
5855  ExecFlagEnum & exec_enum = parameters.set<ExecFlagEnum>("execute_on", true);
5856  std::shared_ptr<MultiApp> multiapp;
5857  if (parameters.isParamValid("multi_app"))
5858  multiapp = getMultiApp(parameters.get<MultiAppName>("multi_app"));
5859  // This catches the sibling transfer case, where we want to be executing only as often as the
5860  // receiving application. A transfer 'to' a multiapp is executed before that multiapp
5861  else if (parameters.isParamValid("to_multi_app"))
5862  multiapp = getMultiApp(parameters.get<MultiAppName>("to_multi_app"));
5863  else if (parameters.isParamValid("from_multi_app"))
5864  multiapp = getMultiApp(parameters.get<MultiAppName>("from_multi_app"));
5865  // else do nothing because the user has provided invalid input. They should get a nice error
5866  // about this during transfer construction. This necessitates checking for null in this next
5867  // line, however
5868  if (multiapp)
5869  exec_enum = multiapp->getParam<ExecFlagEnum>("execute_on");
5870  }
5871 
5872  // Create the Transfer objects
5873  std::shared_ptr<Transfer> transfer = _factory.create<Transfer>(transfer_name, name, parameters);
5874  logAdd("Transfer", name, transfer_name, parameters);
5875 
5876  // Add MultiAppTransfer object
5877  std::shared_ptr<MultiAppTransfer> multi_app_transfer =
5879  if (multi_app_transfer)
5880  {
5881  if (multi_app_transfer->directions().isValueSet(MultiAppTransfer::TO_MULTIAPP))
5882  _to_multi_app_transfers.addObject(multi_app_transfer);
5883  if (multi_app_transfer->directions().isValueSet(MultiAppTransfer::FROM_MULTIAPP))
5884  _from_multi_app_transfers.addObject(multi_app_transfer);
5885  if (multi_app_transfer->directions().isValueSet(MultiAppTransfer::BETWEEN_MULTIAPP))
5886  _between_multi_app_transfers.addObject(multi_app_transfer);
5887  }
5888  else
5889  _transfers.addObject(transfer);
5890 }
5891 
5892 bool
5893 FEProblemBase::hasVariable(const std::string & var_name) const
5894 {
5895  for (auto & sys : _solver_systems)
5896  if (sys->hasVariable(var_name))
5897  return true;
5898  if (_aux->hasVariable(var_name))
5899  return true;
5900 
5901  return false;
5902 }
5903 
5904 bool
5905 FEProblemBase::hasSolverVariable(const std::string & var_name) const
5906 {
5907  for (auto & sys : _solver_systems)
5908  if (sys->hasVariable(var_name))
5909  return true;
5910 
5911  return false;
5912 }
5913 
5914 const MooseVariableFieldBase &
5916  const std::string & var_name,
5917  Moose::VarKindType expected_var_type,
5918  Moose::VarFieldType expected_var_field_type) const
5919 {
5920  return getVariableHelper(
5921  tid, var_name, expected_var_type, expected_var_field_type, _solver_systems, *_aux);
5922 }
5923 
5924 MooseVariable &
5925 FEProblemBase::getStandardVariable(const THREAD_ID tid, const std::string & var_name)
5926 {
5927  for (auto & sys : _solver_systems)
5928  if (sys->hasVariable(var_name))
5929  return sys->getFieldVariable<Real>(tid, var_name);
5930  if (_aux->hasVariable(var_name))
5931  return _aux->getFieldVariable<Real>(tid, var_name);
5932 
5933  mooseError("Unknown variable " + var_name);
5934 }
5935 
5937 FEProblemBase::getActualFieldVariable(const THREAD_ID tid, const std::string & var_name)
5938 {
5939  for (auto & sys : _solver_systems)
5940  if (sys->hasVariable(var_name))
5941  return sys->getActualFieldVariable<Real>(tid, var_name);
5942  if (_aux->hasVariable(var_name))
5943  return _aux->getActualFieldVariable<Real>(tid, var_name);
5944 
5945  mooseError("Unknown variable " + var_name);
5946 }
5947 
5949 FEProblemBase::getVectorVariable(const THREAD_ID tid, const std::string & var_name)
5950 {
5951  for (auto & sys : _solver_systems)
5952  if (sys->hasVariable(var_name))
5953  return sys->getFieldVariable<RealVectorValue>(tid, var_name);
5954  if (_aux->hasVariable(var_name))
5955  return _aux->getFieldVariable<RealVectorValue>(tid, var_name);
5956 
5957  mooseError("Unknown variable " + var_name);
5958 }
5959 
5961 FEProblemBase::getArrayVariable(const THREAD_ID tid, const std::string & var_name)
5962 {
5963  for (auto & sys : _solver_systems)
5964  if (sys->hasVariable(var_name))
5965  return sys->getFieldVariable<RealEigenVector>(tid, var_name);
5966  if (_aux->hasVariable(var_name))
5967  return _aux->getFieldVariable<RealEigenVector>(tid, var_name);
5968 
5969  mooseError("Unknown variable " + var_name);
5970 }
5971 
5972 bool
5973 FEProblemBase::hasScalarVariable(const std::string & var_name) const
5974 {
5975  for (auto & sys : _solver_systems)
5976  if (sys->hasScalarVariable(var_name))
5977  return true;
5978  if (_aux->hasScalarVariable(var_name))
5979  return true;
5980 
5981  return false;
5982 }
5983 
5985 FEProblemBase::getScalarVariable(const THREAD_ID tid, const std::string & var_name)
5986 {
5987  for (auto & sys : _solver_systems)
5988  if (sys->hasScalarVariable(var_name))
5989  return sys->getScalarVariable(tid, var_name);
5990  if (_aux->hasScalarVariable(var_name))
5991  return _aux->getScalarVariable(tid, var_name);
5992 
5993  mooseError("Unknown variable " + var_name);
5994 }
5995 
5996 System &
5997 FEProblemBase::getSystem(const std::string & var_name)
5998 {
5999  const auto [var_in_sys, sys_num] = determineSolverSystem(var_name);
6000  if (var_in_sys)
6001  return _solver_systems[sys_num]->system();
6002  else if (_aux->hasVariable(var_name) || _aux->hasScalarVariable(var_name))
6003  return _aux->system();
6004  else
6005  mooseError("Unable to find a system containing the variable " + var_name);
6006 }
6007 
6010 {
6011  return _req.get();
6012 }
6013 
6014 void
6016 {
6018 
6019  if (_displaced_problem)
6020  _displaced_problem->setActiveFEVariableCoupleableMatrixTags(mtags, tid);
6021 }
6022 
6023 void
6025 {
6027 
6028  if (_displaced_problem)
6029  _displaced_problem->setActiveFEVariableCoupleableVectorTags(vtags, tid);
6030 }
6031 
6032 void
6034  const THREAD_ID tid)
6035 {
6037 
6038  if (_displaced_problem)
6039  _displaced_problem->setActiveScalarVariableCoupleableMatrixTags(mtags, tid);
6040 }
6041 
6042 void
6044  const THREAD_ID tid)
6045 {
6047 
6048  if (_displaced_problem)
6049  _displaced_problem->setActiveScalarVariableCoupleableVectorTags(vtags, tid);
6050 }
6051 
6052 void
6053 FEProblemBase::setActiveElementalMooseVariables(const std::set<MooseVariableFEBase *> & moose_vars,
6054  const THREAD_ID tid)
6055 {
6057 
6058  if (_displaced_problem)
6059  _displaced_problem->setActiveElementalMooseVariables(moose_vars, tid);
6060 }
6061 
6062 void
6064 {
6066 
6067  if (_displaced_problem)
6068  _displaced_problem->clearActiveElementalMooseVariables(tid);
6069 }
6070 
6071 void
6073 {
6075 
6076  if (_displaced_problem)
6077  _displaced_problem->clearActiveFEVariableCoupleableMatrixTags(tid);
6078 }
6079 
6080 void
6082 {
6084 
6085  if (_displaced_problem)
6086  _displaced_problem->clearActiveFEVariableCoupleableVectorTags(tid);
6087 }
6088 
6089 void
6091 {
6093 
6094  if (_displaced_problem)
6095  _displaced_problem->clearActiveScalarVariableCoupleableMatrixTags(tid);
6096 }
6097 
6098 void
6100 {
6102 
6103  if (_displaced_problem)
6104  _displaced_problem->clearActiveScalarVariableCoupleableVectorTags(tid);
6105 }
6106 
6107 void
6108 FEProblemBase::setActiveMaterialProperties(const std::unordered_set<unsigned int> & mat_prop_ids,
6109  const THREAD_ID tid)
6110 {
6111  // mark active properties in every material
6112  for (auto & mat : _all_materials.getObjects(tid))
6113  mat->setActiveProperties(mat_prop_ids);
6114  for (auto & mat : _all_materials[Moose::FACE_MATERIAL_DATA].getObjects(tid))
6115  mat->setActiveProperties(mat_prop_ids);
6116  for (auto & mat : _all_materials[Moose::NEIGHBOR_MATERIAL_DATA].getObjects(tid))
6117  mat->setActiveProperties(mat_prop_ids);
6118 
6119  _has_active_material_properties[tid] = !mat_prop_ids.empty();
6120 }
6121 
6122 bool
6124 {
6125  return _has_active_material_properties[tid];
6126 }
6127 
6128 void
6130 {
6132 }
6133 
6134 void
6136 {
6137 #ifdef LIBMESH_ENABLE_AMR
6138  if ((_adaptivity.isOn() || _num_grid_steps) &&
6141  {
6142  // Even on a serialized Mesh, we don't keep our material
6143  // properties serialized, so we'll rely on the callback to
6144  // redistribute() to redistribute properties at the same time
6145  // libMesh is redistributing elements.
6146  auto add_redistributer = [this](MooseMesh & mesh,
6147  const std::string & redistributer_name,
6148  const bool use_displaced_mesh)
6149  {
6150  InputParameters redistribute_params = RedistributeProperties::validParams();
6151  redistribute_params.set<MooseApp *>(MooseBase::app_param) = &_app;
6152  redistribute_params.set<std::string>("for_whom") = this->name();
6153  redistribute_params.set<MooseMesh *>("mesh") = &mesh;
6154  redistribute_params.set<Moose::RelationshipManagerType>("rm_type") =
6156  redistribute_params.set<bool>("use_displaced_mesh") = use_displaced_mesh;
6157  redistribute_params.setHitNode(*parameters().getHitNode(), {});
6158 
6159  std::shared_ptr<RedistributeProperties> redistributer =
6161  "RedistributeProperties", redistributer_name, redistribute_params);
6162 
6165 
6167  redistributer->addMaterialPropertyStorage(_bnd_material_props);
6168 
6170  redistributer->addMaterialPropertyStorage(_neighbor_material_props);
6171 
6172  mesh.getMesh().add_ghosting_functor(redistributer);
6173  };
6174 
6175  add_redistributer(_mesh, "mesh_property_redistributer", false);
6176  if (_displaced_problem)
6177  add_redistributer(_displaced_problem->mesh(), "displaced_mesh_property_redistributer", true);
6178  }
6179 #endif // LIBMESH_ENABLE_AMR
6180 }
6181 
6182 void
6184 {
6185  // Find the maximum number of quadrature points
6186  {
6187  MaxQpsThread mqt(*this);
6188  Threads::parallel_reduce(*_mesh.getActiveLocalElementRange(), mqt);
6189  _max_qps = mqt.max();
6190 
6191  // If we have more shape functions or more quadrature points on
6192  // another processor, then we may need to handle those elements
6193  // ourselves later after repartitioning.
6195  }
6196 
6197  unsigned int max_qpts = getMaxQps();
6198  if (max_qpts > Moose::constMaxQpsPerElem)
6199  mooseError("Max quadrature points per element assumptions made in some code (e.g. Coupleable ",
6200  "and MaterialPropertyInterface classes) have been violated.\n",
6201  "Complain to Moose developers to have constMaxQpsPerElem increased from ",
6203  " to ",
6204  max_qpts);
6205  for (unsigned int tid = 0; tid < libMesh::n_threads(); ++tid)
6206  {
6207  // the highest available order in libMesh is 43
6208  _scalar_zero[tid].resize(FORTYTHIRD, 0);
6209  _zero[tid].resize(max_qpts, 0);
6210  _ad_zero[tid].resize(max_qpts, 0);
6211  _grad_zero[tid].resize(max_qpts, RealGradient(0.));
6212  _ad_grad_zero[tid].resize(max_qpts, ADRealGradient(0));
6213  _second_zero[tid].resize(max_qpts, RealTensor(0.));
6214  _ad_second_zero[tid].resize(max_qpts, ADRealTensorValue(0));
6215  _vector_zero[tid].resize(max_qpts, RealGradient(0.));
6216  _vector_curl_zero[tid].resize(max_qpts, RealGradient(0.));
6217  }
6218 }
6219 
6220 void
6222 {
6223  for (unsigned int tid = 0; tid < libMesh::n_threads(); ++tid)
6224  for (const auto i : index_range(_nl))
6225  _assembly[tid][i]->bumpVolumeQRuleOrder(order, block);
6226 
6227  if (_displaced_problem)
6228  _displaced_problem->bumpVolumeQRuleOrder(order, block);
6229 
6230  updateMaxQps();
6231 }
6232 
6233 void
6235 {
6236  for (unsigned int tid = 0; tid < libMesh::n_threads(); ++tid)
6237  for (const auto i : index_range(_nl))
6238  _assembly[tid][i]->bumpAllQRuleOrder(order, block);
6239 
6240  if (_displaced_problem)
6241  _displaced_problem->bumpAllQRuleOrder(order, block);
6242 
6243  updateMaxQps();
6244 }
6245 
6246 void
6248  Order order,
6249  Order volume_order,
6250  Order face_order,
6251  SubdomainID block,
6252  const bool allow_negative_qweights)
6253 {
6254  if (order == INVALID_ORDER)
6255  {
6256  // automatically determine the integration order
6257  order = _solver_systems[0]->getMinQuadratureOrder();
6258  for (const auto i : make_range(std::size_t(1), _solver_systems.size()))
6259  if (order < _solver_systems[i]->getMinQuadratureOrder())
6260  order = _solver_systems[i]->getMinQuadratureOrder();
6261  if (order < _aux->getMinQuadratureOrder())
6262  order = _aux->getMinQuadratureOrder();
6263  }
6264 
6265  if (volume_order == INVALID_ORDER)
6266  volume_order = order;
6267 
6268  if (face_order == INVALID_ORDER)
6269  face_order = order;
6270 
6271  for (unsigned int tid = 0; tid < libMesh::n_threads(); ++tid)
6272  for (const auto i : index_range(_solver_systems))
6273  _assembly[tid][i]->createQRules(
6274  type, order, volume_order, face_order, block, allow_negative_qweights);
6275 
6276  if (_displaced_problem)
6277  _displaced_problem->createQRules(
6278  type, order, volume_order, face_order, block, allow_negative_qweights);
6279 
6280  updateMaxQps();
6281 }
6282 
6283 void
6285 {
6287  {
6289  mooseError("Someone told us (the FEProblemBase) to trust the user coupling matrix, but we "
6290  "haven't been provided a coupling matrix!");
6291 
6292  // We've been told to trust the user coupling matrix, so we're going to leave things alone
6293  return;
6294  }
6295 
6296  _coupling = type;
6297 }
6298 
6299 void
6301 {
6302  // TODO: Deprecate method
6304  _cm[i].reset(cm);
6305 }
6306 
6307 void
6308 FEProblemBase::setCouplingMatrix(std::unique_ptr<CouplingMatrix> cm, const unsigned int i)
6309 {
6311  _cm[i] = std::move(cm);
6312 }
6313 
6314 void
6316 {
6318  mooseError("Someone told us (the FEProblemBase) to trust the user coupling matrix, but we "
6319  "haven't been provided a coupling matrix!");
6320 
6322 }
6323 
6324 void
6326 {
6327  TIME_SECTION("setNonlocalCouplingMatrix", 5, "Setting Nonlocal Coupling Matrix");
6328 
6329  if (_nl.size() > 1)
6330  mooseError("Nonlocal kernels are weirdly stored on the FEProblem so we don't currently support "
6331  "multiple nonlinear systems with nonlocal kernels.");
6332 
6333  for (const auto nl_sys_num : index_range(_nl))
6334  {
6335  auto & nl = _nl[nl_sys_num];
6336  auto & nonlocal_cm = _nonlocal_cm[nl_sys_num];
6337  unsigned int n_vars = nl->nVariables();
6338  nonlocal_cm.resize(n_vars);
6339  const auto & vars = nl->getVariables(0);
6340  const auto & nonlocal_kernel = _nonlocal_kernels.getObjects();
6341  const auto & nonlocal_integrated_bc = _nonlocal_integrated_bcs.getObjects();
6342  for (const auto & ivar : vars)
6343  {
6344  for (const auto & kernel : nonlocal_kernel)
6345  {
6346  for (unsigned int i = ivar->number(); i < ivar->number() + ivar->count(); ++i)
6347  if (i == kernel->variable().number())
6348  for (const auto & jvar : vars)
6349  {
6350  const auto it = _var_dof_map.find(jvar->name());
6351  if (it != _var_dof_map.end())
6352  {
6353  unsigned int j = jvar->number();
6354  nonlocal_cm(i, j) = 1;
6355  }
6356  }
6357  }
6358  for (const auto & integrated_bc : nonlocal_integrated_bc)
6359  {
6360  for (unsigned int i = ivar->number(); i < ivar->number() + ivar->count(); ++i)
6361  if (i == integrated_bc->variable().number())
6362  for (const auto & jvar : vars)
6363  {
6364  const auto it = _var_dof_map.find(jvar->name());
6365  if (it != _var_dof_map.end())
6366  {
6367  unsigned int j = jvar->number();
6368  nonlocal_cm(i, j) = 1;
6369  }
6370  }
6371  }
6372  }
6373  }
6374 }
6375 
6376 bool
6377 FEProblemBase::areCoupled(const unsigned int ivar,
6378  const unsigned int jvar,
6379  const unsigned int nl_sys) const
6380 {
6381  return (*_cm[nl_sys])(ivar, jvar);
6382 }
6383 
6384 std::vector<std::pair<MooseVariableFEBase *, MooseVariableFEBase *>> &
6385 FEProblemBase::couplingEntries(const THREAD_ID tid, const unsigned int nl_sys)
6386 {
6387  return _assembly[tid][nl_sys]->couplingEntries();
6388 }
6389 
6390 std::vector<std::pair<MooseVariableFEBase *, MooseVariableFEBase *>> &
6391 FEProblemBase::nonlocalCouplingEntries(const THREAD_ID tid, const unsigned int nl_sys)
6392 {
6393  return _assembly[tid][nl_sys]->nonlocalCouplingEntries();
6394 }
6395 
6396 void
6398 {
6399  if (_initialized)
6400  return;
6401 
6402  TIME_SECTION("init", 2, "Initializing");
6403 
6404  // call executioner's preProblemInit so that it can do some setups before problem init
6406 
6407  // If we have AD and we are doing global AD indexing, then we should by default set the matrix
6408  // coupling to full. If the user has told us to trust their coupling matrix, then this call will
6409  // not do anything
6412 
6413  for (const auto i : index_range(_nl))
6414  {
6415  auto & nl = _nl[i];
6416  auto & cm = _cm[i];
6417 
6418  unsigned int n_vars = nl->nVariables();
6419  {
6420  TIME_SECTION("fillCouplingMatrix", 3, "Filling Coupling Matrix");
6421 
6422  switch (_coupling)
6423  {
6424  case Moose::COUPLING_DIAG:
6425  cm = std::make_unique<CouplingMatrix>(n_vars);
6426  for (unsigned int i = 0; i < n_vars; i++)
6427  (*cm)(i, i) = 1;
6428  break;
6429 
6430  // for full jacobian
6431  case Moose::COUPLING_FULL:
6432  cm = std::make_unique<CouplingMatrix>(n_vars);
6433  for (unsigned int i = 0; i < n_vars; i++)
6434  for (unsigned int j = 0; j < n_vars; j++)
6435  (*cm)(i, j) = 1;
6436  break;
6437 
6439  // do nothing, _cm was already set through couplingMatrix() call
6440  break;
6441  }
6442  }
6443 
6444  nl->dofMap()._dof_coupling = cm.get();
6445 
6446  // If there are no variables, make sure to pass a nullptr coupling
6447  // matrix, to avoid warnings about non-nullptr yet empty
6448  // CouplingMatrices.
6449  if (n_vars == 0)
6450  nl->dofMap()._dof_coupling = nullptr;
6451 
6452  nl->dofMap().attach_extra_sparsity_function(&extraSparsity, nl.get());
6453  nl->dofMap().attach_extra_send_list_function(&extraSendList, nl.get());
6454  _aux->dofMap().attach_extra_send_list_function(&extraSendList, _aux.get());
6455 
6456  if (!_skip_nl_system_check && _solve && n_vars == 0)
6457  mooseError("No variables specified in nonlinear system '", nl->name(), "'.");
6458  }
6459 
6460  ghostGhostedBoundaries(); // We do this again right here in case new boundaries have been added
6461 
6462  // We may have added element/nodes to the mesh in ghostGhostedBoundaries so we need to update
6463  // all of our mesh information. We need to make sure that mesh information is up-to-date before
6464  // EquationSystems::init because that will call through to updateGeomSearch (for sparsity
6465  // augmentation) and if we haven't added back boundary node information before that latter call,
6466  // then we're screwed. We'll get things like "Unable to find closest node!"
6467  _mesh.meshChanged();
6468  if (_displaced_problem)
6470 
6471  if (_mesh.doingPRefinement())
6472  {
6474  if (_displaced_problem)
6475  _displaced_problem->preparePRefinement();
6476  }
6477 
6478  // do not assemble system matrix for JFNK solve
6479  for (auto & nl : _nl)
6480  if (solverParams(nl->number())._type == Moose::ST_JFNK)
6481  nl->turnOffJacobian();
6482 
6483  for (auto & sys : _solver_systems)
6484  sys->preInit();
6485  _aux->preInit();
6486 
6487  // Build the mortar segment meshes, if they haven't been already, for a couple reasons:
6488  // 1) Get the ghosting correct for both static and dynamic meshes
6489  // 2) Make sure the mortar mesh is built for mortar constraints that live on the static mesh
6490  //
6491  // It is worth-while to note that mortar meshes that live on a dynamic mesh will be built
6492  // during residual and Jacobian evaluation because when displacements are solution variables
6493  // the mortar mesh will move and change during the course of a non-linear solve. We DO NOT
6494  // redo ghosting during non-linear solve, so for purpose 1) the below call has to be made
6495  if (!_mortar_data.initialized())
6496  updateMortarMesh();
6497 
6498  {
6499  TIME_SECTION("EquationSystems::Init", 2, "Initializing Equation Systems");
6500  es().init();
6501  }
6502 
6503  for (auto & sys : _solver_systems)
6504  sys->postInit();
6505  _aux->postInit();
6506 
6507  // Now that the equation system and the dof distribution is done, we can generate the
6508  // finite volume-related parts if needed.
6509  if (haveFV())
6511 
6512  for (auto & sys : _solver_systems)
6513  sys->update();
6514  _aux->update();
6515 
6516  for (THREAD_ID tid = 0; tid < libMesh::n_threads(); ++tid)
6517  for (const auto i : index_range(_nl))
6518  {
6519  mooseAssert(
6520  _cm[i],
6521  "Coupling matrix not set for system "
6522  << i
6523  << ". This should only happen if a preconditioner was not setup for this system");
6524  _assembly[tid][i]->init(_cm[i].get());
6525  }
6526 
6527  if (_displaced_problem)
6528  _displaced_problem->init();
6529 
6530 #ifdef MOOSE_KOKKOS_ENABLED
6531  if (_has_kokkos_objects)
6532  initKokkos();
6533 #endif
6534 
6535  _initialized = true;
6536 }
6537 
6538 unsigned int
6539 FEProblemBase::nlSysNum(const NonlinearSystemName & nl_sys_name) const
6540 {
6541  std::istringstream ss(nl_sys_name);
6542  unsigned int nl_sys_num;
6543  if (!(ss >> nl_sys_num) || !ss.eof())
6544  nl_sys_num = libmesh_map_find(_nl_sys_name_to_num, nl_sys_name);
6545 
6546  return nl_sys_num;
6547 }
6548 
6549 unsigned int
6550 FEProblemBase::linearSysNum(const LinearSystemName & linear_sys_name) const
6551 {
6552  std::istringstream ss(linear_sys_name);
6553  unsigned int linear_sys_num;
6554  if (!(ss >> linear_sys_num) || !ss.eof())
6555  linear_sys_num = libmesh_map_find(_linear_sys_name_to_num, linear_sys_name);
6556 
6557  return linear_sys_num;
6558 }
6559 
6560 unsigned int
6561 FEProblemBase::solverSysNum(const SolverSystemName & solver_sys_name) const
6562 {
6563  std::istringstream ss(solver_sys_name);
6564  unsigned int solver_sys_num;
6565  if (!(ss >> solver_sys_num) || !ss.eof())
6566  {
6567  const auto & search = _solver_sys_name_to_num.find(solver_sys_name);
6568  if (search == _solver_sys_name_to_num.end())
6569  mooseError("The solver system number was requested for system '" + solver_sys_name,
6570  "' but this system does not exist in the Problem. Systems can be added to the "
6571  "problem using the 'nl_sys_names'/'linear_sys_names' parameter.\nSystems in the "
6572  "Problem: " +
6574  solver_sys_num = search->second;
6575  }
6576 
6577  return solver_sys_num;
6578 }
6579 
6580 unsigned int
6581 FEProblemBase::systemNumForVariable(const VariableName & variable_name) const
6582 {
6583  for (const auto & solver_sys : _solver_systems)
6584  if (solver_sys->hasVariable(variable_name))
6585  return solver_sys->number();
6586  mooseAssert(_aux, "Should have an auxiliary system");
6587  if (_aux->hasVariable(variable_name))
6588  return _aux->number();
6589 
6590  mooseError("Variable '",
6591  variable_name,
6592  "' was not found in any solver (nonlinear/linear) or auxiliary system");
6593 }
6594 
6595 void
6596 FEProblemBase::solve(const unsigned int nl_sys_num)
6597 {
6598  TIME_SECTION("solve", 1, "Solving", false);
6599 
6600  setCurrentNonlinearSystem(nl_sys_num);
6601 
6602  // This prevents stale dof indices from lingering around and possibly leading to invalid reads
6603  // and writes. Dof indices may be made stale through operations like mesh adaptivity
6605  if (_displaced_problem)
6606  _displaced_problem->clearAllDofIndices();
6607 
6608  // Setup the output system for printing linear/nonlinear iteration information and some solver
6609  // settings, including setting matrix prefixes. This must occur before petscSetOptions
6611 
6612 #if PETSC_RELEASE_LESS_THAN(3, 12, 0)
6614  _petsc_options, _solver_params); // Make sure the PETSc options are setup for this app
6615 #else
6616  // Now this database will be the default
6617  // Each app should have only one database
6618  if (!_app.isUltimateMaster())
6619  LibmeshPetscCall(PetscOptionsPush(_petsc_option_data_base));
6620  // We did not add PETSc options to database yet
6622  {
6623  // Insert options for all systems all at once
6626  }
6627 #endif
6628 
6629  // set up DM which is required if use a field split preconditioner
6630  // We need to setup DM every "solve()" because libMesh destroy SNES after solve()
6631  // Do not worry, DM setup is very cheap
6633 
6635 
6636  // reset flag so that residual evaluation does not get skipped
6637  // and the next non-linear iteration does not automatically fail with
6638  // "DIVERGED_NANORINF", when we throw an exception and stop solve
6640 
6641  if (_solve)
6642  {
6645  }
6646 
6647  // sync solutions in displaced problem
6648  if (_displaced_problem)
6649  _displaced_problem->syncSolutions();
6650 
6651 #if !PETSC_RELEASE_LESS_THAN(3, 12, 0)
6652  if (!_app.isUltimateMaster())
6653  LibmeshPetscCall(PetscOptionsPop());
6654 #endif
6655 }
6656 
6657 void
6658 FEProblemBase::setException(const std::string & message)
6659 {
6660  _has_exception = true;
6661  _exception_message = message;
6662 }
6663 
6664 void
6666 {
6668  return;
6669 
6670  TIME_SECTION("checkExceptionAndStopSolve", 5);
6671 
6672  // See if any processor had an exception. If it did, get back the
6673  // processor that the exception occurred on.
6674  unsigned int processor_id;
6675 
6677 
6678  if (_has_exception)
6679  {
6681 
6684  {
6685  // Print the message
6686  if (_communicator.rank() == 0 && print_message)
6687  {
6688  _console << "\n" << _exception_message << "\n";
6689  if (isTransient())
6690  _console
6691  << "To recover, the solution will fail and then be re-attempted with a reduced time "
6692  "step.\n"
6693  << std::endl;
6694  }
6695 
6696  // Stop the solve -- this entails setting
6697  // SNESSetFunctionDomainError() or directly inserting NaNs in the
6698  // residual vector to let PETSc >= 3.6 return DIVERGED_NANORINF.
6699  if (_current_nl_sys)
6701 
6702  if (_current_linear_sys)
6704 
6705  // and close Aux system (we MUST do this here; see #11525)
6706  _aux->solution().close();
6707 
6708  // We've handled this exception, so we no longer have one.
6709  _has_exception = false;
6710 
6711  // Force the next non-linear convergence check to fail (and all further residual evaluation
6712  // to be skipped).
6714 
6715  // Repropagate the exception, so it can be caught at a higher level, typically
6716  // this is NonlinearSystem::computeResidual().
6718  }
6719  else
6720  mooseError("The following parallel-communicated exception was detected during " +
6721  Moose::stringify(_current_execute_on_flag) + " evaluation:\n" +
6723  "\nBecause this did not occur during residual evaluation, there"
6724  " is no way to handle this, so the solution is aborting.\n");
6725  }
6726 }
6727 
6728 void
6730 {
6731  // Our default state is to allow computing derivatives
6732  ADReal::do_derivatives = true;
6734 
6735  // Clear the VectorTags and MatrixTags
6738 
6741 
6745  if (_displaced_problem)
6746  {
6747  _displaced_problem->setCurrentlyComputingResidual(false);
6748  _displaced_problem->setCurrentlyComputingJacobian(false);
6749  _displaced_problem->setCurrentlyComputingResidualAndJacobian(false);
6750  }
6751 }
6752 
6753 void
6754 FEProblemBase::solveLinearSystem(const unsigned int linear_sys_num,
6756 {
6757  TIME_SECTION("solve", 1, "Solving", false);
6758 
6759  setCurrentLinearSystem(linear_sys_num);
6760 
6761  const Moose::PetscSupport::PetscOptions & options = po ? *po : _petsc_options;
6762  auto & solver_params = _solver_params[numNonlinearSystems() + linear_sys_num];
6763 
6764  // Set custom convergence criteria
6766 
6767 #if PETSC_RELEASE_LESS_THAN(3, 12, 0)
6768  LibmeshPetscCall(Moose::PetscSupport::petscSetOptions(
6769  options, solver_params)); // Make sure the PETSc options are setup for this app
6770 #else
6771  // Now this database will be the default
6772  // Each app should have only one database
6773  if (!_app.isUltimateMaster())
6774  LibmeshPetscCall(PetscOptionsPush(_petsc_option_data_base));
6775 
6776  // We did not add PETSc options to database yet
6778  {
6779  Moose::PetscSupport::petscSetOptions(options, solver_params, this);
6781  }
6782 #endif
6783 
6784  if (_solve)
6786 
6787 #if !PETSC_RELEASE_LESS_THAN(3, 12, 0)
6788  if (!_app.isUltimateMaster())
6789  LibmeshPetscCall(PetscOptionsPop());
6790 #endif
6791 }
6792 
6793 bool
6794 FEProblemBase::solverSystemConverged(const unsigned int sys_num)
6795 {
6796  if (_solve)
6797  return _solver_systems[sys_num]->converged();
6798  else
6799  return true;
6800 }
6801 
6802 unsigned int
6803 FEProblemBase::nNonlinearIterations(const unsigned int nl_sys_num) const
6804 {
6805  return _nl[nl_sys_num]->nNonlinearIterations();
6806 }
6807 
6808 unsigned int
6809 FEProblemBase::nLinearIterations(const unsigned int nl_sys_num) const
6810 {
6811  return _nl[nl_sys_num]->nLinearIterations();
6812 }
6813 
6814 Real
6815 FEProblemBase::finalNonlinearResidual(const unsigned int nl_sys_num) const
6816 {
6817  return _nl[nl_sys_num]->finalNonlinearResidual();
6818 }
6819 
6820 bool
6821 FEProblemBase::computingPreSMOResidual(const unsigned int nl_sys_num) const
6822 {
6823  return _nl[nl_sys_num]->computingPreSMOResidual();
6824 }
6825 
6826 void
6828 {
6829  TIME_SECTION("copySolutionsBackwards", 3, "Copying Solutions Backward");
6830 
6831  for (auto & sys : _solver_systems)
6832  sys->copySolutionsBackwards();
6833  _aux->copySolutionsBackwards();
6834 }
6835 
6836 void
6838 {
6839  TIME_SECTION("advanceState", 5, "Advancing State");
6840 
6841  for (auto & sys : _solver_systems)
6842  sys->copyOldSolutions();
6843  _aux->copyOldSolutions();
6844 
6845  if (_displaced_problem)
6846  {
6847  for (const auto i : index_range(_solver_systems))
6848  _displaced_problem->solverSys(i).copyOldSolutions();
6849  _displaced_problem->auxSys().copyOldSolutions();
6850  }
6851 
6853 
6855 
6858 
6861 
6864 
6865 #ifdef MOOSE_KOKKOS_ENABLED
6868 
6871 
6874 #endif
6875 }
6876 
6877 void
6879 {
6880  TIME_SECTION("restoreSolutions", 5, "Restoring Solutions");
6881 
6882  if (!_not_zeroed_tagged_vectors.empty())
6883  paramError("not_zeroed_tag_vectors",
6884  "There is currently no way to restore not-zeroed vectors.");
6885 
6886  for (auto & sys : _solver_systems)
6887  {
6888  if (_verbose_restore)
6889  _console << "Restoring solutions on system " << sys->name() << "..." << std::endl;
6890  sys->restoreSolutions();
6891  }
6892 
6893  if (_verbose_restore)
6894  _console << "Restoring solutions on Auxiliary system..." << std::endl;
6895  _aux->restoreSolutions();
6896 
6897  if (_verbose_restore)
6898  _console << "Restoring postprocessor, vector-postprocessor, and reporter data..." << std::endl;
6900 
6901  if (_displaced_problem)
6902  _displaced_problem->updateMesh();
6903 }
6904 
6905 void
6907 {
6908  TIME_SECTION("saveOldSolutions", 5, "Saving Old Solutions");
6909 
6910  for (auto & sys : _solver_systems)
6911  sys->saveOldSolutions();
6912  _aux->saveOldSolutions();
6913 }
6914 
6915 void
6917 {
6918  TIME_SECTION("restoreOldSolutions", 5, "Restoring Old Solutions");
6919 
6920  for (auto & sys : _solver_systems)
6921  sys->restoreOldSolutions();
6922  _aux->restoreOldSolutions();
6923 }
6924 
6925 void
6927 {
6928  TIME_SECTION("outputStep", 1, "Outputting");
6929 
6931 
6932  for (auto & sys : _solver_systems)
6933  sys->update();
6934  _aux->update();
6935 
6936  if (_displaced_problem)
6937  _displaced_problem->syncSolutions();
6939 
6941 }
6942 
6943 void
6945 {
6947 }
6948 
6949 void
6951 {
6953 }
6954 
6955 void
6957 {
6960 }
6961 
6962 void
6964 {
6965  TIME_SECTION("onTimestepBegin", 2);
6966 
6967  for (auto & nl : _nl)
6968  nl->onTimestepBegin();
6969 }
6970 
6971 void
6973 {
6974 }
6975 
6976 Real
6978 {
6980  // If we are any iteration type other than time (e.g. nonlinear), then temporally we are still
6981  // in the present time
6982  return time();
6983 
6984  switch (state.state)
6985  {
6986  case 0:
6987  return time();
6988 
6989  case 1:
6990  return timeOld();
6991 
6992  default:
6993  mooseError("Unhandled state ", state.state, " in FEProblemBase::getTimeFromStateArg");
6994  }
6995 }
6996 
6997 void
6998 FEProblemBase::addTimeIntegrator(const std::string & type,
6999  const std::string & name,
7000  InputParameters & parameters)
7001 {
7002  parallel_object_only();
7003 
7004  parameters.set<SubProblem *>("_subproblem") = this;
7005  logAdd("TimeIntegrator", name, type, parameters);
7006  _aux->addTimeIntegrator(type, name + ":aux", parameters);
7007  for (auto & sys : _solver_systems)
7008  sys->addTimeIntegrator(type, name + ":" + sys->name(), parameters);
7009  _has_time_integrator = true;
7010 
7011  // add vectors to store u_dot, u_dotdot, udot_old, u_dotdot_old and
7012  // solution vectors older than 2 time steps, if requested by the time
7013  // integrator
7014  _aux->addDotVectors();
7015  for (auto & nl : _nl)
7016  {
7017  nl->addDotVectors();
7018 
7019  auto tag_udot = nl->getTimeIntegrators()[0]->uDotFactorTag();
7020  if (!nl->hasVector(tag_udot))
7021  nl->associateVectorToTag(*nl->solutionUDot(), tag_udot);
7022  auto tag_udotdot = nl->getTimeIntegrators()[0]->uDotDotFactorTag();
7023  if (!nl->hasVector(tag_udotdot) && uDotDotRequested())
7024  nl->associateVectorToTag(*nl->solutionUDotDot(), tag_udotdot);
7025  }
7026 
7027  if (_displaced_problem)
7028  // Time integrator does not exist when displaced problem is created.
7029  _displaced_problem->addTimeIntegrator();
7030 }
7031 
7032 void
7033 FEProblemBase::addPredictor(const std::string & type,
7034  const std::string & name,
7035  InputParameters & parameters)
7036 {
7037  parallel_object_only();
7038 
7040  mooseError("Vector bounds cannot be used with LinearSystems!");
7041 
7042  parameters.set<SubProblem *>("_subproblem") = this;
7043  std::shared_ptr<Predictor> predictor = _factory.create<Predictor>(type, name, parameters);
7044  logAdd("Predictor", name, type, parameters);
7045 
7046  for (auto & nl : _nl)
7047  nl->setPredictor(predictor);
7048 }
7049 
7050 Real
7052 {
7053  _current_nl_sys = &sys;
7054  computeResidual(*sys.currentSolution(), sys.RHS(), sys.number());
7055  return sys.RHS().l2_norm();
7056 }
7057 
7058 Real
7060 {
7061  _current_linear_sys = &sys;
7062 
7063  // We assemble the current system to check the current residual
7066  *sys.linearImplicitSystem().rhs,
7067  /*compute fresh gradients*/ true);
7068 
7069  // Unfortunate, but we have to allocate a new vector for the residual
7070  auto residual = sys.linearImplicitSystem().rhs->clone();
7071  residual->scale(-1.0);
7072  residual->add_vector(*sys.currentSolution(), *sys.linearImplicitSystem().matrix);
7073  return residual->l2_norm();
7074 }
7075 
7076 Real
7078 {
7079  TIME_SECTION("computeResidualL2Norm", 2, "Computing L2 Norm of Residual");
7080 
7081  // We use sum the squared norms of the individual systems and then take the square root of it
7082  Real l2_norm = 0.0;
7083  for (auto sys : _nl)
7084  {
7085  const auto norm = computeResidualL2Norm(*sys);
7086  l2_norm += norm * norm;
7087  }
7088 
7089  for (auto sys : _linear_systems)
7090  {
7091  const auto norm = computeResidualL2Norm(*sys);
7092  l2_norm += norm * norm;
7093  }
7094 
7095  return std::sqrt(l2_norm);
7096 }
7097 
7098 void
7100  const NumericVector<Number> & soln,
7101  NumericVector<Number> & residual)
7102 {
7103  parallel_object_only();
7104 
7105  TIME_SECTION("computeResidualSys", 5);
7106 
7107  computeResidual(soln, residual, sys.number());
7108 }
7109 
7110 void
7112  const NumericVector<Number> & soln,
7113  NumericVector<Number> & residual)
7114 {
7115  mooseDeprecated("Please use computeResidualSys");
7116 
7117  computeResidualSys(sys, soln, residual);
7118 }
7119 
7120 void
7122  NumericVector<Number> & residual,
7123  const unsigned int nl_sys_num)
7124 {
7125  setCurrentNonlinearSystem(nl_sys_num);
7126 
7127  // We associate the residual tag with the given residual vector to make sure we
7128  // don't filter it out below
7130  const auto & residual_vector_tags = getVectorTags(Moose::VECTOR_TAG_RESIDUAL);
7131 
7132  mooseAssert(_fe_vector_tags.empty(), "This should be empty indicating a clean starting state");
7133  // We filter out tags which do not have associated vectors in the current nonlinear
7134  // system. This is essential to be able to use system-dependent residual tags.
7136 
7137  computeResidualInternal(soln, residual, _fe_vector_tags);
7138  _fe_vector_tags.clear();
7139 }
7140 
7141 void
7143  NumericVector<Number> & residual,
7144  SparseMatrix<Number> & jacobian)
7145 {
7146  try
7147  {
7148  try
7149  {
7150  // vector tags
7152  const auto & residual_vector_tags = getVectorTags(Moose::VECTOR_TAG_RESIDUAL);
7153 
7154  mooseAssert(_fe_vector_tags.empty(),
7155  "This should be empty indicating a clean starting state");
7156  // We filter out tags which do not have associated vectors in the current nonlinear
7157  // system. This is essential to be able to use system-dependent residual tags.
7159 
7161 
7162  // matrix tags
7163  {
7164  _fe_matrix_tags.clear();
7165 
7166  auto & tags = getMatrixTags();
7167  for (auto & tag : tags)
7168  _fe_matrix_tags.insert(tag.second);
7169  }
7170 
7172 
7175 
7176  for (const auto tag : _fe_matrix_tags)
7177  if (_current_nl_sys->hasMatrix(tag))
7178  {
7179  auto & matrix = _current_nl_sys->getMatrix(tag);
7180  matrix.zero();
7182  // PETSc algorithms require diagonal allocations regardless of whether there is non-zero
7183  // diagonal dependence. With global AD indexing we only add non-zero
7184  // dependence, so PETSc will scream at us unless we artificially add the diagonals.
7185  for (auto index : make_range(matrix.row_start(), matrix.row_stop()))
7186  matrix.add(index, index, 0);
7187  }
7188 
7189  _aux->zeroVariablesForResidual();
7190 
7191  unsigned int n_threads = libMesh::n_threads();
7192 
7194 
7195  // Random interface objects
7196  for (const auto & it : _random_data_objects)
7197  it.second->updateSeeds(EXEC_LINEAR);
7198 
7202  if (_displaced_problem)
7203  {
7204  _displaced_problem->setCurrentlyComputingResidual(true);
7205  _displaced_problem->setCurrentlyComputingJacobian(true);
7206  _displaced_problem->setCurrentlyComputingResidualAndJacobian(true);
7207  }
7208 
7210 
7212 
7213  for (unsigned int tid = 0; tid < n_threads; tid++)
7214  reinitScalars(tid);
7215 
7217 
7218  _aux->residualSetup();
7219 
7220  if (_displaced_problem)
7221  {
7223  _displaced_problem->updateMesh();
7225  updateMortarMesh();
7226  }
7227 
7228  for (THREAD_ID tid = 0; tid < n_threads; tid++)
7229  {
7232  }
7233 
7235 
7237 
7239 
7241 
7244 
7246 
7249  }
7250  catch (...)
7251  {
7252  handleException("computeResidualAndJacobian");
7253  }
7254  }
7255  catch (const MooseException &)
7256  {
7257  // The buck stops here, we have already handled the exception by
7258  // calling the system's stopSolve() method, it is now up to PETSc to return a
7259  // "diverged" reason during the next solve.
7260  }
7261  catch (...)
7262  {
7263  mooseError("Unexpected exception type");
7264  }
7265 
7266  resetState();
7267  _fe_vector_tags.clear();
7268  _fe_matrix_tags.clear();
7269 }
7270 
7271 void
7273  NumericVector<Number> & residual,
7274  TagID tag)
7275 {
7276  try
7277  {
7279 
7280  _current_nl_sys->associateVectorToTag(residual, tag);
7281 
7282  computeResidualTags({tag});
7283 
7285  }
7286  catch (MooseException & e)
7287  {
7288  // If a MooseException propagates all the way to here, it means
7289  // that it was thrown from a MOOSE system where we do not
7290  // (currently) properly support the throwing of exceptions, and
7291  // therefore we have no choice but to error out. It may be
7292  // *possible* to handle exceptions from other systems, but in the
7293  // meantime, we don't want to silently swallow any unhandled
7294  // exceptions here.
7295  mooseError("An unhandled MooseException was raised during residual computation. Please "
7296  "contact the MOOSE team for assistance.");
7297  }
7298 }
7299 
7300 void
7302  NumericVector<Number> & residual,
7303  const std::set<TagID> & tags)
7304 {
7305  parallel_object_only();
7306 
7307  TIME_SECTION("computeResidualInternal", 1);
7308 
7309  try
7310  {
7312 
7314 
7315  computeResidualTags(tags);
7316 
7318  }
7319  catch (MooseException & e)
7320  {
7321  // If a MooseException propagates all the way to here, it means
7322  // that it was thrown from a MOOSE system where we do not
7323  // (currently) properly support the throwing of exceptions, and
7324  // therefore we have no choice but to error out. It may be
7325  // *possible* to handle exceptions from other systems, but in the
7326  // meantime, we don't want to silently swallow any unhandled
7327  // exceptions here.
7328  mooseError("An unhandled MooseException was raised during residual computation. Please "
7329  "contact the MOOSE team for assistance.");
7330  }
7331 }
7332 
7333 void
7335  NumericVector<Number> & residual,
7336  TagID tag)
7337 {
7338  TIME_SECTION("computeResidualType", 5);
7339 
7340  try
7341  {
7343 
7345 
7347 
7349  }
7350  catch (MooseException & e)
7351  {
7352  // If a MooseException propagates all the way to here, it means
7353  // that it was thrown from a MOOSE system where we do not
7354  // (currently) properly support the throwing of exceptions, and
7355  // therefore we have no choice but to error out. It may be
7356  // *possible* to handle exceptions from other systems, but in the
7357  // meantime, we don't want to silently swallow any unhandled
7358  // exceptions here.
7359  mooseError("An unhandled MooseException was raised during residual computation. Please "
7360  "contact the MOOSE team for assistance.");
7361  }
7362 }
7363 
7364 void
7365 FEProblemBase::handleException(const std::string & calling_method)
7366 {
7367  auto create_exception_message =
7368  [&calling_method](const std::string & exception_type, const auto & exception)
7369  {
7370  return std::string("A " + exception_type + " was raised during FEProblemBase::" +
7371  calling_method + "\n" + std::string(exception.what()));
7372  };
7373 
7374  try
7375  {
7376  throw;
7377  }
7378  catch (const libMesh::LogicError & e)
7379  {
7380  setException(create_exception_message("libMesh::LogicError", e));
7381  }
7382  catch (const MooseException & e)
7383  {
7384  setException(create_exception_message("MooseException", e));
7385  }
7386  catch (const MetaPhysicL::LogicError & e)
7387  {
7389  }
7390  catch (const libMesh::PetscSolverException & e)
7391  {
7392  // One PETSc solver exception that we cannot currently recover from are new nonzero errors. In
7393  // particular I have observed the following scenario in a parallel test:
7394  // - Both processes throw because of a new nonzero during MOOSE's computeJacobianTags
7395  // - We potentially handle the exceptions nicely here
7396  // - When the matrix is closed in libMesh's libmesh_petsc_snes_solver, there is a new nonzero
7397  // throw which we do not catch here in MOOSE and the simulation terminates. This only appears
7398  // in parallel (and not all the time; a test I was examining threw with distributed mesh, but
7399  // not with replicated). In serial there are no new throws from libmesh_petsc_snes_solver.
7400  // So for uniformity of behavior across serial/parallel, we will choose to abort here and always
7401  // produce a non-zero exit code
7402  mooseError(create_exception_message("libMesh::PetscSolverException", e));
7403  }
7404  catch (const std::exception & e)
7405  {
7406  const auto message = create_exception_message("std::exception", e);
7408  mooseError(message);
7409  else
7410  setException(message);
7411  }
7412 
7414 }
7415 
7416 void
7417 FEProblemBase::computeResidualTags(const std::set<TagID> & tags)
7418 {
7419  parallel_object_only();
7420 
7421  try
7422  {
7423  try
7424  {
7425  TIME_SECTION("computeResidualTags", 5, "Computing Residual");
7426 
7427  ADReal::do_derivatives = false;
7428 
7430 
7431  _aux->zeroVariablesForResidual();
7432 
7433  unsigned int n_threads = libMesh::n_threads();
7434 
7436 
7437  // Random interface objects
7438  for (const auto & it : _random_data_objects)
7439  it.second->updateSeeds(EXEC_LINEAR);
7440 
7442 
7444 
7445  for (unsigned int tid = 0; tid < n_threads; tid++)
7446  reinitScalars(tid);
7447 
7449 
7450  _aux->residualSetup();
7451 
7452  if (_displaced_problem)
7453  {
7455  _displaced_problem->updateMesh();
7457  updateMortarMesh();
7458  }
7459 
7460  for (THREAD_ID tid = 0; tid < n_threads; tid++)
7461  {
7464  }
7465 
7467 
7469 
7471 
7473 
7476  }
7477  catch (...)
7478  {
7479  handleException("computeResidualTags");
7480  }
7481  }
7482  catch (const MooseException &)
7483  {
7484  // The buck stops here, we have already handled the exception by
7485  // calling the system's stopSolve() method, it is now up to PETSc to return a
7486  // "diverged" reason during the next solve.
7487  }
7488  catch (...)
7489  {
7490  mooseError("Unexpected exception type");
7491  }
7492 
7493  resetState();
7494 }
7495 
7496 void
7498  const NumericVector<Number> & soln,
7499  SparseMatrix<Number> & jacobian)
7500 {
7501  computeJacobian(soln, jacobian, sys.number());
7502 }
7503 
7504 void
7506  SparseMatrix<Number> & jacobian,
7507  TagID tag)
7508 {
7510 
7511  _current_nl_sys->associateMatrixToTag(jacobian, tag);
7512 
7513  computeJacobianTags({tag});
7514 
7516 }
7517 
7518 void
7520  SparseMatrix<Number> & jacobian,
7521  const unsigned int nl_sys_num)
7522 {
7523  setCurrentNonlinearSystem(nl_sys_num);
7524 
7525  _fe_matrix_tags.clear();
7526 
7527  auto & tags = getMatrixTags();
7528  for (auto & tag : tags)
7529  _fe_matrix_tags.insert(tag.second);
7530 
7531  computeJacobianInternal(soln, jacobian, _fe_matrix_tags);
7532 }
7533 
7534 void
7536  SparseMatrix<Number> & jacobian,
7537  const std::set<TagID> & tags)
7538 {
7539  TIME_SECTION("computeJacobianInternal", 1);
7540 
7542 
7544 
7545  computeJacobianTags(tags);
7546 
7548 }
7549 
7550 void
7551 FEProblemBase::computeJacobianTags(const std::set<TagID> & tags)
7552 {
7553  try
7554  {
7555  try
7556  {
7557  if (!_has_jacobian || !_const_jacobian)
7558  {
7559  TIME_SECTION("computeJacobianTags", 5, "Computing Jacobian");
7560 
7561  for (auto tag : tags)
7562  if (_current_nl_sys->hasMatrix(tag))
7563  {
7564  auto & matrix = _current_nl_sys->getMatrix(tag);
7567  else
7568  matrix.zero();
7570  // PETSc algorithms require diagonal allocations regardless of whether there is
7571  // non-zero diagonal dependence. With global AD indexing we only add non-zero
7572  // dependence, so PETSc will scream at us unless we artificially add the diagonals.
7573  for (auto index : make_range(matrix.row_start(), matrix.row_stop()))
7574  matrix.add(index, index, 0);
7575  }
7576 
7577  _aux->zeroVariablesForJacobian();
7578 
7579  unsigned int n_threads = libMesh::n_threads();
7580 
7581  // Random interface objects
7582  for (const auto & it : _random_data_objects)
7583  it.second->updateSeeds(EXEC_NONLINEAR);
7584 
7587  if (_displaced_problem)
7588  _displaced_problem->setCurrentlyComputingJacobian(true);
7589 
7592 
7593  for (unsigned int tid = 0; tid < n_threads; tid++)
7594  reinitScalars(tid);
7595 
7597 
7598  _aux->jacobianSetup();
7599 
7600  if (_displaced_problem)
7601  {
7603  _displaced_problem->updateMesh();
7604  }
7605 
7606  for (unsigned int tid = 0; tid < n_threads; tid++)
7607  {
7610  }
7611 
7613 
7615 
7617 
7619 
7621 
7623 
7624  // For explicit Euler calculations for example we often compute the Jacobian one time and
7625  // then re-use it over and over. If we're performing automatic scaling, we don't want to
7626  // use that kernel, diagonal-block only Jacobian for our actual matrix when performing
7627  // solves!
7629  _has_jacobian = true;
7630  }
7631  }
7632  catch (...)
7633  {
7634  handleException("computeJacobianTags");
7635  }
7636  }
7637  catch (const MooseException &)
7638  {
7639  // The buck stops here, we have already handled the exception by
7640  // calling the system's stopSolve() method, it is now up to PETSc to return a
7641  // "diverged" reason during the next solve.
7642  }
7643  catch (...)
7644  {
7645  mooseError("Unexpected exception type");
7646  }
7647 
7648  resetState();
7649 }
7650 
7651 void
7652 FEProblemBase::computeJacobianBlocks(std::vector<JacobianBlock *> & blocks,
7653  const unsigned int nl_sys_num)
7654 {
7655  TIME_SECTION("computeTransientImplicitJacobian", 2);
7656  setCurrentNonlinearSystem(nl_sys_num);
7657 
7658  if (_displaced_problem)
7659  {
7661  _displaced_problem->updateMesh();
7662  }
7663 
7665 
7669 }
7670 
7671 void
7673  libMesh::System & precond_system,
7674  unsigned int ivar,
7675  unsigned int jvar)
7676 {
7677  JacobianBlock jac_block(precond_system, jacobian, ivar, jvar);
7678  std::vector<JacobianBlock *> blocks = {&jac_block};
7679  mooseAssert(_current_nl_sys, "This should be non-null");
7681 }
7682 
7683 void
7685  NumericVector<Number> & lower,
7686  NumericVector<Number> & upper)
7687 {
7688  try
7689  {
7690  try
7691  {
7692  mooseAssert(_current_nl_sys && (sys.number() == _current_nl_sys->number()),
7693  "I expect these system numbers to be the same");
7694 
7695  if (!_current_nl_sys->hasVector("lower_bound") || !_current_nl_sys->hasVector("upper_bound"))
7696  return;
7697 
7698  TIME_SECTION("computeBounds", 1, "Computing Bounds");
7699 
7700  NumericVector<Number> & _lower = _current_nl_sys->getVector("lower_bound");
7701  NumericVector<Number> & _upper = _current_nl_sys->getVector("upper_bound");
7702  _lower.swap(lower);
7703  _upper.swap(upper);
7704  for (THREAD_ID tid = 0; tid < libMesh::n_threads(); tid++)
7706 
7707  _aux->residualSetup();
7709  _lower.swap(lower);
7710  _upper.swap(upper);
7711  }
7712  catch (...)
7713  {
7714  handleException("computeBounds");
7715  }
7716  }
7717  catch (MooseException & e)
7718  {
7719  mooseError("Irrecoverable exception: " + std::string(e.what()));
7720  }
7721  catch (...)
7722  {
7723  mooseError("Unexpected exception type");
7724  }
7725 }
7726 
7727 void
7729  SparseMatrix<Number> & system_matrix,
7730  NumericVector<Number> & rhs,
7731  const bool compute_gradients)
7732 {
7733  TIME_SECTION("computeLinearSystemSys", 5);
7734 
7736 
7739 
7740  // We are using the residual tag system for right hand sides so we fetch everything
7741  const auto & vector_tags = getVectorTags(Moose::VECTOR_TAG_RESIDUAL);
7742 
7743  // We filter out tags which do not have associated vectors in the current
7744  // system. This is essential to be able to use system-dependent vector tags.
7747 
7751  compute_gradients);
7752 
7757  // We reset the tags to the default containers for further operations
7762 }
7763 
7764 void
7766  const std::set<TagID> & vector_tags,
7767  const std::set<TagID> & matrix_tags,
7768  const bool compute_gradients)
7769 {
7770  TIME_SECTION("computeLinearSystemTags", 5, "Computing Linear System");
7771 
7773 
7774  for (auto tag : matrix_tags)
7775  {
7776  auto & matrix = _current_linear_sys->getMatrix(tag);
7777  matrix.zero();
7778  }
7779 
7780  unsigned int n_threads = libMesh::n_threads();
7781 
7783 
7784  // Random interface objects
7785  for (const auto & it : _random_data_objects)
7786  it.second->updateSeeds(EXEC_NONLINEAR);
7787 
7790 
7792 
7793  _aux->jacobianSetup();
7794 
7795  for (THREAD_ID tid = 0; tid < n_threads; tid++)
7796  {
7798  }
7799 
7800  try
7801  {
7803  }
7804  catch (MooseException & e)
7805  {
7806  _console << "\nA MooseException was raised during Auxiliary variable computation.\n"
7807  << "The next solve will fail, the timestep will be reduced, and we will try again.\n"
7808  << std::endl;
7809 
7810  // We know the next solve is going to fail, so there's no point in
7811  // computing anything else after this. Plus, using incompletely
7812  // computed AuxVariables in subsequent calculations could lead to
7813  // other errors or unhandled exceptions being thrown.
7814  return;
7815  }
7816 
7819 
7821 
7822  _current_linear_sys->computeLinearSystemTags(vector_tags, matrix_tags, compute_gradients);
7823 
7824  // Reset execution flag as after this point we are no longer on LINEAR
7826 
7827  // These are the relevant parts of resetState()
7830 }
7831 
7832 void
7834  std::vector<NumericVector<Number> *> & sp)
7835 {
7836  mooseAssert(_current_nl_sys && (sys.number() == _current_nl_sys->number()),
7837  "I expect these system numbers to be the same");
7838 
7839  sp.clear();
7840  for (unsigned int i = 0; i < subspaceDim("NearNullSpace"); ++i)
7841  {
7842  std::stringstream postfix;
7843  postfix << "_" << i;
7844  std::string modename = "NearNullSpace" + postfix.str();
7845  sp.push_back(&_current_nl_sys->getVector(modename));
7846  }
7847 }
7848 
7849 void
7851  std::vector<NumericVector<Number> *> & sp)
7852 {
7853  mooseAssert(_current_nl_sys && (sys.number() == _current_nl_sys->number()),
7854  "I expect these system numbers to be the same");
7855  sp.clear();
7856  for (unsigned int i = 0; i < subspaceDim("NullSpace"); ++i)
7857  {
7858  std::stringstream postfix;
7859  postfix << "_" << i;
7860  sp.push_back(&_current_nl_sys->getVector("NullSpace" + postfix.str()));
7861  }
7862 }
7863 
7864 void
7866  std::vector<NumericVector<Number> *> & sp)
7867 {
7868  mooseAssert(_current_nl_sys && (sys.number() == _current_nl_sys->number()),
7869  "I expect these system numbers to be the same");
7870  sp.clear();
7871  for (unsigned int i = 0; i < subspaceDim("TransposeNullSpace"); ++i)
7872  {
7873  std::stringstream postfix;
7874  postfix << "_" << i;
7875  sp.push_back(&_current_nl_sys->getVector("TransposeNullSpace" + postfix.str()));
7876  }
7877 }
7878 
7879 void
7881  const NumericVector<Number> & old_soln,
7882  NumericVector<Number> & search_direction,
7883  NumericVector<Number> & new_soln,
7884  bool & changed_search_direction,
7885  bool & changed_new_soln)
7886 {
7887  mooseAssert(_current_nl_sys && (sys.number() == _current_nl_sys->number()),
7888  "I expect these system numbers to be the same");
7889 
7890  // This function replaces the old PetscSupport::dampedCheck() function.
7891  //
7892  // 1.) Recreate code in PetscSupport::dampedCheck() for constructing
7893  // ghosted "soln" and "update" vectors.
7894  // 2.) Call FEProblemBase::computeDamping() with these ghost vectors.
7895  // 3.) Recreate the code in PetscSupport::dampedCheck() to actually update
7896  // the solution vector based on the damping, and set the "changed" flags
7897  // appropriately.
7898 
7899  TIME_SECTION("computePostCheck", 2, "Computing Post Check");
7900 
7902 
7903  // MOOSE's FEProblemBase doesn't update the solution during the
7904  // postcheck, but FEProblemBase-derived classes might.
7906  {
7907  // We need ghosted versions of new_soln and search_direction (the
7908  // ones we get from libmesh/PETSc are PARALLEL vectors. To make
7909  // our lives simpler, we use the same ghosting pattern as the
7910  // system's current_local_solution to create new ghosted vectors.
7911 
7912  // Construct zeroed-out clones with the same ghosted dofs as the
7913  // System's current_local_solution.
7914  std::unique_ptr<NumericVector<Number>> ghosted_solution =
7915  sys.current_local_solution->zero_clone(),
7916  ghosted_search_direction =
7917  sys.current_local_solution->zero_clone();
7918 
7919  // Copy values from input vectors into clones with ghosted values.
7920  *ghosted_solution = new_soln;
7921  *ghosted_search_direction = search_direction;
7922 
7923  if (_has_dampers)
7924  {
7925  // Compute the damping coefficient using the ghosted vectors
7926  Real damping = computeDamping(*ghosted_solution, *ghosted_search_direction);
7927 
7928  // If some non-trivial damping was computed, update the new_soln
7929  // vector accordingly.
7930  if (damping < 1.0)
7931  {
7932  new_soln = old_soln;
7933  new_soln.add(-damping, search_direction);
7934  changed_new_soln = true;
7935  }
7936  }
7937 
7938  if (shouldUpdateSolution())
7939  {
7940  // Update the ghosted copy of the new solution, if necessary.
7941  if (changed_new_soln)
7942  *ghosted_solution = new_soln;
7943 
7944  bool updated_solution = updateSolution(new_soln, *ghosted_solution);
7945  if (updated_solution)
7946  changed_new_soln = true;
7947  }
7948  }
7949 
7951  {
7953  _aux->copyCurrentIntoPreviousNL();
7954  }
7955 
7956  // MOOSE doesn't change the search_direction
7957  changed_search_direction = false;
7958 
7960 }
7961 
7962 Real
7964  const NumericVector<Number> & update)
7965 {
7966  // Default to no damping
7967  Real damping = 1.0;
7968 
7969  if (_has_dampers)
7970  {
7971  TIME_SECTION("computeDamping", 1, "Computing Damping");
7972 
7973  // Save pointer to the current solution
7974  const NumericVector<Number> * _saved_current_solution = _current_nl_sys->currentSolution();
7975 
7977  // For now, do not re-compute auxiliary variables. Doing so allows a wild solution increment
7978  // to get to the material models, which may not be able to cope with drastically different
7979  // values. Once more complete dependency checking is in place, auxiliary variables (and
7980  // material properties) will be computed as needed by dampers.
7981  // _aux.compute();
7982  damping = _current_nl_sys->computeDamping(soln, update);
7983 
7984  // restore saved solution
7985  _current_nl_sys->setSolution(*_saved_current_solution);
7986  }
7987 
7988  return damping;
7989 }
7990 
7991 bool
7993 {
7994  return false;
7995 }
7996 
7997 bool
7999  NumericVector<Number> & /*ghosted_solution*/)
8000 {
8001  return false;
8002 }
8003 
8004 void
8006 {
8007 }
8008 
8009 void
8010 FEProblemBase::addDisplacedProblem(std::shared_ptr<DisplacedProblem> displaced_problem)
8011 {
8012  parallel_object_only();
8013 
8016 }
8017 
8018 void
8020 {
8021  TIME_SECTION("updateGeometricSearch", 3, "Updating Geometric Search");
8022 
8024 
8025  if (_displaced_problem)
8026  _displaced_problem->updateGeomSearch(type);
8027 }
8028 
8029 void
8031 {
8032  TIME_SECTION("updateMortarMesh", 5, "Updating Mortar Mesh");
8033 
8034  FloatingPointExceptionGuard fpe_guard(_app);
8035 
8036  _mortar_data.update();
8037 }
8038 
8039 void
8041  const std::pair<BoundaryID, BoundaryID> & primary_secondary_boundary_pair,
8042  const std::pair<SubdomainID, SubdomainID> & primary_secondary_subdomain_pair,
8043  bool on_displaced,
8044  bool periodic,
8045  const bool debug,
8046  const bool correct_edge_dropping,
8047  const Real minimum_projection_angle)
8048 {
8049  _has_mortar = true;
8050 
8051  if (on_displaced)
8052  return _mortar_data.createMortarInterface(primary_secondary_boundary_pair,
8053  primary_secondary_subdomain_pair,
8055  on_displaced,
8056  periodic,
8057  debug,
8058  correct_edge_dropping,
8059  minimum_projection_angle);
8060  else
8061  return _mortar_data.createMortarInterface(primary_secondary_boundary_pair,
8062  primary_secondary_subdomain_pair,
8063  *this,
8064  on_displaced,
8065  periodic,
8066  debug,
8067  correct_edge_dropping,
8068  minimum_projection_angle);
8069 }
8070 
8073  const std::pair<BoundaryID, BoundaryID> & primary_secondary_boundary_pair,
8074  const std::pair<SubdomainID, SubdomainID> & primary_secondary_subdomain_pair,
8075  bool on_displaced) const
8076 {
8078  primary_secondary_boundary_pair, primary_secondary_subdomain_pair, on_displaced);
8079 }
8080 
8083  const std::pair<BoundaryID, BoundaryID> & primary_secondary_boundary_pair,
8084  const std::pair<SubdomainID, SubdomainID> & primary_secondary_subdomain_pair,
8085  bool on_displaced)
8086 {
8088  primary_secondary_boundary_pair, primary_secondary_subdomain_pair, on_displaced);
8089 }
8090 
8091 const std::unordered_map<std::pair<BoundaryID, BoundaryID>, AutomaticMortarGeneration> &
8092 FEProblemBase::getMortarInterfaces(bool on_displaced) const
8093 {
8094  return _mortar_data.getMortarInterfaces(on_displaced);
8095 }
8096 
8097 void
8099 {
8100  if (_displaced_problem) // Only need to do this if things are moving...
8101  {
8102  TIME_SECTION("possiblyRebuildGeomSearchPatches", 5, "Rebuilding Geometric Search Patches");
8103 
8104  switch (_mesh.getPatchUpdateStrategy())
8105  {
8106  case Moose::Never:
8107  break;
8108  case Moose::Iteration:
8109  // Update the list of ghosted elements at the start of the time step
8112 
8113  _displaced_problem->geomSearchData().updateGhostedElems();
8115 
8116  // The commands below ensure that the sparsity of the Jacobian matrix is
8117  // augmented at the start of the time step using neighbor nodes from the end
8118  // of the previous time step.
8119 
8121 
8122  // This is needed to reinitialize PETSc output
8124 
8125  break;
8126 
8127  case Moose::Auto:
8128  {
8129  Real max = _displaced_problem->geomSearchData().maxPatchPercentage();
8131 
8132  // If we haven't moved very far through the patch
8133  if (max < 0.4)
8134  break;
8135  }
8136  libmesh_fallthrough();
8137 
8138  // Let this fall through if things do need to be updated...
8139  case Moose::Always:
8140  // Flush output here to see the message before the reinitialization, which could take a
8141  // while
8142  _console << "\n\nUpdating geometric search patches\n" << std::endl;
8143 
8146 
8147  _displaced_problem->geomSearchData().clearNearestNodeLocators();
8149 
8151 
8152  // This is needed to reinitialize PETSc output
8154  }
8155  }
8156 }
8157 
8158 #ifdef LIBMESH_ENABLE_AMR
8159 void
8161 {
8162  unsigned int n = adaptivity().getInitialSteps();
8163  _cycles_completed = 0;
8164  if (n)
8165  {
8166  if (!_mesh.interiorLowerDBlocks().empty() || !_mesh.boundaryLowerDBlocks().empty())
8167  mooseError("HFEM does not support mesh adaptivity currently.");
8168 
8169  TIME_SECTION("initialAdaptMesh", 2, "Performing Initial Adaptivity");
8170 
8171  for (unsigned int i = 0; i < n; i++)
8172  {
8174  computeMarkers();
8175 
8177  {
8178  meshChanged(
8179  /*intermediate_change=*/false, /*contract_mesh=*/true, /*clean_refinement_flags=*/true);
8180 
8181  // reproject the initial condition
8182  projectSolution();
8183 
8185  }
8186  else
8187  {
8188  _console << "Mesh unchanged, skipping remaining steps..." << std::endl;
8189  return;
8190  }
8191  }
8192  }
8193 }
8194 
8195 bool
8197 {
8198  // reset cycle counter
8199  _cycles_completed = 0;
8200 
8202  return false;
8203 
8204  TIME_SECTION("adaptMesh", 3, "Adapting Mesh");
8205 
8206  unsigned int cycles_per_step = _adaptivity.getCyclesPerStep();
8207 
8208  bool mesh_changed = false;
8209 
8210  for (unsigned int i = 0; i < cycles_per_step; ++i)
8211  {
8212  if (!_mesh.interiorLowerDBlocks().empty() || !_mesh.boundaryLowerDBlocks().empty())
8213  mooseError("HFEM does not support mesh adaptivity currently.");
8214 
8215  // Markers were already computed once by Executioner
8216  if (_adaptivity.getRecomputeMarkersFlag() && i > 0)
8217  computeMarkers();
8218 
8219  bool mesh_changed_this_step;
8220  mesh_changed_this_step = _adaptivity.adaptMesh();
8221 
8222  if (mesh_changed_this_step)
8223  {
8224  mesh_changed = true;
8225 
8226  meshChanged(
8227  /*intermediate_change=*/true, /*contract_mesh=*/true, /*clean_refinement_flags=*/true);
8229  }
8230  else
8231  {
8232  // If the mesh didn't change, we still need to update the displaced mesh
8233  // to undo the undisplacement performed in Adaptivity::adaptMesh
8234  if (_displaced_problem)
8235  _displaced_problem->updateMesh();
8236 
8237  _console << "Mesh unchanged, skipping remaining steps..." << std::endl;
8238  break;
8239  }
8240 
8241  // Show adaptivity progress
8242  _console << std::flush;
8243  }
8244 
8245  // We're done with all intermediate changes; now get systems ready
8246  // for real if necessary.
8247  if (mesh_changed)
8248  es().reinit_systems();
8249 
8250  // Execute multi-apps that need to run after adaptivity, but before the next timestep.
8252 
8253  return mesh_changed;
8254 }
8255 #endif // LIBMESH_ENABLE_AMR
8256 
8257 void
8258 FEProblemBase::initXFEM(std::shared_ptr<XFEMInterface> xfem)
8259 {
8260  _xfem = xfem;
8261  _xfem->setMesh(&_mesh);
8262  if (_displaced_mesh)
8263  _xfem->setDisplacedMesh(_displaced_mesh);
8264 
8265  auto fill_data = [](auto & storage)
8266  {
8267  std::vector<MaterialData *> data(libMesh::n_threads());
8268  for (const auto tid : make_range(libMesh::n_threads()))
8269  data[tid] = &storage.getMaterialData(tid);
8270  return data;
8271  };
8272  _xfem->setMaterialData(fill_data(_material_props));
8273  _xfem->setBoundaryMaterialData(fill_data(_bnd_material_props));
8274 
8275  unsigned int n_threads = libMesh::n_threads();
8276  for (unsigned int i = 0; i < n_threads; ++i)
8277  for (const auto nl_sys_num : index_range(_nl))
8278  {
8279  _assembly[i][nl_sys_num]->setXFEM(_xfem);
8280  if (_displaced_problem)
8281  _displaced_problem->assembly(i, nl_sys_num).setXFEM(_xfem);
8282  }
8283 }
8284 
8285 bool
8287 {
8288  TIME_SECTION("updateMeshXFEM", 5, "Updating XFEM");
8289 
8290  bool updated = false;
8291  if (haveXFEM())
8292  {
8293  if (_xfem->updateHeal())
8294  // XFEM exodiff tests rely on a given numbering because they cannot use map = true due to
8295  // having coincident elements. While conceptually speaking we do not need to contract the
8296  // mesh, we need its call to renumber_nodes_and_elements in order to preserve these tests
8297  meshChanged(
8298  /*intermediate_change=*/false, /*contract_mesh=*/true, /*clean_refinement_flags=*/false);
8299 
8300  updated = _xfem->update(_time, _nl, *_aux);
8301  if (updated)
8302  {
8303  meshChanged(
8304  /*intermediate_change=*/false, /*contract_mesh=*/true, /*clean_refinement_flags=*/false);
8305  _xfem->initSolution(_nl, *_aux);
8306  restoreSolutions();
8307  _console << "\nXFEM update complete: Mesh modified" << std::endl;
8308  }
8309  else
8310  _console << "\nXFEM update complete: Mesh not modified" << std::endl;
8311  }
8312  return updated;
8313 }
8314 
8315 void
8316 FEProblemBase::meshChanged(const bool intermediate_change,
8317  const bool contract_mesh,
8318  const bool clean_refinement_flags)
8319 {
8320  TIME_SECTION("meshChanged", 3, "Handling Mesh Changes");
8321 
8324  _mesh.cacheChangedLists(); // Currently only used with adaptivity and stateful material
8325  // properties
8326 
8327  // Clear these out because they corresponded to the old mesh
8328  _ghosted_elems.clear();
8330 
8331  // The mesh changed. We notify the MooseMesh first, because
8332  // callbacks (e.g. for sparsity calculations) triggered by the
8333  // EquationSystems reinit may require up-to-date MooseMesh caches.
8334  _mesh.meshChanged();
8335 
8336  // If we're just going to alter the mesh again, all we need to
8337  // handle here is AMR and projections, not full system reinit
8338  if (intermediate_change)
8339  es().reinit_solutions();
8340  else
8341  es().reinit();
8342 
8343  if (contract_mesh)
8344  // Once vectors are restricted, we can delete children of coarsened elements
8345  _mesh.getMesh().contract();
8346  if (clean_refinement_flags)
8347  {
8348  // Finally clear refinement flags so that if someone tries to project vectors again without
8349  // an intervening mesh refinement to clear flags they won't run into trouble
8350  MeshRefinement refinement(_mesh.getMesh());
8351  refinement.clean_refinement_flags();
8352  }
8353 
8354  if (!intermediate_change)
8355  {
8356  // Since the mesh has changed, we need to make sure that we update any of our
8357  // MOOSE-system specific data.
8358  for (auto & sys : _solver_systems)
8359  sys->reinit();
8360  _aux->reinit();
8361  }
8362 
8363  // Updating MooseMesh first breaks other adaptivity code, unless we
8364  // then *again* update the MooseMesh caches. E.g. the definition of
8365  // "active" and "local" may have been *changed* by refinement and
8366  // repartitioning done in EquationSystems::reinit().
8367  _mesh.meshChanged();
8368 
8369  // If we have finite volume variables, we will need to recompute additional elemental/face
8370  // quantities
8373 
8374  // Let the meshChangedInterface notify the mesh changed event before we update the active
8375  // semilocal nodes, because the set of ghosted elements may potentially be updated during a mesh
8376  // changed event.
8377  for (const auto & mci : _notify_when_mesh_changes)
8378  mci->meshChanged();
8379 
8380  // Since the Mesh changed, update the PointLocator object used by DiracKernels.
8382 
8383  // Need to redo ghosting
8385 
8386  if (_displaced_problem)
8387  {
8388  _displaced_problem->meshChanged(contract_mesh, clean_refinement_flags);
8390  }
8391 
8393 
8396 
8397  // Just like we reinitialized our geometric search objects, we also need to reinitialize our
8398  // mortar meshes. Note that this needs to happen after DisplacedProblem::meshChanged because the
8399  // mortar mesh discretization will depend necessarily on the displaced mesh being re-displaced
8400  updateMortarMesh();
8401 
8402  // Nonlinear systems hold the mortar mesh functors. The domains of definition of the mortar
8403  // functors might have changed when the mesh changed.
8404  for (auto & nl_sys : _nl)
8405  nl_sys->reinitMortarFunctors();
8406 
8407  reinitBecauseOfGhostingOrNewGeomObjects(/*mortar_changed=*/true);
8408 
8409  // We need to create new storage for newly active elements, and copy
8410  // stateful properties from the old elements.
8413  {
8414  if (havePRefinement())
8416 
8417  // Prolong properties onto newly refined elements' children
8418  {
8420  /* refine = */ true, *this, _material_props, _bnd_material_props, _assembly);
8421  const auto & range = *_mesh.refinedElementRange();
8422  Threads::parallel_reduce(range, pmp);
8423 
8424  // Concurrent erasure from the shared hash map is not safe while we are reading from it in
8425  // ProjectMaterialProperties, so we handle erasure here. Moreover, erasure based on key is
8426  // not thread safe in and of itself because it is a read-write operation. Note that we do not
8427  // do the erasure for p-refinement because the coarse level element is the same as our active
8428  // refined level element
8429  if (!doingPRefinement())
8430  for (const auto & elem : range)
8431  {
8435  }
8436  }
8437 
8438  // Restrict properties onto newly coarsened elements
8439  {
8441  /* refine = */ false, *this, _material_props, _bnd_material_props, _assembly);
8442  const auto & range = *_mesh.coarsenedElementRange();
8443  Threads::parallel_reduce(range, pmp);
8444  // Note that we do not do the erasure for p-refinement because the coarse level element is the
8445  // same as our active refined level element
8446  if (!doingPRefinement())
8447  for (const auto & elem : range)
8448  {
8449  auto && coarsened_children = _mesh.coarsenedElementChildren(elem);
8450  for (auto && child : coarsened_children)
8451  {
8455  }
8456  }
8457  }
8458  }
8459 
8462 
8463  _has_jacobian = false; // we have to recompute jacobian when mesh changed
8464 
8465  // Now for backwards compatibility with user code that overrode the old no-arg meshChanged we must
8466  // call it here
8467  meshChanged();
8468 }
8469 
8470 void
8472 {
8473  _notify_when_mesh_changes.push_back(mci);
8474 }
8475 
8476 void
8478 {
8479  _notify_when_mesh_displaces.push_back(mdi);
8480 }
8481 
8482 void
8484 {
8485  for (const auto & mdi : _notify_when_mesh_displaces)
8486  mdi->meshDisplaced();
8487 }
8488 
8489 void
8490 FEProblemBase::initElementStatefulProps(const ConstElemRange & elem_range, const bool threaded)
8491 {
8494  if (threaded)
8495  Threads::parallel_reduce(elem_range, cmt);
8496  else
8497  cmt(elem_range, true);
8498 
8499 #ifdef MOOSE_KOKKOS_ENABLED
8500  if (_has_kokkos_objects)
8502 #endif
8503 }
8504 
8505 void
8507 {
8508  TIME_SECTION("checkProblemIntegrity", 5);
8509 
8510  // Subdomains specified by the "Problem/block" parameter
8511  const auto & subdomain_names = getParam<std::vector<SubdomainName>>("block");
8512  auto mesh_subdomains_vec = MooseMeshUtils::getSubdomainIDs(_mesh, subdomain_names);
8513  std::set<SubdomainID> mesh_subdomains(mesh_subdomains_vec.begin(), mesh_subdomains_vec.end());
8514 
8515  // Check kernel coverage of subdomains (blocks) in the mesh
8518  {
8519  std::set<SubdomainID> blocks;
8522  blocks = mesh_subdomains;
8524  {
8525  blocks = mesh_subdomains;
8526  for (const auto & subdomain_name : _kernel_coverage_blocks)
8527  {
8528  const auto id = _mesh.getSubdomainID(subdomain_name);
8529  if (id == Moose::INVALID_BLOCK_ID)
8530  paramError("kernel_coverage_block_list",
8531  "Subdomain \"",
8532  subdomain_name,
8533  "\" not found in mesh.");
8534  blocks.erase(id);
8535  }
8536  }
8538  for (const auto & subdomain_name : _kernel_coverage_blocks)
8539  {
8540  const auto id = _mesh.getSubdomainID(subdomain_name);
8541  if (id == Moose::INVALID_BLOCK_ID)
8542  paramError("kernel_coverage_block_list",
8543  "Subdomain \"",
8544  subdomain_name,
8545  "\" not found in mesh.");
8546  blocks.insert(id);
8547  }
8548  if (!blocks.empty())
8549  for (auto & nl : _nl)
8550  nl->checkKernelCoverage(blocks);
8551  }
8552 
8553  // Check materials
8554  {
8555 #ifdef LIBMESH_ENABLE_AMR
8556  if ((_adaptivity.isOn() || _num_grid_steps) &&
8559  {
8560  _console << "Using EXPERIMENTAL Stateful Material Property projection with Adaptivity!\n"
8561  << std::flush;
8562  }
8563 #endif
8564 
8565  std::set<SubdomainID> local_mesh_subs(mesh_subdomains);
8566 
8569  {
8574  bool check_material_coverage = false;
8575  std::set<SubdomainID> ids = _all_materials.getActiveBlocks();
8576  for (const auto & id : ids)
8577  {
8578  local_mesh_subs.erase(id);
8579  check_material_coverage = true;
8580  }
8581 
8582  // did the user limit the subdomains to be checked?
8584  {
8585  for (const auto & subdomain_name : _material_coverage_blocks)
8586  {
8587  const auto id = _mesh.getSubdomainID(subdomain_name);
8588  if (id == Moose::INVALID_BLOCK_ID)
8589  paramError("material_coverage_block_list",
8590  "Subdomain \"" + subdomain_name + "\" not found in mesh.");
8591  local_mesh_subs.erase(id);
8592  }
8593  }
8595  {
8596  std::set<SubdomainID> blocks(local_mesh_subs);
8597  for (const auto & subdomain_name : _material_coverage_blocks)
8598  {
8599  const auto id = _mesh.getSubdomainID(subdomain_name);
8600  if (id == Moose::INVALID_BLOCK_ID)
8601  paramError("material_coverage_block_list",
8602  "Subdomain \"" + subdomain_name + "\" not found in mesh.");
8603  blocks.erase(id);
8604  }
8605  for (const auto id : blocks)
8606  local_mesh_subs.erase(id);
8607  }
8608 
8609  // also exclude mortar spaces from the material check
8610  auto && mortar_subdomain_ids = _mortar_data.getMortarSubdomainIDs();
8611  for (auto subdomain_id : mortar_subdomain_ids)
8612  local_mesh_subs.erase(subdomain_id);
8613 
8614  // Check Material Coverage
8615  if (check_material_coverage && !local_mesh_subs.empty())
8616  {
8617  std::stringstream extra_subdomain_ids;
8619  std::copy(local_mesh_subs.begin(),
8620  local_mesh_subs.end(),
8621  std::ostream_iterator<unsigned int>(extra_subdomain_ids, " "));
8623  std::vector<SubdomainID> local_mesh_subs_vec(local_mesh_subs.begin(),
8624  local_mesh_subs.end());
8625 
8626  mooseError("The following blocks from your input mesh do not contain an active material: " +
8627  extra_subdomain_ids.str() +
8628  "(names: " + Moose::stringify(_mesh.getSubdomainNames(local_mesh_subs_vec)) +
8629  ")\nWhen ANY mesh block contains a Material object, "
8630  "all blocks must contain a Material object.\n");
8631  }
8632  }
8633 
8634  // Check material properties on blocks and boundaries
8637 
8638  // Check that material properties exist when requested by other properties on a given block
8639  const auto & materials = _all_materials.getActiveObjects();
8640  for (const auto & material : materials)
8641  material->checkStatefulSanity();
8642 
8643  // auto mats_to_check = _materials.getActiveBlockObjects();
8644  // const auto & discrete_materials = _discrete_materials.getActiveBlockObjects();
8645  // for (const auto & map_it : discrete_materials)
8646  // for (const auto & container_element : map_it.second)
8647  // mats_to_check[map_it.first].push_back(container_element);
8650  }
8651 
8652  checkUserObjects();
8653 
8654  // Verify that we don't have any Element type/Coordinate Type conflicts
8656 
8657  // Coordinate transforms are only intended for use with MultiApps at this time. If you are not
8658  // using multiapps but still require these, contact a moose developer
8660  !hasMultiApps())
8661  mooseError("Coordinate transformation parameters, listed below, are only to be used in the "
8662  "context of application to application field transfers at this time. The mesh is "
8663  "not modified by these parameters within an application.\n"
8664  "You should likely use a 'TransformGenerator' in the [Mesh] block to achieve the "
8665  "desired mesh modification.\n\n",
8667 
8668  // If using displacements, verify that the order of the displacement
8669  // variables matches the order of the elements in the displaced
8670  // mesh.
8672 
8673  // Check for postprocessor names with same name as a scalar variable
8675 }
8676 
8677 void
8679 {
8680  if (_displaced_problem)
8681  {
8682  bool mesh_has_second_order_elements = false;
8683  for (const auto & elem : as_range(_displaced_mesh->activeLocalElementsBegin(),
8685  {
8686  if (elem->default_order() == SECOND)
8687  {
8688  mesh_has_second_order_elements = true;
8689  break;
8690  }
8691  }
8692 
8693  // We checked our local elements, so take the max over all processors.
8694  _displaced_mesh->comm().max(mesh_has_second_order_elements);
8695 
8696  // If the Mesh has second order elements, make sure the
8697  // displacement variables are second-order.
8698  if (mesh_has_second_order_elements)
8699  {
8700  const std::vector<std::string> & displacement_variables =
8701  _displaced_problem->getDisplacementVarNames();
8702 
8703  for (const auto & var_name : displacement_variables)
8704  {
8705  MooseVariableFEBase & mv =
8706  _displaced_problem->getVariable(/*tid=*/0,
8707  var_name,
8710  if (mv.order() != SECOND)
8711  mooseError("Error: mesh has SECOND order elements, so all displacement variables must be "
8712  "SECOND order.");
8713  }
8714  }
8715  }
8716 }
8717 
8718 void
8720 {
8721  // Check user_objects block coverage
8722  std::set<SubdomainID> mesh_subdomains = _mesh.meshSubdomains();
8723  std::set<SubdomainID> user_objects_blocks;
8724 
8725  // gather names of all user_objects that were defined in the input file
8726  // and the blocks that they are defined on
8727  std::set<std::string> names;
8728 
8729  std::vector<UserObject *> objects;
8731 
8732  for (const auto & obj : objects)
8733  names.insert(obj->name());
8734 
8735  // See if all referenced blocks are covered
8736  std::set<SubdomainID> difference;
8737  std::set_difference(user_objects_blocks.begin(),
8738  user_objects_blocks.end(),
8739  mesh_subdomains.begin(),
8740  mesh_subdomains.end(),
8741  std::inserter(difference, difference.end()));
8742 
8743  if (!difference.empty())
8744  {
8745  std::ostringstream oss;
8746  oss << "One or more UserObjects is referencing a nonexistent block:\n";
8747  for (const auto & id : difference)
8748  oss << id << "\n";
8749  mooseError(oss.str());
8750  }
8751 }
8752 
8753 void
8755  const std::map<SubdomainID, std::vector<std::shared_ptr<MaterialBase>>> & materials_map)
8756 {
8757  for (const auto & it : materials_map)
8758  {
8760  std::set<std::string> block_depend_props, block_supplied_props;
8761 
8762  for (const auto & mat1 : it.second)
8763  {
8764  auto & alldeps = mat1->getMatPropDependencies(); // includes requested stateful props
8765  for (auto & dep : alldeps)
8766  block_depend_props.insert(_material_prop_registry.getName(dep));
8767 
8768  // See if any of the active materials supply this property
8769  for (const auto & mat2 : it.second)
8770  {
8771  const std::set<std::string> & supplied_props = mat2->MaterialBase::getSuppliedItems();
8772  block_supplied_props.insert(supplied_props.begin(), supplied_props.end());
8773  }
8774  }
8775 
8776  // Add zero material properties specific to this block and unrestricted
8777  block_supplied_props.insert(_zero_block_material_props[it.first].begin(),
8778  _zero_block_material_props[it.first].end());
8779 
8780  // Error check to make sure all properties consumed by materials are supplied on this block
8781  std::set<std::string> difference;
8782  std::set_difference(block_depend_props.begin(),
8783  block_depend_props.end(),
8784  block_supplied_props.begin(),
8785  block_supplied_props.end(),
8786  std::inserter(difference, difference.end()));
8787 
8788  if (!difference.empty())
8789  {
8790  std::ostringstream oss;
8791  oss << "One or more Material Properties were not supplied on block ";
8792  const std::string & subdomain_name = _mesh.getSubdomainName(it.first);
8793  if (subdomain_name.length() > 0)
8794  oss << subdomain_name << " (" << it.first << ")";
8795  else
8796  oss << it.first;
8797  oss << ":\n";
8798  for (const auto & name : difference)
8799  oss << name << "\n";
8800  mooseError(oss.str());
8801  }
8802  }
8803 
8804  // This loop checks that materials are not supplied by multiple Material objects
8805  for (const auto & it : materials_map)
8806  {
8807  const auto & materials = it.second;
8808  std::set<std::string> inner_supplied, outer_supplied;
8809 
8810  for (const auto & outer_mat : materials)
8811  {
8812  // Storage for properties for this material (outer) and all other materials (inner)
8813  outer_supplied = outer_mat->getSuppliedItems();
8814  inner_supplied.clear();
8815 
8816  // Property to material map for error reporting
8817  std::map<std::string, std::set<std::string>> prop_to_mat;
8818  for (const auto & name : outer_supplied)
8819  prop_to_mat[name].insert(outer_mat->name());
8820 
8821  for (const auto & inner_mat : materials)
8822  {
8823  if (outer_mat == inner_mat)
8824  continue;
8825 
8826  // Check whether these materials are an AD pair
8827  auto outer_mat_type = outer_mat->type();
8828  auto inner_mat_type = inner_mat->type();
8829  removeSubstring(outer_mat_type, "<RESIDUAL>");
8830  removeSubstring(outer_mat_type, "<JACOBIAN>");
8831  removeSubstring(inner_mat_type, "<RESIDUAL>");
8832  removeSubstring(inner_mat_type, "<JACOBIAN>");
8833  if (outer_mat_type == inner_mat_type && outer_mat_type != outer_mat->type() &&
8834  inner_mat_type != inner_mat->type())
8835  continue;
8836 
8837  inner_supplied.insert(inner_mat->getSuppliedItems().begin(),
8838  inner_mat->getSuppliedItems().end());
8839 
8840  for (const auto & inner_supplied_name : inner_supplied)
8841  prop_to_mat[inner_supplied_name].insert(inner_mat->name());
8842  }
8843 
8844  // Test that a property isn't supplied on multiple blocks
8845  std::set<std::string> intersection;
8846  std::set_intersection(outer_supplied.begin(),
8847  outer_supplied.end(),
8848  inner_supplied.begin(),
8849  inner_supplied.end(),
8850  std::inserter(intersection, intersection.end()));
8851 
8852  if (!intersection.empty())
8853  {
8854  std::ostringstream oss;
8855  oss << "The following material properties are declared on block " << it.first
8856  << " by multiple materials:\n";
8857  oss << ConsoleUtils::indent(2) << std::setw(30) << std::left << "Material Property"
8858  << "Material Objects\n";
8859  for (const auto & outer_name : intersection)
8860  {
8861  oss << ConsoleUtils::indent(2) << std::setw(30) << std::left << outer_name;
8862  for (const auto & inner_name : prop_to_mat[outer_name])
8863  oss << inner_name << " ";
8864  oss << '\n';
8865  }
8866 
8867  mooseError(oss.str());
8868  break;
8869  }
8870  }
8871  }
8872 }
8873 
8874 void
8876 {
8878 }
8879 
8880 void
8881 FEProblemBase::setRestartFile(const std::string & file_name)
8882 {
8883  if (_app.isRecovering())
8884  {
8885  mooseInfo("Restart file ", file_name, " is NOT being used since we are performing recovery.");
8886  }
8887  else
8888  {
8889  _app.setRestart(true);
8890  _app.setRestartRecoverFileBase(file_name);
8891  mooseInfo("Using ", file_name, " for restart.");
8892  }
8893 }
8894 
8895 std::vector<VariableName>
8897 {
8898  std::vector<VariableName> names;
8899 
8900  for (auto & sys : _solver_systems)
8901  {
8902  const std::vector<VariableName> & var_names = sys->getVariableNames();
8903  names.insert(names.end(), var_names.begin(), var_names.end());
8904  }
8905 
8906  const std::vector<VariableName> & aux_var_names = _aux->getVariableNames();
8907  names.insert(names.end(), aux_var_names.begin(), aux_var_names.end());
8908 
8909  return names;
8910 }
8911 
8912 SolverParams &
8913 FEProblemBase::solverParams(const unsigned int solver_sys_num)
8914 {
8915  mooseAssert(solver_sys_num < numSolverSystems(),
8916  "Solver system number '" << solver_sys_num << "' is out of bounds. We have '"
8917  << numSolverSystems() << "' solver systems");
8918  return _solver_params[solver_sys_num];
8919 }
8920 
8921 const SolverParams &
8922 FEProblemBase::solverParams(const unsigned int solver_sys_num) const
8923 {
8924  return const_cast<FEProblemBase *>(this)->solverParams(solver_sys_num);
8925 }
8926 
8927 void
8928 FEProblemBase::registerRandomInterface(RandomInterface & random_interface, const std::string & name)
8929 {
8930  auto insert_pair = moose_try_emplace(
8931  _random_data_objects, name, std::make_unique<RandomData>(*this, random_interface));
8932 
8933  auto random_data_ptr = insert_pair.first->second.get();
8934  random_interface.setRandomDataPointer(random_data_ptr);
8935 }
8936 
8937 bool
8939 {
8940  if (_bnd_mat_side_cache[tid].find(bnd_id) == _bnd_mat_side_cache[tid].end())
8941  {
8942  auto & bnd_mat_side_cache = _bnd_mat_side_cache[tid][bnd_id];
8943  bnd_mat_side_cache = false;
8944 
8945  // Check systems
8946  if (_aux->needMaterialOnSide(bnd_id))
8947  {
8948  bnd_mat_side_cache = true;
8949  return true;
8950  }
8951  for (auto & nl : _nl)
8952  if (nl->needBoundaryMaterialOnSide(bnd_id, tid))
8953  {
8954  bnd_mat_side_cache = true;
8955  return true;
8956  }
8957 
8958  // TODO: these objects should be checked for whether they actually consume materials
8959  // NOTE: InterfaceUO can use use boundary properties too
8960  if (theWarehouse()
8961  .query()
8962  .condition<AttribThread>(tid)
8963  .condition<AttribInterfaces>(Interfaces::SideUserObject | Interfaces::DomainUserObject |
8965  .condition<AttribBoundaries>(bnd_id)
8966  .count() > 0)
8967  {
8968  bnd_mat_side_cache = true;
8969  return true;
8970  }
8971  }
8972 
8973  return _bnd_mat_side_cache[tid][bnd_id];
8974 }
8975 
8976 bool
8978 {
8979  if (_interface_mat_side_cache[tid].find(bnd_id) == _interface_mat_side_cache[tid].end())
8980  {
8981  auto & interface_mat_side_cache = _interface_mat_side_cache[tid][bnd_id];
8982  interface_mat_side_cache = false;
8983 
8984  // Aux-system has not needed interface materials so far
8985  for (auto & nl : _nl)
8986  if (nl->needInterfaceMaterialOnSide(bnd_id, tid))
8987  {
8988  interface_mat_side_cache = true;
8989  return true;
8990  }
8991 
8992  // TODO: these objects should be checked for whether they actually consume materials
8993  if (theWarehouse()
8994  .query()
8995  .condition<AttribThread>(tid)
8996  .condition<AttribInterfaces>(Interfaces::InterfaceUserObject |
8998  .condition<AttribBoundaries>(bnd_id)
8999  .count() > 0)
9000  {
9001  interface_mat_side_cache = true;
9002  return true;
9003  }
9004  else if (_interface_materials.hasActiveBoundaryObjects(bnd_id, tid))
9005  {
9006  interface_mat_side_cache = true;
9007  return true;
9008  }
9009  }
9010  return _interface_mat_side_cache[tid][bnd_id];
9011 }
9012 
9013 bool
9015 {
9016  if (_block_mat_side_cache[tid].find(subdomain_id) == _block_mat_side_cache[tid].end())
9017  {
9018  _block_mat_side_cache[tid][subdomain_id] = false;
9019 
9020  for (auto & nl : _nl)
9021  if (nl->needInternalNeighborSideMaterial(subdomain_id, tid))
9022  {
9023  _block_mat_side_cache[tid][subdomain_id] = true;
9024  return true;
9025  }
9026 
9027  // TODO: these objects should be checked for whether they actually consume materials
9028  if (theWarehouse()
9029  .query()
9030  .condition<AttribThread>(tid)
9031  .condition<AttribInterfaces>(Interfaces::InternalSideUserObject |
9033  .condition<AttribSubdomains>(subdomain_id)
9034  .count() > 0)
9035  {
9036  _block_mat_side_cache[tid][subdomain_id] = true;
9037  return true;
9038  }
9039  }
9040 
9041  return _block_mat_side_cache[tid][subdomain_id];
9042 }
9043 
9044 bool
9046 {
9048 }
9049 
9050 void
9052 {
9054  mooseError("Previous nonlinear solution is required but not added through "
9055  "Problem/previous_nl_solution_required=true");
9056 }
9057 
9058 bool
9060 {
9061  return _has_jacobian;
9062 }
9063 
9064 bool
9066 {
9067  return _const_jacobian;
9068 }
9069 
9070 void
9071 FEProblemBase::addOutput(const std::string & object_type,
9072  const std::string & object_name,
9073  InputParameters & parameters)
9074 {
9075  parallel_object_only();
9076 
9077  // Get a reference to the OutputWarehouse
9078  OutputWarehouse & output_warehouse = _app.getOutputWarehouse();
9079 
9080  // Reject the reserved names for objects not built by MOOSE
9081  if (!parameters.get<bool>("_built_by_moose") && output_warehouse.isReservedName(object_name))
9082  mooseError("The name '", object_name, "' is a reserved name for output objects");
9083 
9084  // Check that an object by the same name does not already exist; this must be done before the
9085  // object is created to avoid getting misleading errors from the Parser
9086  if (output_warehouse.hasOutput(object_name))
9087  mooseError("An output object named '", object_name, "' already exists");
9088 
9089  // Add a pointer to the FEProblemBase class
9090  parameters.addPrivateParam<FEProblemBase *>("_fe_problem_base", this);
9091 
9092  // Create common parameter exclude list
9093  std::vector<std::string> exclude;
9094  if (object_type == "Console")
9095  {
9096  exclude.push_back("execute_on");
9097 
9098  // --show-input should enable the display of the input file on the screen
9099  if (_app.getParam<bool>("show_input") && parameters.get<bool>("output_screen"))
9100  parameters.set<ExecFlagEnum>("execute_input_on") = EXEC_INITIAL;
9101  }
9102  // Need this because Checkpoint::validParams changes the default value of
9103  // execute_on
9104  else if (object_type == "Checkpoint")
9105  exclude.push_back("execute_on");
9106 
9107  // Apply the common parameters loaded with Outputs input syntax
9108  const InputParameters * common = output_warehouse.getCommonParameters();
9109  if (common)
9110  parameters.applyParameters(*common, exclude);
9111  if (common && std::find(exclude.begin(), exclude.end(), "execute_on") != exclude.end() &&
9112  common->isParamSetByUser("execute_on") && object_type != "Console")
9114  "'execute_on' parameter specified in [Outputs] block is ignored for object '" +
9115  object_name +
9116  "'.\nDefine this object in its own sub-block of [Outputs] to modify its "
9117  "execution schedule.");
9118 
9119  // Set the correct value for the binary flag for XDA/XDR output
9120  if (object_type == "XDR")
9121  parameters.set<bool>("_binary") = true;
9122  else if (object_type == "XDA")
9123  parameters.set<bool>("_binary") = false;
9124 
9125  // Adjust the checkpoint suffix if auto recovery was enabled
9126  if (object_name == "auto_recovery_checkpoint")
9127  parameters.set<std::string>("suffix") = "auto_recovery";
9128 
9129  // Create the object and add it to the warehouse
9130  std::shared_ptr<Output> output = _factory.create<Output>(object_type, object_name, parameters);
9131  logAdd("Output", object_name, object_type, parameters);
9132  output_warehouse.addOutput(output);
9133 }
9134 
9135 void
9136 FEProblemBase::haveADObjects(const bool have_ad_objects)
9137 {
9138  _have_ad_objects = have_ad_objects;
9139  if (_displaced_problem)
9140  _displaced_problem->SubProblem::haveADObjects(have_ad_objects);
9141 }
9142 
9143 const SystemBase &
9144 FEProblemBase::getSystemBase(const unsigned int sys_num) const
9145 {
9146  if (sys_num < _solver_systems.size())
9147  return *_solver_systems[sys_num];
9148 
9149  return *_aux;
9150 }
9151 
9152 SystemBase &
9153 FEProblemBase::getSystemBase(const std::string & sys_name)
9154 {
9155  if (std::find(_solver_sys_names.begin(), _solver_sys_names.end(), sys_name) !=
9156  _solver_sys_names.end())
9157  return getSystemBase(solverSysNum(sys_name));
9158  else if (sys_name == "aux0")
9159  return *_aux;
9160  else
9161  mooseError("System '" + sys_name + "' was requested from problem but does not exist.");
9162 }
9163 
9164 SystemBase &
9165 FEProblemBase::getSystemBase(const unsigned int sys_num)
9166 {
9167  if (sys_num < _solver_systems.size())
9168  return *_solver_systems[sys_num];
9169 
9170  return *_aux;
9171 }
9172 
9173 const SystemBase &
9174 FEProblemBase::systemBaseNonlinear(const unsigned int sys_num) const
9175 {
9176  mooseAssert(sys_num < _nl.size(), "System number greater than the number of nonlinear systems");
9177  return *_nl[sys_num];
9178 }
9179 
9180 SystemBase &
9181 FEProblemBase::systemBaseNonlinear(const unsigned int sys_num)
9182 {
9183  mooseAssert(sys_num < _nl.size(), "System number greater than the number of nonlinear systems");
9184  return *_nl[sys_num];
9185 }
9186 
9187 const SystemBase &
9188 FEProblemBase::systemBaseLinear(const unsigned int sys_num) const
9189 {
9190  mooseAssert(sys_num < _linear_systems.size(),
9191  "System number greater than the number of linear systems");
9192  return *_linear_systems[sys_num];
9193 }
9194 
9195 SystemBase &
9196 FEProblemBase::systemBaseLinear(const unsigned int sys_num)
9197 {
9198  mooseAssert(sys_num < _linear_systems.size(),
9199  "System number greater than the number of linear systems");
9200  return *_linear_systems[sys_num];
9201 }
9202 
9203 const SystemBase &
9204 FEProblemBase::systemBaseSolver(const unsigned int sys_num) const
9205 {
9206  mooseAssert(sys_num < _solver_systems.size(),
9207  "System number greater than the number of solver systems");
9208  return *_solver_systems[sys_num];
9209 }
9210 
9211 SystemBase &
9212 FEProblemBase::systemBaseSolver(const unsigned int sys_num)
9213 {
9214  mooseAssert(sys_num < _solver_systems.size(),
9215  "System number greater than the number of solver systems");
9216  return *_solver_systems[sys_num];
9217 }
9218 
9219 const SystemBase &
9221 {
9222  return *_aux;
9223 }
9224 
9225 SystemBase &
9227 {
9228  return *_aux;
9229 }
9230 
9231 void
9232 FEProblemBase::computingNonlinearResid(bool computing_nonlinear_residual)
9233 {
9234  parallel_object_only();
9235 
9236  if (_displaced_problem)
9237  _displaced_problem->computingNonlinearResid(computing_nonlinear_residual);
9238  _computing_nonlinear_residual = computing_nonlinear_residual;
9239 }
9240 
9241 void
9242 FEProblemBase::setCurrentlyComputingResidual(bool currently_computing_residual)
9243 {
9244  if (_displaced_problem)
9245  _displaced_problem->setCurrentlyComputingResidual(currently_computing_residual);
9246  _currently_computing_residual = currently_computing_residual;
9247 }
9248 
9249 void
9251 {
9252  // ResetDisplacedMeshThread::onNode looks up the reference mesh by ID, so we need to make sure
9253  // we undisplace before adapting the reference mesh
9254  if (_displaced_problem)
9255  _displaced_problem->undisplaceMesh();
9256 
9258  if (_displaced_problem)
9260 
9261  meshChanged(
9262  /*intermediate_change=*/false, /*contract_mesh=*/true, /*clean_refinement_flags=*/true);
9263 }
9264 
9265 void
9266 FEProblemBase::automaticScaling(bool automatic_scaling)
9267 {
9268  if (_displaced_problem)
9269  _displaced_problem->automaticScaling(automatic_scaling);
9270 
9271  SubProblem::automaticScaling(automatic_scaling);
9272 }
9273 
9274 void
9276  unsigned int side,
9277  Real tolerance,
9278  const std::vector<Point> * const pts,
9279  const std::vector<Real> * const weights,
9280  const THREAD_ID tid)
9281 {
9282  SubProblem::reinitElemFaceRef(elem, side, tolerance, pts, weights, tid);
9283 
9284  if (_displaced_problem)
9285  _displaced_problem->reinitElemFaceRef(
9286  _displaced_mesh->elemPtr(elem->id()), side, tolerance, pts, weights, tid);
9287 }
9288 
9289 void
9291  unsigned int neighbor_side,
9292  Real tolerance,
9293  const std::vector<Point> * const pts,
9294  const std::vector<Real> * const weights,
9295  const THREAD_ID tid)
9296 {
9297  SubProblem::reinitNeighborFaceRef(neighbor_elem, neighbor_side, tolerance, pts, weights, tid);
9298 
9299  if (_displaced_problem)
9300  _displaced_problem->reinitNeighborFaceRef(
9301  _displaced_mesh->elemPtr(neighbor_elem->id()), neighbor_side, tolerance, pts, weights, tid);
9302 }
9303 
9304 void
9306  const SubdomainID blk_id,
9307  std::vector<std::shared_ptr<MaterialBase>> & face_materials,
9308  std::vector<std::shared_ptr<MaterialBase>> & neighbor_materials,
9309  std::set<MooseVariableFieldBase *> & variables,
9310  const THREAD_ID tid)
9311 {
9312  if (_materials[Moose::FACE_MATERIAL_DATA].hasActiveBlockObjects(blk_id, tid))
9313  {
9314  auto & this_face_mats =
9316  for (std::shared_ptr<MaterialBase> face_mat : this_face_mats)
9317  if (face_mat->ghostable())
9318  {
9319  face_materials.push_back(face_mat);
9320  auto & var_deps = face_mat->getMooseVariableDependencies();
9321  for (auto * var : var_deps)
9322  {
9323  if (!var->isFV())
9324  mooseError(
9325  "Ghostable materials should only have finite volume variables coupled into them.");
9326  else if (face_mat->hasStatefulProperties())
9327  mooseError("Finite volume materials do not currently support stateful properties.");
9328  variables.insert(var);
9329  }
9330  }
9331  }
9332 
9333  if (_materials[Moose::NEIGHBOR_MATERIAL_DATA].hasActiveBlockObjects(blk_id, tid))
9334  {
9335  auto & this_neighbor_mats =
9337  for (std::shared_ptr<MaterialBase> neighbor_mat : this_neighbor_mats)
9338  if (neighbor_mat->ghostable())
9339  {
9340  neighbor_materials.push_back(neighbor_mat);
9341 #ifndef NDEBUG
9342  auto & var_deps = neighbor_mat->getMooseVariableDependencies();
9343  for (auto * var : var_deps)
9344  {
9345  if (!var->isFV())
9346  mooseError(
9347  "Ghostable materials should only have finite volume variables coupled into them.");
9348  else if (neighbor_mat->hasStatefulProperties())
9349  mooseError("Finite volume materials do not currently support stateful properties.");
9350  auto pr = variables.insert(var);
9351  mooseAssert(!pr.second,
9352  "We should not have inserted any new variables dependencies from our "
9353  "neighbor materials that didn't exist for our face materials");
9354  }
9355 #endif
9356  }
9357  }
9358 }
9359 
9360 void
9362  const unsigned int nqp,
9363  const THREAD_ID tid)
9364 {
9365  getMaterialData(data_type, tid).resize(nqp);
9366 }
9367 
9368 void
9369 FEProblemBase::setNonlinearConvergenceNames(const std::vector<ConvergenceName> & convergence_names)
9370 {
9371  if (convergence_names.size() != numNonlinearSystems())
9372  paramError("nonlinear_convergence",
9373  "There must be one convergence object per nonlinear system");
9374  _nonlinear_convergence_names = convergence_names;
9375 }
9376 
9377 void
9378 FEProblemBase::setMultiAppFixedPointConvergenceName(const ConvergenceName & convergence_name)
9379 {
9380  _multiapp_fixed_point_convergence_name = convergence_name;
9381 }
9382 
9383 void
9384 FEProblemBase::setSteadyStateConvergenceName(const ConvergenceName & convergence_name)
9385 {
9386  _steady_state_convergence_name = convergence_name;
9387 }
9388 
9389 const std::vector<ConvergenceName> &
9391 {
9394  mooseError("The nonlinear system convergence name(s) have not been set.");
9395 }
9396 
9397 bool
9399 {
9400  // If false,this means we have not set one, not that we are querying this too early
9401  // TODO: once there is a default linear CV object, error on the 'not set' case
9402  return _linear_convergence_names.has_value();
9403 }
9404 
9405 void
9406 FEProblemBase::setLinearConvergenceNames(const std::vector<ConvergenceName> & convergence_names)
9407 {
9408  if (convergence_names.size() != numLinearSystems())
9409  paramError("linear_convergence", "There must be one convergence object per linear system");
9410  _linear_convergence_names = convergence_names;
9411 }
9412 
9413 const std::vector<ConvergenceName> &
9415 {
9417  return *_linear_convergence_names;
9418  mooseError("The linear convergence name(s) have not been set.");
9419 }
9420 
9421 const ConvergenceName &
9423 {
9426  else
9427  mooseError("The fixed point convergence name has not been set.");
9428 }
9429 
9430 const ConvergenceName &
9432 {
9434  return _steady_state_convergence_name.value();
9435  else
9436  mooseError("The steady convergence name has not been set.");
9437 }
9438 
9439 void
9441 {
9443  // We need to setup all the nonlinear systems other than our current one which actually called
9444  // this method (so we have to make sure we don't go in a circle)
9445  for (const auto i : make_range(numNonlinearSystems()))
9446  if (i != currentNlSysNum())
9447  _nl[i]->residualSetup();
9448  // We don't setup the aux sys because that's been done elsewhere
9449  if (_displaced_problem)
9450  _displaced_problem->residualSetup();
9451 }
9452 
9453 void
9455 {
9457  // We need to setup all the nonlinear systems other than our current one which actually called
9458  // this method (so we have to make sure we don't go in a circle)
9459  for (const auto i : make_range(numNonlinearSystems()))
9460  if (i != currentNlSysNum())
9461  _nl[i]->jacobianSetup();
9462  // We don't setup the aux sys because that's been done elsewhere
9463  if (_displaced_problem)
9464  _displaced_problem->jacobianSetup();
9465 }
9466 
9469 {
9470  return mesh().coordTransform();
9471 }
9472 
9473 unsigned int
9475 {
9476  // If we don't have nonlinear systems this should be an invalid number
9477  unsigned int current_nl_sys_num = libMesh::invalid_uint;
9478  if (_nl.size())
9479  current_nl_sys_num = currentNonlinearSystem().number();
9480 
9481  return current_nl_sys_num;
9482 }
9483 
9484 unsigned int
9486 {
9487  // If we don't have linear systems this should be an invalid number
9488  unsigned int current_linear_sys_num = libMesh::invalid_uint;
9489  if (_linear_systems.size())
9490  current_linear_sys_num = currentLinearSystem().number();
9491 
9492  return current_linear_sys_num;
9493 }
9494 
9495 bool
9497 {
9498  // For now, only support printing from thread 0
9499  if (tid != 0)
9500  return false;
9501 
9504  return true;
9505  else
9506  return false;
9507 }
9508 
9509 std::vector<MortarUserObject *>
9511  const BoundaryID secondary_boundary_id,
9512  const bool displaced,
9513  const std::vector<MortarUserObject *> & mortar_uo_superset)
9514 {
9515  std::vector<MortarUserObject *> mortar_uos;
9516  auto * const subproblem = displaced ? static_cast<SubProblem *>(_displaced_problem.get())
9517  : static_cast<SubProblem *>(this);
9518  for (auto * const obj : mortar_uo_superset)
9519  if (obj->onInterface(primary_boundary_id, secondary_boundary_id) &&
9520  (&obj->getSubProblem() == subproblem))
9521  mortar_uos.push_back(obj);
9522 
9523  return mortar_uos;
9524 }
9525 
9526 std::vector<MortarUserObject *>
9528  const BoundaryID secondary_boundary_id,
9529  const bool displaced)
9530 {
9531  std::vector<MortarUserObject *> mortar_uos;
9532  theWarehouse()
9533  .query()
9535  .queryInto(mortar_uos);
9536  return getMortarUserObjects(primary_boundary_id, secondary_boundary_id, displaced, mortar_uos);
9537 }
9538 
9539 void
9541  const BoundaryID secondary_boundary_id,
9542  const bool displaced)
9543 {
9544  const auto mortar_uos =
9545  getMortarUserObjects(primary_boundary_id, secondary_boundary_id, displaced);
9546  for (auto * const mortar_uo : mortar_uos)
9547  {
9548  mortar_uo->setNormals();
9549  mortar_uo->reinit();
9550  }
9551 }
9552 
9553 void
9555 {
9556  _verbose_setup = verbose ? "true" : "false";
9557  _verbose_multiapps = verbose;
9558  _verbose_restore = verbose;
9559 }
9560 
9561 void
9562 FEProblemBase::setCurrentLowerDElem(const Elem * const lower_d_elem, const THREAD_ID tid)
9563 {
9564  SubProblem::setCurrentLowerDElem(lower_d_elem, tid);
9565  if (_displaced_problem)
9566  _displaced_problem->setCurrentLowerDElem(
9567  lower_d_elem ? _displaced_mesh->elemPtr(lower_d_elem->id()) : nullptr, tid);
9568 }
9569 
9570 void
9572 {
9574  if (_displaced_problem)
9575  _displaced_problem->setCurrentBoundaryID(bid, tid);
9576 }
9577 
9578 void
9579 FEProblemBase::setCurrentNonlinearSystem(const unsigned int nl_sys_num)
9580 {
9581  mooseAssert(nl_sys_num < _nl.size(),
9582  "System number greater than the number of nonlinear systems");
9583  _current_nl_sys = _nl[nl_sys_num].get();
9585 }
9586 
9587 void
9588 FEProblemBase::setCurrentLinearSystem(const unsigned int sys_num)
9589 {
9590  mooseAssert(sys_num < _linear_systems.size(),
9591  "System number greater than the number of linear systems");
9592  _current_linear_sys = _linear_systems[sys_num].get();
9594 }
9595 
9596 void
9598 {
9599  // When performing an adjoint solve in the optimization module, the current solver system is the
9600  // adjoint. However, the adjoint solve requires having accurate time derivative calculations for
9601  // the forward system. The cleanest way to handle such uses is just to compute the time
9602  // derivatives for all solver systems instead of trying to guess which ones we need and don't need
9603  for (auto & solver_sys : _solver_systems)
9604  solver_sys->compute(type);
9605 
9606  _aux->compute(type);
9607 }
9608 
9609 const ConstElemRange &
9611 {
9614 
9616 }
9617 const ConstNodeRange &
9619 {
9621  return *_mesh.getLocalNodeRange();
9622 
9624 }
9625 const ConstBndNodeRange &
9627 {
9629  return *_mesh.getBoundaryNodeRange();
9630 
9632 }
9633 
9634 void
9636 {
9637  if (!range)
9638  {
9640  return;
9641  }
9642 
9643  _current_algebraic_elem_range = std::make_unique<ConstElemRange>(*range);
9644 }
9645 void
9647 {
9648  if (!range)
9649  {
9651  return;
9652  }
9653 
9654  _current_algebraic_node_range = std::make_unique<ConstNodeRange>(*range);
9655 }
9656 void
9658 {
9659  if (!range)
9660  {
9662  return;
9663  }
9664 
9665  _current_algebraic_bnd_node_range = std::make_unique<ConstBndNodeRange>(*range);
9666 }
9667 
9668 unsigned short
9670 {
9671  return _current_ic_state;
9672 }
9673 
9674 std::string
9675 FEProblemBase::solverTypeString(const unsigned int solver_sys_num)
9676 {
9677  return Moose::stringify(solverParams(solver_sys_num)._type);
9678 }
9679 
9682 {
9683  SolverParams solver_params;
9684  solver_params._type = Moose::SolveType::ST_LINEAR;
9686  return solver_params;
9687 }
9688 
9691 {
9692  return _nonlocal_cm[i];
9693 }
9694 
9695 bool
9697 {
9699 }
bool _reinit_displaced_elem
Whether to call DisplacedProblem::reinitElem when this->reinitElem is called.
This class determines the maximum number of Quadrature Points and Shape Functions used for a given si...
Definition: MaxQpsThread.h:27
virtual void addInterfaceMaterial(const std::string &material_name, const std::string &name, InputParameters &parameters)
std::map< NonlinearSystemName, unsigned int > _nl_sys_name_to_num
Map from nonlinear system name to number.
void setCurrentAlgebraicElementRange(libMesh::ConstElemRange *range)
These functions allow setting custom ranges for the algebraic elements, nodes, and boundary nodes tha...
std::string indent(unsigned int spaces)
Create empty string for indenting.
Definition: ConsoleUtils.C:41
void addControllableParameterConnection(const MooseObjectParameterName &primary, const MooseObjectParameterName &secondary, bool error_on_empty=true)
Method for linking control parameters of different names.
std::vector< Point > _point_zero
Interface for objects that need parallel consistent random numbers without patterns over the course o...
void updateVariableDependency(std::set< MooseVariableFieldBase *> &needed_moose_vars, THREAD_ID tid=0) const
Update variable dependency vector.
virtual void addCachedResidual(const THREAD_ID tid)
Definition: SubProblem.C:1310
virtual void computeJacobianTag(const NumericVector< libMesh::Number > &soln, libMesh::SparseMatrix< libMesh::Number > &jacobian, TagID tag)
Form a Jacobian matrix for a given tag.
void addObject(std::shared_ptr< T > object, THREAD_ID tid=0, bool recurse=true) override
Adds an object to the storage structure.
unsigned short getCurrentICState()
Retrieves the current initial condition state.
void finalizeMultiApps()
virtual void addFVInitialCondition(const std::string &ic_name, const std::string &name, InputParameters &parameters)
Add an initial condition for a finite volume variables.
bool adaptMesh(std::string marker_name=std::string())
Adapts the mesh based on the error estimator used.
Definition: Adaptivity.C:131
void sort(THREAD_ID tid=0)
Sort the objects using the DependencyResolver.
VarFieldType
Definition: MooseTypes.h:722
virtual void addMaterialHelper(std::vector< MaterialWarehouse *> warehouse, const std::string &material_name, const std::string &name, InputParameters &parameters)
bool initialAdaptMesh()
Used during initial adaptivity.
Definition: Adaptivity.C:268
virtual void residualSetup(THREAD_ID tid=0) const
virtual bool hasVariable(const std::string &var_name) const override
Whether or not this problem has the variable.
virtual void stopSolve(const ExecFlagType &exec_flag, const std::set< TagID > &vector_tags_to_close) override
Quit the current solve as soon as possible.
Definition: LinearSystem.C:339
bool hasInvalidSolutionError() const
Whether or not an invalid solution was encountered that was an error.
void mooseInfo(Args &&... args) const
Definition: MooseBase.h:321
void setActiveMaterialProperties(const std::unordered_set< unsigned int > &mat_prop_ids, const THREAD_ID tid)
Record and set the material properties required by the current computing thread.
const bool _regard_general_exceptions_as_errors
If we catch an exception during residual/Jacobian evaluaton for which we don&#39;t have specific handling...
const std::size_t _num_nl_sys
The number of nonlinear systems.
void setVariableAllDoFMap(const std::vector< const MooseVariableFEBase *> &moose_vars)
void computeJacobianBlocks(std::vector< JacobianBlock *> &blocks)
Computes several Jacobian blocks simultaneously, summing their contributions into smaller preconditio...
virtual void initPetscOutputAndSomeSolverSettings()
Reinitialize PETSc output for proper linear/nonlinear iteration display.
const std::vector< ConvergenceName > & getNonlinearConvergenceNames() const
Gets the nonlinear system convergence object name(s).
MetaPhysicL::DualNumber< V, D, asd > abs(const MetaPhysicL::DualNumber< V, D, asd > &a)
Definition: EigenADReal.h:42
void timestepSetup() override
virtual void addSampler(const std::string &type, const std::string &name, InputParameters &parameters)
The following functions will enable MOOSE to have the capability to import Samplers.
bool _skip_exception_check
If or not skip &#39;exception and stop solve&#39;.
const std::vector< std::string > & get_global_var_names()
bool isFiniteVolumeInfoDirty() const
Definition: MooseMesh.h:1322
Helper class for holding the preconditioning blocks to fill.
virtual void restore_original_nonzero_pattern()
bool _reinit_displaced_neighbor
Whether to call DisplacedProblem::reinitNeighbor when this->reinitNeighbor is called.
virtual void clearActiveFEVariableCoupleableMatrixTags(const THREAD_ID tid)
Definition: SubProblem.C:385
void outputStep(ExecFlagType type)
Calls the outputStep method for each output object.
virtual void meshChanged()
Deprecated.
virtual void addDamper(const std::string &damper_name, const std::string &name, InputParameters &parameters)
std::map< LinearSystemName, unsigned int > _linear_sys_name_to_num
Map from linear system name to number.
virtual void clearActiveFEVariableCoupleableVectorTags(const THREAD_ID tid)
Definition: SubProblem.C:379
libMesh::ConstElemRange * getActiveLocalElementRange()
Return pointers to range objects for various types of ranges (local nodes, boundary elems...
Definition: MooseMesh.C:1276
void getFVMatsAndDependencies(SubdomainID block_id, std::vector< std::shared_ptr< MaterialBase >> &face_materials, std::vector< std::shared_ptr< MaterialBase >> &neighbor_materials, std::set< MooseVariableFieldBase *> &variables, const THREAD_ID tid)
Get the materials and variables potentially needed for FV.
std::vector< MooseArray< ADRealTensorValue > > _ad_second_zero
bool _have_ad_objects
AD flag indicating whether any AD objects have been added.
Definition: SubProblem.h:1116
void shift()
Shift the material properties in time.
virtual void prepareFace(const Elem *elem, const THREAD_ID tid) override
Base class for function objects.
Definition: Function.h:36
void setPreserveMatrixSparsityPattern(bool preserve)
Set whether the sparsity pattern of the matrices being formed during the solve (usually the Jacobian)...
void reinitBecauseOfGhostingOrNewGeomObjects(bool mortar_changed=false)
Call when it is possible that the needs for ghosted elements has changed.
void fill_data(std::map< processor_id_type, std::vector< std::set< unsigned int >>> &data, int M)
virtual void addTransfer(const std::string &transfer_name, const std::string &name, InputParameters &parameters)
Add a Transfer to the problem.
KOKKOS_INLINE_FUNCTION const T * find(const T &target, const T *const begin, const T *const end)
Find a value in an array.
Definition: KokkosUtils.h:30
const std::string & getBoundaryName(BoundaryID boundary_id) const
Return the name of the boundary given the id.
Definition: MooseMesh.C:1830
virtual libMesh::System & getSystem(const std::string &var_name) override
Returns the equation system containing the variable provided.
virtual void setActiveScalarVariableCoupleableMatrixTags(std::set< TagID > &mtags, const THREAD_ID tid)
Definition: SubProblem.C:403
static const std::string app_param
The name of the parameter that contains the MooseApp.
Definition: MooseBase.h:59
A MultiMooseEnum object to hold "execute_on" flags.
Definition: ExecFlagEnum.h:21
static SolverParams makeLinearSolverParams()
Make basic solver params for linear solves.
Order
bool _parallel_barrier_messaging
Whether or not information about how many transfers have completed is printed.
MooseVariableFieldBase & getVariableHelper(const THREAD_ID tid, const std::string &var_name, Moose::VarKindType expected_var_type, Moose::VarFieldType expected_var_field_type, const std::vector< T > &nls, const SystemBase &aux) const
Helper function called by getVariable that handles the logic for checking whether Variables of the re...
virtual void addResidualLower(const THREAD_ID tid) override
A class for creating restricted objects.
Definition: Restartable.h:28
bool isUltimateMaster() const
Whether or not this app is the ultimate master app.
Definition: MooseApp.h:820
virtual void addJacobianLowerD(const THREAD_ID tid) override
Factory & _factory
The Factory for building objects.
Definition: SubProblem.h:1049
virtual void clearActiveScalarVariableCoupleableVectorTags(const THREAD_ID tid) override
MaterialPropertyStorage & _bnd_material_props
virtual void addGhostedElem(dof_id_type elem_id) override
Will make sure that all dofs connected to elem_id are ghosted to this processor.
void setNonlocalCouplingMatrix()
Set custom coupling matrix for variables requiring nonlocal contribution.
Threads::spin_mutex get_function_mutex
void initialSetup()
Calls the initialSetup function for each of the output objects.
virtual Real & time() const
virtual const char * what() const
Get out the error message.
std::vector< std::pair< MooseVariableFEBase *, MooseVariableFEBase * > > & couplingEntries(const THREAD_ID tid, const unsigned int nl_sys_num)
const Variable & variable(unsigned int var) const
void checkDependMaterialsHelper(const std::map< SubdomainID, std::vector< std::shared_ptr< MaterialBase >>> &materials_map)
Helper method for checking Material object dependency.
void extraSparsity(libMesh::SparsityPattern::Graph &sparsity, std::vector< dof_id_type > &n_nz, std::vector< dof_id_type > &n_oz, void *context)
Free function used for a libMesh callback.
Definition: SystemBase.C:48
unsigned int n_threads()
void projectFunctionOnCustomRange(ConstElemRange &elem_range, Number(*func)(const Point &, const libMesh::Parameters &, const std::string &, const std::string &), Gradient(*func_grad)(const Point &, const libMesh::Parameters &, const std::string &, const std::string &), const libMesh::Parameters &params, const VariableName &target_var)
Project a function onto a range of elements for a given variable.
virtual void cacheResidualNeighbor(const THREAD_ID tid) override
void addDeprecatedParam(const std::string &name, const T &value, const std::string &doc_string, const std::string &deprecation_message)
ExecFlagType _current_execute_on_flag
Current execute_on flag.
const std::set< SubdomainID > & interiorLowerDBlocks() const
Definition: MooseMesh.h:1421
void clearCurrentResidualVectorTags()
Clear the current residual vector tag data structure.
unsigned int max() const
Definition: MaxQpsThread.h:39
bool hasActiveBlockObjects(THREAD_ID tid=0) const
QueryCache is a convenient way to construct and pass around (possible partially constructed) warehous...
Definition: TheWarehouse.h:208
std::shared_ptr< DisplacedProblem > displaced_problem
const unsigned int invalid_uint
virtual void reinitLowerDElem(const Elem *lower_d_elem, const THREAD_ID tid, const std::vector< Point > *const pts=nullptr, const std::vector< Real > *const weights=nullptr)
Definition: SubProblem.C:958
RelationshipManagerType
Main types of Relationship Managers.
Definition: MooseTypes.h:964
bool hasVector(const std::string &tag_name) const
Check if the named vector exists in the system.
Definition: SystemBase.C:924
unsigned int get_node_index(const Node *node_ptr) const
virtual void checkExceptionAndStopSolve(bool print_message=true)
Check to see if an exception has occurred on any processor and, if possible, force the solve to fail...
virtual void meshDisplaced()
Update data after a mesh displaced.
const std::set< BoundaryID > & getSubdomainBoundaryIds(const SubdomainID subdomain_id) const
Get the list of boundary ids associated with the given subdomain id.
Definition: MooseMesh.C:3518
std::optional< ConvergenceName > _multiapp_fixed_point_convergence_name
MultiApp fixed point convergence name.
const std::string & name() const
Definition: MooseEnumItem.h:35
MooseAppCoordTransform & coordTransform()
virtual void setActiveFEVariableCoupleableMatrixTags(std::set< TagID > &mtags, const THREAD_ID tid) override
void setCurrentAlgebraicNodeRange(libMesh::ConstNodeRange *range)
static InputParameters validParams()
Describes the parameters this object can take to setup transformations.
const AutomaticMortarGeneration & getMortarInterface(const std::pair< BoundaryID, BoundaryID > &boundary_key, const std::pair< SubdomainID, SubdomainID > &, bool on_displaced) const
Getter to retrieve the AutomaticMortarGeneration object corresponding to the boundary and subdomain k...
Definition: MortarData.C:116
SCALAR
void paramError(const std::string &param, Args... args) const
Emits an error prefixed with the file and line number of the given param (from the input file) along ...
Definition: MooseBase.h:439
const std::map< SubdomainID, std::vector< std::shared_ptr< T > > > & getActiveBlockObjects(THREAD_ID tid=0) const
unsigned int TagID
Definition: MooseTypes.h:210
Real computeDamping(const NumericVector< Number > &solution, const NumericVector< Number > &update)
Compute damping.
const T & getParam(const std::string &name) const
Retrieve a parameter for the object.
Definition: MooseBase.h:388
virtual void reinitNode(const Node *node, const THREAD_ID tid) override
virtual std::size_t numNonlinearSystems() const override
Base class for implementing interface user objects.
virtual void setPreviousNewtonSolution(const NumericVector< Number > &soln)
virtual void predictorCleanup(NumericVector< libMesh::Number > &ghosted_solution)
Perform cleanup tasks after application of predictor to solution vector.
virtual void prepare(const Elem *elem, const THREAD_ID tid) override
TagID rightHandSideVectorTag() const
Definition: LinearSystem.h:114
virtual Elem * elemPtr(const dof_id_type i)
Definition: MooseMesh.C:3134
MPI_Datatype data_type
TagID systemMatrixTag() const override
Return the Matrix Tag ID for System.
NumericVector< Number > & solution()
Definition: SystemBase.h:196
bool hasObjects(THREAD_ID tid=0) const
Convenience functions for determining if objects exist.
bool _has_jacobian
Indicates if the Jacobian was computed.
virtual bool haveFV() const override
returns true if this problem includes/needs finite volume functionality.
char ** blocks
Interface for objects acting when the mesh has been displaced.
static void uniformRefine(MooseMesh *mesh, unsigned int level=libMesh::invalid_uint)
Performs uniform refinement of the passed Mesh object.
Definition: Adaptivity.C:274
void addPrivateParam(const std::string &name, const T &value)
These method add a parameter to the InputParameters object which can be retrieved like any other para...
bool _has_dampers
Whether or not this system has any Dampers associated with it.
MooseObjectWarehouse< InternalSideIndicatorBase > _internal_side_indicators
void shift()
Shift current, old, and older material property data storages.
std::vector< SubdomainName > _kernel_coverage_blocks
const std::map< dof_id_type, std::vector< dof_id_type > > & nodeToActiveSemilocalElemMap()
If not already created, creates a map from every node to all active semilocal elements to which they ...
Definition: MooseMesh.C:1244
virtual Distribution & getDistribution(const std::string &name)
void swapBack(const Elem &elem, unsigned int side=0)
material properties for given element (and possible side)
Definition: MaterialData.C:58
bool _has_nonlocal_coupling
Indicates if nonlocal coupling is required/exists.
void setCurrentAlgebraicBndNodeRange(ConstBndNodeRange *range)
void dof_indices(const Elem *const elem, std::vector< dof_id_type > &di) const
This is the base class for Samplers as used within the Stochastic Tools module.
Definition: Sampler.h:43
Base class for predictors.
Definition: Predictor.h:28
bool areCoupled(const unsigned int ivar, const unsigned int jvar, const unsigned int nl_sys_num) const
Moose::LineSearchType _line_search
Definition: SolverParams.h:20
const std::string & getObjectName() const
const T & get() const
Get the restartable value.
Definition: Restartable.h:58
void setPostprocessorValueByName(const PostprocessorName &name, const PostprocessorValue &value, std::size_t t_index=0)
Set the value of a PostprocessorValue.
virtual void clearActiveScalarVariableCoupleableMatrixTags(const THREAD_ID tid) override
virtual void postExecute()
Method called at the end of the simulation.
void reinit(bool reinit_for_derivative_reordering=false)
Fill out the VariableValue arrays from the system solution vector.
unsigned int number() const
Get variable number coming from libMesh.
void eraseProperty(const Elem *elem)
Remove the property storage and element pointer from internal data structures Use this when elements ...
bool isSolverSystemNonlinear(const unsigned int sys_num)
Check if the solver system is nonlinear.
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:450
std::unordered_set< TagID > _not_zeroed_tagged_vectors
the list of vector tags that will not be zeroed when all other tags are
Definition: SubProblem.h:1119
void joinAndFinalize(TheWarehouse::Query query, bool isgen=false)
DISCRETE_L2
bool hasInitialBackup() const
Definition: MooseApp.h:1001
std::vector< MooseArray< ADRealVectorValue > > _ad_grad_zero
std::vector< SolverParams > _solver_params
InputParameterWarehouse & getInputParameterWarehouse()
Get the InputParameterWarehouse for MooseObjects.
Definition: MooseApp.C:2973
ExecuteMooseObjectWarehouse< Control > _control_warehouse
The control logic warehouse.
void reinitMaterialsFaceOnBoundary(const BoundaryID boundary_id, const SubdomainID blk_id, const THREAD_ID tid, const bool swap_stateful=true, const std::deque< MaterialBase *> *const reinit_mats=nullptr)
reinit materials on element faces on a boundary (internal or external) This specific routine helps us...
void updateActive(THREAD_ID tid=0) override
Updates the active objects storage.
virtual std::pair< bool, unsigned int > determineSolverSystem(const std::string &var_name, bool error_if_not_found=false) const override
Determine what solver system the provided variable name lies in.
std::unique_ptr< libMesh::ConstNodeRange > _current_algebraic_node_range
virtual void setActiveScalarVariableCoupleableMatrixTags(std::set< TagID > &mtags, const THREAD_ID tid) override
void setCoupling(Moose::CouplingType type)
Set the coupling between variables TODO: allow user-defined coupling.
constexpr std::size_t constMaxQpsPerElem
This is used for places where we initialize some qp-sized data structures that would end up being siz...
Definition: MooseTypes.h:230
const ExecFlagType & getCurrentExecuteOnFlag() const
Return/set the current execution flag.
unsigned int _cycles_completed
bool _currently_computing_jacobian
Flag to determine whether the problem is currently computing Jacobian.
Definition: SubProblem.h:1098
virtual void reinitScalars(const THREAD_ID tid, bool reinit_for_derivative_reordering=false) override
fills the VariableValue arrays for scalar variables from the solution vector
const ExecFlagEnum & getExecuteOnEnum() const
Return the app level ExecFlagEnum, this contains all the available flags for the app.
Definition: MooseApp.h:994
virtual void init() override
void add(std::shared_ptr< MooseObject > obj)
add adds a new object to the warehouse and stores attributes/metadata about it for running queries/fi...
Definition: TheWarehouse.C:116
void translateMetaPhysicLError(const MetaPhysicL::LogicError &)
emit a relatively clear error message when we catch a MetaPhysicL logic error
Definition: MooseError.C:141
virtual void getDiracElements(std::set< const Elem *> &elems) override
Fills "elems" with the elements that should be looped over for Dirac Kernels.
virtual void setActiveElementalMooseVariables(const std::set< MooseVariableFieldBase *> &moose_vars, const THREAD_ID tid)
Set the MOOSE variables to be reinited on each element.
Definition: SubProblem.C:444
void parentOutputPositionChanged()
Calls parentOutputPositionChanged() on all sub apps.
void setupDM()
Setup the PETSc DM object (when appropriate)
virtual void setCurrentBoundaryID(BoundaryID bid, const THREAD_ID tid)
sets the current boundary ID in assembly
Definition: SubProblem.C:790
virtual void addInterfaceKernel(const std::string &kernel_name, const std::string &name, InputParameters &parameters)
virtual void neighborSubdomainSetup(THREAD_ID tid=0) const
libMesh::LinearImplicitSystem & linearImplicitSystem()
Return a reference to the stored linear implicit system.
Definition: LinearSystem.h:86
bool _is_petsc_options_inserted
If or not PETSc options have been added to database.
void setCurrentlyComputingResidual(bool currently_computing_residual) final
Set whether or not the problem is in the process of computing the residual.
virtual void addMaterial(const std::string &material_name, const std::string &name, InputParameters &parameters)
virtual void lineSearch()
execute MOOSE line search
const std::vector< T > & getSortedValues()
This function also returns dependency resolved values but with a simpler single vector interface...
unsigned int getCyclesPerStep() const
Pull out the number of cycles_per_step previously set through the AdaptivityAction.
Definition: Adaptivity.h:112
virtual void setCurrentLowerDElem(const Elem *const lower_d_elem, const THREAD_ID tid)
Set the current lower dimensional element.
Definition: SubProblem.C:1385
const Elem * getLowerDElem(const Elem *, unsigned short int) const
Returns a const pointer to a lower dimensional element that corresponds to a side of a higher dimensi...
Definition: MooseMesh.C:1739
NonlocalIntegratedBC is used for solving integral terms in integro-differential equations.
virtual bool checkNonlocalCouplingRequirement() const override
virtual bool uDotDotRequested()
Get boolean flag to check whether solution second time derivative needs to be stored.
bool _has_kokkos_objects
Whether we have any Kokkos objects.
void updateErrorVectors()
Update the ErrorVectors that have been requested through calls to getErrorVector().
Definition: Adaptivity.C:372
const InputParameters & parameters() const
Get the parameters of the object.
Definition: MooseBase.h:131
unsigned short _current_ic_state
char ** vars
FORTYTHIRD
virtual void reinitNeighborPhys(const Elem *neighbor, unsigned int neighbor_side, const std::vector< Point > &physical_points, const THREAD_ID tid) override
virtual TagID addVectorTag(const TagName &tag_name, const Moose::VectorTagType type=Moose::VECTOR_TAG_RESIDUAL)
Create a Tag.
Definition: SubProblem.C:93
std::vector< MeshDisplacedInterface * > _notify_when_mesh_displaces
Objects to be notified when the mesh displaces.
std::vector< T * > & queryInto(std::vector< T *> &results, Args &&... args)
queryInto executes the query and stores the results in the given vector.
Definition: TheWarehouse.h:311
void trustUserCouplingMatrix()
Whether to trust the user coupling matrix even if we want to do things like be paranoid and create a ...
virtual void newAssemblyArray(std::vector< std::shared_ptr< SolverSystem >> &solver_systems)
const bool _uo_aux_state_check
Whether or not checking the state of uo/aux evaluation.
virtual const std::set< MooseVariableFieldBase * > & getActiveElementalMooseVariables(const THREAD_ID tid) const
Get the MOOSE variables to be reinited on each element.
Definition: SubProblem.C:455
This is a template class that implements the workhorse compute and computeNodal methods.
virtual void addMeshDivision(const std::string &type, const std::string &name, InputParameters &params)
Add a MeshDivision.
const ExecFlagType EXEC_NONE
Definition: Moose.C:29
A struct for storing the various types of petsc options and values.
Definition: PetscSupport.h:44
virtual void computeMarkers()
void reportMooseObjectDependency(MooseObject *a, MooseObject *b)
Register a MOOSE object dependency so we can either order operations properly or report when we canno...
void residualSetup() override
MaterialDataType
MaterialData types.
Definition: MooseTypes.h:692
void computeUserObjectsInternal(const ExecFlagType &type, const Moose::AuxGroup &group, TheWarehouse::Query &query)
TagID nonTimeVectorTag() const override
A class for "pretty printing" a table of data.
Definition: PerfGraph.h:34
virtual void addCachedJacobian(const THREAD_ID tid)
Definition: SubProblem.C:1331
void cacheChangedLists()
Cache information about what elements were refined and coarsened in the previous step.
Definition: MooseMesh.C:928
virtual void residualSetup()
Definition: SubProblem.C:1204
Positions objects are under the hood Reporters.
Definition: Positions.h:20
T & set(const std::string &name, bool quiet_mode=false)
Returns a writable reference to the named parameters.
void reinitMortarUserObjects(BoundaryID primary_boundary_id, BoundaryID secondary_boundary_id, bool displaced)
Call reinit on mortar user objects with matching primary boundary ID, secondary boundary ID...
virtual TagID systemMatrixTag() const override
Return the Matrix Tag ID for System.
Definition: LinearSystem.h:115
virtual void associateVectorToTag(NumericVector< Number > &vec, TagID tag)
Associate a vector for a given tag.
Definition: SystemBase.C:981
virtual void reinitNodes(const std::vector< dof_id_type > &nodes, const THREAD_ID tid) override
virtual void updateActiveObjects()
Update the active objects in the warehouses.
Stores the stateful material properties computed by materials.
const RestartableEquationSystems & getRestartableEquationSystems() const
Get the RestartableEquationSystems object.
virtual void computeIndicatorsAndMarkers()
Definition: Marker.h:41
void reinitMaterialsBoundary(BoundaryID boundary_id, const THREAD_ID tid, bool swap_stateful=true, const std::deque< MaterialBase *> *reinit_mats=nullptr)
reinit materials on a boundary
virtual void addJacobianOffDiagScalar(unsigned int ivar, const THREAD_ID tid=0)
virtual void setException(const std::string &message)
Set an exception, which is stored at this point by toggling a member variable in this class...
virtual void addJacobian(const THREAD_ID tid) override
void addFunctor(const std::string &name, const Moose::FunctorBase< T > &functor, const THREAD_ID tid)
add a functor to the problem functor container
Definition: SubProblem.h:1380
virtual libMesh::System & system()=0
Get the reference to the libMesh system.
std::filesystem::path restartFolderBase(const std::filesystem::path &folder_base) const
The file suffix for restartable data.
Definition: MooseApp.C:3160
virtual void addAuxScalarKernel(const std::string &kernel_name, const std::string &name, InputParameters &parameters)
virtual void customSetup(const ExecFlagType &exec_type, THREAD_ID tid=0) const
bool isReservedName(const std::string &name)
Test if the given name is reserved.
bool globalADIndexing()
Whether we are using global AD indexing.
Definition: ADUtils.h:28
bool hasOutput(const std::string &name) const
Returns true if the output object exists.
Base class for MOOSE-based applications.
Definition: MooseApp.h:103
void mooseInfoRepeated(Args &&... args)
Emit an informational message with the given stringified, concatenated args.
Definition: MooseError.h:398
PetscOptions _petsc_option_data_base
bool needBoundaryMaterialOnSide(BoundaryID bnd_id, const THREAD_ID tid)
These methods are used to determine whether stateful material properties need to be stored on interna...
virtual const std::vector< VectorTag > & currentResidualVectorTags() const override
Return the residual vector tags we are currently computing.
processor_id_type rank() const
The main MOOSE class responsible for handling user-defined parameters in almost every MOOSE system...
std::vector< SubdomainName > _material_coverage_blocks
bool computingScalingJacobian() const
Whether we are computing an initial Jacobian for automatic variable scaling.
Definition: SystemBase.C:1552
TODO: delete this later - it is a temporary hack for dealing with inter-system dependencies.
Definition: Attributes.h:313
NumericVector< Number > * rhs
void setSteadyStateConvergenceName(const ConvergenceName &convergence_name)
Sets the steady-state detection convergence object name if there is one.
void applyParameters(const InputParameters &common, const std::vector< std::string > &exclude={}, const bool allow_private=false)
Method for applying common parameters.
virtual void addAuxScalarVariable(const std::string &var_name, libMesh::Order order, Real scale_factor=1., const std::set< SubdomainID > *const active_subdomains=NULL)
bool initialized() const
Definition: MortarData.h:127
virtual const SystemBase & systemBaseLinear(unsigned int sys_num) const override
Get a constant base class reference to a linear system.
const Parallel::Communicator & comm() const
void logAdd(const std::string &system, const std::string &name, const std::string &type, const InputParameters &params) const
Output information about the object just added to the problem.
QuadratureType
virtual bool hasScalarVariable(const std::string &var_name) const override
Returns a Boolean indicating whether any system contains a variable with the name provided...
void setSolution(const NumericVector< Number > &soln)
Set the solution to a given vector.
Definition: SolverSystem.C:67
MultiApp Implementation for Transient Apps.
Solving a linear problem.
Definition: MooseTypes.h:849
void resizeMaterialData(Moose::MaterialDataType data_type, unsigned int nqp, const THREAD_ID tid)
Resize material data.
void finishMultiAppStep(ExecFlagType type, bool recurse_through_multiapp_levels=false)
Finish the MultiApp time step (endStep, postStep) associated with the ExecFlagType.
virtual void addFunctorMaterial(const std::string &functor_material_name, const std::string &name, InputParameters &parameters)
virtual void timestepSetup(THREAD_ID tid=0) const
std::vector< VariableSecond > _second_zero
std::map< SolverVariableName, unsigned int > _solver_var_to_sys_num
Map connecting variable names with their respective solver systems.
virtual std::unique_ptr< NumericVector< T > > clone() const=0
std::vector< MooseArray< ADReal > > _ad_zero
void customSetup(const ExecFlagType &exec_type)
Calls the setup function for each of the output objects.
virtual bool hasMatrix(TagID tag) const
Check if the tagged matrix exists in the system.
Definition: SystemBase.h:360
bool _requires_nonlocal_coupling
nonlocal coupling requirement flag
virtual void onTimestepEnd() override
virtual void computeNearNullSpace(libMesh::NonlinearImplicitSystem &sys, std::vector< NumericVector< libMesh::Number > *> &sp)
virtual void addNodalKernel(const std::string &kernel_name, const std::string &name, InputParameters &parameters)
std::vector< std::shared_ptr< SolverSystem > > _solver_systems
Combined container to base pointer of every solver system.
All Distributions should inherit from this class.
Definition: Distribution.h:18
void setCurrentDirection(const int direction)
Set this Transfer to be executed in a given direction.
Definition: Transfer.h:89
std::unique_ptr< T_DEST, T_DELETER > dynamic_pointer_cast(std::unique_ptr< T_SRC, T_DELETER > &src)
These are reworked from https://stackoverflow.com/a/11003103.
ConstElemPointerRange * refinedElementRange() const
Return a range that is suitable for threaded execution over elements that were just refined...
Definition: MooseMesh.C:946
MaterialWarehouse _kokkos_materials
std::vector< VectorVariableCurl > _vector_curl_zero
static void selectVectorTagsFromSystem(const SystemBase &system, const std::vector< VectorTag > &input_vector_tags, std::set< TagID > &selected_tags)
Select the vector tags which belong to a specific system.
Definition: SubProblem.C:290
Base class for user objects executed one or more sidesets, which may be on the outer boundary of the ...
bool _has_exception
Whether or not an exception has occurred.
unsigned int _num_grid_steps
Number of steps in a grid sequence.
virtual void associateMatrixToTag(libMesh::SparseMatrix< Number > &matrix, TagID tag)
Associate a matrix to a tag.
Definition: SystemBase.C:1076
bool haveXFEM()
Find out whether the current analysis is using XFEM.
virtual void addJacobianBlockTags(libMesh::SparseMatrix< libMesh::Number > &jacobian, unsigned int ivar, unsigned int jvar, const DofMap &dof_map, std::vector< dof_id_type > &dof_indices, const std::set< TagID > &tags, const THREAD_ID tid)
void registerRandomInterface(RandomInterface &random_interface, const std::string &name)
bool _has_time_integrator
Indicates whether or not this executioner has a time integrator (during setup)
This class provides an interface for common operations on field variables of both FE and FV types wit...
const Parallel::Communicator & _communicator
virtual void addAuxKernel(const std::string &kernel_name, const std::string &name, InputParameters &parameters)
MaterialPropertyRegistry _material_prop_registry
virtual void jacobianSetup()
Definition: SubProblem.C:1212
void clearActiveMaterialProperties(const THREAD_ID tid)
Clear the active material properties.
virtual unsigned int nLinearIterations(const unsigned int nl_sys_num) const override
bool has_static_condensation() const
std::vector< subdomain_id_type > getSubdomainIDs(const libMesh::MeshBase &mesh, const std::vector< SubdomainName > &subdomain_name)
Get the associated subdomainIDs for the subdomain names that are passed in.
ExecuteMooseObjectWarehouse< TransientMultiApp > _transient_multi_apps
Storage for TransientMultiApps (only needed for calling &#39;computeDT&#39;)
bool hasUserObject(const std::string &name) const
Check if there if a user object of given name.
MaterialWarehouse _interface_materials
Real getStartTime() const
Definition: MooseApp.h:300
Thread to compute threaded general user objects.
The following methods are specializations for using the libMesh::Parallel::packed_range_* routines fo...
bool _ignore_zeros_in_jacobian
Whether to ignore zeros in the Jacobian, thereby leading to a reduced sparsity pattern.
const libMesh::ConstElemRange & getCurrentAlgebraicElementRange()
These are the element and nodes that contribute to the jacobian and residual for this local processor...
void setup(const ExecFlagType &exec_flag, THREAD_ID tid=0) const
void setCurrentExecuteOnFlag(const ExecFlagType &)
virtual void computeResidualInternal(const NumericVector< libMesh::Number > &soln, NumericVector< libMesh::Number > &residual, const std::set< TagID > &tags)
Form a residual vector for a set of tags.
void copyValuesBack()
Copies current chain control data values into old values.
void initElementStatefulProps(const libMesh::ConstElemRange &elem_range, const bool threaded)
Initialize stateful properties for elements in a specific elem_range This is needed when elements/bou...
const libMesh::ConstNodeRange & getCurrentAlgebraicNodeRange()
void setCurrentlyComputingResidualAndJacobian(bool currently_computing_residual_and_jacobian)
Set whether or not the problem is in the process of computing the Jacobian.
Definition: SubProblem.h:1498
ExecuteMooseObjectWarehouse< Transfer > _from_multi_app_transfers
Transfers executed just after MultiApps to transfer data from them.
virtual void addKernel(const std::string &kernel_name, const std::string &name, InputParameters &parameters)
libMesh::TensorValue< ADReal > ADRealTensorValue
Definition: MooseTypes.h:372
Base class for a system (of equations)
Definition: SystemBase.h:84
const ExecFlagType EXEC_ALWAYS
Definition: Moose.C:51
SparseMatrix< Number > & getSystemMatrix()
Fetching the system matrix from the libmesh system.
Definition: LinearSystem.h:126
This user object allows related evaluations on elements, boundaries, internal sides, interfaces in one single place.
virtual void addAuxVariable(const std::string &var_type, const std::string &var_name, InputParameters &params)
Canonical method for adding an auxiliary variable.
SECOND
std::pair< typename M::iterator, bool > moose_try_emplace(M &m, const typename M::key_type &k, Args &&... args)
Function to mirror the behavior of the C++17 std::map::try_emplace() method (no hint).
Definition: Moose.h:101
const T_sys & get_system(std::string_view name) const
std::optional< ConvergenceName > _steady_state_convergence_name
Steady-state detection convergence name.
Base class for MeshDivision objects.
Definition: MeshDivision.h:35
bool computingNonlinearResid() const
Returns true if the problem is in the process of computing the nonlinear residual.
Definition: SubProblem.h:707
virtual void addFVInterfaceKernel(const std::string &fv_ik_name, const std::string &name, InputParameters &parameters)
MeshDivision & getMeshDivision(const std::string &name, const THREAD_ID tid=0) const
Get a MeshDivision.
bool isRestarting() const
Whether or not this is a "restart" calculation.
Definition: MooseApp.C:1880
Base class for creating new nodally-based mortar user objects.
Reporter objects allow for the declaration of arbitrary data types that are aggregate values for a si...
Definition: Reporter.h:47
const Positions & getPositionsObject(const std::string &name) const
Get the Positions object by its name.
libMesh::ConstNodeRange * getLocalNodeRange()
Definition: MooseMesh.C:1313
std::map< SolverSystemName, unsigned int > _solver_sys_name_to_num
Map connecting solver system names with their respective systems.
FEProblemBase(const InputParameters &parameters)
void addEdge(const T &a, const T &b)
Add an edge between nodes &#39;a&#39; and &#39;b&#39;.
std::string convertLatestCheckpoint(std::string orig)
Replaces "LATEST" placeholders with the latest checkpoint file name.
Definition: MooseUtils.C:157
void prepareScalar()
Definition: Assembly.C:2945
bool isOn()
Is adaptivity on?
Definition: Adaptivity.h:179
void computeResidualTags(const std::set< TagID > &tags)
Form multiple tag-associated residual vectors for all the given tags.
virtual void cacheJacobianNeighbor(const THREAD_ID tid) override
const std::string & getBase() const
Specialization of SubProblem for solving nonlinear equations plus auxiliary equations.
virtual void clearActiveElementalMooseVariables(const THREAD_ID tid)
Clear the active elemental MooseVariableFieldBase.
Definition: SubProblem.C:467
std::vector< std::unordered_map< BoundaryID, bool > > _bnd_mat_side_cache
Cache for calculating materials on side.
bool hasLinearConvergenceObjects() const
Whether we have linear convergence objects.
virtual const Node & nodeRef(const dof_id_type i) const
Definition: MooseMesh.C:849
std::set< dof_id_type > _ghosted_elems
Elements that should have Dofs ghosted to the local processor.
Definition: SubProblem.h:1095
ExecFlagEnum _print_execution_on
When to print the execution of loops.
std::vector< SubdomainID > getSubdomainIDs(const std::vector< SubdomainName > &subdomain_names) const
Get the associated subdomainIDs for the subdomain names that are passed in.
Definition: MooseMesh.C:1775
void clearAllDofIndices()
Clear dof indices from variables in nl and aux systems.
Definition: SubProblem.C:1178
virtual void setResidual(NumericVector< libMesh::Number > &residual, const THREAD_ID tid) override
virtual void solve(const unsigned int nl_sys_num)
virtual void setCurrentLowerDElem(const Elem *const lower_d_elem, const THREAD_ID tid) override
Set the current lower dimensional element.
std::set< TagID > _linear_matrix_tags
Temporary storage for filtered matrix tags for linear systems.
MooseApp & getMooseApp() const
Get the MooseApp this class is associated with.
Definition: MooseBase.h:87
void bumpAllQRuleOrder(libMesh::Order order, SubdomainID block)
Real computeMultiAppsDT(ExecFlagType type)
Find the smallest timestep over all MultiApps.
const std::string & getSubdomainName(SubdomainID subdomain_id) const
Return the name of a block given an id.
Definition: MooseMesh.C:1801
virtual void reinitNeighborFaceRef(const Elem *neighbor_elem, unsigned int neighbor_side, Real tolerance, const std::vector< Point > *const pts, const std::vector< Real > *const weights=nullptr, const THREAD_ID tid=0)
reinitialize FE objects on a given neighbor element on a given side at a given set of reference point...
Definition: SubProblem.C:922
void projectSolution()
virtual const MooseVariableFieldBase & getVariable(const THREAD_ID tid, const std::string &var_name, Moose::VarKindType expected_var_type=Moose::VarKindType::VAR_ANY, Moose::VarFieldType expected_var_field_type=Moose::VarFieldType::VAR_FIELD_ANY) const override
Returns the variable reference for requested variable which must be of the expected_var_type (Nonline...
void reinitMaterialsFace(SubdomainID blk_id, const THREAD_ID tid, bool swap_stateful=true, const std::deque< MaterialBase *> *reinit_mats=nullptr)
reinit materials on element faces
std::unique_ptr< libMesh::ConstElemRange > _nl_evaluable_local_elem_range
virtual void disassociateMatrixFromTag(libMesh::SparseMatrix< Number > &matrix, TagID tag)
Disassociate a matrix from a tag.
Definition: SystemBase.C:1088
Scope guard for starting and stopping Floating Point Exception Trapping.
virtual void computeResidualTags(const std::set< TagID > &tags)
Form multiple residual vectors and each is associated with one tag.
void forceOutput()
Indicates that the next call to outputStep should be forced This is private, users should utilize FEP...
virtual void computeJacobianSys(libMesh::NonlinearImplicitSystem &sys, const NumericVector< libMesh::Number > &soln, libMesh::SparseMatrix< libMesh::Number > &jacobian)
Form a Jacobian matrix.
auto max(const L &left, const R &right)
std::shared_ptr< MultiApp > getMultiApp(const std::string &multi_app_name) const
Get a MultiApp object by name.
ExecuteMooseObjectWarehouse< UserObject > _all_user_objects
virtual void reinitElemNeighborAndLowerD(const Elem *elem, unsigned int side, const THREAD_ID tid) override
bool hasSolverVariable(const std::string &var_name) const
void preparePRefinement()
Prepare DofMap and Assembly classes with our p-refinement information.
Definition: SubProblem.C:1337
AuxGroup
Flag for AuxKernel related execution type.
Definition: MooseTypes.h:704
virtual Elem * queryElemPtr(const dof_id_type i)
Definition: MooseMesh.C:3146
virtual void addMarker(const std::string &marker_name, const std::string &name, InputParameters &parameters)
void updateGhostedElems()
Updates the list of ghosted elements at the start of each time step for the nonlinear iteration patch...
unsigned int subspaceDim(const std::string &prefix) const
Dimension of the subspace spanned by vectors with a given prefix.
elem_info_iterator ownedElemInfoBegin()
Iterators to owned faceInfo objects.
Definition: MooseMesh.C:1566
void setCurrentlyComputingJacobian(const bool currently_computing_jacobian)
Set whether or not the problem is in the process of computing the Jacobian.
Definition: SubProblem.h:689
unsigned int variable_number(std::string_view var) const
const std::unordered_map< std::pair< BoundaryID, BoundaryID >, AutomaticMortarGeneration > & getMortarInterfaces(bool on_displaced) const
Return all automatic mortar generation objects on either the displaced or undisplaced mesh...
Definition: MortarData.h:73
A ReporterName that represents a VectorPostprocessor.
Definition: ReporterName.h:152
bool needsPreviousNewtonIteration() const
Check to see whether we need to compute the variable values of the previous Newton iterate...
virtual void addBoundaryCondition(const std::string &bc_name, const std::string &name, InputParameters &parameters)
bool _computing_nonlinear_residual
Whether the non-linear residual is being evaluated.
Definition: SubProblem.h:1104
virtual bool computingPreSMOResidual(const unsigned int nl_sys_num) const override
Returns true if the problem is in the process of computing it&#39;s initial residual. ...
void update()
Update the system (doing libMesh magic)
Definition: SystemBase.C:1243
This class is a container/interface for the objects involved in automatic generation of mortar spaces...
virtual Assembly & assembly(const THREAD_ID tid, const unsigned int sys_num) override
void createTagMatrices(CreateTaggedMatrixKey)
const bool _skip_nl_system_check
virtual void resetState()
Reset state of this object in preparation for the next evaluation.
void jacobianSetup()
Calls the jacobianSetup function for each of the output objects.
std::vector< MooseObjectParameterName > getControllableParameterNames(const MooseObjectParameterName &input) const
Return a vector of parameters names matching the supplied name.
virtual void addInitialCondition(const std::string &ic_name, const std::string &name, InputParameters &parameters)
virtual void addCachedResidualDirectly(NumericVector< libMesh::Number > &residual, const THREAD_ID tid)
Allows for all the residual contributions that are currently cached to be added directly into the vec...
bool hasObjects() const
Returns whether we have any active AutomaticMortarGeneration objects.
Definition: MortarData.h:104
bool hasActiveBoundaryObjects(THREAD_ID tid=0) const
virtual void jacobianSetup(THREAD_ID tid=0) const
const SubdomainID INVALID_BLOCK_ID
Definition: MooseTypes.C:20
ScalarInitialConditionWarehouse _scalar_ics
virtual void computeLinearSystemSys(libMesh::LinearImplicitSystem &sys, libMesh::SparseMatrix< libMesh::Number > &system_matrix, NumericVector< libMesh::Number > &rhs, const bool compute_gradients=true)
Assemble both the right hand side and the system matrix of a given linear system. ...
Nonlinear system to be solved.
bool getExodusFileRestart() const
Whether or not we need to use a separate Exodus reader to read the mesh BEFORE we create the mesh...
Definition: MooseApp.h:430
virtual void swapBackMaterialsFace(const THREAD_ID tid)
virtual void addDistribution(const std::string &type, const std::string &name, InputParameters &parameters)
The following functions will enable MOOSE to have the capability to import distributions.
virtual void advanceState()
Advance all of the state holding vectors / datastructures so that we can move to the next timestep...
A user object that runs over all the nodes and does an aggregation step to compute a single value...
ExecuteMooseObjectWarehouse< Transfer > _transfers
Normal Transfers.
void setAuxKernelParamsAndLog(const std::string &ak_name, const std::string &name, InputParameters &parameters, const std::string &base_name)
Set the subproblem and system parameters for auxiliary kernels and log their addition.
virtual void customSetup(const ExecFlagType &exec_type)
Definition: SubProblem.C:1196
virtual void checkBoundaryMatProps()
Checks boundary material properties integrity.
Definition: SubProblem.C:666
std::map< std::string, std::vector< dof_id_type > > _var_dof_map
Definition: SubProblem.h:674
Based class for output objects.
Definition: Output.h:43
const VectorPostprocessorValue & getVectorPostprocessorValueByName(const std::string &object_name, const std::string &vector_name, std::size_t t_index=0) const
Get a read-only reference to the vector value associated with the VectorPostprocessor.
virtual void addPredictor(const std::string &type, const std::string &name, InputParameters &parameters)
virtual Function & getFunction(const std::string &name, const THREAD_ID tid=0)
virtual void computeJacobianBlocks(std::vector< JacobianBlock *> &blocks, const unsigned int nl_sys_num)
Computes several Jacobian blocks simultaneously, summing their contributions into smaller preconditio...
virtual void copySolutionsBackwards()
const ConstBndNodeRange & getCurrentAlgebraicBndNodeRange()
bool _calculate_jacobian_in_uo
TODO: delete this later - it is a temporary hack for dealing with inter-system dependencies.
Definition: Attributes.h:294
virtual void reinitElemFaceRef(const Elem *elem, unsigned int side, Real tolerance, const std::vector< Point > *const pts, const std::vector< Real > *const weights=nullptr, const THREAD_ID tid=0) override
reinitialize FE objects on a given element on a given side at a given set of reference points and the...
virtual void setActiveScalarVariableCoupleableVectorTags(std::set< TagID > &vtags, const THREAD_ID tid)
Definition: SubProblem.C:410
virtual void prepareFaceShapes(unsigned int var, const THREAD_ID tid) override
virtual void addPostprocessor(const std::string &pp_name, const std::string &name, InputParameters &parameters)
virtual Real finalNonlinearResidual(const unsigned int nl_sys_num) const override
void addItem(const T &value)
Add an independent item to the set.
std::vector< std::shared_ptr< NonlinearSystemBase > > _nl
The nonlinear systems.
bool automaticScaling() const
Automatic scaling getter.
Definition: SubProblem.C:1163
virtual void computeUserObjects(const ExecFlagType &type, const Moose::AuxGroup &group)
Call compute methods on UserObjects.
virtual void setActiveElementalMooseVariables(const std::set< MooseVariableFEBase *> &moose_vars, const THREAD_ID tid) override
Set the MOOSE variables to be reinited on each element.
virtual void reinit_systems()
std::map< std::pair< BoundaryID, BoundaryID >, NearestNodeLocator * > _nearest_node_locators
std::vector< VariablePhiGradient > _grad_phi_zero
void mooseWarning(Args &&... args) const
void initialSetup(THREAD_ID tid)
Initial setup.
bool hasJacobian() const
Returns _has_jacobian.
void notifyWhenMeshDisplaces(MeshDisplacedInterface *mdi)
Register an object that derives from MeshDisplacedInterface to be notified when the displaced mesh ge...
void createTagSolutions()
Create extra tagged solution vectors.
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.
bool _verbose_restore
Whether or not to be verbose on solution restoration post a failed time step.
bool _previous_nl_solution_required
Indicates we need to save the previous NL iteration variable values.
processor_id_type n_processors() const
bool _trust_user_coupling_matrix
Whether to trust the user coupling matrix no matter what.
void setRestartRecoverFileBase(const std::string &file_base)
mutator for recover_base (set by RecoverBaseAction)
Definition: MooseApp.h:506
unsigned int number() const
const ConvergenceName & getSteadyStateConvergenceName() const
Gets the steady-state detection convergence object name.
void computeResidualAndJacobianTags(const std::set< TagID > &vector_tags, const std::set< TagID > &matrix_tags)
Form possibly multiple tag-associated vectors and matrices.
void handleException(const std::string &calling_method)
Handle exceptions.
virtual std::vector< VariableName > getVariableNames()
Returns a list of all the variables in the problem (both from the NL and Aux systems.
ReporterData _reporter_data
const std::string & name() const
Get the name of the class.
Definition: MooseBase.h:103
void uniformRefine()
uniformly refine the problem mesh(es).
virtual void computeResidualSys(libMesh::NonlinearImplicitSystem &sys, const NumericVector< libMesh::Number > &soln, NumericVector< libMesh::Number > &residual)
This function is called by Libmesh to form a residual.
const ReporterData & getReporterData() const
Provides const access the ReporterData object.
virtual const libMesh::CouplingMatrix & nonlocalCouplingMatrix(const unsigned i) const override
std::unique_ptr< libMesh::ConstElemRange > _current_algebraic_elem_range
FunctorMaterials compute functor material properties.
std::vector< std::shared_ptr< Transfer > > getTransfers(ExecFlagType type, Transfer::DIRECTION direction) const
Get Transfers by ExecFlagType and direction.
virtual void addConvergence(const std::string &type, const std::string &name, InputParameters &parameters)
Adds a Convergence object.
MultiPointMap & getPoints()
Returns a writeable reference to the _points container.
bool shouldPrintExecution(const THREAD_ID tid) const
Check whether the problem should output execution orders at this time.
const std::vector< std::shared_ptr< T > > & getActiveObjects(THREAD_ID tid=0) const
Retrieve complete vector to the active all/block/boundary restricted objects for a given thread...
const std::set< subdomain_id_type > & active_subdomains() const
bool havePRefinement() const
Query whether p-refinement has been requested at any point during the simulation. ...
Definition: SubProblem.h:1011
virtual Real l2_norm() const=0
bool getRecomputeMarkersFlag() const
Pull out the _recompute_markers_during_cycles flag previously set through the AdaptivityAction.
Definition: Adaptivity.h:125
const bool & _solve
Whether or not to actually solve the nonlinear system.
virtual const SystemBase & systemBaseSolver(const unsigned int sys_num) const override
Return the solver system object as a base class reference given the system number.
DenseVector< Real > getAllRealReporterValues() const
Get all real reporter values including postprocessor and vector postprocessor values into a dense vec...
Definition: ReporterData.C:81
ExecuteMooseObjectWarehouse< Transfer > _to_multi_app_transfers
Transfers executed just before MultiApps to transfer data to them.
std::set< SubdomainID > getActiveBlocks(THREAD_ID tid=0) const
Return a set of active SubdomainsIDs.
virtual void zero()=0
NonlinearSystemBase * _current_nl_sys
The current nonlinear system that we are solving.
MooseObjectWarehouse< Convergence > _convergences
convergence warehouse
Interface for notifications that the mesh has changed.
void sort(THREAD_ID tid=0, bool sort_all_objects=false)
By default, this method only sorts block and boundary-wise object storages that are used by the MOOSE...
virtual std::unique_ptr< Base > create()=0
void createMortarInterface(const std::pair< BoundaryID, BoundaryID > &boundary_key, const std::pair< SubdomainID, SubdomainID > &subdomain_key, SubProblem &subproblem, bool on_displaced, bool periodic, const bool debug, const bool correct_edge_dropping, const Real minimum_projection_angle)
Create mortar generation object.
Definition: MortarData.C:22
void setCurrentNonlinearSystem(const unsigned int nl_sys_num)
std::shared_ptr< T > getActiveObject(const std::string &name, THREAD_ID tid=0) const
bool hasScalingOrRotationTransformation() const
Returns true if the app has scaling and/or rotation transformation.
const std::vector< std::shared_ptr< T > > & getObjects(THREAD_ID tid=0) const
Retrieve complete vector to the all/block/boundary restricted objects for a given thread...
virtual const NumericVector< Number > *const & currentSolution() const override final
The solution vector that is currently being operated on.
Definition: SolverSystem.h:117
dof_id_type id() const
Real value(unsigned n, unsigned alpha, unsigned beta, Real x)
Base class for convergence criteria.
Definition: Convergence.h:21
MeshBase & getMesh()
Accessor for the underlying libMesh Mesh object.
Definition: MooseMesh.C:3469
void min(const T &r, T &o, Request &req) const
virtual void reinitElem(const Elem *elem, const THREAD_ID tid) override
const T & getReporterValue(const ReporterName &reporter_name, const MooseObject &consumer, const ReporterMode &mode, const std::size_t time_index=0) const
Method for returning read only references to Reporter values.
Definition: ReporterData.h:388
virtual Convergence & getConvergence(const std::string &name, const THREAD_ID tid=0) const
Gets a Convergence object.
TheWarehouse & theWarehouse() const
void createTagVectors()
Create extra tagged vectors and matrices.
virtual void createQRules(libMesh::QuadratureType type, libMesh::Order order, libMesh::Order volume_order=libMesh::INVALID_ORDER, libMesh::Order face_order=libMesh::INVALID_ORDER, SubdomainID block=Moose::ANY_BLOCK_ID, bool allow_negative_qweights=true)
unsigned int n_vars
void reinitMaterialsNeighbor(SubdomainID blk_id, const THREAD_ID tid, bool swap_stateful=true, const std::deque< MaterialBase *> *reinit_mats=nullptr)
reinit materials on the neighboring element face
void setMultiAppFixedPointConvergenceName(const ConvergenceName &convergence_name)
Sets the MultiApp fixed point convergence object name if there is one.
void checkUserObjects()
Moose::CouplingType _coupling
Type of variable coupling.
Every object that can be built by the factory should be derived from this class.
Definition: MooseObject.h:28
Real l2_norm() const
void parallelBarrierNotify(const libMesh::Parallel::Communicator &comm, bool messaging=true)
This function implements a parallel barrier function but writes progress to stdout.
Definition: MooseUtils.C:327
virtual bool shouldUpdateSolution()
Check to see whether the problem should update the solution.
virtual void setActiveFEVariableCoupleableVectorTags(std::set< TagID > &vtags, const THREAD_ID tid)
Definition: SubProblem.C:370
void extraSendList(std::vector< dof_id_type > &send_list, void *context)
///< Type of coordinate system
Definition: SystemBase.C:40
void addObjects(std::shared_ptr< MaterialBase > block, std::shared_ptr< MaterialBase > neighbor, std::shared_ptr< MaterialBase > face, THREAD_ID tid=0)
A special method unique to this class for adding Block, Neighbor, and Face material objects...
const ConvergenceName & getMultiAppFixedPointConvergenceName() const
Gets the MultiApp fixed point convergence object name.
std::vector< std::string > getAllRealReporterFullNames() const
Get full names of all real reporter values Note: For a postprocessor, the full name is the postproces...
Definition: ReporterData.C:106
virtual void clearActiveScalarVariableCoupleableVectorTags(const THREAD_ID tid)
Definition: SubProblem.C:420
Real getTimeFromStateArg(const Moose::StateArg &state) const
Returns the time associated with the requested state.
virtual std::string solverTypeString(unsigned int solver_sys_num=0)
Return solver type as a human readable string.
const ExecFlagType EXEC_TIMESTEP_BEGIN
Definition: Moose.C:37
std::shared_ptr< T > getObject(const std::string &name, THREAD_ID tid=0) const
void executeSamplers(const ExecFlagType &exec_type)
Performs setup and execute calls for Sampler objects.
unsigned int which_neighbor_am_i(const Elem *e) const
virtual void computeJacobianInternal(const NumericVector< libMesh::Number > &soln, libMesh::SparseMatrix< libMesh::Number > &jacobian, const std::set< TagID > &tags)
Form a Jacobian matrix for multiple tags.
bool _safe_access_tagged_vectors
Is it safe to retrieve data from tagged vectors.
Definition: SubProblem.h:1113
virtual void computeJacobian(const NumericVector< libMesh::Number > &soln, libMesh::SparseMatrix< libMesh::Number > &jacobian, const unsigned int nl_sys_num)
Form a Jacobian matrix with the default tag (system).
void reinitMaterialsNeighborOnBoundary(const BoundaryID boundary_id, const SubdomainID blk_id, const THREAD_ID tid, const bool swap_stateful=true, const std::deque< MaterialBase *> *const reinit_mats=nullptr)
reinit materials on neighbor element (usually faces) on a boundary (internal or external) This specif...
void addOutput(const std::string &, const std::string &, InputParameters &)
Adds an Output object.
SolutionIterationType iteration_type
The solution iteration type, e.g. time or nonlinear.
boundary_id_type BoundaryID
void boundaryIntegrityCheckError(const MooseObject &object, const std::set< MooseVariableFieldBase *> &variables, const BoundaryName &boundary_name)
Compose boundary restricted error message for the provided object, variables, and boundary_name if th...
const bool _allow_ics_during_restart
bool constJacobian() const
Returns _const_jacobian (whether a MOOSE object has specified that the Jacobian is the same as the pr...
virtual void clearActiveFEVariableCoupleableMatrixTags(const THREAD_ID tid) override
void computeJacobianTags(const std::set< TagID > &tags)
Computes multiple (tag associated) Jacobian matricese.
SolutionInvalidity & solutionInvalidity()
Get the SolutionInvalidity for this app.
Definition: MooseApp.h:179
std::vector< MeshChangedInterface * > _notify_when_mesh_changes
Objects to be notified when the mesh changes.
virtual void timestepSetup(THREAD_ID tid=0) const
void checkNonlocalCoupling()
VarKindType
Framework-wide stuff.
Definition: MooseTypes.h:715
void addDefaultSteadyStateConvergence(const InputParameters &params)
Adds the default steady-state detection Convergence.
NonlinearSystemBase & currentNonlinearSystem()
SimpleRange< IndexType > as_range(const std::pair< IndexType, IndexType > &p)
Jacobian-Free Newton Krylov.
Definition: MooseTypes.h:846
void groupUserObjects(TheWarehouse &w, AuxiliarySystem &aux, const ExecFlagEnum &execute_flags, const std::vector< T *> &objs, const std::set< std::string > &ic_deps)
void checkDisplacementOrders()
Verify that SECOND order mesh uses SECOND order displacements.
virtual void addFunction(const std::string &type, const std::string &name, InputParameters &parameters)
Real PostprocessorValue
various MOOSE typedefs
Definition: MooseTypes.h:202
void uniformly_coarsen(unsigned int n=1)
virtual void addJacobianNeighbor(const THREAD_ID tid) override
virtual TagID addMatrixTag(TagName tag_name)
Create a Tag.
Definition: SubProblem.C:312
virtual libMesh::EquationSystems & es() override
std::vector< std::unordered_map< SubdomainID, bool > > _block_mat_side_cache
Cache for calculating materials on side.
MortarData _mortar_data
std::shared_ptr< AuxiliarySystem > _aux
The auxiliary system.
void setRestart(bool value)
Sets the restart/recover flags.
Definition: MooseApp.C:2985
AttribBoundaries tracks all boundary IDs associated with an object.
Definition: Attributes.h:188
void setValue(unsigned int i, Number value)
Set the nodal value for this variable (to keep everything up to date.
virtual void reinitElemFaceRef(const Elem *elem, unsigned int side, Real tolerance, const std::vector< Point > *const pts, const std::vector< Real > *const weights=nullptr, const THREAD_ID tid=0)
reinitialize FE objects on a given element on a given side at a given set of reference points and the...
Definition: SubProblem.C:883
virtual void addVectorPostprocessor(const std::string &pp_name, const std::string &name, InputParameters &parameters)
MooseMesh wraps a libMesh::Mesh object and enhances its capabilities by caching additional data and s...
Definition: MooseMesh.h:92
virtual bool converged(const unsigned int sys_num)
Eventually we want to convert this virtual over to taking a solver system number argument.
Definition: SubProblem.h:113
virtual unsigned int currentNlSysNum() const override
virtual void computeIndicators()
virtual MooseVariableScalar & getScalarVariable(const THREAD_ID tid, const std::string &var_name) override
Returns the scalar variable reference from whichever system contains it.
const bool _boundary_restricted_node_integrity_check
whether to perform checking of boundary restricted nodal object variable dependencies, e.g.
virtual void setActiveScalarVariableCoupleableVectorTags(std::set< TagID > &vtags, const THREAD_ID tid) override
MooseMesh & _mesh
virtual void updateActive(THREAD_ID tid=0)
Update the active status of Kernels.
virtual bool updateMeshXFEM()
Update the mesh due to changing XFEM cuts.
virtual const SystemBase & systemBaseNonlinear(const unsigned int sys_num) const override
Return the nonlinear system object as a base class reference given the system number.
std::vector< MortarUserObject * > getMortarUserObjects(BoundaryID primary_boundary_id, BoundaryID secondary_boundary_id, bool displaced, const std::vector< MortarUserObject *> &mortar_uo_superset)
Helper for getting mortar objects corresponding to primary boundary ID, secondary boundary ID...
virtual void restoreSolutions()
virtual bool hasConvergence(const std::string &name, const THREAD_ID tid=0) const
Returns true if the problem has a Convergence object of the given name.
void markFamilyPRefinement(const InputParameters &params)
Mark a variable family for either disabling or enabling p-refinement with valid parameters of a varia...
Definition: SubProblem.C:1372
virtual const std::vector< dof_id_type > & dofIndices() const
Get local DoF indices.
void addAnyRedistributers()
void mooseDeprecated(Args &&... args) const
const std::string & type() const
Get the type of this class.
Definition: MooseBase.h:93
bool hasPostprocessorValueByName(const PostprocessorName &name) const
Whether or not a Postprocessor value exists by a given name.
virtual void checkBlockMatProps()
Checks block material properties integrity.
Definition: SubProblem.C:624
void restoreFromInitialBackup(const bool for_restart)
Restores from a "initial" backup, that is, one set in _initial_backup.
Definition: MooseApp.C:1982
void setAxisymmetricCoordAxis(const MooseEnum &rz_coord_axis)
void initialSetup() override
This is a "smart" enum class intended to replace many of the shortcomings in the C++ enum type It sho...
Definition: MooseEnum.h:33
void reinit()
Completely redo all geometric search objects.
Adaptivity _adaptivity
std::vector< VectorTag > getVectorTags(const std::set< TagID > &tag_ids) const
Definition: SubProblem.C:173
bool allowInvalidSolution() const
Whether to accept / allow an invalid solution.
bool needInternalNeighborSideMaterial(SubdomainID subdomain_id, const THREAD_ID tid)
virtual const SystemBase & systemBaseAuxiliary() const override
Return the auxiliary system object as a base class reference.
Moose::SolveType _type
Definition: SolverParams.h:19
void setLinearConvergenceNames(const std::vector< ConvergenceName > &convergence_names)
Sets the linear convergence object name(s) if there is one.
void checkUserObjectJacobianRequirement(THREAD_ID tid)
MooseVariableFieldBase & getActualFieldVariable(const THREAD_ID tid, const std::string &var_name) override
Returns the variable reference for requested MooseVariableField which may be in any system...
void finalize(const std::string &object_name)
Helper function for performing post calculation actions via the ReporterContext objects.
Definition: ReporterData.C:48
void addObject(std::shared_ptr< InitialConditionBase > object, THREAD_ID tid, bool recurse=true)
Add object to the warehouse.
virtual void disassociateVectorFromTag(NumericVector< Number > &vec, TagID tag)
Disassociate a given vector from a given tag.
virtual void computeNullSpace(libMesh::NonlinearImplicitSystem &sys, std::vector< NumericVector< libMesh::Number > *> &sp)
virtual void addTimeIntegrator(const std::string &type, const std::string &name, InputParameters &parameters)
LinearSystem * _current_linear_sys
The current linear system that we are solving.
virtual void cacheResidual(const THREAD_ID tid) override
virtual void computeResidualType(const NumericVector< libMesh::Number > &soln, NumericVector< libMesh::Number > &residual, TagID tag)
Form a residual vector for a given tag and "residual" tag.
const bool _force_restart
void checkCoordinateSystems()
Performs a sanity check for every element in the mesh.
Definition: MooseMesh.C:4328
QueryCache clone() const
clone creates and returns an independent copy of the query in its current state.
Definition: TheWarehouse.h:292
const std::set< SubdomainID > & getMortarSubdomainIDs() const
Returns the mortar covered subdomains.
Definition: MortarData.h:84
void forceOutput()
Indicates that the next call to outputStep should be forced.
const VectorPostprocessor & getVectorPostprocessorObjectByName(const std::string &object_name, const THREAD_ID tid=0) const
Return the VPP object given the name.
std::vector< VariablePhiSecond > _second_phi_zero
StoredRange< std::vector< GeneralUserObject * >::iterator, GeneralUserObject * > GeneralUserObjectRange
bool _started_initial_setup
At or beyond initialSteup stage.
std::map< std::string, std::unique_ptr< RandomData > > _random_data_objects
A map of objects that consume random numbers.
virtual bool vectorTagExists(const TagID tag_id) const
Check to see if a particular Tag exists.
Definition: SubProblem.h:201
std::unique_ptr< ConstBndNodeRange > _current_algebraic_bnd_node_range
virtual void addResidual(const THREAD_ID tid) override
void checkParams(const std::string &parsing_syntax)
This function checks parameters stored in the object to make sure they are in the correct state as th...
virtual void addResidualNeighbor(const THREAD_ID tid) override
virtual void reinitNeighborFaceRef(const Elem *neighbor_elem, unsigned int neighbor_side, Real tolerance, const std::vector< Point > *const pts, const std::vector< Real > *const weights=nullptr, const THREAD_ID tid=0) override
reinitialize FE objects on a given neighbor element on a given side at a given set of reference point...
void setCoordSystem(const std::vector< SubdomainName > &blocks, const MultiMooseEnum &coord_sys)
Set the coordinate system for the provided blocks to coord_sys.
Definition: MooseMesh.C:4102
Base class for all Postprocessors.
Definition: Postprocessor.h:23
libMesh::ExodusII_IO * getExReaderForRestart() const
Get the Exodus reader to restart variables from an Exodus mesh file.
Definition: MooseApp.h:443
void needSolutionState(unsigned int oldest_needed, Moose::SolutionIterationType iteration_type)
Declare that we need up to old (1) or older (2) solution states for a given type of iteration...
void clearPoints()
Remove all of the current points and elements.
std::string typeAndName() const
Get the class&#39;s combined type and name; useful in error handling.
Definition: MooseBase.C:57
MooseApp & _app
The MOOSE application this is associated with.
Definition: MooseBase.h:357
virtual void clearActiveFEVariableCoupleableVectorTags(const THREAD_ID tid) override
void maxloc(T &r, unsigned int &max_id) const
bool isValueSet(const std::string &value) const
Methods for seeing if a value is set in the MultiMooseEnum.
void setCouplingMatrix(std::unique_ptr< libMesh::CouplingMatrix > cm, const unsigned int nl_sys_num)
Set custom coupling matrix.
unsigned int number() const
Gets the number of this system.
Definition: SystemBase.C:1157
virtual void addDefaultNonlinearConvergence(const InputParameters &params)
Adds the default nonlinear Convergence associated with the problem.
virtual void solve() override
Solve the system (using libMesh magic)
Definition: LinearSystem.C:312
void setNonlinearConvergenceNames(const std::vector< ConvergenceName > &convergence_names)
Sets the nonlinear convergence object name(s) if there is one.
auto norm(const T &a) -> decltype(std::abs(a))
unsigned int uniformRefineLevel() const
Returns the level of uniform refinement requested (zero if AMR is disabled).
Definition: MooseMesh.C:3237
const ExecFlagType EXEC_LINEAR
Definition: Moose.C:31
TODO: delete this later - it is a temporary hack for dealing with inter-system dependencies.
Definition: Attributes.h:344
virtual bool solverSystemConverged(const unsigned int solver_sys_num) override
std::string stringify(const T &t)
conversion to string
Definition: Conversion.h:64
std::string _exception_message
The error message to go with an exception.
const std::set< SubdomainID > & boundaryLowerDBlocks() const
Definition: MooseMesh.h:1425
std::vector< SubdomainName > getSubdomainNames(const std::vector< SubdomainID > &subdomain_ids) const
Get the associated subdomainNames for the subdomain ids that are passed in.
Definition: MooseMesh.C:1807
virtual void checkProblemIntegrity()
Method called to perform a series of sanity checks before a simulation is run.
void setReporterValue(const ReporterName &reporter_name, const T &value, const std::size_t time_index=0)
Method for setting Reporter values that already exist.
Definition: ReporterData.h:481
Class for storing and utilizing output objects.
AuxiliarySystem & getAuxiliarySystem()
virtual void initialSetup(THREAD_ID tid=0) const
Convenience methods for calling object setup methods.
virtual void updateGeomSearch(GeometricSearchData::GeometricSearchType type=GeometricSearchData::ALL) override
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:230
MooseObjectWarehouse< MeshDivision > _mesh_divisions
Warehouse to store mesh divisions NOTE: this could probably be moved to the MooseMesh instead of the ...
virtual void addConstraint(const std::string &c_name, const std::string &name, InputParameters &parameters)
void buildRefinementAndCoarseningMaps(Assembly *assembly)
Create the refinement and coarsening maps necessary for projection of stateful material properties wh...
Definition: MooseMesh.C:2500
MooseObjectWarehouse< Indicator > _indicators
virtual void addMultiApp(const std::string &multi_app_name, const std::string &name, InputParameters &parameters)
Add a MultiApp to the problem.
virtual void prepareAssembly(const THREAD_ID tid) override
bool haveADObjects() const
Method for reading wehther we have any ad objects.
Definition: SubProblem.h:771
unsigned int systemNumForVariable(const VariableName &variable_name) const
bool _checking_uo_aux_state
Flag used to indicate whether we are doing the uo/aux state check in execute.
const PostprocessorValue & getPostprocessorValueByName(const PostprocessorName &name, std::size_t t_index=0) const
Get a read-only reference to the value associated with a Postprocessor that exists.
MeshBase::element_iterator activeLocalElementsBegin()
Calls active_local_nodes_begin/end() on the underlying libMesh mesh object.
Definition: MooseMesh.C:3072
InitialConditions are objects that set the initial value of variables.
Base class for user objects executed on all element sides internal to one or more blocks...
virtual void clearActiveScalarVariableCoupleableMatrixTags(const THREAD_ID tid)
Definition: SubProblem.C:426
virtual std::map< TagName, TagID > & getMatrixTags()
Return all matrix tags in the system, where a tag is represented by a map from name to ID...
Definition: SubProblem.h:253
virtual void initNullSpaceVectors(const InputParameters &parameters, std::vector< std::shared_ptr< NonlinearSystemBase >> &nl)
virtual bool hasVariable(const std::string &var_name) const
Query a system for a variable.
Definition: SystemBase.C:851
Executioner * getExecutioner() const
Retrieve the Executioner for this App.
Definition: MooseApp.C:2196
virtual void setCurrentSubdomainID(const Elem *elem, const THREAD_ID tid) override
MaterialData & getMaterialData(Moose::MaterialDataType type, const THREAD_ID tid=0, const MooseObject *object=nullptr) const
void broadcast(T &data, const unsigned int root_id=0, const bool identical_sizes=false) const
virtual void clearDiracInfo() override
Gets called before Dirac Kernels are asked to add the points they are supposed to be evaluated in...
virtual void addIndicator(const std::string &indicator_name, const std::string &name, InputParameters &parameters)
virtual void reinitNodesNeighbor(const std::vector< dof_id_type > &nodes, const THREAD_ID tid) override
bool duplicateVariableCheck(const std::string &var_name, const libMesh::FEType &type, bool is_aux, const std::set< SubdomainID > *const active_subdomains)
Helper to check for duplicate variable names across systems or within a single system.
virtual void solve() override=0
Solve the system (using libMesh magic)
GeometricSearchType
Used to select groups of geometric search objects to update.
void backupMultiApps(ExecFlagType type)
Backup the MultiApps associated with the ExecFlagType.
virtual ~FEProblemBase()
A ReporterName that represents a Postprocessor.
Definition: ReporterName.h:143
virtual void addVariable(const std::string &var_type, const std::string &var_name, InputParameters &params)
Canonical method for adding a non-linear variable.
bool doingPRefinement() const
Definition: SubProblem.C:1366
ExecuteMooseObjectWarehouse< MultiApp > _multi_apps
MultiApp Warehouse.
virtual void jacobianSetup(THREAD_ID tid=0) const
void updateBoundaryMatPropDependency(std::unordered_set< unsigned int > &needed_mat_props, THREAD_ID tid=0) const
void uniformRefineWithProjection()
Performs uniform refinement on the meshes in the current object.
Definition: Adaptivity.C:301
TagID residualVectorTag() const override
std::vector< std::vector< std::unique_ptr< Assembly > > > _assembly
The Assembly objects.
virtual void addDisplacedProblem(std::shared_ptr< DisplacedProblem > displaced_problem)
const std::map< BoundaryID, std::vector< std::shared_ptr< T > > > & getActiveBoundaryObjects(THREAD_ID tid=0) const
void computeResidual(libMesh::NonlinearImplicitSystem &sys, const NumericVector< libMesh::Number > &soln, NumericVector< libMesh::Number > &residual)
This function is called by Libmesh to form a residual.
virtual void cacheJacobianNeighbor(const THREAD_ID tid)
Definition: SubProblem.C:1325
MONOMIAL
void setResidualObjectParamsAndLog(const std::string &ro_name, const std::string &name, InputParameters &parameters, const unsigned int nl_sys_num, const std::string &base_name, bool &reinit_displaced)
Set the subproblem and system parameters for residual objects and log their addition.
void setVectorPostprocessorValueByName(const std::string &object_name, const std::string &vector_name, const VectorPostprocessorValue &value, std::size_t t_index=0)
Set the value of a VectorPostprocessor vector.
virtual MooseVariable & getStandardVariable(const THREAD_ID tid, const std::string &var_name) override
Returns the variable reference for requested MooseVariable which may be in any system.
virtual void initialSetup(THREAD_ID tid=0) const
Convenience methods for calling object setup methods that handle the extra neighbor and face objects...
void setCoordSystem(const std::vector< SubdomainName > &blocks, const MultiMooseEnum &coord_sys)
virtual void swapBackMaterialsNeighbor(const THREAD_ID tid)
virtual void addLinearFVKernel(const std::string &kernel_name, const std::string &name, InputParameters &parameters)
void residualSetup()
Calls the residualSetup function for each of the output objects.
virtual NonlinearSystem & getNonlinearSystem(const unsigned int sys_num)
void solveSetup()
Calls the timestepSetup function for each of the output objects.
virtual bool reinitDirac(const Elem *elem, const THREAD_ID tid) override
Returns true if the Problem has Dirac kernels it needs to compute on elem.
MooseAppCoordTransform & coordTransform()
Definition: MooseMesh.h:1923
bool have_parameter(std::string_view name) const
A wrapper around the Parameters base class method.
virtual void cacheResidual(const THREAD_ID tid)
Definition: SubProblem.C:1296
virtual void timestepSetup()
Definition: SubProblem.C:1186
libMesh::Order order() const
Get the order of this variable Note: Order enum can be implicitly converted to unsigned int...
const ExecFlagType EXEC_PRE_DISPLACE
Definition: Moose.C:52
virtual const Elem * elem_ptr(const dof_id_type i) const=0
const std::vector< NonlinearSystemName > _nl_sys_names
The nonlinear system names.
const ExecFlagType EXEC_POSTCHECK
Definition: Moose.C:35
query_obj query
PetscErrorCode PetscInt const PetscInt fields[]
const ExecFlagType EXEC_NONLINEAR
Definition: Moose.C:33
bool isParamSetByUser(const std::string &name) const
Method returns true if the parameter was set by the user.
std::vector< Real > VectorPostprocessorValue
Definition: MooseTypes.h:203
virtual void updateMortarMesh()
void copyValuesBack()
At the end of a timestep this method is called to copy the values back in time in preparation for the...
Definition: ReporterData.C:17
void update()
Builds mortar segment meshes for each mortar interface.
Definition: MortarData.C:149
const std::vector< const Elem * > & coarsenedElementChildren(const Elem *elem) const
Get the newly removed children element ids for an element that was just coarsened.
Definition: MooseMesh.C:958
void restore(const std::filesystem::path &folder_base, const bool for_restart)
Restore an application from file.
Definition: MooseApp.C:1947
void addDefaultMultiAppFixedPointConvergence(const InputParameters &params)
Adds the default fixed point Convergence associated with the problem.
std::set< TagID > _fe_matrix_tags
Moose::Kokkos::MaterialPropertyStorage & _kokkos_material_props
virtual NumericVector< Number > & RHS()=0
virtual void addAuxArrayVariable(const std::string &var_name, const libMesh::FEType &type, unsigned int components, const std::set< SubdomainID > *const active_subdomains=NULL)
const ExecuteMooseObjectWarehouse< Transfer > & getMultiAppTransferWarehouse(Transfer::DIRECTION direction) const
Return the complete warehouse for MultiAppTransfer object for the given direction.
virtual const SystemBase & getSystemBase(const unsigned int sys_num) const
Get constant reference to a system in this problem.
const Elem * neighbor_ptr(unsigned int i) const
virtual void reinitLowerDElem(const Elem *lower_d_elem, const THREAD_ID tid, const std::vector< Point > *const pts=nullptr, const std::vector< Real > *const weights=nullptr) override
void removeSubstring(std::string &main, const std::string &sub)
find, erase, length algorithm for removing a substring from a string
Definition: MooseUtils.C:1201
Provides a way for users to bail out of the current solve.
virtual void addReporter(const std::string &type, const std::string &name, InputParameters &parameters)
Add a Reporter object to the simulation.
virtual void swapBackMaterials(const THREAD_ID tid)
std::vector< VariablePhiValue > _phi_zero
InitialConditionWarehouse _ics
std::vector< unsigned char > _has_active_material_properties
Whether there are active material properties on each thread.
std::string varName(const std::string &var_param_name, const std::string &moose_object_with_var_param_name) const
Determine the actual variable name from the given variable parameter name.
MaterialWarehouse _discrete_materials
bool _reinit_displaced_face
Whether to call DisplacedProblem::reinitElemFace when this->reinitElemFace is called.
void updateBlockMatPropDependency(SubdomainID id, std::unordered_set< unsigned int > &needed_mat_props, THREAD_ID tid=0) const
void setSinglePetscOption(const std::string &name, const std::string &value="", FEProblemBase *const problem=nullptr)
A wrapper function for dealing with different versions of PetscOptionsSetValue.
virtual void initialSetup()
Definition: SubProblem.C:1220
NumericVector< Number > & getRightHandSideVector()
Fetching the right hand side vector from the libmesh system.
Definition: LinearSystem.h:119
virtual void addDGKernel(const std::string &kernel_name, const std::string &name, InputParameters &parameters)
virtual void setCurrentBoundaryID(BoundaryID bid, const THREAD_ID tid) override
sets the current boundary ID in assembly
SolverSystem * _current_solver_sys
The current solver system.
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
virtual std::shared_ptr< const DisplacedProblem > getDisplacedProblem() const
virtual bool contract()=0
std::optional< std::vector< ConvergenceName > > _nonlinear_convergence_names
Nonlinear system(s) convergence name(s)
Generic class for solving transient nonlinear problems.
Definition: SubProblem.h:78
virtual void preProblemInit()
Perform initializations during executing actions right before init_problem task.
Definition: Executioner.h:57
void updateActiveSemiLocalNodeRange(std::set< dof_id_type > &ghosted_elems)
Clears the "semi-local" node list and rebuilds it.
Definition: MooseMesh.C:966
subdomain_id_type subdomain_id() const
virtual void stopSolve(const ExecFlagType &exec_flag, const std::set< TagID > &vector_tags_to_close)=0
Quit the current solve as soon as possible.
const InputParameters * getCommonParameters() const
Get a reference to the common output parameters.
TagID timeVectorTag() const override
Ideally, we should not need this API.
std::map< SubdomainID, std::set< MaterialPropertyName > > _zero_block_material_props
Set of properties returned as zero properties.
Definition: SubProblem.h:1060
Class for containing MooseEnum item information.
Definition: MooseEnumItem.h:18
unsigned int solverSysNum(const SolverSystemName &solver_sys_name) const override
std::shared_ptr< MaterialBase > getMaterial(std::string name, Moose::MaterialDataType type, const THREAD_ID tid=0, bool no_warn=false)
Return a pointer to a MaterialBase object.
virtual void swap(NumericVector< T > &v)
bool hasActiveObject(const std::string &name, THREAD_ID tid=0) const
Convenience functions for checking/getting specific objects.
std::vector< VariableGradient > _grad_zero
bool hasActiveObjects(THREAD_ID tid=0) const
void clearCurrentJacobianMatrixTags()
Clear the current Jacobian matrix tag data structure ...
CTSub CT_OPERATOR_BINARY CTMul CTCompareLess CTCompareGreater CTCompareEqual _arg template * sqrt(_arg)) *_arg.template D< dtag >()) CT_SIMPLE_UNARY_FUNCTION(tanh
virtual void subdomainSetup(SubdomainID subdomain, const THREAD_ID tid)
virtual void restoreOldSolutions()
Restore old solutions from the backup vectors and deallocate them.
unsigned int getInitialSteps() const
Pull out the number of initial steps previously set by calling init()
Definition: Adaptivity.h:98
void max(const T &r, T &o, Request &req) const
void reinitMaterials(SubdomainID blk_id, const THREAD_ID tid, bool swap_stateful=true)
virtual unsigned short dim() const=0
const AutomaticMortarGeneration & getMortarInterface(const std::pair< BoundaryID, BoundaryID > &primary_secondary_boundary_pair, const std::pair< SubdomainID, SubdomainID > &primary_secondary_subdomain_pair, bool on_displaced) const
Return the undisplaced or displaced mortar generation object associated with the provided boundaries ...
bool acceptInvalidSolution() const
Whether or not to accept the solution based on its invalidity.
void setLoadAllVectors(const bool load_all_vectors)
Sets whether or not all vectors are to be loaded.
Class for threaded computation of UserObjects.
const bool _restore_original_nonzero_pattern
Whether we should restore the original nonzero pattern for every Jacobian evaluation.
void setRandomDataPointer(RandomData *random_data)
Base class for all MultiAppTransfer objects.
virtual libMesh::SparseMatrix< Number > & getMatrix(TagID tag)
Get a raw SparseMatrix.
Definition: SystemBase.C:1024
void execMultiAppTransfers(ExecFlagType type, Transfer::DIRECTION direction)
Execute MultiAppTransfers associated with execution flag and direction.
T & set(const std::string &)
Wrapper class that owns a libMesh EquationSystem and adds advanced restart capability to it...
void restoreMultiApps(ExecFlagType type, bool force=false)
Restore the MultiApps associated with the ExecFlagType.
virtual void addLinearFVBC(const std::string &fv_bc_name, const std::string &name, InputParameters &parameters)
virtual bool is_vertex(const unsigned int i) const=0
void subdomainSetup()
Calls the subdomainSetup function for each of the output objects.
const std::string & getName(const unsigned int id) const
const std::vector< dof_id_type > & allDofIndices() const
Get all global dofindices for the variable.
const std::vector< std::string > & get_elem_var_names()
void addMaterialPropertyStorage(MaterialPropertyStorage &mat_props)
Pushes the given pair ( mat_data , mat_props ) onto our list of _materials data to redistribute each ...
SparseMatrix< Number > * matrix
void customSetup(const ExecFlagType &exec_type) override
void setRestartFile(const std::string &file_name)
Communicate to the Resurector the name of the restart filer.
void setCurrentLinearSystem(unsigned int sys_num)
Set the current linear system pointer.
void initNonlocalCoupling()
Create pair of variables requiring nonlocal jacobian contributions.
Definition: Assembly.C:2647
void executeControls(const ExecFlagType &exec_type)
Performs setup and execute calls for Control objects.
virtual std::vector< std::shared_ptr< UserObject > > addUserObject(const std::string &user_object_name, const std::string &name, InputParameters &parameters)
Query query()
query creates and returns an initialized a query object for querying objects from the warehouse...
Definition: TheWarehouse.h:466
void allowOutput(bool state)
Ability to enable/disable output calls This is private, users should utilize FEProblemBase::allowOutp...
bool hasStartTime() const
Definition: MooseApp.h:295
virtual void onTimestepBegin() override
virtual void computeBounds(libMesh::NonlinearImplicitSystem &sys, NumericVector< libMesh::Number > &lower, NumericVector< libMesh::Number > &upper)
Nonlinear system to be solved.
void initKokkos()
Construct Kokkos assembly and systems and allocate Kokkos material property storages.
virtual void computePostCheck(libMesh::NonlinearImplicitSystem &sys, const NumericVector< libMesh::Number > &old_soln, NumericVector< libMesh::Number > &search_direction, NumericVector< libMesh::Number > &new_soln, bool &changed_search_direction, bool &changed_new_soln)
void checkDuplicatePostprocessorVariableNames()
void addConsumer(Moose::MaterialDataType type, const MooseObject *object)
Add object as the consumer of storage of type type.
void setAxisymmetricCoordAxis(const MooseEnum &rz_coord_axis)
For axisymmetric simulations, set the symmetry coordinate axis.
Definition: MooseMesh.C:4234
void addOutput(std::shared_ptr< Output > output)
Adds an existing output object to the warehouse.
void computeResidualAndJacobian(const NumericVector< libMesh::Number > &soln, NumericVector< libMesh::Number > &residual, libMesh::SparseMatrix< libMesh::Number > &jacobian)
Form a residual and Jacobian with default tags.
bool hasDisplacedObjects() const
Returns whether any of the AutomaticMortarGeneration objects are running on a displaced mesh...
Definition: MortarData.h:99
std::vector< std::pair< MooseVariableFEBase *, MooseVariableFEBase * > > & nonlocalCouplingEntries(const THREAD_ID tid, const unsigned int nl_sys_num)
static void selectMatrixTagsFromSystem(const SystemBase &system, const std::map< TagName, TagID > &input_matrix_tags, std::set< TagID > &selected_tags)
Select the matrix tags which belong to a specific system.
Definition: SubProblem.C:301
std::vector< VariableValue > _scalar_zero
virtual Real computeResidualL2Norm()
Computes the residual using whatever is sitting in the current solution vector then returns the L2 no...
void update(GeometricSearchType type=ALL)
Update all of the search objects.
const std::vector< LinearSystemName > _linear_sys_names
The linear system names.
void incrementMultiAppTStep(ExecFlagType type)
Advance the MultiApps t_step (incrementStepOrReject) associated with the ExecFlagType.
Class for scalar variables (they are different).
IntRange< T > make_range(T beg, T end)
void computeLinearSystemTags(const NumericVector< libMesh::Number > &soln, const std::set< TagID > &vector_tags, const std::set< TagID > &matrix_tags, const bool compute_gradients=true)
Assemble the current linear system given a set of vector and matrix tags.
void bumpVolumeQRuleOrder(libMesh::Order order, SubdomainID block)
Increases the element/volume quadrature order for the specified mesh block if and only if the current...
const bool _material_dependency_check
Determines whether a check to verify material dependencies on every subdomain.
std::vector< std::vector< const MooseVariableFEBase * > > _uo_jacobian_moose_vars
virtual MooseMesh & mesh() override
NonlocalKernel is used for solving integral terms in integro-differential equations.
virtual void subdomainSetup(THREAD_ID tid=0) const
std::vector< VariableValue > _zero
CouplingType
Definition: MooseTypes.h:731
void mooseError(Args &&... args) const
Emits an error prefixed with object name and type and optionally a file path to the top-level block p...
Definition: MooseBase.h:271
const ExecFlagType EXEC_SAME_AS_MULTIAPP
Definition: Moose.C:53
unsigned int linearSysNum(const LinearSystemName &linear_sys_name) const override
LinearSystem & currentLinearSystem()
Get a non-constant reference to the current linear system.
virtual void updateActive(THREAD_ID tid=0) override
Update the active status of Kernels.
std::set< TagID > _fe_vector_tags
const std::set< const MooseObject * > & getConsumers(Moose::MaterialDataType type) const
const std::set< const MooseObject * > & getMaterialPropertyStorageConsumers(Moose::MaterialDataType type) const
void addObjectParamsHelper(InputParameters &params, const std::string &object_name, const std::string &var_param_name="variable")
Helper for setting the "_subproblem" and "_sys" parameters in addObject() and in addUserObject().
virtual unsigned int size() const override final
SolverParams & solverParams(unsigned int solver_sys_num=0)
Get the solver parameters.
virtual void saveOldSolutions()
Allocate vectors and save old solutions into them.
std::unique_ptr< NumericVector< Number > > current_local_solution
ADRealVectorValue ADRealGradient
Definition: MooseTypes.h:370
virtual void setActiveFEVariableCoupleableMatrixTags(std::set< TagID > &mtags, const THREAD_ID tid)
Definition: SubProblem.C:364
void mooseConsole()
Send current output buffer to Console output objects.
std::set< std::string > getDependObjects() const
Get a list of dependent UserObjects for this exec type.
virtual void computeTransposeNullSpace(libMesh::NonlinearImplicitSystem &sys, std::vector< NumericVector< libMesh::Number > *> &sp)
bool hasPostprocessor(const std::string &name) const
Deprecated.
virtual bool updateSolution(NumericVector< libMesh::Number > &vec_solution, NumericVector< libMesh::Number > &ghosted_solution)
Update the solution.
ChainControlDataSystem & getChainControlDataSystem()
Gets the system that manages the ChainControls.
Definition: MooseApp.h:845
std::shared_ptr< DisplacedProblem > _displaced_problem
GeometricSearchData _geometric_search_data
State argument for evaluating functors.
void setCurrentResidualVectorTags(const std::set< TagID > &vector_tags)
Set the current residual vector tag data structure based on the passed in tag IDs.
MooseObjectWarehouse< Function > _functions
functions
void project_vector(NumericVector< Number > &new_vector, FunctionBase< Number > *f, FunctionBase< Gradient > *g=nullptr, int is_adjoint=-1) const
virtual void addObject(std::shared_ptr< T > object, THREAD_ID tid=0, bool recurse=true)
Adds an object to the storage structure.
virtual Real & timeOld() const
Proxy for accessing MaterialPropertyStorage.
Definition: MaterialData.h:37
std::vector< VectorVariableValue > _vector_zero
bool hasMultiApp(const std::string &name) const
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...
void createMortarInterface(const std::pair< BoundaryID, BoundaryID > &primary_secondary_boundary_pair, const std::pair< SubdomainID, SubdomainID > &primary_secondary_subdomain_pair, bool on_displaced, bool periodic, const bool debug, const bool correct_edge_dropping, const Real minimum_projection_angle)
std::vector< std::unique_ptr< libMesh::CouplingMatrix > > _cm
Coupling matrix for variables.
bool needInterfaceMaterialOnSide(BoundaryID bnd_id, const THREAD_ID tid)
void reinitElemFace(const Elem *elem, unsigned int side, BoundaryID, const THREAD_ID tid)
virtual void cacheResidualNeighbor(const THREAD_ID tid)
Definition: SubProblem.C:1303
Linear system to be solved.
Definition: LinearSystem.h:35
bool hasReporterValue(const ReporterName &reporter_name) const
Return True if a Reporter value with the given type and name have been created.
Definition: ReporterData.h:445
std::optional< std::vector< ConvergenceName > > _linear_convergence_names
Linear system(s) convergence name(s) (if any)
bool _has_initialized_stateful
Whether nor not stateful materials have been initialized.
void checkICRestartError(const std::string &ic_name, const std::string &name, const VariableName &var_name)
Checks if the variable of the initial condition is getting restarted and errors for specific cases...
virtual void setResidualNeighbor(NumericVector< libMesh::Number > &residual, const THREAD_ID tid) override
QueryCache & condition(Args &&... args)
Adds a new condition to the query.
Definition: TheWarehouse.h:284
const TagName SOLUTION_TAG
Definition: MooseTypes.C:25
unsigned int _max_qps
Maximum number of quadrature points used in the problem.
A class for storing an input parameter name.
static InputParameters validParams()
Eigen::Matrix< Real, Eigen::Dynamic, 1 > RealEigenVector
Definition: MooseTypes.h:146
virtual void addScalarKernel(const std::string &kernel_name, const std::string &name, InputParameters &parameters)
elem_info_iterator ownedElemInfoEnd()
Definition: MooseMesh.C:1574
std::set< const Elem * > & getElements()
Returns a writeable reference to the _elements container.
virtual void set(const numeric_index_type i, const T value)=0
void addGhostedBoundary(BoundaryID boundary_id)
This will add the boundary ids to be ghosted to this processor.
Definition: MooseMesh.C:3250
bool _preserve_matrix_sparsity_pattern
Whether to preserve the system matrix / Jacobian sparsity pattern, using 0-valued entries usually...
virtual unsigned int nNonlinearIterations(const unsigned int nl_sys_num) const override
void setHitNode(const std::string &param, const hit::Node &node, const SetParamHitNodeKey)
Sets the hit node associated with the parameter param to node.
CoverageCheckMode _material_coverage_check
Determines whether and which subdomains are to be checked to ensure that they have an active material...
bool isAdaptivityDue()
Query if an adaptivity step should be performed at the current time / time step.
Definition: Adaptivity.C:393
virtual std::size_t numLinearSystems() const override
MaterialPropertyStorage & _neighbor_material_props
std::unique_ptr< Backup > finalizeRestore()
Finalizes (closes) the restoration process done in restore().
Definition: MooseApp.C:1989
libMesh::StoredRange< MooseMesh::const_bnd_elem_iterator, const BndElement * > * getBoundaryElementRange()
Definition: MooseMesh.C:1341
bool isParamValid(const std::string &name) const
Test if the supplied parameter is valid.
Definition: MooseBase.h:199
MOOSE now contains C++17 code, so give a reasonable error message stating what the user can do to add...
const ConsoleStream _console
An instance of helper class to write streams to the Console objects.
const std::size_t _num_linear_sys
The number of linear systems.
std::map< std::string, unsigned int > _subspace_dim
Dimension of the subspace spanned by the vectors with a given prefix.
const libMesh::ConstElemRange & getEvaluableElementRange()
In general, {evaluable elements} >= {local elements} U {algebraic ghosting elements}.
static InputParameters validParams()
Definition: SubProblem.C:36
bool _currently_computing_residual
Whether the residual is being evaluated.
Definition: SubProblem.h:1107
const UserObject & getUserObjectBase(const std::string &name, const THREAD_ID tid=0) const
Get the user object by its name.
This is a "smart" enum class intended to replace many of the shortcomings in the C++ enum type...
MooseVariableFieldBase & getVariable(THREAD_ID tid, const std::string &var_name) const
Gets a reference to a variable of with specified name.
Definition: SystemBase.C:90
bool _has_internal_edge_residual_objects
Whether the problem has dgkernels or interface kernels.
bool execMultiApps(ExecFlagType type, bool auto_advance=true)
Execute the MultiApps associated with the ExecFlagType.
const std::string & name() const
const std::unordered_map< std::pair< BoundaryID, BoundaryID >, AutomaticMortarGeneration > & getMortarInterfaces(bool on_displaced) const
void paramWarning(const std::string &param, Args... args) const
virtual ArrayMooseVariable & getArrayVariable(const THREAD_ID tid, const std::string &var_name) override
Returns the variable reference for requested ArrayMooseVariable which may be in any system...
const ExecFlagType EXEC_SUBDOMAIN
Definition: Moose.C:50
bool _has_constraints
Whether or not this system has any Constraints.
virtual bool isTransient() const override
bool hasMultiApps() const
Returns whether or not the current simulation has any multiapps.
virtual void reinitNeighbor(const Elem *elem, unsigned int side, const THREAD_ID tid) override
const MaterialData & getMaterialData(const THREAD_ID tid) const
void doingPRefinement(bool doing_p_refinement)
Indicate whether the kind of adaptivity we&#39;re doing is p-refinement.
Definition: MooseMesh.h:1365
const bool & currentlyComputingJacobian() const
Returns true if the problem is in the process of computing the Jacobian.
Definition: SubProblem.h:684
void notifyWhenMeshChanges(MeshChangedInterface *mci)
Register an object that derives from MeshChangedInterface to be notified when the mesh changes...
ConstElemPointerRange * coarsenedElementRange() const
Return a range that is suitable for threaded execution over elements that were just coarsened...
Definition: MooseMesh.C:952
std::unique_ptr< libMesh::ConstElemRange > _evaluable_local_elem_range
const Moose::PatchUpdateType & getPatchUpdateStrategy() const
Get the current patch update strategy.
Definition: MooseMesh.C:3434
virtual void executeAllObjects(const ExecFlagType &exec_type)
CoverageCheckMode _kernel_coverage_check
Determines whether and which subdomains are to be checked to ensure that they have an active kernel...
virtual void setActiveFEVariableCoupleableVectorTags(std::set< TagID > &vtags, const THREAD_ID tid) override
void check() const
Perform integrity check for get/declare calls.
Definition: ReporterData.C:162
std::set< std::string > getPostprocessorNames() const
Return a list of all postprocessor names.
Definition: ReporterData.C:71
bool _fail_next_system_convergence_check
void ghostGhostedBoundaries()
Actually do the ghosting of boundaries that need to be ghosted to this processor. ...
Definition: MooseMesh.C:3335
std::vector< std::shared_ptr< LinearSystem > > _linear_systems
The vector of linear systems.
const hit::Node * getHitNode() const
Definition: MooseBase.h:136
std::shared_ptr< XFEMInterface > _xfem
Pointer to XFEM controller.
virtual void prepareShapes(unsigned int var, const THREAD_ID tid) override
const bool _boundary_restricted_elem_integrity_check
whether to perform checking of boundary restricted elemental object variable dependencies, e.g.
void reinitMaterialsInterface(BoundaryID boundary_id, const THREAD_ID tid, bool swap_stateful=true)
bool _const_jacobian
true if the Jacobian is constant
virtual void computeJacobianBlock(libMesh::SparseMatrix< libMesh::Number > &jacobian, libMesh::System &precond_system, unsigned int ivar, unsigned int jvar)
Really not a good idea to use this.
virtual void solveLinearSystem(const unsigned int linear_sys_num, const Moose::PetscSupport::PetscOptions *po=nullptr)
Build and solve a linear system.
virtual void computeUserObjectByName(const ExecFlagType &type, const Moose::AuxGroup &group, const std::string &name)
Compute an user object with the given name.
virtual void possiblyRebuildGeomSearchPatches()
virtual void add(const numeric_index_type i, const T value)=0
bool _safe_access_tagged_matrices
Is it safe to retrieve data from tagged matrices.
Definition: SubProblem.h:1110
std::set< TagID > _linear_vector_tags
Temporary storage for filtered vector tags for linear systems.
Class that represents the dependecy as a graph.
Moose::Kokkos::MaterialPropertyStorage & _kokkos_bnd_material_props
DiracKernelInfo _dirac_kernel_info
Definition: SubProblem.h:1051
A MultiApp represents one or more MOOSE applications that are running simultaneously.
Definition: MultiApp.h:112
const TagName PREVIOUS_NL_SOLUTION_TAG
Definition: MooseTypes.C:28
void updateBoundaryVariableDependency(std::set< MooseVariableFieldBase *> &needed_moose_vars, THREAD_ID tid=0) const
processor_id_type processor_id() const
void addObject(std::shared_ptr< FVInitialConditionBase > object, THREAD_ID tid, bool recurse=true)
Add object to the warehouse.
std::vector< T * > & queryIntoUnsorted(std::vector< T *> &results, Args &&... args)
queryInto executes the query and stores the results in the given vector.
Definition: TheWarehouse.h:324
const libMesh::ConstElemRange & getNonlinearEvaluableElementRange()
A class for storing the names of MooseObject by tag and object name.
MaterialPropertyStorage & _material_props
Base class for Postprocessors that produce a vector of values.
virtual Order default_order() const=0
void prepareMaterials(const std::unordered_set< unsigned int > &consumer_needed_mat_props, const SubdomainID blk_id, const THREAD_ID tid)
Add the MooseVariables and the material properties that the current materials depend on to the depend...
virtual void addFVKernel(const std::string &kernel_name, const std::string &name, InputParameters &parameters)
virtual void addFVBC(const std::string &fv_bc_name, const std::string &name, InputParameters &parameters)
libMesh::Order _max_scalar_order
Maximum scalar variable order.
virtual void addGhostedBoundary(BoundaryID boundary_id) override
Will make sure that all necessary elements from boundary_id are ghosted to this processor.
virtual bool hasFunction(const std::string &name, const THREAD_ID tid=0)
Adaptivity & adaptivity()
bool hasActiveMaterialProperties(const THREAD_ID tid) const
Method to check whether or not a list of active material roperties has been set.
ExecuteMooseObjectWarehouse< Transfer > _between_multi_app_transfers
Transfers executed just before MultiApps to transfer data between them.
bool isRecovering() const
Whether or not this is a "recover" calculation.
Definition: MooseApp.C:1874
SystemBase & sys()
Get the system this variable is part of.
virtual void cacheJacobian(const THREAD_ID tid) override
auto min(const L &left, const R &right)
TYPE_VECTOR
void jacobianSetup() override
virtual std::size_t numSolverSystems() const override
virtual void addHDGKernel(const std::string &kernel_name, const std::string &name, InputParameters &parameters)
virtual NumericVector< Number > & getVector(const std::string &name)
Get a raw NumericVector by name.
Definition: SystemBase.C:933
Restartable::ManagedValue< RestartableEquationSystems > _req
The EquationSystems object, wrapped for restart.
virtual unsigned int currentLinearSysNum() const override
std::vector< libMesh::CouplingMatrix > _nonlocal_cm
nonlocal coupling matrix
virtual void reinitNodeFace(const Node *node, BoundaryID bnd_id, const THREAD_ID tid) override
virtual void reinitOffDiagScalars(const THREAD_ID tid) override
processor_id_type processor_id() const
virtual void reinitElemPhys(const Elem *elem, const std::vector< Point > &phys_points_in_elem, const THREAD_ID tid) override
std::vector< std::unordered_map< BoundaryID, bool > > _interface_mat_side_cache
Cache for calculating materials on interface.
virtual void addObject(std::shared_ptr< T > object, THREAD_ID tid=0, bool recurse=true) override
Adds an object to the storage structure.
void initKokkosStatefulProps()
const std::vector< std::string > & get_nodal_var_names()
std::string getRestartRecoverFileBase() const
The file_base for the recovery file.
Definition: MooseApp.h:494
virtual void addJacobianNeighborLowerD(const THREAD_ID tid) override
virtual void prepareNeighborShapes(unsigned int var, const THREAD_ID tid) override
MooseObjectWarehouse< Marker > _markers
FVInitialConditionWarehouse _fv_ics
void setVerboseProblem(bool verbose)
Make the problem be verbose.
virtual void setNeighborSubdomainID(const Elem *elem, unsigned int side, const THREAD_ID tid) override
virtual const VectorTag & getVectorTag(const TagID tag_id) const
Get a VectorTag from a TagID.
Definition: SubProblem.C:162
MaterialBases compute MaterialProperties.
Definition: MaterialBase.h:62
virtual void initialAdaptMesh()
void updatePointLocator(const MooseMesh &mesh)
Called during FEProblemBase::meshChanged() to update the PointLocator object used by the DiracKernels...
virtual void addResidualScalar(const THREAD_ID tid=0)
Moose::Kokkos::MaterialPropertyStorage & _kokkos_neighbor_material_props
This is a template class that implements the workhorse compute and computeNodal methods.
MaterialWarehouse _all_materials
const MeshBase::element_iterator activeLocalElementsEnd()
Definition: MooseMesh.C:3078
virtual void addCachedResidual(const THREAD_ID tid) override
void declareControllable(const std::string &name, std::set< ExecFlagType > execute_flags={})
Declare the given parameters as controllable.
for(PetscInt i=0;i< nvars;++i)
void clearNearestNodeLocators()
Clear out the Penetration Locators so they will redo the search.
Moose::PetscSupport::PetscOptions _petsc_options
PETSc option storage.
libMesh::StoredRange< MooseMesh::const_bnd_node_iterator, const BndNode * > * getBoundaryNodeRange()
Definition: MooseMesh.C:1327
virtual const std::vector< std::shared_ptr< Convergence > > & getConvergenceObjects(const THREAD_ID tid=0) const
Gets the Convergence objects.
void ErrorVector unsigned int
virtual void clearActiveElementalMooseVariables(const THREAD_ID tid) override
Clear the active elemental MooseVariableFEBase.
auto index_range(const T &sizable)
Base class for user-specific data.
Definition: UserObject.h:40
void timestepSetup()
Calls the timestepSetup function for each of the output objects.
void allowOutput(bool state)
Ability to enable/disable all output calls.
virtual void cacheJacobian(const THREAD_ID tid)
Definition: SubProblem.C:1317
virtual Sampler & getSampler(const std::string &name, const THREAD_ID tid=0)
const std::string & _type
The type of this class.
Definition: MooseBase.h:360
virtual void outputStep(ExecFlagType type)
Output the current step.
void projectInitialConditionOnCustomRange(libMesh::ConstElemRange &elem_range, ConstBndNodeRange &bnd_node_range, const std::optional< std::set< VariableName >> &target_vars=std::nullopt)
Project initial conditions for custom elem_range and bnd_node_range This is needed when elements/boun...
virtual unsigned int nlSysNum(const NonlinearSystemName &nl_sys_name) const override
OutputWarehouse & getOutputWarehouse()
Get the OutputWarehouse objects.
Definition: MooseApp.C:2515
MooseEnum _verbose_setup
Whether or not to be verbose during setup.
static InputParameters validParams()
RedistributeProperties is used for its redistribute() callback, which ensures that any stateful prope...
unsigned int state
The state.
virtual void computeJacobianTags(const std::set< TagID > &tags)
Form multiple matrices, and each is associated with a tag.
void computeSystems(const ExecFlagType &type)
Do generic system computations.
SolutionIterationType
Definition: MooseTypes.h:241
MooseMesh * _displaced_mesh
void resize(unsigned int n_qpoints)
Resize the data to hold properties for n_qpoints quadrature points.
Definition: MaterialData.C:21
bool _has_mortar
Whether the simulation requires mortar coupling.
void computeLinearSystemTags(const std::set< TagID > &vector_tags, const std::set< TagID > &matrix_tags, const bool compute_gradients=true)
Compute the right hand side and the system matrix of the system for given tags.
Definition: LinearSystem.C:154
libMesh::Order getMaxScalarOrder() const
void execTransfers(ExecFlagType type)
Execute the Transfers associated with the ExecFlagType.
void addNotZeroedVectorTag(const TagID tag)
Adds a vector tag to the list of vectors that will not be zeroed when other tagged vectors are...
Definition: SubProblem.C:150
Base variable class.
void restoreState(bool verbose=false)
When a time step fails, this method is called to revert the current reporter values to their old stat...
Definition: ReporterData.C:24
void meshChanged()
Declares that the MooseMesh has changed, invalidates cached data and rebuilds caches.
Definition: MooseMesh.C:897
void buildPRefinementAndCoarseningMaps(Assembly *assembly)
Definition: MooseMesh.C:2406
const std::vector< ConvergenceName > & getLinearConvergenceNames() const
Gets the linear convergence object name(s).
unsigned int THREAD_ID
Definition: MooseTypes.h:209
virtual void ghostGhostedBoundaries() override
Causes the boundaries added using addGhostedBoundary to actually be ghosted.
const ExecFlagType EXEC_POST_ADAPTIVITY
Definition: Moose.C:58
void add_ghosting_functor(GhostingFunctor &ghosting_functor)
MaterialWarehouse _materials
uint8_t dof_id_type
virtual bool adaptMesh()
virtual void addJacobianScalar(const THREAD_ID tid=0)
virtual void addDiracKernel(const std::string &kernel_name, const std::string &name, InputParameters &parameters)
An instance of this object type has one copy per thread that runs on each thread. ...
MooseObjectWarehouse< IntegratedBCBase > _nonlocal_integrated_bcs
nonlocal integrated_bcs
virtual void computeResidualTag(const NumericVector< libMesh::Number > &soln, NumericVector< libMesh::Number > &residual, TagID tag)
Form a residual vector for a given tag.
virtual VectorMooseVariable & getVectorVariable(const THREAD_ID tid, const std::string &var_name) override
Returns the variable reference for requested VectorMooseVariable which may be in any system...
std::shared_ptr< LineSearch > _line_search
void initXFEM(std::shared_ptr< XFEMInterface > xfem)
Create XFEM controller object.
const std::set< SubdomainID > & meshSubdomains() const
Returns a read-only reference to the set of subdomains currently present in the Mesh.
Definition: MooseMesh.C:3192
SubdomainID getSubdomainID(const SubdomainName &subdomain_name) const
Get the associated subdomain ID for the subdomain name.
Definition: MooseMesh.C:1769
const FEType & type() const
Base class for all Transfer objects.
Definition: Transfer.h:36
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...
virtual void neighborSubdomainSetup(SubdomainID subdomain, const THREAD_ID tid)
void setupFiniteVolumeMeshData() const
Sets up the additional data needed for finite volume computations.
Definition: MooseMesh.C:4093
virtual void addCachedJacobian(const THREAD_ID tid) override
virtual void residualSetup(THREAD_ID tid=0) const
virtual void sizeZeroes(unsigned int size, const THREAD_ID tid)
virtual Real computeDamping(const NumericVector< libMesh::Number > &soln, const NumericVector< libMesh::Number > &update)
std::vector< Real > _real_zero
Convenience zeros.
MooseObjectWarehouse< KernelBase > _nonlocal_kernels
nonlocal kernels
void checkCoordinateSystems()
Verify that there are no element type/coordinate type conflicts.
bool isParamValid(const std::string &name) const
This method returns parameters that have been initialized in one fashion or another, i.e.
unsigned int getMaxQps() const
const ExecFlagType EXEC_INITIAL
Definition: Moose.C:30
virtual libMesh::System & system() override
Get the reference to the libMesh system.
bool _verbose_multiapps
Whether or not to be verbose with multiapps.
Key structure for APIs manipulating global vectors/matrices.
Definition: Assembly.h:844