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