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