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