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