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