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