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