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