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