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