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