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 "Reporter.h"
118#include "ADUtils.h"
119#include "Executioner.h"
120#include "VariadicTable.h"
123#include "NodalBCBase.h"
124#include "MortarUserObject.h"
127#include "Checkpoint.h"
130#include "DependencyResolver.h"
131
132#include "libmesh/exodusII_io.h"
133#include "libmesh/quadrature.h"
134#include "libmesh/coupling_matrix.h"
135#include "libmesh/nonlinear_solver.h"
136#include "libmesh/sparse_matrix.h"
137#include "libmesh/string_to_enum.h"
138#include "libmesh/fe_interface.h"
139#include "libmesh/enum_norm_type.h"
140#include "libmesh/petsc_solver_exception.h"
141
142#include "metaphysicl/dualnumber.h"
143
144// C++
145#include <cstring> // for "Jacobian" exception test
146
147// Anonymous namespace for helper function
148namespace
149{
153bool
154sortMooseVariables(const MooseVariableFEBase * a, const MooseVariableFEBase * b)
155{
156 return a->number() < b->number();
157}
158
159bool
160shouldSolveForSplineDofs(const libMesh::MeshBase & mesh)
161{
162 // With new libMesh, the most accurate thing to do is always solve
163 // for spline DoFs when we have them. With older libMesh, there's a
164 // bug that prevents that solve from working on meshes where we
165 // store some spline DoFs directly on assembly element vertices,
166 // including a mesh in our regression tests. For now we can detect
167 // these cases and avoid the solve for them.
168 bool have_constraint_rows = !mesh.get_constraint_rows().empty();
169
170 mesh.comm().max(have_constraint_rows);
171
172 // Are there any elements we weren't able to properly evaluate on
173 // directly?
174 bool returnval = false;
175 if (have_constraint_rows)
176 {
177 for (const auto & elem : mesh.active_local_element_ptr_range())
178 if (elem->mapping_type() == libMesh::INVALID_MAP // newer libMesh
179 || elem->type() == libMesh::NODEELEM) // older libMesh
180 {
181 returnval = true;
182 break;
183 }
184
185 mesh.comm().max(returnval);
186 }
187
188 return returnval;
189}
190
191void
192solveForSplineDofs(SystemBase & moose_sys)
193{
194 libMesh::System & sys = moose_sys.system();
196
197 // Old libMesh defaults to a *linear* solver tolerance here, which
198 // turns out to be enough in some cases (where a decent
199 // preconditioner converges us way past it) but which in parallel is
200 // too loose for a solve where we're not taking multiple
201 // quasi-Newton steps.
202 const Real old_linear_tol = es.parameters.get<Real>("linear solver tolerance");
203 es.parameters.set<Real>("linear solver tolerance") =
204 es.parameters.get<Real>("nonlinear solver relative residual tolerance");
205
206 sys.solve_for_unconstrained_dofs(moose_sys.solution());
207 sys.get_dof_map().enforce_constraints_exactly(sys, &moose_sys.solution());
208
209 es.parameters.set<Real>("linear solver tolerance") = old_linear_tol;
210}
211
212} // namespace
213
215
218{
220 params.addParam<unsigned int>("null_space_dimension", 0, "The dimension of the nullspace");
221 params.addParam<unsigned int>(
222 "transpose_null_space_dimension", 0, "The dimension of the transpose nullspace");
223 params.addParam<unsigned int>(
224 "near_null_space_dimension", 0, "The dimension of the near nullspace");
225 params.addParam<bool>("solve",
226 true,
227 "Whether or not to actually solve the Nonlinear system. "
228 "This is handy in the case that all you want to do is "
229 "execute AuxKernels, Transfers, etc. without actually "
230 "solving anything");
231 params.addParam<bool>("use_nonlinear",
232 true,
233 "Determines whether to use a Nonlinear vs a "
234 "Eigenvalue system (Automatically determined based "
235 "on executioner)");
236 params.addParam<bool>("error_on_jacobian_nonzero_reallocation",
237 "This causes PETSc to error if it had to reallocate memory in the Jacobian "
238 "matrix due to not having enough nonzeros");
239 params.addParam<bool>("ignore_zeros_in_jacobian",
240 false,
241 "Do not explicitly store zero values in "
242 "the Jacobian matrix if true");
243 params.addParam<bool>("force_restart",
244 false,
245 "EXPERIMENTAL: If true, a sub_app may use a "
246 "restart file instead of using of using the master "
247 "backup file");
248 params.addDeprecatedParam<bool>("skip_additional_restart_data",
249 false,
250 "True to skip additional data in equation system for restart.",
251 "This parameter is no longer used, as we do not load additional "
252 "vectors by default with restart");
253 params.addParam<bool>("skip_nl_system_check",
254 false,
255 "True to skip the NonlinearSystem check for work to do (e.g. Make sure "
256 "that there are variables to solve for).");
257 params.addParam<bool>("allow_initial_conditions_with_restart",
258 false,
259 "True to allow the user to specify initial conditions when restarting. "
260 "Initial conditions can override any restarted field");
261
262 auto coverage_check_description = [](std::string scope, std::string list_param_name)
263 {
264 return "Controls, if and how a " + scope +
265 " subdomain coverage check is performed. "
266 "With 'TRUE' or 'ON' all subdomains are checked (the default). Setting 'FALSE' or 'OFF' "
267 "will disable the check for all subdomains. "
268 "To exclude a predefined set of subdomains 'SKIP_LIST' is to "
269 "be used, while the subdomains to skip are to be defined in the parameter '" +
270 list_param_name +
271 "'. To limit the check to a list of subdomains, 'ONLY_LIST' is to "
272 "be used (again, using the parameter '" +
273 list_param_name + "').";
274 };
275
276 params.addParam<std::vector<SubdomainName>>(
277 "block",
278 {"ANY_BLOCK_ID"},
279 "List of subdomains for kernel coverage and material coverage checks. Setting this parameter "
280 "is equivalent to setting 'kernel_coverage_block_list' and 'material_coverage_block_list' as "
281 "well as using 'ONLY_LIST' as the coverage check mode.");
282
283 MooseEnum kernel_coverage_check_modes("FALSE TRUE OFF ON SKIP_LIST ONLY_LIST", "TRUE");
284 params.addParam<MooseEnum>("kernel_coverage_check",
285 kernel_coverage_check_modes,
286 coverage_check_description("kernel", "kernel_coverage_block_list"));
287 params.addParam<std::vector<SubdomainName>>(
288 "kernel_coverage_block_list",
289 {},
290 "List of subdomains for kernel coverage check. The meaning of this list is controlled by the "
291 "parameter 'kernel_coverage_check' (whether this is the list of subdomains to be checked, "
292 "not to be checked or not taken into account).");
293 params.addParam<bool>(
294 "boundary_restricted_node_integrity_check",
295 true,
296 "Set to false to disable checking of boundary restricted nodal object variable dependencies, "
297 "e.g. are the variable dependencies defined on the selected boundaries?");
298 params.addParam<bool>("boundary_restricted_elem_integrity_check",
299 true,
300 "Set to false to disable checking of boundary restricted elemental object "
301 "variable dependencies, e.g. are the variable dependencies defined on the "
302 "selected boundaries?");
303 params.addParam<bool>(
304 "side_uo_interface_mat_prop_integrity_check",
305 true,
306 "Set to false to disable checking that side user objects do not consume material "
307 "properties declared by interface materials on the same boundary.");
308 MooseEnum material_coverage_check_modes("FALSE TRUE OFF ON SKIP_LIST ONLY_LIST", "TRUE");
309 params.addParam<MooseEnum>(
310 "material_coverage_check",
311 material_coverage_check_modes,
312 coverage_check_description("material", "material_coverage_block_list"));
313 params.addParam<std::vector<SubdomainName>>(
314 "material_coverage_block_list",
315 {},
316 "List of subdomains for material coverage check. The meaning of this list is controlled by "
317 "the parameter 'material_coverage_check' (whether this is the list of subdomains to be "
318 "checked, not to be checked or not taken into account).");
319
320 params.addParam<bool>("fv_bcs_integrity_check",
321 true,
322 "Set to false to disable checking of overlapping Dirichlet and Flux BCs "
323 "and/or multiple DirichletBCs per sideset");
324
325 params.addParam<bool>(
326 "fv_face_integrity_check",
327 true,
328 "Set to false to disable checking that FV flux boundary conditions and FV interface "
329 "kernels are applied to faces with valid variable ownership and interface topology.");
330
331 params.addParam<bool>(
332 "material_dependency_check", true, "Set to false to disable material dependency check");
333 params.addParam<bool>("parallel_barrier_messaging",
334 false,
335 "Displays messaging from parallel "
336 "barrier notifications when executing "
337 "or transferring to/from Multiapps "
338 "(default: false)");
339 params.addParam<unsigned int>(
340 "num_concurrent_multiapps",
341 1,
342 "Set greater than 1 to solve the multiapps sharing an 'execution_order_group' "
343 "concurrently. Each such multiapp is assigned a disjoint subset of the MPI ranks "
344 "(partitioned using their 'min_procs_per_app'/'max_procs_per_app', otherwise evenly), so "
345 "they solve at the same time on different ranks. The specific value only acts as an "
346 "on/off switch; the number that run at once is set by the ranks available.");
347
348 MooseEnum verbosity("false true extra", "false");
349 params.addParam<MooseEnum>("verbose_setup",
350 verbosity,
351 "Set to 'true' to have the problem report on any object created. Set "
352 "to 'extra' to also display all parameters.");
353 params.addParam<bool>("verbose_multiapps",
354 false,
355 "Set to True to enable verbose screen printing related to MultiApps");
356 params.addParam<bool>(
357 "verbose_restore",
358 false,
359 "Set to True to enable verbose screen printing related to solution restoration");
360
361 params.addParam<FileNameNoExtension>("restart_file_base",
362 "File base name used for restart (e.g. "
363 "<path>/<filebase> or <path>/LATEST to "
364 "grab the latest file available)");
365
366 params.addParam<std::vector<std::vector<TagName>>>(
367 "extra_tag_vectors",
368 {},
369 "Extra vectors to add to the system that can be filled by objects which compute residuals "
370 "and Jacobians (Kernels, BCs, etc.) by setting tags on them. The outer index is for which "
371 "nonlinear system the extra tag vectors should be added for");
372
373 params.addParam<std::vector<std::vector<TagName>>>(
374 "not_zeroed_tag_vectors",
375 {},
376 "Extra vector tags which the sytem will not zero when other vector tags are zeroed. "
377 "The outer index is for which nonlinear system the extra tag vectors should be added for");
378
379 params.addParam<std::vector<std::vector<TagName>>>(
380 "extra_tag_matrices",
381 {},
382 "Extra matrices to add to the system that can be filled "
383 "by objects which compute residuals and Jacobians "
384 "(Kernels, BCs, etc.) by setting tags on them. The outer index is for which "
385 "nonlinear system the extra tag vectors should be added for");
386
387 params.addParam<std::vector<TagName>>(
388 "extra_tag_solutions",
389 {},
390 "Extra solution vectors to add to the system that can be used by "
391 "objects for coupling variable values stored in them.");
392
393 params.addParam<bool>("previous_nl_solution_required",
394 false,
395 "True to indicate that this calculation requires a solution vector for "
396 "storing the previous nonlinear iteration.");
397
398 params.addParam<std::vector<NonlinearSystemName>>(
399 "nl_sys_names", std::vector<NonlinearSystemName>{"nl0"}, "The nonlinear system names");
400
401 params.addParam<std::vector<LinearSystemName>>("linear_sys_names", {}, "The linear system names");
402
403 params.addParam<bool>("check_uo_aux_state",
404 false,
405 "True to turn on a check that no state presents during the evaluation of "
406 "user objects and aux kernels");
407
408 params.addPrivateParam<MooseMesh *>("mesh");
409
410 params.declareControllable("solve");
411
412 params.addParam<bool>(
413 "allow_invalid_solution",
414 false,
415 "Set to true to allow convergence even though the solution has been marked as 'invalid'");
416 params.addParam<bool>("show_invalid_solution_console",
417 true,
418 "Set to true to show the invalid solution occurrence summary in console");
419 params.addParam<bool>("immediately_print_invalid_solution",
420 false,
421 "Whether or not to report invalid solution warnings at the time the "
422 "warning is produced instead of after the calculation");
423
424 params.addParam<bool>(
425 "identify_variable_groups_in_nl",
426 true,
427 "Whether to identify variable groups in nonlinear systems. This affects dof ordering");
428
429 params.addParam<bool>(
430 "regard_general_exceptions_as_errors",
431 false,
432 "If we catch an exception during residual/Jacobian evaluaton for which we don't have "
433 "specific handling, immediately error instead of allowing the time step to be cut");
434
435 params.addParam<bool>("use_hash_table_matrix_assembly",
436 false,
437 "Whether to assemble matrices using hash tables instead of preallocating "
438 "matrix memory. This can be a good option if the sparsity pattern changes "
439 "throughout the course of the simulation.");
440 params.addParam<bool>(
441 "restore_original_nonzero_pattern",
442 "Whether we should reset matrix memory for every Jacobian evaluation. This option is useful "
443 "if the sparsity pattern is constantly changing and you are using hash table assembly or if "
444 "you wish to continually restore the matrix to the originally preallocated sparsity pattern "
445 "computed by relationship managers.");
446
448 "skip_nl_system_check kernel_coverage_check kernel_coverage_block_list "
449 "boundary_restricted_node_integrity_check "
450 "boundary_restricted_elem_integrity_check "
451 "side_uo_interface_mat_prop_integrity_check material_coverage_check "
452 "material_coverage_block_list fv_bcs_integrity_check fv_face_integrity_check "
453 "material_dependency_check check_uo_aux_state error_on_jacobian_nonzero_reallocation",
454 "Simulation checks");
455 params.addParamNamesToGroup("use_nonlinear previous_nl_solution_required nl_sys_names "
456 "ignore_zeros_in_jacobian identify_variable_groups_in_nl "
457 "use_hash_table_matrix_assembly restore_original_nonzero_pattern",
458 "Nonlinear system(s)");
460 "restart_file_base force_restart allow_initial_conditions_with_restart", "Restart");
462 "verbose_setup verbose_multiapps verbose_restore parallel_barrier_messaging", "Verbosity");
464 "null_space_dimension transpose_null_space_dimension near_null_space_dimension",
465 "Null space removal");
467 "extra_tag_vectors extra_tag_matrices extra_tag_solutions not_zeroed_tag_vectors",
468 "Contribution to tagged field data");
470 "allow_invalid_solution show_invalid_solution_console immediately_print_invalid_solution",
471 "Solution validity control");
472
473 return params;
474}
475
477 : SubProblem(parameters),
478 Restartable(this, "FEProblemBase"),
479 _mesh(*getCheckedPointerParam<MooseMesh *>("mesh")),
480 _req(declareManagedRestartableDataWithContext<RestartableEquationSystems>(
481 "equation_systems", nullptr, _mesh)),
482 _initialized(false),
483 _solve(getParam<bool>("solve")),
484 _transient(false),
485 _time(declareRestartableData<Real>("time")),
486 _time_old(declareRestartableData<Real>("time_old")),
487 _time_older(declareRestartableData<Real>("time_older")),
488 _t_step(declareRecoverableData<int>("t_step")),
489 _dt(declareRestartableData<Real>("dt")),
490 _dt_old(declareRestartableData<Real>("dt_old")),
491 _need_to_add_default_nonlinear_convergence(false),
492 _need_to_add_default_multiapp_fixed_point_convergence(false),
493 _need_to_add_default_steady_state_convergence(false),
494 _linear_sys_names(getParam<std::vector<LinearSystemName>>("linear_sys_names")),
495 _num_linear_sys(_linear_sys_names.size()),
496 _linear_systems(_num_linear_sys, nullptr),
497 _current_linear_sys(nullptr),
498 _using_default_nl(!isParamSetByUser("nl_sys_names")),
499 _nl_sys_names(!_using_default_nl || (_using_default_nl && !_linear_sys_names.size())
500 ? getParam<std::vector<NonlinearSystemName>>("nl_sys_names")
501 : std::vector<NonlinearSystemName>()),
502 _num_nl_sys(_nl_sys_names.size()),
503 _nl(_num_nl_sys, nullptr),
504 _current_nl_sys(nullptr),
505 _solver_systems(_num_nl_sys + _num_linear_sys, nullptr),
506 _aux(nullptr),
507 _coupling(Moose::COUPLING_DIAG),
508#ifdef MOOSE_KOKKOS_ENABLED
509 _kokkos_assembly(*this),
510#endif
511 _mesh_divisions(numThreads()),
512 _functions(numThreads()),
513#ifdef MOOSE_KOKKOS_ENABLED
514 _kokkos_functions(numThreads()),
515#endif
516 _convergences(numThreads()),
517 _nonlocal_kernels(numThreads()),
518 _nonlocal_integrated_bcs(numThreads()),
519 _ics(numThreads()),
520 _fv_ics(numThreads()),
521 _material_props(declareRestartableDataWithContext<MaterialPropertyStorage>(
522 "material_props", &_mesh, _material_prop_registry, *this)),
523 _bnd_material_props(declareRestartableDataWithContext<MaterialPropertyStorage>(
524 "bnd_material_props", &_mesh, _material_prop_registry, *this)),
525 _neighbor_material_props(declareRestartableDataWithContext<MaterialPropertyStorage>(
526 "neighbor_material_props", &_mesh, _material_prop_registry, *this)),
527#ifdef MOOSE_KOKKOS_ENABLED
528 _kokkos_material_props(
529 declareRestartableDataWithContext<Moose::Kokkos::MaterialPropertyStorage>(
530 "kokkos_material_props", &_mesh, _material_prop_registry, *this)),
531 _kokkos_bnd_material_props(
532 declareRestartableDataWithContext<Moose::Kokkos::MaterialPropertyStorage>(
533 "kokkos_bnd_material_props", &_mesh, _material_prop_registry, *this)),
534 _kokkos_neighbor_material_props(
535 declareRestartableDataWithContext<Moose::Kokkos::MaterialPropertyStorage>(
536 "kokkos_neighbor_material_props", &_mesh, _material_prop_registry, *this)),
537#endif
538 _materials(numThreads()),
539 _interface_materials(numThreads()),
540 _discrete_materials(numThreads()),
541 _all_materials(numThreads()),
542#ifdef MOOSE_KOKKOS_ENABLED
543 _kokkos_materials(numThreads()),
544#endif
545 _indicators(numThreads()),
546 _internal_side_indicators(numThreads()),
547 _markers(numThreads()),
548 _reporter_data(_app),
549 _multi_apps(_app.getExecuteOnEnum(), numThreads()),
550 _transient_multi_apps(_app.getExecuteOnEnum(), numThreads()),
551 _transfers(_app.getExecuteOnEnum(), /*num_threads=*/1),
552 _to_multi_app_transfers(_app.getExecuteOnEnum(), /*num_threads=*/1),
553 _from_multi_app_transfers(_app.getExecuteOnEnum(), /*num_threads=*/1),
554 _between_multi_app_transfers(_app.getExecuteOnEnum(), /*num_threads=*/1),
555 _num_concurrent_multiapps(getParam<unsigned int>("num_concurrent_multiapps")),
556#ifdef LIBMESH_ENABLE_AMR
557 _adaptivity(*this),
558 _cycles_completed(0),
559#endif
560 _displaced_mesh(nullptr),
561 _geometric_search_data(*this, _mesh),
562 _mortar_data(std::make_unique<MortarInterfaceWarehouse>(*this)),
563 _reinit_displaced_elem(false),
564 _reinit_displaced_face(false),
565 _reinit_displaced_neighbor(false),
566 _input_file_saved(false),
567 _has_dampers(false),
568 _has_constraints(false),
569 _snesmf_reuse_base(true),
570 _skip_exception_check(false),
571 _snesmf_reuse_base_set_by_user(false),
572 _has_initialized_stateful(false),
573 _const_jacobian(false),
574 _has_jacobian(false),
575 _needs_old_newton_iter(false),
576 _previous_nl_solution_required(getParam<bool>("previous_nl_solution_required")),
577 _previous_multiapp_fp_nl_solution_required(_num_nl_sys + _num_linear_sys, false),
578 _previous_multiapp_fp_aux_solution_required(false),
579 _previous_multisystem_fp_nl_solution_required(_num_nl_sys + _num_linear_sys, false),
580 _previous_multisystem_fp_aux_solution_required(false),
581 _has_nonlocal_coupling(false),
582 _calculate_jacobian_in_uo(false),
583 _kernel_coverage_check(
584 getParam<MooseEnum>("kernel_coverage_check").getEnum<CoverageCheckMode>()),
585 _kernel_coverage_blocks(getParam<std::vector<SubdomainName>>("kernel_coverage_block_list")),
586 _boundary_restricted_node_integrity_check(
587 getParam<bool>("boundary_restricted_node_integrity_check")),
588 _boundary_restricted_elem_integrity_check(
589 getParam<bool>("boundary_restricted_elem_integrity_check")),
590 _side_uo_interface_mat_prop_integrity_check(
591 getParam<bool>("side_uo_interface_mat_prop_integrity_check")),
592 _material_coverage_check(
593 getParam<MooseEnum>("material_coverage_check").getEnum<CoverageCheckMode>()),
594 _material_coverage_blocks(getParam<std::vector<SubdomainName>>("material_coverage_block_list")),
595 _fv_bcs_integrity_check(getParam<bool>("fv_bcs_integrity_check")),
596 _fv_face_integrity_check(getParam<bool>("fv_face_integrity_check")),
597 _material_dependency_check(getParam<bool>("material_dependency_check")),
598 _uo_aux_state_check(getParam<bool>("check_uo_aux_state")),
599#ifndef NDEBUG
600 _check_residual_for_nans(false),
601#endif
602 _max_qps(std::numeric_limits<unsigned int>::max()),
603 _max_scalar_order(INVALID_ORDER),
604 _has_time_integrator(false),
605 _has_exception(false),
606 _parallel_barrier_messaging(getParam<bool>("parallel_barrier_messaging")),
607 _verbose_setup(getParam<MooseEnum>("verbose_setup")),
608 _verbose_multiapps(getParam<bool>("verbose_multiapps")),
609 _verbose_restore(getParam<bool>("verbose_restore")),
610 _current_execute_on_flag(EXEC_NONE),
611 _control_warehouse(_app.getExecuteOnEnum(), /*num_threads=*/1),
612 _is_petsc_options_inserted(false),
613 _line_search(nullptr),
614 _using_ad_mat_props(false),
615 _current_ic_state(0),
616 _use_hash_table_matrix_assembly(getParam<bool>("use_hash_table_matrix_assembly")),
617 _error_on_jacobian_nonzero_reallocation(
618 isParamValid("error_on_jacobian_nonzero_reallocation")
619 ? getParam<bool>("error_on_jacobian_nonzero_reallocation")
620 : _app.errorOnJacobianNonzeroReallocation()),
621 _restore_original_nonzero_pattern(isParamValid("restore_original_nonzero_pattern")
622 ? getParam<bool>("restore_original_nonzero_pattern")
623 : _use_hash_table_matrix_assembly),
624 _ignore_zeros_in_jacobian(getParam<bool>("ignore_zeros_in_jacobian")),
625 _preserve_matrix_sparsity_pattern(true),
626 _force_restart(getParam<bool>("force_restart")),
627 _allow_ics_during_restart(getParam<bool>("allow_initial_conditions_with_restart")),
628 _skip_nl_system_check(getParam<bool>("skip_nl_system_check")),
629 _fail_next_system_convergence_check(false),
630 _allow_invalid_solution(getParam<bool>("allow_invalid_solution")),
631 _show_invalid_solution_console(getParam<bool>("show_invalid_solution_console")),
632 _immediately_print_invalid_solution(getParam<bool>("immediately_print_invalid_solution")),
633 _started_initial_setup(false),
634 _has_internal_edge_residual_objects(false),
635 _u_dot_requested(false),
636 _u_dotdot_requested(false),
637 _u_dot_old_requested(false),
638 _u_dotdot_old_requested(false),
639 _has_mortar(false),
640 _num_grid_steps(0),
641 _print_execution_on(),
642 _identify_variable_groups_in_nl(getParam<bool>("identify_variable_groups_in_nl")),
643 _regard_general_exceptions_as_errors(getParam<bool>("regard_general_exceptions_as_errors")),
644 _requires_nonlocal_coupling(false)
645{
646 auto checkCoverageCheckConflict =
647 [this](const std::string & coverage_check,
648 const CoverageCheckMode & coverage_check_mode,
649 const std::vector<SubdomainName> & coverage_blocks) -> void
650 {
651 if (coverage_check_mode != CoverageCheckMode::FALSE &&
652 coverage_check_mode != CoverageCheckMode::OFF)
653 if (coverage_blocks.size() > 1)
654 if (std::find(coverage_blocks.begin(), coverage_blocks.end(), "ANY_BLOCK_ID") !=
655 coverage_blocks.end())
656 paramError(coverage_check,
657 "The list of blocks used for ",
658 coverage_check,
659 " cannot contain 'ANY_BLOCK_ID' along with other blocks. ");
660 };
661
662 checkCoverageCheckConflict(
663 "kernel_coverage_check", _kernel_coverage_check, _kernel_coverage_blocks);
664 checkCoverageCheckConflict(
665 "material_coverage_check", _material_coverage_check, _material_coverage_blocks);
666
667 // Initialize static do_derivatives member. We initialize this to true so that all the
668 // default AD things that we setup early in the simulation actually get their derivative
669 // vectors initalized. We will toggle this to false when doing residual evaluations
670 ADReal::do_derivatives = true;
671
672 // Disable refinement/coarsening in EquationSystems::reinit because we already do this ourselves
674
676 // Default constructor fine for nonlinear because it will be populated later by framework
677 // executioner/solve object parameters
679 for (const auto i : index_range(_nl_sys_names))
680 {
681 const auto & name = _nl_sys_names[i];
684 _solver_sys_names.push_back(name);
685 }
686
687 for (const auto i : index_range(_linear_sys_names))
688 {
689 const auto & name = _linear_sys_names[i];
692 _solver_sys_names.push_back(name);
693 // Unlike for nonlinear these are basically dummy parameters
695 }
696
698 _cm.resize(numSolverSystems());
699
700 _time = 0.0;
701 _time_old = 0.0;
702 _time_older = 0.0;
703 _t_step = 0;
704 _dt = 0;
705 _dt_old = _dt;
706
707 unsigned int n_threads = numThreads();
708
709 _real_zero.resize(n_threads, 0.);
710 _scalar_zero.resize(n_threads);
711 _zero.resize(n_threads);
712 _phi_zero.resize(n_threads);
713 _ad_zero.resize(n_threads);
714 _grad_zero.resize(n_threads);
715 _ad_grad_zero.resize(n_threads);
716 _grad_phi_zero.resize(n_threads);
717 _second_zero.resize(n_threads);
718 _ad_second_zero.resize(n_threads);
719 _second_phi_zero.resize(n_threads);
720 _point_zero.resize(n_threads);
721 _vector_zero.resize(n_threads);
722 _vector_curl_zero.resize(n_threads);
723 _uo_jacobian_moose_vars.resize(n_threads);
724
725 _has_active_material_properties.resize(n_threads, 0);
726
727 _block_mat_side_cache.resize(n_threads);
728 _bnd_mat_side_cache.resize(n_threads);
729 _interface_mat_side_cache.resize(n_threads);
730
731 es().parameters.set<FEProblemBase *>("_fe_problem_base") = this;
732
733 if (isParamValid("restart_file_base"))
734 {
735 std::string restart_file_base = getParam<FileNameNoExtension>("restart_file_base");
736
737 // This check reverts to old behavior of providing "restart_file_base=" to mean
738 // don't restart... BISON currently relies on this. It could probably be removed.
739 // The new MooseUtils::convertLatestCheckpoint will error out if a checkpoint file
740 // is not found, which I think makes sense. Which means, without this, if you
741 // set "restart_file_base=", you'll get a "No checkpoint file found" error
742 if (restart_file_base.size())
743 {
744 restart_file_base = MooseUtils::convertLatestCheckpoint(restart_file_base);
745 setRestartFile(restart_file_base);
746 }
747 }
748
749 // // Generally speaking, the mesh is prepared for use, and consequently remote elements are deleted
750 // // well before our Problem(s) are constructed. Historically, in MooseMesh we have a bunch of
751 // // needs_prepare type flags that make it so we never call prepare_for_use (and consequently
752 // // delete_remote_elements) again. So the below line, historically, has had no impact. HOWEVER:
753 // // I've added some code in SetupMeshCompleteAction for deleting remote elements post
754 // // EquationSystems::init. If I execute that code without default ghosting, then I get > 40 MOOSE
755 // // test failures, so we clearly have some simulations that are not yet covered properly by
756 // // relationship managers. Until that is resolved, I am going to retain default geometric ghosting
757 // if (!_default_ghosting)
758 // _mesh.getMesh().remove_ghosting_functor(_mesh.getMesh().default_ghosting());
759
760#if !PETSC_RELEASE_LESS_THAN(3, 12, 0)
761 // Main app should hold the default database to handle system petsc options
762 if (!_app.isUltimateMaster())
763 LibmeshPetscCall(PetscOptionsCreate(&_petsc_option_data_base));
764#endif
765
766 if (!_solve)
767 {
768 // If we are not solving, we do not care about seeing unused petsc options
769 Moose::PetscSupport::setSinglePetscOption("-options_left", "0");
770 // We don't want petscSetOptions being called in solve and clearing the option that was just set
772 }
773}
774
775const MooseMesh &
776FEProblemBase::mesh(bool use_displaced) const
777{
778 if (use_displaced && !_displaced_problem)
779 mooseWarning("Displaced mesh was requested but the displaced problem does not exist. "
780 "Regular mesh will be returned");
781 return ((use_displaced && _displaced_problem) ? _displaced_problem->mesh() : mesh());
782}
783
784MooseMesh &
785FEProblemBase::mesh(bool use_displaced)
786{
787 if (use_displaced && !_displaced_problem)
788 mooseWarning("Displaced mesh was requested but the displaced problem does not exist. "
789 "Regular mesh will be returned");
790 return ((use_displaced && _displaced_problem) ? _displaced_problem->mesh() : mesh());
791}
792
793void
795{
796 // add vectors and their tags to system
797 auto & vectors = getParam<std::vector<std::vector<TagName>>>("extra_tag_vectors");
798 for (const auto sys_num : index_range(vectors))
799 for (auto & vector : vectors[sys_num])
800 {
801 auto tag = addVectorTag(vector);
802 _solver_systems[sys_num]->addVector(tag, false, libMesh::GHOSTED);
803 }
804
805 auto & not_zeroed_vectors = getParam<std::vector<std::vector<TagName>>>("not_zeroed_tag_vectors");
806 for (const auto sys_num : index_range(not_zeroed_vectors))
807 for (auto & vector : not_zeroed_vectors[sys_num])
808 {
809 auto tag = addVectorTag(vector);
810 _solver_systems[sys_num]->addVector(tag, false, GHOSTED);
812 }
813}
814
815void
817{
818 auto & matrices = getParam<std::vector<std::vector<TagName>>>("extra_tag_matrices");
819 for (const auto sys_num : index_range(matrices))
820 for (auto & matrix : matrices[sys_num])
821 {
822 auto tag = addMatrixTag(matrix);
823 _solver_systems[sys_num]->addMatrix(tag);
824 }
825
826 for (auto & sys : _solver_systems)
827 sys->sizeVariableMatrixData();
828 _aux->sizeVariableMatrixData();
829}
830
831void
833{
834 for (auto & vector : getParam<std::vector<TagName>>("extra_tag_solutions"))
835 {
836 auto tag = addVectorTag(vector, Moose::VECTOR_TAG_SOLUTION);
837 for (auto & sys : _solver_systems)
838 sys->addVector(tag, false, libMesh::GHOSTED);
839 _aux->addVector(tag, false, libMesh::GHOSTED);
840 }
841
843 {
844 // We'll populate the zeroth state of the nonlinear iterations with the current solution for
845 // ease of use in doing things like copying solutions backwards. We're just storing pointers in
846 // the solution states containers so populating the zeroth state does not cost us the memory of
847 // a new vector
849 }
850
852 for (auto & sys : _solver_systems)
853 sys->associateVectorToTag(*sys->system().current_local_solution.get(), tag);
854 _aux->associateVectorToTag(*_aux->system().current_local_solution.get(), tag);
855}
856
857void
859{
860 for (auto & sys : _solver_systems)
861 sys->needSolutionState(state, iteration_type);
862 _aux->needSolutionState(state, iteration_type);
863}
864
865bool
867 Moose::SolutionIterationType iteration_type) const
868{
869 bool has_solution_state = false;
870 for (auto & sys : _solver_systems)
871 has_solution_state |= sys->hasSolutionState(state, iteration_type);
872 has_solution_state |= _aux->hasSolutionState(state, iteration_type);
873 return has_solution_state;
874}
875
876void
877FEProblemBase::newAssemblyArray(std::vector<std::shared_ptr<SolverSystem>> & solver_systems)
878{
879 unsigned int n_threads = numThreads();
880
881 _assembly.resize(n_threads);
882 for (const auto i : make_range(n_threads))
883 {
884 _assembly[i].resize(solver_systems.size());
885 for (const auto j : index_range(solver_systems))
886 _assembly[i][j] = std::make_unique<Assembly>(*solver_systems[j], i);
887 }
888}
889
890void
892 std::vector<std::shared_ptr<NonlinearSystemBase>> & nls)
893{
894 TIME_SECTION("initNullSpaceVectors", 5, "Initializing Null Space Vectors");
895
896 unsigned int dimNullSpace = parameters.get<unsigned int>("null_space_dimension");
897 unsigned int dimTransposeNullSpace =
898 parameters.get<unsigned int>("transpose_null_space_dimension");
899 unsigned int dimNearNullSpace = parameters.get<unsigned int>("near_null_space_dimension");
900 for (unsigned int i = 0; i < dimNullSpace; ++i)
901 {
902 std::ostringstream oss;
903 oss << "_" << i;
904 // do not project, since this will be recomputed, but make it ghosted, since the near nullspace
905 // builder might march over all nodes
906 for (auto & nl : nls)
907 nl->addVector("NullSpace" + oss.str(), false, libMesh::GHOSTED);
908 }
909 _subspace_dim["NullSpace"] = dimNullSpace;
910 for (unsigned int i = 0; i < dimTransposeNullSpace; ++i)
911 {
912 std::ostringstream oss;
913 oss << "_" << i;
914 // do not project, since this will be recomputed, but make it ghosted, since the near nullspace
915 // builder might march over all nodes
916 for (auto & nl : nls)
917 nl->addVector("TransposeNullSpace" + oss.str(), false, libMesh::GHOSTED);
918 }
919 _subspace_dim["TransposeNullSpace"] = dimTransposeNullSpace;
920 for (unsigned int i = 0; i < dimNearNullSpace; ++i)
921 {
922 std::ostringstream oss;
923 oss << "_" << i;
924 // do not project, since this will be recomputed, but make it ghosted, since the near-nullspace
925 // builder might march over all semilocal nodes
926 for (auto & nl : nls)
927 nl->addVector("NearNullSpace" + oss.str(), false, libMesh::GHOSTED);
928 }
929 _subspace_dim["NearNullSpace"] = dimNearNullSpace;
930}
931
933{
934 // Flush the Console stream, the underlying call to Console::mooseConsole
935 // relies on a call to Output::checkInterval that has references to
936 // _time, etc. If it is not flushed here memory problems arise if you have
937 // an unflushed stream and start destructing things.
938 _console << std::flush;
939
940 unsigned int n_threads = numThreads();
941 for (unsigned int i = 0; i < n_threads; i++)
942 {
943 _zero[i].release();
944 _phi_zero[i].release();
945 _scalar_zero[i].release();
946 _grad_zero[i].release();
947 _grad_phi_zero[i].release();
948 _second_zero[i].release();
949 _second_phi_zero[i].release();
950 _vector_zero[i].release();
951 _vector_curl_zero[i].release();
952 _ad_zero[i].release();
953 _ad_grad_zero[i].release();
954 _ad_second_zero[i].release();
955 }
956
957#if !PETSC_RELEASE_LESS_THAN(3, 12, 0)
958 if (!_app.isUltimateMaster())
959 {
960 auto ierr = PetscOptionsDestroy(&_petsc_option_data_base);
961 // Don't throw on destruction
962 CHKERRABORT(this->comm().get(), ierr);
963 }
964#endif
965}
966
967void
968FEProblemBase::setCoordSystem(const std::vector<SubdomainName> & blocks,
969 const MultiMooseEnum & coord_sys)
970{
971 TIME_SECTION("setCoordSystem", 5, "Setting Coordinate System");
972 _mesh.setCoordSystem(blocks, coord_sys);
973}
974
975void
977{
978 _mesh.setAxisymmetricCoordAxis(rz_coord_axis);
979}
980
981const ConstElemRange &
983{
985 {
986 std::vector<const DofMap *> dof_maps(es().n_systems());
987 for (const auto i : make_range(es().n_systems()))
988 {
989 const auto & sys = es().get_system(i);
990 dof_maps[i] = &sys.get_dof_map();
991 }
993 std::make_unique<ConstElemRange>(_mesh.getMesh().multi_evaluable_elements_begin(dof_maps),
994 _mesh.getMesh().multi_evaluable_elements_end(dof_maps));
995 }
997}
998
999const ConstElemRange &
1001{
1003 {
1004 std::vector<const DofMap *> dof_maps(_nl.size());
1005 for (const auto i : index_range(dof_maps))
1006 dof_maps[i] = &_nl[i]->dofMap();
1008 std::make_unique<ConstElemRange>(_mesh.getMesh().multi_evaluable_elements_begin(dof_maps),
1009 _mesh.getMesh().multi_evaluable_elements_end(dof_maps));
1010 }
1011
1013}
1014
1015void
1017{
1018 TIME_SECTION("initialSetup", 2, "Performing Initial Setup");
1019
1021
1023 mooseError("Checkpoint recovery and restart and exodus restart are all mutually exclusive.");
1024
1026 mooseWarning("MOOSE may fail to catch an exception when the \"skip_exception_check\" parameter "
1027 "is used. If you receive a terse MPI error during execution, remove this "
1028 "parameter and rerun your simulation");
1029
1030 // set state flag indicating that we are in or beyond initialSetup.
1031 // This can be used to throw errors in methods that _must_ be called at construction time.
1034
1035 // Setup the solution states (current, old, etc) in each system based on
1036 // its default and the states requested of each of its variables
1037 for (const auto i : index_range(_solver_systems))
1038 {
1039 _solver_systems[i]->initSolutionState();
1040 if (getDisplacedProblem())
1041 getDisplacedProblem()->solverSys(i).initSolutionState();
1042 }
1043 _aux->initSolutionState();
1044 if (getDisplacedProblem())
1045 getDisplacedProblem()->auxSys().initSolutionState();
1046
1047 // always execute to get the max number of DoF per element and node needed to initialize phi_zero
1048 // variables
1049 dof_id_type global_max_var_n_dofs_per_elem = 0;
1050 for (const auto i : index_range(_solver_systems))
1051 {
1052 auto & sys = *_solver_systems[i];
1053 dof_id_type max_var_n_dofs_per_elem;
1054 dof_id_type max_var_n_dofs_per_node;
1055 {
1056 TIME_SECTION("computingMaxDofs", 3, "Computing Max Dofs Per Element");
1057
1058 MaxVarNDofsPerElem mvndpe(*this, sys);
1060 max_var_n_dofs_per_elem = mvndpe.max();
1061 _communicator.max(max_var_n_dofs_per_elem);
1062
1063 MaxVarNDofsPerNode mvndpn(*this, sys);
1065 max_var_n_dofs_per_node = mvndpn.max();
1066 _communicator.max(max_var_n_dofs_per_node);
1067 global_max_var_n_dofs_per_elem =
1068 std::max(global_max_var_n_dofs_per_elem, max_var_n_dofs_per_elem);
1069 }
1070
1071 {
1072 TIME_SECTION("assignMaxDofs", 5, "Assigning Maximum Dofs Per Elem");
1073
1074 sys.assignMaxVarNDofsPerElem(max_var_n_dofs_per_elem);
1077 displaced_problem->solverSys(i).assignMaxVarNDofsPerElem(max_var_n_dofs_per_elem);
1078
1079 sys.assignMaxVarNDofsPerNode(max_var_n_dofs_per_node);
1081 displaced_problem->solverSys(i).assignMaxVarNDofsPerNode(max_var_n_dofs_per_node);
1082 }
1083 }
1084
1085 {
1086 TIME_SECTION("resizingVarValues", 5, "Resizing Variable Values");
1087
1088 for (unsigned int tid = 0; tid < numThreads(); ++tid)
1089 {
1090 _phi_zero[tid].resize(global_max_var_n_dofs_per_elem, std::vector<Real>(getMaxQps(), 0.));
1091 _grad_phi_zero[tid].resize(global_max_var_n_dofs_per_elem,
1092 std::vector<RealGradient>(getMaxQps(), RealGradient(0.)));
1093 _second_phi_zero[tid].resize(global_max_var_n_dofs_per_elem,
1094 std::vector<RealTensor>(getMaxQps(), RealTensor(0.)));
1095 }
1096 }
1097
1098 // Set up stateful material property redistribution, if we suspect
1099 // it may be necessary later.
1101
1103 {
1104 // Only load all of the vectors if we're recovering
1106
1107 // This forces stateful material property loading to be an exact one-to-one match
1108 if (_app.isRecovering())
1109 {
1111 props->setRecovering();
1112
1113#ifdef MOOSE_KOKKOS_ENABLED
1114 for (auto props :
1116 props->setRecovering();
1117#endif
1118 }
1119
1120 TIME_SECTION("restore", 3, "Restoring from backup");
1121
1122 // We could have a cached backup when this app is a sub-app and has been given a Backup
1123 if (!_app.hasInitialBackup())
1125 else
1127
1133 if (_app.isRestarting())
1134 {
1135 if (_app.hasStartTime())
1137 else
1138 {
1140 _time_old = _time;
1141 }
1142 }
1143 }
1144 else
1145 {
1147
1148 if (reader)
1149 {
1150 TIME_SECTION("copyingFromExodus", 3, "Copying Variables From Exodus");
1151
1152 for (auto & sys : _solver_systems)
1153 sys->copyVars(*reader);
1154 _aux->copyVars(*reader);
1155 }
1156 else
1157 {
1158 if (_solver_systems[0]->hasVarCopy() || _aux->hasVarCopy())
1159 mooseError("Need Exodus reader to restart variables but the reader is not available\n"
1160 "Use either FileMesh with an Exodus mesh file or FileMeshGenerator with an "
1161 "Exodus mesh file and with use_for_exodus_restart equal to true");
1162 }
1163 }
1164
1165 // Perform output related setups
1167
1168 // Flush all output to _console that occur during construction and initialization of objects
1170
1171 // Build Refinement and Coarsening maps for stateful material projections if necessary
1172 if ((_adaptivity.isOn() || _num_grid_steps) &&
1175 {
1177 mooseError("Stateful neighbor material properties do not work with mesh adaptivity");
1178
1180 }
1181
1182 if (!_app.isRecovering())
1183 {
1190 {
1191 if (!_app.isUltimateMaster())
1192 mooseError(
1193 "Doing extra refinements when restarting is NOT supported for sub-apps of a MultiApp");
1194
1196 }
1197 }
1198
1199 unsigned int n_threads = numThreads();
1200
1201 // Convergence initial setup
1202 {
1203 TIME_SECTION("convergenceInitialSetup", 5, "Initializing Convergence objects");
1204
1205 for (THREAD_ID tid = 0; tid < n_threads; tid++)
1207 }
1208
1209 // UserObject initialSetup
1210 std::set<std::string> depend_objects_ic = _ics.getDependObjects();
1211 std::set<std::string> depend_objects_aux = _aux->getDependObjects();
1212
1213 std::map<int, std::vector<UserObjectBase *>> group_userobjs;
1214
1215 // This replaces all prior updateDependObjects calls on the old user object warehouses.
1216 TheWarehouse::Query uo_query = theWarehouse().query().condition<AttribSystem>("UserObject");
1217 std::vector<UserObjectBase *> userobjs;
1218 uo_query.queryInto(userobjs);
1220 theWarehouse(), getAuxiliarySystem(), _app.getExecuteOnEnum(), userobjs, depend_objects_ic);
1221
1222 for (auto obj : userobjs)
1223 group_userobjs[obj->getParam<int>("execution_order_group")].push_back(obj);
1224
1225#ifdef MOOSE_KOKKOS_ENABLED
1226 {
1227 TheWarehouse::Query uo_query =
1228 theWarehouse().query().condition<AttribSystem>("KokkosUserObject");
1229 std::vector<UserObjectBase *> userobjs;
1230 uo_query.queryInto(userobjs);
1232 theWarehouse(), getAuxiliarySystem(), _app.getExecuteOnEnum(), userobjs, depend_objects_ic);
1233
1234 for (auto obj : userobjs)
1235 group_userobjs[obj->getParam<int>("execution_order_group")].push_back(obj);
1236 }
1237#endif
1238
1239 for (auto & [group, objs] : group_userobjs)
1240 for (auto obj : objs)
1241 obj->initialSetup();
1242
1243 // check if jacobian calculation is done in userobject
1244 for (THREAD_ID tid = 0; tid < n_threads; ++tid)
1246
1247 // Check whether nonlocal coupling is required or not
1251
1252 {
1253 TIME_SECTION("initializingFunctions", 5, "Initializing Functions");
1254
1255 // Call the initialSetup methods for functions
1256 for (THREAD_ID tid = 0; tid < n_threads; tid++)
1257 {
1258 reinitScalars(tid); // initialize scalars so they are properly sized for use as input into
1259 // ParsedFunctions
1261 }
1262
1263#ifdef MOOSE_KOKKOS_ENABLED
1265#endif
1266 }
1267
1268 {
1269 TIME_SECTION("initializingRandomObjects", 5, "Initializing Random Objects");
1270
1271 // Random interface objects
1272 for (const auto & it : _random_data_objects)
1273 it.second->updateSeeds(EXEC_INITIAL);
1274 }
1275
1276 if (!_app.isRecovering())
1277 {
1279
1280 {
1281 TIME_SECTION("ICinitialSetup", 5, "Setting Up Initial Conditions");
1282
1283 for (THREAD_ID tid = 0; tid < n_threads; tid++)
1284 {
1285 _ics.initialSetup(tid);
1286 _fv_ics.initialSetup(tid);
1287 }
1288
1290 }
1291
1293 }
1294
1295 // Materials
1297 {
1298 TIME_SECTION("materialInitialSetup", 3, "Setting Up Materials");
1299
1300 for (THREAD_ID tid = 0; tid < n_threads; tid++)
1301 {
1302 // Sort the Material objects, these will be actually computed by MOOSE in reinit methods.
1303 _materials.sort(tid);
1305
1306 // Call initialSetup on all material objects
1308
1309 // Discrete materials may insert additional dependencies on materials during the initial
1310 // setup. Therefore we resolve the dependencies once more, now with the additional
1311 // dependencies due to discrete materials.
1313 {
1314 _materials.sort(tid);
1316 }
1317 }
1318
1319#ifdef MOOSE_KOKKOS_ENABLED
1320 _kokkos_materials.sort(0, true);
1321#endif
1322
1323 {
1324 TIME_SECTION("computingInitialStatefulProps", 3, "Computing Initial Material Values");
1325
1327
1331#ifdef MOOSE_KOKKOS_ENABLED
1336#endif
1337 }
1338 }
1339
1340 // setRestartInPlace() is set because the property maps have now been setup and we can
1341 // dataLoad() them directly in place
1342 // setRecovering() is set because from now on we require a one-to-one mapping of
1343 // stateful properties because we shouldn't be declaring any more
1345 {
1346 props->setRestartInPlace();
1347 props->setRecovering();
1348 }
1349
1350 for (THREAD_ID tid = 0; tid < n_threads; tid++)
1351 {
1354 _markers.sort(tid);
1356 }
1357
1358#ifdef LIBMESH_ENABLE_AMR
1359
1361 {
1362 unsigned int n = adaptivity().getInitialSteps();
1363 if (n && !_app.isUltimateMaster() && _app.isRestarting())
1364 mooseError("Cannot perform initial adaptivity during restart on sub-apps of a MultiApp!");
1365
1367 }
1368
1369#endif // LIBMESH_ENABLE_AMR
1370
1371 if (!_app.isRecovering() && !_app.isRestarting())
1372 {
1373 // During initial setup the solution is copied to the older solution states (old, older, etc)
1375
1376 // Check if there are old state initial conditions
1377 auto ics = _ics.getActiveObjects();
1378 auto fv_ics = _fv_ics.getActiveObjects();
1379 auto scalar_ics = _scalar_ics.getActiveObjects();
1380 unsigned short ic_state_max = 0;
1381
1382 auto findMax = [&ic_state_max](const auto & obj_list)
1383 {
1384 for (auto ic : obj_list.getActiveObjects())
1385 ic_state_max = std::max(ic_state_max, ic->getState());
1386 };
1387 findMax(_ics);
1388 findMax(_fv_ics);
1389 findMax(_scalar_ics);
1390
1391 // if there are old state ICs, compute them and write to old states accordingly
1392 if (ic_state_max > 0)
1393 {
1394 // state 0 copy (we'll overwrite current state when evaluating ICs and need to restore it once
1395 // we're done with the old/older state ICs)
1396 std::vector<std::unique_ptr<NumericVector<Real>>> state0_sys_buffers(_solver_systems.size());
1397 std::unique_ptr<NumericVector<Real>> state0_aux_buffer;
1398
1399 // save state 0
1400 for (const auto i : index_range(_solver_systems))
1401 state0_sys_buffers[i] = _solver_systems[i]->solutionState(0).clone();
1402
1403 state0_aux_buffer = _aux->solutionState(0).clone();
1404
1405 // compute old state ICs
1406 for (_current_ic_state = 1; _current_ic_state <= ic_state_max; _current_ic_state++)
1407 {
1409
1410 for (auto & sys : _solver_systems)
1411 sys->solutionState(_current_ic_state) = sys->solutionState(0);
1412
1413 _aux->solutionState(_current_ic_state) = _aux->solutionState(0);
1414 }
1416
1417 // recover state 0
1418 for (const auto i : index_range(_solver_systems))
1419 {
1420 _solver_systems[i]->solutionState(0) = *state0_sys_buffers[i];
1421 _solver_systems[i]->solutionState(0).close();
1422 _solver_systems[i]->update();
1423 }
1424 _aux->solutionState(0) = *state0_aux_buffer;
1425 _aux->solutionState(0).close();
1426 _aux->update();
1427 }
1428 }
1429
1430 if (!_app.isRecovering())
1431 {
1432 if (haveXFEM())
1434 }
1435
1436 // Call initialSetup on the solver systems
1437 for (auto & sys : _solver_systems)
1438 sys->initialSetup();
1439
1440 // Auxilary variable initialSetup calls
1441 _aux->initialSetup();
1442
1444 // initialSetup for displaced systems
1445 _displaced_problem->initialSetup();
1446
1447 for (auto & sys : _solver_systems)
1448 sys->setSolution(*(sys->system().current_local_solution.get()));
1449
1450 // Update the nearest node searches (has to be called after the problem is all set up)
1451 // We do this here because this sets up the Element's DoFs to ghost
1453
1455 if (_displaced_mesh)
1457
1458 // We need to move the mesh in order to build a map between mortar secondary and primary
1459 // interfaces. This map will then be used by the AgumentSparsityOnInterface ghosting functor to
1460 // know which dofs we need ghosted when we call EquationSystems::reinit
1461 if (_displaced_problem && _mortar_data->hasDisplacedObjects())
1462 {
1463 _displaced_problem->updateMesh();
1464 // if displacements were applied to the mesh, the mortar mesh should be updated too
1466 }
1467
1468 // Possibly reinit one more time to get ghosting correct
1470
1471 if (_displaced_mesh)
1472 _displaced_problem->updateMesh();
1473
1474 updateGeomSearch(); // Call all of the rest of the geometric searches
1475
1476 for (auto & sys : _solver_systems)
1477 {
1478 const auto & tis = sys->getTimeIntegrators();
1479
1480 {
1481 TIME_SECTION("timeIntegratorInitialSetup", 5, "Initializing Time Integrator");
1482 for (auto & ti : tis)
1483 ti->initialSetup();
1484 }
1485 }
1486
1487 // HUGE NOTE: MultiApp initialSetup() MUST... I repeat MUST be _after_ main-app restartable data
1488 // has been restored
1489
1490 // Call initialSetup on the MultiApps
1491 if (_multi_apps.hasObjects())
1492 {
1493 TIME_SECTION("initialSetupMultiApps", 2, "Initializing MultiApps", false);
1494 // Assign concurrent multiapps their disjoint rank partitions before the sub-apps are created
1495 // so that each is created on the communicator it will actually run on
1498 }
1499
1500 // Call initialSetup on the transfers
1501 {
1502 TIME_SECTION("initialSetupTransfers", 2, "Initializing Transfers");
1503
1505
1506 // Call initialSetup on the MultiAppTransfers to be executed on TO_MULTIAPP
1507 const auto & to_multi_app_objects = _to_multi_app_transfers.getActiveObjects();
1508 for (const auto & transfer : to_multi_app_objects)
1509 {
1510 transfer->setCurrentDirection(Transfer::DIRECTION::TO_MULTIAPP);
1511 transfer->initialSetup();
1512 }
1513
1514 // Call initialSetup on the MultiAppTransfers to be executed on FROM_MULTIAPP
1515 const auto & from_multi_app_objects = _from_multi_app_transfers.getActiveObjects();
1516 for (const auto & transfer : from_multi_app_objects)
1517 {
1518 transfer->setCurrentDirection(Transfer::DIRECTION::FROM_MULTIAPP);
1519 transfer->initialSetup();
1520 }
1521
1522 // Call initialSetup on the MultiAppTransfers to be executed on BETWEEN_MULTIAPP
1523 const auto & between_multi_app_objects = _between_multi_app_transfers.getActiveObjects();
1524 for (const auto & transfer : between_multi_app_objects)
1525 {
1526 transfer->setCurrentDirection(Transfer::DIRECTION::BETWEEN_MULTIAPP);
1527 transfer->initialSetup();
1528 }
1529 }
1530
1532 {
1533 TIME_SECTION("BoundaryRestrictedNodeIntegrityCheck", 5);
1534
1535 // check that variables are defined along boundaries of boundary restricted nodal objects
1536 const auto & bnd_nodes = getCurrentAlgebraicBndNodeRange();
1537 BoundaryNodeIntegrityCheckThread bnict(*this, uo_query);
1538 Threads::parallel_reduce(bnd_nodes, bnict, numThreads());
1539
1540 // Nodal bcs aren't threaded
1541 for (auto & nl : _nl)
1542 {
1543 const auto & nodal_bcs = nl->getNodalBCWarehouse();
1544 if (!nodal_bcs.hasBoundaryObjects())
1545 continue;
1546
1547 for (const auto & bnode : bnd_nodes)
1548 {
1549 const auto boundary_id = bnode->_bnd_id;
1550 const Node * const node = bnode->_node;
1551
1552 if (node->processor_id() != this->processor_id())
1553 continue;
1554
1555 const auto & bnd_name = _mesh.getBoundaryName(boundary_id);
1556
1557 // Avoid assertion in getBoundaryObjects that we have boundary objects for this boundary ID
1558 if (!nodal_bcs.hasBoundaryObjects(boundary_id))
1559 continue;
1560
1561 const auto & bnd_objects = nodal_bcs.getBoundaryObjects(boundary_id);
1562 for (const auto & bnd_object : bnd_objects)
1563 {
1564 const auto & bnd_variable = bnd_object->variable();
1565 // Skip if this object uses geometric search because coupled variables may be defined on
1566 // paired boundaries instead of the boundary this node is on. Also skip if this boundary
1567 // condition isn't applicable to the current node, e.g. if the node doesn't have any
1568 // degrees of freedom for the boundary condition's variable
1569 if (!bnd_object->requiresGeometricSearch() &&
1570 bnd_object->checkVariableBoundaryIntegrity() &&
1571 node->n_dofs(nl->number(), bnd_variable.number()))
1572 {
1573 std::set<MooseVariableFieldBase *> vars_to_omit = {
1574 &cast_ref<MooseVariableFieldBase &>(const_cast<MooseVariableBase &>(bnd_variable))};
1575
1577 *bnd_object, bnd_object->checkAllVariables(*node, vars_to_omit), bnd_name);
1578 }
1579 }
1580 }
1581 }
1582 }
1583
1585 {
1586 TIME_SECTION("BoundaryRestrictedElemIntegrityCheck", 5);
1587
1588 // check that variables are defined along boundaries of boundary restricted elemental objects
1590 BoundaryElemIntegrityCheckThread beict(*this, uo_query);
1591 Threads::parallel_reduce(bnd_elems, beict, numThreads());
1592 }
1593
1595 {
1596 TIME_SECTION("FVFaceIntegrityCheck", 5);
1597
1598 auto check_fv_face_integrity = [this](MooseMesh & fv_mesh, const bool on_displaced)
1599 {
1600 auto flux_bc_base_query = theWarehouse()
1601 .query()
1602 .condition<AttribSystem>("FVFluxBC")
1603 .condition<AttribDisplaced>(on_displaced)
1604 .condition<AttribThread>(0);
1605 TheWarehouse::QueryCache<AttribBoundaries> flux_bc_query(flux_bc_base_query);
1606
1607 auto interface_kernel_base_query = theWarehouse()
1608 .query()
1609 .condition<AttribSystem>("FVInterfaceKernel")
1610 .condition<AttribDisplaced>(on_displaced)
1611 .condition<AttribThread>(0);
1612 TheWarehouse::QueryCache<AttribBoundaries> interface_kernel_query(
1613 interface_kernel_base_query);
1614
1615 std::vector<FVFluxBC *> flux_bcs;
1616 std::vector<FVInterfaceKernel *> interface_kernels;
1617
1618 for (auto face_it = fv_mesh.ownedFaceInfoBegin(); face_it != fv_mesh.ownedFaceInfoEnd();
1619 ++face_it)
1620 {
1621 const FaceInfo & fi = **face_it;
1622
1623 for (const auto boundary_id : fi.boundaryIDs())
1624 {
1625 auto boundary_key = std::make_tuple(boundary_id, false);
1626
1627 flux_bc_query.queryInto(flux_bcs, boundary_key);
1628 for (const auto * const flux_bc : flux_bcs)
1629 if (flux_bc->checkVariableBoundaryIntegrity())
1630 flux_bc->checkFaceIntegrity(fi);
1631
1632 interface_kernel_query.queryInto(interface_kernels, boundary_key);
1633 for (const auto * const interface_kernel : interface_kernels)
1634 interface_kernel->checkFaceIntegrity(fi);
1635 }
1636 }
1637 };
1638
1639 if (haveFV())
1640 check_fv_face_integrity(mesh(), false);
1641
1642 if (_displaced_problem && _displaced_problem->haveFV())
1643 check_fv_face_integrity(_displaced_problem->mesh(), true);
1644 }
1645
1646 if (!_app.isRecovering())
1647 {
1649 if (!converged)
1650 mooseError("failed to converge initial MultiApp");
1651
1652 // We'll backup the Multiapp here
1654
1655 for (THREAD_ID tid = 0; tid < n_threads; tid++)
1656 reinitScalars(tid);
1657
1659
1660 // The FEProblemBase::execute method doesn't call all the systems on EXEC_INITIAL, but it does
1661 // set/unset the current flag. Therefore, this resets the current flag to EXEC_INITIAL so that
1662 // subsequent calls (e.g., executeControls) have the proper flag.
1664 }
1665
1666 // Here we will initialize the stateful properties once more since they may have been updated
1667 // during initialSetup by calls to computeProperties.
1668 //
1669 // It's really bad that we don't allow this during restart. It means that we can't add new
1670 // stateful materials
1671 // during restart. This is only happening because this _has_ to be below initial userobject
1672 // execution.
1673 // Otherwise this could be done up above... _before_ restoring restartable data... which would
1674 // allow you to have
1675 // this happen during restart. I honestly have no idea why this has to happen after initial user
1676 // object computation.
1677 // THAT is something we should fix... so I've opened this ticket: #5804
1678 if (!_app.isRecovering() && !_app.isRestarting())
1679 {
1682 {
1683 TIME_SECTION("computeMaterials", 2, "Computing Initial Material Properties");
1684
1686 }
1687#ifdef MOOSE_KOKKOS_ENABLED
1691 {
1692 TIME_SECTION("computeMaterials", 2, "Computing Initial Material Properties");
1693
1695 }
1696#endif
1697 }
1698
1699 // Control Logic
1702
1703 // Scalar variables need to reinited for the initial conditions to be available for output
1704 for (unsigned int tid = 0; tid < n_threads; tid++)
1705 reinitScalars(tid);
1706
1707 if (_displaced_mesh)
1708 _displaced_problem->syncSolutions();
1709
1710 // Writes all calls to _console from initialSetup() methods
1712
1714 {
1716 for (THREAD_ID tid = 0; tid < n_threads; ++tid)
1717 for (auto & assembly : _assembly[tid])
1718 assembly->initNonlocalCoupling();
1719 }
1720
1721 {
1722 TIME_SECTION("lineSearchInitialSetup", 5, "Initializing Line Search");
1723
1724 if (_line_search)
1725 _line_search->initialSetup();
1726 }
1727
1728 // Perform Reporter get/declare check
1730
1731 // We do this late to allow objects to get late restartable data
1734
1736}
1737
1738void
1740{
1741 for (const auto & pp : _reporter_data.getPostprocessorNames())
1742 if (hasScalarVariable(pp))
1743 mooseError("Postprocessor \"" + pp +
1744 "\" has the same name as a scalar variable in the system.");
1745}
1746
1747void
1749{
1751
1752 if (_t_step > 1 && _num_grid_steps)
1753 {
1754 libMesh::MeshRefinement mesh_refinement(_mesh);
1755 std::unique_ptr<libMesh::MeshRefinement> displaced_mesh_refinement(nullptr);
1756 if (_displaced_mesh)
1757 displaced_mesh_refinement = std::make_unique<libMesh::MeshRefinement>(*_displaced_mesh);
1758
1759 for (MooseIndex(_num_grid_steps) i = 0; i < _num_grid_steps; ++i)
1760 {
1762 // If the DisplacedProblem is active, undisplace the DisplacedMesh in preparation for
1763 // refinement. We can't safely refine the DisplacedMesh directly, since the Hilbert keys
1764 // computed on the inconsistenly-displaced Mesh are different on different processors,
1765 // leading to inconsistent Hilbert keys. We must do this before the undisplaced Mesh is
1766 // coarsensed, so that the element and node numbering is still consistent. We also have to
1767 // make sure this is done during every step of coarsening otherwise different partitions
1768 // will be generated for the reference and displaced meshes (even for replicated)
1769 _displaced_problem->undisplaceMesh();
1770
1771 mesh_refinement.uniformly_coarsen();
1772 if (_displaced_mesh)
1773 displaced_mesh_refinement->uniformly_coarsen();
1774
1775 // Mark this as an intermediate change because we do not yet want to reinit_systems. E.g. we
1776 // need things to happen in the following order for the undisplaced problem:
1777 // u1) EquationSystems::reinit_solutions. This will restrict the solution vectors and then
1778 // contract the mesh
1779 // u2) MooseMesh::meshChanged. This will update the node/side lists and other
1780 // things which needs to happen after the contraction
1781 // u3) GeometricSearchData::reinit. Once the node/side lists are updated we can perform our
1782 // geometric searches which will aid in determining sparsity patterns
1783 //
1784 // We do these things for the displaced problem (if it exists)
1785 // d1) EquationSystems::reinit. Restrict the displaced problem vector copies and then contract
1786 // the mesh. It's safe to do a full reinit with the displaced because there are no
1787 // matrices that sparsity pattern calculations will be conducted for
1788 // d2) MooseMesh::meshChanged. This will update the node/side lists and other
1789 // things which needs to happen after the contraction
1790 // d3) UpdateDisplacedMeshThread::operator(). Re-displace the mesh using the *displaced*
1791 // solution vector copy because we don't know the state of the reference solution vector.
1792 // It's safe to use the displaced copy because we are outside of a non-linear solve,
1793 // and there is no concern about differences between solution and current_local_solution
1794 // d4) GeometricSearchData::reinit. With the node/side lists updated and the mesh
1795 // re-displaced, we can perform our geometric searches, which will aid in determining the
1796 // sparsity pattern of the matrix held by the libMesh::ImplicitSystem held by the
1797 // NonlinearSystem held by this
1799 /*intermediate_change=*/true, /*contract_mesh=*/true, /*clean_refinement_flags=*/true);
1800 }
1801
1802 // u4) Now that all the geometric searches have been done (both undisplaced and displaced),
1803 // we're ready to update the sparsity pattern
1804 es().reinit_systems();
1805 }
1806
1808 if (_line_search)
1809 _line_search->timestepSetup();
1810
1811 // Random interface objects
1812 for (const auto & it : _random_data_objects)
1813 it.second->updateSeeds(EXEC_TIMESTEP_BEGIN);
1814
1815 unsigned int n_threads = numThreads();
1816 for (THREAD_ID tid = 0; tid < n_threads; tid++)
1817 {
1820 }
1821
1822#ifdef MOOSE_KOKKOS_ENABLED
1824#endif
1825
1826 _aux->timestepSetup();
1827 for (auto & sys : _solver_systems)
1828 sys->timestepSetup();
1829
1831 // timestepSetup for displaced systems
1832 _displaced_problem->timestepSetup();
1833
1834 for (THREAD_ID tid = 0; tid < n_threads; tid++)
1835 {
1839 }
1840
1841 std::vector<UserObject *> userobjs;
1842 theWarehouse().query().condition<AttribSystem>("UserObject").queryIntoUnsorted(userobjs);
1843 for (auto obj : userobjs)
1844 obj->timestepSetup();
1845
1846#ifdef MOOSE_KOKKOS_ENABLED
1847 {
1848 std::vector<UserObjectBase *> userobjs;
1849 theWarehouse().query().condition<AttribSystem>("KokkosUserObject").queryIntoUnsorted(userobjs);
1850 for (auto obj : userobjs)
1851 obj->timestepSetup();
1852 }
1853#endif
1854
1855 // Timestep setup of output objects
1857
1861}
1862
1863unsigned int
1865{
1866 if (_max_qps == std::numeric_limits<unsigned int>::max())
1867 mooseError("Max QPS uninitialized");
1868 return _max_qps;
1869}
1870
1871Order
1874 return _max_scalar_order;
1875}
1876
1877void
1879{
1880 TIME_SECTION("checkNonlocalCoupling", 5, "Checking Nonlocal Coupling");
1881
1882 for (THREAD_ID tid = 0; tid < numThreads(); tid++)
1883 for (auto & nl : _nl)
1884 {
1885 const auto & all_kernels = nl->getKernelWarehouse();
1886 const auto & kernels = all_kernels.getObjects(tid);
1887 for (const auto & kernel : kernels)
1888 {
1889 std::shared_ptr<NonlocalKernel> nonlocal_kernel =
1890 std::dynamic_pointer_cast<NonlocalKernel>(kernel);
1891 if (nonlocal_kernel)
1892 {
1895 _nonlocal_kernels.addObject(kernel, tid);
1896 }
1897 }
1898 const MooseObjectWarehouse<IntegratedBCBase> & all_integrated_bcs =
1899 nl->getIntegratedBCWarehouse();
1900 const auto & integrated_bcs = all_integrated_bcs.getObjects(tid);
1901 for (const auto & integrated_bc : integrated_bcs)
1902 {
1903 std::shared_ptr<NonlocalIntegratedBC> nonlocal_integrated_bc =
1904 std::dynamic_pointer_cast<NonlocalIntegratedBC>(integrated_bc);
1905 if (nonlocal_integrated_bc)
1906 {
1909 _nonlocal_integrated_bcs.addObject(integrated_bc, tid);
1910 }
1911 }
1912 }
1913}
1914
1915void
1917{
1918 std::set<const MooseVariableFEBase *> uo_jacobian_moose_vars;
1919 {
1920 std::vector<ShapeElementUserObject *> objs;
1921 theWarehouse()
1922 .query()
1924 .condition<AttribThread>(tid)
1925 .queryInto(objs);
1926
1927 for (const auto & uo : objs)
1928 {
1929 _calculate_jacobian_in_uo = uo->computeJacobianFlag();
1930 const auto & mv_deps = uo->jacobianMooseVariables();
1931 uo_jacobian_moose_vars.insert(mv_deps.begin(), mv_deps.end());
1932 }
1933 }
1934 {
1935 std::vector<ShapeSideUserObject *> objs;
1936 theWarehouse()
1937 .query()
1939 .condition<AttribThread>(tid)
1940 .queryInto(objs);
1941 for (const auto & uo : objs)
1942 {
1943 _calculate_jacobian_in_uo = uo->computeJacobianFlag();
1944 const auto & mv_deps = uo->jacobianMooseVariables();
1945 uo_jacobian_moose_vars.insert(mv_deps.begin(), mv_deps.end());
1946 }
1947 }
1948
1949 _uo_jacobian_moose_vars[tid].assign(uo_jacobian_moose_vars.begin(), uo_jacobian_moose_vars.end());
1950 std::sort(
1951 _uo_jacobian_moose_vars[tid].begin(), _uo_jacobian_moose_vars[tid].end(), sortMooseVariables);
1952}
1953
1954void
1955FEProblemBase::setVariableAllDoFMap(const std::vector<const MooseVariableFEBase *> & moose_vars)
1956{
1957 for (unsigned int i = 0; i < moose_vars.size(); ++i)
1958 {
1959 VariableName var_name = moose_vars[i]->name();
1960 auto & sys = _solver_systems[moose_vars[i]->sys().number()];
1961 sys->setVariableGlobalDoFs(var_name);
1962 _var_dof_map[var_name] = sys->getVariableGlobalDoFs();
1963 }
1964}
1965
1966void
1967FEProblemBase::prepare(const Elem * elem, const THREAD_ID tid)
1968{
1969 for (const auto i : index_range(_solver_systems))
1970 {
1971 _assembly[tid][i]->reinit(elem);
1972 _solver_systems[i]->prepare(tid);
1973
1974 if (i < _num_nl_sys)
1975 {
1976 // This method is called outside of residual/Jacobian callbacks during initial condition
1977 // evaluation
1979 _assembly[tid][i]->prepareJacobianBlock();
1980 _assembly[tid][i]->prepareResidual();
1982 _assembly[tid][i]->prepareNonlocal();
1983 }
1984 }
1985 _aux->prepare(tid);
1986
1987 if (_displaced_problem &&
1988 // _reinit_displaced_neighbor applies to interface type objects which will do computations
1989 // based on both elem and neighbor. Consequently, despite what you might think by its name, we
1990 // must make sure we prepare the displaced elem
1992 {
1993 _displaced_problem->prepare(_displaced_mesh->elemPtr(elem->id()), tid);
1995 _displaced_problem->prepareNonlocal(tid);
1996 }
1997}
1998
1999void
2000FEProblemBase::prepareFace(const Elem * elem, const THREAD_ID tid)
2001{
2002 for (auto & nl : _nl)
2003 nl->prepareFace(tid, true);
2004 _aux->prepareFace(tid, false);
2005
2007 _displaced_problem->prepareFace(_displaced_mesh->elemPtr(elem->id()), tid);
2008}
2009
2010void
2011FEProblemBase::prepare(const Elem * elem,
2012 unsigned int ivar,
2013 unsigned int jvar,
2014 const std::vector<dof_id_type> & dof_indices,
2015 const THREAD_ID tid)
2016{
2017 for (const auto i : index_range(_nl))
2018 {
2019 _assembly[tid][i]->reinit(elem);
2020 _nl[i]->prepare(tid);
2021 }
2022
2023 _aux->prepare(tid);
2024 const auto current_nl_sys_num = _current_nl_sys->number();
2025 _assembly[tid][current_nl_sys_num]->prepareBlock(ivar, jvar, dof_indices);
2027 if (_nonlocal_cm[current_nl_sys_num](ivar, jvar) != 0)
2028 {
2030 _assembly[tid][current_nl_sys_num]->prepareBlockNonlocal(
2031 ivar, jvar, dof_indices, jv.allDofIndices());
2032 }
2033
2035 {
2036 _displaced_problem->prepare(_displaced_mesh->elemPtr(elem->id()), ivar, jvar, dof_indices, tid);
2038 if (_nonlocal_cm[current_nl_sys_num](ivar, jvar) != 0)
2039 {
2041 _displaced_problem->prepareBlockNonlocal(ivar, jvar, dof_indices, jv.allDofIndices(), tid);
2042 }
2043 }
2044}
2045
2046void
2048{
2049 SubdomainID did = elem->subdomain_id();
2050 for (const auto i : index_range(_solver_systems))
2051 {
2052 _assembly[tid][i]->setCurrentSubdomainID(did);
2053 if (_displaced_problem &&
2055 _displaced_problem->assembly(tid, i).setCurrentSubdomainID(did);
2056 }
2057}
2058
2059void
2060FEProblemBase::setNeighborSubdomainID(const Elem * elem, unsigned int side, const THREAD_ID tid)
2061{
2062 SubdomainID did = elem->neighbor_ptr(side)->subdomain_id();
2063 for (const auto i : index_range(_nl))
2064 {
2065 _assembly[tid][i]->setCurrentNeighborSubdomainID(did);
2066 if (_displaced_problem &&
2068 _displaced_problem->assembly(tid, i).setCurrentNeighborSubdomainID(did);
2069 }
2070}
2071
2072void
2074{
2075 SubdomainID did = elem->subdomain_id();
2076 for (const auto i : index_range(_nl))
2077 {
2078 _assembly[tid][i]->setCurrentNeighborSubdomainID(did);
2079 if (_displaced_problem &&
2081 _displaced_problem->assembly(tid, i).setCurrentNeighborSubdomainID(did);
2082 }
2083}
2084
2085void
2087{
2090 _assembly[tid][_current_nl_sys->number()]->prepareNonlocal();
2091
2092 if (_displaced_problem &&
2094 {
2095 _displaced_problem->prepareAssembly(tid);
2097 _displaced_problem->prepareNonlocal(tid);
2098 }
2099}
2100
2101void
2103{
2104 _assembly[tid][_current_nl_sys->number()]->prepareNeighbor();
2105
2107 _displaced_problem->prepareAssemblyNeighbor(tid);
2108}
2109
2110void
2112{
2115
2117 _displaced_problem->addResidual(tid);
2118}
2119
2120void
2122{
2123 _assembly[tid][_current_nl_sys->number()]->addResidualNeighbor(Assembly::GlobalDataKey{},
2125
2127 _displaced_problem->addResidualNeighbor(tid);
2128}
2129
2130void
2132{
2133 _assembly[tid][_current_nl_sys->number()]->addResidualLower(Assembly::GlobalDataKey{},
2135
2137 _displaced_problem->addResidualLower(tid);
2138}
2139
2140void
2142{
2143 _assembly[tid][_current_nl_sys->number()]->addResidualScalar(Assembly::GlobalDataKey{},
2145}
2146
2147void
2149{
2152 _displaced_problem->cacheResidual(tid);
2153}
2154
2155void
2157{
2160 _displaced_problem->cacheResidualNeighbor(tid);
2161}
2162
2163void
2165{
2168 _displaced_problem->addCachedResidual(tid);
2169}
2170
2171void
2172FEProblemBase::addCachedResidualDirectly(NumericVector<Number> & residual, const THREAD_ID tid)
2173{
2175 _assembly[tid][_current_nl_sys->number()]->addCachedResidualDirectly(
2177
2179 _assembly[tid][_current_nl_sys->number()]->addCachedResidualDirectly(
2181
2182 std::vector<VectorTag> extra_residual_vector_tags;
2183 extra_residual_vector_tags.reserve(currentResidualVectorTags().size());
2184 const auto time_tag = _current_nl_sys->timeVectorTag();
2185 const auto non_time_tag = _current_nl_sys->nonTimeVectorTag();
2186 for (const auto & vector_tag : currentResidualVectorTags())
2187 if (vector_tag._id != time_tag && vector_tag._id != non_time_tag)
2188 extra_residual_vector_tags.push_back(vector_tag);
2189
2190 // Flush extra vector tag caches (e.g. from extra_vector_tags on NodalConstraints)
2191 // to their respective system vectors after the standard TIME/NONTIME caches above.
2192 // Without this, NodalConstraint contributions to extra vector tags are silently
2193 // discarded by the blanket clearCachedResiduals.
2194 _assembly[tid][_current_nl_sys->number()]->addCachedResiduals(Assembly::GlobalDataKey{},
2195 extra_residual_vector_tags);
2196
2197 // We do this because by adding the cached residual directly, we cannot ensure that all of the
2198 // cached residuals are emptied after only the two add calls above
2199 _assembly[tid][_current_nl_sys->number()]->clearCachedResiduals(Assembly::GlobalDataKey{});
2200
2202 _displaced_problem->addCachedResidualDirectly(residual, tid);
2203}
2204
2205void
2206FEProblemBase::setResidual(NumericVector<Number> & residual, const THREAD_ID tid)
2207{
2208 _assembly[tid][_current_nl_sys->number()]->setResidual(
2209 residual,
2211 getVectorTag(_nl[_current_nl_sys->number()]->residualVectorTag()));
2213 _displaced_problem->setResidual(residual, tid);
2214}
2215
2216void
2217FEProblemBase::setResidualNeighbor(NumericVector<Number> & residual, const THREAD_ID tid)
2218{
2219 _assembly[tid][_current_nl_sys->number()]->setResidualNeighbor(
2222 _displaced_problem->setResidualNeighbor(residual, tid);
2223}
2224
2225void
2227{
2230 _assembly[tid][_current_nl_sys->number()]->addJacobianNonlocal(Assembly::GlobalDataKey{});
2232 {
2233 _displaced_problem->addJacobian(tid);
2235 _displaced_problem->addJacobianNonlocal(tid);
2236 }
2237}
2238
2239void
2241{
2242 _assembly[tid][_current_nl_sys->number()]->addJacobianNeighbor(Assembly::GlobalDataKey{});
2244 _displaced_problem->addJacobianNeighbor(tid);
2245}
2246
2247void
2249{
2250 _assembly[tid][_current_nl_sys->number()]->addJacobianNeighborLowerD(Assembly::GlobalDataKey{});
2252 _displaced_problem->addJacobianNeighborLowerD(tid);
2253}
2254
2255void
2257{
2258 _assembly[tid][_current_nl_sys->number()]->addJacobianLowerD(Assembly::GlobalDataKey{});
2260 _displaced_problem->addJacobianLowerD(tid);
2261}
2262
2263void
2265{
2266 _assembly[tid][_current_nl_sys->number()]->addJacobianScalar(Assembly::GlobalDataKey{});
2267}
2268
2269void
2270FEProblemBase::addJacobianOffDiagScalar(unsigned int ivar, const THREAD_ID tid /* = 0*/)
2271{
2272 _assembly[tid][_current_nl_sys->number()]->addJacobianOffDiagScalar(ivar,
2274}
2275
2276void
2278{
2281 _displaced_problem->cacheJacobian(tid);
2282}
2283
2284void
2286{
2289 _displaced_problem->cacheJacobianNeighbor(tid);
2290}
2291
2292void
2294{
2297 _displaced_problem->addCachedJacobian(tid);
2298}
2299
2300void
2301FEProblemBase::addJacobianBlockTags(SparseMatrix<Number> & jacobian,
2302 unsigned int ivar,
2303 unsigned int jvar,
2304 const DofMap & dof_map,
2305 std::vector<dof_id_type> & dof_indices,
2306 const std::set<TagID> & tags,
2307 const THREAD_ID tid)
2308{
2309 _assembly[tid][_current_nl_sys->number()]->addJacobianBlockTags(
2310 jacobian, ivar, jvar, dof_map, dof_indices, Assembly::GlobalDataKey{}, tags);
2311
2313 if (_nonlocal_cm[_current_nl_sys->number()](ivar, jvar) != 0)
2314 {
2316 _assembly[tid][_current_nl_sys->number()]->addJacobianBlockNonlocalTags(
2317 jacobian,
2318 ivar,
2319 jvar,
2320 dof_map,
2321 dof_indices,
2322 jv.allDofIndices(),
2324 tags);
2325 }
2326
2328 {
2329 _displaced_problem->addJacobianBlockTags(jacobian, ivar, jvar, dof_map, dof_indices, tags, tid);
2331 if (_nonlocal_cm[_current_nl_sys->number()](ivar, jvar) != 0)
2332 {
2334 _displaced_problem->addJacobianBlockNonlocal(
2335 jacobian, ivar, jvar, dof_map, dof_indices, jv.allDofIndices(), tags, tid);
2336 }
2337 }
2338}
2339
2340void
2341FEProblemBase::addJacobianNeighbor(SparseMatrix<Number> & jacobian,
2342 unsigned int ivar,
2343 unsigned int jvar,
2344 const DofMap & dof_map,
2345 std::vector<dof_id_type> & dof_indices,
2346 std::vector<dof_id_type> & neighbor_dof_indices,
2347 const std::set<TagID> & tags,
2348 const THREAD_ID tid)
2349{
2350 _assembly[tid][_current_nl_sys->number()]->addJacobianNeighborTags(jacobian,
2351 ivar,
2352 jvar,
2353 dof_map,
2354 dof_indices,
2355 neighbor_dof_indices,
2357 tags);
2359 _displaced_problem->addJacobianNeighbor(
2360 jacobian, ivar, jvar, dof_map, dof_indices, neighbor_dof_indices, tags, tid);
2361}
2362
2363void
2364FEProblemBase::prepareShapes(unsigned int var, const THREAD_ID tid)
2365{
2366 _assembly[tid][_current_nl_sys->number()]->copyShapes(var);
2367}
2368
2369void
2371{
2372 _assembly[tid][_current_nl_sys->number()]->copyFaceShapes(var);
2373}
2374
2375void
2377{
2378 _assembly[tid][_current_nl_sys->number()]->copyNeighborShapes(var);
2379}
2380
2381void
2383{
2384 if (_mesh.elemPtr(elem_id)->processor_id() != processor_id())
2385 _ghosted_elems.insert(elem_id);
2386}
2387
2388void
2395
2396void
2398{
2399 TIME_SECTION("ghostGhostedBoundaries", 3, "Ghosting Ghosted Boundaries");
2400
2402
2405}
2406
2407void
2408FEProblemBase::sizeZeroes(unsigned int /*size*/, const THREAD_ID /*tid*/)
2409{
2410 mooseDoOnce(mooseWarning(
2411 "This function is deprecated and no longer performs any function. Please do not call it."));
2412}
2413
2414bool
2415FEProblemBase::reinitDirac(const Elem * elem, const THREAD_ID tid)
2416{
2417 std::vector<Point> & points = _dirac_kernel_info.getPoints()[elem].first;
2418
2419 unsigned int n_points = points.size();
2420
2421 if (n_points)
2422 {
2423 if (n_points > _max_qps)
2424 {
2425 _max_qps = n_points;
2426
2431 unsigned int max_qpts = getMaxQps();
2432 for (unsigned int tid = 0; tid < numThreads(); ++tid)
2433 {
2434 // the highest available order in libMesh is 43
2435 _scalar_zero[tid].resize(libMesh::FORTYTHIRD, 0);
2436 _zero[tid].resize(max_qpts, 0);
2437 _grad_zero[tid].resize(max_qpts, RealGradient(0.));
2438 _second_zero[tid].resize(max_qpts, RealTensor(0.));
2439 _vector_zero[tid].resize(max_qpts, RealGradient(0.));
2440 _vector_curl_zero[tid].resize(max_qpts, RealGradient(0.));
2441 }
2442 }
2443
2444 for (const auto i : index_range(_nl))
2445 {
2446 _assembly[tid][i]->reinitAtPhysical(elem, points);
2447 _nl[i]->prepare(tid);
2448 }
2449 _aux->prepare(tid);
2450
2451 reinitElem(elem, tid);
2452 }
2453
2454 _assembly[tid][_current_nl_sys->number()]->prepare();
2456 _assembly[tid][_current_nl_sys->number()]->prepareNonlocal();
2457
2458 bool have_points = n_points > 0;
2460 {
2461 have_points |= _displaced_problem->reinitDirac(_displaced_mesh->elemPtr(elem->id()), tid);
2463 _displaced_problem->prepareNonlocal(tid);
2464 }
2465
2466 return have_points;
2467}
2468
2469void
2470FEProblemBase::reinitElem(const Elem * elem, const THREAD_ID tid)
2471{
2472 for (auto & sys : _solver_systems)
2473 sys->reinitElem(elem, tid);
2474 _aux->reinitElem(elem, tid);
2475
2477 _displaced_problem->reinitElem(_displaced_mesh->elemPtr(elem->id()), tid);
2478}
2479
2480void
2481FEProblemBase::reinitElemPhys(const Elem * const elem,
2482 const std::vector<Point> & phys_points_in_elem,
2483 const THREAD_ID tid)
2484{
2485 mooseAssert(_mesh.queryElemPtr(elem->id()) == elem,
2486 "Are you calling this method with a displaced mesh element?");
2487
2488 for (const auto i : index_range(_solver_systems))
2489 {
2490 _assembly[tid][i]->reinitAtPhysical(elem, phys_points_in_elem);
2491 _solver_systems[i]->prepare(tid);
2492 _assembly[tid][i]->prepare();
2494 _assembly[tid][i]->prepareNonlocal();
2495 }
2496 _aux->prepare(tid);
2497
2498 reinitElem(elem, tid);
2499}
2500
2501void
2502FEProblemBase::reinitElemFace(const Elem * const elem,
2503 const unsigned int side,
2504 const BoundaryID,
2505 const THREAD_ID tid)
2506{
2508 "reinitElemFace with a BoundaryID argument is deprecated because the boundary id was never "
2509 "used. Please call reinitElemFace without the BoundaryID argument instead");
2510
2511 reinitElemFace(elem, side, tid);
2512}
2513
2514void
2515FEProblemBase::reinitElemFace(const Elem * const elem, const unsigned int side, const THREAD_ID tid)
2516{
2517 for (const auto i : index_range(_solver_systems))
2518 {
2519 _assembly[tid][i]->reinit(elem, side);
2520 _solver_systems[i]->reinitElemFace(elem, side, tid);
2521 }
2522 _aux->reinitElemFace(elem, side, tid);
2523
2525 _displaced_problem->reinitElemFace(_displaced_mesh->elemPtr(elem->id()), side, tid);
2526}
2527
2528void
2529FEProblemBase::reinitLowerDElem(const Elem * lower_d_elem,
2530 const THREAD_ID tid,
2531 const std::vector<Point> * const pts,
2532 const std::vector<Real> * const weights)
2533{
2534 SubProblem::reinitLowerDElem(lower_d_elem, tid, pts, weights);
2535
2537 _displaced_problem->reinitLowerDElem(
2538 _displaced_mesh->elemPtr(lower_d_elem->id()), tid, pts, weights);
2539}
2540
2541void
2542FEProblemBase::reinitNode(const Node * node, const THREAD_ID tid)
2543{
2545 _displaced_problem->reinitNode(&_displaced_mesh->nodeRef(node->id()), tid);
2546
2547 for (const auto i : index_range(_nl))
2548 {
2549 _assembly[tid][i]->reinit(node);
2550 _nl[i]->reinitNode(node, tid);
2551 }
2552 _aux->reinitNode(node, tid);
2553}
2554
2555void
2556FEProblemBase::reinitNodeFace(const Node * node, BoundaryID bnd_id, const THREAD_ID tid)
2557{
2559 _displaced_problem->reinitNodeFace(&_displaced_mesh->nodeRef(node->id()), bnd_id, tid);
2560
2561 for (const auto i : index_range(_nl))
2562 {
2563 _assembly[tid][i]->reinit(node);
2564 _nl[i]->reinitNodeFace(node, bnd_id, tid);
2565 }
2566 _aux->reinitNodeFace(node, bnd_id, tid);
2567}
2568
2569void
2570FEProblemBase::reinitScalars(const THREAD_ID tid, bool reinit_for_derivative_reordering /*=false*/)
2571{
2572 TIME_SECTION("reinitScalars", 3, "Reinitializing Scalar Variables");
2573
2575 _displaced_problem->reinitScalars(tid, reinit_for_derivative_reordering);
2576
2577 for (auto & nl : _nl)
2578 nl->reinitScalars(tid, reinit_for_derivative_reordering);
2579 _aux->reinitScalars(tid, reinit_for_derivative_reordering);
2580
2581 // This is called outside of residual/Jacobian call-backs
2582 for (auto & assembly : _assembly[tid])
2584}
2585
2586void
2588{
2589 _assembly[tid][_current_nl_sys->number()]->prepareOffDiagScalar();
2591 _displaced_problem->reinitOffDiagScalars(tid);
2592}
2593
2594void
2595FEProblemBase::reinitNeighbor(const Elem * elem, unsigned int side, const THREAD_ID tid)
2596{
2597 setNeighborSubdomainID(elem, side, tid);
2598
2599 const Elem * neighbor = elem->neighbor_ptr(side);
2600 unsigned int neighbor_side = neighbor->which_neighbor_am_i(elem);
2601
2602 for (const auto i : index_range(_nl))
2603 {
2604 _assembly[tid][i]->reinitElemAndNeighbor(elem, side, neighbor, neighbor_side);
2605 _nl[i]->prepareNeighbor(tid);
2606 // Called during stateful material property evaluation outside of solve
2607 _assembly[tid][i]->prepareNeighbor();
2608 }
2609 _aux->prepareNeighbor(tid);
2610
2611 for (auto & nl : _nl)
2612 {
2613 nl->reinitElemFace(elem, side, tid);
2614 nl->reinitNeighborFace(neighbor, neighbor_side, tid);
2615 }
2616 _aux->reinitElemFace(elem, side, tid);
2617 _aux->reinitNeighborFace(neighbor, neighbor_side, tid);
2618
2620 {
2621 // There are cases like for cohesive zone modeling without significant sliding where we cannot
2622 // use FEInterface::inverse_map in Assembly::reinitElemAndNeighbor in the displaced problem
2623 // because the physical points coming from the element don't actually lie on the neighbor.
2624 // Moreover, what's the point of doing another physical point inversion in other cases? We only
2625 // care about the reference points which we can just take from the undisplaced computation
2626 const auto & displaced_ref_pts = _assembly[tid][0]->qRuleNeighbor()->get_points();
2627
2628 _displaced_problem->reinitNeighbor(
2629 _displaced_mesh->elemPtr(elem->id()), side, tid, &displaced_ref_pts);
2630 }
2631}
2632
2633void
2635 unsigned int side,
2636 const THREAD_ID tid)
2637{
2638 reinitNeighbor(elem, side, tid);
2639
2640 const Elem * lower_d_elem = _mesh.getLowerDElem(elem, side);
2641 if (lower_d_elem && _mesh.interiorLowerDBlocks().count(lower_d_elem->subdomain_id()) > 0)
2642 reinitLowerDElem(lower_d_elem, tid);
2643 else
2644 {
2645 // with mesh refinement, lower-dimensional element might be defined on neighbor side
2646 auto & neighbor = _assembly[tid][0]->neighbor();
2647 auto & neighbor_side = _assembly[tid][0]->neighborSide();
2648 const Elem * lower_d_elem_neighbor = _mesh.getLowerDElem(neighbor, neighbor_side);
2649 if (lower_d_elem_neighbor &&
2650 _mesh.interiorLowerDBlocks().count(lower_d_elem_neighbor->subdomain_id()) > 0)
2651 {
2652 auto qps = _assembly[tid][0]->qPointsFaceNeighbor().stdVector();
2653 std::vector<Point> reference_points;
2654 FEMap::inverse_map(
2655 lower_d_elem_neighbor->dim(), lower_d_elem_neighbor, qps, reference_points);
2656 reinitLowerDElem(lower_d_elem_neighbor, tid, &reference_points);
2657 }
2658 }
2659
2661 _displaced_problem->reinitElemNeighborAndLowerD(
2662 _displaced_mesh->elemPtr(elem->id()), side, tid);
2663}
2664
2665void
2667 unsigned int neighbor_side,
2668 const std::vector<Point> & physical_points,
2669 const THREAD_ID tid)
2670{
2671 mooseAssert(_mesh.queryElemPtr(neighbor->id()) == neighbor,
2672 "Are you calling this method with a displaced mesh element?");
2673
2674 for (const auto i : index_range(_nl))
2675 {
2676 // Reinits shape the functions at the physical points
2677 _assembly[tid][i]->reinitNeighborAtPhysical(neighbor, neighbor_side, physical_points);
2678
2679 // Sets the neighbor dof indices
2680 _nl[i]->prepareNeighbor(tid);
2681 }
2682 _aux->prepareNeighbor(tid);
2683
2684 // Resizes Re and Ke
2685 _assembly[tid][_current_nl_sys->number()]->prepareNeighbor();
2686
2687 // Compute the values of each variable at the points
2688 for (auto & nl : _nl)
2689 nl->reinitNeighborFace(neighbor, neighbor_side, tid);
2690 _aux->reinitNeighborFace(neighbor, neighbor_side, tid);
2691}
2692
2693void
2695 const std::vector<Point> & physical_points,
2696 const THREAD_ID tid)
2697{
2698 mooseAssert(_mesh.queryElemPtr(neighbor->id()) == neighbor,
2699 "Are you calling this method with a displaced mesh element?");
2700
2701 for (const auto i : index_range(_nl))
2702 {
2703 // Reinits shape the functions at the physical points
2704 _assembly[tid][i]->reinitNeighborAtPhysical(neighbor, physical_points);
2705
2706 // Sets the neighbor dof indices
2707 _nl[i]->prepareNeighbor(tid);
2708 }
2709 _aux->prepareNeighbor(tid);
2710
2711 // Resizes Re and Ke
2712 _assembly[tid][_current_nl_sys->number()]->prepareNeighbor();
2713
2714 // Compute the values of each variable at the points
2715 for (auto & nl : _nl)
2716 nl->reinitNeighbor(neighbor, tid);
2717 _aux->reinitNeighbor(neighbor, tid);
2718}
2719
2720void
2721FEProblemBase::getDiracElements(std::set<const Elem *> & elems)
2722{
2723 // First add in the undisplaced elements
2725
2727 {
2728 std::set<const Elem *> displaced_elements;
2729 _displaced_problem->getDiracElements(displaced_elements);
2730
2731 { // Use the ids from the displaced elements to get the undisplaced elements
2732 // and add them to the list
2733 for (const auto & elem : displaced_elements)
2734 elems.insert(_mesh.elemPtr(elem->id()));
2735 }
2736 }
2737}
2738
2739void
2741{
2743
2745 _displaced_problem->clearDiracInfo();
2746}
2747
2748void
2750{
2751 _all_materials.subdomainSetup(subdomain, tid);
2752 // Call the subdomain methods of the output system, these are not threaded so only call it once
2753 if (tid == 0)
2755
2756 for (auto & nl : _nl)
2757 nl->subdomainSetup(subdomain, tid);
2758
2759 // FIXME: call displaced_problem->subdomainSetup() ?
2760 // When adding possibility with materials being evaluated on displaced mesh
2761}
2762
2763void
2768
2769void
2770FEProblemBase::addFunction(const std::string & type,
2771 const std::string & name,
2772 InputParameters & parameters)
2773{
2774#ifdef MOOSE_KOKKOS_ENABLED
2777#endif
2778
2779 parallel_object_only();
2780
2781 parameters.set<SubProblem *>("_subproblem") = this;
2782
2783 for (THREAD_ID tid = 0; tid < numThreads(); tid++)
2784 {
2785 std::shared_ptr<Function> func = _factory.create<Function>(type, name, parameters, tid);
2786 logAdd("Function", name, type, parameters);
2787 _functions.addObject(func, tid);
2788
2789 if (auto * const functor = dynamic_cast<Moose::FunctorBase<Real> *>(func.get()))
2790 {
2791 this->addFunctor(name, *functor, tid);
2793 _displaced_problem->addFunctor(name, *functor, tid);
2794 }
2795 else
2796 mooseError("Unrecognized function functor type");
2797 }
2798}
2799
2800void
2801FEProblemBase::addConvergence(const std::string & type,
2802 const std::string & name,
2803 InputParameters & parameters)
2804{
2805 parallel_object_only();
2806
2807 for (THREAD_ID tid = 0; tid < numThreads(); tid++)
2808 {
2809 std::shared_ptr<Convergence> conv = _factory.create<Convergence>(type, name, parameters, tid);
2810 _convergences.addObject(conv, tid);
2811 }
2812}
2813
2814void
2816{
2817 const std::string class_name = "DefaultNonlinearConvergence";
2818 InputParameters params = _factory.getValidParams(class_name);
2819 params.applyParameters(params_to_apply);
2820 params.applyParameters(parameters());
2821 params.set<bool>("added_as_default") = true;
2822 for (const auto & conv_name : getNonlinearConvergenceNames())
2823 addConvergence(class_name, conv_name, params);
2824}
2825
2826void
2828{
2829 const std::string class_name = "DefaultMultiAppFixedPointConvergence";
2830 InputParameters params = _factory.getValidParams(class_name);
2831 params.applyParameters(params_to_apply);
2832 params.applyParameters(parameters());
2833 params.set<bool>("added_as_default") = true;
2835}
2836
2837void
2839{
2840 const std::string class_name = "DefaultSteadyStateConvergence";
2841 InputParameters params = _factory.getValidParams(class_name);
2842 params.applyParameters(params_to_apply);
2843 params.applyParameters(parameters());
2844 params.set<bool>("added_as_default") = true;
2845 addConvergence(class_name, getSteadyStateConvergenceName(), params);
2846}
2847
2848bool
2849FEProblemBase::hasFunction(const std::string & name, const THREAD_ID tid)
2850{
2851 return _functions.hasActiveObject(name, tid);
2852}
2853
2854Function &
2855FEProblemBase::getFunction(const std::string & name, const THREAD_ID tid)
2856{
2857 // This thread lock is necessary since this method will create functions
2858 // for all threads if one is missing.
2859 Threads::spin_mutex::scoped_lock lock(get_function_mutex);
2860
2861 if (!hasFunction(name, tid))
2862 {
2863 // If we didn't find a function, it might be a default function, attempt to construct one now
2864 std::istringstream ss(name);
2865 Real real_value;
2866
2867 // First see if it's just a constant. If it is, build a ConstantFunction
2868 if (ss >> real_value && ss.eof())
2869 {
2870 InputParameters params = _factory.getValidParams("ConstantFunction");
2871 params.set<Real>("value") = real_value;
2872 addFunction("ConstantFunction", ss.str(), params);
2873 }
2874 else
2875 {
2877 std::string vars = "x,y,z,t,NaN,pi,e";
2878 if (fp.Parse(name, vars) == -1) // -1 for success
2879 {
2880 // It parsed ok, so build a MooseParsedFunction
2881 InputParameters params = _factory.getValidParams("ParsedFunction");
2882 params.set<std::string>("expression") = name;
2883 addFunction("ParsedFunction", name, params);
2884 }
2885 }
2886
2887 // Try once more
2888 if (!hasFunction(name, tid))
2889 {
2890 mooseAssert(getMooseApp().actionWarehouse().isTaskComplete("add_function"),
2891 "getFunction() was called before Functions have been constructed. The requested "
2892 "Function '" +
2893 name + "' may exist in the input file, but Functions are not available yet.");
2894
2895 mooseError("Unable to find function " + name);
2896 }
2897 }
2898
2899 auto * const ret = dynamic_cast<Function *>(_functions.getActiveObject(name, tid).get());
2900 if (!ret)
2901 mooseError("No function named ", name, " of appropriate type");
2902
2903 return *ret;
2904}
2905
2906bool
2907FEProblemBase::hasConvergence(const std::string & name, const THREAD_ID tid) const
2908{
2909 return _convergences.hasActiveObject(name, tid);
2910}
2911
2913FEProblemBase::getConvergence(const std::string & name, const THREAD_ID tid) const
2914{
2915 auto * const ret = dynamic_cast<Convergence *>(_convergences.getActiveObject(name, tid).get());
2916 if (!ret)
2917 mooseError("The Convergence object '", name, "' does not exist.");
2918
2919 return *ret;
2920}
2921
2922const std::vector<std::shared_ptr<Convergence>> &
2927
2928void
2929FEProblemBase::addMeshDivision(const std::string & type,
2930 const std::string & name,
2931 InputParameters & parameters)
2932{
2933 parallel_object_only();
2934 parameters.set<FEProblemBase *>("_fe_problem_base") = this;
2935 parameters.set<SubProblem *>("_subproblem") = this;
2936 for (THREAD_ID tid = 0; tid < numThreads(); tid++)
2937 {
2938 std::shared_ptr<MeshDivision> func = _factory.create<MeshDivision>(type, name, parameters, tid);
2939 _mesh_divisions.addObject(func, tid);
2940 }
2941}
2942
2944FEProblemBase::getMeshDivision(const std::string & name, const THREAD_ID tid) const
2945{
2946 auto * const ret = dynamic_cast<MeshDivision *>(_mesh_divisions.getActiveObject(name, tid).get());
2947 if (!ret)
2948 mooseError("No MeshDivision object named ", name, " of appropriate type");
2949 return *ret;
2950}
2951
2952void
2954{
2955 _line_search->lineSearch();
2956}
2957
2959FEProblemBase::getNonlinearSystem(const unsigned int sys_num)
2960{
2961 mooseDeprecated("FEProblemBase::getNonlinearSystem() is deprecated, please use "
2962 "FEProblemBase::getNonlinearSystemBase() \n");
2963
2964 mooseAssert(sys_num < _nl.size(), "System number greater than the number of nonlinear systems");
2965 auto nl_sys = std::dynamic_pointer_cast<NonlinearSystem>(_nl[sys_num]);
2966
2967 if (!nl_sys)
2968 mooseError("This is not a NonlinearSystem");
2969
2970 return *nl_sys;
2971}
2972
2973void
2974FEProblemBase::addDistribution(const std::string & type,
2975 const std::string & name,
2976 InputParameters & parameters)
2977{
2978 parameters.set<std::string>("type") = type;
2979 addObject<Distribution>(type, name, parameters, /* threaded = */ false);
2980}
2981
2982bool
2983FEProblemBase::hasDistribution(const std::string & name) const
2984{
2985 std::vector<Distribution *> objs;
2986 theWarehouse()
2987 .query()
2988 .condition<AttribSystem>("Distribution")
2989 .condition<AttribName>(name)
2990 .queryInto(objs);
2991 return !objs.empty();
2992}
2993
2995FEProblemBase::getDistribution(const std::string & name)
2996{
2997 std::vector<Distribution *> objs;
2998 theWarehouse()
2999 .query()
3000 .condition<AttribSystem>("Distribution")
3001 .condition<AttribName>(name)
3002 .queryInto(objs);
3003 if (objs.empty())
3004 {
3005 mooseAssert(getMooseApp().actionWarehouse().isTaskComplete("add_distribution"),
3006 "A Distribution getter was called before Distributions have been constructed. "
3007 "If you are attempting to access this object in the constructor of another object "
3008 "then make sure that the Distribution is constructed before the object using it.");
3009 mooseError("Unable to find Distribution with name '" + name + "'");
3010 }
3011 return *(objs[0]);
3012}
3013
3014void
3015FEProblemBase::addSampler(const std::string & type,
3016 const std::string & name,
3017 InputParameters & parameters)
3018{
3019 const auto samplers = addObject<Sampler>(type, name, parameters);
3020 for (auto & sampler : samplers)
3021 sampler->init();
3022}
3023
3024Sampler &
3025FEProblemBase::getSampler(const std::string & name, const THREAD_ID tid)
3026{
3027 std::vector<Sampler *> objs;
3028 theWarehouse()
3029 .query()
3030 .condition<AttribSystem>("Sampler")
3031 .condition<AttribThread>(tid)
3032 .condition<AttribName>(name)
3033 .queryInto(objs);
3034 if (objs.empty())
3035 {
3036 mooseAssert(getMooseApp().actionWarehouse().isTaskComplete("add_sampler"),
3037 "A Sampler getter was called before Samplers have been constructed. "
3038 "If you are attempting to access this object in the constructor of another object "
3039 "then make sure that the Sampler is constructed before the object using it.");
3040
3041 mooseError(
3042 "Unable to find Sampler with name '" + name +
3043 "', if you are attempting to access this object in the constructor of another object then "
3044 "make sure that the Sampler is constructed before the object using it.");
3045 }
3046 return *(objs[0]);
3047}
3048
3049bool
3050FEProblemBase::duplicateVariableCheck(const std::string & var_name,
3051 const FEType & type,
3052 bool is_aux,
3053 const std::set<SubdomainID> * const active_subdomains)
3054{
3055 std::set<SubdomainID> subdomainIDs;
3056 if (active_subdomains->size() == 0)
3057 {
3058 const auto subdomains = _mesh.meshSubdomains();
3059 subdomainIDs.insert(subdomains.begin(), subdomains.end());
3060 }
3061 else
3062 subdomainIDs.insert(active_subdomains->begin(), active_subdomains->end());
3063
3064 for (auto & sys : _solver_systems)
3065 {
3066 SystemBase * curr_sys_ptr = sys.get();
3067 SystemBase * other_sys_ptr = _aux.get();
3068 std::string error_prefix = "";
3069 if (is_aux)
3070 {
3071 curr_sys_ptr = _aux.get();
3072 other_sys_ptr = sys.get();
3073 error_prefix = "aux";
3074 }
3075
3076 if (other_sys_ptr->hasVariable(var_name))
3077 mooseError("Cannot have an auxiliary variable and a solver variable with the same name: ",
3078 var_name);
3079
3080 if (curr_sys_ptr->hasVariable(var_name))
3081 {
3082 const libMesh::Variable & var =
3083 curr_sys_ptr->system().variable(curr_sys_ptr->system().variable_number(var_name));
3084
3085 // variable type
3086 if (var.type() != type)
3087 mooseError("Mismatching types are specified for ",
3088 error_prefix,
3089 "variable with name '",
3090 var_name,
3091 "': '",
3092 Moose::stringify(var.type()),
3093 "' and '",
3095 "'");
3096
3097 // block-restriction
3098 if (!(active_subdomains->size() == 0 && var.active_subdomains().size() == 0))
3099 {
3100 const auto varActiveSubdomains = var.active_subdomains();
3101 std::set<SubdomainID> varSubdomainIDs;
3102 if (varActiveSubdomains.size() == 0)
3103 {
3104 const auto subdomains = _mesh.meshSubdomains();
3105 varSubdomainIDs.insert(subdomains.begin(), subdomains.end());
3106 }
3107 else
3108 varSubdomainIDs.insert(varActiveSubdomains.begin(), varActiveSubdomains.end());
3109
3110 // Is subdomainIDs a subset of varSubdomainIDs? With this we allow the case that the newly
3111 // requested block restriction is only a subset of the existing one.
3112 const auto isSubset = std::includes(varSubdomainIDs.begin(),
3113 varSubdomainIDs.end(),
3114 subdomainIDs.begin(),
3115 subdomainIDs.end());
3116
3117 if (!isSubset)
3118 {
3119 // helper function: make a string from a set of subdomain ids
3120 const auto stringifySubdomains = [this](std::set<SubdomainID> subdomainIDs)
3121 {
3122 std::stringstream s;
3123 for (auto const i : subdomainIDs)
3124 {
3125 // do we need to insert a comma?
3126 if (s.tellp() != 0)
3127 s << ", ";
3128
3129 // insert subdomain name and id -or- only the id (if no name is given)
3130 const auto subdomainName = _mesh.getSubdomainName(i);
3131 if (subdomainName.empty())
3132 s << i;
3133 else
3134 s << subdomainName << " (" << i << ")";
3135 }
3136 return s.str();
3137 };
3138
3139 const std::string msg = "Mismatching block-restrictions are specified for " +
3140 error_prefix + "variable with name '" + var_name + "': {" +
3141 stringifySubdomains(varSubdomainIDs) + "} and {" +
3142 stringifySubdomains(subdomainIDs) + "}";
3143
3144 mooseError(msg);
3145 }
3146 }
3147
3148 return true;
3149 }
3150 }
3151
3152 return false;
3153}
3154
3155void
3156FEProblemBase::addVariable(const std::string & var_type,
3157 const std::string & var_name,
3158 InputParameters & params)
3159{
3160 parallel_object_only();
3161
3162 const auto fe_type = MooseUtils::variableFEType(params);
3163
3164 const auto active_subdomains_vector =
3165 _mesh.getSubdomainIDs(params.get<std::vector<SubdomainName>>("block"));
3166 const std::set<SubdomainID> active_subdomains(active_subdomains_vector.begin(),
3167 active_subdomains_vector.end());
3168
3169 if (duplicateVariableCheck(var_name, fe_type, /* is_aux = */ false, &active_subdomains))
3170 return;
3171
3172 params.set<FEProblemBase *>("_fe_problem_base") = this;
3174 SolverSystemName sys_name = params.get<SolverSystemName>("solver_sys");
3175
3176 const auto solver_system_number = solverSysNum(sys_name);
3177 logAdd("Variable", var_name, var_type, params);
3178 _solver_systems[solver_system_number]->addVariable(var_type, var_name, params);
3180 // MooseObjects need to be unique so change the name here
3181 _displaced_problem->addVariable(var_type, var_name, params, solver_system_number);
3182
3183 _solver_var_to_sys_num[var_name] = solver_system_number;
3184}
3185
3186std::pair<bool, unsigned int>
3187FEProblemBase::determineSolverSystem(const std::string & var_name,
3188 const bool error_if_not_found) const
3189{
3190 auto map_it = _solver_var_to_sys_num.find(var_name);
3191 const bool var_in_sys = map_it != _solver_var_to_sys_num.end();
3192 if (var_in_sys)
3193 mooseAssert(_solver_systems[map_it->second]->hasVariable(var_name) ||
3194 _solver_systems[map_it->second]->hasScalarVariable(var_name),
3195 "If the variable is in our FEProblem solver system map, then it must be in the "
3196 "solver system we expect");
3197 else if (error_if_not_found)
3198 {
3199 if (_aux->hasVariable(var_name) || _aux->hasScalarVariable(var_name))
3200 mooseError("No solver variable named ",
3201 var_name,
3202 " found. Did you specify an auxiliary variable when you meant to specify a "
3203 "solver variable?");
3204 else
3205 mooseError("Unknown variable '",
3206 var_name,
3207 "'. It does not exist in the solver system(s) or auxiliary system");
3208 }
3209
3210 return std::make_pair(var_in_sys, var_in_sys ? map_it->second : libMesh::invalid_uint);
3211}
3212
3213void
3215 const std::string & name,
3216 InputParameters & parameters,
3217 const unsigned int nl_sys_num,
3218 const std::string & base_name,
3219 bool & reinit_displaced)
3220{
3221 if (_displaced_problem && parameters.get<bool>("use_displaced_mesh"))
3222 {
3223 parameters.set<SubProblem *>("_subproblem") = _displaced_problem.get();
3224 parameters.set<SystemBase *>("_sys") = &_displaced_problem->solverSys(nl_sys_num);
3225 reinit_displaced = true;
3226 }
3227 else
3228 {
3229 if (_displaced_problem == nullptr && parameters.get<bool>("use_displaced_mesh"))
3230 {
3231 // We allow Kernels to request that they use_displaced_mesh,
3232 // but then be overridden when no displacements variables are
3233 // provided in the Mesh block. If that happened, update the value
3234 // of use_displaced_mesh appropriately for this Kernel.
3235 if (parameters.have_parameter<bool>("use_displaced_mesh"))
3236 parameters.set<bool>("use_displaced_mesh") = false;
3237 }
3238
3239 parameters.set<SubProblem *>("_subproblem") = this;
3240 parameters.set<SystemBase *>("_sys") = _nl[nl_sys_num].get();
3241 }
3242
3243 logAdd(base_name, name, ro_name, parameters);
3244}
3245
3246void
3248 const std::string & name,
3249 InputParameters & parameters,
3250 const std::string & base_name)
3251{
3252 if (_displaced_problem && parameters.get<bool>("use_displaced_mesh"))
3253 {
3254 parameters.set<SubProblem *>("_subproblem") = _displaced_problem.get();
3255 parameters.set<SystemBase *>("_sys") = &_displaced_problem->auxSys();
3256 parameters.set<SystemBase *>("_nl_sys") = &_displaced_problem->solverSys(0);
3257 if (!parameters.get<std::vector<BoundaryName>>("boundary").empty())
3259 else
3261 }
3262 else
3263 {
3264 if (_displaced_problem == nullptr && parameters.get<bool>("use_displaced_mesh"))
3265 {
3266 // We allow AuxKernels to request that they use_displaced_mesh,
3267 // but then be overridden when no displacements variables are
3268 // provided in the Mesh block. If that happened, update the value
3269 // of use_displaced_mesh appropriately for this AuxKernel.
3270 if (parameters.have_parameter<bool>("use_displaced_mesh"))
3271 parameters.set<bool>("use_displaced_mesh") = false;
3272 }
3273
3274 parameters.set<SubProblem *>("_subproblem") = this;
3275 parameters.set<SystemBase *>("_sys") = _aux.get();
3276 parameters.set<SystemBase *>("_nl_sys") = _solver_systems[0].get();
3277 }
3278
3279 logAdd(base_name, name, ak_name, parameters);
3280}
3281
3282void
3283FEProblemBase::addKernel(const std::string & kernel_name,
3284 const std::string & name,
3285 InputParameters & parameters)
3286{
3287#ifdef MOOSE_KOKKOS_ENABLED
3289 return addKokkosKernel(kernel_name, name, parameters);
3290#endif
3291
3292 parallel_object_only();
3293 const auto nl_sys_num = determineSolverSystem(parameters.varName("variable", name), true).second;
3294 if (!isSolverSystemNonlinear(nl_sys_num))
3295 mooseError("You are trying to add a Kernel to a linear variable/system, which is not "
3296 "supported at the moment!");
3298 kernel_name, name, parameters, nl_sys_num, "Kernel", _reinit_displaced_elem);
3299
3300 _nl[nl_sys_num]->addKernel(kernel_name, name, parameters);
3301}
3302
3303void
3304FEProblemBase::addHDGKernel(const std::string & kernel_name,
3305 const std::string & name,
3306 InputParameters & parameters)
3307{
3308 parallel_object_only();
3309 const auto nl_sys_num = determineSolverSystem(parameters.varName("variable", name), true).second;
3310 if (!isSolverSystemNonlinear(nl_sys_num))
3311 mooseError("You are trying to add a HDGKernel to a linear variable/system, which is not "
3312 "supported at the moment!");
3314 kernel_name, name, parameters, nl_sys_num, "HDGKernel", _reinit_displaced_elem);
3315
3316 _nl[nl_sys_num]->addHDGKernel(kernel_name, name, parameters);
3317}
3318
3319void
3320FEProblemBase::addNodalKernel(const std::string & kernel_name,
3321 const std::string & name,
3322 InputParameters & parameters)
3323{
3324#ifdef MOOSE_KOKKOS_ENABLED
3326 return addKokkosNodalKernel(kernel_name, name, parameters);
3327#endif
3328
3329 parallel_object_only();
3330
3331 const auto nl_sys_num = determineSolverSystem(parameters.varName("variable", name), true).second;
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);
3337 }
3338 else
3339 {
3340 if (_displaced_problem == nullptr && parameters.get<bool>("use_displaced_mesh"))
3341 {
3342 // We allow NodalKernels 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 NodalKernel.
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 logAdd("NodalKernel", name, kernel_name, parameters);
3354 _nl[nl_sys_num]->addNodalKernel(kernel_name, name, parameters);
3355}
3356
3357void
3358FEProblemBase::addScalarKernel(const std::string & kernel_name,
3359 const std::string & name,
3360 InputParameters & parameters)
3361{
3362 parallel_object_only();
3363
3364 const auto nl_sys_num = determineSolverSystem(parameters.varName("variable", name), true).second;
3365 if (!isSolverSystemNonlinear(nl_sys_num))
3366 mooseError("You are trying to add a ScalarKernel to a linear variable/system, which is not "
3367 "supported at the moment!");
3368
3369 if (_displaced_problem && parameters.get<bool>("use_displaced_mesh"))
3370 {
3371 parameters.set<SubProblem *>("_subproblem") = _displaced_problem.get();
3372 parameters.set<SystemBase *>("_sys") = &_displaced_problem->solverSys(nl_sys_num);
3373 }
3374 else
3375 {
3376 if (_displaced_problem == nullptr && parameters.get<bool>("use_displaced_mesh"))
3377 {
3378 // We allow ScalarKernels to request that they use_displaced_mesh,
3379 // but then be overridden when no displacements variables are
3380 // provided in the Mesh block. If that happened, update the value
3381 // of use_displaced_mesh appropriately for this ScalarKernel.
3382 if (parameters.have_parameter<bool>("use_displaced_mesh"))
3383 parameters.set<bool>("use_displaced_mesh") = false;
3384 }
3385
3386 parameters.set<SubProblem *>("_subproblem") = this;
3387 parameters.set<SystemBase *>("_sys") = _nl[nl_sys_num].get();
3388 }
3389
3390 logAdd("ScalarKernel", name, kernel_name, parameters);
3391 _nl[nl_sys_num]->addScalarKernel(kernel_name, name, parameters);
3392}
3393
3394void
3395FEProblemBase::addBoundaryCondition(const std::string & bc_name,
3396 const std::string & name,
3397 InputParameters & parameters)
3398{
3399#ifdef MOOSE_KOKKOS_ENABLED
3401 return addKokkosBoundaryCondition(bc_name, name, parameters);
3402#endif
3403
3404 parallel_object_only();
3405
3406 const auto nl_sys_num = determineSolverSystem(parameters.varName("variable", name), true).second;
3407 if (!isSolverSystemNonlinear(nl_sys_num))
3408 mooseError(
3409 "You are trying to add a BoundaryCondition to a linear variable/system, which is not "
3410 "supported at the moment!");
3411
3413 bc_name, name, parameters, nl_sys_num, "BoundaryCondition", _reinit_displaced_face);
3414 _nl[nl_sys_num]->addBoundaryCondition(bc_name, name, parameters);
3415}
3416
3417void
3418FEProblemBase::addConstraint(const std::string & c_name,
3419 const std::string & name,
3420 InputParameters & parameters)
3421{
3422 parallel_object_only();
3423
3424 _has_constraints = true;
3425
3426 auto determine_var_param_name = [&parameters, this]()
3427 {
3428 if (parameters.isParamValid("variable"))
3429 return "variable";
3430 else
3431 {
3432 // must be a mortar constraint
3433 const bool has_secondary_var = parameters.isParamValid("secondary_variable");
3434 const bool has_primary_var = parameters.isParamValid("primary_variable");
3435 if (!has_secondary_var && !has_primary_var)
3436 mooseError(
3437 "Either a 'secondary_variable' or 'primary_variable' parameter must be supplied for '",
3439 "'");
3440 return has_secondary_var ? "secondary_variable" : "primary_variable";
3441 }
3442 };
3443
3444 const auto nl_sys_num =
3445 determineSolverSystem(parameters.varName(determine_var_param_name(), name), true).second;
3446 if (!isSolverSystemNonlinear(nl_sys_num))
3447 mooseError("You are trying to add a Constraint to a linear variable/system, which is not "
3448 "supported at the moment!");
3449
3450 if (_displaced_problem && parameters.get<bool>("use_displaced_mesh"))
3451 {
3452 parameters.set<SubProblem *>("_subproblem") = _displaced_problem.get();
3453 parameters.set<SystemBase *>("_sys") = &_displaced_problem->solverSys(nl_sys_num);
3455 }
3456 else
3457 {
3458 // It might _want_ to use a displaced mesh... but we're not so set it to false
3459 if (parameters.have_parameter<bool>("use_displaced_mesh"))
3460 parameters.set<bool>("use_displaced_mesh") = false;
3461
3462 parameters.set<SubProblem *>("_subproblem") = this;
3463 parameters.set<SystemBase *>("_sys") = _nl[nl_sys_num].get();
3464 }
3465
3466 logAdd("Constraint", name, c_name, parameters);
3467 _nl[nl_sys_num]->addConstraint(c_name, name, parameters);
3468}
3469
3470void
3471FEProblemBase::addAuxVariable(const std::string & var_type,
3472 const std::string & var_name,
3473 InputParameters & params)
3474{
3475 parallel_object_only();
3476
3477 const auto fe_type = MooseUtils::variableFEType(params);
3478
3479 const auto active_subdomains_vector =
3480 _mesh.getSubdomainIDs(params.get<std::vector<SubdomainName>>("block"));
3481 const std::set<SubdomainID> active_subdomains(active_subdomains_vector.begin(),
3482 active_subdomains_vector.end());
3483
3484 if (duplicateVariableCheck(var_name, fe_type, /* is_aux = */ true, &active_subdomains))
3485 return;
3486
3487 params.set<FEProblemBase *>("_fe_problem_base") = this;
3489
3490 logAdd("AuxVariable", var_name, var_type, params);
3491 _aux->addVariable(var_type, var_name, params);
3493 // MooseObjects need to be unique so change the name here
3494 _displaced_problem->addAuxVariable(var_type, var_name, params);
3495}
3496
3497void
3498FEProblemBase::addElementalFieldVariable(const std::string & var_type,
3499 const std::string & var_name,
3500 InputParameters & params)
3501{
3502 addAuxVariable(var_type, var_name, params);
3503}
3504
3505void
3506FEProblemBase::addAuxVariable(const std::string & var_name,
3507 const FEType & type,
3508 const std::set<SubdomainID> * const active_subdomains)
3509{
3510 parallel_object_only();
3511
3512 mooseDeprecated("Please use the addAuxVariable(var_type, var_name, params) API instead");
3513
3514 if (duplicateVariableCheck(var_name, type, /* is_aux = */ true, active_subdomains))
3515 return;
3516
3517 std::string var_type;
3518 if (type.order == CONSTANT && type.family == MONOMIAL && !type.p_refinement)
3519 var_type = "MooseVariableConstMonomial";
3520 else if (type.family == SCALAR)
3521 var_type = "MooseVariableScalar";
3522 else if (FEInterface::field_type(type) == libMesh::TYPE_VECTOR)
3523 var_type = "VectorMooseVariable";
3524 else
3525 var_type = "MooseVariable";
3526
3527 InputParameters params = _factory.getValidParams(var_type);
3528 params.set<FEProblemBase *>("_fe_problem_base") = this;
3530 params.set<MooseEnum>("order") = type.order.get_order();
3531 params.set<MooseEnum>("family") = Moose::stringify(type.family);
3532 params.set<bool>("p_refinement") = type.p_refinement;
3533
3534 if (active_subdomains)
3535 for (const SubdomainID & id : *active_subdomains)
3536 params.set<std::vector<SubdomainName>>("block").push_back(Moose::stringify(id));
3537
3538 logAdd("AuxVariable", var_name, var_type, params);
3539 _aux->addVariable(var_type, var_name, params);
3541 _displaced_problem->addAuxVariable("MooseVariable", var_name, params);
3542}
3543
3544void
3545FEProblemBase::addAuxArrayVariable(const std::string & var_name,
3546 const FEType & type,
3547 unsigned int components,
3548 const std::set<SubdomainID> * const active_subdomains)
3549{
3550 parallel_object_only();
3551
3552 mooseDeprecated("Please use the addAuxVariable(var_type, var_name, params) API instead");
3553
3554 if (duplicateVariableCheck(var_name, type, /* is_aux = */ true, active_subdomains))
3555 return;
3556
3557 InputParameters params = _factory.getValidParams("ArrayMooseVariable");
3558 params.set<FEProblemBase *>("_fe_problem_base") = this;
3560 params.set<MooseEnum>("order") = type.order.get_order();
3561 params.set<MooseEnum>("family") = Moose::stringify(type.family);
3562 params.set<bool>("p_refinement") = type.p_refinement;
3563 params.set<unsigned int>("components") = components;
3564
3565 if (active_subdomains)
3566 for (const SubdomainID & id : *active_subdomains)
3567 params.set<std::vector<SubdomainName>>("block").push_back(Moose::stringify(id));
3568
3569 logAdd("Variable", var_name, "ArrayMooseVariable", params);
3570 _aux->addVariable("ArrayMooseVariable", var_name, params);
3572 _displaced_problem->addAuxVariable("ArrayMooseVariable", var_name, params);
3573}
3574
3575void
3576FEProblemBase::addAuxScalarVariable(const std::string & var_name,
3577 Order order,
3578 Real /*scale_factor*/,
3579 const std::set<SubdomainID> * const active_subdomains)
3580{
3581 parallel_object_only();
3582
3583 mooseDeprecated("Please use the addAuxVariable(var_type, var_name, params) API instead");
3584
3585 if (order > _max_scalar_order)
3586 _max_scalar_order = order;
3587
3588 FEType type(order, SCALAR);
3589 if (duplicateVariableCheck(var_name, type, /* is_aux = */ true, active_subdomains))
3590 return;
3591
3592 InputParameters params = _factory.getValidParams("MooseVariableScalar");
3593 params.set<FEProblemBase *>("_fe_problem_base") = this;
3595
3596 params.set<MooseEnum>("order") = type.order.get_order();
3597 params.set<MooseEnum>("family") = "SCALAR";
3598 params.set<std::vector<Real>>("scaling") = std::vector<Real>{1};
3599 if (active_subdomains)
3600 for (const SubdomainID & id : *active_subdomains)
3601 params.set<std::vector<SubdomainName>>("block").push_back(Moose::stringify(id));
3602
3603 logAdd("ScalarVariable", var_name, "MooseVariableScalar", params);
3604 _aux->addVariable("MooseVariableScalar", var_name, params);
3606 _displaced_problem->addAuxVariable("MooseVariableScalar", var_name, params);
3607}
3608
3609void
3610FEProblemBase::addAuxKernel(const std::string & kernel_name,
3611 const std::string & name,
3612 InputParameters & parameters)
3613{
3614#ifdef MOOSE_KOKKOS_ENABLED
3616 return addKokkosAuxKernel(kernel_name, name, parameters);
3617#endif
3618
3619 parallel_object_only();
3620
3621 setAuxKernelParamsAndLog(kernel_name, name, parameters, "AuxKernel");
3622
3623 _aux->addKernel(kernel_name, name, parameters);
3624}
3625
3626void
3627FEProblemBase::addAuxScalarKernel(const std::string & kernel_name,
3628 const std::string & name,
3629 InputParameters & parameters)
3630{
3631 parallel_object_only();
3632
3633 if (_displaced_problem && parameters.get<bool>("use_displaced_mesh"))
3634 {
3635 parameters.set<SubProblem *>("_subproblem") = _displaced_problem.get();
3636 parameters.set<SystemBase *>("_sys") = &_displaced_problem->auxSys();
3637 }
3638 else
3639 {
3640 if (_displaced_problem == nullptr && parameters.get<bool>("use_displaced_mesh"))
3641 {
3642 // We allow AuxScalarKernels to request that they use_displaced_mesh,
3643 // but then be overridden when no displacements variables are
3644 // provided in the Mesh block. If that happened, update the value
3645 // of use_displaced_mesh appropriately for this AuxScalarKernel.
3646 if (parameters.have_parameter<bool>("use_displaced_mesh"))
3647 parameters.set<bool>("use_displaced_mesh") = false;
3648 }
3649
3650 parameters.set<SubProblem *>("_subproblem") = this;
3651 parameters.set<SystemBase *>("_sys") = _aux.get();
3652 }
3653
3654 logAdd("AuxScalarKernel", name, kernel_name, parameters);
3655 _aux->addScalarKernel(kernel_name, name, parameters);
3656}
3657
3658void
3659FEProblemBase::addDiracKernel(const std::string & kernel_name,
3660 const std::string & name,
3661 InputParameters & parameters)
3662{
3663 parallel_object_only();
3664
3665 const auto nl_sys_num = determineSolverSystem(parameters.varName("variable", name), true).second;
3666 if (!isSolverSystemNonlinear(nl_sys_num))
3667 mooseError("You are trying to add a DiracKernel to a linear variable/system, which is not "
3668 "supported at the moment!");
3669
3670 if (_displaced_problem && parameters.get<bool>("use_displaced_mesh"))
3671 {
3672 parameters.set<SubProblem *>("_subproblem") = _displaced_problem.get();
3673 parameters.set<SystemBase *>("_sys") = &_displaced_problem->solverSys(nl_sys_num);
3675 }
3676 else
3677 {
3678 if (_displaced_problem == nullptr && parameters.get<bool>("use_displaced_mesh"))
3679 {
3680 // We allow DiracKernels to request that they use_displaced_mesh,
3681 // but then be overridden when no displacements variables are
3682 // provided in the Mesh block. If that happened, update the value
3683 // of use_displaced_mesh appropriately for this DiracKernel.
3684 if (parameters.have_parameter<bool>("use_displaced_mesh"))
3685 parameters.set<bool>("use_displaced_mesh") = false;
3686 }
3687
3688 parameters.set<SubProblem *>("_subproblem") = this;
3689 parameters.set<SystemBase *>("_sys") = _nl[nl_sys_num].get();
3690 }
3691
3692 logAdd("DiracKernel", name, kernel_name, parameters);
3693 _nl[nl_sys_num]->addDiracKernel(kernel_name, name, parameters);
3694}
3695
3696// DGKernels ////
3697
3698void
3699FEProblemBase::addDGKernel(const std::string & dg_kernel_name,
3700 const std::string & name,
3701 InputParameters & parameters)
3702{
3703 parallel_object_only();
3704
3705 const auto nl_sys_num = determineSolverSystem(parameters.varName("variable", name), true).second;
3706 if (!isSolverSystemNonlinear(nl_sys_num))
3707 mooseError("You are trying to add a DGKernel to a linear variable/system, which is not "
3708 "supported at the moment!");
3709
3710 if (_displaced_problem && parameters.get<bool>("use_displaced_mesh"))
3711 {
3712 parameters.set<SubProblem *>("_subproblem") = _displaced_problem.get();
3713 parameters.set<SystemBase *>("_sys") = &_displaced_problem->solverSys(nl_sys_num);
3715 }
3716 else
3717 {
3718 if (_displaced_problem == nullptr && parameters.get<bool>("use_displaced_mesh"))
3719 {
3720 // We allow DGKernels to request that they use_displaced_mesh,
3721 // but then be overridden when no displacements variables are
3722 // provided in the Mesh block. If that happened, update the value
3723 // of use_displaced_mesh appropriately for this DGKernel.
3724 if (parameters.have_parameter<bool>("use_displaced_mesh"))
3725 parameters.set<bool>("use_displaced_mesh") = false;
3726 }
3727
3728 parameters.set<SubProblem *>("_subproblem") = this;
3729 parameters.set<SystemBase *>("_sys") = _nl[nl_sys_num].get();
3730 }
3731
3732 logAdd("DGKernel", name, dg_kernel_name, parameters);
3733 _nl[nl_sys_num]->addDGKernel(dg_kernel_name, name, parameters);
3734
3736}
3737
3738void
3739FEProblemBase::addFVKernel(const std::string & fv_kernel_name,
3740 const std::string & name,
3741 InputParameters & parameters)
3742{
3743 if (_displaced_problem && parameters.get<bool>("use_displaced_mesh"))
3744 // FVElementalKernels are computed in the historically finite element threaded loops. They rely
3745 // on Assembly data like _current_elem. When we call reinit on the FEProblemBase we will only
3746 // reinit the DisplacedProblem and its associated Assembly objects if we mark this boolean as
3747 // true
3749 addObject<FVKernel>(fv_kernel_name, name, parameters);
3750}
3751
3752void
3753FEProblemBase::addFVBC(const std::string & fv_bc_name,
3754 const std::string & name,
3755 InputParameters & parameters)
3756{
3757 addObject<FVBoundaryCondition>(fv_bc_name, name, parameters);
3758}
3759
3760void
3761FEProblemBase::addFVInterfaceKernel(const std::string & fv_ik_name,
3762 const std::string & name,
3763 InputParameters & parameters)
3764{
3767 addObject<FVInterfaceKernel>(
3768 fv_ik_name, name, parameters, /*threaded=*/true, /*variable_param_name=*/"variable1");
3769}
3770
3771void
3772FEProblemBase::addLinearFVKernel(const std::string & kernel_name,
3773 const std::string & name,
3774 InputParameters & parameters)
3775{
3776#ifdef MOOSE_KOKKOS_ENABLED
3778 return addKokkosLinearFVKernel(kernel_name, name, parameters);
3779#endif
3780
3781 addObject<LinearFVKernel>(kernel_name, name, parameters);
3782}
3783
3784void
3785FEProblemBase::addLinearFVBC(const std::string & bc_name,
3786 const std::string & name,
3787 InputParameters & parameters)
3788{
3789#ifdef MOOSE_KOKKOS_ENABLED
3791 return addKokkosLinearFVBC(bc_name, name, parameters);
3792#endif
3793
3794 addObject<LinearFVBoundaryCondition>(bc_name, name, parameters);
3795}
3796
3797// InterfaceKernels ////
3798
3799void
3800FEProblemBase::addInterfaceKernel(const std::string & interface_kernel_name,
3801 const std::string & name,
3802 InputParameters & parameters)
3803{
3804 parallel_object_only();
3805
3806 const auto nl_sys_num = determineSolverSystem(parameters.varName("variable", name), true).second;
3807 if (!isSolverSystemNonlinear(nl_sys_num))
3808 mooseError("You are trying to add a InterfaceKernel to a linear variable/system, which is not "
3809 "supported at the moment!");
3810
3811 if (_displaced_problem && parameters.get<bool>("use_displaced_mesh"))
3812 {
3813 parameters.set<SubProblem *>("_subproblem") = _displaced_problem.get();
3814 parameters.set<SystemBase *>("_sys") = &_displaced_problem->solverSys(nl_sys_num);
3816 }
3817 else
3818 {
3819 if (_displaced_problem == nullptr && parameters.get<bool>("use_displaced_mesh"))
3820 {
3821 // We allow InterfaceKernels to request that they use_displaced_mesh,
3822 // but then be overridden when no displacements variables are
3823 // provided in the Mesh block. If that happened, update the value
3824 // of use_displaced_mesh appropriately for this InterfaceKernel.
3825 if (parameters.have_parameter<bool>("use_displaced_mesh"))
3826 parameters.set<bool>("use_displaced_mesh") = false;
3827 }
3828
3829 parameters.set<SubProblem *>("_subproblem") = this;
3830 parameters.set<SystemBase *>("_sys") = _nl[nl_sys_num].get();
3831 }
3832
3833 logAdd("InterfaceKernel", name, interface_kernel_name, parameters);
3834 _nl[nl_sys_num]->addInterfaceKernel(interface_kernel_name, name, parameters);
3835
3837}
3838
3839void
3840FEProblemBase::checkICRestartError(const std::string & ic_name,
3841 const std::string & name,
3842 const VariableName & var_name)
3843{
3845 {
3846 std::string restart_method = "";
3847 if (_app.isRestarting())
3848 restart_method =
3849 "a checkpoint restart, by IC object '" + ic_name + "' for variable '" + name + "'";
3850 else if (_app.getExReaderForRestart())
3851 {
3852 std::vector<std::string> restarted_vars = _app.getExReaderForRestart()->get_elem_var_names();
3853 const auto nodal_vars = _app.getExReaderForRestart()->get_nodal_var_names();
3854 const auto global_vars = _app.getExReaderForRestart()->get_global_var_names();
3855 restarted_vars.insert(restarted_vars.end(), nodal_vars.begin(), nodal_vars.end());
3856 restarted_vars.insert(restarted_vars.end(), global_vars.begin(), global_vars.end());
3857
3858 if (std::find(restarted_vars.begin(), restarted_vars.end(), var_name) != restarted_vars.end())
3859 restart_method = "an Exodus restart, by IC object '" + ic_name + "' for variable '" + name +
3860 "' that is also being restarted";
3861 }
3862 if (!restart_method.empty())
3863 mooseError(
3864 "Initial conditions have been specified during ",
3865 restart_method,
3866 ".\nThis is only allowed if you specify 'allow_initial_conditions_with_restart' to "
3867 "the [Problem], as initial conditions can override restarted fields");
3868 }
3869}
3870
3871void
3872FEProblemBase::addInitialCondition(const std::string & ic_name,
3873 const std::string & name,
3874 InputParameters & parameters)
3875{
3876 parallel_object_only();
3877
3878 // before we start to mess with the initial condition, we need to check parameters for errors.
3880 const std::string & var_name = parameters.get<VariableName>("variable");
3881
3882 // Forbid initial conditions on a restarted problem, as they would override the restart
3883 checkICRestartError(ic_name, name, var_name);
3884
3885 parameters.set<SubProblem *>("_subproblem") = this;
3886
3887 // field IC
3888 if (hasVariable(var_name))
3889 {
3890 for (THREAD_ID tid = 0; tid < numThreads(); ++tid)
3891 {
3894 parameters.set<SystemBase *>("_sys") = &var.sys();
3895 std::shared_ptr<InitialConditionBase> ic;
3896 if (dynamic_cast<MooseVariable *>(&var))
3897 ic = _factory.create<InitialCondition>(ic_name, name, parameters, tid);
3898 else if (dynamic_cast<VectorMooseVariable *>(&var))
3900 else if (dynamic_cast<ArrayMooseVariable *>(&var))
3901 ic = _factory.create<ArrayInitialCondition>(ic_name, name, parameters, tid);
3902 else if (dynamic_cast<MooseVariableFVReal *>(&var))
3903 ic = _factory.create<InitialCondition>(ic_name, name, parameters, tid);
3904 else if (dynamic_cast<MooseLinearVariableFVReal *>(&var))
3905 ic = _factory.create<InitialCondition>(ic_name, name, parameters, tid);
3906 else
3907 mooseError("Your FE variable in initial condition ",
3908 name,
3909 " must be either of scalar or vector type");
3910 logAdd("IC", name, ic_name, parameters);
3911 _ics.addObject(ic, tid);
3912 }
3913 }
3914
3915 // scalar IC
3916 else if (hasScalarVariable(var_name))
3917 {
3918 MooseVariableScalar & var = getScalarVariable(0, var_name);
3919 parameters.set<SystemBase *>("_sys") = &var.sys();
3920 std::shared_ptr<ScalarInitialCondition> ic =
3922 logAdd("ScalarIC", name, ic_name, parameters);
3924 }
3925
3926 else
3927 mooseError(
3928 "Variable '", var_name, "' requested in initial condition '", name, "' does not exist.");
3929}
3930
3931void
3932FEProblemBase::addFVInitialCondition(const std::string & ic_name,
3933 const std::string & name,
3934 InputParameters & parameters)
3935{
3936 parallel_object_only();
3937
3938 // before we start to mess with the initial condition, we need to check parameters for errors.
3940 const std::string & var_name = parameters.get<VariableName>("variable");
3941
3942 // Forbid initial conditions on a restarted problem, as they would override the restart
3943 checkICRestartError(ic_name, name, var_name);
3944
3945 parameters.set<SubProblem *>("_subproblem") = this;
3946
3947 // field IC
3948 if (hasVariable(var_name))
3949 {
3950 for (THREAD_ID tid = 0; tid < numThreads(); ++tid)
3951 {
3952 auto & var = getVariable(
3954 parameters.set<SystemBase *>("_sys") = &var.sys();
3955 std::shared_ptr<FVInitialConditionBase> ic;
3956 if (var.isFV())
3957 ic = _factory.create<FVInitialCondition>(ic_name, name, parameters, tid);
3958 else
3959 mooseError(
3960 "Your variable for an FVInitialCondition needs to be an a finite volume variable!");
3961 _fv_ics.addObject(ic, tid);
3962 }
3963 }
3964 else
3965 mooseError("Variable '",
3966 var_name,
3967 "' requested in finite volume initial condition '",
3968 name,
3969 "' does not exist.");
3970}
3971
3972void
3974{
3975 TIME_SECTION("projectSolution", 2, "Projecting Initial Solutions")
3976
3978
3981
3982 if (haveFV())
3983 {
3984 using ElemInfoRange = StoredRange<MooseMesh::const_elem_info_iterator, const ElemInfo *>;
3985 ElemInfoRange elem_info_range(_mesh.ownedElemInfoBegin(), _mesh.ownedElemInfoEnd());
3986
3988 Threads::parallel_reduce(elem_info_range, cfvic, numThreads());
3989 }
3990
3991 // Need to close the solution vector here so that boundary ICs take precendence
3992 for (auto & nl : _nl)
3993 nl->solution().close();
3994 _aux->solution().close();
3995
3996 // now run boundary-restricted initial conditions
3999
4000 for (auto & nl : _nl)
4001 nl->solution().close();
4002 _aux->solution().close();
4003
4004 // Also, load values into the SCALAR dofs
4005 // Note: We assume that all SCALAR dofs are on the
4006 // processor with highest ID
4008 {
4009 const auto & ics = _scalar_ics.getActiveObjects();
4010 for (const auto & ic : ics)
4011 {
4012 MooseVariableScalar & var = ic->variable();
4013 var.reinit();
4014
4015 DenseVector<Number> vals(var.order());
4016 ic->compute(vals);
4017
4018 const unsigned int n_scalar_dofs = var.dofIndices().size();
4019 for (unsigned int i = 0; i < n_scalar_dofs; i++)
4020 {
4021 const auto global_index = var.dofIndices()[i];
4022 var.sys().solution().set(global_index, vals(i));
4023 var.setValue(i, vals(i));
4024 }
4025 }
4026 }
4027
4028 // Spline node ICs may need to be evaluated indirectly.
4029 bool solve_for_spline_dofs = shouldSolveForSplineDofs(_mesh.getMesh());
4030
4031 for (auto & sys : _solver_systems)
4032 {
4033 sys->solution().close();
4034 if (solve_for_spline_dofs)
4035 solveForSplineDofs(*sys);
4036 sys->solution().localize(*sys->system().current_local_solution, sys->dofMap().get_send_list());
4037 }
4038
4039 _aux->solution().close();
4040 if (solve_for_spline_dofs)
4041 solveForSplineDofs(*_aux);
4042 _aux->solution().localize(*_aux->sys().current_local_solution, _aux->dofMap().get_send_list());
4043}
4044
4045void
4047 ConstElemRange & elem_range,
4048 ConstBndNodeRange & bnd_nodes,
4049 const std::optional<std::set<VariableName>> & target_vars)
4050{
4051 if (target_vars)
4052 {
4053 ComputeInitialConditionThread cic(*this, &(*target_vars));
4054 Threads::parallel_reduce(elem_range, cic, numThreads());
4055 }
4056 else
4057 {
4059 Threads::parallel_reduce(elem_range, cic, numThreads());
4060 }
4061
4062 // Need to close the solution vector here so that boundary ICs take precendence
4063 for (auto & nl : _nl)
4064 nl->solution().close();
4065 _aux->solution().close();
4066
4067 if (target_vars)
4068 {
4069 ComputeBoundaryInitialConditionThread cbic(*this, &(*target_vars));
4070 Threads::parallel_reduce(bnd_nodes, cbic, numThreads());
4071 }
4072 else
4073 {
4075 Threads::parallel_reduce(bnd_nodes, cbic, numThreads());
4076 }
4077
4078 for (auto & nl : _nl)
4079 nl->solution().close();
4080 _aux->solution().close();
4081
4082 // Also, load values into the SCALAR dofs
4083 // Note: We assume that all SCALAR dofs are on the
4084 // processor with highest ID
4086 {
4087 const auto & ics = _scalar_ics.getActiveObjects();
4088 for (const auto & ic : ics)
4089 {
4090 MooseVariableScalar & var = ic->variable();
4091
4092 if (target_vars && !target_vars->count(var.name()))
4093 continue;
4094
4095 var.reinit();
4096
4097 DenseVector<Number> vals(var.order());
4098 ic->compute(vals);
4099
4100 const unsigned int n_scalar_dofs = var.dofIndices().size();
4101 for (unsigned int i = 0; i < n_scalar_dofs; i++)
4102 {
4103 const auto global_index = var.dofIndices()[i];
4104 var.sys().solution().set(global_index, vals(i));
4105 var.setValue(i, vals(i));
4106 }
4107 }
4108 }
4109
4110 // Spline node ICs may need to be evaluated indirectly.
4111 bool solve_for_spline_dofs = shouldSolveForSplineDofs(_mesh.getMesh());
4112
4113 for (auto & nl : _nl)
4114 {
4115 nl->solution().close();
4116 if (solve_for_spline_dofs)
4117 solveForSplineDofs(*nl);
4118 nl->solution().localize(*nl->system().current_local_solution, nl->dofMap().get_send_list());
4119 }
4120
4121 _aux->solution().close();
4122 if (solve_for_spline_dofs)
4123 solveForSplineDofs(*_aux);
4124 _aux->solution().localize(*_aux->sys().current_local_solution, _aux->dofMap().get_send_list());
4125}
4126
4127void
4129 Number (*func)(const Point &,
4130 const libMesh::Parameters &,
4131 const std::string &,
4132 const std::string &),
4133 Gradient (*func_grad)(const Point &,
4134 const libMesh::Parameters &,
4135 const std::string &,
4136 const std::string &),
4137 const libMesh::Parameters & params,
4138 const std::vector<VariableName> & target_vars)
4139{
4140 mooseAssert(!Threads::in_threads,
4141 "We're performing a projection based on data from just the thread 0 variable, so any "
4142 "modifications to the variable solution must have been thread joined already");
4143
4144 std::unordered_map<unsigned int, std::vector<unsigned int>> sys_to_var_nums;
4145
4146 for (const auto & target_var : target_vars)
4147 {
4148 const auto sn = systemNumForVariable(target_var);
4149 const auto & var = getStandardVariable(0, target_var);
4150 sys_to_var_nums[sn].push_back(var.number());
4151 }
4152
4153 for (const auto & [sys_num, var_nums] : sys_to_var_nums)
4154 {
4155 System & libmesh_sys = getSystemBase(sys_num).system();
4156 libmesh_sys.project_solution(func, func_grad, params, elem_range, var_nums);
4157 }
4158}
4159
4160std::shared_ptr<MaterialBase>
4163 const THREAD_ID tid,
4164 bool no_warn)
4165{
4166 switch (type)
4167 {
4169 name += "_neighbor";
4170 break;
4172 name += "_face";
4173 break;
4174 default:
4175 break;
4176 }
4177
4178 std::shared_ptr<MaterialBase> material = _all_materials[type].getActiveObject(name, tid);
4179 if (!no_warn && material->getParam<bool>("compute") && type == Moose::BLOCK_MATERIAL_DATA)
4180 mooseWarning("You are retrieving a Material object (",
4181 material->name(),
4182 "), but its compute flag is set to true. This indicates that MOOSE is "
4183 "computing this property which may not be desired and produce un-expected "
4184 "results.");
4185
4186 return material;
4187}
4188
4191 const THREAD_ID tid,
4192 const MooseObject * object) const
4193{
4194 switch (type)
4195 {
4197 if (object)
4199 return _material_props.getMaterialData(tid);
4201 if (object)
4207 if (object)
4210 }
4211
4212 mooseError("FEProblemBase::getMaterialData(): Invalid MaterialDataType ", type);
4213}
4214
4215const std::set<const MooseObject *> &
4217{
4218 switch (type)
4219 {
4228 }
4229
4230 mooseError("FEProblemBase::getMaterialPropertyStorageConsumers(): Invalid MaterialDataType ",
4231 type);
4232}
4233
4234void
4236{
4237 if (_ignore_zeros_in_jacobian && preserve)
4239 "ignore_zeros_in_jacobian",
4240 "We likely cannot preserve the sparsity pattern if ignoring zeros in the Jacobian, which "
4241 "leads to removing those entries from the Jacobian sparsity pattern");
4243}
4244
4245bool
4247{
4248 return allowInvalidSolution() || // invalid solutions are always allowed
4249 !_app.solutionInvalidity().hasInvalidSolutionError(); // if not allowed, check for errors
4250}
4251
4252void
4253FEProblemBase::addFunctorMaterial(const std::string & functor_material_name,
4254 const std::string & name,
4255 InputParameters & parameters)
4256{
4257 parallel_object_only();
4258
4259 auto add_functor_materials = [&](const auto & parameters, const auto & name)
4260 {
4261 for (THREAD_ID tid = 0; tid < numThreads(); tid++)
4262 {
4263 // Create the general Block/Boundary MaterialBase object
4264 std::shared_ptr<MaterialBase> material =
4265 _factory.create<MaterialBase>(functor_material_name, name, parameters, tid);
4266 logAdd("FunctorMaterial", name, functor_material_name, parameters);
4267 _all_materials.addObject(material, tid);
4268 _materials.addObject(material, tid);
4269 }
4270 };
4271
4272 parameters.set<SubProblem *>("_subproblem") = this;
4273 add_functor_materials(parameters, name);
4275 {
4276 auto disp_params = parameters;
4277 disp_params.set<SubProblem *>("_subproblem") = _displaced_problem.get();
4278 add_functor_materials(disp_params, name + "_displaced");
4279 }
4280}
4281
4282void
4283FEProblemBase::addMaterial(const std::string & mat_name,
4284 const std::string & name,
4285 InputParameters & parameters)
4286{
4287#ifdef MOOSE_KOKKOS_ENABLED
4289 return addKokkosMaterial(mat_name, name, parameters);
4290#endif
4291
4293}
4294
4295void
4296FEProblemBase::addInterfaceMaterial(const std::string & mat_name,
4297 const std::string & name,
4298 InputParameters & parameters)
4299{
4301}
4302
4303void
4304FEProblemBase::addMaterialHelper(std::vector<MaterialWarehouse *> warehouses,
4305 const std::string & mat_name,
4306 const std::string & name,
4307 InputParameters & parameters)
4308{
4309 parallel_object_only();
4310
4311 if (_displaced_problem && parameters.get<bool>("use_displaced_mesh"))
4312 {
4313 parameters.set<SubProblem *>("_subproblem") = _displaced_problem.get();
4315 }
4316 else
4317 {
4318 if (_displaced_problem == nullptr && parameters.get<bool>("use_displaced_mesh"))
4319 {
4320 // We allow Materials to request that they use_displaced_mesh,
4321 // but then be overridden when no displacements variables are
4322 // provided in the Mesh block. If that happened, update the value
4323 // of use_displaced_mesh appropriately for this Material.
4324 if (parameters.have_parameter<bool>("use_displaced_mesh"))
4325 parameters.set<bool>("use_displaced_mesh") = false;
4326 }
4327
4328 parameters.set<SubProblem *>("_subproblem") = this;
4329 }
4330
4331 unsigned int n_threads = numThreads();
4332
4333#ifdef MOOSE_KOKKOS_ENABLED
4335 n_threads = 1;
4336#endif
4337
4338 for (THREAD_ID tid = 0; tid < n_threads; tid++)
4339 {
4340 // Create the general Block/Boundary MaterialBase object
4341 std::shared_ptr<MaterialBase> material =
4342 _factory.create<MaterialBase>(mat_name, name, parameters, tid);
4343 logAdd("Material", name, mat_name, parameters);
4344 bool discrete = !material->getParam<bool>("compute");
4345
4346 // If the object is boundary restricted or if it is a functor material we do not create the
4347 // neighbor and face objects
4348 if (material->boundaryRestricted() || dynamic_cast<FunctorMaterial *>(material.get()))
4349 {
4350 _all_materials.addObject(material, tid);
4351 if (discrete)
4352 _discrete_materials.addObject(material, tid);
4353 else
4354 for (auto && warehouse : warehouses)
4355 warehouse->addObject(material, tid);
4356 }
4357
4358 // Non-boundary restricted require face and neighbor objects
4359 else
4360 {
4361 // TODO: we only need to do this if we have needs for face materials (e.g.
4362 // FV, DG, etc.) - but currently we always do it. Figure out how to fix
4363 // this.
4364
4365 // The name of the object being created, this is changed multiple times as objects are
4366 // created below
4367 std::string object_name;
4368
4369 // Create a copy of the supplied parameters to the setting for "_material_data_type" isn't
4370 // used from a previous tid loop
4371 InputParameters current_parameters = parameters;
4372
4373 // face material
4374 current_parameters.set<Moose::MaterialDataType>("_material_data_type") =
4376 object_name = name + "_face";
4377 std::shared_ptr<MaterialBase> face_material =
4378 _factory.create<MaterialBase>(mat_name, object_name, current_parameters, tid);
4379
4380 // neighbor material
4381 current_parameters.set<Moose::MaterialDataType>("_material_data_type") =
4383 current_parameters.set<bool>("_neighbor") = true;
4384 object_name = name + "_neighbor";
4385 std::shared_ptr<MaterialBase> neighbor_material =
4386 _factory.create<MaterialBase>(mat_name, object_name, current_parameters, tid);
4387
4388 // Store the material objects
4389 _all_materials.addObjects(material, neighbor_material, face_material, tid);
4390
4391 if (discrete)
4392 _discrete_materials.addObjects(material, neighbor_material, face_material, tid);
4393 else
4394 for (auto && warehouse : warehouses)
4395 warehouse->addObjects(material, neighbor_material, face_material, tid);
4396
4397 // Names of all controllable parameters for this Material object
4398 const std::string & base = parameters.getBase();
4399 MooseObjectParameterName name(MooseObjectName(base, material->name()), "*");
4400 const auto param_names =
4402
4403 // Connect parameters of the primary Material object to those on the face and neighbor
4404 // objects
4405 for (const auto & p_name : param_names)
4406 {
4407 MooseObjectParameterName primary_name(MooseObjectName(base, material->name()),
4408 p_name.parameter());
4409 MooseObjectParameterName face_name(MooseObjectName(base, face_material->name()),
4410 p_name.parameter());
4411 MooseObjectParameterName neighbor_name(MooseObjectName(base, neighbor_material->name()),
4412 p_name.parameter());
4414 primary_name, face_name, false);
4416 primary_name, neighbor_name, false);
4417 }
4418 }
4419 }
4420}
4421
4422void
4423FEProblemBase::prepareMaterials(const std::unordered_set<unsigned int> & consumer_needed_mat_props,
4424 const SubdomainID blk_id,
4425 const THREAD_ID tid)
4426{
4427 std::set<MooseVariableFEBase *> needed_moose_vars;
4428 std::unordered_set<unsigned int> needed_mat_props;
4429
4430 if (_all_materials.hasActiveBlockObjects(blk_id, tid))
4431 {
4432 _all_materials.updateVariableDependency(needed_moose_vars, tid);
4433 _all_materials.updateBlockMatPropDependency(blk_id, needed_mat_props, tid);
4434 }
4435
4436 const auto & ids = _mesh.getSubdomainBoundaryIds(blk_id);
4437 for (const auto id : ids)
4438 {
4439 _materials.updateBoundaryVariableDependency(id, needed_moose_vars, tid);
4440 _materials.updateBoundaryMatPropDependency(id, needed_mat_props, tid);
4441 }
4442
4443 const auto & current_active_elemental_moose_variables = getActiveElementalMooseVariables(tid);
4444 needed_moose_vars.insert(current_active_elemental_moose_variables.begin(),
4445 current_active_elemental_moose_variables.end());
4446
4447 needed_mat_props.insert(consumer_needed_mat_props.begin(), consumer_needed_mat_props.end());
4448
4449 setActiveElementalMooseVariables(needed_moose_vars, tid);
4450 setActiveMaterialProperties(needed_mat_props, tid);
4451}
4452
4453void
4454FEProblemBase::reinitMaterials(SubdomainID blk_id, const THREAD_ID tid, bool swap_stateful)
4455{
4457 {
4458 auto && elem = _assembly[tid][0]->elem();
4459 unsigned int n_points = _assembly[tid][0]->qRule()->n_points();
4460
4461 auto & material_data = _material_props.getMaterialData(tid);
4462 material_data.resize(n_points);
4463
4464 // Only swap if requested
4465 if (swap_stateful)
4466 material_data.swap(*elem);
4467
4469 material_data.reset(_discrete_materials.getActiveBlockObjects(blk_id, tid));
4470
4471 if (_materials.hasActiveBlockObjects(blk_id, tid))
4472 material_data.reinit(_materials.getActiveBlockObjects(blk_id, tid));
4473 }
4474}
4475
4476void
4478 const THREAD_ID tid,
4479 const bool swap_stateful,
4480 const std::deque<MaterialBase *> * const reinit_mats)
4481{
4482 // we reinit more often than needed here because we dont have a way to check whether
4483 // we need to compute the face materials on a particular (possibly external) face
4485 {
4486 auto && elem = _assembly[tid][0]->elem();
4487 unsigned int side = _assembly[tid][0]->side();
4488 unsigned int n_points = _assembly[tid][0]->qRuleFace()->n_points();
4489
4490 auto & bnd_material_data = _bnd_material_props.getMaterialData(tid);
4491 bnd_material_data.resize(n_points);
4492
4493 if (swap_stateful && !bnd_material_data.isSwapped())
4494 bnd_material_data.swap(*elem, side);
4495
4496 if (_discrete_materials[Moose::FACE_MATERIAL_DATA].hasActiveBlockObjects(blk_id, tid))
4497 bnd_material_data.reset(
4498 _discrete_materials[Moose::FACE_MATERIAL_DATA].getActiveBlockObjects(blk_id, tid));
4499
4500 if (reinit_mats)
4501 bnd_material_data.reinit(*reinit_mats);
4502 else if (_materials[Moose::FACE_MATERIAL_DATA].hasActiveBlockObjects(blk_id, tid))
4503 bnd_material_data.reinit(
4504 _materials[Moose::FACE_MATERIAL_DATA].getActiveBlockObjects(blk_id, tid));
4505 }
4506}
4507
4508void
4510 const SubdomainID blk_id,
4511 const THREAD_ID tid,
4512 const bool swap_stateful,
4513 const std::deque<MaterialBase *> * const reinit_mats)
4514{
4515 if (hasActiveMaterialProperties(tid) && (needBoundaryMaterialOnSide(boundary_id, tid) ||
4516 needInterfaceMaterialOnSide(boundary_id, tid) ||
4518 {
4519 const auto * const elem = _assembly[tid][0]->elem();
4520 unsigned int side = _assembly[tid][0]->side();
4521 unsigned int n_points = _assembly[tid][0]->qRuleFace()->n_points();
4522
4523 auto & bnd_material_data = _bnd_material_props.getMaterialData(tid);
4524 bnd_material_data.resize(n_points);
4525
4526 if (swap_stateful && !bnd_material_data.isSwapped())
4527 bnd_material_data.swap(*elem, side);
4528
4529 if (_discrete_materials[Moose::FACE_MATERIAL_DATA].hasActiveBlockObjects(blk_id, tid))
4530 bnd_material_data.reset(
4531 _discrete_materials[Moose::FACE_MATERIAL_DATA].getActiveBlockObjects(blk_id, tid));
4532
4533 if (reinit_mats)
4534 bnd_material_data.reinit(*reinit_mats);
4535 else if (_materials[Moose::FACE_MATERIAL_DATA].hasActiveBlockObjects(blk_id, tid))
4536 bnd_material_data.reinit(
4537 _materials[Moose::FACE_MATERIAL_DATA].getActiveBlockObjects(blk_id, tid));
4538 }
4539}
4540
4541void
4543 const BoundaryID boundary_id,
4544 const SubdomainID blk_id,
4545 const THREAD_ID tid,
4546 const bool swap_stateful,
4547 const std::deque<MaterialBase *> * const reinit_mats)
4548{
4549 // Since objects don't declare whether they need the face or neighbor (side) material properties,
4550 // we use the same criteria for skipping material property computations as for face material
4551 // properties This could be a future optimization.
4552 if (hasActiveMaterialProperties(tid) && (needBoundaryMaterialOnSide(boundary_id, tid) ||
4553 needInterfaceMaterialOnSide(boundary_id, tid) ||
4555 reinitMaterialsNeighbor(blk_id, tid, swap_stateful, reinit_mats);
4556}
4557
4558void
4560 const THREAD_ID tid,
4561 const bool swap_stateful,
4562 const std::deque<MaterialBase *> * const reinit_mats)
4563{
4565 {
4566 // NOTE: this will not work with h-adaptivity
4567 // lindsayad: why not?
4568
4569 const Elem * neighbor = _assembly[tid][0]->neighbor();
4570 unsigned int neighbor_side = neighbor->which_neighbor_am_i(_assembly[tid][0]->elem());
4571
4572 mooseAssert(neighbor, "neighbor should be non-null");
4573 mooseAssert(blk_id == neighbor->subdomain_id(),
4574 "The provided blk_id " << blk_id << " and neighbor subdomain ID "
4575 << neighbor->subdomain_id() << " do not match.");
4576
4577 unsigned int n_points = _assembly[tid][0]->qRuleNeighbor()->n_points();
4578
4579 auto & neighbor_material_data = _neighbor_material_props.getMaterialData(tid);
4580 neighbor_material_data.resize(n_points);
4581
4582 // Only swap if requested
4583 if (swap_stateful)
4584 neighbor_material_data.swap(*neighbor, neighbor_side);
4585
4586 if (_discrete_materials[Moose::NEIGHBOR_MATERIAL_DATA].hasActiveBlockObjects(blk_id, tid))
4587 neighbor_material_data.reset(
4588 _discrete_materials[Moose::NEIGHBOR_MATERIAL_DATA].getActiveBlockObjects(blk_id, tid));
4589
4590 if (reinit_mats)
4591 neighbor_material_data.reinit(*reinit_mats);
4592 else if (_materials[Moose::NEIGHBOR_MATERIAL_DATA].hasActiveBlockObjects(blk_id, tid))
4593 neighbor_material_data.reinit(
4594 _materials[Moose::NEIGHBOR_MATERIAL_DATA].getActiveBlockObjects(blk_id, tid));
4595 }
4596}
4597
4598void
4600 const THREAD_ID tid,
4601 const bool swap_stateful,
4602 const std::deque<MaterialBase *> * const reinit_mats)
4603{
4604 if (hasActiveMaterialProperties(tid) && needBoundaryMaterialOnSide(boundary_id, tid))
4605 {
4606 auto && elem = _assembly[tid][0]->elem();
4607 unsigned int side = _assembly[tid][0]->side();
4608 unsigned int n_points = _assembly[tid][0]->qRuleFace()->n_points();
4609
4610 auto & bnd_material_data = _bnd_material_props.getMaterialData(tid);
4611 bnd_material_data.resize(n_points);
4612
4613 if (swap_stateful && !bnd_material_data.isSwapped())
4614 bnd_material_data.swap(*elem, side);
4615
4616 if (_discrete_materials.hasActiveBoundaryObjects(boundary_id, tid))
4617 bnd_material_data.reset(_discrete_materials.getActiveBoundaryObjects(boundary_id, tid));
4618
4619 if (reinit_mats)
4620 bnd_material_data.reinit(*reinit_mats);
4621 else if (_materials.hasActiveBoundaryObjects(boundary_id, tid))
4622 bnd_material_data.reinit(_materials.getActiveBoundaryObjects(boundary_id, tid));
4623 }
4624}
4625
4626void
4628 const THREAD_ID tid,
4629 bool swap_stateful)
4630{
4631 if (hasActiveMaterialProperties(tid) && needInterfaceMaterialOnSide(boundary_id, tid))
4632 {
4633 const Elem * const & elem = _assembly[tid][0]->elem();
4634 unsigned int side = _assembly[tid][0]->side();
4635 unsigned int n_points = _assembly[tid][0]->qRuleFace()->n_points();
4636
4637 auto & bnd_material_data = _bnd_material_props.getMaterialData(tid);
4638 bnd_material_data.resize(n_points);
4639
4640 if (swap_stateful && !bnd_material_data.isSwapped())
4641 bnd_material_data.swap(*elem, side);
4642
4643 if (_interface_materials.hasActiveBoundaryObjects(boundary_id, tid))
4644 bnd_material_data.reinit(_interface_materials.getActiveBoundaryObjects(boundary_id, tid));
4645 }
4646}
4647
4648void
4650{
4651 auto && elem = _assembly[tid][0]->elem();
4653}
4654
4655void
4657{
4658 auto && elem = _assembly[tid][0]->elem();
4659 unsigned int side = _assembly[tid][0]->side();
4661}
4662
4663void
4665{
4666 // NOTE: this will not work with h-adaptivity
4667 const Elem * neighbor = _assembly[tid][0]->neighbor();
4668 unsigned int neighbor_side =
4669 neighbor ? neighbor->which_neighbor_am_i(_assembly[tid][0]->elem()) : libMesh::invalid_uint;
4670
4671 if (!neighbor)
4672 {
4673 if (haveFV())
4674 {
4675 // If neighbor is null, then we're on the neighbor side of a mesh boundary, e.g. we're off
4676 // the mesh in ghost-land. If we're using the finite volume method, then variable values and
4677 // consequently material properties have well-defined values in this ghost region outside of
4678 // the mesh and we really do want to reinit our neighbor materials in this case. Since we're
4679 // off in ghost land it's safe to do swaps with `MaterialPropertyStorage` using the elem and
4680 // elem_side keys
4681 neighbor = _assembly[tid][0]->elem();
4682 neighbor_side = _assembly[tid][0]->side();
4683 mooseAssert(neighbor, "We should have an appropriate value for elem coming from Assembly");
4684 }
4685 else
4686 mooseError("neighbor is null in Assembly!");
4687 }
4688
4689 _neighbor_material_props.getMaterialData(tid).swapBack(*neighbor, neighbor_side);
4690}
4691
4692void
4693FEProblemBase::logAdd(const std::string & system,
4694 const std::string & name,
4695 const std::string & type,
4696 const InputParameters & params) const
4697{
4698 if (_verbose_setup != "false")
4699 _console << "[DBG] Adding " << system << " '" << name << "' of type " << type << std::endl;
4700 if (_verbose_setup == "extra")
4701 _console << params << std::endl;
4702}
4703
4704void
4706 const std::string & object_name,
4707 const std::string & var_param_name)
4708{
4709 // Due to objects like SolutionUserObject which manipulate libmesh objects
4710 // and variables directly at the back end, we need a default option here
4711 // which is going to be the pointer to the first solver system within this
4712 // problem
4713 unsigned int sys_num = 0;
4714 if (parameters.isParamValid(var_param_name))
4715 {
4716 const auto variable_name = parameters.varName(var_param_name, object_name);
4717 if (this->hasVariable(variable_name) || this->hasScalarVariable(variable_name))
4718 sys_num = getSystem(variable_name).number();
4719 }
4720 if (parameters.isParamValid("solver_sys"))
4721 {
4722 const auto var_sys_num = sys_num;
4723 sys_num = getSystemBase(parameters.get<SolverSystemName>("solver_sys")).number();
4724 if (sys_num != var_sys_num && parameters.isParamValid(var_param_name))
4725 mooseError("We dont support setting 'variable' to a variable that is not set to the same "
4726 "system as the 'solver_sys' parameter");
4727 }
4728
4729 if (_displaced_problem && parameters.have_parameter<bool>("use_displaced_mesh") &&
4730 parameters.get<bool>("use_displaced_mesh"))
4731 {
4732 parameters.set<SubProblem *>("_subproblem") = _displaced_problem.get();
4733 if (sys_num == _aux->number())
4734 parameters.set<SystemBase *>("_sys") = &_displaced_problem->systemBaseAuxiliary();
4735 else
4736 parameters.set<SystemBase *>("_sys") = &_displaced_problem->solverSys(sys_num);
4737 }
4738 else
4739 {
4740 // The object requested use_displaced_mesh, but it was overridden
4741 // due to there being no displacements variables in the [Mesh] block.
4742 // If that happened, update the value of use_displaced_mesh appropriately.
4743 if (!_displaced_problem && parameters.have_parameter<bool>("use_displaced_mesh") &&
4744 parameters.get<bool>("use_displaced_mesh"))
4745 parameters.set<bool>("use_displaced_mesh") = false;
4746
4747 parameters.set<SubProblem *>("_subproblem") = this;
4748
4749 if (sys_num == _aux->number())
4750 parameters.set<SystemBase *>("_sys") = _aux.get();
4751 else
4752 parameters.set<SystemBase *>("_sys") = _solver_systems[sys_num].get();
4753 }
4754}
4755
4756void
4758 const std::string & type) const
4759{
4760 if (hasUserObject(name))
4761 mooseError("A ",
4763 " already exists. You may not add a ",
4764 type,
4765 " by the same name.");
4766
4767#ifdef MOOSE_KOKKOS_ENABLED
4769 mooseError("A ",
4770 getKokkosUserObject<UserObjectBase>(name).typeAndName(),
4771 " already exists. You may not add a ",
4772 type,
4773 " by the same name.");
4774#endif
4775}
4776
4777void
4778FEProblemBase::addPostprocessor(const std::string & pp_name,
4779 const std::string & name,
4780 InputParameters & parameters)
4781{
4782#ifdef MOOSE_KOKKOS_ENABLED
4784 return addKokkosPostprocessor(pp_name, name, parameters);
4785#endif
4786
4787 checkUserObjectNameCollision(name, "Postprocessor");
4788
4789 addUserObject(pp_name, name, parameters);
4790}
4791
4792void
4793FEProblemBase::addVectorPostprocessor(const std::string & pp_name,
4794 const std::string & name,
4795 InputParameters & parameters)
4796{
4797#ifdef MOOSE_KOKKOS_ENABLED
4800#endif
4801
4802 checkUserObjectNameCollision(name, "VectorPostprocessor");
4803
4804 addUserObject(pp_name, name, parameters);
4805}
4806
4807void
4808FEProblemBase::addReporter(const std::string & type,
4809 const std::string & name,
4810 InputParameters & parameters)
4811{
4812#ifdef MOOSE_KOKKOS_ENABLED
4815#endif
4816
4818
4820}
4821
4822std::vector<std::shared_ptr<UserObject>>
4823FEProblemBase::addUserObject(const std::string & user_object_name,
4824 const std::string & name,
4825 InputParameters & parameters)
4826{
4827#ifdef MOOSE_KOKKOS_ENABLED
4829 {
4830 addKokkosUserObject(user_object_name, name, parameters);
4831 return {};
4832 }
4833#endif
4834
4835 parallel_object_only();
4836
4837 std::vector<std::shared_ptr<UserObject>> uos;
4838
4839 // Add the _subproblem and _sys parameters depending on use_displaced_mesh
4841
4842 for (const auto tid : make_range(numThreads()))
4843 {
4844 // Create the UserObject
4845 std::shared_ptr<UserObject> user_object =
4846 _factory.create<UserObject>(user_object_name, name, parameters, tid);
4847 logAdd("UserObject", name, user_object_name, parameters);
4848 uos.push_back(user_object);
4849
4850 if (tid != 0)
4851 user_object->setPrimaryThreadCopy(uos[0].get());
4852
4853 theWarehouse().add(user_object);
4854
4855 // Attempt to create all the possible UserObject types
4856 auto euo = std::dynamic_pointer_cast<ElementUserObject>(user_object);
4857 auto suo = std::dynamic_pointer_cast<SideUserObject>(user_object);
4858 auto isuo = std::dynamic_pointer_cast<InternalSideUserObject>(user_object);
4859 auto iuo = std::dynamic_pointer_cast<InterfaceUserObjectBase>(user_object);
4860 auto nuo = std::dynamic_pointer_cast<NodalUserObject>(user_object);
4861 auto duo = std::dynamic_pointer_cast<DomainUserObject>(user_object);
4862 auto guo = std::dynamic_pointer_cast<GeneralUserObject>(user_object);
4863 auto tguo = std::dynamic_pointer_cast<ThreadedGeneralUserObject>(user_object);
4864 auto muo = std::dynamic_pointer_cast<MortarUserObject>(user_object);
4865
4866 // Account for displaced mesh use
4867 if (_displaced_problem && parameters.get<bool>("use_displaced_mesh"))
4868 {
4869 // Whether to re-init or not depends on the attributes of the base classes.
4870 // For example, InterfaceUOBase has "_current_side_elem" and "_neighbor_elem"
4871 // so it needs to reinit on displaced neighbors and faces
4872 // _reinit_displaced_elem -> _current_elem will be reinited
4873 // _reinit_displaced_face -> _current_elem, lowerD if any and _current_side_elem to be
4874 // reinited _reinit_displaced_neighbor -> _current_elem, lowerD if any and _current_neighbor
4875 // to be reinited Note that as soon as you use materials on the displaced mesh, all three get
4876 // turned on.
4877 if (euo || nuo || duo)
4879 if (suo || duo || isuo || iuo)
4881 if (iuo || duo || isuo)
4883 }
4884
4885 // These objects only require one thread
4886 if ((guo && !tguo) || muo)
4887 break;
4888 }
4889
4890 // Add as a Functor if it is one. We usually need to add the user object from thread 0 as the
4891 // registered functor for all threads because when user objects are thread joined, generally only
4892 // the primary thread copy ends up with all the data
4893 for (const auto tid : make_range(numThreads()))
4894 {
4895 const decltype(uos)::size_type uo_index = uos.front()->needThreadedCopy() ? tid : 0;
4896 if (const auto functor = dynamic_cast<Moose::FunctorBase<Real> *>(uos[uo_index].get()))
4897 {
4898 this->addFunctor(name, *functor, tid);
4900 _displaced_problem->addFunctor(name, *functor, tid);
4901 }
4902 }
4903
4904 return uos;
4905}
4906
4907void
4908FEProblemBase::addFVInterpolationMethod(const std::string & method_type,
4909 const std::string & name,
4910 InputParameters & parameters)
4911{
4912 parallel_object_only();
4913
4915
4916 for (const auto tid : make_range(numThreads()))
4917 {
4918 auto method = _factory.create<FVInterpolationMethod>(method_type, name, parameters, tid);
4919 logAdd("FVInterpolationMethod", name, method_type, parameters);
4920 theWarehouse().add(method);
4921 }
4922}
4923
4924void
4925FEProblemBase::addFVGradientMethod(const std::string & method_type,
4926 const std::string & name,
4927 InputParameters & parameters)
4928{
4929 parallel_object_only();
4930
4932
4933 for (const auto tid : make_range(libMesh::n_threads()))
4934 {
4935 auto method = _factory.create<FVGradientMethod>(method_type, name, parameters, tid);
4936 logAdd("FVGradientMethod", name, method_type, parameters);
4937 theWarehouse().add(method);
4938 }
4939}
4940
4941const UserObject &
4942FEProblemBase::getUserObjectBase(const std::string & name, const THREAD_ID tid /* = 0 */) const
4943{
4944 std::vector<UserObject *> objs;
4945 theWarehouse()
4946 .query()
4947 .condition<AttribSystem>("UserObject")
4948 .condition<AttribThread>(tid)
4949 .condition<AttribName>(name)
4950 .queryInto(objs);
4951 if (objs.empty())
4952 {
4953 mooseAssert(getMooseApp().actionWarehouse().isTaskComplete("add_user_object"),
4954 "A UserObject getter was called before UserObjects have been constructed. The "
4955 "requested UserObject '" +
4956 name + "' may exist in the input file, but UserObjects are not available yet.");
4957
4958 mooseError("Unable to find user object with name '" + name + "'");
4959 }
4960 mooseAssert(objs.size() == 1, "Should only find one UO");
4961 return *(objs[0]);
4962}
4963
4964const Positions &
4965FEProblemBase::getPositionsObject(const std::string & name) const
4966{
4967 std::vector<Positions *> objs;
4968 theWarehouse()
4969 .query()
4970 .condition<AttribSystem>("UserObject")
4971 .condition<AttribName>(name)
4972 .queryInto(objs);
4973 if (objs.empty())
4974 mooseError("Unable to find Positions object with name '" + name + "'");
4975 mooseAssert(objs.size() == 1, "Should only find one Positions");
4976 return *(objs[0]);
4977}
4978
4979bool
4980FEProblemBase::hasUserObject(const std::string & name) const
4981{
4982 std::vector<UserObject *> objs;
4983 theWarehouse()
4984 .query()
4985 .condition<AttribSystem>("UserObject")
4986 .condition<AttribThread>(0)
4987 .condition<AttribName>(name)
4988 .queryInto(objs);
4989 return !objs.empty();
4990}
4991
4992const FVGradientMethod &
4993FEProblemBase::getFVGradientMethod(const GradientMethodName & name, const THREAD_ID tid) const
4994{
4995 std::vector<FVGradientMethod *> methods;
4996 theWarehouse()
4997 .query()
4998 .condition<AttribSystem>("FVGradientMethod")
4999 .condition<AttribThread>(tid)
5000 .condition<AttribName>(name)
5001 .queryInto(methods);
5002
5003 if (methods.empty())
5004 mooseError("Unable to find FVGradientMethod with name '", name, "'");
5005
5006 mooseAssert(methods.size() == 1, "Expected a single FVGradientMethod per thread");
5007 return *(methods[0]);
5008}
5009
5011FEProblemBase::getFVGradientMethod(const GradientMethodName & name, const THREAD_ID tid)
5012{
5013 return const_cast<FVGradientMethod &>(
5014 static_cast<const FEProblemBase &>(*this).getFVGradientMethod(name, tid));
5015}
5016
5017bool
5018FEProblemBase::hasFVGradientMethod(const GradientMethodName & name) const
5019{
5020 std::vector<FVGradientMethod *> methods;
5021 theWarehouse()
5022 .query()
5023 .condition<AttribSystem>("FVGradientMethod")
5024 .condition<AttribThread>(0)
5025 .condition<AttribName>(name)
5026 .queryInto(methods);
5027 return !methods.empty();
5028}
5029
5031FEProblemBase::getFVInterpolationMethod(const InterpolationMethodName & name,
5032 const THREAD_ID tid) const
5033{
5034 std::vector<FVInterpolationMethod *> methods;
5035 theWarehouse()
5036 .query()
5037 .condition<AttribSystem>("FVInterpolationMethod")
5038 .condition<AttribThread>(tid)
5039 .condition<AttribName>(name)
5040 .queryInto(methods);
5041
5042 if (methods.empty())
5043 {
5044 mooseAssert(getMooseApp().actionWarehouse().isTaskComplete("add_interpolation_method"),
5045 "An FVInterpolationMethod getter was called before FVInterpolationMethods have "
5046 "been constructed. If you are attempting to access this object in the constructor "
5047 "of another object then make sure that the FVInterpolationMethod is constructed "
5048 "before the object using it.");
5049
5050 mooseError("Unable to find FVInterpolationMethod with name '", name, "'");
5051 }
5052
5053 mooseAssert(methods.size() == 1, "Expected a single FVInterpolationMethod per thread");
5054 return *(methods[0]);
5055}
5056
5058FEProblemBase::getFVFaceInterpolationMethod(const InterpolationMethodName & name,
5059 const THREAD_ID tid) const
5060{
5061 const auto & method = getFVInterpolationMethod(name, tid);
5062 const auto * face_method = dynamic_cast<const FVFaceInterpolationMethod *>(&method);
5063
5064 if (!face_method)
5065 mooseError("FVInterpolationMethod '",
5066 name,
5067 "' (",
5068 method.type(),
5069 ") is not a scalar face interpolation method.");
5070
5071 return *face_method;
5072}
5073
5075FEProblemBase::getFVAdvectedInterpolationMethod(const InterpolationMethodName & name,
5076 const THREAD_ID tid) const
5077{
5078 const auto & method = getFVInterpolationMethod(name, tid);
5079 const auto * advected_method = dynamic_cast<const FVAdvectedInterpolationMethod *>(&method);
5080
5081 if (!advected_method)
5082 mooseError("FVInterpolationMethod '",
5083 name,
5084 "' (",
5085 method.type(),
5086 ") is not an advected interpolation method.");
5087
5088 return *advected_method;
5089}
5090
5091bool
5092FEProblemBase::hasFVInterpolationMethod(const InterpolationMethodName & name) const
5093{
5094 std::vector<FVInterpolationMethod *> methods;
5095 theWarehouse()
5096 .query()
5097 .condition<AttribSystem>("FVInterpolationMethod")
5098 .condition<AttribThread>(0)
5099 .condition<AttribName>(name)
5100 .queryInto(methods);
5101 return !methods.empty();
5102}
5103
5104bool
5109
5110const Postprocessor &
5111FEProblemBase::getPostprocessorObjectByName(const PostprocessorName & object_name,
5112 const THREAD_ID tid) const
5113{
5114 std::vector<Postprocessor *> objs;
5115 theWarehouse()
5116 .query()
5118 .condition<AttribThread>(tid)
5119 .condition<AttribName>(object_name)
5120 .queryInto(objs);
5121
5122 if (objs.empty())
5123 mooseError("Unable to find Postprocessor with name '", object_name, "'");
5124 mooseAssert(objs.size() == 1,
5125 "We shouldn't find more than one postprocessor object for a given name");
5126 return *(objs[0]);
5127}
5128
5129const PostprocessorValue &
5130FEProblemBase::getPostprocessorValueByName(const PostprocessorName & name,
5131 std::size_t t_index) const
5132{
5134 t_index);
5135}
5136
5137void
5138FEProblemBase::setPostprocessorValueByName(const PostprocessorName & name,
5139 const PostprocessorValue & value,
5140 std::size_t t_index)
5141{
5143 PostprocessorReporterName(name), value, t_index);
5144}
5145
5146bool
5147FEProblemBase::hasPostprocessor(const std::string & name) const
5148{
5149 mooseDeprecated("FEProblemBase::hasPostprocssor is being removed; use "
5150 "hasPostprocessorValueByName instead.");
5152}
5153
5156 const std::string & vector_name,
5157 std::size_t t_index) const
5158{
5160 VectorPostprocessorReporterName(object_name, vector_name), t_index);
5161}
5162
5163void
5165 const std::string & vector_name,
5166 const VectorPostprocessorValue & value,
5167 std::size_t t_index)
5168{
5170 VectorPostprocessorReporterName(object_name, vector_name), value, t_index);
5171}
5172
5173const VectorPostprocessor &
5175 const THREAD_ID tid) const
5176{
5177 std::vector<VectorPostprocessor *> objs;
5178 theWarehouse()
5179 .query()
5181 .condition<AttribThread>(tid)
5182 .condition<AttribName>(object_name)
5183 .queryInto(objs);
5184
5185 if (objs.empty())
5186 {
5187 mooseAssert(
5188 getMooseApp().actionWarehouse().isTaskComplete("add_vector_postprocessor"),
5189 "A VectorPostprocessor getter was called before VectorPostprocessors have been "
5190 "constructed. The requested VectorPostprocessor '" +
5191 object_name +
5192 "' may exist in the input file, but VectorPostprocessors are not available yet.");
5193
5194 mooseError("Unable to find VectorPostprocessor with name '", object_name, "'");
5195 }
5196 mooseAssert(objs.size() == 1,
5197 "We shouldn't find more than one vector postprocessor object for a given name");
5198 return *(objs[0]);
5199}
5200
5201void
5203{
5204 for (const auto & it : _multi_apps)
5205 {
5206 const auto & objects = it.second.getActiveObjects();
5207 for (const auto & obj : objects)
5208 obj->parentOutputPositionChanged();
5209 }
5210}
5211
5212void
5218
5219void
5221{
5222 // Initialize indicator aux variable fields
5224 {
5225 TIME_SECTION("computeIndicators", 1, "Computing Indicators");
5226
5227 // Internal side indicators may lead to creating a much larger sparsity pattern than dictated by
5228 // the actual finite element scheme (e.g. CFEM)
5229 const auto old_do_derivatives = ADReal::do_derivatives;
5230 ADReal::do_derivatives = false;
5231
5232 std::vector<std::string> fields;
5233
5234 // Indicator Fields
5235 const auto & indicators = _indicators.getActiveObjects();
5236 for (const auto & indicator : indicators)
5237 fields.push_back(indicator->name());
5238
5239 // InternalSideIndicator Fields
5240 const auto & internal_indicators = _internal_side_indicators.getActiveObjects();
5241 for (const auto & internal_indicator : internal_indicators)
5242 fields.push_back(internal_indicator->name());
5243
5244 _aux->zeroVariables(fields);
5245
5246 // compute Indicators
5247 ComputeIndicatorThread cit(*this);
5249 _aux->solution().close();
5250 _aux->update();
5251
5252 ComputeIndicatorThread finalize_cit(*this, true);
5254 _aux->solution().close();
5255 _aux->update();
5256
5257 ADReal::do_derivatives = old_do_derivatives;
5258 }
5259}
5260
5261void
5263{
5265 {
5266 TIME_SECTION("computeMarkers", 1, "Computing Markers");
5267
5268 std::vector<std::string> fields;
5269
5270 // Marker Fields
5271 const auto & markers = _markers.getActiveObjects();
5272 for (const auto & marker : markers)
5273 fields.push_back(marker->name());
5274
5275 _aux->zeroVariables(fields);
5276
5278
5279 for (THREAD_ID tid = 0; tid < numThreads(); ++tid)
5280 {
5281 const auto & markers = _markers.getActiveObjects(tid);
5282 for (const auto & marker : markers)
5283 marker->markerSetup();
5284 }
5285
5286 ComputeMarkerThread cmt(*this);
5288
5289 _aux->solution().close();
5290 _aux->update();
5291 }
5292}
5293
5294const ExecFlagType &
5299
5300void
5305
5306void
5308{
5309}
5310
5311void
5313{
5314 SubProblem::customSetup(exec_type);
5315
5316 if (_line_search)
5317 _line_search->customSetup(exec_type);
5318
5319 unsigned int n_threads = numThreads();
5320 for (THREAD_ID tid = 0; tid < n_threads; tid++)
5321 {
5322 _all_materials.customSetup(exec_type, tid);
5323 _functions.customSetup(exec_type, tid);
5324 }
5325
5326#ifdef MOOSE_KOKKOS_ENABLED
5327 _kokkos_functions.customSetup(exec_type);
5328#endif
5329
5330 _aux->customSetup(exec_type);
5331 for (auto & nl : _nl)
5332 nl->customSetup(exec_type);
5333
5335 _displaced_problem->customSetup(exec_type);
5336
5337 for (THREAD_ID tid = 0; tid < n_threads; tid++)
5338 {
5339 _internal_side_indicators.customSetup(exec_type, tid);
5340 _indicators.customSetup(exec_type, tid);
5341 _markers.customSetup(exec_type, tid);
5342 }
5343
5344 std::vector<UserObject *> userobjs;
5345 theWarehouse().query().condition<AttribSystem>("UserObject").queryIntoUnsorted(userobjs);
5346 for (auto obj : userobjs)
5347 obj->customSetup(exec_type);
5348
5349#ifdef MOOSE_KOKKOS_ENABLED
5350 {
5351 std::vector<UserObjectBase *> userobjs;
5352 theWarehouse().query().condition<AttribSystem>("KokkosUserObject").queryIntoUnsorted(userobjs);
5353 for (auto obj : userobjs)
5354 obj->customSetup(exec_type);
5355 }
5356#endif
5357
5358 _app.getOutputWarehouse().customSetup(exec_type);
5359}
5360
5361void
5363{
5364 // Set the current flag
5365 setCurrentExecuteOnFlag(exec_type);
5366
5367 if (exec_type != EXEC_INITIAL)
5368 executeControls(exec_type);
5369
5370 // intentially call this after executing controls because the setups may rely on the controls
5371 // FIXME: we skip the following flags because they have dedicated setup functions in
5372 // SetupInterface and it may not be appropriate to call them here.
5373 if (!(exec_type == EXEC_INITIAL || exec_type == EXEC_TIMESTEP_BEGIN ||
5374 exec_type == EXEC_SUBDOMAIN || exec_type == EXEC_NONLINEAR || exec_type == EXEC_LINEAR))
5375 customSetup(exec_type);
5376
5377 executeSamplers(exec_type);
5378
5379 // Pre-aux UserObjects
5381
5382 // Systems (includes system time derivative and aux kernel calculations)
5383 computeSystems(exec_type);
5384 // With the auxiliary system solution computed, sync the displaced problem auxiliary solution
5385 // before computation of post-aux user objects. The undisplaced auxiliary system current local
5386 // solution is updated (via System::update) within the AuxiliarySystem class's variable
5387 // computation methods (e.g. computeElementalVarsHelper, computeNodalVarsHelper), so it is safe to
5388 // use it here
5390 _displaced_problem->syncAuxSolution(*getAuxiliarySystem().currentSolution());
5391
5392 // Post-aux UserObjects
5394
5395 // Return the current flag to None
5397
5399 {
5400 // we will only check aux variables and postprocessors
5401 // checking more reporter data can be added in the future if needed
5402 std::unique_ptr<NumericVector<Number>> x = _aux->currentSolution()->clone();
5403 DenseVector<Real> pp_values = getReporterData().getAllRealReporterValues();
5404
5405 // call THIS execute one more time for checking the possible states
5407 FEProblemBase::execute(exec_type);
5408 _checking_uo_aux_state = false;
5409
5410 const Real check_tol = 1e-8;
5411
5412 const Real xnorm = x->l2_norm();
5413 *x -= *_aux->currentSolution();
5414 if (x->l2_norm() > check_tol * xnorm)
5415 {
5416 const auto & sys = _aux->system();
5417 const unsigned int n_vars = sys.n_vars();
5418 std::multimap<Real, std::string, std::greater<Real>> ordered_map;
5419 for (const auto i : make_range(n_vars))
5420 {
5421 const Real vnorm = sys.calculate_norm(*x, i, DISCRETE_L2);
5422 ordered_map.emplace(vnorm, sys.variable_name(i));
5423 }
5424
5425 std::ostringstream oss;
5426 for (const auto & [error_norm, var_name] : ordered_map)
5427 oss << " {" << var_name << ", " << error_norm << "},\n";
5428
5429 mooseError("Aux kernels, user objects appear to have states for aux variables on ",
5430 exec_type,
5431 ".\nVariable error norms in descending order:\n",
5432 oss.str());
5433 }
5434
5435 const DenseVector<Real> new_pp_values = getReporterData().getAllRealReporterValues();
5436 if (pp_values.size() != new_pp_values.size())
5437 mooseError("Second execution for uo/aux state check should not change the number of "
5438 "real reporter values");
5439
5440 const Real ppnorm = pp_values.l2_norm();
5441 pp_values -= new_pp_values;
5442 if (pp_values.l2_norm() > check_tol * ppnorm)
5443 {
5444 const auto pp_names = getReporterData().getAllRealReporterFullNames();
5445 std::multimap<Real, std::string, std::greater<Real>> ordered_map;
5446 for (const auto i : index_range(pp_names))
5447 ordered_map.emplace(std::abs(pp_values(i)), pp_names[i]);
5448
5449 std::ostringstream oss;
5450 for (const auto & [error_norm, pp_name] : ordered_map)
5451 oss << " {" << pp_name << ", " << error_norm << "},\n";
5452
5453 mooseError("Aux kernels, user objects appear to have states for real reporter values on ",
5454 exec_type,
5455 ".\nErrors of real reporter values in descending order:\n",
5456 oss.str());
5457 }
5458 }
5459}
5460
5461// Finalize, threadJoin, and update PP values of Elemental/Nodal/Side/InternalSideUserObjects
5462void
5464{
5465 std::vector<UserObject *> objs;
5466 query.queryInto(objs);
5467 if (!isgen)
5468 {
5469 // join all threaded user objects (i.e. not regular general user objects) to the primary
5470 // thread
5471 for (auto obj : objs)
5472 if (obj->primaryThreadCopy())
5473 obj->primaryThreadCopy()->threadJoin(*obj);
5474 }
5475
5476 query.condition<AttribThread>(0).queryInto(objs);
5477
5478 // finalize objects and retrieve/store any postprocessor values
5479 for (auto obj : objs)
5480 {
5481 if (isgen && dynamic_cast<ThreadedGeneralUserObject *>(obj))
5482 continue;
5483 if (isgen)
5484 {
5485 // general user objects are not run in their own threaded loop object - so run them here
5486 if (shouldPrintExecution(0))
5487 _console << "[DBG] Initializing, executing & finalizing general UO '" << obj->name()
5488 << "' on " << _current_execute_on_flag.name() << std::endl;
5489 obj->initialize();
5490 obj->execute();
5491 }
5492
5493 obj->finalize();
5494
5495 // These have to be stored piecemeal (with every call to this function) because general
5496 // postprocessors (which run last after other userobjects have been completed) might depend on
5497 // them being stored. This wouldn't be a problem if all userobjects satisfied the dependency
5498 // resolver interface and could be sorted appropriately with the general userobjects, but they
5499 // don't.
5500 auto pp = dynamic_cast<const Postprocessor *>(obj);
5501 if (pp)
5502 {
5503 _reporter_data.finalize(obj->name());
5504 setPostprocessorValueByName(obj->name(), pp->getValue());
5505 }
5506
5507 auto vpp = dynamic_cast<VectorPostprocessor *>(obj);
5508 if (vpp)
5509 _reporter_data.finalize(obj->name());
5510
5511 // Update Reporter data
5512 auto reporter = dynamic_cast<Reporter *>(obj);
5513 if (reporter)
5514 _reporter_data.finalize(obj->name());
5515 }
5516}
5517
5519FEProblemBase::getUOQuery(const std::string & system,
5520 const ExecFlagType & type,
5521 const Moose::AuxGroup & group) const
5522{
5524 theWarehouse().query().condition<AttribSystem>(system).condition<AttribExecOns>(type);
5525
5526 if (group == Moose::PRE_IC)
5527 query.condition<AttribPreIC>(true);
5528 else if (group == Moose::PRE_AUX)
5529 query.condition<AttribPreAux>(type);
5530 else if (group == Moose::POST_AUX)
5531 query.condition<AttribPostAux>(type);
5532
5533 return query;
5534}
5535
5536void
5538 std::set<int> & execution_groups) const
5539{
5540 std::vector<UserObjectBase *> uos;
5541 query.queryIntoUnsorted(uos);
5542 for (const auto & uo : uos)
5543 execution_groups.insert(uo->getParam<int>("execution_order_group"));
5544}
5545
5546void
5548 const Moose::AuxGroup & group,
5549 const std::string & name)
5550{
5551 const auto old_exec_flag = _current_execute_on_flag;
5553
5554 std::set<int> execution_groups;
5555
5556#ifdef MOOSE_KOKKOS_ENABLED
5557 TheWarehouse::Query kokkos_query =
5558 getUOQuery("KokkosUserObject", type, group).condition<AttribName>(name);
5559 getUOExecutionGroups(kokkos_query, execution_groups);
5560#endif
5561
5563 getUOExecutionGroups(query, execution_groups);
5564
5565 for (const auto execution_group : execution_groups)
5566 {
5567#ifdef MOOSE_KOKKOS_ENABLED
5569 type, kokkos_query.clone().condition<AttribExecutionOrderGroup>(execution_group));
5570#endif
5571
5573 query.clone().condition<AttribExecutionOrderGroup>(execution_group));
5574 }
5575
5576 _current_execute_on_flag = old_exec_flag;
5577}
5578
5579void
5581{
5582 std::set<int> execution_groups;
5583
5584#ifdef MOOSE_KOKKOS_ENABLED
5585 TheWarehouse::Query kokkos_query = getUOQuery("KokkosUserObject", type, group);
5586 getUOExecutionGroups(kokkos_query, execution_groups);
5587#endif
5588
5589 TheWarehouse::Query query = getUOQuery("UserObject", type, group);
5590 getUOExecutionGroups(query, execution_groups);
5591
5592 for (const auto execution_group : execution_groups)
5593 {
5594#ifdef MOOSE_KOKKOS_ENABLED
5596 type, kokkos_query.clone().condition<AttribExecutionOrderGroup>(execution_group));
5597#endif
5598
5600 query.clone().condition<AttribExecutionOrderGroup>(execution_group));
5601 }
5602
5603 // Exceptions raised on solver execution flags are communicated and handled by the PARALLEL_CATCH
5604 // surrounding the assembly loops of the residual, Jacobian and linear systems. On all other
5605 // execution flags there is no solve left to fail, so the exception is communicated here in order
5606 // to report it at the point of the simulation where it was raised
5609}
5610
5611void
5613{
5614 try
5615 {
5616 TIME_SECTION("computeUserObjects", 1, "Computing User Objects");
5617
5618 std::vector<GeneralUserObject *> genobjs;
5619 query.clone().condition<AttribInterfaces>(Interfaces::GeneralUserObject).queryInto(genobjs);
5620
5621 std::vector<UserObject *> userobjs;
5622 query.clone()
5626 .queryInto(userobjs);
5627
5628 std::vector<UserObject *> tgobjs;
5629 query.clone()
5631 .queryInto(tgobjs);
5632
5633 std::vector<UserObject *> nodal;
5634 query.clone().condition<AttribInterfaces>(Interfaces::NodalUserObject).queryInto(nodal);
5635
5636 std::vector<MortarUserObject *> mortar;
5637 query.clone().condition<AttribInterfaces>(Interfaces::MortarUserObject).queryInto(mortar);
5638
5639 if (userobjs.empty() && genobjs.empty() && tgobjs.empty() && nodal.empty() && mortar.empty())
5640 return;
5641
5642 // Start the timer here since we have at least one active user object
5643 std::string compute_uo_tag = "computeUserObjects(" + Moose::stringify(type) + ")";
5644
5645 // Perform Residual/Jacobian setups
5646 if (type == EXEC_LINEAR)
5647 {
5648 for (auto obj : userobjs)
5649 obj->residualSetup();
5650 for (auto obj : nodal)
5651 obj->residualSetup();
5652 for (auto obj : mortar)
5653 obj->residualSetup();
5654 for (auto obj : tgobjs)
5655 obj->residualSetup();
5656 for (auto obj : genobjs)
5657 obj->residualSetup();
5658 }
5659 else if (type == EXEC_NONLINEAR)
5660 {
5661 for (auto obj : userobjs)
5662 obj->jacobianSetup();
5663 for (auto obj : nodal)
5664 obj->jacobianSetup();
5665 for (auto obj : mortar)
5666 obj->jacobianSetup();
5667 for (auto obj : tgobjs)
5668 obj->jacobianSetup();
5669 for (auto obj : genobjs)
5670 obj->jacobianSetup();
5671 }
5672
5673 for (auto obj : userobjs)
5674 obj->initialize();
5675
5676 // Execute Side/InternalSide/Interface/Elemental/DomainUserObjects
5677 if (!userobjs.empty())
5678 {
5679 // non-nodal user objects have to be run separately before the nodal user objects run
5680 // because some nodal user objects (NodalNormal related) depend on elemental user objects
5681 // :-(
5682 ComputeUserObjectsThread cppt(*this, query);
5684
5685 // There is one instance in rattlesnake where an elemental user object's finalize depends
5686 // on a side user object having been finalized first :-(
5693 }
5694
5695 // if any elemental user object may have written to variables we need to close the aux solution
5696 for (const auto & uo : userobjs)
5697 if (auto euo = dynamic_cast<const ElementUserObject *>(uo);
5698 euo && euo->hasWritableCoupledVariables())
5699 {
5700 _aux->solution().close();
5701 _aux->system().update();
5702 break;
5703 }
5704
5705 // Execute NodalUserObjects
5706 // BISON has an axial reloc elemental user object that has a finalize func that depends on a
5707 // nodal user object's prev value. So we can't initialize this until after elemental objects
5708 // have been finalized :-(
5709 for (auto obj : nodal)
5710 obj->initialize();
5711 if (query.clone().condition<AttribInterfaces>(Interfaces::NodalUserObject).count() > 0)
5712 {
5716 }
5717
5718 // if any nodal user object may have written to variables we need to close the aux solution
5719 for (const auto & uo : nodal)
5720 if (auto nuo = dynamic_cast<const NodalUserObject *>(uo);
5721 nuo && nuo->hasWritableCoupledVariables())
5722 {
5723 _aux->solution().close();
5724 _aux->system().update();
5725 break;
5726 }
5727
5728 // Execute MortarUserObjects
5729 {
5730 for (auto obj : mortar)
5731 obj->initialize();
5732 if (!mortar.empty())
5733 {
5734 auto create_and_run_mortar_functors = [this, type, &mortar](const bool displaced)
5735 {
5736 // go over mortar interfaces and construct functors
5737 const auto & mortar_interfaces = getMortarInterfaces(displaced);
5738 for (const auto & [primary_secondary_boundary_pair, interface_config] : mortar_interfaces)
5739 {
5740 auto mortar_uos_to_execute =
5741 getMortarUserObjects(primary_secondary_boundary_pair.first,
5742 primary_secondary_boundary_pair.second,
5743 displaced,
5744 mortar);
5745
5746 auto * const subproblem = displaced ? cast_ptr<SubProblem *>(_displaced_problem.get())
5747 : cast_ptr<SubProblem *>(this);
5748 MortarUserObjectThread muot(mortar_uos_to_execute,
5749 *interface_config.amg,
5750 *subproblem,
5751 *this,
5752 displaced,
5753 subproblem->assembly(0, 0));
5754
5755 muot();
5756 }
5757 };
5758
5759 create_and_run_mortar_functors(false);
5761 create_and_run_mortar_functors(true);
5762 }
5763 for (auto obj : mortar)
5764 obj->finalize();
5765 }
5766
5767 // Execute threaded general user objects
5768 for (auto obj : tgobjs)
5769 obj->initialize();
5770 std::vector<GeneralUserObject *> tguos_zero;
5771 query.clone()
5772 .condition<AttribThread>(0)
5773 .condition<AttribInterfaces>(Interfaces::ThreadedGeneralUserObject)
5774 .queryInto(tguos_zero);
5775 for (auto obj : tguos_zero)
5776 {
5777 std::vector<GeneralUserObject *> tguos;
5778 auto q = query.clone()
5779 .condition<AttribName>(obj->name())
5780 .condition<AttribInterfaces>(Interfaces::ThreadedGeneralUserObject);
5781 q.queryInto(tguos);
5782
5784
5785 // Force one thread per ThreadedGeneralUserObject via grainsize
5787 tguos.end(),
5788 /*grainsize=*/1),
5789 ctguot,
5790 numThreads());
5791 joinAndFinalize(q);
5792 }
5793
5794 // Execute general user objects
5796 }
5797 catch (...)
5798 {
5799 handleException("computeUserObjectsInternal");
5800 }
5801}
5802
5803void
5805{
5806 if (_control_warehouse[exec_type].hasActiveObjects())
5807 {
5808 TIME_SECTION("executeControls", 1, "Executing Controls");
5809
5811
5812 auto controls_wh = _control_warehouse[exec_type];
5813 // Add all of the dependencies into the resolver and sort them
5814 for (const auto & it : controls_wh.getActiveObjects())
5815 {
5816 // Make sure an item with no dependencies comes out too!
5817 resolver.addItem(it);
5818
5819 std::vector<std::string> & dependent_controls = it->getDependencies();
5820 for (const auto & depend_name : dependent_controls)
5821 {
5822 if (controls_wh.hasActiveObject(depend_name))
5823 {
5824 auto dep_control = controls_wh.getActiveObject(depend_name);
5825 resolver.addEdge(dep_control, it);
5826 }
5827 else
5828 mooseError("The Control \"",
5829 depend_name,
5830 "\" was not created, did you make a "
5831 "spelling mistake or forget to include it "
5832 "in your input file?");
5833 }
5834 }
5835
5836 const auto & ordered_controls = resolver.getSortedValues();
5837
5838 if (!ordered_controls.empty())
5839 {
5840 // already called by initialSetup when exec_type == EXEC_INITIAL
5841 if (exec_type != EXEC_INITIAL)
5842 _control_warehouse.setup(exec_type);
5843
5844 // Run the controls in the proper order
5845 for (const auto & control : ordered_controls)
5846 control->execute();
5847 }
5848 }
5849}
5850
5851void
5853{
5854 // TODO: This should be done in a threaded loop, but this should be super quick so for now
5855 // do a serial loop.
5856 for (THREAD_ID tid = 0; tid < numThreads(); ++tid)
5857 {
5858 std::vector<Sampler *> objects;
5859 theWarehouse()
5860 .query()
5861 .condition<AttribSystem>("Sampler")
5862 .condition<AttribThread>(tid)
5863 .condition<AttribExecOns>(exec_type)
5864 .queryInto(objects);
5865
5866 if (!objects.empty())
5867 {
5868 TIME_SECTION("executeSamplers", 1, "Executing Samplers");
5869 FEProblemBase::objectSetupHelper<Sampler>(objects, exec_type);
5870 FEProblemBase::objectExecuteHelper<Sampler>(objects);
5871 }
5872 }
5873}
5874
5875void
5877{
5878 TIME_SECTION("updateActiveObjects", 5, "Updating Active Objects");
5879
5880 for (THREAD_ID tid = 0; tid < numThreads(); ++tid)
5881 {
5882 for (auto & nl : _nl)
5883 nl->updateActive(tid);
5884 _aux->updateActive(tid);
5891 }
5892
5900
5901#ifdef MOOSE_KOKKOS_ENABLED
5903#endif
5904}
5905
5906void
5908{
5909 //<< "Object " << a->name() << " -> " << b->name() << std::endl;
5910}
5911
5912void
5914{
5915 TIME_SECTION("reinitBecauseOfGhostingOrNewGeomObjects",
5916 3,
5917 "Reinitializing Because of Geometric Search Objects");
5918
5919 // Need to see if _any_ processor has ghosted elems or geometry objects.
5920 bool needs_reinit = !_ghosted_elems.empty();
5921 needs_reinit = needs_reinit || !_geometric_search_data._nearest_node_locators.empty() ||
5922 (_mortar_data->hasObjects() && mortar_changed);
5923 needs_reinit =
5924 needs_reinit || (_displaced_problem &&
5925 (!_displaced_problem->geomSearchData()._nearest_node_locators.empty() ||
5926 (_mortar_data->hasDisplacedObjects() && mortar_changed)));
5927 _communicator.max(needs_reinit);
5928
5929 if (needs_reinit)
5930 {
5931 // Call reinit to get the ghosted vectors correct now that some geometric search has been done
5932 es().reinit();
5933
5934 if (_displaced_mesh)
5935 _displaced_problem->es().reinit();
5936 }
5937}
5938
5939void
5940FEProblemBase::addDamper(const std::string & damper_name,
5941 const std::string & name,
5942 InputParameters & parameters)
5943{
5944 parallel_object_only();
5945
5946 const auto nl_sys_num =
5947 parameters.isParamValid("variable")
5948 ? determineSolverSystem(parameters.varName("variable", name), true).second
5949 : (unsigned int)0;
5950
5951 if (!isSolverSystemNonlinear(nl_sys_num))
5952 mooseError("You are trying to add a DGKernel to a linear variable/system, which is not "
5953 "supported at the moment!");
5954
5955 parameters.set<SubProblem *>("_subproblem") = this;
5956 parameters.set<SystemBase *>("_sys") = _nl[nl_sys_num].get();
5957
5958 _has_dampers = true;
5959 logAdd("Damper", name, damper_name, parameters);
5960 _nl[nl_sys_num]->addDamper(damper_name, name, parameters);
5961}
5962
5963void
5965{
5966 for (auto & nl : _nl)
5967 nl->setupDampers();
5968}
5969
5970void
5971FEProblemBase::addIndicator(const std::string & indicator_name,
5972 const std::string & name,
5973 InputParameters & parameters)
5974{
5975 parallel_object_only();
5976
5977 if (_displaced_problem && parameters.get<bool>("use_displaced_mesh"))
5978 {
5979 parameters.set<SubProblem *>("_subproblem") = _displaced_problem.get();
5980 parameters.set<SystemBase *>("_sys") = &_displaced_problem->auxSys();
5982 }
5983 else
5984 {
5985 if (_displaced_problem == nullptr && parameters.get<bool>("use_displaced_mesh"))
5986 {
5987 // We allow Indicators to request that they use_displaced_mesh,
5988 // but then be overridden when no displacements variables are
5989 // provided in the Mesh block. If that happened, update the value
5990 // of use_displaced_mesh appropriately for this Indicator.
5991 if (parameters.have_parameter<bool>("use_displaced_mesh"))
5992 parameters.set<bool>("use_displaced_mesh") = false;
5993 }
5994
5995 parameters.set<SubProblem *>("_subproblem") = this;
5996 parameters.set<SystemBase *>("_sys") = _aux.get();
5997 }
5998
5999 for (THREAD_ID tid = 0; tid < numThreads(); tid++)
6000 {
6001 std::shared_ptr<Indicator> indicator =
6002 _factory.create<Indicator>(indicator_name, name, parameters, tid);
6003 logAdd("Indicator", name, indicator_name, parameters);
6004 std::shared_ptr<InternalSideIndicatorBase> isi =
6005 std::dynamic_pointer_cast<InternalSideIndicatorBase>(indicator);
6006 if (isi)
6008 else
6009 _indicators.addObject(indicator, tid);
6010 }
6011}
6012
6013void
6014FEProblemBase::addMarker(const std::string & marker_name,
6015 const std::string & name,
6016 InputParameters & parameters)
6017{
6018 parallel_object_only();
6019
6020 if (_displaced_problem && parameters.get<bool>("use_displaced_mesh"))
6021 {
6022 parameters.set<SubProblem *>("_subproblem") = _displaced_problem.get();
6023 parameters.set<SystemBase *>("_sys") = &_displaced_problem->auxSys();
6025 }
6026 else
6027 {
6028 if (_displaced_problem == nullptr && parameters.get<bool>("use_displaced_mesh"))
6029 {
6030 // We allow Markers to request that they use_displaced_mesh,
6031 // but then be overridden when no displacements variables are
6032 // provided in the Mesh block. If that happened, update the value
6033 // of use_displaced_mesh appropriately for this Marker.
6034 if (parameters.have_parameter<bool>("use_displaced_mesh"))
6035 parameters.set<bool>("use_displaced_mesh") = false;
6036 }
6037
6038 parameters.set<SubProblem *>("_subproblem") = this;
6039 parameters.set<SystemBase *>("_sys") = _aux.get();
6040 }
6041
6042 for (THREAD_ID tid = 0; tid < numThreads(); tid++)
6043 {
6044 std::shared_ptr<Marker> marker = _factory.create<Marker>(marker_name, name, parameters, tid);
6045 logAdd("Marker", name, marker_name, parameters);
6046 _markers.addObject(marker, tid);
6047 }
6048}
6049
6050void
6051FEProblemBase::addMultiApp(const std::string & multi_app_name,
6052 const std::string & name,
6053 InputParameters & parameters)
6054{
6055 parallel_object_only();
6056
6057 parameters.set<MPI_Comm>("_mpi_comm") = _communicator.get();
6058
6059 if (_displaced_problem && parameters.get<bool>("use_displaced_mesh"))
6060 {
6061 parameters.set<SubProblem *>("_subproblem") = _displaced_problem.get();
6062 parameters.set<SystemBase *>("_sys") = &_displaced_problem->auxSys();
6064 }
6065 else
6066 {
6067 if (_displaced_problem == nullptr && parameters.get<bool>("use_displaced_mesh"))
6068 {
6069 // We allow MultiApps to request that they use_displaced_mesh,
6070 // but then be overridden when no displacements variables are
6071 // provided in the Mesh block. If that happened, update the value
6072 // of use_displaced_mesh appropriately for this MultiApp.
6073 if (parameters.have_parameter<bool>("use_displaced_mesh"))
6074 parameters.set<bool>("use_displaced_mesh") = false;
6075 }
6076
6077 parameters.set<SubProblem *>("_subproblem") = this;
6078 parameters.set<SystemBase *>("_sys") = _aux.get();
6079 }
6080
6081 std::shared_ptr<MultiApp> multi_app = _factory.create<MultiApp>(multi_app_name, name, parameters);
6082 logAdd("MultiApp", name, multi_app_name, parameters);
6083 multi_app->possiblyCreateChildApplications();
6084
6085 _multi_apps.addObject(multi_app);
6086
6087 // Store TransientMultiApp objects in another container, this is needed for calling computeDT
6088 std::shared_ptr<TransientMultiApp> trans_multi_app =
6089 std::dynamic_pointer_cast<TransientMultiApp>(multi_app);
6090 if (trans_multi_app)
6091 _transient_multi_apps.addObject(trans_multi_app);
6092}
6093
6094bool
6099
6100bool
6101FEProblemBase::hasMultiApp(const std::string & multi_app_name) const
6102{
6103 return _multi_apps.hasActiveObject(multi_app_name);
6104}
6105
6106std::shared_ptr<MultiApp>
6107FEProblemBase::getMultiApp(const std::string & multi_app_name) const
6108{
6109 if (!hasMultiApp(multi_app_name))
6110 mooseAssert(getMooseApp().actionWarehouse().isTaskComplete("add_multi_app"),
6111 "A MultiApp getter was called before MultiApps have been constructed. "
6112 "If you are attempting to access this object in the constructor of another object "
6113 "then make sure that the MultiApp is constructed before the object using it.");
6114
6115 return _multi_apps.getObject(multi_app_name);
6116}
6117
6118void
6120 Transfer::DIRECTION direction,
6121 const MultiAppName & source_app)
6122{
6123 // Keep track of whether a transfer is actually executed to avoid extraneous console output
6124 bool is_executing_a_transfer = false;
6125 bool to_multiapp = direction == MultiAppTransfer::TO_MULTIAPP;
6126 bool from_multiapp = direction == MultiAppTransfer::FROM_MULTIAPP;
6127
6128 // Build console output
6129 std::string string_direction;
6130 std::string additional_source_info = "";
6131 if (to_multiapp)
6132 string_direction = " To ";
6133 else if (from_multiapp)
6134 string_direction = " From ";
6135 else
6136 string_direction = " Between ";
6137 if (!source_app.empty())
6138 additional_source_info = " from app '" + source_app + "'";
6139
6140 // This lambda only checks the source app, since the exec_type selection is done in the warehouse
6141 auto executeThisTransfer = [this, &direction, &source_app, &type](auto & transfer)
6142 {
6143 mooseAssert(transfer->getExecuteOnEnum().contains(type), "Should execute on this schedule");
6144 // no restriction / ordering groups on transfers from parent to child at this time
6145 if (direction != MultiAppTransfer::BETWEEN_MULTIAPP)
6146 return true;
6147 // on sibling transfers, we can delay until the app has been executed if the transfer is set
6148 // that way.
6149 if (transfer->getFromName() == source_app && transfer->executeAfterSiblingSourceApp())
6150 {
6151 libmesh_ignore(this);
6152 mooseAssert(this->getMultiApp(transfer->getFromName())->getExecuteOnEnum().contains(type),
6153 "from_multiapp should also execute on this schedule");
6154 }
6155 // Execute if:
6156 // - transfer is set execute before from_multiapp, and we are calling this before source apps
6157 // - from_multiapp app is not executing on this execute_on
6158 // - from_multiapp just executed (set to source app)
6159 if ((source_app.empty() && (!transfer->executeAfterSiblingSourceApp() ||
6160 !transfer->getFromMultiApp()->getExecuteOnEnum().contains(type))) ||
6161 (transfer->getFromName() == source_app && transfer->executeAfterSiblingSourceApp()))
6162 return true;
6163 return false;
6164 };
6165
6167 : from_multiapp ? _from_multi_app_transfers[type]
6169
6170 if (wh.hasActiveObjects())
6171 {
6172 TIME_SECTION("execMultiAppTransfers", 1, "Executing Transfers");
6173
6174 const auto & transfers = wh.getActiveObjects();
6175
6177 {
6179 {"Name", "Type", "From", "To"});
6180
6181 // Build Table of Transfer Info
6182 for (const auto & transfer : transfers)
6183 {
6184 auto multiapp_transfer = dynamic_cast<MultiAppTransfer *>(transfer.get());
6185
6186 // Don't add transfer to table if it won't execute
6187 if (!executeThisTransfer(multiapp_transfer))
6188 continue;
6189
6190 is_executing_a_transfer = true;
6191 table.addRow(multiapp_transfer->name(),
6192 multiapp_transfer->type(),
6193 multiapp_transfer->getFromName(),
6194 multiapp_transfer->getToName());
6195 }
6196
6197 // Print it
6198 if (is_executing_a_transfer)
6199 {
6200 _console << COLOR_CYAN << "\nTransfers on " << Moose::stringify(type) << string_direction
6201 << "MultiApps" << additional_source_info << COLOR_DEFAULT << ":" << std::endl;
6202
6203 table.print(_console);
6204 }
6205 }
6206
6207 for (const auto & transfer : transfers)
6208 {
6209 auto multiapp_transfer = libMesh::cast_ptr<MultiAppTransfer *>(transfer.get());
6210 if (!executeThisTransfer(multiapp_transfer))
6211 continue;
6212
6213 transfer->setCurrentDirection(direction);
6214 transfer->execute();
6215 }
6216
6218
6219 if (_verbose_multiapps && is_executing_a_transfer)
6220 _console << COLOR_CYAN << "Transfers on " << Moose::stringify(type) << " Are Finished\n"
6221 << COLOR_DEFAULT << std::endl;
6222 }
6223
6224 if (_multi_apps[type].getActiveObjects().size() && !is_executing_a_transfer && _verbose_multiapps)
6225 _console << COLOR_CYAN << "\nNo Transfers on " << Moose::stringify(type) << string_direction
6226 << "MultiApps\n"
6227 << COLOR_DEFAULT << std::endl;
6228}
6229
6230std::vector<std::shared_ptr<Transfer>>
6240
6241std::vector<std::shared_ptr<Transfer>>
6251
6254{
6255 if (direction == MultiAppTransfer::TO_MULTIAPP)
6257 else if (direction == MultiAppTransfer::FROM_MULTIAPP)
6259 else
6261}
6262
6263void
6265{
6267 return;
6268
6269 // Group the multiapps by execution order group. Only position-based multiapps are partitioned
6270 // here; sampler-style (non-positions) multiapps assign their own rank configuration.
6271 std::map<unsigned int, std::vector<std::shared_ptr<MultiApp>>> groups;
6272 for (const auto & multi_app : _multi_apps.getActiveObjects())
6273 if (multi_app->usingPositions())
6274 groups[multi_app->getParam<unsigned int>("execution_order_group")].push_back(multi_app);
6275
6276 // For the MultiApps that are using samplers, their partitioning is already handled there
6277 // so we just skipped them. But if they were to share an execution_order_group, we would crash
6278 // if using concurrent multiapps. So let's error.
6279 // For any other MultiApps that are not using positions, we would just need them to know
6280 // numGlobalApps() to benefit from this concurrent partitioning. We can allow them here in the
6281 // future.
6282 std::map<unsigned int, std::vector<std::shared_ptr<MultiApp>>> check_groups;
6283 for (const auto & multi_app : _multi_apps.getActiveObjects())
6284 check_groups[multi_app->getParam<unsigned int>("execution_order_group")].push_back(multi_app);
6285 for (const auto & [group_id, group] : check_groups)
6286 for (const auto & multi_app : group)
6287 if (group.size() > 1 && !multi_app->usingPositions())
6288 multi_app->paramError(
6289 "execution_order_group",
6290 "This MultiApp must be placed in its own execution order group as concurrent execution "
6291 "has not been implemented for this type of app at this time");
6292
6293 const auto n_procs = n_processors();
6294 const auto my_rank = processor_id();
6295
6296 for (const auto & [group_id, group] : groups)
6297 {
6298 // Nothing to run concurrently unless the group has more than one multiapp
6299 if (group.size() < 2)
6300 continue;
6301
6302 // Number of ranks handed to each multiapp. Start each at its per-app minimum (at least one
6303 // rank), then distribute the rest; caps prevent giving a multiapp more ranks than it could
6304 // spread its apps over at 'max_procs_per_app'. With the defaults (min 1, max unbounded) this
6305 // is just an even split.
6306 std::vector<processor_id_type> count(group.size());
6307 std::vector<processor_id_type> caps(group.size());
6308 std::vector<processor_id_type> mins(group.size());
6309 std::vector<processor_id_type> maxs(group.size());
6310 processor_id_type min_total = 0;
6311 for (const auto m : index_range(group))
6312 {
6313 // Each multiapp needs at least one rank, so a 'min_procs_per_app' of 0 is treated as 1
6314 mins[m] = group[m]->getParam<processor_id_type>("min_procs_per_app");
6315 maxs[m] = group[m]->getParam<processor_id_type>("max_procs_per_app");
6316 const auto n_apps_m = cast_int<processor_id_type>(group[m]->numGlobalApps());
6317 caps[m] = (maxs[m] >= n_procs) ? n_procs : std::min(n_procs, n_apps_m * maxs[m]);
6318 count[m] = mins[m];
6319 min_total += mins[m];
6320 }
6321
6322 if (min_total > n_procs)
6323 mooseError("Not enough MPI ranks to run the ",
6324 group.size(),
6325 " multiapps of 'execution_order_group' ",
6326 group_id,
6327 " concurrently: they need at least ",
6328 min_total,
6329 " ranks (from 'min_procs_per_app') but only ",
6330 n_procs,
6331 " are available. Reduce the number of concurrent multiapps, lower "
6332 "'min_procs_per_app', or run with more processors.");
6333
6334 // Hand out the remaining ranks round-robin to multiapps still below their cap
6335 processor_id_type remaining = n_procs - min_total;
6336 bool progress = true;
6337 while (remaining > 0 && progress)
6338 {
6339 progress = false;
6340 for (const auto m : index_range(group))
6341 if (remaining > 0 && count[m] < caps[m])
6342 {
6343 count[m]++;
6344 remaining--;
6345 progress = true;
6346 }
6347 }
6348 // Any leftover ranks (all multiapps already at their cap) simply run no app in this group.
6349
6350 // Assign each multiapp a contiguous, disjoint rank range and (re)initialize it on that range.
6351 // This is collective: every rank calls init() (hence buildComm's split) for every multiapp.
6352 processor_id_type offset = 0;
6353 for (const auto m : index_range(group))
6354 {
6355 LocalRankConfig cfg{0, 0, 0, 0, false, 0};
6356 if (my_rank >= offset && my_rank < offset + count[m])
6357 cfg = rankConfig(
6358 my_rank - offset, count[m], group[m]->numGlobalApps(), mins[m], maxs[m], false);
6359 group[m]->init(group[m]->numGlobalApps(), cfg);
6360 offset += count[m];
6361 }
6362 }
6363}
6364
6365bool
6367{
6368 // Active MultiApps
6369 const std::vector<MooseSharedPointer<MultiApp>> & multi_apps =
6370 _multi_apps[exec_on].getActiveObjects();
6371
6372 // Do anything that needs to be done to Apps before transfers
6373 for (const auto & multi_app : multi_apps)
6374 multi_app->preTransfer(_dt, _time);
6375
6376 // Execute Transfers _to_ MultiApps
6378
6379 // Execute Transfers _beween_ MultiApps for the multiapps that don't execute on this flag
6380 // NOTE: there is usually no need to execute a transfer unless the multiapp providing its
6381 // data also executed. But we need to obey what the user requested for the execution schedule,
6382 // hence the two executions
6384
6385 // Order the multiapps based on their execution group
6386 // Build the ordered multiapp groups
6387 std::map<unsigned int, std::vector<MooseSharedPointer<MultiApp>>> ordered_multi_apps;
6388
6389 for (const auto & multi_app : multi_apps)
6390 ordered_multi_apps[multi_app->getParam<unsigned int>("execution_order_group")].push_back(
6391 multi_app);
6392
6393 // Check that concurrent multiapps will even be used
6394 if (multi_apps.size() && _num_concurrent_multiapps > 1)
6395 {
6396 bool has_concurrent_apps = false;
6397 for (const auto & [group, multi_app_group] : ordered_multi_apps)
6398 if (multi_app_group.size() > 1)
6399 has_concurrent_apps = true;
6400 if (!has_concurrent_apps)
6401 paramInfo(
6402 "num_concurrent_multiapps",
6403 "Due to the specified multiapp execution groups, or differences in execution schedules, "
6404 "concurrent multiapps are not actually used on " +
6405 Moose::stringify(exec_on));
6406 }
6407
6408 // Execute MultiApps
6409 if (multi_apps.size())
6410 {
6411 TIME_SECTION("execMultiApps", 1, "Executing MultiApps", false);
6412
6414 _console << COLOR_CYAN << "\nExecuting MultiApps on " << Moose::stringify(exec_on)
6415 << COLOR_DEFAULT << std::endl;
6416
6417 bool success = true;
6418
6419 for (const auto & [group_id, multi_app_group] : ordered_multi_apps)
6420 {
6421 bool group_success = true;
6422 if (_verbose_multiapps && ordered_multi_apps.size() > 1)
6423 _console << COLOR_CYAN << "\nExecuting MultiApps group " << Moose::stringify(group_id)
6424 << COLOR_DEFAULT << std::endl;
6425
6426 if (_verbose_multiapps && multi_app_group.size() > 1)
6427 {
6428 // Let the user know about concurrent multiapp use (new option: help them set it up)
6429 _console << COLOR_CYAN << "\nConcurrent MultiApps: " << std::endl;
6430 for (const auto & multi_app : multi_app_group)
6431 _console << multi_app->name() << " ";
6432 _console << COLOR_DEFAULT << std::endl;
6433 }
6434
6435 // With concurrent multiapps, the multiapps in a group have each been assigned a disjoint
6436 // subset of the ranks (see partitionConcurrentMultiApps()), so solveStep() does real work
6437 // only on those ranks and returns early on the others. Looping here therefore lets different
6438 // ranks advance different multiapps at the same time - the concurrency comes from the rank
6439 // partition. This notably avoids racing PETSc's process-global state (communicator and
6440 // options database).
6441 for (const auto & multi_app : multi_app_group)
6442 if (!multi_app->solveStep(_dt, _time, auto_advance))
6443 group_success = false;
6444
6445 // Whether to move on to the next group must be a collective decision so that every rank
6446 // leaves the group loop together and stays aligned for the following collectives.
6447 _communicator.min(group_success);
6448
6449 // No need to solve the other groups if this group failed
6450 if (!group_success)
6451 {
6452 success = false;
6453 break;
6454 }
6455
6456 // Execute Transfers _between_ MultiApps after each app executes
6457 for (const auto & multi_app : multi_app_group)
6459 }
6460
6462 _communicator.min(success);
6463
6464 if (!success)
6465 return false;
6466
6468 _console << COLOR_CYAN << "Finished Executing MultiApps on " << Moose::stringify(exec_on)
6469 << "\n"
6470 << COLOR_DEFAULT << std::endl;
6471 }
6472
6473 // Execute Transfers _from_ MultiApps (to the parent app)
6475
6476 // If we made it here then everything passed
6477 return true;
6478}
6479
6480void
6482{
6483 const auto & multi_apps = _multi_apps.getActiveObjects();
6484
6485 for (const auto & multi_app : multi_apps)
6486 multi_app->finalize();
6487}
6488
6489void
6491{
6492 const auto & multi_apps = _multi_apps.getActiveObjects();
6493
6494 for (const auto & multi_app : multi_apps)
6495 multi_app->postExecute();
6496}
6497
6498void
6500{
6501 const auto & multi_apps = _multi_apps[type].getActiveObjects();
6502
6503 if (multi_apps.size())
6504 for (const auto & multi_app : multi_apps)
6505 multi_app->incrementTStep(_time);
6506}
6507
6508void
6509FEProblemBase::finishMultiAppStep(ExecFlagType type, bool recurse_through_multiapp_levels)
6510{
6511 const auto & multi_apps = _multi_apps[type].getActiveObjects();
6512
6513 if (multi_apps.size())
6514 {
6516 _console << COLOR_CYAN << "\nAdvancing MultiApps on " << type.name() << COLOR_DEFAULT
6517 << std::endl;
6518
6519 for (const auto & multi_app : multi_apps)
6520 multi_app->finishStep(recurse_through_multiapp_levels);
6521
6523
6525 _console << COLOR_CYAN << "Finished Advancing MultiApps on " << type.name() << "\n"
6526 << COLOR_DEFAULT << std::endl;
6527 }
6528}
6529
6530void
6532{
6533 const auto & multi_apps = _multi_apps[type].getActiveObjects();
6534
6535 if (multi_apps.size())
6536 {
6537 TIME_SECTION("backupMultiApps", 5, "Backing Up MultiApp");
6538
6540 _console << COLOR_CYAN << "\nBacking Up MultiApps on " << type.name() << COLOR_DEFAULT
6541 << std::endl;
6542
6543 for (const auto & multi_app : multi_apps)
6544 multi_app->backup();
6545
6547
6549 _console << COLOR_CYAN << "Finished Backing Up MultiApps on " << type.name() << "\n"
6550 << COLOR_DEFAULT << std::endl;
6551 }
6552}
6553
6554void
6556{
6557 const auto & multi_apps = _multi_apps[type].getActiveObjects();
6558
6559 if (multi_apps.size())
6560 {
6562 {
6563 if (force)
6564 _console << COLOR_CYAN << "\nRestoring Multiapps on " << type.name()
6565 << " because of solve failure!" << COLOR_DEFAULT << std::endl;
6566 else
6567 _console << COLOR_CYAN << "\nRestoring MultiApps on " << type.name() << COLOR_DEFAULT
6568 << std::endl;
6569 }
6570
6571 for (const auto & multi_app : multi_apps)
6572 multi_app->restore(force);
6573
6575
6577 _console << COLOR_CYAN << "Finished Restoring MultiApps on " << type.name() << "\n"
6578 << COLOR_DEFAULT << std::endl;
6579 }
6580}
6581
6582Real
6584{
6585 const auto & multi_apps = _transient_multi_apps[type].getActiveObjects();
6586
6587 Real smallest_dt = std::numeric_limits<Real>::max();
6588
6589 for (const auto & multi_app : multi_apps)
6590 smallest_dt = std::min(smallest_dt, multi_app->computeDT());
6591
6592 return smallest_dt;
6593}
6594
6595void
6596FEProblemBase::addTransfer(const std::string & transfer_name,
6597 const std::string & name,
6598 InputParameters & parameters)
6599{
6600 parallel_object_only();
6601
6602 if (_displaced_problem && parameters.get<bool>("use_displaced_mesh"))
6603 {
6604 parameters.set<SubProblem *>("_subproblem") = _displaced_problem.get();
6605 parameters.set<SystemBase *>("_sys") = &_displaced_problem->auxSys();
6607 }
6608 else
6609 {
6610 if (_displaced_problem == nullptr && parameters.get<bool>("use_displaced_mesh"))
6611 {
6612 // We allow Transfers to request that they use_displaced_mesh,
6613 // but then be overridden when no displacements variables are
6614 // provided in the Mesh block. If that happened, update the value
6615 // of use_displaced_mesh appropriately for this Transfer.
6616 if (parameters.have_parameter<bool>("use_displaced_mesh"))
6617 parameters.set<bool>("use_displaced_mesh") = false;
6618 }
6619
6620 parameters.set<SubProblem *>("_subproblem") = this;
6621 parameters.set<SystemBase *>("_sys") = _aux.get();
6622 }
6623
6624 // Handle the "SAME_AS_MULTIAPP" execute option. The get method is used to test for the
6625 // flag so the set by user flag is not reset, calling set with the true flag causes the set
6626 // by user status to be reset, which should only be done if the EXEC_SAME_AS_MULTIAPP is
6627 // being applied to the object.
6629 {
6630 ExecFlagEnum & exec_enum = parameters.set<ExecFlagEnum>("execute_on", true);
6631 std::shared_ptr<MultiApp> multiapp;
6632 if (parameters.isParamValid("multi_app"))
6633 multiapp = getMultiApp(parameters.get<MultiAppName>("multi_app"));
6634 // This catches the sibling transfer case, where we want to be executing only as often as the
6635 // receiving application. A transfer 'to' a multiapp is executed before that multiapp
6636 else if (parameters.isParamValid("to_multi_app"))
6637 multiapp = getMultiApp(parameters.get<MultiAppName>("to_multi_app"));
6638 else if (parameters.isParamValid("from_multi_app"))
6639 multiapp = getMultiApp(parameters.get<MultiAppName>("from_multi_app"));
6640 // else do nothing because the user has provided invalid input. They should get a nice error
6641 // about this during transfer construction. This necessitates checking for null in this next
6642 // line, however
6643 if (multiapp)
6644 exec_enum = multiapp->getParam<ExecFlagEnum>("execute_on");
6645 }
6646
6647 // Create the Transfer objects
6648 std::shared_ptr<Transfer> transfer = _factory.create<Transfer>(transfer_name, name, parameters);
6649 logAdd("Transfer", name, transfer_name, parameters);
6650
6651 // Add MultiAppTransfer object
6652 std::shared_ptr<MultiAppTransfer> multi_app_transfer =
6653 std::dynamic_pointer_cast<MultiAppTransfer>(transfer);
6654 if (multi_app_transfer)
6655 {
6656 if (multi_app_transfer->directions().isValueSet(MultiAppTransfer::TO_MULTIAPP))
6657 _to_multi_app_transfers.addObject(multi_app_transfer);
6658 if (multi_app_transfer->directions().isValueSet(MultiAppTransfer::FROM_MULTIAPP))
6659 _from_multi_app_transfers.addObject(multi_app_transfer);
6660 if (multi_app_transfer->directions().isValueSet(MultiAppTransfer::BETWEEN_MULTIAPP))
6661 _between_multi_app_transfers.addObject(multi_app_transfer);
6662 }
6663 else
6664 _transfers.addObject(transfer);
6665}
6666
6667bool
6668FEProblemBase::hasVariable(const std::string & var_name) const
6669{
6670 for (auto & sys : _solver_systems)
6671 if (sys->hasVariable(var_name))
6672 return true;
6673 if (_aux->hasVariable(var_name))
6674 return true;
6675
6676 return false;
6677}
6678
6679bool
6680FEProblemBase::hasSolverVariable(const std::string & var_name) const
6681{
6682 for (auto & sys : _solver_systems)
6683 if (sys->hasVariable(var_name))
6684 return true;
6685
6686 return false;
6687}
6688
6691 const std::string & var_name,
6692 Moose::VarKindType expected_var_type,
6693 Moose::VarFieldType expected_var_field_type) const
6694{
6695 return getVariableHelper(
6696 tid, var_name, expected_var_type, expected_var_field_type, _solver_systems, *_aux);
6697}
6698
6700FEProblemBase::getStandardVariable(const THREAD_ID tid, const std::string & var_name)
6701{
6702 for (auto & sys : _solver_systems)
6703 if (sys->hasVariable(var_name))
6704 return sys->getFieldVariable<Real>(tid, var_name);
6705 if (_aux->hasVariable(var_name))
6706 return _aux->getFieldVariable<Real>(tid, var_name);
6707
6708 mooseError("Unknown variable " + var_name);
6709}
6710
6712FEProblemBase::getActualFieldVariable(const THREAD_ID tid, const std::string & var_name)
6713{
6714 for (auto & sys : _solver_systems)
6715 if (sys->hasVariable(var_name))
6716 return sys->getActualFieldVariable<Real>(tid, var_name);
6717 if (_aux->hasVariable(var_name))
6718 return _aux->getActualFieldVariable<Real>(tid, var_name);
6719
6720 mooseError("Unknown variable " + var_name);
6721}
6722
6724FEProblemBase::getVectorVariable(const THREAD_ID tid, const std::string & var_name)
6725{
6726 for (auto & sys : _solver_systems)
6727 if (sys->hasVariable(var_name))
6728 return sys->getFieldVariable<RealVectorValue>(tid, var_name);
6729 if (_aux->hasVariable(var_name))
6730 return _aux->getFieldVariable<RealVectorValue>(tid, var_name);
6731
6732 mooseError("Unknown variable " + var_name);
6733}
6734
6736FEProblemBase::getArrayVariable(const THREAD_ID tid, const std::string & var_name)
6737{
6738 for (auto & sys : _solver_systems)
6739 if (sys->hasVariable(var_name))
6740 return sys->getFieldVariable<RealEigenVector>(tid, var_name);
6741 if (_aux->hasVariable(var_name))
6742 return _aux->getFieldVariable<RealEigenVector>(tid, var_name);
6743
6744 mooseError("Unknown variable " + var_name);
6745}
6746
6747bool
6748FEProblemBase::hasScalarVariable(const std::string & var_name) const
6749{
6750 for (auto & sys : _solver_systems)
6751 if (sys->hasScalarVariable(var_name))
6752 return true;
6753 if (_aux->hasScalarVariable(var_name))
6754 return true;
6755
6756 return false;
6757}
6758
6760FEProblemBase::getScalarVariable(const THREAD_ID tid, const std::string & var_name)
6761{
6762 for (auto & sys : _solver_systems)
6763 if (sys->hasScalarVariable(var_name))
6764 return sys->getScalarVariable(tid, var_name);
6765 if (_aux->hasScalarVariable(var_name))
6766 return _aux->getScalarVariable(tid, var_name);
6767
6768 mooseError("Unknown variable " + var_name);
6769}
6770
6771System &
6772FEProblemBase::getSystem(const std::string & var_name)
6773{
6774 const auto [var_in_sys, sys_num] = determineSolverSystem(var_name);
6775 if (var_in_sys)
6776 return _solver_systems[sys_num]->system();
6777 else if (_aux->hasVariable(var_name) || _aux->hasScalarVariable(var_name))
6778 return _aux->system();
6779 else
6780 mooseError("Unable to find a system containing the variable " + var_name);
6781}
6782
6785{
6786 return _req.get();
6787}
6788
6789void
6791{
6793
6795 _displaced_problem->setActiveFEVariableCoupleableMatrixTags(mtags, tid);
6796}
6797
6798void
6800{
6802
6804 _displaced_problem->setActiveFEVariableCoupleableVectorTags(vtags, tid);
6805}
6806
6807void
6809 const THREAD_ID tid)
6810{
6812
6814 _displaced_problem->setActiveScalarVariableCoupleableMatrixTags(mtags, tid);
6815}
6816
6817void
6819 const THREAD_ID tid)
6820{
6822
6824 _displaced_problem->setActiveScalarVariableCoupleableVectorTags(vtags, tid);
6825}
6826
6827void
6828FEProblemBase::setActiveElementalMooseVariables(const std::set<MooseVariableFEBase *> & moose_vars,
6829 const THREAD_ID tid)
6830{
6832
6834 _displaced_problem->setActiveElementalMooseVariables(moose_vars, tid);
6835}
6836
6837void
6839{
6841
6843 _displaced_problem->clearActiveElementalMooseVariables(tid);
6844}
6845
6846void
6848{
6850
6852 _displaced_problem->clearActiveFEVariableCoupleableMatrixTags(tid);
6853}
6854
6855void
6857{
6859
6861 _displaced_problem->clearActiveFEVariableCoupleableVectorTags(tid);
6862}
6863
6864void
6866{
6868
6870 _displaced_problem->clearActiveScalarVariableCoupleableMatrixTags(tid);
6871}
6872
6873void
6875{
6877
6879 _displaced_problem->clearActiveScalarVariableCoupleableVectorTags(tid);
6880}
6881
6882void
6883FEProblemBase::setActiveMaterialProperties(const std::unordered_set<unsigned int> & mat_prop_ids,
6884 const THREAD_ID tid)
6885{
6886 // mark active properties in every material
6887 for (auto & mat : _all_materials.getObjects(tid))
6888 mat->setActiveProperties(mat_prop_ids);
6889 for (auto & mat : _all_materials[Moose::FACE_MATERIAL_DATA].getObjects(tid))
6890 mat->setActiveProperties(mat_prop_ids);
6892 mat->setActiveProperties(mat_prop_ids);
6893
6894 _has_active_material_properties[tid] = !mat_prop_ids.empty();
6895}
6896
6897bool
6902
6903void
6908
6909void
6911{
6912#ifdef LIBMESH_ENABLE_AMR
6913 if ((_adaptivity.isOn() || _num_grid_steps) &&
6916 {
6917 // Even on a serialized Mesh, we don't keep our material
6918 // properties serialized, so we'll rely on the callback to
6919 // redistribute() to redistribute properties at the same time
6920 // libMesh is redistributing elements.
6921 auto add_redistributer = [this](MooseMesh & mesh,
6922 const std::string & redistributer_name,
6923 const bool use_displaced_mesh)
6924 {
6926 redistribute_params.set<MooseApp *>(MooseBase::app_param) = &_app;
6927 redistribute_params.set<std::string>("for_whom") = this->name();
6928 redistribute_params.set<MooseMesh *>("mesh") = &mesh;
6929 redistribute_params.set<Moose::RelationshipManagerType>("rm_type") =
6931 redistribute_params.set<bool>("use_displaced_mesh") = use_displaced_mesh;
6932 redistribute_params.setHitNode(*parameters().getHitNode(), {});
6933
6934 std::shared_ptr<RedistributeProperties> redistributer =
6936 "RedistributeProperties", redistributer_name, redistribute_params);
6937
6940
6942 redistributer->addMaterialPropertyStorage(_bnd_material_props);
6943
6945 redistributer->addMaterialPropertyStorage(_neighbor_material_props);
6946
6947 mesh.getMesh().add_ghosting_functor(redistributer);
6948 };
6949
6950 add_redistributer(_mesh, "mesh_property_redistributer", false);
6952 add_redistributer(_displaced_problem->mesh(), "displaced_mesh_property_redistributer", true);
6953 }
6954#endif // LIBMESH_ENABLE_AMR
6955}
6956
6957void
6959{
6960 // Find the maximum number of quadrature points
6961 {
6962 MaxQpsThread mqt(*this);
6964 _max_qps = mqt.max();
6965
6966 // If we have more shape functions or more quadrature points on
6967 // another processor, then we may need to handle those elements
6968 // ourselves later after repartitioning.
6970 }
6971
6972 unsigned int max_qpts = getMaxQps();
6973 if (max_qpts > Moose::constMaxQpsPerElem)
6974 mooseError("Max quadrature points per element assumptions made in some code (e.g. Coupleable ",
6975 "and MaterialPropertyInterface classes) have been violated.\n",
6976 "Complain to Moose developers to have constMaxQpsPerElem increased from ",
6978 " to ",
6979 max_qpts);
6980 for (unsigned int tid = 0; tid < numThreads(); ++tid)
6981 {
6982 // the highest available order in libMesh is 43
6983 _scalar_zero[tid].resize(libMesh::FORTYTHIRD, 0);
6984 _zero[tid].resize(max_qpts, 0);
6985 _ad_zero[tid].resize(max_qpts, 0);
6986 _grad_zero[tid].resize(max_qpts, RealGradient(0.));
6987 _ad_grad_zero[tid].resize(max_qpts, ADRealGradient(0));
6988 _second_zero[tid].resize(max_qpts, RealTensor(0.));
6989 _ad_second_zero[tid].resize(max_qpts, ADRealTensorValue(0));
6990 _vector_zero[tid].resize(max_qpts, RealGradient(0.));
6991 _vector_curl_zero[tid].resize(max_qpts, RealGradient(0.));
6992 }
6993}
6994
6995void
6997{
6998 for (unsigned int tid = 0; tid < numThreads(); ++tid)
6999 for (const auto i : index_range(_nl))
7000 _assembly[tid][i]->bumpVolumeQRuleOrder(order, block);
7001
7003 _displaced_problem->bumpVolumeQRuleOrder(order, block);
7004
7005 updateMaxQps();
7006}
7007
7008void
7010{
7011 for (unsigned int tid = 0; tid < numThreads(); ++tid)
7012 for (const auto i : index_range(_nl))
7013 _assembly[tid][i]->bumpAllQRuleOrder(order, block);
7014
7016 _displaced_problem->bumpAllQRuleOrder(order, block);
7017
7018 updateMaxQps();
7019}
7020
7021void
7023 Order order,
7024 Order volume_order,
7025 Order face_order,
7026 SubdomainID block,
7027 const bool allow_negative_qweights)
7028{
7029 if (order == INVALID_ORDER)
7030 {
7031 // automatically determine the integration order
7032 order = _solver_systems[0]->getMinQuadratureOrder();
7033 for (const auto i : make_range(std::size_t(1), _solver_systems.size()))
7034 if (order < _solver_systems[i]->getMinQuadratureOrder())
7035 order = _solver_systems[i]->getMinQuadratureOrder();
7036 if (order < _aux->getMinQuadratureOrder())
7037 order = _aux->getMinQuadratureOrder();
7038 }
7039
7040 if (volume_order == INVALID_ORDER)
7041 volume_order = order;
7042
7043 if (face_order == INVALID_ORDER)
7044 face_order = order;
7045
7046 for (unsigned int tid = 0; tid < numThreads(); ++tid)
7047 for (const auto i : index_range(_solver_systems))
7048 _assembly[tid][i]->createQRules(
7049 type, order, volume_order, face_order, block, allow_negative_qweights);
7050
7052 _displaced_problem->createQRules(
7053 type, order, volume_order, face_order, block, allow_negative_qweights);
7054
7055 updateMaxQps();
7056}
7057
7058void
7060{
7062 {
7064 mooseError("Someone told us (the FEProblemBase) to trust the user coupling matrix, but we "
7065 "haven't been provided a coupling matrix!");
7066
7067 // We've been told to trust the user coupling matrix, so we're going to leave things alone
7068 return;
7069 }
7070
7071 _coupling = type;
7072}
7073
7074void
7075FEProblemBase::setCouplingMatrix(CouplingMatrix * cm, const unsigned int i)
7076{
7077 // TODO: Deprecate method
7079 _cm[i].reset(cm);
7080}
7081
7082void
7083FEProblemBase::setCouplingMatrix(std::unique_ptr<CouplingMatrix> cm, const unsigned int i)
7084{
7086 _cm[i] = std::move(cm);
7087}
7088
7089void
7091{
7093 mooseError("Someone told us (the FEProblemBase) to trust the user coupling matrix, but we "
7094 "haven't been provided a coupling matrix!");
7095
7097}
7098
7099void
7101{
7102 TIME_SECTION("setNonlocalCouplingMatrix", 5, "Setting Nonlocal Coupling Matrix");
7103
7104 if (_nl.size() > 1)
7105 mooseError("Nonlocal kernels are weirdly stored on the FEProblem so we don't currently support "
7106 "multiple nonlinear systems with nonlocal kernels.");
7107
7108 for (const auto nl_sys_num : index_range(_nl))
7109 {
7110 auto & nl = _nl[nl_sys_num];
7111 auto & nonlocal_cm = _nonlocal_cm[nl_sys_num];
7112 unsigned int n_vars = nl->nVariables();
7113 nonlocal_cm.resize(n_vars);
7114 const auto & vars = nl->getVariables(0);
7115 const auto & nonlocal_kernel = _nonlocal_kernels.getObjects();
7116 const auto & nonlocal_integrated_bc = _nonlocal_integrated_bcs.getObjects();
7117 for (const auto & ivar : vars)
7118 {
7119 for (const auto & kernel : nonlocal_kernel)
7120 {
7121 for (unsigned int i = ivar->number(); i < ivar->number() + ivar->count(); ++i)
7122 if (i == kernel->variable().number())
7123 for (const auto & jvar : vars)
7124 {
7125 const auto it = _var_dof_map.find(jvar->name());
7126 if (it != _var_dof_map.end())
7127 {
7128 unsigned int j = jvar->number();
7129 nonlocal_cm(i, j) = 1;
7130 }
7131 }
7132 }
7133 for (const auto & integrated_bc : nonlocal_integrated_bc)
7134 {
7135 for (unsigned int i = ivar->number(); i < ivar->number() + ivar->count(); ++i)
7136 if (i == integrated_bc->variable().number())
7137 for (const auto & jvar : vars)
7138 {
7139 const auto it = _var_dof_map.find(jvar->name());
7140 if (it != _var_dof_map.end())
7141 {
7142 unsigned int j = jvar->number();
7143 nonlocal_cm(i, j) = 1;
7144 }
7145 }
7146 }
7147 }
7148 }
7149}
7150
7151bool
7152FEProblemBase::areCoupled(const unsigned int ivar,
7153 const unsigned int jvar,
7154 const unsigned int nl_sys) const
7155{
7156 return (*_cm[nl_sys])(ivar, jvar);
7157}
7158
7159std::vector<std::pair<MooseVariableFieldBase *, MooseVariableFieldBase *>> &
7160FEProblemBase::couplingEntries(const THREAD_ID tid, const unsigned int nl_sys)
7161{
7162 return _assembly[tid][nl_sys]->couplingEntries();
7163}
7164
7165std::vector<std::pair<MooseVariableFieldBase *, MooseVariableFieldBase *>> &
7166FEProblemBase::nonlocalCouplingEntries(const THREAD_ID tid, const unsigned int nl_sys)
7167{
7168 return _assembly[tid][nl_sys]->nonlocalCouplingEntries();
7169}
7170
7171const std::vector<std::pair<MooseVariableFieldBase *, MooseVariableScalar *>> &
7172FEProblemBase::fieldScalarCouplingEntries(const THREAD_ID tid, const unsigned int nl_sys) const
7173{
7174 return _assembly[tid][nl_sys]->fieldScalarCouplingEntries();
7175}
7176
7177void
7179{
7180 if (_initialized)
7181 return;
7182
7183 TIME_SECTION("init", 2, "Initializing");
7184
7185 // call executioner's preProblemInit so that it can do some setups before problem init
7187
7188 // If we have AD and we are doing global AD indexing, then we should by default set the matrix
7189 // coupling to full. If the user has told us to trust their coupling matrix, then this call will
7190 // not do anything
7193
7194 for (const auto i : index_range(_nl))
7195 {
7196 auto & nl = _nl[i];
7197 auto & cm = _cm[i];
7198
7199 unsigned int n_vars = nl->nVariables();
7200 {
7201 TIME_SECTION("fillCouplingMatrix", 3, "Filling Coupling Matrix");
7202
7203 switch (_coupling)
7204 {
7206 cm = std::make_unique<CouplingMatrix>(n_vars);
7207 for (unsigned int i = 0; i < n_vars; i++)
7208 (*cm)(i, i) = 1;
7209 break;
7210
7211 // for full jacobian
7213 cm = std::make_unique<CouplingMatrix>(n_vars);
7214 for (unsigned int i = 0; i < n_vars; i++)
7215 for (unsigned int j = 0; j < n_vars; j++)
7216 (*cm)(i, j) = 1;
7217 break;
7218
7220 // do nothing, _cm was already set through couplingMatrix() call
7221 break;
7222 }
7223 }
7224
7225 nl->dofMap()._dof_coupling = cm.get();
7226
7227 // If there are no variables, make sure to pass a nullptr coupling
7228 // matrix, to avoid warnings about non-nullptr yet empty
7229 // CouplingMatrices.
7230 if (n_vars == 0)
7231 nl->dofMap()._dof_coupling = nullptr;
7232
7233 nl->dofMap().attach_extra_sparsity_function(&extraSparsity, nl.get());
7234 nl->dofMap().attach_extra_send_list_function(&extraSendList, nl.get());
7235 _aux->dofMap().attach_extra_send_list_function(&extraSendList, _aux.get());
7236
7237 if (!_skip_nl_system_check && _solve && n_vars == 0)
7238 mooseError("No variables specified in nonlinear system '", nl->name(), "'.");
7239 }
7240
7241 ghostGhostedBoundaries(); // We do this again right here in case new boundaries have been added
7242
7243 // We may have added element/nodes to the mesh in ghostGhostedBoundaries so we need to update
7244 // all of our mesh information. We need to make sure that mesh information is up-to-date before
7245 // EquationSystems::init because that will call through to updateGeomSearch (for sparsity
7246 // augmentation) and if we haven't added back boundary node information before that latter call,
7247 // then we're screwed. We'll get things like "Unable to find closest node!"
7251
7252 if (_mesh.doingPRefinement())
7253 {
7256 _displaced_problem->preparePRefinement();
7257 }
7258
7259 // do not assemble system matrix for JFNK solve
7260 for (auto & nl : _nl)
7261 if (solverParams(nl->number())._type == Moose::ST_JFNK)
7262 nl->turnOffJacobian();
7263
7264 for (auto & sys : _solver_systems)
7265 sys->preInit();
7266 _aux->preInit();
7267
7268 // Build the mortar segment meshes, if they haven't been already, for a couple reasons:
7269 // 1) Get the ghosting correct for both static and dynamic meshes
7270 // 2) Make sure the mortar mesh is built for mortar constraints that live on the static mesh
7271 //
7272 // It is worth-while to note that mortar meshes that live on a dynamic mesh will be built
7273 // during residual and Jacobian evaluation because when displacements are solution variables
7274 // the mortar mesh will move and change during the course of a non-linear solve. We DO NOT
7275 // redo ghosting during non-linear solve, so for purpose 1) the below call has to be made
7276 if (!_mortar_data->initialized())
7278
7279 {
7280 TIME_SECTION("EquationSystems::Init", 2, "Initializing Equation Systems");
7281 es().init();
7282 }
7283
7284 for (auto & sys : _solver_systems)
7285 sys->postInit();
7286 _aux->postInit();
7287
7288 // Now that the equation system and the dof distribution is done, we can generate the
7289 // finite volume-related parts if needed.
7290 if (haveFV())
7292
7293 for (auto & sys : _solver_systems)
7294 sys->update();
7295 _aux->update();
7296
7297 for (THREAD_ID tid = 0; tid < numThreads(); ++tid)
7298 for (const auto i : index_range(_nl))
7299 {
7300 mooseAssert(
7301 _cm[i],
7302 "Coupling matrix not set for system "
7303 << i
7304 << ". This should only happen if a preconditioner was not setup for this system");
7305 _assembly[tid][i]->init(_cm[i].get());
7306 }
7307
7309 _displaced_problem->init();
7310
7311#ifdef MOOSE_KOKKOS_ENABLED
7313 initKokkos();
7314#endif
7315
7316 _initialized = true;
7317}
7318
7319unsigned int
7320FEProblemBase::nlSysNum(const NonlinearSystemName & nl_sys_name) const
7321{
7322 std::istringstream ss(nl_sys_name);
7323 unsigned int nl_sys_num;
7324 if (!(ss >> nl_sys_num) || !ss.eof())
7325 nl_sys_num = libmesh_map_find(_nl_sys_name_to_num, nl_sys_name);
7326
7327 return nl_sys_num;
7328}
7329
7330unsigned int
7331FEProblemBase::linearSysNum(const LinearSystemName & linear_sys_name) const
7332{
7333 std::istringstream ss(linear_sys_name);
7334 unsigned int linear_sys_num;
7335 if (!(ss >> linear_sys_num) || !ss.eof())
7336 linear_sys_num = libmesh_map_find(_linear_sys_name_to_num, linear_sys_name);
7337
7338 return linear_sys_num;
7339}
7340
7341unsigned int
7342FEProblemBase::solverSysNum(const SolverSystemName & solver_sys_name) const
7343{
7344 std::istringstream ss(solver_sys_name);
7345 unsigned int solver_sys_num;
7346 if (!(ss >> solver_sys_num) || !ss.eof())
7347 {
7348 const auto & search = _solver_sys_name_to_num.find(solver_sys_name);
7349 if (search == _solver_sys_name_to_num.end())
7350 mooseError("The solver system number was requested for system '" + solver_sys_name,
7351 "' but this system does not exist in the Problem. Systems can be added to the "
7352 "problem using the 'nl_sys_names'/'linear_sys_names' parameter.\nSystems in the "
7353 "Problem: " +
7355 solver_sys_num = search->second;
7356 }
7357
7358 return solver_sys_num;
7359}
7360
7361unsigned int
7362FEProblemBase::systemNumForVariable(const VariableName & variable_name) const
7363{
7364 for (const auto & solver_sys : _solver_systems)
7365 if (solver_sys->hasVariable(variable_name))
7366 return solver_sys->number();
7367 mooseAssert(_aux, "Should have an auxiliary system");
7368 if (_aux->hasVariable(variable_name))
7369 return _aux->number();
7370
7371 mooseError("Variable '",
7372 variable_name,
7373 "' was not found in any solver (nonlinear/linear) or auxiliary system");
7374}
7375
7376void
7377FEProblemBase::solve(const unsigned int nl_sys_num)
7378{
7379 TIME_SECTION("solve", 1, "Solving", false);
7380
7381 setCurrentNonlinearSystem(nl_sys_num);
7382
7383 // This prevents stale dof indices from lingering around and possibly leading to invalid reads
7384 // and writes. Dof indices may be made stale through operations like mesh adaptivity
7387 _displaced_problem->clearAllDofIndices();
7388
7389 // Setup the output system for printing linear/nonlinear iteration information and some solver
7390 // settings, including setting matrix prefixes. This must occur before petscSetOptions
7392
7393#if PETSC_RELEASE_LESS_THAN(3, 12, 0)
7395 _petsc_options, _solver_params); // Make sure the PETSc options are setup for this app
7396#else
7397 // Now this database will be the default
7398 // Each app should have only one database
7399 if (!_app.isUltimateMaster())
7400 LibmeshPetscCall(PetscOptionsPush(_petsc_option_data_base));
7401 // We did not add PETSc options to database yet
7403 {
7404 // Insert options for all systems all at once
7407 }
7408#endif
7409
7410 // set up DM which is required if use a field split preconditioner
7411 // We need to setup DM every "solve()" because libMesh destroy SNES after solve()
7412 // Do not worry, DM setup is very cheap
7414
7416
7417 // reset flag so that residual evaluation does not get skipped
7418 // and the next non-linear iteration does not automatically fail with
7419 // "DIVERGED_NANORINF", when we throw an exception and stop solve
7421
7422 if (_solve)
7423 {
7426 }
7427
7428 // sync solutions in displaced problem
7430 _displaced_problem->syncSolutions();
7431
7432#if !PETSC_RELEASE_LESS_THAN(3, 12, 0)
7433 if (!_app.isUltimateMaster())
7434 LibmeshPetscCall(PetscOptionsPop());
7435#endif
7436}
7437
7438void
7439FEProblemBase::setException(const std::string & message)
7440{
7441 _has_exception = true;
7442 _exception_message = message;
7443}
7444
7445void
7447{
7449 return;
7450
7451 TIME_SECTION("checkExceptionAndStopSolve", 5);
7452
7453 // See if any processor had an exception. If it did, get back the
7454 // processor that the exception occurred on.
7455 unsigned int processor_id;
7456
7458
7459 if (_has_exception)
7460 {
7462
7464 {
7465 // Print the message
7466 if (_communicator.rank() == 0 && print_message)
7467 {
7468 _console << "\n" << _exception_message << "\n";
7469 if (isTransient())
7470 _console
7471 << "To recover, the solution will fail and then be re-attempted with a reduced time "
7472 "step.\n"
7473 << std::endl;
7474 }
7475
7476 // Stop the solve -- this entails setting
7477 // SNESSetFunctionDomainError() or directly inserting NaNs in the
7478 // residual vector to let PETSc >= 3.6 return DIVERGED_NANORINF.
7479 if (_current_nl_sys)
7481
7484
7485 // and close Aux system (we MUST do this here; see #11525)
7486 _aux->solution().close();
7487
7488 // We've handled this exception, so we no longer have one.
7489 _has_exception = false;
7490
7491 // Force the next non-linear convergence check to fail (and all further residual evaluation
7492 // to be skipped).
7494
7495 // Repropagate the exception, so it can be caught at a higher level, typically
7496 // this is NonlinearSystem::computeResidual().
7498 }
7499 else
7500 mooseError("The following parallel-communicated exception was detected during " +
7501 Moose::stringify(_current_execute_on_flag) + " evaluation:\n" +
7503 "\nBecause this did not occur during residual evaluation, there"
7504 " is no way to handle this, so the solution is aborting.\n");
7505 }
7506}
7507
7508void
7510{
7511 // Our default state is to allow computing derivatives
7512 ADReal::do_derivatives = true;
7514
7515 // Clear the VectorTags and MatrixTags
7518
7521
7526 {
7527 _displaced_problem->setCurrentlyComputingResidual(false);
7528 _displaced_problem->setCurrentlyComputingJacobian(false);
7529 _displaced_problem->setCurrentlyComputingResidualAndJacobian(false);
7530 }
7531}
7532
7533void
7534FEProblemBase::solveLinearSystem(const unsigned int linear_sys_num,
7536{
7537 TIME_SECTION("solve", 1, "Solving", false);
7538
7539 setCurrentLinearSystem(linear_sys_num);
7540
7541 const Moose::PetscSupport::PetscOptions & options = po ? *po : _petsc_options;
7542 auto & solver_params = _solver_params[numNonlinearSystems() + linear_sys_num];
7543
7544 // Set custom convergence criteria
7546
7547#if PETSC_RELEASE_LESS_THAN(3, 12, 0)
7548 LibmeshPetscCall(Moose::PetscSupport::petscSetOptions(
7549 options, solver_params)); // Make sure the PETSc options are setup for this app
7550#else
7551 // Now this database will be the default
7552 // Each app should have only one database
7553 if (!_app.isUltimateMaster())
7554 LibmeshPetscCall(PetscOptionsPush(_petsc_option_data_base));
7555
7556 // We did not add PETSc options to database yet
7558 {
7559 Moose::PetscSupport::petscSetOptions(options, solver_params, this);
7561 }
7562#endif
7563
7564 if (_solve)
7566
7567#if !PETSC_RELEASE_LESS_THAN(3, 12, 0)
7568 if (!_app.isUltimateMaster())
7569 LibmeshPetscCall(PetscOptionsPop());
7570#endif
7571}
7572
7573bool
7574FEProblemBase::solverSystemConverged(const unsigned int sys_num)
7575{
7576 if (_solve)
7577 return _solver_systems[sys_num]->converged();
7578 else
7579 return true;
7580}
7581
7582unsigned int
7583FEProblemBase::nNonlinearIterations(const unsigned int nl_sys_num) const
7584{
7585 return _nl[nl_sys_num]->nNonlinearIterations();
7586}
7587
7588unsigned int
7589FEProblemBase::nLinearIterations(const unsigned int nl_sys_num) const
7590{
7591 return _nl[nl_sys_num]->nLinearIterations();
7592}
7593
7594Real
7595FEProblemBase::finalNonlinearResidual(const unsigned int nl_sys_num) const
7596{
7597 return _nl[nl_sys_num]->finalNonlinearResidual();
7598}
7599
7600bool
7601FEProblemBase::computingPreSMOResidual(const unsigned int nl_sys_num) const
7602{
7603 return _nl[nl_sys_num]->computingPreSMOResidual();
7604}
7605
7606void
7608{
7609 TIME_SECTION("copySolutionsBackwards", 3, "Copying Solutions Backward");
7610
7611 for (auto & sys : _solver_systems)
7612 sys->copyStateHistoryBackwards();
7613 _aux->copyStateHistoryBackwards();
7614}
7615
7616void
7618{
7619 for (auto & sys : _solver_systems)
7620 sys->skipNextSolutionToOldCopy();
7621 _aux->skipNextSolutionToOldCopy();
7622}
7623
7624void
7626{
7627 TIME_SECTION("advanceState", 5, "Advancing State");
7628
7629 for (auto & sys : _solver_systems)
7630 sys->advanceStateHistory(Moose::SolutionIterationType::Time);
7631 _aux->advanceStateHistory(Moose::SolutionIterationType::Time);
7632
7634 {
7635 for (const auto i : index_range(_solver_systems))
7636 _displaced_problem->solverSys(i).advanceStateHistory(Moose::SolutionIterationType::Time);
7637 _displaced_problem->auxSys().advanceStateHistory(Moose::SolutionIterationType::Time);
7638 }
7639
7641
7643
7646
7649
7652
7653#ifdef MOOSE_KOKKOS_ENABLED
7656
7659
7662#endif
7663
7665}
7666
7667void
7669{
7671
7673 _displaced_problem->geomSearchData().backup();
7674}
7675
7676void
7678{
7680
7682 _displaced_problem->geomSearchData().restore();
7683}
7684
7685void
7687{
7688 TIME_SECTION("restoreSolutions", 5, "Restoring Solutions");
7689
7690 if (!_not_zeroed_tagged_vectors.empty())
7691 paramError("not_zeroed_tag_vectors",
7692 "There is currently no way to restore not-zeroed vectors.");
7693
7694 for (auto & sys : _solver_systems)
7695 {
7696 if (_verbose_restore)
7697 _console << "Restoring solutions on system " << sys->name() << "..." << std::endl;
7698 sys->restoreStateHistory();
7699 }
7700
7701 if (_verbose_restore)
7702 _console << "Restoring solutions on Auxiliary system..." << std::endl;
7703 _aux->restoreStateHistory();
7704
7705 if (_verbose_restore)
7706 _console << "Restoring postprocessor, vector-postprocessor, and reporter data..." << std::endl;
7708
7710 _displaced_problem->updateMesh();
7711}
7712
7713void
7715{
7716 TIME_SECTION("saveOldSolutions", 5, "Saving Old Solutions");
7717
7718 for (auto & sys : _solver_systems)
7719 sys->saveOldSolutions();
7720 _aux->saveOldSolutions();
7721}
7722
7723void
7725{
7726 TIME_SECTION("restoreOldSolutions", 5, "Restoring Old Solutions");
7727
7728 for (auto & sys : _solver_systems)
7729 sys->restoreOldSolutions();
7730 _aux->restoreOldSolutions();
7731}
7732
7733void
7735{
7736 TIME_SECTION("outputStep", 1, "Outputting");
7737
7739
7740 for (auto & sys : _solver_systems)
7741 sys->update();
7742 _aux->update();
7743
7745 _displaced_problem->syncSolutions();
7747
7749}
7750
7751void
7753{
7755}
7756
7757void
7762
7763void
7769
7770void
7772{
7773 TIME_SECTION("onTimestepBegin", 2);
7774
7775 for (auto & nl : _nl)
7776 nl->onTimestepBegin();
7777}
7778
7779void
7783
7784Real
7786{
7788 // If we are any iteration type other than time (e.g. nonlinear), then temporally we are still
7789 // in the present time
7790 return time();
7791
7792 switch (state.state)
7793 {
7794 case 0:
7795 return time();
7796
7797 case 1:
7798 return timeOld();
7799
7800 case 2:
7801 return timeOlder();
7802
7803 default:
7804 mooseError("Unhandled state ", state.state, " in FEProblemBase::getTimeFromStateArg");
7805 }
7806}
7807
7808void
7809FEProblemBase::addTimeIntegrator(const std::string & type,
7810 const std::string & name,
7811 InputParameters & parameters)
7812{
7813 parallel_object_only();
7814
7815 parameters.set<SubProblem *>("_subproblem") = this;
7816 logAdd("TimeIntegrator", name, type, parameters);
7817 _aux->addTimeIntegrator(type, name + ":aux", parameters);
7818 for (auto & sys : _solver_systems)
7819 sys->addTimeIntegrator(type, name + ":" + sys->name(), parameters);
7820 _has_time_integrator = true;
7821
7822 // add vectors to store u_dot, u_dotdot, udot_old, u_dotdot_old and
7823 // solution vectors older than 2 time steps, if requested by the time
7824 // integrator
7825 _aux->addDotVectors();
7826 for (auto & nl : _nl)
7827 {
7828 nl->addDotVectors();
7829
7830 auto tag_udot = nl->getTimeIntegrators()[0]->uDotFactorTag();
7831 if (!nl->hasVector(tag_udot))
7832 nl->associateVectorToTag(*nl->solutionUDot(), tag_udot);
7833 auto tag_udotdot = nl->getTimeIntegrators()[0]->uDotDotFactorTag();
7834 if (!nl->hasVector(tag_udotdot) && uDotDotRequested())
7835 nl->associateVectorToTag(*nl->solutionUDotDot(), tag_udotdot);
7836 }
7837
7839 // Time integrator does not exist when displaced problem is created.
7840 _displaced_problem->addTimeIntegrator();
7841}
7842
7843void
7844FEProblemBase::addPredictor(const std::string & type,
7845 const std::string & name,
7846 InputParameters & parameters)
7847{
7848 parallel_object_only();
7849
7851 mooseError("Vector bounds cannot be used with LinearSystems!");
7852
7853 parameters.set<SubProblem *>("_subproblem") = this;
7854 std::shared_ptr<Predictor> predictor = _factory.create<Predictor>(type, name, parameters);
7855 logAdd("Predictor", name, type, parameters);
7856
7857 for (auto & nl : _nl)
7858 nl->setPredictor(predictor);
7859}
7860
7861Real
7863{
7864 _current_nl_sys = &sys;
7865 computeResidual(*sys.currentSolution(), sys.RHS(), sys.number());
7866 return sys.RHS().l2_norm();
7867}
7868
7869Real
7871{
7872 _current_linear_sys = &sys;
7873
7874 // We assemble the current system to check the current residual
7878 /*compute fresh gradients*/ true);
7879
7880 // Unfortunate, but we have to allocate a new vector for the residual
7881 auto residual = sys.linearImplicitSystem().rhs->clone();
7882 residual->scale(-1.0);
7883 residual->add_vector(*sys.currentSolution(), *sys.linearImplicitSystem().matrix);
7884 return residual->l2_norm();
7885}
7886
7887Real
7889{
7890 TIME_SECTION("computeResidualL2Norm", 2, "Computing L2 Norm of Residual");
7891
7892 // We use sum the squared norms of the individual systems and then take the square root of it
7893 Real l2_norm = 0.0;
7894 for (auto sys : _nl)
7895 {
7896 const auto norm = computeResidualL2Norm(*sys);
7897 l2_norm += norm * norm;
7898 }
7899
7900 for (auto sys : _linear_systems)
7901 {
7902 const auto norm = computeResidualL2Norm(*sys);
7903 l2_norm += norm * norm;
7904 }
7905
7906 return std::sqrt(l2_norm);
7907}
7908
7909void
7910FEProblemBase::computeResidualSys(NonlinearImplicitSystem & sys,
7911 const NumericVector<Number> & soln,
7912 NumericVector<Number> & residual)
7913{
7914 parallel_object_only();
7915
7916 TIME_SECTION("computeResidualSys", 5);
7917 // Reset before residual setup, calculation & execution
7919
7920 computeResidual(soln, residual, sys.number());
7921}
7922
7923void
7924FEProblemBase::computeResidual(NonlinearImplicitSystem & sys,
7925 const NumericVector<Number> & soln,
7926 NumericVector<Number> & residual)
7927{
7928 mooseDeprecated("Please use computeResidualSys");
7929
7930 computeResidualSys(sys, soln, residual);
7931}
7932
7933void
7934FEProblemBase::computeResidual(const NumericVector<Number> & soln,
7935 NumericVector<Number> & residual,
7936 const unsigned int nl_sys_num)
7937{
7938 setCurrentNonlinearSystem(nl_sys_num);
7939
7940 // We associate the residual tag with the given residual vector to make sure we
7941 // don't filter it out below
7943 const auto & residual_vector_tags = getVectorTags(Moose::VECTOR_TAG_RESIDUAL);
7944
7945 mooseAssert(_fe_vector_tags.empty(), "This should be empty indicating a clean starting state");
7946 // We filter out tags which do not have associated vectors in the current nonlinear
7947 // system. This is essential to be able to use system-dependent residual tags.
7949
7951 _fe_vector_tags.clear();
7952}
7953
7954void
7955FEProblemBase::computeResidualAndJacobian(const NumericVector<Number> & soln,
7956 NumericVector<Number> & residual,
7957 SparseMatrix<Number> & jacobian)
7958{
7959 try
7960 {
7961 try
7962 {
7963 // vector tags
7965 const auto & residual_vector_tags = getVectorTags(Moose::VECTOR_TAG_RESIDUAL);
7966
7967 mooseAssert(_fe_vector_tags.empty(),
7968 "This should be empty indicating a clean starting state");
7969 // We filter out tags which do not have associated vectors in the current nonlinear
7970 // system. This is essential to be able to use system-dependent residual tags.
7972
7974
7975 // matrix tags
7976 {
7977 _fe_matrix_tags.clear();
7978
7979 auto & tags = getMatrixTags();
7980 for (auto & tag : tags)
7981 _fe_matrix_tags.insert(tag.second);
7982 }
7983
7985
7988
7989 for (const auto tag : _fe_matrix_tags)
7990 if (_current_nl_sys->hasMatrix(tag))
7991 {
7992 auto & matrix = _current_nl_sys->getMatrix(tag);
7993 matrix.zero();
7995 // PETSc algorithms require diagonal allocations regardless of whether there is non-zero
7996 // diagonal dependence. With global AD indexing we only add non-zero
7997 // dependence, so PETSc will scream at us unless we artificially add the diagonals.
7998 for (auto index : make_range(matrix.row_start(), matrix.row_stop()))
7999 matrix.add(index, index, 0);
8000 }
8001
8002 _aux->zeroVariablesForResidual();
8003
8004 unsigned int n_threads = numThreads();
8005
8007
8008 // Random interface objects
8009 for (const auto & it : _random_data_objects)
8010 it.second->updateSeeds(EXEC_LINEAR);
8011
8016 {
8017 _displaced_problem->setCurrentlyComputingResidual(true);
8018 _displaced_problem->setCurrentlyComputingJacobian(true);
8019 _displaced_problem->setCurrentlyComputingResidualAndJacobian(true);
8020 }
8021
8023
8024 for (unsigned int tid = 0; tid < n_threads; tid++)
8025 reinitScalars(tid);
8026
8028
8029 _aux->residualSetup();
8030
8032 {
8034 _displaced_problem->updateMesh();
8035 if (_mortar_data->hasDisplacedObjects())
8037 }
8038
8039 for (THREAD_ID tid = 0; tid < n_threads; tid++)
8040 {
8043 }
8044
8045#ifdef MOOSE_KOKKOS_ENABLED
8047#endif
8048
8050
8052
8054
8056
8059
8061
8064 }
8065 catch (...)
8066 {
8067 handleException("computeResidualAndJacobian");
8068 }
8069 }
8070 catch (const MooseException &)
8071 {
8072 // The buck stops here, we have already handled the exception by
8073 // calling the system's stopSolve() method, it is now up to PETSc to return a
8074 // "diverged" reason during the next solve.
8075 }
8076 catch (...)
8077 {
8078 mooseError("Unexpected exception type");
8079 }
8080
8081 resetState();
8082 _fe_vector_tags.clear();
8083 _fe_matrix_tags.clear();
8084}
8085
8086void
8087FEProblemBase::computeResidualTag(const NumericVector<Number> & soln,
8088 NumericVector<Number> & residual,
8089 TagID tag)
8090{
8091 try
8092 {
8094
8095 _current_nl_sys->associateVectorToTag(residual, tag);
8096
8097 computeResidualTags({tag});
8098
8100 }
8101 catch (MooseException & e)
8102 {
8103 // If a MooseException propagates all the way to here, it means
8104 // that it was thrown from a MOOSE system where we do not
8105 // (currently) properly support the throwing of exceptions, and
8106 // therefore we have no choice but to error out. It may be
8107 // *possible* to handle exceptions from other systems, but in the
8108 // meantime, we don't want to silently swallow any unhandled
8109 // exceptions here.
8110 mooseError("An unhandled MooseException was raised during residual computation. Please "
8111 "contact the MOOSE team for assistance.");
8112 }
8113}
8114
8115void
8116FEProblemBase::computeResidualInternal(const NumericVector<Number> & soln,
8117 NumericVector<Number> & residual,
8118 const std::set<TagID> & tags)
8119{
8120 parallel_object_only();
8121
8122 TIME_SECTION("computeResidualInternal", 1);
8123
8124 try
8125 {
8127
8129
8130 computeResidualTags(tags);
8131
8133 }
8134 catch (MooseException & e)
8135 {
8136 // If a MooseException propagates all the way to here, it means
8137 // that it was thrown from a MOOSE system where we do not
8138 // (currently) properly support the throwing of exceptions, and
8139 // therefore we have no choice but to error out. It may be
8140 // *possible* to handle exceptions from other systems, but in the
8141 // meantime, we don't want to silently swallow any unhandled
8142 // exceptions here.
8143 mooseError("An unhandled MooseException was raised during residual computation. Please "
8144 "contact the MOOSE team for assistance.");
8145 }
8146}
8147
8148void
8149FEProblemBase::computeResidualType(const NumericVector<Number> & soln,
8150 NumericVector<Number> & residual,
8151 TagID tag)
8152{
8153 TIME_SECTION("computeResidualType", 5);
8154
8155 try
8156 {
8158
8160
8162
8164 }
8165 catch (MooseException & e)
8166 {
8167 // If a MooseException propagates all the way to here, it means
8168 // that it was thrown from a MOOSE system where we do not
8169 // (currently) properly support the throwing of exceptions, and
8170 // therefore we have no choice but to error out. It may be
8171 // *possible* to handle exceptions from other systems, but in the
8172 // meantime, we don't want to silently swallow any unhandled
8173 // exceptions here.
8174 mooseError("An unhandled MooseException was raised during residual computation. Please "
8175 "contact the MOOSE team for assistance.");
8176 }
8177}
8178
8179void
8180FEProblemBase::handleException(const std::string & calling_method)
8181{
8182 auto create_exception_message =
8183 [&calling_method](const std::string & exception_type, const auto & exception)
8184 {
8185 return std::string("A " + exception_type + " was raised during FEProblemBase::" +
8186 calling_method + "\n" + std::string(exception.what()));
8187 };
8188
8189 try
8190 {
8191 throw;
8192 }
8193 catch (const MooseException & e)
8194 {
8195 setException(create_exception_message("MooseException", e));
8196 }
8197 catch (const MetaPhysicL::LogicError & e)
8198 {
8200 }
8201 catch (const libMesh::PetscSolverException & e)
8202 {
8203 // One PETSc solver exception that we cannot currently recover from are new nonzero errors. In
8204 // particular I have observed the following scenario in a parallel test:
8205 // - Both processes throw because of a new nonzero during MOOSE's computeJacobianTags
8206 // - We potentially handle the exceptions nicely here
8207 // - When the matrix is closed in libMesh's libmesh_petsc_snes_solver, there is a new nonzero
8208 // throw which we do not catch here in MOOSE and the simulation terminates. This only appears
8209 // in parallel (and not all the time; a test I was examining threw with distributed mesh, but
8210 // not with replicated). In serial there are no new throws from libmesh_petsc_snes_solver.
8211 // So for uniformity of behavior across serial/parallel, we will choose to abort here and always
8212 // produce a non-zero exit code
8213 mooseError(create_exception_message("libMesh::PetscSolverException", e));
8214 }
8215 catch (const std::exception & e)
8216 {
8217 // This might be libMesh detecting a degenerate Jacobian or matrix
8218 if (strstr(e.what(), "Jacobian") || strstr(e.what(), "singular") ||
8219 strstr(e.what(), "det != 0"))
8220 setException(create_exception_message("libMesh DegenerateMap", e));
8221 else
8222 {
8223 const auto message = create_exception_message("std::exception", e);
8225 mooseError(message);
8226 else
8227 setException(message);
8228 }
8229 }
8230
8232}
8233
8234void
8235FEProblemBase::computeResidualTags(const std::set<TagID> & tags)
8236{
8237 parallel_object_only();
8238
8239 try
8240 {
8241 try
8242 {
8243 TIME_SECTION("computeResidualTags", 5, "Computing Residual");
8244
8245 ADReal::do_derivatives = false;
8246
8248
8249 _aux->zeroVariablesForResidual();
8250
8251 unsigned int n_threads = numThreads();
8252
8254
8255 // Random interface objects
8256 for (const auto & it : _random_data_objects)
8257 it.second->updateSeeds(EXEC_LINEAR);
8258
8259 // This is itself a residual evaluation (distinct from the combined residual/Jacobian path
8260 // above, which sets this before its own updateMortarMesh() call): mark it so that
8261 // updateMortarMesh() below knows not to reinit the equation systems mid-evaluation. Reset by
8262 // resetState() at the bottom of this function.
8265 _displaced_problem->setCurrentlyComputingResidual(true);
8266
8268
8269 for (unsigned int tid = 0; tid < n_threads; tid++)
8270 reinitScalars(tid);
8271
8273
8274 _aux->residualSetup();
8275
8277 {
8279 _displaced_problem->updateMesh();
8280 if (_mortar_data->hasDisplacedObjects())
8282 }
8283
8284 for (THREAD_ID tid = 0; tid < n_threads; tid++)
8285 {
8288 }
8289
8290#ifdef MOOSE_KOKKOS_ENABLED
8292#endif
8293
8295
8297
8299
8301
8304 }
8305 catch (...)
8306 {
8307 handleException("computeResidualTags");
8308 }
8309 }
8310 catch (const MooseException &)
8311 {
8312 // The buck stops here, we have already handled the exception by
8313 // calling the system's stopSolve() method, it is now up to PETSc to return a
8314 // "diverged" reason during the next solve.
8315 }
8316 catch (...)
8317 {
8318 mooseError("Unexpected exception type");
8319 }
8320
8321 resetState();
8322}
8323
8324void
8325FEProblemBase::computeJacobianSys(NonlinearImplicitSystem & sys,
8326 const NumericVector<Number> & soln,
8327 SparseMatrix<Number> & jacobian)
8328{
8329 // Reset before Jacobian setup, calculation & execution
8331 computeJacobian(soln, jacobian, sys.number());
8332}
8333
8334void
8335FEProblemBase::computeJacobianTag(const NumericVector<Number> & soln,
8336 SparseMatrix<Number> & jacobian,
8337 TagID tag)
8338{
8340
8341 _current_nl_sys->associateMatrixToTag(jacobian, tag);
8342
8343 computeJacobianTags({tag});
8344
8346}
8347
8348void
8349FEProblemBase::computeJacobian(const NumericVector<Number> & soln,
8350 SparseMatrix<Number> & jacobian,
8351 const unsigned int nl_sys_num)
8352{
8353 setCurrentNonlinearSystem(nl_sys_num);
8354
8355 _fe_matrix_tags.clear();
8356
8357 auto & tags = getMatrixTags();
8358 for (auto & tag : tags)
8359 _fe_matrix_tags.insert(tag.second);
8360
8362}
8363
8364void
8365FEProblemBase::computeJacobianInternal(const NumericVector<Number> & soln,
8366 SparseMatrix<Number> & jacobian,
8367 const std::set<TagID> & tags)
8368{
8369 TIME_SECTION("computeJacobianInternal", 1);
8370
8372
8374
8375 computeJacobianTags(tags);
8376
8378}
8379
8380void
8381FEProblemBase::computeJacobianTags(const std::set<TagID> & tags)
8382{
8383 try
8384 {
8385 try
8386 {
8388 {
8389 TIME_SECTION("computeJacobianTags", 5, "Computing Jacobian");
8390
8391 for (auto tag : tags)
8392 if (_current_nl_sys->hasMatrix(tag))
8393 {
8394 auto & matrix = _current_nl_sys->getMatrix(tag);
8397 else
8398 matrix.zero();
8400 // PETSc algorithms require diagonal allocations regardless of whether there is
8401 // non-zero diagonal dependence. With global AD indexing we only add non-zero
8402 // dependence, so PETSc will scream at us unless we artificially add the diagonals.
8403 for (auto index : make_range(matrix.row_start(), matrix.row_stop()))
8404 matrix.add(index, index, 0);
8405 }
8406
8407 _aux->zeroVariablesForJacobian();
8408
8409 unsigned int n_threads = numThreads();
8410
8411 // Random interface objects
8412 for (const auto & it : _random_data_objects)
8413 it.second->updateSeeds(EXEC_NONLINEAR);
8414
8418 _displaced_problem->setCurrentlyComputingJacobian(true);
8419
8421
8422 for (unsigned int tid = 0; tid < n_threads; tid++)
8423 reinitScalars(tid);
8424
8426
8427 _aux->jacobianSetup();
8428
8430 {
8432 _displaced_problem->updateMesh();
8433 // A standalone scaling Jacobian is assembled without a preceding residual evaluation, so
8434 // the displaced mortar segment mesh can be stale relative to the just-updated displaced
8435 // parent mesh. Every other Jacobian evaluation is preceded by a residual (or combined
8436 // residual/Jacobian) evaluation that already rebuilt the mortar mesh, so doing it here in
8437 // the general case would be duplicative.
8438 if (_current_nl_sys->computingScalingJacobian() && _mortar_data->hasDisplacedObjects())
8440 }
8441
8442 for (unsigned int tid = 0; tid < n_threads; tid++)
8443 {
8446 }
8447
8448#ifdef MOOSE_KOKKOS_ENABLED
8450#endif
8451
8453
8455
8457
8459
8461
8463
8464 // For explicit Euler calculations for example we often compute the Jacobian one time and
8465 // then re-use it over and over. If we're performing automatic scaling, we don't want to
8466 // use that kernel, diagonal-block only Jacobian for our actual matrix when performing
8467 // solves!
8469 _has_jacobian = true;
8470 }
8471 }
8472 catch (...)
8473 {
8474 handleException("computeJacobianTags");
8475 }
8476 }
8477 catch (const MooseException &)
8478 {
8479 // The buck stops here, we have already handled the exception by
8480 // calling the system's stopSolve() method, it is now up to PETSc to return a
8481 // "diverged" reason during the next solve.
8482 }
8483 catch (...)
8484 {
8485 mooseError("Unexpected exception type");
8486 }
8487
8488 resetState();
8489}
8490
8491void
8492FEProblemBase::computeJacobianBlocks(std::vector<JacobianBlock *> & blocks,
8493 const unsigned int nl_sys_num)
8494{
8495 TIME_SECTION("computeTransientImplicitJacobian", 2);
8496 setCurrentNonlinearSystem(nl_sys_num);
8497
8499 {
8501 _displaced_problem->updateMesh();
8502 }
8503
8505
8509}
8510
8511void
8512FEProblemBase::computeJacobianBlock(SparseMatrix<Number> & jacobian,
8513 libMesh::System & precond_system,
8514 unsigned int ivar,
8515 unsigned int jvar)
8516{
8517 JacobianBlock jac_block(precond_system, jacobian, ivar, jvar);
8518 std::vector<JacobianBlock *> blocks = {&jac_block};
8519 mooseAssert(_current_nl_sys, "This should be non-null");
8521}
8522
8523void
8524FEProblemBase::computeBounds(NonlinearImplicitSystem & libmesh_dbg_var(sys),
8525 NumericVector<Number> & lower,
8526 NumericVector<Number> & upper)
8527{
8528 try
8529 {
8530 try
8531 {
8532 mooseAssert(_current_nl_sys && (sys.number() == _current_nl_sys->number()),
8533 "I expect these system numbers to be the same");
8534
8535 if (!_current_nl_sys->hasVector("lower_bound") || !_current_nl_sys->hasVector("upper_bound"))
8536 return;
8537
8538 TIME_SECTION("computeBounds", 1, "Computing Bounds");
8539
8540 NumericVector<Number> & _lower = _current_nl_sys->getVector("lower_bound");
8541 NumericVector<Number> & _upper = _current_nl_sys->getVector("upper_bound");
8542 _lower.swap(lower);
8543 _upper.swap(upper);
8544 for (THREAD_ID tid = 0; tid < numThreads(); tid++)
8546
8547 _aux->residualSetup();
8549 _lower.swap(lower);
8550 _upper.swap(upper);
8551 }
8552 catch (...)
8553 {
8554 handleException("computeBounds");
8555 }
8556 }
8557 catch (MooseException & e)
8558 {
8559 mooseError("Irrecoverable exception: " + std::string(e.what()));
8560 }
8561 catch (...)
8562 {
8563 mooseError("Unexpected exception type");
8564 }
8565}
8566
8567void
8568FEProblemBase::computeLinearSystemSys(LinearImplicitSystem & sys,
8569 SparseMatrix<Number> & system_matrix,
8570 NumericVector<Number> & rhs,
8571 const bool compute_gradients)
8572{
8573 TIME_SECTION("computeLinearSystemSys", 5);
8574
8576
8579
8580 // We are using the residual tag system for right hand sides so we fetch everything
8581 const auto & vector_tags = getVectorTags(Moose::VECTOR_TAG_RESIDUAL);
8582
8583 // We filter out tags which do not have associated vectors in the current
8584 // system. This is essential to be able to use system-dependent vector tags.
8587
8591 compute_gradients);
8592
8597 // We reset the tags to the default containers for further operations
8602}
8603
8604void
8605FEProblemBase::computeLinearSystemTags(const NumericVector<Number> & soln,
8606 const std::set<TagID> & vector_tags,
8607 const std::set<TagID> & matrix_tags,
8608 const bool compute_gradients)
8609{
8610 TIME_SECTION("computeLinearSystemTags", 5, "Computing Linear System");
8611
8613
8614 for (auto tag : matrix_tags)
8615 {
8616 auto & matrix = _current_linear_sys->getMatrix(tag);
8617 matrix.zero();
8618 }
8619
8620 unsigned int n_threads = numThreads();
8621
8623
8624 // Random interface objects
8625 for (const auto & it : _random_data_objects)
8626 it.second->updateSeeds(EXEC_NONLINEAR);
8627
8629
8631
8632 _aux->jacobianSetup();
8633
8634 for (THREAD_ID tid = 0; tid < n_threads; tid++)
8635 {
8637 }
8638
8639#ifdef MOOSE_KOKKOS_ENABLED
8641#endif
8642
8643 try
8644 {
8646 }
8647 catch (MooseException & e)
8648 {
8649 _console << "\nA MooseException was raised during Auxiliary variable computation.\n"
8650 << "The next solve will fail, the timestep will be reduced, and we will try again.\n"
8651 << std::endl;
8652
8653 // We know the next solve is going to fail, so there's no point in
8654 // computing anything else after this. Plus, using incompletely
8655 // computed AuxVariables in subsequent calculations could lead to
8656 // other errors or unhandled exceptions being thrown.
8657 return;
8658 }
8659
8662
8664
8665 _current_linear_sys->computeLinearSystemTags(vector_tags, matrix_tags, compute_gradients);
8666
8667 // Reset execution flag as after this point we are no longer on LINEAR
8669
8670 // These are the relevant parts of resetState()
8673}
8674
8675void
8676FEProblemBase::computeNearNullSpace(NonlinearImplicitSystem & libmesh_dbg_var(sys),
8677 std::vector<NumericVector<Number> *> & sp)
8678{
8679 mooseAssert(_current_nl_sys && (sys.number() == _current_nl_sys->number()),
8680 "I expect these system numbers to be the same");
8681
8682 sp.clear();
8683 for (unsigned int i = 0; i < subspaceDim("NearNullSpace"); ++i)
8684 {
8685 std::stringstream postfix;
8686 postfix << "_" << i;
8687 std::string modename = "NearNullSpace" + postfix.str();
8688 sp.push_back(&_current_nl_sys->getVector(modename));
8689 }
8690}
8691
8692void
8693FEProblemBase::computeNullSpace(NonlinearImplicitSystem & libmesh_dbg_var(sys),
8694 std::vector<NumericVector<Number> *> & sp)
8695{
8696 mooseAssert(_current_nl_sys && (sys.number() == _current_nl_sys->number()),
8697 "I expect these system numbers to be the same");
8698 sp.clear();
8699 for (unsigned int i = 0; i < subspaceDim("NullSpace"); ++i)
8700 {
8701 std::stringstream postfix;
8702 postfix << "_" << i;
8703 sp.push_back(&_current_nl_sys->getVector("NullSpace" + postfix.str()));
8704 }
8705}
8706
8707void
8708FEProblemBase::computeTransposeNullSpace(NonlinearImplicitSystem & libmesh_dbg_var(sys),
8709 std::vector<NumericVector<Number> *> & sp)
8710{
8711 mooseAssert(_current_nl_sys && (sys.number() == _current_nl_sys->number()),
8712 "I expect these system numbers to be the same");
8713 sp.clear();
8714 for (unsigned int i = 0; i < subspaceDim("TransposeNullSpace"); ++i)
8715 {
8716 std::stringstream postfix;
8717 postfix << "_" << i;
8718 sp.push_back(&_current_nl_sys->getVector("TransposeNullSpace" + postfix.str()));
8719 }
8720}
8721
8722void
8723FEProblemBase::computePostCheck(NonlinearImplicitSystem & sys,
8724 const NumericVector<Number> & old_soln,
8725 NumericVector<Number> & search_direction,
8726 NumericVector<Number> & new_soln,
8727 bool & changed_search_direction,
8728 bool & changed_new_soln)
8729{
8730 mooseAssert(_current_nl_sys && (sys.number() == _current_nl_sys->number()),
8731 "I expect these system numbers to be the same");
8732
8733 // This function replaces the old PetscSupport::dampedCheck() function.
8734 //
8735 // 1.) Recreate code in PetscSupport::dampedCheck() for constructing
8736 // ghosted "soln" and "update" vectors.
8737 // 2.) Call FEProblemBase::computeDamping() with these ghost vectors.
8738 // 3.) Recreate the code in PetscSupport::dampedCheck() to actually update
8739 // the solution vector based on the damping, and set the "changed" flags
8740 // appropriately.
8741
8742 TIME_SECTION("computePostCheck", 2, "Computing Post Check");
8743
8745
8746 // MOOSE's FEProblemBase doesn't update the solution during the
8747 // postcheck, but FEProblemBase-derived classes might.
8749 {
8750 // We need ghosted versions of new_soln and search_direction (the
8751 // ones we get from libmesh/PETSc are PARALLEL vectors. To make
8752 // our lives simpler, we use the same ghosting pattern as the
8753 // system's current_local_solution to create new ghosted vectors.
8754
8755 // Construct zeroed-out clones with the same ghosted dofs as the
8756 // System's current_local_solution.
8757 std::unique_ptr<NumericVector<Number>> ghosted_solution =
8758 sys.current_local_solution->zero_clone(),
8759 ghosted_search_direction =
8760 sys.current_local_solution->zero_clone();
8761
8762 // Copy values from input vectors into clones with ghosted values.
8763 *ghosted_solution = new_soln;
8764 *ghosted_search_direction = search_direction;
8765
8766 if (_has_dampers)
8767 {
8768 // Compute the damping coefficient using the ghosted vectors
8769 Real damping = computeDamping(*ghosted_solution, *ghosted_search_direction);
8770
8771 // If some non-trivial damping was computed, update the new_soln
8772 // vector accordingly.
8773 if (damping < 1.0)
8774 {
8775 new_soln = old_soln;
8776 new_soln.add(-damping, search_direction);
8777 changed_new_soln = true;
8778 }
8779 }
8780
8782 {
8783 // Update the ghosted copy of the new solution, if necessary.
8784 if (changed_new_soln)
8785 *ghosted_solution = new_soln;
8786
8787 bool updated_solution = updateSolution(new_soln, *ghosted_solution);
8788 if (updated_solution)
8789 changed_new_soln = true;
8790 }
8791 }
8792
8794 {
8796 _aux->copyCurrentIntoPreviousNL();
8797 }
8798
8799 // MOOSE doesn't change the search_direction
8800 changed_search_direction = false;
8801
8803}
8804
8805Real
8806FEProblemBase::computeDamping(const NumericVector<Number> & soln,
8807 const NumericVector<Number> & update)
8808{
8809 // Default to no damping
8810 Real damping = 1.0;
8811
8812 if (_has_dampers)
8813 {
8814 TIME_SECTION("computeDamping", 1, "Computing Damping");
8815
8816 // Save pointer to the current solution
8817 const NumericVector<Number> * _saved_current_solution = _current_nl_sys->currentSolution();
8818
8820 // For now, do not re-compute auxiliary variables. Doing so allows a wild solution increment
8821 // to get to the material models, which may not be able to cope with drastically different
8822 // values. Once more complete dependency checking is in place, auxiliary variables (and
8823 // material properties) will be computed as needed by dampers.
8824 // _aux.compute();
8825 damping = _current_nl_sys->computeDamping(soln, update);
8826
8827 // restore saved solution
8828 _current_nl_sys->setSolution(*_saved_current_solution);
8829 }
8830
8831 return damping;
8832}
8833
8834bool
8836{
8837 return false;
8838}
8839
8840bool
8841FEProblemBase::updateSolution(NumericVector<Number> & /*vec_solution*/,
8842 NumericVector<Number> & /*ghosted_solution*/)
8843{
8844 return false;
8845}
8846
8847void
8848FEProblemBase::predictorCleanup(NumericVector<Number> & /*ghosted_solution*/)
8849{
8850}
8851
8852void
8854{
8855 parallel_object_only();
8856
8859}
8860
8861void
8863{
8864 TIME_SECTION("updateGeometricSearch", 3, "Updating Geometric Search");
8865
8867
8869 _displaced_problem->updateGeomSearch(type);
8870}
8871
8872void
8874{
8875 TIME_SECTION("updateMortarMesh", 5, "Updating Mortar Mesh");
8876
8878
8879 // If any mortar interface's coverage changed, the DoF ghosting and sparsity that
8880 // AugmentSparsityOnInterface computed from the previous coverage are stale (see
8881 // reinitBecauseOfGhostingOrNewGeomObjects()'s mortar_changed parameter); refresh them now rather
8882 // than leaving that to the caller, since this may be called mid-solve where no other reinit
8883 // follows. Guard on _initialized: this is also called from init() itself, before es().init() has
8884 // run for the first time, and reinit()ing an EquationSystems that has never been init()ed is not
8885 // meaningful (init() immediately after will pick up whatever _mortar_data->update() just built).
8886 if (_mortar_data->update() && _initialized && !currentlyComputingResidual() &&
8888 reinitBecauseOfGhostingOrNewGeomObjects(/*mortar_changed=*/true);
8889}
8890
8891void
8893 const std::pair<BoundaryID, BoundaryID> & primary_secondary_boundary_pair,
8894 const std::pair<SubdomainID, SubdomainID> & primary_secondary_subdomain_pair,
8895 bool on_displaced,
8896 bool periodic,
8897 const bool debug,
8898 const bool correct_edge_dropping,
8899 const Real minimum_projection_angle,
8900 const Mortar3DSubpatchPlane mortar_3d_subpatch_plane,
8901 const MooseEnum & triangulation,
8902 const bool triangulate_triangles,
8903 const Mortar3DQuadraturePointMapping mortar_3d_qp_mapping)
8904{
8905 _has_mortar = true;
8906
8907 if (on_displaced)
8908 return _mortar_data->createMortarInterface(primary_secondary_boundary_pair,
8909 primary_secondary_subdomain_pair,
8911 on_displaced,
8912 periodic,
8913 debug,
8914 correct_edge_dropping,
8915 minimum_projection_angle,
8916 mortar_3d_subpatch_plane,
8917 triangulation,
8918 triangulate_triangles,
8919 mortar_3d_qp_mapping);
8920 else
8921 return _mortar_data->createMortarInterface(primary_secondary_boundary_pair,
8922 primary_secondary_subdomain_pair,
8923 *this,
8924 on_displaced,
8925 periodic,
8926 debug,
8927 correct_edge_dropping,
8928 minimum_projection_angle,
8929 mortar_3d_subpatch_plane,
8930 triangulation,
8931 triangulate_triangles,
8932 mortar_3d_qp_mapping);
8933}
8934
8937 const std::pair<BoundaryID, BoundaryID> & primary_secondary_boundary_pair,
8938 const std::pair<SubdomainID, SubdomainID> & primary_secondary_subdomain_pair,
8939 bool on_displaced) const
8940{
8941 return _mortar_data->getMortarInterface(
8942 primary_secondary_boundary_pair, primary_secondary_subdomain_pair, on_displaced);
8943}
8944
8947 const std::pair<BoundaryID, BoundaryID> & primary_secondary_boundary_pair,
8948 const std::pair<SubdomainID, SubdomainID> & primary_secondary_subdomain_pair,
8949 bool on_displaced)
8950{
8951 return _mortar_data->getMortarInterface(
8952 primary_secondary_boundary_pair, primary_secondary_subdomain_pair, on_displaced);
8953}
8954
8955void
8957{
8958 if (_displaced_problem) // Only need to do this if things are moving...
8959 {
8960 TIME_SECTION("possiblyRebuildGeomSearchPatches", 5, "Rebuilding Geometric Search Patches");
8961
8962 switch (_mesh.getPatchUpdateStrategy())
8963 {
8964 case Moose::Never:
8965 break;
8966 case Moose::Iteration:
8967 // Update the list of ghosted elements at the start of the time step
8970
8971 _displaced_problem->geomSearchData().updateGhostedElems();
8973
8974 // The commands below ensure that the sparsity of the Jacobian matrix is
8975 // augmented at the start of the time step using neighbor nodes from the end
8976 // of the previous time step.
8977
8979
8980 // This is needed to reinitialize PETSc output
8982
8983 break;
8984
8985 case Moose::Auto:
8986 {
8987 Real max = _displaced_problem->geomSearchData().maxPatchPercentage();
8988 _communicator.max(max);
8989
8990 // If we haven't moved very far through the patch
8991 if (max < 0.4)
8992 break;
8993 }
8994 libmesh_fallthrough();
8995
8996 // Let this fall through if things do need to be updated...
8997 case Moose::Always:
8998 // Flush output here to see the message before the reinitialization, which could take a
8999 // while
9000 _console << "\n\nUpdating geometric search patches\n" << std::endl;
9001
9004
9005 _displaced_problem->geomSearchData().clearNearestNodeLocators();
9007
9009
9010 // This is needed to reinitialize PETSc output
9012 }
9013 }
9014}
9015
9016#ifdef LIBMESH_ENABLE_AMR
9017void
9019{
9020 unsigned int n = adaptivity().getInitialSteps();
9022 if (n)
9023 {
9024 if (!_mesh.interiorLowerDBlocks().empty() || !_mesh.boundaryLowerDBlocks().empty())
9025 mooseError("HFEM does not support mesh adaptivity currently.");
9026
9027 TIME_SECTION("initialAdaptMesh", 2, "Performing Initial Adaptivity");
9028
9029 for (unsigned int i = 0; i < n; i++)
9030 {
9033
9035 {
9037 /*intermediate_change=*/false, /*contract_mesh=*/true, /*clean_refinement_flags=*/true);
9038
9039 // reproject the initial condition
9041
9043 }
9044 else
9045 {
9046 _console << "Mesh unchanged, skipping remaining steps..." << std::endl;
9047 return;
9048 }
9049 }
9050 }
9051}
9052
9053bool
9055{
9056 // reset cycle counter
9058
9060 return false;
9061
9062 TIME_SECTION("adaptMesh", 3, "Adapting Mesh");
9063
9064 unsigned int cycles_per_step = _adaptivity.getCyclesPerStep();
9065
9066 bool mesh_changed = false;
9067
9068 for (unsigned int i = 0; i < cycles_per_step; ++i)
9069 {
9070 if (!_mesh.interiorLowerDBlocks().empty() || !_mesh.boundaryLowerDBlocks().empty())
9071 mooseError("HFEM does not support mesh adaptivity currently.");
9072
9073 // Markers were already computed once by Executioner
9074 if (_adaptivity.getRecomputeMarkersFlag() && i > 0)
9076
9077 bool mesh_changed_this_step;
9078 mesh_changed_this_step = _adaptivity.adaptMesh();
9079
9080 if (mesh_changed_this_step)
9081 {
9082 mesh_changed = true;
9083
9085 /*intermediate_change=*/true, /*contract_mesh=*/true, /*clean_refinement_flags=*/true);
9087 }
9088 else
9089 {
9090 // If the mesh didn't change, we still need to update the displaced mesh
9091 // to undo the undisplacement performed in Adaptivity::adaptMesh
9093 _displaced_problem->updateMesh();
9094
9095 _console << "Mesh unchanged, skipping remaining steps..." << std::endl;
9096 break;
9097 }
9098
9099 // Show adaptivity progress
9100 _console << std::flush;
9101 }
9102
9103 // We're done with all intermediate changes; now get systems ready
9104 // for real if necessary.
9105 if (mesh_changed)
9106 es().reinit_systems();
9107
9108 // Execute multi-apps that need to run after adaptivity, but before the next timestep.
9110
9111 return mesh_changed;
9112}
9113#endif // LIBMESH_ENABLE_AMR
9114
9115void
9116FEProblemBase::initXFEM(std::shared_ptr<XFEMInterface> xfem)
9117{
9118 _xfem = xfem;
9119 _xfem->setMesh(&_mesh);
9120 if (_displaced_mesh)
9121 _xfem->setDisplacedMesh(_displaced_mesh);
9122
9123 auto fill_data = [this](auto & storage)
9124 {
9125 std::vector<MaterialData *> data(numThreads());
9126 for (const auto tid : make_range(numThreads()))
9127 data[tid] = &storage.getMaterialData(tid);
9128 return data;
9129 };
9130 _xfem->setMaterialData(fill_data(_material_props));
9131 _xfem->setBoundaryMaterialData(fill_data(_bnd_material_props));
9132
9133 unsigned int n_threads = numThreads();
9134 for (unsigned int i = 0; i < n_threads; ++i)
9135 for (const auto nl_sys_num : index_range(_nl))
9136 {
9137 _assembly[i][nl_sys_num]->setXFEM(_xfem);
9139 _displaced_problem->assembly(i, nl_sys_num).setXFEM(_xfem);
9140 }
9141}
9142
9143bool
9145{
9146 TIME_SECTION("updateMeshXFEM", 5, "Updating XFEM");
9147
9148 bool updated = false;
9149 if (haveXFEM())
9150 {
9151 if (_xfem->updateHeal())
9152 // XFEM exodiff tests rely on a given numbering because they cannot use map = true due to
9153 // having coincident elements. While conceptually speaking we do not need to contract the
9154 // mesh, we need its call to renumber_nodes_and_elements in order to preserve these tests
9156 /*intermediate_change=*/false, /*contract_mesh=*/true, /*clean_refinement_flags=*/false);
9157
9158 updated = _xfem->update(_time, _nl, *_aux);
9159 if (updated)
9160 {
9162 /*intermediate_change=*/false, /*contract_mesh=*/true, /*clean_refinement_flags=*/false);
9163 _xfem->initSolution(_nl, *_aux);
9165 _console << "\nXFEM update complete: Mesh modified" << std::endl;
9166 }
9167 else
9168 _console << "\nXFEM update complete: Mesh not modified" << std::endl;
9169 }
9170 return updated;
9171}
9172
9173void
9174FEProblemBase::meshChanged(const bool intermediate_change,
9175 const bool contract_mesh,
9176 const bool clean_refinement_flags)
9177{
9178 TIME_SECTION("meshChanged", 3, "Handling Mesh Changes");
9179
9180 const bool should_contract = contract_mesh && allowMeshContractionAfterMeshChanged();
9181
9183
9186 _mesh.cacheChangedLists(); // Currently only used with adaptivity and stateful material
9187 // properties
9188
9189 // Clear these out because they corresponded to the old mesh
9190 _ghosted_elems.clear();
9192
9193 // The mesh changed. We notify the MooseMesh first, because
9194 // callbacks (e.g. for sparsity calculations) triggered by the
9195 // EquationSystems reinit may require up-to-date MooseMesh caches.
9197
9198 // If we're just going to alter the mesh again, all we need to
9199 // handle here is AMR and projections, not full system reinit
9200 if (intermediate_change)
9201 es().reinit_solutions();
9202 else
9203 es().reinit();
9204
9205 if (should_contract)
9206 // Once vectors are restricted, we can delete children of coarsened elements
9207 _mesh.getMesh().contract();
9208 if (clean_refinement_flags)
9209 {
9210 // Finally clear refinement flags so that if someone tries to project vectors again without
9211 // an intervening mesh refinement to clear flags they won't run into trouble
9213 refinement.clean_refinement_flags();
9214 }
9215
9216 if (!intermediate_change)
9217 {
9218 // Since the mesh has changed, we need to make sure that we update any of our
9219 // MOOSE-system specific data.
9220 for (auto & sys : _solver_systems)
9221 sys->reinit();
9222 _aux->reinit();
9223 }
9224
9225 // Updating MooseMesh first breaks other adaptivity code, unless we
9226 // then *again* update the MooseMesh caches. E.g. the definition of
9227 // "active" and "local" may have been *changed* by refinement and
9228 // repartitioning done in EquationSystems::reinit().
9230
9231 // If we have finite volume variables, we will need to recompute additional elemental/face
9232 // quantities
9235
9236 // Let the meshChangedInterface notify the mesh changed event before we update the active
9237 // semilocal nodes, because the set of ghosted elements may potentially be updated during a mesh
9238 // changed event.
9239 for (const auto & mci : _notify_when_mesh_changes)
9240 mci->meshChanged();
9241
9242 // Since the Mesh changed, update the PointLocator object used by DiracKernels.
9244
9245 // Need to redo ghosting
9247
9249 {
9250 // Mesh contraction is necessary when a displaced problem is used.
9252 mooseError("Disabling mesh contraction is not implemented when a displaced problem is used. "
9253 "Please contact a "
9254 "developer of this application to discuss the combination of these features.");
9255
9256 _displaced_problem->meshChanged(should_contract, clean_refinement_flags);
9258 }
9259
9261
9264
9265 // Just like we reinitialized our geometric search objects, we also need to reinitialize our
9266 // mortar meshes. Note that this needs to happen after DisplacedProblem::meshChanged because the
9267 // mortar mesh discretization will depend necessarily on the displaced mesh being re-displaced
9268 _mortar_data->meshChanged();
9269
9270 // Nonlinear systems hold the mortar mesh functors. The domains of definition of the mortar
9271 // functors might have changed when the mesh changed.
9272 for (auto & nl_sys : _nl)
9273 nl_sys->reinitMortarFunctors();
9274
9275 reinitBecauseOfGhostingOrNewGeomObjects(/*mortar_changed=*/true);
9276
9277 // We need to create new storage for newly active elements, and copy
9278 // stateful properties from the old elements.
9281 {
9282 if (doingPRefinement())
9284
9285 // Prolong properties onto newly refined elements' children
9286 {
9288 /* refine = */ true, *this, _material_props, _bnd_material_props, _assembly);
9289 const auto & range = *_mesh.refinedElementRange();
9290 Threads::parallel_reduce(range, pmp, numThreads());
9291
9292 // Concurrent erasure from the shared hash map is not safe while we are reading from it in
9293 // ProjectMaterialProperties, so we handle erasure here. Moreover, erasure based on key is
9294 // not thread safe in and of itself because it is a read-write operation. Note that we do not
9295 // do the erasure for p-refinement because the coarse level element is the same as our active
9296 // refined level element
9297 if (!doingPRefinement())
9298 for (const auto & elem : range)
9299 {
9303 }
9304 }
9305
9306 // Restrict properties onto newly coarsened elements
9307 {
9309 /* refine = */ false, *this, _material_props, _bnd_material_props, _assembly);
9310 const auto & range = *_mesh.coarsenedElementRange();
9311 Threads::parallel_reduce(range, pmp, numThreads());
9312 // Note that we do not do the erasure for p-refinement because the coarse level element is the
9313 // same as our active refined level element
9314 if (!doingPRefinement())
9315 for (const auto & elem : range)
9316 {
9317 auto && coarsened_children = _mesh.coarsenedElementChildren(elem);
9318 for (auto && child : coarsened_children)
9319 {
9323 }
9324 }
9325 }
9326 }
9327
9330
9331 _has_jacobian = false; // we have to recompute jacobian when mesh changed
9332
9333 // Now for backwards compatibility with user code that overrode the old no-arg meshChanged we must
9334 // call it here
9335 meshChanged();
9336}
9337
9338void
9343
9344void
9349
9350void
9352{
9353 for (const auto & mdi : _notify_when_mesh_displaces)
9354 mdi->meshDisplaced();
9355}
9356
9357void
9358FEProblemBase::initElementStatefulProps(const ConstElemRange & elem_range, const bool threaded)
9359{
9362 if (threaded)
9363 Threads::parallel_reduce(elem_range, cmt, numThreads());
9364 else
9365 cmt(elem_range, true);
9366
9367#ifdef MOOSE_KOKKOS_ENABLED
9370#endif
9371}
9372
9373void
9375{
9376 TIME_SECTION("checkProblemIntegrity", 5);
9377
9378 // Subdomains specified by the "Problem/block" parameter
9379 const auto & subdomain_names = getParam<std::vector<SubdomainName>>("block");
9380 auto mesh_subdomains_vec = MooseMeshUtils::getSubdomainIDs(_mesh, subdomain_names);
9381 std::set<SubdomainID> mesh_subdomains(mesh_subdomains_vec.begin(), mesh_subdomains_vec.end());
9382
9383 // Check kernel coverage of subdomains (blocks) in the mesh
9386 {
9387 std::set<SubdomainID> blocks;
9390 blocks = mesh_subdomains;
9392 {
9393 blocks = mesh_subdomains;
9394 for (const auto & subdomain_name : _kernel_coverage_blocks)
9395 {
9396 const auto id = _mesh.getSubdomainID(subdomain_name);
9397 if (id == Moose::INVALID_BLOCK_ID)
9398 paramError("kernel_coverage_block_list",
9399 "Subdomain \"",
9400 subdomain_name,
9401 "\" not found in mesh.");
9402 blocks.erase(id);
9403 }
9404 }
9406 for (const auto & subdomain_name : _kernel_coverage_blocks)
9407 {
9408 const auto id = _mesh.getSubdomainID(subdomain_name);
9409 if (id == Moose::INVALID_BLOCK_ID)
9410 paramError("kernel_coverage_block_list",
9411 "Subdomain \"",
9412 subdomain_name,
9413 "\" not found in mesh.");
9414 blocks.insert(id);
9415 }
9416 if (!blocks.empty())
9417 for (auto & nl : _nl)
9418 nl->checkKernelCoverage(blocks);
9419 }
9420
9421 // Check materials
9422 {
9423#ifdef LIBMESH_ENABLE_AMR
9424 if ((_adaptivity.isOn() || _num_grid_steps) &&
9427 {
9428 _console << "Using EXPERIMENTAL Stateful Material Property projection with Adaptivity!\n"
9429 << std::flush;
9430 }
9431#endif
9432
9433 std::set<SubdomainID> local_mesh_subs(mesh_subdomains);
9434
9437 {
9442 bool check_material_coverage = false;
9443 std::set<SubdomainID> ids = _all_materials.getActiveBlocks();
9444 for (const auto & id : ids)
9445 {
9446 local_mesh_subs.erase(id);
9447 check_material_coverage = true;
9448 }
9449
9450 // did the user limit the subdomains to be checked?
9452 {
9453 for (const auto & subdomain_name : _material_coverage_blocks)
9454 {
9455 const auto id = _mesh.getSubdomainID(subdomain_name);
9456 if (id == Moose::INVALID_BLOCK_ID)
9457 paramError("material_coverage_block_list",
9458 "Subdomain \"" + subdomain_name + "\" not found in mesh.");
9459 local_mesh_subs.erase(id);
9460 }
9461 }
9463 {
9464 std::set<SubdomainID> blocks(local_mesh_subs);
9465 for (const auto & subdomain_name : _material_coverage_blocks)
9466 {
9467 const auto id = _mesh.getSubdomainID(subdomain_name);
9468 if (id == Moose::INVALID_BLOCK_ID)
9469 paramError("material_coverage_block_list",
9470 "Subdomain \"" + subdomain_name + "\" not found in mesh.");
9471 blocks.erase(id);
9472 }
9473 for (const auto id : blocks)
9474 local_mesh_subs.erase(id);
9475 }
9476
9477 // also exclude mortar spaces from the material check
9478 auto && mortar_subdomain_ids = _mortar_data->getMortarSubdomainIDs();
9479 for (auto subdomain_id : mortar_subdomain_ids)
9480 local_mesh_subs.erase(subdomain_id);
9481
9482 // Check Material Coverage
9483 if (check_material_coverage && !local_mesh_subs.empty())
9484 {
9485 std::stringstream extra_subdomain_ids;
9487 std::copy(local_mesh_subs.begin(),
9488 local_mesh_subs.end(),
9489 std::ostream_iterator<unsigned int>(extra_subdomain_ids, " "));
9491 std::vector<SubdomainID> local_mesh_subs_vec(local_mesh_subs.begin(),
9492 local_mesh_subs.end());
9493
9494 mooseError("The following blocks from your input mesh do not contain an active material: " +
9495 extra_subdomain_ids.str() +
9496 "(names: " + Moose::stringify(_mesh.getSubdomainNames(local_mesh_subs_vec)) +
9497 ")\nWhen ANY mesh block contains a Material object, "
9498 "all blocks must contain a Material object.\n");
9499 }
9500 }
9501
9502 // Check material properties on blocks and boundaries
9505
9506 // Check that material properties exist when requested by other properties on a given block
9507 const auto & materials = _all_materials.getActiveObjects();
9508 for (const auto & material : materials)
9509 material->checkStatefulSanity();
9510
9511 // auto mats_to_check = _materials.getActiveBlockObjects();
9512 // const auto & discrete_materials = _discrete_materials.getActiveBlockObjects();
9513 // for (const auto & map_it : discrete_materials)
9514 // for (const auto & container_element : map_it.second)
9515 // mats_to_check[map_it.first].push_back(container_element);
9518 }
9519
9521
9523
9524 // Verify that we don't have any Element type/Coordinate Type conflicts
9526
9527 // Coordinate transforms are only intended for use with MultiApps at this time. If you are not
9528 // using multiapps but still require these, contact a moose developer
9530 !hasMultiApps())
9531 mooseError("Coordinate transformation parameters, listed below, are only to be used in the "
9532 "context of application to application field transfers at this time. The mesh is "
9533 "not modified by these parameters within an application.\n"
9534 "You should likely use a 'TransformGenerator' in the [Mesh] block to achieve the "
9535 "desired mesh modification.\n\n",
9537
9538 // If using displacements, verify that the order of the displacement
9539 // variables matches the order of the elements in the displaced
9540 // mesh.
9542
9543 // Check for postprocessor names with same name as a scalar variable
9545}
9546
9547void
9549{
9551 {
9552 bool mesh_has_second_order_elements = false;
9553 for (const auto & elem : as_range(_displaced_mesh->activeLocalElementsBegin(),
9555 {
9556 if (elem->default_order() == SECOND)
9557 {
9558 mesh_has_second_order_elements = true;
9559 break;
9560 }
9561 }
9562
9563 // We checked our local elements, so take the max over all processors.
9564 _displaced_mesh->comm().max(mesh_has_second_order_elements);
9565
9566 // If the Mesh has second order elements, make sure the
9567 // displacement variables are second-order.
9568 if (mesh_has_second_order_elements)
9569 {
9570 const std::vector<std::string> & displacement_variables =
9571 _displaced_problem->getDisplacementVarNames();
9572
9573 for (const auto & var_name : displacement_variables)
9574 {
9575 MooseVariableFEBase & mv =
9576 _displaced_problem->getVariable(/*tid=*/0,
9577 var_name,
9580 if (mv.order() != SECOND)
9581 mooseError("Error: mesh has SECOND order elements, so all displacement variables must be "
9582 "SECOND order.");
9583 }
9584 }
9585 }
9586}
9587
9588void
9590{
9591 // Check user_objects block coverage
9592 std::set<SubdomainID> mesh_subdomains = _mesh.meshSubdomains();
9593 std::set<SubdomainID> user_objects_blocks;
9594
9595 // gather names of all user_objects that were defined in the input file
9596 // and the blocks that they are defined on
9597 std::set<std::string> names;
9598
9599 std::vector<UserObjectBase *> objects;
9601
9602 for (const auto & obj : objects)
9603 names.insert(obj->name());
9604
9605 // See if all referenced blocks are covered
9606 std::set<SubdomainID> difference;
9607 std::set_difference(user_objects_blocks.begin(),
9608 user_objects_blocks.end(),
9609 mesh_subdomains.begin(),
9610 mesh_subdomains.end(),
9611 std::inserter(difference, difference.end()));
9612
9613 if (!difference.empty())
9614 {
9615 std::ostringstream oss;
9616 oss << "One or more UserObjects is referencing a nonexistent block:\n";
9617 for (const auto & id : difference)
9618 oss << id << "\n";
9619 mooseError(oss.str());
9620 }
9621}
9622
9623void
9625{
9626 std::vector<FVGradientMethod *> methods;
9627 theWarehouse().query().condition<AttribSystem>("FVGradientMethod").queryInto(methods);
9628 for (auto * method : methods)
9629 method->resolveGradientMethodDependencies(*this);
9630}
9631
9632void
9634 const std::map<SubdomainID, std::vector<std::shared_ptr<MaterialBase>>> & materials_map)
9635{
9636 for (const auto & it : materials_map)
9637 {
9639 std::set<std::string> block_depend_props, block_supplied_props;
9640
9641 for (const auto & mat1 : it.second)
9642 {
9643 auto & alldeps = mat1->getMatPropDependencies(); // includes requested stateful props
9644 for (auto & dep : alldeps)
9645 block_depend_props.insert(_material_prop_registry.getName(dep));
9646
9647 // See if any of the active materials supply this property
9648 for (const auto & mat2 : it.second)
9649 {
9650 const std::set<std::string> & supplied_props = mat2->MaterialBase::getSuppliedItems();
9651 block_supplied_props.insert(supplied_props.begin(), supplied_props.end());
9652 }
9653 }
9654
9655 // Add zero material properties specific to this block and unrestricted
9656 block_supplied_props.insert(_zero_block_material_props[it.first].begin(),
9657 _zero_block_material_props[it.first].end());
9658
9659 // Error check to make sure all properties consumed by materials are supplied on this block
9660 std::set<std::string> difference;
9661 std::set_difference(block_depend_props.begin(),
9662 block_depend_props.end(),
9663 block_supplied_props.begin(),
9664 block_supplied_props.end(),
9665 std::inserter(difference, difference.end()));
9666
9667 if (!difference.empty())
9668 {
9669 std::ostringstream oss;
9670 oss << "One or more Material Properties were not supplied on block ";
9671 const std::string & subdomain_name = _mesh.getSubdomainName(it.first);
9672 if (subdomain_name.length() > 0)
9673 oss << subdomain_name << " (" << it.first << ")";
9674 else
9675 oss << it.first;
9676 oss << ":\n";
9677 for (const auto & name : difference)
9678 oss << name << "\n";
9679 mooseError(oss.str());
9680 }
9681 }
9682
9683 // This loop checks that materials are not supplied by multiple Material objects
9684 for (const auto & it : materials_map)
9685 {
9686 const auto & materials = it.second;
9687 std::set<std::string> inner_supplied, outer_supplied;
9688
9689 for (const auto & outer_mat : materials)
9690 {
9691 // Storage for properties for this material (outer) and all other materials (inner)
9692 outer_supplied = outer_mat->getSuppliedItems();
9693 inner_supplied.clear();
9694
9695 // Property to material map for error reporting
9696 std::map<std::string, std::set<std::string>> prop_to_mat;
9697 for (const auto & name : outer_supplied)
9698 prop_to_mat[name].insert(outer_mat->name());
9699
9700 for (const auto & inner_mat : materials)
9701 {
9702 if (outer_mat == inner_mat)
9703 continue;
9704
9705 // Check whether these materials are an AD pair
9706 auto outer_mat_type = outer_mat->type();
9707 auto inner_mat_type = inner_mat->type();
9708 removeSubstring(outer_mat_type, "<RESIDUAL>");
9709 removeSubstring(outer_mat_type, "<JACOBIAN>");
9710 removeSubstring(inner_mat_type, "<RESIDUAL>");
9711 removeSubstring(inner_mat_type, "<JACOBIAN>");
9712 if (outer_mat_type == inner_mat_type && outer_mat_type != outer_mat->type() &&
9713 inner_mat_type != inner_mat->type())
9714 continue;
9715
9716 inner_supplied.insert(inner_mat->getSuppliedItems().begin(),
9717 inner_mat->getSuppliedItems().end());
9718
9719 for (const auto & inner_supplied_name : inner_supplied)
9720 prop_to_mat[inner_supplied_name].insert(inner_mat->name());
9721 }
9722
9723 // Test that a property isn't supplied on multiple blocks
9724 std::set<std::string> intersection;
9725 std::set_intersection(outer_supplied.begin(),
9726 outer_supplied.end(),
9727 inner_supplied.begin(),
9728 inner_supplied.end(),
9729 std::inserter(intersection, intersection.end()));
9730
9731 if (!intersection.empty())
9732 {
9733 std::ostringstream oss;
9734 oss << "The following material properties are declared on block " << it.first
9735 << " by multiple materials:\n";
9736 oss << ConsoleUtils::indent(2) << std::setw(30) << std::left << "Material Property"
9737 << "Material Objects\n";
9738 for (const auto & outer_name : intersection)
9739 {
9740 oss << ConsoleUtils::indent(2) << std::setw(30) << std::left << outer_name;
9741 for (const auto & inner_name : prop_to_mat[outer_name])
9742 oss << inner_name << " ";
9743 oss << '\n';
9744 }
9745
9746 mooseError(oss.str());
9747 break;
9748 }
9749 }
9750 }
9751}
9752
9753void
9758
9759void
9760FEProblemBase::setRestartFile(const std::string & file_name)
9761{
9762 if (_app.isRecovering())
9763 {
9764 mooseInfo("Restart file ", file_name, " is NOT being used since we are performing recovery.");
9765 }
9766 else
9767 {
9768 _app.setRestart(true);
9770 mooseInfo("Using ", file_name, " for restart.");
9771 }
9772}
9773
9774std::vector<VariableName>
9776{
9777 std::vector<VariableName> names;
9778
9779 for (auto & sys : _solver_systems)
9780 {
9781 const std::vector<VariableName> & var_names = sys->getVariableNames();
9782 names.insert(names.end(), var_names.begin(), var_names.end());
9783 }
9784
9785 const std::vector<VariableName> & aux_var_names = _aux->getVariableNames();
9786 names.insert(names.end(), aux_var_names.begin(), aux_var_names.end());
9787
9788 return names;
9789}
9790
9792FEProblemBase::solverParams(const unsigned int solver_sys_num)
9793{
9794 mooseAssert(solver_sys_num < numSolverSystems(),
9795 "Solver system number '" << solver_sys_num << "' is out of bounds. We have '"
9796 << numSolverSystems() << "' solver systems");
9797 return _solver_params[solver_sys_num];
9798}
9799
9800const SolverParams &
9801FEProblemBase::solverParams(const unsigned int solver_sys_num) const
9802{
9803 return const_cast<FEProblemBase *>(this)->solverParams(solver_sys_num);
9804}
9805
9806void
9807FEProblemBase::registerRandomInterface(RandomInterface & random_interface, const std::string & name)
9808{
9809 auto insert_pair = moose_try_emplace(
9810 _random_data_objects, name, std::make_unique<RandomData>(*this, random_interface));
9811
9812 auto random_data_ptr = insert_pair.first->second.get();
9813 random_interface.setRandomDataPointer(random_data_ptr);
9814}
9815
9816bool
9818{
9819 if (_bnd_mat_side_cache[tid].find(bnd_id) == _bnd_mat_side_cache[tid].end())
9820 {
9821 auto & bnd_mat_side_cache = _bnd_mat_side_cache[tid][bnd_id];
9822 bnd_mat_side_cache = false;
9823
9824 // Check systems
9825 if (_aux->needMaterialOnSide(bnd_id))
9826 {
9827 bnd_mat_side_cache = true;
9828 return true;
9829 }
9830 for (auto & nl : _nl)
9831 if (nl->needBoundaryMaterialOnSide(bnd_id, tid))
9832 {
9833 bnd_mat_side_cache = true;
9834 return true;
9835 }
9836
9837 // TODO: these objects should be checked for whether they actually consume materials
9838 // NOTE: InterfaceUO can use use boundary properties too
9839 if (theWarehouse()
9840 .query()
9841 .condition<AttribThread>(tid)
9842 .condition<AttribInterfaces>(Interfaces::SideUserObject | Interfaces::DomainUserObject |
9844 .condition<AttribBoundaries>(bnd_id)
9845 .count() > 0)
9846 {
9847 bnd_mat_side_cache = true;
9848 return true;
9849 }
9850 }
9851
9852 return _bnd_mat_side_cache[tid][bnd_id];
9853}
9854
9855bool
9857{
9858 if (_interface_mat_side_cache[tid].find(bnd_id) == _interface_mat_side_cache[tid].end())
9859 {
9860 auto & interface_mat_side_cache = _interface_mat_side_cache[tid][bnd_id];
9861 interface_mat_side_cache = false;
9862
9863 // Aux-system has not needed interface materials so far
9864 for (auto & nl : _nl)
9865 if (nl->needInterfaceMaterialOnSide(bnd_id, tid))
9866 {
9867 interface_mat_side_cache = true;
9868 return true;
9869 }
9870
9871 // TODO: these objects should be checked for whether they actually consume materials
9872 if (theWarehouse()
9873 .query()
9874 .condition<AttribThread>(tid)
9875 .condition<AttribInterfaces>(Interfaces::InterfaceUserObject |
9877 .condition<AttribBoundaries>(bnd_id)
9878 .count() > 0)
9879 {
9880 interface_mat_side_cache = true;
9881 return true;
9882 }
9883 else if (_interface_materials.hasActiveBoundaryObjects(bnd_id, tid))
9884 {
9885 interface_mat_side_cache = true;
9886 return true;
9887 }
9888 }
9889 return _interface_mat_side_cache[tid][bnd_id];
9890}
9891
9892bool
9894{
9895 if (_block_mat_side_cache[tid].find(subdomain_id) == _block_mat_side_cache[tid].end())
9896 {
9897 _block_mat_side_cache[tid][subdomain_id] = false;
9898
9899 for (auto & nl : _nl)
9900 if (nl->needInternalNeighborSideMaterial(subdomain_id, tid))
9901 {
9902 _block_mat_side_cache[tid][subdomain_id] = true;
9903 return true;
9904 }
9905
9906 // TODO: these objects should be checked for whether they actually consume materials
9907 if (theWarehouse()
9908 .query()
9909 .condition<AttribThread>(tid)
9910 .condition<AttribInterfaces>(Interfaces::InternalSideUserObject |
9912 .condition<AttribSubdomains>(subdomain_id)
9913 .count() > 0)
9914 {
9915 _block_mat_side_cache[tid][subdomain_id] = true;
9916 return true;
9917 }
9918 }
9919
9920 return _block_mat_side_cache[tid][subdomain_id];
9921}
9922
9923bool
9928
9929void
9931{
9933 mooseError("Previous nonlinear solution is required but not added through "
9934 "Problem/previous_nl_solution_required=true");
9935}
9936
9937void
9939 const unsigned int solver_sys_num)
9940{
9941 _previous_multiapp_fp_nl_solution_required[solver_sys_num] = needed;
9942}
9943
9944bool
9946 const unsigned int solver_sys_num) const
9947{
9948 return _previous_multiapp_fp_nl_solution_required[solver_sys_num];
9949}
9950
9951void
9956
9957bool
9962
9963void
9965 bool needed, const unsigned int solver_sys_num)
9966{
9967 _previous_multisystem_fp_nl_solution_required[solver_sys_num] = needed;
9968}
9969
9970bool
9972 const unsigned int solver_sys_num) const
9973{
9974 return _previous_multisystem_fp_nl_solution_required[solver_sys_num];
9975}
9976
9977void
9982
9983bool
9988
9989bool
9991{
9992 return _has_jacobian;
9993}
9994
9995bool
9997{
9998 return _const_jacobian;
9999}
10000
10001void
10002FEProblemBase::addOutput(const std::string & object_type,
10003 const std::string & object_name,
10004 InputParameters & parameters)
10005{
10006 parallel_object_only();
10007
10008 // Get a reference to the OutputWarehouse
10009 OutputWarehouse & output_warehouse = _app.getOutputWarehouse();
10010
10011 // Reject the reserved names for objects not built by MOOSE
10012 if (!parameters.get<bool>("_built_by_moose") && output_warehouse.isReservedName(object_name))
10013 mooseError("The name '", object_name, "' is a reserved name for output objects");
10014
10015 // Check that an object by the same name does not already exist; this must be done before the
10016 // object is created to avoid getting misleading errors from the Parser
10017 if (output_warehouse.hasOutput(object_name))
10018 mooseError("An output object named '", object_name, "' already exists");
10019
10020 // Add a pointer to the FEProblemBase class
10021 parameters.addPrivateParam<FEProblemBase *>("_fe_problem_base", this);
10022
10023 // --show-input should enable the display of the input file on the screen
10024 if (object_type == "Console" && _app.getParam<bool>("show_input") &&
10025 parameters.get<bool>("output_screen"))
10026 parameters.set<ExecFlagEnum>("execute_input_on") = EXEC_INITIAL;
10027
10028 // Record whether this object's own block set 'file_base' itself before a common 'file_base'
10029 // from the [Outputs] block, if any, is copied down onto it below -- that copy makes
10030 // 'file_base' look valid and user-set on this object even when only the common block set it
10031 // (see #4215), so this must be captured first.
10032 if (parameters.isParamDefined("_file_base_set_by_own_block"))
10033 parameters.set<bool>("_file_base_set_by_own_block") = parameters.isParamSetByUser("file_base");
10034
10035 // Apply only user-set parameters from the common [Outputs] block so that
10036 // each output type's own defaults are not overridden by common defaults.
10037 const InputParameters * common = output_warehouse.getCommonParameters();
10038 if (common)
10040
10041 // Set the correct value for the binary flag for XDA/XDR output
10042 if (object_type == "XDR")
10043 parameters.set<bool>("_binary") = true;
10044 else if (object_type == "XDA")
10045 parameters.set<bool>("_binary") = false;
10046
10047 // Adjust the checkpoint suffix if auto recovery was enabled
10048 if (object_name == "auto_recovery_checkpoint")
10049 parameters.set<std::string>("suffix") = "auto_recovery";
10050
10051 // Create the object and add it to the warehouse
10052 std::shared_ptr<Output> output = _factory.create<Output>(object_type, object_name, parameters);
10053 logAdd("Output", object_name, object_type, parameters);
10054 output_warehouse.addOutput(output);
10055}
10056
10057void
10058FEProblemBase::haveADObjects(const bool have_ad_objects)
10059{
10060 _have_ad_objects = have_ad_objects;
10062 _displaced_problem->SubProblem::haveADObjects(have_ad_objects);
10063}
10064
10065const SystemBase &
10066FEProblemBase::getSystemBase(const unsigned int sys_num) const
10067{
10068 if (sys_num < _solver_systems.size())
10069 return *_solver_systems[sys_num];
10070
10071 return *_aux;
10072}
10073
10074SystemBase &
10075FEProblemBase::getSystemBase(const std::string & sys_name)
10076{
10077 if (std::find(_solver_sys_names.begin(), _solver_sys_names.end(), sys_name) !=
10078 _solver_sys_names.end())
10079 return getSystemBase(solverSysNum(sys_name));
10080 else if (sys_name == "aux0")
10081 return *_aux;
10082 else
10083 mooseError("System '" + sys_name + "' was requested from problem but does not exist.");
10084}
10085
10086SystemBase &
10087FEProblemBase::getSystemBase(const unsigned int sys_num)
10088{
10089 if (sys_num < _solver_systems.size())
10090 return *_solver_systems[sys_num];
10091
10092 return *_aux;
10093}
10094
10095const SystemBase &
10096FEProblemBase::systemBaseNonlinear(const unsigned int sys_num) const
10097{
10098 mooseAssert(sys_num < _nl.size(), "System number greater than the number of nonlinear systems");
10099 return *_nl[sys_num];
10100}
10101
10102SystemBase &
10103FEProblemBase::systemBaseNonlinear(const unsigned int sys_num)
10104{
10105 mooseAssert(sys_num < _nl.size(), "System number greater than the number of nonlinear systems");
10106 return *_nl[sys_num];
10107}
10108
10109const SystemBase &
10110FEProblemBase::systemBaseLinear(const unsigned int sys_num) const
10111{
10112 mooseAssert(sys_num < _linear_systems.size(),
10113 "System number greater than the number of linear systems");
10114 return *_linear_systems[sys_num];
10115}
10116
10117SystemBase &
10118FEProblemBase::systemBaseLinear(const unsigned int sys_num)
10119{
10120 mooseAssert(sys_num < _linear_systems.size(),
10121 "System number greater than the number of linear systems");
10122 return *_linear_systems[sys_num];
10123}
10124
10125const SystemBase &
10126FEProblemBase::systemBaseSolver(const unsigned int sys_num) const
10127{
10128 mooseAssert(sys_num < _solver_systems.size(),
10129 "System number greater than the number of solver systems");
10130 return *_solver_systems[sys_num];
10131}
10132
10133SystemBase &
10134FEProblemBase::systemBaseSolver(const unsigned int sys_num)
10135{
10136 mooseAssert(sys_num < _solver_systems.size(),
10137 "System number greater than the number of solver systems");
10138 return *_solver_systems[sys_num];
10139}
10140
10141const SystemBase &
10143{
10144 return *_aux;
10145}
10146
10147SystemBase &
10149{
10150 return *_aux;
10151}
10152
10153void
10154FEProblemBase::computingNonlinearResid(bool computing_nonlinear_residual)
10155{
10156 parallel_object_only();
10157
10159 _displaced_problem->computingNonlinearResid(computing_nonlinear_residual);
10160 _computing_nonlinear_residual = computing_nonlinear_residual;
10161}
10162
10163void
10164FEProblemBase::setCurrentlyComputingResidual(bool currently_computing_residual)
10165{
10167 _displaced_problem->setCurrentlyComputingResidual(currently_computing_residual);
10168 _currently_computing_residual = currently_computing_residual;
10169}
10170
10171void
10173{
10174 // ResetDisplacedMeshThread::onNode looks up the reference mesh by ID, so we need to make sure
10175 // we undisplace before adapting the reference mesh
10177 _displaced_problem->undisplaceMesh();
10178
10182
10184 /*intermediate_change=*/false, /*contract_mesh=*/true, /*clean_refinement_flags=*/true);
10185}
10186
10187void
10188FEProblemBase::automaticScaling(bool automatic_scaling)
10189{
10191 _displaced_problem->automaticScaling(automatic_scaling);
10192
10193 SubProblem::automaticScaling(automatic_scaling);
10194}
10195
10196void
10198 unsigned int side,
10199 Real tolerance,
10200 const std::vector<Point> * const pts,
10201 const std::vector<Real> * const weights,
10202 const THREAD_ID tid)
10203{
10204 SubProblem::reinitElemFaceRef(elem, side, tolerance, pts, weights, tid);
10205
10207 _displaced_problem->reinitElemFaceRef(
10208 _displaced_mesh->elemPtr(elem->id()), side, tolerance, pts, weights, tid);
10209}
10210
10211void
10212FEProblemBase::reinitNeighborFaceRef(const Elem * neighbor_elem,
10213 unsigned int neighbor_side,
10214 Real tolerance,
10215 const std::vector<Point> * const pts,
10216 const std::vector<Real> * const weights,
10217 const THREAD_ID tid)
10218{
10219 SubProblem::reinitNeighborFaceRef(neighbor_elem, neighbor_side, tolerance, pts, weights, tid);
10220
10222 _displaced_problem->reinitNeighborFaceRef(
10223 _displaced_mesh->elemPtr(neighbor_elem->id()), neighbor_side, tolerance, pts, weights, tid);
10224}
10225
10226void
10228 const SubdomainID blk_id,
10229 std::vector<std::shared_ptr<MaterialBase>> & face_materials,
10230 std::vector<std::shared_ptr<MaterialBase>> & neighbor_materials,
10231 std::set<MooseVariableFieldBase *> & variables,
10232 const THREAD_ID tid)
10233{
10234 if (_materials[Moose::FACE_MATERIAL_DATA].hasActiveBlockObjects(blk_id, tid))
10235 {
10236 auto & this_face_mats =
10238 for (std::shared_ptr<MaterialBase> face_mat : this_face_mats)
10239 if (face_mat->ghostable())
10240 {
10241 face_materials.push_back(face_mat);
10242 auto & var_deps = face_mat->getMooseVariableDependencies();
10243 for (auto * var : var_deps)
10244 {
10245 if (!var->isFV())
10246 mooseError(
10247 "Ghostable materials should only have finite volume variables coupled into them.");
10248 else if (face_mat->hasStatefulProperties())
10249 mooseError("Finite volume materials do not currently support stateful properties.");
10250 variables.insert(var);
10251 }
10252 }
10253 }
10254
10255 if (_materials[Moose::NEIGHBOR_MATERIAL_DATA].hasActiveBlockObjects(blk_id, tid))
10256 {
10257 auto & this_neighbor_mats =
10259 for (std::shared_ptr<MaterialBase> neighbor_mat : this_neighbor_mats)
10260 if (neighbor_mat->ghostable())
10261 {
10262 neighbor_materials.push_back(neighbor_mat);
10263#ifndef NDEBUG
10264 auto & var_deps = neighbor_mat->getMooseVariableDependencies();
10265 for (auto * var : var_deps)
10266 {
10267 if (!var->isFV())
10268 mooseError(
10269 "Ghostable materials should only have finite volume variables coupled into them.");
10270 else if (neighbor_mat->hasStatefulProperties())
10271 mooseError("Finite volume materials do not currently support stateful properties.");
10272 auto pr = variables.insert(var);
10273 mooseAssert(!pr.second,
10274 "We should not have inserted any new variables dependencies from our "
10275 "neighbor materials that didn't exist for our face materials");
10276 }
10277#endif
10278 }
10279 }
10280}
10281
10282void
10284 const unsigned int nqp,
10285 const THREAD_ID tid)
10286{
10287 getMaterialData(data_type, tid).resize(nqp);
10288}
10289
10290void
10291FEProblemBase::setNonlinearConvergenceNames(const std::vector<ConvergenceName> & convergence_names)
10292{
10293 if (convergence_names.size() != numNonlinearSystems())
10294 paramError("nonlinear_convergence",
10295 "There must be one convergence object per nonlinear system");
10296
10297 _nonlinear_convergence_names = convergence_names;
10298
10299 for (const auto i : make_range(numNonlinearSystems()))
10300 _nl[i]->setConvergenceName(convergence_names[i]);
10301}
10302
10303void
10304FEProblemBase::setMultiAppFixedPointConvergenceName(const ConvergenceName & convergence_name)
10305{
10306 _multiapp_fixed_point_convergence_name = convergence_name;
10307}
10308
10309void
10310FEProblemBase::setSteadyStateConvergenceName(const ConvergenceName & convergence_name)
10311{
10312 _steady_state_convergence_name = convergence_name;
10313}
10314
10315const std::vector<ConvergenceName> &
10317{
10320 mooseError("The nonlinear system convergence name(s) have not been set.");
10321}
10322
10323bool
10325{
10326 // If false,this means we have not set one, not that we are querying this too early
10327 // TODO: once there is a default linear CV object, error on the 'not set' case
10328 return _linear_convergence_names.has_value();
10329}
10330
10331void
10332FEProblemBase::setLinearConvergenceNames(const std::vector<ConvergenceName> & convergence_names)
10333{
10334 if (convergence_names.size() != numLinearSystems())
10335 paramError("linear_convergence", "There must be one convergence object per linear system");
10336 _linear_convergence_names = convergence_names;
10337}
10338
10339const std::vector<ConvergenceName> &
10341{
10344 mooseError("The linear convergence name(s) have not been set.");
10345}
10346
10347const ConvergenceName &
10349{
10352 else
10353 mooseError("The fixed point convergence name has not been set.");
10354}
10355
10356const ConvergenceName &
10358{
10360 return _steady_state_convergence_name.value();
10361 else
10362 mooseError("The steady convergence name has not been set.");
10363}
10364
10365void
10367{
10369 // We need to setup all the nonlinear systems other than our current one which actually called
10370 // this method (so we have to make sure we don't go in a circle)
10371 for (const auto i : make_range(numNonlinearSystems()))
10372 if (i != currentNlSysNum())
10373 _nl[i]->residualSetup();
10374 // We don't setup the aux sys because that's been done elsewhere
10376 _displaced_problem->residualSetup();
10377}
10378
10379void
10381{
10383 // We need to setup all the nonlinear systems other than our current one which actually called
10384 // this method (so we have to make sure we don't go in a circle)
10385 for (const auto i : make_range(numNonlinearSystems()))
10386 if (i != currentNlSysNum())
10387 _nl[i]->jacobianSetup();
10388 // We don't setup the aux sys because that's been done elsewhere
10390 _displaced_problem->jacobianSetup();
10391}
10392
10395{
10396 return mesh().coordTransform();
10397}
10398
10399unsigned int
10401{
10402 // If we don't have nonlinear systems this should be an invalid number
10403 unsigned int current_nl_sys_num = libMesh::invalid_uint;
10404 if (_nl.size())
10405 current_nl_sys_num = currentNonlinearSystem().number();
10406
10407 return current_nl_sys_num;
10408}
10409
10410unsigned int
10412{
10413 // If we don't have linear systems this should be an invalid number
10414 unsigned int current_linear_sys_num = libMesh::invalid_uint;
10415 if (_linear_systems.size())
10416 current_linear_sys_num = currentLinearSystem().number();
10417
10418 return current_linear_sys_num;
10419}
10420
10421bool
10423{
10424 // For now, only support printing from thread 0
10425 if (tid != 0)
10426 return false;
10427
10430 return true;
10431 else
10432 return false;
10433}
10434
10435std::vector<MortarUserObject *>
10437 const BoundaryID secondary_boundary_id,
10438 const bool displaced,
10439 const std::vector<MortarUserObject *> & mortar_uo_superset)
10440{
10441 std::vector<MortarUserObject *> mortar_uos;
10442 auto * const subproblem =
10443 displaced ? cast_ptr<SubProblem *>(_displaced_problem.get()) : cast_ptr<SubProblem *>(this);
10444 for (auto * const obj : mortar_uo_superset)
10445 if (obj->onInterface(primary_boundary_id, secondary_boundary_id) &&
10446 (&obj->getSubProblem() == subproblem))
10447 mortar_uos.push_back(obj);
10448
10449 return mortar_uos;
10450}
10451
10452std::vector<MortarUserObject *>
10454 const BoundaryID secondary_boundary_id,
10455 const bool displaced)
10456{
10457 std::vector<MortarUserObject *> mortar_uos;
10458 theWarehouse()
10459 .query()
10461 .queryInto(mortar_uos);
10462 return getMortarUserObjects(primary_boundary_id, secondary_boundary_id, displaced, mortar_uos);
10463}
10464
10465void
10467 const BoundaryID secondary_boundary_id,
10468 const bool displaced)
10469{
10470 const auto mortar_uos =
10471 getMortarUserObjects(primary_boundary_id, secondary_boundary_id, displaced);
10472 for (auto * const mortar_uo : mortar_uos)
10473 {
10474 mortar_uo->setNormals();
10475 mortar_uo->reinit();
10476 }
10477}
10478
10479void
10481{
10482 _verbose_setup = verbose ? "true" : "false";
10483 _verbose_multiapps = verbose;
10484 _verbose_restore = verbose;
10485}
10486
10487void
10488FEProblemBase::setCurrentLowerDElem(const Elem * const lower_d_elem, const THREAD_ID tid)
10489{
10490 SubProblem::setCurrentLowerDElem(lower_d_elem, tid);
10492 _displaced_problem->setCurrentLowerDElem(
10493 lower_d_elem ? _displaced_mesh->elemPtr(lower_d_elem->id()) : nullptr, tid);
10494}
10495
10496void
10498{
10501 _displaced_problem->setCurrentBoundaryID(bid, tid);
10502}
10503
10504void
10505FEProblemBase::setCurrentNonlinearSystem(const unsigned int nl_sys_num)
10506{
10507 mooseAssert(nl_sys_num < _nl.size(),
10508 "System number greater than the number of nonlinear systems");
10509 _current_nl_sys = _nl[nl_sys_num].get();
10511}
10512
10513void
10514FEProblemBase::setCurrentLinearSystem(const unsigned int sys_num)
10515{
10516 mooseAssert(sys_num < _linear_systems.size(),
10517 "System number greater than the number of linear systems");
10518 _current_linear_sys = _linear_systems[sys_num].get();
10520}
10521
10522void
10524{
10525 // When performing an adjoint solve in the optimization module, the current solver system is the
10526 // adjoint. However, the adjoint solve requires having accurate time derivative calculations for
10527 // the forward system. The cleanest way to handle such uses is just to compute the time
10528 // derivatives for all solver systems instead of trying to guess which ones we need and don't need
10529 for (auto & solver_sys : _solver_systems)
10530 solver_sys->compute(type);
10531
10532 _aux->compute(type);
10533}
10534
10535const ConstElemRange &
10543const ConstNodeRange &
10551const ConstBndNodeRange &
10559
10560void
10562{
10563 if (!range)
10564 {
10566 return;
10567 }
10568
10569 _current_algebraic_elem_range = std::make_unique<ConstElemRange>(*range);
10570}
10571void
10573{
10574 if (!range)
10575 {
10577 return;
10578 }
10579
10580 _current_algebraic_node_range = std::make_unique<ConstNodeRange>(*range);
10581}
10582void
10584{
10585 if (!range)
10586 {
10588 return;
10589 }
10590
10591 _current_algebraic_bnd_node_range = std::make_unique<ConstBndNodeRange>(*range);
10592}
10593
10594unsigned short
10599
10600std::string
10601FEProblemBase::solverTypeString(const unsigned int solver_sys_num)
10602{
10603 return Moose::stringify(solverParams(solver_sys_num)._type);
10604}
10605
10608{
10609 SolverParams solver_params;
10610 solver_params._type = Moose::SolveType::ST_LINEAR;
10612 return solver_params;
10613}
10614
10617{
10618 return _nonlocal_cm[i];
10619}
10620
10621bool
10626
10627const std::unordered_map<std::pair<BoundaryID, BoundaryID>, MortarInterfaceConfig> &
10629{
10630 return _mortar_data->getMortarInterfaces(on_displaced);
10631}
@ 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
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 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)
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.
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:3477
void setupFiniteVolumeMeshData() const
Sets up the additional data needed for finite volume computations.
Definition MooseMesh.C:4156
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:3561
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:1648
face_info_iterator ownedFaceInfoEnd()
Definition MooseMesh.C:1467
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:3280
elem_info_iterator ownedElemInfoEnd()
Definition MooseMesh.C:1484
virtual Elem * elemPtr(const dof_id_type i)
Definition MooseMesh.C:3177
MeshBase & getMesh()
Accessor for the underlying libMesh Mesh object.
Definition MooseMesh.C:3512
void buildRefinementAndCoarseningMaps(Assembly *assembly)
Create the refinement and coarsening maps necessary for projection of stateful material properties wh...
Definition MooseMesh.C:2476
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:1720
const std::string & getBoundaryName(const BoundaryID boundary_id) const
Return the name of the boundary given the id.
Definition MooseMesh.C:1743
MooseAppCoordTransform & coordTransform()
Definition MooseMesh.h:2062
void addGhostedBoundary(BoundaryID boundary_id)
This will add the boundary ids to be ghosted to this processor.
Definition MooseMesh.C:3293
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:1678
face_info_iterator ownedFaceInfoBegin()
Iterators to owned faceInfo objects.
Definition MooseMesh.C:1458
libMesh::ConstNodeRange * getLocalNodeRange()
Definition MooseMesh.C:1276
elem_info_iterator ownedElemInfoBegin()
Iterators to owned faceInfo objects.
Definition MooseMesh.C:1476
void ghostGhostedBoundaries()
Actually do the ghosting of boundaries that need to be ghosted to this processor.
Definition MooseMesh.C:3378
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:4391
bool isFiniteVolumeInfoDirty() const
Definition MooseMesh.h:1459
virtual Elem * queryElemPtr(const dof_id_type i)
Definition MooseMesh.C:3189
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:1550
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:1684
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:1714
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:3235
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:4165
const MeshBase::element_iterator activeLocalElementsEnd()
Definition MooseMesh.C:3121
void doingPRefinement(bool doing_p_refinement)
Indicate whether the kind of adaptivity we're doing includes p-refinement.
Definition MooseMesh.h:1502
void setAxisymmetricCoordAxis(const MooseEnum &rz_coord_axis)
For axisymmetric simulations, set the symmetry coordinate axis.
Definition MooseMesh.C:4297
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:1554
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:3115
void buildPRefinementAndCoarseningMaps(Assembly *assembly)
Definition MooseMesh.C:2382
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 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:902
@ ST_JFNK
Jacobian-Free Newton Krylov.
Definition MooseTypes.h:899
@ VAR_FIELD_STANDARD
Definition MooseTypes.h:777
@ VAR_FIELD_ANY
Definition MooseTypes.h:781
AuxGroup
Flag for AuxKernel related execution type.
Definition MooseTypes.h:758
@ POST_AUX
Definition MooseTypes.h:761
@ PRE_AUX
Definition MooseTypes.h:760
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:983
@ 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:746
@ NEIGHBOR_MATERIAL_DATA
Definition MooseTypes.h:750
@ BOUNDARY_MATERIAL_DATA
Definition MooseTypes.h:748
@ INTERFACE_MATERIAL_DATA
Definition MooseTypes.h:751
@ BLOCK_MATERIAL_DATA
Definition MooseTypes.h:747
@ FACE_MATERIAL_DATA
Definition MooseTypes.h:749
SolutionIterationType
Definition MooseTypes.h:270
@ COUPLING_FULL
Definition MooseTypes.h:787
@ COUPLING_DIAG
Definition MooseTypes.h:786
@ COUPLING_CUSTOM
Definition MooseTypes.h:788
VarKindType
Framework-wide stuff.
Definition MooseTypes.h:769
@ VAR_ANY
Definition MooseTypes.h:772
@ VAR_AUXILIARY
Definition MooseTypes.h:771
@ VAR_SOLVER
Definition MooseTypes.h:770
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
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
RealTensorValue RealTensor
RealVectorValue RealGradient
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.