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 void
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 
3880 const UserObject &
3881 FEProblemBase::getUserObjectBase(const std::string & name, const THREAD_ID tid /* = 0 */) const
3882 {
3883  std::vector<UserObject *> objs;
3884  theWarehouse()
3885  .query()
3886  .condition<AttribSystem>("UserObject")
3887  .condition<AttribThread>(tid)
3888  .condition<AttribName>(name)
3889  .queryInto(objs);
3890  if (objs.empty())
3891  mooseError("Unable to find user object with name '" + name + "'");
3892  mooseAssert(objs.size() == 1, "Should only find one UO");
3893  return *(objs[0]);
3894 }
3895 
3896 const Positions &
3897 FEProblemBase::getPositionsObject(const std::string & name) const
3898 {
3899  std::vector<Positions *> objs;
3900  theWarehouse()
3901  .query()
3902  .condition<AttribSystem>("UserObject")
3903  .condition<AttribName>(name)
3904  .queryInto(objs);
3905  if (objs.empty())
3906  mooseError("Unable to find Positions object with name '" + name + "'");
3907  mooseAssert(objs.size() == 1, "Should only find one Positions");
3908  return *(objs[0]);
3909 }
3910 
3911 bool
3912 FEProblemBase::hasUserObject(const std::string & name) const
3913 {
3914  std::vector<UserObject *> objs;
3915  theWarehouse()
3916  .query()
3917  .condition<AttribSystem>("UserObject")
3918  .condition<AttribThread>(0)
3919  .condition<AttribName>(name)
3920  .queryInto(objs);
3921  return !objs.empty();
3922 }
3923 
3924 bool
3925 FEProblemBase::hasPostprocessorValueByName(const PostprocessorName & name) const
3926 {
3928 }
3929 
3930 const PostprocessorValue &
3931 FEProblemBase::getPostprocessorValueByName(const PostprocessorName & name,
3932  std::size_t t_index) const
3933 {
3935  t_index);
3936 }
3937 
3938 void
3939 FEProblemBase::setPostprocessorValueByName(const PostprocessorName & name,
3940  const PostprocessorValue & value,
3941  std::size_t t_index)
3942 {
3944  PostprocessorReporterName(name), value, t_index);
3945 }
3946 
3947 bool
3948 FEProblemBase::hasPostprocessor(const std::string & name) const
3949 {
3950  mooseDeprecated("FEProblemBase::hasPostprocssor is being removed; use "
3951  "hasPostprocessorValueByName instead.");
3953 }
3954 
3957  const std::string & vector_name,
3958  std::size_t t_index) const
3959 {
3961  VectorPostprocessorReporterName(object_name, vector_name), t_index);
3962 }
3963 
3964 void
3966  const std::string & vector_name,
3967  const VectorPostprocessorValue & value,
3968  std::size_t t_index)
3969 {
3971  VectorPostprocessorReporterName(object_name, vector_name), value, t_index);
3972 }
3973 
3974 const VectorPostprocessor &
3976  const THREAD_ID tid) const
3977 {
3978  return getUserObject<VectorPostprocessor>(object_name, tid);
3979 }
3980 
3981 void
3983 {
3984  for (const auto & it : _multi_apps)
3985  {
3986  const auto & objects = it.second.getActiveObjects();
3987  for (const auto & obj : objects)
3988  obj->parentOutputPositionChanged();
3989  }
3990 }
3991 
3992 void
3994 {
3996  computeMarkers();
3997 }
3998 
3999 void
4001 {
4002  // Initialize indicator aux variable fields
4004  {
4005  TIME_SECTION("computeIndicators", 1, "Computing Indicators");
4006 
4007  // Internal side indicators may lead to creating a much larger sparsity pattern than dictated by
4008  // the actual finite element scheme (e.g. CFEM)
4009  const auto old_do_derivatives = ADReal::do_derivatives;
4010  ADReal::do_derivatives = false;
4011 
4012  std::vector<std::string> fields;
4013 
4014  // Indicator Fields
4015  const auto & indicators = _indicators.getActiveObjects();
4016  for (const auto & indicator : indicators)
4017  fields.push_back(indicator->name());
4018 
4019  // InternalSideIndicator Fields
4020  const auto & internal_indicators = _internal_side_indicators.getActiveObjects();
4021  for (const auto & internal_indicator : internal_indicators)
4022  fields.push_back(internal_indicator->name());
4023 
4024  _aux->zeroVariables(fields);
4025 
4026  // compute Indicators
4027  ComputeIndicatorThread cit(*this);
4028  Threads::parallel_reduce(*_mesh.getActiveLocalElementRange(), cit);
4029  _aux->solution().close();
4030  _aux->update();
4031 
4032  ComputeIndicatorThread finalize_cit(*this, true);
4033  Threads::parallel_reduce(*_mesh.getActiveLocalElementRange(), finalize_cit);
4034  _aux->solution().close();
4035  _aux->update();
4036 
4037  ADReal::do_derivatives = old_do_derivatives;
4038  }
4039 }
4040 
4041 void
4043 {
4044  if (_markers.hasActiveObjects())
4045  {
4046  TIME_SECTION("computeMarkers", 1, "Computing Markers");
4047 
4048  std::vector<std::string> fields;
4049 
4050  // Marker Fields
4051  const auto & markers = _markers.getActiveObjects();
4052  for (const auto & marker : markers)
4053  fields.push_back(marker->name());
4054 
4055  _aux->zeroVariables(fields);
4056 
4058 
4059  for (THREAD_ID tid = 0; tid < libMesh::n_threads(); ++tid)
4060  {
4061  const auto & markers = _markers.getActiveObjects(tid);
4062  for (const auto & marker : markers)
4063  marker->markerSetup();
4064  }
4065 
4066  ComputeMarkerThread cmt(*this);
4067  Threads::parallel_reduce(*_mesh.getActiveLocalElementRange(), cmt);
4068 
4069  _aux->solution().close();
4070  _aux->update();
4071  }
4072 }
4073 
4074 const ExecFlagType &
4076 {
4077  return _current_execute_on_flag;
4078 }
4079 
4080 void
4082 {
4083  _current_execute_on_flag = flag;
4084 }
4085 
4086 void
4088 {
4089 }
4090 
4091 void
4093 {
4094  SubProblem::customSetup(exec_type);
4095 
4096  if (_line_search)
4097  _line_search->customSetup(exec_type);
4098 
4099  unsigned int n_threads = libMesh::n_threads();
4100  for (THREAD_ID tid = 0; tid < n_threads; tid++)
4101  {
4102  _all_materials.customSetup(exec_type, tid);
4103  _functions.customSetup(exec_type, tid);
4104  }
4105 
4106  _aux->customSetup(exec_type);
4107  for (auto & nl : _nl)
4108  nl->customSetup(exec_type);
4109 
4110  if (_displaced_problem)
4111  _displaced_problem->customSetup(exec_type);
4112 
4113  for (THREAD_ID tid = 0; tid < n_threads; tid++)
4114  {
4115  _internal_side_indicators.customSetup(exec_type, tid);
4116  _indicators.customSetup(exec_type, tid);
4117  _markers.customSetup(exec_type, tid);
4118  }
4119 
4120  std::vector<UserObject *> userobjs;
4121  theWarehouse().query().condition<AttribSystem>("UserObject").queryIntoUnsorted(userobjs);
4122  for (auto obj : userobjs)
4123  obj->customSetup(exec_type);
4124 
4125  _app.getOutputWarehouse().customSetup(exec_type);
4126 }
4127 
4128 void
4130 {
4131  // Set the current flag
4132  setCurrentExecuteOnFlag(exec_type);
4133 
4134  if (exec_type != EXEC_INITIAL)
4135  executeControls(exec_type);
4136 
4137  // intentially call this after executing controls because the setups may rely on the controls
4138  // FIXME: we skip the following flags because they have dedicated setup functions in
4139  // SetupInterface and it may not be appropriate to call them here.
4140  if (!(exec_type == EXEC_INITIAL || exec_type == EXEC_TIMESTEP_BEGIN ||
4141  exec_type == EXEC_SUBDOMAIN || exec_type == EXEC_NONLINEAR || exec_type == EXEC_LINEAR))
4142  customSetup(exec_type);
4143 
4144  // Samplers; EXEC_INITIAL is not called because the Sampler::init() method that is called after
4145  // construction makes the first Sampler::execute() call. This ensures that the random number
4146  // generator object is the correct state prior to any other object (e.g., Transfers) attempts to
4147  // extract data from the Sampler. That is, if the Sampler::execute() call is delayed to here
4148  // then it is not in the correct state for other objects.
4149  if (exec_type != EXEC_INITIAL)
4150  executeSamplers(exec_type);
4151 
4152  // Pre-aux UserObjects
4153  computeUserObjects(exec_type, Moose::PRE_AUX);
4154 
4155  // AuxKernels
4156  computeAuxiliaryKernels(exec_type);
4157 
4158  // Post-aux UserObjects
4159  computeUserObjects(exec_type, Moose::POST_AUX);
4160 
4161  // Return the current flag to None
4163 
4165  {
4166  // we will only check aux variables and postprocessors
4167  // checking more reporter data can be added in the future if needed
4168  std::unique_ptr<NumericVector<Number>> x = _aux->currentSolution()->clone();
4169  DenseVector<Real> pp_values = getReporterData().getAllRealReporterValues();
4170 
4171  // call THIS execute one more time for checking the possible states
4172  _checking_uo_aux_state = true;
4173  FEProblemBase::execute(exec_type);
4174  _checking_uo_aux_state = false;
4175 
4176  const Real check_tol = 1e-8;
4177 
4178  const Real xnorm = x->l2_norm();
4179  *x -= *_aux->currentSolution();
4180  if (x->l2_norm() > check_tol * xnorm)
4181  {
4182  const auto & sys = _aux->system();
4183  const unsigned int n_vars = sys.n_vars();
4184  std::multimap<Real, std::string, std::greater<Real>> ordered_map;
4185  for (const auto i : make_range(n_vars))
4186  {
4187  const Real vnorm = sys.calculate_norm(*x, i, DISCRETE_L2);
4188  ordered_map.emplace(vnorm, sys.variable_name(i));
4189  }
4190 
4191  std::ostringstream oss;
4192  for (const auto & [error_norm, var_name] : ordered_map)
4193  oss << " {" << var_name << ", " << error_norm << "},\n";
4194 
4195  mooseError("Aux kernels, user objects appear to have states for aux variables on ",
4196  exec_type,
4197  ".\nVariable error norms in descending order:\n",
4198  oss.str());
4199  }
4200 
4201  const DenseVector<Real> new_pp_values = getReporterData().getAllRealReporterValues();
4202  if (pp_values.size() != new_pp_values.size())
4203  mooseError("Second execution for uo/aux state check should not change the number of "
4204  "real reporter values");
4205 
4206  const Real ppnorm = pp_values.l2_norm();
4207  pp_values -= new_pp_values;
4208  if (pp_values.l2_norm() > check_tol * ppnorm)
4209  {
4210  const auto pp_names = getReporterData().getAllRealReporterFullNames();
4211  std::multimap<Real, std::string, std::greater<Real>> ordered_map;
4212  for (const auto i : index_range(pp_names))
4213  ordered_map.emplace(std::abs(pp_values(i)), pp_names[i]);
4214 
4215  std::ostringstream oss;
4216  for (const auto & [error_norm, pp_name] : ordered_map)
4217  oss << " {" << pp_name << ", " << error_norm << "},\n";
4218 
4219  mooseError("Aux kernels, user objects appear to have states for real reporter values on ",
4220  exec_type,
4221  ".\nErrors of real reporter values in descending order:\n",
4222  oss.str());
4223  }
4224  }
4225 }
4226 
4227 void
4229 {
4230  _aux->compute(type);
4231 }
4232 
4233 // Finalize, threadJoin, and update PP values of Elemental/Nodal/Side/InternalSideUserObjects
4234 void
4236 {
4237  std::vector<UserObject *> objs;
4238  query.queryInto(objs);
4239  if (!isgen)
4240  {
4241  // join all threaded user objects (i.e. not regular general user objects) to the primary
4242  // thread
4243  for (auto obj : objs)
4244  if (obj->primaryThreadCopy())
4245  obj->primaryThreadCopy()->threadJoin(*obj);
4246  }
4247 
4248  query.condition<AttribThread>(0).queryInto(objs);
4249 
4250  // finalize objects and retrieve/store any postprocessor values
4251  for (auto obj : objs)
4252  {
4253  if (isgen && dynamic_cast<ThreadedGeneralUserObject *>(obj))
4254  continue;
4255  if (isgen)
4256  {
4257  // general user objects are not run in their own threaded loop object - so run them here
4258  if (shouldPrintExecution(0))
4259  _console << "[DBG] Initializing, executing & finalizing general UO '" << obj->name()
4260  << "' on " << _current_execute_on_flag.name() << std::endl;
4261  obj->initialize();
4262  obj->execute();
4263  }
4264 
4265  obj->finalize();
4266 
4267  // These have to be stored piecemeal (with every call to this function) because general
4268  // postprocessors (which run last after other userobjects have been completed) might depend on
4269  // them being stored. This wouldn't be a problem if all userobjects satisfied the dependency
4270  // resolver interface and could be sorted appropriately with the general userobjects, but they
4271  // don't.
4272  auto pp = dynamic_cast<const Postprocessor *>(obj);
4273  if (pp)
4274  {
4275  _reporter_data.finalize(obj->name());
4276  setPostprocessorValueByName(obj->name(), pp->getValue());
4277  }
4278 
4279  auto vpp = dynamic_cast<VectorPostprocessor *>(obj);
4280  if (vpp)
4281  _reporter_data.finalize(obj->name());
4282 
4283  // Update Reporter data
4284  auto reporter = dynamic_cast<Reporter *>(obj);
4285  if (reporter)
4286  _reporter_data.finalize(obj->name());
4287  }
4288 }
4289 
4290 void
4292  const Moose::AuxGroup & group,
4293  const std::string & name)
4294 {
4295  const auto old_exec_flag = _current_execute_on_flag;
4298  .query()
4299  .condition<AttribSystem>("UserObject")
4300  .condition<AttribExecOns>(type)
4301  .condition<AttribName>(name);
4303  _current_execute_on_flag = old_exec_flag;
4304 }
4305 
4306 void
4308 {
4310  theWarehouse().query().condition<AttribSystem>("UserObject").condition<AttribExecOns>(type);
4312 }
4313 
4314 void
4316  const Moose::AuxGroup & group,
4317  TheWarehouse::Query & primary_query)
4318 {
4319  try
4320  {
4321  TIME_SECTION("computeUserObjects", 1, "Computing User Objects");
4322 
4323  // Add group to query
4324  if (group == Moose::PRE_IC)
4325  primary_query.condition<AttribPreIC>(true);
4326  else if (group == Moose::PRE_AUX)
4327  primary_query.condition<AttribPreAux>(type);
4328  else if (group == Moose::POST_AUX)
4329  primary_query.condition<AttribPostAux>(type);
4330 
4331  // query everything first to obtain a list of execution groups
4332  std::vector<UserObject *> uos;
4333  primary_query.clone().queryIntoUnsorted(uos);
4334  std::set<int> execution_groups;
4335  for (const auto & uo : uos)
4336  execution_groups.insert(uo->getParam<int>("execution_order_group"));
4337 
4338  // iterate over execution order groups
4339  for (const auto execution_group : execution_groups)
4340  {
4341  auto query = primary_query.clone().condition<AttribExecutionOrderGroup>(execution_group);
4342 
4343  std::vector<GeneralUserObject *> genobjs;
4344  query.clone().condition<AttribInterfaces>(Interfaces::GeneralUserObject).queryInto(genobjs);
4345 
4346  std::vector<UserObject *> userobjs;
4347  query.clone()
4352  .queryInto(userobjs);
4353 
4354  std::vector<UserObject *> tgobjs;
4355  query.clone()
4357  .queryInto(tgobjs);
4358 
4359  std::vector<UserObject *> nodal;
4360  query.clone().condition<AttribInterfaces>(Interfaces::NodalUserObject).queryInto(nodal);
4361 
4362  std::vector<MortarUserObject *> mortar;
4363  query.clone().condition<AttribInterfaces>(Interfaces::MortarUserObject).queryInto(mortar);
4364 
4365  if (userobjs.empty() && genobjs.empty() && tgobjs.empty() && nodal.empty() && mortar.empty())
4366  continue;
4367 
4368  // Start the timer here since we have at least one active user object
4369  std::string compute_uo_tag = "computeUserObjects(" + Moose::stringify(type) + ")";
4370 
4371  // Perform Residual/Jacobian setups
4372  if (type == EXEC_LINEAR)
4373  {
4374  for (auto obj : userobjs)
4375  obj->residualSetup();
4376  for (auto obj : nodal)
4377  obj->residualSetup();
4378  for (auto obj : mortar)
4379  obj->residualSetup();
4380  for (auto obj : tgobjs)
4381  obj->residualSetup();
4382  for (auto obj : genobjs)
4383  obj->residualSetup();
4384  }
4385  else if (type == EXEC_NONLINEAR)
4386  {
4387  for (auto obj : userobjs)
4388  obj->jacobianSetup();
4389  for (auto obj : nodal)
4390  obj->jacobianSetup();
4391  for (auto obj : mortar)
4392  obj->jacobianSetup();
4393  for (auto obj : tgobjs)
4394  obj->jacobianSetup();
4395  for (auto obj : genobjs)
4396  obj->jacobianSetup();
4397  }
4398 
4399  for (auto obj : userobjs)
4400  obj->initialize();
4401 
4402  // Execute Side/InternalSide/Interface/Elemental/DomainUserObjects
4403  if (!userobjs.empty())
4404  {
4405  // non-nodal user objects have to be run separately before the nodal user objects run
4406  // because some nodal user objects (NodalNormal related) depend on elemental user objects
4407  // :-(
4408  ComputeUserObjectsThread cppt(*this, query);
4409  Threads::parallel_reduce(*_mesh.getActiveLocalElementRange(), cppt);
4410 
4411  // There is one instance in rattlesnake where an elemental user object's finalize depends
4412  // on a side user object having been finalized first :-(
4419  }
4420 
4421  // if any userobject may have written to variables we need to close the aux solution
4422  for (const auto & uo : userobjs)
4423  if (auto euo = dynamic_cast<const ElementUserObject *>(uo);
4424  euo && euo->hasWritableCoupledVariables())
4425  {
4426  _aux->solution().close();
4427  _aux->system().update();
4428  break;
4429  }
4430 
4431  // Execute NodalUserObjects
4432  // BISON has an axial reloc elemental user object that has a finalize func that depends on a
4433  // nodal user object's prev value. So we can't initialize this until after elemental objects
4434  // have been finalized :-(
4435  for (auto obj : nodal)
4436  obj->initialize();
4437  if (query.clone().condition<AttribInterfaces>(Interfaces::NodalUserObject).count() > 0)
4438  {
4439  ComputeNodalUserObjectsThread cnppt(*this, query);
4440  Threads::parallel_reduce(*_mesh.getLocalNodeRange(), cnppt);
4442  }
4443 
4444  // if any userobject may have written to variables we need to close the aux solution
4445  for (const auto & uo : nodal)
4446  if (auto nuo = dynamic_cast<const NodalUserObject *>(uo);
4447  nuo && nuo->hasWritableCoupledVariables())
4448  {
4449  _aux->solution().close();
4450  _aux->system().update();
4451  break;
4452  }
4453 
4454  // Execute MortarUserObjects
4455  {
4456  for (auto obj : mortar)
4457  obj->initialize();
4458  if (!mortar.empty())
4459  {
4460  auto create_and_run_mortar_functors = [this, type, &mortar](const bool displaced)
4461  {
4462  // go over mortar interfaces and construct functors
4463  const auto & mortar_interfaces = getMortarInterfaces(displaced);
4464  for (const auto & mortar_interface : mortar_interfaces)
4465  {
4466  const auto primary_secondary_boundary_pair = mortar_interface.first;
4467  auto mortar_uos_to_execute =
4468  getMortarUserObjects(primary_secondary_boundary_pair.first,
4469  primary_secondary_boundary_pair.second,
4470  displaced,
4471  mortar);
4472  const auto & mortar_generation_object = mortar_interface.second;
4473 
4474  auto * const subproblem = displaced
4475  ? static_cast<SubProblem *>(_displaced_problem.get())
4476  : static_cast<SubProblem *>(this);
4477  MortarUserObjectThread muot(mortar_uos_to_execute,
4478  mortar_generation_object,
4479  *subproblem,
4480  *this,
4481  displaced,
4482  subproblem->assembly(0, 0));
4483 
4484  muot();
4485  }
4486  };
4487 
4488  create_and_run_mortar_functors(false);
4489  if (_displaced_problem)
4490  create_and_run_mortar_functors(true);
4491  }
4492  for (auto obj : mortar)
4493  obj->finalize();
4494  }
4495 
4496  // Execute threaded general user objects
4497  for (auto obj : tgobjs)
4498  obj->initialize();
4499  std::vector<GeneralUserObject *> tguos_zero;
4500  query.clone()
4501  .condition<AttribThread>(0)
4502  .condition<AttribInterfaces>(Interfaces::ThreadedGeneralUserObject)
4503  .queryInto(tguos_zero);
4504  for (auto obj : tguos_zero)
4505  {
4506  std::vector<GeneralUserObject *> tguos;
4507  auto q = query.clone()
4508  .condition<AttribName>(obj->name())
4509  .condition<AttribInterfaces>(Interfaces::ThreadedGeneralUserObject);
4510  q.queryInto(tguos);
4511 
4513  Threads::parallel_reduce(GeneralUserObjectRange(tguos.begin(), tguos.end()), ctguot);
4514  joinAndFinalize(q);
4515  }
4516 
4517  // Execute general user objects
4519  true);
4520  }
4521  }
4522  catch (...)
4523  {
4524  handleException("computeUserObjectsInternal");
4525  }
4526 }
4527 
4528 void
4530 {
4531  if (_control_warehouse[exec_type].hasActiveObjects())
4532  {
4533  TIME_SECTION("executeControls", 1, "Executing Controls");
4534 
4536 
4537  auto controls_wh = _control_warehouse[exec_type];
4538  // Add all of the dependencies into the resolver and sort them
4539  for (const auto & it : controls_wh.getActiveObjects())
4540  {
4541  // Make sure an item with no dependencies comes out too!
4542  resolver.addItem(it);
4543 
4544  std::vector<std::string> & dependent_controls = it->getDependencies();
4545  for (const auto & depend_name : dependent_controls)
4546  {
4547  if (controls_wh.hasActiveObject(depend_name))
4548  {
4549  auto dep_control = controls_wh.getActiveObject(depend_name);
4550  resolver.addEdge(dep_control, it);
4551  }
4552  else
4553  mooseError("The Control \"",
4554  depend_name,
4555  "\" was not created, did you make a "
4556  "spelling mistake or forget to include it "
4557  "in your input file?");
4558  }
4559  }
4560 
4561  const auto & ordered_controls = resolver.getSortedValues();
4562 
4563  if (!ordered_controls.empty())
4564  {
4565  _control_warehouse.setup(exec_type);
4566  // Run the controls in the proper order
4567  for (const auto & control : ordered_controls)
4568  control->execute();
4569  }
4570  }
4571 }
4572 
4573 void
4575 {
4576  // TODO: This should be done in a threaded loop, but this should be super quick so for now
4577  // do a serial loop.
4578  for (THREAD_ID tid = 0; tid < libMesh::n_threads(); ++tid)
4579  {
4580  std::vector<Sampler *> objects;
4581  theWarehouse()
4582  .query()
4583  .condition<AttribSystem>("Sampler")
4584  .condition<AttribThread>(tid)
4585  .condition<AttribExecOns>(exec_type)
4586  .queryInto(objects);
4587 
4588  if (!objects.empty())
4589  {
4590  TIME_SECTION("executeSamplers", 1, "Executing Samplers");
4591  FEProblemBase::objectSetupHelper<Sampler>(objects, exec_type);
4592  FEProblemBase::objectExecuteHelper<Sampler>(objects);
4593  }
4594  }
4595 }
4596 
4597 void
4599 {
4600  TIME_SECTION("updateActiveObjects", 5, "Updating Active Objects");
4601 
4602  for (THREAD_ID tid = 0; tid < libMesh::n_threads(); ++tid)
4603  {
4604  for (auto & nl : _nl)
4605  nl->updateActive(tid);
4606  _aux->updateActive(tid);
4609  _markers.updateActive(tid);
4611  _materials.updateActive(tid);
4613  }
4614 
4622 }
4623 
4624 void
4626 {
4627  //<< "Object " << a->name() << " -> " << b->name() << std::endl;
4628 }
4629 
4630 void
4632 {
4633  TIME_SECTION("reinitBecauseOfGhostingOrNewGeomObjects",
4634  3,
4635  "Reinitializing Because of Geometric Search Objects");
4636 
4637  // Need to see if _any_ processor has ghosted elems or geometry objects.
4638  bool needs_reinit = !_ghosted_elems.empty();
4639  needs_reinit = needs_reinit || !_geometric_search_data._nearest_node_locators.empty() ||
4640  (_mortar_data.hasObjects() && mortar_changed);
4641  needs_reinit =
4642  needs_reinit || (_displaced_problem &&
4643  (!_displaced_problem->geomSearchData()._nearest_node_locators.empty() ||
4644  (_mortar_data.hasDisplacedObjects() && mortar_changed)));
4645  _communicator.max(needs_reinit);
4646 
4647  if (needs_reinit)
4648  {
4649  // Call reinit to get the ghosted vectors correct now that some geometric search has been done
4650  es().reinit();
4651 
4652  if (_displaced_mesh)
4653  _displaced_problem->es().reinit();
4654  }
4655 }
4656 
4657 void
4658 FEProblemBase::addDamper(const std::string & damper_name,
4659  const std::string & name,
4660  InputParameters & parameters)
4661 {
4662  parallel_object_only();
4663 
4664  const auto nl_sys_num =
4665  parameters.isParamValid("variable")
4666  ? determineNonlinearSystem(parameters.varName("variable", name), true).second
4667  : (unsigned int)0;
4668 
4669  parameters.set<SubProblem *>("_subproblem") = this;
4670  parameters.set<SystemBase *>("_sys") = _nl[nl_sys_num].get();
4671 
4672  _has_dampers = true;
4673  logAdd("Damper", name, damper_name);
4674  _nl[nl_sys_num]->addDamper(damper_name, name, parameters);
4675 }
4676 
4677 void
4679 {
4680  for (auto & nl : _nl)
4681  nl->setupDampers();
4682 }
4683 
4684 void
4685 FEProblemBase::addIndicator(const std::string & indicator_name,
4686  const std::string & name,
4687  InputParameters & parameters)
4688 {
4689  parallel_object_only();
4690 
4691  if (_displaced_problem && parameters.get<bool>("use_displaced_mesh"))
4692  {
4693  parameters.set<SubProblem *>("_subproblem") = _displaced_problem.get();
4694  parameters.set<SystemBase *>("_sys") = &_displaced_problem->auxSys();
4695  _reinit_displaced_elem = true;
4696  }
4697  else
4698  {
4699  if (_displaced_problem == nullptr && parameters.get<bool>("use_displaced_mesh"))
4700  {
4701  // We allow Indicators to request that they use_displaced_mesh,
4702  // but then be overridden when no displacements variables are
4703  // provided in the Mesh block. If that happened, update the value
4704  // of use_displaced_mesh appropriately for this Indicator.
4705  if (parameters.have_parameter<bool>("use_displaced_mesh"))
4706  parameters.set<bool>("use_displaced_mesh") = false;
4707  }
4708 
4709  parameters.set<SubProblem *>("_subproblem") = this;
4710  parameters.set<SystemBase *>("_sys") = _aux.get();
4711  }
4712 
4713  for (THREAD_ID tid = 0; tid < libMesh::n_threads(); tid++)
4714  {
4715  std::shared_ptr<Indicator> indicator =
4716  _factory.create<Indicator>(indicator_name, name, parameters, tid);
4717  logAdd("Indicator", name, indicator_name);
4718  std::shared_ptr<InternalSideIndicator> isi =
4720  if (isi)
4722  else
4723  _indicators.addObject(indicator, tid);
4724  }
4725 }
4726 
4727 void
4728 FEProblemBase::addMarker(const std::string & marker_name,
4729  const std::string & name,
4730  InputParameters & parameters)
4731 {
4732  parallel_object_only();
4733 
4734  if (_displaced_problem && parameters.get<bool>("use_displaced_mesh"))
4735  {
4736  parameters.set<SubProblem *>("_subproblem") = _displaced_problem.get();
4737  parameters.set<SystemBase *>("_sys") = &_displaced_problem->auxSys();
4738  _reinit_displaced_elem = true;
4739  }
4740  else
4741  {
4742  if (_displaced_problem == nullptr && parameters.get<bool>("use_displaced_mesh"))
4743  {
4744  // We allow Markers to request that they use_displaced_mesh,
4745  // but then be overridden when no displacements variables are
4746  // provided in the Mesh block. If that happened, update the value
4747  // of use_displaced_mesh appropriately for this Marker.
4748  if (parameters.have_parameter<bool>("use_displaced_mesh"))
4749  parameters.set<bool>("use_displaced_mesh") = false;
4750  }
4751 
4752  parameters.set<SubProblem *>("_subproblem") = this;
4753  parameters.set<SystemBase *>("_sys") = _aux.get();
4754  }
4755 
4756  for (THREAD_ID tid = 0; tid < libMesh::n_threads(); tid++)
4757  {
4758  std::shared_ptr<Marker> marker = _factory.create<Marker>(marker_name, name, parameters, tid);
4759  logAdd("Marker", name, marker_name);
4760  _markers.addObject(marker, tid);
4761  }
4762 }
4763 
4764 void
4765 FEProblemBase::addMultiApp(const std::string & multi_app_name,
4766  const std::string & name,
4767  InputParameters & parameters)
4768 {
4769  parallel_object_only();
4770 
4771  parameters.set<MPI_Comm>("_mpi_comm") = _communicator.get();
4772  parameters.set<std::shared_ptr<CommandLine>>("_command_line") = _app.commandLine();
4773 
4774  if (_displaced_problem && parameters.get<bool>("use_displaced_mesh"))
4775  {
4776  parameters.set<SubProblem *>("_subproblem") = _displaced_problem.get();
4777  parameters.set<SystemBase *>("_sys") = &_displaced_problem->auxSys();
4778  _reinit_displaced_elem = true;
4779  }
4780  else
4781  {
4782  if (_displaced_problem == nullptr && parameters.get<bool>("use_displaced_mesh"))
4783  {
4784  // We allow MultiApps to request that they use_displaced_mesh,
4785  // but then be overridden when no displacements variables are
4786  // provided in the Mesh block. If that happened, update the value
4787  // of use_displaced_mesh appropriately for this MultiApp.
4788  if (parameters.have_parameter<bool>("use_displaced_mesh"))
4789  parameters.set<bool>("use_displaced_mesh") = false;
4790  }
4791 
4792  parameters.set<SubProblem *>("_subproblem") = this;
4793  parameters.set<SystemBase *>("_sys") = _aux.get();
4794  }
4795 
4796  std::shared_ptr<MultiApp> multi_app = _factory.create<MultiApp>(multi_app_name, name, parameters);
4797  logAdd("MultiApp", name, multi_app_name);
4798  multi_app->setupPositions();
4799 
4800  _multi_apps.addObject(multi_app);
4801 
4802  // Store TransientMultiApp objects in another container, this is needed for calling computeDT
4803  std::shared_ptr<TransientMultiApp> trans_multi_app =
4805  if (trans_multi_app)
4806  _transient_multi_apps.addObject(trans_multi_app);
4807 }
4808 
4809 bool
4811 {
4812  return _multi_apps[type].hasActiveObjects();
4813 }
4814 
4815 bool
4816 FEProblemBase::hasMultiApp(const std::string & multi_app_name) const
4817 {
4818  return _multi_apps.hasActiveObject(multi_app_name);
4819 }
4820 
4821 std::shared_ptr<MultiApp>
4822 FEProblemBase::getMultiApp(const std::string & multi_app_name) const
4823 {
4824  return _multi_apps.getObject(multi_app_name);
4825 }
4826 
4827 void
4829 {
4830  bool to_multiapp = direction == MultiAppTransfer::TO_MULTIAPP;
4831  bool from_multiapp = direction == MultiAppTransfer::FROM_MULTIAPP;
4832  std::string string_direction;
4833  if (to_multiapp)
4834  string_direction = " To ";
4835  else if (from_multiapp)
4836  string_direction = " From ";
4837  else
4838  string_direction = " Between ";
4839 
4840  const MooseObjectWarehouse<Transfer> & wh = to_multiapp ? _to_multi_app_transfers[type]
4841  : from_multiapp ? _from_multi_app_transfers[type]
4843 
4844  if (wh.hasActiveObjects())
4845  {
4846  TIME_SECTION("execMultiAppTransfers", 1, "Executing Transfers");
4847 
4848  const auto & transfers = wh.getActiveObjects();
4849 
4850  if (_verbose_multiapps)
4851  {
4852  _console << COLOR_CYAN << "\nTransfers on " << Moose::stringify(type) << string_direction
4853  << "MultiApps" << COLOR_DEFAULT << ":" << std::endl;
4854 
4856  {"Name", "Type", "From", "To"});
4857 
4858  // Build Table of Transfer Info
4859  for (const auto & transfer : transfers)
4860  {
4861  auto multiapp_transfer = dynamic_cast<MultiAppTransfer *>(transfer.get());
4862 
4863  table.addRow(multiapp_transfer->name(),
4864  multiapp_transfer->type(),
4865  multiapp_transfer->getFromName(),
4866  multiapp_transfer->getToName());
4867  }
4868 
4869  // Print it
4870  table.print(_console);
4871  }
4872 
4873  for (const auto & transfer : transfers)
4874  {
4875  transfer->setCurrentDirection(direction);
4876  transfer->execute();
4877  }
4878 
4880 
4881  if (_verbose_multiapps)
4882  _console << COLOR_CYAN << "Transfers on " << Moose::stringify(type) << " Are Finished\n"
4883  << COLOR_DEFAULT << std::endl;
4884  }
4885  else if (_multi_apps[type].getActiveObjects().size())
4886  {
4887  if (_verbose_multiapps)
4888  _console << COLOR_CYAN << "\nNo Transfers on " << Moose::stringify(type) << string_direction
4889  << "MultiApps\n"
4890  << COLOR_DEFAULT << std::endl;
4891  }
4892 }
4893 
4894 std::vector<std::shared_ptr<Transfer>>
4896 {
4897  if (direction == MultiAppTransfer::TO_MULTIAPP)
4899  else if (direction == MultiAppTransfer::FROM_MULTIAPP)
4901  else
4903 }
4904 
4905 std::vector<std::shared_ptr<Transfer>>
4907 {
4908  if (direction == MultiAppTransfer::TO_MULTIAPP)
4910  else if (direction == MultiAppTransfer::FROM_MULTIAPP)
4912  else
4914 }
4915 
4918 {
4919  if (direction == MultiAppTransfer::TO_MULTIAPP)
4920  return _to_multi_app_transfers;
4921  else if (direction == MultiAppTransfer::FROM_MULTIAPP)
4923  else
4925 }
4926 
4927 bool
4929 {
4930  // Active MultiApps
4931  const std::vector<MooseSharedPointer<MultiApp>> & multi_apps =
4933 
4934  // Do anything that needs to be done to Apps before transfers
4935  for (const auto & multi_app : multi_apps)
4936  multi_app->preTransfer(_dt, _time);
4937 
4938  // Execute Transfers _to_ MultiApps
4940 
4941  // Execute Transfers _between_ Multiapps
4943 
4944  // Execute MultiApps
4945  if (multi_apps.size())
4946  {
4947  TIME_SECTION("execMultiApps", 1, "Executing MultiApps", false);
4948 
4949  if (_verbose_multiapps)
4950  _console << COLOR_CYAN << "\nExecuting MultiApps on " << Moose::stringify(type)
4951  << COLOR_DEFAULT << std::endl;
4952 
4953  bool success = true;
4954 
4955  for (const auto & multi_app : multi_apps)
4956  {
4957  success = multi_app->solveStep(_dt, _time, auto_advance);
4958  // no need to finish executing the subapps if one fails
4959  if (!success)
4960  break;
4961  }
4962 
4964 
4965  _communicator.min(success);
4966 
4967  if (!success)
4968  return false;
4969 
4970  if (_verbose_multiapps)
4971  _console << COLOR_CYAN << "Finished Executing MultiApps on " << Moose::stringify(type) << "\n"
4972  << COLOR_DEFAULT << std::endl;
4973  }
4974 
4975  // Execute Transfers _from_ MultiApps
4977 
4978  // If we made it here then everything passed
4979  return true;
4980 }
4981 
4982 void
4984 {
4985  const auto & multi_apps = _multi_apps.getActiveObjects();
4986 
4987  for (const auto & multi_app : multi_apps)
4988  multi_app->finalize();
4989 }
4990 
4991 void
4993 {
4994  const auto & multi_apps = _multi_apps.getActiveObjects();
4995 
4996  for (const auto & multi_app : multi_apps)
4997  multi_app->postExecute();
4998 }
4999 
5000 void
5002 {
5003  const auto & multi_apps = _multi_apps[type].getActiveObjects();
5004 
5005  if (multi_apps.size())
5006  for (const auto & multi_app : multi_apps)
5007  multi_app->incrementTStep(_time);
5008 }
5009 
5010 void
5011 FEProblemBase::finishMultiAppStep(ExecFlagType type, bool recurse_through_multiapp_levels)
5012 {
5013  const auto & multi_apps = _multi_apps[type].getActiveObjects();
5014 
5015  if (multi_apps.size())
5016  {
5017  if (_verbose_multiapps)
5018  _console << COLOR_CYAN << "\nAdvancing MultiApps on " << type.name() << COLOR_DEFAULT
5019  << std::endl;
5020 
5021  for (const auto & multi_app : multi_apps)
5022  multi_app->finishStep(recurse_through_multiapp_levels);
5023 
5025 
5026  if (_verbose_multiapps)
5027  _console << COLOR_CYAN << "Finished Advancing MultiApps on " << type.name() << "\n"
5028  << COLOR_DEFAULT << std::endl;
5029  }
5030 }
5031 
5032 void
5034 {
5035  const auto & multi_apps = _multi_apps[type].getActiveObjects();
5036 
5037  if (multi_apps.size())
5038  {
5039  TIME_SECTION("backupMultiApps", 5, "Backing Up MultiApp");
5040 
5041  if (_verbose_multiapps)
5042  _console << COLOR_CYAN << "\nBacking Up MultiApps on " << type.name() << COLOR_DEFAULT
5043  << std::endl;
5044 
5045  for (const auto & multi_app : multi_apps)
5046  multi_app->backup();
5047 
5049 
5050  if (_verbose_multiapps)
5051  _console << COLOR_CYAN << "Finished Backing Up MultiApps on " << type.name() << "\n"
5052  << COLOR_DEFAULT << std::endl;
5053  }
5054 }
5055 
5056 void
5058 {
5059  const auto & multi_apps = _multi_apps[type].getActiveObjects();
5060 
5061  if (multi_apps.size())
5062  {
5063  if (_verbose_multiapps)
5064  {
5065  if (force)
5066  _console << COLOR_CYAN << "\nRestoring Multiapps on " << type.name()
5067  << " because of solve failure!" << COLOR_DEFAULT << std::endl;
5068  else
5069  _console << COLOR_CYAN << "\nRestoring MultiApps on " << type.name() << COLOR_DEFAULT
5070  << std::endl;
5071  }
5072 
5073  for (const auto & multi_app : multi_apps)
5074  multi_app->restore(force);
5075 
5077 
5078  if (_verbose_multiapps)
5079  _console << COLOR_CYAN << "Finished Restoring MultiApps on " << type.name() << "\n"
5080  << COLOR_DEFAULT << std::endl;
5081  }
5082 }
5083 
5084 Real
5086 {
5087  const auto & multi_apps = _transient_multi_apps[type].getActiveObjects();
5088 
5089  Real smallest_dt = std::numeric_limits<Real>::max();
5090 
5091  for (const auto & multi_app : multi_apps)
5092  smallest_dt = std::min(smallest_dt, multi_app->computeDT());
5093 
5094  return smallest_dt;
5095 }
5096 
5097 void
5099 {
5100  if (_transfers[type].hasActiveObjects())
5101  {
5102  TIME_SECTION("execTransfers", 3, "Executing Transfers");
5103 
5104  const auto & transfers = _transfers[type].getActiveObjects();
5105 
5106  for (const auto & transfer : transfers)
5107  transfer->execute();
5108  }
5109 }
5110 
5111 void
5112 FEProblemBase::addTransfer(const std::string & transfer_name,
5113  const std::string & name,
5114  InputParameters & parameters)
5115 {
5116  parallel_object_only();
5117 
5118  if (_displaced_problem && parameters.get<bool>("use_displaced_mesh"))
5119  {
5120  parameters.set<SubProblem *>("_subproblem") = _displaced_problem.get();
5121  parameters.set<SystemBase *>("_sys") = &_displaced_problem->auxSys();
5122  _reinit_displaced_elem = true;
5123  }
5124  else
5125  {
5126  if (_displaced_problem == nullptr && parameters.get<bool>("use_displaced_mesh"))
5127  {
5128  // We allow Transfers to request that they use_displaced_mesh,
5129  // but then be overridden when no displacements variables are
5130  // provided in the Mesh block. If that happened, update the value
5131  // of use_displaced_mesh appropriately for this Transfer.
5132  if (parameters.have_parameter<bool>("use_displaced_mesh"))
5133  parameters.set<bool>("use_displaced_mesh") = false;
5134  }
5135 
5136  parameters.set<SubProblem *>("_subproblem") = this;
5137  parameters.set<SystemBase *>("_sys") = _aux.get();
5138  }
5139 
5140  // Handle the "SAME_AS_MULTIAPP" execute option. The get method is used to test for the
5141  // flag so the set by user flag is not reset, calling set with the true flag causes the set
5142  // by user status to be reset, which should only be done if the EXEC_SAME_AS_MULTIAPP is
5143  // being applied to the object.
5145  {
5146  ExecFlagEnum & exec_enum = parameters.set<ExecFlagEnum>("execute_on", true);
5147  std::shared_ptr<MultiApp> multiapp;
5148  if (parameters.isParamValid("multi_app"))
5149  multiapp = getMultiApp(parameters.get<MultiAppName>("multi_app"));
5150  else if (parameters.isParamValid("from_multi_app"))
5151  multiapp = getMultiApp(parameters.get<MultiAppName>("from_multi_app"));
5152  else if (parameters.isParamValid("to_multi_app"))
5153  multiapp = getMultiApp(parameters.get<MultiAppName>("to_multi_app"));
5154  // else do nothing because the user has provided invalid input. They should get a nice error
5155  // about this during transfer construction. This necessitates checking for null in this next
5156  // line, however
5157  if (multiapp)
5158  exec_enum = multiapp->getParam<ExecFlagEnum>("execute_on");
5159  }
5160 
5161  // Create the Transfer objects
5162  std::shared_ptr<Transfer> transfer = _factory.create<Transfer>(transfer_name, name, parameters);
5163  logAdd("Transfer", name, transfer_name);
5164 
5165  // Add MultiAppTransfer object
5166  std::shared_ptr<MultiAppTransfer> multi_app_transfer =
5168  if (multi_app_transfer)
5169  {
5170  if (multi_app_transfer->directions().contains(MultiAppTransfer::TO_MULTIAPP))
5171  _to_multi_app_transfers.addObject(multi_app_transfer);
5172  if (multi_app_transfer->directions().contains(MultiAppTransfer::FROM_MULTIAPP))
5173  _from_multi_app_transfers.addObject(multi_app_transfer);
5174  if (multi_app_transfer->directions().contains(MultiAppTransfer::BETWEEN_MULTIAPP))
5175  _between_multi_app_transfers.addObject(multi_app_transfer);
5176  }
5177  else
5178  _transfers.addObject(transfer);
5179 }
5180 
5181 bool
5182 FEProblemBase::hasVariable(const std::string & var_name) const
5183 {
5184  for (auto & nl : _nl)
5185  if (nl->hasVariable(var_name))
5186  return true;
5187  if (_aux->hasVariable(var_name))
5188  return true;
5189 
5190  return false;
5191 }
5192 
5193 const MooseVariableFieldBase &
5195  const std::string & var_name,
5196  Moose::VarKindType expected_var_type,
5197  Moose::VarFieldType expected_var_field_type) const
5198 {
5199  return getVariableHelper(tid, var_name, expected_var_type, expected_var_field_type, _nl, *_aux);
5200 }
5201 
5202 MooseVariable &
5203 FEProblemBase::getStandardVariable(const THREAD_ID tid, const std::string & var_name)
5204 {
5205  for (auto & nl : _nl)
5206  if (nl->hasVariable(var_name))
5207  return nl->getFieldVariable<Real>(tid, var_name);
5208  if (_aux->hasVariable(var_name))
5209  return _aux->getFieldVariable<Real>(tid, var_name);
5210 
5211  mooseError("Unknown variable " + var_name);
5212 }
5213 
5215 FEProblemBase::getActualFieldVariable(const THREAD_ID tid, const std::string & var_name)
5216 {
5217  for (auto & nl : _nl)
5218  if (nl->hasVariable(var_name))
5219  return nl->getActualFieldVariable<Real>(tid, var_name);
5220  if (_aux->hasVariable(var_name))
5221  return _aux->getActualFieldVariable<Real>(tid, var_name);
5222 
5223  mooseError("Unknown variable " + var_name);
5224 }
5225 
5227 FEProblemBase::getVectorVariable(const THREAD_ID tid, const std::string & var_name)
5228 {
5229  for (auto & nl : _nl)
5230  if (nl->hasVariable(var_name))
5231  return nl->getFieldVariable<RealVectorValue>(tid, var_name);
5232  if (_aux->hasVariable(var_name))
5233  return _aux->getFieldVariable<RealVectorValue>(tid, var_name);
5234 
5235  mooseError("Unknown variable " + var_name);
5236 }
5237 
5239 FEProblemBase::getArrayVariable(const THREAD_ID tid, const std::string & var_name)
5240 {
5241  for (auto & nl : _nl)
5242  if (nl->hasVariable(var_name))
5243  return nl->getFieldVariable<RealEigenVector>(tid, var_name);
5244  if (_aux->hasVariable(var_name))
5245  return _aux->getFieldVariable<RealEigenVector>(tid, var_name);
5246 
5247  mooseError("Unknown variable " + var_name);
5248 }
5249 
5250 bool
5251 FEProblemBase::hasScalarVariable(const std::string & var_name) const
5252 {
5253  for (auto & nl : _nl)
5254  if (nl->hasScalarVariable(var_name))
5255  return true;
5256  if (_aux->hasScalarVariable(var_name))
5257  return true;
5258 
5259  return false;
5260 }
5261 
5263 FEProblemBase::getScalarVariable(const THREAD_ID tid, const std::string & var_name)
5264 {
5265  for (auto & nl : _nl)
5266  if (nl->hasScalarVariable(var_name))
5267  return nl->getScalarVariable(tid, var_name);
5268  if (_aux->hasScalarVariable(var_name))
5269  return _aux->getScalarVariable(tid, var_name);
5270 
5271  mooseError("Unknown variable " + var_name);
5272 }
5273 
5274 System &
5275 FEProblemBase::getSystem(const std::string & var_name)
5276 {
5277  const auto [var_in_nl, nl_sys_num] = determineNonlinearSystem(var_name);
5278  if (var_in_nl)
5279  return _nl[nl_sys_num]->system();
5280  else if (_aux->hasVariable(var_name))
5281  return _aux->system();
5282  else
5283  mooseError("Unable to find a system containing the variable " + var_name);
5284 }
5285 
5286 void
5288 {
5290 
5291  if (_displaced_problem)
5292  _displaced_problem->setActiveFEVariableCoupleableMatrixTags(mtags, tid);
5293 }
5294 
5295 void
5297 {
5299 
5300  if (_displaced_problem)
5301  _displaced_problem->setActiveFEVariableCoupleableVectorTags(vtags, tid);
5302 }
5303 
5304 void
5306  const THREAD_ID tid)
5307 {
5309 
5310  if (_displaced_problem)
5311  _displaced_problem->setActiveScalarVariableCoupleableMatrixTags(mtags, tid);
5312 }
5313 
5314 void
5316  const THREAD_ID tid)
5317 {
5319 
5320  if (_displaced_problem)
5321  _displaced_problem->setActiveScalarVariableCoupleableVectorTags(vtags, tid);
5322 }
5323 
5324 void
5325 FEProblemBase::setActiveElementalMooseVariables(const std::set<MooseVariableFEBase *> & moose_vars,
5326  const THREAD_ID tid)
5327 {
5329 
5330  if (_displaced_problem)
5331  _displaced_problem->setActiveElementalMooseVariables(moose_vars, tid);
5332 }
5333 
5334 void
5336 {
5338 
5339  if (_displaced_problem)
5340  _displaced_problem->clearActiveElementalMooseVariables(tid);
5341 }
5342 
5343 void
5345 {
5347 
5348  if (_displaced_problem)
5349  _displaced_problem->clearActiveFEVariableCoupleableMatrixTags(tid);
5350 }
5351 
5352 void
5354 {
5356 
5357  if (_displaced_problem)
5358  _displaced_problem->clearActiveFEVariableCoupleableVectorTags(tid);
5359 }
5360 
5361 void
5363 {
5365 
5366  if (_displaced_problem)
5367  _displaced_problem->clearActiveScalarVariableCoupleableMatrixTags(tid);
5368 }
5369 
5370 void
5372 {
5374 
5375  if (_displaced_problem)
5376  _displaced_problem->clearActiveScalarVariableCoupleableVectorTags(tid);
5377 }
5378 
5379 void
5380 FEProblemBase::setActiveMaterialProperties(const std::unordered_set<unsigned int> & mat_prop_ids,
5381  const THREAD_ID tid)
5382 {
5383  // mark active properties in every material
5384  for (auto & mat : _all_materials.getObjects(tid))
5385  mat->setActiveProperties(mat_prop_ids);
5386  for (auto & mat : _all_materials[Moose::FACE_MATERIAL_DATA].getObjects(tid))
5387  mat->setActiveProperties(mat_prop_ids);
5388  for (auto & mat : _all_materials[Moose::NEIGHBOR_MATERIAL_DATA].getObjects(tid))
5389  mat->setActiveProperties(mat_prop_ids);
5390 
5391  _has_active_material_properties[tid] = !mat_prop_ids.empty();
5392 }
5393 
5394 bool
5396 {
5397  return _has_active_material_properties[tid];
5398 }
5399 
5400 void
5402 {
5404 }
5405 
5406 void
5408 {
5409 #ifdef LIBMESH_ENABLE_AMR
5410  if ((_adaptivity.isOn() || _num_grid_steps) &&
5413  {
5414  // Even on a serialized Mesh, we don't keep our material
5415  // properties serialized, so we'll rely on the callback to
5416  // redistribute() to redistribute properties at the same time
5417  // libMesh is redistributing elements.
5418  auto add_redistributer = [this](MooseMesh & mesh,
5419  const std::string & redistributer_name,
5420  const bool use_displaced_mesh)
5421  {
5422  InputParameters redistribute_params = RedistributeProperties::validParams();
5423  redistribute_params.set<MooseApp *>("_moose_app") = &_app;
5424  redistribute_params.set<std::string>("for_whom") = this->name();
5425  redistribute_params.set<MooseMesh *>("mesh") = &mesh;
5426  redistribute_params.set<Moose::RelationshipManagerType>("rm_type") =
5428  redistribute_params.set<bool>("use_displaced_mesh") = use_displaced_mesh;
5429 
5430  std::shared_ptr<RedistributeProperties> redistributer =
5432  "RedistributeProperties", redistributer_name, redistribute_params);
5433 
5436 
5438  redistributer->addMaterialPropertyStorage(_bnd_material_props);
5439 
5441  redistributer->addMaterialPropertyStorage(_neighbor_material_props);
5442 
5443  mesh.getMesh().add_ghosting_functor(redistributer);
5444  };
5445 
5446  add_redistributer(_mesh, "mesh_property_redistributer", false);
5447  if (_displaced_problem)
5448  add_redistributer(_displaced_problem->mesh(), "displaced_mesh_property_redistributer", true);
5449  }
5450 #endif // LIBMESH_ENABLE_AMR
5451 }
5452 
5453 void
5455 {
5456  // Find the maximum number of quadrature points
5457  {
5458  MaxQpsThread mqt(*this);
5459  Threads::parallel_reduce(*_mesh.getActiveLocalElementRange(), mqt);
5460  _max_qps = mqt.max();
5461 
5462  // If we have more shape functions or more quadrature points on
5463  // another processor, then we may need to handle those elements
5464  // ourselves later after repartitioning.
5466  }
5467 
5468  unsigned int max_qpts = getMaxQps();
5469  if (max_qpts > Moose::constMaxQpsPerElem)
5470  mooseError("Max quadrature points per element assumptions made in some code (e.g. Coupleable ",
5471  "and MaterialPropertyInterface classes) have been violated.\n",
5472  "Complain to Moose developers to have constMaxQpsPerElem increased from ",
5474  " to ",
5475  max_qpts);
5476  for (unsigned int tid = 0; tid < libMesh::n_threads(); ++tid)
5477  {
5478  // the highest available order in libMesh is 43
5479  _scalar_zero[tid].resize(FORTYTHIRD, 0);
5480  _zero[tid].resize(max_qpts, 0);
5481  _ad_zero[tid].resize(max_qpts, 0);
5482  _grad_zero[tid].resize(max_qpts, RealGradient(0.));
5483  _ad_grad_zero[tid].resize(max_qpts, ADRealGradient(0));
5484  _second_zero[tid].resize(max_qpts, RealTensor(0.));
5485  _ad_second_zero[tid].resize(max_qpts, ADRealTensorValue(0));
5486  _vector_zero[tid].resize(max_qpts, RealGradient(0.));
5487  _vector_curl_zero[tid].resize(max_qpts, RealGradient(0.));
5488  }
5489 }
5490 
5491 void
5493 {
5494  for (unsigned int tid = 0; tid < libMesh::n_threads(); ++tid)
5495  for (const auto i : index_range(_nl))
5496  _assembly[tid][i]->bumpVolumeQRuleOrder(order, block);
5497 
5498  if (_displaced_problem)
5499  _displaced_problem->bumpVolumeQRuleOrder(order, block);
5500 
5501  updateMaxQps();
5502 }
5503 
5504 void
5506 {
5507  for (unsigned int tid = 0; tid < libMesh::n_threads(); ++tid)
5508  for (const auto i : index_range(_nl))
5509  _assembly[tid][i]->bumpAllQRuleOrder(order, block);
5510 
5511  if (_displaced_problem)
5512  _displaced_problem->bumpAllQRuleOrder(order, block);
5513 
5514  updateMaxQps();
5515 }
5516 
5517 void
5519  Order order,
5520  Order volume_order,
5521  Order face_order,
5522  SubdomainID block,
5523  const bool allow_negative_qweights)
5524 {
5525  if (order == INVALID_ORDER)
5526  {
5527  // automatically determine the integration order
5528  order = _nl[0]->getMinQuadratureOrder();
5529  for (const auto i : make_range(std::size_t(1), _nl.size()))
5530  if (order < _nl[i]->getMinQuadratureOrder())
5531  order = _nl[i]->getMinQuadratureOrder();
5532  if (order < _aux->getMinQuadratureOrder())
5533  order = _aux->getMinQuadratureOrder();
5534  }
5535 
5536  if (volume_order == INVALID_ORDER)
5537  volume_order = order;
5538 
5539  if (face_order == INVALID_ORDER)
5540  face_order = order;
5541 
5542  for (unsigned int tid = 0; tid < libMesh::n_threads(); ++tid)
5543  for (const auto i : index_range(_nl))
5544  _assembly[tid][i]->createQRules(
5545  type, order, volume_order, face_order, block, allow_negative_qweights);
5546 
5547  if (_displaced_problem)
5548  _displaced_problem->createQRules(
5549  type, order, volume_order, face_order, block, allow_negative_qweights);
5550 
5551  updateMaxQps();
5552 }
5553 
5554 void
5556 {
5558  {
5560  mooseError("Someone told us (the FEProblemBase) to trust the user coupling matrix, but we "
5561  "haven't been provided a coupling matrix!");
5562 
5563  // We've been told to trust the user coupling matrix, so we're going to leave things alone
5564  return;
5565  }
5566 
5567  _coupling = type;
5568 }
5569 
5570 void
5571 FEProblemBase::setCouplingMatrix(CouplingMatrix * cm, const unsigned int i)
5572 {
5573  // TODO: Deprecate method
5575  _cm[i].reset(cm);
5576 }
5577 
5578 void
5579 FEProblemBase::setCouplingMatrix(std::unique_ptr<CouplingMatrix> cm, const unsigned int i)
5580 {
5582  _cm[i] = std::move(cm);
5583 }
5584 
5585 void
5587 {
5589  mooseError("Someone told us (the FEProblemBase) to trust the user coupling matrix, but we "
5590  "haven't been provided a coupling matrix!");
5591 
5593 }
5594 
5595 void
5597 {
5598  TIME_SECTION("setNonlocalCouplingMatrix", 5, "Setting Nonlocal Coupling Matrix");
5599 
5600  if (_nl.size() > 1)
5601  mooseError("Nonlocal kernels are weirdly stored on the FEProblem so we don't currently support "
5602  "multiple nonlinear systems with nonlocal kernels.");
5603 
5604  for (const auto nl_sys_num : index_range(_nl))
5605  {
5606  auto & nl = _nl[nl_sys_num];
5607  auto & nonlocal_cm = _nonlocal_cm[nl_sys_num];
5608  unsigned int n_vars = nl->nVariables();
5609  nonlocal_cm.resize(n_vars);
5610  const auto & vars = nl->getVariables(0);
5611  const auto & nonlocal_kernel = _nonlocal_kernels.getObjects();
5612  const auto & nonlocal_integrated_bc = _nonlocal_integrated_bcs.getObjects();
5613  for (const auto & ivar : vars)
5614  {
5615  for (const auto & kernel : nonlocal_kernel)
5616  {
5617  for (unsigned int i = ivar->number(); i < ivar->number() + ivar->count(); ++i)
5618  if (i == kernel->variable().number())
5619  for (const auto & jvar : vars)
5620  {
5621  const auto it = _var_dof_map.find(jvar->name());
5622  if (it != _var_dof_map.end())
5623  {
5624  unsigned int j = jvar->number();
5625  nonlocal_cm(i, j) = 1;
5626  }
5627  }
5628  }
5629  for (const auto & integrated_bc : nonlocal_integrated_bc)
5630  {
5631  for (unsigned int i = ivar->number(); i < ivar->number() + ivar->count(); ++i)
5632  if (i == integrated_bc->variable().number())
5633  for (const auto & jvar : vars)
5634  {
5635  const auto it = _var_dof_map.find(jvar->name());
5636  if (it != _var_dof_map.end())
5637  {
5638  unsigned int j = jvar->number();
5639  nonlocal_cm(i, j) = 1;
5640  }
5641  }
5642  }
5643  }
5644  }
5645 }
5646 
5647 bool
5648 FEProblemBase::areCoupled(const unsigned int ivar,
5649  const unsigned int jvar,
5650  const unsigned int nl_sys) const
5651 {
5652  return (*_cm[nl_sys])(ivar, jvar);
5653 }
5654 
5655 std::vector<std::pair<MooseVariableFEBase *, MooseVariableFEBase *>> &
5656 FEProblemBase::couplingEntries(const THREAD_ID tid, const unsigned int nl_sys)
5657 {
5658  return _assembly[tid][nl_sys]->couplingEntries();
5659 }
5660 
5661 std::vector<std::pair<MooseVariableFEBase *, MooseVariableFEBase *>> &
5662 FEProblemBase::nonlocalCouplingEntries(const THREAD_ID tid, const unsigned int nl_sys)
5663 {
5664  return _assembly[tid][nl_sys]->nonlocalCouplingEntries();
5665 }
5666 
5667 void
5669 {
5670  if (_initialized)
5671  return;
5672 
5673  TIME_SECTION("init", 2, "Initializing");
5674 
5675  // call executioner's preProblemInit so that it can do some setups before problem init
5677 
5678  // If we have AD and we are doing global AD indexing, then we should by default set the matrix
5679  // coupling to full. If the user has told us to trust their coupling matrix, then this call will
5680  // not do anything
5683 
5684  for (const auto i : index_range(_nl))
5685  {
5686  auto & nl = _nl[i];
5687  auto & cm = _cm[i];
5688 
5689  unsigned int n_vars = nl->nVariables();
5690  {
5691  TIME_SECTION("fillCouplingMatrix", 3, "Filling Coupling Matrix");
5692 
5693  switch (_coupling)
5694  {
5695  case Moose::COUPLING_DIAG:
5696  cm = std::make_unique<CouplingMatrix>(n_vars);
5697  for (unsigned int i = 0; i < n_vars; i++)
5698  (*cm)(i, i) = 1;
5699  break;
5700 
5701  // for full jacobian
5702  case Moose::COUPLING_FULL:
5703  cm = std::make_unique<CouplingMatrix>(n_vars);
5704  for (unsigned int i = 0; i < n_vars; i++)
5705  for (unsigned int j = 0; j < n_vars; j++)
5706  (*cm)(i, j) = 1;
5707  break;
5708 
5710  // do nothing, _cm was already set through couplingMatrix() call
5711  break;
5712  }
5713  }
5714 
5715  nl->dofMap()._dof_coupling = cm.get();
5716 
5717  // If there are no variables, make sure to pass a nullptr coupling
5718  // matrix, to avoid warnings about non-nullptr yet empty
5719  // CouplingMatrices.
5720  if (n_vars == 0)
5721  nl->dofMap()._dof_coupling = nullptr;
5722 
5723  nl->dofMap().attach_extra_sparsity_function(&extraSparsity, nl.get());
5724  nl->dofMap().attach_extra_send_list_function(&extraSendList, nl.get());
5725  _aux->dofMap().attach_extra_send_list_function(&extraSendList, _aux.get());
5726 
5727  if (!_skip_nl_system_check && _solve && n_vars == 0)
5728  mooseError("No variables specified in the FEProblemBase '", name(), "'.");
5729  }
5730 
5731  ghostGhostedBoundaries(); // We do this again right here in case new boundaries have been added
5732 
5733  // We may have added element/nodes to the mesh in ghostGhostedBoundaries so we need to update
5734  // all of our mesh information. We need to make sure that mesh information is up-to-date before
5735  // EquationSystems::init because that will call through to updateGeomSearch (for sparsity
5736  // augmentation) and if we haven't added back boundary node information before that latter call,
5737  // then we're screwed. We'll get things like "Unable to find closest node!"
5738  _mesh.meshChanged();
5739  if (_displaced_problem)
5741 
5742  // do not assemble system matrix for JFNK solve
5743  for (auto & nl : _nl)
5744  {
5746  nl->turnOffJacobian();
5747  nl->init();
5748  }
5749  _aux->init();
5750 
5751  // Build the mortar segment meshes, if they haven't been already, for a couple reasons:
5752  // 1) Get the ghosting correct for both static and dynamic meshes
5753  // 2) Make sure the mortar mesh is built for mortar constraints that live on the static mesh
5754  //
5755  // It is worth-while to note that mortar meshes that live on a dynamic mesh will be built
5756  // during residual and Jacobian evaluation because when displacements are solution variables
5757  // the mortar mesh will move and change during the course of a non-linear solve. We DO NOT
5758  // redo ghosting during non-linear solve, so for purpose 1) the below call has to be made
5759  if (!_mortar_data.initialized())
5760  updateMortarMesh();
5761 
5762  {
5763  TIME_SECTION("EquationSystems::Init", 2, "Initializing Equation Systems");
5764  es().init();
5765  }
5766 
5767  // Now that the equation system and the dof distribution is done, we can generate the
5768  // finite volume-related parts if needed.
5769  if (haveFV())
5771 
5772  for (auto & nl : _nl)
5773  nl->update();
5774  _aux->update();
5775 
5776  for (THREAD_ID tid = 0; tid < libMesh::n_threads(); ++tid)
5777  for (const auto i : index_range(_nl))
5778  _assembly[tid][i]->init(_cm[i].get());
5779 
5780  if (_displaced_problem)
5781  _displaced_problem->init();
5782 
5783  _initialized = true;
5784 }
5785 
5786 unsigned int
5787 FEProblemBase::nlSysNum(const NonlinearSystemName & nl_sys_name) const
5788 {
5789  std::istringstream ss(nl_sys_name);
5790  unsigned int nl_sys_num;
5791  if (!(ss >> nl_sys_num) || !ss.eof())
5792  nl_sys_num = libmesh_map_find(_nl_sys_name_to_num, nl_sys_name);
5793 
5794  return nl_sys_num;
5795 }
5796 
5797 void
5798 FEProblemBase::solve(const unsigned int nl_sys_num)
5799 {
5800  TIME_SECTION("solve", 1, "Solving", false);
5801 
5802  setCurrentNonlinearSystem(nl_sys_num);
5803 
5804  // This prevents stale dof indices from lingering around and possibly leading to invalid reads
5805  // and writes. Dof indices may be made stale through operations like mesh adaptivity
5807  if (_displaced_problem)
5808  _displaced_problem->clearAllDofIndices();
5809 
5810 #if PETSC_RELEASE_LESS_THAN(3, 12, 0)
5812  _petsc_options, _solver_params); // Make sure the PETSc options are setup for this app
5813 #else
5814  // Now this database will be the default
5815  // Each app should have only one database
5816  if (!_app.isUltimateMaster())
5817  PetscOptionsPush(_petsc_option_data_base);
5818  // We did not add PETSc options to database yet
5820  {
5823  }
5824 #endif
5825 
5826  // set up DM which is required if use a field split preconditioner
5827  // We need to setup DM every "solve()" because libMesh destroy SNES after solve()
5828  // Do not worry, DM setup is very cheap
5830 
5831  // Setup the output system for printing linear/nonlinear iteration information and some solver
5832  // settings
5834 
5836 
5837  // reset flag so that residual evaluation does not get skipped
5838  // and the next non-linear iteration does not automatically fail with
5839  // "DIVERGED_NANORINF", when we throw an exception and stop solve
5841 
5842  if (_solve)
5844 
5845  if (_solve)
5847 
5848  // sync solutions in displaced problem
5849  if (_displaced_problem)
5850  _displaced_problem->syncSolutions();
5851 
5852 #if !PETSC_RELEASE_LESS_THAN(3, 12, 0)
5853  if (!_app.isUltimateMaster())
5854  PetscOptionsPop();
5855 #endif
5856 }
5857 
5858 void
5859 FEProblemBase::setException(const std::string & message)
5860 {
5861  _has_exception = true;
5862  _exception_message = message;
5863 }
5864 
5865 void
5867 {
5869  return;
5870 
5871  TIME_SECTION("checkExceptionAndStopSolve", 5);
5872 
5873  // See if any processor had an exception. If it did, get back the
5874  // processor that the exception occurred on.
5875  unsigned int processor_id;
5876 
5878 
5879  if (_has_exception)
5880  {
5882 
5885  {
5886  // Print the message
5887  if (_communicator.rank() == 0 && print_message)
5888  {
5889  _console << "\n" << _exception_message << "\n";
5890  if (isTransient())
5891  _console
5892  << "To recover, the solution will fail and then be re-attempted with a reduced time "
5893  "step.\n"
5894  << std::endl;
5895  }
5896 
5897  // Stop the solve -- this entails setting
5898  // SNESSetFunctionDomainError() or directly inserting NaNs in the
5899  // residual vector to let PETSc >= 3.6 return DIVERGED_NANORINF.
5901 
5902  // and close Aux system (we MUST do this here; see #11525)
5903  _aux->solution().close();
5904 
5905  // We've handled this exception, so we no longer have one.
5906  _has_exception = false;
5907 
5908  // Force the next non-linear convergence check to fail (and all further residual evaluation
5909  // to be skipped).
5911 
5912  // Repropagate the exception, so it can be caught at a higher level, typically
5913  // this is NonlinearSystem::computeResidual().
5915  }
5916  else
5917  mooseError("The following parallel-communicated exception was detected during " +
5918  Moose::stringify(_current_execute_on_flag) + " evaluation:\n" +
5920  "\nBecause this did not occur during residual evaluation, there"
5921  " is no way to handle this, so the solution is aborting.\n");
5922  }
5923 }
5924 
5925 void
5927 {
5928  // Our default state is to allow computing derivatives
5929  ADReal::do_derivatives = true;
5931 
5934 
5937 
5941  if (_displaced_problem)
5942  {
5943  _displaced_problem->setCurrentlyComputingResidual(false);
5944  _displaced_problem->setCurrentlyComputingJacobian(false);
5945  _displaced_problem->setCurrentlyComputingResidualAndJacobian(false);
5946  }
5947 }
5948 
5949 bool
5950 FEProblemBase::nlConverged(const unsigned int nl_sys_num)
5951 {
5952  if (_solve)
5953  return _nl[nl_sys_num]->converged();
5954  else
5955  return true;
5956 }
5957 
5958 unsigned int
5959 FEProblemBase::nNonlinearIterations(const unsigned int nl_sys_num) const
5960 {
5961  return _nl[nl_sys_num]->nNonlinearIterations();
5962 }
5963 
5964 unsigned int
5965 FEProblemBase::nLinearIterations(const unsigned int nl_sys_num) const
5966 {
5967  return _nl[nl_sys_num]->nLinearIterations();
5968 }
5969 
5970 Real
5971 FEProblemBase::finalNonlinearResidual(const unsigned int nl_sys_num) const
5972 {
5973  return _nl[nl_sys_num]->finalNonlinearResidual();
5974 }
5975 
5976 bool
5977 FEProblemBase::computingInitialResidual(const unsigned int nl_sys_num) const
5978 {
5979  return _nl[nl_sys_num]->computingInitialResidual();
5980 }
5981 
5982 void
5984 {
5985  TIME_SECTION("copySolutionsBackwards", 3, "Copying Solutions Backward");
5986 
5987  for (auto & nl : _nl)
5988  nl->copySolutionsBackwards();
5989  _aux->copySolutionsBackwards();
5990 }
5991 
5992 void
5994 {
5995  TIME_SECTION("advanceState", 5, "Advancing State");
5996 
5997  for (auto & nl : _nl)
5998  nl->copyOldSolutions();
5999  _aux->copyOldSolutions();
6000 
6001  if (_displaced_problem)
6002  {
6003  for (const auto i : index_range(_nl))
6004  _displaced_problem->nlSys(i).copyOldSolutions();
6005  _displaced_problem->auxSys().copyOldSolutions();
6006  }
6007 
6009 
6012 
6015 
6018 }
6019 
6020 void
6022 {
6023  TIME_SECTION("restoreSolutions", 5, "Restoring Solutions");
6024 
6025  for (auto & nl : _nl)
6026  nl->restoreSolutions();
6027  _aux->restoreSolutions();
6028 
6029  if (_displaced_problem)
6030  _displaced_problem->updateMesh();
6031 }
6032 
6033 void
6035 {
6036  TIME_SECTION("saveOldSolutions", 5, "Saving Old Solutions");
6037 
6038  for (auto & nl : _nl)
6039  nl->saveOldSolutions();
6040  _aux->saveOldSolutions();
6041 }
6042 
6043 void
6045 {
6046  TIME_SECTION("restoreOldSolutions", 5, "Restoring Old Solutions");
6047 
6048  for (auto & nl : _nl)
6049  nl->restoreOldSolutions();
6050  _aux->restoreOldSolutions();
6051 }
6052 
6053 void
6055 {
6056  TIME_SECTION("outputStep", 1, "Outputting");
6057 
6059 
6060  for (auto & nl : _nl)
6061  nl->update();
6062  _aux->update();
6063  if (_displaced_problem)
6064  _displaced_problem->syncSolutions();
6066 
6068 }
6069 
6070 void
6072 {
6074 }
6075 
6076 void
6078 {
6080 }
6081 
6082 void
6084 {
6087 }
6088 
6089 void
6091 {
6092  TIME_SECTION("onTimestepBegin", 2);
6093 
6094  for (auto & nl : _nl)
6095  nl->onTimestepBegin();
6096 }
6097 
6098 void
6100 {
6101 }
6102 
6103 Real
6105 {
6107  // If we are any iteration type other than time (e.g. nonlinear), then temporally we are still
6108  // in the present time
6109  return time();
6110 
6111  switch (state.state)
6112  {
6113  case 0:
6114  return time();
6115 
6116  case 1:
6117  return timeOld();
6118 
6119  default:
6120  mooseError("Unhandled state ", state.state, " in FEProblemBase::getTimeFromStateArg");
6121  }
6122 }
6123 
6124 void
6125 FEProblemBase::addTimeIntegrator(const std::string & type,
6126  const std::string & name,
6127  InputParameters & parameters)
6128 {
6129  parallel_object_only();
6130 
6131  parameters.set<SubProblem *>("_subproblem") = this;
6132  logAdd("TimeIntegrator", name, type);
6133  _aux->addTimeIntegrator(type, name + ":aux", parameters);
6134  for (auto & nl : _nl)
6135  nl->addTimeIntegrator(type, name + ":" + nl->name(), parameters);
6136  _has_time_integrator = true;
6137 
6138  // add vectors to store u_dot, u_dotdot, udot_old, u_dotdot_old and
6139  // solution vectors older than 2 time steps, if requested by the time
6140  // integrator
6141  _aux->addDotVectors();
6142  for (auto & nl : _nl)
6143  {
6144  nl->addDotVectors();
6145 
6146  auto tag_udot = nl->getTimeIntegrator()->uDotFactorTag();
6147  if (!nl->hasVector(tag_udot))
6148  nl->associateVectorToTag(*nl->solutionUDot(), tag_udot);
6149  auto tag_udotdot = nl->getTimeIntegrator()->uDotDotFactorTag();
6150  if (!nl->hasVector(tag_udotdot) && uDotDotRequested())
6151  nl->associateVectorToTag(*nl->solutionUDotDot(), tag_udotdot);
6152  }
6153 }
6154 
6155 void
6156 FEProblemBase::addPredictor(const std::string & type,
6157  const std::string & name,
6158  InputParameters & parameters)
6159 {
6160  parallel_object_only();
6161 
6162  parameters.set<SubProblem *>("_subproblem") = this;
6163  std::shared_ptr<Predictor> predictor = _factory.create<Predictor>(type, name, parameters);
6164  logAdd("Predictor", name, type);
6165 
6166  for (auto & nl : _nl)
6167  nl->setPredictor(predictor);
6168 }
6169 
6170 Real
6172 {
6173  TIME_SECTION("computeResidualL2Norm", 2, "Computing L2 Norm of Residual");
6174 
6175  if (_nl.size() > 1)
6176  mooseError("Multiple nonlinear systems in the same input are not currently supported when "
6177  "performing fixed point iterations in multi-app contexts");
6178 
6179  _current_nl_sys = _nl[0].get();
6180  computeResidual(*_nl[0]->currentSolution(), _nl[0]->RHS(), /*nl_sys=*/0);
6181 
6182  return _nl[0]->RHS().l2_norm();
6183 }
6184 
6185 void
6186 FEProblemBase::computeResidualSys(NonlinearImplicitSystem & sys,
6187  const NumericVector<Number> & soln,
6188  NumericVector<Number> & residual)
6189 {
6190  parallel_object_only();
6191 
6192  TIME_SECTION("computeResidualSys", 5);
6193 
6194  computeResidual(soln, residual, sys.number());
6195 }
6196 
6197 void
6198 FEProblemBase::computeResidual(NonlinearImplicitSystem & sys,
6199  const NumericVector<Number> & soln,
6200  NumericVector<Number> & residual)
6201 {
6202  mooseDeprecated("Please use computeResidualSys");
6203 
6204  computeResidualSys(sys, soln, residual);
6205 }
6206 
6207 void
6209  NumericVector<Number> & residual,
6210  const unsigned int nl_sys_num)
6211 {
6212  setCurrentNonlinearSystem(nl_sys_num);
6213 
6214  // We associate the residual tag with the given residual vector to make sure we
6215  // don't filter it out below
6217  const auto & residual_vector_tags = getVectorTags(Moose::VECTOR_TAG_RESIDUAL);
6218 
6219  // We filter out tags which do not have associated vectors in the current nonlinear
6220  // system. This is essential to be able to use system-dependent residual tags.
6222 
6223  computeResidualInternal(soln, residual, _fe_vector_tags);
6224 }
6225 
6226 void
6228  NumericVector<Number> & residual,
6229  SparseMatrix<Number> & jacobian)
6230 {
6231  try
6232  {
6233  try
6234  {
6235  // vector tags
6236  {
6238  const auto & residual_vector_tags = getVectorTags(Moose::VECTOR_TAG_RESIDUAL);
6239 
6240  // We filter out tags which do not have associated vectors in the current nonlinear
6241  // system. This is essential to be able to use system-dependent residual tags.
6243 
6245  }
6246 
6247  // matrix tags
6248  {
6249  _fe_matrix_tags.clear();
6250 
6251  auto & tags = getMatrixTags();
6252  for (auto & tag : tags)
6253  _fe_matrix_tags.insert(tag.second);
6254  }
6255 
6257 
6260 
6261  for (const auto tag : _fe_matrix_tags)
6262  if (_current_nl_sys->hasMatrix(tag))
6263  {
6264  auto & matrix = _current_nl_sys->getMatrix(tag);
6265  matrix.zero();
6266  if (haveADObjects())
6267  // PETSc algorithms require diagonal allocations regardless of whether there is non-zero
6268  // diagonal dependence. With global AD indexing we only add non-zero
6269  // dependence, so PETSc will scream at us unless we artificially add the diagonals.
6270  for (auto index : make_range(matrix.row_start(), matrix.row_stop()))
6271  matrix.add(index, index, 0);
6272  }
6273 
6274  _aux->zeroVariablesForResidual();
6275 
6276  unsigned int n_threads = libMesh::n_threads();
6277 
6279 
6280  // Random interface objects
6281  for (const auto & it : _random_data_objects)
6282  it.second->updateSeeds(EXEC_LINEAR);
6283 
6287  if (_displaced_problem)
6288  {
6289  _displaced_problem->setCurrentlyComputingResidual(true);
6290  _displaced_problem->setCurrentlyComputingJacobian(true);
6291  _displaced_problem->setCurrentlyComputingResidualAndJacobian(true);
6292  }
6293 
6295 
6297 
6298  for (unsigned int tid = 0; tid < n_threads; tid++)
6299  reinitScalars(tid);
6300 
6302 
6303  _aux->residualSetup();
6304 
6305  if (_displaced_problem)
6306  {
6307  _aux->compute(EXEC_PRE_DISPLACE);
6308  _displaced_problem->updateMesh();
6310  updateMortarMesh();
6311  }
6312 
6313  for (THREAD_ID tid = 0; tid < n_threads; tid++)
6314  {
6317  }
6318 
6319  // Where is the aux system done? Could the non-current nonlinear systems also be done there?
6320  for (auto & nl : _nl)
6321  nl->computeTimeDerivatives();
6322 
6323  _aux->compute(EXEC_LINEAR);
6324 
6326 
6328 
6330 
6333 
6335 
6338  }
6339  catch (...)
6340  {
6341  handleException("computeResidualAndJacobian");
6342  }
6343  }
6344  catch (const MooseException &)
6345  {
6346  // The buck stops here, we have already handled the exception by
6347  // calling the system's stopSolve() method, it is now up to PETSc to return a
6348  // "diverged" reason during the next solve.
6349  }
6350  catch (...)
6351  {
6352  mooseError("Unexpected exception type");
6353  }
6354 
6355  resetState();
6356 }
6357 
6358 void
6360  NumericVector<Number> & residual,
6361  TagID tag)
6362 {
6363  try
6364  {
6366 
6367  _current_nl_sys->associateVectorToTag(residual, tag);
6368 
6369  computeResidualTags({tag});
6370 
6372  }
6373  catch (MooseException & e)
6374  {
6375  // If a MooseException propagates all the way to here, it means
6376  // that it was thrown from a MOOSE system where we do not
6377  // (currently) properly support the throwing of exceptions, and
6378  // therefore we have no choice but to error out. It may be
6379  // *possible* to handle exceptions from other systems, but in the
6380  // meantime, we don't want to silently swallow any unhandled
6381  // exceptions here.
6382  mooseError("An unhandled MooseException was raised during residual computation. Please "
6383  "contact the MOOSE team for assistance.");
6384  }
6385 }
6386 
6387 void
6389  NumericVector<Number> & residual,
6390  const std::set<TagID> & tags)
6391 {
6392  parallel_object_only();
6393 
6394  TIME_SECTION("computeResidualInternal", 1);
6395 
6396  try
6397  {
6399 
6401 
6402  computeResidualTags(tags);
6403 
6405  }
6406  catch (MooseException & e)
6407  {
6408  // If a MooseException propagates all the way to here, it means
6409  // that it was thrown from a MOOSE system where we do not
6410  // (currently) properly support the throwing of exceptions, and
6411  // therefore we have no choice but to error out. It may be
6412  // *possible* to handle exceptions from other systems, but in the
6413  // meantime, we don't want to silently swallow any unhandled
6414  // exceptions here.
6415  mooseError("An unhandled MooseException was raised during residual computation. Please "
6416  "contact the MOOSE team for assistance.");
6417  }
6418 }
6419 
6420 void
6422  NumericVector<Number> & residual,
6423  TagID tag)
6424 {
6425  TIME_SECTION("computeResidualType", 5);
6426 
6427  try
6428  {
6430 
6432 
6434 
6436  }
6437  catch (MooseException & e)
6438  {
6439  // If a MooseException propagates all the way to here, it means
6440  // that it was thrown from a MOOSE system where we do not
6441  // (currently) properly support the throwing of exceptions, and
6442  // therefore we have no choice but to error out. It may be
6443  // *possible* to handle exceptions from other systems, but in the
6444  // meantime, we don't want to silently swallow any unhandled
6445  // exceptions here.
6446  mooseError("An unhandled MooseException was raised during residual computation. Please "
6447  "contact the MOOSE team for assistance.");
6448  }
6449 }
6450 
6451 void
6452 FEProblemBase::handleException(const std::string & calling_method)
6453 {
6454  auto create_exception_message =
6455  [&calling_method](const std::string & exception_type, const auto & exception)
6456  {
6457  return std::string("A " + exception_type + " was raised during FEProblemBase::" +
6458  calling_method + "\n" + std::string(exception.what()));
6459  };
6460 
6461  try
6462  {
6463  throw;
6464  }
6465  catch (const libMesh::LogicError & e)
6466  {
6467  setException(create_exception_message("libMesh::LogicError", e));
6468  }
6469  catch (const MooseException & e)
6470  {
6471  setException(create_exception_message("MooseException", e));
6472  }
6473  catch (const MetaPhysicL::LogicError & e)
6474  {
6476  }
6477  catch (const libMesh::PetscSolverException & e)
6478  {
6479  // One PETSc solver exception that we cannot currently recover from are new nonzero errors. In
6480  // particular I have observed the following scenario in a parallel test:
6481  // - Both processes throw because of a new nonzero during MOOSE's computeJacobianTags
6482  // - We potentially handle the exceptions nicely here
6483  // - When the matrix is closed in libMesh's libmesh_petsc_snes_solver, there is a new nonzero
6484  // throw which we do not catch here in MOOSE and the simulation terminates. This only appears
6485  // in parallel (and not all the time; a test I was examining threw with distributed mesh, but
6486  // not with replicated). In serial there are no new throws from libmesh_petsc_snes_solver.
6487  // So for uniformity of behavior across serial/parallel, we will choose to abort here and always
6488  // produce a non-zero exit code
6489  mooseError(create_exception_message("libMesh::PetscSolverException", e));
6490  }
6491  catch (const std::exception & e)
6492  {
6493  const auto message = create_exception_message("std::exception", e);
6495  mooseError(message);
6496  else
6497  setException(message);
6498  }
6499 
6501 }
6502 
6503 void
6504 FEProblemBase::computeResidualTags(const std::set<TagID> & tags)
6505 {
6506  parallel_object_only();
6507 
6508  try
6509  {
6510  try
6511  {
6512  TIME_SECTION("computeResidualTags", 5, "Computing Residual");
6513 
6514  ADReal::do_derivatives = false;
6515 
6517 
6518  _aux->zeroVariablesForResidual();
6519 
6520  unsigned int n_threads = libMesh::n_threads();
6521 
6523 
6524  // Random interface objects
6525  for (const auto & it : _random_data_objects)
6526  it.second->updateSeeds(EXEC_LINEAR);
6527 
6529 
6531 
6532  for (unsigned int tid = 0; tid < n_threads; tid++)
6533  reinitScalars(tid);
6534 
6536 
6537  _aux->residualSetup();
6538 
6539  if (_displaced_problem)
6540  {
6541  _aux->compute(EXEC_PRE_DISPLACE);
6542  _displaced_problem->updateMesh();
6544  updateMortarMesh();
6545  }
6546 
6547  for (THREAD_ID tid = 0; tid < n_threads; tid++)
6548  {
6551  }
6552 
6553  // Where is the aux system done? Could the non-current nonlinear systems also be done there?
6554  for (auto & nl : _nl)
6555  nl->computeTimeDerivatives();
6556 
6557  _aux->compute(EXEC_LINEAR);
6558 
6560 
6562 
6564 
6567  }
6568  catch (...)
6569  {
6570  handleException("computeResidualTags");
6571  }
6572  }
6573  catch (const MooseException &)
6574  {
6575  // The buck stops here, we have already handled the exception by
6576  // calling the system's stopSolve() method, it is now up to PETSc to return a
6577  // "diverged" reason during the next solve.
6578  }
6579  catch (...)
6580  {
6581  mooseError("Unexpected exception type");
6582  }
6583 
6584  resetState();
6585 }
6586 
6587 void
6588 FEProblemBase::computeJacobianSys(NonlinearImplicitSystem & sys,
6589  const NumericVector<Number> & soln,
6590  SparseMatrix<Number> & jacobian)
6591 {
6592  computeJacobian(soln, jacobian, sys.number());
6593 }
6594 
6595 void
6597  SparseMatrix<Number> & jacobian,
6598  TagID tag)
6599 {
6601 
6602  _current_nl_sys->associateMatrixToTag(jacobian, tag);
6603 
6604  computeJacobianTags({tag});
6605 
6607 }
6608 
6609 void
6611  SparseMatrix<Number> & jacobian,
6612  const unsigned int nl_sys_num)
6613 {
6614  setCurrentNonlinearSystem(nl_sys_num);
6615 
6616  _fe_matrix_tags.clear();
6617 
6618  auto & tags = getMatrixTags();
6619  for (auto & tag : tags)
6620  _fe_matrix_tags.insert(tag.second);
6621 
6622  computeJacobianInternal(soln, jacobian, _fe_matrix_tags);
6623 }
6624 
6625 void
6627  SparseMatrix<Number> & jacobian,
6628  const std::set<TagID> & tags)
6629 {
6630  TIME_SECTION("computeJacobianInternal", 1);
6631 
6633 
6635 
6636  computeJacobianTags(tags);
6637 
6639 }
6640 
6641 void
6642 FEProblemBase::computeJacobianTags(const std::set<TagID> & tags)
6643 {
6644  try
6645  {
6646  try
6647  {
6648  if (!_has_jacobian || !_const_jacobian)
6649  {
6650  TIME_SECTION("computeJacobianTags", 5, "Computing Jacobian");
6651 
6652  for (auto tag : tags)
6653  if (_current_nl_sys->hasMatrix(tag))
6654  {
6655  auto & matrix = _current_nl_sys->getMatrix(tag);
6656  matrix.zero();
6657  if (haveADObjects())
6658  // PETSc algorithms require diagonal allocations regardless of whether there is
6659  // non-zero diagonal dependence. With global AD indexing we only add non-zero
6660  // dependence, so PETSc will scream at us unless we artificially add the diagonals.
6661  for (auto index : make_range(matrix.row_start(), matrix.row_stop()))
6662  matrix.add(index, index, 0);
6663  }
6664 
6665  _aux->zeroVariablesForJacobian();
6666 
6667  unsigned int n_threads = libMesh::n_threads();
6668 
6669  // Random interface objects
6670  for (const auto & it : _random_data_objects)
6671  it.second->updateSeeds(EXEC_NONLINEAR);
6672 
6675  if (_displaced_problem)
6676  _displaced_problem->setCurrentlyComputingJacobian(true);
6677 
6680 
6681  for (unsigned int tid = 0; tid < n_threads; tid++)
6682  reinitScalars(tid);
6683 
6685 
6686  _aux->jacobianSetup();
6687 
6688  if (_displaced_problem)
6689  {
6690  _aux->compute(EXEC_PRE_DISPLACE);
6691  _displaced_problem->updateMesh();
6692  }
6693 
6694  for (unsigned int tid = 0; tid < n_threads; tid++)
6695  {
6698  }
6699 
6700  // When computing the initial Jacobian for automatic variable scaling we need to make sure
6701  // that the time derivatives have been calculated. So we'll call down to the nonlinear
6702  // system here. Note that if we are not doing this initial Jacobian calculation we will
6703  // just exit in that class to avoid redundant calculation (the residual function also
6704  // computes time derivatives)
6705  _current_nl_sys->computeTimeDerivatives(/*jacobian_calculation =*/true);
6706 
6707  _aux->compute(EXEC_NONLINEAR);
6708 
6710 
6712 
6714 
6716 
6718 
6719  // For explicit Euler calculations for example we often compute the Jacobian one time and
6720  // then re-use it over and over. If we're performing automatic scaling, we don't want to
6721  // use that kernel, diagonal-block only Jacobian for our actual matrix when performing
6722  // solves!
6724  _has_jacobian = true;
6725  }
6726  }
6727  catch (...)
6728  {
6729  handleException("computeJacobianTags");
6730  }
6731  }
6732  catch (const MooseException &)
6733  {
6734  // The buck stops here, we have already handled the exception by
6735  // calling the system's stopSolve() method, it is now up to PETSc to return a
6736  // "diverged" reason during the next solve.
6737  }
6738  catch (...)
6739  {
6740  mooseError("Unexpected exception type");
6741  }
6742 
6743  resetState();
6744 }
6745 
6746 void
6747 FEProblemBase::computeJacobianBlocks(std::vector<JacobianBlock *> & blocks,
6748  const unsigned int nl_sys_num)
6749 {
6750  TIME_SECTION("computeTransientImplicitJacobian", 2);
6751  setCurrentNonlinearSystem(nl_sys_num);
6752 
6753  if (_displaced_problem)
6754  {
6755  _aux->compute(EXEC_PRE_DISPLACE);
6756  _displaced_problem->updateMesh();
6757  }
6758 
6759  _aux->compute(EXEC_NONLINEAR);
6760 
6764 }
6765 
6766 void
6768  libMesh::System & precond_system,
6769  unsigned int ivar,
6770  unsigned int jvar)
6771 {
6772  JacobianBlock jac_block(precond_system, jacobian, ivar, jvar);
6773  std::vector<JacobianBlock *> blocks = {&jac_block};
6774  mooseAssert(_current_nl_sys, "This should be non-null");
6776 }
6777 
6778 void
6779 FEProblemBase::computeBounds(NonlinearImplicitSystem & libmesh_dbg_var(sys),
6780  NumericVector<Number> & lower,
6781  NumericVector<Number> & upper)
6782 {
6783  try
6784  {
6785  try
6786  {
6787  mooseAssert(_current_nl_sys && (sys.number() == _current_nl_sys->number()),
6788  "I expect these system numbers to be the same");
6789 
6790  if (!_current_nl_sys->hasVector("lower_bound") || !_current_nl_sys->hasVector("upper_bound"))
6791  return;
6792 
6793  TIME_SECTION("computeBounds", 1, "Computing Bounds");
6794 
6795  NumericVector<Number> & _lower = _current_nl_sys->getVector("lower_bound");
6796  NumericVector<Number> & _upper = _current_nl_sys->getVector("upper_bound");
6797  _lower.swap(lower);
6798  _upper.swap(upper);
6799  for (THREAD_ID tid = 0; tid < libMesh::n_threads(); tid++)
6801 
6802  _aux->residualSetup();
6803  _aux->compute(EXEC_LINEAR);
6804  _lower.swap(lower);
6805  _upper.swap(upper);
6806  }
6807  catch (...)
6808  {
6809  handleException("computeBounds");
6810  }
6811  }
6812  catch (MooseException & e)
6813  {
6814  mooseError("Irrecoverable exception: " + std::string(e.what()));
6815  }
6816  catch (...)
6817  {
6818  mooseError("Unexpected exception type");
6819  }
6820 }
6821 
6822 void
6823 FEProblemBase::computeNearNullSpace(NonlinearImplicitSystem & libmesh_dbg_var(sys),
6824  std::vector<NumericVector<Number> *> & sp)
6825 {
6826  mooseAssert(_current_nl_sys && (sys.number() == _current_nl_sys->number()),
6827  "I expect these system numbers to be the same");
6828 
6829  sp.clear();
6830  for (unsigned int i = 0; i < subspaceDim("NearNullSpace"); ++i)
6831  {
6832  std::stringstream postfix;
6833  postfix << "_" << i;
6834  std::string modename = "NearNullSpace" + postfix.str();
6835  sp.push_back(&_current_nl_sys->getVector(modename));
6836  }
6837 }
6838 
6839 void
6840 FEProblemBase::computeNullSpace(NonlinearImplicitSystem & libmesh_dbg_var(sys),
6841  std::vector<NumericVector<Number> *> & sp)
6842 {
6843  mooseAssert(_current_nl_sys && (sys.number() == _current_nl_sys->number()),
6844  "I expect these system numbers to be the same");
6845  sp.clear();
6846  for (unsigned int i = 0; i < subspaceDim("NullSpace"); ++i)
6847  {
6848  std::stringstream postfix;
6849  postfix << "_" << i;
6850  sp.push_back(&_current_nl_sys->getVector("NullSpace" + postfix.str()));
6851  }
6852 }
6853 
6854 void
6855 FEProblemBase::computeTransposeNullSpace(NonlinearImplicitSystem & libmesh_dbg_var(sys),
6856  std::vector<NumericVector<Number> *> & sp)
6857 {
6858  mooseAssert(_current_nl_sys && (sys.number() == _current_nl_sys->number()),
6859  "I expect these system numbers to be the same");
6860  sp.clear();
6861  for (unsigned int i = 0; i < subspaceDim("TransposeNullSpace"); ++i)
6862  {
6863  std::stringstream postfix;
6864  postfix << "_" << i;
6865  sp.push_back(&_current_nl_sys->getVector("TransposeNullSpace" + postfix.str()));
6866  }
6867 }
6868 
6869 void
6870 FEProblemBase::computePostCheck(NonlinearImplicitSystem & sys,
6871  const NumericVector<Number> & old_soln,
6872  NumericVector<Number> & search_direction,
6873  NumericVector<Number> & new_soln,
6874  bool & changed_search_direction,
6875  bool & changed_new_soln)
6876 {
6877  mooseAssert(_current_nl_sys && (sys.number() == _current_nl_sys->number()),
6878  "I expect these system numbers to be the same");
6879 
6880  // This function replaces the old PetscSupport::dampedCheck() function.
6881  //
6882  // 1.) Recreate code in PetscSupport::dampedCheck() for constructing
6883  // ghosted "soln" and "update" vectors.
6884  // 2.) Call FEProblemBase::computeDamping() with these ghost vectors.
6885  // 3.) Recreate the code in PetscSupport::dampedCheck() to actually update
6886  // the solution vector based on the damping, and set the "changed" flags
6887  // appropriately.
6888 
6889  TIME_SECTION("computePostCheck", 2, "Computing Post Check");
6890 
6892 
6893  // MOOSE's FEProblemBase doesn't update the solution during the
6894  // postcheck, but FEProblemBase-derived classes might.
6896  {
6897  // We need ghosted versions of new_soln and search_direction (the
6898  // ones we get from libmesh/PETSc are PARALLEL vectors. To make
6899  // our lives simpler, we use the same ghosting pattern as the
6900  // system's current_local_solution to create new ghosted vectors.
6901 
6902  // Construct zeroed-out clones with the same ghosted dofs as the
6903  // System's current_local_solution.
6904  std::unique_ptr<NumericVector<Number>> ghosted_solution =
6905  sys.current_local_solution->zero_clone(),
6906  ghosted_search_direction =
6907  sys.current_local_solution->zero_clone();
6908 
6909  // Copy values from input vectors into clones with ghosted values.
6910  *ghosted_solution = new_soln;
6911  *ghosted_search_direction = search_direction;
6912 
6913  if (_has_dampers)
6914  {
6915  // Compute the damping coefficient using the ghosted vectors
6916  Real damping = computeDamping(*ghosted_solution, *ghosted_search_direction);
6917 
6918  // If some non-trivial damping was computed, update the new_soln
6919  // vector accordingly.
6920  if (damping < 1.0)
6921  {
6922  new_soln = old_soln;
6923  new_soln.add(-damping, search_direction);
6924  changed_new_soln = true;
6925  }
6926  }
6927 
6928  if (shouldUpdateSolution())
6929  {
6930  // Update the ghosted copy of the new solution, if necessary.
6931  if (changed_new_soln)
6932  *ghosted_solution = new_soln;
6933 
6934  bool updated_solution = updateSolution(new_soln, *ghosted_solution);
6935  if (updated_solution)
6936  changed_new_soln = true;
6937  }
6938  }
6939 
6941  {
6943  _aux->setPreviousNewtonSolution();
6944  }
6945 
6946  // MOOSE doesn't change the search_direction
6947  changed_search_direction = false;
6948 
6950 }
6951 
6952 Real
6954  const NumericVector<Number> & update)
6955 {
6956  // Default to no damping
6957  Real damping = 1.0;
6958 
6959  if (_has_dampers)
6960  {
6961  TIME_SECTION("computeDamping", 1, "Computing Damping");
6962 
6963  // Save pointer to the current solution
6964  const NumericVector<Number> * _saved_current_solution = _current_nl_sys->currentSolution();
6965 
6967  // For now, do not re-compute auxiliary variables. Doing so allows a wild solution increment
6968  // to get to the material models, which may not be able to cope with drastically different
6969  // values. Once more complete dependency checking is in place, auxiliary variables (and
6970  // material properties) will be computed as needed by dampers.
6971  // _aux.compute();
6972  damping = _current_nl_sys->computeDamping(soln, update);
6973 
6974  // restore saved solution
6975  _current_nl_sys->setSolution(*_saved_current_solution);
6976  }
6977 
6978  return damping;
6979 }
6980 
6981 bool
6983 {
6984  return false;
6985 }
6986 
6987 bool
6989  NumericVector<Number> & /*ghosted_solution*/)
6990 {
6991  return false;
6992 }
6993 
6994 void
6996 {
6997 }
6998 
6999 void
7000 FEProblemBase::addDisplacedProblem(std::shared_ptr<DisplacedProblem> displaced_problem)
7001 {
7002  parallel_object_only();
7003 
7004  _displaced_mesh = &displaced_problem->mesh();
7005  _displaced_problem = displaced_problem;
7006 }
7007 
7008 void
7010 {
7011  TIME_SECTION("updateGeometricSearch", 3, "Updating Geometric Search");
7012 
7014 
7015  if (_displaced_problem)
7016  _displaced_problem->updateGeomSearch(type);
7017 }
7018 
7019 void
7021 {
7022  TIME_SECTION("updateMortarMesh", 5, "Updating Mortar Mesh");
7023 
7024  FloatingPointExceptionGuard fpe_guard(_app);
7025 
7026  _mortar_data.update();
7027 }
7028 
7029 void
7031  const std::pair<BoundaryID, BoundaryID> & primary_secondary_boundary_pair,
7032  const std::pair<SubdomainID, SubdomainID> & primary_secondary_subdomain_pair,
7033  bool on_displaced,
7034  bool periodic,
7035  const bool debug,
7036  const bool correct_edge_dropping,
7037  const Real minimum_projection_angle)
7038 {
7039  _has_mortar = true;
7040 
7041  if (on_displaced)
7042  return _mortar_data.createMortarInterface(primary_secondary_boundary_pair,
7043  primary_secondary_subdomain_pair,
7045  on_displaced,
7046  periodic,
7047  debug,
7048  correct_edge_dropping,
7049  minimum_projection_angle);
7050  else
7051  return _mortar_data.createMortarInterface(primary_secondary_boundary_pair,
7052  primary_secondary_subdomain_pair,
7053  *this,
7054  on_displaced,
7055  periodic,
7056  debug,
7057  correct_edge_dropping,
7058  minimum_projection_angle);
7059 }
7060 
7063  const std::pair<BoundaryID, BoundaryID> & primary_secondary_boundary_pair,
7064  const std::pair<SubdomainID, SubdomainID> & primary_secondary_subdomain_pair,
7065  bool on_displaced) const
7066 {
7068  primary_secondary_boundary_pair, primary_secondary_subdomain_pair, on_displaced);
7069 }
7070 
7073  const std::pair<BoundaryID, BoundaryID> & primary_secondary_boundary_pair,
7074  const std::pair<SubdomainID, SubdomainID> & primary_secondary_subdomain_pair,
7075  bool on_displaced)
7076 {
7078  primary_secondary_boundary_pair, primary_secondary_subdomain_pair, on_displaced);
7079 }
7080 
7081 const std::unordered_map<std::pair<BoundaryID, BoundaryID>, AutomaticMortarGeneration> &
7082 FEProblemBase::getMortarInterfaces(bool on_displaced) const
7083 {
7084  return _mortar_data.getMortarInterfaces(on_displaced);
7085 }
7086 
7087 void
7089 {
7090  if (_displaced_problem) // Only need to do this if things are moving...
7091  {
7092  TIME_SECTION("possiblyRebuildGeomSearchPatches", 5, "Rebuilding Geometric Search Patches");
7093 
7094  switch (_mesh.getPatchUpdateStrategy())
7095  {
7096  case Moose::Never:
7097  break;
7098  case Moose::Iteration:
7099  // Update the list of ghosted elements at the start of the time step
7102 
7103  _displaced_problem->geomSearchData().updateGhostedElems();
7105 
7106  // The commands below ensure that the sparsity of the Jacobian matrix is
7107  // augmented at the start of the time step using neighbor nodes from the end
7108  // of the previous time step.
7109 
7111 
7112  // This is needed to reinitialize PETSc output
7114 
7115  break;
7116 
7117  case Moose::Auto:
7118  {
7119  Real max = _displaced_problem->geomSearchData().maxPatchPercentage();
7121 
7122  // If we haven't moved very far through the patch
7123  if (max < 0.4)
7124  break;
7125  }
7126  libmesh_fallthrough();
7127 
7128  // Let this fall through if things do need to be updated...
7129  case Moose::Always:
7130  // Flush output here to see the message before the reinitialization, which could take a
7131  // while
7132  _console << "\n\nUpdating geometric search patches\n" << std::endl;
7133 
7136 
7137  _displaced_problem->geomSearchData().clearNearestNodeLocators();
7139 
7141 
7142  // This is needed to reinitialize PETSc output
7144  }
7145  }
7146 }
7147 
7148 #ifdef LIBMESH_ENABLE_AMR
7149 void
7151 {
7152  unsigned int n = adaptivity().getInitialSteps();
7153  _cycles_completed = 0;
7154  if (n)
7155  {
7158  mooseError("HFEM does not support mesh adaptivity currently.");
7159 
7160  TIME_SECTION("initialAdaptMesh", 2, "Performing Initial Adaptivity");
7161 
7162  for (unsigned int i = 0; i < n; i++)
7163  {
7165  computeMarkers();
7166 
7168  {
7169  meshChanged();
7170 
7171  // reproject the initial condition
7172  projectSolution();
7173 
7175  }
7176  else
7177  {
7178  _console << "Mesh unchanged, skipping remaining steps..." << std::endl;
7179  return;
7180  }
7181  }
7182  }
7183 }
7184 
7185 bool
7187 {
7188  // reset cycle counter
7189  _cycles_completed = 0;
7190 
7192  return false;
7193 
7194  TIME_SECTION("adaptMesh", 3, "Adapting Mesh");
7195 
7196  unsigned int cycles_per_step = _adaptivity.getCyclesPerStep();
7197 
7198  bool mesh_changed = false;
7199 
7200  for (unsigned int i = 0; i < cycles_per_step; ++i)
7201  {
7204  mooseError("HFEM does not support mesh adaptivity currently.");
7205 
7206  // Markers were already computed once by Executioner
7207  if (_adaptivity.getRecomputeMarkersFlag() && i > 0)
7208  computeMarkers();
7209 
7210  bool mesh_changed_this_step;
7211  mesh_changed_this_step = _adaptivity.adaptMesh();
7212 
7213  if (mesh_changed_this_step)
7214  {
7215  mesh_changed = true;
7216 
7217  meshChangedHelper(true); // This may be an intermediate change
7219  }
7220  else
7221  {
7222  _console << "Mesh unchanged, skipping remaining steps..." << std::endl;
7223  break;
7224  }
7225 
7226  // Show adaptivity progress
7227  _console << std::flush;
7228  }
7229 
7230  // We're done with all intermediate changes; now get systems ready
7231  // for real if necessary.
7232  if (mesh_changed)
7233  es().reinit_systems();
7234 
7235  return mesh_changed;
7236 }
7237 #endif // LIBMESH_ENABLE_AMR
7238 
7239 void
7240 FEProblemBase::initXFEM(std::shared_ptr<XFEMInterface> xfem)
7241 {
7242  _xfem = xfem;
7243  _xfem->setMesh(&_mesh);
7244  if (_displaced_mesh)
7245  _xfem->setDisplacedMesh(_displaced_mesh);
7246 
7247  auto fill_data = [](auto & storage)
7248  {
7249  std::vector<MaterialData *> data(libMesh::n_threads());
7250  for (const auto tid : make_range(libMesh::n_threads()))
7251  data[tid] = &storage.getMaterialData(tid);
7252  return data;
7253  };
7254  _xfem->setMaterialData(fill_data(_material_props));
7255  _xfem->setBoundaryMaterialData(fill_data(_bnd_material_props));
7256 
7257  unsigned int n_threads = libMesh::n_threads();
7258  for (unsigned int i = 0; i < n_threads; ++i)
7259  for (const auto nl_sys_num : index_range(_assembly[i]))
7260  {
7261  _assembly[i][nl_sys_num]->setXFEM(_xfem);
7262  if (_displaced_problem)
7263  _displaced_problem->assembly(i, nl_sys_num).setXFEM(_xfem);
7264  }
7265 }
7266 
7267 bool
7269 {
7270  TIME_SECTION("updateMeshXFEM", 5, "Updating XFEM");
7271 
7272  bool updated = false;
7273  if (haveXFEM())
7274  {
7275  if (_xfem->updateHeal())
7276  meshChanged();
7277 
7278  updated = _xfem->update(_time, _nl, *_aux);
7279  if (updated)
7280  {
7281  meshChanged();
7282  _xfem->initSolution(_nl, *_aux);
7283  restoreSolutions();
7284  }
7285  }
7286  return updated;
7287 }
7288 
7289 void
7291 {
7292  TIME_SECTION("meshChanged", 3, "Handling Mesh Changes");
7293 
7294  this->meshChangedHelper();
7295 }
7296 
7297 void
7298 FEProblemBase::meshChangedHelper(bool intermediate_change)
7299 {
7300  TIME_SECTION("meshChangedHelper", 5);
7301 
7304  _mesh.cacheChangedLists(); // Currently only used with adaptivity and stateful material
7305  // properties
7306 
7307  // Clear these out because they corresponded to the old mesh
7308  _ghosted_elems.clear();
7310 
7311  // The mesh changed. We notify the MooseMesh first, because
7312  // callbacks (e.g. for sparsity calculations) triggered by the
7313  // EquationSystems reinit may require up-to-date MooseMesh caches.
7314  _mesh.meshChanged();
7315 
7316  // If we're just going to alter the mesh again, all we need to
7317  // handle here is AMR and projections, not full system reinit
7318  if (intermediate_change)
7319  es().reinit_solutions();
7320  else
7321  es().reinit();
7322 
7323  // Updating MooseMesh first breaks other adaptivity code, unless we
7324  // then *again* update the MooseMesh caches. E.g. the definition of
7325  // "active" and "local" may have been *changed* by refinement and
7326  // repartitioning done in EquationSystems::reinit().
7327  _mesh.meshChanged();
7328 
7329  // If we have finite volume variables, we will need to recompute additional elemental/face
7330  // quantities
7333 
7334  // Let the meshChangedInterface notify the mesh changed event before we update the active
7335  // semilocal nodes, because the set of ghosted elements may potentially be updated during a mesh
7336  // changed event.
7337  for (const auto & mci : _notify_when_mesh_changes)
7338  mci->meshChanged();
7339 
7340  // Since the Mesh changed, update the PointLocator object used by DiracKernels.
7342 
7343  // Need to redo ghosting
7345 
7346  if (_displaced_problem)
7347  {
7348  _displaced_problem->meshChanged();
7350  }
7351 
7353 
7356 
7357  // Just like we reinitialized our geometric search objects, we also need to reinitialize our
7358  // mortar meshes. Note that this needs to happen after DisplacedProblem::meshChanged because the
7359  // mortar mesh discretization will depend necessarily on the displaced mesh being re-displaced
7360  updateMortarMesh();
7361 
7362  reinitBecauseOfGhostingOrNewGeomObjects(/*mortar_changed=*/true);
7363 
7364  // We need to create new storage for newly active elements, and copy
7365  // stateful properties from the old elements.
7368  {
7369  if (havePRefinement())
7371 
7372  // Prolong properties onto newly refined elements' children
7373  {
7375  /* refine = */ true, *this, _material_props, _bnd_material_props, _assembly);
7376  const auto & range = *_mesh.refinedElementRange();
7377  Threads::parallel_reduce(range, pmp);
7378 
7379  // Concurrent erasure from the shared hash map is not safe while we are reading from it in
7380  // ProjectMaterialProperties, so we handle erasure here. Moreover, erasure based on key is
7381  // not thread safe in and of itself because it is a read-write operation. Note that we do not
7382  // do the erasure for p-refinement because the coarse level element is the same as our active
7383  // refined level element
7384  if (!doingPRefinement())
7385  for (const auto & elem : range)
7386  {
7390  }
7391  }
7392 
7393  // Restrict properties onto newly coarsened elements
7394  {
7396  /* refine = */ false, *this, _material_props, _bnd_material_props, _assembly);
7397  const auto & range = *_mesh.coarsenedElementRange();
7398  Threads::parallel_reduce(range, pmp);
7399  // Note that we do not do the erasure for p-refinement because the coarse level element is the
7400  // same as our active refined level element
7401  if (!doingPRefinement())
7402  for (const auto & elem : range)
7403  {
7404  auto && coarsened_children = _mesh.coarsenedElementChildren(elem);
7405  for (auto && child : coarsened_children)
7406  {
7410  }
7411  }
7412  }
7413  }
7414 
7417 
7418  _has_jacobian = false; // we have to recompute jacobian when mesh changed
7419 
7420  // Since the mesh has changed, we need to make sure that we update any of our
7421  // MOOSE-system specific data. libmesh system data has already been updated
7422  for (auto & nl : _nl)
7423  nl->update(/*update_libmesh_system=*/false);
7424  _aux->update(/*update_libmesh_system=*/false);
7425 }
7426 
7427 void
7429 {
7430  _notify_when_mesh_changes.push_back(mci);
7431 }
7432 
7433 void
7434 FEProblemBase::initElementStatefulProps(const ConstElemRange & elem_range, const bool threaded)
7435 {
7438  if (threaded)
7439  Threads::parallel_reduce(elem_range, cmt);
7440  else
7441  cmt(elem_range, true);
7442 }
7443 
7444 void
7446 {
7447  TIME_SECTION("checkProblemIntegrity", 5);
7448 
7449  // Check for unsatisfied actions
7450  const std::set<SubdomainID> & mesh_subdomains = _mesh.meshSubdomains();
7451 
7452  // Check kernel coverage of subdomains (blocks) in the mesh
7454  for (auto & nl : _nl)
7455  nl->checkKernelCoverage(mesh_subdomains);
7456 
7457  // Check materials
7458  {
7459 #ifdef LIBMESH_ENABLE_AMR
7460  if ((_adaptivity.isOn() || _num_grid_steps) &&
7463  {
7464  _console << "Using EXPERIMENTAL Stateful Material Property projection with Adaptivity!\n"
7465  << std::flush;
7466  }
7467 #endif
7468 
7469  std::set<SubdomainID> local_mesh_subs(mesh_subdomains);
7470 
7472  {
7477  bool check_material_coverage = false;
7478  std::set<SubdomainID> ids = _all_materials.getActiveBlocks();
7479  for (const auto & id : ids)
7480  {
7481  local_mesh_subs.erase(id);
7482  check_material_coverage = true;
7483  }
7484 
7485  // also exclude mortar spaces from the material check
7486  auto && mortar_subdomain_ids = _mortar_data.getMortarSubdomainIDs();
7487  for (auto subdomain_id : mortar_subdomain_ids)
7488  local_mesh_subs.erase(subdomain_id);
7489 
7490  // Check Material Coverage
7491  if (check_material_coverage && !local_mesh_subs.empty())
7492  {
7493  std::stringstream extra_subdomain_ids;
7495  std::copy(local_mesh_subs.begin(),
7496  local_mesh_subs.end(),
7497  std::ostream_iterator<unsigned int>(extra_subdomain_ids, " "));
7498 
7499  mooseError("The following blocks from your input mesh do not contain an active material: " +
7500  extra_subdomain_ids.str() +
7501  "\nWhen ANY mesh block contains a Material object, "
7502  "all blocks must contain a Material object.\n");
7503  }
7504  }
7505 
7506  // Check material properties on blocks and boundaries
7509 
7510  // Check that material properties exist when requested by other properties on a given block
7511  const auto & materials = _all_materials.getActiveObjects();
7512  for (const auto & material : materials)
7513  material->checkStatefulSanity();
7514 
7515  // auto mats_to_check = _materials.getActiveBlockObjects();
7516  // const auto & discrete_materials = _discrete_materials.getActiveBlockObjects();
7517  // for (const auto & map_it : discrete_materials)
7518  // for (const auto & container_element : map_it.second)
7519  // mats_to_check[map_it.first].push_back(container_element);
7522  }
7523 
7524  checkUserObjects();
7525 
7526  // Verify that we don't have any Element type/Coordinate Type conflicts
7528 
7529  // If using displacements, verify that the order of the displacement
7530  // variables matches the order of the elements in the displaced
7531  // mesh.
7533 
7534  // Check for postprocessor names with same name as a scalar variable
7536 }
7537 
7538 void
7540 {
7541  if (_displaced_problem)
7542  {
7543  bool mesh_has_second_order_elements = false;
7544  for (const auto & elem : as_range(_displaced_mesh->activeLocalElementsBegin(),
7546  {
7547  if (elem->default_order() == SECOND)
7548  {
7549  mesh_has_second_order_elements = true;
7550  break;
7551  }
7552  }
7553 
7554  // We checked our local elements, so take the max over all processors.
7555  _displaced_mesh->comm().max(mesh_has_second_order_elements);
7556 
7557  // If the Mesh has second order elements, make sure the
7558  // displacement variables are second-order.
7559  if (mesh_has_second_order_elements)
7560  {
7561  const std::vector<std::string> & displacement_variables =
7562  _displaced_problem->getDisplacementVarNames();
7563 
7564  for (const auto & var_name : displacement_variables)
7565  {
7566  MooseVariableFEBase & mv =
7567  _displaced_problem->getVariable(/*tid=*/0,
7568  var_name,
7571  if (mv.order() != SECOND)
7572  mooseError("Error: mesh has SECOND order elements, so all displacement variables must be "
7573  "SECOND order.");
7574  }
7575  }
7576  }
7577 }
7578 
7579 void
7581 {
7582  // Check user_objects block coverage
7583  std::set<SubdomainID> mesh_subdomains = _mesh.meshSubdomains();
7584  std::set<SubdomainID> user_objects_blocks;
7585 
7586  // gather names of all user_objects that were defined in the input file
7587  // and the blocks that they are defined on
7588  std::set<std::string> names;
7589 
7590  std::vector<UserObject *> objects;
7592 
7593  for (const auto & obj : objects)
7594  names.insert(obj->name());
7595 
7596  // See if all referenced blocks are covered
7597  std::set<SubdomainID> difference;
7598  std::set_difference(user_objects_blocks.begin(),
7599  user_objects_blocks.end(),
7600  mesh_subdomains.begin(),
7601  mesh_subdomains.end(),
7602  std::inserter(difference, difference.end()));
7603 
7604  if (!difference.empty())
7605  {
7606  std::ostringstream oss;
7607  oss << "One or more UserObjects is referencing a nonexistent block:\n";
7608  for (const auto & id : difference)
7609  oss << id << "\n";
7610  mooseError(oss.str());
7611  }
7612 }
7613 
7614 void
7616  const std::map<SubdomainID, std::vector<std::shared_ptr<MaterialBase>>> & materials_map)
7617 {
7618  for (const auto & it : materials_map)
7619  {
7621  std::set<std::string> block_depend_props, block_supplied_props;
7622 
7623  for (const auto & mat1 : it.second)
7624  {
7625  const std::set<std::string> & depend_props = mat1->getRequestedItems();
7626  block_depend_props.insert(depend_props.begin(), depend_props.end());
7627 
7628  auto & alldeps = mat1->getMatPropDependencies(); // includes requested stateful props
7629  for (auto & dep : alldeps)
7630  if (const auto name = _material_props.queryStatefulPropName(dep))
7631  block_depend_props.insert(*name);
7632 
7633  // See if any of the active materials supply this property
7634  for (const auto & mat2 : it.second)
7635  {
7636  const std::set<std::string> & supplied_props = mat2->MaterialBase::getSuppliedItems();
7637  block_supplied_props.insert(supplied_props.begin(), supplied_props.end());
7638  }
7639  }
7640 
7641  // Add zero material properties specific to this block and unrestricted
7642  block_supplied_props.insert(_zero_block_material_props[it.first].begin(),
7643  _zero_block_material_props[it.first].end());
7644 
7645  // Error check to make sure all properties consumed by materials are supplied on this block
7646  std::set<std::string> difference;
7647  std::set_difference(block_depend_props.begin(),
7648  block_depend_props.end(),
7649  block_supplied_props.begin(),
7650  block_supplied_props.end(),
7651  std::inserter(difference, difference.end()));
7652 
7653  if (!difference.empty())
7654  {
7655  std::ostringstream oss;
7656  oss << "One or more Material Properties were not supplied on block ";
7657  const std::string & subdomain_name = _mesh.getSubdomainName(it.first);
7658  if (subdomain_name.length() > 0)
7659  oss << subdomain_name << " (" << it.first << ")";
7660  else
7661  oss << it.first;
7662  oss << ":\n";
7663  for (const auto & name : difference)
7664  oss << name << "\n";
7665  mooseError(oss.str());
7666  }
7667  }
7668 
7669  // This loop checks that materials are not supplied by multiple Material objects
7670  for (const auto & it : materials_map)
7671  {
7672  const auto & materials = it.second;
7673  std::set<std::string> inner_supplied, outer_supplied;
7674 
7675  for (const auto & outer_mat : materials)
7676  {
7677  // Storage for properties for this material (outer) and all other materials (inner)
7678  outer_supplied = outer_mat->getSuppliedItems();
7679  inner_supplied.clear();
7680 
7681  // Property to material map for error reporting
7682  std::map<std::string, std::set<std::string>> prop_to_mat;
7683  for (const auto & name : outer_supplied)
7684  prop_to_mat[name].insert(outer_mat->name());
7685 
7686  for (const auto & inner_mat : materials)
7687  {
7688  if (outer_mat == inner_mat)
7689  continue;
7690 
7691  // Check whether these materials are an AD pair
7692  auto outer_mat_type = outer_mat->type();
7693  auto inner_mat_type = inner_mat->type();
7694  removeSubstring(outer_mat_type, "<RESIDUAL>");
7695  removeSubstring(outer_mat_type, "<JACOBIAN>");
7696  removeSubstring(inner_mat_type, "<RESIDUAL>");
7697  removeSubstring(inner_mat_type, "<JACOBIAN>");
7698  if (outer_mat_type == inner_mat_type && outer_mat_type != outer_mat->type() &&
7699  inner_mat_type != inner_mat->type())
7700  continue;
7701 
7702  inner_supplied.insert(inner_mat->getSuppliedItems().begin(),
7703  inner_mat->getSuppliedItems().end());
7704 
7705  for (const auto & inner_supplied_name : inner_supplied)
7706  prop_to_mat[inner_supplied_name].insert(inner_mat->name());
7707  }
7708 
7709  // Test that a property isn't supplied on multiple blocks
7710  std::set<std::string> intersection;
7711  std::set_intersection(outer_supplied.begin(),
7712  outer_supplied.end(),
7713  inner_supplied.begin(),
7714  inner_supplied.end(),
7715  std::inserter(intersection, intersection.end()));
7716 
7717  if (!intersection.empty())
7718  {
7719  std::ostringstream oss;
7720  oss << "The following material properties are declared on block " << it.first
7721  << " by multiple materials:\n";
7722  oss << ConsoleUtils::indent(2) << std::setw(30) << std::left << "Material Property"
7723  << "Material Objects\n";
7724  for (const auto & outer_name : intersection)
7725  {
7726  oss << ConsoleUtils::indent(2) << std::setw(30) << std::left << outer_name;
7727  for (const auto & inner_name : prop_to_mat[outer_name])
7728  oss << inner_name << " ";
7729  oss << '\n';
7730  }
7731 
7732  mooseError(oss.str());
7733  break;
7734  }
7735  }
7736  }
7737 }
7738 
7739 void
7741 {
7743 }
7744 
7745 void
7746 FEProblemBase::setRestartFile(const std::string & file_name)
7747 {
7748  if (_app.isRecovering())
7749  {
7750  mooseInfo("Restart file ", file_name, " is NOT being used since we are performing recovery.");
7751  }
7752  else
7753  {
7754  _app.setRestart(true);
7755  _app.setRestartRecoverFileBase(file_name);
7756  mooseInfo("Using ", file_name, " for restart.");
7757  }
7758 }
7759 
7760 std::vector<VariableName>
7762 {
7763  std::vector<VariableName> names;
7764 
7765  for (auto & nl : _nl)
7766  {
7767  const std::vector<VariableName> & nl_var_names = nl->getVariableNames();
7768  names.insert(names.end(), nl_var_names.begin(), nl_var_names.end());
7769  }
7770 
7771  const std::vector<VariableName> & aux_var_names = _aux->getVariableNames();
7772  names.insert(names.end(), aux_var_names.begin(), aux_var_names.end());
7773 
7774  return names;
7775 }
7776 
7779  const PetscInt it,
7780  const Real xnorm,
7781  const Real snorm,
7782  const Real fnorm,
7783  const Real rtol,
7784  const Real divtol,
7785  const Real stol,
7786  const Real abstol,
7787  const PetscInt nfuncs,
7788  const PetscInt max_funcs,
7789  const Real initial_residual_before_preset_bcs,
7790  const Real div_threshold)
7791 {
7792  TIME_SECTION("checkNonlinearConvergence", 5, "Checking Nonlinear Convergence");
7793  mooseAssert(_current_nl_sys, "This should be non-null");
7794 
7796 
7798  {
7801  }
7802 
7805 
7806  Real fnorm_old;
7807  // This is the first residual before any iterations have been done,
7808  // but after preset BCs (if any) have been imposed on the solution
7809  // vector. We save it, and use it to detect convergence if
7810  // compute_initial_residual_before_preset_bcs=false.
7811  if (it == 0)
7812  {
7813  system._initial_residual_after_preset_bcs = fnorm;
7814  fnorm_old = fnorm;
7815  _n_nl_pingpong = 0;
7816  }
7817  else
7818  fnorm_old = system._last_nl_rnorm;
7819 
7820  // Check for nonlinear residual pingpong.
7821  // Pingpong will always start from a residual increase
7822  if ((_n_nl_pingpong % 2 == 1 && !(fnorm > fnorm_old)) ||
7823  (_n_nl_pingpong % 2 == 0 && fnorm > fnorm_old))
7824  _n_nl_pingpong += 1;
7825  else
7826  _n_nl_pingpong = 0;
7827 
7828  std::ostringstream oss;
7829  if (fnorm != fnorm)
7830  {
7831  oss << "Failed to converge, function norm is NaN\n";
7833  }
7834  else if ((it >= _nl_forced_its) && fnorm < abstol)
7835  {
7836  oss << "Converged due to function norm " << fnorm << " < " << abstol << '\n';
7838  }
7839  else if (nfuncs >= max_funcs)
7840  {
7841  oss << "Exceeded maximum number of function evaluations: " << nfuncs << " > " << max_funcs
7842  << '\n';
7844  }
7845  else if ((it >= _nl_forced_its) && it && fnorm > system._last_nl_rnorm && fnorm >= div_threshold)
7846  {
7847  oss << "Nonlinear solve was blowing up!\n";
7849  }
7850 
7851  if ((it >= _nl_forced_its) && it && reason == MooseNonlinearConvergenceReason::ITERATING)
7852  {
7853  // If compute_initial_residual_before_preset_bcs==false, then use the
7854  // first residual computed by PETSc to determine convergence.
7856  ? initial_residual_before_preset_bcs
7858  if (checkRelativeConvergence(it, fnorm, the_residual, rtol, abstol, oss))
7860  else if (snorm < stol * xnorm)
7861  {
7862  oss << "Converged due to small update length: " << snorm << " < " << stol << " * " << xnorm
7863  << '\n';
7865  }
7866  else if (divtol > 0 && fnorm > the_residual * divtol)
7867  {
7868  oss << "Diverged due to initial residual " << the_residual << " > divergence tolerance "
7869  << divtol << " * initial residual " << the_residual << '\n';
7871  }
7872  else if (_nl_abs_div_tol > 0 && fnorm > _nl_abs_div_tol)
7873  {
7874  oss << "Diverged due to residual " << fnorm << " > absolute divergence tolerance "
7875  << _nl_abs_div_tol << '\n';
7877  }
7879  {
7880  oss << "Diverged due to maximum nonlinear residual pingpong achieved" << '\n';
7882  }
7883  }
7884 
7885  system._last_nl_rnorm = fnorm;
7886  system._current_nl_its = static_cast<unsigned int>(it);
7887 
7888  msg = oss.str();
7889  if (_app.multiAppLevel() > 0)
7891 
7892  return reason;
7893 }
7894 
7895 bool
7897  const Real fnorm,
7898  const Real the_residual,
7899  const Real rtol,
7900  const Real /*abstol*/,
7901  std::ostringstream & oss)
7902 {
7904  return false;
7905  if (fnorm <= the_residual * rtol)
7906  {
7907  oss << "Converged due to function norm " << fnorm << " < relative tolerance (" << rtol << ")\n";
7908  return true;
7909  }
7910  return false;
7911 }
7912 
7913 SolverParams &
7915 {
7916  return _solver_params;
7917 }
7918 
7919 const SolverParams &
7921 {
7922  return _solver_params;
7923 }
7924 
7925 void
7926 FEProblemBase::registerRandomInterface(RandomInterface & random_interface, const std::string & name)
7927 {
7928  auto insert_pair = moose_try_emplace(
7929  _random_data_objects, name, std::make_unique<RandomData>(*this, random_interface));
7930 
7931  auto random_data_ptr = insert_pair.first->second.get();
7932  random_interface.setRandomDataPointer(random_data_ptr);
7933 }
7934 
7935 bool
7937 {
7938  if (_bnd_mat_side_cache[tid].find(bnd_id) == _bnd_mat_side_cache[tid].end())
7939  {
7940  auto & bnd_mat_side_cache = _bnd_mat_side_cache[tid][bnd_id];
7941  bnd_mat_side_cache = false;
7942 
7943  if (_aux->needMaterialOnSide(bnd_id))
7944  {
7945  bnd_mat_side_cache = true;
7946  return true;
7947  }
7948  else
7949  for (auto & nl : _nl)
7950  if (nl->needBoundaryMaterialOnSide(bnd_id, tid))
7951  {
7952  bnd_mat_side_cache = true;
7953  return true;
7954  }
7955 
7956  if (theWarehouse()
7957  .query()
7958  .condition<AttribThread>(tid)
7959  .condition<AttribInterfaces>(Interfaces::SideUserObject)
7960  .condition<AttribBoundaries>(bnd_id)
7961  .count() > 0)
7962  {
7963  bnd_mat_side_cache = true;
7964  return true;
7965  }
7966  }
7967 
7968  return _bnd_mat_side_cache[tid][bnd_id];
7969 }
7970 
7971 bool
7973 {
7974  if (_interface_mat_side_cache[tid].find(bnd_id) == _interface_mat_side_cache[tid].end())
7975  {
7976  auto & interface_mat_side_cache = _interface_mat_side_cache[tid][bnd_id];
7977  interface_mat_side_cache = false;
7978 
7979  for (auto & nl : _nl)
7980  if (nl->needInterfaceMaterialOnSide(bnd_id, tid))
7981  {
7982  interface_mat_side_cache = true;
7983  return true;
7984  }
7985 
7986  if (theWarehouse()
7987  .query()
7988  .condition<AttribThread>(tid)
7989  .condition<AttribInterfaces>(Interfaces::InterfaceUserObject)
7990  .condition<AttribBoundaries>(bnd_id)
7991  .count() > 0)
7992  {
7993  interface_mat_side_cache = true;
7994  return true;
7995  }
7996  else if (_interface_materials.hasActiveBoundaryObjects(bnd_id, tid))
7997  {
7998  interface_mat_side_cache = true;
7999  return true;
8000  }
8001  }
8002  return _interface_mat_side_cache[tid][bnd_id];
8003 }
8004 
8005 bool
8007 {
8008  if (_block_mat_side_cache[tid].find(subdomain_id) == _block_mat_side_cache[tid].end())
8009  {
8010  _block_mat_side_cache[tid][subdomain_id] = false;
8011 
8012  for (auto & nl : _nl)
8013  if (nl->needSubdomainMaterialOnSide(subdomain_id, tid))
8014  {
8015  _block_mat_side_cache[tid][subdomain_id] = true;
8016  return true;
8017  }
8018 
8019  if (theWarehouse()
8020  .query()
8021  .condition<AttribThread>(tid)
8022  .condition<AttribInterfaces>(Interfaces::InternalSideUserObject)
8023  .condition<AttribSubdomains>(subdomain_id)
8024  .count() > 0)
8025  {
8026  _block_mat_side_cache[tid][subdomain_id] = true;
8027  return true;
8028  }
8029  }
8030 
8031  return _block_mat_side_cache[tid][subdomain_id];
8032 }
8033 
8034 bool
8036 {
8038 }
8039 
8040 void
8042 {
8044  mooseError("Previous nonlinear solution is required but not added through "
8045  "Problem/previous_nl_solution_required=true");
8046 }
8047 
8048 bool
8050 {
8051  return _has_jacobian;
8052 }
8053 
8054 bool
8056 {
8057  return _const_jacobian;
8058 }
8059 
8060 void
8061 FEProblemBase::addOutput(const std::string & object_type,
8062  const std::string & object_name,
8063  InputParameters & parameters)
8064 {
8065  parallel_object_only();
8066 
8067  // Get a reference to the OutputWarehouse
8068  OutputWarehouse & output_warehouse = _app.getOutputWarehouse();
8069 
8070  // Reject the reserved names for objects not built by MOOSE
8071  if (!parameters.get<bool>("_built_by_moose") && output_warehouse.isReservedName(object_name))
8072  mooseError("The name '", object_name, "' is a reserved name for output objects");
8073 
8074  // Check that an object by the same name does not already exist; this must be done before the
8075  // object is created to avoid getting misleading errors from the Parser
8076  if (output_warehouse.hasOutput(object_name))
8077  mooseError("An output object named '", object_name, "' already exists");
8078 
8079  // Add a pointer to the FEProblemBase class
8080  parameters.addPrivateParam<FEProblemBase *>("_fe_problem_base", this);
8081 
8082  // Create common parameter exclude list
8083  std::vector<std::string> exclude;
8084  if (object_type == "Console")
8085  {
8086  exclude.push_back("execute_on");
8087 
8088  // --show-input should enable the display of the input file on the screen
8089  if (_app.getParam<bool>("show_input") && parameters.get<bool>("output_screen"))
8090  parameters.set<ExecFlagEnum>("execute_input_on") = EXEC_INITIAL;
8091  }
8092  // Need this because Checkpoint::validParams changes the default value of
8093  // execute_on
8094  else if (object_type == "Checkpoint")
8095  exclude.push_back("execute_on");
8096 
8097  // Apply the common parameters loaded with Outputs input syntax
8098  const InputParameters * common = output_warehouse.getCommonParameters();
8099  if (common)
8100  parameters.applyParameters(*common, exclude);
8101 
8102  // Set the correct value for the binary flag for XDA/XDR output
8103  if (object_type == "XDR")
8104  parameters.set<bool>("_binary") = true;
8105  else if (object_type == "XDA")
8106  parameters.set<bool>("_binary") = false;
8107 
8108  // Adjust the checkpoint suffix if auto recovery was enabled
8109  if (object_name == "auto_recovery_checkpoint")
8110  parameters.set<std::string>("suffix") = "auto_recovery";
8111 
8112  // Create the object and add it to the warehouse
8113  std::shared_ptr<Output> output = _factory.create<Output>(object_type, object_name, parameters);
8114  logAdd("Output", object_name, object_type);
8115  output_warehouse.addOutput(output);
8116 }
8117 
8118 void
8119 FEProblemBase::haveADObjects(const bool have_ad_objects)
8120 {
8121  _have_ad_objects = have_ad_objects;
8122  if (_displaced_problem)
8123  _displaced_problem->SubProblem::haveADObjects(have_ad_objects);
8124 }
8125 
8126 const SystemBase &
8127 FEProblemBase::systemBaseNonlinear(const unsigned int sys_num) const
8128 {
8129  mooseAssert(sys_num < _nl.size(), "System number greater than the number of nonlinear systems");
8130  return *_nl[sys_num];
8131 }
8132 
8133 SystemBase &
8134 FEProblemBase::systemBaseNonlinear(const unsigned int sys_num)
8135 {
8136  return *_nl[sys_num];
8137 }
8138 
8139 const SystemBase &
8141 {
8142  return *_aux;
8143 }
8144 
8145 SystemBase &
8147 {
8148  return *_aux;
8149 }
8150 
8151 void
8152 FEProblemBase::computingNonlinearResid(bool computing_nonlinear_residual)
8153 {
8154  parallel_object_only();
8155 
8156  if (_displaced_problem)
8157  _displaced_problem->computingNonlinearResid(computing_nonlinear_residual);
8158  _computing_nonlinear_residual = computing_nonlinear_residual;
8159 }
8160 
8161 void
8162 FEProblemBase::setCurrentlyComputingResidual(bool currently_computing_residual)
8163 {
8164  if (_displaced_problem)
8165  _displaced_problem->setCurrentlyComputingResidual(currently_computing_residual);
8166  _currently_computing_residual = currently_computing_residual;
8167 }
8168 
8169 void
8171 {
8172  // ResetDisplacedMeshThread::onNode looks up the reference mesh by ID, so we need to make sure
8173  // we undisplace before adapting the reference mesh
8174  if (_displaced_problem)
8175  _displaced_problem->undisplaceMesh();
8176 
8178  if (_displaced_problem)
8180 
8181  meshChangedHelper(/*intermediate_change=*/false);
8182 }
8183 
8184 void
8185 FEProblemBase::automaticScaling(bool automatic_scaling)
8186 {
8187  if (_displaced_problem)
8188  _displaced_problem->automaticScaling(automatic_scaling);
8189 
8190  SubProblem::automaticScaling(automatic_scaling);
8191 }
8192 
8193 void
8195  unsigned int side,
8196  BoundaryID bnd_id,
8197  Real tolerance,
8198  const std::vector<Point> * const pts,
8199  const std::vector<Real> * const weights,
8200  const THREAD_ID tid)
8201 {
8202  SubProblem::reinitElemFaceRef(elem, side, bnd_id, tolerance, pts, weights, tid);
8203 
8204  if (_displaced_problem)
8205  _displaced_problem->reinitElemFaceRef(
8206  _displaced_mesh->elemPtr(elem->id()), side, bnd_id, tolerance, pts, weights, tid);
8207 }
8208 
8209 void
8210 FEProblemBase::reinitNeighborFaceRef(const Elem * neighbor_elem,
8211  unsigned int neighbor_side,
8212  BoundaryID bnd_id,
8213  Real tolerance,
8214  const std::vector<Point> * const pts,
8215  const std::vector<Real> * const weights,
8216  const THREAD_ID tid)
8217 {
8219  neighbor_elem, neighbor_side, bnd_id, tolerance, pts, weights, tid);
8220 
8221  if (_displaced_problem)
8222  _displaced_problem->reinitNeighborFaceRef(_displaced_mesh->elemPtr(neighbor_elem->id()),
8223  neighbor_side,
8224  bnd_id,
8225  tolerance,
8226  pts,
8227  weights,
8228  tid);
8229 }
8230 
8231 void
8233  const SubdomainID blk_id,
8234  std::vector<std::shared_ptr<MaterialBase>> & face_materials,
8235  std::vector<std::shared_ptr<MaterialBase>> & neighbor_materials,
8236  std::set<MooseVariableFieldBase *> & variables,
8237  const THREAD_ID tid)
8238 {
8239  if (_materials[Moose::FACE_MATERIAL_DATA].hasActiveBlockObjects(blk_id, tid))
8240  {
8241  auto & this_face_mats =
8243  for (std::shared_ptr<MaterialBase> face_mat : this_face_mats)
8244  if (face_mat->ghostable())
8245  {
8246  mooseAssert(!face_mat->hasStatefulProperties(),
8247  "Finite volume materials do not currently support stateful properties.");
8248  face_materials.push_back(face_mat);
8249  auto & var_deps = face_mat->getMooseVariableDependencies();
8250  for (auto * var : var_deps)
8251  {
8252  mooseAssert(
8253  var->isFV(),
8254  "Ghostable materials should only have finite volume variables coupled into them.");
8255  variables.insert(var);
8256  }
8257  }
8258  }
8259 
8260  if (_materials[Moose::NEIGHBOR_MATERIAL_DATA].hasActiveBlockObjects(blk_id, tid))
8261  {
8262  auto & this_neighbor_mats =
8264  for (std::shared_ptr<MaterialBase> neighbor_mat : this_neighbor_mats)
8265  if (neighbor_mat->ghostable())
8266  {
8267  mooseAssert(!neighbor_mat->hasStatefulProperties(),
8268  "Finite volume materials do not currently support stateful properties.");
8269  neighbor_materials.push_back(neighbor_mat);
8270 #ifndef NDEBUG
8271  auto & var_deps = neighbor_mat->getMooseVariableDependencies();
8272  for (auto * var : var_deps)
8273  {
8274  mooseAssert(
8275  var->isFV(),
8276  "Ghostable materials should only have finite volume variables coupled into them.");
8277  auto pr = variables.insert(var);
8278  mooseAssert(!pr.second,
8279  "We should not have inserted any new variables dependencies from our "
8280  "neighbor materials that didn't exist for our face materials");
8281  }
8282 #endif
8283  }
8284  }
8285 }
8286 
8287 void
8289  const unsigned int nqp,
8290  const THREAD_ID tid)
8291 {
8292  getMaterialData(data_type, tid).resize(nqp);
8293 }
8294 
8295 void
8297 {
8299  // We need to setup all the nonlinear systems other than our current one which actually called
8300  // this method (so we have to make sure we don't go in a circle)
8301  for (const auto i : make_range(numNonlinearSystems()))
8302  if (i != currentNlSysNum())
8303  _nl[i]->residualSetup();
8304  // We don't setup the aux sys because that's been done elsewhere
8305  if (_displaced_problem)
8306  _displaced_problem->residualSetup();
8307 }
8308 
8309 void
8311 {
8313  // We need to setup all the nonlinear systems other than our current one which actually called
8314  // this method (so we have to make sure we don't go in a circle)
8315  for (const auto i : make_range(numNonlinearSystems()))
8316  if (i != currentNlSysNum())
8317  _nl[i]->jacobianSetup();
8318  // We don't setup the aux sys because that's been done elsewhere
8319  if (_displaced_problem)
8320  _displaced_problem->jacobianSetup();
8321 }
8322 
8325 {
8326  return mesh().coordTransform();
8327 }
8328 
8329 unsigned int
8331 {
8332  return currentNonlinearSystem().number();
8333 }
8334 
8335 bool
8337 {
8338  // For now, only support printing from thread 0
8339  if (tid != 0)
8340  return false;
8341 
8344  return true;
8345  else
8346  return false;
8347 }
8348 
8349 std::vector<MortarUserObject *>
8351  const BoundaryID secondary_boundary_id,
8352  const bool displaced,
8353  const std::vector<MortarUserObject *> & mortar_uo_superset)
8354 {
8355  std::vector<MortarUserObject *> mortar_uos;
8356  auto * const subproblem = displaced ? static_cast<SubProblem *>(_displaced_problem.get())
8357  : static_cast<SubProblem *>(this);
8358  for (auto * const obj : mortar_uo_superset)
8359  if (obj->onInterface(primary_boundary_id, secondary_boundary_id) &&
8360  (&obj->getSubProblem() == subproblem))
8361  mortar_uos.push_back(obj);
8362 
8363  return mortar_uos;
8364 }
8365 
8366 std::vector<MortarUserObject *>
8368  const BoundaryID secondary_boundary_id,
8369  const bool displaced)
8370 {
8371  std::vector<MortarUserObject *> mortar_uos;
8372  theWarehouse()
8373  .query()
8375  .queryInto(mortar_uos);
8376  return getMortarUserObjects(primary_boundary_id, secondary_boundary_id, displaced, mortar_uos);
8377 }
8378 
8379 void
8381  const BoundaryID secondary_boundary_id,
8382  const bool displaced)
8383 {
8384  const auto mortar_uos =
8385  getMortarUserObjects(primary_boundary_id, secondary_boundary_id, displaced);
8386  for (auto * const mortar_uo : mortar_uos)
8387  {
8388  mortar_uo->setNormals();
8389  mortar_uo->reinit();
8390  }
8391 }
8392 
8393 void
8394 FEProblemBase::doingPRefinement(const bool doing_p_refinement,
8395  const MultiMooseEnum & disable_p_refinement_for_families)
8396 {
8397  SubProblem::doingPRefinement(doing_p_refinement, disable_p_refinement_for_families);
8398  if (_displaced_problem)
8399  _displaced_problem->doingPRefinement(doing_p_refinement, disable_p_refinement_for_families);
8400 }
8401 
8402 void
8404 {
8405  _verbose_setup = verbose;
8406  _verbose_multiapps = verbose;
8407 }
8408 
8409 void
8410 FEProblemBase::setCurrentLowerDElem(const Elem * const lower_d_elem, const THREAD_ID tid)
8411 {
8412  SubProblem::setCurrentLowerDElem(lower_d_elem, tid);
8413  if (_displaced_problem)
8414  _displaced_problem->setCurrentLowerDElem(
8415  lower_d_elem ? _displaced_mesh->elemPtr(lower_d_elem->id()) : nullptr, tid);
8416 }
8417 
8418 void
8420 {
8422  if (_displaced_problem)
8423  _displaced_problem->setCurrentBoundaryID(bid, tid);
8424 }
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 std::string & name() const
Get the name of the object.
Definition: MooseApp.h:106
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:823
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.
virtual void addUserObject(const std::string &user_object_name, const std::string &name, InputParameters &parameters)
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:425
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:999
std::vector< MooseArray< ADRealVectorValue > > _ad_grad_zero
InputParameterWarehouse & getInputParameterWarehouse()
Get the InputParameterWarehouse for MooseObjects.
Definition: MooseApp.C:2224
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:992
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)
Build an object (must be registered) - THIS METHOD IS DEPRECATED (Use create<T>()) ...
Definition: Factory.C:86
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:2411
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:812
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:69
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
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:295
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:447
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:1173
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:56
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:437
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:510
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.
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:721
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:2236
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:50
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:1275
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:69
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
void applyParameters(const InputParameters &common, std::vector< std::string > exclude=std::vector< std::string >())
Method for applying common parameters.
Executioner * getExecutioner() const
Retrieve the Executioner for this App.
Definition: MooseApp.C:1482
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:1240
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:1474
void removeSubstring(std::string &main, const std::string &sub)
find, erase, length algorithm for removing a substring from a string
Definition: MooseUtils.C:1253
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.
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:290
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
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:1282
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:1167
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:498
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.
const std::string & _type
The type of this class.
Definition: MooseBase.h:72
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:1772
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