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