www.mooseframework.org
FEProblemBase.C
Go to the documentation of this file.
1 //* This file is part of the MOOSE framework
2 //* https://www.mooseframework.org
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 "NonlinearSystem.h"
39 #include "Distribution.h"
40 #include "Sampler.h"
41 #include "PetscSupport.h"
42 #include "RandomInterface.h"
43 #include "RandomData.h"
44 #include "MooseEigenSystem.h"
45 #include "MooseParsedFunction.h"
46 #include "MeshChangedInterface.h"
48 #include "ScalarInitialCondition.h"
50 #include "ElementPostprocessor.h"
51 #include "NodalPostprocessor.h"
52 #include "SidePostprocessor.h"
54 #include "InterfacePostprocessor.h"
55 #include "GeneralPostprocessor.h"
61 #include "Positions.h"
62 #include "Indicator.h"
63 #include "Marker.h"
64 #include "MultiApp.h"
65 #include "MultiAppTransfer.h"
66 #include "TransientMultiApp.h"
67 #include "ElementUserObject.h"
68 #include "DomainUserObject.h"
69 #include "NodalUserObject.h"
70 #include "SideUserObject.h"
71 #include "InternalSideUserObject.h"
72 #include "InterfaceUserObject.h"
73 #include "GeneralUserObject.h"
75 #include "InternalSideIndicator.h"
76 #include "Transfer.h"
77 #include "MultiAppTransfer.h"
78 #include "MultiMooseEnum.h"
79 #include "Predictor.h"
80 #include "Assembly.h"
81 #include "Control.h"
82 #include "XFEMInterface.h"
83 #include "ConsoleUtils.h"
84 #include "NonlocalKernel.h"
85 #include "NonlocalIntegratedBC.h"
86 #include "ShapeElementUserObject.h"
87 #include "ShapeSideUserObject.h"
88 #include "MooseVariableFE.h"
89 #include "MooseVariableScalar.h"
91 #include "TimeIntegrator.h"
92 #include "LineSearch.h"
94 #include "MaxVarNDofsPerElem.h"
95 #include "MaxVarNDofsPerNode.h"
96 #include "FVKernel.h"
97 #include "FVTimeKernel.h"
98 #include "MooseVariableFV.h"
99 #include "FVBoundaryCondition.h"
100 #include "FVInterfaceKernel.h"
101 #include "Reporter.h"
102 #include "ADUtils.h"
103 #include "Executioner.h"
104 #include "VariadicTable.h"
107 #include "NodalBCBase.h"
108 #include "MortarUserObject.h"
109 #include "MortarUserObjectThread.h"
110 #include "RedistributeProperties.h"
111 #include "Checkpoint.h"
112 
113 #include "libmesh/exodusII_io.h"
114 #include "libmesh/quadrature.h"
115 #include "libmesh/coupling_matrix.h"
116 #include "libmesh/nonlinear_solver.h"
117 #include "libmesh/sparse_matrix.h"
118 #include "libmesh/string_to_enum.h"
119 #include "libmesh/fe_interface.h"
120 #include "libmesh/enum_norm_type.h"
121 #include "libmesh/petsc_solver_exception.h"
122 
123 #include "metaphysicl/dualnumber.h"
124 
125 // Anonymous namespace for helper function
126 namespace
127 {
131 bool
132 sortMooseVariables(const MooseVariableFEBase * a, const MooseVariableFEBase * b)
133 {
134  return a->number() < b->number();
135 }
136 } // namespace
137 
138 Threads::spin_mutex get_function_mutex;
139 
142 {
144  params.addParam<unsigned int>("null_space_dimension", 0, "The dimension of the nullspace");
145  params.addParam<unsigned int>(
146  "transpose_null_space_dimension", 0, "The dimension of the transpose nullspace");
147  params.addParam<unsigned int>(
148  "near_null_space_dimension", 0, "The dimension of the near nullspace");
149  params.addParam<bool>("solve",
150  true,
151  "Whether or not to actually solve the Nonlinear system. "
152  "This is handy in the case that all you want to do is "
153  "execute AuxKernels, Transfers, etc. without actually "
154  "solving anything");
155  params.addParam<bool>("use_nonlinear",
156  true,
157  "Determines whether to use a Nonlinear vs a "
158  "Eigenvalue system (Automatically determined based "
159  "on executioner)");
160  params.addParam<bool>("error_on_jacobian_nonzero_reallocation",
161  "This causes PETSc to error if it had to reallocate memory in the Jacobian "
162  "matrix due to not having enough nonzeros");
163  params.addParam<bool>("ignore_zeros_in_jacobian",
164  false,
165  "Do not explicitly store zero values in "
166  "the Jacobian matrix if true");
167  params.addParam<bool>("force_restart",
168  false,
169  "EXPERIMENTAL: If true, a sub_app may use a "
170  "restart file instead of using of using the master "
171  "backup file");
172  params.addDeprecatedParam<bool>("skip_additional_restart_data",
173  false,
174  "True to skip additional data in equation system for restart.",
175  "This parameter is no longer used, as we do not load additional "
176  "vectors by default with restart");
177  params.addParam<bool>("skip_nl_system_check",
178  false,
179  "True to skip the NonlinearSystem check for work to do (e.g. Make sure "
180  "that there are variables to solve for).");
181  params.addParam<bool>("allow_initial_conditions_with_restart",
182  false,
183  "True to allow the user to specify initial conditions when restarting. "
184  "Initial conditions can override any restarted field");
185 
191  params.addDeprecatedParam<std::vector<SubdomainName>>(
192  "block", {}, "Block IDs for the coordinate systems", "Please use 'Mesh/coord_block' instead");
193  MultiMooseEnum coord_types("XYZ RZ RSPHERICAL", "XYZ");
194  MooseEnum rz_coord_axis("X=0 Y=1", "Y");
195  params.addDeprecatedParam<MultiMooseEnum>("coord_type",
196  coord_types,
197  "Type of the coordinate system per block param",
198  "Please use 'Mesh/coord_type' instead");
199  params.addDeprecatedParam<MooseEnum>("rz_coord_axis",
200  rz_coord_axis,
201  "The rotation axis (X | Y) for axisymetric coordinates",
202  "Please use 'Mesh/rz_coord_axis' instead");
203  params.addParam<bool>(
204  "kernel_coverage_check", true, "Set to false to disable kernel->subdomain coverage check");
205  params.addParam<bool>(
206  "boundary_restricted_node_integrity_check",
207  true,
208  "Set to false to disable checking of boundary restricted nodal object variable dependencies, "
209  "e.g. are the variable dependencies defined on the selected boundaries?");
210  params.addParam<bool>("boundary_restricted_elem_integrity_check",
211  true,
212  "Set to false to disable checking of boundary restricted elemental object "
213  "variable dependencies, e.g. are the variable dependencies defined on the "
214  "selected boundaries?");
215  params.addParam<bool>("material_coverage_check",
216  true,
217  "Set to false to disable material->subdomain coverage check");
218  params.addParam<bool>("fv_bcs_integrity_check",
219  true,
220  "Set to false to disable checking of overlapping Dirichlet and Flux BCs "
221  "and/or multiple DirichletBCs per sideset");
222 
223  params.addParam<bool>(
224  "material_dependency_check", true, "Set to false to disable material dependency check");
225  params.addParam<bool>("parallel_barrier_messaging",
226  false,
227  "Displays messaging from parallel "
228  "barrier notifications when executing "
229  "or transferring to/from Multiapps "
230  "(default: false)");
231 
232  params.addParam<bool>(
233  "verbose_setup", false, "Set to True to have the problem report on any object created");
234  params.addParam<bool>("verbose_multiapps",
235  false,
236  "Set to True to enable verbose screen printing related to MultiApps");
237 
238  params.addParam<FileNameNoExtension>("restart_file_base",
239  "File base name used for restart (e.g. "
240  "<path>/<filebase> or <path>/LATEST to "
241  "grab the latest file available)");
242 
243  params.addParam<std::vector<std::vector<TagName>>>(
244  "extra_tag_vectors",
245  {},
246  "Extra vectors to add to the system that can be filled by objects which compute residuals "
247  "and Jacobians (Kernels, BCs, etc.) by setting tags on them. The outer index is for which "
248  "nonlinear system the extra tag vectors should be added for");
249 
250  params.addParam<std::vector<std::vector<TagName>>>(
251  "extra_tag_matrices",
252  {},
253  "Extra matrices to add to the system that can be filled "
254  "by objects which compute residuals and Jacobians "
255  "(Kernels, BCs, etc.) by setting tags on them. The outer index is for which "
256  "nonlinear system the extra tag vectors should be added for");
257 
258  params.addParam<std::vector<TagName>>(
259  "extra_tag_solutions",
260  {},
261  "Extra solution vectors to add to the system that can be used by "
262  "objects for coupling variable values stored in them.");
263 
264  params.addParam<bool>("previous_nl_solution_required",
265  false,
266  "True to indicate that this calculation requires a solution vector for "
267  "storing the previous nonlinear iteration.");
268 
269  params.addParam<std::vector<NonlinearSystemName>>(
270  "nl_sys_names", std::vector<NonlinearSystemName>{"nl0"}, "The nonlinear system names");
271 
272  params.addParam<bool>("check_uo_aux_state",
273  false,
274  "True to turn on a check that no state presents during the evaluation of "
275  "user objects and aux kernels");
276 
277  params.addPrivateParam<MooseMesh *>("mesh");
278 
279  params.declareControllable("solve");
280 
281  params.addParam<bool>(
282  "allow_invalid_solution",
283  false,
284  "Set to true to allow convergence even though the solution has been marked as 'invalid'");
285  params.addParam<bool>("immediately_print_invalid_solution",
286  false,
287  "Whether or not to report invalid solution warnings at the time the "
288  "warning is produced instead of after the calculation");
289 
290  params.addParam<bool>(
291  "identify_variable_groups_in_nl",
292  true,
293  "Whether to identify variable groups in nonlinear systems. This affects dof ordering");
294 
295  params.addParam<bool>(
296  "regard_general_exceptions_as_errors",
297  false,
298  "If we catch an exception during residual/Jacobian evaluaton for which we don't have "
299  "specific handling, immediately error instead of allowing the time step to be cut");
300 
301  params.addParamNamesToGroup(
302  "skip_nl_system_check kernel_coverage_check boundary_restricted_node_integrity_check "
303  "boundary_restricted_elem_integrity_check material_coverage_check fv_bcs_integrity_check "
304  "material_dependency_check check_uo_aux_state error_on_jacobian_nonzero_reallocation",
305  "Simulation checks");
306  params.addParamNamesToGroup("use_nonlinear previous_nl_solution_required nl_sys_names "
307  "ignore_zeros_in_jacobian",
308  "Nonlinear system(s)");
309  params.addParamNamesToGroup(
310  "restart_file_base force_restart allow_initial_conditions_with_restart", "Restart");
311  params.addParamNamesToGroup("verbose_setup verbose_multiapps parallel_barrier_messaging",
312  "Verbosity");
313  params.addParamNamesToGroup(
314  "null_space_dimension transpose_null_space_dimension near_null_space_dimension",
315  "Null space removal");
316  params.addParamNamesToGroup("extra_tag_vectors extra_tag_matrices extra_tag_solutions",
317  "Tagging");
318  params.addParamNamesToGroup("allow_invalid_solution immediately_print_invalid_solution",
319  "Solution validity control");
320 
321  return params;
322 }
323 
325  : SubProblem(parameters),
326  Restartable(this, "FEProblemBase"),
327  _mesh(*getCheckedPointerParam<MooseMesh *>("mesh")),
328  _req(declareManagedRestartableDataWithContext<RestartableEquationSystems>(
329  "equation_systems", nullptr, _mesh)),
330  _initialized(false),
331  _solve(getParam<bool>("solve")),
332  _transient(false),
333  _time(declareRestartableData<Real>("time")),
334  _time_old(declareRestartableData<Real>("time_old")),
335  _t_step(declareRecoverableData<int>("t_step")),
336  _dt(declareRestartableData<Real>("dt")),
337  _dt_old(declareRestartableData<Real>("dt_old")),
338  _nl_sys_names(getParam<std::vector<NonlinearSystemName>>("nl_sys_names")),
339  _num_nl_sys(_nl_sys_names.size()),
340  _nl(_num_nl_sys, nullptr),
341  _current_nl_sys(nullptr),
342  _aux(nullptr),
343  _coupling(Moose::COUPLING_DIAG),
344  _mesh_divisions(/*threaded=*/true),
345  _material_props(declareRestartableDataWithContext<MaterialPropertyStorage>(
346  "material_props", &_mesh, _material_prop_registry)),
347  _bnd_material_props(declareRestartableDataWithContext<MaterialPropertyStorage>(
348  "bnd_material_props", &_mesh, _material_prop_registry)),
349  _neighbor_material_props(declareRestartableDataWithContext<MaterialPropertyStorage>(
350  "neighbor_material_props", &_mesh, _material_prop_registry)),
351  _reporter_data(_app),
352  // TODO: delete the following line after apps have been updated to not call getUserObjects
353  _all_user_objects(_app.getExecuteOnEnum()),
354  _multi_apps(_app.getExecuteOnEnum()),
355  _transient_multi_apps(_app.getExecuteOnEnum()),
356  _transfers(_app.getExecuteOnEnum(), /*threaded=*/false),
357  _to_multi_app_transfers(_app.getExecuteOnEnum(), /*threaded=*/false),
358  _from_multi_app_transfers(_app.getExecuteOnEnum(), /*threaded=*/false),
359  _between_multi_app_transfers(_app.getExecuteOnEnum(), /*threaded=*/false),
360 #ifdef LIBMESH_ENABLE_AMR
361  _adaptivity(*this),
362  _cycles_completed(0),
363 #endif
364  _displaced_mesh(nullptr),
365  _geometric_search_data(*this, _mesh),
366  _mortar_data(*this),
367  _reinit_displaced_elem(false),
368  _reinit_displaced_face(false),
369  _reinit_displaced_neighbor(false),
370  _input_file_saved(false),
371  _has_dampers(false),
372  _has_constraints(false),
373  _snesmf_reuse_base(true),
374  _skip_exception_check(false),
375  _snesmf_reuse_base_set_by_user(false),
376  _has_initialized_stateful(false),
377  _const_jacobian(false),
378  _has_jacobian(false),
379  _needs_old_newton_iter(false),
380  _has_nonlocal_coupling(false),
381  _calculate_jacobian_in_uo(false),
382  _kernel_coverage_check(getParam<bool>("kernel_coverage_check")),
383  _boundary_restricted_node_integrity_check(
384  getParam<bool>("boundary_restricted_node_integrity_check")),
385  _boundary_restricted_elem_integrity_check(
386  getParam<bool>("boundary_restricted_elem_integrity_check")),
387  _material_coverage_check(getParam<bool>("material_coverage_check")),
388  _fv_bcs_integrity_check(getParam<bool>("fv_bcs_integrity_check")),
389  _material_dependency_check(getParam<bool>("material_dependency_check")),
390  _uo_aux_state_check(getParam<bool>("check_uo_aux_state")),
391  _max_qps(std::numeric_limits<unsigned int>::max()),
392  _max_scalar_order(INVALID_ORDER),
393  _has_time_integrator(false),
394  _has_exception(false),
395  _parallel_barrier_messaging(getParam<bool>("parallel_barrier_messaging")),
396  _verbose_setup(getParam<bool>("verbose_setup")),
397  _verbose_multiapps(getParam<bool>("verbose_multiapps")),
398  _current_execute_on_flag(EXEC_NONE),
399  _control_warehouse(_app.getExecuteOnEnum(), /*threaded=*/false),
400  _is_petsc_options_inserted(false),
401  _line_search(nullptr),
402  _using_ad_mat_props(false),
403  _error_on_jacobian_nonzero_reallocation(
404  isParamValid("error_on_jacobian_nonzero_reallocation")
405  ? getParam<bool>("error_on_jacobian_nonzero_reallocation")
406  : _app.errorOnJacobianNonzeroReallocation()),
407  _ignore_zeros_in_jacobian(getParam<bool>("ignore_zeros_in_jacobian")),
408  _force_restart(getParam<bool>("force_restart")),
409  _allow_ics_during_restart(getParam<bool>("allow_initial_conditions_with_restart")),
410  _skip_nl_system_check(getParam<bool>("skip_nl_system_check")),
411  _fail_next_nonlinear_convergence_check(false),
412  _allow_invalid_solution(getParam<bool>("allow_invalid_solution")),
413  _immediately_print_invalid_solution(getParam<bool>("immediately_print_invalid_solution")),
414  _started_initial_setup(false),
415  _has_internal_edge_residual_objects(false),
416  _u_dot_requested(false),
417  _u_dotdot_requested(false),
418  _u_dot_old_requested(false),
419  _u_dotdot_old_requested(false),
420  _has_mortar(false),
421  _num_grid_steps(0),
422  _print_execution_on(),
423  _identify_variable_groups_in_nl(getParam<bool>("identify_variable_groups_in_nl")),
424  _regard_general_exceptions_as_errors(getParam<bool>("regard_general_exceptions_as_errors"))
425 {
426  // Initialize static do_derivatives member. We initialize this to true so that all the default AD
427  // things that we setup early in the simulation actually get their derivative vectors initalized.
428  // We will toggle this to false when doing residual evaluations
429  ADReal::do_derivatives = true;
430 
431  for (const auto i : index_range(_nl_sys_names))
433  _nonlocal_cm.resize(_nl_sys_names.size());
434  _cm.resize(_nl_sys_names.size());
435 
436  _time = 0.0;
437  _time_old = 0.0;
438  _t_step = 0;
439  _dt = 0;
440  _dt_old = _dt;
441 
442  unsigned int n_threads = libMesh::n_threads();
443 
444  _real_zero.resize(n_threads, 0.);
445  _scalar_zero.resize(n_threads);
446  _zero.resize(n_threads);
447  _phi_zero.resize(n_threads);
448  _ad_zero.resize(n_threads);
449  _grad_zero.resize(n_threads);
450  _ad_grad_zero.resize(n_threads);
451  _grad_phi_zero.resize(n_threads);
452  _second_zero.resize(n_threads);
453  _ad_second_zero.resize(n_threads);
454  _second_phi_zero.resize(n_threads);
455  _point_zero.resize(n_threads);
456  _vector_zero.resize(n_threads);
459 
461 
465 
466  es().parameters.set<FEProblemBase *>("_fe_problem_base") = this;
467 
468  if (parameters.isParamSetByUser("coord_type"))
469  setCoordSystem(getParam<std::vector<SubdomainName>>("block"),
470  getParam<MultiMooseEnum>("coord_type"));
471  if (parameters.isParamSetByUser("rz_coord_axis"))
472  setAxisymmetricCoordAxis(getParam<MooseEnum>("rz_coord_axis"));
473 
474  if (isParamValid("restart_file_base"))
475  {
476  std::string restart_file_base = getParam<FileNameNoExtension>("restart_file_base");
477 
478  // This check reverts to old behavior of providing "restart_file_base=" to mean
479  // don't restart... BISON currently relies on this. It could probably be removed.
480  // The new MooseUtils::convertLatestCheckpoint will error out if a checkpoint file
481  // is not found, which I think makes sense. Which means, without this, if you
482  // set "restart_file_base=", you'll get a "No checkpoint file found" error
483  if (restart_file_base.size())
484  {
485  restart_file_base = MooseUtils::convertLatestCheckpoint(restart_file_base);
486  setRestartFile(restart_file_base);
487  }
488  }
489 
490  // // Generally speaking, the mesh is prepared for use, and consequently remote elements are deleted
491  // // well before our Problem(s) are constructed. Historically, in MooseMesh we have a bunch of
492  // // needs_prepare type flags that make it so we never call prepare_for_use (and consequently
493  // // delete_remote_elements) again. So the below line, historically, has had no impact. HOWEVER:
494  // // I've added some code in SetupMeshCompleteAction for deleting remote elements post
495  // // EquationSystems::init. If I execute that code without default ghosting, then I get > 40 MOOSE
496  // // test failures, so we clearly have some simulations that are not yet covered properly by
497  // // relationship managers. Until that is resolved, I am going to retain default geometric ghosting
498  // if (!_default_ghosting)
499  // _mesh.getMesh().remove_ghosting_functor(_mesh.getMesh().default_ghosting());
500 
501 #if !PETSC_RELEASE_LESS_THAN(3, 12, 0)
502  // Main app should hold the default database to handle system petsc options
503  if (!_app.isUltimateMaster())
504  PetscOptionsCreate(&_petsc_option_data_base);
505 #endif
506 }
507 
508 const MooseMesh &
509 FEProblemBase::mesh(bool use_displaced) const
510 {
511  if (use_displaced && !_displaced_problem)
512  mooseWarning("Displaced mesh was requested but the displaced problem does not exist. "
513  "Regular mesh will be returned");
514  return ((use_displaced && _displaced_problem) ? _displaced_problem->mesh() : mesh());
515 }
516 
517 void
519 {
520  // add vectors and their tags to system
521  auto & vectors = getParam<std::vector<std::vector<TagName>>>("extra_tag_vectors");
522  for (const auto nl_sys_num : index_range(vectors))
523  for (auto & vector : vectors[nl_sys_num])
524  {
525  auto tag = addVectorTag(vector);
526  _nl[nl_sys_num]->addVector(tag, false, GHOSTED);
527  }
528 
529  // add matrices and their tags
530  auto & matrices = getParam<std::vector<std::vector<TagName>>>("extra_tag_matrices");
531  for (const auto nl_sys_num : index_range(matrices))
532  for (auto & matrix : matrices[nl_sys_num])
533  {
534  auto tag = addMatrixTag(matrix);
535  _nl[nl_sys_num]->addMatrix(tag);
536  }
537 }
538 
539 void
541 {
542  for (auto & vector : getParam<std::vector<TagName>>("extra_tag_solutions"))
543  {
544  auto tag = addVectorTag(vector, Moose::VECTOR_TAG_SOLUTION);
545  for (auto & nl : _nl)
546  nl->addVector(tag, false, GHOSTED);
547  _aux->addVector(tag, false, GHOSTED);
548  }
549 
550  if (getParam<bool>("previous_nl_solution_required"))
551  {
552  // We'll populate the zeroth state of the nonlinear iterations with the current solution for
553  // ease of use in doing things like copying solutions backwards. We're just storing pointers in
554  // the solution states containers so populating the zeroth state does not cost us the memory of
555  // a new vector
556  for (const auto i : make_range(0, 2))
557  {
558  for (auto & nl : _nl)
559  nl->needSolutionState(i, Moose::SolutionIterationType::Nonlinear);
560  _aux->needSolutionState(i, Moose::SolutionIterationType::Nonlinear);
561  }
562  }
563 
565  for (auto & nl : _nl)
566  nl->associateVectorToTag(*nl->system().current_local_solution.get(), tag);
567  _aux->associateVectorToTag(*_aux->system().current_local_solution.get(), tag);
568 }
569 
570 void
571 FEProblemBase::newAssemblyArray(std::vector<std::shared_ptr<NonlinearSystemBase>> & nls)
572 {
573  unsigned int n_threads = libMesh::n_threads();
574 
575  _assembly.resize(n_threads);
576  for (const auto i : make_range(n_threads))
577  {
578  _assembly[i].resize(nls.size());
579  for (const auto j : index_range(nls))
580  _assembly[i][j] = std::make_unique<Assembly>(*nls[j], i);
581  }
582 }
583 
584 void
586  std::vector<std::shared_ptr<NonlinearSystemBase>> & nls)
587 {
588  TIME_SECTION("initNullSpaceVectors", 5, "Initializing Null Space Vectors");
589 
590  unsigned int dimNullSpace = parameters.get<unsigned int>("null_space_dimension");
591  unsigned int dimTransposeNullSpace =
592  parameters.get<unsigned int>("transpose_null_space_dimension");
593  unsigned int dimNearNullSpace = parameters.get<unsigned int>("near_null_space_dimension");
594  for (unsigned int i = 0; i < dimNullSpace; ++i)
595  {
596  std::ostringstream oss;
597  oss << "_" << i;
598  // do not project, since this will be recomputed, but make it ghosted, since the near nullspace
599  // builder might march over all nodes
600  for (auto & nl : nls)
601  nl->addVector("NullSpace" + oss.str(), false, GHOSTED);
602  }
603  _subspace_dim["NullSpace"] = dimNullSpace;
604  for (unsigned int i = 0; i < dimTransposeNullSpace; ++i)
605  {
606  std::ostringstream oss;
607  oss << "_" << i;
608  // do not project, since this will be recomputed, but make it ghosted, since the near nullspace
609  // builder might march over all nodes
610  for (auto & nl : nls)
611  nl->addVector("TransposeNullSpace" + oss.str(), false, GHOSTED);
612  }
613  _subspace_dim["TransposeNullSpace"] = dimTransposeNullSpace;
614  for (unsigned int i = 0; i < dimNearNullSpace; ++i)
615  {
616  std::ostringstream oss;
617  oss << "_" << i;
618  // do not project, since this will be recomputed, but make it ghosted, since the near-nullspace
619  // builder might march over all semilocal nodes
620  for (auto & nl : nls)
621  nl->addVector("NearNullSpace" + oss.str(), false, GHOSTED);
622  }
623  _subspace_dim["NearNullSpace"] = dimNearNullSpace;
624 }
625 
627 {
628  // Flush the Console stream, the underlying call to Console::mooseConsole
629  // relies on a call to Output::checkInterval that has references to
630  // _time, etc. If it is not flushed here memory problems arise if you have
631  // an unflushed stream and start destructing things.
632  _console << std::flush;
633 
634  unsigned int n_threads = libMesh::n_threads();
635  for (unsigned int i = 0; i < n_threads; i++)
636  {
637  _zero[i].release();
638  _phi_zero[i].release();
639  _scalar_zero[i].release();
640  _grad_zero[i].release();
641  _grad_phi_zero[i].release();
642  _second_zero[i].release();
643  _second_phi_zero[i].release();
644  _vector_zero[i].release();
645  _vector_curl_zero[i].release();
646  _ad_zero[i].release();
647  _ad_grad_zero[i].release();
648  _ad_second_zero[i].release();
649  }
650 
651 #if !PETSC_RELEASE_LESS_THAN(3, 12, 0)
652  if (!_app.isUltimateMaster())
653  PetscOptionsDestroy(&_petsc_option_data_base);
654 #endif
655 }
656 
657 void
658 FEProblemBase::setCoordSystem(const std::vector<SubdomainName> & blocks,
659  const MultiMooseEnum & coord_sys)
660 {
661  TIME_SECTION("setCoordSystem", 5, "Setting Coordinate System");
662  _mesh.setCoordSystem(blocks, coord_sys);
663 }
664 
665 void
667 {
668  _mesh.setAxisymmetricCoordAxis(rz_coord_axis);
669 }
670 
671 const ConstElemRange &
673 {
675  {
676  std::vector<const DofMap *> dof_maps(es().n_systems());
677  for (const auto i : make_range(es().n_systems()))
678  {
679  const auto & sys = es().get_system(i);
680  dof_maps[i] = &sys.get_dof_map();
681  }
683  std::make_unique<ConstElemRange>(_mesh.getMesh().multi_evaluable_elements_begin(dof_maps),
684  _mesh.getMesh().multi_evaluable_elements_end(dof_maps));
685  }
687 }
688 
689 const ConstElemRange &
691 {
693  {
694  std::vector<const DofMap *> dof_maps(_nl.size());
695  for (const auto i : index_range(dof_maps))
696  dof_maps[i] = &_nl[i]->dofMap();
698  std::make_unique<ConstElemRange>(_mesh.getMesh().multi_evaluable_elements_begin(dof_maps),
699  _mesh.getMesh().multi_evaluable_elements_end(dof_maps));
700  }
701 
703 }
704 
705 void
707 {
708  TIME_SECTION("initialSetup", 2, "Performing Initial Setup");
709 
711 
713  mooseError("Checkpoint recovery and restart and exodus restart are all mutually exclusive.");
714 
716  mooseWarning("MOOSE may fail to catch an exception when the \"skip_exception_check\" parameter "
717  "is used. If you receive a terse MPI error during execution, remove this "
718  "parameter and rerun your simulation");
719 
720  // set state flag indicating that we are in or beyond initialSetup.
721  // This can be used to throw errors in methods that _must_ be called at construction time.
722  _started_initial_setup = true;
724 
725  // Setup the solution states (current, old, etc) in each system based on
726  // its default and the states requested of each of its variables
727  for (const auto i : index_range(_nl))
728  {
729  _nl[i]->initSolutionState();
730  if (getDisplacedProblem())
731  getDisplacedProblem()->nlSys(i).initSolutionState();
732  }
733  _aux->initSolutionState();
734  if (getDisplacedProblem())
735  getDisplacedProblem()->auxSys().initSolutionState();
736 
737  // always execute to get the max number of DoF per element and node needed to initialize phi_zero
738  // variables
739  dof_id_type global_max_var_n_dofs_per_elem = 0;
740  for (const auto i : index_range(_nl))
741  {
742  auto & nl = *_nl[i];
743  dof_id_type max_var_n_dofs_per_elem;
744  dof_id_type max_var_n_dofs_per_node;
745  {
746  TIME_SECTION("computingMaxDofs", 3, "Computing Max Dofs Per Element");
747 
748  MaxVarNDofsPerElem mvndpe(*this, nl);
749  Threads::parallel_reduce(*_mesh.getActiveLocalElementRange(), mvndpe);
750  max_var_n_dofs_per_elem = mvndpe.max();
751  _communicator.max(max_var_n_dofs_per_elem);
752 
753  MaxVarNDofsPerNode mvndpn(*this, nl);
754  Threads::parallel_reduce(*_mesh.getLocalNodeRange(), mvndpn);
755  max_var_n_dofs_per_node = mvndpn.max();
756  _communicator.max(max_var_n_dofs_per_node);
757  global_max_var_n_dofs_per_elem =
758  std::max(global_max_var_n_dofs_per_elem, max_var_n_dofs_per_elem);
759  }
760 
761  {
762  TIME_SECTION("assignMaxDofs", 5, "Assigning Maximum Dofs Per Elem");
763 
764  nl.assignMaxVarNDofsPerElem(max_var_n_dofs_per_elem);
765  auto displaced_problem = getDisplacedProblem();
766  if (displaced_problem)
767  displaced_problem->nlSys(i).assignMaxVarNDofsPerElem(max_var_n_dofs_per_elem);
768 
769  nl.assignMaxVarNDofsPerNode(max_var_n_dofs_per_node);
770  if (displaced_problem)
771  displaced_problem->nlSys(i).assignMaxVarNDofsPerNode(max_var_n_dofs_per_node);
772  }
773  }
774 
775  {
776  TIME_SECTION("resizingVarValues", 5, "Resizing Variable Values");
777 
778  for (unsigned int tid = 0; tid < libMesh::n_threads(); ++tid)
779  {
780  _phi_zero[tid].resize(global_max_var_n_dofs_per_elem, std::vector<Real>(getMaxQps(), 0.));
781  _grad_phi_zero[tid].resize(global_max_var_n_dofs_per_elem,
782  std::vector<RealGradient>(getMaxQps(), RealGradient(0.)));
783  _second_phi_zero[tid].resize(global_max_var_n_dofs_per_elem,
784  std::vector<RealTensor>(getMaxQps(), RealTensor(0.)));
785  }
786  }
787 
788  // Set up stateful material property redistribution, if we suspect
789  // it may be necessary later.
791 
793  {
794  // Only load all of the vectors if we're recovering
796 
797  // This forces stateful material property loading to be an exact one-to-one match
798  if (_app.isRecovering())
800  props->setRecovering();
801 
802  TIME_SECTION("restore", 3, "Restoring from backup");
803 
804  // We could have a cached backup when this app is a sub-app and has been given a Backup
805  if (!_app.hasInitialBackup())
807  else
809 
815  if (_app.isRestarting())
816  {
817  if (_app.hasStartTime())
819  else
820  _time_old = _time;
821  }
822  }
823  else
824  {
825  ExodusII_IO * reader = _app.getExReaderForRestart();
826 
827  if (reader)
828  {
829  TIME_SECTION("copyingFromExodus", 3, "Copying Variables From Exodus");
830 
831  for (auto & nl : _nl)
832  nl->copyVars(*reader);
833  _aux->copyVars(*reader);
834  }
835  else
836  {
837  if (_nl[0]->hasVarCopy() || _aux->hasVarCopy())
838  mooseError("Need Exodus reader to restart variables but the reader is not available\n"
839  "Use either FileMesh with an Exodus mesh file or FileMeshGenerator with an "
840  "Exodus mesh file and with use_for_exodus_restart equal to true");
841  }
842  }
843 
844  // Perform output related setups
846 
847  // Flush all output to _console that occur during construction and initialization of objects
849 
850  // Build Refinement and Coarsening maps for stateful material projections if necessary
851  if ((_adaptivity.isOn() || _num_grid_steps) &&
854  {
856  mooseError("Stateful neighbor material properties do not work with mesh adaptivity");
857 
859  }
860 
861  if (!_app.isRecovering())
862  {
869  {
870  if (!_app.isUltimateMaster())
871  mooseError(
872  "Doing extra refinements when restarting is NOT supported for sub-apps of a MultiApp");
873 
875  }
876  }
877 
878  unsigned int n_threads = libMesh::n_threads();
879 
880  // UserObject initialSetup
881  std::set<std::string> depend_objects_ic = _ics.getDependObjects();
882  std::set<std::string> depend_objects_aux = _aux->getDependObjects();
883 
884  // This replaces all prior updateDependObjects calls on the old user object warehouses.
885  TheWarehouse::Query uo_query = theWarehouse().query().condition<AttribSystem>("UserObject");
886  std::vector<UserObject *> userobjs;
887  uo_query.queryInto(userobjs);
889  theWarehouse(), getAuxiliarySystem(), _app.getExecuteOnEnum(), userobjs, depend_objects_ic);
890 
891  for (auto obj : userobjs)
892  obj->initialSetup();
893 
894  // check if jacobian calculation is done in userobject
895  for (THREAD_ID tid = 0; tid < n_threads; ++tid)
897 
898  // Check whether nonlocal couling is required or not
902 
903  {
904  TIME_SECTION("initializingFunctions", 5, "Initializing Functions");
905 
906  // Call the initialSetup methods for functions
907  for (THREAD_ID tid = 0; tid < n_threads; tid++)
908  {
909  reinitScalars(tid); // initialize scalars so they are properly sized for use as input into
910  // ParsedFunctions
912  }
913  }
914 
915  {
916  TIME_SECTION("initializingRandomObjects", 5, "Initializing Random Objects");
917 
918  // Random interface objects
919  for (const auto & it : _random_data_objects)
920  it.second->updateSeeds(EXEC_INITIAL);
921  }
922 
923  if (!_app.isRecovering())
924  {
926 
927  {
928  TIME_SECTION("ICiniitalSetup", 5, "Setting Up Initial Conditions");
929 
930  for (THREAD_ID tid = 0; tid < n_threads; tid++)
931  _ics.initialSetup(tid);
932 
934  }
935 
936  projectSolution();
937  }
938 
939  // Materials
941  {
942  TIME_SECTION("materialInitialSetup", 3, "Setting Up Materials");
943 
944  for (THREAD_ID tid = 0; tid < n_threads; tid++)
945  {
946  // Sort the Material objects, these will be actually computed by MOOSE in reinit methods.
947  _materials.sort(tid);
949 
950  // Call initialSetup on all material objects
952 
953  // Discrete materials may insert additional dependencies on materials during the initial
954  // setup. Therefore we resolve the dependencies once more, now with the additional
955  // dependencies due to discrete materials.
957  {
958  _materials.sort(tid);
960  }
961  }
962 
963  {
964  TIME_SECTION("computingInitialStatefulProps", 3, "Computing Initial Material Values");
965 
967 
971  }
972  }
973 
974  // setRestartInPlace() is set because the property maps have now been setup and we can
975  // dataLoad() them directly in place
976  // setRecovering() is set because from now on we require a one-to-one mapping of
977  // stateful properties because we shouldn't be declaring any more
979  {
980  props->setRestartInPlace();
981  props->setRecovering();
982  }
983 
984  for (THREAD_ID tid = 0; tid < n_threads; tid++)
985  {
988  _markers.sort(tid);
989  _markers.initialSetup(tid);
990  }
991 
992 #ifdef LIBMESH_ENABLE_AMR
993 
994  if (!_app.isRecovering())
995  {
996  unsigned int n = adaptivity().getInitialSteps();
997  if (n && !_app.isUltimateMaster() && _app.isRestarting())
998  mooseError("Cannot perform initial adaptivity during restart on sub-apps of a MultiApp!");
999 
1000  initialAdaptMesh();
1001  }
1002 
1003 #endif // LIBMESH_ENABLE_AMR
1004 
1005  if (!_app.isRecovering() && !_app.isRestarting())
1006  {
1007  // During initial setup the solution is copied to the older solution states (old, older, etc)
1009  }
1010 
1011  if (!_app.isRecovering())
1012  {
1013  if (haveXFEM())
1014  updateMeshXFEM();
1015  }
1016 
1017  // Call initialSetup on the nonlinear system
1018  for (auto & nl : _nl)
1019  nl->initialSetup();
1020 
1021  // Auxilary variable initialSetup calls
1022  _aux->initialSetup();
1023 
1024  if (_displaced_problem)
1025  // initialSetup for displaced systems
1026  _displaced_problem->initialSetup();
1027 
1028  for (auto & nl : _nl)
1029  nl->setSolution(*(nl->system().current_local_solution.get()));
1030 
1031  // Update the nearest node searches (has to be called after the problem is all set up)
1032  // We do this here because this sets up the Element's DoFs to ghost
1034 
1036  if (_displaced_mesh)
1038 
1039  // We need to move the mesh in order to build a map between mortar secondary and primary
1040  // interfaces. This map will then be used by the AgumentSparsityOnInterface ghosting functor to
1041  // know which dofs we need ghosted when we call EquationSystems::reinit
1043  _displaced_problem->updateMesh();
1044 
1045  // Possibly reinit one more time to get ghosting correct
1047 
1048  if (_displaced_mesh)
1049  _displaced_problem->updateMesh();
1050 
1051  updateGeomSearch(); // Call all of the rest of the geometric searches
1052 
1053  for (auto & nl : _nl)
1054  {
1055  auto ti = nl->getTimeIntegrator();
1056 
1057  if (ti)
1058  {
1059  TIME_SECTION("timeIntegratorInitialSetup", 5, "Initializing Time Integrator");
1060  ti->initialSetup();
1061  }
1062  }
1063 
1064  // HUGE NOTE: MultiApp initialSetup() MUST... I repeat MUST be _after_ main-app restartable data
1065  // has been restored
1066 
1067  // Call initialSetup on the MultiApps
1068  if (_multi_apps.hasObjects())
1069  {
1070  TIME_SECTION("initialSetupMultiApps", 2, "Initializing MultiApps", false);
1072  }
1073 
1074  // Call initialSetup on the transfers
1075  {
1076  TIME_SECTION("initialSetupTransfers", 2, "Initializing Transfers");
1077 
1079 
1080  // Call initialSetup on the MultiAppTransfers to be executed on TO_MULTIAPP
1081  const auto & to_multi_app_objects = _to_multi_app_transfers.getActiveObjects();
1082  for (const auto & transfer : to_multi_app_objects)
1083  {
1084  transfer->setCurrentDirection(Transfer::DIRECTION::TO_MULTIAPP);
1085  transfer->initialSetup();
1086  }
1087 
1088  // Call initialSetup on the MultiAppTransfers to be executed on FROM_MULTIAPP
1089  const auto & from_multi_app_objects = _from_multi_app_transfers.getActiveObjects();
1090  for (const auto & transfer : from_multi_app_objects)
1091  {
1092  transfer->setCurrentDirection(Transfer::DIRECTION::FROM_MULTIAPP);
1093  transfer->initialSetup();
1094  }
1095 
1096  // Call initialSetup on the MultiAppTransfers to be executed on BETWEEN_MULTIAPP
1097  const auto & between_multi_app_objects = _between_multi_app_transfers.getActiveObjects();
1098  for (const auto & transfer : between_multi_app_objects)
1099  {
1100  transfer->setCurrentDirection(Transfer::DIRECTION::BETWEEN_MULTIAPP);
1101  transfer->initialSetup();
1102  }
1103  }
1104 
1106  {
1107  TIME_SECTION("BoundaryRestrictedNodeIntegrityCheck", 5);
1108 
1109  // check that variables are defined along boundaries of boundary restricted nodal objects
1110  ConstBndNodeRange & bnd_nodes = *mesh().getBoundaryNodeRange();
1111  BoundaryNodeIntegrityCheckThread bnict(*this, uo_query);
1112  Threads::parallel_reduce(bnd_nodes, bnict);
1113 
1114  // Nodal bcs aren't threaded
1115  const auto & node_to_elem_map = _mesh.nodeToActiveSemilocalElemMap();
1116  for (const auto & bnode : bnd_nodes)
1117  {
1118  const auto boundary_id = bnode->_bnd_id;
1119  const Node * const node = bnode->_node;
1120 
1121  if (node->processor_id() != this->processor_id())
1122  continue;
1123 
1124  // Only check vertices. Variables may not be defined on non-vertex nodes (think first order
1125  // Lagrange on a second order mesh) and user-code can often handle that
1126  const Elem * const an_elem =
1127  _mesh.getMesh().elem_ptr(libmesh_map_find(node_to_elem_map, node->id()).front());
1128  if (!an_elem->is_vertex(an_elem->get_node_index(node)))
1129  continue;
1130 
1131  const auto & bnd_name = _mesh.getBoundaryName(boundary_id);
1132 
1133  for (auto & nl : _nl)
1134  {
1135  const auto & nodal_bcs = nl->getNodalBCWarehouse();
1136  if (!nodal_bcs.hasBoundaryObjects(boundary_id, 0))
1137  continue;
1138 
1139  const auto & bnd_objects = nodal_bcs.getBoundaryObjects(boundary_id, 0);
1140  for (const auto & bnd_object : bnd_objects)
1141  // Skip if this object uses geometric search because coupled variables may be defined on
1142  // paired boundaries instead of the boundary this node is on
1143  if (!bnd_object->requiresGeometricSearch() &&
1144  bnd_object->checkVariableBoundaryIntegrity())
1145  {
1146  std::set<MooseVariableFieldBase *> vars_to_omit = {
1147  &static_cast<MooseVariableFieldBase &>(
1148  const_cast<MooseVariableBase &>(bnd_object->variable()))};
1149 
1151  *bnd_object, bnd_object->checkAllVariables(*node, vars_to_omit), bnd_name);
1152  }
1153  }
1154  }
1155  }
1156 
1158  {
1159  TIME_SECTION("BoundaryRestrictedElemIntegrityCheck", 5);
1160 
1161  // check that variables are defined along boundaries of boundary restricted elemental objects
1162  ConstBndElemRange & bnd_elems = *mesh().getBoundaryElementRange();
1163  BoundaryElemIntegrityCheckThread beict(*this, uo_query);
1164  Threads::parallel_reduce(bnd_elems, beict);
1165  }
1166 
1167  if (!_app.isRecovering())
1168  {
1170 
1172  if (!converged)
1173  mooseError("failed to converge initial MultiApp");
1174 
1175  // We'll backup the Multiapp here
1177 
1178  for (THREAD_ID tid = 0; tid < n_threads; tid++)
1179  reinitScalars(tid);
1180 
1182 
1183  // The FEProblemBase::execute method doesn't call all the systems on EXEC_INITIAL, but it does
1184  // set/unset the current flag. Therefore, this resets the current flag to EXEC_INITIAL so that
1185  // subsequent calls (e.g., executeControls) have the proper flag.
1187  }
1188 
1189  // Here we will initialize the stateful properties once more since they may have been updated
1190  // during initialSetup by calls to computeProperties.
1191  //
1192  // It's really bad that we don't allow this during restart. It means that we can't add new
1193  // stateful materials
1194  // during restart. This is only happening because this _has_ to be below initial userobject
1195  // execution.
1196  // Otherwise this could be done up above... _before_ restoring restartable data... which would
1197  // allow you to have
1198  // this happen during restart. I honestly have no idea why this has to happen after initial user
1199  // object computation.
1200  // THAT is something we should fix... so I've opened this ticket: #5804
1201  if (!_app.isRecovering() && !_app.isRestarting() &&
1204  {
1205  TIME_SECTION("computeMaterials", 2, "Computing Initial Material Properties");
1206 
1208  }
1209 
1210  // Control Logic
1212 
1213  // Scalar variables need to reinited for the initial conditions to be available for output
1214  for (unsigned int tid = 0; tid < n_threads; tid++)
1215  reinitScalars(tid);
1216 
1217  if (_displaced_mesh)
1218  _displaced_problem->syncSolutions();
1219 
1220  // Writes all calls to _console from initialSetup() methods
1222 
1224  {
1226  for (THREAD_ID tid = 0; tid < n_threads; ++tid)
1227  for (auto & assembly : _assembly[tid])
1229  }
1230 
1231  {
1232  TIME_SECTION("lineSearchInitialSetup", 5, "Initializing Line Search");
1233 
1234  if (_line_search)
1235  _line_search->initialSetup();
1236  }
1237 
1238  // Perform Reporter get/declare check
1240 
1241  // We do this late to allow objects to get late restartable data
1244 
1246 }
1247 
1248 void
1250 {
1251  for (const auto & pp : _reporter_data.getPostprocessorNames())
1252  if (hasScalarVariable(pp))
1253  mooseError("Postprocessor \"" + pp +
1254  "\" has the same name as a scalar variable in the system.");
1255 }
1256 
1257 void
1259 {
1261 
1262  if (_t_step > 1 && _num_grid_steps)
1263  {
1264  MeshRefinement mesh_refinement(_mesh);
1265  std::unique_ptr<MeshRefinement> displaced_mesh_refinement(nullptr);
1266  if (_displaced_mesh)
1267  displaced_mesh_refinement = std::make_unique<MeshRefinement>(*_displaced_mesh);
1268 
1269  for (MooseIndex(_num_grid_steps) i = 0; i < _num_grid_steps; ++i)
1270  {
1271  if (_displaced_problem)
1272  // If the DisplacedProblem is active, undisplace the DisplacedMesh in preparation for
1273  // refinement. We can't safely refine the DisplacedMesh directly, since the Hilbert keys
1274  // computed on the inconsistenly-displaced Mesh are different on different processors,
1275  // leading to inconsistent Hilbert keys. We must do this before the undisplaced Mesh is
1276  // coarsensed, so that the element and node numbering is still consistent. We also have to
1277  // make sure this is done during every step of coarsening otherwise different partitions
1278  // will be generated for the reference and displaced meshes (even for replicated)
1279  _displaced_problem->undisplaceMesh();
1280 
1281  mesh_refinement.uniformly_coarsen();
1282  if (_displaced_mesh)
1283  displaced_mesh_refinement->uniformly_coarsen();
1284 
1285  // Mark this as an intermediate change because we do not yet want to reinit_systems. E.g. we
1286  // need things to happen in the following order for the undisplaced problem:
1287  // u1) EquationSystems::reinit_solutions. This will restrict the solution vectors and then
1288  // contract the mesh
1289  // u2) MooseMesh::meshChanged. This will update the node/side lists and other
1290  // things which needs to happen after the contraction
1291  // u3) GeometricSearchData::reinit. Once the node/side lists are updated we can perform our
1292  // geometric searches which will aid in determining sparsity patterns
1293  //
1294  // We do these things for the displaced problem (if it exists)
1295  // d1) EquationSystems::reinit. Restrict the displaced problem vector copies and then contract
1296  // the mesh. It's safe to do a full reinit with the displaced because there are no
1297  // matrices that sparsity pattern calculations will be conducted for
1298  // d2) MooseMesh::meshChanged. This will update the node/side lists and other
1299  // things which needs to happen after the contraction
1300  // d3) UpdateDisplacedMeshThread::operator(). Re-displace the mesh using the *displaced*
1301  // solution vector copy because we don't know the state of the reference solution vector.
1302  // It's safe to use the displaced copy because we are outside of a non-linear solve,
1303  // and there is no concern about differences between solution and current_local_solution
1304  // d4) GeometricSearchData::reinit. With the node/side lists updated and the mesh
1305  // re-displaced, we can perform our geometric searches, which will aid in determining the
1306  // sparsity pattern of the matrix held by the libMesh::ImplicitSystem held by the
1307  // NonlinearSystem held by this
1308  meshChangedHelper(/*intermediate_change=*/true);
1309  }
1310 
1311  // u4) Now that all the geometric searches have been done (both undisplaced and displaced),
1312  // we're ready to update the sparsity pattern
1313  es().reinit_systems();
1314  }
1315 
1316  if (_line_search)
1317  _line_search->timestepSetup();
1318 
1319  // Random interface objects
1320  for (const auto & it : _random_data_objects)
1321  it.second->updateSeeds(EXEC_TIMESTEP_BEGIN);
1322 
1323  unsigned int n_threads = libMesh::n_threads();
1324  for (THREAD_ID tid = 0; tid < n_threads; tid++)
1325  {
1328  }
1329 
1330  _aux->timestepSetup();
1331  for (auto & nl : _nl)
1332  nl->timestepSetup();
1333 
1334  if (_displaced_problem)
1335  // timestepSetup for displaced systems
1336  _displaced_problem->timestepSetup();
1337 
1338  for (THREAD_ID tid = 0; tid < n_threads; tid++)
1339  {
1342  _markers.timestepSetup(tid);
1343  }
1344 
1345  std::vector<UserObject *> userobjs;
1346  theWarehouse().query().condition<AttribSystem>("UserObject").queryIntoUnsorted(userobjs);
1347  for (auto obj : userobjs)
1348  obj->timestepSetup();
1349 
1350  // Timestep setup of output objects
1352 
1355  _has_nonlocal_coupling = true;
1356 }
1357 
1358 unsigned int
1360 {
1362  mooseError("Max QPS uninitialized");
1363  return _max_qps;
1364 }
1365 
1366 Order
1368 {
1369  return _max_scalar_order;
1370 }
1371 
1372 void
1374 {
1375  TIME_SECTION("checkNonlocalCoupling", 5, "Checking Nonlocal Coupling");
1376 
1377  for (THREAD_ID tid = 0; tid < libMesh::n_threads(); tid++)
1378  for (auto & nl : _nl)
1379  {
1380  const auto & all_kernels = nl->getKernelWarehouse();
1381  const auto & kernels = all_kernels.getObjects(tid);
1382  for (const auto & kernel : kernels)
1383  {
1384  std::shared_ptr<NonlocalKernel> nonlocal_kernel =
1386  if (nonlocal_kernel)
1387  {
1390  _nonlocal_kernels.addObject(kernel, tid);
1391  }
1392  }
1393  const MooseObjectWarehouse<IntegratedBCBase> & all_integrated_bcs =
1394  nl->getIntegratedBCWarehouse();
1395  const auto & integrated_bcs = all_integrated_bcs.getObjects(tid);
1396  for (const auto & integrated_bc : integrated_bcs)
1397  {
1398  std::shared_ptr<NonlocalIntegratedBC> nonlocal_integrated_bc =
1400  if (nonlocal_integrated_bc)
1401  {
1404  _nonlocal_integrated_bcs.addObject(integrated_bc, tid);
1405  }
1406  }
1407  }
1408 }
1409 
1410 void
1412 {
1413  std::set<const MooseVariableFEBase *> uo_jacobian_moose_vars;
1414  {
1415  std::vector<ShapeElementUserObject *> objs;
1416  theWarehouse()
1417  .query()
1419  .condition<AttribThread>(tid)
1420  .queryInto(objs);
1421 
1422  for (const auto & uo : objs)
1423  {
1424  _calculate_jacobian_in_uo = uo->computeJacobianFlag();
1425  const auto & mv_deps = uo->jacobianMooseVariables();
1426  uo_jacobian_moose_vars.insert(mv_deps.begin(), mv_deps.end());
1427  }
1428  }
1429  {
1430  std::vector<ShapeSideUserObject *> objs;
1431  theWarehouse()
1432  .query()
1434  .condition<AttribThread>(tid)
1435  .queryInto(objs);
1436  for (const auto & uo : objs)
1437  {
1438  _calculate_jacobian_in_uo = uo->computeJacobianFlag();
1439  const auto & mv_deps = uo->jacobianMooseVariables();
1440  uo_jacobian_moose_vars.insert(mv_deps.begin(), mv_deps.end());
1441  }
1442  }
1443 
1444  _uo_jacobian_moose_vars[tid].assign(uo_jacobian_moose_vars.begin(), uo_jacobian_moose_vars.end());
1445  std::sort(
1446  _uo_jacobian_moose_vars[tid].begin(), _uo_jacobian_moose_vars[tid].end(), sortMooseVariables);
1447 }
1448 
1449 void
1450 FEProblemBase::setVariableAllDoFMap(const std::vector<const MooseVariableFEBase *> & moose_vars)
1451 {
1452  for (unsigned int i = 0; i < moose_vars.size(); ++i)
1453  {
1454  VariableName var_name = moose_vars[i]->name();
1455  auto & nl = _nl[moose_vars[i]->sys().number()];
1456  nl->setVariableGlobalDoFs(var_name);
1457  _var_dof_map[var_name] = nl->getVariableGlobalDoFs();
1458  }
1459 }
1460 
1461 void
1462 FEProblemBase::prepare(const Elem * elem, const THREAD_ID tid)
1463 {
1464  for (const auto i : index_range(_nl))
1465  {
1466  _assembly[tid][i]->reinit(elem);
1467  _nl[i]->prepare(tid);
1468 
1469  // This method is called outside of residual/Jacobian callbacks during initial condition
1470  // evaluation
1472  _assembly[tid][i]->prepareJacobianBlock();
1473  _assembly[tid][i]->prepareResidual();
1475  _assembly[tid][i]->prepareNonlocal();
1476  }
1477  _aux->prepare(tid);
1478 
1479  if (_displaced_problem &&
1480  // _reinit_displaced_neighbor applies to interface type objects which will do computations
1481  // based on both elem and neighbor. Consequently, despite what you might think by its name, we
1482  // must make sure we prepare the displaced elem
1484  {
1485  _displaced_problem->prepare(_displaced_mesh->elemPtr(elem->id()), tid);
1487  _displaced_problem->prepareNonlocal(tid);
1488  }
1489 }
1490 
1491 void
1492 FEProblemBase::prepareFace(const Elem * elem, const THREAD_ID tid)
1493 {
1494  for (auto & nl : _nl)
1495  nl->prepareFace(tid, true);
1496  _aux->prepareFace(tid, false);
1497 
1499  _displaced_problem->prepareFace(_displaced_mesh->elemPtr(elem->id()), tid);
1500 }
1501 
1502 void
1503 FEProblemBase::prepare(const Elem * elem,
1504  unsigned int ivar,
1505  unsigned int jvar,
1506  const std::vector<dof_id_type> & dof_indices,
1507  const THREAD_ID tid)
1508 {
1509  for (const auto i : index_range(_nl))
1510  {
1511  _assembly[tid][i]->reinit(elem);
1512  _nl[i]->prepare(tid);
1513  }
1514 
1515  _aux->prepare(tid);
1516  const auto current_nl_sys_num = _current_nl_sys->number();
1517  _assembly[tid][current_nl_sys_num]->prepareBlock(ivar, jvar, dof_indices);
1519  if (_nonlocal_cm[current_nl_sys_num](ivar, jvar) != 0)
1520  {
1521  MooseVariableFEBase & jv = _current_nl_sys->getVariable(tid, jvar);
1522  _assembly[tid][current_nl_sys_num]->prepareBlockNonlocal(
1523  ivar, jvar, dof_indices, jv.allDofIndices());
1524  }
1525 
1527  {
1528  _displaced_problem->prepare(_displaced_mesh->elemPtr(elem->id()), ivar, jvar, dof_indices, tid);
1530  if (_nonlocal_cm[current_nl_sys_num](ivar, jvar) != 0)
1531  {
1532  MooseVariableFEBase & jv = _current_nl_sys->getVariable(tid, jvar);
1533  _displaced_problem->prepareBlockNonlocal(ivar, jvar, dof_indices, jv.allDofIndices(), tid);
1534  }
1535  }
1536 }
1537 
1538 void
1540 {
1541  SubdomainID did = elem->subdomain_id();
1542  for (const auto i : index_range(_nl))
1543  {
1544  _assembly[tid][i]->setCurrentSubdomainID(did);
1545  if (_displaced_problem &&
1547  _displaced_problem->assembly(tid, i).setCurrentSubdomainID(did);
1548  }
1549 }
1550 
1551 void
1552 FEProblemBase::setNeighborSubdomainID(const Elem * elem, unsigned int side, const THREAD_ID tid)
1553 {
1554  SubdomainID did = elem->neighbor_ptr(side)->subdomain_id();
1555  for (const auto i : index_range(_nl))
1556  {
1557  _assembly[tid][i]->setCurrentNeighborSubdomainID(did);
1558  if (_displaced_problem &&
1560  _displaced_problem->assembly(tid, i).setCurrentNeighborSubdomainID(did);
1561  }
1562 }
1563 
1564 void
1566 {
1567  SubdomainID did = elem->subdomain_id();
1568  for (const auto i : index_range(_nl))
1569  {
1570  _assembly[tid][i]->setCurrentNeighborSubdomainID(did);
1571  if (_displaced_problem &&
1573  _displaced_problem->assembly(tid, i).setCurrentNeighborSubdomainID(did);
1574  }
1575 }
1576 
1577 void
1579 {
1580  _assembly[tid][_current_nl_sys->number()]->prepare();
1582  _assembly[tid][_current_nl_sys->number()]->prepareNonlocal();
1583 
1585  {
1586  _displaced_problem->prepareAssembly(tid);
1588  _displaced_problem->prepareNonlocal(tid);
1589  }
1590 }
1591 
1592 void
1594 {
1595  _assembly[tid][_current_nl_sys->number()]->addResidual(Assembly::GlobalDataKey{},
1597 
1598  if (_displaced_problem)
1599  _displaced_problem->addResidual(tid);
1600 }
1601 
1602 void
1604 {
1605  _assembly[tid][_current_nl_sys->number()]->addResidualNeighbor(Assembly::GlobalDataKey{},
1607 
1608  if (_displaced_problem)
1609  _displaced_problem->addResidualNeighbor(tid);
1610 }
1611 
1612 void
1614 {
1615  _assembly[tid][_current_nl_sys->number()]->addResidualLower(Assembly::GlobalDataKey{},
1617 
1618  if (_displaced_problem)
1619  _displaced_problem->addResidualLower(tid);
1620 }
1621 
1622 void
1624 {
1625  _assembly[tid][_current_nl_sys->number()]->addResidualScalar(Assembly::GlobalDataKey{},
1627 }
1628 
1629 void
1631 {
1633  if (_displaced_problem)
1634  _displaced_problem->cacheResidual(tid);
1635 }
1636 
1637 void
1639 {
1641  if (_displaced_problem)
1642  _displaced_problem->cacheResidualNeighbor(tid);
1643 }
1644 
1645 void
1647 {
1649  if (_displaced_problem)
1650  _displaced_problem->addCachedResidual(tid);
1651 }
1652 
1653 void
1655 {
1657  _assembly[tid][_current_nl_sys->number()]->addCachedResidualDirectly(
1659 
1661  _assembly[tid][_current_nl_sys->number()]->addCachedResidualDirectly(
1663 
1664  // We do this because by adding the cached residual directly, we cannot ensure that all of the
1665  // cached residuals are emptied after only the two add calls above
1666  _assembly[tid][_current_nl_sys->number()]->clearCachedResiduals(Assembly::GlobalDataKey{});
1667 
1668  if (_displaced_problem)
1669  _displaced_problem->addCachedResidualDirectly(residual, tid);
1670 }
1671 
1672 void
1674 {
1675  _assembly[tid][_current_nl_sys->number()]->setResidual(
1676  residual,
1678  getVectorTag(_nl[_current_nl_sys->number()]->residualVectorTag()));
1679  if (_displaced_problem)
1680  _displaced_problem->setResidual(residual, tid);
1681 }
1682 
1683 void
1685 {
1686  _assembly[tid][_current_nl_sys->number()]->setResidualNeighbor(
1688  if (_displaced_problem)
1689  _displaced_problem->setResidualNeighbor(residual, tid);
1690 }
1691 
1692 void
1694 {
1695  _assembly[tid][_current_nl_sys->number()]->addJacobian(Assembly::GlobalDataKey{});
1697  _assembly[tid][_current_nl_sys->number()]->addJacobianNonlocal(Assembly::GlobalDataKey{});
1698  if (_displaced_problem)
1699  {
1700  _displaced_problem->addJacobian(tid);
1702  _displaced_problem->addJacobianNonlocal(tid);
1703  }
1704 }
1705 
1706 void
1708 {
1709  _assembly[tid][_current_nl_sys->number()]->addJacobianNeighbor(Assembly::GlobalDataKey{});
1710  if (_displaced_problem)
1711  _displaced_problem->addJacobianNeighbor(tid);
1712 }
1713 
1714 void
1716 {
1717  _assembly[tid][_current_nl_sys->number()]->addJacobianNeighborLowerD(Assembly::GlobalDataKey{});
1718  if (_displaced_problem)
1719  _displaced_problem->addJacobianNeighborLowerD(tid);
1720 }
1721 
1722 void
1724 {
1725  _assembly[tid][_current_nl_sys->number()]->addJacobianLowerD(Assembly::GlobalDataKey{});
1726  if (_displaced_problem)
1727  _displaced_problem->addJacobianLowerD(tid);
1728 }
1729 
1730 void
1732 {
1733  _assembly[tid][_current_nl_sys->number()]->addJacobianScalar(Assembly::GlobalDataKey{});
1734 }
1735 
1736 void
1737 FEProblemBase::addJacobianOffDiagScalar(unsigned int ivar, const THREAD_ID tid /* = 0*/)
1738 {
1739  _assembly[tid][_current_nl_sys->number()]->addJacobianOffDiagScalar(ivar,
1741 }
1742 
1743 void
1745 {
1747  if (_displaced_problem)
1748  _displaced_problem->cacheJacobian(tid);
1749 }
1750 
1751 void
1753 {
1755  if (_displaced_problem)
1756  _displaced_problem->cacheJacobianNeighbor(tid);
1757 }
1758 
1759 void
1761 {
1763  if (_displaced_problem)
1764  _displaced_problem->addCachedJacobian(tid);
1765 }
1766 
1767 void
1769  unsigned int ivar,
1770  unsigned int jvar,
1771  const DofMap & dof_map,
1772  std::vector<dof_id_type> & dof_indices,
1773  const std::set<TagID> & tags,
1774  const THREAD_ID tid)
1775 {
1776  _assembly[tid][_current_nl_sys->number()]->addJacobianBlockTags(
1777  jacobian, ivar, jvar, dof_map, dof_indices, Assembly::GlobalDataKey{}, tags);
1778 
1780  if (_nonlocal_cm[_current_nl_sys->number()](ivar, jvar) != 0)
1781  {
1782  MooseVariableFEBase & jv = _current_nl_sys->getVariable(tid, jvar);
1783  _assembly[tid][_current_nl_sys->number()]->addJacobianBlockNonlocalTags(
1784  jacobian,
1785  ivar,
1786  jvar,
1787  dof_map,
1788  dof_indices,
1789  jv.allDofIndices(),
1791  tags);
1792  }
1793 
1794  if (_displaced_problem)
1795  {
1796  _displaced_problem->addJacobianBlockTags(jacobian, ivar, jvar, dof_map, dof_indices, tags, tid);
1798  if (_nonlocal_cm[_current_nl_sys->number()](ivar, jvar) != 0)
1799  {
1800  MooseVariableFEBase & jv = _current_nl_sys->getVariable(tid, jvar);
1801  _displaced_problem->addJacobianBlockNonlocal(
1802  jacobian, ivar, jvar, dof_map, dof_indices, jv.allDofIndices(), tags, tid);
1803  }
1804  }
1805 }
1806 
1807 void
1809  unsigned int ivar,
1810  unsigned int jvar,
1811  const DofMap & dof_map,
1812  std::vector<dof_id_type> & dof_indices,
1813  std::vector<dof_id_type> & neighbor_dof_indices,
1814  const std::set<TagID> & tags,
1815  const THREAD_ID tid)
1816 {
1817  _assembly[tid][_current_nl_sys->number()]->addJacobianNeighborTags(jacobian,
1818  ivar,
1819  jvar,
1820  dof_map,
1821  dof_indices,
1822  neighbor_dof_indices,
1824  tags);
1825  if (_displaced_problem)
1826  _displaced_problem->addJacobianNeighbor(
1827  jacobian, ivar, jvar, dof_map, dof_indices, neighbor_dof_indices, tags, tid);
1828 }
1829 
1830 void
1831 FEProblemBase::prepareShapes(unsigned int var, const THREAD_ID tid)
1832 {
1833  _assembly[tid][_current_nl_sys->number()]->copyShapes(var);
1834 }
1835 
1836 void
1837 FEProblemBase::prepareFaceShapes(unsigned int var, const THREAD_ID tid)
1838 {
1839  _assembly[tid][_current_nl_sys->number()]->copyFaceShapes(var);
1840 }
1841 
1842 void
1844 {
1845  _assembly[tid][_current_nl_sys->number()]->copyNeighborShapes(var);
1846 }
1847 
1848 void
1850 {
1851  if (_mesh.elemPtr(elem_id)->processor_id() != processor_id())
1852  _ghosted_elems.insert(elem_id);
1853 }
1854 
1855 void
1857 {
1858  _mesh.addGhostedBoundary(boundary_id);
1859  if (_displaced_problem)
1860  _displaced_mesh->addGhostedBoundary(boundary_id);
1861 }
1862 
1863 void
1865 {
1866  TIME_SECTION("ghostGhostedBoundaries", 3, "Ghosting Ghosted Boundaries");
1867 
1869 
1870  if (_displaced_problem)
1872 }
1873 
1874 void
1875 FEProblemBase::sizeZeroes(unsigned int /*size*/, const THREAD_ID /*tid*/)
1876 {
1877  mooseDoOnce(mooseWarning(
1878  "This function is deprecated and no longer performs any function. Please do not call it."));
1879 }
1880 
1881 bool
1882 FEProblemBase::reinitDirac(const Elem * elem, const THREAD_ID tid)
1883 {
1884  std::vector<Point> & points = _dirac_kernel_info.getPoints()[elem].first;
1885 
1886  unsigned int n_points = points.size();
1887 
1888  if (n_points)
1889  {
1890  if (n_points > _max_qps)
1891  {
1892  _max_qps = n_points;
1893 
1898  unsigned int max_qpts = getMaxQps();
1899  for (unsigned int tid = 0; tid < libMesh::n_threads(); ++tid)
1900  {
1901  // the highest available order in libMesh is 43
1902  _scalar_zero[tid].resize(FORTYTHIRD, 0);
1903  _zero[tid].resize(max_qpts, 0);
1904  _grad_zero[tid].resize(max_qpts, RealGradient(0.));
1905  _second_zero[tid].resize(max_qpts, RealTensor(0.));
1906  _vector_zero[tid].resize(max_qpts, RealGradient(0.));
1907  _vector_curl_zero[tid].resize(max_qpts, RealGradient(0.));
1908  }
1909  }
1910 
1911  for (const auto i : index_range(_nl))
1912  {
1913  _assembly[tid][i]->reinitAtPhysical(elem, points);
1914  _nl[i]->prepare(tid);
1915  }
1916  _aux->prepare(tid);
1917 
1918  reinitElem(elem, tid);
1919  }
1920 
1921  _assembly[tid][_current_nl_sys->number()]->prepare();
1923  _assembly[tid][_current_nl_sys->number()]->prepareNonlocal();
1924 
1925  bool have_points = n_points > 0;
1927  {
1928  have_points |= _displaced_problem->reinitDirac(_displaced_mesh->elemPtr(elem->id()), tid);
1930  _displaced_problem->prepareNonlocal(tid);
1931  }
1932 
1933  return have_points;
1934 }
1935 
1936 void
1937 FEProblemBase::reinitElem(const Elem * elem, const THREAD_ID tid)
1938 {
1939  for (auto & nl : _nl)
1940  nl->reinitElem(elem, tid);
1941  _aux->reinitElem(elem, tid);
1942 
1944  _displaced_problem->reinitElem(_displaced_mesh->elemPtr(elem->id()), tid);
1945 }
1946 
1947 void
1949  const std::vector<Point> & phys_points_in_elem,
1950  const THREAD_ID tid)
1951 {
1952  mooseAssert(_mesh.queryElemPtr(elem->id()) == elem,
1953  "Are you calling this method with a displaced mesh element?");
1954 
1955  for (const auto i : index_range(_nl))
1956  {
1957  _assembly[tid][i]->reinitAtPhysical(elem, phys_points_in_elem);
1958  _nl[i]->prepare(tid);
1959  _assembly[tid][i]->prepare();
1961  _assembly[tid][i]->prepareNonlocal();
1962  }
1963  _aux->prepare(tid);
1964 
1965  reinitElem(elem, tid);
1966 }
1967 
1968 void
1970  unsigned int side,
1971  BoundaryID bnd_id,
1972  const THREAD_ID tid)
1973 {
1974  for (const auto i : index_range(_nl))
1975  {
1976  _assembly[tid][i]->reinit(elem, side);
1977  _nl[i]->reinitElemFace(elem, side, bnd_id, tid);
1978  }
1979  _aux->reinitElemFace(elem, side, bnd_id, tid);
1980 
1982  _displaced_problem->reinitElemFace(_displaced_mesh->elemPtr(elem->id()), side, bnd_id, tid);
1983 }
1984 
1985 void
1986 FEProblemBase::reinitLowerDElem(const Elem * lower_d_elem,
1987  const THREAD_ID tid,
1988  const std::vector<Point> * const pts,
1989  const std::vector<Real> * const weights)
1990 {
1991  SubProblem::reinitLowerDElem(lower_d_elem, tid, pts, weights);
1992 
1994  _displaced_problem->reinitLowerDElem(
1995  _displaced_mesh->elemPtr(lower_d_elem->id()), tid, pts, weights);
1996 }
1997 
1998 void
1999 FEProblemBase::reinitNode(const Node * node, const THREAD_ID tid)
2000 {
2002  _displaced_problem->reinitNode(&_displaced_mesh->nodeRef(node->id()), tid);
2003 
2004  for (const auto i : index_range(_nl))
2005  {
2006  _assembly[tid][i]->reinit(node);
2007  _nl[i]->reinitNode(node, tid);
2008  }
2009  _aux->reinitNode(node, tid);
2010 }
2011 
2012 void
2013 FEProblemBase::reinitNodeFace(const Node * node, BoundaryID bnd_id, const THREAD_ID tid)
2014 {
2016  _displaced_problem->reinitNodeFace(&_displaced_mesh->nodeRef(node->id()), bnd_id, tid);
2017 
2018  for (const auto i : index_range(_nl))
2019  {
2020  _assembly[tid][i]->reinit(node);
2021  _nl[i]->reinitNodeFace(node, bnd_id, tid);
2022  }
2023  _aux->reinitNodeFace(node, bnd_id, tid);
2024 }
2025 
2026 void
2027 FEProblemBase::reinitNodes(const std::vector<dof_id_type> & nodes, const THREAD_ID tid)
2028 {
2030  _displaced_problem->reinitNodes(nodes, tid);
2031 
2032  for (auto & nl : _nl)
2033  nl->reinitNodes(nodes, tid);
2034  _aux->reinitNodes(nodes, tid);
2035 }
2036 
2037 void
2038 FEProblemBase::reinitNodesNeighbor(const std::vector<dof_id_type> & nodes, const THREAD_ID tid)
2039 {
2041  _displaced_problem->reinitNodesNeighbor(nodes, tid);
2042 
2043  for (auto & nl : _nl)
2044  nl->reinitNodesNeighbor(nodes, tid);
2045  _aux->reinitNodesNeighbor(nodes, tid);
2046 }
2047 
2048 void
2049 FEProblemBase::reinitScalars(const THREAD_ID tid, bool reinit_for_derivative_reordering /*=false*/)
2050 {
2051  TIME_SECTION("reinitScalars", 3, "Reinitializing Scalar Variables");
2052 
2054  _displaced_problem->reinitScalars(tid, reinit_for_derivative_reordering);
2055 
2056  for (auto & nl : _nl)
2057  nl->reinitScalars(tid, reinit_for_derivative_reordering);
2058  _aux->reinitScalars(tid, reinit_for_derivative_reordering);
2059 
2060  // This is called outside of residual/Jacobian call-backs
2061  for (auto & assembly : _assembly[tid])
2063 }
2064 
2065 void
2067 {
2068  _assembly[tid][_current_nl_sys->number()]->prepareOffDiagScalar();
2069  if (_displaced_problem)
2070  _displaced_problem->reinitOffDiagScalars(tid);
2071 }
2072 
2073 void
2074 FEProblemBase::reinitNeighbor(const Elem * elem, unsigned int side, const THREAD_ID tid)
2075 {
2076  setNeighborSubdomainID(elem, side, tid);
2077 
2078  const Elem * neighbor = elem->neighbor_ptr(side);
2079  unsigned int neighbor_side = neighbor->which_neighbor_am_i(elem);
2080 
2081  for (const auto i : index_range(_nl))
2082  {
2083  _assembly[tid][i]->reinitElemAndNeighbor(elem, side, neighbor, neighbor_side);
2084  _nl[i]->prepareNeighbor(tid);
2085  // Called during stateful material property evaluation outside of solve
2086  _assembly[tid][i]->prepareNeighbor();
2087  }
2088  _aux->prepareNeighbor(tid);
2089 
2090  BoundaryID bnd_id = 0; // some dummy number (it is not really used for anything, right now)
2091  for (auto & nl : _nl)
2092  {
2093  nl->reinitElemFace(elem, side, bnd_id, tid);
2094  nl->reinitNeighborFace(neighbor, neighbor_side, bnd_id, tid);
2095  }
2096  _aux->reinitElemFace(elem, side, bnd_id, tid);
2097  _aux->reinitNeighborFace(neighbor, neighbor_side, bnd_id, tid);
2098 
2100  {
2101  // There are cases like for cohesive zone modeling without significant sliding where we cannot
2102  // use FEInterface::inverse_map in Assembly::reinitElemAndNeighbor in the displaced problem
2103  // because the physical points coming from the element don't actually lie on the neighbor.
2104  // Moreover, what's the point of doing another physical point inversion in other cases? We only
2105  // care about the reference points which we can just take from the undisplaced computation
2106  const auto & displaced_ref_pts = _assembly[tid][0]->qRuleNeighbor()->get_points();
2107 
2108  _displaced_problem->reinitNeighbor(
2109  _displaced_mesh->elemPtr(elem->id()), side, tid, &displaced_ref_pts);
2110  }
2111 }
2112 
2113 void
2115  unsigned int side,
2116  const THREAD_ID tid)
2117 {
2118  reinitNeighbor(elem, side, tid);
2119 
2120  const Elem * lower_d_elem = _mesh.getLowerDElem(elem, side);
2121  if (lower_d_elem && lower_d_elem->subdomain_id() == Moose::INTERNAL_SIDE_LOWERD_ID)
2122  reinitLowerDElem(lower_d_elem, tid);
2123  else
2124  {
2125  // with mesh refinement, lower-dimensional element might be defined on neighbor side
2126  auto & neighbor = _assembly[tid][0]->neighbor();
2127  auto & neighbor_side = _assembly[tid][0]->neighborSide();
2128  const Elem * lower_d_elem_neighbor = _mesh.getLowerDElem(neighbor, neighbor_side);
2129  if (lower_d_elem_neighbor &&
2130  lower_d_elem_neighbor->subdomain_id() == Moose::INTERNAL_SIDE_LOWERD_ID)
2131  {
2132  auto qps = _assembly[tid][0]->qPointsFaceNeighbor().stdVector();
2133  std::vector<Point> reference_points;
2134  FEInterface::inverse_map(
2135  lower_d_elem_neighbor->dim(), FEType(), lower_d_elem_neighbor, qps, reference_points);
2136  reinitLowerDElem(lower_d_elem_neighbor, tid, &reference_points);
2137  }
2138  }
2139 
2140  if (_displaced_problem &&
2142  _displaced_problem->reinitElemNeighborAndLowerD(
2143  _displaced_mesh->elemPtr(elem->id()), side, tid);
2144 }
2145 
2146 void
2148  unsigned int neighbor_side,
2149  const std::vector<Point> & physical_points,
2150  const THREAD_ID tid)
2151 {
2152  mooseAssert(_mesh.queryElemPtr(neighbor->id()) == neighbor,
2153  "Are you calling this method with a displaced mesh element?");
2154 
2155  for (const auto i : index_range(_nl))
2156  {
2157  // Reinits shape the functions at the physical points
2158  _assembly[tid][i]->reinitNeighborAtPhysical(neighbor, neighbor_side, physical_points);
2159 
2160  // Sets the neighbor dof indices
2161  _nl[i]->prepareNeighbor(tid);
2162  }
2163  _aux->prepareNeighbor(tid);
2164 
2165  // Resizes Re and Ke
2166  _assembly[tid][_current_nl_sys->number()]->prepareNeighbor();
2167 
2168  // Compute the values of each variable at the points
2169  for (auto & nl : _nl)
2170  nl->reinitNeighborFace(neighbor, neighbor_side, 0, tid);
2171  _aux->reinitNeighborFace(neighbor, neighbor_side, 0, tid);
2172 }
2173 
2174 void
2176  const std::vector<Point> & physical_points,
2177  const THREAD_ID tid)
2178 {
2179  mooseAssert(_mesh.queryElemPtr(neighbor->id()) == neighbor,
2180  "Are you calling this method with a displaced mesh element?");
2181 
2182  for (const auto i : index_range(_nl))
2183  {
2184  // Reinits shape the functions at the physical points
2185  _assembly[tid][i]->reinitNeighborAtPhysical(neighbor, physical_points);
2186 
2187  // Sets the neighbor dof indices
2188  _nl[i]->prepareNeighbor(tid);
2189  }
2190  _aux->prepareNeighbor(tid);
2191 
2192  // Resizes Re and Ke
2193  _assembly[tid][_current_nl_sys->number()]->prepareNeighbor();
2194 
2195  // Compute the values of each variable at the points
2196  for (auto & nl : _nl)
2197  nl->reinitNeighbor(neighbor, tid);
2198  _aux->reinitNeighbor(neighbor, tid);
2199 }
2200 
2201 void
2202 FEProblemBase::getDiracElements(std::set<const Elem *> & elems)
2203 {
2204  // First add in the undisplaced elements
2205  elems = _dirac_kernel_info.getElements();
2206 
2207  if (_displaced_problem)
2208  {
2209  std::set<const Elem *> displaced_elements;
2210  _displaced_problem->getDiracElements(displaced_elements);
2211 
2212  { // Use the ids from the displaced elements to get the undisplaced elements
2213  // and add them to the list
2214  for (const auto & elem : displaced_elements)
2215  elems.insert(_mesh.elemPtr(elem->id()));
2216  }
2217  }
2218 }
2219 
2220 void
2222 {
2224 
2225  if (_displaced_problem)
2226  _displaced_problem->clearDiracInfo();
2227 }
2228 
2229 void
2231 {
2232  _all_materials.subdomainSetup(subdomain, tid);
2233 
2234  // Call the subdomain methods of the output system, these are not threaded so only call it once
2235  if (tid == 0)
2237 
2238  for (auto & nl : _nl)
2239  nl->subdomainSetup(subdomain, tid);
2240 
2241  // FIXME: call displaced_problem->subdomainSetup() ?
2242  // When adding possibility with materials being evaluated on displaced mesh
2243 }
2244 
2245 void
2247 {
2248  _all_materials.neighborSubdomainSetup(subdomain, tid);
2249 }
2250 
2251 void
2252 FEProblemBase::addFunction(const std::string & type,
2253  const std::string & name,
2254  InputParameters & parameters)
2255 {
2256  parallel_object_only();
2257 
2258  parameters.set<SubProblem *>("_subproblem") = this;
2259 
2260  for (THREAD_ID tid = 0; tid < libMesh::n_threads(); tid++)
2261  {
2262  std::shared_ptr<Function> func = _factory.create<Function>(type, name, parameters, tid);
2263  logAdd("Function", name, type);
2264  _functions.addObject(func, tid);
2265 
2266  if (auto * const functor = dynamic_cast<Moose::FunctorBase<Real> *>(func.get()))
2267  {
2268  this->addFunctor(name, *functor, tid);
2269  if (_displaced_problem)
2270  _displaced_problem->addFunctor(name, *functor, tid);
2271  }
2272  else
2273  mooseError("Unrecognized function functor type");
2274  }
2275 }
2276 
2277 bool
2278 FEProblemBase::hasFunction(const std::string & name, const THREAD_ID tid)
2279 {
2280  return _functions.hasActiveObject(name, tid);
2281 }
2282 
2283 Function &
2284 FEProblemBase::getFunction(const std::string & name, const THREAD_ID tid)
2285 {
2286  // This thread lock is necessary since this method will create functions
2287  // for all threads if one is missing.
2288  Threads::spin_mutex::scoped_lock lock(get_function_mutex);
2289 
2290  if (!hasFunction(name, tid))
2291  {
2292  // If we didn't find a function, it might be a default function, attempt to construct one now
2293  std::istringstream ss(name);
2294  Real real_value;
2295 
2296  // First see if it's just a constant. If it is, build a ConstantFunction
2297  if (ss >> real_value && ss.eof())
2298  {
2299  InputParameters params = _factory.getValidParams("ConstantFunction");
2300  params.set<Real>("value") = real_value;
2301  addFunction("ConstantFunction", ss.str(), params);
2302  }
2303  else
2304  {
2306  std::string vars = "x,y,z,t,NaN,pi,e";
2307  if (fp.Parse(name, vars) == -1) // -1 for success
2308  {
2309  // It parsed ok, so build a MooseParsedFunction
2310  InputParameters params = _factory.getValidParams("ParsedFunction");
2311  params.set<std::string>("expression") = name;
2312  addFunction("ParsedFunction", name, params);
2313  }
2314  }
2315 
2316  // Try once more
2317  if (!hasFunction(name, tid))
2318  mooseError("Unable to find function " + name);
2319  }
2320 
2321  auto * const ret = dynamic_cast<Function *>(_functions.getActiveObject(name, tid).get());
2322  if (!ret)
2323  mooseError("No function named ", name, " of appropriate type");
2324 
2325  return *ret;
2326 }
2327 
2328 void
2329 FEProblemBase::addMeshDivision(const std::string & type,
2330  const std::string & name,
2331  InputParameters & parameters)
2332 {
2333  parallel_object_only();
2334  parameters.set<FEProblemBase *>("_fe_problem_base") = this;
2335  parameters.set<SubProblem *>("_subproblem") = this;
2336  for (THREAD_ID tid = 0; tid < libMesh::n_threads(); tid++)
2337  {
2338  std::shared_ptr<MeshDivision> func = _factory.create<MeshDivision>(type, name, parameters, tid);
2339  _mesh_divisions.addObject(func, tid);
2340  }
2341 }
2342 
2343 MeshDivision &
2344 FEProblemBase::getMeshDivision(const std::string & name, const THREAD_ID tid) const
2345 {
2346  auto * const ret = dynamic_cast<MeshDivision *>(_mesh_divisions.getActiveObject(name, tid).get());
2347  if (!ret)
2348  mooseError("No MeshDivision object named ", name, " of appropriate type");
2349  return *ret;
2350 }
2351 
2352 void
2354 {
2355  _line_search->lineSearch();
2356 }
2357 
2359 FEProblemBase::getNonlinearSystem(const unsigned int sys_num)
2360 {
2361  mooseDeprecated("FEProblemBase::getNonlinearSystem() is deprecated, please use "
2362  "FEProblemBase::getNonlinearSystemBase() \n");
2363 
2364  mooseAssert(sys_num < _nl.size(), "System number greater than the number of nonlinear systems");
2365  auto nl_sys = std::dynamic_pointer_cast<NonlinearSystem>(_nl[sys_num]);
2366 
2367  if (!nl_sys)
2368  mooseError("This is not a NonlinearSystem");
2369 
2370  return *nl_sys;
2371 }
2372 
2373 void
2374 FEProblemBase::addDistribution(const std::string & type,
2375  const std::string & name,
2376  InputParameters & parameters)
2377 {
2378  parameters.set<std::string>("type") = type;
2379  addObject<Distribution>(type, name, parameters, /* threaded = */ false);
2380 }
2381 
2382 Distribution &
2383 FEProblemBase::getDistribution(const std::string & name)
2384 {
2385  std::vector<Distribution *> objs;
2386  theWarehouse()
2387  .query()
2388  .condition<AttribSystem>("Distribution")
2389  .condition<AttribName>(name)
2390  .queryInto(objs);
2391  if (objs.empty())
2392  mooseError("Unable to find Distribution with name '" + name + "'");
2393  return *(objs[0]);
2394 }
2395 
2396 void
2397 FEProblemBase::addSampler(const std::string & type,
2398  const std::string & name,
2399  InputParameters & parameters)
2400 {
2401  const auto samplers = addObject<Sampler>(type, name, parameters);
2402  for (auto & sampler : samplers)
2403  sampler->init();
2404 }
2405 
2406 Sampler &
2407 FEProblemBase::getSampler(const std::string & name, const THREAD_ID tid)
2408 {
2409  std::vector<Sampler *> objs;
2410  theWarehouse()
2411  .query()
2412  .condition<AttribSystem>("Sampler")
2413  .condition<AttribThread>(tid)
2414  .condition<AttribName>(name)
2415  .queryInto(objs);
2416  if (objs.empty())
2417  mooseError(
2418  "Unable to find Sampler with name '" + name +
2419  "', if you are attempting to access this object in the constructor of another object then "
2420  "the object being retrieved must occur prior to the caller within the input file.");
2421  return *(objs[0]);
2422 }
2423 
2424 bool
2425 FEProblemBase::duplicateVariableCheck(const std::string & var_name,
2426  const FEType & type,
2427  bool is_aux)
2428 {
2429  for (auto & nl : _nl)
2430  {
2431  SystemBase * curr_sys_ptr = nl.get();
2432  SystemBase * other_sys_ptr = _aux.get();
2433  std::string error_prefix = "";
2434  if (is_aux)
2435  {
2436  curr_sys_ptr = _aux.get();
2437  other_sys_ptr = nl.get();
2438  error_prefix = "Aux";
2439  }
2440 
2441  if (other_sys_ptr->hasVariable(var_name))
2442  mooseError("Cannot have an auxiliary variable and a nonlinear variable with the same name: ",
2443  var_name);
2444 
2445  if (curr_sys_ptr->hasVariable(var_name))
2446  {
2447  const Variable & var =
2448  curr_sys_ptr->system().variable(curr_sys_ptr->system().variable_number(var_name));
2449  if (var.type() != type)
2450  mooseError(error_prefix,
2451  "Variable with name '",
2452  var_name,
2453  "' already exists but is of a differing type!");
2454 
2455  return true;
2456  }
2457  }
2458 
2459  return false;
2460 }
2461 
2462 void
2463 FEProblemBase::addVariable(const std::string & var_type,
2464  const std::string & var_name,
2465  InputParameters & params)
2466 {
2467  parallel_object_only();
2468 
2469  auto fe_type = FEType(Utility::string_to_enum<Order>(params.get<MooseEnum>("order")),
2470  Utility::string_to_enum<FEFamily>(params.get<MooseEnum>("family")));
2471 
2472  if (duplicateVariableCheck(var_name, fe_type, /* is_aux = */ false))
2473  return;
2474 
2475  params.set<FEProblemBase *>("_fe_problem_base") = this;
2477 
2478  const auto & nl_sys_name = params.get<NonlinearSystemName>("nl_sys");
2479  std::istringstream ss(nl_sys_name);
2480  unsigned int nl_sys_num;
2481  if (!(ss >> nl_sys_num) || !ss.eof())
2482  nl_sys_num = libmesh_map_find(_nl_sys_name_to_num, nl_sys_name);
2483 
2484  logAdd("Variable", var_name, var_type);
2485  _nl[nl_sys_num]->addVariable(var_type, var_name, params);
2486  if (_displaced_problem)
2487  // MooseObjects need to be unique so change the name here
2488  _displaced_problem->addVariable(var_type, var_name, params, nl_sys_num);
2489 
2490  _nl_var_to_sys_num[var_name] = nl_sys_num;
2491 }
2492 
2493 std::pair<bool, unsigned int>
2494 FEProblemBase::determineNonlinearSystem(const std::string & var_name,
2495  const bool error_if_not_found) const
2496 {
2497  auto nl_map_it = _nl_var_to_sys_num.find(var_name);
2498  const bool var_in_nl = nl_map_it != _nl_var_to_sys_num.end();
2499  if (var_in_nl)
2500  mooseAssert(_nl[nl_map_it->second]->hasVariable(var_name) ||
2501  _nl[nl_map_it->second]->hasScalarVariable(var_name),
2502  "If the variable is in our FEProblem nonlinear system map, then it must be in the "
2503  "nonlinear system we expect");
2504  else if (error_if_not_found)
2505  {
2506  if (_aux->hasVariable(var_name) || _aux->hasScalarVariable(var_name))
2507  mooseError("No nonlinear variable named ",
2508  var_name,
2509  " found. Did you specify an auxiliary variable when you meant to specify a "
2510  "nonlinear variable?");
2511  else
2512  mooseError("Unknown variable '",
2513  var_name,
2514  "'. It does not exist in the nonlinear system(s) or auxiliary system");
2515  }
2516 
2517  return std::make_pair(var_in_nl, var_in_nl ? nl_map_it->second : libMesh::invalid_uint);
2518 }
2519 
2520 void
2521 FEProblemBase::addKernel(const std::string & kernel_name,
2522  const std::string & name,
2523  InputParameters & parameters)
2524 {
2525  parallel_object_only();
2526 
2527  const auto nl_sys_num =
2528  determineNonlinearSystem(parameters.varName("variable", name), true).second;
2529  if (_displaced_problem && parameters.get<bool>("use_displaced_mesh"))
2530  {
2531  parameters.set<SubProblem *>("_subproblem") = _displaced_problem.get();
2532  parameters.set<SystemBase *>("_sys") = &_displaced_problem->nlSys(nl_sys_num);
2533  _reinit_displaced_elem = true;
2534  }
2535  else
2536  {
2537  if (_displaced_problem == nullptr && parameters.get<bool>("use_displaced_mesh"))
2538  {
2539  // We allow Kernels to request that they use_displaced_mesh,
2540  // but then be overridden when no displacements variables are
2541  // provided in the Mesh block. If that happened, update the value
2542  // of use_displaced_mesh appropriately for this Kernel.
2543  if (parameters.have_parameter<bool>("use_displaced_mesh"))
2544  parameters.set<bool>("use_displaced_mesh") = false;
2545  }
2546 
2547  parameters.set<SubProblem *>("_subproblem") = this;
2548  parameters.set<SystemBase *>("_sys") = _nl[nl_sys_num].get();
2549  }
2550 
2551  logAdd("Kernel", name, kernel_name);
2552  _nl[nl_sys_num]->addKernel(kernel_name, name, parameters);
2553 }
2554 
2555 void
2556 FEProblemBase::addNodalKernel(const std::string & kernel_name,
2557  const std::string & name,
2558  InputParameters & parameters)
2559 {
2560  parallel_object_only();
2561 
2562  const auto nl_sys_num =
2563  determineNonlinearSystem(parameters.varName("variable", name), true).second;
2564  if (_displaced_problem && parameters.get<bool>("use_displaced_mesh"))
2565  {
2566  parameters.set<SubProblem *>("_subproblem") = _displaced_problem.get();
2567  parameters.set<SystemBase *>("_sys") = &_displaced_problem->nlSys(nl_sys_num);
2568  _reinit_displaced_elem = true;
2569  }
2570  else
2571  {
2572  if (_displaced_problem == nullptr && parameters.get<bool>("use_displaced_mesh"))
2573  {
2574  // We allow NodalKernels to request that they use_displaced_mesh,
2575  // but then be overridden when no displacements variables are
2576  // provided in the Mesh block. If that happened, update the value
2577  // of use_displaced_mesh appropriately for this NodalKernel.
2578  if (parameters.have_parameter<bool>("use_displaced_mesh"))
2579  parameters.set<bool>("use_displaced_mesh") = false;
2580  }
2581 
2582  parameters.set<SubProblem *>("_subproblem") = this;
2583  parameters.set<SystemBase *>("_sys") = _nl[nl_sys_num].get();
2584  }
2585  logAdd("NodalKernel", name, kernel_name);
2586  _nl[nl_sys_num]->addNodalKernel(kernel_name, name, parameters);
2587 }
2588 
2589 void
2590 FEProblemBase::addScalarKernel(const std::string & kernel_name,
2591  const std::string & name,
2592  InputParameters & parameters)
2593 {
2594  parallel_object_only();
2595 
2596  const auto nl_sys_num =
2597  determineNonlinearSystem(parameters.varName("variable", name), true).second;
2598  if (_displaced_problem && parameters.get<bool>("use_displaced_mesh"))
2599  {
2600  parameters.set<SubProblem *>("_subproblem") = _displaced_problem.get();
2601  parameters.set<SystemBase *>("_sys") = &_displaced_problem->nlSys(nl_sys_num);
2602  }
2603  else
2604  {
2605  if (_displaced_problem == nullptr && parameters.get<bool>("use_displaced_mesh"))
2606  {
2607  // We allow ScalarKernels to request that they use_displaced_mesh,
2608  // but then be overridden when no displacements variables are
2609  // provided in the Mesh block. If that happened, update the value
2610  // of use_displaced_mesh appropriately for this ScalarKernel.
2611  if (parameters.have_parameter<bool>("use_displaced_mesh"))
2612  parameters.set<bool>("use_displaced_mesh") = false;
2613  }
2614 
2615  parameters.set<SubProblem *>("_subproblem") = this;
2616  parameters.set<SystemBase *>("_sys") = _nl[nl_sys_num].get();
2617  }
2618 
2619  logAdd("ScalarKernel", name, kernel_name);
2620  _nl[nl_sys_num]->addScalarKernel(kernel_name, name, parameters);
2621 }
2622 
2623 void
2624 FEProblemBase::addBoundaryCondition(const std::string & bc_name,
2625  const std::string & name,
2626  InputParameters & parameters)
2627 {
2628  parallel_object_only();
2629 
2630  const auto nl_sys_num =
2631  determineNonlinearSystem(parameters.varName("variable", name), true).second;
2632  if (_displaced_problem && parameters.get<bool>("use_displaced_mesh"))
2633  {
2634  parameters.set<SubProblem *>("_subproblem") = _displaced_problem.get();
2635  parameters.set<SystemBase *>("_sys") = &_displaced_problem->nlSys(nl_sys_num);
2636  _reinit_displaced_face = true;
2637  }
2638  else
2639  {
2640  if (_displaced_problem == nullptr && parameters.get<bool>("use_displaced_mesh"))
2641  {
2642  // We allow Materials to request that they use_displaced_mesh,
2643  // but then be overridden when no displacements variables are
2644  // provided in the Mesh block. If that happened, update the value
2645  // of use_displaced_mesh appropriately for this Material.
2646  if (parameters.have_parameter<bool>("use_displaced_mesh"))
2647  parameters.set<bool>("use_displaced_mesh") = false;
2648  }
2649 
2650  parameters.set<SubProblem *>("_subproblem") = this;
2651  parameters.set<SystemBase *>("_sys") = _nl[nl_sys_num].get();
2652  }
2653 
2654  logAdd("BoundaryCondition", name, bc_name);
2655  _nl[nl_sys_num]->addBoundaryCondition(bc_name, name, parameters);
2656 }
2657 
2658 void
2659 FEProblemBase::addConstraint(const std::string & c_name,
2660  const std::string & name,
2661  InputParameters & parameters)
2662 {
2663  parallel_object_only();
2664 
2665  _has_constraints = true;
2666 
2667  auto determine_var_param_name = [&parameters, this]()
2668  {
2669  if (parameters.isParamValid("variable"))
2670  return "variable";
2671  else
2672  {
2673  // must be a mortar constraint
2674  const bool has_secondary_var = parameters.isParamValid("secondary_variable");
2675  const bool has_primary_var = parameters.isParamValid("primary_variable");
2676  if (!has_secondary_var && !has_primary_var)
2677  mooseError(
2678  "Either a 'secondary_variable' or 'primary_variable' parameter must be supplied for '",
2679  parameters.get<std::string>("_object_name"),
2680  "'");
2681  return has_secondary_var ? "secondary_variable" : "primary_variable";
2682  }
2683  };
2684 
2685  const auto nl_sys_num =
2686  determineNonlinearSystem(parameters.varName(determine_var_param_name(), name), true).second;
2687 
2688  if (_displaced_problem && parameters.get<bool>("use_displaced_mesh"))
2689  {
2690  parameters.set<SubProblem *>("_subproblem") = _displaced_problem.get();
2691  parameters.set<SystemBase *>("_sys") = &_displaced_problem->nlSys(nl_sys_num);
2692  _reinit_displaced_face = true;
2693  }
2694  else
2695  {
2696  // It might _want_ to use a displaced mesh... but we're not so set it to false
2697  if (parameters.have_parameter<bool>("use_displaced_mesh"))
2698  parameters.set<bool>("use_displaced_mesh") = false;
2699 
2700  parameters.set<SubProblem *>("_subproblem") = this;
2701  parameters.set<SystemBase *>("_sys") = _nl[nl_sys_num].get();
2702  }
2703 
2704  logAdd("Constraint", name, c_name);
2705  _nl[nl_sys_num]->addConstraint(c_name, name, parameters);
2706 }
2707 
2708 void
2709 FEProblemBase::addAuxVariable(const std::string & var_type,
2710  const std::string & var_name,
2711  InputParameters & params)
2712 {
2713  parallel_object_only();
2714 
2715  auto fe_type = FEType(Utility::string_to_enum<Order>(params.get<MooseEnum>("order")),
2716  Utility::string_to_enum<FEFamily>(params.get<MooseEnum>("family")));
2717 
2718  if (duplicateVariableCheck(var_name, fe_type, /* is_aux = */ true))
2719  return;
2720 
2721  params.set<FEProblemBase *>("_fe_problem_base") = this;
2723 
2724  logAdd("AuxVariable", var_name, var_type);
2725  _aux->addVariable(var_type, var_name, params);
2726  if (_displaced_problem)
2727  // MooseObjects need to be unique so change the name here
2728  _displaced_problem->addAuxVariable(var_type, var_name, params);
2729 }
2730 
2731 void
2732 FEProblemBase::addAuxVariable(const std::string & var_name,
2733  const FEType & type,
2734  const std::set<SubdomainID> * const active_subdomains)
2735 {
2736  parallel_object_only();
2737 
2738  mooseDeprecated("Please use the addAuxVariable(var_type, var_name, params) API instead");
2739 
2740  if (duplicateVariableCheck(var_name, type, /* is_aux = */ true))
2741  return;
2742 
2743  std::string var_type;
2744  if (type == FEType(0, MONOMIAL))
2745  var_type = "MooseVariableConstMonomial";
2746  else if (type.family == SCALAR)
2747  var_type = "MooseVariableScalar";
2748  else if (type.family == LAGRANGE_VEC || type.family == NEDELEC_ONE ||
2749  type.family == MONOMIAL_VEC || type.family == RAVIART_THOMAS)
2750  var_type = "VectorMooseVariable";
2751  else
2752  var_type = "MooseVariable";
2753 
2754  InputParameters params = _factory.getValidParams(var_type);
2755  params.set<FEProblemBase *>("_fe_problem_base") = this;
2757  params.set<MooseEnum>("order") = type.order.get_order();
2758  params.set<MooseEnum>("family") = Moose::stringify(type.family);
2759 
2760  if (active_subdomains)
2761  for (const SubdomainID & id : *active_subdomains)
2762  params.set<std::vector<SubdomainName>>("block").push_back(Moose::stringify(id));
2763 
2764  logAdd("AuxVariable", var_name, var_type);
2765  _aux->addVariable(var_type, var_name, params);
2766  if (_displaced_problem)
2767  _displaced_problem->addAuxVariable("MooseVariable", var_name, params);
2768 }
2769 
2770 void
2771 FEProblemBase::addAuxArrayVariable(const std::string & var_name,
2772  const FEType & type,
2773  unsigned int components,
2774  const std::set<SubdomainID> * const active_subdomains)
2775 {
2776  parallel_object_only();
2777 
2778  mooseDeprecated("Please use the addAuxVariable(var_type, var_name, params) API instead");
2779 
2780  if (duplicateVariableCheck(var_name, type, /* is_aux = */ true))
2781  return;
2782 
2783  InputParameters params = _factory.getValidParams("ArrayMooseVariable");
2784  params.set<FEProblemBase *>("_fe_problem_base") = this;
2786  params.set<MooseEnum>("order") = type.order.get_order();
2787  params.set<MooseEnum>("family") = Moose::stringify(type.family);
2788  params.set<unsigned int>("components") = components;
2789 
2790  if (active_subdomains)
2791  for (const SubdomainID & id : *active_subdomains)
2792  params.set<std::vector<SubdomainName>>("block").push_back(Moose::stringify(id));
2793 
2794  logAdd("Variable", var_name, "ArrayMooseVariable");
2795  _aux->addVariable("ArrayMooseVariable", var_name, params);
2796  if (_displaced_problem)
2797  _displaced_problem->addAuxVariable("ArrayMooseVariable", var_name, params);
2798 }
2799 
2800 void
2801 FEProblemBase::addAuxScalarVariable(const std::string & var_name,
2802  Order order,
2803  Real /*scale_factor*/,
2804  const std::set<SubdomainID> * const active_subdomains)
2805 {
2806  parallel_object_only();
2807 
2808  mooseDeprecated("Please use the addAuxVariable(var_type, var_name, params) API instead");
2809 
2810  if (order > _max_scalar_order)
2811  _max_scalar_order = order;
2812 
2813  FEType type(order, SCALAR);
2814  if (duplicateVariableCheck(var_name, type, /* is_aux = */ true))
2815  return;
2816 
2817  InputParameters params = _factory.getValidParams("MooseVariableScalar");
2818  params.set<FEProblemBase *>("_fe_problem_base") = this;
2820 
2821  params.set<MooseEnum>("order") = type.order.get_order();
2822  params.set<MooseEnum>("family") = "SCALAR";
2823  params.set<std::vector<Real>>("scaling") = {1};
2824  if (active_subdomains)
2825  for (const SubdomainID & id : *active_subdomains)
2826  params.set<std::vector<SubdomainName>>("block").push_back(Moose::stringify(id));
2827 
2828  logAdd("ScalarVariable", var_name, "MooseVariableScalar");
2829  _aux->addVariable("MooseVariableScalar", var_name, params);
2830  if (_displaced_problem)
2831  _displaced_problem->addAuxVariable("MooseVariableScalar", var_name, params);
2832 }
2833 
2834 void
2835 FEProblemBase::addAuxKernel(const std::string & kernel_name,
2836  const std::string & name,
2837  InputParameters & parameters)
2838 {
2839  parallel_object_only();
2840 
2841  if (_displaced_problem && parameters.get<bool>("use_displaced_mesh"))
2842  {
2843  parameters.set<SubProblem *>("_subproblem") = _displaced_problem.get();
2844  parameters.set<SystemBase *>("_sys") = &_displaced_problem->auxSys();
2845  parameters.set<SystemBase *>("_nl_sys") = &_displaced_problem->nlSys(0);
2846  if (!parameters.get<std::vector<BoundaryName>>("boundary").empty())
2847  _reinit_displaced_face = true;
2848  else
2849  _reinit_displaced_elem = true;
2850  }
2851  else
2852  {
2853  if (_displaced_problem == nullptr && parameters.get<bool>("use_displaced_mesh"))
2854  {
2855  // We allow AuxKernels to request that they use_displaced_mesh,
2856  // but then be overridden when no displacements variables are
2857  // provided in the Mesh block. If that happened, update the value
2858  // of use_displaced_mesh appropriately for this AuxKernel.
2859  if (parameters.have_parameter<bool>("use_displaced_mesh"))
2860  parameters.set<bool>("use_displaced_mesh") = false;
2861  }
2862 
2863  parameters.set<SubProblem *>("_subproblem") = this;
2864  parameters.set<SystemBase *>("_sys") = _aux.get();
2865  parameters.set<SystemBase *>("_nl_sys") = _nl[0].get();
2866  }
2867 
2868  logAdd("AuxKernel", name, kernel_name);
2869  _aux->addKernel(kernel_name, name, parameters);
2870 }
2871 
2872 void
2873 FEProblemBase::addAuxScalarKernel(const std::string & kernel_name,
2874  const std::string & name,
2875  InputParameters & parameters)
2876 {
2877  parallel_object_only();
2878 
2879  if (_displaced_problem && parameters.get<bool>("use_displaced_mesh"))
2880  {
2881  parameters.set<SubProblem *>("_subproblem") = _displaced_problem.get();
2882  parameters.set<SystemBase *>("_sys") = &_displaced_problem->auxSys();
2883  }
2884  else
2885  {
2886  if (_displaced_problem == nullptr && parameters.get<bool>("use_displaced_mesh"))
2887  {
2888  // We allow AuxScalarKernels to request that they use_displaced_mesh,
2889  // but then be overridden when no displacements variables are
2890  // provided in the Mesh block. If that happened, update the value
2891  // of use_displaced_mesh appropriately for this AuxScalarKernel.
2892  if (parameters.have_parameter<bool>("use_displaced_mesh"))
2893  parameters.set<bool>("use_displaced_mesh") = false;
2894  }
2895 
2896  parameters.set<SubProblem *>("_subproblem") = this;
2897  parameters.set<SystemBase *>("_sys") = _aux.get();
2898  }
2899 
2900  logAdd("AuxScalarKernel", name, kernel_name);
2901  _aux->addScalarKernel(kernel_name, name, parameters);
2902 }
2903 
2904 void
2905 FEProblemBase::addDiracKernel(const std::string & kernel_name,
2906  const std::string & name,
2907  InputParameters & parameters)
2908 {
2909  parallel_object_only();
2910 
2911  const auto nl_sys_num =
2912  determineNonlinearSystem(parameters.varName("variable", name), true).second;
2913  if (_displaced_problem && parameters.get<bool>("use_displaced_mesh"))
2914  {
2915  parameters.set<SubProblem *>("_subproblem") = _displaced_problem.get();
2916  parameters.set<SystemBase *>("_sys") = &_displaced_problem->nlSys(nl_sys_num);
2917  _reinit_displaced_elem = true;
2918  }
2919  else
2920  {
2921  if (_displaced_problem == nullptr && parameters.get<bool>("use_displaced_mesh"))
2922  {
2923  // We allow DiracKernels to request that they use_displaced_mesh,
2924  // but then be overridden when no displacements variables are
2925  // provided in the Mesh block. If that happened, update the value
2926  // of use_displaced_mesh appropriately for this DiracKernel.
2927  if (parameters.have_parameter<bool>("use_displaced_mesh"))
2928  parameters.set<bool>("use_displaced_mesh") = false;
2929  }
2930 
2931  parameters.set<SubProblem *>("_subproblem") = this;
2932  parameters.set<SystemBase *>("_sys") = _nl[nl_sys_num].get();
2933  }
2934 
2935  logAdd("DiracKernel", name, kernel_name);
2936  _nl[nl_sys_num]->addDiracKernel(kernel_name, name, parameters);
2937 }
2938 
2939 // DGKernels ////
2940 
2941 void
2942 FEProblemBase::addDGKernel(const std::string & dg_kernel_name,
2943  const std::string & name,
2944  InputParameters & parameters)
2945 {
2946  parallel_object_only();
2947 
2948  const auto nl_sys_num =
2949  determineNonlinearSystem(parameters.varName("variable", name), true).second;
2950 
2951  if (_displaced_problem && parameters.get<bool>("use_displaced_mesh"))
2952  {
2953  parameters.set<SubProblem *>("_subproblem") = _displaced_problem.get();
2954  parameters.set<SystemBase *>("_sys") = &_displaced_problem->nlSys(nl_sys_num);
2956  }
2957  else
2958  {
2959  if (_displaced_problem == nullptr && parameters.get<bool>("use_displaced_mesh"))
2960  {
2961  // We allow DGKernels to request that they use_displaced_mesh,
2962  // but then be overridden when no displacements variables are
2963  // provided in the Mesh block. If that happened, update the value
2964  // of use_displaced_mesh appropriately for this DGKernel.
2965  if (parameters.have_parameter<bool>("use_displaced_mesh"))
2966  parameters.set<bool>("use_displaced_mesh") = false;
2967  }
2968 
2969  parameters.set<SubProblem *>("_subproblem") = this;
2970  parameters.set<SystemBase *>("_sys") = _nl[nl_sys_num].get();
2971  }
2972 
2973  logAdd("DGKernel", name, dg_kernel_name);
2974  _nl[nl_sys_num]->addDGKernel(dg_kernel_name, name, parameters);
2975 
2977 }
2978 
2979 void
2980 FEProblemBase::addFVKernel(const std::string & fv_kernel_name,
2981  const std::string & name,
2982  InputParameters & parameters)
2983 {
2984  if (_displaced_problem && parameters.get<bool>("use_displaced_mesh"))
2985  // FVElementalKernels are computed in the historically finite element threaded loops. They rely
2986  // on Assembly data like _current_elem. When we call reinit on the FEProblemBase we will only
2987  // reinit the DisplacedProblem and its associated Assembly objects if we mark this boolean as
2988  // true
2989  _reinit_displaced_elem = true;
2990  addObject<FVKernel>(fv_kernel_name, name, parameters);
2991 }
2992 
2993 void
2994 FEProblemBase::addFVBC(const std::string & fv_bc_name,
2995  const std::string & name,
2996  InputParameters & parameters)
2997 {
2998  addObject<FVBoundaryCondition>(fv_bc_name, name, parameters);
2999 }
3000 
3001 void
3002 FEProblemBase::addFVInterfaceKernel(const std::string & fv_ik_name,
3003  const std::string & name,
3004  InputParameters & parameters)
3005 {
3008  addObject<FVInterfaceKernel>(
3009  fv_ik_name, name, parameters, /*threaded=*/true, /*variable_param_name=*/"variable1");
3010 }
3011 
3012 // InterfaceKernels ////
3013 
3014 void
3015 FEProblemBase::addInterfaceKernel(const std::string & interface_kernel_name,
3016  const std::string & name,
3017  InputParameters & parameters)
3018 {
3019  parallel_object_only();
3020 
3021  const auto nl_sys_num =
3022  determineNonlinearSystem(parameters.varName("variable", name), true).second;
3023 
3024  if (_displaced_problem && parameters.get<bool>("use_displaced_mesh"))
3025  {
3026  parameters.set<SubProblem *>("_subproblem") = _displaced_problem.get();
3027  parameters.set<SystemBase *>("_sys") = &_displaced_problem->nlSys(nl_sys_num);
3029  }
3030  else
3031  {
3032  if (_displaced_problem == nullptr && parameters.get<bool>("use_displaced_mesh"))
3033  {
3034  // We allow InterfaceKernels to request that they use_displaced_mesh,
3035  // but then be overridden when no displacements variables are
3036  // provided in the Mesh block. If that happened, update the value
3037  // of use_displaced_mesh appropriately for this InterfaceKernel.
3038  if (parameters.have_parameter<bool>("use_displaced_mesh"))
3039  parameters.set<bool>("use_displaced_mesh") = false;
3040  }
3041 
3042  parameters.set<SubProblem *>("_subproblem") = this;
3043  parameters.set<SystemBase *>("_sys") = _nl[nl_sys_num].get();
3044  }
3045 
3046  logAdd("InterfaceKernel", name, interface_kernel_name);
3047  _nl[nl_sys_num]->addInterfaceKernel(interface_kernel_name, name, parameters);
3048 
3050 }
3051 
3052 void
3053 FEProblemBase::checkICRestartError(const std::string & ic_name,
3054  const std::string & name,
3055  const VariableName & var_name)
3056 {
3058  {
3059  std::string restart_method = "";
3060  if (_app.isRestarting())
3061  restart_method =
3062  "a checkpoint restart, by IC object '" + ic_name + "' for variable '" + name + "'";
3063  else if (_app.getExReaderForRestart())
3064  {
3065  std::vector<std::string> restarted_vars = _app.getExReaderForRestart()->get_elem_var_names();
3066  const auto nodal_vars = _app.getExReaderForRestart()->get_nodal_var_names();
3067  const auto global_vars = _app.getExReaderForRestart()->get_global_var_names();
3068  restarted_vars.insert(restarted_vars.end(), nodal_vars.begin(), nodal_vars.end());
3069  restarted_vars.insert(restarted_vars.end(), global_vars.begin(), global_vars.end());
3070 
3071  if (std::find(restarted_vars.begin(), restarted_vars.end(), var_name) != restarted_vars.end())
3072  restart_method = "an Exodus restart, by IC object '" + ic_name + "' for variable '" + name +
3073  "' that is also being restarted";
3074  }
3075  if (!restart_method.empty())
3076  mooseError(
3077  "Initial conditions have been specified during ",
3078  restart_method,
3079  ".\nThis is only allowed if you specify 'allow_initial_conditions_with_restart' to "
3080  "the [Problem], as initial conditions can override restarted fields");
3081  }
3082 }
3083 
3084 void
3085 FEProblemBase::addInitialCondition(const std::string & ic_name,
3086  const std::string & name,
3087  InputParameters & parameters)
3088 {
3089  parallel_object_only();
3090 
3091  // before we start to mess with the initial condition, we need to check parameters for errors.
3093  const std::string & var_name = parameters.get<VariableName>("variable");
3094 
3095  // Forbid initial conditions on a restarted problem, as they would override the restart
3096  checkICRestartError(ic_name, name, var_name);
3097 
3098  parameters.set<SubProblem *>("_subproblem") = this;
3099 
3100  // field IC
3101  if (hasVariable(var_name))
3102  {
3103  for (THREAD_ID tid = 0; tid < libMesh::n_threads(); ++tid)
3104  {
3107  parameters.set<SystemBase *>("_sys") = &var.sys();
3108  std::shared_ptr<InitialConditionBase> ic;
3109  if (dynamic_cast<MooseVariable *>(&var))
3110  ic = _factory.create<InitialCondition>(ic_name, name, parameters, tid);
3111  else if (dynamic_cast<VectorMooseVariable *>(&var))
3112  ic = _factory.create<VectorInitialCondition>(ic_name, name, parameters, tid);
3113  else if (dynamic_cast<ArrayMooseVariable *>(&var))
3114  ic = _factory.create<ArrayInitialCondition>(ic_name, name, parameters, tid);
3115  else if (dynamic_cast<MooseVariableFVReal *>(&var))
3116  ic = _factory.create<InitialCondition>(ic_name, name, parameters, tid);
3117  else
3118  mooseError("Your FE variable in initial condition ",
3119  name,
3120  " must be either of scalar or vector type");
3121  logAdd("IC", name, ic_name);
3122  _ics.addObject(ic, tid);
3123  }
3124  }
3125 
3126  // scalar IC
3127  else if (hasScalarVariable(var_name))
3128  {
3129  MooseVariableScalar & var = getScalarVariable(0, var_name);
3130  parameters.set<SystemBase *>("_sys") = &var.sys();
3131  std::shared_ptr<ScalarInitialCondition> ic =
3133  logAdd("ScalarIC", name, ic_name);
3134  _scalar_ics.addObject(ic);
3135  }
3136 
3137  else
3138  mooseError(
3139  "Variable '", var_name, "' requested in initial condition '", name, "' does not exist.");
3140 }
3141 
3142 void
3143 FEProblemBase::addFVInitialCondition(const std::string & ic_name,
3144  const std::string & name,
3145  InputParameters & parameters)
3146 {
3147  parallel_object_only();
3148 
3149  // before we start to mess with the initial condition, we need to check parameters for errors.
3151  const std::string & var_name = parameters.get<VariableName>("variable");
3152 
3153  // Forbid initial conditions on a restarted problem, as they would override the restart
3154  checkICRestartError(ic_name, name, var_name);
3155 
3156  parameters.set<SubProblem *>("_subproblem") = this;
3157 
3158  // field IC
3159  if (hasVariable(var_name))
3160  {
3161  for (THREAD_ID tid = 0; tid < libMesh::n_threads(); ++tid)
3162  {
3163  auto & var = getVariable(
3165  parameters.set<SystemBase *>("_sys") = &var.sys();
3166  std::shared_ptr<FVInitialConditionBase> ic;
3167  if (dynamic_cast<MooseVariableFVReal *>(&var))
3168  ic = _factory.create<FVInitialCondition>(ic_name, name, parameters, tid);
3169  else
3170  mooseError(
3171  "Your variable for an FVInitialCondition needs to be an a finite volume variable!");
3172  _fv_ics.addObject(ic, tid);
3173  }
3174  }
3175  else
3176  mooseError("Variable '",
3177  var_name,
3178  "' requested in finite volume initial condition '",
3179  name,
3180  "' does not exist.");
3181 }
3182 
3183 void
3185 {
3186  TIME_SECTION("projectSolution", 2, "Projecting Initial Solutions")
3187 
3188  FloatingPointExceptionGuard fpe_guard(_app);
3189 
3191  ComputeInitialConditionThread cic(*this);
3192  Threads::parallel_reduce(elem_range, cic);
3193 
3194  if (haveFV())
3195  {
3196  using ElemInfoRange = StoredRange<MooseMesh::const_elem_info_iterator, const ElemInfo *>;
3197  ElemInfoRange elem_info_range(_mesh.ownedElemInfoBegin(), _mesh.ownedElemInfoEnd());
3198 
3199  ComputeFVInitialConditionThread cfvic(*this);
3200  Threads::parallel_reduce(elem_info_range, cfvic);
3201  }
3202 
3203  // Need to close the solution vector here so that boundary ICs take precendence
3204  for (auto & nl : _nl)
3205  nl->solution().close();
3206  _aux->solution().close();
3207 
3208  // now run boundary-restricted initial conditions
3209  ConstBndNodeRange & bnd_nodes = *_mesh.getBoundaryNodeRange();
3211  Threads::parallel_reduce(bnd_nodes, cbic);
3212 
3213  for (auto & nl : _nl)
3214  nl->solution().close();
3215  _aux->solution().close();
3216 
3217  // Also, load values into the SCALAR dofs
3218  // Note: We assume that all SCALAR dofs are on the
3219  // processor with highest ID
3220  if (processor_id() == (n_processors() - 1) && _scalar_ics.hasActiveObjects())
3221  {
3222  const auto & ics = _scalar_ics.getActiveObjects();
3223  for (const auto & ic : ics)
3224  {
3225  MooseVariableScalar & var = ic->variable();
3226  var.reinit();
3227 
3228  DenseVector<Number> vals(var.order());
3229  ic->compute(vals);
3230 
3231  const unsigned int n_SCALAR_dofs = var.dofIndices().size();
3232  for (unsigned int i = 0; i < n_SCALAR_dofs; i++)
3233  {
3234  const dof_id_type global_index = var.dofIndices()[i];
3235  var.sys().solution().set(global_index, vals(i));
3236  var.setValue(i, vals(i));
3237  }
3238  }
3239  }
3240 
3241  for (auto & nl : _nl)
3242  {
3243  nl->solution().close();
3244  nl->solution().localize(*nl->system().current_local_solution, nl->dofMap().get_send_list());
3245  }
3246 
3247  _aux->solution().close();
3248  _aux->solution().localize(*_aux->sys().current_local_solution, _aux->dofMap().get_send_list());
3249 }
3250 
3251 void
3253  ConstBndNodeRange & bnd_nodes)
3254 {
3255  ComputeInitialConditionThread cic(*this);
3256  Threads::parallel_reduce(elem_range, cic);
3257 
3258  // Need to close the solution vector here so that boundary ICs take precendence
3259  for (auto & nl : _nl)
3260  nl->solution().close();
3261  _aux->solution().close();
3262 
3264  Threads::parallel_reduce(bnd_nodes, cbic);
3265 
3266  for (auto & nl : _nl)
3267  nl->solution().close();
3268  _aux->solution().close();
3269 
3270  // Also, load values into the SCALAR dofs
3271  // Note: We assume that all SCALAR dofs are on the
3272  // processor with highest ID
3273  if (processor_id() == (n_processors() - 1) && _scalar_ics.hasActiveObjects())
3274  {
3275  const auto & ics = _scalar_ics.getActiveObjects();
3276  for (const auto & ic : ics)
3277  {
3278  MooseVariableScalar & var = ic->variable();
3279  var.reinit();
3280 
3281  DenseVector<Number> vals(var.order());
3282  ic->compute(vals);
3283 
3284  const unsigned int n_SCALAR_dofs = var.dofIndices().size();
3285  for (unsigned int i = 0; i < n_SCALAR_dofs; i++)
3286  {
3287  const dof_id_type global_index = var.dofIndices()[i];
3288  var.sys().solution().set(global_index, vals(i));
3289  var.setValue(i, vals(i));
3290  }
3291  }
3292  }
3293 
3294  for (auto & nl : _nl)
3295  {
3296  nl->solution().close();
3297  nl->solution().localize(*nl->system().current_local_solution, nl->dofMap().get_send_list());
3298  }
3299 
3300  _aux->solution().close();
3301  _aux->solution().localize(*_aux->sys().current_local_solution, _aux->dofMap().get_send_list());
3302 }
3303 
3304 std::shared_ptr<MaterialBase>
3307  const THREAD_ID tid,
3308  bool no_warn)
3309 {
3310  switch (type)
3311  {
3313  name += "_neighbor";
3314  break;
3316  name += "_face";
3317  break;
3318  default:
3319  break;
3320  }
3321 
3322  std::shared_ptr<MaterialBase> material = _all_materials[type].getActiveObject(name, tid);
3323  if (!no_warn && material->getParam<bool>("compute") && type == Moose::BLOCK_MATERIAL_DATA)
3324  mooseWarning("You are retrieving a Material object (",
3325  material->name(),
3326  "), but its compute flag is set to true. This indicates that MOOSE is "
3327  "computing this property which may not be desired and produce un-expected "
3328  "results.");
3329 
3330  return material;
3331 }
3332 
3333 MaterialData &
3335 {
3336  switch (type)
3337  {
3339  return _material_props.getMaterialData(tid);
3346  }
3347 
3348  mooseError("FEProblemBase::getMaterialData(): Invalid MaterialDataType ", type);
3349 }
3350 
3351 void
3352 FEProblemBase::addFunctorMaterial(const std::string & functor_material_name,
3353  const std::string & name,
3354  InputParameters & parameters)
3355 {
3356  parallel_object_only();
3357 
3358  auto add_functor_materials = [&](const auto & parameters, const auto & name)
3359  {
3360  for (THREAD_ID tid = 0; tid < libMesh::n_threads(); tid++)
3361  {
3362  // Create the general Block/Boundary MaterialBase object
3363  std::shared_ptr<MaterialBase> material =
3364  _factory.create<MaterialBase>(functor_material_name, name, parameters, tid);
3365  logAdd("FunctorMaterial", name, functor_material_name);
3366  _all_materials.addObject(material, tid);
3367  _materials.addObject(material, tid);
3368  }
3369  };
3370 
3371  parameters.set<SubProblem *>("_subproblem") = this;
3372  add_functor_materials(parameters, name);
3373  if (_displaced_problem)
3374  {
3375  auto disp_params = parameters;
3376  disp_params.set<SubProblem *>("_subproblem") = _displaced_problem.get();
3377  add_functor_materials(disp_params, name + "_displaced");
3378  }
3379 }
3380 
3381 void
3382 FEProblemBase::addMaterial(const std::string & mat_name,
3383  const std::string & name,
3384  InputParameters & parameters)
3385 {
3386  addMaterialHelper({&_materials}, mat_name, name, parameters);
3387 }
3388 
3389 void
3390 FEProblemBase::addInterfaceMaterial(const std::string & mat_name,
3391  const std::string & name,
3392  InputParameters & parameters)
3393 {
3395 }
3396 
3397 void
3398 FEProblemBase::addMaterialHelper(std::vector<MaterialWarehouse *> warehouses,
3399  const std::string & mat_name,
3400  const std::string & name,
3401  InputParameters & parameters)
3402 {
3403  parallel_object_only();
3404 
3405  if (_displaced_problem && parameters.get<bool>("use_displaced_mesh"))
3406  {
3407  parameters.set<SubProblem *>("_subproblem") = _displaced_problem.get();
3409  }
3410  else
3411  {
3412  if (_displaced_problem == nullptr && parameters.get<bool>("use_displaced_mesh"))
3413  {
3414  // We allow Materials to request that they use_displaced_mesh,
3415  // but then be overridden when no displacements variables are
3416  // provided in the Mesh block. If that happened, update the value
3417  // of use_displaced_mesh appropriately for this Material.
3418  if (parameters.have_parameter<bool>("use_displaced_mesh"))
3419  parameters.set<bool>("use_displaced_mesh") = false;
3420  }
3421 
3422  parameters.set<SubProblem *>("_subproblem") = this;
3423  }
3424 
3425  for (THREAD_ID tid = 0; tid < libMesh::n_threads(); tid++)
3426  {
3427  // Create the general Block/Boundary MaterialBase object
3428  std::shared_ptr<MaterialBase> material =
3429  _factory.create<MaterialBase>(mat_name, name, parameters, tid);
3430  logAdd("Material", name, mat_name);
3431  bool discrete = !material->getParam<bool>("compute");
3432 
3433  // If the object is boundary restricted or if it is a functor material we do not create the
3434  // neighbor and face objects
3435  if (material->boundaryRestricted() || dynamic_cast<FunctorMaterial *>(material.get()))
3436  {
3437  _all_materials.addObject(material, tid);
3438  if (discrete)
3439  _discrete_materials.addObject(material, tid);
3440  else
3441  for (auto && warehouse : warehouses)
3442  warehouse->addObject(material, tid);
3443  }
3444 
3445  // Non-boundary restricted require face and neighbor objects
3446  else
3447  {
3448  // TODO: we only need to do this if we have needs for face materials (e.g.
3449  // FV, DG, etc.) - but currently we always do it. Figure out how to fix
3450  // this.
3451 
3452  // The name of the object being created, this is changed multiple times as objects are
3453  // created below
3454  std::string object_name;
3455 
3456  // Create a copy of the supplied parameters to the setting for "_material_data_type" isn't
3457  // used from a previous tid loop
3458  InputParameters current_parameters = parameters;
3459 
3460  // face material
3461  current_parameters.set<Moose::MaterialDataType>("_material_data_type") =
3463  object_name = name + "_face";
3464  std::shared_ptr<MaterialBase> face_material =
3465  _factory.create<MaterialBase>(mat_name, object_name, current_parameters, tid);
3466 
3467  // neighbor material
3468  current_parameters.set<Moose::MaterialDataType>("_material_data_type") =
3470  current_parameters.set<bool>("_neighbor") = true;
3471  object_name = name + "_neighbor";
3472  std::shared_ptr<MaterialBase> neighbor_material =
3473  _factory.create<MaterialBase>(mat_name, object_name, current_parameters, tid);
3474 
3475  // Store the material objects
3476  _all_materials.addObjects(material, neighbor_material, face_material, tid);
3477 
3478  if (discrete)
3479  _discrete_materials.addObjects(material, neighbor_material, face_material, tid);
3480  else
3481  for (auto && warehouse : warehouses)
3482  warehouse->addObjects(material, neighbor_material, face_material, tid);
3483 
3484  // Names of all controllable parameters for this Material object
3485  const std::string & base = parameters.get<std::string>("_moose_base");
3486  MooseObjectParameterName name(MooseObjectName(base, material->name()), "*");
3487  const auto param_names =
3489 
3490  // Connect parameters of the primary Material object to those on the face and neighbor
3491  // objects
3492  for (const auto & p_name : param_names)
3493  {
3494  MooseObjectParameterName primary_name(MooseObjectName(base, material->name()),
3495  p_name.parameter());
3496  MooseObjectParameterName face_name(MooseObjectName(base, face_material->name()),
3497  p_name.parameter());
3498  MooseObjectParameterName neighbor_name(MooseObjectName(base, neighbor_material->name()),
3499  p_name.parameter());
3501  primary_name, face_name, false);
3503  primary_name, neighbor_name, false);
3504  }
3505  }
3506  }
3507 }
3508 
3509 void
3510 FEProblemBase::prepareMaterials(const std::unordered_set<unsigned int> & consumer_needed_mat_props,
3511  const SubdomainID blk_id,
3512  const THREAD_ID tid)
3513 {
3514  std::set<MooseVariableFEBase *> needed_moose_vars;
3515  std::unordered_set<unsigned int> needed_mat_props;
3516 
3517  if (_all_materials.hasActiveBlockObjects(blk_id, tid))
3518  {
3519  _all_materials.updateVariableDependency(needed_moose_vars, tid);
3520  _all_materials.updateBlockMatPropDependency(blk_id, needed_mat_props, tid);
3521  }
3522 
3523  const auto & ids = _mesh.getSubdomainBoundaryIds(blk_id);
3524  for (const auto id : ids)
3525  {
3526  _materials.updateBoundaryVariableDependency(id, needed_moose_vars, tid);
3527  _materials.updateBoundaryMatPropDependency(id, needed_mat_props, tid);
3528  }
3529 
3530  const auto & current_active_elemental_moose_variables = getActiveElementalMooseVariables(tid);
3531  needed_moose_vars.insert(current_active_elemental_moose_variables.begin(),
3532  current_active_elemental_moose_variables.end());
3533 
3534  needed_mat_props.insert(consumer_needed_mat_props.begin(), consumer_needed_mat_props.end());
3535 
3536  setActiveElementalMooseVariables(needed_moose_vars, tid);
3537  setActiveMaterialProperties(needed_mat_props, tid);
3538 }
3539 
3540 void
3541 FEProblemBase::reinitMaterials(SubdomainID blk_id, const THREAD_ID tid, bool swap_stateful)
3542 {
3543  if (hasActiveMaterialProperties(tid))
3544  {
3545  auto && elem = _assembly[tid][0]->elem();
3546  unsigned int n_points = _assembly[tid][0]->qRule()->n_points();
3547 
3548  auto & material_data = _material_props.getMaterialData(tid);
3549  material_data.resize(n_points);
3550 
3551  // Only swap if requested
3552  if (swap_stateful)
3553  material_data.swap(*elem);
3554 
3555  if (_discrete_materials.hasActiveBlockObjects(blk_id, tid))
3556  material_data.reset(_discrete_materials.getActiveBlockObjects(blk_id, tid));
3557 
3558  if (_materials.hasActiveBlockObjects(blk_id, tid))
3559  material_data.reinit(_materials.getActiveBlockObjects(blk_id, tid));
3560  }
3561 }
3562 
3563 void
3565  const THREAD_ID tid,
3566  const bool swap_stateful,
3567  const std::deque<MaterialBase *> * const reinit_mats)
3568 {
3569  if (hasActiveMaterialProperties(tid))
3570  {
3571  auto && elem = _assembly[tid][0]->elem();
3572  unsigned int side = _assembly[tid][0]->side();
3573  unsigned int n_points = _assembly[tid][0]->qRuleFace()->n_points();
3574 
3575  auto & bnd_material_data = _bnd_material_props.getMaterialData(tid);
3576  bnd_material_data.resize(n_points);
3577 
3578  if (swap_stateful && !bnd_material_data.isSwapped())
3579  bnd_material_data.swap(*elem, side);
3580 
3581  if (_discrete_materials[Moose::FACE_MATERIAL_DATA].hasActiveBlockObjects(blk_id, tid))
3582  bnd_material_data.reset(
3583  _discrete_materials[Moose::FACE_MATERIAL_DATA].getActiveBlockObjects(blk_id, tid));
3584 
3585  if (reinit_mats)
3586  bnd_material_data.reinit(*reinit_mats);
3587  else if (_materials[Moose::FACE_MATERIAL_DATA].hasActiveBlockObjects(blk_id, tid))
3588  bnd_material_data.reinit(
3589  _materials[Moose::FACE_MATERIAL_DATA].getActiveBlockObjects(blk_id, tid));
3590  }
3591 }
3592 
3593 void
3595  const THREAD_ID tid,
3596  const bool swap_stateful,
3597  const std::deque<MaterialBase *> * const reinit_mats)
3598 {
3599  if (hasActiveMaterialProperties(tid))
3600  {
3601  // NOTE: this will not work with h-adaptivity
3602  // lindsayad: why not?
3603 
3604  const Elem * neighbor = _assembly[tid][0]->neighbor();
3605  unsigned int neighbor_side = neighbor->which_neighbor_am_i(_assembly[tid][0]->elem());
3606 
3607  mooseAssert(neighbor, "neighbor should be non-null");
3608  mooseAssert(blk_id == neighbor->subdomain_id(),
3609  "The provided blk_id " << blk_id << " and neighbor subdomain ID "
3610  << neighbor->subdomain_id() << " do not match.");
3611 
3612  unsigned int n_points = _assembly[tid][0]->qRuleNeighbor()->n_points();
3613 
3614  auto & neighbor_material_data = _neighbor_material_props.getMaterialData(tid);
3615  neighbor_material_data.resize(n_points);
3616 
3617  // Only swap if requested
3618  if (swap_stateful)
3619  neighbor_material_data.swap(*neighbor, neighbor_side);
3620 
3621  if (_discrete_materials[Moose::NEIGHBOR_MATERIAL_DATA].hasActiveBlockObjects(blk_id, tid))
3622  neighbor_material_data.reset(
3623  _discrete_materials[Moose::NEIGHBOR_MATERIAL_DATA].getActiveBlockObjects(blk_id, tid));
3624 
3625  if (reinit_mats)
3626  neighbor_material_data.reinit(*reinit_mats);
3627  else if (_materials[Moose::NEIGHBOR_MATERIAL_DATA].hasActiveBlockObjects(blk_id, tid))
3628  neighbor_material_data.reinit(
3629  _materials[Moose::NEIGHBOR_MATERIAL_DATA].getActiveBlockObjects(blk_id, tid));
3630  }
3631 }
3632 
3633 void
3635  const THREAD_ID tid,
3636  const bool swap_stateful,
3637  const std::deque<MaterialBase *> * const reinit_mats)
3638 {
3639  if (hasActiveMaterialProperties(tid))
3640  {
3641  auto && elem = _assembly[tid][0]->elem();
3642  unsigned int side = _assembly[tid][0]->side();
3643  unsigned int n_points = _assembly[tid][0]->qRuleFace()->n_points();
3644 
3645  auto & bnd_material_data = _bnd_material_props.getMaterialData(tid);
3646  bnd_material_data.resize(n_points);
3647 
3648  if (swap_stateful && !bnd_material_data.isSwapped())
3649  bnd_material_data.swap(*elem, side);
3650 
3651  if (_discrete_materials.hasActiveBoundaryObjects(boundary_id, tid))
3652  bnd_material_data.reset(_discrete_materials.getActiveBoundaryObjects(boundary_id, tid));
3653 
3654  if (reinit_mats)
3655  bnd_material_data.reinit(*reinit_mats);
3656  else if (_materials.hasActiveBoundaryObjects(boundary_id, tid))
3657  bnd_material_data.reinit(_materials.getActiveBoundaryObjects(boundary_id, tid));
3658  }
3659 }
3660 
3661 void
3663  const THREAD_ID tid,
3664  bool swap_stateful)
3665 {
3666  if (hasActiveMaterialProperties(tid))
3667  {
3668  const Elem * const & elem = _assembly[tid][0]->elem();
3669  unsigned int side = _assembly[tid][0]->side();
3670  unsigned int n_points = _assembly[tid][0]->qRuleFace()->n_points();
3671 
3672  auto & bnd_material_data = _bnd_material_props.getMaterialData(tid);
3673  bnd_material_data.resize(n_points);
3674 
3675  if (swap_stateful && !bnd_material_data.isSwapped())
3676  bnd_material_data.swap(*elem, side);
3677 
3678  if (_interface_materials.hasActiveBoundaryObjects(boundary_id, tid))
3679  bnd_material_data.reinit(_interface_materials.getActiveBoundaryObjects(boundary_id, tid));
3680  }
3681 }
3682 
3683 void
3685 {
3686  auto && elem = _assembly[tid][0]->elem();
3688 }
3689 
3690 void
3692 {
3693  auto && elem = _assembly[tid][0]->elem();
3694  unsigned int side = _assembly[tid][0]->side();
3695  _bnd_material_props.getMaterialData(tid).swapBack(*elem, side);
3696 }
3697 
3698 void
3700 {
3701  // NOTE: this will not work with h-adaptivity
3702  const Elem * neighbor = _assembly[tid][0]->neighbor();
3703  unsigned int neighbor_side =
3704  neighbor ? neighbor->which_neighbor_am_i(_assembly[tid][0]->elem()) : libMesh::invalid_uint;
3705 
3706  if (!neighbor)
3707  {
3708  if (haveFV())
3709  {
3710  // If neighbor is null, then we're on the neighbor side of a mesh boundary, e.g. we're off
3711  // the mesh in ghost-land. If we're using the finite volume method, then variable values and
3712  // consequently material properties have well-defined values in this ghost region outside of
3713  // the mesh and we really do want to reinit our neighbor materials in this case. Since we're
3714  // off in ghost land it's safe to do swaps with `MaterialPropertyStorage` using the elem and
3715  // elem_side keys
3716  neighbor = _assembly[tid][0]->elem();
3717  neighbor_side = _assembly[tid][0]->side();
3718  mooseAssert(neighbor, "We should have an appropriate value for elem coming from Assembly");
3719  }
3720  else
3721  mooseError("neighbor is null in Assembly!");
3722  }
3723 
3724  _neighbor_material_props.getMaterialData(tid).swapBack(*neighbor, neighbor_side);
3725 }
3726 
3727 void
3728 FEProblemBase::logAdd(const std::string & system,
3729  const std::string & name,
3730  const std::string & type) const
3731 {
3732  if (_verbose_setup)
3733  _console << "[DBG] Adding " << system << " '" << name << "' of type " << type << std::endl;
3734 }
3735 
3736 void
3738  const std::string & object_name,
3739  const std::string & var_param_name)
3740 {
3741  const auto nl_sys_num =
3742  parameters.isParamValid(var_param_name) &&
3743  determineNonlinearSystem(parameters.varName(var_param_name, object_name)).first
3744  ? determineNonlinearSystem(parameters.varName(var_param_name, object_name)).second
3745  : (unsigned int)0;
3746 
3747  if (_displaced_problem && parameters.have_parameter<bool>("use_displaced_mesh") &&
3748  parameters.get<bool>("use_displaced_mesh"))
3749  {
3750  parameters.set<SubProblem *>("_subproblem") = _displaced_problem.get();
3751  parameters.set<SystemBase *>("_sys") = &_displaced_problem->nlSys(nl_sys_num);
3752  }
3753  else
3754  {
3755  // The object requested use_displaced_mesh, but it was overridden
3756  // due to there being no displacements variables in the [Mesh] block.
3757  // If that happened, update the value of use_displaced_mesh appropriately.
3758  if (!_displaced_problem && parameters.have_parameter<bool>("use_displaced_mesh") &&
3759  parameters.get<bool>("use_displaced_mesh"))
3760  parameters.set<bool>("use_displaced_mesh") = false;
3761 
3762  parameters.set<SubProblem *>("_subproblem") = this;
3763  parameters.set<SystemBase *>("_sys") = _nl[nl_sys_num].get();
3764  }
3765 }
3766 
3767 void
3768 FEProblemBase::addPostprocessor(const std::string & pp_name,
3769  const std::string & name,
3770  InputParameters & parameters)
3771 {
3772  // Check for name collision
3773  if (hasUserObject(name))
3774  mooseError("A UserObject with the name \"",
3775  name,
3776  "\" already exists. You may not add a Postprocessor by the same name.");
3777 
3778  addUserObject(pp_name, name, parameters);
3779 }
3780 
3781 void
3782 FEProblemBase::addVectorPostprocessor(const std::string & pp_name,
3783  const std::string & name,
3784  InputParameters & parameters)
3785 {
3786  // Check for name collision
3787  if (hasUserObject(name))
3788  mooseError("A UserObject with the name \"",
3789  name,
3790  "\" already exists. You may not add a VectorPostprocessor by the same name.");
3791 
3792  addUserObject(pp_name, name, parameters);
3793 }
3794 
3795 void
3796 FEProblemBase::addReporter(const std::string & type,
3797  const std::string & name,
3798  InputParameters & parameters)
3799 {
3800  // Check for name collision
3801  if (hasUserObject(name))
3802  mooseError(std::string("A UserObject with the name \"") + name +
3803  "\" already exists. You may not add a Reporter by the same name.");
3804 
3806 }
3807 
3808 std::vector<std::shared_ptr<UserObject>>
3809 FEProblemBase::addUserObject(const std::string & user_object_name,
3810  const std::string & name,
3811  InputParameters & parameters)
3812 {
3813  parallel_object_only();
3814 
3815  std::vector<std::shared_ptr<UserObject>> uos;
3816 
3817  // Add the _subproblem and _sys parameters depending on use_displaced_mesh
3819 
3820  for (const auto tid : make_range(libMesh::n_threads()))
3821  {
3822  // Create the UserObject
3823  std::shared_ptr<UserObject> user_object =
3824  _factory.create<UserObject>(user_object_name, name, parameters, tid);
3825  logAdd("UserObject", name, user_object_name);
3826  uos.push_back(user_object);
3827 
3828  if (tid != 0)
3829  user_object->setPrimaryThreadCopy(uos[0].get());
3830 
3831  // TODO: delete this line after apps have been updated to not call getUserObjects
3832  _all_user_objects.addObject(user_object, tid);
3833 
3834  theWarehouse().add(user_object);
3835 
3836  // Attempt to create all the possible UserObject types
3837  auto euo = std::dynamic_pointer_cast<ElementUserObject>(user_object);
3838  auto suo = std::dynamic_pointer_cast<SideUserObject>(user_object);
3839  auto isuo = std::dynamic_pointer_cast<InternalSideUserObject>(user_object);
3840  auto iuob = std::dynamic_pointer_cast<InterfaceUserObjectBase>(user_object);
3841  auto nuo = std::dynamic_pointer_cast<NodalUserObject>(user_object);
3842  auto duo = std::dynamic_pointer_cast<DomainUserObject>(user_object);
3843  auto guo = std::dynamic_pointer_cast<GeneralUserObject>(user_object);
3844  auto tguo = std::dynamic_pointer_cast<ThreadedGeneralUserObject>(user_object);
3845  auto muo = std::dynamic_pointer_cast<MortarUserObject>(user_object);
3846 
3847  // Account for displaced mesh use
3848  if (_displaced_problem && parameters.get<bool>("use_displaced_mesh"))
3849  {
3850  if (euo || nuo || duo)
3851  _reinit_displaced_elem = true;
3852  else if (suo)
3853  // shouldn't we add isuo
3854  _reinit_displaced_face = true;
3855  else if (iuob)
3857  }
3858 
3859  // These objects only require one thread
3860  if ((guo && !tguo) || muo)
3861  break;
3862  }
3863 
3864  // Add as a Functor if it is one
3865  // At the timing of adding this, this is only Postprocessors... but technically it
3866  // should enable any UO that is a Real Functor to be used as one
3867  // The ternary operator used in getting the functor is there because some UOs
3868  // are threaded and some are not. When a UO is not threaded, we need to add
3869  // the functor from thread 0 as the registered functor for all threads
3870  for (const auto tid : make_range(libMesh::n_threads()))
3871  if (const auto functor =
3872  dynamic_cast<Moose::FunctorBase<Real> *>(uos[uos.size() == 1 ? 0 : tid].get()))
3873  {
3874  this->addFunctor(name, *functor, tid);
3875  if (_displaced_problem)
3876  _displaced_problem->addFunctor(name, *functor, tid);
3877  }
3878 
3879  return uos;
3880 }
3881 
3882 const UserObject &
3883 FEProblemBase::getUserObjectBase(const std::string & name, const THREAD_ID tid /* = 0 */) const
3884 {
3885  std::vector<UserObject *> objs;
3886  theWarehouse()
3887  .query()
3888  .condition<AttribSystem>("UserObject")
3889  .condition<AttribThread>(tid)
3890  .condition<AttribName>(name)
3891  .queryInto(objs);
3892  if (objs.empty())
3893  mooseError("Unable to find user object with name '" + name + "'");
3894  mooseAssert(objs.size() == 1, "Should only find one UO");
3895  return *(objs[0]);
3896 }
3897 
3898 const Positions &
3899 FEProblemBase::getPositionsObject(const std::string & name) const
3900 {
3901  std::vector<Positions *> objs;
3902  theWarehouse()
3903  .query()
3904  .condition<AttribSystem>("UserObject")
3905  .condition<AttribName>(name)
3906  .queryInto(objs);
3907  if (objs.empty())
3908  mooseError("Unable to find Positions object with name '" + name + "'");
3909  mooseAssert(objs.size() == 1, "Should only find one Positions");
3910  return *(objs[0]);
3911 }
3912 
3913 bool
3914 FEProblemBase::hasUserObject(const std::string & name) const
3915 {
3916  std::vector<UserObject *> objs;
3917  theWarehouse()
3918  .query()
3919  .condition<AttribSystem>("UserObject")
3920  .condition<AttribThread>(0)
3921  .condition<AttribName>(name)
3922  .queryInto(objs);
3923  return !objs.empty();
3924 }
3925 
3926 bool
3927 FEProblemBase::hasPostprocessorValueByName(const PostprocessorName & name) const
3928 {
3930 }
3931 
3932 const PostprocessorValue &
3933 FEProblemBase::getPostprocessorValueByName(const PostprocessorName & name,
3934  std::size_t t_index) const
3935 {
3937  t_index);
3938 }
3939 
3940 void
3941 FEProblemBase::setPostprocessorValueByName(const PostprocessorName & name,
3942  const PostprocessorValue & value,
3943  std::size_t t_index)
3944 {
3946  PostprocessorReporterName(name), value, t_index);
3947 }
3948 
3949 bool
3950 FEProblemBase::hasPostprocessor(const std::string & name) const
3951 {
3952  mooseDeprecated("FEProblemBase::hasPostprocssor is being removed; use "
3953  "hasPostprocessorValueByName instead.");
3955 }
3956 
3959  const std::string & vector_name,
3960  std::size_t t_index) const
3961 {
3963  VectorPostprocessorReporterName(object_name, vector_name), t_index);
3964 }
3965 
3966 void
3968  const std::string & vector_name,
3969  const VectorPostprocessorValue & value,
3970  std::size_t t_index)
3971 {
3973  VectorPostprocessorReporterName(object_name, vector_name), value, t_index);
3974 }
3975 
3976 const VectorPostprocessor &
3978  const THREAD_ID tid) const
3979 {
3980  return getUserObject<VectorPostprocessor>(object_name, tid);
3981 }
3982 
3983 void
3985 {
3986  for (const auto & it : _multi_apps)
3987  {
3988  const auto & objects = it.second.getActiveObjects();
3989  for (const auto & obj : objects)
3990  obj->parentOutputPositionChanged();
3991  }
3992 }
3993 
3994 void
3996 {
3998  computeMarkers();
3999 }
4000 
4001 void
4003 {
4004  // Initialize indicator aux variable fields
4006  {
4007  TIME_SECTION("computeIndicators", 1, "Computing Indicators");
4008 
4009  // Internal side indicators may lead to creating a much larger sparsity pattern than dictated by
4010  // the actual finite element scheme (e.g. CFEM)
4011  const auto old_do_derivatives = ADReal::do_derivatives;
4012  ADReal::do_derivatives = false;
4013 
4014  std::vector<std::string> fields;
4015 
4016  // Indicator Fields
4017  const auto & indicators = _indicators.getActiveObjects();
4018  for (const auto & indicator : indicators)
4019  fields.push_back(indicator->name());
4020 
4021  // InternalSideIndicator Fields
4022  const auto & internal_indicators = _internal_side_indicators.getActiveObjects();
4023  for (const auto & internal_indicator : internal_indicators)
4024  fields.push_back(internal_indicator->name());
4025 
4026  _aux->zeroVariables(fields);
4027 
4028  // compute Indicators
4029  ComputeIndicatorThread cit(*this);
4030  Threads::parallel_reduce(*_mesh.getActiveLocalElementRange(), cit);
4031  _aux->solution().close();
4032  _aux->update();
4033 
4034  ComputeIndicatorThread finalize_cit(*this, true);
4035  Threads::parallel_reduce(*_mesh.getActiveLocalElementRange(), finalize_cit);
4036  _aux->solution().close();
4037  _aux->update();
4038 
4039  ADReal::do_derivatives = old_do_derivatives;
4040  }
4041 }
4042 
4043 void
4045 {
4046  if (_markers.hasActiveObjects())
4047  {
4048  TIME_SECTION("computeMarkers", 1, "Computing Markers");
4049 
4050  std::vector<std::string> fields;
4051 
4052  // Marker Fields
4053  const auto & markers = _markers.getActiveObjects();
4054  for (const auto & marker : markers)
4055  fields.push_back(marker->name());
4056 
4057  _aux->zeroVariables(fields);
4058 
4060 
4061  for (THREAD_ID tid = 0; tid < libMesh::n_threads(); ++tid)
4062  {
4063  const auto & markers = _markers.getActiveObjects(tid);
4064  for (const auto & marker : markers)
4065  marker->markerSetup();
4066  }
4067 
4068  ComputeMarkerThread cmt(*this);
4069  Threads::parallel_reduce(*_mesh.getActiveLocalElementRange(), cmt);
4070 
4071  _aux->solution().close();
4072  _aux->update();
4073  }
4074 }
4075 
4076 const ExecFlagType &
4078 {
4079  return _current_execute_on_flag;
4080 }
4081 
4082 void
4084 {
4085  _current_execute_on_flag = flag;
4086 }
4087 
4088 void
4090 {
4091 }
4092 
4093 void
4095 {
4096  SubProblem::customSetup(exec_type);
4097 
4098  if (_line_search)
4099  _line_search->customSetup(exec_type);
4100 
4101  unsigned int n_threads = libMesh::n_threads();
4102  for (THREAD_ID tid = 0; tid < n_threads; tid++)
4103  {
4104  _all_materials.customSetup(exec_type, tid);
4105  _functions.customSetup(exec_type, tid);
4106  }
4107 
4108  _aux->customSetup(exec_type);
4109  for (auto & nl : _nl)
4110  nl->customSetup(exec_type);
4111 
4112  if (_displaced_problem)
4113  _displaced_problem->customSetup(exec_type);
4114 
4115  for (THREAD_ID tid = 0; tid < n_threads; tid++)
4116  {
4117  _internal_side_indicators.customSetup(exec_type, tid);
4118  _indicators.customSetup(exec_type, tid);
4119  _markers.customSetup(exec_type, tid);
4120  }
4121 
4122  std::vector<UserObject *> userobjs;
4123  theWarehouse().query().condition<AttribSystem>("UserObject").queryIntoUnsorted(userobjs);
4124  for (auto obj : userobjs)
4125  obj->customSetup(exec_type);
4126 
4127  _app.getOutputWarehouse().customSetup(exec_type);
4128 }
4129 
4130 void
4132 {
4133  // Set the current flag
4134  setCurrentExecuteOnFlag(exec_type);
4135 
4136  if (exec_type != EXEC_INITIAL)
4137  executeControls(exec_type);
4138 
4139  // intentially call this after executing controls because the setups may rely on the controls
4140  // FIXME: we skip the following flags because they have dedicated setup functions in
4141  // SetupInterface and it may not be appropriate to call them here.
4142  if (!(exec_type == EXEC_INITIAL || exec_type == EXEC_TIMESTEP_BEGIN ||
4143  exec_type == EXEC_SUBDOMAIN || exec_type == EXEC_NONLINEAR || exec_type == EXEC_LINEAR))
4144  customSetup(exec_type);
4145 
4146  // Samplers; EXEC_INITIAL is not called because the Sampler::init() method that is called after
4147  // construction makes the first Sampler::execute() call. This ensures that the random number
4148  // generator object is the correct state prior to any other object (e.g., Transfers) attempts to
4149  // extract data from the Sampler. That is, if the Sampler::execute() call is delayed to here
4150  // then it is not in the correct state for other objects.
4151  if (exec_type != EXEC_INITIAL)
4152  executeSamplers(exec_type);
4153 
4154  // Pre-aux UserObjects
4155  computeUserObjects(exec_type, Moose::PRE_AUX);
4156 
4157  // AuxKernels
4158  computeAuxiliaryKernels(exec_type);
4159 
4160  // Post-aux UserObjects
4161  computeUserObjects(exec_type, Moose::POST_AUX);
4162 
4163  // Return the current flag to None
4165 
4167  {
4168  // we will only check aux variables and postprocessors
4169  // checking more reporter data can be added in the future if needed
4170  std::unique_ptr<NumericVector<Number>> x = _aux->currentSolution()->clone();
4171  DenseVector<Real> pp_values = getReporterData().getAllRealReporterValues();
4172 
4173  // call THIS execute one more time for checking the possible states
4174  _checking_uo_aux_state = true;
4175  FEProblemBase::execute(exec_type);
4176  _checking_uo_aux_state = false;
4177 
4178  const Real check_tol = 1e-8;
4179 
4180  const Real xnorm = x->l2_norm();
4181  *x -= *_aux->currentSolution();
4182  if (x->l2_norm() > check_tol * xnorm)
4183  {
4184  const auto & sys = _aux->system();
4185  const unsigned int n_vars = sys.n_vars();
4186  std::multimap<Real, std::string, std::greater<Real>> ordered_map;
4187  for (const auto i : make_range(n_vars))
4188  {
4189  const Real vnorm = sys.calculate_norm(*x, i, DISCRETE_L2);
4190  ordered_map.emplace(vnorm, sys.variable_name(i));
4191  }
4192 
4193  std::ostringstream oss;
4194  for (const auto & [error_norm, var_name] : ordered_map)
4195  oss << " {" << var_name << ", " << error_norm << "},\n";
4196 
4197  mooseError("Aux kernels, user objects appear to have states for aux variables on ",
4198  exec_type,
4199  ".\nVariable error norms in descending order:\n",
4200  oss.str());
4201  }
4202 
4203  const DenseVector<Real> new_pp_values = getReporterData().getAllRealReporterValues();
4204  if (pp_values.size() != new_pp_values.size())
4205  mooseError("Second execution for uo/aux state check should not change the number of "
4206  "real reporter values");
4207 
4208  const Real ppnorm = pp_values.l2_norm();
4209  pp_values -= new_pp_values;
4210  if (pp_values.l2_norm() > check_tol * ppnorm)
4211  {
4212  const auto pp_names = getReporterData().getAllRealReporterFullNames();
4213  std::multimap<Real, std::string, std::greater<Real>> ordered_map;
4214  for (const auto i : index_range(pp_names))
4215  ordered_map.emplace(std::abs(pp_values(i)), pp_names[i]);
4216 
4217  std::ostringstream oss;
4218  for (const auto & [error_norm, pp_name] : ordered_map)
4219  oss << " {" << pp_name << ", " << error_norm << "},\n";
4220 
4221  mooseError("Aux kernels, user objects appear to have states for real reporter values on ",
4222  exec_type,
4223  ".\nErrors of real reporter values in descending order:\n",
4224  oss.str());
4225  }
4226  }
4227 }
4228 
4229 void
4231 {
4232  _aux->compute(type);
4233 }
4234 
4235 // Finalize, threadJoin, and update PP values of Elemental/Nodal/Side/InternalSideUserObjects
4236 void
4238 {
4239  std::vector<UserObject *> objs;
4240  query.queryInto(objs);
4241  if (!isgen)
4242  {
4243  // join all threaded user objects (i.e. not regular general user objects) to the primary
4244  // thread
4245  for (auto obj : objs)
4246  if (obj->primaryThreadCopy())
4247  obj->primaryThreadCopy()->threadJoin(*obj);
4248  }
4249 
4250  query.condition<AttribThread>(0).queryInto(objs);
4251 
4252  // finalize objects and retrieve/store any postprocessor values
4253  for (auto obj : objs)
4254  {
4255  if (isgen && dynamic_cast<ThreadedGeneralUserObject *>(obj))
4256  continue;
4257  if (isgen)
4258  {
4259  // general user objects are not run in their own threaded loop object - so run them here
4260  if (shouldPrintExecution(0))
4261  _console << "[DBG] Initializing, executing & finalizing general UO '" << obj->name()
4262  << "' on " << _current_execute_on_flag.name() << std::endl;
4263  obj->initialize();
4264  obj->execute();
4265  }
4266 
4267  obj->finalize();
4268 
4269  // These have to be stored piecemeal (with every call to this function) because general
4270  // postprocessors (which run last after other userobjects have been completed) might depend on
4271  // them being stored. This wouldn't be a problem if all userobjects satisfied the dependency
4272  // resolver interface and could be sorted appropriately with the general userobjects, but they
4273  // don't.
4274  auto pp = dynamic_cast<const Postprocessor *>(obj);
4275  if (pp)
4276  {
4277  _reporter_data.finalize(obj->name());
4278  setPostprocessorValueByName(obj->name(), pp->getValue());
4279  }
4280 
4281  auto vpp = dynamic_cast<VectorPostprocessor *>(obj);
4282  if (vpp)
4283  _reporter_data.finalize(obj->name());
4284 
4285  // Update Reporter data
4286  auto reporter = dynamic_cast<Reporter *>(obj);
4287  if (reporter)
4288  _reporter_data.finalize(obj->name());
4289  }
4290 }
4291 
4292 void
4294  const Moose::AuxGroup & group,
4295  const std::string & name)
4296 {
4297  const auto old_exec_flag = _current_execute_on_flag;
4300  .query()
4301  .condition<AttribSystem>("UserObject")
4302  .condition<AttribExecOns>(type)
4303  .condition<AttribName>(name);
4305  _current_execute_on_flag = old_exec_flag;
4306 }
4307 
4308 void
4310 {
4312  theWarehouse().query().condition<AttribSystem>("UserObject").condition<AttribExecOns>(type);
4314 }
4315 
4316 void
4318  const Moose::AuxGroup & group,
4319  TheWarehouse::Query & primary_query)
4320 {
4321  try
4322  {
4323  TIME_SECTION("computeUserObjects", 1, "Computing User Objects");
4324 
4325  // Add group to query
4326  if (group == Moose::PRE_IC)
4327  primary_query.condition<AttribPreIC>(true);
4328  else if (group == Moose::PRE_AUX)
4329  primary_query.condition<AttribPreAux>(type);
4330  else if (group == Moose::POST_AUX)
4331  primary_query.condition<AttribPostAux>(type);
4332 
4333  // query everything first to obtain a list of execution groups
4334  std::vector<UserObject *> uos;
4335  primary_query.clone().queryIntoUnsorted(uos);
4336  std::set<int> execution_groups;
4337  for (const auto & uo : uos)
4338  execution_groups.insert(uo->getParam<int>("execution_order_group"));
4339 
4340  // iterate over execution order groups
4341  for (const auto execution_group : execution_groups)
4342  {
4343  auto query = primary_query.clone().condition<AttribExecutionOrderGroup>(execution_group);
4344 
4345  std::vector<GeneralUserObject *> genobjs;
4346  query.clone().condition<AttribInterfaces>(Interfaces::GeneralUserObject).queryInto(genobjs);
4347 
4348  std::vector<UserObject *> userobjs;
4349  query.clone()
4354  .queryInto(userobjs);
4355 
4356  std::vector<UserObject *> tgobjs;
4357  query.clone()
4359  .queryInto(tgobjs);
4360 
4361  std::vector<UserObject *> nodal;
4362  query.clone().condition<AttribInterfaces>(Interfaces::NodalUserObject).queryInto(nodal);
4363 
4364  std::vector<MortarUserObject *> mortar;
4365  query.clone().condition<AttribInterfaces>(Interfaces::MortarUserObject).queryInto(mortar);
4366 
4367  if (userobjs.empty() && genobjs.empty() && tgobjs.empty() && nodal.empty() && mortar.empty())
4368  continue;
4369 
4370  // Start the timer here since we have at least one active user object
4371  std::string compute_uo_tag = "computeUserObjects(" + Moose::stringify(type) + ")";
4372 
4373  // Perform Residual/Jacobian setups
4374  if (type == EXEC_LINEAR)
4375  {
4376  for (auto obj : userobjs)
4377  obj->residualSetup();
4378  for (auto obj : nodal)
4379  obj->residualSetup();
4380  for (auto obj : mortar)
4381  obj->residualSetup();
4382  for (auto obj : tgobjs)
4383  obj->residualSetup();
4384  for (auto obj : genobjs)
4385  obj->residualSetup();
4386  }
4387  else if (type == EXEC_NONLINEAR)
4388  {
4389  for (auto obj : userobjs)
4390  obj->jacobianSetup();
4391  for (auto obj : nodal)
4392  obj->jacobianSetup();
4393  for (auto obj : mortar)
4394  obj->jacobianSetup();
4395  for (auto obj : tgobjs)
4396  obj->jacobianSetup();
4397  for (auto obj : genobjs)
4398  obj->jacobianSetup();
4399  }
4400 
4401  for (auto obj : userobjs)
4402  obj->initialize();
4403 
4404  // Execute Side/InternalSide/Interface/Elemental/DomainUserObjects
4405  if (!userobjs.empty())
4406  {
4407  // non-nodal user objects have to be run separately before the nodal user objects run
4408  // because some nodal user objects (NodalNormal related) depend on elemental user objects
4409  // :-(
4410  ComputeUserObjectsThread cppt(*this, query);
4411  Threads::parallel_reduce(*_mesh.getActiveLocalElementRange(), cppt);
4412 
4413  // There is one instance in rattlesnake where an elemental user object's finalize depends
4414  // on a side user object having been finalized first :-(
4421  }
4422 
4423  // if any userobject may have written to variables we need to close the aux solution
4424  for (const auto & uo : userobjs)
4425  if (auto euo = dynamic_cast<const ElementUserObject *>(uo);
4426  euo && euo->hasWritableCoupledVariables())
4427  {
4428  _aux->solution().close();
4429  _aux->system().update();
4430  break;
4431  }
4432 
4433  // Execute NodalUserObjects
4434  // BISON has an axial reloc elemental user object that has a finalize func that depends on a
4435  // nodal user object's prev value. So we can't initialize this until after elemental objects
4436  // have been finalized :-(
4437  for (auto obj : nodal)
4438  obj->initialize();
4439  if (query.clone().condition<AttribInterfaces>(Interfaces::NodalUserObject).count() > 0)
4440  {
4441  ComputeNodalUserObjectsThread cnppt(*this, query);
4442  Threads::parallel_reduce(*_mesh.getLocalNodeRange(), cnppt);
4444  }
4445 
4446  // if any userobject may have written to variables we need to close the aux solution
4447  for (const auto & uo : nodal)
4448  if (auto nuo = dynamic_cast<const NodalUserObject *>(uo);
4449  nuo && nuo->hasWritableCoupledVariables())
4450  {
4451  _aux->solution().close();
4452  _aux->system().update();
4453  break;
4454  }
4455 
4456  // Execute MortarUserObjects
4457  {
4458  for (auto obj : mortar)
4459  obj->initialize();
4460  if (!mortar.empty())
4461  {
4462  auto create_and_run_mortar_functors = [this, type, &mortar](const bool displaced)
4463  {
4464  // go over mortar interfaces and construct functors
4465  const auto & mortar_interfaces = getMortarInterfaces(displaced);
4466  for (const auto & mortar_interface : mortar_interfaces)
4467  {
4468  const auto primary_secondary_boundary_pair = mortar_interface.first;
4469  auto mortar_uos_to_execute =
4470  getMortarUserObjects(primary_secondary_boundary_pair.first,
4471  primary_secondary_boundary_pair.second,
4472  displaced,
4473  mortar);
4474  const auto & mortar_generation_object = mortar_interface.second;
4475 
4476  auto * const subproblem = displaced
4477  ? static_cast<SubProblem *>(_displaced_problem.get())
4478  : static_cast<SubProblem *>(this);
4479  MortarUserObjectThread muot(mortar_uos_to_execute,
4480  mortar_generation_object,
4481  *subproblem,
4482  *this,
4483  displaced,
4484  subproblem->assembly(0, 0));
4485 
4486  muot();
4487  }
4488  };
4489 
4490  create_and_run_mortar_functors(false);
4491  if (_displaced_problem)
4492  create_and_run_mortar_functors(true);
4493  }
4494  for (auto obj : mortar)
4495  obj->finalize();
4496  }
4497 
4498  // Execute threaded general user objects
4499  for (auto obj : tgobjs)
4500  obj->initialize();
4501  std::vector<GeneralUserObject *> tguos_zero;
4502  query.clone()
4503  .condition<AttribThread>(0)
4504  .condition<AttribInterfaces>(Interfaces::ThreadedGeneralUserObject)
4505  .queryInto(tguos_zero);
4506  for (auto obj : tguos_zero)
4507  {
4508  std::vector<GeneralUserObject *> tguos;
4509  auto q = query.clone()
4510  .condition<AttribName>(obj->name())
4511  .condition<AttribInterfaces>(Interfaces::ThreadedGeneralUserObject);
4512  q.queryInto(tguos);
4513 
4515  Threads::parallel_reduce(GeneralUserObjectRange(tguos.begin(), tguos.end()), ctguot);
4516  joinAndFinalize(q);
4517  }
4518 
4519  // Execute general user objects
4521  true);
4522  }
4523  }
4524  catch (...)
4525  {
4526  handleException("computeUserObjectsInternal");
4527  }
4528 }
4529 
4530 void
4532 {
4533  if (_control_warehouse[exec_type].hasActiveObjects())
4534  {
4535  TIME_SECTION("executeControls", 1, "Executing Controls");
4536 
4538 
4539  auto controls_wh = _control_warehouse[exec_type];
4540  // Add all of the dependencies into the resolver and sort them
4541  for (const auto & it : controls_wh.getActiveObjects())
4542  {
4543  // Make sure an item with no dependencies comes out too!
4544  resolver.addItem(it);
4545 
4546  std::vector<std::string> & dependent_controls = it->getDependencies();
4547  for (const auto & depend_name : dependent_controls)
4548  {
4549  if (controls_wh.hasActiveObject(depend_name))
4550  {
4551  auto dep_control = controls_wh.getActiveObject(depend_name);
4552  resolver.addEdge(dep_control, it);
4553  }
4554  else
4555  mooseError("The Control \"",
4556  depend_name,
4557  "\" was not created, did you make a "
4558  "spelling mistake or forget to include it "
4559  "in your input file?");
4560  }
4561  }
4562 
4563  const auto & ordered_controls = resolver.getSortedValues();
4564 
4565  if (!ordered_controls.empty())
4566  {
4567  _control_warehouse.setup(exec_type);
4568  // Run the controls in the proper order
4569  for (const auto & control : ordered_controls)
4570  control->execute();
4571  }
4572  }
4573 }
4574 
4575 void
4577 {
4578  // TODO: This should be done in a threaded loop, but this should be super quick so for now
4579  // do a serial loop.
4580  for (THREAD_ID tid = 0; tid < libMesh::n_threads(); ++tid)
4581  {
4582  std::vector<Sampler *> objects;
4583  theWarehouse()
4584  .query()
4585  .condition<AttribSystem>("Sampler")
4586  .condition<AttribThread>(tid)
4587  .condition<AttribExecOns>(exec_type)
4588  .queryInto(objects);
4589 
4590  if (!objects.empty())
4591  {
4592  TIME_SECTION("executeSamplers", 1, "Executing Samplers");
4593  FEProblemBase::objectSetupHelper<Sampler>(objects, exec_type);
4594  FEProblemBase::objectExecuteHelper<Sampler>(objects);
4595  }
4596  }
4597 }
4598 
4599 void
4601 {
4602  TIME_SECTION("updateActiveObjects", 5, "Updating Active Objects");
4603 
4604  for (THREAD_ID tid = 0; tid < libMesh::n_threads(); ++tid)
4605  {
4606  for (auto & nl : _nl)
4607  nl->updateActive(tid);
4608  _aux->updateActive(tid);
4611  _markers.updateActive(tid);
4613  _materials.updateActive(tid);
4615  }
4616 
4624 }
4625 
4626 void
4628 {
4629  //<< "Object " << a->name() << " -> " << b->name() << std::endl;
4630 }
4631 
4632 void
4634 {
4635  TIME_SECTION("reinitBecauseOfGhostingOrNewGeomObjects",
4636  3,
4637  "Reinitializing Because of Geometric Search Objects");
4638 
4639  // Need to see if _any_ processor has ghosted elems or geometry objects.
4640  bool needs_reinit = !_ghosted_elems.empty();
4641  needs_reinit = needs_reinit || !_geometric_search_data._nearest_node_locators.empty() ||
4642  (_mortar_data.hasObjects() && mortar_changed);
4643  needs_reinit =
4644  needs_reinit || (_displaced_problem &&
4645  (!_displaced_problem->geomSearchData()._nearest_node_locators.empty() ||
4646  (_mortar_data.hasDisplacedObjects() && mortar_changed)));
4647  _communicator.max(needs_reinit);
4648 
4649  if (needs_reinit)
4650  {
4651  // Call reinit to get the ghosted vectors correct now that some geometric search has been done
4652  es().reinit();
4653 
4654  if (_displaced_mesh)
4655  _displaced_problem->es().reinit();
4656  }
4657 }
4658 
4659 void
4660 FEProblemBase::addDamper(const std::string & damper_name,
4661  const std::string & name,
4662  InputParameters & parameters)
4663 {
4664  parallel_object_only();
4665 
4666  const auto nl_sys_num =
4667  parameters.isParamValid("variable")
4668  ? determineNonlinearSystem(parameters.varName("variable", name), true).second
4669  : (unsigned int)0;
4670 
4671  parameters.set<SubProblem *>("_subproblem") = this;
4672  parameters.set<SystemBase *>("_sys") = _nl[nl_sys_num].get();
4673 
4674  _has_dampers = true;
4675  logAdd("Damper", name, damper_name);
4676  _nl[nl_sys_num]->addDamper(damper_name, name, parameters);
4677 }
4678 
4679 void
4681 {
4682  for (auto & nl : _nl)
4683  nl->setupDampers();
4684 }
4685 
4686 void
4687 FEProblemBase::addIndicator(const std::string & indicator_name,
4688  const std::string & name,
4689  InputParameters & parameters)
4690 {
4691  parallel_object_only();
4692 
4693  if (_displaced_problem && parameters.get<bool>("use_displaced_mesh"))
4694  {
4695  parameters.set<SubProblem *>("_subproblem") = _displaced_problem.get();
4696  parameters.set<SystemBase *>("_sys") = &_displaced_problem->auxSys();
4697  _reinit_displaced_elem = true;
4698  }
4699  else
4700  {
4701  if (_displaced_problem == nullptr && parameters.get<bool>("use_displaced_mesh"))
4702  {
4703  // We allow Indicators to request that they use_displaced_mesh,
4704  // but then be overridden when no displacements variables are
4705  // provided in the Mesh block. If that happened, update the value
4706  // of use_displaced_mesh appropriately for this Indicator.
4707  if (parameters.have_parameter<bool>("use_displaced_mesh"))
4708  parameters.set<bool>("use_displaced_mesh") = false;
4709  }
4710 
4711  parameters.set<SubProblem *>("_subproblem") = this;
4712  parameters.set<SystemBase *>("_sys") = _aux.get();
4713  }
4714 
4715  for (THREAD_ID tid = 0; tid < libMesh::n_threads(); tid++)
4716  {
4717  std::shared_ptr<Indicator> indicator =
4718  _factory.create<Indicator>(indicator_name, name, parameters, tid);
4719  logAdd("Indicator", name, indicator_name);
4720  std::shared_ptr<InternalSideIndicator> isi =
4722  if (isi)
4724  else
4725  _indicators.addObject(indicator, tid);
4726  }
4727 }
4728 
4729 void
4730 FEProblemBase::addMarker(const std::string & marker_name,
4731  const std::string & name,
4732  InputParameters & parameters)
4733 {
4734  parallel_object_only();
4735 
4736  if (_displaced_problem && parameters.get<bool>("use_displaced_mesh"))
4737  {
4738  parameters.set<SubProblem *>("_subproblem") = _displaced_problem.get();
4739  parameters.set<SystemBase *>("_sys") = &_displaced_problem->auxSys();
4740  _reinit_displaced_elem = true;
4741  }
4742  else
4743  {
4744  if (_displaced_problem == nullptr && parameters.get<bool>("use_displaced_mesh"))
4745  {
4746  // We allow Markers to request that they use_displaced_mesh,
4747  // but then be overridden when no displacements variables are
4748  // provided in the Mesh block. If that happened, update the value
4749  // of use_displaced_mesh appropriately for this Marker.
4750  if (parameters.have_parameter<bool>("use_displaced_mesh"))
4751  parameters.set<bool>("use_displaced_mesh") = false;
4752  }
4753 
4754  parameters.set<SubProblem *>("_subproblem") = this;
4755  parameters.set<SystemBase *>("_sys") = _aux.get();
4756  }
4757 
4758  for (THREAD_ID tid = 0; tid < libMesh::n_threads(); tid++)
4759  {
4760  std::shared_ptr<Marker> marker = _factory.create<Marker>(marker_name, name, parameters, tid);
4761  logAdd("Marker", name, marker_name);
4762  _markers.addObject(marker, tid);
4763  }
4764 }
4765 
4766 void
4767 FEProblemBase::addMultiApp(const std::string & multi_app_name,
4768  const std::string & name,
4769  InputParameters & parameters)
4770 {
4771  parallel_object_only();
4772 
4773  parameters.set<MPI_Comm>("_mpi_comm") = _communicator.get();
4774  parameters.set<std::shared_ptr<CommandLine>>("_command_line") = _app.commandLine();
4775 
4776  if (_displaced_problem && parameters.get<bool>("use_displaced_mesh"))
4777  {
4778  parameters.set<SubProblem *>("_subproblem") = _displaced_problem.get();
4779  parameters.set<SystemBase *>("_sys") = &_displaced_problem->auxSys();
4780  _reinit_displaced_elem = true;
4781  }
4782  else
4783  {
4784  if (_displaced_problem == nullptr && parameters.get<bool>("use_displaced_mesh"))
4785  {
4786  // We allow MultiApps to request that they use_displaced_mesh,
4787  // but then be overridden when no displacements variables are
4788  // provided in the Mesh block. If that happened, update the value
4789  // of use_displaced_mesh appropriately for this MultiApp.
4790  if (parameters.have_parameter<bool>("use_displaced_mesh"))
4791  parameters.set<bool>("use_displaced_mesh") = false;
4792  }
4793 
4794  parameters.set<SubProblem *>("_subproblem") = this;
4795  parameters.set<SystemBase *>("_sys") = _aux.get();
4796  }
4797 
4798  std::shared_ptr<MultiApp> multi_app = _factory.create<MultiApp>(multi_app_name, name, parameters);
4799  logAdd("MultiApp", name, multi_app_name);
4800  multi_app->setupPositions();
4801 
4802  _multi_apps.addObject(multi_app);
4803 
4804  // Store TransientMultiApp objects in another container, this is needed for calling computeDT
4805  std::shared_ptr<TransientMultiApp> trans_multi_app =
4807  if (trans_multi_app)
4808  _transient_multi_apps.addObject(trans_multi_app);
4809 }
4810 
4811 bool
4813 {
4814  return _multi_apps[type].hasActiveObjects();
4815 }
4816 
4817 bool
4818 FEProblemBase::hasMultiApp(const std::string & multi_app_name) const
4819 {
4820  return _multi_apps.hasActiveObject(multi_app_name);
4821 }
4822 
4823 std::shared_ptr<MultiApp>
4824 FEProblemBase::getMultiApp(const std::string & multi_app_name) const
4825 {
4826  return _multi_apps.getObject(multi_app_name);
4827 }
4828 
4829 void
4831 {
4832  bool to_multiapp = direction == MultiAppTransfer::TO_MULTIAPP;
4833  bool from_multiapp = direction == MultiAppTransfer::FROM_MULTIAPP;
4834  std::string string_direction;
4835  if (to_multiapp)
4836  string_direction = " To ";
4837  else if (from_multiapp)
4838  string_direction = " From ";
4839  else
4840  string_direction = " Between ";
4841 
4842  const MooseObjectWarehouse<Transfer> & wh = to_multiapp ? _to_multi_app_transfers[type]
4843  : from_multiapp ? _from_multi_app_transfers[type]
4845 
4846  if (wh.hasActiveObjects())
4847  {
4848  TIME_SECTION("execMultiAppTransfers", 1, "Executing Transfers");
4849 
4850  const auto & transfers = wh.getActiveObjects();
4851 
4852  if (_verbose_multiapps)
4853  {
4854  _console << COLOR_CYAN << "\nTransfers on " << Moose::stringify(type) << string_direction
4855  << "MultiApps" << COLOR_DEFAULT << ":" << std::endl;
4856 
4858  {"Name", "Type", "From", "To"});
4859 
4860  // Build Table of Transfer Info
4861  for (const auto & transfer : transfers)
4862  {
4863  auto multiapp_transfer = dynamic_cast<MultiAppTransfer *>(transfer.get());
4864 
4865  table.addRow(multiapp_transfer->name(),
4866  multiapp_transfer->type(),
4867  multiapp_transfer->getFromName(),
4868  multiapp_transfer->getToName());
4869  }
4870 
4871  // Print it
4872  table.print(_console);
4873  }
4874 
4875  for (const auto & transfer : transfers)
4876  {
4877  transfer->setCurrentDirection(direction);
4878  transfer->execute();
4879  }
4880 
4882 
4883  if (_verbose_multiapps)
4884  _console << COLOR_CYAN << "Transfers on " << Moose::stringify(type) << " Are Finished\n"
4885  << COLOR_DEFAULT << std::endl;
4886  }
4887  else if (_multi_apps[type].getActiveObjects().size())
4888  {
4889  if (_verbose_multiapps)
4890  _console << COLOR_CYAN << "\nNo Transfers on " << Moose::stringify(type) << string_direction
4891  << "MultiApps\n"
4892  << COLOR_DEFAULT << std::endl;
4893  }
4894 }
4895 
4896 std::vector<std::shared_ptr<Transfer>>
4898 {
4899  if (direction == MultiAppTransfer::TO_MULTIAPP)
4901  else if (direction == MultiAppTransfer::FROM_MULTIAPP)
4903  else
4905 }
4906 
4907 std::vector<std::shared_ptr<Transfer>>
4909 {
4910  if (direction == MultiAppTransfer::TO_MULTIAPP)
4912  else if (direction == MultiAppTransfer::FROM_MULTIAPP)
4914  else
4916 }
4917 
4920 {
4921  if (direction == MultiAppTransfer::TO_MULTIAPP)
4922  return _to_multi_app_transfers;
4923  else if (direction == MultiAppTransfer::FROM_MULTIAPP)
4925  else
4927 }
4928 
4929 bool
4931 {
4932  // Active MultiApps
4933  const std::vector<MooseSharedPointer<MultiApp>> & multi_apps =
4935 
4936  // Do anything that needs to be done to Apps before transfers
4937  for (const auto & multi_app : multi_apps)
4938  multi_app->preTransfer(_dt, _time);
4939 
4940  // Execute Transfers _to_ MultiApps
4942 
4943  // Execute Transfers _between_ Multiapps
4945 
4946  // Execute MultiApps
4947  if (multi_apps.size())
4948  {
4949  TIME_SECTION("execMultiApps", 1, "Executing MultiApps", false);
4950 
4951  if (_verbose_multiapps)
4952  _console << COLOR_CYAN << "\nExecuting MultiApps on " << Moose::stringify(type)
4953  << COLOR_DEFAULT << std::endl;
4954 
4955  bool success = true;
4956 
4957  for (const auto & multi_app : multi_apps)
4958  {
4959  success = multi_app->solveStep(_dt, _time, auto_advance);
4960  // no need to finish executing the subapps if one fails
4961  if (!success)
4962  break;
4963  }
4964 
4966 
4967  _communicator.min(success);
4968 
4969  if (!success)
4970  return false;
4971 
4972  if (_verbose_multiapps)
4973  _console << COLOR_CYAN << "Finished Executing MultiApps on " << Moose::stringify(type) << "\n"
4974  << COLOR_DEFAULT << std::endl;
4975  }
4976 
4977  // Execute Transfers _from_ MultiApps
4979 
4980  // If we made it here then everything passed
4981  return true;
4982 }
4983 
4984 void
4986 {
4987  const auto & multi_apps = _multi_apps.getActiveObjects();
4988 
4989  for (const auto & multi_app : multi_apps)
4990  multi_app->finalize();
4991 }
4992 
4993 void
4995 {
4996  const auto & multi_apps = _multi_apps.getActiveObjects();
4997 
4998  for (const auto & multi_app : multi_apps)
4999  multi_app->postExecute();
5000 }
5001 
5002 void
5004 {
5005  const auto & multi_apps = _multi_apps[type].getActiveObjects();
5006 
5007  if (multi_apps.size())
5008  for (const auto & multi_app : multi_apps)
5009  multi_app->incrementTStep(_time);
5010 }
5011 
5012 void
5013 FEProblemBase::finishMultiAppStep(ExecFlagType type, bool recurse_through_multiapp_levels)
5014 {
5015  const auto & multi_apps = _multi_apps[type].getActiveObjects();
5016 
5017  if (multi_apps.size())
5018  {
5019  if (_verbose_multiapps)
5020  _console << COLOR_CYAN << "\nAdvancing MultiApps on " << type.name() << COLOR_DEFAULT
5021  << std::endl;
5022 
5023  for (const auto & multi_app : multi_apps)
5024  multi_app->finishStep(recurse_through_multiapp_levels);
5025 
5027 
5028  if (_verbose_multiapps)
5029  _console << COLOR_CYAN << "Finished Advancing MultiApps on " << type.name() << "\n"
5030  << COLOR_DEFAULT << std::endl;
5031  }
5032 }
5033 
5034 void
5036 {
5037  const auto & multi_apps = _multi_apps[type].getActiveObjects();
5038 
5039  if (multi_apps.size())
5040  {
5041  TIME_SECTION("backupMultiApps", 5, "Backing Up MultiApp");
5042 
5043  if (_verbose_multiapps)
5044  _console << COLOR_CYAN << "\nBacking Up MultiApps on " << type.name() << COLOR_DEFAULT
5045  << std::endl;
5046 
5047  for (const auto & multi_app : multi_apps)
5048  multi_app->backup();
5049 
5051 
5052  if (_verbose_multiapps)
5053  _console << COLOR_CYAN << "Finished Backing Up MultiApps on " << type.name() << "\n"
5054  << COLOR_DEFAULT << std::endl;
5055  }
5056 }
5057 
5058 void
5060 {
5061  const auto & multi_apps = _multi_apps[type].getActiveObjects();
5062 
5063  if (multi_apps.size())
5064  {
5065  if (_verbose_multiapps)
5066  {
5067  if (force)
5068  _console << COLOR_CYAN << "\nRestoring Multiapps on " << type.name()
5069  << " because of solve failure!" << COLOR_DEFAULT << std::endl;
5070  else
5071  _console << COLOR_CYAN << "\nRestoring MultiApps on " << type.name() << COLOR_DEFAULT
5072  << std::endl;
5073  }
5074 
5075  for (const auto & multi_app : multi_apps)
5076  multi_app->restore(force);
5077 
5079 
5080  if (_verbose_multiapps)
5081  _console << COLOR_CYAN << "Finished Restoring MultiApps on " << type.name() << "\n"
5082  << COLOR_DEFAULT << std::endl;
5083  }
5084 }
5085 
5086 Real
5088 {
5089  const auto & multi_apps = _transient_multi_apps[type].getActiveObjects();
5090 
5091  Real smallest_dt = std::numeric_limits<Real>::max();
5092 
5093  for (const auto & multi_app : multi_apps)
5094  smallest_dt = std::min(smallest_dt, multi_app->computeDT());
5095 
5096  return smallest_dt;
5097 }
5098 
5099 void
5101 {
5102  if (_transfers[type].hasActiveObjects())
5103  {
5104  TIME_SECTION("execTransfers", 3, "Executing Transfers");
5105 
5106  const auto & transfers = _transfers[type].getActiveObjects();
5107 
5108  for (const auto & transfer : transfers)
5109  transfer->execute();
5110  }
5111 }
5112 
5113 void
5114 FEProblemBase::addTransfer(const std::string & transfer_name,
5115  const std::string & name,
5116  InputParameters & parameters)
5117 {
5118  parallel_object_only();
5119 
5120  if (_displaced_problem && parameters.get<bool>("use_displaced_mesh"))
5121  {
5122  parameters.set<SubProblem *>("_subproblem") = _displaced_problem.get();
5123  parameters.set<SystemBase *>("_sys") = &_displaced_problem->auxSys();
5124  _reinit_displaced_elem = true;
5125  }
5126  else
5127  {
5128  if (_displaced_problem == nullptr && parameters.get<bool>("use_displaced_mesh"))
5129  {
5130  // We allow Transfers to request that they use_displaced_mesh,
5131  // but then be overridden when no displacements variables are
5132  // provided in the Mesh block. If that happened, update the value
5133  // of use_displaced_mesh appropriately for this Transfer.
5134  if (parameters.have_parameter<bool>("use_displaced_mesh"))
5135  parameters.set<bool>("use_displaced_mesh") = false;
5136  }
5137 
5138  parameters.set<SubProblem *>("_subproblem") = this;
5139  parameters.set<SystemBase *>("_sys") = _aux.get();
5140  }
5141 
5142  // Handle the "SAME_AS_MULTIAPP" execute option. The get method is used to test for the
5143  // flag so the set by user flag is not reset, calling set with the true flag causes the set
5144  // by user status to be reset, which should only be done if the EXEC_SAME_AS_MULTIAPP is
5145  // being applied to the object.
5147  {
5148  ExecFlagEnum & exec_enum = parameters.set<ExecFlagEnum>("execute_on", true);
5149  std::shared_ptr<MultiApp> multiapp;
5150  if (parameters.isParamValid("multi_app"))
5151  multiapp = getMultiApp(parameters.get<MultiAppName>("multi_app"));
5152  else if (parameters.isParamValid("from_multi_app"))
5153  multiapp = getMultiApp(parameters.get<MultiAppName>("from_multi_app"));
5154  else if (parameters.isParamValid("to_multi_app"))
5155  multiapp = getMultiApp(parameters.get<MultiAppName>("to_multi_app"));
5156  // else do nothing because the user has provided invalid input. They should get a nice error
5157  // about this during transfer construction. This necessitates checking for null in this next
5158  // line, however
5159  if (multiapp)
5160  exec_enum = multiapp->getParam<ExecFlagEnum>("execute_on");
5161  }
5162 
5163  // Create the Transfer objects
5164  std::shared_ptr<Transfer> transfer = _factory.create<Transfer>(transfer_name, name, parameters);
5165  logAdd("Transfer", name, transfer_name);
5166 
5167  // Add MultiAppTransfer object
5168  std::shared_ptr<MultiAppTransfer> multi_app_transfer =
5170  if (multi_app_transfer)
5171  {
5172  if (multi_app_transfer->directions().contains(MultiAppTransfer::TO_MULTIAPP))
5173  _to_multi_app_transfers.addObject(multi_app_transfer);
5174  if (multi_app_transfer->directions().contains(MultiAppTransfer::FROM_MULTIAPP))
5175  _from_multi_app_transfers.addObject(multi_app_transfer);
5176  if (multi_app_transfer->directions().contains(MultiAppTransfer::BETWEEN_MULTIAPP))
5177  _between_multi_app_transfers.addObject(multi_app_transfer);
5178  }
5179  else
5180  _transfers.addObject(transfer);
5181 }
5182 
5183 bool
5184 FEProblemBase::hasVariable(const std::string & var_name) const
5185 {
5186  for (auto & nl : _nl)
5187  if (nl->hasVariable(var_name))
5188  return true;
5189  if (_aux->hasVariable(var_name))
5190  return true;
5191 
5192  return false;
5193 }
5194 
5195 const MooseVariableFieldBase &
5197  const std::string & var_name,
5198  Moose::VarKindType expected_var_type,
5199  Moose::VarFieldType expected_var_field_type) const
5200 {
5201  return getVariableHelper(tid, var_name, expected_var_type, expected_var_field_type, _nl, *_aux);
5202 }
5203 
5204 MooseVariable &
5205 FEProblemBase::getStandardVariable(const THREAD_ID tid, const std::string & var_name)
5206 {
5207  for (auto & nl : _nl)
5208  if (nl->hasVariable(var_name))
5209  return nl->getFieldVariable<Real>(tid, var_name);
5210  if (_aux->hasVariable(var_name))
5211  return _aux->getFieldVariable<Real>(tid, var_name);
5212 
5213  mooseError("Unknown variable " + var_name);
5214 }
5215 
5217 FEProblemBase::getActualFieldVariable(const THREAD_ID tid, const std::string & var_name)
5218 {
5219  for (auto & nl : _nl)
5220  if (nl->hasVariable(var_name))
5221  return nl->getActualFieldVariable<Real>(tid, var_name);
5222  if (_aux->hasVariable(var_name))
5223  return _aux->getActualFieldVariable<Real>(tid, var_name);
5224 
5225  mooseError("Unknown variable " + var_name);
5226 }
5227 
5229 FEProblemBase::getVectorVariable(const THREAD_ID tid, const std::string & var_name)
5230 {
5231  for (auto & nl : _nl)
5232  if (nl->hasVariable(var_name))
5233  return nl->getFieldVariable<RealVectorValue>(tid, var_name);
5234  if (_aux->hasVariable(var_name))
5235  return _aux->getFieldVariable<RealVectorValue>(tid, var_name);
5236 
5237  mooseError("Unknown variable " + var_name);
5238 }
5239 
5241 FEProblemBase::getArrayVariable(const THREAD_ID tid, const std::string & var_name)
5242 {
5243  for (auto & nl : _nl)
5244  if (nl->hasVariable(var_name))
5245  return nl->getFieldVariable<RealEigenVector>(tid, var_name);
5246  if (_aux->hasVariable(var_name))
5247  return _aux->getFieldVariable<RealEigenVector>(tid, var_name);
5248 
5249  mooseError("Unknown variable " + var_name);
5250 }
5251 
5252 bool
5253 FEProblemBase::hasScalarVariable(const std::string & var_name) const
5254 {
5255  for (auto & nl : _nl)
5256  if (nl->hasScalarVariable(var_name))
5257  return true;
5258  if (_aux->hasScalarVariable(var_name))
5259  return true;
5260 
5261  return false;
5262 }
5263 
5265 FEProblemBase::getScalarVariable(const THREAD_ID tid, const std::string & var_name)
5266 {
5267  for (auto & nl : _nl)
5268  if (nl->hasScalarVariable(var_name))
5269  return nl->getScalarVariable(tid, var_name);
5270  if (_aux->hasScalarVariable(var_name))
5271  return _aux->getScalarVariable(tid, var_name);
5272 
5273  mooseError("Unknown variable " + var_name);
5274 }
5275 
5276 System &
5277 FEProblemBase::getSystem(const std::string & var_name)
5278 {
5279  const auto [var_in_nl, nl_sys_num] = determineNonlinearSystem(var_name);
5280  if (var_in_nl)
5281  return _nl[nl_sys_num]->system();
5282  else if (_aux->hasVariable(var_name))
5283  return _aux->system();
5284  else
5285  mooseError("Unable to find a system containing the variable " + var_name);
5286 }
5287 
5288 void
5290 {
5292 
5293  if (_displaced_problem)
5294  _displaced_problem->setActiveFEVariableCoupleableMatrixTags(mtags, tid);
5295 }
5296 
5297 void
5299 {
5301 
5302  if (_displaced_problem)
5303  _displaced_problem->setActiveFEVariableCoupleableVectorTags(vtags, tid);
5304 }
5305 
5306 void
5308  const THREAD_ID tid)
5309 {
5311 
5312  if (_displaced_problem)
5313  _displaced_problem->setActiveScalarVariableCoupleableMatrixTags(mtags, tid);
5314 }
5315 
5316 void
5318  const THREAD_ID tid)
5319 {
5321 
5322  if (_displaced_problem)
5323  _displaced_problem->setActiveScalarVariableCoupleableVectorTags(vtags, tid);
5324 }
5325 
5326 void
5327 FEProblemBase::setActiveElementalMooseVariables(const std::set<MooseVariableFEBase *> & moose_vars,
5328  const THREAD_ID tid)
5329 {
5331 
5332  if (_displaced_problem)
5333  _displaced_problem->setActiveElementalMooseVariables(moose_vars, tid);
5334 }
5335 
5336 void
5338 {
5340 
5341  if (_displaced_problem)
5342  _displaced_problem->clearActiveElementalMooseVariables(tid);
5343 }
5344 
5345 void
5347 {
5349 
5350  if (_displaced_problem)
5351  _displaced_problem->clearActiveFEVariableCoupleableMatrixTags(tid);
5352 }
5353 
5354 void
5356 {
5358 
5359  if (_displaced_problem)
5360  _displaced_problem->clearActiveFEVariableCoupleableVectorTags(tid);
5361 }
5362 
5363 void
5365 {
5367 
5368  if (_displaced_problem)
5369  _displaced_problem->clearActiveScalarVariableCoupleableMatrixTags(tid);
5370 }
5371 
5372 void
5374 {
5376 
5377  if (_displaced_problem)
5378  _displaced_problem->clearActiveScalarVariableCoupleableVectorTags(tid);
5379 }
5380 
5381 void
5382 FEProblemBase::setActiveMaterialProperties(const std::unordered_set<unsigned int> & mat_prop_ids,
5383  const THREAD_ID tid)
5384 {
5385  // mark active properties in every material
5386  for (auto & mat : _all_materials.getObjects(tid))
5387  mat->setActiveProperties(mat_prop_ids);
5388  for (auto & mat : _all_materials[Moose::FACE_MATERIAL_DATA].getObjects(tid))
5389  mat->setActiveProperties(mat_prop_ids);
5390  for (auto & mat : _all_materials[Moose::NEIGHBOR_MATERIAL_DATA].getObjects(tid))
5391  mat->setActiveProperties(mat_prop_ids);
5392 
5393  _has_active_material_properties[tid] = !mat_prop_ids.empty();
5394 }
5395 
5396 bool
5398 {
5399  return _has_active_material_properties[tid];
5400 }
5401 
5402 void
5404 {
5406 }
5407 
5408 void
5410 {
5411 #ifdef LIBMESH_ENABLE_AMR
5412  if ((_adaptivity.isOn() || _num_grid_steps) &&
5415  {
5416  // Even on a serialized Mesh, we don't keep our material
5417  // properties serialized, so we'll rely on the callback to
5418  // redistribute() to redistribute properties at the same time
5419  // libMesh is redistributing elements.
5420  auto add_redistributer = [this](MooseMesh & mesh,
5421  const std::string & redistributer_name,
5422  const bool use_displaced_mesh)
5423  {
5424  InputParameters redistribute_params = RedistributeProperties::validParams();
5425  redistribute_params.set<MooseApp *>("_moose_app") = &_app;
5426  redistribute_params.set<std::string>("for_whom") = this->name();
5427  redistribute_params.set<MooseMesh *>("mesh") = &mesh;
5428  redistribute_params.set<Moose::RelationshipManagerType>("rm_type") =
5430  redistribute_params.set<bool>("use_displaced_mesh") = use_displaced_mesh;
5431  redistribute_params.setHitNode(*parameters().getHitNode(), {});
5432 
5433  std::shared_ptr<RedistributeProperties> redistributer =
5435  "RedistributeProperties", redistributer_name, redistribute_params);
5436 
5439 
5441  redistributer->addMaterialPropertyStorage(_bnd_material_props);
5442 
5444  redistributer->addMaterialPropertyStorage(_neighbor_material_props);
5445 
5446  mesh.getMesh().add_ghosting_functor(redistributer);
5447  };
5448 
5449  add_redistributer(_mesh, "mesh_property_redistributer", false);
5450  if (_displaced_problem)
5451  add_redistributer(_displaced_problem->mesh(), "displaced_mesh_property_redistributer", true);
5452  }
5453 #endif // LIBMESH_ENABLE_AMR
5454 }
5455 
5456 void
5458 {
5459  // Find the maximum number of quadrature points
5460  {
5461  MaxQpsThread mqt(*this);
5462  Threads::parallel_reduce(*_mesh.getActiveLocalElementRange(), mqt);
5463  _max_qps = mqt.max();
5464 
5465  // If we have more shape functions or more quadrature points on
5466  // another processor, then we may need to handle those elements
5467  // ourselves later after repartitioning.
5469  }
5470 
5471  unsigned int max_qpts = getMaxQps();
5472  if (max_qpts > Moose::constMaxQpsPerElem)
5473  mooseError("Max quadrature points per element assumptions made in some code (e.g. Coupleable ",
5474  "and MaterialPropertyInterface classes) have been violated.\n",
5475  "Complain to Moose developers to have constMaxQpsPerElem increased from ",
5477  " to ",
5478  max_qpts);
5479  for (unsigned int tid = 0; tid < libMesh::n_threads(); ++tid)
5480  {
5481  // the highest available order in libMesh is 43
5482  _scalar_zero[tid].resize(FORTYTHIRD, 0);
5483  _zero[tid].resize(max_qpts, 0);
5484  _ad_zero[tid].resize(max_qpts, 0);
5485  _grad_zero[tid].resize(max_qpts, RealGradient(0.));
5486  _ad_grad_zero[tid].resize(max_qpts, ADRealGradient(0));
5487  _second_zero[tid].resize(max_qpts, RealTensor(0.));
5488  _ad_second_zero[tid].resize(max_qpts, ADRealTensorValue(0));
5489  _vector_zero[tid].resize(max_qpts, RealGradient(0.));
5490  _vector_curl_zero[tid].resize(max_qpts, RealGradient(0.));
5491  }
5492 }
5493 
5494 void
5496 {
5497  for (unsigned int tid = 0; tid < libMesh::n_threads(); ++tid)
5498  for (const auto i : index_range(_nl))
5499  _assembly[tid][i]->bumpVolumeQRuleOrder(order, block);
5500 
5501  if (_displaced_problem)
5502  _displaced_problem->bumpVolumeQRuleOrder(order, block);
5503 
5504  updateMaxQps();
5505 }
5506 
5507 void
5509 {
5510  for (unsigned int tid = 0; tid < libMesh::n_threads(); ++tid)
5511  for (const auto i : index_range(_nl))
5512  _assembly[tid][i]->bumpAllQRuleOrder(order, block);
5513 
5514  if (_displaced_problem)
5515  _displaced_problem->bumpAllQRuleOrder(order, block);
5516 
5517  updateMaxQps();
5518 }
5519 
5520 void
5522  Order order,
5523  Order volume_order,
5524  Order face_order,
5525  SubdomainID block,
5526  const bool allow_negative_qweights)
5527 {
5528  if (order == INVALID_ORDER)
5529  {
5530  // automatically determine the integration order
5531  order = _nl[0]->getMinQuadratureOrder();
5532  for (const auto i : make_range(std::size_t(1), _nl.size()))
5533  if (order < _nl[i]->getMinQuadratureOrder())
5534  order = _nl[i]->getMinQuadratureOrder();
5535  if (order < _aux->getMinQuadratureOrder())
5536  order = _aux->getMinQuadratureOrder();
5537  }
5538 
5539  if (volume_order == INVALID_ORDER)
5540  volume_order = order;
5541 
5542  if (face_order == INVALID_ORDER)
5543  face_order = order;
5544 
5545  for (unsigned int tid = 0; tid < libMesh::n_threads(); ++tid)
5546  for (const auto i : index_range(_nl))
5547  _assembly[tid][i]->createQRules(
5548  type, order, volume_order, face_order, block, allow_negative_qweights);
5549 
5550  if (_displaced_problem)
5551  _displaced_problem->createQRules(
5552  type, order, volume_order, face_order, block, allow_negative_qweights);
5553 
5554  updateMaxQps();
5555 }
5556 
5557 void
5559 {
5561  {
5563  mooseError("Someone told us (the FEProblemBase) to trust the user coupling matrix, but we "
5564  "haven't been provided a coupling matrix!");
5565 
5566  // We've been told to trust the user coupling matrix, so we're going to leave things alone
5567  return;
5568  }
5569 
5570  _coupling = type;
5571 }
5572 
5573 void
5574 FEProblemBase::setCouplingMatrix(CouplingMatrix * cm, const unsigned int i)
5575 {
5576  // TODO: Deprecate method
5578  _cm[i].reset(cm);
5579 }
5580 
5581 void
5582 FEProblemBase::setCouplingMatrix(std::unique_ptr<CouplingMatrix> cm, const unsigned int i)
5583 {
5585  _cm[i] = std::move(cm);
5586 }
5587 
5588 void
5590 {
5592  mooseError("Someone told us (the FEProblemBase) to trust the user coupling matrix, but we "
5593  "haven't been provided a coupling matrix!");
5594 
5596 }
5597 
5598 void
5600 {
5601  TIME_SECTION("setNonlocalCouplingMatrix", 5, "Setting Nonlocal Coupling Matrix");
5602 
5603  if (_nl.size() > 1)
5604  mooseError("Nonlocal kernels are weirdly stored on the FEProblem so we don't currently support "
5605  "multiple nonlinear systems with nonlocal kernels.");
5606 
5607  for (const auto nl_sys_num : index_range(_nl))
5608  {
5609  auto & nl = _nl[nl_sys_num];
5610  auto & nonlocal_cm = _nonlocal_cm[nl_sys_num];
5611  unsigned int n_vars = nl->nVariables();
5612  nonlocal_cm.resize(n_vars);
5613  const auto & vars = nl->getVariables(0);
5614  const auto & nonlocal_kernel = _nonlocal_kernels.getObjects();
5615  const auto & nonlocal_integrated_bc = _nonlocal_integrated_bcs.getObjects();
5616  for (const auto & ivar : vars)
5617  {
5618  for (const auto & kernel : nonlocal_kernel)
5619  {
5620  for (unsigned int i = ivar->number(); i < ivar->number() + ivar->count(); ++i)
5621  if (i == kernel->variable().number())
5622  for (const auto & jvar : vars)
5623  {
5624  const auto it = _var_dof_map.find(jvar->name());
5625  if (it != _var_dof_map.end())
5626  {
5627  unsigned int j = jvar->number();
5628  nonlocal_cm(i, j) = 1;
5629  }
5630  }
5631  }
5632  for (const auto & integrated_bc : nonlocal_integrated_bc)
5633  {
5634  for (unsigned int i = ivar->number(); i < ivar->number() + ivar->count(); ++i)
5635  if (i == integrated_bc->variable().number())
5636  for (const auto & jvar : vars)
5637  {
5638  const auto it = _var_dof_map.find(jvar->name());
5639  if (it != _var_dof_map.end())
5640  {
5641  unsigned int j = jvar->number();
5642  nonlocal_cm(i, j) = 1;
5643  }
5644  }
5645  }
5646  }
5647  }
5648 }
5649 
5650 bool
5651 FEProblemBase::areCoupled(const unsigned int ivar,
5652  const unsigned int jvar,
5653  const unsigned int nl_sys) const
5654 {
5655  return (*_cm[nl_sys])(ivar, jvar);
5656 }
5657 
5658 std::vector<std::pair<MooseVariableFEBase *, MooseVariableFEBase *>> &
5659 FEProblemBase::couplingEntries(const THREAD_ID tid, const unsigned int nl_sys)
5660 {
5661  return _assembly[tid][nl_sys]->couplingEntries();
5662 }
5663 
5664 std::vector<std::pair<MooseVariableFEBase *, MooseVariableFEBase *>> &
5665 FEProblemBase::nonlocalCouplingEntries(const THREAD_ID tid, const unsigned int nl_sys)
5666 {
5667  return _assembly[tid][nl_sys]->nonlocalCouplingEntries();
5668 }
5669 
5670 void
5672 {
5673  if (_initialized)
5674  return;
5675 
5676  TIME_SECTION("init", 2, "Initializing");
5677 
5678  // call executioner's preProblemInit so that it can do some setups before problem init
5680 
5681  // If we have AD and we are doing global AD indexing, then we should by default set the matrix
5682  // coupling to full. If the user has told us to trust their coupling matrix, then this call will
5683  // not do anything
5686 
5687  for (const auto i : index_range(_nl))
5688  {
5689  auto & nl = _nl[i];
5690  auto & cm = _cm[i];
5691 
5692  unsigned int n_vars = nl->nVariables();
5693  {
5694  TIME_SECTION("fillCouplingMatrix", 3, "Filling Coupling Matrix");
5695 
5696  switch (_coupling)
5697  {
5698  case Moose::COUPLING_DIAG:
5699  cm = std::make_unique<CouplingMatrix>(n_vars);
5700  for (unsigned int i = 0; i < n_vars; i++)
5701  (*cm)(i, i) = 1;
5702  break;
5703 
5704  // for full jacobian
5705  case Moose::COUPLING_FULL:
5706  cm = std::make_unique<CouplingMatrix>(n_vars);
5707  for (unsigned int i = 0; i < n_vars; i++)
5708  for (unsigned int j = 0; j < n_vars; j++)
5709  (*cm)(i, j) = 1;
5710  break;
5711 
5713  // do nothing, _cm was already set through couplingMatrix() call
5714  break;
5715  }
5716  }
5717 
5718  nl->dofMap()._dof_coupling = cm.get();
5719 
5720  // If there are no variables, make sure to pass a nullptr coupling
5721  // matrix, to avoid warnings about non-nullptr yet empty
5722  // CouplingMatrices.
5723  if (n_vars == 0)
5724  nl->dofMap()._dof_coupling = nullptr;
5725 
5726  nl->dofMap().attach_extra_sparsity_function(&extraSparsity, nl.get());
5727  nl->dofMap().attach_extra_send_list_function(&extraSendList, nl.get());
5728  _aux->dofMap().attach_extra_send_list_function(&extraSendList, _aux.get());
5729 
5730  if (!_skip_nl_system_check && _solve && n_vars == 0)
5731  mooseError("No variables specified in the FEProblemBase '", name(), "'.");
5732  }
5733 
5734  ghostGhostedBoundaries(); // We do this again right here in case new boundaries have been added
5735 
5736  // We may have added element/nodes to the mesh in ghostGhostedBoundaries so we need to update
5737  // all of our mesh information. We need to make sure that mesh information is up-to-date before
5738  // EquationSystems::init because that will call through to updateGeomSearch (for sparsity
5739  // augmentation) and if we haven't added back boundary node information before that latter call,
5740  // then we're screwed. We'll get things like "Unable to find closest node!"
5741  _mesh.meshChanged();
5742  if (_displaced_problem)
5744 
5745  // do not assemble system matrix for JFNK solve
5746  for (auto & nl : _nl)
5747  {
5749  nl->turnOffJacobian();
5750  nl->init();
5751  }
5752  _aux->init();
5753 
5754  // Build the mortar segment meshes, if they haven't been already, for a couple reasons:
5755  // 1) Get the ghosting correct for both static and dynamic meshes
5756  // 2) Make sure the mortar mesh is built for mortar constraints that live on the static mesh
5757  //
5758  // It is worth-while to note that mortar meshes that live on a dynamic mesh will be built
5759  // during residual and Jacobian evaluation because when displacements are solution variables
5760  // the mortar mesh will move and change during the course of a non-linear solve. We DO NOT
5761  // redo ghosting during non-linear solve, so for purpose 1) the below call has to be made
5762  if (!_mortar_data.initialized())
5763  updateMortarMesh();
5764 
5765  {
5766  TIME_SECTION("EquationSystems::Init", 2, "Initializing Equation Systems");
5767  es().init();
5768  }
5769 
5770  // Now that the equation system and the dof distribution is done, we can generate the
5771  // finite volume-related parts if needed.
5772  if (haveFV())
5774 
5775  for (auto & nl : _nl)
5776  nl->update();
5777  _aux->update();
5778 
5779  for (THREAD_ID tid = 0; tid < libMesh::n_threads(); ++tid)
5780  for (const auto i : index_range(_nl))
5781  _assembly[tid][i]->init(_cm[i].get());
5782 
5783  if (_displaced_problem)
5784  _displaced_problem->init();
5785 
5786  _initialized = true;
5787 }
5788 
5789 unsigned int
5790 FEProblemBase::nlSysNum(const NonlinearSystemName & nl_sys_name) const
5791 {
5792  std::istringstream ss(nl_sys_name);
5793  unsigned int nl_sys_num;
5794  if (!(ss >> nl_sys_num) || !ss.eof())
5795  nl_sys_num = libmesh_map_find(_nl_sys_name_to_num, nl_sys_name);
5796 
5797  return nl_sys_num;
5798 }
5799 
5800 void
5801 FEProblemBase::solve(const unsigned int nl_sys_num)
5802 {
5803  TIME_SECTION("solve", 1, "Solving", false);
5804 
5805  setCurrentNonlinearSystem(nl_sys_num);
5806 
5807  // This prevents stale dof indices from lingering around and possibly leading to invalid reads
5808  // and writes. Dof indices may be made stale through operations like mesh adaptivity
5810  if (_displaced_problem)
5811  _displaced_problem->clearAllDofIndices();
5812 
5813 #if PETSC_RELEASE_LESS_THAN(3, 12, 0)
5815  _petsc_options, _solver_params); // Make sure the PETSc options are setup for this app
5816 #else
5817  // Now this database will be the default
5818  // Each app should have only one database
5819  if (!_app.isUltimateMaster())
5820  PetscOptionsPush(_petsc_option_data_base);
5821  // We did not add PETSc options to database yet
5823  {
5826  }
5827 #endif
5828 
5829  // set up DM which is required if use a field split preconditioner
5830  // We need to setup DM every "solve()" because libMesh destroy SNES after solve()
5831  // Do not worry, DM setup is very cheap
5833 
5834  // Setup the output system for printing linear/nonlinear iteration information and some solver
5835  // settings
5837 
5839 
5840  // reset flag so that residual evaluation does not get skipped
5841  // and the next non-linear iteration does not automatically fail with
5842  // "DIVERGED_NANORINF", when we throw an exception and stop solve
5844 
5845  if (_solve)
5847 
5848  if (_solve)
5850 
5851  // sync solutions in displaced problem
5852  if (_displaced_problem)
5853  _displaced_problem->syncSolutions();
5854 
5855 #if !PETSC_RELEASE_LESS_THAN(3, 12, 0)
5856  if (!_app.isUltimateMaster())
5857  PetscOptionsPop();
5858 #endif
5859 }
5860 
5861 void
5862 FEProblemBase::setException(const std::string & message)
5863 {
5864  _has_exception = true;
5865  _exception_message = message;
5866 }
5867 
5868 void
5870 {
5872  return;
5873 
5874  TIME_SECTION("checkExceptionAndStopSolve", 5);
5875 
5876  // See if any processor had an exception. If it did, get back the
5877  // processor that the exception occurred on.
5878  unsigned int processor_id;
5879 
5881 
5882  if (_has_exception)
5883  {
5885 
5888  {
5889  // Print the message
5890  if (_communicator.rank() == 0 && print_message)
5891  {
5892  _console << "\n" << _exception_message << "\n";
5893  if (isTransient())
5894  _console
5895  << "To recover, the solution will fail and then be re-attempted with a reduced time "
5896  "step.\n"
5897  << std::endl;
5898  }
5899 
5900  // Stop the solve -- this entails setting
5901  // SNESSetFunctionDomainError() or directly inserting NaNs in the
5902  // residual vector to let PETSc >= 3.6 return DIVERGED_NANORINF.
5904 
5905  // and close Aux system (we MUST do this here; see #11525)
5906  _aux->solution().close();
5907 
5908  // We've handled this exception, so we no longer have one.
5909  _has_exception = false;
5910 
5911  // Force the next non-linear convergence check to fail (and all further residual evaluation
5912  // to be skipped).
5914 
5915  // Repropagate the exception, so it can be caught at a higher level, typically
5916  // this is NonlinearSystem::computeResidual().
5918  }
5919  else
5920  mooseError("The following parallel-communicated exception was detected during " +
5921  Moose::stringify(_current_execute_on_flag) + " evaluation:\n" +
5923  "\nBecause this did not occur during residual evaluation, there"
5924  " is no way to handle this, so the solution is aborting.\n");
5925  }
5926 }
5927 
5928 void
5930 {
5931  // Our default state is to allow computing derivatives
5932  ADReal::do_derivatives = true;
5934 
5937 
5940 
5944  if (_displaced_problem)
5945  {
5946  _displaced_problem->setCurrentlyComputingResidual(false);
5947  _displaced_problem->setCurrentlyComputingJacobian(false);
5948  _displaced_problem->setCurrentlyComputingResidualAndJacobian(false);
5949  }
5950 }
5951 
5952 bool
5953 FEProblemBase::nlConverged(const unsigned int nl_sys_num)
5954 {
5955  if (_solve)
5956  return _nl[nl_sys_num]->converged();
5957  else
5958  return true;
5959 }
5960 
5961 unsigned int
5962 FEProblemBase::nNonlinearIterations(const unsigned int nl_sys_num) const
5963 {
5964  return _nl[nl_sys_num]->nNonlinearIterations();
5965 }
5966 
5967 unsigned int
5968 FEProblemBase::nLinearIterations(const unsigned int nl_sys_num) const
5969 {
5970  return _nl[nl_sys_num]->nLinearIterations();
5971 }
5972 
5973 Real
5974 FEProblemBase::finalNonlinearResidual(const unsigned int nl_sys_num) const
5975 {
5976  return _nl[nl_sys_num]->finalNonlinearResidual();
5977 }
5978 
5979 bool
5980 FEProblemBase::computingInitialResidual(const unsigned int nl_sys_num) const
5981 {
5982  return _nl[nl_sys_num]->computingInitialResidual();
5983 }
5984 
5985 void
5987 {
5988  TIME_SECTION("copySolutionsBackwards", 3, "Copying Solutions Backward");
5989 
5990  for (auto & nl : _nl)
5991  nl->copySolutionsBackwards();
5992  _aux->copySolutionsBackwards();
5993 }
5994 
5995 void
5997 {
5998  TIME_SECTION("advanceState", 5, "Advancing State");
5999 
6000  for (auto & nl : _nl)
6001  nl->copyOldSolutions();
6002  _aux->copyOldSolutions();
6003 
6004  if (_displaced_problem)
6005  {
6006  for (const auto i : index_range(_nl))
6007  _displaced_problem->nlSys(i).copyOldSolutions();
6008  _displaced_problem->auxSys().copyOldSolutions();
6009  }
6010 
6012 
6015 
6018 
6021 }
6022 
6023 void
6025 {
6026  TIME_SECTION("restoreSolutions", 5, "Restoring Solutions");
6027 
6028  for (auto & nl : _nl)
6029  nl->restoreSolutions();
6030  _aux->restoreSolutions();
6031 
6032  if (_displaced_problem)
6033  _displaced_problem->updateMesh();
6034 }
6035 
6036 void
6038 {
6039  TIME_SECTION("saveOldSolutions", 5, "Saving Old Solutions");
6040 
6041  for (auto & nl : _nl)
6042  nl->saveOldSolutions();
6043  _aux->saveOldSolutions();
6044 }
6045 
6046 void
6048 {
6049  TIME_SECTION("restoreOldSolutions", 5, "Restoring Old Solutions");
6050 
6051  for (auto & nl : _nl)
6052  nl->restoreOldSolutions();
6053  _aux->restoreOldSolutions();
6054 }
6055 
6056 void
6058 {
6059  TIME_SECTION("outputStep", 1, "Outputting");
6060 
6062 
6063  for (auto & nl : _nl)
6064  nl->update();
6065  _aux->update();
6066  if (_displaced_problem)
6067  _displaced_problem->syncSolutions();
6069 
6071 }
6072 
6073 void
6075 {
6077 }
6078 
6079 void
6081 {
6083 }
6084 
6085 void
6087 {
6090 }
6091 
6092 void
6094 {
6095  TIME_SECTION("onTimestepBegin", 2);
6096 
6097  for (auto & nl : _nl)
6098  nl->onTimestepBegin();
6099 }
6100 
6101 void
6103 {
6104 }
6105 
6106 Real
6108 {
6110  // If we are any iteration type other than time (e.g. nonlinear), then temporally we are still
6111  // in the present time
6112  return time();
6113 
6114  switch (state.state)
6115  {
6116  case 0:
6117  return time();
6118 
6119  case 1:
6120  return timeOld();
6121 
6122  default:
6123  mooseError("Unhandled state ", state.state, " in FEProblemBase::getTimeFromStateArg");
6124  }
6125 }
6126 
6127 void
6128 FEProblemBase::addTimeIntegrator(const std::string & type,
6129  const std::string & name,
6130  InputParameters & parameters)
6131 {
6132  parallel_object_only();
6133 
6134  parameters.set<SubProblem *>("_subproblem") = this;
6135  logAdd("TimeIntegrator", name, type);
6136  _aux->addTimeIntegrator(type, name + ":aux", parameters);
6137  for (auto & nl : _nl)
6138  nl->addTimeIntegrator(type, name + ":" + nl->name(), parameters);
6139  _has_time_integrator = true;
6140 
6141  // add vectors to store u_dot, u_dotdot, udot_old, u_dotdot_old and
6142  // solution vectors older than 2 time steps, if requested by the time
6143  // integrator
6144  _aux->addDotVectors();
6145  for (auto & nl : _nl)
6146  {
6147  nl->addDotVectors();
6148 
6149  auto tag_udot = nl->getTimeIntegrator()->uDotFactorTag();
6150  if (!nl->hasVector(tag_udot))
6151  nl->associateVectorToTag(*nl->solutionUDot(), tag_udot);
6152  auto tag_udotdot = nl->getTimeIntegrator()->uDotDotFactorTag();
6153  if (!nl->hasVector(tag_udotdot) && uDotDotRequested())
6154  nl->associateVectorToTag(*nl->solutionUDotDot(), tag_udotdot);
6155  }
6156 }
6157 
6158 void
6159 FEProblemBase::addPredictor(const std::string & type,
6160  const std::string & name,
6161  InputParameters & parameters)
6162 {
6163  parallel_object_only();
6164 
6165  parameters.set<SubProblem *>("_subproblem") = this;
6166  std::shared_ptr<Predictor> predictor = _factory.create<Predictor>(type, name, parameters);
6167  logAdd("Predictor", name, type);
6168 
6169  for (auto & nl : _nl)
6170  nl->setPredictor(predictor);
6171 }
6172 
6173 Real
6175 {
6176  TIME_SECTION("computeResidualL2Norm", 2, "Computing L2 Norm of Residual");
6177 
6178  if (_nl.size() > 1)
6179  mooseError("Multiple nonlinear systems in the same input are not currently supported when "
6180  "performing fixed point iterations in multi-app contexts");
6181 
6182  _current_nl_sys = _nl[0].get();
6183  computeResidual(*_nl[0]->currentSolution(), _nl[0]->RHS(), /*nl_sys=*/0);
6184 
6185  return _nl[0]->RHS().l2_norm();
6186 }
6187 
6188 void
6189 FEProblemBase::computeResidualSys(NonlinearImplicitSystem & sys,
6190  const NumericVector<Number> & soln,
6191  NumericVector<Number> & residual)
6192 {
6193  parallel_object_only();
6194 
6195  TIME_SECTION("computeResidualSys", 5);
6196 
6197  computeResidual(soln, residual, sys.number());
6198 }
6199 
6200 void
6201 FEProblemBase::computeResidual(NonlinearImplicitSystem & sys,
6202  const NumericVector<Number> & soln,
6203  NumericVector<Number> & residual)
6204 {
6205  mooseDeprecated("Please use computeResidualSys");
6206 
6207  computeResidualSys(sys, soln, residual);
6208 }
6209 
6210 void
6212  NumericVector<Number> & residual,
6213  const unsigned int nl_sys_num)
6214 {
6215  setCurrentNonlinearSystem(nl_sys_num);
6216 
6217  // We associate the residual tag with the given residual vector to make sure we
6218  // don't filter it out below
6220  const auto & residual_vector_tags = getVectorTags(Moose::VECTOR_TAG_RESIDUAL);
6221 
6222  // We filter out tags which do not have associated vectors in the current nonlinear
6223  // system. This is essential to be able to use system-dependent residual tags.
6225 
6226  computeResidualInternal(soln, residual, _fe_vector_tags);
6227 }
6228 
6229 void
6231  NumericVector<Number> & residual,
6232  SparseMatrix<Number> & jacobian)
6233 {
6234  try
6235  {
6236  try
6237  {
6238  // vector tags
6239  {
6241  const auto & residual_vector_tags = getVectorTags(Moose::VECTOR_TAG_RESIDUAL);
6242 
6243  // We filter out tags which do not have associated vectors in the current nonlinear
6244  // system. This is essential to be able to use system-dependent residual tags.
6246 
6248  }
6249 
6250  // matrix tags
6251  {
6252  _fe_matrix_tags.clear();
6253 
6254  auto & tags = getMatrixTags();
6255  for (auto & tag : tags)
6256  _fe_matrix_tags.insert(tag.second);
6257  }
6258 
6260 
6263 
6264  for (const auto tag : _fe_matrix_tags)
6265  if (_current_nl_sys->hasMatrix(tag))
6266  {
6267  auto & matrix = _current_nl_sys->getMatrix(tag);
6268  matrix.zero();
6269  if (haveADObjects())
6270  // PETSc algorithms require diagonal allocations regardless of whether there is non-zero
6271  // diagonal dependence. With global AD indexing we only add non-zero
6272  // dependence, so PETSc will scream at us unless we artificially add the diagonals.
6273  for (auto index : make_range(matrix.row_start(), matrix.row_stop()))
6274  matrix.add(index, index, 0);
6275  }
6276 
6277  _aux->zeroVariablesForResidual();
6278 
6279  unsigned int n_threads = libMesh::n_threads();
6280 
6282 
6283  // Random interface objects
6284  for (const auto & it : _random_data_objects)
6285  it.second->updateSeeds(EXEC_LINEAR);
6286 
6290  if (_displaced_problem)
6291  {
6292  _displaced_problem->setCurrentlyComputingResidual(true);
6293  _displaced_problem->setCurrentlyComputingJacobian(true);
6294  _displaced_problem->setCurrentlyComputingResidualAndJacobian(true);
6295  }
6296 
6298 
6300 
6301  for (unsigned int tid = 0; tid < n_threads; tid++)
6302  reinitScalars(tid);
6303 
6305 
6306  _aux->residualSetup();
6307 
6308  if (_displaced_problem)
6309  {
6310  _aux->compute(EXEC_PRE_DISPLACE);
6311  _displaced_problem->updateMesh();
6313  updateMortarMesh();
6314  }
6315 
6316  for (THREAD_ID tid = 0; tid < n_threads; tid++)
6317  {
6320  }
6321 
6322  // Where is the aux system done? Could the non-current nonlinear systems also be done there?
6323  for (auto & nl : _nl)
6324  nl->computeTimeDerivatives();
6325 
6326  _aux->compute(EXEC_LINEAR);
6327 
6329 
6331 
6333 
6336 
6338 
6341  }
6342  catch (...)
6343  {
6344  handleException("computeResidualAndJacobian");
6345  }
6346  }
6347  catch (const MooseException &)
6348  {
6349  // The buck stops here, we have already handled the exception by
6350  // calling the system's stopSolve() method, it is now up to PETSc to return a
6351  // "diverged" reason during the next solve.
6352  }
6353  catch (...)
6354  {
6355  mooseError("Unexpected exception type");
6356  }
6357 
6358  resetState();
6359 }
6360 
6361 void
6363  NumericVector<Number> & residual,
6364  TagID tag)
6365 {
6366  try
6367  {
6369 
6370  _current_nl_sys->associateVectorToTag(residual, tag);
6371 
6372  computeResidualTags({tag});
6373 
6375  }
6376  catch (MooseException & e)
6377  {
6378  // If a MooseException propagates all the way to here, it means
6379  // that it was thrown from a MOOSE system where we do not
6380  // (currently) properly support the throwing of exceptions, and
6381  // therefore we have no choice but to error out. It may be
6382  // *possible* to handle exceptions from other systems, but in the
6383  // meantime, we don't want to silently swallow any unhandled
6384  // exceptions here.
6385  mooseError("An unhandled MooseException was raised during residual computation. Please "
6386  "contact the MOOSE team for assistance.");
6387  }
6388 }
6389 
6390 void
6392  NumericVector<Number> & residual,
6393  const std::set<TagID> & tags)
6394 {
6395  parallel_object_only();
6396 
6397  TIME_SECTION("computeResidualInternal", 1);
6398 
6399  try
6400  {
6402 
6404 
6405  computeResidualTags(tags);
6406 
6408  }
6409  catch (MooseException & e)
6410  {
6411  // If a MooseException propagates all the way to here, it means
6412  // that it was thrown from a MOOSE system where we do not
6413  // (currently) properly support the throwing of exceptions, and
6414  // therefore we have no choice but to error out. It may be
6415  // *possible* to handle exceptions from other systems, but in the
6416  // meantime, we don't want to silently swallow any unhandled
6417  // exceptions here.
6418  mooseError("An unhandled MooseException was raised during residual computation. Please "
6419  "contact the MOOSE team for assistance.");
6420  }
6421 }
6422 
6423 void
6425  NumericVector<Number> & residual,
6426  TagID tag)
6427 {
6428  TIME_SECTION("computeResidualType", 5);
6429 
6430  try
6431  {
6433 
6435 
6437 
6439  }
6440  catch (MooseException & e)
6441  {
6442  // If a MooseException propagates all the way to here, it means
6443  // that it was thrown from a MOOSE system where we do not
6444  // (currently) properly support the throwing of exceptions, and
6445  // therefore we have no choice but to error out. It may be
6446  // *possible* to handle exceptions from other systems, but in the
6447  // meantime, we don't want to silently swallow any unhandled
6448  // exceptions here.
6449  mooseError("An unhandled MooseException was raised during residual computation. Please "
6450  "contact the MOOSE team for assistance.");
6451  }
6452 }
6453 
6454 void
6455 FEProblemBase::handleException(const std::string & calling_method)
6456 {
6457  auto create_exception_message =
6458  [&calling_method](const std::string & exception_type, const auto & exception)
6459  {
6460  return std::string("A " + exception_type + " was raised during FEProblemBase::" +
6461  calling_method + "\n" + std::string(exception.what()));
6462  };
6463 
6464  try
6465  {
6466  throw;
6467  }
6468  catch (const libMesh::LogicError & e)
6469  {
6470  setException(create_exception_message("libMesh::LogicError", e));
6471  }
6472  catch (const MooseException & e)
6473  {
6474  setException(create_exception_message("MooseException", e));
6475  }
6476  catch (const MetaPhysicL::LogicError & e)
6477  {
6479  }
6480  catch (const libMesh::PetscSolverException & e)
6481  {
6482  // One PETSc solver exception that we cannot currently recover from are new nonzero errors. In
6483  // particular I have observed the following scenario in a parallel test:
6484  // - Both processes throw because of a new nonzero during MOOSE's computeJacobianTags
6485  // - We potentially handle the exceptions nicely here
6486  // - When the matrix is closed in libMesh's libmesh_petsc_snes_solver, there is a new nonzero
6487  // throw which we do not catch here in MOOSE and the simulation terminates. This only appears
6488  // in parallel (and not all the time; a test I was examining threw with distributed mesh, but
6489  // not with replicated). In serial there are no new throws from libmesh_petsc_snes_solver.
6490  // So for uniformity of behavior across serial/parallel, we will choose to abort here and always
6491  // produce a non-zero exit code
6492  mooseError(create_exception_message("libMesh::PetscSolverException", e));
6493  }
6494  catch (const std::exception & e)
6495  {
6496  const auto message = create_exception_message("std::exception", e);
6498  mooseError(message);
6499  else
6500  setException(message);
6501  }
6502 
6504 }
6505 
6506 void
6507 FEProblemBase::computeResidualTags(const std::set<TagID> & tags)
6508 {
6509  parallel_object_only();
6510 
6511  try
6512  {
6513  try
6514  {
6515  TIME_SECTION("computeResidualTags", 5, "Computing Residual");
6516 
6517  ADReal::do_derivatives = false;
6518 
6520 
6521  _aux->zeroVariablesForResidual();
6522 
6523  unsigned int n_threads = libMesh::n_threads();
6524 
6526 
6527  // Random interface objects
6528  for (const auto & it : _random_data_objects)
6529  it.second->updateSeeds(EXEC_LINEAR);
6530 
6532 
6534 
6535  for (unsigned int tid = 0; tid < n_threads; tid++)
6536  reinitScalars(tid);
6537 
6539 
6540  _aux->residualSetup();
6541 
6542  if (_displaced_problem)
6543  {
6544  _aux->compute(EXEC_PRE_DISPLACE);
6545  _displaced_problem->updateMesh();
6547  updateMortarMesh();
6548  }
6549 
6550  for (THREAD_ID tid = 0; tid < n_threads; tid++)
6551  {
6554  }
6555 
6556  // Where is the aux system done? Could the non-current nonlinear systems also be done there?
6557  for (auto & nl : _nl)
6558  nl->computeTimeDerivatives();
6559 
6560  _aux->compute(EXEC_LINEAR);
6561 
6563 
6565 
6567 
6570  }
6571  catch (...)
6572  {
6573  handleException("computeResidualTags");
6574  }
6575  }
6576  catch (const MooseException &)
6577  {
6578  // The buck stops here, we have already handled the exception by
6579  // calling the system's stopSolve() method, it is now up to PETSc to return a
6580  // "diverged" reason during the next solve.
6581  }
6582  catch (...)
6583  {
6584  mooseError("Unexpected exception type");
6585  }
6586 
6587  resetState();
6588 }
6589 
6590 void
6591 FEProblemBase::computeJacobianSys(NonlinearImplicitSystem & sys,
6592  const NumericVector<Number> & soln,
6593  SparseMatrix<Number> & jacobian)
6594 {
6595  computeJacobian(soln, jacobian, sys.number());
6596 }
6597 
6598 void
6600  SparseMatrix<Number> & jacobian,
6601  TagID tag)
6602 {
6604 
6605  _current_nl_sys->associateMatrixToTag(jacobian, tag);
6606 
6607  computeJacobianTags({tag});
6608 
6610 }
6611 
6612 void
6614  SparseMatrix<Number> & jacobian,
6615  const unsigned int nl_sys_num)
6616 {
6617  setCurrentNonlinearSystem(nl_sys_num);
6618 
6619  _fe_matrix_tags.clear();
6620 
6621  auto & tags = getMatrixTags();
6622  for (auto & tag : tags)
6623  _fe_matrix_tags.insert(tag.second);
6624 
6625  computeJacobianInternal(soln, jacobian, _fe_matrix_tags);
6626 }
6627 
6628 void
6630  SparseMatrix<Number> & jacobian,
6631  const std::set<TagID> & tags)
6632 {
6633  TIME_SECTION("computeJacobianInternal", 1);
6634 
6636 
6638 
6639  computeJacobianTags(tags);
6640 
6642 }
6643 
6644 void
6645 FEProblemBase::computeJacobianTags(const std::set<TagID> & tags)
6646 {
6647  try
6648  {
6649  try
6650  {
6651  if (!_has_jacobian || !_const_jacobian)
6652  {
6653  TIME_SECTION("computeJacobianTags", 5, "Computing Jacobian");
6654 
6655  for (auto tag : tags)
6656  if (_current_nl_sys->hasMatrix(tag))
6657  {
6658  auto & matrix = _current_nl_sys->getMatrix(tag);
6659  matrix.zero();
6660  if (haveADObjects())
6661  // PETSc algorithms require diagonal allocations regardless of whether there is
6662  // non-zero diagonal dependence. With global AD indexing we only add non-zero
6663  // dependence, so PETSc will scream at us unless we artificially add the diagonals.
6664  for (auto index : make_range(matrix.row_start(), matrix.row_stop()))
6665  matrix.add(index, index, 0);
6666  }
6667 
6668  _aux->zeroVariablesForJacobian();
6669 
6670  unsigned int n_threads = libMesh::n_threads();
6671 
6672  // Random interface objects
6673  for (const auto & it : _random_data_objects)
6674  it.second->updateSeeds(EXEC_NONLINEAR);
6675 
6678  if (_displaced_problem)
6679  _displaced_problem->setCurrentlyComputingJacobian(true);
6680 
6683 
6684  for (unsigned int tid = 0; tid < n_threads; tid++)
6685  reinitScalars(tid);
6686 
6688 
6689  _aux->jacobianSetup();
6690 
6691  if (_displaced_problem)
6692  {
6693  _aux->compute(EXEC_PRE_DISPLACE);
6694  _displaced_problem->updateMesh();
6695  }
6696 
6697  for (unsigned int tid = 0; tid < n_threads; tid++)
6698  {
6701  }
6702 
6703  // When computing the initial Jacobian for automatic variable scaling we need to make sure
6704  // that the time derivatives have been calculated. So we'll call down to the nonlinear
6705  // system here. Note that if we are not doing this initial Jacobian calculation we will
6706  // just exit in that class to avoid redundant calculation (the residual function also
6707  // computes time derivatives)
6708  _current_nl_sys->computeTimeDerivatives(/*jacobian_calculation =*/true);
6709 
6710  _aux->compute(EXEC_NONLINEAR);
6711 
6713 
6715 
6717 
6719 
6721 
6722  // For explicit Euler calculations for example we often compute the Jacobian one time and
6723  // then re-use it over and over. If we're performing automatic scaling, we don't want to
6724  // use that kernel, diagonal-block only Jacobian for our actual matrix when performing
6725  // solves!
6727  _has_jacobian = true;
6728  }
6729  }
6730  catch (...)
6731  {
6732  handleException("computeJacobianTags");
6733  }
6734  }
6735  catch (const MooseException &)
6736  {
6737  // The buck stops here, we have already handled the exception by
6738  // calling the system's stopSolve() method, it is now up to PETSc to return a
6739  // "diverged" reason during the next solve.
6740  }
6741  catch (...)
6742  {
6743  mooseError("Unexpected exception type");
6744  }
6745 
6746  resetState();
6747 }
6748 
6749 void
6750 FEProblemBase::computeJacobianBlocks(std::vector<JacobianBlock *> & blocks,
6751  const unsigned int nl_sys_num)
6752 {
6753  TIME_SECTION("computeTransientImplicitJacobian", 2);
6754  setCurrentNonlinearSystem(nl_sys_num);
6755 
6756  if (_displaced_problem)
6757  {
6758  _aux->compute(EXEC_PRE_DISPLACE);
6759  _displaced_problem->updateMesh();
6760  }
6761 
6762  _aux->compute(EXEC_NONLINEAR);
6763 
6767 }
6768 
6769 void
6771  libMesh::System & precond_system,
6772  unsigned int ivar,
6773  unsigned int jvar)
6774 {
6775  JacobianBlock jac_block(precond_system, jacobian, ivar, jvar);
6776  std::vector<JacobianBlock *> blocks = {&jac_block};
6777  mooseAssert(_current_nl_sys, "This should be non-null");
6779 }
6780 
6781 void
6782 FEProblemBase::computeBounds(NonlinearImplicitSystem & libmesh_dbg_var(sys),
6783  NumericVector<Number> & lower,
6784  NumericVector<Number> & upper)
6785 {
6786  try
6787  {
6788  try
6789  {
6790  mooseAssert(_current_nl_sys && (sys.number() == _current_nl_sys->number()),
6791  "I expect these system numbers to be the same");
6792 
6793  if (!_current_nl_sys->hasVector("lower_bound") || !_current_nl_sys->hasVector("upper_bound"))
6794  return;
6795 
6796  TIME_SECTION("computeBounds", 1, "Computing Bounds");
6797 
6798  NumericVector<Number> & _lower = _current_nl_sys->getVector("lower_bound");
6799  NumericVector<Number> & _upper = _current_nl_sys->getVector("upper_bound");
6800  _lower.swap(lower);
6801  _upper.swap(upper);
6802  for (THREAD_ID tid = 0; tid < libMesh::n_threads(); tid++)
6804 
6805  _aux->residualSetup();
6806  _aux->compute(EXEC_LINEAR);
6807  _lower.swap(lower);
6808  _upper.swap(upper);
6809  }
6810  catch (...)
6811  {
6812  handleException("computeBounds");
6813  }
6814  }
6815  catch (MooseException & e)
6816  {
6817  mooseError("Irrecoverable exception: " + std::string(e.what()));
6818  }
6819  catch (...)
6820  {
6821  mooseError("Unexpected exception type");
6822  }
6823 }
6824 
6825 void
6826 FEProblemBase::computeNearNullSpace(NonlinearImplicitSystem & libmesh_dbg_var(sys),
6827  std::vector<NumericVector<Number> *> & sp)
6828 {
6829  mooseAssert(_current_nl_sys && (sys.number() == _current_nl_sys->number()),
6830  "I expect these system numbers to be the same");
6831 
6832  sp.clear();
6833  for (unsigned int i = 0; i < subspaceDim("NearNullSpace"); ++i)
6834  {
6835  std::stringstream postfix;
6836  postfix << "_" << i;
6837  std::string modename = "NearNullSpace" + postfix.str();
6838  sp.push_back(&_current_nl_sys->getVector(modename));
6839  }
6840 }
6841 
6842 void
6843 FEProblemBase::computeNullSpace(NonlinearImplicitSystem & libmesh_dbg_var(sys),
6844  std::vector<NumericVector<Number> *> & sp)
6845 {
6846  mooseAssert(_current_nl_sys && (sys.number() == _current_nl_sys->number()),
6847  "I expect these system numbers to be the same");
6848  sp.clear();
6849  for (unsigned int i = 0; i < subspaceDim("NullSpace"); ++i)
6850  {
6851  std::stringstream postfix;
6852  postfix << "_" << i;
6853  sp.push_back(&_current_nl_sys->getVector("NullSpace" + postfix.str()));
6854  }
6855 }
6856 
6857 void
6858 FEProblemBase::computeTransposeNullSpace(NonlinearImplicitSystem & libmesh_dbg_var(sys),
6859  std::vector<NumericVector<Number> *> & sp)
6860 {
6861  mooseAssert(_current_nl_sys && (sys.number() == _current_nl_sys->number()),
6862  "I expect these system numbers to be the same");
6863  sp.clear();
6864  for (unsigned int i = 0; i < subspaceDim("TransposeNullSpace"); ++i)
6865  {
6866  std::stringstream postfix;
6867  postfix << "_" << i;
6868  sp.push_back(&_current_nl_sys->getVector("TransposeNullSpace" + postfix.str()));
6869  }
6870 }
6871 
6872 void
6873 FEProblemBase::computePostCheck(NonlinearImplicitSystem & sys,
6874  const NumericVector<Number> & old_soln,
6875  NumericVector<Number> & search_direction,
6876  NumericVector<Number> & new_soln,
6877  bool & changed_search_direction,
6878  bool & changed_new_soln)
6879 {
6880  mooseAssert(_current_nl_sys && (sys.number() == _current_nl_sys->number()),
6881  "I expect these system numbers to be the same");
6882 
6883  // This function replaces the old PetscSupport::dampedCheck() function.
6884  //
6885  // 1.) Recreate code in PetscSupport::dampedCheck() for constructing
6886  // ghosted "soln" and "update" vectors.
6887  // 2.) Call FEProblemBase::computeDamping() with these ghost vectors.
6888  // 3.) Recreate the code in PetscSupport::dampedCheck() to actually update
6889  // the solution vector based on the damping, and set the "changed" flags
6890  // appropriately.
6891 
6892  TIME_SECTION("computePostCheck", 2, "Computing Post Check");
6893 
6895 
6896  // MOOSE's FEProblemBase doesn't update the solution during the
6897  // postcheck, but FEProblemBase-derived classes might.
6899  {
6900  // We need ghosted versions of new_soln and search_direction (the
6901  // ones we get from libmesh/PETSc are PARALLEL vectors. To make
6902  // our lives simpler, we use the same ghosting pattern as the
6903  // system's current_local_solution to create new ghosted vectors.
6904 
6905  // Construct zeroed-out clones with the same ghosted dofs as the
6906  // System's current_local_solution.
6907  std::unique_ptr<NumericVector<Number>> ghosted_solution =
6908  sys.current_local_solution->zero_clone(),
6909  ghosted_search_direction =
6910  sys.current_local_solution->zero_clone();
6911 
6912  // Copy values from input vectors into clones with ghosted values.
6913  *ghosted_solution = new_soln;
6914  *ghosted_search_direction = search_direction;
6915 
6916  if (_has_dampers)
6917  {
6918  // Compute the damping coefficient using the ghosted vectors
6919  Real damping = computeDamping(*ghosted_solution, *ghosted_search_direction);
6920 
6921  // If some non-trivial damping was computed, update the new_soln
6922  // vector accordingly.
6923  if (damping < 1.0)
6924  {
6925  new_soln = old_soln;
6926  new_soln.add(-damping, search_direction);
6927  changed_new_soln = true;
6928  }
6929  }
6930 
6931  if (shouldUpdateSolution())
6932  {
6933  // Update the ghosted copy of the new solution, if necessary.
6934  if (changed_new_soln)
6935  *ghosted_solution = new_soln;
6936 
6937  bool updated_solution = updateSolution(new_soln, *ghosted_solution);
6938  if (updated_solution)
6939  changed_new_soln = true;
6940  }
6941  }
6942 
6944  {
6946  _aux->setPreviousNewtonSolution();
6947  }
6948 
6949  // MOOSE doesn't change the search_direction
6950  changed_search_direction = false;
6951 
6953 }
6954 
6955 Real
6957  const NumericVector<Number> & update)
6958 {
6959  // Default to no damping
6960  Real damping = 1.0;
6961 
6962  if (_has_dampers)
6963  {
6964  TIME_SECTION("computeDamping", 1, "Computing Damping");
6965 
6966  // Save pointer to the current solution
6967  const NumericVector<Number> * _saved_current_solution = _current_nl_sys->currentSolution();
6968 
6970  // For now, do not re-compute auxiliary variables. Doing so allows a wild solution increment
6971  // to get to the material models, which may not be able to cope with drastically different
6972  // values. Once more complete dependency checking is in place, auxiliary variables (and
6973  // material properties) will be computed as needed by dampers.
6974  // _aux.compute();
6975  damping = _current_nl_sys->computeDamping(soln, update);
6976 
6977  // restore saved solution
6978  _current_nl_sys->setSolution(*_saved_current_solution);
6979  }
6980 
6981  return damping;
6982 }
6983 
6984 bool
6986 {
6987  return false;
6988 }
6989 
6990 bool
6992  NumericVector<Number> & /*ghosted_solution*/)
6993 {
6994  return false;
6995 }
6996 
6997 void
6999 {
7000 }
7001 
7002 void
7003 FEProblemBase::addDisplacedProblem(std::shared_ptr<DisplacedProblem> displaced_problem)
7004 {
7005  parallel_object_only();
7006 
7007  _displaced_mesh = &displaced_problem->mesh();
7008  _displaced_problem = displaced_problem;
7009 }
7010 
7011 void
7013 {
7014  TIME_SECTION("updateGeometricSearch", 3, "Updating Geometric Search");
7015 
7017 
7018  if (_displaced_problem)
7019  _displaced_problem->updateGeomSearch(type);
7020 }
7021 
7022 void
7024 {
7025  TIME_SECTION("updateMortarMesh", 5, "Updating Mortar Mesh");
7026 
7027  FloatingPointExceptionGuard fpe_guard(_app);
7028 
7029  _mortar_data.update();
7030 }
7031 
7032 void
7034  const std::pair<BoundaryID, BoundaryID> & primary_secondary_boundary_pair,
7035  const std::pair<SubdomainID, SubdomainID> & primary_secondary_subdomain_pair,
7036  bool on_displaced,
7037  bool periodic,
7038  const bool debug,
7039  const bool correct_edge_dropping,
7040  const Real minimum_projection_angle)
7041 {
7042  _has_mortar = true;
7043 
7044  if (on_displaced)
7045  return _mortar_data.createMortarInterface(primary_secondary_boundary_pair,
7046  primary_secondary_subdomain_pair,
7048  on_displaced,
7049  periodic,
7050  debug,
7051  correct_edge_dropping,
7052  minimum_projection_angle);
7053  else
7054  return _mortar_data.createMortarInterface(primary_secondary_boundary_pair,
7055  primary_secondary_subdomain_pair,
7056  *this,
7057  on_displaced,
7058  periodic,
7059  debug,
7060  correct_edge_dropping,
7061  minimum_projection_angle);
7062 }
7063 
7066  const std::pair<BoundaryID, BoundaryID> & primary_secondary_boundary_pair,
7067  const std::pair<SubdomainID, SubdomainID> & primary_secondary_subdomain_pair,
7068  bool on_displaced) const
7069 {
7071  primary_secondary_boundary_pair, primary_secondary_subdomain_pair, on_displaced);
7072 }
7073 
7076  const std::pair<BoundaryID, BoundaryID> & primary_secondary_boundary_pair,
7077  const std::pair<SubdomainID, SubdomainID> & primary_secondary_subdomain_pair,
7078  bool on_displaced)
7079 {
7081  primary_secondary_boundary_pair, primary_secondary_subdomain_pair, on_displaced);
7082 }
7083 
7084 const std::unordered_map<std::pair<BoundaryID, BoundaryID>, AutomaticMortarGeneration> &
7085 FEProblemBase::getMortarInterfaces(bool on_displaced) const
7086 {
7087  return _mortar_data.getMortarInterfaces(on_displaced);
7088 }
7089 
7090 void
7092 {
7093  if (_displaced_problem) // Only need to do this if things are moving...
7094  {
7095  TIME_SECTION("possiblyRebuildGeomSearchPatches", 5, "Rebuilding Geometric Search Patches");
7096 
7097  switch (_mesh.getPatchUpdateStrategy())
7098  {
7099  case Moose::Never:
7100  break;
7101  case Moose::Iteration:
7102  // Update the list of ghosted elements at the start of the time step
7105 
7106  _displaced_problem->geomSearchData().updateGhostedElems();
7108 
7109  // The commands below ensure that the sparsity of the Jacobian matrix is
7110  // augmented at the start of the time step using neighbor nodes from the end
7111  // of the previous time step.
7112 
7114 
7115  // This is needed to reinitialize PETSc output
7117 
7118  break;
7119 
7120  case Moose::Auto:
7121  {
7122  Real max = _displaced_problem->geomSearchData().maxPatchPercentage();
7124 
7125  // If we haven't moved very far through the patch
7126  if (max < 0.4)
7127  break;
7128  }
7129  libmesh_fallthrough();
7130 
7131  // Let this fall through if things do need to be updated...
7132  case Moose::Always:
7133  // Flush output here to see the message before the reinitialization, which could take a
7134  // while
7135  _console << "\n\nUpdating geometric search patches\n" << std::endl;
7136 
7139 
7140  _displaced_problem->geomSearchData().clearNearestNodeLocators();
7142 
7144 
7145  // This is needed to reinitialize PETSc output
7147  }
7148  }
7149 }
7150 
7151 #ifdef LIBMESH_ENABLE_AMR
7152 void
7154 {
7155  unsigned int n = adaptivity().getInitialSteps();
7156  _cycles_completed = 0;
7157  if (n)
7158  {
7161  mooseError("HFEM does not support mesh adaptivity currently.");
7162 
7163  TIME_SECTION("initialAdaptMesh", 2, "Performing Initial Adaptivity");
7164 
7165  for (unsigned int i = 0; i < n; i++)
7166  {
7168  computeMarkers();
7169 
7171  {
7172  meshChanged();
7173 
7174  // reproject the initial condition
7175  projectSolution();
7176 
7178  }
7179  else
7180  {
7181  _console << "Mesh unchanged, skipping remaining steps..." << std::endl;
7182  return;
7183  }
7184  }
7185  }
7186 }
7187 
7188 bool
7190 {
7191  // reset cycle counter
7192  _cycles_completed = 0;
7193 
7195  return false;
7196 
7197  TIME_SECTION("adaptMesh", 3, "Adapting Mesh");
7198 
7199  unsigned int cycles_per_step = _adaptivity.getCyclesPerStep();
7200 
7201  bool mesh_changed = false;
7202 
7203  for (unsigned int i = 0; i < cycles_per_step; ++i)
7204  {
7207  mooseError("HFEM does not support mesh adaptivity currently.");
7208 
7209  // Markers were already computed once by Executioner
7210  if (_adaptivity.getRecomputeMarkersFlag() && i > 0)
7211  computeMarkers();
7212 
7213  bool mesh_changed_this_step;
7214  mesh_changed_this_step = _adaptivity.adaptMesh();
7215 
7216  if (mesh_changed_this_step)
7217  {
7218  mesh_changed = true;
7219 
7220  meshChangedHelper(true); // This may be an intermediate change
7222  }
7223  else
7224  {
7225  _console << "Mesh unchanged, skipping remaining steps..." << std::endl;
7226  break;
7227  }
7228 
7229  // Show adaptivity progress
7230  _console << std::flush;
7231  }
7232 
7233  // We're done with all intermediate changes; now get systems ready
7234  // for real if necessary.
7235  if (mesh_changed)
7236  es().reinit_systems();
7237 
7238  return mesh_changed;
7239 }
7240 #endif // LIBMESH_ENABLE_AMR
7241 
7242 void
7243 FEProblemBase::initXFEM(std::shared_ptr<XFEMInterface> xfem)
7244 {
7245  _xfem = xfem;
7246  _xfem->setMesh(&_mesh);
7247  if (_displaced_mesh)
7248  _xfem->setDisplacedMesh(_displaced_mesh);
7249 
7250  auto fill_data = [](auto & storage)
7251  {
7252  std::vector<MaterialData *> data(libMesh::n_threads());
7253  for (const auto tid : make_range(libMesh::n_threads()))
7254  data[tid] = &storage.getMaterialData(tid);
7255  return data;
7256  };
7257  _xfem->setMaterialData(fill_data(_material_props));
7258  _xfem->setBoundaryMaterialData(fill_data(_bnd_material_props));
7259 
7260  unsigned int n_threads = libMesh::n_threads();
7261  for (unsigned int i = 0; i < n_threads; ++i)
7262  for (const auto nl_sys_num : index_range(_assembly[i]))
7263  {
7264  _assembly[i][nl_sys_num]->setXFEM(_xfem);
7265  if (_displaced_problem)
7266  _displaced_problem->assembly(i, nl_sys_num).setXFEM(_xfem);
7267  }
7268 }
7269 
7270 bool
7272 {
7273  TIME_SECTION("updateMeshXFEM", 5, "Updating XFEM");
7274 
7275  bool updated = false;
7276  if (haveXFEM())
7277  {
7278  if (_xfem->updateHeal())
7279  meshChanged();
7280 
7281  updated = _xfem->update(_time, _nl, *_aux);
7282  if (updated)
7283  {
7284  meshChanged();
7285  _xfem->initSolution(_nl, *_aux);
7286  restoreSolutions();
7287  }
7288  }
7289  return updated;
7290 }
7291 
7292 void
7294 {
7295  TIME_SECTION("meshChanged", 3, "Handling Mesh Changes");
7296 
7297  this->meshChangedHelper();
7298 }
7299 
7300 void
7301 FEProblemBase::meshChangedHelper(bool intermediate_change)
7302 {
7303  TIME_SECTION("meshChangedHelper", 5);
7304 
7307  _mesh.cacheChangedLists(); // Currently only used with adaptivity and stateful material
7308  // properties
7309 
7310  // Clear these out because they corresponded to the old mesh
7311  _ghosted_elems.clear();
7313 
7314  // The mesh changed. We notify the MooseMesh first, because
7315  // callbacks (e.g. for sparsity calculations) triggered by the
7316  // EquationSystems reinit may require up-to-date MooseMesh caches.
7317  _mesh.meshChanged();
7318 
7319  // If we're just going to alter the mesh again, all we need to
7320  // handle here is AMR and projections, not full system reinit
7321  if (intermediate_change)
7322  es().reinit_solutions();
7323  else
7324  es().reinit();
7325 
7326  // Updating MooseMesh first breaks other adaptivity code, unless we
7327  // then *again* update the MooseMesh caches. E.g. the definition of
7328  // "active" and "local" may have been *changed* by refinement and
7329  // repartitioning done in EquationSystems::reinit().
7330  _mesh.meshChanged();
7331 
7332  // If we have finite volume variables, we will need to recompute additional elemental/face
7333  // quantities
7336 
7337  // Let the meshChangedInterface notify the mesh changed event before we update the active
7338  // semilocal nodes, because the set of ghosted elements may potentially be updated during a mesh
7339  // changed event.
7340  for (const auto & mci : _notify_when_mesh_changes)
7341  mci->meshChanged();
7342 
7343  // Since the Mesh changed, update the PointLocator object used by DiracKernels.
7345 
7346  // Need to redo ghosting
7348 
7349  if (_displaced_problem)
7350  {
7351  _displaced_problem->meshChanged();
7353  }
7354 
7356 
7359 
7360  // Just like we reinitialized our geometric search objects, we also need to reinitialize our
7361  // mortar meshes. Note that this needs to happen after DisplacedProblem::meshChanged because the
7362  // mortar mesh discretization will depend necessarily on the displaced mesh being re-displaced
7363  updateMortarMesh();
7364 
7365  reinitBecauseOfGhostingOrNewGeomObjects(/*mortar_changed=*/true);
7366 
7367  // We need to create new storage for newly active elements, and copy
7368  // stateful properties from the old elements.
7371  {
7372  if (havePRefinement())
7374 
7375  // Prolong properties onto newly refined elements' children
7376  {
7378  /* refine = */ true, *this, _material_props, _bnd_material_props, _assembly);
7379  const auto & range = *_mesh.refinedElementRange();
7380  Threads::parallel_reduce(range, pmp);
7381 
7382  // Concurrent erasure from the shared hash map is not safe while we are reading from it in
7383  // ProjectMaterialProperties, so we handle erasure here. Moreover, erasure based on key is
7384  // not thread safe in and of itself because it is a read-write operation. Note that we do not
7385  // do the erasure for p-refinement because the coarse level element is the same as our active
7386  // refined level element
7387  if (!doingPRefinement())
7388  for (const auto & elem : range)
7389  {
7393  }
7394  }
7395 
7396  // Restrict properties onto newly coarsened elements
7397  {
7399  /* refine = */ false, *this, _material_props, _bnd_material_props, _assembly);
7400  const auto & range = *_mesh.coarsenedElementRange();
7401  Threads::parallel_reduce(range, pmp);
7402  // Note that we do not do the erasure for p-refinement because the coarse level element is the
7403  // same as our active refined level element
7404  if (!doingPRefinement())
7405  for (const auto & elem : range)
7406  {
7407  auto && coarsened_children = _mesh.coarsenedElementChildren(elem);
7408  for (auto && child : coarsened_children)
7409  {
7413  }
7414  }
7415  }
7416  }
7417 
7420 
7421  _has_jacobian = false; // we have to recompute jacobian when mesh changed
7422 
7423  // Since the mesh has changed, we need to make sure that we update any of our
7424  // MOOSE-system specific data. libmesh system data has already been updated
7425  for (auto & nl : _nl)
7426  nl->update(/*update_libmesh_system=*/false);
7427  _aux->update(/*update_libmesh_system=*/false);
7428 }
7429 
7430 void
7432 {
7433  _notify_when_mesh_changes.push_back(mci);
7434 }
7435 
7436 void
7437 FEProblemBase::initElementStatefulProps(const ConstElemRange & elem_range, const bool threaded)
7438 {
7441  if (threaded)
7442  Threads::parallel_reduce(elem_range, cmt);
7443  else
7444  cmt(elem_range, true);
7445 }
7446 
7447 void
7449 {
7450  TIME_SECTION("checkProblemIntegrity", 5);
7451 
7452  // Check for unsatisfied actions
7453  const std::set<SubdomainID> & mesh_subdomains = _mesh.meshSubdomains();
7454 
7455  // Check kernel coverage of subdomains (blocks) in the mesh
7457  for (auto & nl : _nl)
7458  nl->checkKernelCoverage(mesh_subdomains);
7459 
7460  // Check materials
7461  {
7462 #ifdef LIBMESH_ENABLE_AMR
7463  if ((_adaptivity.isOn() || _num_grid_steps) &&
7466  {
7467  _console << "Using EXPERIMENTAL Stateful Material Property projection with Adaptivity!\n"
7468  << std::flush;
7469  }
7470 #endif
7471 
7472  std::set<SubdomainID> local_mesh_subs(mesh_subdomains);
7473 
7475  {
7480  bool check_material_coverage = false;
7481  std::set<SubdomainID> ids = _all_materials.getActiveBlocks();
7482  for (const auto & id : ids)
7483  {
7484  local_mesh_subs.erase(id);
7485  check_material_coverage = true;
7486  }
7487 
7488  // also exclude mortar spaces from the material check
7489  auto && mortar_subdomain_ids = _mortar_data.getMortarSubdomainIDs();
7490  for (auto subdomain_id : mortar_subdomain_ids)
7491  local_mesh_subs.erase(subdomain_id);
7492 
7493  // Check Material Coverage
7494  if (check_material_coverage && !local_mesh_subs.empty())
7495  {
7496  std::stringstream extra_subdomain_ids;
7498  std::copy(local_mesh_subs.begin(),
7499  local_mesh_subs.end(),
7500  std::ostream_iterator<unsigned int>(extra_subdomain_ids, " "));
7501 
7502  mooseError("The following blocks from your input mesh do not contain an active material: " +
7503  extra_subdomain_ids.str() +
7504  "\nWhen ANY mesh block contains a Material object, "
7505  "all blocks must contain a Material object.\n");
7506  }
7507  }
7508 
7509  // Check material properties on blocks and boundaries
7512 
7513  // Check that material properties exist when requested by other properties on a given block
7514  const auto & materials = _all_materials.getActiveObjects();
7515  for (const auto & material : materials)
7516  material->checkStatefulSanity();
7517 
7518  // auto mats_to_check = _materials.getActiveBlockObjects();
7519  // const auto & discrete_materials = _discrete_materials.getActiveBlockObjects();
7520  // for (const auto & map_it : discrete_materials)
7521  // for (const auto & container_element : map_it.second)
7522  // mats_to_check[map_it.first].push_back(container_element);
7525  }
7526 
7527  checkUserObjects();
7528 
7529  // Verify that we don't have any Element type/Coordinate Type conflicts
7531 
7532  // If using displacements, verify that the order of the displacement
7533  // variables matches the order of the elements in the displaced
7534  // mesh.
7536 
7537  // Check for postprocessor names with same name as a scalar variable
7539 }
7540 
7541 void
7543 {
7544  if (_displaced_problem)
7545  {
7546  bool mesh_has_second_order_elements = false;
7547  for (const auto & elem : as_range(_displaced_mesh->activeLocalElementsBegin(),
7549  {
7550  if (elem->default_order() == SECOND)
7551  {
7552  mesh_has_second_order_elements = true;
7553  break;
7554  }
7555  }
7556 
7557  // We checked our local elements, so take the max over all processors.
7558  _displaced_mesh->comm().max(mesh_has_second_order_elements);
7559 
7560  // If the Mesh has second order elements, make sure the
7561  // displacement variables are second-order.
7562  if (mesh_has_second_order_elements)
7563  {
7564  const std::vector<std::string> & displacement_variables =
7565  _displaced_problem->getDisplacementVarNames();
7566 
7567  for (const auto & var_name : displacement_variables)
7568  {
7569  MooseVariableFEBase & mv =
7570  _displaced_problem->getVariable(/*tid=*/0,
7571  var_name,
7574  if (mv.order() != SECOND)
7575  mooseError("Error: mesh has SECOND order elements, so all displacement variables must be "
7576  "SECOND order.");
7577  }
7578  }
7579  }
7580 }
7581 
7582 void
7584 {
7585  // Check user_objects block coverage
7586  std::set<SubdomainID> mesh_subdomains = _mesh.meshSubdomains();
7587  std::set<SubdomainID> user_objects_blocks;
7588 
7589  // gather names of all user_objects that were defined in the input file
7590  // and the blocks that they are defined on
7591  std::set<std::string> names;
7592 
7593  std::vector<UserObject *> objects;
7595 
7596  for (const auto & obj : objects)
7597  names.insert(obj->name());
7598 
7599  // See if all referenced blocks are covered
7600  std::set<SubdomainID> difference;
7601  std::set_difference(user_objects_blocks.begin(),
7602  user_objects_blocks.end(),
7603  mesh_subdomains.begin(),
7604  mesh_subdomains.end(),
7605  std::inserter(difference, difference.end()));
7606 
7607  if (!difference.empty())
7608  {
7609  std::ostringstream oss;
7610  oss << "One or more UserObjects is referencing a nonexistent block:\n";
7611  for (const auto & id : difference)
7612  oss << id << "\n";
7613  mooseError(oss.str());
7614  }
7615 }
7616 
7617 void
7619  const std::map<SubdomainID, std::vector<std::shared_ptr<MaterialBase>>> & materials_map)
7620 {
7621  for (const auto & it : materials_map)
7622  {
7624  std::set<std::string> block_depend_props, block_supplied_props;
7625 
7626  for (const auto & mat1 : it.second)
7627  {
7628  const std::set<std::string> & depend_props = mat1->getRequestedItems();
7629  block_depend_props.insert(depend_props.begin(), depend_props.end());
7630 
7631  auto & alldeps = mat1->getMatPropDependencies(); // includes requested stateful props
7632  for (auto & dep : alldeps)
7633  if (const auto name = _material_props.queryStatefulPropName(dep))
7634  block_depend_props.insert(*name);
7635 
7636  // See if any of the active materials supply this property
7637  for (const auto & mat2 : it.second)
7638  {
7639  const std::set<std::string> & supplied_props = mat2->MaterialBase::getSuppliedItems();
7640  block_supplied_props.insert(supplied_props.begin(), supplied_props.end());
7641  }
7642  }
7643 
7644  // Add zero material properties specific to this block and unrestricted
7645  block_supplied_props.insert(_zero_block_material_props[it.first].begin(),
7646  _zero_block_material_props[it.first].end());
7647 
7648  // Error check to make sure all properties consumed by materials are supplied on this block
7649  std::set<std::string> difference;
7650  std::set_difference(block_depend_props.begin(),
7651  block_depend_props.end(),
7652  block_supplied_props.begin(),
7653  block_supplied_props.end(),
7654  std::inserter(difference, difference.end()));
7655 
7656  if (!difference.empty())
7657  {
7658  std::ostringstream oss;
7659  oss << "One or more Material Properties were not supplied on block ";
7660  const std::string & subdomain_name = _mesh.getSubdomainName(it.first);
7661  if (subdomain_name.length() > 0)
7662  oss << subdomain_name << " (" << it.first << ")";
7663  else
7664  oss << it.first;
7665  oss << ":\n";
7666  for (const auto & name : difference)
7667  oss << name << "\n";
7668  mooseError(oss.str());
7669  }
7670  }
7671 
7672  // This loop checks that materials are not supplied by multiple Material objects
7673  for (const auto & it : materials_map)
7674  {
7675  const auto & materials = it.second;
7676  std::set<std::string> inner_supplied, outer_supplied;
7677 
7678  for (const auto & outer_mat : materials)
7679  {
7680  // Storage for properties for this material (outer) and all other materials (inner)
7681  outer_supplied = outer_mat->getSuppliedItems();
7682  inner_supplied.clear();
7683 
7684  // Property to material map for error reporting
7685  std::map<std::string, std::set<std::string>> prop_to_mat;
7686  for (const auto & name : outer_supplied)
7687  prop_to_mat[name].insert(outer_mat->name());
7688 
7689  for (const auto & inner_mat : materials)
7690  {
7691  if (outer_mat == inner_mat)
7692  continue;
7693 
7694  // Check whether these materials are an AD pair
7695  auto outer_mat_type = outer_mat->type();
7696  auto inner_mat_type = inner_mat->type();
7697  removeSubstring(outer_mat_type, "<RESIDUAL>");
7698  removeSubstring(outer_mat_type, "<JACOBIAN>");
7699  removeSubstring(inner_mat_type, "<RESIDUAL>");
7700  removeSubstring(inner_mat_type, "<JACOBIAN>");
7701  if (outer_mat_type == inner_mat_type && outer_mat_type != outer_mat->type() &&
7702  inner_mat_type != inner_mat->type())
7703  continue;
7704 
7705  inner_supplied.insert(inner_mat->getSuppliedItems().begin(),
7706  inner_mat->getSuppliedItems().end());
7707 
7708  for (const auto & inner_supplied_name : inner_supplied)
7709  prop_to_mat[inner_supplied_name].insert(inner_mat->name());
7710  }
7711 
7712  // Test that a property isn't supplied on multiple blocks
7713  std::set<std::string> intersection;
7714  std::set_intersection(outer_supplied.begin(),
7715  outer_supplied.end(),
7716  inner_supplied.begin(),
7717  inner_supplied.end(),
7718  std::inserter(intersection, intersection.end()));
7719 
7720  if (!intersection.empty())
7721  {
7722  std::ostringstream oss;
7723  oss << "The following material properties are declared on block " << it.first
7724  << " by multiple materials:\n";
7725  oss << ConsoleUtils::indent(2) << std::setw(30) << std::left << "Material Property"
7726  << "Material Objects\n";
7727  for (const auto & outer_name : intersection)
7728  {
7729  oss << ConsoleUtils::indent(2) << std::setw(30) << std::left << outer_name;
7730  for (const auto & inner_name : prop_to_mat[outer_name])
7731  oss << inner_name << " ";
7732  oss << '\n';
7733  }
7734 
7735  mooseError(oss.str());
7736  break;
7737  }
7738  }
7739  }
7740 }
7741 
7742 void
7744 {
7746 }
7747 
7748 void
7749 FEProblemBase::setRestartFile(const std::string & file_name)
7750 {
7751  if (_app.isRecovering())
7752  {
7753  mooseInfo("Restart file ", file_name, " is NOT being used since we are performing recovery.");
7754  }
7755  else
7756  {
7757  _app.setRestart(true);
7758  _app.setRestartRecoverFileBase(file_name);
7759  mooseInfo("Using ", file_name, " for restart.");
7760  }
7761 }
7762 
7763 std::vector<VariableName>
7765 {
7766  std::vector<VariableName> names;
7767 
7768  for (auto & nl : _nl)
7769  {
7770  const std::vector<VariableName> & nl_var_names = nl->getVariableNames();
7771  names.insert(names.end(), nl_var_names.begin(), nl_var_names.end());
7772  }
7773 
7774  const std::vector<VariableName> & aux_var_names = _aux->getVariableNames();
7775  names.insert(names.end(), aux_var_names.begin(), aux_var_names.end());
7776 
7777  return names;
7778 }
7779 
7782  const PetscInt it,
7783  const Real xnorm,
7784  const Real snorm,
7785  const Real fnorm,
7786  const Real rtol,
7787  const Real divtol,
7788  const Real stol,
7789  const Real abstol,
7790  const PetscInt nfuncs,
7791  const PetscInt max_funcs,
7792  const Real initial_residual_before_preset_bcs,
7793  const Real div_threshold)
7794 {
7795  TIME_SECTION("checkNonlinearConvergence", 5, "Checking Nonlinear Convergence");
7796  mooseAssert(_current_nl_sys, "This should be non-null");
7797 
7799 
7801  {
7804  }
7805 
7808 
7809  Real fnorm_old;
7810  // This is the first residual before any iterations have been done,
7811  // but after preset BCs (if any) have been imposed on the solution
7812  // vector. We save it, and use it to detect convergence if
7813  // compute_initial_residual_before_preset_bcs=false.
7814  if (it == 0)
7815  {
7816  system._initial_residual_after_preset_bcs = fnorm;
7817  fnorm_old = fnorm;
7818  _n_nl_pingpong = 0;
7819  }
7820  else
7821  fnorm_old = system._last_nl_rnorm;
7822 
7823  // Check for nonlinear residual pingpong.
7824  // Pingpong will always start from a residual increase
7825  if ((_n_nl_pingpong % 2 == 1 && !(fnorm > fnorm_old)) ||
7826  (_n_nl_pingpong % 2 == 0 && fnorm > fnorm_old))
7827  _n_nl_pingpong += 1;
7828  else
7829  _n_nl_pingpong = 0;
7830 
7831  std::ostringstream oss;
7832  if (fnorm != fnorm)
7833  {
7834  oss << "Failed to converge, function norm is NaN\n";
7836  }
7837  else if ((it >= _nl_forced_its) && fnorm < abstol)
7838  {
7839  oss << "Converged due to function norm " << fnorm << " < " << abstol << '\n';
7841  }
7842  else if (nfuncs >= max_funcs)
7843  {
7844  oss << "Exceeded maximum number of function evaluations: " << nfuncs << " > " << max_funcs
7845  << '\n';
7847  }
7848  else if ((it >= _nl_forced_its) && it && fnorm > system._last_nl_rnorm && fnorm >= div_threshold)
7849  {
7850  oss << "Nonlinear solve was blowing up!\n";
7852  }
7853 
7854  if ((it >= _nl_forced_its) && it && reason == MooseNonlinearConvergenceReason::ITERATING)
7855  {
7856  // If compute_initial_residual_before_preset_bcs==false, then use the
7857  // first residual computed by PETSc to determine convergence.
7859  ? initial_residual_before_preset_bcs
7861  if (checkRelativeConvergence(it, fnorm, the_residual, rtol, abstol, oss))
7863  else if (snorm < stol * xnorm)
7864  {
7865  oss << "Converged due to small update length: " << snorm << " < " << stol << " * " << xnorm
7866  << '\n';
7868  }
7869  else if (divtol > 0 && fnorm > the_residual * divtol)
7870  {
7871  oss << "Diverged due to initial residual " << the_residual << " > divergence tolerance "
7872  << divtol << " * initial residual " << the_residual << '\n';
7874  }
7875  else if (_nl_abs_div_tol > 0 && fnorm > _nl_abs_div_tol)
7876  {
7877  oss << "Diverged due to residual " << fnorm << " > absolute divergence tolerance "
7878  << _nl_abs_div_tol << '\n';
7880  }
7882  {
7883  oss << "Diverged due to maximum nonlinear residual pingpong achieved" << '\n';
7885  }
7886  }
7887 
7888  system._last_nl_rnorm = fnorm;
7889  system._current_nl_its = static_cast<unsigned int>(it);
7890 
7891  msg = oss.str();
7892  if (_app.multiAppLevel() > 0)
7894 
7895  return reason;
7896 }
7897 
7898 bool
7900  const Real fnorm,
7901  const Real the_residual,
7902  const Real rtol,
7903  const Real /*abstol*/,
7904  std::ostringstream & oss)
7905 {
7907  return false;
7908  if (fnorm <= the_residual * rtol)
7909  {
7910  oss << "Converged due to function norm " << fnorm << " < relative tolerance (" << rtol << ")\n";
7911  return true;
7912  }
7913  return false;
7914 }
7915 
7916 SolverParams &
7918 {
7919  return _solver_params;
7920 }
7921 
7922 const SolverParams &
7924 {
7925  return _solver_params;
7926 }
7927 
7928 void
7929 FEProblemBase::registerRandomInterface(RandomInterface & random_interface, const std::string & name)
7930 {
7931  auto insert_pair = moose_try_emplace(
7932  _random_data_objects, name, std::make_unique<RandomData>(*this, random_interface));
7933 
7934  auto random_data_ptr = insert_pair.first->second.get();
7935  random_interface.setRandomDataPointer(random_data_ptr);
7936 }
7937 
7938 bool
7940 {
7941  if (_bnd_mat_side_cache[tid].find(bnd_id) == _bnd_mat_side_cache[tid].end())
7942  {
7943  auto & bnd_mat_side_cache = _bnd_mat_side_cache[tid][bnd_id];
7944  bnd_mat_side_cache = false;
7945 
7946  if (_aux->needMaterialOnSide(bnd_id))
7947  {
7948  bnd_mat_side_cache = true;
7949  return true;
7950  }
7951  else
7952  for (auto & nl : _nl)
7953  if (nl->needBoundaryMaterialOnSide(bnd_id, tid))
7954  {
7955  bnd_mat_side_cache = true;
7956  return true;
7957  }
7958 
7959  if (theWarehouse()
7960  .query()
7961  .condition<AttribThread>(tid)
7962  .condition<AttribInterfaces>(Interfaces::SideUserObject)
7963  .condition<AttribBoundaries>(bnd_id)
7964  .count() > 0)
7965  {
7966  bnd_mat_side_cache = true;
7967  return true;
7968  }
7969  }
7970 
7971  return _bnd_mat_side_cache[tid][bnd_id];
7972 }
7973 
7974 bool
7976 {
7977  if (_interface_mat_side_cache[tid].find(bnd_id) == _interface_mat_side_cache[tid].end())
7978  {
7979  auto & interface_mat_side_cache = _interface_mat_side_cache[tid][bnd_id];
7980  interface_mat_side_cache = false;
7981 
7982  for (auto & nl : _nl)
7983  if (nl->needInterfaceMaterialOnSide(bnd_id, tid))
7984  {
7985  interface_mat_side_cache = true;
7986  return true;
7987  }
7988 
7989  if (theWarehouse()
7990  .query()
7991  .condition<AttribThread>(tid)
7992  .condition<AttribInterfaces>(Interfaces::InterfaceUserObject)
7993  .condition<AttribBoundaries>(bnd_id)
7994  .count() > 0)
7995  {
7996  interface_mat_side_cache = true;
7997  return true;
7998  }
7999  else if (_interface_materials.hasActiveBoundaryObjects(bnd_id, tid))
8000  {
8001  interface_mat_side_cache = true;
8002  return true;
8003  }
8004  }
8005  return _interface_mat_side_cache[tid][bnd_id];
8006 }
8007 
8008 bool
8010 {
8011  if (_block_mat_side_cache[tid].find(subdomain_id) == _block_mat_side_cache[tid].end())
8012  {
8013  _block_mat_side_cache[tid][subdomain_id] = false;
8014 
8015  for (auto & nl : _nl)
8016  if (nl->needSubdomainMaterialOnSide(subdomain_id, tid))
8017  {
8018  _block_mat_side_cache[tid][subdomain_id] = true;
8019  return true;
8020  }
8021 
8022  if (theWarehouse()
8023  .query()
8024  .condition<AttribThread>(tid)
8025  .condition<AttribInterfaces>(Interfaces::InternalSideUserObject)
8026  .condition<AttribSubdomains>(subdomain_id)
8027  .count() > 0)
8028  {
8029  _block_mat_side_cache[tid][subdomain_id] = true;
8030  return true;
8031  }
8032  }
8033 
8034  return _block_mat_side_cache[tid][subdomain_id];
8035 }
8036 
8037 bool
8039 {
8041 }
8042 
8043 void
8045 {
8047  mooseError("Previous nonlinear solution is required but not added through "
8048  "Problem/previous_nl_solution_required=true");
8049 }
8050 
8051 bool
8053 {
8054  return _has_jacobian;
8055 }
8056 
8057 bool
8059 {
8060  return _const_jacobian;
8061 }
8062 
8063 void
8064 FEProblemBase::addOutput(const std::string & object_type,
8065  const std::string & object_name,
8066  InputParameters & parameters)
8067 {
8068  parallel_object_only();
8069 
8070  // Get a reference to the OutputWarehouse
8071  OutputWarehouse & output_warehouse = _app.getOutputWarehouse();
8072 
8073  // Reject the reserved names for objects not built by MOOSE
8074  if (!parameters.get<bool>("_built_by_moose") && output_warehouse.isReservedName(object_name))
8075  mooseError("The name '", object_name, "' is a reserved name for output objects");
8076 
8077  // Check that an object by the same name does not already exist; this must be done before the
8078  // object is created to avoid getting misleading errors from the Parser
8079  if (output_warehouse.hasOutput(object_name))
8080  mooseError("An output object named '", object_name, "' already exists");
8081 
8082  // Add a pointer to the FEProblemBase class
8083  parameters.addPrivateParam<FEProblemBase *>("_fe_problem_base", this);
8084 
8085  // Create common parameter exclude list
8086  std::vector<std::string> exclude;
8087  if (object_type == "Console")
8088  {
8089  exclude.push_back("execute_on");
8090 
8091  // --show-input should enable the display of the input file on the screen
8092  if (_app.getParam<bool>("show_input") && parameters.get<bool>("output_screen"))
8093  parameters.set<ExecFlagEnum>("execute_input_on") = EXEC_INITIAL;
8094  }
8095  // Need this because Checkpoint::validParams changes the default value of
8096  // execute_on
8097  else if (object_type == "Checkpoint")
8098  exclude.push_back("execute_on");
8099 
8100  // Apply the common parameters loaded with Outputs input syntax
8101  const InputParameters * common = output_warehouse.getCommonParameters();
8102  if (common)
8103  parameters.applyParameters(*common, exclude);
8104 
8105  // Set the correct value for the binary flag for XDA/XDR output
8106  if (object_type == "XDR")
8107  parameters.set<bool>("_binary") = true;
8108  else if (object_type == "XDA")
8109  parameters.set<bool>("_binary") = false;
8110 
8111  // Adjust the checkpoint suffix if auto recovery was enabled
8112  if (object_name == "auto_recovery_checkpoint")
8113  parameters.set<std::string>("suffix") = "auto_recovery";
8114 
8115  // Create the object and add it to the warehouse
8116  std::shared_ptr<Output> output = _factory.create<Output>(object_type, object_name, parameters);
8117  logAdd("Output", object_name, object_type);
8118  output_warehouse.addOutput(output);
8119 }
8120 
8121 void
8122 FEProblemBase::haveADObjects(const bool have_ad_objects)
8123 {
8124  _have_ad_objects = have_ad_objects;
8125  if (_displaced_problem)
8126  _displaced_problem->SubProblem::haveADObjects(have_ad_objects);
8127 }
8128 
8129 const SystemBase &
8130 FEProblemBase::systemBaseNonlinear(const unsigned int sys_num) const
8131 {
8132  mooseAssert(sys_num < _nl.size(), "System number greater than the number of nonlinear systems");
8133  return *_nl[sys_num];
8134 }
8135 
8136 SystemBase &
8137 FEProblemBase::systemBaseNonlinear(const unsigned int sys_num)
8138 {
8139  return *_nl[sys_num];
8140 }
8141 
8142 const SystemBase &
8144 {
8145  return *_aux;
8146 }
8147 
8148 SystemBase &
8150 {
8151  return *_aux;
8152 }
8153 
8154 void
8155 FEProblemBase::computingNonlinearResid(bool computing_nonlinear_residual)
8156 {
8157  parallel_object_only();
8158 
8159  if (_displaced_problem)
8160  _displaced_problem->computingNonlinearResid(computing_nonlinear_residual);
8161  _computing_nonlinear_residual = computing_nonlinear_residual;
8162 }
8163 
8164 void
8165 FEProblemBase::setCurrentlyComputingResidual(bool currently_computing_residual)
8166 {
8167  if (_displaced_problem)
8168  _displaced_problem->setCurrentlyComputingResidual(currently_computing_residual);
8169  _currently_computing_residual = currently_computing_residual;
8170 }
8171 
8172 void
8174 {
8175  // ResetDisplacedMeshThread::onNode looks up the reference mesh by ID, so we need to make sure
8176  // we undisplace before adapting the reference mesh
8177  if (_displaced_problem)
8178  _displaced_problem->undisplaceMesh();
8179 
8181  if (_displaced_problem)
8183 
8184  meshChangedHelper(/*intermediate_change=*/false);
8185 }
8186 
8187 void
8188 FEProblemBase::automaticScaling(bool automatic_scaling)
8189 {
8190  if (_displaced_problem)
8191  _displaced_problem->automaticScaling(automatic_scaling);
8192 
8193  SubProblem::automaticScaling(automatic_scaling);
8194 }
8195 
8196 void
8198  unsigned int side,
8199  BoundaryID bnd_id,
8200  Real tolerance,
8201  const std::vector<Point> * const pts,
8202  const std::vector<Real> * const weights,
8203  const THREAD_ID tid)
8204 {
8205  SubProblem::reinitElemFaceRef(elem, side, bnd_id, tolerance, pts, weights, tid);
8206 
8207  if (_displaced_problem)
8208  _displaced_problem->reinitElemFaceRef(
8209  _displaced_mesh->elemPtr(elem->id()), side, bnd_id, tolerance, pts, weights, tid);
8210 }
8211 
8212 void
8213 FEProblemBase::reinitNeighborFaceRef(const Elem * neighbor_elem,
8214  unsigned int neighbor_side,
8215  BoundaryID bnd_id,
8216  Real tolerance,
8217  const std::vector<Point> * const pts,
8218  const std::vector<Real> * const weights,
8219  const THREAD_ID tid)
8220 {
8222  neighbor_elem, neighbor_side, bnd_id, tolerance, pts, weights, tid);
8223 
8224  if (_displaced_problem)
8225  _displaced_problem->reinitNeighborFaceRef(_displaced_mesh->elemPtr(neighbor_elem->id()),
8226  neighbor_side,
8227  bnd_id,
8228  tolerance,
8229  pts,
8230  weights,
8231  tid);
8232 }
8233 
8234 void
8236  const SubdomainID blk_id,
8237  std::vector<std::shared_ptr<MaterialBase>> & face_materials,
8238  std::vector<std::shared_ptr<MaterialBase>> & neighbor_materials,
8239  std::set<MooseVariableFieldBase *> & variables,
8240  const THREAD_ID tid)
8241 {
8242  if (_materials[Moose::FACE_MATERIAL_DATA].hasActiveBlockObjects(blk_id, tid))
8243  {
8244  auto & this_face_mats =
8246  for (std::shared_ptr<MaterialBase> face_mat : this_face_mats)
8247  if (face_mat->ghostable())
8248  {
8249  mooseAssert(!face_mat->hasStatefulProperties(),
8250  "Finite volume materials do not currently support stateful properties.");
8251  face_materials.push_back(face_mat);
8252  auto & var_deps = face_mat->getMooseVariableDependencies();
8253  for (auto * var : var_deps)
8254  {
8255  mooseAssert(
8256  var->isFV(),
8257  "Ghostable materials should only have finite volume variables coupled into them.");
8258  variables.insert(var);
8259  }
8260  }
8261  }
8262 
8263  if (_materials[Moose::NEIGHBOR_MATERIAL_DATA].hasActiveBlockObjects(blk_id, tid))
8264  {
8265  auto & this_neighbor_mats =
8267  for (std::shared_ptr<MaterialBase> neighbor_mat : this_neighbor_mats)
8268  if (neighbor_mat->ghostable())
8269  {
8270  mooseAssert(!neighbor_mat->hasStatefulProperties(),
8271  "Finite volume materials do not currently support stateful properties.");
8272  neighbor_materials.push_back(neighbor_mat);
8273 #ifndef NDEBUG
8274  auto & var_deps = neighbor_mat->getMooseVariableDependencies();
8275  for (auto * var : var_deps)
8276  {
8277  mooseAssert(
8278  var->isFV(),
8279  "Ghostable materials should only have finite volume variables coupled into them.");
8280  auto pr = variables.insert(var);
8281  mooseAssert(!pr.second,
8282  "We should not have inserted any new variables dependencies from our "
8283  "neighbor materials that didn't exist for our face materials");
8284  }
8285 #endif
8286  }
8287  }
8288 }
8289 
8290 void
8292  const unsigned int nqp,
8293  const THREAD_ID tid)
8294 {
8295  getMaterialData(data_type, tid).resize(nqp);
8296 }
8297 
8298 void
8300 {
8302  // We need to setup all the nonlinear systems other than our current one which actually called
8303  // this method (so we have to make sure we don't go in a circle)
8304  for (const auto i : make_range(numNonlinearSystems()))
8305  if (i != currentNlSysNum())
8306  _nl[i]->residualSetup();
8307  // We don't setup the aux sys because that's been done elsewhere
8308  if (_displaced_problem)
8309  _displaced_problem->residualSetup();
8310 }
8311 
8312 void
8314 {
8316  // We need to setup all the nonlinear systems other than our current one which actually called
8317  // this method (so we have to make sure we don't go in a circle)
8318  for (const auto i : make_range(numNonlinearSystems()))
8319  if (i != currentNlSysNum())
8320  _nl[i]->jacobianSetup();
8321  // We don't setup the aux sys because that's been done elsewhere
8322  if (_displaced_problem)
8323  _displaced_problem->jacobianSetup();
8324 }
8325 
8328 {
8329  return mesh().coordTransform();
8330 }
8331 
8332 unsigned int
8334 {
8335  return currentNonlinearSystem().number();
8336 }
8337 
8338 bool
8340 {
8341  // For now, only support printing from thread 0
8342  if (tid != 0)
8343  return false;
8344 
8347  return true;
8348  else
8349  return false;
8350 }
8351 
8352 std::vector<MortarUserObject *>
8354  const BoundaryID secondary_boundary_id,
8355  const bool displaced,
8356  const std::vector<MortarUserObject *> & mortar_uo_superset)
8357 {
8358  std::vector<MortarUserObject *> mortar_uos;
8359  auto * const subproblem = displaced ? static_cast<SubProblem *>(_displaced_problem.get())
8360  : static_cast<SubProblem *>(this);
8361  for (auto * const obj : mortar_uo_superset)
8362  if (obj->onInterface(primary_boundary_id, secondary_boundary_id) &&
8363  (&obj->getSubProblem() == subproblem))
8364  mortar_uos.push_back(obj);
8365 
8366  return mortar_uos;
8367 }
8368 
8369 std::vector<MortarUserObject *>
8371  const BoundaryID secondary_boundary_id,
8372  const bool displaced)
8373 {
8374  std::vector<MortarUserObject *> mortar_uos;
8375  theWarehouse()
8376  .query()
8378  .queryInto(mortar_uos);
8379  return getMortarUserObjects(primary_boundary_id, secondary_boundary_id, displaced, mortar_uos);
8380 }
8381 
8382 void
8384  const BoundaryID secondary_boundary_id,
8385  const bool displaced)
8386 {
8387  const auto mortar_uos =
8388  getMortarUserObjects(primary_boundary_id, secondary_boundary_id, displaced);
8389  for (auto * const mortar_uo : mortar_uos)
8390  {
8391  mortar_uo->setNormals();
8392  mortar_uo->reinit();
8393  }
8394 }
8395 
8396 void
8397 FEProblemBase::doingPRefinement(const bool doing_p_refinement,
8398  const MultiMooseEnum & disable_p_refinement_for_families)
8399 {
8400  SubProblem::doingPRefinement(doing_p_refinement, disable_p_refinement_for_families);
8401  if (_displaced_problem)
8402  _displaced_problem->doingPRefinement(doing_p_refinement, disable_p_refinement_for_families);
8403 }
8404 
8405 void
8407 {
8408  _verbose_setup = verbose;
8409  _verbose_multiapps = verbose;
8410 }
8411 
8412 void
8413 FEProblemBase::setCurrentLowerDElem(const Elem * const lower_d_elem, const THREAD_ID tid)
8414 {
8415  SubProblem::setCurrentLowerDElem(lower_d_elem, tid);
8416  if (_displaced_problem)
8417  _displaced_problem->setCurrentLowerDElem(
8418  lower_d_elem ? _displaced_mesh->elemPtr(lower_d_elem->id()) : nullptr, tid);
8419 }
8420 
8421 void
8423 {
8425  if (_displaced_problem)
8426  _displaced_problem->setCurrentBoundaryID(bid, tid);
8427 }
ADRealVectorValue ADRealGradient
Definition: MooseTypes.h:357
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.
std::string indent(unsigned int spaces)
Create empty string for indenting.
Definition: ConsoleUtils.C:31
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:1250
void addObject(std::shared_ptr< T > object, THREAD_ID tid=0, bool recurse=true) override
Adds an object to the storage structure.
virtual void update(bool update_libmesh_system=true)
Update the system (doing libMesh magic)
Definition: SystemBase.C:1211
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:123
void sort(THREAD_ID tid=0)
Sort the objects using the DependencyResolver.
VarFieldType
Definition: MooseTypes.h:634
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:260
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.
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.
void logAdd(const std::string &system, const std::string &name, const std::string &type) const
Output information about the object just added to the problem.
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...
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.
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;.
bool isFiniteVolumeInfoDirty() const
Definition: MooseMesh.h:1282
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 computeJacobianSys(NonlinearImplicitSystem &sys, const NumericVector< Number > &soln, SparseMatrix< Number > &jacobian)
Form a Jacobian matrix.
virtual void clearActiveFEVariableCoupleableMatrixTags(const THREAD_ID tid)
Definition: SubProblem.C:350
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)
virtual void clearActiveFEVariableCoupleableVectorTags(const THREAD_ID tid)
Definition: SubProblem.C:344
bool _requires_nonlocal_coupling
nonlocal coupling requirement flag
Definition: SubProblem.h:1017
ConstElemRange * getActiveLocalElementRange()
Return pointers to range objects for various types of ranges (local nodes, boundary elems...
Definition: MooseMesh.C:1040
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:1044
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:37
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 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:368
A MultiMooseEnum object to hold "execute_on" flags.
Definition: ExecFlagEnum.h:21
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
virtual void disassociateVectorFromTag(NumericVector< Number > &vec, TagID tag)
Disassociate a given vector from a given tag.
Definition: SystemBase.C:942
bool isUltimateMaster() const
Whether or not this app is the ultimate master app.
Definition: MooseApp.h:805
virtual void addJacobianLowerD(const THREAD_ID tid) override
Factory & _factory
The Factory for building objects.
Definition: SubProblem.h:972
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
SolverParams _solver_params
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)
SolverParams & solverParams()
Get the solver parameters.
virtual void addJacobianBlockTags(SparseMatrix< 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 checkDependMaterialsHelper(const std::map< SubdomainID, std::vector< std::shared_ptr< MaterialBase >>> &materials_map)
Helper method for checking Material object dependency.
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)
int _nl_forced_its
the number of forced nonlinear iterations
ExecFlagType _current_execute_on_flag
Current execute_on flag.
void clearCurrentResidualVectorTags()
Clear the current residual vector tag data structure.
unsigned int max() const
Definition: MaxQpsThread.h:39
bool hasActiveBlockObjects(THREAD_ID tid=0) const
QueryCache is a convenient way to construct and pass around (possible partially constructed) warehous...
Definition: TheWarehouse.h:208
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:908
RelationshipManagerType
Main types of Relationship Managers.
Definition: MooseTypes.h:876
bool hasVector(const std::string &tag_name) const
Check if the named vector exists in the system.
Definition: SystemBase.C:873
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:3247
void mooseDeprecated(Args &&... args) const
LAGRANGE_VEC
const std::string & name() const
Definition: MooseEnumItem.h:35
bool duplicateVariableCheck(const std::string &var_name, const FEType &type, bool is_aux)
Helper to check for duplicate variable names across systems or within a single system.
virtual bool converged(const unsigned int nl_sys_num)
Eventually we want to convert this virtual over to taking a nonlinear system number argument...
Definition: SubProblem.h:101
Class for stuff related to variables.
Definition: Adaptivity.h:31
MooseAppCoordTransform & coordTransform()
virtual void setActiveFEVariableCoupleableMatrixTags(std::set< TagID > &mtags, const THREAD_ID tid) override
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
virtual void reinitElemFaceRef(const Elem *elem, unsigned int side, BoundaryID bnd_id, 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...
SCALAR
const std::map< SubdomainID, std::vector< std::shared_ptr< T > > > & getActiveBlockObjects(THREAD_ID tid=0) const
unsigned int TagID
Definition: MooseTypes.h:199
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 Elem * elemPtr(const dof_id_type i)
Definition: MooseMesh.C:2863
MPI_Datatype data_type
TagID systemMatrixTag() const override
Return the Matrix Tag ID for System.
NumericVector< Number > & solution()
Definition: SystemBase.h:176
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:266
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...
virtual void computeNullSpace(NonlinearImplicitSystem &sys, std::vector< NumericVector< Number > *> &sp)
bool _has_dampers
Whether or not this system has any Dampers associated with it.
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:1008
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.
virtual void setSolution(const NumericVector< Number > &soln)
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
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:413
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 ...
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:500
void joinAndFinalize(TheWarehouse::Query query, bool isgen=false)
DISCRETE_L2
bool hasInitialBackup() const
Definition: MooseApp.h:990
std::vector< MooseArray< ADRealVectorValue > > _ad_grad_zero
InputParameterWarehouse & getInputParameterWarehouse()
Get the InputParameterWarehouse for MooseObjects.
Definition: MooseApp.C:2218
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 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.
std::unique_ptr< ConstElemRange > _evaluable_local_elem_range
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:218
const ExecFlagType & getCurrentExecuteOnFlag() const
Return/set the current execution flag.
unsigned int _cycles_completed
bool _currently_computing_jacobian
Flag to determine whether the problem is currently computing Jacobian.
Definition: SubProblem.h:1026
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:983
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:98
virtual void setResidualNeighbor(NumericVector< Number > &residual, const THREAD_ID tid) override
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:409
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:753
virtual void addInterfaceKernel(const std::string &kernel_name, const std::string &name, InputParameters &parameters)
virtual void neighborSubdomainSetup(THREAD_ID tid=0) const
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:111
virtual void setCurrentLowerDElem(const Elem *const lower_d_elem, const THREAD_ID tid)
Set the current lower dimensional element.
Definition: SubProblem.C:1318
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:1483
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.
StoredRange< MooseMesh::const_bnd_elem_iterator, const BndElement * > ConstBndElemRange
Definition: MooseMesh.h:2027
void updateErrorVectors()
Update the ErrorVectors that have been requested through calls to getErrorVector().
Definition: Adaptivity.C:363
FORTYTHIRD
virtual TagID addVectorTag(const TagName &tag_name, const Moose::VectorTagType type=Moose::VECTOR_TAG_RESIDUAL)
Create a Tag.
Definition: SubProblem.C:81
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
std::vector< std::unique_ptr< CouplingMatrix > > _cm
Coupling matrix for variables.
void trustUserCouplingMatrix()
Whether to trust the user coupling matrix even if we want to do things like be paranoid and create a ...
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:420
This is a template class that implements the workhorse compute and computeNodal methods.
virtual void stopSolve(const ExecFlagType &exec_flag)=0
Quit the current solve as soon as possible.
void addMeshDivision(const std::string &type, const std::string &name, InputParameters &params)
Add a MeshDivision.
const ExecFlagType EXEC_NONE
Definition: Moose.C:27
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:604
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.
virtual void addCachedJacobian(const THREAD_ID tid)
Definition: SubProblem.C:1271
const std::string & getBoundaryName(BoundaryID boundary_id)
Return the name of the boundary given the id.
Definition: MooseMesh.C:1566
void cacheChangedLists()
Cache information about what elements were refined and coarsened in the previous step.
Definition: MooseMesh.C:715
virtual void residualSetup()
Definition: SubProblem.C:1146
Positions objects are under the hood Reporters.
Definition: Positions.h:19
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 void associateVectorToTag(NumericVector< Number > &vec, TagID tag)
Associate a vector for a given tag.
Definition: SystemBase.C:930
std::shared_ptr< MooseObject > create(const std::string &obj_name, const std::string &name, const InputParameters &parameters, THREAD_ID tid=0, bool print_deprecated=true)
Definition: Factory.C:110
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 bool checkRelativeConvergence(const PetscInt it, const Real fnorm, const Real the_residual, const Real rtol, const Real abstol, std::ostringstream &oss)
Check the relative convergence of the nonlinear solution.
virtual void computeIndicatorsAndMarkers()
Definition: Marker.h:35
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:1289
std::filesystem::path restartFolderBase(const std::filesystem::path &folder_base) const
The file suffix for restartable data.
Definition: MooseApp.C:2405
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
const SubdomainID BOUNDARY_SIDE_LOWERD_ID
Definition: MooseTypes.C:21
unsigned int multiAppLevel() const
The MultiApp Level.
Definition: MooseApp.h:794
bool isReservedName(const std::string &name)
Test if the given name is reserved.
InputParameters getValidParams(const std::string &name) const
Get valid parameters for the object.
Definition: Factory.C:67
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:73
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...
bool computingScalingJacobian() const
Whether we are computing an initial Jacobian for automatic variable scaling.
Definition: SystemBase.C:1481
TODO: delete this later - it is a temporary hack for dealing with inter-system dependencies.
Definition: Attributes.h:313
void applyParameters(const InputParameters &common, const std::vector< std::string > &exclude={}, const bool allow_private=false)
Method for applying common parameters.
virtual void createQRules(QuadratureType type, Order order, Order volume_order=INVALID_ORDER, Order face_order=INVALID_ORDER, SubdomainID block=Moose::ANY_BLOCK_ID, bool allow_negative_qweights=true)
bool initialized() const
Definition: MortarData.h:127
const Parallel::Communicator & comm() const
virtual void computeBounds(NonlinearImplicitSystem &sys, NumericVector< Number > &lower, NumericVector< Number > &upper)
RealTensorValue RealTensor
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...
MultiApp Implementation for Transient Apps.
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.
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::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:328
virtual void onTimestepEnd() override
virtual void addNodalKernel(const std::string &kernel_name, const std::string &name, InputParameters &parameters)
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:733
std::vector< VectorVariableCurl > _vector_curl_zero
virtual bool updateSolution(NumericVector< Number > &vec_solution, NumericVector< Number > &ghosted_solution)
Update the solution.
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:266
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.
bool haveXFEM()
Find out whether the current analysis is using XFEM.
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:1154
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:284
Thread to compute threaded general user objects.
virtual void computeJacobianTag(const NumericVector< Number > &soln, SparseMatrix< Number > &jacobian, TagID tag)
Form a Jacobian matrix for a given tag.
void setup(const ExecFlagType &exec_flag, THREAD_ID tid=0) const
void setCurrentExecuteOnFlag(const ExecFlagType &)
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:1394
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)
ExodusII_IO * getExReaderForRestart() const
Get the Exodus reader to restart variables from an Exodus mesh file.
Definition: MooseApp.h:435
Base class for a system (of equations)
Definition: SystemBase.h:84
const ExecFlagType EXEC_ALWAYS
Definition: Moose.C:43
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:94
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:662
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:1167
void petscSetOptions(const PetscOptions &po, const SolverParams &solver_params)
A function for setting the PETSc options in PETSc from the options supplied to MOOSE.
Definition: PetscSupport.C:238
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.
ConstNodeRange * getLocalNodeRange()
Definition: MooseMesh.C:1077
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:146
void prepareScalar()
Definition: Assembly.C:2941
bool isOn()
Is adaptivity on?
Definition: Adaptivity.h:179
void computeResidualTags(const std::set< TagID > &tags)
Form multiple tag-associated residual vectors for all the given tags.
virtual void cacheJacobianNeighbor(const THREAD_ID tid) override
Specialization of SubProblem for solving nonlinear equations plus auxiliary equations.
virtual void clearActiveElementalMooseVariables(const THREAD_ID tid)
Clear the active elemental MooseVariableFieldBase.
Definition: SubProblem.C:432
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:636
std::set< dof_id_type > _ghosted_elems
Elements that should have Dofs ghosted to the local processor.
Definition: SubProblem.h:1023
ExecFlagEnum _print_execution_on
When to print the execution of loops.
std::vector< CouplingMatrix > _nonlocal_cm
Definition: SubProblem.h:974
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:1122
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.
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:1537
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
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...
StoredRange< MeshBase::const_element_iterator, const Elem *> ConstElemRange
auto max(const L &left, const R &right)
virtual void newAssemblyArray(std::vector< std::shared_ptr< NonlinearSystemBase >> &nl)
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
AuxGroup
Flag for AuxKernel related execution type.
Definition: MooseTypes.h:616
virtual Elem * queryElemPtr(const dof_id_type i)
Definition: MooseMesh.C:2875
virtual void addMarker(const std::string &marker_name, const std::string &name, InputParameters &parameters)
MONOMIAL_VEC
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:1310
void setCurrentlyComputingJacobian(const bool currently_computing_jacobian)
Set whether or not the problem is in the process of computing the Jacobian.
Definition: SubProblem.h:644
virtual Real computeDamping(const NumericVector< Number > &soln, const NumericVector< Number > &update)
virtual void computeJacobian(const NumericVector< Number > &soln, SparseMatrix< Number > &jacobian, const unsigned int nl_sys_num)
Form a Jacobian matrix with the default tag (system).
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:1032
virtual EquationSystems & es() override
This class is a container/interface for the objects involved in automatic generation of mortar spaces...
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)
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
ScalarInitialConditionWarehouse _scalar_ics
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:425
virtual void swapBackMaterialsFace(const THREAD_ID tid)
ADRealEigenVector< T, D, asd > abs(const ADRealEigenVector< T, D, asd > &)
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.
Real _nl_abs_div_tol
the absolute non linear divergence tolerance
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:1138
virtual void checkBoundaryMatProps()
Checks boundary material properties integrity.
Definition: SubProblem.C:631
std::map< std::string, std::vector< dof_id_type > > _var_dof_map
Definition: SubProblem.h:629
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 bool nlConverged(const unsigned int nl_sys_num) override
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()
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 setActiveScalarVariableCoupleableVectorTags(std::set< TagID > &vtags, const THREAD_ID tid)
Definition: SubProblem.C:375
virtual void prepareFaceShapes(unsigned int var, const THREAD_ID tid) override
unsigned int _n_max_nl_pingpong
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:1107
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.
std::map< std::pair< BoundaryID, BoundaryID >, NearestNodeLocator * > _nearest_node_locators
std::vector< VariablePhiGradient > _grad_phi_zero
void initialSetup(THREAD_ID tid)
Initial setup.
virtual void addCachedResidualDirectly(NumericVector< Number > &residual, const THREAD_ID tid)
Allows for all the residual contributions that are currently cached to be added directly into the vec...
bool hasJacobian() const
Returns _has_jacobian.
void createTagSolutions()
Create extra tagged solution vectors.
bool contains(const std::string &value) const
Contains methods for seeing if a value is in the MultiMooseEnum.
virtual void execute(const ExecFlagType &exec_type)
Convenience function for performing execution of MOOSE systems.
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:498
void computeResidualAndJacobianTags(const std::set< TagID > &vector_tags, const std::set< TagID > &matrix_tags)
Form possibly multiple tag-associated vectors and matrices.
void extraSparsity(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:42
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
virtual void reinitNeighborFaceRef(const Elem *neighbor_elem, unsigned int neighbor_side, BoundaryID bnd_id, 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:871
void uniformRefine()
uniformly refine the problem mesh(es).
const ReporterData & getReporterData() const
Provides const access the ReporterData object.
virtual void computeResidualTag(const NumericVector< Number > &soln, NumericVector< Number > &residual, TagID tag)
Form a residual vector for a given tag.
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 setResidual(NumericVector< Number > &residual, const THREAD_ID tid) override
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...
bool havePRefinement() const
Query whether p-refinement has been requested at any point during the simulation. ...
Definition: SubProblem.h:940
bool getRecomputeMarkersFlag() const
Pull out the _recompute_markers_during_cycles flag previously set through the AdaptivityAction.
Definition: Adaptivity.h:124
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.
virtual void nonlinearConvergenceSetup()
Perform steps required before checking nonlinear convergence.
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.
Interface for notifications that the mesh has changed.
void computeTimeDerivatives(bool jacobian_calculation=false)
Computes the time derivative vector.
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)
void computeResidualAndJacobian(const NumericVector< Number > &soln, NumericVector< Number > &residual, SparseMatrix< Number > &jacobian)
Form a residual and Jacobian with default tags.
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...
Real value(unsigned n, unsigned alpha, unsigned beta, Real x)
MeshBase & getMesh()
Accessor for the underlying libMesh Mesh object.
Definition: MooseMesh.C:3198
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:379
void indentMessage(const std::string &prefix, std::string &message, const char *color=COLOR_CYAN, bool dont_indent_first_line=true, const std::string &post_prefix=": ")
Indents the supplied message given the prefix and color.
Definition: MooseUtils.C:724
TheWarehouse & theWarehouse() const
virtual void computeResidualType(const NumericVector< Number > &soln, NumericVector< Number > &residual, TagID tag)
Form a residual vector for a given tag and "residual" tag.
void createTagVectors()
Create extra tagged vectors and matrices.
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:33
void parallelBarrierNotify(const libMesh::Parallel::Communicator &comm, bool messaging=true)
This function implements a parallel barrier function but writes progress to stdout.
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:335
void extraSendList(std::vector< dof_id_type > &send_list, void *context)
///< Type of coordinate system
Definition: SystemBase.C:34
virtual void reinitElemFace(const Elem *elem, unsigned int side, BoundaryID bnd_id, const THREAD_ID tid) override
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:385
Real getTimeFromStateArg(const Moose::StateArg &state) const
Returns the time associated with the requested state.
const ExecFlagType EXEC_TIMESTEP_BEGIN
Definition: Moose.C:33
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.
bool _safe_access_tagged_vectors
Is it safe to retrieve data from tagged vectors.
Definition: SubProblem.h:1041
std::optional< std::string > queryStatefulPropName(const unsigned int id) const
virtual void reinitNeighborPhys(const Elem *neighbor, unsigned int neighbor_side, const std::vector< Point > &physical_points, const THREAD_ID tid) override
GHOSTED
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 setCouplingMatrix(std::unique_ptr< CouplingMatrix > cm, const unsigned int nl_sys_num)
Set custom coupling matrix.
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.
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:627
NonlinearSystemBase & currentNonlinearSystem()
SimpleRange< IndexType > as_range(const std::pair< IndexType, IndexType > &p)
Jacobian-Free Newton Krylov.
Definition: MooseTypes.h:758
void groupUserObjects(TheWarehouse &w, AuxiliarySystem &aux, const ExecFlagEnum &execute_flags, const std::vector< T *> &objs, const std::set< std::string > &ic_deps)
virtual void predictorCleanup(NumericVector< Number > &ghosted_solution)
Perform cleanup tasks after application of predictor to solution vector.
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:191
virtual void addJacobianNeighbor(const THREAD_ID tid) override
virtual TagID addMatrixTag(TagName tag_name)
Create a Tag.
Definition: SubProblem.C:277
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:2230
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 associateMatrixToTag(SparseMatrix< Number > &matrix, TagID tag)
Associate a matrix to a tag.
Definition: SystemBase.C:1025
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 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 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:589
void restoreFromInitialBackup(const bool for_restart)
Restores from a "initial" backup, that is, one set in _initial_backup.
Definition: MooseApp.C:1269
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:31
void reinit()
Completely redo all geometric search objects.
Adaptivity _adaptivity
std::vector< VectorTag > getVectorTags(const std::set< TagID > &tag_ids) const
Definition: SubProblem.C:149
virtual const SystemBase & systemBaseAuxiliary() const override
Return the auxiliary system object as a base class reference.
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 computePostCheck(NonlinearImplicitSystem &sys, const NumericVector< Number > &old_soln, NumericVector< Number > &search_direction, NumericVector< Number > &new_soln, bool &changed_search_direction, bool &changed_new_soln)
virtual void addTimeIntegrator(const std::string &type, const std::string &name, InputParameters &parameters)
virtual void cacheResidual(const THREAD_ID tid) override
const bool _force_restart
void checkCoordinateSystems()
Performs a sanity check for every element in the mesh.
Definition: MooseMesh.C:4023
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
virtual void reinitElemFaceRef(const Elem *elem, unsigned int side, BoundaryID bnd_id, 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:831
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 MooseNonlinearConvergenceReason checkNonlinearConvergence(std::string &msg, const PetscInt it, const Real xnorm, const Real snorm, const Real fnorm, const Real rtol, const Real divtol, const Real stol, const Real abstol, const PetscInt nfuncs, const PetscInt max_funcs, const Real initial_residual_before_preset_bcs, const Real div_threshold)
Check for convergence of the nonlinear solution.
virtual bool vectorTagExists(const TagID tag_id) const
Check to see if a particular Tag exists.
Definition: SubProblem.h:163
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
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:3823
void initElementStatefulProps(const ConstElemRange &elem_range, const bool threaded)
Initialize stateful properties for elements in a specific elem_range This is needed when elements/bou...
Base class for all Postprocessors.
Definition: Postprocessor.h:23
virtual System & system()=0
Get the reference to the libMesh system.
void clearPoints()
Remove all of the current points and elements.
MooseApp & _app
The MOOSE application this is associated with.
Definition: MooseBase.h:84
virtual void clearActiveFEVariableCoupleableVectorTags(const THREAD_ID tid) override
void maxloc(T &r, unsigned int &max_id) const
unsigned int number() const
Gets the number of this system.
Definition: SystemBase.C:1125
virtual void addAuxArrayVariable(const std::string &var_name, const FEType &type, unsigned int components, const std::set< SubdomainID > *const active_subdomains=NULL)
bool _verbose_setup
Whether or not to be verbose during setup.
INVALID_ORDER
unsigned int uniformRefineLevel() const
Returns the level of uniform refinement requested (zero if AMR is disabled).
Definition: MooseMesh.C:2966
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
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.
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:472
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
bool _kernel_coverage_check
Determines whether a check to verify an active kernel on every subdomain.
MooseObjectWarehouse< MeshDivision > _mesh_divisions
Warehouse to store mesh divisions NOTE: this could probably be moved to the MooseMesh instead of the ...
libMesh::TensorValue< ADReal > ADRealTensorValue
Definition: MooseTypes.h:359
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:2209
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:726
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:2801
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:391
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:215
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:800
Executioner * getExecutioner() const
Retrieve the Executioner for this App.
Definition: MooseApp.C:1476
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
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:1312
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:293
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
virtual void cacheJacobianNeighbor(const THREAD_ID tid)
Definition: SubProblem.C:1265
MONOMIAL
void setVectorPostprocessorValueByName(const std::string &object_name, const std::string &vector_name, const VectorPostprocessorValue &value, std::size_t t_index=0)
Set the value of a VectorPostprocessor vector.
virtual MooseVariable & getStandardVariable(const THREAD_ID tid, const std::string &var_name) override
Returns the variable reference for requested MooseVariable which may be in any system.
virtual void initialSetup(THREAD_ID tid=0) const
Convenience methods for calling object setup methods that handle the extra neighbor and face objects...
void setCoordSystem(const std::vector< SubdomainName > &blocks, const MultiMooseEnum &coord_sys)
const NumericVector< Number > *const & currentSolution() const override
The solution vector that is currently being operated on.
virtual void swapBackMaterialsNeighbor(const THREAD_ID tid)
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:1830
bool have_parameter(std::string_view name) const
A wrapper around the Parameters base class method.
virtual void computeJacobianInternal(const NumericVector< Number > &soln, SparseMatrix< Number > &jacobian, const std::set< TagID > &tags)
Form a Jacobian matrix for multiple tags.
virtual void cacheResidual(const THREAD_ID tid)
Definition: SubProblem.C:1236
virtual void timestepSetup()
Definition: SubProblem.C:1130
MooseNonlinearConvergenceReason
Enumeration for nonlinear convergence reasons.
Definition: FEProblemBase.h:98
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:44
virtual void disassociateMatrixFromTag(SparseMatrix< Number > &matrix, TagID tag)
Disassociate a matrix from a tag.
Definition: SystemBase.C:1037
bool _compute_initial_residual_before_preset_bcs
const std::vector< NonlinearSystemName > _nl_sys_names
The nonlinear system names.
const ExecFlagType EXEC_POSTCHECK
Definition: Moose.C:31
query_obj query
PetscErrorCode PetscInt const PetscInt fields[]
void projectInitialConditionOnCustomRange(ConstElemRange &elem_range, ConstBndNodeRange &bnd_node_range)
Project initial conditions for custom elem_range and bnd_node_range This is needed when elements/boun...
const ExecFlagType EXEC_NONLINEAR
Definition: Moose.C:30
bool isParamSetByUser(const std::string &name) const
Method returns true if the parameter was by the user.
std::vector< Real > VectorPostprocessorValue
Definition: MooseTypes.h:192
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
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:745
void restore(const std::filesystem::path &folder_base, const bool for_restart)
Restore an application from file.
Definition: MooseApp.C:1234
std::set< TagID > _fe_matrix_tags
const ExecuteMooseObjectWarehouse< Transfer > & getMultiAppTransferWarehouse(Transfer::DIRECTION direction) const
Return the complete warehouse for MultiAppTransfer object for the given direction.
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:1465
void removeSubstring(std::string &main, const std::string &sub)
find, erase, length algorithm for removing a substring from a string
Definition: MooseUtils.C:1256
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
virtual void initialSetup()
Definition: SubProblem.C:1162
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
RAVIART_THOMAS
virtual void addAuxScalarVariable(const std::string &var_name, Order order, Real scale_factor=1., const std::set< SubdomainID > *const active_subdomains=NULL)
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
virtual std::shared_ptr< const DisplacedProblem > getDisplacedProblem() const
Generic class for solving transient nonlinear problems.
Definition: SubProblem.h:75
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:753
void clearCurrentJacobianVectorTags()
Clear the current Jacobian vector tag data structure ...
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:985
Class for containing MooseEnum item information.
Definition: MooseEnumItem.h:18
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< Number > &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
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:97
void max(const T &r, T &o, Request &req) const
void reinitMaterials(SubdomainID blk_id, const THREAD_ID tid, bool swap_stateful=true)
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 ...
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 SparseMatrix< Number > & getMatrix(TagID tag)
Get a raw SparseMatrix.
Definition: SystemBase.C:973
void execMultiAppTransfers(ExecFlagType type, Transfer::DIRECTION direction)
Execute MultiAppTransfers associated with execution flag and direction.
const SubdomainID INTERNAL_SIDE_LOWERD_ID
Definition: MooseTypes.C:20
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 prepare(const Elem *elem, const THREAD_ID tid) override
void subdomainSetup()
Calls the subdomainSetup function for each of the output objects.
std::pair< bool, unsigned int > determineNonlinearSystem(const std::string &var_name, bool error_if_not_found=false) const override
Determine what nonlinear system the provided variable name lies in.
const std::vector< dof_id_type > & allDofIndices() const
Get all global dofindices for the variable.
virtual void computeAuxiliaryKernels(const ExecFlagType &type)
Call compute methods on AuxKernels.
void addMaterialPropertyStorage(MaterialPropertyStorage &mat_props)
Pushes the given pair ( mat_data , mat_props ) onto our list of _materials data to redistribute each ...
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 initNonlocalCoupling()
Create pair of variables requiring nonlocal jacobian contributions.
Definition: Assembly.C:2643
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:279
virtual void onTimestepBegin() override
Nonlinear system to be solved.
void checkDuplicatePostprocessorVariableNames()
void setAxisymmetricCoordAxis(const MooseEnum &rz_coord_axis)
For axisymmetric simulations, set the symmetry coordinate axis.
Definition: MooseMesh.C:3929
void addOutput(std::shared_ptr< Output > output)
Adds an existing output object to the warehouse.
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)
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.
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)
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:643
const ExecFlagType EXEC_SAME_AS_MULTIAPP
Definition: Moose.C:45
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 void saveOldSolutions()
Allocate vectors and save old solutions into them.
virtual void setActiveFEVariableCoupleableMatrixTags(std::set< TagID > &mtags, const THREAD_ID tid)
Definition: SubProblem.C:329
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.
MaterialData & getMaterialData(const THREAD_ID tid)
bool hasPostprocessor(const std::string &name) const
Deprecated.
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 option parameter and a documentation string to the InputParameters object...
virtual bool computingInitialResidual(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 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)
bool needInterfaceMaterialOnSide(BoundaryID bnd_id, const THREAD_ID tid)
virtual void cacheResidualNeighbor(const THREAD_ID tid)
Definition: SubProblem.C:1243
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:436
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...
QueryCache & condition(Args &&... args)
Adds a new condition to the query.
Definition: TheWarehouse.h:284
const TagName SOLUTION_TAG
Definition: MooseTypes.C:27
unsigned int _max_qps
Maximum number of quadrature points used in the problem.
A class for storing an input parameter name.
static InputParameters validParams()
Eigen::Matrix< Real, Eigen::Dynamic, 1 > RealEigenVector
Definition: MooseTypes.h:138
virtual void addScalarKernel(const std::string &kernel_name, const std::string &name, InputParameters &parameters)
elem_info_iterator ownedElemInfoEnd()
Definition: MooseMesh.C:1318
std::set< const Elem * > & getElements()
Returns a writeable reference to the _elements container.
virtual void set(const numeric_index_type i, const Number value)=0
void addGhostedBoundary(BoundaryID boundary_id)
This will add the boundary ids to be ghosted to this processor.
Definition: MooseMesh.C:2979
void bumpAllQRuleOrder(Order order, SubdomainID block)
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.
bool isAdaptivityDue()
Query if an adaptivity step should be performed at the current time / time step.
Definition: Adaptivity.C:384
MaterialPropertyStorage & _neighbor_material_props
std::unique_ptr< Backup > finalizeRestore()
Finalizes (closes) the restoration process done in restore().
Definition: MooseApp.C:1276
StoredRange< MooseMesh::const_bnd_elem_iterator, const BndElement * > * getBoundaryElementRange()
Definition: MooseMesh.C:1105
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.
std::map< std::string, unsigned int > _subspace_dim
Dimension of the subspace spanned by the vectors with a given prefix.
const ConstElemRange & getEvaluableElementRange()
In general, {evaluable elements} >= {local elements} U {algebraic ghosting elements}.
static InputParameters validParams()
Definition: SubProblem.C:33
unsigned int _n_nl_pingpong
maximum numbver
bool _currently_computing_residual
Whether the residual is being evaluated.
Definition: SubProblem.h:1035
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 It sho...
MooseVariableFieldBase & getVariable(THREAD_ID tid, const std::string &var_name) const
Gets a reference to a variable of with specified name.
Definition: SystemBase.C:79
bool _has_internal_edge_residual_objects
Whether the problem has dgkernels or interface kernels.
NEDELEC_ONE
bool execMultiApps(ExecFlagType type, bool auto_advance=true)
Execute the MultiApps associated with the ExecFlagType.
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:42
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.
StoredRange< MooseMesh::const_bnd_node_iterator, const BndNode * > ConstBndNodeRange
Some useful StoredRange typedefs.
Definition: MooseMesh.h:2026
virtual void reinitNeighbor(const Elem *elem, unsigned int side, const THREAD_ID tid) override
const bool & currentlyComputingJacobian() const
Returns true if the problem is in the process of computing the Jacobian.
Definition: SubProblem.h:639
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:739
const Moose::PatchUpdateType & getPatchUpdateStrategy() const
Get the current patch update strategy.
Definition: MooseMesh.C:3163
void computeResidual(NonlinearImplicitSystem &sys, const NumericVector< Number > &soln, NumericVector< Number > &residual)
This function is called by Libmesh to form a residual.
virtual void executeAllObjects(const ExecFlagType &exec_type)
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:3064
virtual void computeJacobianBlock(SparseMatrix< Number > &jacobian, libMesh::System &precond_system, unsigned int ivar, unsigned int jvar)
Really not a good idea to use this.
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 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 Number value)=0
bool _safe_access_tagged_matrices
Is it safe to retrieve data from tagged matrices.
Definition: SubProblem.h:1038
Class that represents the dependecy as a graph.
DiracKernelInfo _dirac_kernel_info
nonlocal coupling matrix;
Definition: SubProblem.h:976
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:30
void updateBoundaryVariableDependency(std::set< MooseVariableFieldBase *> &needed_moose_vars, THREAD_ID tid=0) const
processor_id_type processor_id() const
Assembly & assembly(const THREAD_ID tid, const unsigned int nl_sys_num) override
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 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.
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)
virtual void addGhostedBoundary(BoundaryID boundary_id) override
Will make sure that all necessary elements from boundary_id are ghosted to this processor.
virtual void reinitNeighborFaceRef(const Elem *neighbor_elem, unsigned int neighbor_side, BoundaryID bnd_id, 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...
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:1161
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)
void jacobianSetup() override
virtual NumericVector< Number > & getVector(const std::string &name)
Get a raw NumericVector by name.
Definition: SystemBase.C:882
Restartable::ManagedValue< RestartableEquationSystems > _req
The EquationSystems object, wrapped for restart.
virtual void reinitNodeFace(const Node *node, BoundaryID bnd_id, const THREAD_ID tid) override
virtual void reinitOffDiagScalars(const THREAD_ID tid) override
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.
std::string getRestartRecoverFileBase() const
The file_base for the recovery file.
Definition: MooseApp.h:486
virtual void computeResidualSys(NonlinearImplicitSystem &sys, const NumericVector< Number > &soln, NumericVector< Number > &residual)
This function is called by Libmesh to form a residual.
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 const VectorTag & getVectorTag(const TagID tag_id) const
Get a VectorTag from a TagID.
Definition: SubProblem.C:138
MaterialBases compute MaterialProperties.
Definition: MaterialBase.h:60
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)
bool _material_coverage_check
Determines whether a check to verify an active material on every subdomain.
This is a template class that implements the workhorse compute and computeNodal methods.
Order _max_scalar_order
Maximum scalar variable order.
MaterialWarehouse _all_materials
void bumpVolumeQRuleOrder(Order order, SubdomainID block)
Increases the element/volume quadrature order for the specified mesh block if and only if the current...
const MeshBase::element_iterator activeLocalElementsEnd()
Definition: MooseMesh.C:2807
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.
StoredRange< MooseMesh::const_bnd_node_iterator, const BndNode * > * getBoundaryNodeRange()
Definition: MooseMesh.C:1091
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:1257
virtual Sampler & getSampler(const std::string &name, const THREAD_ID tid=0)
std::map< NonlinearVariableName, unsigned int > _nl_var_to_sys_num
Map from nonlinear variable name to nonlinear system number.
virtual void outputStep(ExecFlagType type)
Output the current step.
std::unique_ptr< ConstElemRange > _nl_evaluable_local_elem_range
virtual unsigned int nlSysNum(const NonlinearSystemName &nl_sys_name) const override
OutputWarehouse & getOutputWarehouse()
Get the OutputWarehouse objects.
Definition: MooseApp.C:1766
virtual void computeTransposeNullSpace(NonlinearImplicitSystem &sys, std::vector< NumericVector< Number > *> &sp)
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.
virtual void computeNearNullSpace(NonlinearImplicitSystem &sys, std::vector< NumericVector< Number > *> &sp)
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.
Order getMaxScalarOrder() const
void execTransfers(ExecFlagType type)
Execute the Transfers associated with the ExecFlagType.
void meshChanged()
Declares that the MooseMesh has changed, invalidates cached data and rebuilds caches.
Definition: MooseMesh.C:684
virtual void computeResidualInternal(const NumericVector< Number > &soln, NumericVector< Number > &residual, const std::set< TagID > &tags)
Form a residual vector for a set of tags.
void buildPRefinementAndCoarseningMaps(Assembly *assembly)
Definition: MooseMesh.C:2111
unsigned int THREAD_ID
Definition: MooseTypes.h:198
virtual void ghostGhostedBoundaries() override
Causes the boundaries added using addGhostedBoundary to actually be ghosted.
virtual void setNeighborSubdomainID(const Elem *elem, unsigned int side, const THREAD_ID tid) override
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 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:2921
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:3814
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)
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:794