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