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