Line data Source code
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
11 : #include "KokkosMaterialPropertyStorage.h"
12 : #endif
13 :
14 : #include "FEProblemBase.h"
15 : #include "AuxiliarySystem.h"
16 : #include "MaterialPropertyStorage.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"
23 : #include "ComputeUserObjectsThread.h"
24 : #include "ComputeNodalUserObjectsThread.h"
25 : #include "ComputeThreadedGeneralUserObjectsThread.h"
26 : #include "ComputeMaterialsObjectThread.h"
27 : #include "ProjectMaterialProperties.h"
28 : #include "ComputeIndicatorThread.h"
29 : #include "ComputeMarkerThread.h"
30 : #include "ComputeInitialConditionThread.h"
31 : #include "ComputeFVInitialConditionThread.h"
32 : #include "ComputeBoundaryInitialConditionThread.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"
48 : #include "PetscSupport.h"
49 : #include "RandomInterface.h"
50 : #include "RandomData.h"
51 : #include "MooseEigenSystem.h"
52 : #include "MooseParsedFunction.h"
53 : #include "MeshChangedInterface.h"
54 : #include "MeshDisplacedInterface.h"
55 : #include "ComputeJacobianBlocksThread.h"
56 : #include "ScalarInitialCondition.h"
57 : #include "FVInitialConditionTempl.h"
58 : #include "ElementPostprocessor.h"
59 : #include "NodalPostprocessor.h"
60 : #include "SidePostprocessor.h"
61 : #include "InternalSidePostprocessor.h"
62 : #include "InterfacePostprocessor.h"
63 : #include "GeneralPostprocessor.h"
64 : #include "ElementVectorPostprocessor.h"
65 : #include "NodalVectorPostprocessor.h"
66 : #include "SideVectorPostprocessor.h"
67 : #include "InternalSideVectorPostprocessor.h"
68 : #include "GeneralVectorPostprocessor.h"
69 : #include "Positions.h"
70 : #include "Indicator.h"
71 : #include "Marker.h"
72 : #include "MultiApp.h"
73 : #include "MultiAppTransfer.h"
74 : #include "TransientMultiApp.h"
75 : #include "ElementUserObject.h"
76 : #include "DomainUserObject.h"
77 : #include "NodalUserObject.h"
78 : #include "SideUserObject.h"
79 : #include "InternalSideUserObject.h"
80 : #include "InterfaceUserObject.h"
81 : #include "GeneralUserObject.h"
82 : #include "ThreadedGeneralUserObject.h"
83 : #include "InternalSideIndicatorBase.h"
84 : #include "Transfer.h"
85 : #include "MultiAppTransfer.h"
86 : #include "MultiMooseEnum.h"
87 : #include "Predictor.h"
88 : #include "Assembly.h"
89 : #include "Control.h"
90 : #include "XFEMInterface.h"
91 : #include "ConsoleUtils.h"
92 : #include "NonlocalKernel.h"
93 : #include "NonlocalIntegratedBC.h"
94 : #include "ShapeElementUserObject.h"
95 : #include "ShapeSideUserObject.h"
96 : #include "MooseVariableFE.h"
97 : #include "MooseVariableScalar.h"
98 : #include "InputParameterWarehouse.h"
99 : #include "TimeIntegrator.h"
100 : #include "LineSearch.h"
101 : #include "FloatingPointExceptionGuard.h"
102 : #include "MaxVarNDofsPerElem.h"
103 : #include "MaxVarNDofsPerNode.h"
104 : #include "FVKernel.h"
105 : #include "LinearFVKernel.h"
106 : #include "FVTimeKernel.h"
107 : #include "MooseVariableFV.h"
108 : #include "MooseLinearVariableFV.h"
109 : #include "FVBoundaryCondition.h"
110 : #include "LinearFVBoundaryCondition.h"
111 : #include "FVInterfaceKernel.h"
112 : #include "Reporter.h"
113 : #include "ADUtils.h"
114 : #include "Executioner.h"
115 : #include "VariadicTable.h"
116 : #include "BoundaryNodeIntegrityCheckThread.h"
117 : #include "BoundaryElemIntegrityCheckThread.h"
118 : #include "NodalBCBase.h"
119 : #include "MortarUserObject.h"
120 : #include "MortarUserObjectThread.h"
121 : #include "RedistributeProperties.h"
122 : #include "Checkpoint.h"
123 : #include "MortarInterfaceWarehouse.h"
124 : #include "AutomaticMortarGeneration.h"
125 :
126 : #include "libmesh/exodusII_io.h"
127 : #include "libmesh/quadrature.h"
128 : #include "libmesh/coupling_matrix.h"
129 : #include "libmesh/nonlinear_solver.h"
130 : #include "libmesh/sparse_matrix.h"
131 : #include "libmesh/string_to_enum.h"
132 : #include "libmesh/fe_interface.h"
133 : #include "libmesh/enum_norm_type.h"
134 : #include "libmesh/petsc_solver_exception.h"
135 :
136 : #include "metaphysicl/dualnumber.h"
137 :
138 : // C++
139 : #include <cstring> // for "Jacobian" exception test
140 :
141 : using namespace libMesh;
142 :
143 : // Anonymous namespace for helper function
144 : namespace
145 : {
146 : /**
147 : * Method for sorting the MooseVariableFEBases based on variable numbers
148 : */
149 : bool
150 75 : sortMooseVariables(const MooseVariableFEBase * a, const MooseVariableFEBase * b)
151 : {
152 75 : return a->number() < b->number();
153 : }
154 : } // namespace
155 :
156 : Threads::spin_mutex get_function_mutex;
157 :
158 : InputParameters
159 344487 : FEProblemBase::validParams()
160 : {
161 344487 : InputParameters params = SubProblem::validParams();
162 1377948 : params.addParam<unsigned int>("null_space_dimension", 0, "The dimension of the nullspace");
163 1033461 : params.addParam<unsigned int>(
164 688974 : "transpose_null_space_dimension", 0, "The dimension of the transpose nullspace");
165 1033461 : params.addParam<unsigned int>(
166 688974 : "near_null_space_dimension", 0, "The dimension of the near nullspace");
167 1033461 : params.addParam<bool>("solve",
168 688974 : true,
169 : "Whether or not to actually solve the Nonlinear system. "
170 : "This is handy in the case that all you want to do is "
171 : "execute AuxKernels, Transfers, etc. without actually "
172 : "solving anything");
173 1033461 : params.addParam<bool>("use_nonlinear",
174 688974 : true,
175 : "Determines whether to use a Nonlinear vs a "
176 : "Eigenvalue system (Automatically determined based "
177 : "on executioner)");
178 1377948 : params.addParam<bool>("error_on_jacobian_nonzero_reallocation",
179 : "This causes PETSc to error if it had to reallocate memory in the Jacobian "
180 : "matrix due to not having enough nonzeros");
181 1033461 : params.addParam<bool>("ignore_zeros_in_jacobian",
182 688974 : false,
183 : "Do not explicitly store zero values in "
184 : "the Jacobian matrix if true");
185 1033461 : params.addParam<bool>("force_restart",
186 688974 : false,
187 : "EXPERIMENTAL: If true, a sub_app may use a "
188 : "restart file instead of using of using the master "
189 : "backup file");
190 1722435 : params.addDeprecatedParam<bool>("skip_additional_restart_data",
191 688974 : false,
192 : "True to skip additional data in equation system for restart.",
193 : "This parameter is no longer used, as we do not load additional "
194 : "vectors by default with restart");
195 1033461 : params.addParam<bool>("skip_nl_system_check",
196 688974 : false,
197 : "True to skip the NonlinearSystem check for work to do (e.g. Make sure "
198 : "that there are variables to solve for).");
199 1033461 : params.addParam<bool>("allow_initial_conditions_with_restart",
200 688974 : false,
201 : "True to allow the user to specify initial conditions when restarting. "
202 : "Initial conditions can override any restarted field");
203 :
204 688974 : auto coverage_check_description = [](std::string scope, std::string list_param_name)
205 : {
206 1377948 : return "Controls, if and how a " + scope +
207 : " subdomain coverage check is performed. "
208 : "With 'TRUE' or 'ON' all subdomains are checked (the default). Setting 'FALSE' or 'OFF' "
209 : "will disable the check for all subdomains. "
210 : "To exclude a predefined set of subdomains 'SKIP_LIST' is to "
211 1377948 : "be used, while the subdomains to skip are to be defined in the parameter '" +
212 1377948 : list_param_name +
213 : "'. To limit the check to a list of subdomains, 'ONLY_LIST' is to "
214 2066922 : "be used (again, using the parameter '" +
215 1377948 : list_param_name + "').";
216 : };
217 :
218 1722435 : params.addParam<std::vector<SubdomainName>>(
219 : "block",
220 : {"ANY_BLOCK_ID"},
221 : "List of subdomains for kernel coverage and material coverage checks. Setting this parameter "
222 : "is equivalent to setting 'kernel_coverage_block_list' and 'material_coverage_block_list' as "
223 : "well as using 'ONLY_LIST' as the coverage check mode.");
224 :
225 1377948 : MooseEnum kernel_coverage_check_modes("FALSE TRUE OFF ON SKIP_LIST ONLY_LIST", "TRUE");
226 344487 : params.addParam<MooseEnum>("kernel_coverage_check",
227 : kernel_coverage_check_modes,
228 1722435 : coverage_check_description("kernel", "kernel_coverage_block_list"));
229 1377948 : params.addParam<std::vector<SubdomainName>>(
230 : "kernel_coverage_block_list",
231 : {},
232 : "List of subdomains for kernel coverage check. The meaning of this list is controlled by the "
233 : "parameter 'kernel_coverage_check' (whether this is the list of subdomains to be checked, "
234 : "not to be checked or not taken into account).");
235 1033461 : params.addParam<bool>(
236 : "boundary_restricted_node_integrity_check",
237 688974 : true,
238 : "Set to false to disable checking of boundary restricted nodal object variable dependencies, "
239 : "e.g. are the variable dependencies defined on the selected boundaries?");
240 1033461 : params.addParam<bool>("boundary_restricted_elem_integrity_check",
241 688974 : true,
242 : "Set to false to disable checking of boundary restricted elemental object "
243 : "variable dependencies, e.g. are the variable dependencies defined on the "
244 : "selected boundaries?");
245 1377948 : MooseEnum material_coverage_check_modes("FALSE TRUE OFF ON SKIP_LIST ONLY_LIST", "TRUE");
246 344487 : params.addParam<MooseEnum>(
247 : "material_coverage_check",
248 : material_coverage_check_modes,
249 1722435 : coverage_check_description("material", "material_coverage_block_list"));
250 1377948 : params.addParam<std::vector<SubdomainName>>(
251 : "material_coverage_block_list",
252 : {},
253 : "List of subdomains for material coverage check. The meaning of this list is controlled by "
254 : "the parameter 'material_coverage_check' (whether this is the list of subdomains to be "
255 : "checked, not to be checked or not taken into account).");
256 :
257 1033461 : params.addParam<bool>("fv_bcs_integrity_check",
258 688974 : true,
259 : "Set to false to disable checking of overlapping Dirichlet and Flux BCs "
260 : "and/or multiple DirichletBCs per sideset");
261 :
262 1033461 : params.addParam<bool>(
263 688974 : "material_dependency_check", true, "Set to false to disable material dependency check");
264 1033461 : params.addParam<bool>("parallel_barrier_messaging",
265 688974 : false,
266 : "Displays messaging from parallel "
267 : "barrier notifications when executing "
268 : "or transferring to/from Multiapps "
269 : "(default: false)");
270 :
271 1377948 : MooseEnum verbosity("false true extra", "false");
272 1377948 : params.addParam<MooseEnum>("verbose_setup",
273 : verbosity,
274 : "Set to 'true' to have the problem report on any object created. Set "
275 : "to 'extra' to also display all parameters.");
276 1033461 : params.addParam<bool>("verbose_multiapps",
277 688974 : false,
278 : "Set to True to enable verbose screen printing related to MultiApps");
279 1033461 : params.addParam<bool>(
280 : "verbose_restore",
281 688974 : false,
282 : "Set to True to enable verbose screen printing related to solution restoration");
283 :
284 1377948 : params.addParam<FileNameNoExtension>("restart_file_base",
285 : "File base name used for restart (e.g. "
286 : "<path>/<filebase> or <path>/LATEST to "
287 : "grab the latest file available)");
288 :
289 1377948 : params.addParam<std::vector<std::vector<TagName>>>(
290 : "extra_tag_vectors",
291 : {},
292 : "Extra vectors to add to the system that can be filled by objects which compute residuals "
293 : "and Jacobians (Kernels, BCs, etc.) by setting tags on them. The outer index is for which "
294 : "nonlinear system the extra tag vectors should be added for");
295 :
296 1377948 : params.addParam<std::vector<std::vector<TagName>>>(
297 : "not_zeroed_tag_vectors",
298 : {},
299 : "Extra vector tags which the sytem will not zero when other vector tags are zeroed. "
300 : "The outer index is for which nonlinear system the extra tag vectors should be added for");
301 :
302 1377948 : params.addParam<std::vector<std::vector<TagName>>>(
303 : "extra_tag_matrices",
304 : {},
305 : "Extra matrices to add to the system that can be filled "
306 : "by objects which compute residuals and Jacobians "
307 : "(Kernels, BCs, etc.) by setting tags on them. The outer index is for which "
308 : "nonlinear system the extra tag vectors should be added for");
309 :
310 1377948 : params.addParam<std::vector<TagName>>(
311 : "extra_tag_solutions",
312 : {},
313 : "Extra solution vectors to add to the system that can be used by "
314 : "objects for coupling variable values stored in them.");
315 :
316 1033461 : params.addParam<bool>("previous_nl_solution_required",
317 688974 : false,
318 : "True to indicate that this calculation requires a solution vector for "
319 : "storing the previous nonlinear iteration.");
320 :
321 1033461 : params.addParam<std::vector<NonlinearSystemName>>(
322 1377948 : "nl_sys_names", std::vector<NonlinearSystemName>{"nl0"}, "The nonlinear system names");
323 :
324 1377948 : params.addParam<std::vector<LinearSystemName>>("linear_sys_names", {}, "The linear system names");
325 :
326 1033461 : params.addParam<bool>("check_uo_aux_state",
327 688974 : false,
328 : "True to turn on a check that no state presents during the evaluation of "
329 : "user objects and aux kernels");
330 :
331 344487 : params.addPrivateParam<MooseMesh *>("mesh");
332 :
333 1033461 : params.declareControllable("solve");
334 :
335 1033461 : params.addParam<bool>(
336 : "allow_invalid_solution",
337 688974 : false,
338 : "Set to true to allow convergence even though the solution has been marked as 'invalid'");
339 1033461 : params.addParam<bool>("show_invalid_solution_console",
340 688974 : true,
341 : "Set to true to show the invalid solution occurance summary in console");
342 1033461 : params.addParam<bool>("immediately_print_invalid_solution",
343 688974 : false,
344 : "Whether or not to report invalid solution warnings at the time the "
345 : "warning is produced instead of after the calculation");
346 :
347 1033461 : params.addParam<bool>(
348 : "identify_variable_groups_in_nl",
349 688974 : true,
350 : "Whether to identify variable groups in nonlinear systems. This affects dof ordering");
351 :
352 1033461 : params.addParam<bool>(
353 : "regard_general_exceptions_as_errors",
354 688974 : false,
355 : "If we catch an exception during residual/Jacobian evaluaton for which we don't have "
356 : "specific handling, immediately error instead of allowing the time step to be cut");
357 :
358 1033461 : params.addParam<bool>("use_hash_table_matrix_assembly",
359 688974 : false,
360 : "Whether to assemble matrices using hash tables instead of preallocating "
361 : "matrix memory. This can be a good option if the sparsity pattern changes "
362 : "throughout the course of the simulation.");
363 1377948 : params.addParam<bool>(
364 : "restore_original_nonzero_pattern",
365 : "Whether we should reset matrix memory for every Jacobian evaluation. This option is useful "
366 : "if the sparsity pattern is constantly changing and you are using hash table assembly or if "
367 : "you wish to continually restore the matrix to the originally preallocated sparsity pattern "
368 : "computed by relationship managers.");
369 :
370 1377948 : params.addParamNamesToGroup(
371 : "skip_nl_system_check kernel_coverage_check kernel_coverage_block_list "
372 : "boundary_restricted_node_integrity_check "
373 : "boundary_restricted_elem_integrity_check material_coverage_check "
374 : "material_coverage_block_list fv_bcs_integrity_check "
375 : "material_dependency_check check_uo_aux_state error_on_jacobian_nonzero_reallocation",
376 : "Simulation checks");
377 1377948 : params.addParamNamesToGroup("use_nonlinear previous_nl_solution_required nl_sys_names "
378 : "ignore_zeros_in_jacobian identify_variable_groups_in_nl "
379 : "use_hash_table_matrix_assembly restore_original_nonzero_pattern",
380 : "Nonlinear system(s)");
381 1377948 : params.addParamNamesToGroup(
382 : "restart_file_base force_restart allow_initial_conditions_with_restart", "Restart");
383 1377948 : params.addParamNamesToGroup(
384 : "verbose_setup verbose_multiapps verbose_restore parallel_barrier_messaging", "Verbosity");
385 1377948 : params.addParamNamesToGroup(
386 : "null_space_dimension transpose_null_space_dimension near_null_space_dimension",
387 : "Null space removal");
388 1377948 : params.addParamNamesToGroup(
389 : "extra_tag_vectors extra_tag_matrices extra_tag_solutions not_zeroed_tag_vectors",
390 : "Contribution to tagged field data");
391 1033461 : params.addParamNamesToGroup(
392 : "allow_invalid_solution show_invalid_solution_console immediately_print_invalid_solution",
393 : "Solution validity control");
394 :
395 688974 : return params;
396 1033461 : }
397 :
398 64845 : FEProblemBase::FEProblemBase(const InputParameters & parameters)
399 : : SubProblem(parameters),
400 : Restartable(this, "FEProblemBase"),
401 259380 : _mesh(*getCheckedPointerParam<MooseMesh *>("mesh")),
402 129690 : _req(declareManagedRestartableDataWithContext<RestartableEquationSystems>(
403 : "equation_systems", nullptr, _mesh)),
404 64845 : _initialized(false),
405 129690 : _solve(getParam<bool>("solve")),
406 64845 : _transient(false),
407 129690 : _time(declareRestartableData<Real>("time")),
408 129690 : _time_old(declareRestartableData<Real>("time_old")),
409 129690 : _t_step(declareRecoverableData<int>("t_step")),
410 129690 : _dt(declareRestartableData<Real>("dt")),
411 129690 : _dt_old(declareRestartableData<Real>("dt_old")),
412 64845 : _need_to_add_default_nonlinear_convergence(false),
413 64845 : _need_to_add_default_multiapp_fixed_point_convergence(false),
414 64845 : _need_to_add_default_steady_state_convergence(false),
415 129690 : _linear_sys_names(getParam<std::vector<LinearSystemName>>("linear_sys_names")),
416 64845 : _num_linear_sys(_linear_sys_names.size()),
417 129690 : _linear_systems(_num_linear_sys, nullptr),
418 64845 : _current_linear_sys(nullptr),
419 129690 : _using_default_nl(!isParamSetByUser("nl_sys_names")),
420 191981 : _nl_sys_names(!_using_default_nl || (_using_default_nl && !_linear_sys_names.size())
421 64845 : ? getParam<std::vector<NonlinearSystemName>>("nl_sys_names")
422 : : std::vector<NonlinearSystemName>()),
423 64845 : _num_nl_sys(_nl_sys_names.size()),
424 129690 : _nl(_num_nl_sys, nullptr),
425 64845 : _current_nl_sys(nullptr),
426 129690 : _solver_systems(_num_nl_sys + _num_linear_sys, nullptr),
427 64845 : _aux(nullptr),
428 64845 : _coupling(Moose::COUPLING_DIAG),
429 : #ifdef MOOSE_KOKKOS_ENABLED
430 43258 : _kokkos_assembly(*this),
431 : #endif
432 64845 : _mesh_divisions(/*threaded=*/true),
433 64845 : _material_props(declareRestartableDataWithContext<MaterialPropertyStorage>(
434 64845 : "material_props", &_mesh, _material_prop_registry, *this)),
435 64845 : _bnd_material_props(declareRestartableDataWithContext<MaterialPropertyStorage>(
436 64845 : "bnd_material_props", &_mesh, _material_prop_registry, *this)),
437 64845 : _neighbor_material_props(declareRestartableDataWithContext<MaterialPropertyStorage>(
438 64845 : "neighbor_material_props", &_mesh, _material_prop_registry, *this)),
439 : #ifdef MOOSE_KOKKOS_ENABLED
440 43258 : _kokkos_material_props(
441 43258 : declareRestartableDataWithContext<Moose::Kokkos::MaterialPropertyStorage>(
442 43258 : "kokkos_material_props", &_mesh, _material_prop_registry, *this)),
443 43258 : _kokkos_bnd_material_props(
444 43258 : declareRestartableDataWithContext<Moose::Kokkos::MaterialPropertyStorage>(
445 43258 : "kokkos_bnd_material_props", &_mesh, _material_prop_registry, *this)),
446 43258 : _kokkos_neighbor_material_props(
447 43258 : declareRestartableDataWithContext<Moose::Kokkos::MaterialPropertyStorage>(
448 43258 : "kokkos_neighbor_material_props", &_mesh, _material_prop_registry, *this)),
449 : #endif
450 64845 : _reporter_data(_app),
451 : // TODO: delete the following line after apps have been updated to not call getUserObjects
452 64845 : _all_user_objects(_app.getExecuteOnEnum()),
453 64845 : _multi_apps(_app.getExecuteOnEnum()),
454 64845 : _transient_multi_apps(_app.getExecuteOnEnum()),
455 64845 : _transfers(_app.getExecuteOnEnum(), /*threaded=*/false),
456 64845 : _to_multi_app_transfers(_app.getExecuteOnEnum(), /*threaded=*/false),
457 64845 : _from_multi_app_transfers(_app.getExecuteOnEnum(), /*threaded=*/false),
458 64845 : _between_multi_app_transfers(_app.getExecuteOnEnum(), /*threaded=*/false),
459 : #ifdef LIBMESH_ENABLE_AMR
460 64845 : _adaptivity(*this),
461 64845 : _cycles_completed(0),
462 : #endif
463 64845 : _displaced_mesh(nullptr),
464 64845 : _geometric_search_data(*this, _mesh),
465 64845 : _mortar_data(std::make_unique<MortarInterfaceWarehouse>(*this)),
466 64845 : _reinit_displaced_elem(false),
467 64845 : _reinit_displaced_face(false),
468 64845 : _reinit_displaced_neighbor(false),
469 64845 : _input_file_saved(false),
470 64845 : _has_dampers(false),
471 64845 : _has_constraints(false),
472 64845 : _snesmf_reuse_base(true),
473 64845 : _skip_exception_check(false),
474 64845 : _snesmf_reuse_base_set_by_user(false),
475 64845 : _has_initialized_stateful(false),
476 64845 : _const_jacobian(false),
477 64845 : _has_jacobian(false),
478 64845 : _needs_old_newton_iter(false),
479 129690 : _previous_nl_solution_required(getParam<bool>("previous_nl_solution_required")),
480 64845 : _has_nonlocal_coupling(false),
481 64845 : _calculate_jacobian_in_uo(false),
482 64845 : _kernel_coverage_check(
483 129690 : getParam<MooseEnum>("kernel_coverage_check").getEnum<CoverageCheckMode>()),
484 129690 : _kernel_coverage_blocks(getParam<std::vector<SubdomainName>>("kernel_coverage_block_list")),
485 64845 : _boundary_restricted_node_integrity_check(
486 129690 : getParam<bool>("boundary_restricted_node_integrity_check")),
487 64845 : _boundary_restricted_elem_integrity_check(
488 129690 : getParam<bool>("boundary_restricted_elem_integrity_check")),
489 64845 : _material_coverage_check(
490 129690 : getParam<MooseEnum>("material_coverage_check").getEnum<CoverageCheckMode>()),
491 129690 : _material_coverage_blocks(getParam<std::vector<SubdomainName>>("material_coverage_block_list")),
492 129690 : _fv_bcs_integrity_check(getParam<bool>("fv_bcs_integrity_check")),
493 129690 : _material_dependency_check(getParam<bool>("material_dependency_check")),
494 129690 : _uo_aux_state_check(getParam<bool>("check_uo_aux_state")),
495 64845 : _max_qps(std::numeric_limits<unsigned int>::max()),
496 64845 : _max_scalar_order(INVALID_ORDER),
497 64845 : _has_time_integrator(false),
498 64845 : _has_exception(false),
499 129690 : _parallel_barrier_messaging(getParam<bool>("parallel_barrier_messaging")),
500 129690 : _verbose_setup(getParam<MooseEnum>("verbose_setup")),
501 129690 : _verbose_multiapps(getParam<bool>("verbose_multiapps")),
502 129690 : _verbose_restore(getParam<bool>("verbose_restore")),
503 64845 : _current_execute_on_flag(EXEC_NONE),
504 64845 : _control_warehouse(_app.getExecuteOnEnum(), /*threaded=*/false),
505 64845 : _is_petsc_options_inserted(false),
506 64845 : _line_search(nullptr),
507 64845 : _using_ad_mat_props(false),
508 64845 : _current_ic_state(0),
509 129690 : _use_hash_table_matrix_assembly(getParam<bool>("use_hash_table_matrix_assembly")),
510 64845 : _error_on_jacobian_nonzero_reallocation(
511 129690 : isParamValid("error_on_jacobian_nonzero_reallocation")
512 130296 : ? getParam<bool>("error_on_jacobian_nonzero_reallocation")
513 64239 : : _app.errorOnJacobianNonzeroReallocation()),
514 129690 : _restore_original_nonzero_pattern(isParamValid("restore_original_nonzero_pattern")
515 129690 : ? getParam<bool>("restore_original_nonzero_pattern")
516 64845 : : _use_hash_table_matrix_assembly),
517 129690 : _ignore_zeros_in_jacobian(getParam<bool>("ignore_zeros_in_jacobian")),
518 64845 : _preserve_matrix_sparsity_pattern(true),
519 129690 : _force_restart(getParam<bool>("force_restart")),
520 129690 : _allow_ics_during_restart(getParam<bool>("allow_initial_conditions_with_restart")),
521 129690 : _skip_nl_system_check(getParam<bool>("skip_nl_system_check")),
522 64845 : _fail_next_system_convergence_check(false),
523 129690 : _allow_invalid_solution(getParam<bool>("allow_invalid_solution")),
524 129690 : _show_invalid_solution_console(getParam<bool>("show_invalid_solution_console")),
525 129690 : _immediately_print_invalid_solution(getParam<bool>("immediately_print_invalid_solution")),
526 64845 : _started_initial_setup(false),
527 64845 : _has_internal_edge_residual_objects(false),
528 64845 : _u_dot_requested(false),
529 64845 : _u_dotdot_requested(false),
530 64845 : _u_dot_old_requested(false),
531 64845 : _u_dotdot_old_requested(false),
532 64845 : _has_mortar(false),
533 64845 : _num_grid_steps(0),
534 64845 : _print_execution_on(),
535 129690 : _identify_variable_groups_in_nl(getParam<bool>("identify_variable_groups_in_nl")),
536 64845 : _regard_general_exceptions_as_errors(getParam<bool>("regard_general_exceptions_as_errors")),
537 1232055 : _requires_nonlocal_coupling(false)
538 : {
539 : auto checkCoverageCheckConflict =
540 129690 : [this](const std::string & coverage_check,
541 : const CoverageCheckMode & coverage_check_mode,
542 : const std::vector<SubdomainName> & coverage_blocks) -> void
543 : {
544 129690 : if (coverage_check_mode != CoverageCheckMode::FALSE &&
545 124932 : coverage_check_mode != CoverageCheckMode::OFF)
546 124911 : if (coverage_blocks.size() > 1)
547 0 : if (std::find(coverage_blocks.begin(), coverage_blocks.end(), "ANY_BLOCK_ID") !=
548 0 : coverage_blocks.end())
549 0 : paramError(coverage_check,
550 : "The list of blocks used for ",
551 : coverage_check,
552 : " cannot contain 'ANY_BLOCK_ID' along with other blocks. ");
553 129690 : };
554 :
555 64845 : checkCoverageCheckConflict(
556 64845 : "kernel_coverage_check", _kernel_coverage_check, _kernel_coverage_blocks);
557 64845 : checkCoverageCheckConflict(
558 64845 : "material_coverage_check", _material_coverage_check, _material_coverage_blocks);
559 :
560 : // Initialize static do_derivatives member. We initialize this to true so that all the
561 : // default AD things that we setup early in the simulation actually get their derivative
562 : // vectors initalized. We will toggle this to false when doing residual evaluations
563 64845 : ADReal::do_derivatives = true;
564 :
565 : // Disable refinement/coarsening in EquationSystems::reinit because we already do this ourselves
566 64845 : es().disable_refine_in_reinit();
567 :
568 64845 : _solver_params.reserve(_num_nl_sys + _num_linear_sys);
569 : // Default constructor fine for nonlinear because it will be populated later by framework
570 : // executioner/solve object parameters
571 64845 : _solver_params.resize(_num_nl_sys);
572 128653 : for (const auto i : index_range(_nl_sys_names))
573 : {
574 63808 : const auto & name = _nl_sys_names[i];
575 63808 : _nl_sys_name_to_num[name] = i;
576 63808 : _solver_sys_name_to_num[name] = i;
577 63808 : _solver_sys_names.push_back(name);
578 : }
579 :
580 66185 : for (const auto i : index_range(_linear_sys_names))
581 : {
582 1340 : const auto & name = _linear_sys_names[i];
583 1340 : _linear_sys_name_to_num[name] = i;
584 1340 : _solver_sys_name_to_num[name] = i + _num_nl_sys;
585 1340 : _solver_sys_names.push_back(name);
586 : // Unlike for nonlinear these are basically dummy parameters
587 1340 : _solver_params.push_back(makeLinearSolverParams());
588 : }
589 :
590 64845 : _nonlocal_cm.resize(numSolverSystems());
591 64845 : _cm.resize(numSolverSystems());
592 :
593 64845 : _time = 0.0;
594 64845 : _time_old = 0.0;
595 64845 : _t_step = 0;
596 64845 : _dt = 0;
597 64845 : _dt_old = _dt;
598 :
599 64845 : unsigned int n_threads = libMesh::n_threads();
600 :
601 64845 : _real_zero.resize(n_threads, 0.);
602 64845 : _scalar_zero.resize(n_threads);
603 64845 : _zero.resize(n_threads);
604 64845 : _phi_zero.resize(n_threads);
605 64845 : _ad_zero.resize(n_threads);
606 64845 : _grad_zero.resize(n_threads);
607 64845 : _ad_grad_zero.resize(n_threads);
608 64845 : _grad_phi_zero.resize(n_threads);
609 64845 : _second_zero.resize(n_threads);
610 64845 : _ad_second_zero.resize(n_threads);
611 64845 : _second_phi_zero.resize(n_threads);
612 64845 : _point_zero.resize(n_threads);
613 64845 : _vector_zero.resize(n_threads);
614 64845 : _vector_curl_zero.resize(n_threads);
615 64845 : _uo_jacobian_moose_vars.resize(n_threads);
616 :
617 64845 : _has_active_material_properties.resize(n_threads, 0);
618 :
619 64845 : _block_mat_side_cache.resize(n_threads);
620 64845 : _bnd_mat_side_cache.resize(n_threads);
621 64845 : _interface_mat_side_cache.resize(n_threads);
622 :
623 129690 : es().parameters.set<FEProblemBase *>("_fe_problem_base") = this;
624 :
625 194535 : if (isParamValid("restart_file_base"))
626 : {
627 1018 : std::string restart_file_base = getParam<FileNameNoExtension>("restart_file_base");
628 :
629 : // This check reverts to old behavior of providing "restart_file_base=" to mean
630 : // don't restart... BISON currently relies on this. It could probably be removed.
631 : // The new MooseUtils::convertLatestCheckpoint will error out if a checkpoint file
632 : // is not found, which I think makes sense. Which means, without this, if you
633 : // set "restart_file_base=", you'll get a "No checkpoint file found" error
634 509 : if (restart_file_base.size())
635 : {
636 509 : restart_file_base = MooseUtils::convertLatestCheckpoint(restart_file_base);
637 509 : setRestartFile(restart_file_base);
638 : }
639 509 : }
640 :
641 : // // Generally speaking, the mesh is prepared for use, and consequently remote elements are deleted
642 : // // well before our Problem(s) are constructed. Historically, in MooseMesh we have a bunch of
643 : // // needs_prepare type flags that make it so we never call prepare_for_use (and consequently
644 : // // delete_remote_elements) again. So the below line, historically, has had no impact. HOWEVER:
645 : // // I've added some code in SetupMeshCompleteAction for deleting remote elements post
646 : // // EquationSystems::init. If I execute that code without default ghosting, then I get > 40 MOOSE
647 : // // test failures, so we clearly have some simulations that are not yet covered properly by
648 : // // relationship managers. Until that is resolved, I am going to retain default geometric ghosting
649 : // if (!_default_ghosting)
650 : // _mesh.getMesh().remove_ghosting_functor(_mesh.getMesh().default_ghosting());
651 :
652 : #if !PETSC_RELEASE_LESS_THAN(3, 12, 0)
653 : // Main app should hold the default database to handle system petsc options
654 64845 : if (!_app.isUltimateMaster())
655 12471 : LibmeshPetscCall(PetscOptionsCreate(&_petsc_option_data_base));
656 : #endif
657 :
658 64845 : if (!_solve)
659 : {
660 : // If we are not solving, we do not care about seeing unused petsc options
661 47421 : Moose::PetscSupport::setSinglePetscOption("-options_left", "0");
662 : // We don't want petscSetOptions being called in solve and clearing the option that was just set
663 15807 : _is_petsc_options_inserted = true;
664 : }
665 64845 : }
666 :
667 : const MooseMesh &
668 322586 : FEProblemBase::mesh(bool use_displaced) const
669 : {
670 322586 : if (use_displaced && !_displaced_problem)
671 0 : mooseWarning("Displaced mesh was requested but the displaced problem does not exist. "
672 : "Regular mesh will be returned");
673 322586 : return ((use_displaced && _displaced_problem) ? _displaced_problem->mesh() : mesh());
674 : }
675 :
676 : void
677 64845 : FEProblemBase::createTagVectors()
678 : {
679 : // add vectors and their tags to system
680 129690 : auto & vectors = getParam<std::vector<std::vector<TagName>>>("extra_tag_vectors");
681 65570 : for (const auto sys_num : index_range(vectors))
682 1694 : for (auto & vector : vectors[sys_num])
683 : {
684 969 : auto tag = addVectorTag(vector);
685 969 : _solver_systems[sys_num]->addVector(tag, false, libMesh::GHOSTED);
686 : }
687 :
688 129690 : auto & not_zeroed_vectors = getParam<std::vector<std::vector<TagName>>>("not_zeroed_tag_vectors");
689 64857 : for (const auto sys_num : index_range(not_zeroed_vectors))
690 24 : for (auto & vector : not_zeroed_vectors[sys_num])
691 : {
692 12 : auto tag = addVectorTag(vector);
693 12 : _solver_systems[sys_num]->addVector(tag, false, GHOSTED);
694 12 : addNotZeroedVectorTag(tag);
695 : }
696 64845 : }
697 :
698 : void
699 63967 : FEProblemBase::createTagMatrices(CreateTaggedMatrixKey)
700 : {
701 127934 : auto & matrices = getParam<std::vector<std::vector<TagName>>>("extra_tag_matrices");
702 64215 : for (const auto sys_num : index_range(matrices))
703 692 : for (auto & matrix : matrices[sys_num])
704 : {
705 444 : auto tag = addMatrixTag(matrix);
706 444 : _solver_systems[sys_num]->addMatrix(tag);
707 : }
708 :
709 128209 : for (auto & sys : _solver_systems)
710 64242 : sys->sizeVariableMatrixData();
711 63967 : _aux->sizeVariableMatrixData();
712 63967 : }
713 :
714 : void
715 64845 : FEProblemBase::createTagSolutions()
716 : {
717 194566 : for (auto & vector : getParam<std::vector<TagName>>("extra_tag_solutions"))
718 : {
719 31 : auto tag = addVectorTag(vector, Moose::VECTOR_TAG_SOLUTION);
720 62 : for (auto & sys : _solver_systems)
721 31 : sys->addVector(tag, false, libMesh::GHOSTED);
722 31 : _aux->addVector(tag, false, libMesh::GHOSTED);
723 : }
724 :
725 64845 : if (_previous_nl_solution_required)
726 : {
727 : // We'll populate the zeroth state of the nonlinear iterations with the current solution for
728 : // ease of use in doing things like copying solutions backwards. We're just storing pointers in
729 : // the solution states containers so populating the zeroth state does not cost us the memory of
730 : // a new vector
731 94 : needSolutionState(1, Moose::SolutionIterationType::Nonlinear);
732 : }
733 :
734 64845 : auto tag = addVectorTag(Moose::SOLUTION_TAG, Moose::VECTOR_TAG_SOLUTION);
735 129993 : for (auto & sys : _solver_systems)
736 65148 : sys->associateVectorToTag(*sys->system().current_local_solution.get(), tag);
737 64845 : _aux->associateVectorToTag(*_aux->system().current_local_solution.get(), tag);
738 64845 : }
739 :
740 : void
741 150 : FEProblemBase::needSolutionState(unsigned int state, Moose::SolutionIterationType iteration_type)
742 : {
743 300 : for (auto & sys : _solver_systems)
744 150 : sys->needSolutionState(state, iteration_type);
745 150 : _aux->needSolutionState(state, iteration_type);
746 150 : }
747 :
748 : void
749 64845 : FEProblemBase::newAssemblyArray(std::vector<std::shared_ptr<SolverSystem>> & solver_systems)
750 : {
751 64845 : unsigned int n_threads = libMesh::n_threads();
752 :
753 64845 : _assembly.resize(n_threads);
754 136030 : for (const auto i : make_range(n_threads))
755 : {
756 71185 : _assembly[i].resize(solver_systems.size());
757 142697 : for (const auto j : index_range(solver_systems))
758 71512 : _assembly[i][j] = std::make_unique<Assembly>(*solver_systems[j], i);
759 : }
760 64845 : }
761 :
762 : void
763 62865 : FEProblemBase::initNullSpaceVectors(const InputParameters & parameters,
764 : std::vector<std::shared_ptr<NonlinearSystemBase>> & nls)
765 : {
766 314325 : TIME_SECTION("initNullSpaceVectors", 5, "Initializing Null Space Vectors");
767 :
768 62865 : unsigned int dimNullSpace = parameters.get<unsigned int>("null_space_dimension");
769 : unsigned int dimTransposeNullSpace =
770 62865 : parameters.get<unsigned int>("transpose_null_space_dimension");
771 62865 : unsigned int dimNearNullSpace = parameters.get<unsigned int>("near_null_space_dimension");
772 62891 : for (unsigned int i = 0; i < dimNullSpace; ++i)
773 : {
774 26 : std::ostringstream oss;
775 26 : oss << "_" << i;
776 : // do not project, since this will be recomputed, but make it ghosted, since the near nullspace
777 : // builder might march over all nodes
778 52 : for (auto & nl : nls)
779 26 : nl->addVector("NullSpace" + oss.str(), false, libMesh::GHOSTED);
780 26 : }
781 125730 : _subspace_dim["NullSpace"] = dimNullSpace;
782 62878 : for (unsigned int i = 0; i < dimTransposeNullSpace; ++i)
783 : {
784 13 : std::ostringstream oss;
785 13 : oss << "_" << i;
786 : // do not project, since this will be recomputed, but make it ghosted, since the near nullspace
787 : // builder might march over all nodes
788 26 : for (auto & nl : nls)
789 13 : nl->addVector("TransposeNullSpace" + oss.str(), false, libMesh::GHOSTED);
790 13 : }
791 125730 : _subspace_dim["TransposeNullSpace"] = dimTransposeNullSpace;
792 62865 : for (unsigned int i = 0; i < dimNearNullSpace; ++i)
793 : {
794 0 : std::ostringstream oss;
795 0 : oss << "_" << i;
796 : // do not project, since this will be recomputed, but make it ghosted, since the near-nullspace
797 : // builder might march over all semilocal nodes
798 0 : for (auto & nl : nls)
799 0 : nl->addVector("NearNullSpace" + oss.str(), false, libMesh::GHOSTED);
800 0 : }
801 125730 : _subspace_dim["NearNullSpace"] = dimNearNullSpace;
802 62865 : }
803 :
804 181149 : FEProblemBase::~FEProblemBase()
805 : {
806 : // Flush the Console stream, the underlying call to Console::mooseConsole
807 : // relies on a call to Output::checkInterval that has references to
808 : // _time, etc. If it is not flushed here memory problems arise if you have
809 : // an unflushed stream and start destructing things.
810 60383 : _console << std::flush;
811 :
812 60383 : unsigned int n_threads = libMesh::n_threads();
813 125977 : for (unsigned int i = 0; i < n_threads; i++)
814 : {
815 65594 : _zero[i].release();
816 65594 : _phi_zero[i].release();
817 65594 : _scalar_zero[i].release();
818 65594 : _grad_zero[i].release();
819 65594 : _grad_phi_zero[i].release();
820 65594 : _second_zero[i].release();
821 65594 : _second_phi_zero[i].release();
822 65594 : _vector_zero[i].release();
823 65594 : _vector_curl_zero[i].release();
824 65594 : _ad_zero[i].release();
825 65594 : _ad_grad_zero[i].release();
826 65594 : _ad_second_zero[i].release();
827 : }
828 :
829 : #if !PETSC_RELEASE_LESS_THAN(3, 12, 0)
830 60383 : if (!_app.isUltimateMaster())
831 : {
832 11081 : auto ierr = PetscOptionsDestroy(&_petsc_option_data_base);
833 : // Don't throw on destruction
834 11081 : CHKERRABORT(this->comm().get(), ierr);
835 : }
836 : #endif
837 60383 : }
838 :
839 : void
840 0 : FEProblemBase::setCoordSystem(const std::vector<SubdomainName> & blocks,
841 : const MultiMooseEnum & coord_sys)
842 : {
843 0 : TIME_SECTION("setCoordSystem", 5, "Setting Coordinate System");
844 0 : _mesh.setCoordSystem(blocks, coord_sys);
845 0 : }
846 :
847 : void
848 0 : FEProblemBase::setAxisymmetricCoordAxis(const MooseEnum & rz_coord_axis)
849 : {
850 0 : _mesh.setAxisymmetricCoordAxis(rz_coord_axis);
851 0 : }
852 :
853 : const ConstElemRange &
854 1457 : FEProblemBase::getEvaluableElementRange()
855 : {
856 1457 : if (!_evaluable_local_elem_range)
857 : {
858 688 : std::vector<const DofMap *> dof_maps(es().n_systems());
859 2064 : for (const auto i : make_range(es().n_systems()))
860 : {
861 1376 : const auto & sys = es().get_system(i);
862 1376 : dof_maps[i] = &sys.get_dof_map();
863 : }
864 : _evaluable_local_elem_range =
865 1376 : std::make_unique<ConstElemRange>(_mesh.getMesh().multi_evaluable_elements_begin(dof_maps),
866 2064 : _mesh.getMesh().multi_evaluable_elements_end(dof_maps));
867 688 : }
868 1457 : return *_evaluable_local_elem_range;
869 : }
870 :
871 : const ConstElemRange &
872 234 : FEProblemBase::getNonlinearEvaluableElementRange()
873 : {
874 234 : if (!_nl_evaluable_local_elem_range)
875 : {
876 234 : std::vector<const DofMap *> dof_maps(_nl.size());
877 468 : for (const auto i : index_range(dof_maps))
878 234 : dof_maps[i] = &_nl[i]->dofMap();
879 : _nl_evaluable_local_elem_range =
880 468 : std::make_unique<ConstElemRange>(_mesh.getMesh().multi_evaluable_elements_begin(dof_maps),
881 702 : _mesh.getMesh().multi_evaluable_elements_end(dof_maps));
882 234 : }
883 :
884 234 : return *_nl_evaluable_local_elem_range;
885 : }
886 :
887 : void
888 62213 : FEProblemBase::initialSetup()
889 : {
890 311065 : TIME_SECTION("initialSetup", 2, "Performing Initial Setup");
891 :
892 62213 : SubProblem::initialSetup();
893 :
894 62213 : if (_app.isRecovering() + _app.isRestarting() + bool(_app.getExReaderForRestart()) > 1)
895 0 : mooseError("Checkpoint recovery and restart and exodus restart are all mutually exclusive.");
896 :
897 62213 : if (_skip_exception_check)
898 10 : mooseWarning("MOOSE may fail to catch an exception when the \"skip_exception_check\" parameter "
899 : "is used. If you receive a terse MPI error during execution, remove this "
900 : "parameter and rerun your simulation");
901 :
902 : // set state flag indicating that we are in or beyond initialSetup.
903 : // This can be used to throw errors in methods that _must_ be called at construction time.
904 62213 : _started_initial_setup = true;
905 62213 : setCurrentExecuteOnFlag(EXEC_INITIAL);
906 :
907 : // Setup the solution states (current, old, etc) in each system based on
908 : // its default and the states requested of each of its variables
909 124701 : for (const auto i : index_range(_solver_systems))
910 : {
911 62488 : _solver_systems[i]->initSolutionState();
912 62488 : if (getDisplacedProblem())
913 2234 : getDisplacedProblem()->solverSys(i).initSolutionState();
914 : }
915 62213 : _aux->initSolutionState();
916 62213 : if (getDisplacedProblem())
917 2234 : getDisplacedProblem()->auxSys().initSolutionState();
918 :
919 : // always execute to get the max number of DoF per element and node needed to initialize phi_zero
920 : // variables
921 62213 : dof_id_type global_max_var_n_dofs_per_elem = 0;
922 124701 : for (const auto i : index_range(_solver_systems))
923 : {
924 62488 : auto & sys = *_solver_systems[i];
925 : dof_id_type max_var_n_dofs_per_elem;
926 : dof_id_type max_var_n_dofs_per_node;
927 : {
928 312440 : TIME_SECTION("computingMaxDofs", 3, "Computing Max Dofs Per Element");
929 :
930 62488 : MaxVarNDofsPerElem mvndpe(*this, sys);
931 62488 : Threads::parallel_reduce(*_mesh.getActiveLocalElementRange(), mvndpe);
932 62488 : max_var_n_dofs_per_elem = mvndpe.max();
933 62488 : _communicator.max(max_var_n_dofs_per_elem);
934 :
935 62488 : MaxVarNDofsPerNode mvndpn(*this, sys);
936 62488 : Threads::parallel_reduce(*_mesh.getLocalNodeRange(), mvndpn);
937 62488 : max_var_n_dofs_per_node = mvndpn.max();
938 62488 : _communicator.max(max_var_n_dofs_per_node);
939 62488 : global_max_var_n_dofs_per_elem =
940 62488 : std::max(global_max_var_n_dofs_per_elem, max_var_n_dofs_per_elem);
941 62488 : }
942 :
943 : {
944 312440 : TIME_SECTION("assignMaxDofs", 5, "Assigning Maximum Dofs Per Elem");
945 :
946 62488 : sys.assignMaxVarNDofsPerElem(max_var_n_dofs_per_elem);
947 62488 : auto displaced_problem = getDisplacedProblem();
948 62488 : if (displaced_problem)
949 2234 : displaced_problem->solverSys(i).assignMaxVarNDofsPerElem(max_var_n_dofs_per_elem);
950 :
951 62488 : sys.assignMaxVarNDofsPerNode(max_var_n_dofs_per_node);
952 62488 : if (displaced_problem)
953 2234 : displaced_problem->solverSys(i).assignMaxVarNDofsPerNode(max_var_n_dofs_per_node);
954 62488 : }
955 : }
956 :
957 : {
958 311065 : TIME_SECTION("resizingVarValues", 5, "Resizing Variable Values");
959 :
960 130164 : for (unsigned int tid = 0; tid < libMesh::n_threads(); ++tid)
961 : {
962 135902 : _phi_zero[tid].resize(global_max_var_n_dofs_per_elem, std::vector<Real>(getMaxQps(), 0.));
963 135902 : _grad_phi_zero[tid].resize(global_max_var_n_dofs_per_elem,
964 135902 : std::vector<RealGradient>(getMaxQps(), RealGradient(0.)));
965 135902 : _second_phi_zero[tid].resize(global_max_var_n_dofs_per_elem,
966 135902 : std::vector<RealTensor>(getMaxQps(), RealTensor(0.)));
967 : }
968 62213 : }
969 :
970 : // Set up stateful material property redistribution, if we suspect
971 : // it may be necessary later.
972 62213 : addAnyRedistributers();
973 :
974 62213 : if (_app.isRestarting() || _app.isRecovering() || _force_restart)
975 : {
976 : // Only load all of the vectors if we're recovering
977 4602 : _req.set().setLoadAllVectors(_app.isRecovering());
978 :
979 : // This forces stateful material property loading to be an exact one-to-one match
980 4602 : if (_app.isRecovering())
981 : {
982 16092 : for (auto props : {&_material_props, &_bnd_material_props, &_neighbor_material_props})
983 12069 : props->setRecovering();
984 :
985 : #ifdef MOOSE_KOKKOS_ENABLED
986 15872 : for (auto props :
987 19840 : {&_kokkos_material_props, &_kokkos_bnd_material_props, &_kokkos_neighbor_material_props})
988 11904 : props->setRecovering();
989 : #endif
990 : }
991 :
992 23010 : TIME_SECTION("restore", 3, "Restoring from backup");
993 :
994 : // We could have a cached backup when this app is a sub-app and has been given a Backup
995 4602 : if (!_app.hasInitialBackup())
996 3605 : _app.restore(_app.restartFolderBase(_app.getRestartRecoverFileBase()), _app.isRestarting());
997 : else
998 997 : _app.restoreFromInitialBackup(_app.isRestarting());
999 :
1000 : /**
1001 : * If this is a restart run, the user may want to override the start time, which we already set
1002 : * in the constructor. "_time" however will have been "restored" from the restart file. We need
1003 : * to honor the original request of the developer now that the restore has been completed.
1004 : */
1005 4555 : if (_app.isRestarting())
1006 : {
1007 532 : if (_app.hasStartTime())
1008 178 : _time = _time_old = _app.getStartTime();
1009 : else
1010 354 : _time_old = _time;
1011 : }
1012 4555 : }
1013 : else
1014 : {
1015 57611 : libMesh::ExodusII_IO * reader = _app.getExReaderForRestart();
1016 :
1017 57611 : if (reader)
1018 : {
1019 1445 : TIME_SECTION("copyingFromExodus", 3, "Copying Variables From Exodus");
1020 :
1021 586 : for (auto & sys : _solver_systems)
1022 301 : sys->copyVars(*reader);
1023 285 : _aux->copyVars(*reader);
1024 285 : }
1025 : else
1026 : {
1027 57322 : if (_solver_systems[0]->hasVarCopy() || _aux->hasVarCopy())
1028 0 : mooseError("Need Exodus reader to restart variables but the reader is not available\n"
1029 : "Use either FileMesh with an Exodus mesh file or FileMeshGenerator with an "
1030 : "Exodus mesh file and with use_for_exodus_restart equal to true");
1031 : }
1032 : }
1033 :
1034 : // Perform output related setups
1035 62162 : _app.getOutputWarehouse().initialSetup();
1036 :
1037 : // Flush all output to _console that occur during construction and initialization of objects
1038 62094 : _app.getOutputWarehouse().mooseConsole();
1039 :
1040 : // Build Refinement and Coarsening maps for stateful material projections if necessary
1041 64514 : if ((_adaptivity.isOn() || _num_grid_steps) &&
1042 2420 : (_material_props.hasStatefulProperties() || _bnd_material_props.hasStatefulProperties() ||
1043 2349 : _neighbor_material_props.hasStatefulProperties()))
1044 : {
1045 71 : if (_has_internal_edge_residual_objects)
1046 8 : mooseError("Stateful neighbor material properties do not work with mesh adaptivity");
1047 :
1048 63 : _mesh.buildRefinementAndCoarseningMaps(_assembly[0][0].get());
1049 : }
1050 :
1051 62086 : if (!_app.isRecovering())
1052 : {
1053 : /**
1054 : * If we are not recovering but we are doing restart (_app.getExodusFileRestart() == true) with
1055 : * additional uniform refinements. We have to delay the refinement until this point
1056 : * in time so that the equation systems are initialized and projections can be performed.
1057 : */
1058 58063 : if (_mesh.uniformRefineLevel() > 0 && _app.getExodusFileRestart())
1059 : {
1060 11 : if (!_app.isUltimateMaster())
1061 0 : mooseError(
1062 : "Doing extra refinements when restarting is NOT supported for sub-apps of a MultiApp");
1063 :
1064 11 : adaptivity().uniformRefineWithProjection();
1065 : }
1066 : }
1067 :
1068 62086 : unsigned int n_threads = libMesh::n_threads();
1069 :
1070 : // Convergence initial setup
1071 : {
1072 310430 : TIME_SECTION("convergenceInitialSetup", 5, "Initializing Convergence objects");
1073 :
1074 129851 : for (THREAD_ID tid = 0; tid < n_threads; tid++)
1075 67785 : _convergences.initialSetup(tid);
1076 62066 : }
1077 :
1078 : // UserObject initialSetup
1079 62066 : std::set<std::string> depend_objects_ic = _ics.getDependObjects();
1080 62066 : std::set<std::string> depend_objects_aux = _aux->getDependObjects();
1081 :
1082 : // This replaces all prior updateDependObjects calls on the old user object warehouses.
1083 62066 : TheWarehouse::Query uo_query = theWarehouse().query().condition<AttribSystem>("UserObject");
1084 62066 : std::vector<UserObject *> userobjs;
1085 62066 : uo_query.queryInto(userobjs);
1086 62066 : groupUserObjects(
1087 62066 : theWarehouse(), getAuxiliarySystem(), _app.getExecuteOnEnum(), userobjs, depend_objects_ic);
1088 :
1089 62066 : std::map<int, std::vector<UserObject *>> group_userobjs;
1090 144058 : for (auto obj : userobjs)
1091 245976 : group_userobjs[obj->getParam<int>("execution_order_group")].push_back(obj);
1092 :
1093 94647 : for (auto & [group, objs] : group_userobjs)
1094 114533 : for (auto obj : objs)
1095 81952 : obj->initialSetup();
1096 :
1097 : // check if jacobian calculation is done in userobject
1098 129606 : for (THREAD_ID tid = 0; tid < n_threads; ++tid)
1099 67640 : checkUserObjectJacobianRequirement(tid);
1100 :
1101 : // Check whether nonlocal couling is required or not
1102 61966 : checkNonlocalCoupling();
1103 61966 : if (_requires_nonlocal_coupling)
1104 81 : setVariableAllDoFMap(_uo_jacobian_moose_vars[0]);
1105 :
1106 : {
1107 309830 : TIME_SECTION("initializingFunctions", 5, "Initializing Functions");
1108 :
1109 : // Call the initialSetup methods for functions
1110 129566 : for (THREAD_ID tid = 0; tid < n_threads; tid++)
1111 : {
1112 67632 : reinitScalars(tid); // initialize scalars so they are properly sized for use as input into
1113 : // ParsedFunctions
1114 67632 : _functions.initialSetup(tid);
1115 : }
1116 :
1117 : #ifdef MOOSE_KOKKOS_ENABLED
1118 41614 : _kokkos_functions.initialSetup();
1119 : #endif
1120 61934 : }
1121 :
1122 : {
1123 309670 : TIME_SECTION("initializingRandomObjects", 5, "Initializing Random Objects");
1124 :
1125 : // Random interface objects
1126 62327 : for (const auto & it : _random_data_objects)
1127 393 : it.second->updateSeeds(EXEC_INITIAL);
1128 61934 : }
1129 :
1130 61934 : if (!_app.isRecovering())
1131 : {
1132 57911 : computeUserObjects(EXEC_INITIAL, Moose::PRE_IC);
1133 :
1134 : {
1135 289555 : TIME_SECTION("ICinitialSetup", 5, "Setting Up Initial Conditions");
1136 :
1137 121435 : for (THREAD_ID tid = 0; tid < n_threads; tid++)
1138 63532 : _ics.initialSetup(tid);
1139 :
1140 57903 : _scalar_ics.initialSetup();
1141 57903 : }
1142 :
1143 57903 : projectSolution();
1144 : }
1145 :
1146 : // Materials
1147 61918 : if (_all_materials.hasActiveObjects(0))
1148 : {
1149 44720 : TIME_SECTION("materialInitialSetup", 3, "Setting Up Materials");
1150 :
1151 18536 : for (THREAD_ID tid = 0; tid < n_threads; tid++)
1152 : {
1153 : // Sort the Material objects, these will be actually computed by MOOSE in reinit methods.
1154 9616 : _materials.sort(tid);
1155 9612 : _interface_materials.sort(tid);
1156 :
1157 : // Call initialSetup on all material objects
1158 9612 : _all_materials.initialSetup(tid);
1159 :
1160 : // Discrete materials may insert additional dependencies on materials during the initial
1161 : // setup. Therefore we resolve the dependencies once more, now with the additional
1162 : // dependencies due to discrete materials.
1163 9592 : if (_discrete_materials.hasActiveObjects())
1164 : {
1165 61 : _materials.sort(tid);
1166 61 : _interface_materials.sort(tid);
1167 : }
1168 : }
1169 :
1170 : #ifdef MOOSE_KOKKOS_ENABLED
1171 6001 : _kokkos_materials.sort(0, true);
1172 : #endif
1173 :
1174 : {
1175 44590 : TIME_SECTION("computingInitialStatefulProps", 3, "Computing Initial Material Values");
1176 :
1177 8918 : initElementStatefulProps(*_mesh.getActiveLocalElementRange(), true);
1178 :
1179 17074 : if (_material_props.hasStatefulProperties() || _bnd_material_props.hasStatefulProperties() ||
1180 8156 : _neighbor_material_props.hasStatefulProperties())
1181 762 : _has_initialized_stateful = true;
1182 : #ifdef MOOSE_KOKKOS_ENABLED
1183 5999 : if (_kokkos_material_props.hasStatefulProperties() ||
1184 11846 : _kokkos_bnd_material_props.hasStatefulProperties() ||
1185 5847 : _kokkos_neighbor_material_props.hasStatefulProperties())
1186 152 : _has_initialized_stateful = true;
1187 : #endif
1188 8918 : }
1189 8918 : }
1190 :
1191 : // setRestartInPlace() is set because the property maps have now been setup and we can
1192 : // dataLoad() them directly in place
1193 : // setRecovering() is set because from now on we require a one-to-one mapping of
1194 : // stateful properties because we shouldn't be declaring any more
1195 247568 : for (auto props : {&_material_props, &_bnd_material_props, &_neighbor_material_props})
1196 : {
1197 185676 : props->setRestartInPlace();
1198 185676 : props->setRecovering();
1199 : }
1200 :
1201 129439 : for (THREAD_ID tid = 0; tid < n_threads; tid++)
1202 : {
1203 67547 : _internal_side_indicators.initialSetup(tid);
1204 67547 : _indicators.initialSetup(tid);
1205 67547 : _markers.sort(tid);
1206 67547 : _markers.initialSetup(tid);
1207 : }
1208 :
1209 : #ifdef LIBMESH_ENABLE_AMR
1210 :
1211 61892 : if (!_app.isRecovering())
1212 : {
1213 57869 : unsigned int n = adaptivity().getInitialSteps();
1214 57869 : if (n && !_app.isUltimateMaster() && _app.isRestarting())
1215 0 : mooseError("Cannot perform initial adaptivity during restart on sub-apps of a MultiApp!");
1216 :
1217 57869 : initialAdaptMesh();
1218 : }
1219 :
1220 : #endif // LIBMESH_ENABLE_AMR
1221 :
1222 61888 : if (!_app.isRecovering() && !_app.isRestarting())
1223 : {
1224 : // During initial setup the solution is copied to the older solution states (old, older, etc)
1225 57333 : copySolutionsBackwards();
1226 :
1227 : // Check if there are old state initial conditions
1228 57333 : auto ics = _ics.getActiveObjects();
1229 57333 : auto fv_ics = _fv_ics.getActiveObjects();
1230 57333 : auto scalar_ics = _scalar_ics.getActiveObjects();
1231 57333 : unsigned short ic_state_max = 0;
1232 :
1233 171999 : auto findMax = [&ic_state_max](const auto & obj_list)
1234 : {
1235 202585 : for (auto ic : obj_list.getActiveObjects())
1236 30586 : ic_state_max = std::max(ic_state_max, ic->getState());
1237 229332 : };
1238 57333 : findMax(_ics);
1239 57333 : findMax(_fv_ics);
1240 57333 : findMax(_scalar_ics);
1241 :
1242 : // if there are old state ICs, compute them and write to old states accordingly
1243 57333 : if (ic_state_max > 0)
1244 : {
1245 : // state 0 copy (we'll overwrite current state when evaluating ICs and need to restore it once
1246 : // we're done with the old/older state ICs)
1247 0 : std::vector<std::unique_ptr<NumericVector<Real>>> state0_sys_buffers(_solver_systems.size());
1248 0 : std::unique_ptr<NumericVector<Real>> state0_aux_buffer;
1249 :
1250 : // save state 0
1251 0 : for (const auto i : index_range(_solver_systems))
1252 0 : state0_sys_buffers[i] = _solver_systems[i]->solutionState(0).clone();
1253 :
1254 0 : state0_aux_buffer = _aux->solutionState(0).clone();
1255 :
1256 : // compute old state ICs
1257 0 : for (_current_ic_state = 1; _current_ic_state <= ic_state_max; _current_ic_state++)
1258 : {
1259 0 : projectSolution();
1260 :
1261 0 : for (auto & sys : _solver_systems)
1262 0 : sys->solutionState(_current_ic_state) = sys->solutionState(0);
1263 :
1264 0 : _aux->solutionState(_current_ic_state) = _aux->solutionState(0);
1265 : }
1266 0 : _current_ic_state = 0;
1267 :
1268 : // recover state 0
1269 0 : for (const auto i : index_range(_solver_systems))
1270 : {
1271 0 : _solver_systems[i]->solutionState(0) = *state0_sys_buffers[i];
1272 0 : _solver_systems[i]->solutionState(0).close();
1273 0 : _solver_systems[i]->update();
1274 : }
1275 0 : _aux->solutionState(0) = *state0_aux_buffer;
1276 0 : _aux->solutionState(0).close();
1277 0 : _aux->update();
1278 0 : }
1279 57333 : }
1280 :
1281 61888 : if (!_app.isRecovering())
1282 : {
1283 57865 : if (haveXFEM())
1284 0 : updateMeshXFEM();
1285 : }
1286 :
1287 : // Call initialSetup on the solver systems
1288 124051 : for (auto & sys : _solver_systems)
1289 62163 : sys->initialSetup();
1290 :
1291 : // Auxilary variable initialSetup calls
1292 61888 : _aux->initialSetup();
1293 :
1294 61884 : if (_displaced_problem)
1295 : // initialSetup for displaced systems
1296 2234 : _displaced_problem->initialSetup();
1297 :
1298 124043 : for (auto & sys : _solver_systems)
1299 62159 : sys->setSolution(*(sys->system().current_local_solution.get()));
1300 :
1301 : // Update the nearest node searches (has to be called after the problem is all set up)
1302 : // We do this here because this sets up the Element's DoFs to ghost
1303 61884 : updateGeomSearch(GeometricSearchData::NEAREST_NODE);
1304 :
1305 61884 : _mesh.updateActiveSemiLocalNodeRange(_ghosted_elems);
1306 61884 : if (_displaced_mesh)
1307 2234 : _displaced_mesh->updateActiveSemiLocalNodeRange(_ghosted_elems);
1308 :
1309 : // We need to move the mesh in order to build a map between mortar secondary and primary
1310 : // interfaces. This map will then be used by the AgumentSparsityOnInterface ghosting functor to
1311 : // know which dofs we need ghosted when we call EquationSystems::reinit
1312 61884 : if (_displaced_problem && _mortar_data->hasDisplacedObjects())
1313 : {
1314 124 : _displaced_problem->updateMesh();
1315 : // if displacements were applied to the mesh, the mortar mesh should be updated too
1316 124 : updateMortarMesh();
1317 : }
1318 :
1319 : // Possibly reinit one more time to get ghosting correct
1320 61884 : reinitBecauseOfGhostingOrNewGeomObjects();
1321 :
1322 61884 : if (_displaced_mesh)
1323 2234 : _displaced_problem->updateMesh();
1324 :
1325 61884 : updateGeomSearch(); // Call all of the rest of the geometric searches
1326 :
1327 124039 : for (auto & sys : _solver_systems)
1328 : {
1329 62159 : const auto & tis = sys->getTimeIntegrators();
1330 :
1331 : {
1332 310795 : TIME_SECTION("timeIntegratorInitialSetup", 5, "Initializing Time Integrator");
1333 93386 : for (auto & ti : tis)
1334 31231 : ti->initialSetup();
1335 62155 : }
1336 : }
1337 :
1338 : // HUGE NOTE: MultiApp initialSetup() MUST... I repeat MUST be _after_ main-app restartable data
1339 : // has been restored
1340 :
1341 : // Call initialSetup on the MultiApps
1342 61880 : if (_multi_apps.hasObjects())
1343 : {
1344 32955 : TIME_SECTION("initialSetupMultiApps", 2, "Initializing MultiApps", false);
1345 6591 : _multi_apps.initialSetup();
1346 6583 : }
1347 :
1348 : // Call initialSetup on the transfers
1349 : {
1350 309360 : TIME_SECTION("initialSetupTransfers", 2, "Initializing Transfers");
1351 :
1352 61872 : _transfers.initialSetup();
1353 :
1354 : // Call initialSetup on the MultiAppTransfers to be executed on TO_MULTIAPP
1355 61872 : const auto & to_multi_app_objects = _to_multi_app_transfers.getActiveObjects();
1356 67036 : for (const auto & transfer : to_multi_app_objects)
1357 : {
1358 5228 : transfer->setCurrentDirection(Transfer::DIRECTION::TO_MULTIAPP);
1359 5228 : transfer->initialSetup();
1360 : }
1361 :
1362 : // Call initialSetup on the MultiAppTransfers to be executed on FROM_MULTIAPP
1363 61808 : const auto & from_multi_app_objects = _from_multi_app_transfers.getActiveObjects();
1364 67543 : for (const auto & transfer : from_multi_app_objects)
1365 : {
1366 5791 : transfer->setCurrentDirection(Transfer::DIRECTION::FROM_MULTIAPP);
1367 5791 : transfer->initialSetup();
1368 : }
1369 :
1370 : // Call initialSetup on the MultiAppTransfers to be executed on BETWEEN_MULTIAPP
1371 61752 : const auto & between_multi_app_objects = _between_multi_app_transfers.getActiveObjects();
1372 62948 : for (const auto & transfer : between_multi_app_objects)
1373 : {
1374 1196 : transfer->setCurrentDirection(Transfer::DIRECTION::BETWEEN_MULTIAPP);
1375 1196 : transfer->initialSetup();
1376 : }
1377 61752 : }
1378 :
1379 61752 : if (_boundary_restricted_node_integrity_check)
1380 : {
1381 185217 : TIME_SECTION("BoundaryRestrictedNodeIntegrityCheck", 5);
1382 :
1383 : // check that variables are defined along boundaries of boundary restricted nodal objects
1384 61739 : ConstBndNodeRange & bnd_nodes = *mesh().getBoundaryNodeRange();
1385 61739 : BoundaryNodeIntegrityCheckThread bnict(*this, uo_query);
1386 61739 : Threads::parallel_reduce(bnd_nodes, bnict);
1387 :
1388 : // Nodal bcs aren't threaded
1389 61727 : const auto & node_to_elem_map = _mesh.nodeToActiveSemilocalElemMap();
1390 4697709 : for (const auto & bnode : bnd_nodes)
1391 : {
1392 4635994 : const auto boundary_id = bnode->_bnd_id;
1393 4635994 : const Node * const node = bnode->_node;
1394 :
1395 4635994 : if (node->processor_id() != this->processor_id())
1396 879685 : continue;
1397 :
1398 : // Only check vertices. Variables may not be defined on non-vertex nodes (think first order
1399 : // Lagrange on a second order mesh) and user-code can often handle that
1400 : const Elem * const an_elem =
1401 3756309 : _mesh.getMesh().elem_ptr(libmesh_map_find(node_to_elem_map, node->id()).front());
1402 3756309 : if (!an_elem->is_vertex(an_elem->get_node_index(node)))
1403 464237 : continue;
1404 :
1405 3292072 : const auto & bnd_name = _mesh.getBoundaryName(boundary_id);
1406 :
1407 6537852 : for (auto & nl : _nl)
1408 : {
1409 3245792 : const auto & nodal_bcs = nl->getNodalBCWarehouse();
1410 3245792 : if (!nodal_bcs.hasBoundaryObjects(boundary_id, 0))
1411 2330237 : continue;
1412 :
1413 915555 : const auto & bnd_objects = nodal_bcs.getBoundaryObjects(boundary_id, 0);
1414 1921491 : for (const auto & bnd_object : bnd_objects)
1415 : // Skip if this object uses geometric search because coupled variables may be defined on
1416 : // paired boundaries instead of the boundary this node is on
1417 2011896 : if (!bnd_object->requiresGeometricSearch() &&
1418 1005948 : bnd_object->checkVariableBoundaryIntegrity())
1419 : {
1420 : std::set<MooseVariableFieldBase *> vars_to_omit = {
1421 : &static_cast<MooseVariableFieldBase &>(
1422 2011896 : const_cast<MooseVariableBase &>(bnd_object->variable()))};
1423 :
1424 2011896 : boundaryIntegrityCheckError(
1425 2011884 : *bnd_object, bnd_object->checkAllVariables(*node, vars_to_omit), bnd_name);
1426 1005936 : }
1427 : }
1428 : }
1429 61715 : }
1430 :
1431 61728 : if (_boundary_restricted_elem_integrity_check)
1432 : {
1433 185082 : TIME_SECTION("BoundaryRestrictedElemIntegrityCheck", 5);
1434 :
1435 : // check that variables are defined along boundaries of boundary restricted elemental objects
1436 61694 : ConstBndElemRange & bnd_elems = *mesh().getBoundaryElementRange();
1437 61694 : BoundaryElemIntegrityCheckThread beict(*this, uo_query);
1438 61694 : Threads::parallel_reduce(bnd_elems, beict);
1439 61678 : }
1440 :
1441 61712 : if (!_app.isRecovering())
1442 : {
1443 57689 : execTransfers(EXEC_INITIAL);
1444 :
1445 57689 : bool converged = execMultiApps(EXEC_INITIAL);
1446 57681 : if (!converged)
1447 4 : mooseError("failed to converge initial MultiApp");
1448 :
1449 : // We'll backup the Multiapp here
1450 57677 : backupMultiApps(EXEC_INITIAL);
1451 :
1452 120918 : for (THREAD_ID tid = 0; tid < n_threads; tid++)
1453 63241 : reinitScalars(tid);
1454 :
1455 57677 : execute(EXEC_INITIAL);
1456 :
1457 : // The FEProblemBase::execute method doesn't call all the systems on EXEC_INITIAL, but it does
1458 : // set/unset the current flag. Therefore, this resets the current flag to EXEC_INITIAL so that
1459 : // subsequent calls (e.g., executeControls) have the proper flag.
1460 57608 : setCurrentExecuteOnFlag(EXEC_INITIAL);
1461 : }
1462 :
1463 : // Here we will initialize the stateful properties once more since they may have been updated
1464 : // during initialSetup by calls to computeProperties.
1465 : //
1466 : // It's really bad that we don't allow this during restart. It means that we can't add new
1467 : // stateful materials
1468 : // during restart. This is only happening because this _has_ to be below initial userobject
1469 : // execution.
1470 : // Otherwise this could be done up above... _before_ restoring restartable data... which would
1471 : // allow you to have
1472 : // this happen during restart. I honestly have no idea why this has to happen after initial user
1473 : // object computation.
1474 : // THAT is something we should fix... so I've opened this ticket: #5804
1475 61631 : if (!_app.isRecovering() && !_app.isRestarting())
1476 : {
1477 113506 : if (_material_props.hasStatefulProperties() || _bnd_material_props.hasStatefulProperties() ||
1478 56430 : _neighbor_material_props.hasStatefulProperties())
1479 : {
1480 3230 : TIME_SECTION("computeMaterials", 2, "Computing Initial Material Properties");
1481 :
1482 646 : initElementStatefulProps(*_mesh.getActiveLocalElementRange(), true);
1483 646 : }
1484 : #ifdef MOOSE_KOKKOS_ENABLED
1485 37138 : if (_kokkos_material_props.hasStatefulProperties() ||
1486 74166 : _kokkos_bnd_material_props.hasStatefulProperties() ||
1487 37028 : _kokkos_neighbor_material_props.hasStatefulProperties())
1488 : {
1489 550 : TIME_SECTION("computeMaterials", 2, "Computing Initial Material Properties");
1490 :
1491 110 : initElementStatefulProps(*_mesh.getActiveLocalElementRange(), true);
1492 110 : }
1493 : #endif
1494 : }
1495 :
1496 : // Control Logic
1497 61631 : executeControls(EXEC_INITIAL);
1498 :
1499 : // Scalar variables need to reinited for the initial conditions to be available for output
1500 128772 : for (unsigned int tid = 0; tid < n_threads; tid++)
1501 67177 : reinitScalars(tid);
1502 :
1503 61595 : if (_displaced_mesh)
1504 2234 : _displaced_problem->syncSolutions();
1505 :
1506 : // Writes all calls to _console from initialSetup() methods
1507 61595 : _app.getOutputWarehouse().mooseConsole();
1508 :
1509 61595 : if (_requires_nonlocal_coupling)
1510 : {
1511 81 : setNonlocalCouplingMatrix();
1512 162 : for (THREAD_ID tid = 0; tid < n_threads; ++tid)
1513 162 : for (auto & assembly : _assembly[tid])
1514 81 : assembly->initNonlocalCoupling();
1515 : }
1516 :
1517 : {
1518 307975 : TIME_SECTION("lineSearchInitialSetup", 5, "Initializing Line Search");
1519 :
1520 61595 : if (_line_search)
1521 0 : _line_search->initialSetup();
1522 61595 : }
1523 :
1524 : // Perform Reporter get/declare check
1525 61595 : _reporter_data.check();
1526 :
1527 : // We do this late to allow objects to get late restartable data
1528 61595 : if (_app.isRestarting() || _app.isRecovering() || _force_restart)
1529 4555 : _app.finalizeRestore();
1530 :
1531 61595 : setCurrentExecuteOnFlag(EXEC_NONE);
1532 61595 : }
1533 :
1534 : void
1535 62643 : FEProblemBase::checkDuplicatePostprocessorVariableNames()
1536 : {
1537 118037 : for (const auto & pp : _reporter_data.getPostprocessorNames())
1538 55394 : if (hasScalarVariable(pp))
1539 0 : mooseError("Postprocessor \"" + pp +
1540 62643 : "\" has the same name as a scalar variable in the system.");
1541 62643 : }
1542 :
1543 : void
1544 290331 : FEProblemBase::timestepSetup()
1545 : {
1546 290331 : SubProblem::timestepSetup();
1547 :
1548 290331 : if (_t_step > 1 && _num_grid_steps)
1549 : {
1550 35 : libMesh::MeshRefinement mesh_refinement(_mesh);
1551 35 : std::unique_ptr<libMesh::MeshRefinement> displaced_mesh_refinement(nullptr);
1552 35 : if (_displaced_mesh)
1553 25 : displaced_mesh_refinement = std::make_unique<libMesh::MeshRefinement>(*_displaced_mesh);
1554 :
1555 70 : for (MooseIndex(_num_grid_steps) i = 0; i < _num_grid_steps; ++i)
1556 : {
1557 35 : if (_displaced_problem)
1558 : // If the DisplacedProblem is active, undisplace the DisplacedMesh in preparation for
1559 : // refinement. We can't safely refine the DisplacedMesh directly, since the Hilbert keys
1560 : // computed on the inconsistenly-displaced Mesh are different on different processors,
1561 : // leading to inconsistent Hilbert keys. We must do this before the undisplaced Mesh is
1562 : // coarsensed, so that the element and node numbering is still consistent. We also have to
1563 : // make sure this is done during every step of coarsening otherwise different partitions
1564 : // will be generated for the reference and displaced meshes (even for replicated)
1565 25 : _displaced_problem->undisplaceMesh();
1566 :
1567 35 : mesh_refinement.uniformly_coarsen();
1568 35 : if (_displaced_mesh)
1569 25 : displaced_mesh_refinement->uniformly_coarsen();
1570 :
1571 : // Mark this as an intermediate change because we do not yet want to reinit_systems. E.g. we
1572 : // need things to happen in the following order for the undisplaced problem:
1573 : // u1) EquationSystems::reinit_solutions. This will restrict the solution vectors and then
1574 : // contract the mesh
1575 : // u2) MooseMesh::meshChanged. This will update the node/side lists and other
1576 : // things which needs to happen after the contraction
1577 : // u3) GeometricSearchData::reinit. Once the node/side lists are updated we can perform our
1578 : // geometric searches which will aid in determining sparsity patterns
1579 : //
1580 : // We do these things for the displaced problem (if it exists)
1581 : // d1) EquationSystems::reinit. Restrict the displaced problem vector copies and then contract
1582 : // the mesh. It's safe to do a full reinit with the displaced because there are no
1583 : // matrices that sparsity pattern calculations will be conducted for
1584 : // d2) MooseMesh::meshChanged. This will update the node/side lists and other
1585 : // things which needs to happen after the contraction
1586 : // d3) UpdateDisplacedMeshThread::operator(). Re-displace the mesh using the *displaced*
1587 : // solution vector copy because we don't know the state of the reference solution vector.
1588 : // It's safe to use the displaced copy because we are outside of a non-linear solve,
1589 : // and there is no concern about differences between solution and current_local_solution
1590 : // d4) GeometricSearchData::reinit. With the node/side lists updated and the mesh
1591 : // re-displaced, we can perform our geometric searches, which will aid in determining the
1592 : // sparsity pattern of the matrix held by the libMesh::ImplicitSystem held by the
1593 : // NonlinearSystem held by this
1594 35 : meshChanged(
1595 : /*intermediate_change=*/true, /*contract_mesh=*/true, /*clean_refinement_flags=*/true);
1596 : }
1597 :
1598 : // u4) Now that all the geometric searches have been done (both undisplaced and displaced),
1599 : // we're ready to update the sparsity pattern
1600 35 : es().reinit_systems();
1601 35 : }
1602 :
1603 290331 : if (_line_search)
1604 0 : _line_search->timestepSetup();
1605 :
1606 : // Random interface objects
1607 292044 : for (const auto & it : _random_data_objects)
1608 1713 : it.second->updateSeeds(EXEC_TIMESTEP_BEGIN);
1609 :
1610 290331 : unsigned int n_threads = libMesh::n_threads();
1611 606383 : for (THREAD_ID tid = 0; tid < n_threads; tid++)
1612 : {
1613 316052 : _all_materials.timestepSetup(tid);
1614 316052 : _functions.timestepSetup(tid);
1615 : }
1616 :
1617 : #ifdef MOOSE_KOKKOS_ENABLED
1618 191428 : _kokkos_functions.timestepSetup();
1619 : #endif
1620 :
1621 290331 : _aux->timestepSetup();
1622 584437 : for (auto & sys : _solver_systems)
1623 294106 : sys->timestepSetup();
1624 :
1625 290331 : if (_displaced_problem)
1626 : // timestepSetup for displaced systems
1627 33515 : _displaced_problem->timestepSetup();
1628 :
1629 606383 : for (THREAD_ID tid = 0; tid < n_threads; tid++)
1630 : {
1631 316052 : _internal_side_indicators.timestepSetup(tid);
1632 316052 : _indicators.timestepSetup(tid);
1633 316052 : _markers.timestepSetup(tid);
1634 : }
1635 :
1636 290331 : std::vector<UserObject *> userobjs;
1637 290331 : theWarehouse().query().condition<AttribSystem>("UserObject").queryIntoUnsorted(userobjs);
1638 655230 : for (auto obj : userobjs)
1639 364899 : obj->timestepSetup();
1640 :
1641 : // Timestep setup of output objects
1642 290331 : _app.getOutputWarehouse().timestepSetup();
1643 :
1644 290331 : if (_requires_nonlocal_coupling)
1645 123 : if (_nonlocal_kernels.hasActiveObjects() || _nonlocal_integrated_bcs.hasActiveObjects())
1646 123 : _has_nonlocal_coupling = true;
1647 290331 : }
1648 :
1649 : unsigned int
1650 835524 : FEProblemBase::getMaxQps() const
1651 : {
1652 835524 : if (_max_qps == std::numeric_limits<unsigned int>::max())
1653 0 : mooseError("Max QPS uninitialized");
1654 835524 : return _max_qps;
1655 : }
1656 :
1657 : Order
1658 56 : FEProblemBase::getMaxScalarOrder() const
1659 : {
1660 56 : return _max_scalar_order;
1661 : }
1662 :
1663 : void
1664 61966 : FEProblemBase::checkNonlocalCoupling()
1665 : {
1666 309830 : TIME_SECTION("checkNonlocalCoupling", 5, "Checking Nonlocal Coupling");
1667 :
1668 129606 : for (THREAD_ID tid = 0; tid < libMesh::n_threads(); tid++)
1669 134232 : for (auto & nl : _nl)
1670 : {
1671 66592 : const auto & all_kernels = nl->getKernelWarehouse();
1672 66592 : const auto & kernels = all_kernels.getObjects(tid);
1673 157793 : for (const auto & kernel : kernels)
1674 : {
1675 : std::shared_ptr<NonlocalKernel> nonlocal_kernel =
1676 91201 : std::dynamic_pointer_cast<NonlocalKernel>(kernel);
1677 91201 : if (nonlocal_kernel)
1678 : {
1679 45 : if (_calculate_jacobian_in_uo)
1680 45 : _requires_nonlocal_coupling = true;
1681 45 : _nonlocal_kernels.addObject(kernel, tid);
1682 : }
1683 91201 : }
1684 : const MooseObjectWarehouse<IntegratedBCBase> & all_integrated_bcs =
1685 66592 : nl->getIntegratedBCWarehouse();
1686 66592 : const auto & integrated_bcs = all_integrated_bcs.getObjects(tid);
1687 76407 : for (const auto & integrated_bc : integrated_bcs)
1688 : {
1689 : std::shared_ptr<NonlocalIntegratedBC> nonlocal_integrated_bc =
1690 9815 : std::dynamic_pointer_cast<NonlocalIntegratedBC>(integrated_bc);
1691 9815 : if (nonlocal_integrated_bc)
1692 : {
1693 36 : if (_calculate_jacobian_in_uo)
1694 36 : _requires_nonlocal_coupling = true;
1695 36 : _nonlocal_integrated_bcs.addObject(integrated_bc, tid);
1696 : }
1697 9815 : }
1698 : }
1699 61966 : }
1700 :
1701 : void
1702 67640 : FEProblemBase::checkUserObjectJacobianRequirement(THREAD_ID tid)
1703 : {
1704 67640 : std::set<const MooseVariableFEBase *> uo_jacobian_moose_vars;
1705 : {
1706 67640 : std::vector<ShapeElementUserObject *> objs;
1707 67640 : theWarehouse()
1708 67640 : .query()
1709 135280 : .condition<AttribInterfaces>(Interfaces::ShapeElementUserObject)
1710 67640 : .condition<AttribThread>(tid)
1711 67640 : .queryInto(objs);
1712 :
1713 67696 : for (const auto & uo : objs)
1714 : {
1715 56 : _calculate_jacobian_in_uo = uo->computeJacobianFlag();
1716 56 : const auto & mv_deps = uo->jacobianMooseVariables();
1717 56 : uo_jacobian_moose_vars.insert(mv_deps.begin(), mv_deps.end());
1718 : }
1719 67640 : }
1720 : {
1721 67640 : std::vector<ShapeSideUserObject *> objs;
1722 67640 : theWarehouse()
1723 67640 : .query()
1724 135280 : .condition<AttribInterfaces>(Interfaces::ShapeSideUserObject)
1725 67640 : .condition<AttribThread>(tid)
1726 67640 : .queryInto(objs);
1727 67712 : for (const auto & uo : objs)
1728 : {
1729 72 : _calculate_jacobian_in_uo = uo->computeJacobianFlag();
1730 72 : const auto & mv_deps = uo->jacobianMooseVariables();
1731 72 : uo_jacobian_moose_vars.insert(mv_deps.begin(), mv_deps.end());
1732 : }
1733 67640 : }
1734 :
1735 67640 : _uo_jacobian_moose_vars[tid].assign(uo_jacobian_moose_vars.begin(), uo_jacobian_moose_vars.end());
1736 135280 : std::sort(
1737 135280 : _uo_jacobian_moose_vars[tid].begin(), _uo_jacobian_moose_vars[tid].end(), sortMooseVariables);
1738 67640 : }
1739 :
1740 : void
1741 81 : FEProblemBase::setVariableAllDoFMap(const std::vector<const MooseVariableFEBase *> & moose_vars)
1742 : {
1743 197 : for (unsigned int i = 0; i < moose_vars.size(); ++i)
1744 : {
1745 116 : VariableName var_name = moose_vars[i]->name();
1746 116 : auto & sys = _solver_systems[moose_vars[i]->sys().number()];
1747 116 : sys->setVariableGlobalDoFs(var_name);
1748 116 : _var_dof_map[var_name] = sys->getVariableGlobalDoFs();
1749 116 : }
1750 81 : }
1751 :
1752 : void
1753 431319012 : FEProblemBase::prepare(const Elem * elem, const THREAD_ID tid)
1754 : {
1755 865436984 : for (const auto i : index_range(_solver_systems))
1756 : {
1757 434117972 : _assembly[tid][i]->reinit(elem);
1758 434117972 : _solver_systems[i]->prepare(tid);
1759 :
1760 434117972 : if (i < _num_nl_sys)
1761 : {
1762 : // This method is called outside of residual/Jacobian callbacks during initial condition
1763 : // evaluation
1764 433445142 : if ((!_has_jacobian || !_const_jacobian) && currentlyComputingJacobian())
1765 56178235 : _assembly[tid][i]->prepareJacobianBlock();
1766 433445142 : _assembly[tid][i]->prepareResidual();
1767 433445142 : if (_has_nonlocal_coupling && currentlyComputingJacobian())
1768 11792 : _assembly[tid][i]->prepareNonlocal();
1769 : }
1770 : }
1771 431319012 : _aux->prepare(tid);
1772 :
1773 444601774 : if (_displaced_problem &&
1774 : // _reinit_displaced_neighbor applies to interface type objects which will do computations
1775 : // based on both elem and neighbor. Consequently, despite what you might think by its name, we
1776 : // must make sure we prepare the displaced elem
1777 444601774 : (_reinit_displaced_elem || _reinit_displaced_face || _reinit_displaced_neighbor))
1778 : {
1779 8536374 : _displaced_problem->prepare(_displaced_mesh->elemPtr(elem->id()), tid);
1780 8536346 : if (_has_nonlocal_coupling)
1781 0 : _displaced_problem->prepareNonlocal(tid);
1782 : }
1783 431318984 : }
1784 :
1785 : void
1786 29479 : FEProblemBase::prepareFace(const Elem * elem, const THREAD_ID tid)
1787 : {
1788 58958 : for (auto & nl : _nl)
1789 29479 : nl->prepareFace(tid, true);
1790 29479 : _aux->prepareFace(tid, false);
1791 :
1792 29479 : if (_displaced_problem && (_reinit_displaced_elem || _reinit_displaced_face))
1793 0 : _displaced_problem->prepareFace(_displaced_mesh->elemPtr(elem->id()), tid);
1794 29479 : }
1795 :
1796 : void
1797 0 : FEProblemBase::prepare(const Elem * elem,
1798 : unsigned int ivar,
1799 : unsigned int jvar,
1800 : const std::vector<dof_id_type> & dof_indices,
1801 : const THREAD_ID tid)
1802 : {
1803 0 : for (const auto i : index_range(_nl))
1804 : {
1805 0 : _assembly[tid][i]->reinit(elem);
1806 0 : _nl[i]->prepare(tid);
1807 : }
1808 :
1809 0 : _aux->prepare(tid);
1810 0 : const auto current_nl_sys_num = _current_nl_sys->number();
1811 0 : _assembly[tid][current_nl_sys_num]->prepareBlock(ivar, jvar, dof_indices);
1812 0 : if (_has_nonlocal_coupling)
1813 0 : if (_nonlocal_cm[current_nl_sys_num](ivar, jvar) != 0)
1814 : {
1815 0 : MooseVariableFEBase & jv = _current_nl_sys->getVariable(tid, jvar);
1816 0 : _assembly[tid][current_nl_sys_num]->prepareBlockNonlocal(
1817 : ivar, jvar, dof_indices, jv.allDofIndices());
1818 : }
1819 :
1820 0 : if (_displaced_problem && (_reinit_displaced_elem || _reinit_displaced_face))
1821 : {
1822 0 : _displaced_problem->prepare(_displaced_mesh->elemPtr(elem->id()), ivar, jvar, dof_indices, tid);
1823 0 : if (_has_nonlocal_coupling)
1824 0 : if (_nonlocal_cm[current_nl_sys_num](ivar, jvar) != 0)
1825 : {
1826 0 : MooseVariableFEBase & jv = _current_nl_sys->getVariable(tid, jvar);
1827 0 : _displaced_problem->prepareBlockNonlocal(ivar, jvar, dof_indices, jv.allDofIndices(), tid);
1828 : }
1829 : }
1830 0 : }
1831 :
1832 : void
1833 472150995 : FEProblemBase::setCurrentSubdomainID(const Elem * elem, const THREAD_ID tid)
1834 : {
1835 472150995 : SubdomainID did = elem->subdomain_id();
1836 948239649 : for (const auto i : index_range(_solver_systems))
1837 : {
1838 476088654 : _assembly[tid][i]->setCurrentSubdomainID(did);
1839 490298258 : if (_displaced_problem &&
1840 490298258 : (_reinit_displaced_elem || _reinit_displaced_face || _reinit_displaced_neighbor))
1841 8817056 : _displaced_problem->assembly(tid, i).setCurrentSubdomainID(did);
1842 : }
1843 472150995 : }
1844 :
1845 : void
1846 1664687072 : FEProblemBase::setNeighborSubdomainID(const Elem * elem, unsigned int side, const THREAD_ID tid)
1847 : {
1848 1664687072 : SubdomainID did = elem->neighbor_ptr(side)->subdomain_id();
1849 3334654544 : for (const auto i : index_range(_nl))
1850 : {
1851 1669967472 : _assembly[tid][i]->setCurrentNeighborSubdomainID(did);
1852 1719651575 : if (_displaced_problem &&
1853 1719651575 : (_reinit_displaced_elem || _reinit_displaced_face || _reinit_displaced_neighbor))
1854 29111734 : _displaced_problem->assembly(tid, i).setCurrentNeighborSubdomainID(did);
1855 : }
1856 1664687072 : }
1857 :
1858 : void
1859 23572031 : FEProblemBase::setNeighborSubdomainID(const Elem * elem, const THREAD_ID tid)
1860 : {
1861 23572031 : SubdomainID did = elem->subdomain_id();
1862 48214288 : for (const auto i : index_range(_nl))
1863 : {
1864 24642257 : _assembly[tid][i]->setCurrentNeighborSubdomainID(did);
1865 24699961 : if (_displaced_problem &&
1866 24699961 : (_reinit_displaced_elem || _reinit_displaced_face || _reinit_displaced_neighbor))
1867 57704 : _displaced_problem->assembly(tid, i).setCurrentNeighborSubdomainID(did);
1868 : }
1869 23572031 : }
1870 :
1871 : void
1872 153242 : FEProblemBase::prepareAssembly(const THREAD_ID tid)
1873 : {
1874 153242 : _assembly[tid][_current_nl_sys->number()]->prepare();
1875 153242 : if (_has_nonlocal_coupling)
1876 0 : _assembly[tid][_current_nl_sys->number()]->prepareNonlocal();
1877 :
1878 153242 : if (_displaced_problem && (_reinit_displaced_elem || _reinit_displaced_face))
1879 : {
1880 57704 : _displaced_problem->prepareAssembly(tid);
1881 57704 : if (_has_nonlocal_coupling)
1882 0 : _displaced_problem->prepareNonlocal(tid);
1883 : }
1884 153242 : }
1885 :
1886 : void
1887 300146 : FEProblemBase::addResidual(const THREAD_ID tid)
1888 : {
1889 600292 : _assembly[tid][_current_nl_sys->number()]->addResidual(Assembly::GlobalDataKey{},
1890 300146 : currentResidualVectorTags());
1891 :
1892 300146 : if (_displaced_problem)
1893 5288 : _displaced_problem->addResidual(tid);
1894 300146 : }
1895 :
1896 : void
1897 2337539 : FEProblemBase::addResidualNeighbor(const THREAD_ID tid)
1898 : {
1899 4675078 : _assembly[tid][_current_nl_sys->number()]->addResidualNeighbor(Assembly::GlobalDataKey{},
1900 2337539 : currentResidualVectorTags());
1901 :
1902 2337539 : if (_displaced_problem)
1903 68460 : _displaced_problem->addResidualNeighbor(tid);
1904 2337539 : }
1905 :
1906 : void
1907 2312671 : FEProblemBase::addResidualLower(const THREAD_ID tid)
1908 : {
1909 4625342 : _assembly[tid][_current_nl_sys->number()]->addResidualLower(Assembly::GlobalDataKey{},
1910 2312671 : currentResidualVectorTags());
1911 :
1912 2312671 : if (_displaced_problem)
1913 68688 : _displaced_problem->addResidualLower(tid);
1914 2312671 : }
1915 :
1916 : void
1917 64576 : FEProblemBase::addResidualScalar(const THREAD_ID tid /* = 0*/)
1918 : {
1919 129152 : _assembly[tid][_current_nl_sys->number()]->addResidualScalar(Assembly::GlobalDataKey{},
1920 64576 : currentResidualVectorTags());
1921 64576 : }
1922 :
1923 : void
1924 329625018 : FEProblemBase::cacheResidual(const THREAD_ID tid)
1925 : {
1926 329625018 : SubProblem::cacheResidual(tid);
1927 329625018 : if (_displaced_problem)
1928 8645975 : _displaced_problem->cacheResidual(tid);
1929 329625018 : }
1930 :
1931 : void
1932 55594 : FEProblemBase::cacheResidualNeighbor(const THREAD_ID tid)
1933 : {
1934 55594 : SubProblem::cacheResidualNeighbor(tid);
1935 55594 : if (_displaced_problem)
1936 36 : _displaced_problem->cacheResidualNeighbor(tid);
1937 55594 : }
1938 :
1939 : void
1940 19096482 : FEProblemBase::addCachedResidual(const THREAD_ID tid)
1941 : {
1942 19096482 : SubProblem::addCachedResidual(tid);
1943 19096482 : if (_displaced_problem)
1944 555761 : _displaced_problem->addCachedResidual(tid);
1945 19096482 : }
1946 :
1947 : void
1948 11826 : FEProblemBase::addCachedResidualDirectly(NumericVector<Number> & residual, const THREAD_ID tid)
1949 : {
1950 11826 : if (_current_nl_sys->hasVector(_current_nl_sys->timeVectorTag()))
1951 32553 : _assembly[tid][_current_nl_sys->number()]->addCachedResidualDirectly(
1952 32553 : residual, Assembly::GlobalDataKey{}, getVectorTag(_current_nl_sys->timeVectorTag()));
1953 :
1954 11826 : if (_current_nl_sys->hasVector(_current_nl_sys->nonTimeVectorTag()))
1955 35478 : _assembly[tid][_current_nl_sys->number()]->addCachedResidualDirectly(
1956 35478 : residual, Assembly::GlobalDataKey{}, getVectorTag(_current_nl_sys->nonTimeVectorTag()));
1957 :
1958 : // We do this because by adding the cached residual directly, we cannot ensure that all of the
1959 : // cached residuals are emptied after only the two add calls above
1960 11826 : _assembly[tid][_current_nl_sys->number()]->clearCachedResiduals(Assembly::GlobalDataKey{});
1961 :
1962 11826 : if (_displaced_problem)
1963 48 : _displaced_problem->addCachedResidualDirectly(residual, tid);
1964 11826 : }
1965 :
1966 : void
1967 0 : FEProblemBase::setResidual(NumericVector<Number> & residual, const THREAD_ID tid)
1968 : {
1969 0 : _assembly[tid][_current_nl_sys->number()]->setResidual(
1970 : residual,
1971 0 : Assembly::GlobalDataKey{},
1972 0 : getVectorTag(_nl[_current_nl_sys->number()]->residualVectorTag()));
1973 0 : if (_displaced_problem)
1974 0 : _displaced_problem->setResidual(residual, tid);
1975 0 : }
1976 :
1977 : void
1978 0 : FEProblemBase::setResidualNeighbor(NumericVector<Number> & residual, const THREAD_ID tid)
1979 : {
1980 0 : _assembly[tid][_current_nl_sys->number()]->setResidualNeighbor(
1981 0 : residual, Assembly::GlobalDataKey{}, getVectorTag(_current_nl_sys->residualVectorTag()));
1982 0 : if (_displaced_problem)
1983 0 : _displaced_problem->setResidualNeighbor(residual, tid);
1984 0 : }
1985 :
1986 : void
1987 42097 : FEProblemBase::addJacobian(const THREAD_ID tid)
1988 : {
1989 42097 : _assembly[tid][_current_nl_sys->number()]->addJacobian(Assembly::GlobalDataKey{});
1990 42097 : if (_has_nonlocal_coupling)
1991 0 : _assembly[tid][_current_nl_sys->number()]->addJacobianNonlocal(Assembly::GlobalDataKey{});
1992 42097 : if (_displaced_problem)
1993 : {
1994 224 : _displaced_problem->addJacobian(tid);
1995 224 : if (_has_nonlocal_coupling)
1996 0 : _displaced_problem->addJacobianNonlocal(tid);
1997 : }
1998 42097 : }
1999 :
2000 : void
2001 9105 : FEProblemBase::addJacobianNeighbor(const THREAD_ID tid)
2002 : {
2003 9105 : _assembly[tid][_current_nl_sys->number()]->addJacobianNeighbor(Assembly::GlobalDataKey{});
2004 9105 : if (_displaced_problem)
2005 54 : _displaced_problem->addJacobianNeighbor(tid);
2006 9105 : }
2007 :
2008 : void
2009 127506 : FEProblemBase::addJacobianNeighborLowerD(const THREAD_ID tid)
2010 : {
2011 127506 : _assembly[tid][_current_nl_sys->number()]->addJacobianNeighborLowerD(Assembly::GlobalDataKey{});
2012 127506 : if (_displaced_problem)
2013 3456 : _displaced_problem->addJacobianNeighborLowerD(tid);
2014 127506 : }
2015 :
2016 : void
2017 5220 : FEProblemBase::addJacobianLowerD(const THREAD_ID tid)
2018 : {
2019 5220 : _assembly[tid][_current_nl_sys->number()]->addJacobianLowerD(Assembly::GlobalDataKey{});
2020 5220 : if (_displaced_problem)
2021 216 : _displaced_problem->addJacobianLowerD(tid);
2022 5220 : }
2023 :
2024 : void
2025 15622 : FEProblemBase::addJacobianScalar(const THREAD_ID tid /* = 0*/)
2026 : {
2027 15622 : _assembly[tid][_current_nl_sys->number()]->addJacobianScalar(Assembly::GlobalDataKey{});
2028 15622 : }
2029 :
2030 : void
2031 39233 : FEProblemBase::addJacobianOffDiagScalar(unsigned int ivar, const THREAD_ID tid /* = 0*/)
2032 : {
2033 78466 : _assembly[tid][_current_nl_sys->number()]->addJacobianOffDiagScalar(ivar,
2034 39233 : Assembly::GlobalDataKey{});
2035 39233 : }
2036 :
2037 : void
2038 55544484 : FEProblemBase::cacheJacobian(const THREAD_ID tid)
2039 : {
2040 55544484 : SubProblem::cacheJacobian(tid);
2041 55544484 : if (_displaced_problem)
2042 1767232 : _displaced_problem->cacheJacobian(tid);
2043 55544484 : }
2044 :
2045 : void
2046 10576 : FEProblemBase::cacheJacobianNeighbor(const THREAD_ID tid)
2047 : {
2048 10576 : SubProblem::cacheJacobianNeighbor(tid);
2049 10576 : if (_displaced_problem)
2050 0 : _displaced_problem->cacheJacobianNeighbor(tid);
2051 10576 : }
2052 :
2053 : void
2054 3471647 : FEProblemBase::addCachedJacobian(const THREAD_ID tid)
2055 : {
2056 3471647 : SubProblem::addCachedJacobian(tid);
2057 3471643 : if (_displaced_problem)
2058 108971 : _displaced_problem->addCachedJacobian(tid);
2059 3471643 : }
2060 :
2061 : void
2062 81172 : FEProblemBase::addJacobianBlockTags(SparseMatrix<Number> & jacobian,
2063 : unsigned int ivar,
2064 : unsigned int jvar,
2065 : const DofMap & dof_map,
2066 : std::vector<dof_id_type> & dof_indices,
2067 : const std::set<TagID> & tags,
2068 : const THREAD_ID tid)
2069 : {
2070 162344 : _assembly[tid][_current_nl_sys->number()]->addJacobianBlockTags(
2071 81172 : jacobian, ivar, jvar, dof_map, dof_indices, Assembly::GlobalDataKey{}, tags);
2072 :
2073 81172 : if (_has_nonlocal_coupling)
2074 0 : if (_nonlocal_cm[_current_nl_sys->number()](ivar, jvar) != 0)
2075 : {
2076 0 : MooseVariableFEBase & jv = _current_nl_sys->getVariable(tid, jvar);
2077 0 : _assembly[tid][_current_nl_sys->number()]->addJacobianBlockNonlocalTags(
2078 : jacobian,
2079 : ivar,
2080 : jvar,
2081 : dof_map,
2082 : dof_indices,
2083 : jv.allDofIndices(),
2084 0 : Assembly::GlobalDataKey{},
2085 : tags);
2086 : }
2087 :
2088 81172 : if (_displaced_problem)
2089 : {
2090 0 : _displaced_problem->addJacobianBlockTags(jacobian, ivar, jvar, dof_map, dof_indices, tags, tid);
2091 0 : if (_has_nonlocal_coupling)
2092 0 : if (_nonlocal_cm[_current_nl_sys->number()](ivar, jvar) != 0)
2093 : {
2094 0 : MooseVariableFEBase & jv = _current_nl_sys->getVariable(tid, jvar);
2095 0 : _displaced_problem->addJacobianBlockNonlocal(
2096 : jacobian, ivar, jvar, dof_map, dof_indices, jv.allDofIndices(), tags, tid);
2097 : }
2098 : }
2099 81172 : }
2100 :
2101 : void
2102 1344 : FEProblemBase::addJacobianNeighbor(SparseMatrix<Number> & jacobian,
2103 : unsigned int ivar,
2104 : unsigned int jvar,
2105 : const DofMap & dof_map,
2106 : std::vector<dof_id_type> & dof_indices,
2107 : std::vector<dof_id_type> & neighbor_dof_indices,
2108 : const std::set<TagID> & tags,
2109 : const THREAD_ID tid)
2110 : {
2111 2688 : _assembly[tid][_current_nl_sys->number()]->addJacobianNeighborTags(jacobian,
2112 : ivar,
2113 : jvar,
2114 : dof_map,
2115 : dof_indices,
2116 : neighbor_dof_indices,
2117 1344 : Assembly::GlobalDataKey{},
2118 : tags);
2119 1344 : if (_displaced_problem)
2120 0 : _displaced_problem->addJacobianNeighbor(
2121 : jacobian, ivar, jvar, dof_map, dof_indices, neighbor_dof_indices, tags, tid);
2122 1344 : }
2123 :
2124 : void
2125 146088006 : FEProblemBase::prepareShapes(unsigned int var, const THREAD_ID tid)
2126 : {
2127 146088006 : _assembly[tid][_current_nl_sys->number()]->copyShapes(var);
2128 146088006 : }
2129 :
2130 : void
2131 722841 : FEProblemBase::prepareFaceShapes(unsigned int var, const THREAD_ID tid)
2132 : {
2133 722841 : _assembly[tid][_current_nl_sys->number()]->copyFaceShapes(var);
2134 722841 : }
2135 :
2136 : void
2137 217901 : FEProblemBase::prepareNeighborShapes(unsigned int var, const THREAD_ID tid)
2138 : {
2139 217901 : _assembly[tid][_current_nl_sys->number()]->copyNeighborShapes(var);
2140 217901 : }
2141 :
2142 : void
2143 965942 : FEProblemBase::addGhostedElem(dof_id_type elem_id)
2144 : {
2145 965942 : if (_mesh.elemPtr(elem_id)->processor_id() != processor_id())
2146 205714 : _ghosted_elems.insert(elem_id);
2147 965942 : }
2148 :
2149 : void
2150 31700 : FEProblemBase::addGhostedBoundary(BoundaryID boundary_id)
2151 : {
2152 31700 : _mesh.addGhostedBoundary(boundary_id);
2153 31700 : if (_displaced_problem)
2154 28798 : _displaced_mesh->addGhostedBoundary(boundary_id);
2155 31700 : }
2156 :
2157 : void
2158 70405 : FEProblemBase::ghostGhostedBoundaries()
2159 : {
2160 352025 : TIME_SECTION("ghostGhostedBoundaries", 3, "Ghosting Ghosted Boundaries");
2161 :
2162 70405 : _mesh.ghostGhostedBoundaries();
2163 :
2164 70405 : if (_displaced_problem)
2165 2879 : _displaced_mesh->ghostGhostedBoundaries();
2166 70405 : }
2167 :
2168 : void
2169 0 : FEProblemBase::sizeZeroes(unsigned int /*size*/, const THREAD_ID /*tid*/)
2170 : {
2171 0 : mooseDoOnce(mooseWarning(
2172 : "This function is deprecated and no longer performs any function. Please do not call it."));
2173 0 : }
2174 :
2175 : bool
2176 342243 : FEProblemBase::reinitDirac(const Elem * elem, const THREAD_ID tid)
2177 : {
2178 342243 : std::vector<Point> & points = _dirac_kernel_info.getPoints()[elem].first;
2179 :
2180 342243 : unsigned int n_points = points.size();
2181 :
2182 342243 : if (n_points)
2183 : {
2184 336731 : if (n_points > _max_qps)
2185 : {
2186 0 : _max_qps = n_points;
2187 :
2188 : /**
2189 : * The maximum number of qps can rise if several Dirac points are added to a single element.
2190 : * In that case we need to resize the zeros to compensate.
2191 : */
2192 0 : unsigned int max_qpts = getMaxQps();
2193 0 : for (unsigned int tid = 0; tid < libMesh::n_threads(); ++tid)
2194 : {
2195 : // the highest available order in libMesh is 43
2196 0 : _scalar_zero[tid].resize(FORTYTHIRD, 0);
2197 0 : _zero[tid].resize(max_qpts, 0);
2198 0 : _grad_zero[tid].resize(max_qpts, RealGradient(0.));
2199 0 : _second_zero[tid].resize(max_qpts, RealTensor(0.));
2200 0 : _vector_zero[tid].resize(max_qpts, RealGradient(0.));
2201 0 : _vector_curl_zero[tid].resize(max_qpts, RealGradient(0.));
2202 : }
2203 : }
2204 :
2205 673462 : for (const auto i : index_range(_nl))
2206 : {
2207 336731 : _assembly[tid][i]->reinitAtPhysical(elem, points);
2208 336731 : _nl[i]->prepare(tid);
2209 : }
2210 336731 : _aux->prepare(tid);
2211 :
2212 336731 : reinitElem(elem, tid);
2213 : }
2214 :
2215 342243 : _assembly[tid][_current_nl_sys->number()]->prepare();
2216 342243 : if (_has_nonlocal_coupling)
2217 0 : _assembly[tid][_current_nl_sys->number()]->prepareNonlocal();
2218 :
2219 342243 : bool have_points = n_points > 0;
2220 342243 : if (_displaced_problem && (_reinit_displaced_elem))
2221 : {
2222 5512 : have_points |= _displaced_problem->reinitDirac(_displaced_mesh->elemPtr(elem->id()), tid);
2223 5512 : if (_has_nonlocal_coupling)
2224 0 : _displaced_problem->prepareNonlocal(tid);
2225 : }
2226 :
2227 342243 : return have_points;
2228 : }
2229 :
2230 : void
2231 431583805 : FEProblemBase::reinitElem(const Elem * elem, const THREAD_ID tid)
2232 : {
2233 865966570 : for (auto & sys : _solver_systems)
2234 434382765 : sys->reinitElem(elem, tid);
2235 431583805 : _aux->reinitElem(elem, tid);
2236 :
2237 431583805 : if (_displaced_problem && _reinit_displaced_elem)
2238 4961598 : _displaced_problem->reinitElem(_displaced_mesh->elemPtr(elem->id()), tid);
2239 431583805 : }
2240 :
2241 : void
2242 53607 : FEProblemBase::reinitElemPhys(const Elem * const elem,
2243 : const std::vector<Point> & phys_points_in_elem,
2244 : const THREAD_ID tid)
2245 : {
2246 : mooseAssert(_mesh.queryElemPtr(elem->id()) == elem,
2247 : "Are you calling this method with a displaced mesh element?");
2248 :
2249 107214 : for (const auto i : index_range(_solver_systems))
2250 : {
2251 53607 : _assembly[tid][i]->reinitAtPhysical(elem, phys_points_in_elem);
2252 53607 : _solver_systems[i]->prepare(tid);
2253 53607 : _assembly[tid][i]->prepare();
2254 53607 : if (_has_nonlocal_coupling)
2255 0 : _assembly[tid][i]->prepareNonlocal();
2256 : }
2257 53607 : _aux->prepare(tid);
2258 :
2259 53607 : reinitElem(elem, tid);
2260 53607 : }
2261 :
2262 : void
2263 0 : FEProblemBase::reinitElemFace(const Elem * const elem,
2264 : const unsigned int side,
2265 : const BoundaryID,
2266 : const THREAD_ID tid)
2267 : {
2268 0 : mooseDeprecated(
2269 : "reinitElemFace with a BoundaryID argument is deprecated because the boundary id was never "
2270 : "used. Please call reinitElemFace without the BoundaryID argument instead");
2271 :
2272 0 : reinitElemFace(elem, side, tid);
2273 0 : }
2274 :
2275 : void
2276 8556469 : FEProblemBase::reinitElemFace(const Elem * const elem, const unsigned int side, const THREAD_ID tid)
2277 : {
2278 17113343 : for (const auto i : index_range(_solver_systems))
2279 : {
2280 8556874 : _assembly[tid][i]->reinit(elem, side);
2281 8556874 : _solver_systems[i]->reinitElemFace(elem, side, tid);
2282 : }
2283 8556469 : _aux->reinitElemFace(elem, side, tid);
2284 :
2285 8556469 : if (_displaced_problem && _reinit_displaced_face)
2286 97294 : _displaced_problem->reinitElemFace(_displaced_mesh->elemPtr(elem->id()), side, tid);
2287 8556469 : }
2288 :
2289 : void
2290 300210 : FEProblemBase::reinitLowerDElem(const Elem * lower_d_elem,
2291 : const THREAD_ID tid,
2292 : const std::vector<Point> * const pts,
2293 : const std::vector<Real> * const weights)
2294 : {
2295 300210 : SubProblem::reinitLowerDElem(lower_d_elem, tid, pts, weights);
2296 :
2297 300210 : if (_displaced_problem && _displaced_mesh)
2298 1080 : _displaced_problem->reinitLowerDElem(
2299 1080 : _displaced_mesh->elemPtr(lower_d_elem->id()), tid, pts, weights);
2300 300210 : }
2301 :
2302 : void
2303 29242958 : FEProblemBase::reinitNode(const Node * node, const THREAD_ID tid)
2304 : {
2305 29242958 : if (_displaced_problem && _reinit_displaced_elem)
2306 1122418 : _displaced_problem->reinitNode(&_displaced_mesh->nodeRef(node->id()), tid);
2307 :
2308 58489192 : for (const auto i : index_range(_nl))
2309 : {
2310 29246234 : _assembly[tid][i]->reinit(node);
2311 29246234 : _nl[i]->reinitNode(node, tid);
2312 : }
2313 29242958 : _aux->reinitNode(node, tid);
2314 29242958 : }
2315 :
2316 : void
2317 71972393 : FEProblemBase::reinitNodeFace(const Node * node, BoundaryID bnd_id, const THREAD_ID tid)
2318 : {
2319 71972393 : if (_displaced_problem && _reinit_displaced_face)
2320 3818746 : _displaced_problem->reinitNodeFace(&_displaced_mesh->nodeRef(node->id()), bnd_id, tid);
2321 :
2322 144822194 : for (const auto i : index_range(_nl))
2323 : {
2324 72849801 : _assembly[tid][i]->reinit(node);
2325 72849801 : _nl[i]->reinitNodeFace(node, bnd_id, tid);
2326 : }
2327 71972393 : _aux->reinitNodeFace(node, bnd_id, tid);
2328 71972393 : }
2329 :
2330 : void
2331 6813 : FEProblemBase::reinitNodes(const std::vector<dof_id_type> & nodes, const THREAD_ID tid)
2332 : {
2333 6813 : if (_displaced_problem && _reinit_displaced_elem)
2334 0 : _displaced_problem->reinitNodes(nodes, tid);
2335 :
2336 13626 : for (auto & nl : _nl)
2337 6813 : nl->reinitNodes(nodes, tid);
2338 6813 : _aux->reinitNodes(nodes, tid);
2339 6813 : }
2340 :
2341 : void
2342 723 : FEProblemBase::reinitNodesNeighbor(const std::vector<dof_id_type> & nodes, const THREAD_ID tid)
2343 : {
2344 723 : if (_displaced_problem && _reinit_displaced_elem)
2345 0 : _displaced_problem->reinitNodesNeighbor(nodes, tid);
2346 :
2347 1446 : for (auto & nl : _nl)
2348 723 : nl->reinitNodesNeighbor(nodes, tid);
2349 723 : _aux->reinitNodesNeighbor(nodes, tid);
2350 723 : }
2351 :
2352 : void
2353 9164360 : FEProblemBase::reinitScalars(const THREAD_ID tid, bool reinit_for_derivative_reordering /*=false*/)
2354 : {
2355 45821800 : TIME_SECTION("reinitScalars", 3, "Reinitializing Scalar Variables");
2356 :
2357 9164360 : if (_displaced_problem && _reinit_displaced_elem)
2358 124637 : _displaced_problem->reinitScalars(tid, reinit_for_derivative_reordering);
2359 :
2360 18573459 : for (auto & nl : _nl)
2361 9409099 : nl->reinitScalars(tid, reinit_for_derivative_reordering);
2362 9164360 : _aux->reinitScalars(tid, reinit_for_derivative_reordering);
2363 :
2364 : // This is called outside of residual/Jacobian call-backs
2365 18580263 : for (auto & assembly : _assembly[tid])
2366 9415903 : assembly->prepareScalar();
2367 9164360 : }
2368 :
2369 : void
2370 210604 : FEProblemBase::reinitOffDiagScalars(const THREAD_ID tid)
2371 : {
2372 210604 : _assembly[tid][_current_nl_sys->number()]->prepareOffDiagScalar();
2373 210604 : if (_displaced_problem)
2374 90 : _displaced_problem->reinitOffDiagScalars(tid);
2375 210604 : }
2376 :
2377 : void
2378 4228377 : FEProblemBase::reinitNeighbor(const Elem * elem, unsigned int side, const THREAD_ID tid)
2379 : {
2380 4228377 : setNeighborSubdomainID(elem, side, tid);
2381 :
2382 4228377 : const Elem * neighbor = elem->neighbor_ptr(side);
2383 4228377 : unsigned int neighbor_side = neighbor->which_neighbor_am_i(elem);
2384 :
2385 8456784 : for (const auto i : index_range(_nl))
2386 : {
2387 4228407 : _assembly[tid][i]->reinitElemAndNeighbor(elem, side, neighbor, neighbor_side);
2388 4228407 : _nl[i]->prepareNeighbor(tid);
2389 : // Called during stateful material property evaluation outside of solve
2390 4228407 : _assembly[tid][i]->prepareNeighbor();
2391 : }
2392 4228377 : _aux->prepareNeighbor(tid);
2393 :
2394 8456784 : for (auto & nl : _nl)
2395 : {
2396 4228407 : nl->reinitElemFace(elem, side, tid);
2397 4228407 : nl->reinitNeighborFace(neighbor, neighbor_side, tid);
2398 : }
2399 4228377 : _aux->reinitElemFace(elem, side, tid);
2400 4228377 : _aux->reinitNeighborFace(neighbor, neighbor_side, tid);
2401 :
2402 4228377 : if (_displaced_problem && _reinit_displaced_neighbor)
2403 : {
2404 : // There are cases like for cohesive zone modeling without significant sliding where we cannot
2405 : // use FEInterface::inverse_map in Assembly::reinitElemAndNeighbor in the displaced problem
2406 : // because the physical points coming from the element don't actually lie on the neighbor.
2407 : // Moreover, what's the point of doing another physical point inversion in other cases? We only
2408 : // care about the reference points which we can just take from the undisplaced computation
2409 71886 : const auto & displaced_ref_pts = _assembly[tid][0]->qRuleNeighbor()->get_points();
2410 :
2411 71886 : _displaced_problem->reinitNeighbor(
2412 71886 : _displaced_mesh->elemPtr(elem->id()), side, tid, &displaced_ref_pts);
2413 : }
2414 4228377 : }
2415 :
2416 : void
2417 2433898 : FEProblemBase::reinitElemNeighborAndLowerD(const Elem * elem,
2418 : unsigned int side,
2419 : const THREAD_ID tid)
2420 : {
2421 2433898 : reinitNeighbor(elem, side, tid);
2422 :
2423 2433898 : const Elem * lower_d_elem = _mesh.getLowerDElem(elem, side);
2424 2433898 : if (lower_d_elem && _mesh.interiorLowerDBlocks().count(lower_d_elem->subdomain_id()) > 0)
2425 11610 : reinitLowerDElem(lower_d_elem, tid);
2426 : else
2427 : {
2428 : // with mesh refinement, lower-dimensional element might be defined on neighbor side
2429 2422288 : auto & neighbor = _assembly[tid][0]->neighbor();
2430 2422288 : auto & neighbor_side = _assembly[tid][0]->neighborSide();
2431 2422288 : const Elem * lower_d_elem_neighbor = _mesh.getLowerDElem(neighbor, neighbor_side);
2432 2422288 : if (lower_d_elem_neighbor &&
2433 2422288 : _mesh.interiorLowerDBlocks().count(lower_d_elem_neighbor->subdomain_id()) > 0)
2434 : {
2435 0 : auto qps = _assembly[tid][0]->qPointsFaceNeighbor().stdVector();
2436 0 : std::vector<Point> reference_points;
2437 0 : FEMap::inverse_map(
2438 0 : lower_d_elem_neighbor->dim(), lower_d_elem_neighbor, qps, reference_points);
2439 0 : reinitLowerDElem(lower_d_elem_neighbor, tid, &reference_points);
2440 0 : }
2441 : }
2442 :
2443 2433898 : if (_displaced_problem && (_reinit_displaced_face || _reinit_displaced_neighbor))
2444 71820 : _displaced_problem->reinitElemNeighborAndLowerD(
2445 71820 : _displaced_mesh->elemPtr(elem->id()), side, tid);
2446 2433898 : }
2447 :
2448 : void
2449 108178 : FEProblemBase::reinitNeighborPhys(const Elem * neighbor,
2450 : unsigned int neighbor_side,
2451 : const std::vector<Point> & physical_points,
2452 : const THREAD_ID tid)
2453 : {
2454 : mooseAssert(_mesh.queryElemPtr(neighbor->id()) == neighbor,
2455 : "Are you calling this method with a displaced mesh element?");
2456 :
2457 216356 : for (const auto i : index_range(_nl))
2458 : {
2459 : // Reinits shape the functions at the physical points
2460 108178 : _assembly[tid][i]->reinitNeighborAtPhysical(neighbor, neighbor_side, physical_points);
2461 :
2462 : // Sets the neighbor dof indices
2463 108178 : _nl[i]->prepareNeighbor(tid);
2464 : }
2465 108178 : _aux->prepareNeighbor(tid);
2466 :
2467 : // Resizes Re and Ke
2468 108178 : _assembly[tid][_current_nl_sys->number()]->prepareNeighbor();
2469 :
2470 : // Compute the values of each variable at the points
2471 216356 : for (auto & nl : _nl)
2472 108178 : nl->reinitNeighborFace(neighbor, neighbor_side, tid);
2473 108178 : _aux->reinitNeighborFace(neighbor, neighbor_side, tid);
2474 108178 : }
2475 :
2476 : void
2477 22720 : FEProblemBase::reinitNeighborPhys(const Elem * neighbor,
2478 : const std::vector<Point> & physical_points,
2479 : const THREAD_ID tid)
2480 : {
2481 : mooseAssert(_mesh.queryElemPtr(neighbor->id()) == neighbor,
2482 : "Are you calling this method with a displaced mesh element?");
2483 :
2484 45440 : for (const auto i : index_range(_nl))
2485 : {
2486 : // Reinits shape the functions at the physical points
2487 22720 : _assembly[tid][i]->reinitNeighborAtPhysical(neighbor, physical_points);
2488 :
2489 : // Sets the neighbor dof indices
2490 22720 : _nl[i]->prepareNeighbor(tid);
2491 : }
2492 22720 : _aux->prepareNeighbor(tid);
2493 :
2494 : // Resizes Re and Ke
2495 22720 : _assembly[tid][_current_nl_sys->number()]->prepareNeighbor();
2496 :
2497 : // Compute the values of each variable at the points
2498 45440 : for (auto & nl : _nl)
2499 22720 : nl->reinitNeighbor(neighbor, tid);
2500 22720 : _aux->reinitNeighbor(neighbor, tid);
2501 22720 : }
2502 :
2503 : void
2504 38812 : FEProblemBase::getDiracElements(std::set<const Elem *> & elems)
2505 : {
2506 : // First add in the undisplaced elements
2507 38812 : elems = _dirac_kernel_info.getElements();
2508 :
2509 38812 : if (_displaced_problem)
2510 : {
2511 2539 : std::set<const Elem *> displaced_elements;
2512 2539 : _displaced_problem->getDiracElements(displaced_elements);
2513 :
2514 : { // Use the ids from the displaced elements to get the undisplaced elements
2515 : // and add them to the list
2516 8051 : for (const auto & elem : displaced_elements)
2517 5512 : elems.insert(_mesh.elemPtr(elem->id()));
2518 : }
2519 2539 : }
2520 38812 : }
2521 :
2522 : void
2523 3876179 : FEProblemBase::clearDiracInfo()
2524 : {
2525 3876179 : _dirac_kernel_info.clearPoints();
2526 :
2527 3876179 : if (_displaced_problem)
2528 159253 : _displaced_problem->clearDiracInfo();
2529 3876179 : }
2530 :
2531 : void
2532 6066497 : FEProblemBase::subdomainSetup(SubdomainID subdomain, const THREAD_ID tid)
2533 : {
2534 6066497 : _all_materials.subdomainSetup(subdomain, tid);
2535 : // Call the subdomain methods of the output system, these are not threaded so only call it once
2536 6066497 : if (tid == 0)
2537 5616983 : _app.getOutputWarehouse().subdomainSetup();
2538 :
2539 12284524 : for (auto & nl : _nl)
2540 6218027 : nl->subdomainSetup(subdomain, tid);
2541 :
2542 : // FIXME: call displaced_problem->subdomainSetup() ?
2543 : // When adding possibility with materials being evaluated on displaced mesh
2544 6066497 : }
2545 :
2546 : void
2547 18308496 : FEProblemBase::neighborSubdomainSetup(SubdomainID subdomain, const THREAD_ID tid)
2548 : {
2549 18308496 : _all_materials.neighborSubdomainSetup(subdomain, tid);
2550 18308496 : }
2551 :
2552 : void
2553 53316 : FEProblemBase::addFunction(const std::string & type,
2554 : const std::string & name,
2555 : InputParameters & parameters)
2556 : {
2557 : parallel_object_only();
2558 :
2559 106632 : parameters.set<SubProblem *>("_subproblem") = this;
2560 :
2561 110579 : for (THREAD_ID tid = 0; tid < libMesh::n_threads(); tid++)
2562 : {
2563 57400 : std::shared_ptr<Function> func = _factory.create<Function>(type, name, parameters, tid);
2564 57263 : logAdd("Function", name, type, parameters);
2565 57263 : _functions.addObject(func, tid);
2566 :
2567 57263 : if (auto * const functor = dynamic_cast<Moose::FunctorBase<Real> *>(func.get()))
2568 : {
2569 57263 : this->addFunctor(name, *functor, tid);
2570 57263 : if (_displaced_problem)
2571 1953 : _displaced_problem->addFunctor(name, *functor, tid);
2572 : }
2573 : else
2574 0 : mooseError("Unrecognized function functor type");
2575 57263 : }
2576 53179 : }
2577 :
2578 : void
2579 160321 : FEProblemBase::addConvergence(const std::string & type,
2580 : const std::string & name,
2581 : InputParameters & parameters)
2582 : {
2583 : parallel_object_only();
2584 :
2585 336227 : for (THREAD_ID tid = 0; tid < libMesh::n_threads(); tid++)
2586 : {
2587 175942 : std::shared_ptr<Convergence> conv = _factory.create<Convergence>(type, name, parameters, tid);
2588 175906 : _convergences.addObject(conv, tid);
2589 175906 : }
2590 160285 : }
2591 :
2592 : void
2593 63309 : FEProblemBase::addDefaultNonlinearConvergence(const InputParameters & params_to_apply)
2594 : {
2595 63309 : const std::string class_name = "DefaultNonlinearConvergence";
2596 63309 : InputParameters params = _factory.getValidParams(class_name);
2597 63309 : params.applyParameters(params_to_apply);
2598 63309 : params.applyParameters(parameters());
2599 63309 : params.set<bool>("added_as_default") = true;
2600 125557 : for (const auto & conv_name : getNonlinearConvergenceNames())
2601 62248 : addConvergence(class_name, conv_name, params);
2602 63309 : }
2603 :
2604 : void
2605 64144 : FEProblemBase::addDefaultMultiAppFixedPointConvergence(const InputParameters & params_to_apply)
2606 : {
2607 64144 : const std::string class_name = "DefaultMultiAppFixedPointConvergence";
2608 64144 : InputParameters params = _factory.getValidParams(class_name);
2609 64144 : params.applyParameters(params_to_apply);
2610 64144 : params.applyParameters(parameters());
2611 64144 : params.set<bool>("added_as_default") = true;
2612 64144 : addConvergence(class_name, getMultiAppFixedPointConvergenceName(), params);
2613 64132 : }
2614 :
2615 : void
2616 31989 : FEProblemBase::addDefaultSteadyStateConvergence(const InputParameters & params_to_apply)
2617 : {
2618 31989 : const std::string class_name = "DefaultSteadyStateConvergence";
2619 31989 : InputParameters params = _factory.getValidParams(class_name);
2620 31989 : params.applyParameters(params_to_apply);
2621 31989 : params.applyParameters(parameters());
2622 31989 : params.set<bool>("added_as_default") = true;
2623 31989 : addConvergence(class_name, getSteadyStateConvergenceName(), params);
2624 31989 : }
2625 :
2626 : bool
2627 89078 : FEProblemBase::hasFunction(const std::string & name, const THREAD_ID tid)
2628 : {
2629 89078 : return _functions.hasActiveObject(name, tid);
2630 : }
2631 :
2632 : Function &
2633 64968 : FEProblemBase::getFunction(const std::string & name, const THREAD_ID tid)
2634 : {
2635 : // This thread lock is necessary since this method will create functions
2636 : // for all threads if one is missing.
2637 64968 : Threads::spin_mutex::scoped_lock lock(get_function_mutex);
2638 :
2639 64968 : if (!hasFunction(name, tid))
2640 : {
2641 : // If we didn't find a function, it might be a default function, attempt to construct one now
2642 20250 : std::istringstream ss(name);
2643 : Real real_value;
2644 :
2645 : // First see if it's just a constant. If it is, build a ConstantFunction
2646 20250 : if (ss >> real_value && ss.eof())
2647 : {
2648 12984 : InputParameters params = _factory.getValidParams("ConstantFunction");
2649 12984 : params.set<Real>("value") = real_value;
2650 19476 : addFunction("ConstantFunction", ss.str(), params);
2651 6492 : }
2652 : else
2653 : {
2654 13758 : FunctionParserBase<Real> fp;
2655 13758 : std::string vars = "x,y,z,t,NaN,pi,e";
2656 13758 : if (fp.Parse(name, vars) == -1) // -1 for success
2657 : {
2658 : // It parsed ok, so build a MooseParsedFunction
2659 41262 : InputParameters params = _factory.getValidParams("ParsedFunction");
2660 13754 : params.set<std::string>("expression") = name;
2661 27508 : addFunction("ParsedFunction", name, params);
2662 13754 : }
2663 13758 : }
2664 :
2665 : // Try once more
2666 20250 : if (!hasFunction(name, tid))
2667 4 : mooseError("Unable to find function " + name);
2668 20246 : }
2669 :
2670 64964 : auto * const ret = dynamic_cast<Function *>(_functions.getActiveObject(name, tid).get());
2671 64964 : if (!ret)
2672 0 : mooseError("No function named ", name, " of appropriate type");
2673 :
2674 64964 : return *ret;
2675 64964 : }
2676 :
2677 : bool
2678 222126 : FEProblemBase::hasConvergence(const std::string & name, const THREAD_ID tid) const
2679 : {
2680 222126 : return _convergences.hasActiveObject(name, tid);
2681 : }
2682 :
2683 : Convergence &
2684 1234246 : FEProblemBase::getConvergence(const std::string & name, const THREAD_ID tid) const
2685 : {
2686 1234246 : auto * const ret = dynamic_cast<Convergence *>(_convergences.getActiveObject(name, tid).get());
2687 1234246 : if (!ret)
2688 0 : mooseError("The Convergence object '", name, "' does not exist.");
2689 :
2690 1234246 : return *ret;
2691 : }
2692 :
2693 : const std::vector<std::shared_ptr<Convergence>> &
2694 210836 : FEProblemBase::getConvergenceObjects(const THREAD_ID tid) const
2695 : {
2696 210836 : return _convergences.getActiveObjects(tid);
2697 : }
2698 :
2699 : void
2700 770 : FEProblemBase::addMeshDivision(const std::string & type,
2701 : const std::string & name,
2702 : InputParameters & parameters)
2703 : {
2704 : parallel_object_only();
2705 1540 : parameters.set<FEProblemBase *>("_fe_problem_base") = this;
2706 1540 : parameters.set<SubProblem *>("_subproblem") = this;
2707 1623 : for (THREAD_ID tid = 0; tid < libMesh::n_threads(); tid++)
2708 : {
2709 865 : std::shared_ptr<MeshDivision> func = _factory.create<MeshDivision>(type, name, parameters, tid);
2710 853 : _mesh_divisions.addObject(func, tid);
2711 853 : }
2712 758 : }
2713 :
2714 : MeshDivision &
2715 1665 : FEProblemBase::getMeshDivision(const std::string & name, const THREAD_ID tid) const
2716 : {
2717 1665 : auto * const ret = dynamic_cast<MeshDivision *>(_mesh_divisions.getActiveObject(name, tid).get());
2718 1665 : if (!ret)
2719 0 : mooseError("No MeshDivision object named ", name, " of appropriate type");
2720 1665 : return *ret;
2721 : }
2722 :
2723 : void
2724 0 : FEProblemBase::lineSearch()
2725 : {
2726 0 : _line_search->lineSearch();
2727 0 : }
2728 :
2729 : NonlinearSystem &
2730 0 : FEProblemBase::getNonlinearSystem(const unsigned int sys_num)
2731 : {
2732 0 : mooseDeprecated("FEProblemBase::getNonlinearSystem() is deprecated, please use "
2733 : "FEProblemBase::getNonlinearSystemBase() \n");
2734 :
2735 : mooseAssert(sys_num < _nl.size(), "System number greater than the number of nonlinear systems");
2736 0 : auto nl_sys = std::dynamic_pointer_cast<NonlinearSystem>(_nl[sys_num]);
2737 :
2738 0 : if (!nl_sys)
2739 0 : mooseError("This is not a NonlinearSystem");
2740 :
2741 0 : return *nl_sys;
2742 0 : }
2743 :
2744 : void
2745 0 : FEProblemBase::addDistribution(const std::string & type,
2746 : const std::string & name,
2747 : InputParameters & parameters)
2748 : {
2749 0 : parameters.set<std::string>("type") = type;
2750 0 : addObject<Distribution>(type, name, parameters, /* threaded = */ false);
2751 0 : }
2752 :
2753 : Distribution &
2754 0 : FEProblemBase::getDistribution(const std::string & name)
2755 : {
2756 0 : std::vector<Distribution *> objs;
2757 0 : theWarehouse()
2758 0 : .query()
2759 0 : .condition<AttribSystem>("Distribution")
2760 0 : .condition<AttribName>(name)
2761 0 : .queryInto(objs);
2762 0 : if (objs.empty())
2763 0 : mooseError("Unable to find Distribution with name '" + name + "'");
2764 0 : return *(objs[0]);
2765 0 : }
2766 :
2767 : void
2768 354 : FEProblemBase::addSampler(const std::string & type,
2769 : const std::string & name,
2770 : InputParameters & parameters)
2771 : {
2772 354 : const auto samplers = addObject<Sampler>(type, name, parameters);
2773 722 : for (auto & sampler : samplers)
2774 380 : sampler->init();
2775 342 : }
2776 :
2777 : Sampler &
2778 342 : FEProblemBase::getSampler(const std::string & name, const THREAD_ID tid)
2779 : {
2780 342 : std::vector<Sampler *> objs;
2781 342 : theWarehouse()
2782 684 : .query()
2783 342 : .condition<AttribSystem>("Sampler")
2784 342 : .condition<AttribThread>(tid)
2785 342 : .condition<AttribName>(name)
2786 342 : .queryInto(objs);
2787 342 : if (objs.empty())
2788 0 : mooseError(
2789 0 : "Unable to find Sampler with name '" + name +
2790 : "', if you are attempting to access this object in the constructor of another object then "
2791 : "the object being retrieved must occur prior to the caller within the input file.");
2792 684 : return *(objs[0]);
2793 342 : }
2794 :
2795 : bool
2796 163428 : FEProblemBase::duplicateVariableCheck(const std::string & var_name,
2797 : const FEType & type,
2798 : bool is_aux,
2799 : const std::set<SubdomainID> * const active_subdomains)
2800 : {
2801 163428 : std::set<SubdomainID> subdomainIDs;
2802 163428 : if (active_subdomains->size() == 0)
2803 : {
2804 154658 : const auto subdomains = _mesh.meshSubdomains();
2805 154658 : subdomainIDs.insert(subdomains.begin(), subdomains.end());
2806 154658 : }
2807 : else
2808 8770 : subdomainIDs.insert(active_subdomains->begin(), active_subdomains->end());
2809 :
2810 327597 : for (auto & sys : _solver_systems)
2811 : {
2812 164185 : SystemBase * curr_sys_ptr = sys.get();
2813 164185 : SystemBase * other_sys_ptr = _aux.get();
2814 164185 : std::string error_prefix = "";
2815 164185 : if (is_aux)
2816 : {
2817 98326 : curr_sys_ptr = _aux.get();
2818 98326 : other_sys_ptr = sys.get();
2819 98326 : error_prefix = "aux";
2820 : }
2821 :
2822 164185 : if (other_sys_ptr->hasVariable(var_name))
2823 4 : mooseError("Cannot have an auxiliary variable and a solver variable with the same name: ",
2824 : var_name);
2825 :
2826 164181 : if (curr_sys_ptr->hasVariable(var_name))
2827 : {
2828 : const Variable & var =
2829 12 : curr_sys_ptr->system().variable(curr_sys_ptr->system().variable_number(var_name));
2830 :
2831 : // variable type
2832 12 : if (var.type() != type)
2833 : {
2834 16 : const auto stringifyType = [](FEType t)
2835 16 : { return Moose::stringify(t.family) + " of order " + Moose::stringify(t.order); };
2836 :
2837 8 : mooseError("Mismatching types are specified for ",
2838 : error_prefix,
2839 : "variable with name '",
2840 : var_name,
2841 : "': '",
2842 8 : stringifyType(var.type()),
2843 : "' and '",
2844 8 : stringifyType(type),
2845 : "'");
2846 : }
2847 :
2848 : // block-restriction
2849 4 : if (!(active_subdomains->size() == 0 && var.active_subdomains().size() == 0))
2850 : {
2851 4 : const auto varActiveSubdomains = var.active_subdomains();
2852 4 : std::set<SubdomainID> varSubdomainIDs;
2853 4 : if (varActiveSubdomains.size() == 0)
2854 : {
2855 0 : const auto subdomains = _mesh.meshSubdomains();
2856 0 : varSubdomainIDs.insert(subdomains.begin(), subdomains.end());
2857 0 : }
2858 : else
2859 4 : varSubdomainIDs.insert(varActiveSubdomains.begin(), varActiveSubdomains.end());
2860 :
2861 : // Is subdomainIDs a subset of varSubdomainIDs? With this we allow the case that the newly
2862 : // requested block restriction is only a subset of the existing one.
2863 4 : const auto isSubset = std::includes(varSubdomainIDs.begin(),
2864 : varSubdomainIDs.end(),
2865 : subdomainIDs.begin(),
2866 : subdomainIDs.end());
2867 :
2868 4 : if (!isSubset)
2869 : {
2870 : // helper function: make a string from a set of subdomain ids
2871 8 : const auto stringifySubdomains = [this](std::set<SubdomainID> subdomainIDs)
2872 : {
2873 8 : std::stringstream s;
2874 20 : for (auto const i : subdomainIDs)
2875 : {
2876 : // do we need to insert a comma?
2877 12 : if (s.tellp() != 0)
2878 4 : s << ", ";
2879 :
2880 : // insert subdomain name and id -or- only the id (if no name is given)
2881 12 : const auto subdomainName = _mesh.getSubdomainName(i);
2882 12 : if (subdomainName.empty())
2883 12 : s << i;
2884 : else
2885 0 : s << subdomainName << " (" << i << ")";
2886 12 : }
2887 16 : return s.str();
2888 8 : };
2889 :
2890 8 : const std::string msg = "Mismatching block-restrictions are specified for " +
2891 8 : error_prefix + "variable with name '" + var_name + "': {" +
2892 16 : stringifySubdomains(varSubdomainIDs) + "} and {" +
2893 12 : stringifySubdomains(subdomainIDs) + "}";
2894 :
2895 4 : mooseError(msg);
2896 0 : }
2897 0 : }
2898 :
2899 0 : return true;
2900 : }
2901 164169 : }
2902 :
2903 163412 : return false;
2904 163412 : }
2905 :
2906 : void
2907 65258 : FEProblemBase::addVariable(const std::string & var_type,
2908 : const std::string & var_name,
2909 : InputParameters & params)
2910 : {
2911 : parallel_object_only();
2912 :
2913 65258 : const auto order = Utility::string_to_enum<Order>(params.get<MooseEnum>("order"));
2914 65258 : const auto family = Utility::string_to_enum<FEFamily>(params.get<MooseEnum>("family"));
2915 65258 : const auto fe_type = FEType(order, family);
2916 :
2917 : const auto active_subdomains_vector =
2918 65258 : _mesh.getSubdomainIDs(params.get<std::vector<SubdomainName>>("block"));
2919 : const std::set<SubdomainID> active_subdomains(active_subdomains_vector.begin(),
2920 65258 : active_subdomains_vector.end());
2921 :
2922 65258 : if (duplicateVariableCheck(var_name, fe_type, /* is_aux = */ false, &active_subdomains))
2923 0 : return;
2924 :
2925 195762 : params.set<FEProblemBase *>("_fe_problem_base") = this;
2926 65254 : params.set<Moose::VarKindType>("_var_kind") = Moose::VarKindType::VAR_SOLVER;
2927 65254 : SolverSystemName sys_name = params.get<SolverSystemName>("solver_sys");
2928 :
2929 65254 : const auto solver_system_number = solverSysNum(sys_name);
2930 65254 : logAdd("Variable", var_name, var_type, params);
2931 65254 : _solver_systems[solver_system_number]->addVariable(var_type, var_name, params);
2932 65238 : if (_displaced_problem)
2933 : // MooseObjects need to be unique so change the name here
2934 3839 : _displaced_problem->addVariable(var_type, var_name, params, solver_system_number);
2935 :
2936 65238 : _solver_var_to_sys_num[var_name] = solver_system_number;
2937 :
2938 65238 : markFamilyPRefinement(params);
2939 65238 : }
2940 :
2941 : std::pair<bool, unsigned int>
2942 5077563 : FEProblemBase::determineSolverSystem(const std::string & var_name,
2943 : const bool error_if_not_found) const
2944 : {
2945 5077563 : auto map_it = _solver_var_to_sys_num.find(var_name);
2946 5077563 : const bool var_in_sys = map_it != _solver_var_to_sys_num.end();
2947 5077563 : if (var_in_sys)
2948 : mooseAssert(_solver_systems[map_it->second]->hasVariable(var_name) ||
2949 : _solver_systems[map_it->second]->hasScalarVariable(var_name),
2950 : "If the variable is in our FEProblem solver system map, then it must be in the "
2951 : "solver system we expect");
2952 3434350 : else if (error_if_not_found)
2953 : {
2954 42 : if (_aux->hasVariable(var_name) || _aux->hasScalarVariable(var_name))
2955 28 : mooseError("No solver variable named ",
2956 : var_name,
2957 : " found. Did you specify an auxiliary variable when you meant to specify a "
2958 : "solver variable?");
2959 : else
2960 14 : mooseError("Unknown variable '",
2961 : var_name,
2962 : "'. It does not exist in the solver system(s) or auxiliary system");
2963 : }
2964 :
2965 10155042 : return std::make_pair(var_in_sys, var_in_sys ? map_it->second : libMesh::invalid_uint);
2966 : }
2967 :
2968 : void
2969 170868 : FEProblemBase::setResidualObjectParamsAndLog(const std::string & ro_name,
2970 : const std::string & name,
2971 : InputParameters & parameters,
2972 : const unsigned int nl_sys_num,
2973 : const std::string & base_name,
2974 : bool & reinit_displaced)
2975 : {
2976 170868 : if (_displaced_problem && parameters.get<bool>("use_displaced_mesh"))
2977 : {
2978 2160 : parameters.set<SubProblem *>("_subproblem") = _displaced_problem.get();
2979 2160 : parameters.set<SystemBase *>("_sys") = &_displaced_problem->solverSys(nl_sys_num);
2980 1080 : reinit_displaced = true;
2981 : }
2982 : else
2983 : {
2984 169788 : if (_displaced_problem == nullptr && parameters.get<bool>("use_displaced_mesh"))
2985 : {
2986 : // We allow Kernels to request that they use_displaced_mesh,
2987 : // but then be overridden when no displacements variables are
2988 : // provided in the Mesh block. If that happened, update the value
2989 : // of use_displaced_mesh appropriately for this Kernel.
2990 136 : if (parameters.have_parameter<bool>("use_displaced_mesh"))
2991 272 : parameters.set<bool>("use_displaced_mesh") = false;
2992 : }
2993 :
2994 339576 : parameters.set<SubProblem *>("_subproblem") = this;
2995 509364 : parameters.set<SystemBase *>("_sys") = _nl[nl_sys_num].get();
2996 : }
2997 :
2998 170868 : logAdd(base_name, name, ro_name, parameters);
2999 170868 : }
3000 :
3001 : void
3002 70351 : FEProblemBase::setAuxKernelParamsAndLog(const std::string & ak_name,
3003 : const std::string & name,
3004 : InputParameters & parameters,
3005 : const std::string & base_name)
3006 : {
3007 70351 : if (_displaced_problem && parameters.get<bool>("use_displaced_mesh"))
3008 : {
3009 24808 : parameters.set<SubProblem *>("_subproblem") = _displaced_problem.get();
3010 24808 : parameters.set<SystemBase *>("_sys") = &_displaced_problem->auxSys();
3011 24808 : parameters.set<SystemBase *>("_nl_sys") = &_displaced_problem->solverSys(0);
3012 12404 : if (!parameters.get<std::vector<BoundaryName>>("boundary").empty())
3013 11916 : _reinit_displaced_face = true;
3014 : else
3015 488 : _reinit_displaced_elem = true;
3016 : }
3017 : else
3018 : {
3019 57947 : if (_displaced_problem == nullptr && parameters.get<bool>("use_displaced_mesh"))
3020 : {
3021 : // We allow AuxKernels to request that they use_displaced_mesh,
3022 : // but then be overridden when no displacements variables are
3023 : // provided in the Mesh block. If that happened, update the value
3024 : // of use_displaced_mesh appropriately for this AuxKernel.
3025 863 : if (parameters.have_parameter<bool>("use_displaced_mesh"))
3026 1726 : parameters.set<bool>("use_displaced_mesh") = false;
3027 : }
3028 :
3029 115894 : parameters.set<SubProblem *>("_subproblem") = this;
3030 115894 : parameters.set<SystemBase *>("_sys") = _aux.get();
3031 173841 : parameters.set<SystemBase *>("_nl_sys") = _solver_systems[0].get();
3032 : }
3033 :
3034 70351 : logAdd(base_name, name, ak_name, parameters);
3035 70351 : }
3036 :
3037 : void
3038 83797 : FEProblemBase::addKernel(const std::string & kernel_name,
3039 : const std::string & name,
3040 : InputParameters & parameters)
3041 : {
3042 : parallel_object_only();
3043 167594 : const auto nl_sys_num = determineSolverSystem(parameters.varName("variable", name), true).second;
3044 83781 : if (!isSolverSystemNonlinear(nl_sys_num))
3045 0 : mooseError("You are trying to add a Kernel to a linear variable/system, which is not "
3046 : "supported at the moment!");
3047 83781 : setResidualObjectParamsAndLog(
3048 83781 : kernel_name, name, parameters, nl_sys_num, "Kernel", _reinit_displaced_elem);
3049 :
3050 83781 : _nl[nl_sys_num]->addKernel(kernel_name, name, parameters);
3051 83577 : }
3052 :
3053 : void
3054 808 : FEProblemBase::addHDGKernel(const std::string & kernel_name,
3055 : const std::string & name,
3056 : InputParameters & parameters)
3057 : {
3058 : parallel_object_only();
3059 1616 : const auto nl_sys_num = determineSolverSystem(parameters.varName("variable", name), true).second;
3060 808 : if (!isSolverSystemNonlinear(nl_sys_num))
3061 0 : mooseError("You are trying to add a HDGKernel to a linear variable/system, which is not "
3062 : "supported at the moment!");
3063 808 : setResidualObjectParamsAndLog(
3064 808 : kernel_name, name, parameters, nl_sys_num, "HDGKernel", _reinit_displaced_elem);
3065 :
3066 808 : _nl[nl_sys_num]->addHDGKernel(kernel_name, name, parameters);
3067 808 : }
3068 :
3069 : void
3070 620 : FEProblemBase::addNodalKernel(const std::string & kernel_name,
3071 : const std::string & name,
3072 : InputParameters & parameters)
3073 : {
3074 : parallel_object_only();
3075 :
3076 1240 : const auto nl_sys_num = determineSolverSystem(parameters.varName("variable", name), true).second;
3077 616 : if (_displaced_problem && parameters.get<bool>("use_displaced_mesh"))
3078 : {
3079 0 : parameters.set<SubProblem *>("_subproblem") = _displaced_problem.get();
3080 0 : parameters.set<SystemBase *>("_sys") = &_displaced_problem->solverSys(nl_sys_num);
3081 0 : _reinit_displaced_elem = true;
3082 : }
3083 : else
3084 : {
3085 616 : if (_displaced_problem == nullptr && parameters.get<bool>("use_displaced_mesh"))
3086 : {
3087 : // We allow NodalKernels to request that they use_displaced_mesh,
3088 : // but then be overridden when no displacements variables are
3089 : // provided in the Mesh block. If that happened, update the value
3090 : // of use_displaced_mesh appropriately for this NodalKernel.
3091 0 : if (parameters.have_parameter<bool>("use_displaced_mesh"))
3092 0 : parameters.set<bool>("use_displaced_mesh") = false;
3093 : }
3094 :
3095 1232 : parameters.set<SubProblem *>("_subproblem") = this;
3096 1848 : parameters.set<SystemBase *>("_sys") = _nl[nl_sys_num].get();
3097 : }
3098 616 : logAdd("NodalKernel", name, kernel_name, parameters);
3099 616 : _nl[nl_sys_num]->addNodalKernel(kernel_name, name, parameters);
3100 616 : }
3101 :
3102 : void
3103 1551 : FEProblemBase::addScalarKernel(const std::string & kernel_name,
3104 : const std::string & name,
3105 : InputParameters & parameters)
3106 : {
3107 : parallel_object_only();
3108 :
3109 3102 : const auto nl_sys_num = determineSolverSystem(parameters.varName("variable", name), true).second;
3110 1551 : if (!isSolverSystemNonlinear(nl_sys_num))
3111 0 : mooseError("You are trying to add a ScalarKernel to a linear variable/system, which is not "
3112 : "supported at the moment!");
3113 :
3114 1551 : if (_displaced_problem && parameters.get<bool>("use_displaced_mesh"))
3115 : {
3116 0 : parameters.set<SubProblem *>("_subproblem") = _displaced_problem.get();
3117 0 : parameters.set<SystemBase *>("_sys") = &_displaced_problem->solverSys(nl_sys_num);
3118 : }
3119 : else
3120 : {
3121 1551 : if (_displaced_problem == nullptr && parameters.get<bool>("use_displaced_mesh"))
3122 : {
3123 : // We allow ScalarKernels to request that they use_displaced_mesh,
3124 : // but then be overridden when no displacements variables are
3125 : // provided in the Mesh block. If that happened, update the value
3126 : // of use_displaced_mesh appropriately for this ScalarKernel.
3127 0 : if (parameters.have_parameter<bool>("use_displaced_mesh"))
3128 0 : parameters.set<bool>("use_displaced_mesh") = false;
3129 : }
3130 :
3131 3102 : parameters.set<SubProblem *>("_subproblem") = this;
3132 4653 : parameters.set<SystemBase *>("_sys") = _nl[nl_sys_num].get();
3133 : }
3134 :
3135 1551 : logAdd("ScalarKernel", name, kernel_name, parameters);
3136 1551 : _nl[nl_sys_num]->addScalarKernel(kernel_name, name, parameters);
3137 1543 : }
3138 :
3139 : void
3140 82986 : FEProblemBase::addBoundaryCondition(const std::string & bc_name,
3141 : const std::string & name,
3142 : InputParameters & parameters)
3143 : {
3144 : parallel_object_only();
3145 :
3146 165976 : const auto nl_sys_num = determineSolverSystem(parameters.varName("variable", name), true).second;
3147 82976 : if (!isSolverSystemNonlinear(nl_sys_num))
3148 0 : mooseError(
3149 : "You are trying to add a BoundaryCondition to a linear variable/system, which is not "
3150 : "supported at the moment!");
3151 :
3152 82976 : setResidualObjectParamsAndLog(
3153 82976 : bc_name, name, parameters, nl_sys_num, "BoundaryCondition", _reinit_displaced_face);
3154 82976 : _nl[nl_sys_num]->addBoundaryCondition(bc_name, name, parameters);
3155 82918 : }
3156 :
3157 : void
3158 1731 : FEProblemBase::addConstraint(const std::string & c_name,
3159 : const std::string & name,
3160 : InputParameters & parameters)
3161 : {
3162 : parallel_object_only();
3163 :
3164 1731 : _has_constraints = true;
3165 :
3166 1731 : auto determine_var_param_name = [¶meters, this]()
3167 : {
3168 5193 : if (parameters.isParamValid("variable"))
3169 1125 : return "variable";
3170 : else
3171 : {
3172 : // must be a mortar constraint
3173 1212 : const bool has_secondary_var = parameters.isParamValid("secondary_variable");
3174 1212 : const bool has_primary_var = parameters.isParamValid("primary_variable");
3175 606 : if (!has_secondary_var && !has_primary_var)
3176 0 : mooseError(
3177 : "Either a 'secondary_variable' or 'primary_variable' parameter must be supplied for '",
3178 0 : parameters.getObjectName(),
3179 : "'");
3180 606 : return has_secondary_var ? "secondary_variable" : "primary_variable";
3181 : }
3182 1731 : };
3183 :
3184 : const auto nl_sys_num =
3185 3462 : determineSolverSystem(parameters.varName(determine_var_param_name(), name), true).second;
3186 1727 : if (!isSolverSystemNonlinear(nl_sys_num))
3187 0 : mooseError("You are trying to add a Constraint to a linear variable/system, which is not "
3188 : "supported at the moment!");
3189 :
3190 1727 : if (_displaced_problem && parameters.get<bool>("use_displaced_mesh"))
3191 : {
3192 294 : parameters.set<SubProblem *>("_subproblem") = _displaced_problem.get();
3193 294 : parameters.set<SystemBase *>("_sys") = &_displaced_problem->solverSys(nl_sys_num);
3194 147 : _reinit_displaced_face = true;
3195 : }
3196 : else
3197 : {
3198 : // It might _want_ to use a displaced mesh... but we're not so set it to false
3199 1580 : if (parameters.have_parameter<bool>("use_displaced_mesh"))
3200 3160 : parameters.set<bool>("use_displaced_mesh") = false;
3201 :
3202 3160 : parameters.set<SubProblem *>("_subproblem") = this;
3203 4740 : parameters.set<SystemBase *>("_sys") = _nl[nl_sys_num].get();
3204 : }
3205 :
3206 1727 : logAdd("Constraint", name, c_name, parameters);
3207 1727 : _nl[nl_sys_num]->addConstraint(c_name, name, parameters);
3208 1719 : }
3209 :
3210 : void
3211 98170 : FEProblemBase::addAuxVariable(const std::string & var_type,
3212 : const std::string & var_name,
3213 : InputParameters & params)
3214 : {
3215 : parallel_object_only();
3216 :
3217 98170 : const auto order = Utility::string_to_enum<Order>(params.get<MooseEnum>("order"));
3218 98170 : const auto family = Utility::string_to_enum<FEFamily>(params.get<MooseEnum>("family"));
3219 98170 : const auto fe_type = FEType(order, family);
3220 :
3221 : const auto active_subdomains_vector =
3222 98170 : _mesh.getSubdomainIDs(params.get<std::vector<SubdomainName>>("block"));
3223 : const std::set<SubdomainID> active_subdomains(active_subdomains_vector.begin(),
3224 98170 : active_subdomains_vector.end());
3225 :
3226 98170 : if (duplicateVariableCheck(var_name, fe_type, /* is_aux = */ true, &active_subdomains))
3227 0 : return;
3228 :
3229 294474 : params.set<FEProblemBase *>("_fe_problem_base") = this;
3230 196316 : params.set<Moose::VarKindType>("_var_kind") = Moose::VarKindType::VAR_AUXILIARY;
3231 :
3232 98158 : logAdd("AuxVariable", var_name, var_type, params);
3233 98158 : _aux->addVariable(var_type, var_name, params);
3234 98158 : if (_displaced_problem)
3235 : // MooseObjects need to be unique so change the name here
3236 11112 : _displaced_problem->addAuxVariable(var_type, var_name, params);
3237 :
3238 98158 : markFamilyPRefinement(params);
3239 98158 : }
3240 :
3241 : void
3242 0 : FEProblemBase::addAuxVariable(const std::string & var_name,
3243 : const FEType & type,
3244 : const std::set<SubdomainID> * const active_subdomains)
3245 : {
3246 : parallel_object_only();
3247 :
3248 0 : mooseDeprecated("Please use the addAuxVariable(var_type, var_name, params) API instead");
3249 :
3250 0 : if (duplicateVariableCheck(var_name, type, /* is_aux = */ true, active_subdomains))
3251 0 : return;
3252 :
3253 0 : std::string var_type;
3254 0 : if (type == FEType(0, MONOMIAL))
3255 0 : var_type = "MooseVariableConstMonomial";
3256 0 : else if (type.family == SCALAR)
3257 0 : var_type = "MooseVariableScalar";
3258 0 : else if (FEInterface::field_type(type) == TYPE_VECTOR)
3259 0 : var_type = "VectorMooseVariable";
3260 : else
3261 0 : var_type = "MooseVariable";
3262 :
3263 0 : InputParameters params = _factory.getValidParams(var_type);
3264 0 : params.set<FEProblemBase *>("_fe_problem_base") = this;
3265 0 : params.set<Moose::VarKindType>("_var_kind") = Moose::VarKindType::VAR_AUXILIARY;
3266 0 : params.set<MooseEnum>("order") = type.order.get_order();
3267 0 : params.set<MooseEnum>("family") = Moose::stringify(type.family);
3268 :
3269 0 : if (active_subdomains)
3270 0 : for (const SubdomainID & id : *active_subdomains)
3271 0 : params.set<std::vector<SubdomainName>>("block").push_back(Moose::stringify(id));
3272 :
3273 0 : logAdd("AuxVariable", var_name, var_type, params);
3274 0 : _aux->addVariable(var_type, var_name, params);
3275 0 : if (_displaced_problem)
3276 0 : _displaced_problem->addAuxVariable("MooseVariable", var_name, params);
3277 :
3278 0 : markFamilyPRefinement(params);
3279 0 : }
3280 :
3281 : void
3282 0 : FEProblemBase::addAuxArrayVariable(const std::string & var_name,
3283 : const FEType & type,
3284 : unsigned int components,
3285 : const std::set<SubdomainID> * const active_subdomains)
3286 : {
3287 : parallel_object_only();
3288 :
3289 0 : mooseDeprecated("Please use the addAuxVariable(var_type, var_name, params) API instead");
3290 :
3291 0 : if (duplicateVariableCheck(var_name, type, /* is_aux = */ true, active_subdomains))
3292 0 : return;
3293 :
3294 0 : InputParameters params = _factory.getValidParams("ArrayMooseVariable");
3295 0 : params.set<FEProblemBase *>("_fe_problem_base") = this;
3296 0 : params.set<Moose::VarKindType>("_var_kind") = Moose::VarKindType::VAR_AUXILIARY;
3297 0 : params.set<MooseEnum>("order") = type.order.get_order();
3298 0 : params.set<MooseEnum>("family") = Moose::stringify(type.family);
3299 0 : params.set<unsigned int>("components") = components;
3300 :
3301 0 : if (active_subdomains)
3302 0 : for (const SubdomainID & id : *active_subdomains)
3303 0 : params.set<std::vector<SubdomainName>>("block").push_back(Moose::stringify(id));
3304 :
3305 0 : logAdd("Variable", var_name, "ArrayMooseVariable", params);
3306 0 : _aux->addVariable("ArrayMooseVariable", var_name, params);
3307 0 : if (_displaced_problem)
3308 0 : _displaced_problem->addAuxVariable("ArrayMooseVariable", var_name, params);
3309 :
3310 0 : markFamilyPRefinement(params);
3311 0 : }
3312 :
3313 : void
3314 0 : FEProblemBase::addAuxScalarVariable(const std::string & var_name,
3315 : Order order,
3316 : Real /*scale_factor*/,
3317 : const std::set<SubdomainID> * const active_subdomains)
3318 : {
3319 : parallel_object_only();
3320 :
3321 0 : mooseDeprecated("Please use the addAuxVariable(var_type, var_name, params) API instead");
3322 :
3323 0 : if (order > _max_scalar_order)
3324 0 : _max_scalar_order = order;
3325 :
3326 0 : FEType type(order, SCALAR);
3327 0 : if (duplicateVariableCheck(var_name, type, /* is_aux = */ true, active_subdomains))
3328 0 : return;
3329 :
3330 0 : InputParameters params = _factory.getValidParams("MooseVariableScalar");
3331 0 : params.set<FEProblemBase *>("_fe_problem_base") = this;
3332 0 : params.set<Moose::VarKindType>("_var_kind") = Moose::VarKindType::VAR_AUXILIARY;
3333 :
3334 0 : params.set<MooseEnum>("order") = type.order.get_order();
3335 0 : params.set<MooseEnum>("family") = "SCALAR";
3336 0 : params.set<std::vector<Real>>("scaling") = {1};
3337 0 : if (active_subdomains)
3338 0 : for (const SubdomainID & id : *active_subdomains)
3339 0 : params.set<std::vector<SubdomainName>>("block").push_back(Moose::stringify(id));
3340 :
3341 0 : logAdd("ScalarVariable", var_name, "MooseVariableScalar", params);
3342 0 : _aux->addVariable("MooseVariableScalar", var_name, params);
3343 0 : if (_displaced_problem)
3344 0 : _displaced_problem->addAuxVariable("MooseVariableScalar", var_name, params);
3345 0 : }
3346 :
3347 : void
3348 70035 : FEProblemBase::addAuxKernel(const std::string & kernel_name,
3349 : const std::string & name,
3350 : InputParameters & parameters)
3351 : {
3352 : parallel_object_only();
3353 :
3354 70035 : setAuxKernelParamsAndLog(kernel_name, name, parameters, "AuxKernel");
3355 :
3356 70035 : _aux->addKernel(kernel_name, name, parameters);
3357 69883 : }
3358 :
3359 : void
3360 537 : FEProblemBase::addAuxScalarKernel(const std::string & kernel_name,
3361 : const std::string & name,
3362 : InputParameters & parameters)
3363 : {
3364 : parallel_object_only();
3365 :
3366 537 : if (_displaced_problem && parameters.get<bool>("use_displaced_mesh"))
3367 : {
3368 0 : parameters.set<SubProblem *>("_subproblem") = _displaced_problem.get();
3369 0 : parameters.set<SystemBase *>("_sys") = &_displaced_problem->auxSys();
3370 : }
3371 : else
3372 : {
3373 537 : if (_displaced_problem == nullptr && parameters.get<bool>("use_displaced_mesh"))
3374 : {
3375 : // We allow AuxScalarKernels to request that they use_displaced_mesh,
3376 : // but then be overridden when no displacements variables are
3377 : // provided in the Mesh block. If that happened, update the value
3378 : // of use_displaced_mesh appropriately for this AuxScalarKernel.
3379 0 : if (parameters.have_parameter<bool>("use_displaced_mesh"))
3380 0 : parameters.set<bool>("use_displaced_mesh") = false;
3381 : }
3382 :
3383 1074 : parameters.set<SubProblem *>("_subproblem") = this;
3384 1611 : parameters.set<SystemBase *>("_sys") = _aux.get();
3385 : }
3386 :
3387 537 : logAdd("AuxScalarKernel", name, kernel_name, parameters);
3388 537 : _aux->addScalarKernel(kernel_name, name, parameters);
3389 533 : }
3390 :
3391 : void
3392 942 : FEProblemBase::addDiracKernel(const std::string & kernel_name,
3393 : const std::string & name,
3394 : InputParameters & parameters)
3395 : {
3396 : parallel_object_only();
3397 :
3398 1884 : const auto nl_sys_num = determineSolverSystem(parameters.varName("variable", name), true).second;
3399 938 : if (!isSolverSystemNonlinear(nl_sys_num))
3400 0 : mooseError("You are trying to add a DiracKernel to a linear variable/system, which is not "
3401 : "supported at the moment!");
3402 :
3403 938 : if (_displaced_problem && parameters.get<bool>("use_displaced_mesh"))
3404 : {
3405 26 : parameters.set<SubProblem *>("_subproblem") = _displaced_problem.get();
3406 26 : parameters.set<SystemBase *>("_sys") = &_displaced_problem->solverSys(nl_sys_num);
3407 13 : _reinit_displaced_elem = true;
3408 : }
3409 : else
3410 : {
3411 925 : if (_displaced_problem == nullptr && parameters.get<bool>("use_displaced_mesh"))
3412 : {
3413 : // We allow DiracKernels to request that they use_displaced_mesh,
3414 : // but then be overridden when no displacements variables are
3415 : // provided in the Mesh block. If that happened, update the value
3416 : // of use_displaced_mesh appropriately for this DiracKernel.
3417 0 : if (parameters.have_parameter<bool>("use_displaced_mesh"))
3418 0 : parameters.set<bool>("use_displaced_mesh") = false;
3419 : }
3420 :
3421 1850 : parameters.set<SubProblem *>("_subproblem") = this;
3422 2775 : parameters.set<SystemBase *>("_sys") = _nl[nl_sys_num].get();
3423 : }
3424 :
3425 938 : logAdd("DiracKernel", name, kernel_name, parameters);
3426 938 : _nl[nl_sys_num]->addDiracKernel(kernel_name, name, parameters);
3427 930 : }
3428 :
3429 : // DGKernels ////
3430 :
3431 : void
3432 1453 : FEProblemBase::addDGKernel(const std::string & dg_kernel_name,
3433 : const std::string & name,
3434 : InputParameters & parameters)
3435 : {
3436 : parallel_object_only();
3437 :
3438 2906 : const auto nl_sys_num = determineSolverSystem(parameters.varName("variable", name), true).second;
3439 1449 : if (!isSolverSystemNonlinear(nl_sys_num))
3440 0 : mooseError("You are trying to add a DGKernel to a linear variable/system, which is not "
3441 : "supported at the moment!");
3442 :
3443 1449 : if (_displaced_problem && parameters.get<bool>("use_displaced_mesh"))
3444 : {
3445 52 : parameters.set<SubProblem *>("_subproblem") = _displaced_problem.get();
3446 52 : parameters.set<SystemBase *>("_sys") = &_displaced_problem->solverSys(nl_sys_num);
3447 26 : _reinit_displaced_neighbor = true;
3448 : }
3449 : else
3450 : {
3451 1423 : if (_displaced_problem == nullptr && parameters.get<bool>("use_displaced_mesh"))
3452 : {
3453 : // We allow DGKernels to request that they use_displaced_mesh,
3454 : // but then be overridden when no displacements variables are
3455 : // provided in the Mesh block. If that happened, update the value
3456 : // of use_displaced_mesh appropriately for this DGKernel.
3457 0 : if (parameters.have_parameter<bool>("use_displaced_mesh"))
3458 0 : parameters.set<bool>("use_displaced_mesh") = false;
3459 : }
3460 :
3461 2846 : parameters.set<SubProblem *>("_subproblem") = this;
3462 4269 : parameters.set<SystemBase *>("_sys") = _nl[nl_sys_num].get();
3463 : }
3464 :
3465 1449 : logAdd("DGKernel", name, dg_kernel_name, parameters);
3466 1449 : _nl[nl_sys_num]->addDGKernel(dg_kernel_name, name, parameters);
3467 :
3468 1449 : _has_internal_edge_residual_objects = true;
3469 1449 : }
3470 :
3471 : void
3472 9122 : FEProblemBase::addFVKernel(const std::string & fv_kernel_name,
3473 : const std::string & name,
3474 : InputParameters & parameters)
3475 : {
3476 9122 : if (_displaced_problem && parameters.get<bool>("use_displaced_mesh"))
3477 : // FVElementalKernels are computed in the historically finite element threaded loops. They rely
3478 : // on Assembly data like _current_elem. When we call reinit on the FEProblemBase we will only
3479 : // reinit the DisplacedProblem and its associated Assembly objects if we mark this boolean as
3480 : // true
3481 0 : _reinit_displaced_elem = true;
3482 9122 : addObject<FVKernel>(fv_kernel_name, name, parameters);
3483 9114 : }
3484 :
3485 : void
3486 7779 : FEProblemBase::addFVBC(const std::string & fv_bc_name,
3487 : const std::string & name,
3488 : InputParameters & parameters)
3489 : {
3490 7779 : addObject<FVBoundaryCondition>(fv_bc_name, name, parameters);
3491 7779 : }
3492 :
3493 : void
3494 327 : FEProblemBase::addFVInterfaceKernel(const std::string & fv_ik_name,
3495 : const std::string & name,
3496 : InputParameters & parameters)
3497 : {
3498 : /// We assume that variable1 and variable2 can live on different systems, in this case
3499 : /// the user needs to create two interface kernels with flipped variables and parameters
3500 327 : addObject<FVInterfaceKernel>(
3501 : fv_ik_name, name, parameters, /*threaded=*/true, /*variable_param_name=*/"variable1");
3502 315 : }
3503 :
3504 : void
3505 3295 : FEProblemBase::addLinearFVKernel(const std::string & kernel_name,
3506 : const std::string & name,
3507 : InputParameters & parameters)
3508 : {
3509 3295 : addObject<LinearFVKernel>(kernel_name, name, parameters);
3510 3295 : }
3511 :
3512 : void
3513 2382 : FEProblemBase::addLinearFVBC(const std::string & bc_name,
3514 : const std::string & name,
3515 : InputParameters & parameters)
3516 : {
3517 2382 : addObject<LinearFVBoundaryCondition>(bc_name, name, parameters);
3518 2382 : }
3519 :
3520 : // InterfaceKernels ////
3521 :
3522 : void
3523 919 : FEProblemBase::addInterfaceKernel(const std::string & interface_kernel_name,
3524 : const std::string & name,
3525 : InputParameters & parameters)
3526 : {
3527 : parallel_object_only();
3528 :
3529 1838 : const auto nl_sys_num = determineSolverSystem(parameters.varName("variable", name), true).second;
3530 915 : if (!isSolverSystemNonlinear(nl_sys_num))
3531 0 : mooseError("You are trying to add a InterfaceKernel to a linear variable/system, which is not "
3532 : "supported at the moment!");
3533 :
3534 915 : if (_displaced_problem && parameters.get<bool>("use_displaced_mesh"))
3535 : {
3536 26 : parameters.set<SubProblem *>("_subproblem") = _displaced_problem.get();
3537 26 : parameters.set<SystemBase *>("_sys") = &_displaced_problem->solverSys(nl_sys_num);
3538 13 : _reinit_displaced_neighbor = true;
3539 : }
3540 : else
3541 : {
3542 902 : if (_displaced_problem == nullptr && parameters.get<bool>("use_displaced_mesh"))
3543 : {
3544 : // We allow InterfaceKernels to request that they use_displaced_mesh,
3545 : // but then be overridden when no displacements variables are
3546 : // provided in the Mesh block. If that happened, update the value
3547 : // of use_displaced_mesh appropriately for this InterfaceKernel.
3548 0 : if (parameters.have_parameter<bool>("use_displaced_mesh"))
3549 0 : parameters.set<bool>("use_displaced_mesh") = false;
3550 : }
3551 :
3552 1804 : parameters.set<SubProblem *>("_subproblem") = this;
3553 2706 : parameters.set<SystemBase *>("_sys") = _nl[nl_sys_num].get();
3554 : }
3555 :
3556 915 : logAdd("InterfaceKernel", name, interface_kernel_name, parameters);
3557 915 : _nl[nl_sys_num]->addInterfaceKernel(interface_kernel_name, name, parameters);
3558 :
3559 915 : _has_internal_edge_residual_objects = true;
3560 915 : }
3561 :
3562 : void
3563 34004 : FEProblemBase::checkICRestartError(const std::string & ic_name,
3564 : const std::string & name,
3565 : const VariableName & var_name)
3566 : {
3567 34004 : if (!_allow_ics_during_restart)
3568 : {
3569 33908 : std::string restart_method = "";
3570 33908 : if (_app.isRestarting())
3571 : restart_method =
3572 0 : "a checkpoint restart, by IC object '" + ic_name + "' for variable '" + name + "'";
3573 33908 : else if (_app.getExReaderForRestart())
3574 : {
3575 4 : std::vector<std::string> restarted_vars = _app.getExReaderForRestart()->get_elem_var_names();
3576 4 : const auto nodal_vars = _app.getExReaderForRestart()->get_nodal_var_names();
3577 4 : const auto global_vars = _app.getExReaderForRestart()->get_global_var_names();
3578 4 : restarted_vars.insert(restarted_vars.end(), nodal_vars.begin(), nodal_vars.end());
3579 4 : restarted_vars.insert(restarted_vars.end(), global_vars.begin(), global_vars.end());
3580 :
3581 4 : if (std::find(restarted_vars.begin(), restarted_vars.end(), var_name) != restarted_vars.end())
3582 8 : restart_method = "an Exodus restart, by IC object '" + ic_name + "' for variable '" + name +
3583 4 : "' that is also being restarted";
3584 4 : }
3585 33908 : if (!restart_method.empty())
3586 4 : mooseError(
3587 : "Initial conditions have been specified during ",
3588 : restart_method,
3589 : ".\nThis is only allowed if you specify 'allow_initial_conditions_with_restart' to "
3590 : "the [Problem], as initial conditions can override restarted fields");
3591 33904 : }
3592 34000 : }
3593 :
3594 : void
3595 31148 : FEProblemBase::addInitialCondition(const std::string & ic_name,
3596 : const std::string & name,
3597 : InputParameters & parameters)
3598 : {
3599 : parallel_object_only();
3600 :
3601 : // before we start to mess with the initial condition, we need to check parameters for errors.
3602 31148 : parameters.checkParams(name);
3603 31144 : const std::string & var_name = parameters.get<VariableName>("variable");
3604 :
3605 : // Forbid initial conditions on a restarted problem, as they would override the restart
3606 31144 : checkICRestartError(ic_name, name, var_name);
3607 :
3608 62280 : parameters.set<SubProblem *>("_subproblem") = this;
3609 :
3610 : // field IC
3611 31140 : if (hasVariable(var_name))
3612 : {
3613 61706 : for (THREAD_ID tid = 0; tid < libMesh::n_threads(); ++tid)
3614 : {
3615 32360 : MooseVariableFEBase & var = getVariable(
3616 : tid, var_name, Moose::VarKindType::VAR_ANY, Moose::VarFieldType::VAR_FIELD_ANY);
3617 64720 : parameters.set<SystemBase *>("_sys") = &var.sys();
3618 32360 : std::shared_ptr<InitialConditionBase> ic;
3619 32360 : if (dynamic_cast<MooseVariable *>(&var))
3620 29752 : ic = _factory.create<InitialCondition>(ic_name, name, parameters, tid);
3621 2608 : else if (dynamic_cast<VectorMooseVariable *>(&var))
3622 272 : ic = _factory.create<VectorInitialCondition>(ic_name, name, parameters, tid);
3623 2336 : else if (dynamic_cast<ArrayMooseVariable *>(&var))
3624 1314 : ic = _factory.create<ArrayInitialCondition>(ic_name, name, parameters, tid);
3625 1022 : else if (dynamic_cast<MooseVariableFVReal *>(&var))
3626 1022 : ic = _factory.create<InitialCondition>(ic_name, name, parameters, tid);
3627 0 : else if (dynamic_cast<MooseLinearVariableFVReal *>(&var))
3628 0 : ic = _factory.create<InitialCondition>(ic_name, name, parameters, tid);
3629 : else
3630 0 : mooseError("Your FE variable in initial condition ",
3631 : name,
3632 : " must be either of scalar or vector type");
3633 32332 : logAdd("IC", name, ic_name, parameters);
3634 32332 : _ics.addObject(ic, tid);
3635 32312 : }
3636 : }
3637 :
3638 : // scalar IC
3639 1746 : else if (hasScalarVariable(var_name))
3640 : {
3641 1746 : MooseVariableScalar & var = getScalarVariable(0, var_name);
3642 3492 : parameters.set<SystemBase *>("_sys") = &var.sys();
3643 : std::shared_ptr<ScalarInitialCondition> ic =
3644 1746 : _factory.create<ScalarInitialCondition>(ic_name, name, parameters);
3645 1746 : logAdd("ScalarIC", name, ic_name, parameters);
3646 1746 : _scalar_ics.addObject(ic);
3647 1746 : }
3648 :
3649 : else
3650 0 : mooseError(
3651 : "Variable '", var_name, "' requested in initial condition '", name, "' does not exist.");
3652 31092 : }
3653 :
3654 : void
3655 2860 : FEProblemBase::addFVInitialCondition(const std::string & ic_name,
3656 : const std::string & name,
3657 : InputParameters & parameters)
3658 : {
3659 : parallel_object_only();
3660 :
3661 : // before we start to mess with the initial condition, we need to check parameters for errors.
3662 2860 : parameters.checkParams(name);
3663 2860 : const std::string & var_name = parameters.get<VariableName>("variable");
3664 :
3665 : // Forbid initial conditions on a restarted problem, as they would override the restart
3666 2860 : checkICRestartError(ic_name, name, var_name);
3667 :
3668 5720 : parameters.set<SubProblem *>("_subproblem") = this;
3669 :
3670 : // field IC
3671 2860 : if (hasVariable(var_name))
3672 : {
3673 5802 : for (THREAD_ID tid = 0; tid < libMesh::n_threads(); ++tid)
3674 : {
3675 2942 : auto & var = getVariable(
3676 : tid, var_name, Moose::VarKindType::VAR_ANY, Moose::VarFieldType::VAR_FIELD_ANY);
3677 5884 : parameters.set<SystemBase *>("_sys") = &var.sys();
3678 2942 : std::shared_ptr<FVInitialConditionBase> ic;
3679 2942 : if (var.isFV())
3680 2942 : ic = _factory.create<FVInitialCondition>(ic_name, name, parameters, tid);
3681 : else
3682 0 : mooseError(
3683 : "Your variable for an FVInitialCondition needs to be an a finite volume variable!");
3684 2942 : _fv_ics.addObject(ic, tid);
3685 2942 : }
3686 : }
3687 : else
3688 0 : mooseError("Variable '",
3689 : var_name,
3690 : "' requested in finite volume initial condition '",
3691 : name,
3692 : "' does not exist.");
3693 2860 : }
3694 :
3695 : void
3696 58879 : FEProblemBase::projectSolution()
3697 : {
3698 294395 : TIME_SECTION("projectSolution", 2, "Projecting Initial Solutions")
3699 :
3700 58879 : FloatingPointExceptionGuard fpe_guard(_app);
3701 :
3702 58879 : ConstElemRange & elem_range = *_mesh.getActiveLocalElementRange();
3703 58879 : ComputeInitialConditionThread cic(*this);
3704 58879 : Threads::parallel_reduce(elem_range, cic);
3705 :
3706 58871 : if (haveFV())
3707 : {
3708 : using ElemInfoRange = StoredRange<MooseMesh::const_elem_info_iterator, const ElemInfo *>;
3709 5226 : ElemInfoRange elem_info_range(_mesh.ownedElemInfoBegin(), _mesh.ownedElemInfoEnd());
3710 :
3711 5226 : ComputeFVInitialConditionThread cfvic(*this);
3712 5226 : Threads::parallel_reduce(elem_info_range, cfvic);
3713 5226 : }
3714 :
3715 : // Need to close the solution vector here so that boundary ICs take precendence
3716 116673 : for (auto & nl : _nl)
3717 57802 : nl->solution().close();
3718 58871 : _aux->solution().close();
3719 :
3720 : // now run boundary-restricted initial conditions
3721 58871 : ConstBndNodeRange & bnd_nodes = *_mesh.getBoundaryNodeRange();
3722 58871 : ComputeBoundaryInitialConditionThread cbic(*this);
3723 58871 : Threads::parallel_reduce(bnd_nodes, cbic);
3724 :
3725 116673 : for (auto & nl : _nl)
3726 57802 : nl->solution().close();
3727 58871 : _aux->solution().close();
3728 :
3729 : // Also, load values into the SCALAR dofs
3730 : // Note: We assume that all SCALAR dofs are on the
3731 : // processor with highest ID
3732 58871 : if (processor_id() == (n_processors() - 1) && _scalar_ics.hasActiveObjects())
3733 : {
3734 678 : const auto & ics = _scalar_ics.getActiveObjects();
3735 1864 : for (const auto & ic : ics)
3736 : {
3737 1186 : MooseVariableScalar & var = ic->variable();
3738 1186 : var.reinit();
3739 :
3740 1186 : DenseVector<Number> vals(var.order());
3741 1186 : ic->compute(vals);
3742 :
3743 1186 : const unsigned int n_scalar_dofs = var.dofIndices().size();
3744 2757 : for (unsigned int i = 0; i < n_scalar_dofs; i++)
3745 : {
3746 1571 : const auto global_index = var.dofIndices()[i];
3747 1571 : var.sys().solution().set(global_index, vals(i));
3748 1571 : var.setValue(i, vals(i));
3749 : }
3750 1186 : }
3751 : }
3752 :
3753 117999 : for (auto & sys : _solver_systems)
3754 : {
3755 59128 : sys->solution().close();
3756 59128 : sys->solution().localize(*sys->system().current_local_solution, sys->dofMap().get_send_list());
3757 : }
3758 :
3759 58871 : _aux->solution().close();
3760 58871 : _aux->solution().localize(*_aux->sys().current_local_solution, _aux->dofMap().get_send_list());
3761 58871 : }
3762 :
3763 : void
3764 2191 : FEProblemBase::projectInitialConditionOnCustomRange(
3765 : ConstElemRange & elem_range,
3766 : ConstBndNodeRange & bnd_nodes,
3767 : const std::optional<std::set<VariableName>> & target_vars)
3768 : {
3769 2191 : if (target_vars)
3770 : {
3771 2191 : ComputeInitialConditionThread cic(*this, &(*target_vars));
3772 2191 : Threads::parallel_reduce(elem_range, cic);
3773 : }
3774 : else
3775 : {
3776 0 : ComputeInitialConditionThread cic(*this);
3777 0 : Threads::parallel_reduce(elem_range, cic);
3778 : }
3779 :
3780 : // Need to close the solution vector here so that boundary ICs take precendence
3781 4382 : for (auto & nl : _nl)
3782 2191 : nl->solution().close();
3783 2191 : _aux->solution().close();
3784 :
3785 2191 : if (target_vars)
3786 : {
3787 2191 : ComputeBoundaryInitialConditionThread cbic(*this, &(*target_vars));
3788 2191 : Threads::parallel_reduce(bnd_nodes, cbic);
3789 2191 : }
3790 : else
3791 : {
3792 0 : ComputeBoundaryInitialConditionThread cbic(*this);
3793 0 : Threads::parallel_reduce(bnd_nodes, cbic);
3794 0 : }
3795 :
3796 4382 : for (auto & nl : _nl)
3797 2191 : nl->solution().close();
3798 2191 : _aux->solution().close();
3799 :
3800 : // Also, load values into the SCALAR dofs
3801 : // Note: We assume that all SCALAR dofs are on the
3802 : // processor with highest ID
3803 2191 : if (processor_id() == (n_processors() - 1) && _scalar_ics.hasActiveObjects())
3804 : {
3805 0 : const auto & ics = _scalar_ics.getActiveObjects();
3806 0 : for (const auto & ic : ics)
3807 : {
3808 0 : MooseVariableScalar & var = ic->variable();
3809 :
3810 0 : if (target_vars && !target_vars->count(var.name()))
3811 0 : continue;
3812 :
3813 0 : var.reinit();
3814 :
3815 0 : DenseVector<Number> vals(var.order());
3816 0 : ic->compute(vals);
3817 :
3818 0 : const unsigned int n_scalar_dofs = var.dofIndices().size();
3819 0 : for (unsigned int i = 0; i < n_scalar_dofs; i++)
3820 : {
3821 0 : const auto global_index = var.dofIndices()[i];
3822 0 : var.sys().solution().set(global_index, vals(i));
3823 0 : var.setValue(i, vals(i));
3824 : }
3825 0 : }
3826 : }
3827 :
3828 4382 : for (auto & nl : _nl)
3829 : {
3830 2191 : nl->solution().close();
3831 2191 : nl->solution().localize(*nl->system().current_local_solution, nl->dofMap().get_send_list());
3832 : }
3833 :
3834 2191 : _aux->solution().close();
3835 2191 : _aux->solution().localize(*_aux->sys().current_local_solution, _aux->dofMap().get_send_list());
3836 2191 : }
3837 :
3838 : void
3839 765 : FEProblemBase::projectFunctionOnCustomRange(ConstElemRange & elem_range,
3840 : Number (*func)(const Point &,
3841 : const libMesh::Parameters &,
3842 : const std::string &,
3843 : const std::string &),
3844 : Gradient (*func_grad)(const Point &,
3845 : const libMesh::Parameters &,
3846 : const std::string &,
3847 : const std::string &),
3848 : const libMesh::Parameters & params,
3849 : const VariableName & target_var)
3850 : {
3851 : mooseAssert(!Threads::in_threads,
3852 : "We're performing a projection based on data from just the thread 0 variable, so any "
3853 : "modifications to the variable solution must have been thread joined already");
3854 :
3855 765 : const auto & var = getStandardVariable(0, target_var);
3856 765 : const auto var_num = var.number();
3857 765 : const auto sn = systemNumForVariable(target_var);
3858 765 : auto & sys = getSystemBase(sn);
3859 :
3860 : // Let libmesh handle the projection
3861 765 : System & libmesh_sys = getSystem(target_var);
3862 765 : auto temp_vec = libmesh_sys.current_local_solution->zero_clone();
3863 765 : libmesh_sys.project_vector(func, func_grad, params, *temp_vec);
3864 765 : temp_vec->close();
3865 :
3866 : // Get the dof indices to copy
3867 765 : DofMap & dof_map = sys.dofMap();
3868 765 : std::set<dof_id_type> dof_indices;
3869 765 : std::vector<dof_id_type> elem_dof_indices;
3870 :
3871 4853 : for (const auto & elem : elem_range)
3872 : {
3873 4088 : dof_map.dof_indices(elem, elem_dof_indices, var_num);
3874 4088 : dof_indices.insert(elem_dof_indices.begin(), elem_dof_indices.end());
3875 : }
3876 765 : std::vector<dof_id_type> dof_indices_v(dof_indices.begin(), dof_indices.end());
3877 :
3878 : // Copy the projected values into the solution vector
3879 765 : std::vector<Real> dof_vals;
3880 765 : temp_vec->get(dof_indices_v, dof_vals);
3881 : mooseAssert(sys.solution().closed(),
3882 : "The solution should be closed before mapping our projection");
3883 765 : sys.solution().insert(dof_vals, dof_indices_v);
3884 765 : sys.solution().close();
3885 765 : sys.solution().localize(*libmesh_sys.current_local_solution, sys.dofMap().get_send_list());
3886 765 : }
3887 :
3888 : std::shared_ptr<MaterialBase>
3889 276 : FEProblemBase::getMaterial(std::string name,
3890 : Moose::MaterialDataType type,
3891 : const THREAD_ID tid,
3892 : bool no_warn)
3893 : {
3894 276 : switch (type)
3895 : {
3896 70 : case Moose::NEIGHBOR_MATERIAL_DATA:
3897 70 : name += "_neighbor";
3898 70 : break;
3899 70 : case Moose::FACE_MATERIAL_DATA:
3900 70 : name += "_face";
3901 70 : break;
3902 136 : default:
3903 136 : break;
3904 : }
3905 :
3906 276 : std::shared_ptr<MaterialBase> material = _all_materials[type].getActiveObject(name, tid);
3907 716 : if (!no_warn && material->getParam<bool>("compute") && type == Moose::BLOCK_MATERIAL_DATA)
3908 4 : mooseWarning("You are retrieving a Material object (",
3909 4 : material->name(),
3910 : "), but its compute flag is set to true. This indicates that MOOSE is "
3911 : "computing this property which may not be desired and produce un-expected "
3912 : "results.");
3913 :
3914 268 : return material;
3915 : }
3916 :
3917 : MaterialData &
3918 50281414 : FEProblemBase::getMaterialData(Moose::MaterialDataType type,
3919 : const THREAD_ID tid,
3920 : const MooseObject * object) const
3921 : {
3922 50281414 : switch (type)
3923 : {
3924 913859 : case Moose::BLOCK_MATERIAL_DATA:
3925 913859 : if (object)
3926 284569 : _material_props.addConsumer(type, object);
3927 913859 : return _material_props.getMaterialData(tid);
3928 23467711 : case Moose::NEIGHBOR_MATERIAL_DATA:
3929 23467711 : if (object)
3930 26578 : _neighbor_material_props.addConsumer(type, object);
3931 23467711 : return _neighbor_material_props.getMaterialData(tid);
3932 25899844 : case Moose::BOUNDARY_MATERIAL_DATA:
3933 : case Moose::FACE_MATERIAL_DATA:
3934 : case Moose::INTERFACE_MATERIAL_DATA:
3935 25899844 : if (object)
3936 59055 : _bnd_material_props.addConsumer(type, object);
3937 25899844 : return _bnd_material_props.getMaterialData(tid);
3938 : }
3939 :
3940 0 : mooseError("FEProblemBase::getMaterialData(): Invalid MaterialDataType ", type);
3941 : }
3942 :
3943 : const std::set<const MooseObject *> &
3944 0 : FEProblemBase::getMaterialPropertyStorageConsumers(Moose::MaterialDataType type) const
3945 : {
3946 0 : switch (type)
3947 : {
3948 0 : case Moose::BLOCK_MATERIAL_DATA:
3949 0 : return _material_props.getConsumers(type);
3950 0 : case Moose::NEIGHBOR_MATERIAL_DATA:
3951 0 : return _neighbor_material_props.getConsumers(type);
3952 0 : case Moose::BOUNDARY_MATERIAL_DATA:
3953 : case Moose::FACE_MATERIAL_DATA:
3954 : case Moose::INTERFACE_MATERIAL_DATA:
3955 0 : return _bnd_material_props.getConsumers(type);
3956 : }
3957 :
3958 0 : mooseError("FEProblemBase::getMaterialPropertyStorageConsumers(): Invalid MaterialDataType ",
3959 : type);
3960 : }
3961 :
3962 : void
3963 0 : FEProblemBase::setPreserveMatrixSparsityPattern(bool preserve)
3964 : {
3965 0 : if (_ignore_zeros_in_jacobian && preserve)
3966 0 : paramWarning(
3967 : "ignore_zeros_in_jacobian",
3968 : "We likely cannot preserve the sparsity pattern if ignoring zeros in the Jacobian, which "
3969 : "leads to removing those entries from the Jacobian sparsity pattern");
3970 0 : _preserve_matrix_sparsity_pattern = preserve;
3971 0 : }
3972 :
3973 : bool
3974 340938 : FEProblemBase::acceptInvalidSolution() const
3975 : {
3976 681782 : return allowInvalidSolution() || // invalid solutions are always allowed
3977 681782 : !_app.solutionInvalidity().hasInvalidSolutionError(); // if not allowed, check for errors
3978 : }
3979 :
3980 : void
3981 1177 : FEProblemBase::addFunctorMaterial(const std::string & functor_material_name,
3982 : const std::string & name,
3983 : InputParameters & parameters)
3984 : {
3985 : parallel_object_only();
3986 :
3987 1177 : auto add_functor_materials = [&](const auto & parameters, const auto & name)
3988 : {
3989 2437 : for (THREAD_ID tid = 0; tid < libMesh::n_threads(); tid++)
3990 : {
3991 : // Create the general Block/Boundary MaterialBase object
3992 1260 : std::shared_ptr<MaterialBase> material =
3993 1260 : _factory.create<MaterialBase>(functor_material_name, name, parameters, tid);
3994 2520 : logAdd("FunctorMaterial", name, functor_material_name, parameters);
3995 1260 : _all_materials.addObject(material, tid);
3996 1260 : _materials.addObject(material, tid);
3997 : }
3998 1177 : };
3999 :
4000 2354 : parameters.set<SubProblem *>("_subproblem") = this;
4001 1177 : add_functor_materials(parameters, name);
4002 1177 : if (_displaced_problem)
4003 : {
4004 0 : auto disp_params = parameters;
4005 0 : disp_params.set<SubProblem *>("_subproblem") = _displaced_problem.get();
4006 0 : add_functor_materials(disp_params, name + "_displaced");
4007 0 : }
4008 1177 : }
4009 :
4010 : void
4011 13545 : FEProblemBase::addMaterial(const std::string & mat_name,
4012 : const std::string & name,
4013 : InputParameters & parameters)
4014 : {
4015 27090 : addMaterialHelper({&_materials}, mat_name, name, parameters);
4016 13415 : }
4017 :
4018 : void
4019 348 : FEProblemBase::addInterfaceMaterial(const std::string & mat_name,
4020 : const std::string & name,
4021 : InputParameters & parameters)
4022 : {
4023 696 : addMaterialHelper({&_interface_materials}, mat_name, name, parameters);
4024 348 : }
4025 :
4026 : void
4027 14187 : FEProblemBase::addMaterialHelper(std::vector<MaterialWarehouse *> warehouses,
4028 : const std::string & mat_name,
4029 : const std::string & name,
4030 : InputParameters & parameters)
4031 : {
4032 : parallel_object_only();
4033 :
4034 14187 : if (_displaced_problem && parameters.get<bool>("use_displaced_mesh"))
4035 : {
4036 274 : parameters.set<SubProblem *>("_subproblem") = _displaced_problem.get();
4037 137 : _reinit_displaced_elem = _reinit_displaced_face = _reinit_displaced_neighbor = true;
4038 : }
4039 : else
4040 : {
4041 14050 : if (_displaced_problem == nullptr && parameters.get<bool>("use_displaced_mesh"))
4042 : {
4043 : // We allow Materials to request that they use_displaced_mesh,
4044 : // but then be overridden when no displacements variables are
4045 : // provided in the Mesh block. If that happened, update the value
4046 : // of use_displaced_mesh appropriately for this Material.
4047 0 : if (parameters.have_parameter<bool>("use_displaced_mesh"))
4048 0 : parameters.set<bool>("use_displaced_mesh") = false;
4049 : }
4050 :
4051 42150 : parameters.set<SubProblem *>("_subproblem") = this;
4052 : }
4053 :
4054 29441 : for (THREAD_ID tid = 0; tid < libMesh::n_threads(); tid++)
4055 : {
4056 : // Create the general Block/Boundary MaterialBase object
4057 : std::shared_ptr<MaterialBase> material =
4058 15390 : _factory.create<MaterialBase>(mat_name, name, parameters, tid);
4059 15254 : logAdd("Material", name, mat_name, parameters);
4060 30508 : bool discrete = !material->getParam<bool>("compute");
4061 :
4062 : // If the object is boundary restricted or if it is a functor material we do not create the
4063 : // neighbor and face objects
4064 15254 : if (material->boundaryRestricted() || dynamic_cast<FunctorMaterial *>(material.get()))
4065 : {
4066 3429 : _all_materials.addObject(material, tid);
4067 3429 : if (discrete)
4068 5 : _discrete_materials.addObject(material, tid);
4069 : else
4070 6848 : for (auto && warehouse : warehouses)
4071 3424 : warehouse->addObject(material, tid);
4072 : }
4073 :
4074 : // Non-boundary restricted require face and neighbor objects
4075 : else
4076 : {
4077 : // TODO: we only need to do this if we have needs for face materials (e.g.
4078 : // FV, DG, etc.) - but currently we always do it. Figure out how to fix
4079 : // this.
4080 :
4081 : // The name of the object being created, this is changed multiple times as objects are
4082 : // created below
4083 11825 : std::string object_name;
4084 :
4085 : // Create a copy of the supplied parameters to the setting for "_material_data_type" isn't
4086 : // used from a previous tid loop
4087 11825 : InputParameters current_parameters = parameters;
4088 :
4089 : // face material
4090 11825 : current_parameters.set<Moose::MaterialDataType>("_material_data_type") =
4091 : Moose::FACE_MATERIAL_DATA;
4092 11825 : object_name = name + "_face";
4093 : std::shared_ptr<MaterialBase> face_material =
4094 11825 : _factory.create<MaterialBase>(mat_name, object_name, current_parameters, tid);
4095 :
4096 : // neighbor material
4097 23650 : current_parameters.set<Moose::MaterialDataType>("_material_data_type") =
4098 : Moose::NEIGHBOR_MATERIAL_DATA;
4099 11825 : current_parameters.set<bool>("_neighbor") = true;
4100 11825 : object_name = name + "_neighbor";
4101 : std::shared_ptr<MaterialBase> neighbor_material =
4102 11825 : _factory.create<MaterialBase>(mat_name, object_name, current_parameters, tid);
4103 :
4104 : // Store the material objects
4105 11825 : _all_materials.addObjects(material, neighbor_material, face_material, tid);
4106 :
4107 11825 : if (discrete)
4108 80 : _discrete_materials.addObjects(material, neighbor_material, face_material, tid);
4109 : else
4110 23490 : for (auto && warehouse : warehouses)
4111 11745 : warehouse->addObjects(material, neighbor_material, face_material, tid);
4112 :
4113 : // Names of all controllable parameters for this Material object
4114 11825 : const std::string & base = parameters.getBase();
4115 35475 : MooseObjectParameterName name(MooseObjectName(base, material->name()), "*");
4116 : const auto param_names =
4117 11825 : _app.getInputParameterWarehouse().getControllableParameterNames(name);
4118 :
4119 : // Connect parameters of the primary Material object to those on the face and neighbor
4120 : // objects
4121 30009 : for (const auto & p_name : param_names)
4122 : {
4123 36368 : MooseObjectParameterName primary_name(MooseObjectName(base, material->name()),
4124 36368 : p_name.parameter());
4125 36368 : MooseObjectParameterName face_name(MooseObjectName(base, face_material->name()),
4126 36368 : p_name.parameter());
4127 36368 : MooseObjectParameterName neighbor_name(MooseObjectName(base, neighbor_material->name()),
4128 36368 : p_name.parameter());
4129 18184 : _app.getInputParameterWarehouse().addControllableParameterConnection(
4130 : primary_name, face_name, false);
4131 18184 : _app.getInputParameterWarehouse().addControllableParameterConnection(
4132 : primary_name, neighbor_name, false);
4133 18184 : }
4134 11825 : }
4135 15254 : }
4136 14051 : }
4137 :
4138 : void
4139 5606135 : FEProblemBase::prepareMaterials(const std::unordered_set<unsigned int> & consumer_needed_mat_props,
4140 : const SubdomainID blk_id,
4141 : const THREAD_ID tid)
4142 : {
4143 5606135 : std::set<MooseVariableFEBase *> needed_moose_vars;
4144 5606135 : std::unordered_set<unsigned int> needed_mat_props;
4145 :
4146 5606135 : if (_all_materials.hasActiveBlockObjects(blk_id, tid))
4147 : {
4148 678983 : _all_materials.updateVariableDependency(needed_moose_vars, tid);
4149 678983 : _all_materials.updateBlockMatPropDependency(blk_id, needed_mat_props, tid);
4150 : }
4151 :
4152 5606135 : const auto & ids = _mesh.getSubdomainBoundaryIds(blk_id);
4153 25809534 : for (const auto id : ids)
4154 : {
4155 20203399 : _materials.updateBoundaryVariableDependency(id, needed_moose_vars, tid);
4156 20203399 : _materials.updateBoundaryMatPropDependency(id, needed_mat_props, tid);
4157 : }
4158 :
4159 5606135 : const auto & current_active_elemental_moose_variables = getActiveElementalMooseVariables(tid);
4160 5606135 : needed_moose_vars.insert(current_active_elemental_moose_variables.begin(),
4161 : current_active_elemental_moose_variables.end());
4162 :
4163 5606135 : needed_mat_props.insert(consumer_needed_mat_props.begin(), consumer_needed_mat_props.end());
4164 :
4165 5606135 : setActiveElementalMooseVariables(needed_moose_vars, tid);
4166 5606135 : setActiveMaterialProperties(needed_mat_props, tid);
4167 5606135 : }
4168 :
4169 : void
4170 418994220 : FEProblemBase::reinitMaterials(SubdomainID blk_id, const THREAD_ID tid, bool swap_stateful)
4171 : {
4172 418994220 : if (hasActiveMaterialProperties(tid))
4173 : {
4174 20014216 : auto && elem = _assembly[tid][0]->elem();
4175 20014216 : unsigned int n_points = _assembly[tid][0]->qRule()->n_points();
4176 :
4177 20014216 : auto & material_data = _material_props.getMaterialData(tid);
4178 20014216 : material_data.resize(n_points);
4179 :
4180 : // Only swap if requested
4181 20014216 : if (swap_stateful)
4182 20006877 : material_data.swap(*elem);
4183 :
4184 20014216 : if (_discrete_materials.hasActiveBlockObjects(blk_id, tid))
4185 3089 : material_data.reset(_discrete_materials.getActiveBlockObjects(blk_id, tid));
4186 :
4187 20014212 : if (_materials.hasActiveBlockObjects(blk_id, tid))
4188 19984108 : material_data.reinit(_materials.getActiveBlockObjects(blk_id, tid));
4189 : }
4190 418994138 : }
4191 :
4192 : void
4193 8596481 : FEProblemBase::reinitMaterialsFace(const SubdomainID blk_id,
4194 : const THREAD_ID tid,
4195 : const bool swap_stateful,
4196 : const std::deque<MaterialBase *> * const reinit_mats)
4197 : {
4198 : // we reinit more often than needed here because we dont have a way to check whether
4199 : // we need to compute the face materials on a particular (possibly external) face
4200 8596481 : if (hasActiveMaterialProperties(tid))
4201 : {
4202 2896935 : auto && elem = _assembly[tid][0]->elem();
4203 2896935 : unsigned int side = _assembly[tid][0]->side();
4204 2896935 : unsigned int n_points = _assembly[tid][0]->qRuleFace()->n_points();
4205 :
4206 2896935 : auto & bnd_material_data = _bnd_material_props.getMaterialData(tid);
4207 2896935 : bnd_material_data.resize(n_points);
4208 :
4209 2896935 : if (swap_stateful && !bnd_material_data.isSwapped())
4210 2872583 : bnd_material_data.swap(*elem, side);
4211 :
4212 2896935 : if (_discrete_materials[Moose::FACE_MATERIAL_DATA].hasActiveBlockObjects(blk_id, tid))
4213 0 : bnd_material_data.reset(
4214 0 : _discrete_materials[Moose::FACE_MATERIAL_DATA].getActiveBlockObjects(blk_id, tid));
4215 :
4216 2896935 : if (reinit_mats)
4217 24352 : bnd_material_data.reinit(*reinit_mats);
4218 2872583 : else if (_materials[Moose::FACE_MATERIAL_DATA].hasActiveBlockObjects(blk_id, tid))
4219 2872583 : bnd_material_data.reinit(
4220 2872583 : _materials[Moose::FACE_MATERIAL_DATA].getActiveBlockObjects(blk_id, tid));
4221 : }
4222 8596481 : }
4223 :
4224 : void
4225 4346725 : FEProblemBase::reinitMaterialsFaceOnBoundary(const BoundaryID boundary_id,
4226 : const SubdomainID blk_id,
4227 : const THREAD_ID tid,
4228 : const bool swap_stateful,
4229 : const std::deque<MaterialBase *> * const reinit_mats)
4230 : {
4231 4737879 : if (hasActiveMaterialProperties(tid) && (needBoundaryMaterialOnSide(boundary_id, tid) ||
4232 391154 : needInterfaceMaterialOnSide(boundary_id, tid) ||
4233 391154 : needInternalNeighborSideMaterial(blk_id, tid)))
4234 : {
4235 519715 : const auto * const elem = _assembly[tid][0]->elem();
4236 519715 : unsigned int side = _assembly[tid][0]->side();
4237 519715 : unsigned int n_points = _assembly[tid][0]->qRuleFace()->n_points();
4238 :
4239 519715 : auto & bnd_material_data = _bnd_material_props.getMaterialData(tid);
4240 519715 : bnd_material_data.resize(n_points);
4241 :
4242 519715 : if (swap_stateful && !bnd_material_data.isSwapped())
4243 519715 : bnd_material_data.swap(*elem, side);
4244 :
4245 519715 : if (_discrete_materials[Moose::FACE_MATERIAL_DATA].hasActiveBlockObjects(blk_id, tid))
4246 0 : bnd_material_data.reset(
4247 0 : _discrete_materials[Moose::FACE_MATERIAL_DATA].getActiveBlockObjects(blk_id, tid));
4248 :
4249 519715 : if (reinit_mats)
4250 0 : bnd_material_data.reinit(*reinit_mats);
4251 519715 : else if (_materials[Moose::FACE_MATERIAL_DATA].hasActiveBlockObjects(blk_id, tid))
4252 503690 : bnd_material_data.reinit(
4253 503690 : _materials[Moose::FACE_MATERIAL_DATA].getActiveBlockObjects(blk_id, tid));
4254 : }
4255 4346725 : }
4256 :
4257 : void
4258 54438 : FEProblemBase::reinitMaterialsNeighborOnBoundary(
4259 : const BoundaryID boundary_id,
4260 : const SubdomainID blk_id,
4261 : const THREAD_ID tid,
4262 : const bool swap_stateful,
4263 : const std::deque<MaterialBase *> * const reinit_mats)
4264 : {
4265 : // Since objects don't declare whether they need the face or neighbor (side) material properties,
4266 : // we use the same criteria for skipping material property computations as for face material
4267 : // properties This could be a future optimization.
4268 59223 : if (hasActiveMaterialProperties(tid) && (needBoundaryMaterialOnSide(boundary_id, tid) ||
4269 4785 : needInterfaceMaterialOnSide(boundary_id, tid) ||
4270 4785 : needInternalNeighborSideMaterial(blk_id, tid)))
4271 45110 : reinitMaterialsNeighbor(blk_id, tid, swap_stateful, reinit_mats);
4272 54438 : }
4273 :
4274 : void
4275 4596908 : FEProblemBase::reinitMaterialsNeighbor(const SubdomainID blk_id,
4276 : const THREAD_ID tid,
4277 : const bool swap_stateful,
4278 : const std::deque<MaterialBase *> * const reinit_mats)
4279 : {
4280 4596908 : if (hasActiveMaterialProperties(tid))
4281 : {
4282 : // NOTE: this will not work with h-adaptivity
4283 : // lindsayad: why not?
4284 :
4285 1092527 : const Elem * neighbor = _assembly[tid][0]->neighbor();
4286 1092527 : unsigned int neighbor_side = neighbor->which_neighbor_am_i(_assembly[tid][0]->elem());
4287 :
4288 : mooseAssert(neighbor, "neighbor should be non-null");
4289 : mooseAssert(blk_id == neighbor->subdomain_id(),
4290 : "The provided blk_id " << blk_id << " and neighbor subdomain ID "
4291 : << neighbor->subdomain_id() << " do not match.");
4292 :
4293 1092527 : unsigned int n_points = _assembly[tid][0]->qRuleNeighbor()->n_points();
4294 :
4295 1092527 : auto & neighbor_material_data = _neighbor_material_props.getMaterialData(tid);
4296 1092527 : neighbor_material_data.resize(n_points);
4297 :
4298 : // Only swap if requested
4299 1092527 : if (swap_stateful)
4300 1068175 : neighbor_material_data.swap(*neighbor, neighbor_side);
4301 :
4302 1092527 : if (_discrete_materials[Moose::NEIGHBOR_MATERIAL_DATA].hasActiveBlockObjects(blk_id, tid))
4303 0 : neighbor_material_data.reset(
4304 0 : _discrete_materials[Moose::NEIGHBOR_MATERIAL_DATA].getActiveBlockObjects(blk_id, tid));
4305 :
4306 1092527 : if (reinit_mats)
4307 24352 : neighbor_material_data.reinit(*reinit_mats);
4308 1068175 : else if (_materials[Moose::NEIGHBOR_MATERIAL_DATA].hasActiveBlockObjects(blk_id, tid))
4309 1067876 : neighbor_material_data.reinit(
4310 1067876 : _materials[Moose::NEIGHBOR_MATERIAL_DATA].getActiveBlockObjects(blk_id, tid));
4311 : }
4312 4596908 : }
4313 :
4314 : void
4315 4631154 : FEProblemBase::reinitMaterialsBoundary(const BoundaryID boundary_id,
4316 : const THREAD_ID tid,
4317 : const bool swap_stateful,
4318 : const std::deque<MaterialBase *> * const reinit_mats)
4319 : {
4320 4631154 : if (hasActiveMaterialProperties(tid) && needBoundaryMaterialOnSide(boundary_id, tid))
4321 : {
4322 365687 : auto && elem = _assembly[tid][0]->elem();
4323 365687 : unsigned int side = _assembly[tid][0]->side();
4324 365687 : unsigned int n_points = _assembly[tid][0]->qRuleFace()->n_points();
4325 :
4326 365687 : auto & bnd_material_data = _bnd_material_props.getMaterialData(tid);
4327 365687 : bnd_material_data.resize(n_points);
4328 :
4329 365687 : if (swap_stateful && !bnd_material_data.isSwapped())
4330 310985 : bnd_material_data.swap(*elem, side);
4331 :
4332 365687 : if (_discrete_materials.hasActiveBoundaryObjects(boundary_id, tid))
4333 0 : bnd_material_data.reset(_discrete_materials.getActiveBoundaryObjects(boundary_id, tid));
4334 :
4335 365687 : if (reinit_mats)
4336 24352 : bnd_material_data.reinit(*reinit_mats);
4337 341335 : else if (_materials.hasActiveBoundaryObjects(boundary_id, tid))
4338 25963 : bnd_material_data.reinit(_materials.getActiveBoundaryObjects(boundary_id, tid));
4339 : }
4340 4631154 : }
4341 :
4342 : void
4343 57823 : FEProblemBase::reinitMaterialsInterface(BoundaryID boundary_id,
4344 : const THREAD_ID tid,
4345 : bool swap_stateful)
4346 : {
4347 57823 : if (hasActiveMaterialProperties(tid) && needInterfaceMaterialOnSide(boundary_id, tid))
4348 : {
4349 46343 : const Elem * const & elem = _assembly[tid][0]->elem();
4350 46343 : unsigned int side = _assembly[tid][0]->side();
4351 46343 : unsigned int n_points = _assembly[tid][0]->qRuleFace()->n_points();
4352 :
4353 46343 : auto & bnd_material_data = _bnd_material_props.getMaterialData(tid);
4354 46343 : bnd_material_data.resize(n_points);
4355 :
4356 46343 : if (swap_stateful && !bnd_material_data.isSwapped())
4357 44568 : bnd_material_data.swap(*elem, side);
4358 :
4359 46343 : if (_interface_materials.hasActiveBoundaryObjects(boundary_id, tid))
4360 1317 : bnd_material_data.reinit(_interface_materials.getActiveBoundaryObjects(boundary_id, tid));
4361 : }
4362 57823 : }
4363 :
4364 : void
4365 417164404 : FEProblemBase::swapBackMaterials(const THREAD_ID tid)
4366 : {
4367 417164404 : auto && elem = _assembly[tid][0]->elem();
4368 417164404 : _material_props.getMaterialData(tid).swapBack(*elem);
4369 417164404 : }
4370 :
4371 : void
4372 12658758 : FEProblemBase::swapBackMaterialsFace(const THREAD_ID tid)
4373 : {
4374 12658758 : auto && elem = _assembly[tid][0]->elem();
4375 12658758 : unsigned int side = _assembly[tid][0]->side();
4376 12658758 : _bnd_material_props.getMaterialData(tid).swapBack(*elem, side);
4377 12658758 : }
4378 :
4379 : void
4380 4213629 : FEProblemBase::swapBackMaterialsNeighbor(const THREAD_ID tid)
4381 : {
4382 : // NOTE: this will not work with h-adaptivity
4383 4213629 : const Elem * neighbor = _assembly[tid][0]->neighbor();
4384 : unsigned int neighbor_side =
4385 4213629 : neighbor ? neighbor->which_neighbor_am_i(_assembly[tid][0]->elem()) : libMesh::invalid_uint;
4386 :
4387 4213629 : if (!neighbor)
4388 : {
4389 0 : if (haveFV())
4390 : {
4391 : // If neighbor is null, then we're on the neighbor side of a mesh boundary, e.g. we're off
4392 : // the mesh in ghost-land. If we're using the finite volume method, then variable values and
4393 : // consequently material properties have well-defined values in this ghost region outside of
4394 : // the mesh and we really do want to reinit our neighbor materials in this case. Since we're
4395 : // off in ghost land it's safe to do swaps with `MaterialPropertyStorage` using the elem and
4396 : // elem_side keys
4397 0 : neighbor = _assembly[tid][0]->elem();
4398 0 : neighbor_side = _assembly[tid][0]->side();
4399 : mooseAssert(neighbor, "We should have an appropriate value for elem coming from Assembly");
4400 : }
4401 : else
4402 0 : mooseError("neighbor is null in Assembly!");
4403 : }
4404 :
4405 4213629 : _neighbor_material_props.getMaterialData(tid).swapBack(*neighbor, neighbor_side);
4406 4213629 : }
4407 :
4408 : void
4409 1013702 : FEProblemBase::logAdd(const std::string & system,
4410 : const std::string & name,
4411 : const std::string & type,
4412 : const InputParameters & params) const
4413 : {
4414 1013702 : if (_verbose_setup != "false")
4415 19260 : _console << "[DBG] Adding " << system << " '" << name << "' of type " << type << std::endl;
4416 1013702 : if (_verbose_setup == "extra")
4417 0 : _console << params << std::endl;
4418 1013702 : }
4419 :
4420 : void
4421 136102 : FEProblemBase::addObjectParamsHelper(InputParameters & parameters,
4422 : const std::string & object_name,
4423 : const std::string & var_param_name)
4424 : {
4425 : // Due to objects like SolutionUserObject which manipulate libmesh objects
4426 : // and variables directly at the back end, we need a default option here
4427 : // which is going to be the pointer to the first solver system within this
4428 : // problem
4429 136102 : unsigned int sys_num = 0;
4430 136102 : if (parameters.isParamValid(var_param_name))
4431 : {
4432 59518 : const auto variable_name = parameters.varName(var_param_name, object_name);
4433 59518 : if (this->hasVariable(variable_name) || this->hasScalarVariable(variable_name))
4434 57861 : sys_num = getSystem(variable_name).number();
4435 59518 : }
4436 272204 : if (parameters.isParamValid("solver_sys"))
4437 : {
4438 929 : const auto var_sys_num = sys_num;
4439 929 : sys_num = getSystemBase(parameters.get<SolverSystemName>("solver_sys")).number();
4440 929 : if (sys_num != var_sys_num && parameters.isParamValid(var_param_name))
4441 0 : mooseError("We dont support setting 'variable' to a variable that is not set to the same "
4442 : "system as the 'solver_sys' parameter");
4443 : }
4444 :
4445 137385 : if (_displaced_problem && parameters.have_parameter<bool>("use_displaced_mesh") &&
4446 137385 : parameters.get<bool>("use_displaced_mesh"))
4447 : {
4448 1260 : parameters.set<SubProblem *>("_subproblem") = _displaced_problem.get();
4449 630 : if (sys_num == _aux->number())
4450 1197 : parameters.set<SystemBase *>("_sys") = &_displaced_problem->systemBaseAuxiliary();
4451 : else
4452 693 : parameters.set<SystemBase *>("_sys") = &_displaced_problem->solverSys(sys_num);
4453 : }
4454 : else
4455 : {
4456 : // The object requested use_displaced_mesh, but it was overridden
4457 : // due to there being no displacements variables in the [Mesh] block.
4458 : // If that happened, update the value of use_displaced_mesh appropriately.
4459 235123 : if (!_displaced_problem && parameters.have_parameter<bool>("use_displaced_mesh") &&
4460 235123 : parameters.get<bool>("use_displaced_mesh"))
4461 146 : parameters.set<bool>("use_displaced_mesh") = false;
4462 :
4463 270944 : parameters.set<SubProblem *>("_subproblem") = this;
4464 :
4465 135472 : if (sys_num == _aux->number())
4466 38646 : parameters.set<SystemBase *>("_sys") = _aux.get();
4467 : else
4468 367770 : parameters.set<SystemBase *>("_sys") = _solver_systems[sys_num].get();
4469 : }
4470 136102 : }
4471 :
4472 : void
4473 55312 : FEProblemBase::addPostprocessor(const std::string & pp_name,
4474 : const std::string & name,
4475 : InputParameters & parameters)
4476 : {
4477 : // Check for name collision
4478 55312 : if (hasUserObject(name))
4479 4 : mooseError("A ",
4480 4 : getUserObjectBase(name).typeAndName(),
4481 : " already exists. You may not add a Postprocessor by the same name.");
4482 :
4483 55308 : addUserObject(pp_name, name, parameters);
4484 55272 : }
4485 :
4486 : void
4487 5806 : FEProblemBase::addVectorPostprocessor(const std::string & pp_name,
4488 : const std::string & name,
4489 : InputParameters & parameters)
4490 : {
4491 : // Check for name collision
4492 5806 : if (hasUserObject(name))
4493 4 : mooseError("A ",
4494 4 : getUserObjectBase(name).typeAndName(),
4495 : " already exists. You may not add a VectorPostprocessor by the same name.");
4496 :
4497 5802 : addUserObject(pp_name, name, parameters);
4498 5762 : }
4499 :
4500 : void
4501 4916 : FEProblemBase::addReporter(const std::string & type,
4502 : const std::string & name,
4503 : InputParameters & parameters)
4504 : {
4505 : // Check for name collision
4506 4916 : if (hasUserObject(name))
4507 4 : mooseError("A ",
4508 4 : getUserObjectBase(name).typeAndName(),
4509 : " already exists. You may not add a Reporter by the same name.");
4510 :
4511 4912 : addUserObject(type, name, parameters);
4512 4868 : }
4513 :
4514 : std::vector<std::shared_ptr<UserObject>>
4515 80153 : FEProblemBase::addUserObject(const std::string & user_object_name,
4516 : const std::string & name,
4517 : InputParameters & parameters)
4518 : {
4519 : parallel_object_only();
4520 :
4521 80153 : std::vector<std::shared_ptr<UserObject>> uos;
4522 :
4523 : // Add the _subproblem and _sys parameters depending on use_displaced_mesh
4524 80153 : addObjectParamsHelper(parameters, name);
4525 :
4526 127573 : for (const auto tid : make_range(libMesh::n_threads()))
4527 : {
4528 : // Create the UserObject
4529 : std::shared_ptr<UserObject> user_object =
4530 83748 : _factory.create<UserObject>(user_object_name, name, parameters, tid);
4531 83368 : logAdd("UserObject", name, user_object_name, parameters);
4532 83368 : uos.push_back(user_object);
4533 :
4534 83368 : if (tid != 0)
4535 3595 : user_object->setPrimaryThreadCopy(uos[0].get());
4536 :
4537 : // TODO: delete this line after apps have been updated to not call getUserObjects
4538 83368 : _all_user_objects.addObject(user_object, tid);
4539 :
4540 83360 : theWarehouse().add(user_object);
4541 :
4542 : // Attempt to create all the possible UserObject types
4543 83360 : auto euo = std::dynamic_pointer_cast<ElementUserObject>(user_object);
4544 83360 : auto suo = std::dynamic_pointer_cast<SideUserObject>(user_object);
4545 83360 : auto isuo = std::dynamic_pointer_cast<InternalSideUserObject>(user_object);
4546 83360 : auto iuo = std::dynamic_pointer_cast<InterfaceUserObjectBase>(user_object);
4547 83360 : auto nuo = std::dynamic_pointer_cast<NodalUserObject>(user_object);
4548 83360 : auto duo = std::dynamic_pointer_cast<DomainUserObject>(user_object);
4549 83360 : auto guo = std::dynamic_pointer_cast<GeneralUserObject>(user_object);
4550 83360 : auto tguo = std::dynamic_pointer_cast<ThreadedGeneralUserObject>(user_object);
4551 83360 : auto muo = std::dynamic_pointer_cast<MortarUserObject>(user_object);
4552 :
4553 : // Account for displaced mesh use
4554 83360 : if (_displaced_problem && parameters.get<bool>("use_displaced_mesh"))
4555 : {
4556 : // Whether to re-init or not depends on the attributes of the base classes.
4557 : // For example, InterfaceUOBase has "_current_side_elem" and "_neighbor_elem"
4558 : // so it needs to reinit on displaced neighbors and faces
4559 : // _reinit_displaced_elem -> _current_elem will be reinited
4560 : // _reinit_displaced_face -> _current_elem, lowerD if any and _current_side_elem to be
4561 : // reinited _reinit_displaced_neighbor -> _current_elem, lowerD if any and _current_neighbor
4562 : // to be reinited Note that as soon as you use materials on the displaced mesh, all three get
4563 : // turned on.
4564 680 : if (euo || nuo || duo)
4565 606 : _reinit_displaced_elem = true;
4566 680 : if (suo || duo || isuo || iuo)
4567 35 : _reinit_displaced_face = true;
4568 680 : if (iuo || duo || isuo)
4569 0 : _reinit_displaced_neighbor = true;
4570 : }
4571 :
4572 : // These objects only require one thread
4573 83360 : if ((guo && !tguo) || muo)
4574 35940 : break;
4575 406820 : }
4576 :
4577 : // Add as a Functor if it is one. We usually need to add the user object from thread 0 as the
4578 : // registered functor for all threads because when user objects are thread joined, generally only
4579 : // the primary thread copy ends up with all the data
4580 166659 : for (const auto tid : make_range(libMesh::n_threads()))
4581 : {
4582 86894 : const decltype(uos)::size_type uo_index = uos.front()->needThreadedCopy() ? tid : 0;
4583 86894 : if (const auto functor = dynamic_cast<Moose::FunctorBase<Real> *>(uos[uo_index].get()))
4584 : {
4585 65299 : this->addFunctor(name, *functor, tid);
4586 65299 : if (_displaced_problem)
4587 804 : _displaced_problem->addFunctor(name, *functor, tid);
4588 : }
4589 : }
4590 :
4591 79765 : return uos;
4592 16 : }
4593 :
4594 : const UserObject &
4595 330457 : FEProblemBase::getUserObjectBase(const std::string & name, const THREAD_ID tid /* = 0 */) const
4596 : {
4597 330457 : std::vector<UserObject *> objs;
4598 330457 : theWarehouse()
4599 660914 : .query()
4600 330457 : .condition<AttribSystem>("UserObject")
4601 330457 : .condition<AttribThread>(tid)
4602 330457 : .condition<AttribName>(name)
4603 330457 : .queryInto(objs);
4604 330457 : if (objs.empty())
4605 0 : mooseError("Unable to find user object with name '" + name + "'");
4606 : mooseAssert(objs.size() == 1, "Should only find one UO");
4607 660914 : return *(objs[0]);
4608 330457 : }
4609 :
4610 : const Positions &
4611 1154 : FEProblemBase::getPositionsObject(const std::string & name) const
4612 : {
4613 1154 : std::vector<Positions *> objs;
4614 1154 : theWarehouse()
4615 2308 : .query()
4616 1154 : .condition<AttribSystem>("UserObject")
4617 1154 : .condition<AttribName>(name)
4618 1154 : .queryInto(objs);
4619 1154 : if (objs.empty())
4620 0 : mooseError("Unable to find Positions object with name '" + name + "'");
4621 : mooseAssert(objs.size() == 1, "Should only find one Positions");
4622 2308 : return *(objs[0]);
4623 1154 : }
4624 :
4625 : bool
4626 93816 : FEProblemBase::hasUserObject(const std::string & name) const
4627 : {
4628 93816 : std::vector<UserObject *> objs;
4629 93816 : theWarehouse()
4630 93816 : .query()
4631 93816 : .condition<AttribSystem>("UserObject")
4632 187632 : .condition<AttribThread>(0)
4633 93816 : .condition<AttribName>(name)
4634 93816 : .queryInto(objs);
4635 187632 : return !objs.empty();
4636 93816 : }
4637 :
4638 : bool
4639 477 : FEProblemBase::hasPostprocessorValueByName(const PostprocessorName & name) const
4640 : {
4641 477 : return _reporter_data.hasReporterValue<PostprocessorValue>(PostprocessorReporterName(name));
4642 : }
4643 :
4644 : const PostprocessorValue &
4645 911895 : FEProblemBase::getPostprocessorValueByName(const PostprocessorName & name,
4646 : std::size_t t_index) const
4647 : {
4648 1823790 : return _reporter_data.getReporterValue<PostprocessorValue>(PostprocessorReporterName(name),
4649 1823790 : t_index);
4650 : }
4651 :
4652 : void
4653 602836 : FEProblemBase::setPostprocessorValueByName(const PostprocessorName & name,
4654 : const PostprocessorValue & value,
4655 : std::size_t t_index)
4656 : {
4657 602836 : _reporter_data.setReporterValue<PostprocessorValue>(
4658 1205672 : PostprocessorReporterName(name), value, t_index);
4659 602836 : }
4660 :
4661 : bool
4662 56 : FEProblemBase::hasPostprocessor(const std::string & name) const
4663 : {
4664 56 : mooseDeprecated("FEProblemBase::hasPostprocssor is being removed; use "
4665 : "hasPostprocessorValueByName instead.");
4666 56 : return hasPostprocessorValueByName(name);
4667 : }
4668 :
4669 : const VectorPostprocessorValue &
4670 57 : FEProblemBase::getVectorPostprocessorValueByName(const std::string & object_name,
4671 : const std::string & vector_name,
4672 : std::size_t t_index) const
4673 : {
4674 57 : return _reporter_data.getReporterValue<VectorPostprocessorValue>(
4675 114 : VectorPostprocessorReporterName(object_name, vector_name), t_index);
4676 : }
4677 :
4678 : void
4679 20 : FEProblemBase::setVectorPostprocessorValueByName(const std::string & object_name,
4680 : const std::string & vector_name,
4681 : const VectorPostprocessorValue & value,
4682 : std::size_t t_index)
4683 : {
4684 20 : _reporter_data.setReporterValue<VectorPostprocessorValue>(
4685 40 : VectorPostprocessorReporterName(object_name, vector_name), value, t_index);
4686 20 : }
4687 :
4688 : const VectorPostprocessor &
4689 9268 : FEProblemBase::getVectorPostprocessorObjectByName(const std::string & object_name,
4690 : const THREAD_ID tid) const
4691 : {
4692 9268 : return getUserObject<VectorPostprocessor>(object_name, tid);
4693 : }
4694 :
4695 : void
4696 77 : FEProblemBase::parentOutputPositionChanged()
4697 : {
4698 2156 : for (const auto & it : _multi_apps)
4699 : {
4700 2079 : const auto & objects = it.second.getActiveObjects();
4701 2100 : for (const auto & obj : objects)
4702 21 : obj->parentOutputPositionChanged();
4703 : }
4704 77 : }
4705 :
4706 : void
4707 0 : FEProblemBase::computeIndicatorsAndMarkers()
4708 : {
4709 0 : computeIndicators();
4710 0 : computeMarkers();
4711 0 : }
4712 :
4713 : void
4714 240900 : FEProblemBase::computeIndicators()
4715 : {
4716 : // Initialize indicator aux variable fields
4717 240900 : if (_indicators.hasActiveObjects() || _internal_side_indicators.hasActiveObjects())
4718 : {
4719 12880 : TIME_SECTION("computeIndicators", 1, "Computing Indicators");
4720 :
4721 : // Internal side indicators may lead to creating a much larger sparsity pattern than dictated by
4722 : // the actual finite element scheme (e.g. CFEM)
4723 2576 : const auto old_do_derivatives = ADReal::do_derivatives;
4724 2576 : ADReal::do_derivatives = false;
4725 :
4726 2576 : std::vector<std::string> fields;
4727 :
4728 : // Indicator Fields
4729 2576 : const auto & indicators = _indicators.getActiveObjects();
4730 2736 : for (const auto & indicator : indicators)
4731 160 : fields.push_back(indicator->name());
4732 :
4733 : // InternalSideIndicator Fields
4734 2576 : const auto & internal_indicators = _internal_side_indicators.getActiveObjects();
4735 5056 : for (const auto & internal_indicator : internal_indicators)
4736 2480 : fields.push_back(internal_indicator->name());
4737 :
4738 2576 : _aux->zeroVariables(fields);
4739 :
4740 : // compute Indicators
4741 2576 : ComputeIndicatorThread cit(*this);
4742 2576 : Threads::parallel_reduce(*_mesh.getActiveLocalElementRange(), cit);
4743 2576 : _aux->solution().close();
4744 2576 : _aux->update();
4745 :
4746 2576 : ComputeIndicatorThread finalize_cit(*this, true);
4747 2576 : Threads::parallel_reduce(*_mesh.getActiveLocalElementRange(), finalize_cit);
4748 2576 : _aux->solution().close();
4749 2576 : _aux->update();
4750 :
4751 2576 : ADReal::do_derivatives = old_do_derivatives;
4752 2576 : }
4753 240900 : }
4754 :
4755 : void
4756 240924 : FEProblemBase::computeMarkers()
4757 : {
4758 240924 : if (_markers.hasActiveObjects())
4759 : {
4760 35360 : TIME_SECTION("computeMarkers", 1, "Computing Markers");
4761 :
4762 7072 : std::vector<std::string> fields;
4763 :
4764 : // Marker Fields
4765 7072 : const auto & markers = _markers.getActiveObjects();
4766 15122 : for (const auto & marker : markers)
4767 8050 : fields.push_back(marker->name());
4768 :
4769 7072 : _aux->zeroVariables(fields);
4770 :
4771 7072 : _adaptivity.updateErrorVectors();
4772 :
4773 14764 : for (THREAD_ID tid = 0; tid < libMesh::n_threads(); ++tid)
4774 : {
4775 7696 : const auto & markers = _markers.getActiveObjects(tid);
4776 16453 : for (const auto & marker : markers)
4777 8761 : marker->markerSetup();
4778 : }
4779 :
4780 7068 : ComputeMarkerThread cmt(*this);
4781 7068 : Threads::parallel_reduce(*_mesh.getActiveLocalElementRange(), cmt);
4782 :
4783 7068 : _aux->solution().close();
4784 7068 : _aux->update();
4785 7068 : }
4786 240920 : }
4787 :
4788 : const ExecFlagType &
4789 2751417 : FEProblemBase::getCurrentExecuteOnFlag() const
4790 : {
4791 2751417 : return _current_execute_on_flag;
4792 : }
4793 :
4794 : void
4795 7505580 : FEProblemBase::setCurrentExecuteOnFlag(const ExecFlagType & flag)
4796 : {
4797 7505580 : _current_execute_on_flag = flag;
4798 7505580 : }
4799 :
4800 : void
4801 80 : FEProblemBase::executeAllObjects(const ExecFlagType & /*exec_type*/)
4802 : {
4803 80 : }
4804 :
4805 : void
4806 1925056 : FEProblemBase::customSetup(const ExecFlagType & exec_type)
4807 : {
4808 1925056 : SubProblem::customSetup(exec_type);
4809 :
4810 1925056 : if (_line_search)
4811 0 : _line_search->customSetup(exec_type);
4812 :
4813 1925056 : unsigned int n_threads = libMesh::n_threads();
4814 4022271 : for (THREAD_ID tid = 0; tid < n_threads; tid++)
4815 : {
4816 2097215 : _all_materials.customSetup(exec_type, tid);
4817 2097215 : _functions.customSetup(exec_type, tid);
4818 : }
4819 :
4820 : #ifdef MOOSE_KOKKOS_ENABLED
4821 1268382 : _kokkos_functions.customSetup(exec_type);
4822 : #endif
4823 :
4824 1925056 : _aux->customSetup(exec_type);
4825 3880718 : for (auto & nl : _nl)
4826 1955662 : nl->customSetup(exec_type);
4827 :
4828 1925056 : if (_displaced_problem)
4829 158920 : _displaced_problem->customSetup(exec_type);
4830 :
4831 4022271 : for (THREAD_ID tid = 0; tid < n_threads; tid++)
4832 : {
4833 2097215 : _internal_side_indicators.customSetup(exec_type, tid);
4834 2097215 : _indicators.customSetup(exec_type, tid);
4835 2097215 : _markers.customSetup(exec_type, tid);
4836 : }
4837 :
4838 1925056 : std::vector<UserObject *> userobjs;
4839 1925056 : theWarehouse().query().condition<AttribSystem>("UserObject").queryIntoUnsorted(userobjs);
4840 4778324 : for (auto obj : userobjs)
4841 2853268 : obj->customSetup(exec_type);
4842 :
4843 1925056 : _app.getOutputWarehouse().customSetup(exec_type);
4844 1925056 : }
4845 :
4846 : void
4847 2324794 : FEProblemBase::execute(const ExecFlagType & exec_type)
4848 : {
4849 : // Set the current flag
4850 2324794 : setCurrentExecuteOnFlag(exec_type);
4851 :
4852 2324794 : if (exec_type != EXEC_INITIAL)
4853 2266943 : executeControls(exec_type);
4854 :
4855 : // intentially call this after executing controls because the setups may rely on the controls
4856 : // FIXME: we skip the following flags because they have dedicated setup functions in
4857 : // SetupInterface and it may not be appropriate to call them here.
4858 4252546 : if (!(exec_type == EXEC_INITIAL || exec_type == EXEC_TIMESTEP_BEGIN ||
4859 1927776 : exec_type == EXEC_SUBDOMAIN || exec_type == EXEC_NONLINEAR || exec_type == EXEC_LINEAR))
4860 1925056 : customSetup(exec_type);
4861 :
4862 : // Samplers; EXEC_INITIAL is not called because the Sampler::init() method that is called after
4863 : // construction makes the first Sampler::execute() call. This ensures that the random number
4864 : // generator object is the correct state prior to any other object (e.g., Transfers) attempts to
4865 : // extract data from the Sampler. That is, if the Sampler::execute() call is delayed to here
4866 : // then it is not in the correct state for other objects.
4867 2324770 : if (exec_type != EXEC_INITIAL)
4868 2266919 : executeSamplers(exec_type);
4869 :
4870 : // Pre-aux UserObjects
4871 2324738 : computeUserObjects(exec_type, Moose::PRE_AUX);
4872 :
4873 : // Systems (includes system time derivative and aux kernel calculations)
4874 2324738 : computeSystems(exec_type);
4875 : // With the auxiliary system solution computed, sync the displaced problem auxiliary solution
4876 : // before computation of post-aux user objects. The undisplaced auxiliary system current local
4877 : // solution is updated (via System::update) within the AuxiliarySystem class's variable
4878 : // computation methods (e.g. computeElementalVarsHelper, computeNodalVarsHelper), so it is safe to
4879 : // use it here
4880 2324693 : if (_displaced_problem)
4881 196607 : _displaced_problem->syncAuxSolution(*getAuxiliarySystem().currentSolution());
4882 :
4883 : // Post-aux UserObjects
4884 2324693 : computeUserObjects(exec_type, Moose::POST_AUX);
4885 :
4886 : // Return the current flag to None
4887 2324576 : setCurrentExecuteOnFlag(EXEC_NONE);
4888 :
4889 2324576 : if (_uo_aux_state_check && !_checking_uo_aux_state)
4890 : {
4891 : // we will only check aux variables and postprocessors
4892 : // checking more reporter data can be added in the future if needed
4893 624 : std::unique_ptr<NumericVector<Number>> x = _aux->currentSolution()->clone();
4894 624 : DenseVector<Real> pp_values = getReporterData().getAllRealReporterValues();
4895 :
4896 : // call THIS execute one more time for checking the possible states
4897 624 : _checking_uo_aux_state = true;
4898 624 : FEProblemBase::execute(exec_type);
4899 624 : _checking_uo_aux_state = false;
4900 :
4901 624 : const Real check_tol = 1e-8;
4902 :
4903 624 : const Real xnorm = x->l2_norm();
4904 624 : *x -= *_aux->currentSolution();
4905 624 : if (x->l2_norm() > check_tol * xnorm)
4906 : {
4907 4 : const auto & sys = _aux->system();
4908 4 : const unsigned int n_vars = sys.n_vars();
4909 4 : std::multimap<Real, std::string, std::greater<Real>> ordered_map;
4910 20 : for (const auto i : make_range(n_vars))
4911 : {
4912 16 : const Real vnorm = sys.calculate_norm(*x, i, DISCRETE_L2);
4913 16 : ordered_map.emplace(vnorm, sys.variable_name(i));
4914 : }
4915 :
4916 4 : std::ostringstream oss;
4917 20 : for (const auto & [error_norm, var_name] : ordered_map)
4918 16 : oss << " {" << var_name << ", " << error_norm << "},\n";
4919 :
4920 4 : mooseError("Aux kernels, user objects appear to have states for aux variables on ",
4921 : exec_type,
4922 : ".\nVariable error norms in descending order:\n",
4923 4 : oss.str());
4924 0 : }
4925 :
4926 620 : const DenseVector<Real> new_pp_values = getReporterData().getAllRealReporterValues();
4927 620 : if (pp_values.size() != new_pp_values.size())
4928 0 : mooseError("Second execution for uo/aux state check should not change the number of "
4929 : "real reporter values");
4930 :
4931 620 : const Real ppnorm = pp_values.l2_norm();
4932 620 : pp_values -= new_pp_values;
4933 620 : if (pp_values.l2_norm() > check_tol * ppnorm)
4934 : {
4935 4 : const auto pp_names = getReporterData().getAllRealReporterFullNames();
4936 4 : std::multimap<Real, std::string, std::greater<Real>> ordered_map;
4937 16 : for (const auto i : index_range(pp_names))
4938 12 : ordered_map.emplace(std::abs(pp_values(i)), pp_names[i]);
4939 :
4940 4 : std::ostringstream oss;
4941 16 : for (const auto & [error_norm, pp_name] : ordered_map)
4942 12 : oss << " {" << pp_name << ", " << error_norm << "},\n";
4943 :
4944 4 : mooseError("Aux kernels, user objects appear to have states for real reporter values on ",
4945 : exec_type,
4946 : ".\nErrors of real reporter values in descending order:\n",
4947 4 : oss.str());
4948 0 : }
4949 616 : }
4950 2324568 : }
4951 :
4952 : // Finalize, threadJoin, and update PP values of Elemental/Nodal/Side/InternalSideUserObjects
4953 : void
4954 1428812 : FEProblemBase::joinAndFinalize(TheWarehouse::Query query, bool isgen)
4955 : {
4956 1428812 : std::vector<UserObject *> objs;
4957 1428812 : query.queryInto(objs);
4958 1428812 : if (!isgen)
4959 : {
4960 : // join all threaded user objects (i.e. not regular general user objects) to the primary
4961 : // thread
4962 1511977 : for (auto obj : objs)
4963 392484 : if (obj->primaryThreadCopy())
4964 29195 : obj->primaryThreadCopy()->threadJoin(*obj);
4965 : }
4966 :
4967 1428812 : query.condition<AttribThread>(0).queryInto(objs);
4968 :
4969 : // finalize objects and retrieve/store any postprocessor values
4970 2036466 : for (auto obj : objs)
4971 : {
4972 607763 : if (isgen && dynamic_cast<ThreadedGeneralUserObject *>(obj))
4973 116 : continue;
4974 607647 : if (isgen)
4975 : {
4976 : // general user objects are not run in their own threaded loop object - so run them here
4977 244358 : if (shouldPrintExecution(0))
4978 798 : _console << "[DBG] Initializing, executing & finalizing general UO '" << obj->name()
4979 798 : << "' on " << _current_execute_on_flag.name() << std::endl;
4980 244358 : obj->initialize();
4981 244358 : obj->execute();
4982 : }
4983 :
4984 607578 : obj->finalize();
4985 :
4986 : // These have to be stored piecemeal (with every call to this function) because general
4987 : // postprocessors (which run last after other userobjects have been completed) might depend on
4988 : // them being stored. This wouldn't be a problem if all userobjects satisfied the dependency
4989 : // resolver interface and could be sorted appropriately with the general userobjects, but they
4990 : // don't.
4991 607558 : auto pp = dynamic_cast<const Postprocessor *>(obj);
4992 607558 : if (pp)
4993 : {
4994 529069 : _reporter_data.finalize(obj->name());
4995 529069 : setPostprocessorValueByName(obj->name(), pp->getValue());
4996 : }
4997 :
4998 607546 : auto vpp = dynamic_cast<VectorPostprocessor *>(obj);
4999 607546 : if (vpp)
5000 14358 : _reporter_data.finalize(obj->name());
5001 :
5002 : // Update Reporter data
5003 607546 : auto reporter = dynamic_cast<Reporter *>(obj);
5004 607546 : if (reporter)
5005 5391 : _reporter_data.finalize(obj->name());
5006 : }
5007 1428703 : }
5008 :
5009 : void
5010 57176 : FEProblemBase::computeUserObjectByName(const ExecFlagType & type,
5011 : const Moose::AuxGroup & group,
5012 : const std::string & name)
5013 : {
5014 57176 : const auto old_exec_flag = _current_execute_on_flag;
5015 57176 : _current_execute_on_flag = type;
5016 57176 : TheWarehouse::Query query = theWarehouse()
5017 114352 : .query()
5018 57176 : .condition<AttribSystem>("UserObject")
5019 57176 : .condition<AttribExecOns>(type)
5020 57176 : .condition<AttribName>(name);
5021 57176 : computeUserObjectsInternal(type, group, query);
5022 57176 : _current_execute_on_flag = old_exec_flag;
5023 57176 : }
5024 :
5025 : void
5026 12479530 : FEProblemBase::computeUserObjects(const ExecFlagType & type, const Moose::AuxGroup & group)
5027 : {
5028 : TheWarehouse::Query query =
5029 12479530 : theWarehouse().query().condition<AttribSystem>("UserObject").condition<AttribExecOns>(type);
5030 12479530 : computeUserObjectsInternal(type, group, query);
5031 12479413 : }
5032 :
5033 : void
5034 12536706 : FEProblemBase::computeUserObjectsInternal(const ExecFlagType & type,
5035 : const Moose::AuxGroup & group,
5036 : TheWarehouse::Query & primary_query)
5037 : {
5038 : try
5039 : {
5040 62683530 : TIME_SECTION("computeUserObjects", 1, "Computing User Objects");
5041 :
5042 : // Add group to query
5043 12536706 : if (group == Moose::PRE_IC)
5044 57911 : primary_query.condition<AttribPreIC>(true);
5045 12478795 : else if (group == Moose::PRE_AUX)
5046 6239162 : primary_query.condition<AttribPreAux>(type);
5047 6239633 : else if (group == Moose::POST_AUX)
5048 6239589 : primary_query.condition<AttribPostAux>(type);
5049 :
5050 : // query everything first to obtain a list of execution groups
5051 12536706 : std::vector<UserObject *> uos;
5052 12536706 : primary_query.clone().queryIntoUnsorted(uos);
5053 12536706 : std::set<int> execution_groups;
5054 13173684 : for (const auto & uo : uos)
5055 1910934 : execution_groups.insert(uo->getParam<int>("execution_order_group"));
5056 :
5057 : // iterate over execution order groups
5058 12845924 : for (const auto execution_group : execution_groups)
5059 : {
5060 309335 : auto query = primary_query.clone().condition<AttribExecutionOrderGroup>(execution_group);
5061 :
5062 309335 : std::vector<GeneralUserObject *> genobjs;
5063 309335 : query.clone().condition<AttribInterfaces>(Interfaces::GeneralUserObject).queryInto(genobjs);
5064 :
5065 309335 : std::vector<UserObject *> userobjs;
5066 309335 : query.clone()
5067 618670 : .condition<AttribInterfaces>(Interfaces::ElementUserObject | Interfaces::SideUserObject |
5068 : Interfaces::InternalSideUserObject |
5069 618670 : Interfaces::InterfaceUserObject |
5070 : Interfaces::DomainUserObject)
5071 309335 : .queryInto(userobjs);
5072 :
5073 309335 : std::vector<UserObject *> tgobjs;
5074 309335 : query.clone()
5075 618670 : .condition<AttribInterfaces>(Interfaces::ThreadedGeneralUserObject)
5076 309335 : .queryInto(tgobjs);
5077 :
5078 309335 : std::vector<UserObject *> nodal;
5079 309335 : query.clone().condition<AttribInterfaces>(Interfaces::NodalUserObject).queryInto(nodal);
5080 :
5081 309335 : std::vector<MortarUserObject *> mortar;
5082 309335 : query.clone().condition<AttribInterfaces>(Interfaces::MortarUserObject).queryInto(mortar);
5083 :
5084 309335 : if (userobjs.empty() && genobjs.empty() && tgobjs.empty() && nodal.empty() && mortar.empty())
5085 0 : continue;
5086 :
5087 : // Start the timer here since we have at least one active user object
5088 309335 : std::string compute_uo_tag = "computeUserObjects(" + Moose::stringify(type) + ")";
5089 :
5090 : // Perform Residual/Jacobian setups
5091 309335 : if (type == EXEC_LINEAR)
5092 : {
5093 132237 : for (auto obj : userobjs)
5094 74488 : obj->residualSetup();
5095 62541 : for (auto obj : nodal)
5096 4792 : obj->residualSetup();
5097 57749 : for (auto obj : mortar)
5098 0 : obj->residualSetup();
5099 57749 : for (auto obj : tgobjs)
5100 0 : obj->residualSetup();
5101 69324 : for (auto obj : genobjs)
5102 11575 : obj->residualSetup();
5103 : }
5104 251586 : else if (type == EXEC_NONLINEAR)
5105 : {
5106 11622 : for (auto obj : userobjs)
5107 2809 : obj->jacobianSetup();
5108 9237 : for (auto obj : nodal)
5109 424 : obj->jacobianSetup();
5110 8813 : for (auto obj : mortar)
5111 0 : obj->jacobianSetup();
5112 8813 : for (auto obj : tgobjs)
5113 0 : obj->jacobianSetup();
5114 24077 : for (auto obj : genobjs)
5115 15264 : obj->jacobianSetup();
5116 : }
5117 :
5118 678947 : for (auto obj : userobjs)
5119 369612 : obj->initialize();
5120 :
5121 : // Execute Side/InternalSide/Interface/Elemental/DomainUserObjects
5122 309335 : if (!userobjs.empty())
5123 : {
5124 : // non-nodal user objects have to be run separately before the nodal user objects run
5125 : // because some nodal user objects (NodalNormal related) depend on elemental user objects
5126 : // :-(
5127 220311 : ComputeUserObjectsThread cppt(*this, query);
5128 220311 : Threads::parallel_reduce(*_mesh.getActiveLocalElementRange(), cppt);
5129 :
5130 : // There is one instance in rattlesnake where an elemental user object's finalize depends
5131 : // on a side user object having been finalized first :-(
5132 220303 : joinAndFinalize(query.clone().condition<AttribInterfaces>(Interfaces::SideUserObject));
5133 220299 : joinAndFinalize(
5134 440598 : query.clone().condition<AttribInterfaces>(Interfaces::InternalSideUserObject));
5135 220299 : joinAndFinalize(query.clone().condition<AttribInterfaces>(Interfaces::InterfaceUserObject));
5136 220299 : joinAndFinalize(query.clone().condition<AttribInterfaces>(Interfaces::ElementUserObject));
5137 220295 : joinAndFinalize(query.clone().condition<AttribInterfaces>(Interfaces::DomainUserObject));
5138 220295 : }
5139 :
5140 : // if any userobject may have written to variables we need to close the aux solution
5141 678829 : for (const auto & uo : userobjs)
5142 369546 : if (auto euo = dynamic_cast<const ElementUserObject *>(uo);
5143 369546 : euo && euo->hasWritableCoupledVariables())
5144 : {
5145 36 : _aux->solution().close();
5146 36 : _aux->system().update();
5147 36 : break;
5148 : }
5149 :
5150 : // Execute NodalUserObjects
5151 : // BISON has an axial reloc elemental user object that has a finalize func that depends on a
5152 : // nodal user object's prev value. So we can't initialize this until after elemental objects
5153 : // have been finalized :-(
5154 331779 : for (auto obj : nodal)
5155 22460 : obj->initialize();
5156 309319 : if (query.clone().condition<AttribInterfaces>(Interfaces::NodalUserObject).count() > 0)
5157 : {
5158 17882 : ComputeNodalUserObjectsThread cnppt(*this, query);
5159 17882 : Threads::parallel_reduce(*_mesh.getLocalNodeRange(), cnppt);
5160 17882 : joinAndFinalize(query.clone().condition<AttribInterfaces>(Interfaces::NodalUserObject));
5161 17882 : }
5162 :
5163 : // if any userobject may have written to variables we need to close the aux solution
5164 331740 : for (const auto & uo : nodal)
5165 22445 : if (auto nuo = dynamic_cast<const NodalUserObject *>(uo);
5166 22445 : nuo && nuo->hasWritableCoupledVariables())
5167 : {
5168 24 : _aux->solution().close();
5169 24 : _aux->system().update();
5170 24 : break;
5171 : }
5172 :
5173 : // Execute MortarUserObjects
5174 : {
5175 309343 : for (auto obj : mortar)
5176 24 : obj->initialize();
5177 309319 : if (!mortar.empty())
5178 : {
5179 36 : auto create_and_run_mortar_functors = [this, type, &mortar](const bool displaced)
5180 : {
5181 : // go over mortar interfaces and construct functors
5182 36 : const auto & mortar_interfaces = getMortarInterfaces(displaced);
5183 60 : for (const auto & [primary_secondary_boundary_pair, mortar_generation_ptr] :
5184 96 : mortar_interfaces)
5185 : {
5186 : auto mortar_uos_to_execute =
5187 24 : getMortarUserObjects(primary_secondary_boundary_pair.first,
5188 24 : primary_secondary_boundary_pair.second,
5189 : displaced,
5190 24 : mortar);
5191 :
5192 : auto * const subproblem = displaced
5193 24 : ? static_cast<SubProblem *>(_displaced_problem.get())
5194 24 : : static_cast<SubProblem *>(this);
5195 : MortarUserObjectThread muot(mortar_uos_to_execute,
5196 24 : *mortar_generation_ptr,
5197 : *subproblem,
5198 : *this,
5199 : displaced,
5200 24 : subproblem->assembly(0, 0));
5201 :
5202 24 : muot();
5203 24 : }
5204 60 : };
5205 :
5206 24 : create_and_run_mortar_functors(false);
5207 24 : if (_displaced_problem)
5208 12 : create_and_run_mortar_functors(true);
5209 24 : }
5210 309343 : for (auto obj : mortar)
5211 24 : obj->finalize();
5212 : }
5213 :
5214 : // Execute threaded general user objects
5215 309771 : for (auto obj : tgobjs)
5216 452 : obj->initialize();
5217 309319 : std::vector<GeneralUserObject *> tguos_zero;
5218 309319 : query.clone()
5219 309319 : .condition<AttribThread>(0)
5220 618638 : .condition<AttribInterfaces>(Interfaces::ThreadedGeneralUserObject)
5221 309319 : .queryInto(tguos_zero);
5222 309435 : for (auto obj : tguos_zero)
5223 : {
5224 116 : std::vector<GeneralUserObject *> tguos;
5225 116 : auto q = query.clone()
5226 116 : .condition<AttribName>(obj->name())
5227 116 : .condition<AttribInterfaces>(Interfaces::ThreadedGeneralUserObject);
5228 116 : q.queryInto(tguos);
5229 :
5230 116 : ComputeThreadedGeneralUserObjectsThread ctguot(*this);
5231 116 : Threads::parallel_reduce(GeneralUserObjectRange(tguos.begin(), tguos.end()), ctguot);
5232 116 : joinAndFinalize(q);
5233 116 : }
5234 :
5235 : // Execute general user objects
5236 309319 : joinAndFinalize(query.clone().condition<AttribInterfaces>(Interfaces::GeneralUserObject),
5237 : true);
5238 309218 : }
5239 12536589 : }
5240 0 : catch (...)
5241 : {
5242 0 : handleException("computeUserObjectsInternal");
5243 0 : }
5244 12536589 : }
5245 :
5246 : void
5247 6214644 : FEProblemBase::executeControls(const ExecFlagType & exec_type)
5248 : {
5249 6214644 : if (_control_warehouse[exec_type].hasActiveObjects())
5250 : {
5251 41685 : TIME_SECTION("executeControls", 1, "Executing Controls");
5252 :
5253 8337 : DependencyResolver<std::shared_ptr<Control>> resolver;
5254 :
5255 8337 : auto controls_wh = _control_warehouse[exec_type];
5256 : // Add all of the dependencies into the resolver and sort them
5257 20920 : for (const auto & it : controls_wh.getActiveObjects())
5258 : {
5259 : // Make sure an item with no dependencies comes out too!
5260 12587 : resolver.addItem(it);
5261 :
5262 12587 : std::vector<std::string> & dependent_controls = it->getDependencies();
5263 15712 : for (const auto & depend_name : dependent_controls)
5264 : {
5265 3129 : if (controls_wh.hasActiveObject(depend_name))
5266 : {
5267 3125 : auto dep_control = controls_wh.getActiveObject(depend_name);
5268 3125 : resolver.addEdge(dep_control, it);
5269 3125 : }
5270 : else
5271 4 : mooseError("The Control \"",
5272 : depend_name,
5273 : "\" was not created, did you make a "
5274 : "spelling mistake or forget to include it "
5275 : "in your input file?");
5276 : }
5277 : }
5278 :
5279 8333 : const auto & ordered_controls = resolver.getSortedValues();
5280 :
5281 8333 : if (!ordered_controls.empty())
5282 : {
5283 8333 : _control_warehouse.setup(exec_type);
5284 : // Run the controls in the proper order
5285 20860 : for (const auto & control : ordered_controls)
5286 12583 : control->execute();
5287 : }
5288 8277 : }
5289 6214584 : }
5290 :
5291 : void
5292 2266919 : FEProblemBase::executeSamplers(const ExecFlagType & exec_type)
5293 : {
5294 : // TODO: This should be done in a threaded loop, but this should be super quick so for now
5295 : // do a serial loop.
5296 4736006 : for (THREAD_ID tid = 0; tid < libMesh::n_threads(); ++tid)
5297 : {
5298 2469119 : std::vector<Sampler *> objects;
5299 2469119 : theWarehouse()
5300 4938238 : .query()
5301 2469119 : .condition<AttribSystem>("Sampler")
5302 2469119 : .condition<AttribThread>(tid)
5303 2469119 : .condition<AttribExecOns>(exec_type)
5304 2469119 : .queryInto(objects);
5305 :
5306 2469119 : if (!objects.empty())
5307 : {
5308 275 : TIME_SECTION("executeSamplers", 1, "Executing Samplers");
5309 55 : FEProblemBase::objectSetupHelper<Sampler>(objects, exec_type);
5310 55 : FEProblemBase::objectExecuteHelper<Sampler>(objects);
5311 23 : }
5312 2469087 : }
5313 2266887 : }
5314 :
5315 : void
5316 339126 : FEProblemBase::updateActiveObjects()
5317 : {
5318 1695630 : TIME_SECTION("updateActiveObjects", 5, "Updating Active Objects");
5319 :
5320 708068 : for (THREAD_ID tid = 0; tid < libMesh::n_threads(); ++tid)
5321 : {
5322 740408 : for (auto & nl : _nl)
5323 371466 : nl->updateActive(tid);
5324 368942 : _aux->updateActive(tid);
5325 368942 : _indicators.updateActive(tid);
5326 368942 : _internal_side_indicators.updateActive(tid);
5327 368942 : _markers.updateActive(tid);
5328 368942 : _all_materials.updateActive(tid);
5329 368942 : _materials.updateActive(tid);
5330 368942 : _discrete_materials.updateActive(tid);
5331 : }
5332 :
5333 339126 : _control_warehouse.updateActive();
5334 339126 : _multi_apps.updateActive();
5335 339126 : _transient_multi_apps.updateActive();
5336 339126 : _transfers.updateActive();
5337 339126 : _to_multi_app_transfers.updateActive();
5338 339126 : _from_multi_app_transfers.updateActive();
5339 339126 : _between_multi_app_transfers.updateActive();
5340 :
5341 : #ifdef MOOSE_KOKKOS_ENABLED
5342 223659 : _kokkos_materials.updateActive();
5343 : #endif
5344 339126 : }
5345 :
5346 : void
5347 0 : FEProblemBase::reportMooseObjectDependency(MooseObject * /*a*/, MooseObject * /*b*/)
5348 : {
5349 : //<< "Object " << a->name() << " -> " << b->name() << std::endl;
5350 0 : }
5351 :
5352 : void
5353 70340 : FEProblemBase::reinitBecauseOfGhostingOrNewGeomObjects(const bool mortar_changed)
5354 : {
5355 351700 : TIME_SECTION("reinitBecauseOfGhostingOrNewGeomObjects",
5356 : 3,
5357 : "Reinitializing Because of Geometric Search Objects");
5358 :
5359 : // Need to see if _any_ processor has ghosted elems or geometry objects.
5360 70340 : bool needs_reinit = !_ghosted_elems.empty();
5361 140270 : needs_reinit = needs_reinit || !_geometric_search_data._nearest_node_locators.empty() ||
5362 69930 : (_mortar_data->hasObjects() && mortar_changed);
5363 70340 : needs_reinit =
5364 142223 : needs_reinit || (_displaced_problem &&
5365 5002 : (!_displaced_problem->geomSearchData()._nearest_node_locators.empty() ||
5366 71246 : (_mortar_data->hasDisplacedObjects() && mortar_changed)));
5367 70340 : _communicator.max(needs_reinit);
5368 :
5369 70340 : if (needs_reinit)
5370 : {
5371 : // Call reinit to get the ghosted vectors correct now that some geometric search has been done
5372 2354 : es().reinit();
5373 :
5374 2354 : if (_displaced_mesh)
5375 1748 : _displaced_problem->es().reinit();
5376 : }
5377 70340 : }
5378 :
5379 : void
5380 181 : FEProblemBase::addDamper(const std::string & damper_name,
5381 : const std::string & name,
5382 : InputParameters & parameters)
5383 : {
5384 : parallel_object_only();
5385 :
5386 : const auto nl_sys_num =
5387 181 : parameters.isParamValid("variable")
5388 582 : ? determineSolverSystem(parameters.varName("variable", name), true).second
5389 177 : : (unsigned int)0;
5390 :
5391 177 : if (!isSolverSystemNonlinear(nl_sys_num))
5392 0 : mooseError("You are trying to add a DGKernel to a linear variable/system, which is not "
5393 : "supported at the moment!");
5394 :
5395 354 : parameters.set<SubProblem *>("_subproblem") = this;
5396 354 : parameters.set<SystemBase *>("_sys") = _nl[nl_sys_num].get();
5397 :
5398 177 : _has_dampers = true;
5399 177 : logAdd("Damper", name, damper_name, parameters);
5400 177 : _nl[nl_sys_num]->addDamper(damper_name, name, parameters);
5401 177 : }
5402 :
5403 : void
5404 163 : FEProblemBase::setupDampers()
5405 : {
5406 326 : for (auto & nl : _nl)
5407 163 : nl->setupDampers();
5408 163 : }
5409 :
5410 : void
5411 697 : FEProblemBase::addIndicator(const std::string & indicator_name,
5412 : const std::string & name,
5413 : InputParameters & parameters)
5414 : {
5415 : parallel_object_only();
5416 :
5417 697 : if (_displaced_problem && parameters.get<bool>("use_displaced_mesh"))
5418 : {
5419 0 : parameters.set<SubProblem *>("_subproblem") = _displaced_problem.get();
5420 0 : parameters.set<SystemBase *>("_sys") = &_displaced_problem->auxSys();
5421 0 : _reinit_displaced_elem = true;
5422 : }
5423 : else
5424 : {
5425 697 : if (_displaced_problem == nullptr && parameters.get<bool>("use_displaced_mesh"))
5426 : {
5427 : // We allow Indicators to request that they use_displaced_mesh,
5428 : // but then be overridden when no displacements variables are
5429 : // provided in the Mesh block. If that happened, update the value
5430 : // of use_displaced_mesh appropriately for this Indicator.
5431 0 : if (parameters.have_parameter<bool>("use_displaced_mesh"))
5432 0 : parameters.set<bool>("use_displaced_mesh") = false;
5433 : }
5434 :
5435 1394 : parameters.set<SubProblem *>("_subproblem") = this;
5436 2091 : parameters.set<SystemBase *>("_sys") = _aux.get();
5437 : }
5438 :
5439 1456 : for (THREAD_ID tid = 0; tid < libMesh::n_threads(); tid++)
5440 : {
5441 : std::shared_ptr<Indicator> indicator =
5442 759 : _factory.create<Indicator>(indicator_name, name, parameters, tid);
5443 759 : logAdd("Indicator", name, indicator_name, parameters);
5444 : std::shared_ptr<InternalSideIndicatorBase> isi =
5445 759 : std::dynamic_pointer_cast<InternalSideIndicatorBase>(indicator);
5446 759 : if (isi)
5447 650 : _internal_side_indicators.addObject(isi, tid);
5448 : else
5449 109 : _indicators.addObject(indicator, tid);
5450 759 : }
5451 697 : }
5452 :
5453 : void
5454 2095 : FEProblemBase::addMarker(const std::string & marker_name,
5455 : const std::string & name,
5456 : InputParameters & parameters)
5457 : {
5458 : parallel_object_only();
5459 :
5460 2095 : if (_displaced_problem && parameters.get<bool>("use_displaced_mesh"))
5461 : {
5462 0 : parameters.set<SubProblem *>("_subproblem") = _displaced_problem.get();
5463 0 : parameters.set<SystemBase *>("_sys") = &_displaced_problem->auxSys();
5464 0 : _reinit_displaced_elem = true;
5465 : }
5466 : else
5467 : {
5468 2095 : if (_displaced_problem == nullptr && parameters.get<bool>("use_displaced_mesh"))
5469 : {
5470 : // We allow Markers to request that they use_displaced_mesh,
5471 : // but then be overridden when no displacements variables are
5472 : // provided in the Mesh block. If that happened, update the value
5473 : // of use_displaced_mesh appropriately for this Marker.
5474 0 : if (parameters.have_parameter<bool>("use_displaced_mesh"))
5475 0 : parameters.set<bool>("use_displaced_mesh") = false;
5476 : }
5477 :
5478 4190 : parameters.set<SubProblem *>("_subproblem") = this;
5479 6285 : parameters.set<SystemBase *>("_sys") = _aux.get();
5480 : }
5481 :
5482 4360 : for (THREAD_ID tid = 0; tid < libMesh::n_threads(); tid++)
5483 : {
5484 2269 : std::shared_ptr<Marker> marker = _factory.create<Marker>(marker_name, name, parameters, tid);
5485 2265 : logAdd("Marker", name, marker_name, parameters);
5486 2265 : _markers.addObject(marker, tid);
5487 2265 : }
5488 2091 : }
5489 :
5490 : void
5491 7672 : FEProblemBase::addMultiApp(const std::string & multi_app_name,
5492 : const std::string & name,
5493 : InputParameters & parameters)
5494 : {
5495 : parallel_object_only();
5496 :
5497 15344 : parameters.set<MPI_Comm>("_mpi_comm") = _communicator.get();
5498 :
5499 7672 : if (_displaced_problem && parameters.get<bool>("use_displaced_mesh"))
5500 : {
5501 0 : parameters.set<SubProblem *>("_subproblem") = _displaced_problem.get();
5502 0 : parameters.set<SystemBase *>("_sys") = &_displaced_problem->auxSys();
5503 0 : _reinit_displaced_elem = true;
5504 : }
5505 : else
5506 : {
5507 7672 : if (_displaced_problem == nullptr && parameters.get<bool>("use_displaced_mesh"))
5508 : {
5509 : // We allow MultiApps to request that they use_displaced_mesh,
5510 : // but then be overridden when no displacements variables are
5511 : // provided in the Mesh block. If that happened, update the value
5512 : // of use_displaced_mesh appropriately for this MultiApp.
5513 49 : if (parameters.have_parameter<bool>("use_displaced_mesh"))
5514 98 : parameters.set<bool>("use_displaced_mesh") = false;
5515 : }
5516 :
5517 15344 : parameters.set<SubProblem *>("_subproblem") = this;
5518 23016 : parameters.set<SystemBase *>("_sys") = _aux.get();
5519 : }
5520 :
5521 7672 : std::shared_ptr<MultiApp> multi_app = _factory.create<MultiApp>(multi_app_name, name, parameters);
5522 7656 : logAdd("MultiApp", name, multi_app_name, parameters);
5523 7656 : multi_app->setupPositions();
5524 :
5525 7541 : _multi_apps.addObject(multi_app);
5526 :
5527 : // Store TransientMultiApp objects in another container, this is needed for calling computeDT
5528 : std::shared_ptr<TransientMultiApp> trans_multi_app =
5529 7541 : std::dynamic_pointer_cast<TransientMultiApp>(multi_app);
5530 7541 : if (trans_multi_app)
5531 5401 : _transient_multi_apps.addObject(trans_multi_app);
5532 7541 : }
5533 :
5534 : bool
5535 120680 : FEProblemBase::hasMultiApps(ExecFlagType type) const
5536 : {
5537 120680 : return _multi_apps[type].hasActiveObjects();
5538 : }
5539 :
5540 : bool
5541 0 : FEProblemBase::hasMultiApp(const std::string & multi_app_name) const
5542 : {
5543 0 : return _multi_apps.hasActiveObject(multi_app_name);
5544 : }
5545 :
5546 : std::shared_ptr<MultiApp>
5547 24983 : FEProblemBase::getMultiApp(const std::string & multi_app_name) const
5548 : {
5549 24983 : return _multi_apps.getObject(multi_app_name);
5550 : }
5551 :
5552 : void
5553 15743513 : FEProblemBase::execMultiAppTransfers(ExecFlagType type, Transfer::DIRECTION direction)
5554 : {
5555 15743513 : bool to_multiapp = direction == MultiAppTransfer::TO_MULTIAPP;
5556 15743513 : bool from_multiapp = direction == MultiAppTransfer::FROM_MULTIAPP;
5557 15743513 : std::string string_direction;
5558 15743513 : if (to_multiapp)
5559 5247910 : string_direction = " To ";
5560 10495603 : else if (from_multiapp)
5561 5247741 : string_direction = " From ";
5562 : else
5563 5247862 : string_direction = " Between ";
5564 :
5565 15743730 : const MooseObjectWarehouse<Transfer> & wh = to_multiapp ? _to_multi_app_transfers[type]
5566 26238995 : : from_multiapp ? _from_multi_app_transfers[type]
5567 36734815 : : _between_multi_app_transfers[type];
5568 :
5569 15743513 : if (wh.hasActiveObjects())
5570 : {
5571 570085 : TIME_SECTION("execMultiAppTransfers", 1, "Executing Transfers");
5572 :
5573 114017 : const auto & transfers = wh.getActiveObjects();
5574 :
5575 114017 : if (_verbose_multiapps)
5576 : {
5577 2486 : _console << COLOR_CYAN << "\nTransfers on " << Moose::stringify(type) << string_direction
5578 2486 : << "MultiApps" << COLOR_DEFAULT << ":" << std::endl;
5579 :
5580 : VariadicTable<std::string, std::string, std::string, std::string> table(
5581 4972 : {"Name", "Type", "From", "To"});
5582 :
5583 : // Build Table of Transfer Info
5584 5932 : for (const auto & transfer : transfers)
5585 : {
5586 3446 : auto multiapp_transfer = dynamic_cast<MultiAppTransfer *>(transfer.get());
5587 :
5588 3446 : table.addRow(multiapp_transfer->name(),
5589 3446 : multiapp_transfer->type(),
5590 6892 : multiapp_transfer->getFromName(),
5591 6892 : multiapp_transfer->getToName());
5592 : }
5593 :
5594 : // Print it
5595 2486 : table.print(_console);
5596 2486 : }
5597 :
5598 233099 : for (const auto & transfer : transfers)
5599 : {
5600 119205 : transfer->setCurrentDirection(direction);
5601 119205 : transfer->execute();
5602 : }
5603 :
5604 113894 : MooseUtils::parallelBarrierNotify(_communicator, _parallel_barrier_messaging);
5605 :
5606 113894 : if (_verbose_multiapps)
5607 4956 : _console << COLOR_CYAN << "Transfers on " << Moose::stringify(type) << " Are Finished\n"
5608 2478 : << COLOR_DEFAULT << std::endl;
5609 113894 : }
5610 15629496 : else if (_multi_apps[type].getActiveObjects().size())
5611 : {
5612 116089 : if (_verbose_multiapps)
5613 7988 : _console << COLOR_CYAN << "\nNo Transfers on " << Moose::stringify(type) << string_direction
5614 3994 : << "MultiApps\n"
5615 3994 : << COLOR_DEFAULT << std::endl;
5616 : }
5617 15743390 : }
5618 :
5619 : std::vector<std::shared_ptr<Transfer>>
5620 13 : FEProblemBase::getTransfers(ExecFlagType type, Transfer::DIRECTION direction) const
5621 : {
5622 13 : if (direction == MultiAppTransfer::TO_MULTIAPP)
5623 13 : return _to_multi_app_transfers[type].getActiveObjects();
5624 0 : else if (direction == MultiAppTransfer::FROM_MULTIAPP)
5625 0 : return _from_multi_app_transfers[type].getActiveObjects();
5626 : else
5627 0 : return _between_multi_app_transfers[type].getActiveObjects();
5628 : }
5629 :
5630 : std::vector<std::shared_ptr<Transfer>>
5631 0 : FEProblemBase::getTransfers(Transfer::DIRECTION direction) const
5632 : {
5633 0 : if (direction == MultiAppTransfer::TO_MULTIAPP)
5634 0 : return _to_multi_app_transfers.getActiveObjects();
5635 0 : else if (direction == MultiAppTransfer::FROM_MULTIAPP)
5636 0 : return _from_multi_app_transfers.getActiveObjects();
5637 : else
5638 0 : return _between_multi_app_transfers.getActiveObjects();
5639 : }
5640 :
5641 : const ExecuteMooseObjectWarehouse<Transfer> &
5642 0 : FEProblemBase::getMultiAppTransferWarehouse(Transfer::DIRECTION direction) const
5643 : {
5644 0 : if (direction == MultiAppTransfer::TO_MULTIAPP)
5645 0 : return _to_multi_app_transfers;
5646 0 : else if (direction == MultiAppTransfer::FROM_MULTIAPP)
5647 0 : return _from_multi_app_transfers;
5648 : else
5649 0 : return _between_multi_app_transfers;
5650 : }
5651 :
5652 : bool
5653 5247914 : FEProblemBase::execMultiApps(ExecFlagType type, bool auto_advance)
5654 : {
5655 : // Active MultiApps
5656 : const std::vector<MooseSharedPointer<MultiApp>> & multi_apps =
5657 5247914 : _multi_apps[type].getActiveObjects();
5658 :
5659 : // Do anything that needs to be done to Apps before transfers
5660 5315860 : for (const auto & multi_app : multi_apps)
5661 67950 : multi_app->preTransfer(_dt, _time);
5662 :
5663 : // Execute Transfers _to_ MultiApps
5664 5247910 : execMultiAppTransfers(type, MultiAppTransfer::TO_MULTIAPP);
5665 :
5666 : // Execute Transfers _between_ Multiapps
5667 5247862 : execMultiAppTransfers(type, MultiAppTransfer::BETWEEN_MULTIAPP);
5668 :
5669 : // Execute MultiApps
5670 5247862 : if (multi_apps.size())
5671 : {
5672 333535 : TIME_SECTION("execMultiApps", 1, "Executing MultiApps", false);
5673 :
5674 66707 : if (_verbose_multiapps)
5675 4192 : _console << COLOR_CYAN << "\nExecuting MultiApps on " << Moose::stringify(type)
5676 2096 : << COLOR_DEFAULT << std::endl;
5677 :
5678 66707 : bool success = true;
5679 :
5680 134481 : for (const auto & multi_app : multi_apps)
5681 : {
5682 67887 : success = multi_app->solveStep(_dt, _time, auto_advance);
5683 : // no need to finish executing the subapps if one fails
5684 67875 : if (!success)
5685 101 : break;
5686 : }
5687 :
5688 66695 : MooseUtils::parallelBarrierNotify(_communicator, _parallel_barrier_messaging);
5689 :
5690 66695 : _communicator.min(success);
5691 :
5692 66695 : if (!success)
5693 109 : return false;
5694 :
5695 66586 : if (_verbose_multiapps)
5696 4192 : _console << COLOR_CYAN << "Finished Executing MultiApps on " << Moose::stringify(type) << "\n"
5697 2096 : << COLOR_DEFAULT << std::endl;
5698 66695 : }
5699 :
5700 : // Execute Transfers _from_ MultiApps
5701 5247741 : execMultiAppTransfers(type, MultiAppTransfer::FROM_MULTIAPP);
5702 :
5703 : // If we made it here then everything passed
5704 5247666 : return true;
5705 : }
5706 :
5707 : void
5708 50254 : FEProblemBase::finalizeMultiApps()
5709 : {
5710 50254 : const auto & multi_apps = _multi_apps.getActiveObjects();
5711 :
5712 56613 : for (const auto & multi_app : multi_apps)
5713 6359 : multi_app->finalize();
5714 50254 : }
5715 :
5716 : void
5717 51863 : FEProblemBase::postExecute()
5718 : {
5719 51863 : const auto & multi_apps = _multi_apps.getActiveObjects();
5720 :
5721 58579 : for (const auto & multi_app : multi_apps)
5722 6716 : multi_app->postExecute();
5723 51863 : }
5724 :
5725 : void
5726 727492 : FEProblemBase::incrementMultiAppTStep(ExecFlagType type)
5727 : {
5728 727492 : const auto & multi_apps = _multi_apps[type].getActiveObjects();
5729 :
5730 727492 : if (multi_apps.size())
5731 28639 : for (const auto & multi_app : multi_apps)
5732 14497 : multi_app->incrementTStep(_time);
5733 727492 : }
5734 :
5735 : void
5736 39872 : FEProblemBase::finishMultiAppStep(ExecFlagType type, bool recurse_through_multiapp_levels)
5737 : {
5738 39872 : const auto & multi_apps = _multi_apps[type].getActiveObjects();
5739 :
5740 39872 : if (multi_apps.size())
5741 : {
5742 9407 : if (_verbose_multiapps)
5743 416 : _console << COLOR_CYAN << "\nAdvancing MultiApps on " << type.name() << COLOR_DEFAULT
5744 416 : << std::endl;
5745 :
5746 18828 : for (const auto & multi_app : multi_apps)
5747 9421 : multi_app->finishStep(recurse_through_multiapp_levels);
5748 :
5749 9407 : MooseUtils::parallelBarrierNotify(_communicator, _parallel_barrier_messaging);
5750 :
5751 9407 : if (_verbose_multiapps)
5752 416 : _console << COLOR_CYAN << "Finished Advancing MultiApps on " << type.name() << "\n"
5753 416 : << COLOR_DEFAULT << std::endl;
5754 : }
5755 39872 : }
5756 :
5757 : void
5758 1217857 : FEProblemBase::backupMultiApps(ExecFlagType type)
5759 : {
5760 1217857 : const auto & multi_apps = _multi_apps[type].getActiveObjects();
5761 :
5762 1217857 : if (multi_apps.size())
5763 : {
5764 106985 : TIME_SECTION("backupMultiApps", 5, "Backing Up MultiApp");
5765 :
5766 21397 : if (_verbose_multiapps)
5767 1007 : _console << COLOR_CYAN << "\nBacking Up MultiApps on " << type.name() << COLOR_DEFAULT
5768 1007 : << std::endl;
5769 :
5770 43915 : for (const auto & multi_app : multi_apps)
5771 22518 : multi_app->backup();
5772 :
5773 21397 : MooseUtils::parallelBarrierNotify(_communicator, _parallel_barrier_messaging);
5774 :
5775 21397 : if (_verbose_multiapps)
5776 1007 : _console << COLOR_CYAN << "Finished Backing Up MultiApps on " << type.name() << "\n"
5777 1007 : << COLOR_DEFAULT << std::endl;
5778 21397 : }
5779 1217857 : }
5780 :
5781 : void
5782 118948 : FEProblemBase::restoreMultiApps(ExecFlagType type, bool force)
5783 : {
5784 118948 : const auto & multi_apps = _multi_apps[type].getActiveObjects();
5785 :
5786 118948 : if (multi_apps.size())
5787 : {
5788 45872 : if (_verbose_multiapps)
5789 : {
5790 1092 : if (force)
5791 3 : _console << COLOR_CYAN << "\nRestoring Multiapps on " << type.name()
5792 3 : << " because of solve failure!" << COLOR_DEFAULT << std::endl;
5793 : else
5794 1089 : _console << COLOR_CYAN << "\nRestoring MultiApps on " << type.name() << COLOR_DEFAULT
5795 1089 : << std::endl;
5796 : }
5797 :
5798 91829 : for (const auto & multi_app : multi_apps)
5799 45961 : multi_app->restore(force);
5800 :
5801 45868 : MooseUtils::parallelBarrierNotify(_communicator, _parallel_barrier_messaging);
5802 :
5803 45868 : if (_verbose_multiapps)
5804 1092 : _console << COLOR_CYAN << "Finished Restoring MultiApps on " << type.name() << "\n"
5805 1092 : << COLOR_DEFAULT << std::endl;
5806 : }
5807 118944 : }
5808 :
5809 : Real
5810 756472 : FEProblemBase::computeMultiAppsDT(ExecFlagType type)
5811 : {
5812 756472 : const auto & multi_apps = _transient_multi_apps[type].getActiveObjects();
5813 :
5814 756472 : Real smallest_dt = std::numeric_limits<Real>::max();
5815 :
5816 774998 : for (const auto & multi_app : multi_apps)
5817 18526 : smallest_dt = std::min(smallest_dt, multi_app->computeDT());
5818 :
5819 756472 : return smallest_dt;
5820 : }
5821 :
5822 : void
5823 5192609 : FEProblemBase::execTransfers(ExecFlagType type)
5824 : {
5825 5192609 : if (_transfers[type].hasActiveObjects())
5826 : {
5827 0 : TIME_SECTION("execTransfers", 3, "Executing Transfers");
5828 :
5829 0 : const auto & transfers = _transfers[type].getActiveObjects();
5830 :
5831 0 : for (const auto & transfer : transfers)
5832 0 : transfer->execute();
5833 0 : }
5834 5192609 : }
5835 :
5836 : void
5837 12603 : FEProblemBase::addTransfer(const std::string & transfer_name,
5838 : const std::string & name,
5839 : InputParameters & parameters)
5840 : {
5841 : parallel_object_only();
5842 :
5843 12603 : if (_displaced_problem && parameters.get<bool>("use_displaced_mesh"))
5844 : {
5845 0 : parameters.set<SubProblem *>("_subproblem") = _displaced_problem.get();
5846 0 : parameters.set<SystemBase *>("_sys") = &_displaced_problem->auxSys();
5847 0 : _reinit_displaced_elem = true;
5848 : }
5849 : else
5850 : {
5851 12603 : if (_displaced_problem == nullptr && parameters.get<bool>("use_displaced_mesh"))
5852 : {
5853 : // We allow Transfers to request that they use_displaced_mesh,
5854 : // but then be overridden when no displacements variables are
5855 : // provided in the Mesh block. If that happened, update the value
5856 : // of use_displaced_mesh appropriately for this Transfer.
5857 0 : if (parameters.have_parameter<bool>("use_displaced_mesh"))
5858 0 : parameters.set<bool>("use_displaced_mesh") = false;
5859 : }
5860 :
5861 25206 : parameters.set<SubProblem *>("_subproblem") = this;
5862 37809 : parameters.set<SystemBase *>("_sys") = _aux.get();
5863 : }
5864 :
5865 : // Handle the "SAME_AS_MULTIAPP" execute option. The get method is used to test for the
5866 : // flag so the set by user flag is not reset, calling set with the true flag causes the set
5867 : // by user status to be reset, which should only be done if the EXEC_SAME_AS_MULTIAPP is
5868 : // being applied to the object.
5869 12603 : if (parameters.get<ExecFlagEnum>("execute_on").isValueSet(EXEC_SAME_AS_MULTIAPP))
5870 : {
5871 10280 : ExecFlagEnum & exec_enum = parameters.set<ExecFlagEnum>("execute_on", true);
5872 10280 : std::shared_ptr<MultiApp> multiapp;
5873 20560 : if (parameters.isParamValid("multi_app"))
5874 56 : multiapp = getMultiApp(parameters.get<MultiAppName>("multi_app"));
5875 : // This catches the sibling transfer case, where we want to be executing only as often as the
5876 : // receiving application. A transfer 'to' a multiapp is executed before that multiapp
5877 20448 : else if (parameters.isParamValid("to_multi_app"))
5878 5465 : multiapp = getMultiApp(parameters.get<MultiAppName>("to_multi_app"));
5879 9518 : else if (parameters.isParamValid("from_multi_app"))
5880 4751 : multiapp = getMultiApp(parameters.get<MultiAppName>("from_multi_app"));
5881 : // else do nothing because the user has provided invalid input. They should get a nice error
5882 : // about this during transfer construction. This necessitates checking for null in this next
5883 : // line, however
5884 10280 : if (multiapp)
5885 30816 : exec_enum = multiapp->getParam<ExecFlagEnum>("execute_on");
5886 10280 : }
5887 :
5888 : // Create the Transfer objects
5889 12603 : std::shared_ptr<Transfer> transfer = _factory.create<Transfer>(transfer_name, name, parameters);
5890 12527 : logAdd("Transfer", name, transfer_name, parameters);
5891 :
5892 : // Add MultiAppTransfer object
5893 : std::shared_ptr<MultiAppTransfer> multi_app_transfer =
5894 12527 : std::dynamic_pointer_cast<MultiAppTransfer>(transfer);
5895 12527 : if (multi_app_transfer)
5896 : {
5897 12527 : if (multi_app_transfer->directions().isValueSet(MultiAppTransfer::TO_MULTIAPP))
5898 5352 : _to_multi_app_transfers.addObject(multi_app_transfer);
5899 12527 : if (multi_app_transfer->directions().isValueSet(MultiAppTransfer::FROM_MULTIAPP))
5900 5979 : _from_multi_app_transfers.addObject(multi_app_transfer);
5901 12527 : if (multi_app_transfer->directions().isValueSet(MultiAppTransfer::BETWEEN_MULTIAPP))
5902 1196 : _between_multi_app_transfers.addObject(multi_app_transfer);
5903 : }
5904 : else
5905 0 : _transfers.addObject(transfer);
5906 12527 : }
5907 :
5908 : bool
5909 1522602 : FEProblemBase::hasVariable(const std::string & var_name) const
5910 : {
5911 2470223 : for (auto & sys : _solver_systems)
5912 1528513 : if (sys->hasVariable(var_name))
5913 580892 : return true;
5914 941710 : if (_aux->hasVariable(var_name))
5915 867514 : return true;
5916 :
5917 74196 : return false;
5918 : }
5919 :
5920 : bool
5921 0 : FEProblemBase::hasSolverVariable(const std::string & var_name) const
5922 : {
5923 0 : for (auto & sys : _solver_systems)
5924 0 : if (sys->hasVariable(var_name))
5925 0 : return true;
5926 :
5927 0 : return false;
5928 : }
5929 :
5930 : const MooseVariableFieldBase &
5931 4797251 : FEProblemBase::getVariable(const THREAD_ID tid,
5932 : const std::string & var_name,
5933 : Moose::VarKindType expected_var_type,
5934 : Moose::VarFieldType expected_var_field_type) const
5935 : {
5936 14391745 : return getVariableHelper(
5937 4797251 : tid, var_name, expected_var_type, expected_var_field_type, _solver_systems, *_aux);
5938 : }
5939 :
5940 : MooseVariable &
5941 8001 : FEProblemBase::getStandardVariable(const THREAD_ID tid, const std::string & var_name)
5942 : {
5943 12111 : for (auto & sys : _solver_systems)
5944 8001 : if (sys->hasVariable(var_name))
5945 3891 : return sys->getFieldVariable<Real>(tid, var_name);
5946 4110 : if (_aux->hasVariable(var_name))
5947 4106 : return _aux->getFieldVariable<Real>(tid, var_name);
5948 :
5949 4 : mooseError("Unknown variable " + var_name);
5950 : }
5951 :
5952 : MooseVariableFieldBase &
5953 661 : FEProblemBase::getActualFieldVariable(const THREAD_ID tid, const std::string & var_name)
5954 : {
5955 877 : for (auto & sys : _solver_systems)
5956 661 : if (sys->hasVariable(var_name))
5957 445 : return sys->getActualFieldVariable<Real>(tid, var_name);
5958 216 : if (_aux->hasVariable(var_name))
5959 216 : return _aux->getActualFieldVariable<Real>(tid, var_name);
5960 :
5961 0 : mooseError("Unknown variable " + var_name);
5962 : }
5963 :
5964 : VectorMooseVariable &
5965 0 : FEProblemBase::getVectorVariable(const THREAD_ID tid, const std::string & var_name)
5966 : {
5967 0 : for (auto & sys : _solver_systems)
5968 0 : if (sys->hasVariable(var_name))
5969 0 : return sys->getFieldVariable<RealVectorValue>(tid, var_name);
5970 0 : if (_aux->hasVariable(var_name))
5971 0 : return _aux->getFieldVariable<RealVectorValue>(tid, var_name);
5972 :
5973 0 : mooseError("Unknown variable " + var_name);
5974 : }
5975 :
5976 : ArrayMooseVariable &
5977 378 : FEProblemBase::getArrayVariable(const THREAD_ID tid, const std::string & var_name)
5978 : {
5979 657 : for (auto & sys : _solver_systems)
5980 378 : if (sys->hasVariable(var_name))
5981 99 : return sys->getFieldVariable<RealEigenVector>(tid, var_name);
5982 279 : if (_aux->hasVariable(var_name))
5983 279 : return _aux->getFieldVariable<RealEigenVector>(tid, var_name);
5984 :
5985 0 : mooseError("Unknown variable " + var_name);
5986 : }
5987 :
5988 : bool
5989 190696 : FEProblemBase::hasScalarVariable(const std::string & var_name) const
5990 : {
5991 355985 : for (auto & sys : _solver_systems)
5992 191319 : if (sys->hasScalarVariable(var_name))
5993 26030 : return true;
5994 164666 : if (_aux->hasScalarVariable(var_name))
5995 12603 : return true;
5996 :
5997 152063 : return false;
5998 : }
5999 :
6000 : MooseVariableScalar &
6001 56126 : FEProblemBase::getScalarVariable(const THREAD_ID tid, const std::string & var_name)
6002 : {
6003 71989 : for (auto & sys : _solver_systems)
6004 56126 : if (sys->hasScalarVariable(var_name))
6005 40263 : return sys->getScalarVariable(tid, var_name);
6006 15863 : if (_aux->hasScalarVariable(var_name))
6007 15863 : return _aux->getScalarVariable(tid, var_name);
6008 :
6009 0 : mooseError("Unknown variable " + var_name);
6010 : }
6011 :
6012 : System &
6013 66522 : FEProblemBase::getSystem(const std::string & var_name)
6014 : {
6015 66522 : const auto [var_in_sys, sys_num] = determineSolverSystem(var_name);
6016 66522 : if (var_in_sys)
6017 47676 : return _solver_systems[sys_num]->system();
6018 18846 : else if (_aux->hasVariable(var_name) || _aux->hasScalarVariable(var_name))
6019 18846 : return _aux->system();
6020 : else
6021 0 : mooseError("Unable to find a system containing the variable " + var_name);
6022 : }
6023 :
6024 : const RestartableEquationSystems &
6025 0 : FEProblemBase::getRestartableEquationSystems() const
6026 : {
6027 0 : return _req.get();
6028 : }
6029 :
6030 : void
6031 541978 : FEProblemBase::setActiveFEVariableCoupleableMatrixTags(std::set<TagID> & mtags, const THREAD_ID tid)
6032 : {
6033 541978 : SubProblem::setActiveFEVariableCoupleableMatrixTags(mtags, tid);
6034 :
6035 541978 : if (_displaced_problem)
6036 114396 : _displaced_problem->setActiveFEVariableCoupleableMatrixTags(mtags, tid);
6037 541978 : }
6038 :
6039 : void
6040 7270031 : FEProblemBase::setActiveFEVariableCoupleableVectorTags(std::set<TagID> & vtags, const THREAD_ID tid)
6041 : {
6042 7270031 : SubProblem::setActiveFEVariableCoupleableVectorTags(vtags, tid);
6043 :
6044 7270031 : if (_displaced_problem)
6045 400132 : _displaced_problem->setActiveFEVariableCoupleableVectorTags(vtags, tid);
6046 7270031 : }
6047 :
6048 : void
6049 56031 : FEProblemBase::setActiveScalarVariableCoupleableMatrixTags(std::set<TagID> & mtags,
6050 : const THREAD_ID tid)
6051 : {
6052 56031 : SubProblem::setActiveScalarVariableCoupleableMatrixTags(mtags, tid);
6053 :
6054 56031 : if (_displaced_problem)
6055 0 : _displaced_problem->setActiveScalarVariableCoupleableMatrixTags(mtags, tid);
6056 56031 : }
6057 :
6058 : void
6059 56031 : FEProblemBase::setActiveScalarVariableCoupleableVectorTags(std::set<TagID> & vtags,
6060 : const THREAD_ID tid)
6061 : {
6062 56031 : SubProblem::setActiveScalarVariableCoupleableVectorTags(vtags, tid);
6063 :
6064 56031 : if (_displaced_problem)
6065 0 : _displaced_problem->setActiveScalarVariableCoupleableVectorTags(vtags, tid);
6066 56031 : }
6067 :
6068 : void
6069 11295830 : FEProblemBase::setActiveElementalMooseVariables(const std::set<MooseVariableFEBase *> & moose_vars,
6070 : const THREAD_ID tid)
6071 : {
6072 11295830 : SubProblem::setActiveElementalMooseVariables(moose_vars, tid);
6073 :
6074 11295830 : if (_displaced_problem)
6075 567951 : _displaced_problem->setActiveElementalMooseVariables(moose_vars, tid);
6076 11295830 : }
6077 :
6078 : void
6079 4698876 : FEProblemBase::clearActiveElementalMooseVariables(const THREAD_ID tid)
6080 : {
6081 4698876 : SubProblem::clearActiveElementalMooseVariables(tid);
6082 :
6083 4698876 : if (_displaced_problem)
6084 204061 : _displaced_problem->clearActiveElementalMooseVariables(tid);
6085 4698876 : }
6086 :
6087 : void
6088 249393 : FEProblemBase::clearActiveFEVariableCoupleableMatrixTags(const THREAD_ID tid)
6089 : {
6090 249393 : SubProblem::clearActiveFEVariableCoupleableMatrixTags(tid);
6091 :
6092 249393 : if (_displaced_problem)
6093 50039 : _displaced_problem->clearActiveFEVariableCoupleableMatrixTags(tid);
6094 249393 : }
6095 :
6096 : void
6097 249393 : FEProblemBase::clearActiveFEVariableCoupleableVectorTags(const THREAD_ID tid)
6098 : {
6099 249393 : SubProblem::clearActiveFEVariableCoupleableVectorTags(tid);
6100 :
6101 249393 : if (_displaced_problem)
6102 50039 : _displaced_problem->clearActiveFEVariableCoupleableVectorTags(tid);
6103 249393 : }
6104 :
6105 : void
6106 56031 : FEProblemBase::clearActiveScalarVariableCoupleableMatrixTags(const THREAD_ID tid)
6107 : {
6108 56031 : SubProblem::clearActiveScalarVariableCoupleableMatrixTags(tid);
6109 :
6110 56031 : if (_displaced_problem)
6111 0 : _displaced_problem->clearActiveScalarVariableCoupleableMatrixTags(tid);
6112 56031 : }
6113 :
6114 : void
6115 56031 : FEProblemBase::clearActiveScalarVariableCoupleableVectorTags(const THREAD_ID tid)
6116 : {
6117 56031 : SubProblem::clearActiveScalarVariableCoupleableVectorTags(tid);
6118 :
6119 56031 : if (_displaced_problem)
6120 0 : _displaced_problem->clearActiveScalarVariableCoupleableVectorTags(tid);
6121 56031 : }
6122 :
6123 : void
6124 5834768 : FEProblemBase::setActiveMaterialProperties(const std::unordered_set<unsigned int> & mat_prop_ids,
6125 : const THREAD_ID tid)
6126 : {
6127 : // mark active properties in every material
6128 7075374 : for (auto & mat : _all_materials.getObjects(tid))
6129 1240606 : mat->setActiveProperties(mat_prop_ids);
6130 6818798 : for (auto & mat : _all_materials[Moose::FACE_MATERIAL_DATA].getObjects(tid))
6131 984030 : mat->setActiveProperties(mat_prop_ids);
6132 6818798 : for (auto & mat : _all_materials[Moose::NEIGHBOR_MATERIAL_DATA].getObjects(tid))
6133 984030 : mat->setActiveProperties(mat_prop_ids);
6134 :
6135 5834768 : _has_active_material_properties[tid] = !mat_prop_ids.empty();
6136 5834768 : }
6137 :
6138 : bool
6139 443208302 : FEProblemBase::hasActiveMaterialProperties(const THREAD_ID tid) const
6140 : {
6141 443208302 : return _has_active_material_properties[tid];
6142 : }
6143 :
6144 : void
6145 4806274 : FEProblemBase::clearActiveMaterialProperties(const THREAD_ID tid)
6146 : {
6147 4806274 : _has_active_material_properties[tid] = 0;
6148 4806274 : }
6149 :
6150 : void
6151 62213 : FEProblemBase::addAnyRedistributers()
6152 : {
6153 : #ifdef LIBMESH_ENABLE_AMR
6154 64633 : if ((_adaptivity.isOn() || _num_grid_steps) &&
6155 2420 : (_material_props.hasStatefulProperties() || _bnd_material_props.hasStatefulProperties() ||
6156 2349 : _neighbor_material_props.hasStatefulProperties()))
6157 : {
6158 : // Even on a serialized Mesh, we don't keep our material
6159 : // properties serialized, so we'll rely on the callback to
6160 : // redistribute() to redistribute properties at the same time
6161 : // libMesh is redistributing elements.
6162 71 : auto add_redistributer = [this](MooseMesh & mesh,
6163 : const std::string & redistributer_name,
6164 : const bool use_displaced_mesh)
6165 : {
6166 71 : InputParameters redistribute_params = RedistributeProperties::validParams();
6167 71 : redistribute_params.set<MooseApp *>(MooseBase::app_param) = &_app;
6168 142 : redistribute_params.set<std::string>("for_whom") = this->name();
6169 213 : redistribute_params.set<MooseMesh *>("mesh") = &mesh;
6170 71 : redistribute_params.set<Moose::RelationshipManagerType>("rm_type") =
6171 : Moose::RelationshipManagerType::GEOMETRIC;
6172 142 : redistribute_params.set<bool>("use_displaced_mesh") = use_displaced_mesh;
6173 71 : redistribute_params.setHitNode(*parameters().getHitNode(), {});
6174 :
6175 : std::shared_ptr<RedistributeProperties> redistributer =
6176 71 : _factory.create<RedistributeProperties>(
6177 142 : "RedistributeProperties", redistributer_name, redistribute_params);
6178 :
6179 71 : if (_material_props.hasStatefulProperties())
6180 71 : redistributer->addMaterialPropertyStorage(_material_props);
6181 :
6182 71 : if (_bnd_material_props.hasStatefulProperties())
6183 71 : redistributer->addMaterialPropertyStorage(_bnd_material_props);
6184 :
6185 71 : if (_neighbor_material_props.hasStatefulProperties())
6186 71 : redistributer->addMaterialPropertyStorage(_neighbor_material_props);
6187 :
6188 71 : mesh.getMesh().add_ghosting_functor(redistributer);
6189 142 : };
6190 :
6191 71 : add_redistributer(_mesh, "mesh_property_redistributer", false);
6192 71 : if (_displaced_problem)
6193 0 : add_redistributer(_displaced_problem->mesh(), "displaced_mesh_property_redistributer", true);
6194 : }
6195 : #endif // LIBMESH_ENABLE_AMR
6196 62213 : }
6197 :
6198 : void
6199 64462 : FEProblemBase::updateMaxQps()
6200 : {
6201 : // Find the maximum number of quadrature points
6202 : {
6203 64462 : MaxQpsThread mqt(*this);
6204 64462 : Threads::parallel_reduce(*_mesh.getActiveLocalElementRange(), mqt);
6205 64462 : _max_qps = mqt.max();
6206 :
6207 : // If we have more shape functions or more quadrature points on
6208 : // another processor, then we may need to handle those elements
6209 : // ourselves later after repartitioning.
6210 64462 : _communicator.max(_max_qps);
6211 : }
6212 :
6213 64462 : unsigned int max_qpts = getMaxQps();
6214 64462 : if (max_qpts > Moose::constMaxQpsPerElem)
6215 0 : mooseError("Max quadrature points per element assumptions made in some code (e.g. Coupleable ",
6216 : "and MaterialPropertyInterface classes) have been violated.\n",
6217 : "Complain to Moose developers to have constMaxQpsPerElem increased from ",
6218 : Moose::constMaxQpsPerElem,
6219 : " to ",
6220 : max_qpts);
6221 135186 : for (unsigned int tid = 0; tid < libMesh::n_threads(); ++tid)
6222 : {
6223 : // the highest available order in libMesh is 43
6224 70724 : _scalar_zero[tid].resize(FORTYTHIRD, 0);
6225 70724 : _zero[tid].resize(max_qpts, 0);
6226 70724 : _ad_zero[tid].resize(max_qpts, 0);
6227 70724 : _grad_zero[tid].resize(max_qpts, RealGradient(0.));
6228 70724 : _ad_grad_zero[tid].resize(max_qpts, ADRealGradient(0));
6229 70724 : _second_zero[tid].resize(max_qpts, RealTensor(0.));
6230 70724 : _ad_second_zero[tid].resize(max_qpts, ADRealTensorValue(0));
6231 70724 : _vector_zero[tid].resize(max_qpts, RealGradient(0.));
6232 70724 : _vector_curl_zero[tid].resize(max_qpts, RealGradient(0.));
6233 : }
6234 64462 : }
6235 :
6236 : void
6237 84 : FEProblemBase::bumpVolumeQRuleOrder(Order order, SubdomainID block)
6238 : {
6239 180 : for (unsigned int tid = 0; tid < libMesh::n_threads(); ++tid)
6240 192 : for (const auto i : index_range(_nl))
6241 96 : _assembly[tid][i]->bumpVolumeQRuleOrder(order, block);
6242 :
6243 84 : if (_displaced_problem)
6244 0 : _displaced_problem->bumpVolumeQRuleOrder(order, block);
6245 :
6246 84 : updateMaxQps();
6247 84 : }
6248 :
6249 : void
6250 14 : FEProblemBase::bumpAllQRuleOrder(Order order, SubdomainID block)
6251 : {
6252 30 : for (unsigned int tid = 0; tid < libMesh::n_threads(); ++tid)
6253 32 : for (const auto i : index_range(_nl))
6254 16 : _assembly[tid][i]->bumpAllQRuleOrder(order, block);
6255 :
6256 14 : if (_displaced_problem)
6257 0 : _displaced_problem->bumpAllQRuleOrder(order, block);
6258 :
6259 14 : updateMaxQps();
6260 14 : }
6261 :
6262 : void
6263 64364 : FEProblemBase::createQRules(QuadratureType type,
6264 : Order order,
6265 : Order volume_order,
6266 : Order face_order,
6267 : SubdomainID block,
6268 : const bool allow_negative_qweights)
6269 : {
6270 64364 : if (order == INVALID_ORDER)
6271 : {
6272 : // automatically determine the integration order
6273 63857 : order = _solver_systems[0]->getMinQuadratureOrder();
6274 64136 : for (const auto i : make_range(std::size_t(1), _solver_systems.size()))
6275 279 : if (order < _solver_systems[i]->getMinQuadratureOrder())
6276 0 : order = _solver_systems[i]->getMinQuadratureOrder();
6277 63857 : if (order < _aux->getMinQuadratureOrder())
6278 5616 : order = _aux->getMinQuadratureOrder();
6279 : }
6280 :
6281 64364 : if (volume_order == INVALID_ORDER)
6282 64269 : volume_order = order;
6283 :
6284 64364 : if (face_order == INVALID_ORDER)
6285 64269 : face_order = order;
6286 :
6287 134976 : for (unsigned int tid = 0; tid < libMesh::n_threads(); ++tid)
6288 141521 : for (const auto i : index_range(_solver_systems))
6289 70909 : _assembly[tid][i]->createQRules(
6290 : type, order, volume_order, face_order, block, allow_negative_qweights);
6291 :
6292 64364 : if (_displaced_problem)
6293 2246 : _displaced_problem->createQRules(
6294 : type, order, volume_order, face_order, block, allow_negative_qweights);
6295 :
6296 64364 : updateMaxQps();
6297 64364 : }
6298 :
6299 : void
6300 22768 : FEProblemBase::setCoupling(Moose::CouplingType type)
6301 : {
6302 22768 : if (_trust_user_coupling_matrix)
6303 : {
6304 4 : if (_coupling != Moose::COUPLING_CUSTOM)
6305 0 : mooseError("Someone told us (the FEProblemBase) to trust the user coupling matrix, but we "
6306 : "haven't been provided a coupling matrix!");
6307 :
6308 : // We've been told to trust the user coupling matrix, so we're going to leave things alone
6309 4 : return;
6310 : }
6311 :
6312 22764 : _coupling = type;
6313 : }
6314 :
6315 : void
6316 0 : FEProblemBase::setCouplingMatrix(CouplingMatrix * cm, const unsigned int i)
6317 : {
6318 : // TODO: Deprecate method
6319 0 : setCoupling(Moose::COUPLING_CUSTOM);
6320 0 : _cm[i].reset(cm);
6321 0 : }
6322 :
6323 : void
6324 15104 : FEProblemBase::setCouplingMatrix(std::unique_ptr<CouplingMatrix> cm, const unsigned int i)
6325 : {
6326 15104 : setCoupling(Moose::COUPLING_CUSTOM);
6327 15104 : _cm[i] = std::move(cm);
6328 15104 : }
6329 :
6330 : void
6331 4 : FEProblemBase::trustUserCouplingMatrix()
6332 : {
6333 4 : if (_coupling != Moose::COUPLING_CUSTOM)
6334 0 : mooseError("Someone told us (the FEProblemBase) to trust the user coupling matrix, but we "
6335 : "haven't been provided a coupling matrix!");
6336 :
6337 4 : _trust_user_coupling_matrix = true;
6338 4 : }
6339 :
6340 : void
6341 81 : FEProblemBase::setNonlocalCouplingMatrix()
6342 : {
6343 405 : TIME_SECTION("setNonlocalCouplingMatrix", 5, "Setting Nonlocal Coupling Matrix");
6344 :
6345 81 : if (_nl.size() > 1)
6346 0 : mooseError("Nonlocal kernels are weirdly stored on the FEProblem so we don't currently support "
6347 : "multiple nonlinear systems with nonlocal kernels.");
6348 :
6349 162 : for (const auto nl_sys_num : index_range(_nl))
6350 : {
6351 81 : auto & nl = _nl[nl_sys_num];
6352 81 : auto & nonlocal_cm = _nonlocal_cm[nl_sys_num];
6353 81 : unsigned int n_vars = nl->nVariables();
6354 81 : nonlocal_cm.resize(n_vars);
6355 81 : const auto & vars = nl->getVariables(0);
6356 81 : const auto & nonlocal_kernel = _nonlocal_kernels.getObjects();
6357 81 : const auto & nonlocal_integrated_bc = _nonlocal_integrated_bcs.getObjects();
6358 243 : for (const auto & ivar : vars)
6359 : {
6360 252 : for (const auto & kernel : nonlocal_kernel)
6361 : {
6362 180 : for (unsigned int i = ivar->number(); i < ivar->number() + ivar->count(); ++i)
6363 90 : if (i == kernel->variable().number())
6364 135 : for (const auto & jvar : vars)
6365 : {
6366 90 : const auto it = _var_dof_map.find(jvar->name());
6367 90 : if (it != _var_dof_map.end())
6368 : {
6369 80 : unsigned int j = jvar->number();
6370 80 : nonlocal_cm(i, j) = 1;
6371 : }
6372 : }
6373 : }
6374 234 : for (const auto & integrated_bc : nonlocal_integrated_bc)
6375 : {
6376 144 : for (unsigned int i = ivar->number(); i < ivar->number() + ivar->count(); ++i)
6377 72 : if (i == integrated_bc->variable().number())
6378 108 : for (const auto & jvar : vars)
6379 : {
6380 72 : const auto it = _var_dof_map.find(jvar->name());
6381 72 : if (it != _var_dof_map.end())
6382 : {
6383 36 : unsigned int j = jvar->number();
6384 36 : nonlocal_cm(i, j) = 1;
6385 : }
6386 : }
6387 : }
6388 : }
6389 : }
6390 81 : }
6391 :
6392 : bool
6393 712 : FEProblemBase::areCoupled(const unsigned int ivar,
6394 : const unsigned int jvar,
6395 : const unsigned int nl_sys) const
6396 : {
6397 712 : return (*_cm[nl_sys])(ivar, jvar);
6398 : }
6399 :
6400 : std::vector<std::pair<MooseVariableFEBase *, MooseVariableFEBase *>> &
6401 19040719 : FEProblemBase::couplingEntries(const THREAD_ID tid, const unsigned int nl_sys)
6402 : {
6403 19040719 : return _assembly[tid][nl_sys]->couplingEntries();
6404 : }
6405 :
6406 : std::vector<std::pair<MooseVariableFEBase *, MooseVariableFEBase *>> &
6407 5558 : FEProblemBase::nonlocalCouplingEntries(const THREAD_ID tid, const unsigned int nl_sys)
6408 : {
6409 5558 : return _assembly[tid][nl_sys]->nonlocalCouplingEntries();
6410 : }
6411 :
6412 : void
6413 62818 : FEProblemBase::init()
6414 : {
6415 62818 : if (_initialized)
6416 0 : return;
6417 :
6418 314090 : TIME_SECTION("init", 2, "Initializing");
6419 :
6420 : // call executioner's preProblemInit so that it can do some setups before problem init
6421 62818 : _app.getExecutioner()->preProblemInit();
6422 :
6423 : // If we have AD and we are doing global AD indexing, then we should by default set the matrix
6424 : // coupling to full. If the user has told us to trust their coupling matrix, then this call will
6425 : // not do anything
6426 62818 : if (haveADObjects() && Moose::globalADIndexing())
6427 7562 : setCoupling(Moose::COUPLING_FULL);
6428 :
6429 124571 : for (const auto i : index_range(_nl))
6430 : {
6431 61753 : auto & nl = _nl[i];
6432 61753 : auto & cm = _cm[i];
6433 :
6434 61753 : unsigned int n_vars = nl->nVariables();
6435 : {
6436 308765 : TIME_SECTION("fillCouplingMatrix", 3, "Filling Coupling Matrix");
6437 :
6438 61753 : switch (_coupling)
6439 : {
6440 44746 : case Moose::COUPLING_DIAG:
6441 44746 : cm = std::make_unique<CouplingMatrix>(n_vars);
6442 83215 : for (unsigned int i = 0; i < n_vars; i++)
6443 38469 : (*cm)(i, i) = 1;
6444 44746 : break;
6445 :
6446 : // for full jacobian
6447 7705 : case Moose::COUPLING_FULL:
6448 7705 : cm = std::make_unique<CouplingMatrix>(n_vars);
6449 19555 : for (unsigned int i = 0; i < n_vars; i++)
6450 34034 : for (unsigned int j = 0; j < n_vars; j++)
6451 22184 : (*cm)(i, j) = 1;
6452 7705 : break;
6453 :
6454 9302 : case Moose::COUPLING_CUSTOM:
6455 : // do nothing, _cm was already set through couplingMatrix() call
6456 9302 : break;
6457 : }
6458 61753 : }
6459 :
6460 61753 : nl->dofMap()._dof_coupling = cm.get();
6461 :
6462 : // If there are no variables, make sure to pass a nullptr coupling
6463 : // matrix, to avoid warnings about non-nullptr yet empty
6464 : // CouplingMatrices.
6465 61753 : if (n_vars == 0)
6466 12266 : nl->dofMap()._dof_coupling = nullptr;
6467 :
6468 61753 : nl->dofMap().attach_extra_sparsity_function(&extraSparsity, nl.get());
6469 61753 : nl->dofMap().attach_extra_send_list_function(&extraSendList, nl.get());
6470 61753 : _aux->dofMap().attach_extra_send_list_function(&extraSendList, _aux.get());
6471 :
6472 61753 : if (!_skip_nl_system_check && _solve && n_vars == 0)
6473 0 : mooseError("No variables specified in nonlinear system '", nl->name(), "'.");
6474 : }
6475 :
6476 62818 : ghostGhostedBoundaries(); // We do this again right here in case new boundaries have been added
6477 :
6478 : // We may have added element/nodes to the mesh in ghostGhostedBoundaries so we need to update
6479 : // all of our mesh information. We need to make sure that mesh information is up-to-date before
6480 : // EquationSystems::init because that will call through to updateGeomSearch (for sparsity
6481 : // augmentation) and if we haven't added back boundary node information before that latter call,
6482 : // then we're screwed. We'll get things like "Unable to find closest node!"
6483 62818 : _mesh.meshChanged();
6484 62818 : if (_displaced_problem)
6485 2246 : _displaced_mesh->meshChanged();
6486 :
6487 62818 : if (_mesh.doingPRefinement())
6488 : {
6489 234 : preparePRefinement();
6490 234 : if (_displaced_problem)
6491 0 : _displaced_problem->preparePRefinement();
6492 : }
6493 :
6494 : // do not assemble system matrix for JFNK solve
6495 124571 : for (auto & nl : _nl)
6496 61753 : if (solverParams(nl->number())._type == Moose::ST_JFNK)
6497 139 : nl->turnOffJacobian();
6498 :
6499 125911 : for (auto & sys : _solver_systems)
6500 63093 : sys->preInit();
6501 62818 : _aux->preInit();
6502 :
6503 : // Build the mortar segment meshes, if they haven't been already, for a couple reasons:
6504 : // 1) Get the ghosting correct for both static and dynamic meshes
6505 : // 2) Make sure the mortar mesh is built for mortar constraints that live on the static mesh
6506 : //
6507 : // It is worth-while to note that mortar meshes that live on a dynamic mesh will be built
6508 : // during residual and Jacobian evaluation because when displacements are solution variables
6509 : // the mortar mesh will move and change during the course of a non-linear solve. We DO NOT
6510 : // redo ghosting during non-linear solve, so for purpose 1) the below call has to be made
6511 62818 : if (!_mortar_data->initialized())
6512 46566 : updateMortarMesh();
6513 :
6514 : {
6515 314090 : TIME_SECTION("EquationSystems::Init", 2, "Initializing Equation Systems");
6516 62818 : es().init();
6517 62818 : }
6518 :
6519 125911 : for (auto & sys : _solver_systems)
6520 63093 : sys->postInit();
6521 62818 : _aux->postInit();
6522 :
6523 : // Now that the equation system and the dof distribution is done, we can generate the
6524 : // finite volume-related parts if needed.
6525 62818 : if (haveFV())
6526 5407 : _mesh.setupFiniteVolumeMeshData();
6527 :
6528 125911 : for (auto & sys : _solver_systems)
6529 63093 : sys->update();
6530 62818 : _aux->update();
6531 :
6532 131517 : for (THREAD_ID tid = 0; tid < libMesh::n_threads(); ++tid)
6533 136350 : for (const auto i : index_range(_nl))
6534 : {
6535 : mooseAssert(
6536 : _cm[i],
6537 : "Coupling matrix not set for system "
6538 : << i
6539 : << ". This should only happen if a preconditioner was not setup for this system");
6540 67651 : _assembly[tid][i]->init(_cm[i].get());
6541 : }
6542 :
6543 62818 : if (_displaced_problem)
6544 2246 : _displaced_problem->init();
6545 :
6546 : #ifdef MOOSE_KOKKOS_ENABLED
6547 42075 : if (_has_kokkos_objects)
6548 807 : initKokkos();
6549 : #endif
6550 :
6551 62818 : _initialized = true;
6552 62818 : }
6553 :
6554 : unsigned int
6555 13677 : FEProblemBase::nlSysNum(const NonlinearSystemName & nl_sys_name) const
6556 : {
6557 13677 : std::istringstream ss(nl_sys_name);
6558 : unsigned int nl_sys_num;
6559 13677 : if (!(ss >> nl_sys_num) || !ss.eof())
6560 13677 : nl_sys_num = libmesh_map_find(_nl_sys_name_to_num, nl_sys_name);
6561 :
6562 13677 : return nl_sys_num;
6563 13677 : }
6564 :
6565 : unsigned int
6566 39884 : FEProblemBase::linearSysNum(const LinearSystemName & linear_sys_name) const
6567 : {
6568 39884 : std::istringstream ss(linear_sys_name);
6569 : unsigned int linear_sys_num;
6570 39884 : if (!(ss >> linear_sys_num) || !ss.eof())
6571 39884 : linear_sys_num = libmesh_map_find(_linear_sys_name_to_num, linear_sys_name);
6572 :
6573 39884 : return linear_sys_num;
6574 39884 : }
6575 :
6576 : unsigned int
6577 130973 : FEProblemBase::solverSysNum(const SolverSystemName & solver_sys_name) const
6578 : {
6579 130973 : std::istringstream ss(solver_sys_name);
6580 : unsigned int solver_sys_num;
6581 130973 : if (!(ss >> solver_sys_num) || !ss.eof())
6582 : {
6583 130973 : const auto & search = _solver_sys_name_to_num.find(solver_sys_name);
6584 130973 : if (search == _solver_sys_name_to_num.end())
6585 0 : mooseError("The solver system number was requested for system '" + solver_sys_name,
6586 : "' but this system does not exist in the Problem. Systems can be added to the "
6587 : "problem using the 'nl_sys_names'/'linear_sys_names' parameter.\nSystems in the "
6588 0 : "Problem: " +
6589 0 : Moose::stringify(_solver_sys_names));
6590 130973 : solver_sys_num = search->second;
6591 : }
6592 :
6593 130973 : return solver_sys_num;
6594 130973 : }
6595 :
6596 : unsigned int
6597 1641 : FEProblemBase::systemNumForVariable(const VariableName & variable_name) const
6598 : {
6599 1752 : for (const auto & solver_sys : _solver_systems)
6600 1641 : if (solver_sys->hasVariable(variable_name))
6601 1530 : return solver_sys->number();
6602 : mooseAssert(_aux, "Should have an auxiliary system");
6603 111 : if (_aux->hasVariable(variable_name))
6604 111 : return _aux->number();
6605 :
6606 0 : mooseError("Variable '",
6607 : variable_name,
6608 : "' was not found in any solver (nonlinear/linear) or auxiliary system");
6609 : }
6610 :
6611 : void
6612 348755 : FEProblemBase::solve(const unsigned int nl_sys_num)
6613 : {
6614 1743775 : TIME_SECTION("solve", 1, "Solving", false);
6615 :
6616 348755 : setCurrentNonlinearSystem(nl_sys_num);
6617 :
6618 : // This prevents stale dof indices from lingering around and possibly leading to invalid reads
6619 : // and writes. Dof indices may be made stale through operations like mesh adaptivity
6620 348755 : clearAllDofIndices();
6621 348755 : if (_displaced_problem)
6622 35869 : _displaced_problem->clearAllDofIndices();
6623 :
6624 : // Setup the output system for printing linear/nonlinear iteration information and some solver
6625 : // settings, including setting matrix prefixes. This must occur before petscSetOptions
6626 348755 : initPetscOutputAndSomeSolverSettings();
6627 :
6628 : #if PETSC_RELEASE_LESS_THAN(3, 12, 0)
6629 : Moose::PetscSupport::petscSetOptions(
6630 : _petsc_options, _solver_params); // Make sure the PETSc options are setup for this app
6631 : #else
6632 : // Now this database will be the default
6633 : // Each app should have only one database
6634 348755 : if (!_app.isUltimateMaster())
6635 89156 : LibmeshPetscCall(PetscOptionsPush(_petsc_option_data_base));
6636 : // We did not add PETSc options to database yet
6637 348755 : if (!_is_petsc_options_inserted)
6638 : {
6639 : // Insert options for all systems all at once
6640 42295 : Moose::PetscSupport::petscSetOptions(_petsc_options, _solver_params, this);
6641 42295 : _is_petsc_options_inserted = true;
6642 : }
6643 : #endif
6644 :
6645 : // set up DM which is required if use a field split preconditioner
6646 : // We need to setup DM every "solve()" because libMesh destroy SNES after solve()
6647 : // Do not worry, DM setup is very cheap
6648 348755 : _current_nl_sys->setupDM();
6649 :
6650 348755 : possiblyRebuildGeomSearchPatches();
6651 :
6652 : // reset flag so that residual evaluation does not get skipped
6653 : // and the next non-linear iteration does not automatically fail with
6654 : // "DIVERGED_NANORINF", when we throw an exception and stop solve
6655 348755 : _fail_next_system_convergence_check = false;
6656 :
6657 348755 : if (_solve)
6658 : {
6659 317289 : _current_nl_sys->solve();
6660 317209 : _current_nl_sys->update();
6661 : }
6662 :
6663 : // sync solutions in displaced problem
6664 348675 : if (_displaced_problem)
6665 35865 : _displaced_problem->syncSolutions();
6666 :
6667 : #if !PETSC_RELEASE_LESS_THAN(3, 12, 0)
6668 348675 : if (!_app.isUltimateMaster())
6669 89156 : LibmeshPetscCall(PetscOptionsPop());
6670 : #endif
6671 348675 : }
6672 :
6673 : void
6674 214 : FEProblemBase::setException(const std::string & message)
6675 : {
6676 214 : _has_exception = true;
6677 214 : _exception_message = message;
6678 214 : }
6679 :
6680 : void
6681 21844430 : FEProblemBase::checkExceptionAndStopSolve(bool print_message)
6682 : {
6683 21844430 : if (_skip_exception_check)
6684 240 : return;
6685 :
6686 65532570 : TIME_SECTION("checkExceptionAndStopSolve", 5);
6687 :
6688 : // See if any processor had an exception. If it did, get back the
6689 : // processor that the exception occurred on.
6690 : unsigned int processor_id;
6691 :
6692 21844190 : _communicator.maxloc(_has_exception, processor_id);
6693 :
6694 21844190 : if (_has_exception)
6695 : {
6696 337 : _communicator.broadcast(_exception_message, processor_id);
6697 :
6698 451 : if (_current_execute_on_flag == EXEC_LINEAR || _current_execute_on_flag == EXEC_NONLINEAR ||
6699 114 : _current_execute_on_flag == EXEC_POSTCHECK)
6700 : {
6701 : // Print the message
6702 337 : if (_communicator.rank() == 0 && print_message)
6703 : {
6704 197 : _console << "\n" << _exception_message << "\n";
6705 197 : if (isTransient())
6706 : _console
6707 : << "To recover, the solution will fail and then be re-attempted with a reduced time "
6708 180 : "step.\n"
6709 180 : << std::endl;
6710 : }
6711 :
6712 : // Stop the solve -- this entails setting
6713 : // SNESSetFunctionDomainError() or directly inserting NaNs in the
6714 : // residual vector to let PETSc >= 3.6 return DIVERGED_NANORINF.
6715 337 : if (_current_nl_sys)
6716 337 : _current_nl_sys->stopSolve(_current_execute_on_flag, _fe_vector_tags);
6717 :
6718 337 : if (_current_linear_sys)
6719 0 : _current_linear_sys->stopSolve(_current_execute_on_flag, _fe_vector_tags);
6720 :
6721 : // and close Aux system (we MUST do this here; see #11525)
6722 337 : _aux->solution().close();
6723 :
6724 : // We've handled this exception, so we no longer have one.
6725 337 : _has_exception = false;
6726 :
6727 : // Force the next non-linear convergence check to fail (and all further residual evaluation
6728 : // to be skipped).
6729 337 : _fail_next_system_convergence_check = true;
6730 :
6731 : // Repropagate the exception, so it can be caught at a higher level, typically
6732 : // this is NonlinearSystem::computeResidual().
6733 337 : throw MooseException(_exception_message);
6734 : }
6735 : else
6736 0 : mooseError("The following parallel-communicated exception was detected during " +
6737 0 : Moose::stringify(_current_execute_on_flag) + " evaluation:\n" +
6738 0 : _exception_message +
6739 : "\nBecause this did not occur during residual evaluation, there"
6740 : " is no way to handle this, so the solution is aborting.\n");
6741 : }
6742 21844190 : }
6743 :
6744 : void
6745 3887425 : FEProblemBase::resetState()
6746 : {
6747 : // Our default state is to allow computing derivatives
6748 3887425 : ADReal::do_derivatives = true;
6749 3887425 : _current_execute_on_flag = EXEC_NONE;
6750 :
6751 : // Clear the VectorTags and MatrixTags
6752 3887425 : clearCurrentResidualVectorTags();
6753 3887425 : clearCurrentJacobianMatrixTags();
6754 :
6755 3887425 : _safe_access_tagged_vectors = true;
6756 3887425 : _safe_access_tagged_matrices = true;
6757 :
6758 3887425 : setCurrentlyComputingResidual(false);
6759 3887425 : setCurrentlyComputingJacobian(false);
6760 3887425 : setCurrentlyComputingResidualAndJacobian(false);
6761 3887425 : if (_displaced_problem)
6762 : {
6763 160528 : _displaced_problem->setCurrentlyComputingResidual(false);
6764 160528 : _displaced_problem->setCurrentlyComputingJacobian(false);
6765 160528 : _displaced_problem->setCurrentlyComputingResidualAndJacobian(false);
6766 : }
6767 3887425 : }
6768 :
6769 : void
6770 5648 : FEProblemBase::solveLinearSystem(const unsigned int linear_sys_num,
6771 : const Moose::PetscSupport::PetscOptions * po)
6772 : {
6773 28240 : TIME_SECTION("solve", 1, "Solving", false);
6774 :
6775 5648 : setCurrentLinearSystem(linear_sys_num);
6776 :
6777 5648 : const Moose::PetscSupport::PetscOptions & options = po ? *po : _petsc_options;
6778 5648 : auto & solver_params = _solver_params[numNonlinearSystems() + linear_sys_num];
6779 :
6780 : // Set custom convergence criteria
6781 5648 : Moose::PetscSupport::petscSetDefaults(*this);
6782 :
6783 : #if PETSC_RELEASE_LESS_THAN(3, 12, 0)
6784 : LibmeshPetscCall(Moose::PetscSupport::petscSetOptions(
6785 : options, solver_params)); // Make sure the PETSc options are setup for this app
6786 : #else
6787 : // Now this database will be the default
6788 : // Each app should have only one database
6789 5648 : if (!_app.isUltimateMaster())
6790 235 : LibmeshPetscCall(PetscOptionsPush(_petsc_option_data_base));
6791 :
6792 : // We did not add PETSc options to database yet
6793 5648 : if (!_is_petsc_options_inserted)
6794 : {
6795 1257 : Moose::PetscSupport::petscSetOptions(options, solver_params, this);
6796 1257 : _is_petsc_options_inserted = true;
6797 : }
6798 : #endif
6799 :
6800 5648 : if (_solve)
6801 5636 : _current_linear_sys->solve();
6802 :
6803 : #if !PETSC_RELEASE_LESS_THAN(3, 12, 0)
6804 5648 : if (!_app.isUltimateMaster())
6805 235 : LibmeshPetscCall(PetscOptionsPop());
6806 : #endif
6807 5648 : }
6808 :
6809 : bool
6810 346130 : FEProblemBase::solverSystemConverged(const unsigned int sys_num)
6811 : {
6812 346130 : if (_solve)
6813 346106 : return _solver_systems[sys_num]->converged();
6814 : else
6815 24 : return true;
6816 : }
6817 :
6818 : unsigned int
6819 6328 : FEProblemBase::nNonlinearIterations(const unsigned int nl_sys_num) const
6820 : {
6821 6328 : return _nl[nl_sys_num]->nNonlinearIterations();
6822 : }
6823 :
6824 : unsigned int
6825 5425 : FEProblemBase::nLinearIterations(const unsigned int nl_sys_num) const
6826 : {
6827 5425 : return _nl[nl_sys_num]->nLinearIterations();
6828 : }
6829 :
6830 : Real
6831 258 : FEProblemBase::finalNonlinearResidual(const unsigned int nl_sys_num) const
6832 : {
6833 258 : return _nl[nl_sys_num]->finalNonlinearResidual();
6834 : }
6835 :
6836 : bool
6837 845824 : FEProblemBase::computingPreSMOResidual(const unsigned int nl_sys_num) const
6838 : {
6839 845824 : return _nl[nl_sys_num]->computingPreSMOResidual();
6840 : }
6841 :
6842 : void
6843 57333 : FEProblemBase::copySolutionsBackwards()
6844 : {
6845 286665 : TIME_SECTION("copySolutionsBackwards", 3, "Copying Solutions Backward");
6846 :
6847 114923 : for (auto & sys : _solver_systems)
6848 57590 : sys->copySolutionsBackwards();
6849 57333 : _aux->copySolutionsBackwards();
6850 57333 : }
6851 :
6852 : void
6853 250366 : FEProblemBase::advanceState()
6854 : {
6855 1251830 : TIME_SECTION("advanceState", 5, "Advancing State");
6856 :
6857 504391 : for (auto & sys : _solver_systems)
6858 254025 : sys->copyOldSolutions();
6859 250366 : _aux->copyOldSolutions();
6860 :
6861 250366 : if (_displaced_problem)
6862 : {
6863 67642 : for (const auto i : index_range(_solver_systems))
6864 33821 : _displaced_problem->solverSys(i).copyOldSolutions();
6865 33821 : _displaced_problem->auxSys().copyOldSolutions();
6866 : }
6867 :
6868 250366 : _reporter_data.copyValuesBack();
6869 :
6870 250366 : getMooseApp().getChainControlDataSystem().copyValuesBack();
6871 :
6872 250366 : if (_material_props.hasStatefulProperties())
6873 1970 : _material_props.shift();
6874 :
6875 250366 : if (_bnd_material_props.hasStatefulProperties())
6876 1816 : _bnd_material_props.shift();
6877 :
6878 250366 : if (_neighbor_material_props.hasStatefulProperties())
6879 1682 : _neighbor_material_props.shift();
6880 :
6881 : #ifdef MOOSE_KOKKOS_ENABLED
6882 164730 : if (_kokkos_material_props.hasStatefulProperties())
6883 376 : _kokkos_material_props.shift();
6884 :
6885 164730 : if (_kokkos_bnd_material_props.hasStatefulProperties())
6886 426 : _kokkos_bnd_material_props.shift();
6887 :
6888 164730 : if (_kokkos_neighbor_material_props.hasStatefulProperties())
6889 376 : _kokkos_neighbor_material_props.shift();
6890 : #endif
6891 250366 : }
6892 :
6893 : void
6894 5375 : FEProblemBase::restoreSolutions()
6895 : {
6896 26875 : TIME_SECTION("restoreSolutions", 5, "Restoring Solutions");
6897 :
6898 5375 : if (!_not_zeroed_tagged_vectors.empty())
6899 0 : paramError("not_zeroed_tag_vectors",
6900 : "There is currently no way to restore not-zeroed vectors.");
6901 :
6902 10752 : for (auto & sys : _solver_systems)
6903 : {
6904 5377 : if (_verbose_restore)
6905 395 : _console << "Restoring solutions on system " << sys->name() << "..." << std::endl;
6906 5377 : sys->restoreSolutions();
6907 : }
6908 :
6909 5375 : if (_verbose_restore)
6910 394 : _console << "Restoring solutions on Auxiliary system..." << std::endl;
6911 5375 : _aux->restoreSolutions();
6912 :
6913 5375 : if (_verbose_restore)
6914 394 : _console << "Restoring postprocessor, vector-postprocessor, and reporter data..." << std::endl;
6915 5375 : _reporter_data.restoreState(_verbose_restore);
6916 :
6917 5375 : if (_displaced_problem)
6918 136 : _displaced_problem->updateMesh();
6919 5375 : }
6920 :
6921 : void
6922 115 : FEProblemBase::saveOldSolutions()
6923 : {
6924 575 : TIME_SECTION("saveOldSolutions", 5, "Saving Old Solutions");
6925 :
6926 230 : for (auto & sys : _solver_systems)
6927 115 : sys->saveOldSolutions();
6928 115 : _aux->saveOldSolutions();
6929 115 : }
6930 :
6931 : void
6932 115 : FEProblemBase::restoreOldSolutions()
6933 : {
6934 575 : TIME_SECTION("restoreOldSolutions", 5, "Restoring Old Solutions");
6935 :
6936 230 : for (auto & sys : _solver_systems)
6937 115 : sys->restoreOldSolutions();
6938 115 : _aux->restoreOldSolutions();
6939 115 : }
6940 :
6941 : void
6942 1337403 : FEProblemBase::outputStep(ExecFlagType type)
6943 : {
6944 6687015 : TIME_SECTION("outputStep", 1, "Outputting");
6945 :
6946 1337403 : setCurrentExecuteOnFlag(type);
6947 :
6948 2690250 : for (auto & sys : _solver_systems)
6949 1352847 : sys->update();
6950 1337403 : _aux->update();
6951 :
6952 1337403 : if (_displaced_problem)
6953 138047 : _displaced_problem->syncSolutions();
6954 1337403 : _app.getOutputWarehouse().outputStep(type);
6955 :
6956 1337391 : setCurrentExecuteOnFlag(EXEC_NONE);
6957 1337391 : }
6958 :
6959 : void
6960 89528 : FEProblemBase::allowOutput(bool state)
6961 : {
6962 89528 : _app.getOutputWarehouse().allowOutput(state);
6963 89528 : }
6964 :
6965 : void
6966 25 : FEProblemBase::forceOutput()
6967 : {
6968 25 : _app.getOutputWarehouse().forceOutput();
6969 25 : }
6970 :
6971 : void
6972 369759 : FEProblemBase::initPetscOutputAndSomeSolverSettings()
6973 : {
6974 369759 : _app.getOutputWarehouse().solveSetup();
6975 369759 : Moose::PetscSupport::petscSetDefaults(*this);
6976 369759 : }
6977 :
6978 : void
6979 259910 : FEProblemBase::onTimestepBegin()
6980 : {
6981 779730 : TIME_SECTION("onTimestepBegin", 2);
6982 :
6983 523192 : for (auto & nl : _nl)
6984 263282 : nl->onTimestepBegin();
6985 259910 : }
6986 :
6987 : void
6988 335230 : FEProblemBase::onTimestepEnd()
6989 : {
6990 335230 : }
6991 :
6992 : Real
6993 8145249 : FEProblemBase::getTimeFromStateArg(const Moose::StateArg & state) const
6994 : {
6995 8145249 : if (state.iteration_type != Moose::SolutionIterationType::Time)
6996 : // If we are any iteration type other than time (e.g. nonlinear), then temporally we are still
6997 : // in the present time
6998 0 : return time();
6999 :
7000 8145249 : switch (state.state)
7001 : {
7002 8145249 : case 0:
7003 8145249 : return time();
7004 :
7005 0 : case 1:
7006 0 : return timeOld();
7007 :
7008 0 : default:
7009 0 : mooseError("Unhandled state ", state.state, " in FEProblemBase::getTimeFromStateArg");
7010 : }
7011 : }
7012 :
7013 : void
7014 32125 : FEProblemBase::addTimeIntegrator(const std::string & type,
7015 : const std::string & name,
7016 : InputParameters & parameters)
7017 : {
7018 : parallel_object_only();
7019 :
7020 96375 : parameters.set<SubProblem *>("_subproblem") = this;
7021 32125 : logAdd("TimeIntegrator", name, type, parameters);
7022 32125 : _aux->addTimeIntegrator(type, name + ":aux", parameters);
7023 64284 : for (auto & sys : _solver_systems)
7024 32159 : sys->addTimeIntegrator(type, name + ":" + sys->name(), parameters);
7025 32125 : _has_time_integrator = true;
7026 :
7027 : // add vectors to store u_dot, u_dotdot, udot_old, u_dotdot_old and
7028 : // solution vectors older than 2 time steps, if requested by the time
7029 : // integrator
7030 32125 : _aux->addDotVectors();
7031 64258 : for (auto & nl : _nl)
7032 : {
7033 32133 : nl->addDotVectors();
7034 :
7035 32133 : auto tag_udot = nl->getTimeIntegrators()[0]->uDotFactorTag();
7036 32133 : if (!nl->hasVector(tag_udot))
7037 32075 : nl->associateVectorToTag(*nl->solutionUDot(), tag_udot);
7038 32133 : auto tag_udotdot = nl->getTimeIntegrators()[0]->uDotDotFactorTag();
7039 32133 : if (!nl->hasVector(tag_udotdot) && uDotDotRequested())
7040 164 : nl->associateVectorToTag(*nl->solutionUDotDot(), tag_udotdot);
7041 : }
7042 :
7043 32125 : if (_displaced_problem)
7044 : // Time integrator does not exist when displaced problem is created.
7045 1908 : _displaced_problem->addTimeIntegrator();
7046 32125 : }
7047 :
7048 : void
7049 24 : FEProblemBase::addPredictor(const std::string & type,
7050 : const std::string & name,
7051 : InputParameters & parameters)
7052 : {
7053 : parallel_object_only();
7054 :
7055 24 : if (!numNonlinearSystems() && numLinearSystems())
7056 0 : mooseError("Vector bounds cannot be used with LinearSystems!");
7057 :
7058 48 : parameters.set<SubProblem *>("_subproblem") = this;
7059 24 : std::shared_ptr<Predictor> predictor = _factory.create<Predictor>(type, name, parameters);
7060 24 : logAdd("Predictor", name, type, parameters);
7061 :
7062 48 : for (auto & nl : _nl)
7063 24 : nl->setPredictor(predictor);
7064 24 : }
7065 :
7066 : Real
7067 67294 : FEProblemBase::computeResidualL2Norm(NonlinearSystemBase & sys)
7068 : {
7069 67294 : _current_nl_sys = &sys;
7070 67294 : computeResidual(*sys.currentSolution(), sys.RHS(), sys.number());
7071 67294 : return sys.RHS().l2_norm();
7072 : }
7073 :
7074 : Real
7075 102 : FEProblemBase::computeResidualL2Norm(LinearSystem & sys)
7076 : {
7077 102 : _current_linear_sys = &sys;
7078 :
7079 : // We assemble the current system to check the current residual
7080 102 : computeLinearSystemSys(sys.linearImplicitSystem(),
7081 102 : *sys.linearImplicitSystem().matrix,
7082 102 : *sys.linearImplicitSystem().rhs,
7083 : /*compute fresh gradients*/ true);
7084 :
7085 : // Unfortunate, but we have to allocate a new vector for the residual
7086 102 : auto residual = sys.linearImplicitSystem().rhs->clone();
7087 102 : residual->scale(-1.0);
7088 102 : residual->add_vector(*sys.currentSolution(), *sys.linearImplicitSystem().matrix);
7089 204 : return residual->l2_norm();
7090 102 : }
7091 :
7092 : Real
7093 67360 : FEProblemBase::computeResidualL2Norm()
7094 : {
7095 336800 : TIME_SECTION("computeResidualL2Norm", 2, "Computing L2 Norm of Residual");
7096 :
7097 : // We use sum the squared norms of the individual systems and then take the square root of it
7098 67360 : Real l2_norm = 0.0;
7099 134654 : for (auto sys : _nl)
7100 : {
7101 67294 : const auto norm = computeResidualL2Norm(*sys);
7102 67294 : l2_norm += norm * norm;
7103 67294 : }
7104 :
7105 67462 : for (auto sys : _linear_systems)
7106 : {
7107 102 : const auto norm = computeResidualL2Norm(*sys);
7108 102 : l2_norm += norm * norm;
7109 102 : }
7110 :
7111 134720 : return std::sqrt(l2_norm);
7112 67360 : }
7113 :
7114 : void
7115 3242832 : FEProblemBase::computeResidualSys(NonlinearImplicitSystem & sys,
7116 : const NumericVector<Number> & soln,
7117 : NumericVector<Number> & residual)
7118 : {
7119 : parallel_object_only();
7120 :
7121 9728496 : TIME_SECTION("computeResidualSys", 5);
7122 :
7123 3242832 : computeResidual(soln, residual, sys.number());
7124 3242788 : }
7125 :
7126 : void
7127 0 : FEProblemBase::computeResidual(NonlinearImplicitSystem & sys,
7128 : const NumericVector<Number> & soln,
7129 : NumericVector<Number> & residual)
7130 : {
7131 0 : mooseDeprecated("Please use computeResidualSys");
7132 :
7133 0 : computeResidualSys(sys, soln, residual);
7134 0 : }
7135 :
7136 : void
7137 3306013 : FEProblemBase::computeResidual(const NumericVector<Number> & soln,
7138 : NumericVector<Number> & residual,
7139 : const unsigned int nl_sys_num)
7140 : {
7141 3306013 : setCurrentNonlinearSystem(nl_sys_num);
7142 :
7143 : // We associate the residual tag with the given residual vector to make sure we
7144 : // don't filter it out below
7145 3306013 : _current_nl_sys->associateVectorToTag(residual, _current_nl_sys->residualVectorTag());
7146 3306013 : const auto & residual_vector_tags = getVectorTags(Moose::VECTOR_TAG_RESIDUAL);
7147 :
7148 : mooseAssert(_fe_vector_tags.empty(), "This should be empty indicating a clean starting state");
7149 : // We filter out tags which do not have associated vectors in the current nonlinear
7150 : // system. This is essential to be able to use system-dependent residual tags.
7151 3306013 : selectVectorTagsFromSystem(*_current_nl_sys, residual_vector_tags, _fe_vector_tags);
7152 :
7153 3306013 : computeResidualInternal(soln, residual, _fe_vector_tags);
7154 3305969 : _fe_vector_tags.clear();
7155 3305969 : }
7156 :
7157 : void
7158 3467 : FEProblemBase::computeResidualAndJacobian(const NumericVector<Number> & soln,
7159 : NumericVector<Number> & residual,
7160 : SparseMatrix<Number> & jacobian)
7161 : {
7162 : try
7163 : {
7164 : try
7165 : {
7166 : // vector tags
7167 3467 : _current_nl_sys->associateVectorToTag(residual, _current_nl_sys->residualVectorTag());
7168 3467 : const auto & residual_vector_tags = getVectorTags(Moose::VECTOR_TAG_RESIDUAL);
7169 :
7170 : mooseAssert(_fe_vector_tags.empty(),
7171 : "This should be empty indicating a clean starting state");
7172 : // We filter out tags which do not have associated vectors in the current nonlinear
7173 : // system. This is essential to be able to use system-dependent residual tags.
7174 3467 : selectVectorTagsFromSystem(*_current_nl_sys, residual_vector_tags, _fe_vector_tags);
7175 :
7176 3467 : setCurrentResidualVectorTags(_fe_vector_tags);
7177 :
7178 : // matrix tags
7179 : {
7180 3467 : _fe_matrix_tags.clear();
7181 :
7182 3467 : auto & tags = getMatrixTags();
7183 10401 : for (auto & tag : tags)
7184 6934 : _fe_matrix_tags.insert(tag.second);
7185 : }
7186 :
7187 3467 : _current_nl_sys->setSolution(soln);
7188 :
7189 3467 : _current_nl_sys->associateVectorToTag(residual, _current_nl_sys->residualVectorTag());
7190 3467 : _current_nl_sys->associateMatrixToTag(jacobian, _current_nl_sys->systemMatrixTag());
7191 :
7192 10401 : for (const auto tag : _fe_matrix_tags)
7193 6934 : if (_current_nl_sys->hasMatrix(tag))
7194 : {
7195 3467 : auto & matrix = _current_nl_sys->getMatrix(tag);
7196 3467 : matrix.zero();
7197 3467 : if (haveADObjects() && !_current_nl_sys->system().has_static_condensation())
7198 : // PETSc algorithms require diagonal allocations regardless of whether there is non-zero
7199 : // diagonal dependence. With global AD indexing we only add non-zero
7200 : // dependence, so PETSc will scream at us unless we artificially add the diagonals.
7201 139927 : for (auto index : make_range(matrix.row_start(), matrix.row_stop()))
7202 136580 : matrix.add(index, index, 0);
7203 : }
7204 :
7205 3467 : _aux->zeroVariablesForResidual();
7206 :
7207 3467 : unsigned int n_threads = libMesh::n_threads();
7208 :
7209 3467 : _current_execute_on_flag = EXEC_LINEAR;
7210 :
7211 : // Random interface objects
7212 3467 : for (const auto & it : _random_data_objects)
7213 0 : it.second->updateSeeds(EXEC_LINEAR);
7214 :
7215 3467 : setCurrentlyComputingResidual(true);
7216 3467 : setCurrentlyComputingJacobian(true);
7217 3467 : setCurrentlyComputingResidualAndJacobian(true);
7218 3467 : if (_displaced_problem)
7219 : {
7220 1172 : _displaced_problem->setCurrentlyComputingResidual(true);
7221 1172 : _displaced_problem->setCurrentlyComputingJacobian(true);
7222 1172 : _displaced_problem->setCurrentlyComputingResidualAndJacobian(true);
7223 : }
7224 :
7225 3467 : execTransfers(EXEC_LINEAR);
7226 :
7227 3467 : execMultiApps(EXEC_LINEAR);
7228 :
7229 7273 : for (unsigned int tid = 0; tid < n_threads; tid++)
7230 3806 : reinitScalars(tid);
7231 :
7232 3467 : computeUserObjects(EXEC_LINEAR, Moose::PRE_AUX);
7233 :
7234 3467 : _aux->residualSetup();
7235 :
7236 3467 : if (_displaced_problem)
7237 : {
7238 1172 : computeSystems(EXEC_PRE_DISPLACE);
7239 1172 : _displaced_problem->updateMesh();
7240 1172 : if (_mortar_data->hasDisplacedObjects())
7241 1172 : updateMortarMesh();
7242 : }
7243 :
7244 7273 : for (THREAD_ID tid = 0; tid < n_threads; tid++)
7245 : {
7246 3806 : _all_materials.residualSetup(tid);
7247 3806 : _functions.residualSetup(tid);
7248 : }
7249 :
7250 : #ifdef MOOSE_KOKKOS_ENABLED
7251 2165 : _kokkos_functions.residualSetup();
7252 : #endif
7253 :
7254 3467 : computeSystems(EXEC_LINEAR);
7255 :
7256 3467 : computeUserObjects(EXEC_LINEAR, Moose::POST_AUX);
7257 :
7258 3467 : executeControls(EXEC_LINEAR);
7259 :
7260 3467 : _app.getOutputWarehouse().residualSetup();
7261 :
7262 3467 : _safe_access_tagged_vectors = false;
7263 3467 : _safe_access_tagged_matrices = false;
7264 :
7265 3467 : _current_nl_sys->computeResidualAndJacobianTags(_fe_vector_tags, _fe_matrix_tags);
7266 :
7267 3467 : _current_nl_sys->disassociateMatrixFromTag(jacobian, _current_nl_sys->systemMatrixTag());
7268 3467 : _current_nl_sys->disassociateVectorFromTag(residual, _current_nl_sys->residualVectorTag());
7269 : }
7270 0 : catch (...)
7271 : {
7272 0 : handleException("computeResidualAndJacobian");
7273 0 : }
7274 : }
7275 0 : catch (const MooseException &)
7276 : {
7277 : // The buck stops here, we have already handled the exception by
7278 : // calling the system's stopSolve() method, it is now up to PETSc to return a
7279 : // "diverged" reason during the next solve.
7280 0 : }
7281 0 : catch (...)
7282 : {
7283 0 : mooseError("Unexpected exception type");
7284 0 : }
7285 :
7286 3467 : resetState();
7287 3467 : _fe_vector_tags.clear();
7288 3467 : _fe_matrix_tags.clear();
7289 3467 : }
7290 :
7291 : void
7292 0 : FEProblemBase::computeResidualTag(const NumericVector<Number> & soln,
7293 : NumericVector<Number> & residual,
7294 : TagID tag)
7295 : {
7296 : try
7297 : {
7298 0 : _current_nl_sys->setSolution(soln);
7299 :
7300 0 : _current_nl_sys->associateVectorToTag(residual, tag);
7301 :
7302 0 : computeResidualTags({tag});
7303 :
7304 0 : _current_nl_sys->disassociateVectorFromTag(residual, tag);
7305 : }
7306 0 : catch (MooseException & e)
7307 : {
7308 : // If a MooseException propagates all the way to here, it means
7309 : // that it was thrown from a MOOSE system where we do not
7310 : // (currently) properly support the throwing of exceptions, and
7311 : // therefore we have no choice but to error out. It may be
7312 : // *possible* to handle exceptions from other systems, but in the
7313 : // meantime, we don't want to silently swallow any unhandled
7314 : // exceptions here.
7315 0 : mooseError("An unhandled MooseException was raised during residual computation. Please "
7316 : "contact the MOOSE team for assistance.");
7317 0 : }
7318 0 : }
7319 :
7320 : void
7321 3311617 : FEProblemBase::computeResidualInternal(const NumericVector<Number> & soln,
7322 : NumericVector<Number> & residual,
7323 : const std::set<TagID> & tags)
7324 : {
7325 : parallel_object_only();
7326 :
7327 9934851 : TIME_SECTION("computeResidualInternal", 1);
7328 :
7329 : try
7330 : {
7331 3311617 : _current_nl_sys->setSolution(soln);
7332 :
7333 3311617 : _current_nl_sys->associateVectorToTag(residual, _current_nl_sys->residualVectorTag());
7334 :
7335 3311617 : computeResidualTags(tags);
7336 :
7337 3311573 : _current_nl_sys->disassociateVectorFromTag(residual, _current_nl_sys->residualVectorTag());
7338 : }
7339 0 : catch (MooseException & e)
7340 : {
7341 : // If a MooseException propagates all the way to here, it means
7342 : // that it was thrown from a MOOSE system where we do not
7343 : // (currently) properly support the throwing of exceptions, and
7344 : // therefore we have no choice but to error out. It may be
7345 : // *possible* to handle exceptions from other systems, but in the
7346 : // meantime, we don't want to silently swallow any unhandled
7347 : // exceptions here.
7348 0 : mooseError("An unhandled MooseException was raised during residual computation. Please "
7349 : "contact the MOOSE team for assistance.");
7350 0 : }
7351 3311573 : }
7352 :
7353 : void
7354 0 : FEProblemBase::computeResidualType(const NumericVector<Number> & soln,
7355 : NumericVector<Number> & residual,
7356 : TagID tag)
7357 : {
7358 0 : TIME_SECTION("computeResidualType", 5);
7359 :
7360 : try
7361 : {
7362 0 : _current_nl_sys->setSolution(soln);
7363 :
7364 0 : _current_nl_sys->associateVectorToTag(residual, _current_nl_sys->residualVectorTag());
7365 :
7366 0 : computeResidualTags({tag, _current_nl_sys->residualVectorTag()});
7367 :
7368 0 : _current_nl_sys->disassociateVectorFromTag(residual, _current_nl_sys->residualVectorTag());
7369 : }
7370 0 : catch (MooseException & e)
7371 : {
7372 : // If a MooseException propagates all the way to here, it means
7373 : // that it was thrown from a MOOSE system where we do not
7374 : // (currently) properly support the throwing of exceptions, and
7375 : // therefore we have no choice but to error out. It may be
7376 : // *possible* to handle exceptions from other systems, but in the
7377 : // meantime, we don't want to silently swallow any unhandled
7378 : // exceptions here.
7379 0 : mooseError("An unhandled MooseException was raised during residual computation. Please "
7380 : "contact the MOOSE team for assistance.");
7381 0 : }
7382 0 : }
7383 :
7384 : void
7385 4 : FEProblemBase::handleException(const std::string & calling_method)
7386 : {
7387 : auto create_exception_message =
7388 4 : [&calling_method](const std::string & exception_type, const auto & exception)
7389 : {
7390 : return std::string("A " + exception_type + " was raised during FEProblemBase::" +
7391 8 : calling_method + "\n" + std::string(exception.what()));
7392 4 : };
7393 :
7394 : try
7395 : {
7396 4 : throw;
7397 : }
7398 4 : catch (const MooseException & e)
7399 : {
7400 0 : setException(create_exception_message("MooseException", e));
7401 0 : }
7402 0 : catch (const MetaPhysicL::LogicError & e)
7403 : {
7404 0 : moose::translateMetaPhysicLError(e);
7405 0 : }
7406 4 : catch (const libMesh::PetscSolverException & e)
7407 : {
7408 : // One PETSc solver exception that we cannot currently recover from are new nonzero errors. In
7409 : // particular I have observed the following scenario in a parallel test:
7410 : // - Both processes throw because of a new nonzero during MOOSE's computeJacobianTags
7411 : // - We potentially handle the exceptions nicely here
7412 : // - When the matrix is closed in libMesh's libmesh_petsc_snes_solver, there is a new nonzero
7413 : // throw which we do not catch here in MOOSE and the simulation terminates. This only appears
7414 : // in parallel (and not all the time; a test I was examining threw with distributed mesh, but
7415 : // not with replicated). In serial there are no new throws from libmesh_petsc_snes_solver.
7416 : // So for uniformity of behavior across serial/parallel, we will choose to abort here and always
7417 : // produce a non-zero exit code
7418 8 : mooseError(create_exception_message("libMesh::PetscSolverException", e));
7419 0 : }
7420 0 : catch (const std::exception & e)
7421 : {
7422 : // This might be libMesh detecting a degenerate Jacobian or matrix
7423 0 : if (strstr(e.what(), "Jacobian") || strstr(e.what(), "singular") ||
7424 0 : strstr(e.what(), "det != 0"))
7425 0 : setException(create_exception_message("libMesh DegenerateMap", e));
7426 : else
7427 : {
7428 0 : const auto message = create_exception_message("std::exception", e);
7429 0 : if (_regard_general_exceptions_as_errors)
7430 0 : mooseError(message);
7431 : else
7432 0 : setException(message);
7433 0 : }
7434 0 : }
7435 :
7436 0 : checkExceptionAndStopSolve();
7437 0 : }
7438 :
7439 : void
7440 3347638 : FEProblemBase::computeResidualTags(const std::set<TagID> & tags)
7441 : {
7442 : parallel_object_only();
7443 :
7444 : try
7445 : {
7446 : try
7447 : {
7448 16738190 : TIME_SECTION("computeResidualTags", 5, "Computing Residual");
7449 :
7450 3347638 : ADReal::do_derivatives = false;
7451 :
7452 3347638 : setCurrentResidualVectorTags(tags);
7453 :
7454 3347638 : _aux->zeroVariablesForResidual();
7455 :
7456 3347638 : unsigned int n_threads = libMesh::n_threads();
7457 :
7458 3347638 : _current_execute_on_flag = EXEC_LINEAR;
7459 :
7460 : // Random interface objects
7461 3363421 : for (const auto & it : _random_data_objects)
7462 15783 : it.second->updateSeeds(EXEC_LINEAR);
7463 :
7464 3347638 : execTransfers(EXEC_LINEAR);
7465 :
7466 3347638 : execMultiApps(EXEC_LINEAR);
7467 :
7468 6995965 : for (unsigned int tid = 0; tid < n_threads; tid++)
7469 3648327 : reinitScalars(tid);
7470 :
7471 3347638 : computeUserObjects(EXEC_LINEAR, Moose::PRE_AUX);
7472 :
7473 3347638 : _aux->residualSetup();
7474 :
7475 3347638 : if (_displaced_problem)
7476 : {
7477 136012 : computeSystems(EXEC_PRE_DISPLACE);
7478 136012 : _displaced_problem->updateMesh();
7479 136012 : if (_mortar_data->hasDisplacedObjects())
7480 2429 : updateMortarMesh();
7481 : }
7482 :
7483 6995965 : for (THREAD_ID tid = 0; tid < n_threads; tid++)
7484 : {
7485 3648327 : _all_materials.residualSetup(tid);
7486 3648327 : _functions.residualSetup(tid);
7487 : }
7488 :
7489 : #ifdef MOOSE_KOKKOS_ENABLED
7490 2199706 : _kokkos_functions.residualSetup();
7491 : #endif
7492 :
7493 3347638 : computeSystems(EXEC_LINEAR);
7494 :
7495 3347638 : computeUserObjects(EXEC_LINEAR, Moose::POST_AUX);
7496 :
7497 3347638 : executeControls(EXEC_LINEAR);
7498 :
7499 3347638 : _app.getOutputWarehouse().residualSetup();
7500 :
7501 3347638 : _safe_access_tagged_vectors = false;
7502 3347638 : _current_nl_sys->computeResidualTags(tags);
7503 3347594 : }
7504 0 : catch (...)
7505 : {
7506 0 : handleException("computeResidualTags");
7507 0 : }
7508 : }
7509 0 : catch (const MooseException &)
7510 : {
7511 : // The buck stops here, we have already handled the exception by
7512 : // calling the system's stopSolve() method, it is now up to PETSc to return a
7513 : // "diverged" reason during the next solve.
7514 0 : }
7515 0 : catch (...)
7516 : {
7517 0 : mooseError("Unexpected exception type");
7518 0 : }
7519 :
7520 3347594 : resetState();
7521 3347594 : }
7522 :
7523 : void
7524 527390 : FEProblemBase::computeJacobianSys(NonlinearImplicitSystem & sys,
7525 : const NumericVector<Number> & soln,
7526 : SparseMatrix<Number> & jacobian)
7527 : {
7528 527390 : computeJacobian(soln, jacobian, sys.number());
7529 527370 : }
7530 :
7531 : void
7532 4894 : FEProblemBase::computeJacobianTag(const NumericVector<Number> & soln,
7533 : SparseMatrix<Number> & jacobian,
7534 : TagID tag)
7535 : {
7536 4894 : _current_nl_sys->setSolution(soln);
7537 :
7538 4894 : _current_nl_sys->associateMatrixToTag(jacobian, tag);
7539 :
7540 9788 : computeJacobianTags({tag});
7541 :
7542 4894 : _current_nl_sys->disassociateMatrixFromTag(jacobian, tag);
7543 4894 : }
7544 :
7545 : void
7546 526560 : FEProblemBase::computeJacobian(const NumericVector<Number> & soln,
7547 : SparseMatrix<Number> & jacobian,
7548 : const unsigned int nl_sys_num)
7549 : {
7550 526560 : setCurrentNonlinearSystem(nl_sys_num);
7551 :
7552 526560 : _fe_matrix_tags.clear();
7553 :
7554 526560 : auto & tags = getMatrixTags();
7555 1579952 : for (auto & tag : tags)
7556 1053392 : _fe_matrix_tags.insert(tag.second);
7557 :
7558 526560 : computeJacobianInternal(soln, jacobian, _fe_matrix_tags);
7559 526540 : }
7560 :
7561 : void
7562 526560 : FEProblemBase::computeJacobianInternal(const NumericVector<Number> & soln,
7563 : SparseMatrix<Number> & jacobian,
7564 : const std::set<TagID> & tags)
7565 : {
7566 1579680 : TIME_SECTION("computeJacobianInternal", 1);
7567 :
7568 526560 : _current_nl_sys->setSolution(soln);
7569 :
7570 526560 : _current_nl_sys->associateMatrixToTag(jacobian, _current_nl_sys->systemMatrixTag());
7571 :
7572 526560 : computeJacobianTags(tags);
7573 :
7574 526540 : _current_nl_sys->disassociateMatrixFromTag(jacobian, _current_nl_sys->systemMatrixTag());
7575 526540 : }
7576 :
7577 : void
7578 536384 : FEProblemBase::computeJacobianTags(const std::set<TagID> & tags)
7579 : {
7580 : try
7581 : {
7582 : try
7583 : {
7584 536384 : if (!_has_jacobian || !_const_jacobian)
7585 : {
7586 2646155 : TIME_SECTION("computeJacobianTags", 5, "Computing Jacobian");
7587 :
7588 1579855 : for (auto tag : tags)
7589 1050624 : if (_current_nl_sys->hasMatrix(tag))
7590 : {
7591 531217 : auto & matrix = _current_nl_sys->getMatrix(tag);
7592 531217 : if (_restore_original_nonzero_pattern)
7593 8195 : matrix.restore_original_nonzero_pattern();
7594 : else
7595 523022 : matrix.zero();
7596 531217 : if (haveADObjects() && !_current_nl_sys->system().has_static_condensation())
7597 : // PETSc algorithms require diagonal allocations regardless of whether there is
7598 : // non-zero diagonal dependence. With global AD indexing we only add non-zero
7599 : // dependence, so PETSc will scream at us unless we artificially add the diagonals.
7600 8316520 : for (auto index : make_range(matrix.row_start(), matrix.row_stop()))
7601 8258014 : matrix.add(index, index, 0);
7602 : }
7603 :
7604 529231 : _aux->zeroVariablesForJacobian();
7605 :
7606 529231 : unsigned int n_threads = libMesh::n_threads();
7607 :
7608 : // Random interface objects
7609 531739 : for (const auto & it : _random_data_objects)
7610 2508 : it.second->updateSeeds(EXEC_NONLINEAR);
7611 :
7612 529231 : _current_execute_on_flag = EXEC_NONLINEAR;
7613 529231 : _currently_computing_jacobian = true;
7614 529231 : if (_displaced_problem)
7615 23348 : _displaced_problem->setCurrentlyComputingJacobian(true);
7616 :
7617 529231 : execTransfers(EXEC_NONLINEAR);
7618 529231 : execMultiApps(EXEC_NONLINEAR);
7619 :
7620 1107427 : for (unsigned int tid = 0; tid < n_threads; tid++)
7621 578196 : reinitScalars(tid);
7622 :
7623 529231 : computeUserObjects(EXEC_NONLINEAR, Moose::PRE_AUX);
7624 :
7625 529231 : _aux->jacobianSetup();
7626 :
7627 529231 : if (_displaced_problem)
7628 : {
7629 23348 : computeSystems(EXEC_PRE_DISPLACE);
7630 23348 : _displaced_problem->updateMesh();
7631 : }
7632 :
7633 1107418 : for (unsigned int tid = 0; tid < n_threads; tid++)
7634 : {
7635 578191 : _all_materials.jacobianSetup(tid);
7636 578191 : _functions.jacobianSetup(tid);
7637 : }
7638 :
7639 : #ifdef MOOSE_KOKKOS_ENABLED
7640 346476 : _kokkos_functions.jacobianSetup();
7641 : #endif
7642 :
7643 529227 : computeSystems(EXEC_NONLINEAR);
7644 :
7645 529227 : computeUserObjects(EXEC_NONLINEAR, Moose::POST_AUX);
7646 :
7647 529227 : executeControls(EXEC_NONLINEAR);
7648 :
7649 529227 : _app.getOutputWarehouse().jacobianSetup();
7650 :
7651 529227 : _safe_access_tagged_matrices = false;
7652 :
7653 529227 : _current_nl_sys->computeJacobianTags(tags);
7654 :
7655 : // For explicit Euler calculations for example we often compute the Jacobian one time and
7656 : // then re-use it over and over. If we're performing automatic scaling, we don't want to
7657 : // use that kernel, diagonal-block only Jacobian for our actual matrix when performing
7658 : // solves!
7659 529211 : if (!_current_nl_sys->computingScalingJacobian())
7660 528609 : _has_jacobian = true;
7661 529215 : }
7662 : }
7663 4 : catch (...)
7664 : {
7665 4 : handleException("computeJacobianTags");
7666 0 : }
7667 : }
7668 0 : catch (const MooseException &)
7669 : {
7670 : // The buck stops here, we have already handled the exception by
7671 : // calling the system's stopSolve() method, it is now up to PETSc to return a
7672 : // "diverged" reason during the next solve.
7673 0 : }
7674 0 : catch (...)
7675 : {
7676 0 : mooseError("Unexpected exception type");
7677 0 : }
7678 :
7679 536364 : resetState();
7680 536364 : }
7681 :
7682 : void
7683 302 : FEProblemBase::computeJacobianBlocks(std::vector<JacobianBlock *> & blocks,
7684 : const unsigned int nl_sys_num)
7685 : {
7686 906 : TIME_SECTION("computeTransientImplicitJacobian", 2);
7687 302 : setCurrentNonlinearSystem(nl_sys_num);
7688 :
7689 302 : if (_displaced_problem)
7690 : {
7691 0 : computeSystems(EXEC_PRE_DISPLACE);
7692 0 : _displaced_problem->updateMesh();
7693 : }
7694 :
7695 302 : computeSystems(EXEC_NONLINEAR);
7696 :
7697 302 : _currently_computing_jacobian = true;
7698 302 : _current_nl_sys->computeJacobianBlocks(blocks);
7699 302 : _currently_computing_jacobian = false;
7700 302 : }
7701 :
7702 : void
7703 0 : FEProblemBase::computeJacobianBlock(SparseMatrix<Number> & jacobian,
7704 : libMesh::System & precond_system,
7705 : unsigned int ivar,
7706 : unsigned int jvar)
7707 : {
7708 0 : JacobianBlock jac_block(precond_system, jacobian, ivar, jvar);
7709 0 : std::vector<JacobianBlock *> blocks = {&jac_block};
7710 : mooseAssert(_current_nl_sys, "This should be non-null");
7711 0 : computeJacobianBlocks(blocks, _current_nl_sys->number());
7712 0 : }
7713 :
7714 : void
7715 778 : FEProblemBase::computeBounds(NonlinearImplicitSystem & libmesh_dbg_var(sys),
7716 : NumericVector<Number> & lower,
7717 : NumericVector<Number> & upper)
7718 : {
7719 : try
7720 : {
7721 : try
7722 : {
7723 : mooseAssert(_current_nl_sys && (sys.number() == _current_nl_sys->number()),
7724 : "I expect these system numbers to be the same");
7725 :
7726 3890 : if (!_current_nl_sys->hasVector("lower_bound") || !_current_nl_sys->hasVector("upper_bound"))
7727 0 : return;
7728 :
7729 3890 : TIME_SECTION("computeBounds", 1, "Computing Bounds");
7730 :
7731 1556 : NumericVector<Number> & _lower = _current_nl_sys->getVector("lower_bound");
7732 1556 : NumericVector<Number> & _upper = _current_nl_sys->getVector("upper_bound");
7733 778 : _lower.swap(lower);
7734 778 : _upper.swap(upper);
7735 1620 : for (THREAD_ID tid = 0; tid < libMesh::n_threads(); tid++)
7736 842 : _all_materials.residualSetup(tid);
7737 :
7738 778 : _aux->residualSetup();
7739 778 : computeSystems(EXEC_LINEAR);
7740 778 : _lower.swap(lower);
7741 778 : _upper.swap(upper);
7742 778 : }
7743 0 : catch (...)
7744 : {
7745 0 : handleException("computeBounds");
7746 0 : }
7747 : }
7748 0 : catch (MooseException & e)
7749 : {
7750 0 : mooseError("Irrecoverable exception: " + std::string(e.what()));
7751 0 : }
7752 0 : catch (...)
7753 : {
7754 0 : mooseError("Unexpected exception type");
7755 0 : }
7756 : }
7757 :
7758 : void
7759 5738 : FEProblemBase::computeLinearSystemSys(LinearImplicitSystem & sys,
7760 : SparseMatrix<Number> & system_matrix,
7761 : NumericVector<Number> & rhs,
7762 : const bool compute_gradients)
7763 : {
7764 17214 : TIME_SECTION("computeLinearSystemSys", 5);
7765 :
7766 5738 : setCurrentLinearSystem(linearSysNum(sys.name()));
7767 :
7768 5738 : _current_linear_sys->associateVectorToTag(rhs, _current_linear_sys->rightHandSideVectorTag());
7769 5738 : _current_linear_sys->associateMatrixToTag(system_matrix, _current_linear_sys->systemMatrixTag());
7770 :
7771 : // We are using the residual tag system for right hand sides so we fetch everything
7772 5738 : const auto & vector_tags = getVectorTags(Moose::VECTOR_TAG_RESIDUAL);
7773 :
7774 : // We filter out tags which do not have associated vectors in the current
7775 : // system. This is essential to be able to use system-dependent vector tags.
7776 5738 : selectVectorTagsFromSystem(*_current_linear_sys, vector_tags, _linear_vector_tags);
7777 5738 : selectMatrixTagsFromSystem(*_current_linear_sys, getMatrixTags(), _linear_matrix_tags);
7778 :
7779 5738 : computeLinearSystemTags(*(_current_linear_sys->currentSolution()),
7780 5738 : _linear_vector_tags,
7781 5738 : _linear_matrix_tags,
7782 : compute_gradients);
7783 :
7784 5738 : _current_linear_sys->disassociateMatrixFromTag(system_matrix,
7785 5738 : _current_linear_sys->systemMatrixTag());
7786 5738 : _current_linear_sys->disassociateVectorFromTag(rhs,
7787 5738 : _current_linear_sys->rightHandSideVectorTag());
7788 : // We reset the tags to the default containers for further operations
7789 5738 : _current_linear_sys->associateVectorToTag(_current_linear_sys->getRightHandSideVector(),
7790 5738 : _current_linear_sys->rightHandSideVectorTag());
7791 5738 : _current_linear_sys->associateMatrixToTag(_current_linear_sys->getSystemMatrix(),
7792 5738 : _current_linear_sys->systemMatrixTag());
7793 5738 : }
7794 :
7795 : void
7796 5738 : FEProblemBase::computeLinearSystemTags(const NumericVector<Number> & soln,
7797 : const std::set<TagID> & vector_tags,
7798 : const std::set<TagID> & matrix_tags,
7799 : const bool compute_gradients)
7800 : {
7801 28690 : TIME_SECTION("computeLinearSystemTags", 5, "Computing Linear System");
7802 :
7803 5738 : _current_linear_sys->setSolution(soln);
7804 :
7805 11500 : for (auto tag : matrix_tags)
7806 : {
7807 5762 : auto & matrix = _current_linear_sys->getMatrix(tag);
7808 5762 : matrix.zero();
7809 : }
7810 :
7811 5738 : unsigned int n_threads = libMesh::n_threads();
7812 :
7813 5738 : _current_execute_on_flag = EXEC_NONLINEAR;
7814 :
7815 : // Random interface objects
7816 5738 : for (const auto & it : _random_data_objects)
7817 0 : it.second->updateSeeds(EXEC_NONLINEAR);
7818 :
7819 5738 : execTransfers(EXEC_NONLINEAR);
7820 5738 : execMultiApps(EXEC_NONLINEAR);
7821 :
7822 5738 : computeUserObjects(EXEC_NONLINEAR, Moose::PRE_AUX);
7823 :
7824 5738 : _aux->jacobianSetup();
7825 :
7826 11476 : for (THREAD_ID tid = 0; tid < n_threads; tid++)
7827 : {
7828 5738 : _functions.jacobianSetup(tid);
7829 : }
7830 :
7831 : #ifdef MOOSE_KOKKOS_ENABLED
7832 3357 : _kokkos_functions.jacobianSetup();
7833 : #endif
7834 :
7835 : try
7836 : {
7837 5738 : computeSystems(EXEC_NONLINEAR);
7838 : }
7839 0 : catch (MooseException & e)
7840 : {
7841 0 : _console << "\nA MooseException was raised during Auxiliary variable computation.\n"
7842 0 : << "The next solve will fail, the timestep will be reduced, and we will try again.\n"
7843 0 : << std::endl;
7844 :
7845 : // We know the next solve is going to fail, so there's no point in
7846 : // computing anything else after this. Plus, using incompletely
7847 : // computed AuxVariables in subsequent calculations could lead to
7848 : // other errors or unhandled exceptions being thrown.
7849 0 : return;
7850 0 : }
7851 :
7852 5738 : computeUserObjects(EXEC_NONLINEAR, Moose::POST_AUX);
7853 5738 : executeControls(EXEC_NONLINEAR);
7854 :
7855 5738 : _app.getOutputWarehouse().jacobianSetup();
7856 :
7857 5738 : _current_linear_sys->computeLinearSystemTags(vector_tags, matrix_tags, compute_gradients);
7858 :
7859 : // Reset execution flag as after this point we are no longer on LINEAR
7860 5738 : _current_execute_on_flag = EXEC_NONE;
7861 :
7862 : // These are the relevant parts of resetState()
7863 5738 : _safe_access_tagged_vectors = true;
7864 5738 : _safe_access_tagged_matrices = true;
7865 5738 : }
7866 :
7867 : void
7868 325185 : FEProblemBase::computeNearNullSpace(NonlinearImplicitSystem & libmesh_dbg_var(sys),
7869 : std::vector<NumericVector<Number> *> & sp)
7870 : {
7871 : mooseAssert(_current_nl_sys && (sys.number() == _current_nl_sys->number()),
7872 : "I expect these system numbers to be the same");
7873 :
7874 325185 : sp.clear();
7875 975555 : for (unsigned int i = 0; i < subspaceDim("NearNullSpace"); ++i)
7876 : {
7877 0 : std::stringstream postfix;
7878 0 : postfix << "_" << i;
7879 0 : std::string modename = "NearNullSpace" + postfix.str();
7880 0 : sp.push_back(&_current_nl_sys->getVector(modename));
7881 0 : }
7882 325185 : }
7883 :
7884 : void
7885 325185 : FEProblemBase::computeNullSpace(NonlinearImplicitSystem & libmesh_dbg_var(sys),
7886 : std::vector<NumericVector<Number> *> & sp)
7887 : {
7888 : mooseAssert(_current_nl_sys && (sys.number() == _current_nl_sys->number()),
7889 : "I expect these system numbers to be the same");
7890 325185 : sp.clear();
7891 975627 : for (unsigned int i = 0; i < subspaceDim("NullSpace"); ++i)
7892 : {
7893 24 : std::stringstream postfix;
7894 24 : postfix << "_" << i;
7895 24 : sp.push_back(&_current_nl_sys->getVector("NullSpace" + postfix.str()));
7896 24 : }
7897 325185 : }
7898 :
7899 : void
7900 325185 : FEProblemBase::computeTransposeNullSpace(NonlinearImplicitSystem & libmesh_dbg_var(sys),
7901 : std::vector<NumericVector<Number> *> & sp)
7902 : {
7903 : mooseAssert(_current_nl_sys && (sys.number() == _current_nl_sys->number()),
7904 : "I expect these system numbers to be the same");
7905 325185 : sp.clear();
7906 975591 : for (unsigned int i = 0; i < subspaceDim("TransposeNullSpace"); ++i)
7907 : {
7908 12 : std::stringstream postfix;
7909 12 : postfix << "_" << i;
7910 12 : sp.push_back(&_current_nl_sys->getVector("TransposeNullSpace" + postfix.str()));
7911 12 : }
7912 325185 : }
7913 :
7914 : void
7915 1976 : FEProblemBase::computePostCheck(NonlinearImplicitSystem & sys,
7916 : const NumericVector<Number> & old_soln,
7917 : NumericVector<Number> & search_direction,
7918 : NumericVector<Number> & new_soln,
7919 : bool & changed_search_direction,
7920 : bool & changed_new_soln)
7921 : {
7922 : mooseAssert(_current_nl_sys && (sys.number() == _current_nl_sys->number()),
7923 : "I expect these system numbers to be the same");
7924 :
7925 : // This function replaces the old PetscSupport::dampedCheck() function.
7926 : //
7927 : // 1.) Recreate code in PetscSupport::dampedCheck() for constructing
7928 : // ghosted "soln" and "update" vectors.
7929 : // 2.) Call FEProblemBase::computeDamping() with these ghost vectors.
7930 : // 3.) Recreate the code in PetscSupport::dampedCheck() to actually update
7931 : // the solution vector based on the damping, and set the "changed" flags
7932 : // appropriately.
7933 :
7934 9880 : TIME_SECTION("computePostCheck", 2, "Computing Post Check");
7935 :
7936 1976 : _current_execute_on_flag = EXEC_POSTCHECK;
7937 :
7938 : // MOOSE's FEProblemBase doesn't update the solution during the
7939 : // postcheck, but FEProblemBase-derived classes might.
7940 1976 : if (_has_dampers || shouldUpdateSolution())
7941 : {
7942 : // We need ghosted versions of new_soln and search_direction (the
7943 : // ones we get from libmesh/PETSc are PARALLEL vectors. To make
7944 : // our lives simpler, we use the same ghosting pattern as the
7945 : // system's current_local_solution to create new ghosted vectors.
7946 :
7947 : // Construct zeroed-out clones with the same ghosted dofs as the
7948 : // System's current_local_solution.
7949 : std::unique_ptr<NumericVector<Number>> ghosted_solution =
7950 1420 : sys.current_local_solution->zero_clone(),
7951 : ghosted_search_direction =
7952 1420 : sys.current_local_solution->zero_clone();
7953 :
7954 : // Copy values from input vectors into clones with ghosted values.
7955 1420 : *ghosted_solution = new_soln;
7956 1420 : *ghosted_search_direction = search_direction;
7957 :
7958 1420 : if (_has_dampers)
7959 : {
7960 : // Compute the damping coefficient using the ghosted vectors
7961 1420 : Real damping = computeDamping(*ghosted_solution, *ghosted_search_direction);
7962 :
7963 : // If some non-trivial damping was computed, update the new_soln
7964 : // vector accordingly.
7965 1420 : if (damping < 1.0)
7966 : {
7967 995 : new_soln = old_soln;
7968 995 : new_soln.add(-damping, search_direction);
7969 995 : changed_new_soln = true;
7970 : }
7971 : }
7972 :
7973 1420 : if (shouldUpdateSolution())
7974 : {
7975 : // Update the ghosted copy of the new solution, if necessary.
7976 0 : if (changed_new_soln)
7977 0 : *ghosted_solution = new_soln;
7978 :
7979 0 : bool updated_solution = updateSolution(new_soln, *ghosted_solution);
7980 0 : if (updated_solution)
7981 0 : changed_new_soln = true;
7982 : }
7983 1420 : }
7984 :
7985 1976 : if (vectorTagExists(Moose::PREVIOUS_NL_SOLUTION_TAG))
7986 : {
7987 556 : _current_nl_sys->setPreviousNewtonSolution(old_soln);
7988 556 : _aux->copyCurrentIntoPreviousNL();
7989 : }
7990 :
7991 : // MOOSE doesn't change the search_direction
7992 1976 : changed_search_direction = false;
7993 :
7994 1976 : _current_execute_on_flag = EXEC_NONE;
7995 1976 : }
7996 :
7997 : Real
7998 1420 : FEProblemBase::computeDamping(const NumericVector<Number> & soln,
7999 : const NumericVector<Number> & update)
8000 : {
8001 : // Default to no damping
8002 1420 : Real damping = 1.0;
8003 :
8004 1420 : if (_has_dampers)
8005 : {
8006 7100 : TIME_SECTION("computeDamping", 1, "Computing Damping");
8007 :
8008 : // Save pointer to the current solution
8009 1420 : const NumericVector<Number> * _saved_current_solution = _current_nl_sys->currentSolution();
8010 :
8011 1420 : _current_nl_sys->setSolution(soln);
8012 : // For now, do not re-compute auxiliary variables. Doing so allows a wild solution increment
8013 : // to get to the material models, which may not be able to cope with drastically different
8014 : // values. Once more complete dependency checking is in place, auxiliary variables (and
8015 : // material properties) will be computed as needed by dampers.
8016 : // _aux.compute();
8017 1420 : damping = _current_nl_sys->computeDamping(soln, update);
8018 :
8019 : // restore saved solution
8020 1420 : _current_nl_sys->setSolution(*_saved_current_solution);
8021 1420 : }
8022 :
8023 1420 : return damping;
8024 : }
8025 :
8026 : bool
8027 318864 : FEProblemBase::shouldUpdateSolution()
8028 : {
8029 318864 : return false;
8030 : }
8031 :
8032 : bool
8033 0 : FEProblemBase::updateSolution(NumericVector<Number> & /*vec_solution*/,
8034 : NumericVector<Number> & /*ghosted_solution*/)
8035 : {
8036 0 : return false;
8037 : }
8038 :
8039 : void
8040 223 : FEProblemBase::predictorCleanup(NumericVector<Number> & /*ghosted_solution*/)
8041 : {
8042 223 : }
8043 :
8044 : void
8045 2246 : FEProblemBase::addDisplacedProblem(std::shared_ptr<DisplacedProblem> displaced_problem)
8046 : {
8047 : parallel_object_only();
8048 :
8049 2246 : _displaced_mesh = &displaced_problem->mesh();
8050 2246 : _displaced_problem = displaced_problem;
8051 2246 : }
8052 :
8053 : void
8054 124999 : FEProblemBase::updateGeomSearch(GeometricSearchData::GeometricSearchType type)
8055 : {
8056 624995 : TIME_SECTION("updateGeometricSearch", 3, "Updating Geometric Search");
8057 :
8058 124999 : _geometric_search_data.update(type);
8059 :
8060 124999 : if (_displaced_problem)
8061 4669 : _displaced_problem->updateGeomSearch(type);
8062 124999 : }
8063 :
8064 : void
8065 74130 : FEProblemBase::updateMortarMesh()
8066 : {
8067 370650 : TIME_SECTION("updateMortarMesh", 5, "Updating Mortar Mesh");
8068 :
8069 74130 : FloatingPointExceptionGuard fpe_guard(_app);
8070 :
8071 74130 : _mortar_data->update();
8072 74130 : }
8073 :
8074 : void
8075 1448 : FEProblemBase::createMortarInterface(
8076 : const std::pair<BoundaryID, BoundaryID> & primary_secondary_boundary_pair,
8077 : const std::pair<SubdomainID, SubdomainID> & primary_secondary_subdomain_pair,
8078 : bool on_displaced,
8079 : bool periodic,
8080 : const bool debug,
8081 : const bool correct_edge_dropping,
8082 : const Real minimum_projection_angle)
8083 : {
8084 1448 : _has_mortar = true;
8085 :
8086 1448 : if (on_displaced)
8087 276 : return _mortar_data->createMortarInterface(primary_secondary_boundary_pair,
8088 : primary_secondary_subdomain_pair,
8089 138 : *_displaced_problem,
8090 : on_displaced,
8091 : periodic,
8092 : debug,
8093 : correct_edge_dropping,
8094 138 : minimum_projection_angle);
8095 : else
8096 1310 : return _mortar_data->createMortarInterface(primary_secondary_boundary_pair,
8097 : primary_secondary_subdomain_pair,
8098 : *this,
8099 : on_displaced,
8100 : periodic,
8101 : debug,
8102 : correct_edge_dropping,
8103 1310 : minimum_projection_angle);
8104 : }
8105 :
8106 : const AutomaticMortarGeneration &
8107 0 : FEProblemBase::getMortarInterface(
8108 : const std::pair<BoundaryID, BoundaryID> & primary_secondary_boundary_pair,
8109 : const std::pair<SubdomainID, SubdomainID> & primary_secondary_subdomain_pair,
8110 : bool on_displaced) const
8111 : {
8112 0 : return _mortar_data->getMortarInterface(
8113 0 : primary_secondary_boundary_pair, primary_secondary_subdomain_pair, on_displaced);
8114 : }
8115 :
8116 : AutomaticMortarGeneration &
8117 258234 : FEProblemBase::getMortarInterface(
8118 : const std::pair<BoundaryID, BoundaryID> & primary_secondary_boundary_pair,
8119 : const std::pair<SubdomainID, SubdomainID> & primary_secondary_subdomain_pair,
8120 : bool on_displaced)
8121 : {
8122 258234 : return _mortar_data->getMortarInterface(
8123 258234 : primary_secondary_boundary_pair, primary_secondary_subdomain_pair, on_displaced);
8124 : }
8125 :
8126 : void
8127 348755 : FEProblemBase::possiblyRebuildGeomSearchPatches()
8128 : {
8129 348755 : if (_displaced_problem) // Only need to do this if things are moving...
8130 : {
8131 179345 : TIME_SECTION("possiblyRebuildGeomSearchPatches", 5, "Rebuilding Geometric Search Patches");
8132 :
8133 35869 : switch (_mesh.getPatchUpdateStrategy())
8134 : {
8135 34675 : case Moose::Never:
8136 34675 : break;
8137 398 : case Moose::Iteration:
8138 : // Update the list of ghosted elements at the start of the time step
8139 398 : _geometric_search_data.updateGhostedElems();
8140 398 : _mesh.updateActiveSemiLocalNodeRange(_ghosted_elems);
8141 :
8142 398 : _displaced_problem->geomSearchData().updateGhostedElems();
8143 398 : _displaced_mesh->updateActiveSemiLocalNodeRange(_ghosted_elems);
8144 :
8145 : // The commands below ensure that the sparsity of the Jacobian matrix is
8146 : // augmented at the start of the time step using neighbor nodes from the end
8147 : // of the previous time step.
8148 :
8149 398 : reinitBecauseOfGhostingOrNewGeomObjects();
8150 :
8151 : // This is needed to reinitialize PETSc output
8152 398 : initPetscOutputAndSomeSolverSettings();
8153 :
8154 398 : break;
8155 :
8156 361 : case Moose::Auto:
8157 : {
8158 361 : Real max = _displaced_problem->geomSearchData().maxPatchPercentage();
8159 361 : _communicator.max(max);
8160 :
8161 : // If we haven't moved very far through the patch
8162 361 : if (max < 0.4)
8163 325 : break;
8164 : }
8165 : libmesh_fallthrough();
8166 :
8167 : // Let this fall through if things do need to be updated...
8168 : case Moose::Always:
8169 : // Flush output here to see the message before the reinitialization, which could take a
8170 : // while
8171 471 : _console << "\n\nUpdating geometric search patches\n" << std::endl;
8172 :
8173 471 : _geometric_search_data.clearNearestNodeLocators();
8174 471 : _mesh.updateActiveSemiLocalNodeRange(_ghosted_elems);
8175 :
8176 471 : _displaced_problem->geomSearchData().clearNearestNodeLocators();
8177 471 : _displaced_mesh->updateActiveSemiLocalNodeRange(_ghosted_elems);
8178 :
8179 471 : reinitBecauseOfGhostingOrNewGeomObjects();
8180 :
8181 : // This is needed to reinitialize PETSc output
8182 471 : initPetscOutputAndSomeSolverSettings();
8183 : }
8184 35869 : }
8185 348755 : }
8186 :
8187 : #ifdef LIBMESH_ENABLE_AMR
8188 : void
8189 57869 : FEProblemBase::initialAdaptMesh()
8190 : {
8191 57869 : unsigned int n = adaptivity().getInitialSteps();
8192 57869 : _cycles_completed = 0;
8193 57869 : if (n)
8194 : {
8195 695 : if (!_mesh.interiorLowerDBlocks().empty() || !_mesh.boundaryLowerDBlocks().empty())
8196 4 : mooseError("HFEM does not support mesh adaptivity currently.");
8197 :
8198 3455 : TIME_SECTION("initialAdaptMesh", 2, "Performing Initial Adaptivity");
8199 :
8200 1667 : for (unsigned int i = 0; i < n; i++)
8201 : {
8202 1169 : computeIndicators();
8203 1169 : computeMarkers();
8204 :
8205 1169 : if (_adaptivity.initialAdaptMesh())
8206 : {
8207 976 : meshChanged(
8208 : /*intermediate_change=*/false, /*contract_mesh=*/true, /*clean_refinement_flags=*/true);
8209 :
8210 : // reproject the initial condition
8211 976 : projectSolution();
8212 :
8213 976 : _cycles_completed++;
8214 : }
8215 : else
8216 : {
8217 193 : _console << "Mesh unchanged, skipping remaining steps..." << std::endl;
8218 193 : return;
8219 : }
8220 : }
8221 691 : }
8222 : }
8223 :
8224 : bool
8225 182812 : FEProblemBase::adaptMesh()
8226 : {
8227 : // reset cycle counter
8228 182812 : _cycles_completed = 0;
8229 :
8230 182812 : if (!_adaptivity.isAdaptivityDue())
8231 177876 : return false;
8232 :
8233 24680 : TIME_SECTION("adaptMesh", 3, "Adapting Mesh");
8234 :
8235 4936 : unsigned int cycles_per_step = _adaptivity.getCyclesPerStep();
8236 :
8237 4936 : bool mesh_changed = false;
8238 :
8239 8674 : for (unsigned int i = 0; i < cycles_per_step; ++i)
8240 : {
8241 5102 : if (!_mesh.interiorLowerDBlocks().empty() || !_mesh.boundaryLowerDBlocks().empty())
8242 0 : mooseError("HFEM does not support mesh adaptivity currently.");
8243 :
8244 : // Markers were already computed once by Executioner
8245 5102 : if (_adaptivity.getRecomputeMarkersFlag() && i > 0)
8246 24 : computeMarkers();
8247 :
8248 : bool mesh_changed_this_step;
8249 5102 : mesh_changed_this_step = _adaptivity.adaptMesh();
8250 :
8251 5102 : if (mesh_changed_this_step)
8252 : {
8253 3738 : mesh_changed = true;
8254 :
8255 3738 : meshChanged(
8256 : /*intermediate_change=*/true, /*contract_mesh=*/true, /*clean_refinement_flags=*/true);
8257 3738 : _cycles_completed++;
8258 : }
8259 : else
8260 : {
8261 : // If the mesh didn't change, we still need to update the displaced mesh
8262 : // to undo the undisplacement performed in Adaptivity::adaptMesh
8263 1364 : if (_displaced_problem)
8264 48 : _displaced_problem->updateMesh();
8265 :
8266 1364 : _console << "Mesh unchanged, skipping remaining steps..." << std::endl;
8267 1364 : break;
8268 : }
8269 :
8270 : // Show adaptivity progress
8271 3738 : _console << std::flush;
8272 : }
8273 :
8274 : // We're done with all intermediate changes; now get systems ready
8275 : // for real if necessary.
8276 4936 : if (mesh_changed)
8277 3584 : es().reinit_systems();
8278 :
8279 : // Execute multi-apps that need to run after adaptivity, but before the next timestep.
8280 4936 : execMultiApps(EXEC_POST_ADAPTIVITY);
8281 :
8282 4936 : return mesh_changed;
8283 4936 : }
8284 : #endif // LIBMESH_ENABLE_AMR
8285 :
8286 : void
8287 0 : FEProblemBase::initXFEM(std::shared_ptr<XFEMInterface> xfem)
8288 : {
8289 0 : _xfem = xfem;
8290 0 : _xfem->setMesh(&_mesh);
8291 0 : if (_displaced_mesh)
8292 0 : _xfem->setDisplacedMesh(_displaced_mesh);
8293 :
8294 0 : auto fill_data = [](auto & storage)
8295 : {
8296 0 : std::vector<MaterialData *> data(libMesh::n_threads());
8297 0 : for (const auto tid : make_range(libMesh::n_threads()))
8298 0 : data[tid] = &storage.getMaterialData(tid);
8299 0 : return data;
8300 0 : };
8301 0 : _xfem->setMaterialData(fill_data(_material_props));
8302 0 : _xfem->setBoundaryMaterialData(fill_data(_bnd_material_props));
8303 :
8304 0 : unsigned int n_threads = libMesh::n_threads();
8305 0 : for (unsigned int i = 0; i < n_threads; ++i)
8306 0 : for (const auto nl_sys_num : index_range(_nl))
8307 : {
8308 0 : _assembly[i][nl_sys_num]->setXFEM(_xfem);
8309 0 : if (_displaced_problem)
8310 0 : _displaced_problem->assembly(i, nl_sys_num).setXFEM(_xfem);
8311 : }
8312 0 : }
8313 :
8314 : bool
8315 0 : FEProblemBase::updateMeshXFEM()
8316 : {
8317 0 : TIME_SECTION("updateMeshXFEM", 5, "Updating XFEM");
8318 :
8319 0 : bool updated = false;
8320 0 : if (haveXFEM())
8321 : {
8322 0 : if (_xfem->updateHeal())
8323 : // XFEM exodiff tests rely on a given numbering because they cannot use map = true due to
8324 : // having coincident elements. While conceptually speaking we do not need to contract the
8325 : // mesh, we need its call to renumber_nodes_and_elements in order to preserve these tests
8326 0 : meshChanged(
8327 : /*intermediate_change=*/false, /*contract_mesh=*/true, /*clean_refinement_flags=*/false);
8328 :
8329 0 : updated = _xfem->update(_time, _nl, *_aux);
8330 0 : if (updated)
8331 : {
8332 0 : meshChanged(
8333 : /*intermediate_change=*/false, /*contract_mesh=*/true, /*clean_refinement_flags=*/false);
8334 0 : _xfem->initSolution(_nl, *_aux);
8335 0 : restoreSolutions();
8336 0 : _console << "\nXFEM update complete: Mesh modified" << std::endl;
8337 : }
8338 : else
8339 0 : _console << "\nXFEM update complete: Mesh not modified" << std::endl;
8340 : }
8341 0 : return updated;
8342 0 : }
8343 :
8344 : void
8345 7587 : FEProblemBase::meshChanged(const bool intermediate_change,
8346 : const bool contract_mesh,
8347 : const bool clean_refinement_flags)
8348 : {
8349 37935 : TIME_SECTION("meshChanged", 3, "Handling Mesh Changes");
8350 :
8351 14942 : if (_material_props.hasStatefulProperties() || _bnd_material_props.hasStatefulProperties() ||
8352 7355 : _neighbor_material_props.hasStatefulProperties())
8353 232 : _mesh.cacheChangedLists(); // Currently only used with adaptivity and stateful material
8354 : // properties
8355 :
8356 : // Clear these out because they corresponded to the old mesh
8357 7587 : _ghosted_elems.clear();
8358 7587 : ghostGhostedBoundaries();
8359 :
8360 : // The mesh changed. We notify the MooseMesh first, because
8361 : // callbacks (e.g. for sparsity calculations) triggered by the
8362 : // EquationSystems reinit may require up-to-date MooseMesh caches.
8363 7587 : _mesh.meshChanged();
8364 :
8365 : // If we're just going to alter the mesh again, all we need to
8366 : // handle here is AMR and projections, not full system reinit
8367 7587 : if (intermediate_change)
8368 3773 : es().reinit_solutions();
8369 : else
8370 3814 : es().reinit();
8371 :
8372 7587 : if (contract_mesh)
8373 : // Once vectors are restricted, we can delete children of coarsened elements
8374 4817 : _mesh.getMesh().contract();
8375 7587 : if (clean_refinement_flags)
8376 : {
8377 : // Finally clear refinement flags so that if someone tries to project vectors again without
8378 : // an intervening mesh refinement to clear flags they won't run into trouble
8379 4817 : MeshRefinement refinement(_mesh.getMesh());
8380 4817 : refinement.clean_refinement_flags();
8381 4817 : }
8382 :
8383 7587 : if (!intermediate_change)
8384 : {
8385 : // Since the mesh has changed, we need to make sure that we update any of our
8386 : // MOOSE-system specific data.
8387 7628 : for (auto & sys : _solver_systems)
8388 3814 : sys->reinit();
8389 3814 : _aux->reinit();
8390 : }
8391 :
8392 : // Updating MooseMesh first breaks other adaptivity code, unless we
8393 : // then *again* update the MooseMesh caches. E.g. the definition of
8394 : // "active" and "local" may have been *changed* by refinement and
8395 : // repartitioning done in EquationSystems::reinit().
8396 7587 : _mesh.meshChanged();
8397 :
8398 : // If we have finite volume variables, we will need to recompute additional elemental/face
8399 : // quantities
8400 7587 : if (haveFV() && _mesh.isFiniteVolumeInfoDirty())
8401 384 : _mesh.setupFiniteVolumeMeshData();
8402 :
8403 : // Let the meshChangedInterface notify the mesh changed event before we update the active
8404 : // semilocal nodes, because the set of ghosted elements may potentially be updated during a mesh
8405 : // changed event.
8406 133674 : for (const auto & mci : _notify_when_mesh_changes)
8407 126087 : mci->meshChanged();
8408 :
8409 : // Since the Mesh changed, update the PointLocator object used by DiracKernels.
8410 7587 : _dirac_kernel_info.updatePointLocator(_mesh);
8411 :
8412 : // Need to redo ghosting
8413 7587 : _geometric_search_data.reinit();
8414 :
8415 7587 : if (_displaced_problem)
8416 : {
8417 633 : _displaced_problem->meshChanged(contract_mesh, clean_refinement_flags);
8418 633 : _displaced_mesh->updateActiveSemiLocalNodeRange(_ghosted_elems);
8419 : }
8420 :
8421 7587 : _mesh.updateActiveSemiLocalNodeRange(_ghosted_elems);
8422 :
8423 7587 : _evaluable_local_elem_range.reset();
8424 7587 : _nl_evaluable_local_elem_range.reset();
8425 :
8426 : // Just like we reinitialized our geometric search objects, we also need to reinitialize our
8427 : // mortar meshes. Note that this needs to happen after DisplacedProblem::meshChanged because the
8428 : // mortar mesh discretization will depend necessarily on the displaced mesh being re-displaced
8429 7587 : updateMortarMesh();
8430 :
8431 : // Nonlinear systems hold the mortar mesh functors. The domains of definition of the mortar
8432 : // functors might have changed when the mesh changed.
8433 15162 : for (auto & nl_sys : _nl)
8434 7575 : nl_sys->reinitMortarFunctors();
8435 :
8436 7587 : reinitBecauseOfGhostingOrNewGeomObjects(/*mortar_changed=*/true);
8437 :
8438 : // We need to create new storage for newly active elements, and copy
8439 : // stateful properties from the old elements.
8440 7819 : if (_has_initialized_stateful &&
8441 232 : (_material_props.hasStatefulProperties() || _bnd_material_props.hasStatefulProperties()))
8442 : {
8443 232 : if (havePRefinement())
8444 72 : _mesh.buildPRefinementAndCoarseningMaps(_assembly[0][0].get());
8445 :
8446 : // Prolong properties onto newly refined elements' children
8447 : {
8448 : ProjectMaterialProperties pmp(
8449 232 : /* refine = */ true, *this, _material_props, _bnd_material_props, _assembly);
8450 232 : const auto & range = *_mesh.refinedElementRange();
8451 232 : Threads::parallel_reduce(range, pmp);
8452 :
8453 : // Concurrent erasure from the shared hash map is not safe while we are reading from it in
8454 : // ProjectMaterialProperties, so we handle erasure here. Moreover, erasure based on key is
8455 : // not thread safe in and of itself because it is a read-write operation. Note that we do not
8456 : // do the erasure for p-refinement because the coarse level element is the same as our active
8457 : // refined level element
8458 232 : if (!doingPRefinement())
8459 3758 : for (const auto & elem : range)
8460 : {
8461 3598 : _material_props.eraseProperty(elem);
8462 3598 : _bnd_material_props.eraseProperty(elem);
8463 3598 : _neighbor_material_props.eraseProperty(elem);
8464 : }
8465 232 : }
8466 :
8467 : // Restrict properties onto newly coarsened elements
8468 : {
8469 : ProjectMaterialProperties pmp(
8470 232 : /* refine = */ false, *this, _material_props, _bnd_material_props, _assembly);
8471 232 : const auto & range = *_mesh.coarsenedElementRange();
8472 232 : Threads::parallel_reduce(range, pmp);
8473 : // Note that we do not do the erasure for p-refinement because the coarse level element is the
8474 : // same as our active refined level element
8475 232 : if (!doingPRefinement())
8476 1525 : for (const auto & elem : range)
8477 : {
8478 1365 : auto && coarsened_children = _mesh.coarsenedElementChildren(elem);
8479 8861 : for (auto && child : coarsened_children)
8480 : {
8481 7496 : _material_props.eraseProperty(child);
8482 7496 : _bnd_material_props.eraseProperty(child);
8483 7496 : _neighbor_material_props.eraseProperty(child);
8484 : }
8485 : }
8486 232 : }
8487 : }
8488 :
8489 7587 : if (_calculate_jacobian_in_uo)
8490 0 : setVariableAllDoFMap(_uo_jacobian_moose_vars[0]);
8491 :
8492 7587 : _has_jacobian = false; // we have to recompute jacobian when mesh changed
8493 :
8494 : // Now for backwards compatibility with user code that overrode the old no-arg meshChanged we must
8495 : // call it here
8496 7587 : meshChanged();
8497 7587 : }
8498 :
8499 : void
8500 979160 : FEProblemBase::notifyWhenMeshChanges(MeshChangedInterface * mci)
8501 : {
8502 979160 : _notify_when_mesh_changes.push_back(mci);
8503 979160 : }
8504 :
8505 : void
8506 85609 : FEProblemBase::notifyWhenMeshDisplaces(MeshDisplacedInterface * mdi)
8507 : {
8508 85609 : _notify_when_mesh_displaces.push_back(mdi);
8509 85609 : }
8510 :
8511 : void
8512 70072 : FEProblemBase::meshDisplaced()
8513 : {
8514 101233 : for (const auto & mdi : _notify_when_mesh_displaces)
8515 31161 : mdi->meshDisplaced();
8516 70072 : }
8517 :
8518 : void
8519 10269 : FEProblemBase::initElementStatefulProps(const ConstElemRange & elem_range, const bool threaded)
8520 : {
8521 : ComputeMaterialsObjectThread cmt(
8522 10269 : *this, _material_props, _bnd_material_props, _neighbor_material_props, _assembly);
8523 10269 : if (threaded)
8524 10269 : Threads::parallel_reduce(elem_range, cmt);
8525 : else
8526 0 : cmt(elem_range, true);
8527 :
8528 : #ifdef MOOSE_KOKKOS_ENABLED
8529 6933 : if (_has_kokkos_objects)
8530 310 : initKokkosStatefulProps();
8531 : #endif
8532 10269 : }
8533 :
8534 : void
8535 62749 : FEProblemBase::checkProblemIntegrity()
8536 : {
8537 188247 : TIME_SECTION("checkProblemIntegrity", 5);
8538 :
8539 : // Subdomains specified by the "Problem/block" parameter
8540 125498 : const auto & subdomain_names = getParam<std::vector<SubdomainName>>("block");
8541 62749 : auto mesh_subdomains_vec = MooseMeshUtils::getSubdomainIDs(_mesh, subdomain_names);
8542 62749 : std::set<SubdomainID> mesh_subdomains(mesh_subdomains_vec.begin(), mesh_subdomains_vec.end());
8543 :
8544 : // Check kernel coverage of subdomains (blocks) in the mesh
8545 62749 : if (!_skip_nl_system_check && _solve && _kernel_coverage_check != CoverageCheckMode::FALSE &&
8546 45183 : _kernel_coverage_check != CoverageCheckMode::OFF)
8547 : {
8548 45170 : std::set<SubdomainID> blocks;
8549 45170 : if (_kernel_coverage_check == CoverageCheckMode::TRUE ||
8550 237 : _kernel_coverage_check == CoverageCheckMode::ON)
8551 44933 : blocks = mesh_subdomains;
8552 237 : else if (_kernel_coverage_check == CoverageCheckMode::SKIP_LIST)
8553 : {
8554 13 : blocks = mesh_subdomains;
8555 26 : for (const auto & subdomain_name : _kernel_coverage_blocks)
8556 : {
8557 13 : const auto id = _mesh.getSubdomainID(subdomain_name);
8558 13 : if (id == Moose::INVALID_BLOCK_ID)
8559 0 : paramError("kernel_coverage_block_list",
8560 : "Subdomain \"",
8561 : subdomain_name,
8562 : "\" not found in mesh.");
8563 13 : blocks.erase(id);
8564 : }
8565 : }
8566 224 : else if (_kernel_coverage_check == CoverageCheckMode::ONLY_LIST)
8567 448 : for (const auto & subdomain_name : _kernel_coverage_blocks)
8568 : {
8569 224 : const auto id = _mesh.getSubdomainID(subdomain_name);
8570 224 : if (id == Moose::INVALID_BLOCK_ID)
8571 0 : paramError("kernel_coverage_block_list",
8572 : "Subdomain \"",
8573 : subdomain_name,
8574 : "\" not found in mesh.");
8575 224 : blocks.insert(id);
8576 : }
8577 45170 : if (!blocks.empty())
8578 89246 : for (auto & nl : _nl)
8579 44092 : nl->checkKernelCoverage(blocks);
8580 45154 : }
8581 :
8582 : // Check materials
8583 : {
8584 : #ifdef LIBMESH_ENABLE_AMR
8585 65153 : if ((_adaptivity.isOn() || _num_grid_steps) &&
8586 2420 : (_material_props.hasStatefulProperties() || _bnd_material_props.hasStatefulProperties() ||
8587 2349 : _neighbor_material_props.hasStatefulProperties()))
8588 : {
8589 71 : _console << "Using EXPERIMENTAL Stateful Material Property projection with Adaptivity!\n"
8590 71 : << std::flush;
8591 : }
8592 : #endif
8593 :
8594 62733 : std::set<SubdomainID> local_mesh_subs(mesh_subdomains);
8595 :
8596 62733 : if (_material_coverage_check != CoverageCheckMode::FALSE &&
8597 62641 : _material_coverage_check != CoverageCheckMode::OFF)
8598 : {
8599 : /**
8600 : * If a material is specified for any block in the simulation, then all blocks must
8601 : * have a material specified.
8602 : */
8603 62641 : bool check_material_coverage = false;
8604 62641 : std::set<SubdomainID> ids = _all_materials.getActiveBlocks();
8605 75878 : for (const auto & id : ids)
8606 : {
8607 13237 : local_mesh_subs.erase(id);
8608 13237 : check_material_coverage = true;
8609 : }
8610 :
8611 : // did the user limit the subdomains to be checked?
8612 62641 : if (_material_coverage_check == CoverageCheckMode::SKIP_LIST)
8613 : {
8614 26 : for (const auto & subdomain_name : _material_coverage_blocks)
8615 : {
8616 13 : const auto id = _mesh.getSubdomainID(subdomain_name);
8617 13 : if (id == Moose::INVALID_BLOCK_ID)
8618 0 : paramError("material_coverage_block_list",
8619 0 : "Subdomain \"" + subdomain_name + "\" not found in mesh.");
8620 13 : local_mesh_subs.erase(id);
8621 : }
8622 : }
8623 62628 : else if (_material_coverage_check == CoverageCheckMode::ONLY_LIST)
8624 : {
8625 224 : std::set<SubdomainID> blocks(local_mesh_subs);
8626 448 : for (const auto & subdomain_name : _material_coverage_blocks)
8627 : {
8628 224 : const auto id = _mesh.getSubdomainID(subdomain_name);
8629 224 : if (id == Moose::INVALID_BLOCK_ID)
8630 0 : paramError("material_coverage_block_list",
8631 0 : "Subdomain \"" + subdomain_name + "\" not found in mesh.");
8632 224 : blocks.erase(id);
8633 : }
8634 237 : for (const auto id : blocks)
8635 13 : local_mesh_subs.erase(id);
8636 224 : }
8637 :
8638 : // also exclude mortar spaces from the material check
8639 62641 : auto && mortar_subdomain_ids = _mortar_data->getMortarSubdomainIDs();
8640 64681 : for (auto subdomain_id : mortar_subdomain_ids)
8641 2040 : local_mesh_subs.erase(subdomain_id);
8642 :
8643 : // Check Material Coverage
8644 62641 : if (check_material_coverage && !local_mesh_subs.empty())
8645 : {
8646 8 : std::stringstream extra_subdomain_ids;
8647 : /// unsigned int is necessary to print SubdomainIDs in the statement below
8648 8 : std::copy(local_mesh_subs.begin(),
8649 : local_mesh_subs.end(),
8650 16 : std::ostream_iterator<unsigned int>(extra_subdomain_ids, " "));
8651 : /// vector is necessary to get the subdomain names
8652 : std::vector<SubdomainID> local_mesh_subs_vec(local_mesh_subs.begin(),
8653 8 : local_mesh_subs.end());
8654 :
8655 24 : mooseError("The following blocks from your input mesh do not contain an active material: " +
8656 16 : extra_subdomain_ids.str() +
8657 24 : "(names: " + Moose::stringify(_mesh.getSubdomainNames(local_mesh_subs_vec)) +
8658 : ")\nWhen ANY mesh block contains a Material object, "
8659 : "all blocks must contain a Material object.\n");
8660 0 : }
8661 62633 : }
8662 :
8663 : // Check material properties on blocks and boundaries
8664 62725 : checkBlockMatProps();
8665 62683 : checkBoundaryMatProps();
8666 :
8667 : // Check that material properties exist when requested by other properties on a given block
8668 62671 : const auto & materials = _all_materials.getActiveObjects();
8669 77484 : for (const auto & material : materials)
8670 14813 : material->checkStatefulSanity();
8671 :
8672 : // auto mats_to_check = _materials.getActiveBlockObjects();
8673 : // const auto & discrete_materials = _discrete_materials.getActiveBlockObjects();
8674 : // for (const auto & map_it : discrete_materials)
8675 : // for (const auto & container_element : map_it.second)
8676 : // mats_to_check[map_it.first].push_back(container_element);
8677 62671 : if (_material_dependency_check)
8678 62645 : checkDependMaterialsHelper(_all_materials.getActiveBlockObjects());
8679 62655 : }
8680 :
8681 62655 : checkUserObjects();
8682 :
8683 : // Verify that we don't have any Element type/Coordinate Type conflicts
8684 62655 : checkCoordinateSystems();
8685 :
8686 : // Coordinate transforms are only intended for use with MultiApps at this time. If you are not
8687 : // using multiapps but still require these, contact a moose developer
8688 62806 : if (_mesh.coordTransform().hasScalingOrRotationTransformation() && _app.isUltimateMaster() &&
8689 155 : !hasMultiApps())
8690 4 : mooseError("Coordinate transformation parameters, listed below, are only to be used in the "
8691 : "context of application to application field transfers at this time. The mesh is "
8692 : "not modified by these parameters within an application.\n"
8693 : "You should likely use a 'TransformGenerator' in the [Mesh] block to achieve the "
8694 : "desired mesh modification.\n\n",
8695 4 : Moose::stringify(MooseAppCoordTransform::validParams()));
8696 :
8697 : // If using displacements, verify that the order of the displacement
8698 : // variables matches the order of the elements in the displaced
8699 : // mesh.
8700 62647 : checkDisplacementOrders();
8701 :
8702 : // Check for postprocessor names with same name as a scalar variable
8703 62643 : checkDuplicatePostprocessorVariableNames();
8704 62643 : }
8705 :
8706 : void
8707 62647 : FEProblemBase::checkDisplacementOrders()
8708 : {
8709 62647 : if (_displaced_problem)
8710 : {
8711 2246 : bool mesh_has_second_order_elements = false;
8712 4492 : for (const auto & elem : as_range(_displaced_mesh->activeLocalElementsBegin(),
8713 535056 : _displaced_mesh->activeLocalElementsEnd()))
8714 : {
8715 264537 : if (elem->default_order() == SECOND)
8716 : {
8717 378 : mesh_has_second_order_elements = true;
8718 378 : break;
8719 : }
8720 2246 : }
8721 :
8722 : // We checked our local elements, so take the max over all processors.
8723 2246 : _displaced_mesh->comm().max(mesh_has_second_order_elements);
8724 :
8725 : // If the Mesh has second order elements, make sure the
8726 : // displacement variables are second-order.
8727 2246 : if (mesh_has_second_order_elements)
8728 : {
8729 : const std::vector<std::string> & displacement_variables =
8730 378 : _displaced_problem->getDisplacementVarNames();
8731 :
8732 1242 : for (const auto & var_name : displacement_variables)
8733 : {
8734 : MooseVariableFEBase & mv =
8735 868 : _displaced_problem->getVariable(/*tid=*/0,
8736 : var_name,
8737 : Moose::VarKindType::VAR_ANY,
8738 : Moose::VarFieldType::VAR_FIELD_STANDARD);
8739 868 : if (mv.order() != SECOND)
8740 4 : mooseError("Error: mesh has SECOND order elements, so all displacement variables must be "
8741 : "SECOND order.");
8742 : }
8743 : }
8744 : }
8745 62643 : }
8746 :
8747 : void
8748 62655 : FEProblemBase::checkUserObjects()
8749 : {
8750 : // Check user_objects block coverage
8751 62655 : std::set<SubdomainID> mesh_subdomains = _mesh.meshSubdomains();
8752 62655 : std::set<SubdomainID> user_objects_blocks;
8753 :
8754 : // gather names of all user_objects that were defined in the input file
8755 : // and the blocks that they are defined on
8756 62655 : std::set<std::string> names;
8757 :
8758 62655 : std::vector<UserObject *> objects;
8759 62655 : theWarehouse().query().condition<AttribInterfaces>(Interfaces::UserObject).queryInto(objects);
8760 :
8761 144676 : for (const auto & obj : objects)
8762 82021 : names.insert(obj->name());
8763 :
8764 : // See if all referenced blocks are covered
8765 62655 : std::set<SubdomainID> difference;
8766 62655 : std::set_difference(user_objects_blocks.begin(),
8767 : user_objects_blocks.end(),
8768 : mesh_subdomains.begin(),
8769 : mesh_subdomains.end(),
8770 : std::inserter(difference, difference.end()));
8771 :
8772 62655 : if (!difference.empty())
8773 : {
8774 0 : std::ostringstream oss;
8775 0 : oss << "One or more UserObjects is referencing a nonexistent block:\n";
8776 0 : for (const auto & id : difference)
8777 0 : oss << id << "\n";
8778 0 : mooseError(oss.str());
8779 0 : }
8780 62655 : }
8781 :
8782 : void
8783 62645 : FEProblemBase::checkDependMaterialsHelper(
8784 : const std::map<SubdomainID, std::vector<std::shared_ptr<MaterialBase>>> & materials_map)
8785 : {
8786 75809 : for (const auto & it : materials_map)
8787 : {
8788 : /// These two sets are used to make sure that all dependent props on a block are actually supplied
8789 13174 : std::set<std::string> block_depend_props, block_supplied_props;
8790 :
8791 32645 : for (const auto & mat1 : it.second)
8792 : {
8793 19471 : auto & alldeps = mat1->getMatPropDependencies(); // includes requested stateful props
8794 21923 : for (auto & dep : alldeps)
8795 2452 : block_depend_props.insert(_material_prop_registry.getName(dep));
8796 :
8797 : // See if any of the active materials supply this property
8798 60190 : for (const auto & mat2 : it.second)
8799 : {
8800 40719 : const std::set<std::string> & supplied_props = mat2->MaterialBase::getSuppliedItems();
8801 40719 : block_supplied_props.insert(supplied_props.begin(), supplied_props.end());
8802 : }
8803 : }
8804 :
8805 : // Add zero material properties specific to this block and unrestricted
8806 13174 : block_supplied_props.insert(_zero_block_material_props[it.first].begin(),
8807 13174 : _zero_block_material_props[it.first].end());
8808 :
8809 : // Error check to make sure all properties consumed by materials are supplied on this block
8810 13174 : std::set<std::string> difference;
8811 13174 : std::set_difference(block_depend_props.begin(),
8812 : block_depend_props.end(),
8813 : block_supplied_props.begin(),
8814 : block_supplied_props.end(),
8815 : std::inserter(difference, difference.end()));
8816 :
8817 13174 : if (!difference.empty())
8818 : {
8819 10 : std::ostringstream oss;
8820 10 : oss << "One or more Material Properties were not supplied on block ";
8821 10 : const std::string & subdomain_name = _mesh.getSubdomainName(it.first);
8822 10 : if (subdomain_name.length() > 0)
8823 0 : oss << subdomain_name << " (" << it.first << ")";
8824 : else
8825 10 : oss << it.first;
8826 10 : oss << ":\n";
8827 20 : for (const auto & name : difference)
8828 10 : oss << name << "\n";
8829 10 : mooseError(oss.str());
8830 0 : }
8831 13164 : }
8832 :
8833 : // This loop checks that materials are not supplied by multiple Material objects
8834 75793 : for (const auto & it : materials_map)
8835 : {
8836 13164 : const auto & materials = it.second;
8837 13164 : std::set<std::string> inner_supplied, outer_supplied;
8838 :
8839 32611 : for (const auto & outer_mat : materials)
8840 : {
8841 : // Storage for properties for this material (outer) and all other materials (inner)
8842 19453 : outer_supplied = outer_mat->getSuppliedItems();
8843 19453 : inner_supplied.clear();
8844 :
8845 : // Property to material map for error reporting
8846 19453 : std::map<std::string, std::set<std::string>> prop_to_mat;
8847 40898 : for (const auto & name : outer_supplied)
8848 21445 : prop_to_mat[name].insert(outer_mat->name());
8849 :
8850 60144 : for (const auto & inner_mat : materials)
8851 : {
8852 40691 : if (outer_mat == inner_mat)
8853 19453 : continue;
8854 :
8855 : // Check whether these materials are an AD pair
8856 21238 : auto outer_mat_type = outer_mat->type();
8857 21238 : auto inner_mat_type = inner_mat->type();
8858 42476 : removeSubstring(outer_mat_type, "<RESIDUAL>");
8859 42476 : removeSubstring(outer_mat_type, "<JACOBIAN>");
8860 42476 : removeSubstring(inner_mat_type, "<RESIDUAL>");
8861 21238 : removeSubstring(inner_mat_type, "<JACOBIAN>");
8862 21238 : if (outer_mat_type == inner_mat_type && outer_mat_type != outer_mat->type() &&
8863 0 : inner_mat_type != inner_mat->type())
8864 0 : continue;
8865 :
8866 21238 : inner_supplied.insert(inner_mat->getSuppliedItems().begin(),
8867 21238 : inner_mat->getSuppliedItems().end());
8868 :
8869 124032 : for (const auto & inner_supplied_name : inner_supplied)
8870 102794 : prop_to_mat[inner_supplied_name].insert(inner_mat->name());
8871 21238 : }
8872 :
8873 : // Test that a property isn't supplied on multiple blocks
8874 19453 : std::set<std::string> intersection;
8875 19453 : std::set_intersection(outer_supplied.begin(),
8876 : outer_supplied.end(),
8877 : inner_supplied.begin(),
8878 : inner_supplied.end(),
8879 : std::inserter(intersection, intersection.end()));
8880 :
8881 19453 : if (!intersection.empty())
8882 : {
8883 6 : std::ostringstream oss;
8884 6 : oss << "The following material properties are declared on block " << it.first
8885 6 : << " by multiple materials:\n";
8886 12 : oss << ConsoleUtils::indent(2) << std::setw(30) << std::left << "Material Property"
8887 6 : << "Material Objects\n";
8888 24 : for (const auto & outer_name : intersection)
8889 : {
8890 18 : oss << ConsoleUtils::indent(2) << std::setw(30) << std::left << outer_name;
8891 54 : for (const auto & inner_name : prop_to_mat[outer_name])
8892 36 : oss << inner_name << " ";
8893 18 : oss << '\n';
8894 : }
8895 :
8896 6 : mooseError(oss.str());
8897 : break;
8898 0 : }
8899 19447 : }
8900 13158 : }
8901 62629 : }
8902 :
8903 : void
8904 62655 : FEProblemBase::checkCoordinateSystems()
8905 : {
8906 62655 : _mesh.checkCoordinateSystems();
8907 62651 : }
8908 :
8909 : void
8910 509 : FEProblemBase::setRestartFile(const std::string & file_name)
8911 : {
8912 509 : if (_app.isRecovering())
8913 : {
8914 23 : mooseInfo("Restart file ", file_name, " is NOT being used since we are performing recovery.");
8915 : }
8916 : else
8917 : {
8918 486 : _app.setRestart(true);
8919 486 : _app.setRestartRecoverFileBase(file_name);
8920 486 : mooseInfo("Using ", file_name, " for restart.");
8921 : }
8922 509 : }
8923 :
8924 : std::vector<VariableName>
8925 381705 : FEProblemBase::getVariableNames()
8926 : {
8927 381705 : std::vector<VariableName> names;
8928 :
8929 767918 : for (auto & sys : _solver_systems)
8930 : {
8931 386213 : const std::vector<VariableName> & var_names = sys->getVariableNames();
8932 386213 : names.insert(names.end(), var_names.begin(), var_names.end());
8933 : }
8934 :
8935 381705 : const std::vector<VariableName> & aux_var_names = _aux->getVariableNames();
8936 381705 : names.insert(names.end(), aux_var_names.begin(), aux_var_names.end());
8937 :
8938 381705 : return names;
8939 0 : }
8940 :
8941 : SolverParams &
8942 1708695 : FEProblemBase::solverParams(const unsigned int solver_sys_num)
8943 : {
8944 : mooseAssert(solver_sys_num < numSolverSystems(),
8945 : "Solver system number '" << solver_sys_num << "' is out of bounds. We have '"
8946 : << numSolverSystems() << "' solver systems");
8947 1708695 : return _solver_params[solver_sys_num];
8948 : }
8949 :
8950 : const SolverParams &
8951 12911 : FEProblemBase::solverParams(const unsigned int solver_sys_num) const
8952 : {
8953 12911 : return const_cast<FEProblemBase *>(this)->solverParams(solver_sys_num);
8954 : }
8955 :
8956 : void
8957 456 : FEProblemBase::registerRandomInterface(RandomInterface & random_interface, const std::string & name)
8958 : {
8959 456 : auto insert_pair = moose_try_emplace(
8960 456 : _random_data_objects, name, std::make_unique<RandomData>(*this, random_interface));
8961 :
8962 456 : auto random_data_ptr = insert_pair.first->second.get();
8963 456 : random_interface.setRandomDataPointer(random_data_ptr);
8964 456 : }
8965 :
8966 : bool
8967 1917885 : FEProblemBase::needBoundaryMaterialOnSide(BoundaryID bnd_id, const THREAD_ID tid)
8968 : {
8969 1917885 : if (_bnd_mat_side_cache[tid].find(bnd_id) == _bnd_mat_side_cache[tid].end())
8970 : {
8971 31327 : auto & bnd_mat_side_cache = _bnd_mat_side_cache[tid][bnd_id];
8972 31327 : bnd_mat_side_cache = false;
8973 :
8974 : // Check systems
8975 31327 : if (_aux->needMaterialOnSide(bnd_id))
8976 : {
8977 578 : bnd_mat_side_cache = true;
8978 578 : return true;
8979 : }
8980 58372 : for (auto & nl : _nl)
8981 30423 : if (nl->needBoundaryMaterialOnSide(bnd_id, tid))
8982 : {
8983 2800 : bnd_mat_side_cache = true;
8984 2800 : return true;
8985 : }
8986 :
8987 : // TODO: these objects should be checked for whether they actually consume materials
8988 : // NOTE: InterfaceUO can use use boundary properties too
8989 27949 : if (theWarehouse()
8990 55898 : .query()
8991 27949 : .condition<AttribThread>(tid)
8992 27949 : .condition<AttribInterfaces>(Interfaces::SideUserObject | Interfaces::DomainUserObject |
8993 : Interfaces::InterfaceUserObject)
8994 27949 : .condition<AttribBoundaries>(bnd_id)
8995 27949 : .count() > 0)
8996 : {
8997 634 : bnd_mat_side_cache = true;
8998 634 : return true;
8999 : }
9000 : }
9001 :
9002 1913873 : return _bnd_mat_side_cache[tid][bnd_id];
9003 : }
9004 :
9005 : bool
9006 458582 : FEProblemBase::needInterfaceMaterialOnSide(BoundaryID bnd_id, const THREAD_ID tid)
9007 : {
9008 458582 : if (_interface_mat_side_cache[tid].find(bnd_id) == _interface_mat_side_cache[tid].end())
9009 : {
9010 3238 : auto & interface_mat_side_cache = _interface_mat_side_cache[tid][bnd_id];
9011 3238 : interface_mat_side_cache = false;
9012 :
9013 : // Aux-system has not needed interface materials so far
9014 6206 : for (auto & nl : _nl)
9015 3238 : if (nl->needInterfaceMaterialOnSide(bnd_id, tid))
9016 : {
9017 270 : interface_mat_side_cache = true;
9018 270 : return true;
9019 : }
9020 :
9021 : // TODO: these objects should be checked for whether they actually consume materials
9022 2968 : if (theWarehouse()
9023 5936 : .query()
9024 2968 : .condition<AttribThread>(tid)
9025 2968 : .condition<AttribInterfaces>(Interfaces::InterfaceUserObject |
9026 : Interfaces::DomainUserObject)
9027 2968 : .condition<AttribBoundaries>(bnd_id)
9028 2968 : .count() > 0)
9029 : {
9030 90 : interface_mat_side_cache = true;
9031 90 : return true;
9032 : }
9033 2878 : else if (_interface_materials.hasActiveBoundaryObjects(bnd_id, tid))
9034 : {
9035 11 : interface_mat_side_cache = true;
9036 11 : return true;
9037 : }
9038 : }
9039 458211 : return _interface_mat_side_cache[tid][bnd_id];
9040 : }
9041 :
9042 : bool
9043 446453 : FEProblemBase::needInternalNeighborSideMaterial(SubdomainID subdomain_id, const THREAD_ID tid)
9044 : {
9045 446453 : if (_block_mat_side_cache[tid].find(subdomain_id) == _block_mat_side_cache[tid].end())
9046 : {
9047 13486 : _block_mat_side_cache[tid][subdomain_id] = false;
9048 :
9049 26394 : for (auto & nl : _nl)
9050 13403 : if (nl->needInternalNeighborSideMaterial(subdomain_id, tid))
9051 : {
9052 495 : _block_mat_side_cache[tid][subdomain_id] = true;
9053 495 : return true;
9054 : }
9055 :
9056 : // TODO: these objects should be checked for whether they actually consume materials
9057 12991 : if (theWarehouse()
9058 25982 : .query()
9059 12991 : .condition<AttribThread>(tid)
9060 12991 : .condition<AttribInterfaces>(Interfaces::InternalSideUserObject |
9061 : Interfaces::DomainUserObject)
9062 12991 : .condition<AttribSubdomains>(subdomain_id)
9063 12991 : .count() > 0)
9064 : {
9065 38 : _block_mat_side_cache[tid][subdomain_id] = true;
9066 38 : return true;
9067 : }
9068 : }
9069 :
9070 445920 : return _block_mat_side_cache[tid][subdomain_id];
9071 : }
9072 :
9073 : bool
9074 316888 : FEProblemBase::needsPreviousNewtonIteration() const
9075 : {
9076 316888 : return vectorTagExists(Moose::PREVIOUS_NL_SOLUTION_TAG);
9077 : }
9078 :
9079 : void
9080 82 : FEProblemBase::needsPreviousNewtonIteration(bool state)
9081 : {
9082 82 : if (state && !vectorTagExists(Moose::PREVIOUS_NL_SOLUTION_TAG))
9083 0 : mooseError("Previous nonlinear solution is required but not added through "
9084 : "Problem/previous_nl_solution_required=true");
9085 82 : }
9086 :
9087 : bool
9088 8536346 : FEProblemBase::hasJacobian() const
9089 : {
9090 8536346 : return _has_jacobian;
9091 : }
9092 :
9093 : bool
9094 7990258 : FEProblemBase::constJacobian() const
9095 : {
9096 7990258 : return _const_jacobian;
9097 : }
9098 :
9099 : void
9100 298471 : FEProblemBase::addOutput(const std::string & object_type,
9101 : const std::string & object_name,
9102 : InputParameters & parameters)
9103 : {
9104 : parallel_object_only();
9105 :
9106 : // Get a reference to the OutputWarehouse
9107 298471 : OutputWarehouse & output_warehouse = _app.getOutputWarehouse();
9108 :
9109 : // Reject the reserved names for objects not built by MOOSE
9110 298471 : if (!parameters.get<bool>("_built_by_moose") && output_warehouse.isReservedName(object_name))
9111 8 : mooseError("The name '", object_name, "' is a reserved name for output objects");
9112 :
9113 : // Check that an object by the same name does not already exist; this must be done before the
9114 : // object is created to avoid getting misleading errors from the Parser
9115 298463 : if (output_warehouse.hasOutput(object_name))
9116 4 : mooseError("An output object named '", object_name, "' already exists");
9117 :
9118 : // Add a pointer to the FEProblemBase class
9119 596918 : parameters.addPrivateParam<FEProblemBase *>("_fe_problem_base", this);
9120 :
9121 : // Create common parameter exclude list
9122 298459 : std::vector<std::string> exclude;
9123 298459 : if (object_type == "Console")
9124 : {
9125 63456 : exclude.push_back("execute_on");
9126 :
9127 : // --show-input should enable the display of the input file on the screen
9128 190368 : if (_app.getParam<bool>("show_input") && parameters.get<bool>("output_screen"))
9129 60 : parameters.set<ExecFlagEnum>("execute_input_on") = EXEC_INITIAL;
9130 : }
9131 : // Need this because Checkpoint::validParams changes the default value of
9132 : // execute_on
9133 235003 : else if (object_type == "Checkpoint")
9134 102180 : exclude.push_back("execute_on");
9135 :
9136 : // Apply the common parameters loaded with Outputs input syntax
9137 298459 : const InputParameters * common = output_warehouse.getCommonParameters();
9138 298459 : if (common)
9139 298459 : parameters.applyParameters(*common, exclude);
9140 298459 : if (common && std::find(exclude.begin(), exclude.end(), "execute_on") != exclude.end() &&
9141 826010 : common->isParamSetByUser("execute_on") && object_type != "Console")
9142 7082 : mooseInfoRepeated(
9143 14164 : "'execute_on' parameter specified in [Outputs] block is ignored for object '" +
9144 21246 : object_name +
9145 : "'.\nDefine this object in its own sub-block of [Outputs] to modify its "
9146 : "execution schedule.");
9147 :
9148 : // Set the correct value for the binary flag for XDA/XDR output
9149 298459 : if (object_type == "XDR")
9150 130 : parameters.set<bool>("_binary") = true;
9151 298394 : else if (object_type == "XDA")
9152 242 : parameters.set<bool>("_binary") = false;
9153 :
9154 : // Adjust the checkpoint suffix if auto recovery was enabled
9155 298459 : if (object_name == "auto_recovery_checkpoint")
9156 0 : parameters.set<std::string>("suffix") = "auto_recovery";
9157 :
9158 : // Create the object and add it to the warehouse
9159 298459 : std::shared_ptr<Output> output = _factory.create<Output>(object_type, object_name, parameters);
9160 298443 : logAdd("Output", object_name, object_type, parameters);
9161 298443 : output_warehouse.addOutput(output);
9162 298443 : }
9163 :
9164 : void
9165 28343 : FEProblemBase::haveADObjects(const bool have_ad_objects)
9166 : {
9167 28343 : _have_ad_objects = have_ad_objects;
9168 28343 : if (_displaced_problem)
9169 247 : _displaced_problem->SubProblem::haveADObjects(have_ad_objects);
9170 28343 : }
9171 :
9172 : const SystemBase &
9173 0 : FEProblemBase::getSystemBase(const unsigned int sys_num) const
9174 : {
9175 0 : if (sys_num < _solver_systems.size())
9176 0 : return *_solver_systems[sys_num];
9177 :
9178 0 : return *_aux;
9179 : }
9180 :
9181 : SystemBase &
9182 929 : FEProblemBase::getSystemBase(const std::string & sys_name)
9183 : {
9184 929 : if (std::find(_solver_sys_names.begin(), _solver_sys_names.end(), sys_name) !=
9185 1858 : _solver_sys_names.end())
9186 929 : return getSystemBase(solverSysNum(sys_name));
9187 0 : else if (sys_name == "aux0")
9188 0 : return *_aux;
9189 : else
9190 0 : mooseError("System '" + sys_name + "' was requested from problem but does not exist.");
9191 : }
9192 :
9193 : SystemBase &
9194 2570 : FEProblemBase::getSystemBase(const unsigned int sys_num)
9195 : {
9196 2570 : if (sys_num < _solver_systems.size())
9197 2459 : return *_solver_systems[sys_num];
9198 :
9199 111 : return *_aux;
9200 : }
9201 :
9202 : const SystemBase &
9203 14623 : FEProblemBase::systemBaseNonlinear(const unsigned int sys_num) const
9204 : {
9205 : mooseAssert(sys_num < _nl.size(), "System number greater than the number of nonlinear systems");
9206 14623 : return *_nl[sys_num];
9207 : }
9208 :
9209 : SystemBase &
9210 1397026 : FEProblemBase::systemBaseNonlinear(const unsigned int sys_num)
9211 : {
9212 : mooseAssert(sys_num < _nl.size(), "System number greater than the number of nonlinear systems");
9213 1397026 : return *_nl[sys_num];
9214 : }
9215 :
9216 : const SystemBase &
9217 0 : FEProblemBase::systemBaseLinear(const unsigned int sys_num) const
9218 : {
9219 : mooseAssert(sys_num < _linear_systems.size(),
9220 : "System number greater than the number of linear systems");
9221 0 : return *_linear_systems[sys_num];
9222 : }
9223 :
9224 : SystemBase &
9225 0 : FEProblemBase::systemBaseLinear(const unsigned int sys_num)
9226 : {
9227 : mooseAssert(sys_num < _linear_systems.size(),
9228 : "System number greater than the number of linear systems");
9229 0 : return *_linear_systems[sys_num];
9230 : }
9231 :
9232 : const SystemBase &
9233 0 : FEProblemBase::systemBaseSolver(const unsigned int sys_num) const
9234 : {
9235 : mooseAssert(sys_num < _solver_systems.size(),
9236 : "System number greater than the number of solver systems");
9237 0 : return *_solver_systems[sys_num];
9238 : }
9239 :
9240 : SystemBase &
9241 7403087 : FEProblemBase::systemBaseSolver(const unsigned int sys_num)
9242 : {
9243 : mooseAssert(sys_num < _solver_systems.size(),
9244 : "System number greater than the number of solver systems");
9245 7403087 : return *_solver_systems[sys_num];
9246 : }
9247 :
9248 : const SystemBase &
9249 18 : FEProblemBase::systemBaseAuxiliary() const
9250 : {
9251 18 : return *_aux;
9252 : }
9253 :
9254 : SystemBase &
9255 9412953 : FEProblemBase::systemBaseAuxiliary()
9256 : {
9257 9412953 : return *_aux;
9258 : }
9259 :
9260 : void
9261 4337099 : FEProblemBase::computingNonlinearResid(bool computing_nonlinear_residual)
9262 : {
9263 : parallel_object_only();
9264 :
9265 4337099 : if (_displaced_problem)
9266 212324 : _displaced_problem->computingNonlinearResid(computing_nonlinear_residual);
9267 4337099 : _computing_nonlinear_residual = computing_nonlinear_residual;
9268 4337099 : }
9269 :
9270 : void
9271 10586336 : FEProblemBase::setCurrentlyComputingResidual(bool currently_computing_residual)
9272 : {
9273 10586336 : if (_displaced_problem)
9274 433724 : _displaced_problem->setCurrentlyComputingResidual(currently_computing_residual);
9275 10586336 : _currently_computing_residual = currently_computing_residual;
9276 10586336 : }
9277 :
9278 : void
9279 57 : FEProblemBase::uniformRefine()
9280 : {
9281 : // ResetDisplacedMeshThread::onNode looks up the reference mesh by ID, so we need to make sure
9282 : // we undisplace before adapting the reference mesh
9283 57 : if (_displaced_problem)
9284 37 : _displaced_problem->undisplaceMesh();
9285 :
9286 57 : Adaptivity::uniformRefine(&_mesh, 1);
9287 57 : if (_displaced_problem)
9288 37 : Adaptivity::uniformRefine(&_displaced_problem->mesh(), 1);
9289 :
9290 57 : meshChanged(
9291 : /*intermediate_change=*/false, /*contract_mesh=*/true, /*clean_refinement_flags=*/true);
9292 57 : }
9293 :
9294 : void
9295 63967 : FEProblemBase::automaticScaling(bool automatic_scaling)
9296 : {
9297 63967 : if (_displaced_problem)
9298 2246 : _displaced_problem->automaticScaling(automatic_scaling);
9299 :
9300 63967 : SubProblem::automaticScaling(automatic_scaling);
9301 63967 : }
9302 :
9303 : void
9304 284429 : FEProblemBase::reinitElemFaceRef(const Elem * elem,
9305 : unsigned int side,
9306 : Real tolerance,
9307 : const std::vector<Point> * const pts,
9308 : const std::vector<Real> * const weights,
9309 : const THREAD_ID tid)
9310 : {
9311 284429 : SubProblem::reinitElemFaceRef(elem, side, tolerance, pts, weights, tid);
9312 :
9313 284429 : if (_displaced_problem)
9314 22778 : _displaced_problem->reinitElemFaceRef(
9315 22778 : _displaced_mesh->elemPtr(elem->id()), side, tolerance, pts, weights, tid);
9316 284429 : }
9317 :
9318 : void
9319 284429 : FEProblemBase::reinitNeighborFaceRef(const Elem * neighbor_elem,
9320 : unsigned int neighbor_side,
9321 : Real tolerance,
9322 : const std::vector<Point> * const pts,
9323 : const std::vector<Real> * const weights,
9324 : const THREAD_ID tid)
9325 : {
9326 284429 : SubProblem::reinitNeighborFaceRef(neighbor_elem, neighbor_side, tolerance, pts, weights, tid);
9327 :
9328 284429 : if (_displaced_problem)
9329 22778 : _displaced_problem->reinitNeighborFaceRef(
9330 22778 : _displaced_mesh->elemPtr(neighbor_elem->id()), neighbor_side, tolerance, pts, weights, tid);
9331 284429 : }
9332 :
9333 : void
9334 3857812 : FEProblemBase::getFVMatsAndDependencies(
9335 : const SubdomainID blk_id,
9336 : std::vector<std::shared_ptr<MaterialBase>> & face_materials,
9337 : std::vector<std::shared_ptr<MaterialBase>> & neighbor_materials,
9338 : std::set<MooseVariableFieldBase *> & variables,
9339 : const THREAD_ID tid)
9340 : {
9341 3857812 : if (_materials[Moose::FACE_MATERIAL_DATA].hasActiveBlockObjects(blk_id, tid))
9342 : {
9343 : auto & this_face_mats =
9344 3996 : _materials[Moose::FACE_MATERIAL_DATA].getActiveBlockObjects(blk_id, tid);
9345 8196 : for (std::shared_ptr<MaterialBase> face_mat : this_face_mats)
9346 4200 : if (face_mat->ghostable())
9347 : {
9348 4200 : face_materials.push_back(face_mat);
9349 4200 : auto & var_deps = face_mat->getMooseVariableDependencies();
9350 4608 : for (auto * var : var_deps)
9351 : {
9352 408 : if (!var->isFV())
9353 0 : mooseError(
9354 : "Ghostable materials should only have finite volume variables coupled into them.");
9355 408 : else if (face_mat->hasStatefulProperties())
9356 0 : mooseError("Finite volume materials do not currently support stateful properties.");
9357 408 : variables.insert(var);
9358 : }
9359 4200 : }
9360 : }
9361 :
9362 3857812 : if (_materials[Moose::NEIGHBOR_MATERIAL_DATA].hasActiveBlockObjects(blk_id, tid))
9363 : {
9364 : auto & this_neighbor_mats =
9365 3996 : _materials[Moose::NEIGHBOR_MATERIAL_DATA].getActiveBlockObjects(blk_id, tid);
9366 8196 : for (std::shared_ptr<MaterialBase> neighbor_mat : this_neighbor_mats)
9367 4200 : if (neighbor_mat->ghostable())
9368 : {
9369 4200 : neighbor_materials.push_back(neighbor_mat);
9370 : #ifndef NDEBUG
9371 : auto & var_deps = neighbor_mat->getMooseVariableDependencies();
9372 : for (auto * var : var_deps)
9373 : {
9374 : if (!var->isFV())
9375 : mooseError(
9376 : "Ghostable materials should only have finite volume variables coupled into them.");
9377 : else if (neighbor_mat->hasStatefulProperties())
9378 : mooseError("Finite volume materials do not currently support stateful properties.");
9379 : auto pr = variables.insert(var);
9380 : mooseAssert(!pr.second,
9381 : "We should not have inserted any new variables dependencies from our "
9382 : "neighbor materials that didn't exist for our face materials");
9383 : }
9384 : #endif
9385 4200 : }
9386 : }
9387 3857812 : }
9388 :
9389 : void
9390 48898539 : FEProblemBase::resizeMaterialData(const Moose::MaterialDataType data_type,
9391 : const unsigned int nqp,
9392 : const THREAD_ID tid)
9393 : {
9394 48898539 : getMaterialData(data_type, tid).resize(nqp);
9395 48898539 : }
9396 :
9397 : void
9398 63887 : FEProblemBase::setNonlinearConvergenceNames(const std::vector<ConvergenceName> & convergence_names)
9399 : {
9400 63887 : if (convergence_names.size() != numNonlinearSystems())
9401 0 : paramError("nonlinear_convergence",
9402 : "There must be one convergence object per nonlinear system");
9403 63887 : _nonlinear_convergence_names = convergence_names;
9404 63887 : }
9405 :
9406 : void
9407 64234 : FEProblemBase::setMultiAppFixedPointConvergenceName(const ConvergenceName & convergence_name)
9408 : {
9409 64234 : _multiapp_fixed_point_convergence_name = convergence_name;
9410 64234 : }
9411 :
9412 : void
9413 32027 : FEProblemBase::setSteadyStateConvergenceName(const ConvergenceName & convergence_name)
9414 : {
9415 32027 : _steady_state_convergence_name = convergence_name;
9416 32027 : }
9417 :
9418 : const std::vector<ConvergenceName> &
9419 1080782 : FEProblemBase::getNonlinearConvergenceNames() const
9420 : {
9421 1080782 : if (_nonlinear_convergence_names)
9422 1080782 : return *_nonlinear_convergence_names;
9423 0 : mooseError("The nonlinear system convergence name(s) have not been set.");
9424 : }
9425 :
9426 : bool
9427 6097 : FEProblemBase::hasLinearConvergenceObjects() const
9428 : {
9429 : // If false,this means we have not set one, not that we are querying this too early
9430 : // TODO: once there is a default linear CV object, error on the 'not set' case
9431 6097 : return _linear_convergence_names.has_value();
9432 : }
9433 :
9434 : void
9435 181 : FEProblemBase::setLinearConvergenceNames(const std::vector<ConvergenceName> & convergence_names)
9436 : {
9437 181 : if (convergence_names.size() != numLinearSystems())
9438 0 : paramError("linear_convergence", "There must be one convergence object per linear system");
9439 181 : _linear_convergence_names = convergence_names;
9440 181 : }
9441 :
9442 : const std::vector<ConvergenceName> &
9443 2634 : FEProblemBase::getLinearConvergenceNames() const
9444 : {
9445 2634 : if (_linear_convergence_names)
9446 2634 : return *_linear_convergence_names;
9447 0 : mooseError("The linear convergence name(s) have not been set.");
9448 : }
9449 :
9450 : const ConvergenceName &
9451 265087 : FEProblemBase::getMultiAppFixedPointConvergenceName() const
9452 : {
9453 265087 : if (_multiapp_fixed_point_convergence_name)
9454 265087 : return _multiapp_fixed_point_convergence_name.value();
9455 : else
9456 0 : mooseError("The fixed point convergence name has not been set.");
9457 : }
9458 :
9459 : const ConvergenceName &
9460 109121 : FEProblemBase::getSteadyStateConvergenceName() const
9461 : {
9462 109121 : if (_steady_state_convergence_name)
9463 109121 : return _steady_state_convergence_name.value();
9464 : else
9465 0 : mooseError("The steady convergence name has not been set.");
9466 : }
9467 :
9468 : void
9469 3351236 : FEProblemBase::residualSetup()
9470 : {
9471 3351236 : SubProblem::residualSetup();
9472 : // We need to setup all the nonlinear systems other than our current one which actually called
9473 : // this method (so we have to make sure we don't go in a circle)
9474 6795012 : for (const auto i : make_range(numNonlinearSystems()))
9475 3443776 : if (i != currentNlSysNum())
9476 92540 : _nl[i]->residualSetup();
9477 : // We don't setup the aux sys because that's been done elsewhere
9478 3351236 : if (_displaced_problem)
9479 137184 : _displaced_problem->residualSetup();
9480 3351236 : }
9481 :
9482 : void
9483 529227 : FEProblemBase::jacobianSetup()
9484 : {
9485 529227 : SubProblem::jacobianSetup();
9486 : // We need to setup all the nonlinear systems other than our current one which actually called
9487 : // this method (so we have to make sure we don't go in a circle)
9488 1074514 : for (const auto i : make_range(numNonlinearSystems()))
9489 545287 : if (i != currentNlSysNum())
9490 16060 : _nl[i]->jacobianSetup();
9491 : // We don't setup the aux sys because that's been done elsewhere
9492 529227 : if (_displaced_problem)
9493 23344 : _displaced_problem->jacobianSetup();
9494 529227 : }
9495 :
9496 : MooseAppCoordTransform &
9497 104848 : FEProblemBase::coordTransform()
9498 : {
9499 104848 : return mesh().coordTransform();
9500 : }
9501 :
9502 : unsigned int
9503 594903066 : FEProblemBase::currentNlSysNum() const
9504 : {
9505 : // If we don't have nonlinear systems this should be an invalid number
9506 594903066 : unsigned int current_nl_sys_num = libMesh::invalid_uint;
9507 594903066 : if (_nl.size())
9508 594898970 : current_nl_sys_num = currentNonlinearSystem().number();
9509 :
9510 594903066 : return current_nl_sys_num;
9511 : }
9512 :
9513 : unsigned int
9514 0 : FEProblemBase::currentLinearSysNum() const
9515 : {
9516 : // If we don't have linear systems this should be an invalid number
9517 0 : unsigned int current_linear_sys_num = libMesh::invalid_uint;
9518 0 : if (_linear_systems.size())
9519 0 : current_linear_sys_num = currentLinearSystem().number();
9520 :
9521 0 : return current_linear_sys_num;
9522 : }
9523 :
9524 : bool
9525 139555927 : FEProblemBase::shouldPrintExecution(const THREAD_ID tid) const
9526 : {
9527 : // For now, only support printing from thread 0
9528 139555927 : if (tid != 0)
9529 8147435 : return false;
9530 :
9531 262529722 : if (_print_execution_on.isValueSet(_current_execute_on_flag) ||
9532 131121230 : _print_execution_on.isValueSet(EXEC_ALWAYS))
9533 376597 : return true;
9534 : else
9535 131031895 : return false;
9536 : }
9537 :
9538 : std::vector<MortarUserObject *>
9539 283097 : FEProblemBase::getMortarUserObjects(const BoundaryID primary_boundary_id,
9540 : const BoundaryID secondary_boundary_id,
9541 : const bool displaced,
9542 : const std::vector<MortarUserObject *> & mortar_uo_superset)
9543 : {
9544 283097 : std::vector<MortarUserObject *> mortar_uos;
9545 283097 : auto * const subproblem = displaced ? static_cast<SubProblem *>(_displaced_problem.get())
9546 283097 : : static_cast<SubProblem *>(this);
9547 283121 : for (auto * const obj : mortar_uo_superset)
9548 48 : if (obj->onInterface(primary_boundary_id, secondary_boundary_id) &&
9549 24 : (&obj->getSubProblem() == subproblem))
9550 24 : mortar_uos.push_back(obj);
9551 :
9552 283097 : return mortar_uos;
9553 0 : }
9554 :
9555 : std::vector<MortarUserObject *>
9556 283073 : FEProblemBase::getMortarUserObjects(const BoundaryID primary_boundary_id,
9557 : const BoundaryID secondary_boundary_id,
9558 : const bool displaced)
9559 : {
9560 283073 : std::vector<MortarUserObject *> mortar_uos;
9561 283073 : theWarehouse()
9562 283073 : .query()
9563 566146 : .condition<AttribInterfaces>(Interfaces::MortarUserObject)
9564 283073 : .queryInto(mortar_uos);
9565 566146 : return getMortarUserObjects(primary_boundary_id, secondary_boundary_id, displaced, mortar_uos);
9566 283073 : }
9567 :
9568 : void
9569 283073 : FEProblemBase::reinitMortarUserObjects(const BoundaryID primary_boundary_id,
9570 : const BoundaryID secondary_boundary_id,
9571 : const bool displaced)
9572 : {
9573 : const auto mortar_uos =
9574 283073 : getMortarUserObjects(primary_boundary_id, secondary_boundary_id, displaced);
9575 283073 : for (auto * const mortar_uo : mortar_uos)
9576 : {
9577 0 : mortar_uo->setNormals();
9578 0 : mortar_uo->reinit();
9579 : }
9580 283073 : }
9581 :
9582 : void
9583 1154 : FEProblemBase::setVerboseProblem(bool verbose)
9584 : {
9585 1154 : _verbose_setup = verbose ? "true" : "false";
9586 1154 : _verbose_multiapps = verbose;
9587 1154 : _verbose_restore = verbose;
9588 1154 : }
9589 :
9590 : void
9591 126057 : FEProblemBase::setCurrentLowerDElem(const Elem * const lower_d_elem, const THREAD_ID tid)
9592 : {
9593 126057 : SubProblem::setCurrentLowerDElem(lower_d_elem, tid);
9594 126057 : if (_displaced_problem)
9595 31448 : _displaced_problem->setCurrentLowerDElem(
9596 0 : lower_d_elem ? _displaced_mesh->elemPtr(lower_d_elem->id()) : nullptr, tid);
9597 126057 : }
9598 :
9599 : void
9600 135910256 : FEProblemBase::setCurrentBoundaryID(BoundaryID bid, const THREAD_ID tid)
9601 : {
9602 135910256 : SubProblem::setCurrentBoundaryID(bid, tid);
9603 135910256 : if (_displaced_problem)
9604 10148584 : _displaced_problem->setCurrentBoundaryID(bid, tid);
9605 135910256 : }
9606 :
9607 : void
9608 8159624 : FEProblemBase::setCurrentNonlinearSystem(const unsigned int nl_sys_num)
9609 : {
9610 : mooseAssert(nl_sys_num < _nl.size(),
9611 : "System number greater than the number of nonlinear systems");
9612 8159624 : _current_nl_sys = _nl[nl_sys_num].get();
9613 8159624 : _current_solver_sys = _current_nl_sys;
9614 8159624 : }
9615 :
9616 : void
9617 17124 : FEProblemBase::setCurrentLinearSystem(const unsigned int sys_num)
9618 : {
9619 : mooseAssert(sys_num < _linear_systems.size(),
9620 : "System number greater than the number of linear systems");
9621 17124 : _current_linear_sys = _linear_systems[sys_num].get();
9622 17124 : _current_solver_sys = _current_linear_sys;
9623 17124 : }
9624 :
9625 : void
9626 6372780 : FEProblemBase::computeSystems(const ExecFlagType & type)
9627 : {
9628 : // When performing an adjoint solve in the optimization module, the current solver system is the
9629 : // adjoint. However, the adjoint solve requires having accurate time derivative calculations for
9630 : // the forward system. The cleanest way to handle such uses is just to compute the time
9631 : // derivatives for all solver systems instead of trying to guess which ones we need and don't need
9632 12901329 : for (auto & solver_sys : _solver_systems)
9633 6528549 : solver_sys->compute(type);
9634 :
9635 6372780 : _aux->compute(type);
9636 6372735 : }
9637 :
9638 : const ConstElemRange &
9639 3882267 : FEProblemBase::getCurrentAlgebraicElementRange()
9640 : {
9641 3882267 : if (!_current_algebraic_elem_range)
9642 3882267 : return *_mesh.getActiveLocalElementRange();
9643 :
9644 0 : return *_current_algebraic_elem_range;
9645 : }
9646 : const ConstNodeRange &
9647 20503 : FEProblemBase::getCurrentAlgebraicNodeRange()
9648 : {
9649 20503 : if (!_current_algebraic_node_range)
9650 20503 : return *_mesh.getLocalNodeRange();
9651 :
9652 0 : return *_current_algebraic_node_range;
9653 : }
9654 : const ConstBndNodeRange &
9655 3644239 : FEProblemBase::getCurrentAlgebraicBndNodeRange()
9656 : {
9657 3644239 : if (!_current_algebraic_bnd_node_range)
9658 3644239 : return *_mesh.getBoundaryNodeRange();
9659 :
9660 0 : return *_current_algebraic_bnd_node_range;
9661 : }
9662 :
9663 : void
9664 0 : FEProblemBase::setCurrentAlgebraicElementRange(ConstElemRange * range)
9665 : {
9666 0 : if (!range)
9667 : {
9668 0 : _current_algebraic_elem_range = nullptr;
9669 0 : return;
9670 : }
9671 :
9672 0 : _current_algebraic_elem_range = std::make_unique<ConstElemRange>(*range);
9673 : }
9674 : void
9675 0 : FEProblemBase::setCurrentAlgebraicNodeRange(ConstNodeRange * range)
9676 : {
9677 0 : if (!range)
9678 : {
9679 0 : _current_algebraic_node_range = nullptr;
9680 0 : return;
9681 : }
9682 :
9683 0 : _current_algebraic_node_range = std::make_unique<ConstNodeRange>(*range);
9684 : }
9685 : void
9686 0 : FEProblemBase::setCurrentAlgebraicBndNodeRange(ConstBndNodeRange * range)
9687 : {
9688 0 : if (!range)
9689 : {
9690 0 : _current_algebraic_bnd_node_range = nullptr;
9691 0 : return;
9692 : }
9693 :
9694 0 : _current_algebraic_bnd_node_range = std::make_unique<ConstBndNodeRange>(*range);
9695 : }
9696 :
9697 : unsigned short
9698 66054 : FEProblemBase::getCurrentICState()
9699 : {
9700 66054 : return _current_ic_state;
9701 : }
9702 :
9703 : std::string
9704 56193 : FEProblemBase::solverTypeString(const unsigned int solver_sys_num)
9705 : {
9706 56193 : return Moose::stringify(solverParams(solver_sys_num)._type);
9707 : }
9708 :
9709 : SolverParams
9710 1340 : FEProblemBase::makeLinearSolverParams()
9711 : {
9712 1340 : SolverParams solver_params;
9713 1340 : solver_params._type = Moose::SolveType::ST_LINEAR;
9714 1340 : solver_params._line_search = Moose::LineSearchType::LS_NONE;
9715 1340 : return solver_params;
9716 : }
9717 :
9718 : const libMesh::CouplingMatrix &
9719 73958 : FEProblemBase::nonlocalCouplingMatrix(const unsigned i) const
9720 : {
9721 73958 : return _nonlocal_cm[i];
9722 : }
9723 :
9724 : bool
9725 105865876 : FEProblemBase::checkNonlocalCouplingRequirement() const
9726 : {
9727 105865876 : return _requires_nonlocal_coupling;
9728 : }
9729 :
9730 : const std::unordered_map<std::pair<BoundaryID, BoundaryID>,
9731 : std::unique_ptr<AutomaticMortarGeneration>> &
9732 121682 : FEProblemBase::getMortarInterfaces(bool on_displaced) const
9733 : {
9734 121682 : return _mortar_data->getMortarInterfaces(on_displaced);
9735 : }
|