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