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 63 : sortMooseVariables(const MooseVariableFEBase * a, const MooseVariableFEBase * b)
154 : {
155 63 : return a->number() < b->number();
156 : }
157 : } // namespace
158 :
159 : Threads::spin_mutex get_function_mutex;
160 :
161 : InputParameters
162 190123 : FEProblemBase::validParams()
163 : {
164 190123 : InputParameters params = SubProblem::validParams();
165 760492 : params.addParam<unsigned int>("null_space_dimension", 0, "The dimension of the nullspace");
166 570369 : params.addParam<unsigned int>(
167 380246 : "transpose_null_space_dimension", 0, "The dimension of the transpose nullspace");
168 570369 : params.addParam<unsigned int>(
169 380246 : "near_null_space_dimension", 0, "The dimension of the near nullspace");
170 570369 : params.addParam<bool>("solve",
171 380246 : 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 570369 : params.addParam<bool>("use_nonlinear",
177 380246 : true,
178 : "Determines whether to use a Nonlinear vs a "
179 : "Eigenvalue system (Automatically determined based "
180 : "on executioner)");
181 760492 : 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 570369 : params.addParam<bool>("ignore_zeros_in_jacobian",
185 380246 : false,
186 : "Do not explicitly store zero values in "
187 : "the Jacobian matrix if true");
188 570369 : params.addParam<bool>("force_restart",
189 380246 : 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 950615 : params.addDeprecatedParam<bool>("skip_additional_restart_data",
194 380246 : 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 570369 : params.addParam<bool>("skip_nl_system_check",
199 380246 : 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 570369 : params.addParam<bool>("allow_initial_conditions_with_restart",
203 380246 : false,
204 : "True to allow the user to specify initial conditions when restarting. "
205 : "Initial conditions can override any restarted field");
206 :
207 380246 : auto coverage_check_description = [](std::string scope, std::string list_param_name)
208 : {
209 760492 : 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 760492 : "be used, while the subdomains to skip are to be defined in the parameter '" +
215 760492 : list_param_name +
216 : "'. To limit the check to a list of subdomains, 'ONLY_LIST' is to "
217 1140738 : "be used (again, using the parameter '" +
218 760492 : list_param_name + "').";
219 : };
220 :
221 950615 : 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 760492 : MooseEnum kernel_coverage_check_modes("FALSE TRUE OFF ON SKIP_LIST ONLY_LIST", "TRUE");
229 190123 : params.addParam<MooseEnum>("kernel_coverage_check",
230 : kernel_coverage_check_modes,
231 950615 : coverage_check_description("kernel", "kernel_coverage_block_list"));
232 760492 : 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 570369 : params.addParam<bool>(
239 : "boundary_restricted_node_integrity_check",
240 380246 : 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 570369 : params.addParam<bool>("boundary_restricted_elem_integrity_check",
244 380246 : 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 760492 : MooseEnum material_coverage_check_modes("FALSE TRUE OFF ON SKIP_LIST ONLY_LIST", "TRUE");
249 190123 : params.addParam<MooseEnum>(
250 : "material_coverage_check",
251 : material_coverage_check_modes,
252 950615 : coverage_check_description("material", "material_coverage_block_list"));
253 760492 : 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 570369 : params.addParam<bool>("fv_bcs_integrity_check",
261 380246 : true,
262 : "Set to false to disable checking of overlapping Dirichlet and Flux BCs "
263 : "and/or multiple DirichletBCs per sideset");
264 :
265 570369 : params.addParam<bool>(
266 380246 : "material_dependency_check", true, "Set to false to disable material dependency check");
267 570369 : params.addParam<bool>("parallel_barrier_messaging",
268 380246 : false,
269 : "Displays messaging from parallel "
270 : "barrier notifications when executing "
271 : "or transferring to/from Multiapps "
272 : "(default: false)");
273 :
274 760492 : MooseEnum verbosity("false true extra", "false");
275 760492 : 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 570369 : params.addParam<bool>("verbose_multiapps",
280 380246 : false,
281 : "Set to True to enable verbose screen printing related to MultiApps");
282 570369 : params.addParam<bool>(
283 : "verbose_restore",
284 380246 : false,
285 : "Set to True to enable verbose screen printing related to solution restoration");
286 :
287 760492 : 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 760492 : 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 760492 : 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 760492 : 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 760492 : 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 570369 : params.addParam<bool>("previous_nl_solution_required",
320 380246 : false,
321 : "True to indicate that this calculation requires a solution vector for "
322 : "storing the previous nonlinear iteration.");
323 :
324 570369 : params.addParam<std::vector<NonlinearSystemName>>(
325 760492 : "nl_sys_names", std::vector<NonlinearSystemName>{"nl0"}, "The nonlinear system names");
326 :
327 760492 : params.addParam<std::vector<LinearSystemName>>("linear_sys_names", {}, "The linear system names");
328 :
329 570369 : params.addParam<bool>("check_uo_aux_state",
330 380246 : false,
331 : "True to turn on a check that no state presents during the evaluation of "
332 : "user objects and aux kernels");
333 :
334 190123 : params.addPrivateParam<MooseMesh *>("mesh");
335 :
336 570369 : params.declareControllable("solve");
337 :
338 570369 : params.addParam<bool>(
339 : "allow_invalid_solution",
340 380246 : false,
341 : "Set to true to allow convergence even though the solution has been marked as 'invalid'");
342 570369 : params.addParam<bool>("show_invalid_solution_console",
343 380246 : true,
344 : "Set to true to show the invalid solution occurrence summary in console");
345 570369 : params.addParam<bool>("immediately_print_invalid_solution",
346 380246 : 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 570369 : params.addParam<bool>(
351 : "identify_variable_groups_in_nl",
352 380246 : true,
353 : "Whether to identify variable groups in nonlinear systems. This affects dof ordering");
354 :
355 570369 : params.addParam<bool>(
356 : "regard_general_exceptions_as_errors",
357 380246 : 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 570369 : params.addParam<bool>("use_hash_table_matrix_assembly",
362 380246 : 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 760492 : 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 760492 : 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 760492 : 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 760492 : params.addParamNamesToGroup(
385 : "restart_file_base force_restart allow_initial_conditions_with_restart", "Restart");
386 760492 : params.addParamNamesToGroup(
387 : "verbose_setup verbose_multiapps verbose_restore parallel_barrier_messaging", "Verbosity");
388 760492 : params.addParamNamesToGroup(
389 : "null_space_dimension transpose_null_space_dimension near_null_space_dimension",
390 : "Null space removal");
391 760492 : params.addParamNamesToGroup(
392 : "extra_tag_vectors extra_tag_matrices extra_tag_solutions not_zeroed_tag_vectors",
393 : "Contribution to tagged field data");
394 570369 : params.addParamNamesToGroup(
395 : "allow_invalid_solution show_invalid_solution_console immediately_print_invalid_solution",
396 : "Solution validity control");
397 :
398 380246 : return params;
399 570369 : }
400 :
401 61654 : FEProblemBase::FEProblemBase(const InputParameters & parameters)
402 : : SubProblem(parameters),
403 : Restartable(this, "FEProblemBase"),
404 246616 : _mesh(*getCheckedPointerParam<MooseMesh *>("mesh")),
405 123308 : _req(declareManagedRestartableDataWithContext<RestartableEquationSystems>(
406 : "equation_systems", nullptr, _mesh)),
407 61654 : _initialized(false),
408 123308 : _solve(getParam<bool>("solve")),
409 61654 : _transient(false),
410 123308 : _time(declareRestartableData<Real>("time")),
411 123308 : _time_old(declareRestartableData<Real>("time_old")),
412 123308 : _t_step(declareRecoverableData<int>("t_step")),
413 123308 : _dt(declareRestartableData<Real>("dt")),
414 123308 : _dt_old(declareRestartableData<Real>("dt_old")),
415 61654 : _need_to_add_default_nonlinear_convergence(false),
416 61654 : _need_to_add_default_multiapp_fixed_point_convergence(false),
417 61654 : _need_to_add_default_steady_state_convergence(false),
418 123308 : _linear_sys_names(getParam<std::vector<LinearSystemName>>("linear_sys_names")),
419 61654 : _num_linear_sys(_linear_sys_names.size()),
420 123308 : _linear_systems(_num_linear_sys, nullptr),
421 61654 : _current_linear_sys(nullptr),
422 123308 : _using_default_nl(!isParamSetByUser("nl_sys_names")),
423 183002 : _nl_sys_names(!_using_default_nl || (_using_default_nl && !_linear_sys_names.size())
424 61654 : ? getParam<std::vector<NonlinearSystemName>>("nl_sys_names")
425 : : std::vector<NonlinearSystemName>()),
426 61654 : _num_nl_sys(_nl_sys_names.size()),
427 123308 : _nl(_num_nl_sys, nullptr),
428 61654 : _current_nl_sys(nullptr),
429 123308 : _solver_systems(_num_nl_sys + _num_linear_sys, nullptr),
430 61654 : _aux(nullptr),
431 61654 : _coupling(Moose::COUPLING_DIAG),
432 : #ifdef MOOSE_KOKKOS_ENABLED
433 46604 : _kokkos_assembly(*this),
434 : #endif
435 61654 : _mesh_divisions(/*threaded=*/true),
436 61654 : _material_props(declareRestartableDataWithContext<MaterialPropertyStorage>(
437 61654 : "material_props", &_mesh, _material_prop_registry, *this)),
438 61654 : _bnd_material_props(declareRestartableDataWithContext<MaterialPropertyStorage>(
439 61654 : "bnd_material_props", &_mesh, _material_prop_registry, *this)),
440 61654 : _neighbor_material_props(declareRestartableDataWithContext<MaterialPropertyStorage>(
441 61654 : "neighbor_material_props", &_mesh, _material_prop_registry, *this)),
442 : #ifdef MOOSE_KOKKOS_ENABLED
443 46604 : _kokkos_material_props(
444 46604 : declareRestartableDataWithContext<Moose::Kokkos::MaterialPropertyStorage>(
445 46604 : "kokkos_material_props", &_mesh, _material_prop_registry, *this)),
446 46604 : _kokkos_bnd_material_props(
447 46604 : declareRestartableDataWithContext<Moose::Kokkos::MaterialPropertyStorage>(
448 46604 : "kokkos_bnd_material_props", &_mesh, _material_prop_registry, *this)),
449 46604 : _kokkos_neighbor_material_props(
450 46604 : declareRestartableDataWithContext<Moose::Kokkos::MaterialPropertyStorage>(
451 46604 : "kokkos_neighbor_material_props", &_mesh, _material_prop_registry, *this)),
452 : #endif
453 61654 : _reporter_data(_app),
454 61654 : _multi_apps(_app.getExecuteOnEnum()),
455 61654 : _transient_multi_apps(_app.getExecuteOnEnum()),
456 61654 : _transfers(_app.getExecuteOnEnum(), /*threaded=*/false),
457 61654 : _to_multi_app_transfers(_app.getExecuteOnEnum(), /*threaded=*/false),
458 61654 : _from_multi_app_transfers(_app.getExecuteOnEnum(), /*threaded=*/false),
459 61654 : _between_multi_app_transfers(_app.getExecuteOnEnum(), /*threaded=*/false),
460 : #ifdef LIBMESH_ENABLE_AMR
461 61654 : _adaptivity(*this),
462 61654 : _cycles_completed(0),
463 : #endif
464 61654 : _displaced_mesh(nullptr),
465 61654 : _geometric_search_data(*this, _mesh),
466 61654 : _mortar_data(std::make_unique<MortarInterfaceWarehouse>(*this)),
467 61654 : _reinit_displaced_elem(false),
468 61654 : _reinit_displaced_face(false),
469 61654 : _reinit_displaced_neighbor(false),
470 61654 : _input_file_saved(false),
471 61654 : _has_dampers(false),
472 61654 : _has_constraints(false),
473 61654 : _snesmf_reuse_base(true),
474 61654 : _skip_exception_check(false),
475 61654 : _snesmf_reuse_base_set_by_user(false),
476 61654 : _has_initialized_stateful(false),
477 61654 : _const_jacobian(false),
478 61654 : _has_jacobian(false),
479 61654 : _needs_old_newton_iter(false),
480 123308 : _previous_nl_solution_required(getParam<bool>("previous_nl_solution_required")),
481 123308 : _previous_multiapp_fp_nl_solution_required(_num_nl_sys + _num_linear_sys, false),
482 61654 : _previous_multiapp_fp_aux_solution_required(false),
483 61654 : _has_nonlocal_coupling(false),
484 61654 : _calculate_jacobian_in_uo(false),
485 61654 : _kernel_coverage_check(
486 123308 : getParam<MooseEnum>("kernel_coverage_check").getEnum<CoverageCheckMode>()),
487 123308 : _kernel_coverage_blocks(getParam<std::vector<SubdomainName>>("kernel_coverage_block_list")),
488 61654 : _boundary_restricted_node_integrity_check(
489 123308 : getParam<bool>("boundary_restricted_node_integrity_check")),
490 61654 : _boundary_restricted_elem_integrity_check(
491 123308 : getParam<bool>("boundary_restricted_elem_integrity_check")),
492 61654 : _material_coverage_check(
493 123308 : getParam<MooseEnum>("material_coverage_check").getEnum<CoverageCheckMode>()),
494 123308 : _material_coverage_blocks(getParam<std::vector<SubdomainName>>("material_coverage_block_list")),
495 123308 : _fv_bcs_integrity_check(getParam<bool>("fv_bcs_integrity_check")),
496 123308 : _material_dependency_check(getParam<bool>("material_dependency_check")),
497 123308 : _uo_aux_state_check(getParam<bool>("check_uo_aux_state")),
498 : #ifndef NDEBUG
499 : _check_residual_for_nans(false),
500 : #endif
501 61654 : _max_qps(std::numeric_limits<unsigned int>::max()),
502 61654 : _max_scalar_order(INVALID_ORDER),
503 61654 : _has_time_integrator(false),
504 61654 : _has_exception(false),
505 123308 : _parallel_barrier_messaging(getParam<bool>("parallel_barrier_messaging")),
506 123308 : _verbose_setup(getParam<MooseEnum>("verbose_setup")),
507 123308 : _verbose_multiapps(getParam<bool>("verbose_multiapps")),
508 123308 : _verbose_restore(getParam<bool>("verbose_restore")),
509 61654 : _current_execute_on_flag(EXEC_NONE),
510 61654 : _control_warehouse(_app.getExecuteOnEnum(), /*threaded=*/false),
511 61654 : _is_petsc_options_inserted(false),
512 61654 : _line_search(nullptr),
513 61654 : _using_ad_mat_props(false),
514 61654 : _current_ic_state(0),
515 123308 : _use_hash_table_matrix_assembly(getParam<bool>("use_hash_table_matrix_assembly")),
516 61654 : _error_on_jacobian_nonzero_reallocation(
517 123308 : isParamValid("error_on_jacobian_nonzero_reallocation")
518 123835 : ? getParam<bool>("error_on_jacobian_nonzero_reallocation")
519 61127 : : _app.errorOnJacobianNonzeroReallocation()),
520 123308 : _restore_original_nonzero_pattern(isParamValid("restore_original_nonzero_pattern")
521 123308 : ? getParam<bool>("restore_original_nonzero_pattern")
522 61654 : : _use_hash_table_matrix_assembly),
523 123308 : _ignore_zeros_in_jacobian(getParam<bool>("ignore_zeros_in_jacobian")),
524 61654 : _preserve_matrix_sparsity_pattern(true),
525 123308 : _force_restart(getParam<bool>("force_restart")),
526 123308 : _allow_ics_during_restart(getParam<bool>("allow_initial_conditions_with_restart")),
527 123308 : _skip_nl_system_check(getParam<bool>("skip_nl_system_check")),
528 61654 : _fail_next_system_convergence_check(false),
529 123308 : _allow_invalid_solution(getParam<bool>("allow_invalid_solution")),
530 123308 : _show_invalid_solution_console(getParam<bool>("show_invalid_solution_console")),
531 123308 : _immediately_print_invalid_solution(getParam<bool>("immediately_print_invalid_solution")),
532 61654 : _started_initial_setup(false),
533 61654 : _has_internal_edge_residual_objects(false),
534 61654 : _u_dot_requested(false),
535 61654 : _u_dotdot_requested(false),
536 61654 : _u_dot_old_requested(false),
537 61654 : _u_dotdot_old_requested(false),
538 61654 : _has_mortar(false),
539 61654 : _num_grid_steps(0),
540 61654 : _print_execution_on(),
541 123308 : _identify_variable_groups_in_nl(getParam<bool>("identify_variable_groups_in_nl")),
542 61654 : _regard_general_exceptions_as_errors(getParam<bool>("regard_general_exceptions_as_errors")),
543 1171426 : _requires_nonlocal_coupling(false)
544 : {
545 : auto checkCoverageCheckConflict =
546 123308 : [this](const std::string & coverage_check,
547 : const CoverageCheckMode & coverage_check_mode,
548 : const std::vector<SubdomainName> & coverage_blocks) -> void
549 : {
550 123308 : if (coverage_check_mode != CoverageCheckMode::FALSE &&
551 118905 : coverage_check_mode != CoverageCheckMode::OFF)
552 118887 : 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 123308 : };
560 :
561 61654 : checkCoverageCheckConflict(
562 61654 : "kernel_coverage_check", _kernel_coverage_check, _kernel_coverage_blocks);
563 61654 : checkCoverageCheckConflict(
564 61654 : "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 61654 : ADReal::do_derivatives = true;
570 :
571 : // Disable refinement/coarsening in EquationSystems::reinit because we already do this ourselves
572 61654 : es().disable_refine_in_reinit();
573 :
574 61654 : _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 61654 : _solver_params.resize(_num_nl_sys);
578 122547 : for (const auto i : index_range(_nl_sys_names))
579 : {
580 60893 : const auto & name = _nl_sys_names[i];
581 60893 : _nl_sys_name_to_num[name] = i;
582 60893 : _solver_sys_name_to_num[name] = i;
583 60893 : _solver_sys_names.push_back(name);
584 : }
585 :
586 62686 : 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 61654 : _nonlocal_cm.resize(numSolverSystems());
597 61654 : _cm.resize(numSolverSystems());
598 :
599 61654 : _time = 0.0;
600 61654 : _time_old = 0.0;
601 61654 : _t_step = 0;
602 61654 : _dt = 0;
603 61654 : _dt_old = _dt;
604 :
605 61654 : unsigned int n_threads = libMesh::n_threads();
606 :
607 61654 : _real_zero.resize(n_threads, 0.);
608 61654 : _scalar_zero.resize(n_threads);
609 61654 : _zero.resize(n_threads);
610 61654 : _phi_zero.resize(n_threads);
611 61654 : _ad_zero.resize(n_threads);
612 61654 : _grad_zero.resize(n_threads);
613 61654 : _ad_grad_zero.resize(n_threads);
614 61654 : _grad_phi_zero.resize(n_threads);
615 61654 : _second_zero.resize(n_threads);
616 61654 : _ad_second_zero.resize(n_threads);
617 61654 : _second_phi_zero.resize(n_threads);
618 61654 : _point_zero.resize(n_threads);
619 61654 : _vector_zero.resize(n_threads);
620 61654 : _vector_curl_zero.resize(n_threads);
621 61654 : _uo_jacobian_moose_vars.resize(n_threads);
622 :
623 61654 : _has_active_material_properties.resize(n_threads, 0);
624 :
625 61654 : _block_mat_side_cache.resize(n_threads);
626 61654 : _bnd_mat_side_cache.resize(n_threads);
627 61654 : _interface_mat_side_cache.resize(n_threads);
628 :
629 123308 : es().parameters.set<FEProblemBase *>("_fe_problem_base") = this;
630 :
631 184962 : 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 61654 : if (!_app.isUltimateMaster())
661 12088 : LibmeshPetscCall(PetscOptionsCreate(&_petsc_option_data_base));
662 : #endif
663 :
664 61654 : if (!_solve)
665 : {
666 : // If we are not solving, we do not care about seeing unused petsc options
667 49098 : 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 16366 : _is_petsc_options_inserted = true;
670 : }
671 61654 : }
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 61654 : FEProblemBase::createTagVectors()
693 : {
694 : // add vectors and their tags to system
695 123308 : auto & vectors = getParam<std::vector<std::vector<TagName>>>("extra_tag_vectors");
696 62370 : 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 123308 : auto & not_zeroed_vectors = getParam<std::vector<std::vector<TagName>>>("not_zeroed_tag_vectors");
704 61665 : 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 61654 : }
712 :
713 : void
714 60771 : FEProblemBase::createTagMatrices(CreateTaggedMatrixKey)
715 : {
716 121542 : auto & matrices = getParam<std::vector<std::vector<TagName>>>("extra_tag_matrices");
717 61017 : 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 121789 : for (auto & sys : _solver_systems)
725 61018 : sys->sizeVariableMatrixData();
726 60771 : _aux->sizeVariableMatrixData();
727 60771 : }
728 :
729 : void
730 61654 : FEProblemBase::createTagSolutions()
731 : {
732 184987 : 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 61654 : 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 61654 : auto tag = addVectorTag(Moose::SOLUTION_TAG, Moose::VECTOR_TAG_SOLUTION);
750 123579 : for (auto & sys : _solver_systems)
751 61925 : sys->associateVectorToTag(*sys->system().current_local_solution.get(), tag);
752 61654 : _aux->associateVectorToTag(*_aux->system().current_local_solution.get(), tag);
753 61654 : }
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 61654 : FEProblemBase::newAssemblyArray(std::vector<std::shared_ptr<SolverSystem>> & solver_systems)
776 : {
777 61654 : unsigned int n_threads = libMesh::n_threads();
778 :
779 61654 : _assembly.resize(n_threads);
780 130119 : for (const auto i : make_range(n_threads))
781 : {
782 68465 : _assembly[i].resize(solver_systems.size());
783 137226 : for (const auto j : index_range(solver_systems))
784 68761 : _assembly[i][j] = std::make_unique<Assembly>(*solver_systems[j], i);
785 : }
786 61654 : }
787 :
788 : void
789 58855 : FEProblemBase::initNullSpaceVectors(const InputParameters & parameters,
790 : std::vector<std::shared_ptr<NonlinearSystemBase>> & nls)
791 : {
792 294275 : TIME_SECTION("initNullSpaceVectors", 5, "Initializing Null Space Vectors");
793 :
794 58855 : unsigned int dimNullSpace = parameters.get<unsigned int>("null_space_dimension");
795 : unsigned int dimTransposeNullSpace =
796 58855 : parameters.get<unsigned int>("transpose_null_space_dimension");
797 58855 : unsigned int dimNearNullSpace = parameters.get<unsigned int>("near_null_space_dimension");
798 58879 : 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 117710 : _subspace_dim["NullSpace"] = dimNullSpace;
808 58867 : 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 117710 : _subspace_dim["TransposeNullSpace"] = dimTransposeNullSpace;
818 58855 : 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 117710 : _subspace_dim["NearNullSpace"] = dimNearNullSpace;
828 58855 : }
829 :
830 175722 : 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 58574 : _console << std::flush;
837 :
838 58574 : unsigned int n_threads = libMesh::n_threads();
839 122683 : for (unsigned int i = 0; i < n_threads; i++)
840 : {
841 64109 : _zero[i].release();
842 64109 : _phi_zero[i].release();
843 64109 : _scalar_zero[i].release();
844 64109 : _grad_zero[i].release();
845 64109 : _grad_phi_zero[i].release();
846 64109 : _second_zero[i].release();
847 64109 : _second_phi_zero[i].release();
848 64109 : _vector_zero[i].release();
849 64109 : _vector_curl_zero[i].release();
850 64109 : _ad_zero[i].release();
851 64109 : _ad_grad_zero[i].release();
852 64109 : _ad_second_zero[i].release();
853 : }
854 :
855 : #if !PETSC_RELEASE_LESS_THAN(3, 12, 0)
856 58574 : if (!_app.isUltimateMaster())
857 : {
858 11324 : auto ierr = PetscOptionsDestroy(&_petsc_option_data_base);
859 : // Don't throw on destruction
860 11324 : CHKERRABORT(this->comm().get(), ierr);
861 : }
862 : #endif
863 58574 : }
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 59425 : FEProblemBase::initialSetup()
915 : {
916 297125 : TIME_SECTION("initialSetup", 2, "Performing Initial Setup");
917 :
918 59425 : SubProblem::initialSetup();
919 :
920 59425 : 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 59425 : 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 59425 : _started_initial_setup = true;
931 59425 : 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 119097 : for (const auto i : index_range(_solver_systems))
936 : {
937 59672 : _solver_systems[i]->initSolutionState();
938 59672 : if (getDisplacedProblem())
939 2013 : getDisplacedProblem()->solverSys(i).initSolutionState();
940 : }
941 59425 : _aux->initSolutionState();
942 59425 : 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 59425 : dof_id_type global_max_var_n_dofs_per_elem = 0;
948 119097 : for (const auto i : index_range(_solver_systems))
949 : {
950 59672 : 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 298360 : TIME_SECTION("computingMaxDofs", 3, "Computing Max Dofs Per Element");
955 :
956 59672 : MaxVarNDofsPerElem mvndpe(*this, sys);
957 59672 : Threads::parallel_reduce(getCurrentAlgebraicElementRange(), mvndpe);
958 59672 : max_var_n_dofs_per_elem = mvndpe.max();
959 59672 : _communicator.max(max_var_n_dofs_per_elem);
960 :
961 59672 : MaxVarNDofsPerNode mvndpn(*this, sys);
962 59672 : Threads::parallel_reduce(getCurrentAlgebraicNodeRange(), mvndpn);
963 59672 : max_var_n_dofs_per_node = mvndpn.max();
964 59672 : _communicator.max(max_var_n_dofs_per_node);
965 59672 : global_max_var_n_dofs_per_elem =
966 59672 : std::max(global_max_var_n_dofs_per_elem, max_var_n_dofs_per_elem);
967 59672 : }
968 :
969 : {
970 298360 : TIME_SECTION("assignMaxDofs", 5, "Assigning Maximum Dofs Per Elem");
971 :
972 59672 : sys.assignMaxVarNDofsPerElem(max_var_n_dofs_per_elem);
973 59672 : auto displaced_problem = getDisplacedProblem();
974 59672 : if (displaced_problem)
975 2013 : displaced_problem->solverSys(i).assignMaxVarNDofsPerElem(max_var_n_dofs_per_elem);
976 :
977 59672 : sys.assignMaxVarNDofsPerNode(max_var_n_dofs_per_node);
978 59672 : if (displaced_problem)
979 2013 : displaced_problem->solverSys(i).assignMaxVarNDofsPerNode(max_var_n_dofs_per_node);
980 59672 : }
981 : }
982 :
983 : {
984 297125 : TIME_SECTION("resizingVarValues", 5, "Resizing Variable Values");
985 :
986 124821 : for (unsigned int tid = 0; tid < libMesh::n_threads(); ++tid)
987 : {
988 130792 : _phi_zero[tid].resize(global_max_var_n_dofs_per_elem, std::vector<Real>(getMaxQps(), 0.));
989 130792 : _grad_phi_zero[tid].resize(global_max_var_n_dofs_per_elem,
990 130792 : std::vector<RealGradient>(getMaxQps(), RealGradient(0.)));
991 130792 : _second_phi_zero[tid].resize(global_max_var_n_dofs_per_elem,
992 130792 : std::vector<RealTensor>(getMaxQps(), RealTensor(0.)));
993 : }
994 59425 : }
995 :
996 : // Set up stateful material property redistribution, if we suspect
997 : // it may be necessary later.
998 59425 : addAnyRedistributers();
999 :
1000 59425 : if (_app.isRestarting() || _app.isRecovering() || _force_restart)
1001 : {
1002 : // Only load all of the vectors if we're recovering
1003 4781 : _req.set().setLoadAllVectors(_app.isRecovering());
1004 :
1005 : // This forces stateful material property loading to be an exact one-to-one match
1006 4781 : if (_app.isRecovering())
1007 : {
1008 17012 : for (auto props : {&_material_props, &_bnd_material_props, &_neighbor_material_props})
1009 12759 : props->setRecovering();
1010 :
1011 : #ifdef MOOSE_KOKKOS_ENABLED
1012 16872 : for (auto props :
1013 21090 : {&_kokkos_material_props, &_kokkos_bnd_material_props, &_kokkos_neighbor_material_props})
1014 12654 : props->setRecovering();
1015 : #endif
1016 : }
1017 :
1018 23905 : 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 4781 : if (!_app.hasInitialBackup())
1022 3735 : _app.restore(_app.restartFolderBase(_app.getRestartRecoverFileBase()), _app.isRestarting());
1023 : else
1024 1046 : _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 4748 : 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 4748 : }
1039 : else
1040 : {
1041 54644 : libMesh::ExodusII_IO * reader = _app.getExReaderForRestart();
1042 :
1043 54644 : 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 54266 : 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 59389 : _app.getOutputWarehouse().initialSetup();
1062 :
1063 : // Flush all output to _console that occur during construction and initialization of objects
1064 59343 : _app.getOutputWarehouse().mooseConsole();
1065 :
1066 : // Build Refinement and Coarsening maps for stateful material projections if necessary
1067 61596 : 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 59337 : 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 55084 : 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 59337 : unsigned int n_threads = libMesh::n_threads();
1095 :
1096 : // Convergence initial setup
1097 : {
1098 296685 : TIME_SECTION("convergenceInitialSetup", 5, "Initializing Convergence objects");
1099 :
1100 124594 : for (THREAD_ID tid = 0; tid < n_threads; tid++)
1101 65272 : _convergences.initialSetup(tid);
1102 59322 : }
1103 :
1104 : // UserObject initialSetup
1105 59322 : std::set<std::string> depend_objects_ic = _ics.getDependObjects();
1106 59322 : std::set<std::string> depend_objects_aux = _aux->getDependObjects();
1107 :
1108 59322 : std::map<int, std::vector<UserObjectBase *>> group_userobjs;
1109 :
1110 : // This replaces all prior updateDependObjects calls on the old user object warehouses.
1111 59322 : TheWarehouse::Query uo_query = theWarehouse().query().condition<AttribSystem>("UserObject");
1112 59322 : std::vector<UserObjectBase *> userobjs;
1113 59322 : uo_query.queryInto(userobjs);
1114 59322 : groupUserObjects(
1115 59322 : theWarehouse(), getAuxiliarySystem(), _app.getExecuteOnEnum(), userobjs, depend_objects_ic);
1116 :
1117 130193 : for (auto obj : userobjs)
1118 212613 : group_userobjs[obj->getParam<int>("execution_order_group")].push_back(obj);
1119 :
1120 : #ifdef MOOSE_KOKKOS_ENABLED
1121 : {
1122 : TheWarehouse::Query uo_query =
1123 44888 : theWarehouse().query().condition<AttribSystem>("KokkosUserObject");
1124 44888 : std::vector<UserObjectBase *> userobjs;
1125 44888 : uo_query.queryInto(userobjs);
1126 44888 : groupUserObjects(
1127 44888 : theWarehouse(), getAuxiliarySystem(), _app.getExecuteOnEnum(), userobjs, depend_objects_ic);
1128 :
1129 46113 : for (auto obj : userobjs)
1130 3675 : group_userobjs[obj->getParam<int>("execution_order_group")].push_back(obj);
1131 44888 : }
1132 : #endif
1133 :
1134 89198 : for (auto & [group, objs] : group_userobjs)
1135 101919 : for (auto obj : objs)
1136 72043 : obj->initialSetup();
1137 :
1138 : // check if jacobian calculation is done in userobject
1139 124393 : for (THREAD_ID tid = 0; tid < n_threads; ++tid)
1140 65151 : checkUserObjectJacobianRequirement(tid);
1141 :
1142 : // Check whether nonlocal coupling is required or not
1143 59242 : checkNonlocalCoupling();
1144 59242 : if (_requires_nonlocal_coupling)
1145 63 : setVariableAllDoFMap(_uo_jacobian_moose_vars[0]);
1146 :
1147 : {
1148 296210 : TIME_SECTION("initializingFunctions", 5, "Initializing Functions");
1149 :
1150 : // Call the initialSetup methods for functions
1151 124361 : for (THREAD_ID tid = 0; tid < n_threads; tid++)
1152 : {
1153 65143 : reinitScalars(tid); // initialize scalars so they are properly sized for use as input into
1154 : // ParsedFunctions
1155 65143 : _functions.initialSetup(tid);
1156 : }
1157 :
1158 : #ifdef MOOSE_KOKKOS_ENABLED
1159 44819 : _kokkos_functions.initialSetup();
1160 : #endif
1161 59218 : }
1162 :
1163 : {
1164 296090 : TIME_SECTION("initializingRandomObjects", 5, "Initializing Random Objects");
1165 :
1166 : // Random interface objects
1167 59542 : for (const auto & it : _random_data_objects)
1168 324 : it.second->updateSeeds(EXEC_INITIAL);
1169 59218 : }
1170 :
1171 59218 : if (!_app.isRecovering())
1172 : {
1173 54965 : computeUserObjects(EXEC_INITIAL, Moose::PRE_IC);
1174 :
1175 : {
1176 274825 : TIME_SECTION("ICinitialSetup", 5, "Setting Up Initial Conditions");
1177 :
1178 115778 : for (THREAD_ID tid = 0; tid < n_threads; tid++)
1179 60819 : _ics.initialSetup(tid);
1180 :
1181 54959 : _scalar_ics.initialSetup();
1182 54959 : }
1183 :
1184 54959 : projectSolution();
1185 : }
1186 :
1187 : // Materials
1188 59206 : if (_all_materials.hasActiveObjects(0))
1189 : {
1190 41845 : TIME_SECTION("materialInitialSetup", 3, "Setting Up Materials");
1191 :
1192 17465 : 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 9114 : _materials.sort(tid);
1196 9111 : _interface_materials.sort(tid);
1197 :
1198 : // Call initialSetup on all material objects
1199 9111 : _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 9096 : 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 41745 : TIME_SECTION("computingInitialStatefulProps", 3, "Computing Initial Material Values");
1217 :
1218 8349 : initElementStatefulProps(getCurrentAlgebraicElementRange(), true);
1219 :
1220 16023 : if (_material_props.hasStatefulProperties() || _bnd_material_props.hasStatefulProperties() ||
1221 7674 : _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 8349 : }
1230 8349 : }
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 236744 : for (auto props : {&_material_props, &_bnd_material_props, &_neighbor_material_props})
1237 : {
1238 177558 : props->setRestartInPlace();
1239 177558 : props->setRecovering();
1240 : }
1241 :
1242 124262 : for (THREAD_ID tid = 0; tid < n_threads; tid++)
1243 : {
1244 65076 : _internal_side_indicators.initialSetup(tid);
1245 65076 : _indicators.initialSetup(tid);
1246 65076 : _markers.sort(tid);
1247 65076 : _markers.initialSetup(tid);
1248 : }
1249 :
1250 : #ifdef LIBMESH_ENABLE_AMR
1251 :
1252 59186 : if (!_app.isRecovering())
1253 : {
1254 54933 : unsigned int n = adaptivity().getInitialSteps();
1255 54933 : if (n && !_app.isUltimateMaster() && _app.isRestarting())
1256 0 : mooseError("Cannot perform initial adaptivity during restart on sub-apps of a MultiApp!");
1257 :
1258 54933 : initialAdaptMesh();
1259 : }
1260 :
1261 : #endif // LIBMESH_ENABLE_AMR
1262 :
1263 59183 : if (!_app.isRecovering() && !_app.isRestarting())
1264 : {
1265 : // During initial setup the solution is copied to the older solution states (old, older, etc)
1266 54435 : copySolutionsBackwards();
1267 :
1268 : // Check if there are old state initial conditions
1269 54435 : auto ics = _ics.getActiveObjects();
1270 54435 : auto fv_ics = _fv_ics.getActiveObjects();
1271 54435 : auto scalar_ics = _scalar_ics.getActiveObjects();
1272 54435 : unsigned short ic_state_max = 0;
1273 :
1274 163305 : auto findMax = [&ic_state_max](const auto & obj_list)
1275 : {
1276 193537 : for (auto ic : obj_list.getActiveObjects())
1277 30232 : ic_state_max = std::max(ic_state_max, ic->getState());
1278 217740 : };
1279 54435 : findMax(_ics);
1280 54435 : findMax(_fv_ics);
1281 54435 : findMax(_scalar_ics);
1282 :
1283 : // if there are old state ICs, compute them and write to old states accordingly
1284 54435 : 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 54435 : }
1321 :
1322 59183 : if (!_app.isRecovering())
1323 : {
1324 54930 : if (haveXFEM())
1325 0 : updateMeshXFEM();
1326 : }
1327 :
1328 : // Call initialSetup on the solver systems
1329 118613 : for (auto & sys : _solver_systems)
1330 59430 : sys->initialSetup();
1331 :
1332 : // Auxilary variable initialSetup calls
1333 59183 : _aux->initialSetup();
1334 :
1335 59177 : if (_displaced_problem)
1336 : // initialSetup for displaced systems
1337 2013 : _displaced_problem->initialSetup();
1338 :
1339 118601 : for (auto & sys : _solver_systems)
1340 59424 : 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 59177 : updateGeomSearch(GeometricSearchData::NEAREST_NODE);
1345 :
1346 59177 : _mesh.updateActiveSemiLocalNodeRange(_ghosted_elems);
1347 59177 : 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 59177 : 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 59177 : reinitBecauseOfGhostingOrNewGeomObjects();
1362 :
1363 59177 : if (_displaced_mesh)
1364 2013 : _displaced_problem->updateMesh();
1365 :
1366 59177 : updateGeomSearch(); // Call all of the rest of the geometric searches
1367 :
1368 118598 : for (auto & sys : _solver_systems)
1369 : {
1370 59424 : const auto & tis = sys->getTimeIntegrators();
1371 :
1372 : {
1373 297120 : TIME_SECTION("timeIntegratorInitialSetup", 5, "Initializing Time Integrator");
1374 88787 : for (auto & ti : tis)
1375 29366 : ti->initialSetup();
1376 59421 : }
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 59174 : if (_multi_apps.hasObjects())
1384 : {
1385 34540 : TIME_SECTION("initialSetupMultiApps", 2, "Initializing MultiApps", false);
1386 6908 : _multi_apps.initialSetup();
1387 6902 : }
1388 :
1389 : // Call initialSetup on the transfers
1390 : {
1391 295840 : TIME_SECTION("initialSetupTransfers", 2, "Initializing Transfers");
1392 :
1393 59168 : _transfers.initialSetup();
1394 :
1395 : // Call initialSetup on the MultiAppTransfers to be executed on TO_MULTIAPP
1396 59168 : const auto & to_multi_app_objects = _to_multi_app_transfers.getActiveObjects();
1397 64196 : for (const auto & transfer : to_multi_app_objects)
1398 : {
1399 5076 : transfer->setCurrentDirection(Transfer::DIRECTION::TO_MULTIAPP);
1400 5076 : transfer->initialSetup();
1401 : }
1402 :
1403 : // Call initialSetup on the MultiAppTransfers to be executed on FROM_MULTIAPP
1404 59120 : const auto & from_multi_app_objects = _from_multi_app_transfers.getActiveObjects();
1405 65253 : for (const auto & transfer : from_multi_app_objects)
1406 : {
1407 6175 : transfer->setCurrentDirection(Transfer::DIRECTION::FROM_MULTIAPP);
1408 6175 : transfer->initialSetup();
1409 : }
1410 :
1411 : // Call initialSetup on the MultiAppTransfers to be executed on BETWEEN_MULTIAPP
1412 59078 : const auto & between_multi_app_objects = _between_multi_app_transfers.getActiveObjects();
1413 60547 : for (const auto & transfer : between_multi_app_objects)
1414 : {
1415 1469 : transfer->setCurrentDirection(Transfer::DIRECTION::BETWEEN_MULTIAPP);
1416 1469 : transfer->initialSetup();
1417 : }
1418 59078 : }
1419 :
1420 59078 : if (_boundary_restricted_node_integrity_check)
1421 : {
1422 177198 : TIME_SECTION("BoundaryRestrictedNodeIntegrityCheck", 5);
1423 :
1424 : // check that variables are defined along boundaries of boundary restricted nodal objects
1425 59066 : const auto & bnd_nodes = getCurrentAlgebraicBndNodeRange();
1426 59066 : BoundaryNodeIntegrityCheckThread bnict(*this, uo_query);
1427 59066 : Threads::parallel_reduce(bnd_nodes, bnict);
1428 :
1429 : // Nodal bcs aren't threaded
1430 59057 : const auto & node_to_elem_map = _mesh.nodeToActiveSemilocalElemMap();
1431 4603985 : for (const auto & bnode : bnd_nodes)
1432 : {
1433 4544937 : const auto boundary_id = bnode->_bnd_id;
1434 4544937 : const Node * const node = bnode->_node;
1435 :
1436 4544937 : if (node->processor_id() != this->processor_id())
1437 931821 : 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 3613116 : _mesh.getMesh().elem_ptr(libmesh_map_find(node_to_elem_map, node->id()).front());
1443 3613116 : if (!an_elem->is_vertex(an_elem->get_node_index(node)))
1444 519526 : continue;
1445 :
1446 3093590 : const auto & bnd_name = _mesh.getBoundaryName(boundary_id);
1447 :
1448 6146672 : for (auto & nl : _nl)
1449 : {
1450 3053091 : const auto & nodal_bcs = nl->getNodalBCWarehouse();
1451 3053091 : if (!nodal_bcs.hasBoundaryObjects(boundary_id, 0))
1452 2234543 : continue;
1453 :
1454 818548 : const auto & bnd_objects = nodal_bcs.getBoundaryObjects(boundary_id, 0);
1455 1717580 : 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 1798082 : if (!bnd_object->requiresGeometricSearch() &&
1459 899041 : bnd_object->checkVariableBoundaryIntegrity())
1460 : {
1461 : std::set<MooseVariableFieldBase *> vars_to_omit = {
1462 : &static_cast<MooseVariableFieldBase &>(
1463 1798082 : const_cast<MooseVariableBase &>(bnd_object->variable()))};
1464 :
1465 1798082 : boundaryIntegrityCheckError(
1466 1798073 : *bnd_object, bnd_object->checkAllVariables(*node, vars_to_omit), bnd_name);
1467 899032 : }
1468 : }
1469 : }
1470 59048 : }
1471 :
1472 59060 : if (_boundary_restricted_elem_integrity_check)
1473 : {
1474 177090 : TIME_SECTION("BoundaryRestrictedElemIntegrityCheck", 5);
1475 :
1476 : // check that variables are defined along boundaries of boundary restricted elemental objects
1477 59030 : ConstBndElemRange & bnd_elems = *mesh().getBoundaryElementRange();
1478 59030 : BoundaryElemIntegrityCheckThread beict(*this, uo_query);
1479 59030 : Threads::parallel_reduce(bnd_elems, beict);
1480 59018 : }
1481 :
1482 59048 : if (!_app.isRecovering())
1483 : {
1484 54795 : execTransfers(EXEC_INITIAL);
1485 :
1486 54795 : bool converged = execMultiApps(EXEC_INITIAL);
1487 54789 : if (!converged)
1488 3 : mooseError("failed to converge initial MultiApp");
1489 :
1490 : // We'll backup the Multiapp here
1491 54786 : backupMultiApps(EXEC_INITIAL);
1492 :
1493 115368 : for (THREAD_ID tid = 0; tid < n_threads; tid++)
1494 60582 : reinitScalars(tid);
1495 :
1496 54786 : 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 54711 : 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 58964 : if (!_app.isRecovering() && !_app.isRestarting())
1517 : {
1518 107860 : if (_material_props.hasStatefulProperties() || _bnd_material_props.hasStatefulProperties() ||
1519 53644 : _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 40065 : if (_kokkos_material_props.hasStatefulProperties() ||
1527 79965 : _kokkos_bnd_material_props.hasStatefulProperties() ||
1528 39900 : _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 58964 : _control_warehouse.initialSetup();
1539 58964 : executeControls(EXEC_INITIAL);
1540 :
1541 : // Scalar variables need to reinited for the initial conditions to be available for output
1542 123682 : for (unsigned int tid = 0; tid < n_threads; tid++)
1543 64745 : reinitScalars(tid);
1544 :
1545 58937 : if (_displaced_mesh)
1546 2013 : _displaced_problem->syncSolutions();
1547 :
1548 : // Writes all calls to _console from initialSetup() methods
1549 58937 : _app.getOutputWarehouse().mooseConsole();
1550 :
1551 58937 : 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 294685 : TIME_SECTION("lineSearchInitialSetup", 5, "Initializing Line Search");
1561 :
1562 58937 : if (_line_search)
1563 0 : _line_search->initialSetup();
1564 58937 : }
1565 :
1566 : // Perform Reporter get/declare check
1567 58937 : _reporter_data.check();
1568 :
1569 : // We do this late to allow objects to get late restartable data
1570 58937 : if (_app.isRestarting() || _app.isRecovering() || _force_restart)
1571 4748 : _app.finalizeRestore();
1572 :
1573 58937 : setCurrentExecuteOnFlag(EXEC_NONE);
1574 58937 : }
1575 :
1576 : void
1577 59759 : FEProblemBase::checkDuplicatePostprocessorVariableNames()
1578 : {
1579 109605 : for (const auto & pp : _reporter_data.getPostprocessorNames())
1580 49846 : if (hasScalarVariable(pp))
1581 0 : mooseError("Postprocessor \"" + pp +
1582 59759 : "\" has the same name as a scalar variable in the system.");
1583 59759 : }
1584 :
1585 : void
1586 265172 : FEProblemBase::timestepSetup()
1587 : {
1588 265172 : SubProblem::timestepSetup();
1589 :
1590 265172 : 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 265172 : _control_warehouse.timestepSetup();
1646 265172 : if (_line_search)
1647 0 : _line_search->timestepSetup();
1648 :
1649 : // Random interface objects
1650 266552 : for (const auto & it : _random_data_objects)
1651 1380 : it.second->updateSeeds(EXEC_TIMESTEP_BEGIN);
1652 :
1653 265172 : unsigned int n_threads = libMesh::n_threads();
1654 556711 : for (THREAD_ID tid = 0; tid < n_threads; tid++)
1655 : {
1656 291539 : _all_materials.timestepSetup(tid);
1657 291539 : _functions.timestepSetup(tid);
1658 : }
1659 :
1660 : #ifdef MOOSE_KOKKOS_ENABLED
1661 194446 : _kokkos_functions.timestepSetup();
1662 : #endif
1663 :
1664 265172 : _aux->timestepSetup();
1665 533797 : for (auto & sys : _solver_systems)
1666 268625 : sys->timestepSetup();
1667 :
1668 265172 : if (_displaced_problem)
1669 : // timestepSetup for displaced systems
1670 30674 : _displaced_problem->timestepSetup();
1671 :
1672 556711 : for (THREAD_ID tid = 0; tid < n_threads; tid++)
1673 : {
1674 291539 : _internal_side_indicators.timestepSetup(tid);
1675 291539 : _indicators.timestepSetup(tid);
1676 291539 : _markers.timestepSetup(tid);
1677 : }
1678 :
1679 265172 : std::vector<UserObject *> userobjs;
1680 265172 : theWarehouse().query().condition<AttribSystem>("UserObject").queryIntoUnsorted(userobjs);
1681 588550 : for (auto obj : userobjs)
1682 323378 : obj->timestepSetup();
1683 :
1684 : #ifdef MOOSE_KOKKOS_ENABLED
1685 : {
1686 194446 : std::vector<UserObjectBase *> userobjs;
1687 194446 : theWarehouse().query().condition<AttribSystem>("KokkosUserObject").queryIntoUnsorted(userobjs);
1688 196625 : for (auto obj : userobjs)
1689 2179 : obj->timestepSetup();
1690 194446 : }
1691 : #endif
1692 :
1693 : // Timestep setup of output objects
1694 265172 : _app.getOutputWarehouse().timestepSetup();
1695 :
1696 265172 : if (_requires_nonlocal_coupling)
1697 97 : if (_nonlocal_kernels.hasActiveObjects() || _nonlocal_integrated_bcs.hasActiveObjects())
1698 97 : _has_nonlocal_coupling = true;
1699 265172 : }
1700 :
1701 : unsigned int
1702 767219 : FEProblemBase::getMaxQps() const
1703 : {
1704 767219 : if (_max_qps == std::numeric_limits<unsigned int>::max())
1705 0 : mooseError("Max QPS uninitialized");
1706 767219 : return _max_qps;
1707 : }
1708 :
1709 : Order
1710 52 : FEProblemBase::getMaxScalarOrder() const
1711 : {
1712 52 : return _max_scalar_order;
1713 : }
1714 :
1715 : void
1716 59242 : FEProblemBase::checkNonlocalCoupling()
1717 : {
1718 296210 : TIME_SECTION("checkNonlocalCoupling", 5, "Checking Nonlocal Coupling");
1719 :
1720 124393 : for (THREAD_ID tid = 0; tid < libMesh::n_threads(); tid++)
1721 129536 : for (auto & nl : _nl)
1722 : {
1723 64385 : const auto & all_kernels = nl->getKernelWarehouse();
1724 64385 : const auto & kernels = all_kernels.getObjects(tid);
1725 147750 : for (const auto & kernel : kernels)
1726 : {
1727 : std::shared_ptr<NonlocalKernel> nonlocal_kernel =
1728 83365 : std::dynamic_pointer_cast<NonlocalKernel>(kernel);
1729 83365 : 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 83365 : }
1736 : const MooseObjectWarehouse<IntegratedBCBase> & all_integrated_bcs =
1737 64385 : nl->getIntegratedBCWarehouse();
1738 64385 : const auto & integrated_bcs = all_integrated_bcs.getObjects(tid);
1739 73085 : for (const auto & integrated_bc : integrated_bcs)
1740 : {
1741 : std::shared_ptr<NonlocalIntegratedBC> nonlocal_integrated_bc =
1742 8700 : std::dynamic_pointer_cast<NonlocalIntegratedBC>(integrated_bc);
1743 8700 : 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 8700 : }
1750 : }
1751 59242 : }
1752 :
1753 : void
1754 65151 : FEProblemBase::checkUserObjectJacobianRequirement(THREAD_ID tid)
1755 : {
1756 65151 : std::set<const MooseVariableFEBase *> uo_jacobian_moose_vars;
1757 : {
1758 65151 : std::vector<ShapeElementUserObject *> objs;
1759 65151 : theWarehouse()
1760 65151 : .query()
1761 130302 : .condition<AttribInterfaces>(Interfaces::ShapeElementUserObject)
1762 65151 : .condition<AttribThread>(tid)
1763 65151 : .queryInto(objs);
1764 :
1765 65195 : 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 65151 : }
1772 : {
1773 65151 : std::vector<ShapeSideUserObject *> objs;
1774 65151 : theWarehouse()
1775 65151 : .query()
1776 130302 : .condition<AttribInterfaces>(Interfaces::ShapeSideUserObject)
1777 65151 : .condition<AttribThread>(tid)
1778 65151 : .queryInto(objs);
1779 65207 : 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 65151 : }
1786 :
1787 65151 : _uo_jacobian_moose_vars[tid].assign(uo_jacobian_moose_vars.begin(), uo_jacobian_moose_vars.end());
1788 130302 : std::sort(
1789 130302 : _uo_jacobian_moose_vars[tid].begin(), _uo_jacobian_moose_vars[tid].end(), sortMooseVariables);
1790 65151 : }
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 374135403 : FEProblemBase::prepare(const Elem * elem, const THREAD_ID tid)
1806 : {
1807 750775223 : for (const auto i : index_range(_solver_systems))
1808 : {
1809 376639820 : _assembly[tid][i]->reinit(elem);
1810 376639820 : _solver_systems[i]->prepare(tid);
1811 :
1812 376639820 : if (i < _num_nl_sys)
1813 : {
1814 : // This method is called outside of residual/Jacobian callbacks during initial condition
1815 : // evaluation
1816 376071788 : if ((!_has_jacobian || !_const_jacobian) && currentlyComputingJacobian())
1817 47238573 : _assembly[tid][i]->prepareJacobianBlock();
1818 376071788 : _assembly[tid][i]->prepareResidual();
1819 376071788 : if (_has_nonlocal_coupling && currentlyComputingJacobian())
1820 8824 : _assembly[tid][i]->prepareNonlocal();
1821 : }
1822 : }
1823 374135403 : _aux->prepare(tid);
1824 :
1825 385779898 : 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 385779898 : (_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 374135379 : }
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 405401125 : FEProblemBase::setCurrentSubdomainID(const Elem * elem, const THREAD_ID tid)
1886 : {
1887 405401125 : SubdomainID did = elem->subdomain_id();
1888 814314417 : for (const auto i : index_range(_solver_systems))
1889 : {
1890 408913292 : _assembly[tid][i]->setCurrentSubdomainID(did);
1891 421374828 : if (_displaced_problem &&
1892 421374828 : (_reinit_displaced_elem || _reinit_displaced_face || _reinit_displaced_neighbor))
1893 7814055 : _displaced_problem->assembly(tid, i).setCurrentSubdomainID(did);
1894 : }
1895 405401125 : }
1896 :
1897 : void
1898 1454730241 : FEProblemBase::setNeighborSubdomainID(const Elem * elem, unsigned int side, const THREAD_ID tid)
1899 : {
1900 1454730241 : SubdomainID did = elem->neighbor_ptr(side)->subdomain_id();
1901 2914150485 : for (const auto i : index_range(_nl))
1902 : {
1903 1459420244 : _assembly[tid][i]->setCurrentNeighborSubdomainID(did);
1904 1502996702 : if (_displaced_problem &&
1905 1502996702 : (_reinit_displaced_elem || _reinit_displaced_face || _reinit_displaced_neighbor))
1906 25839139 : _displaced_problem->assembly(tid, i).setCurrentNeighborSubdomainID(did);
1907 : }
1908 1454730241 : }
1909 :
1910 : void
1911 15256677 : FEProblemBase::setNeighborSubdomainID(const Elem * elem, const THREAD_ID tid)
1912 : {
1913 15256677 : SubdomainID did = elem->subdomain_id();
1914 31464666 : for (const auto i : index_range(_nl))
1915 : {
1916 16207989 : _assembly[tid][i]->setCurrentNeighborSubdomainID(did);
1917 16259285 : if (_displaced_problem &&
1918 16259285 : (_reinit_displaced_elem || _reinit_displaced_face || _reinit_displaced_neighbor))
1919 51296 : _displaced_problem->assembly(tid, i).setCurrentNeighborSubdomainID(did);
1920 : }
1921 15256677 : }
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 48428 : FEProblemBase::addResidualScalar(const THREAD_ID tid /* = 0*/)
1970 : {
1971 96856 : _assembly[tid][_current_nl_sys->number()]->addResidualScalar(Assembly::GlobalDataKey{},
1972 48428 : currentResidualVectorTags());
1973 48428 : }
1974 :
1975 : void
1976 287945249 : FEProblemBase::cacheResidual(const THREAD_ID tid)
1977 : {
1978 287945249 : SubProblem::cacheResidual(tid);
1979 287945249 : if (_displaced_problem)
1980 7590898 : _displaced_problem->cacheResidual(tid);
1981 287945249 : }
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 16769689 : FEProblemBase::addCachedResidual(const THREAD_ID tid)
1993 : {
1994 16769689 : SubProblem::addCachedResidual(tid);
1995 16769689 : if (_displaced_problem)
1996 492377 : _displaced_problem->addCachedResidual(tid);
1997 16769689 : }
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 46672974 : FEProblemBase::cacheJacobian(const THREAD_ID tid)
2106 : {
2107 46672974 : SubProblem::cacheJacobian(tid);
2108 46672974 : if (_displaced_problem)
2109 1544138 : _displaced_problem->cacheJacobian(tid);
2110 46672974 : }
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 2854607 : FEProblemBase::addCachedJacobian(const THREAD_ID tid)
2122 : {
2123 2854607 : SubProblem::addCachedJacobian(tid);
2124 2854604 : if (_displaced_problem)
2125 95805 : _displaced_problem->addCachedJacobian(tid);
2126 2854604 : }
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 125665255 : FEProblemBase::prepareShapes(unsigned int var, const THREAD_ID tid)
2193 : {
2194 125665255 : _assembly[tid][_current_nl_sys->number()]->copyShapes(var);
2195 125665255 : }
2196 :
2197 : void
2198 572679 : FEProblemBase::prepareFaceShapes(unsigned int var, const THREAD_ID tid)
2199 : {
2200 572679 : _assembly[tid][_current_nl_sys->number()]->copyFaceShapes(var);
2201 572679 : }
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 66890 : FEProblemBase::ghostGhostedBoundaries()
2226 : {
2227 334450 : TIME_SECTION("ghostGhostedBoundaries", 3, "Ghosting Ghosted Boundaries");
2228 :
2229 66890 : _mesh.ghostGhostedBoundaries();
2230 :
2231 66890 : if (_displaced_problem)
2232 2591 : _displaced_mesh->ghostGhostedBoundaries();
2233 66890 : }
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 374381537 : FEProblemBase::reinitElem(const Elem * elem, const THREAD_ID tid)
2299 : {
2300 751267491 : for (auto & sys : _solver_systems)
2301 376885954 : sys->reinitElem(elem, tid);
2302 374381537 : _aux->reinitElem(elem, tid);
2303 :
2304 374381537 : if (_displaced_problem && _reinit_displaced_elem)
2305 4423675 : _displaced_problem->reinitElem(_displaced_mesh->elemPtr(elem->id()), tid);
2306 374381537 : }
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 5119957 : FEProblemBase::reinitElemFace(const Elem * const elem, const unsigned int side, const THREAD_ID tid)
2344 : {
2345 10240262 : for (const auto i : index_range(_solver_systems))
2346 : {
2347 5120305 : _assembly[tid][i]->reinit(elem, side);
2348 5120305 : _solver_systems[i]->reinitElemFace(elem, side, tid);
2349 : }
2350 5119957 : _aux->reinitElemFace(elem, side, tid);
2351 :
2352 5119957 : if (_displaced_problem && _reinit_displaced_face)
2353 82248 : _displaced_problem->reinitElemFace(_displaced_mesh->elemPtr(elem->id()), side, tid);
2354 5119957 : }
2355 :
2356 : void
2357 268556 : 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 268556 : SubProblem::reinitLowerDElem(lower_d_elem, tid, pts, weights);
2363 :
2364 268556 : if (_displaced_problem && _displaced_mesh)
2365 960 : _displaced_problem->reinitLowerDElem(
2366 960 : _displaced_mesh->elemPtr(lower_d_elem->id()), tid, pts, weights);
2367 268556 : }
2368 :
2369 : void
2370 25954576 : FEProblemBase::reinitNode(const Node * node, const THREAD_ID tid)
2371 : {
2372 25954576 : if (_displaced_problem && _reinit_displaced_elem)
2373 1001711 : _displaced_problem->reinitNode(&_displaced_mesh->nodeRef(node->id()), tid);
2374 :
2375 51912068 : for (const auto i : index_range(_nl))
2376 : {
2377 25957492 : _assembly[tid][i]->reinit(node);
2378 25957492 : _nl[i]->reinitNode(node, tid);
2379 : }
2380 25954576 : _aux->reinitNode(node, tid);
2381 25954576 : }
2382 :
2383 : void
2384 65103419 : FEProblemBase::reinitNodeFace(const Node * node, BoundaryID bnd_id, const THREAD_ID tid)
2385 : {
2386 65103419 : if (_displaced_problem && _reinit_displaced_face)
2387 3388880 : _displaced_problem->reinitNodeFace(&_displaced_mesh->nodeRef(node->id()), bnd_id, tid);
2388 :
2389 130996074 : for (const auto i : index_range(_nl))
2390 : {
2391 65892655 : _assembly[tid][i]->reinit(node);
2392 65892655 : _nl[i]->reinitNodeFace(node, bnd_id, tid);
2393 : }
2394 65103419 : _aux->reinitNodeFace(node, bnd_id, tid);
2395 65103419 : }
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 8413721 : FEProblemBase::reinitScalars(const THREAD_ID tid, bool reinit_for_derivative_reordering /*=false*/)
2421 : {
2422 42068605 : TIME_SECTION("reinitScalars", 3, "Reinitializing Scalar Variables");
2423 :
2424 8413721 : if (_displaced_problem && _reinit_displaced_elem)
2425 113549 : _displaced_problem->reinitScalars(tid, reinit_for_derivative_reordering);
2426 :
2427 17056131 : for (auto & nl : _nl)
2428 8642410 : nl->reinitScalars(tid, reinit_for_derivative_reordering);
2429 8413721 : _aux->reinitScalars(tid, reinit_for_derivative_reordering);
2430 :
2431 : // This is called outside of residual/Jacobian call-backs
2432 17061453 : for (auto & assembly : _assembly[tid])
2433 8647732 : assembly->prepareScalar();
2434 8413721 : }
2435 :
2436 : void
2437 185218 : FEProblemBase::reinitOffDiagScalars(const THREAD_ID tid)
2438 : {
2439 185218 : _assembly[tid][_current_nl_sys->number()]->prepareOffDiagScalar();
2440 185218 : if (_displaced_problem)
2441 60 : _displaced_problem->reinitOffDiagScalars(tid);
2442 185218 : }
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 3511248 : FEProblemBase::clearDiracInfo()
2591 : {
2592 3511248 : _dirac_kernel_info.clearPoints();
2593 :
2594 3511248 : if (_displaced_problem)
2595 144138 : _displaced_problem->clearDiracInfo();
2596 3511248 : }
2597 :
2598 : void
2599 5449040 : FEProblemBase::subdomainSetup(SubdomainID subdomain, const THREAD_ID tid)
2600 : {
2601 5449040 : _all_materials.subdomainSetup(subdomain, tid);
2602 : // Call the subdomain methods of the output system, these are not threaded so only call it once
2603 5449040 : if (tid == 0)
2604 4990157 : _app.getOutputWarehouse().subdomainSetup();
2605 :
2606 11037765 : for (auto & nl : _nl)
2607 5588725 : nl->subdomainSetup(subdomain, tid);
2608 :
2609 : // FIXME: call displaced_problem->subdomainSetup() ?
2610 : // When adding possibility with materials being evaluated on displaced mesh
2611 5449040 : }
2612 :
2613 : void
2614 16900714 : FEProblemBase::neighborSubdomainSetup(SubdomainID subdomain, const THREAD_ID tid)
2615 : {
2616 16900714 : _all_materials.neighborSubdomainSetup(subdomain, tid);
2617 16900714 : }
2618 :
2619 : void
2620 48919 : FEProblemBase::addFunction(const std::string & type,
2621 : const std::string & name,
2622 : InputParameters & parameters)
2623 : {
2624 : parallel_object_only();
2625 :
2626 97838 : parameters.set<SubProblem *>("_subproblem") = this;
2627 :
2628 102132 : for (THREAD_ID tid = 0; tid < libMesh::n_threads(); tid++)
2629 : {
2630 53319 : std::shared_ptr<Function> func = _factory.create<Function>(type, name, parameters, tid);
2631 53213 : logAdd("Function", name, type, parameters);
2632 53213 : _functions.addObject(func, tid);
2633 :
2634 53213 : if (auto * const functor = dynamic_cast<Moose::FunctorBase<Real> *>(func.get()))
2635 : {
2636 53213 : this->addFunctor(name, *functor, tid);
2637 53213 : if (_displaced_problem)
2638 1780 : _displaced_problem->addFunctor(name, *functor, tid);
2639 : }
2640 : else
2641 0 : mooseError("Unrecognized function functor type");
2642 53213 : }
2643 48813 : }
2644 :
2645 : void
2646 150816 : FEProblemBase::addConvergence(const std::string & type,
2647 : const std::string & name,
2648 : InputParameters & parameters)
2649 : {
2650 : parallel_object_only();
2651 :
2652 317887 : for (THREAD_ID tid = 0; tid < libMesh::n_threads(); tid++)
2653 : {
2654 167098 : std::shared_ptr<Convergence> conv = _factory.create<Convergence>(type, name, parameters, tid);
2655 167071 : _convergences.addObject(conv, tid);
2656 167071 : }
2657 150789 : }
2658 :
2659 : void
2660 59133 : FEProblemBase::addDefaultNonlinearConvergence(const InputParameters & params_to_apply)
2661 : {
2662 59133 : const std::string class_name = "DefaultNonlinearConvergence";
2663 59133 : InputParameters params = _factory.getValidParams(class_name);
2664 59133 : params.applyParameters(params_to_apply);
2665 59133 : params.applyParameters(parameters());
2666 59133 : params.set<bool>("added_as_default") = true;
2667 117487 : for (const auto & conv_name : getNonlinearConvergenceNames())
2668 58354 : addConvergence(class_name, conv_name, params);
2669 59133 : }
2670 :
2671 : void
2672 60919 : FEProblemBase::addDefaultMultiAppFixedPointConvergence(const InputParameters & params_to_apply)
2673 : {
2674 60919 : const std::string class_name = "DefaultMultiAppFixedPointConvergence";
2675 60919 : InputParameters params = _factory.getValidParams(class_name);
2676 60919 : params.applyParameters(params_to_apply);
2677 60919 : params.applyParameters(parameters());
2678 60919 : params.set<bool>("added_as_default") = true;
2679 60919 : addConvergence(class_name, getMultiAppFixedPointConvergenceName(), params);
2680 60910 : }
2681 :
2682 : void
2683 29915 : FEProblemBase::addDefaultSteadyStateConvergence(const InputParameters & params_to_apply)
2684 : {
2685 29915 : const std::string class_name = "DefaultSteadyStateConvergence";
2686 29915 : InputParameters params = _factory.getValidParams(class_name);
2687 29915 : params.applyParameters(params_to_apply);
2688 29915 : params.applyParameters(parameters());
2689 29915 : params.set<bool>("added_as_default") = true;
2690 29915 : addConvergence(class_name, getSteadyStateConvergenceName(), params);
2691 29915 : }
2692 :
2693 : bool
2694 85690 : FEProblemBase::hasFunction(const std::string & name, const THREAD_ID tid)
2695 : {
2696 85690 : return _functions.hasActiveObject(name, tid);
2697 : }
2698 :
2699 : Function &
2700 62254 : 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 62254 : Threads::spin_mutex::scoped_lock lock(get_function_mutex);
2705 :
2706 62254 : 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 20330 : 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 20330 : if (ss >> real_value && ss.eof())
2714 : {
2715 12592 : InputParameters params = _factory.getValidParams("ConstantFunction");
2716 12592 : params.set<Real>("value") = real_value;
2717 18888 : addFunction("ConstantFunction", ss.str(), params);
2718 6296 : }
2719 : else
2720 : {
2721 14034 : FunctionParserBase<Real> fp;
2722 14034 : std::string vars = "x,y,z,t,NaN,pi,e";
2723 14034 : if (fp.Parse(name, vars) == -1) // -1 for success
2724 : {
2725 : // It parsed ok, so build a MooseParsedFunction
2726 42087 : InputParameters params = _factory.getValidParams("ParsedFunction");
2727 14029 : params.set<std::string>("expression") = name;
2728 28058 : addFunction("ParsedFunction", name, params);
2729 14029 : }
2730 14034 : }
2731 :
2732 : // Try once more
2733 20330 : 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 20327 : }
2743 :
2744 62249 : auto * const ret = dynamic_cast<Function *>(_functions.getActiveObject(name, tid).get());
2745 62249 : if (!ret)
2746 0 : mooseError("No function named ", name, " of appropriate type");
2747 :
2748 62249 : return *ret;
2749 62251 : }
2750 :
2751 : bool
2752 208938 : FEProblemBase::hasConvergence(const std::string & name, const THREAD_ID tid) const
2753 : {
2754 208938 : return _convergences.hasActiveObject(name, tid);
2755 : }
2756 :
2757 : Convergence &
2758 1128329 : FEProblemBase::getConvergence(const std::string & name, const THREAD_ID tid) const
2759 : {
2760 1128329 : auto * const ret = dynamic_cast<Convergence *>(_convergences.getActiveObject(name, tid).get());
2761 1128329 : if (!ret)
2762 0 : mooseError("The Convergence object '", name, "' does not exist.");
2763 :
2764 1128329 : return *ret;
2765 : }
2766 :
2767 : const std::vector<std::shared_ptr<Convergence>> &
2768 191827 : FEProblemBase::getConvergenceObjects(const THREAD_ID tid) const
2769 : {
2770 191827 : 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 0 : FEProblemBase::addDistribution(const std::string & type,
2820 : const std::string & name,
2821 : InputParameters & parameters)
2822 : {
2823 0 : parameters.set<std::string>("type") = type;
2824 0 : addObject<Distribution>(type, name, parameters, /* threaded = */ false);
2825 0 : }
2826 :
2827 : Distribution &
2828 0 : FEProblemBase::getDistribution(const std::string & name)
2829 : {
2830 0 : std::vector<Distribution *> objs;
2831 0 : theWarehouse()
2832 0 : .query()
2833 0 : .condition<AttribSystem>("Distribution")
2834 0 : .condition<AttribName>(name)
2835 0 : .queryInto(objs);
2836 0 : if (objs.empty())
2837 0 : mooseError("Unable to find Distribution with name '" + name + "'");
2838 0 : return *(objs[0]);
2839 0 : }
2840 :
2841 : void
2842 275 : FEProblemBase::addSampler(const std::string & type,
2843 : const std::string & name,
2844 : InputParameters & parameters)
2845 : {
2846 275 : const auto samplers = addObject<Sampler>(type, name, parameters);
2847 569 : for (auto & sampler : samplers)
2848 303 : sampler->init();
2849 266 : }
2850 :
2851 : Sampler &
2852 266 : FEProblemBase::getSampler(const std::string & name, const THREAD_ID tid)
2853 : {
2854 266 : std::vector<Sampler *> objs;
2855 266 : theWarehouse()
2856 532 : .query()
2857 266 : .condition<AttribSystem>("Sampler")
2858 266 : .condition<AttribThread>(tid)
2859 266 : .condition<AttribName>(name)
2860 266 : .queryInto(objs);
2861 266 : if (objs.empty())
2862 0 : mooseError(
2863 0 : "Unable to find Sampler with name '" + name +
2864 : "', if you are attempting to access this object in the constructor of another object then "
2865 : "the object being retrieved must occur prior to the caller within the input file.");
2866 532 : return *(objs[0]);
2867 266 : }
2868 :
2869 : bool
2870 152996 : FEProblemBase::duplicateVariableCheck(const std::string & var_name,
2871 : const FEType & type,
2872 : bool is_aux,
2873 : const std::set<SubdomainID> * const active_subdomains)
2874 : {
2875 152996 : std::set<SubdomainID> subdomainIDs;
2876 152996 : if (active_subdomains->size() == 0)
2877 : {
2878 144896 : const auto subdomains = _mesh.meshSubdomains();
2879 144896 : subdomainIDs.insert(subdomains.begin(), subdomains.end());
2880 144896 : }
2881 : else
2882 8100 : subdomainIDs.insert(active_subdomains->begin(), active_subdomains->end());
2883 :
2884 306660 : for (auto & sys : _solver_systems)
2885 : {
2886 153676 : SystemBase * curr_sys_ptr = sys.get();
2887 153676 : SystemBase * other_sys_ptr = _aux.get();
2888 153676 : std::string error_prefix = "";
2889 153676 : if (is_aux)
2890 : {
2891 93957 : curr_sys_ptr = _aux.get();
2892 93957 : other_sys_ptr = sys.get();
2893 93957 : error_prefix = "aux";
2894 : }
2895 :
2896 153676 : if (other_sys_ptr->hasVariable(var_name))
2897 3 : mooseError("Cannot have an auxiliary variable and a solver variable with the same name: ",
2898 : var_name);
2899 :
2900 153673 : if (curr_sys_ptr->hasVariable(var_name))
2901 : {
2902 : const Variable & var =
2903 9 : curr_sys_ptr->system().variable(curr_sys_ptr->system().variable_number(var_name));
2904 :
2905 : // variable type
2906 9 : if (var.type() != type)
2907 : {
2908 12 : const auto stringifyType = [](FEType t)
2909 12 : { return Moose::stringify(t.family) + " of order " + Moose::stringify(t.order); };
2910 :
2911 6 : mooseError("Mismatching types are specified for ",
2912 : error_prefix,
2913 : "variable with name '",
2914 : var_name,
2915 : "': '",
2916 6 : stringifyType(var.type()),
2917 : "' and '",
2918 6 : stringifyType(type),
2919 : "'");
2920 : }
2921 :
2922 : // block-restriction
2923 3 : if (!(active_subdomains->size() == 0 && var.active_subdomains().size() == 0))
2924 : {
2925 3 : const auto varActiveSubdomains = var.active_subdomains();
2926 3 : std::set<SubdomainID> varSubdomainIDs;
2927 3 : if (varActiveSubdomains.size() == 0)
2928 : {
2929 0 : const auto subdomains = _mesh.meshSubdomains();
2930 0 : varSubdomainIDs.insert(subdomains.begin(), subdomains.end());
2931 0 : }
2932 : else
2933 3 : varSubdomainIDs.insert(varActiveSubdomains.begin(), varActiveSubdomains.end());
2934 :
2935 : // Is subdomainIDs a subset of varSubdomainIDs? With this we allow the case that the newly
2936 : // requested block restriction is only a subset of the existing one.
2937 3 : const auto isSubset = std::includes(varSubdomainIDs.begin(),
2938 : varSubdomainIDs.end(),
2939 : subdomainIDs.begin(),
2940 : subdomainIDs.end());
2941 :
2942 3 : if (!isSubset)
2943 : {
2944 : // helper function: make a string from a set of subdomain ids
2945 6 : const auto stringifySubdomains = [this](std::set<SubdomainID> subdomainIDs)
2946 : {
2947 6 : std::stringstream s;
2948 15 : for (auto const i : subdomainIDs)
2949 : {
2950 : // do we need to insert a comma?
2951 9 : if (s.tellp() != 0)
2952 3 : s << ", ";
2953 :
2954 : // insert subdomain name and id -or- only the id (if no name is given)
2955 9 : const auto subdomainName = _mesh.getSubdomainName(i);
2956 9 : if (subdomainName.empty())
2957 9 : s << i;
2958 : else
2959 0 : s << subdomainName << " (" << i << ")";
2960 9 : }
2961 12 : return s.str();
2962 6 : };
2963 :
2964 6 : const std::string msg = "Mismatching block-restrictions are specified for " +
2965 6 : error_prefix + "variable with name '" + var_name + "': {" +
2966 12 : stringifySubdomains(varSubdomainIDs) + "} and {" +
2967 9 : stringifySubdomains(subdomainIDs) + "}";
2968 :
2969 3 : mooseError(msg);
2970 0 : }
2971 0 : }
2972 :
2973 0 : return true;
2974 : }
2975 153664 : }
2976 :
2977 152984 : return false;
2978 152984 : }
2979 :
2980 : void
2981 59171 : FEProblemBase::addVariable(const std::string & var_type,
2982 : const std::string & var_name,
2983 : InputParameters & params)
2984 : {
2985 : parallel_object_only();
2986 :
2987 59171 : const auto order = Utility::string_to_enum<Order>(params.get<MooseEnum>("order"));
2988 59171 : const auto family = Utility::string_to_enum<FEFamily>(params.get<MooseEnum>("family"));
2989 59171 : const auto fe_type = FEType(order, family);
2990 :
2991 : const auto active_subdomains_vector =
2992 59171 : _mesh.getSubdomainIDs(params.get<std::vector<SubdomainName>>("block"));
2993 : const std::set<SubdomainID> active_subdomains(active_subdomains_vector.begin(),
2994 59171 : active_subdomains_vector.end());
2995 :
2996 59171 : if (duplicateVariableCheck(var_name, fe_type, /* is_aux = */ false, &active_subdomains))
2997 0 : return;
2998 :
2999 177504 : params.set<FEProblemBase *>("_fe_problem_base") = this;
3000 59168 : params.set<Moose::VarKindType>("_var_kind") = Moose::VarKindType::VAR_SOLVER;
3001 59168 : SolverSystemName sys_name = params.get<SolverSystemName>("solver_sys");
3002 :
3003 59168 : const auto solver_system_number = solverSysNum(sys_name);
3004 59168 : logAdd("Variable", var_name, var_type, params);
3005 59168 : _solver_systems[solver_system_number]->addVariable(var_type, var_name, params);
3006 59156 : if (_displaced_problem)
3007 : // MooseObjects need to be unique so change the name here
3008 3453 : _displaced_problem->addVariable(var_type, var_name, params, solver_system_number);
3009 :
3010 59156 : _solver_var_to_sys_num[var_name] = solver_system_number;
3011 :
3012 59156 : markFamilyPRefinement(params);
3013 59156 : }
3014 :
3015 : std::pair<bool, unsigned int>
3016 4544195 : FEProblemBase::determineSolverSystem(const std::string & var_name,
3017 : const bool error_if_not_found) const
3018 : {
3019 4544195 : auto map_it = _solver_var_to_sys_num.find(var_name);
3020 4544195 : const bool var_in_sys = map_it != _solver_var_to_sys_num.end();
3021 4544195 : if (var_in_sys)
3022 : mooseAssert(_solver_systems[map_it->second]->hasVariable(var_name) ||
3023 : _solver_systems[map_it->second]->hasScalarVariable(var_name),
3024 : "If the variable is in our FEProblem solver system map, then it must be in the "
3025 : "solver system we expect");
3026 3100353 : else if (error_if_not_found)
3027 : {
3028 32 : if (_aux->hasVariable(var_name) || _aux->hasScalarVariable(var_name))
3029 21 : mooseError("No solver variable named ",
3030 : var_name,
3031 : " found. Did you specify an auxiliary variable when you meant to specify a "
3032 : "solver variable?");
3033 : else
3034 11 : mooseError("Unknown variable '",
3035 : var_name,
3036 : "'. It does not exist in the solver system(s) or auxiliary system");
3037 : }
3038 :
3039 9088326 : return std::make_pair(var_in_sys, var_in_sys ? map_it->second : libMesh::invalid_uint);
3040 : }
3041 :
3042 : void
3043 158576 : FEProblemBase::setResidualObjectParamsAndLog(const std::string & ro_name,
3044 : const std::string & name,
3045 : InputParameters & parameters,
3046 : const unsigned int nl_sys_num,
3047 : const std::string & base_name,
3048 : bool & reinit_displaced)
3049 : {
3050 158576 : if (_displaced_problem && parameters.get<bool>("use_displaced_mesh"))
3051 : {
3052 1920 : parameters.set<SubProblem *>("_subproblem") = _displaced_problem.get();
3053 1920 : parameters.set<SystemBase *>("_sys") = &_displaced_problem->solverSys(nl_sys_num);
3054 960 : reinit_displaced = true;
3055 : }
3056 : else
3057 : {
3058 157616 : if (_displaced_problem == nullptr && parameters.get<bool>("use_displaced_mesh"))
3059 : {
3060 : // We allow Kernels to request that they use_displaced_mesh,
3061 : // but then be overridden when no displacements variables are
3062 : // provided in the Mesh block. If that happened, update the value
3063 : // of use_displaced_mesh appropriately for this Kernel.
3064 105 : if (parameters.have_parameter<bool>("use_displaced_mesh"))
3065 210 : parameters.set<bool>("use_displaced_mesh") = false;
3066 : }
3067 :
3068 315232 : parameters.set<SubProblem *>("_subproblem") = this;
3069 472848 : parameters.set<SystemBase *>("_sys") = _nl[nl_sys_num].get();
3070 : }
3071 :
3072 158576 : logAdd(base_name, name, ro_name, parameters);
3073 158576 : }
3074 :
3075 : void
3076 65048 : FEProblemBase::setAuxKernelParamsAndLog(const std::string & ak_name,
3077 : const std::string & name,
3078 : InputParameters & parameters,
3079 : const std::string & base_name)
3080 : {
3081 65048 : if (_displaced_problem && parameters.get<bool>("use_displaced_mesh"))
3082 : {
3083 22872 : parameters.set<SubProblem *>("_subproblem") = _displaced_problem.get();
3084 22872 : parameters.set<SystemBase *>("_sys") = &_displaced_problem->auxSys();
3085 22872 : parameters.set<SystemBase *>("_nl_sys") = &_displaced_problem->solverSys(0);
3086 11436 : if (!parameters.get<std::vector<BoundaryName>>("boundary").empty())
3087 10990 : _reinit_displaced_face = true;
3088 : else
3089 446 : _reinit_displaced_elem = true;
3090 : }
3091 : else
3092 : {
3093 53612 : if (_displaced_problem == nullptr && parameters.get<bool>("use_displaced_mesh"))
3094 : {
3095 : // We allow AuxKernels to request that they use_displaced_mesh,
3096 : // but then be overridden when no displacements variables are
3097 : // provided in the Mesh block. If that happened, update the value
3098 : // of use_displaced_mesh appropriately for this AuxKernel.
3099 795 : if (parameters.have_parameter<bool>("use_displaced_mesh"))
3100 1590 : parameters.set<bool>("use_displaced_mesh") = false;
3101 : }
3102 :
3103 107224 : parameters.set<SubProblem *>("_subproblem") = this;
3104 107224 : parameters.set<SystemBase *>("_sys") = _aux.get();
3105 160836 : parameters.set<SystemBase *>("_nl_sys") = _solver_systems[0].get();
3106 : }
3107 :
3108 65048 : logAdd(base_name, name, ak_name, parameters);
3109 65048 : }
3110 :
3111 : void
3112 76102 : FEProblemBase::addKernel(const std::string & kernel_name,
3113 : const std::string & name,
3114 : InputParameters & parameters)
3115 : {
3116 : parallel_object_only();
3117 152204 : const auto nl_sys_num = determineSolverSystem(parameters.varName("variable", name), true).second;
3118 76090 : if (!isSolverSystemNonlinear(nl_sys_num))
3119 0 : mooseError("You are trying to add a Kernel to a linear variable/system, which is not "
3120 : "supported at the moment!");
3121 76090 : setResidualObjectParamsAndLog(
3122 76090 : kernel_name, name, parameters, nl_sys_num, "Kernel", _reinit_displaced_elem);
3123 :
3124 76090 : _nl[nl_sys_num]->addKernel(kernel_name, name, parameters);
3125 75937 : }
3126 :
3127 : void
3128 431 : FEProblemBase::addHDGKernel(const std::string & kernel_name,
3129 : const std::string & name,
3130 : InputParameters & parameters)
3131 : {
3132 : parallel_object_only();
3133 862 : const auto nl_sys_num = determineSolverSystem(parameters.varName("variable", name), true).second;
3134 431 : if (!isSolverSystemNonlinear(nl_sys_num))
3135 0 : mooseError("You are trying to add a HDGKernel to a linear variable/system, which is not "
3136 : "supported at the moment!");
3137 431 : setResidualObjectParamsAndLog(
3138 431 : kernel_name, name, parameters, nl_sys_num, "HDGKernel", _reinit_displaced_elem);
3139 :
3140 431 : _nl[nl_sys_num]->addHDGKernel(kernel_name, name, parameters);
3141 431 : }
3142 :
3143 : void
3144 602 : FEProblemBase::addNodalKernel(const std::string & kernel_name,
3145 : const std::string & name,
3146 : InputParameters & parameters)
3147 : {
3148 : parallel_object_only();
3149 :
3150 1204 : const auto nl_sys_num = determineSolverSystem(parameters.varName("variable", name), true).second;
3151 599 : if (_displaced_problem && parameters.get<bool>("use_displaced_mesh"))
3152 : {
3153 0 : parameters.set<SubProblem *>("_subproblem") = _displaced_problem.get();
3154 0 : parameters.set<SystemBase *>("_sys") = &_displaced_problem->solverSys(nl_sys_num);
3155 0 : _reinit_displaced_elem = true;
3156 : }
3157 : else
3158 : {
3159 599 : if (_displaced_problem == nullptr && parameters.get<bool>("use_displaced_mesh"))
3160 : {
3161 : // We allow NodalKernels to request that they use_displaced_mesh,
3162 : // but then be overridden when no displacements variables are
3163 : // provided in the Mesh block. If that happened, update the value
3164 : // of use_displaced_mesh appropriately for this NodalKernel.
3165 0 : if (parameters.have_parameter<bool>("use_displaced_mesh"))
3166 0 : parameters.set<bool>("use_displaced_mesh") = false;
3167 : }
3168 :
3169 1198 : parameters.set<SubProblem *>("_subproblem") = this;
3170 1797 : parameters.set<SystemBase *>("_sys") = _nl[nl_sys_num].get();
3171 : }
3172 599 : logAdd("NodalKernel", name, kernel_name, parameters);
3173 599 : _nl[nl_sys_num]->addNodalKernel(kernel_name, name, parameters);
3174 599 : }
3175 :
3176 : void
3177 1319 : FEProblemBase::addScalarKernel(const std::string & kernel_name,
3178 : const std::string & name,
3179 : InputParameters & parameters)
3180 : {
3181 : parallel_object_only();
3182 :
3183 2638 : const auto nl_sys_num = determineSolverSystem(parameters.varName("variable", name), true).second;
3184 1319 : if (!isSolverSystemNonlinear(nl_sys_num))
3185 0 : mooseError("You are trying to add a ScalarKernel to a linear variable/system, which is not "
3186 : "supported at the moment!");
3187 :
3188 1319 : if (_displaced_problem && parameters.get<bool>("use_displaced_mesh"))
3189 : {
3190 0 : parameters.set<SubProblem *>("_subproblem") = _displaced_problem.get();
3191 0 : parameters.set<SystemBase *>("_sys") = &_displaced_problem->solverSys(nl_sys_num);
3192 : }
3193 : else
3194 : {
3195 1319 : if (_displaced_problem == nullptr && parameters.get<bool>("use_displaced_mesh"))
3196 : {
3197 : // We allow ScalarKernels to request that they use_displaced_mesh,
3198 : // but then be overridden when no displacements variables are
3199 : // provided in the Mesh block. If that happened, update the value
3200 : // of use_displaced_mesh appropriately for this ScalarKernel.
3201 0 : if (parameters.have_parameter<bool>("use_displaced_mesh"))
3202 0 : parameters.set<bool>("use_displaced_mesh") = false;
3203 : }
3204 :
3205 2638 : parameters.set<SubProblem *>("_subproblem") = this;
3206 3957 : parameters.set<SystemBase *>("_sys") = _nl[nl_sys_num].get();
3207 : }
3208 :
3209 1319 : logAdd("ScalarKernel", name, kernel_name, parameters);
3210 1319 : _nl[nl_sys_num]->addScalarKernel(kernel_name, name, parameters);
3211 1313 : }
3212 :
3213 : void
3214 74555 : FEProblemBase::addBoundaryCondition(const std::string & bc_name,
3215 : const std::string & name,
3216 : InputParameters & parameters)
3217 : {
3218 : parallel_object_only();
3219 :
3220 149114 : const auto nl_sys_num = determineSolverSystem(parameters.varName("variable", name), true).second;
3221 74547 : if (!isSolverSystemNonlinear(nl_sys_num))
3222 0 : mooseError(
3223 : "You are trying to add a BoundaryCondition to a linear variable/system, which is not "
3224 : "supported at the moment!");
3225 :
3226 74547 : setResidualObjectParamsAndLog(
3227 74547 : bc_name, name, parameters, nl_sys_num, "BoundaryCondition", _reinit_displaced_face);
3228 74547 : _nl[nl_sys_num]->addBoundaryCondition(bc_name, name, parameters);
3229 74503 : }
3230 :
3231 : void
3232 1609 : FEProblemBase::addConstraint(const std::string & c_name,
3233 : const std::string & name,
3234 : InputParameters & parameters)
3235 : {
3236 : parallel_object_only();
3237 :
3238 1609 : _has_constraints = true;
3239 :
3240 1609 : auto determine_var_param_name = [¶meters, this]()
3241 : {
3242 4827 : if (parameters.isParamValid("variable"))
3243 1048 : return "variable";
3244 : else
3245 : {
3246 : // must be a mortar constraint
3247 1122 : const bool has_secondary_var = parameters.isParamValid("secondary_variable");
3248 1122 : const bool has_primary_var = parameters.isParamValid("primary_variable");
3249 561 : if (!has_secondary_var && !has_primary_var)
3250 0 : mooseError(
3251 : "Either a 'secondary_variable' or 'primary_variable' parameter must be supplied for '",
3252 0 : parameters.getObjectName(),
3253 : "'");
3254 561 : return has_secondary_var ? "secondary_variable" : "primary_variable";
3255 : }
3256 1609 : };
3257 :
3258 : const auto nl_sys_num =
3259 3218 : determineSolverSystem(parameters.varName(determine_var_param_name(), name), true).second;
3260 1606 : if (!isSolverSystemNonlinear(nl_sys_num))
3261 0 : mooseError("You are trying to add a Constraint to a linear variable/system, which is not "
3262 : "supported at the moment!");
3263 :
3264 1606 : if (_displaced_problem && parameters.get<bool>("use_displaced_mesh"))
3265 : {
3266 266 : parameters.set<SubProblem *>("_subproblem") = _displaced_problem.get();
3267 266 : parameters.set<SystemBase *>("_sys") = &_displaced_problem->solverSys(nl_sys_num);
3268 133 : _reinit_displaced_face = true;
3269 : }
3270 : else
3271 : {
3272 : // It might _want_ to use a displaced mesh... but we're not so set it to false
3273 1473 : if (parameters.have_parameter<bool>("use_displaced_mesh"))
3274 2946 : parameters.set<bool>("use_displaced_mesh") = false;
3275 :
3276 2946 : parameters.set<SubProblem *>("_subproblem") = this;
3277 4419 : parameters.set<SystemBase *>("_sys") = _nl[nl_sys_num].get();
3278 : }
3279 :
3280 1606 : logAdd("Constraint", name, c_name, parameters);
3281 1606 : _nl[nl_sys_num]->addConstraint(c_name, name, parameters);
3282 1591 : }
3283 :
3284 : void
3285 93825 : FEProblemBase::addAuxVariable(const std::string & var_type,
3286 : const std::string & var_name,
3287 : InputParameters & params)
3288 : {
3289 : parallel_object_only();
3290 :
3291 93825 : const auto order = Utility::string_to_enum<Order>(params.get<MooseEnum>("order"));
3292 93825 : const auto family = Utility::string_to_enum<FEFamily>(params.get<MooseEnum>("family"));
3293 93825 : const auto fe_type = FEType(order, family);
3294 :
3295 : const auto active_subdomains_vector =
3296 93825 : _mesh.getSubdomainIDs(params.get<std::vector<SubdomainName>>("block"));
3297 : const std::set<SubdomainID> active_subdomains(active_subdomains_vector.begin(),
3298 93825 : active_subdomains_vector.end());
3299 :
3300 93825 : if (duplicateVariableCheck(var_name, fe_type, /* is_aux = */ true, &active_subdomains))
3301 0 : return;
3302 :
3303 281448 : params.set<FEProblemBase *>("_fe_problem_base") = this;
3304 187632 : params.set<Moose::VarKindType>("_var_kind") = Moose::VarKindType::VAR_AUXILIARY;
3305 :
3306 93816 : logAdd("AuxVariable", var_name, var_type, params);
3307 93816 : _aux->addVariable(var_type, var_name, params);
3308 93816 : if (_displaced_problem)
3309 : // MooseObjects need to be unique so change the name here
3310 10166 : _displaced_problem->addAuxVariable(var_type, var_name, params);
3311 :
3312 93816 : markFamilyPRefinement(params);
3313 93816 : }
3314 :
3315 : void
3316 2612 : FEProblemBase::addElementalFieldVariable(const std::string & var_type,
3317 : const std::string & var_name,
3318 : InputParameters & params)
3319 : {
3320 2612 : addAuxVariable(var_type, var_name, params);
3321 2612 : }
3322 :
3323 : void
3324 0 : FEProblemBase::addAuxVariable(const std::string & var_name,
3325 : const FEType & type,
3326 : const std::set<SubdomainID> * const active_subdomains)
3327 : {
3328 : parallel_object_only();
3329 :
3330 0 : mooseDeprecated("Please use the addAuxVariable(var_type, var_name, params) API instead");
3331 :
3332 0 : if (duplicateVariableCheck(var_name, type, /* is_aux = */ true, active_subdomains))
3333 0 : return;
3334 :
3335 0 : std::string var_type;
3336 0 : if (type == FEType(0, MONOMIAL))
3337 0 : var_type = "MooseVariableConstMonomial";
3338 0 : else if (type.family == SCALAR)
3339 0 : var_type = "MooseVariableScalar";
3340 0 : else if (FEInterface::field_type(type) == TYPE_VECTOR)
3341 0 : var_type = "VectorMooseVariable";
3342 : else
3343 0 : var_type = "MooseVariable";
3344 :
3345 0 : InputParameters params = _factory.getValidParams(var_type);
3346 0 : params.set<FEProblemBase *>("_fe_problem_base") = this;
3347 0 : params.set<Moose::VarKindType>("_var_kind") = Moose::VarKindType::VAR_AUXILIARY;
3348 0 : params.set<MooseEnum>("order") = type.order.get_order();
3349 0 : params.set<MooseEnum>("family") = Moose::stringify(type.family);
3350 :
3351 0 : if (active_subdomains)
3352 0 : for (const SubdomainID & id : *active_subdomains)
3353 0 : params.set<std::vector<SubdomainName>>("block").push_back(Moose::stringify(id));
3354 :
3355 0 : logAdd("AuxVariable", var_name, var_type, params);
3356 0 : _aux->addVariable(var_type, var_name, params);
3357 0 : if (_displaced_problem)
3358 0 : _displaced_problem->addAuxVariable("MooseVariable", var_name, params);
3359 :
3360 0 : markFamilyPRefinement(params);
3361 0 : }
3362 :
3363 : void
3364 0 : FEProblemBase::addAuxArrayVariable(const std::string & var_name,
3365 : const FEType & type,
3366 : unsigned int components,
3367 : const std::set<SubdomainID> * const active_subdomains)
3368 : {
3369 : parallel_object_only();
3370 :
3371 0 : mooseDeprecated("Please use the addAuxVariable(var_type, var_name, params) API instead");
3372 :
3373 0 : if (duplicateVariableCheck(var_name, type, /* is_aux = */ true, active_subdomains))
3374 0 : return;
3375 :
3376 0 : InputParameters params = _factory.getValidParams("ArrayMooseVariable");
3377 0 : params.set<FEProblemBase *>("_fe_problem_base") = this;
3378 0 : params.set<Moose::VarKindType>("_var_kind") = Moose::VarKindType::VAR_AUXILIARY;
3379 0 : params.set<MooseEnum>("order") = type.order.get_order();
3380 0 : params.set<MooseEnum>("family") = Moose::stringify(type.family);
3381 0 : params.set<unsigned int>("components") = components;
3382 :
3383 0 : if (active_subdomains)
3384 0 : for (const SubdomainID & id : *active_subdomains)
3385 0 : params.set<std::vector<SubdomainName>>("block").push_back(Moose::stringify(id));
3386 :
3387 0 : logAdd("Variable", var_name, "ArrayMooseVariable", params);
3388 0 : _aux->addVariable("ArrayMooseVariable", var_name, params);
3389 0 : if (_displaced_problem)
3390 0 : _displaced_problem->addAuxVariable("ArrayMooseVariable", var_name, params);
3391 :
3392 0 : markFamilyPRefinement(params);
3393 0 : }
3394 :
3395 : void
3396 0 : FEProblemBase::addAuxScalarVariable(const std::string & var_name,
3397 : Order order,
3398 : Real /*scale_factor*/,
3399 : const std::set<SubdomainID> * const active_subdomains)
3400 : {
3401 : parallel_object_only();
3402 :
3403 0 : mooseDeprecated("Please use the addAuxVariable(var_type, var_name, params) API instead");
3404 :
3405 0 : if (order > _max_scalar_order)
3406 0 : _max_scalar_order = order;
3407 :
3408 0 : FEType type(order, SCALAR);
3409 0 : if (duplicateVariableCheck(var_name, type, /* is_aux = */ true, active_subdomains))
3410 0 : return;
3411 :
3412 0 : InputParameters params = _factory.getValidParams("MooseVariableScalar");
3413 0 : params.set<FEProblemBase *>("_fe_problem_base") = this;
3414 0 : params.set<Moose::VarKindType>("_var_kind") = Moose::VarKindType::VAR_AUXILIARY;
3415 :
3416 0 : params.set<MooseEnum>("order") = type.order.get_order();
3417 0 : params.set<MooseEnum>("family") = "SCALAR";
3418 0 : params.set<std::vector<Real>>("scaling") = std::vector<Real>{1};
3419 0 : if (active_subdomains)
3420 0 : for (const SubdomainID & id : *active_subdomains)
3421 0 : params.set<std::vector<SubdomainName>>("block").push_back(Moose::stringify(id));
3422 :
3423 0 : logAdd("ScalarVariable", var_name, "MooseVariableScalar", params);
3424 0 : _aux->addVariable("MooseVariableScalar", var_name, params);
3425 0 : if (_displaced_problem)
3426 0 : _displaced_problem->addAuxVariable("MooseVariableScalar", var_name, params);
3427 0 : }
3428 :
3429 : void
3430 64427 : FEProblemBase::addAuxKernel(const std::string & kernel_name,
3431 : const std::string & name,
3432 : InputParameters & parameters)
3433 : {
3434 : parallel_object_only();
3435 :
3436 64427 : setAuxKernelParamsAndLog(kernel_name, name, parameters, "AuxKernel");
3437 :
3438 64427 : _aux->addKernel(kernel_name, name, parameters);
3439 64316 : }
3440 :
3441 : void
3442 475 : FEProblemBase::addAuxScalarKernel(const std::string & kernel_name,
3443 : const std::string & name,
3444 : InputParameters & parameters)
3445 : {
3446 : parallel_object_only();
3447 :
3448 475 : if (_displaced_problem && parameters.get<bool>("use_displaced_mesh"))
3449 : {
3450 0 : parameters.set<SubProblem *>("_subproblem") = _displaced_problem.get();
3451 0 : parameters.set<SystemBase *>("_sys") = &_displaced_problem->auxSys();
3452 : }
3453 : else
3454 : {
3455 475 : if (_displaced_problem == nullptr && parameters.get<bool>("use_displaced_mesh"))
3456 : {
3457 : // We allow AuxScalarKernels to request that they use_displaced_mesh,
3458 : // but then be overridden when no displacements variables are
3459 : // provided in the Mesh block. If that happened, update the value
3460 : // of use_displaced_mesh appropriately for this AuxScalarKernel.
3461 0 : if (parameters.have_parameter<bool>("use_displaced_mesh"))
3462 0 : parameters.set<bool>("use_displaced_mesh") = false;
3463 : }
3464 :
3465 950 : parameters.set<SubProblem *>("_subproblem") = this;
3466 1425 : parameters.set<SystemBase *>("_sys") = _aux.get();
3467 : }
3468 :
3469 475 : logAdd("AuxScalarKernel", name, kernel_name, parameters);
3470 475 : _aux->addScalarKernel(kernel_name, name, parameters);
3471 472 : }
3472 :
3473 : void
3474 871 : FEProblemBase::addDiracKernel(const std::string & kernel_name,
3475 : const std::string & name,
3476 : InputParameters & parameters)
3477 : {
3478 : parallel_object_only();
3479 :
3480 1742 : const auto nl_sys_num = determineSolverSystem(parameters.varName("variable", name), true).second;
3481 868 : if (!isSolverSystemNonlinear(nl_sys_num))
3482 0 : mooseError("You are trying to add a DiracKernel to a linear variable/system, which is not "
3483 : "supported at the moment!");
3484 :
3485 868 : if (_displaced_problem && parameters.get<bool>("use_displaced_mesh"))
3486 : {
3487 24 : parameters.set<SubProblem *>("_subproblem") = _displaced_problem.get();
3488 24 : parameters.set<SystemBase *>("_sys") = &_displaced_problem->solverSys(nl_sys_num);
3489 12 : _reinit_displaced_elem = true;
3490 : }
3491 : else
3492 : {
3493 856 : if (_displaced_problem == nullptr && parameters.get<bool>("use_displaced_mesh"))
3494 : {
3495 : // We allow DiracKernels to request that they use_displaced_mesh,
3496 : // but then be overridden when no displacements variables are
3497 : // provided in the Mesh block. If that happened, update the value
3498 : // of use_displaced_mesh appropriately for this DiracKernel.
3499 0 : if (parameters.have_parameter<bool>("use_displaced_mesh"))
3500 0 : parameters.set<bool>("use_displaced_mesh") = false;
3501 : }
3502 :
3503 1712 : parameters.set<SubProblem *>("_subproblem") = this;
3504 2568 : parameters.set<SystemBase *>("_sys") = _nl[nl_sys_num].get();
3505 : }
3506 :
3507 868 : logAdd("DiracKernel", name, kernel_name, parameters);
3508 868 : _nl[nl_sys_num]->addDiracKernel(kernel_name, name, parameters);
3509 862 : }
3510 :
3511 : // DGKernels ////
3512 :
3513 : void
3514 1298 : FEProblemBase::addDGKernel(const std::string & dg_kernel_name,
3515 : const std::string & name,
3516 : InputParameters & parameters)
3517 : {
3518 : parallel_object_only();
3519 :
3520 2596 : const auto nl_sys_num = determineSolverSystem(parameters.varName("variable", name), true).second;
3521 1295 : if (!isSolverSystemNonlinear(nl_sys_num))
3522 0 : mooseError("You are trying to add a DGKernel to a linear variable/system, which is not "
3523 : "supported at the moment!");
3524 :
3525 1295 : if (_displaced_problem && parameters.get<bool>("use_displaced_mesh"))
3526 : {
3527 48 : parameters.set<SubProblem *>("_subproblem") = _displaced_problem.get();
3528 48 : parameters.set<SystemBase *>("_sys") = &_displaced_problem->solverSys(nl_sys_num);
3529 24 : _reinit_displaced_neighbor = true;
3530 : }
3531 : else
3532 : {
3533 1271 : if (_displaced_problem == nullptr && parameters.get<bool>("use_displaced_mesh"))
3534 : {
3535 : // We allow DGKernels to request that they use_displaced_mesh,
3536 : // but then be overridden when no displacements variables are
3537 : // provided in the Mesh block. If that happened, update the value
3538 : // of use_displaced_mesh appropriately for this DGKernel.
3539 0 : if (parameters.have_parameter<bool>("use_displaced_mesh"))
3540 0 : parameters.set<bool>("use_displaced_mesh") = false;
3541 : }
3542 :
3543 2542 : parameters.set<SubProblem *>("_subproblem") = this;
3544 3813 : parameters.set<SystemBase *>("_sys") = _nl[nl_sys_num].get();
3545 : }
3546 :
3547 1295 : logAdd("DGKernel", name, dg_kernel_name, parameters);
3548 1295 : _nl[nl_sys_num]->addDGKernel(dg_kernel_name, name, parameters);
3549 :
3550 1295 : _has_internal_edge_residual_objects = true;
3551 1295 : }
3552 :
3553 : void
3554 6609 : FEProblemBase::addFVKernel(const std::string & fv_kernel_name,
3555 : const std::string & name,
3556 : InputParameters & parameters)
3557 : {
3558 6609 : if (_displaced_problem && parameters.get<bool>("use_displaced_mesh"))
3559 : // FVElementalKernels are computed in the historically finite element threaded loops. They rely
3560 : // on Assembly data like _current_elem. When we call reinit on the FEProblemBase we will only
3561 : // reinit the DisplacedProblem and its associated Assembly objects if we mark this boolean as
3562 : // true
3563 0 : _reinit_displaced_elem = true;
3564 6609 : addObject<FVKernel>(fv_kernel_name, name, parameters);
3565 6603 : }
3566 :
3567 : void
3568 5855 : FEProblemBase::addFVBC(const std::string & fv_bc_name,
3569 : const std::string & name,
3570 : InputParameters & parameters)
3571 : {
3572 5855 : addObject<FVBoundaryCondition>(fv_bc_name, name, parameters);
3573 5855 : }
3574 :
3575 : void
3576 238 : FEProblemBase::addFVInterfaceKernel(const std::string & fv_ik_name,
3577 : const std::string & name,
3578 : InputParameters & parameters)
3579 : {
3580 : /// We assume that variable1 and variable2 can live on different systems, in this case
3581 : /// the user needs to create two interface kernels with flipped variables and parameters
3582 238 : addObject<FVInterfaceKernel>(
3583 : fv_ik_name, name, parameters, /*threaded=*/true, /*variable_param_name=*/"variable1");
3584 229 : }
3585 :
3586 : void
3587 2157 : FEProblemBase::addLinearFVKernel(const std::string & kernel_name,
3588 : const std::string & name,
3589 : InputParameters & parameters)
3590 : {
3591 2157 : addObject<LinearFVKernel>(kernel_name, name, parameters);
3592 2157 : }
3593 :
3594 : void
3595 2064 : FEProblemBase::addLinearFVBC(const std::string & bc_name,
3596 : const std::string & name,
3597 : InputParameters & parameters)
3598 : {
3599 2064 : addObject<LinearFVBoundaryCondition>(bc_name, name, parameters);
3600 2064 : }
3601 :
3602 : // InterfaceKernels ////
3603 :
3604 : void
3605 800 : FEProblemBase::addInterfaceKernel(const std::string & interface_kernel_name,
3606 : const std::string & name,
3607 : InputParameters & parameters)
3608 : {
3609 : parallel_object_only();
3610 :
3611 1600 : const auto nl_sys_num = determineSolverSystem(parameters.varName("variable", name), true).second;
3612 797 : if (!isSolverSystemNonlinear(nl_sys_num))
3613 0 : mooseError("You are trying to add a InterfaceKernel to a linear variable/system, which is not "
3614 : "supported at the moment!");
3615 :
3616 797 : if (_displaced_problem && parameters.get<bool>("use_displaced_mesh"))
3617 : {
3618 24 : parameters.set<SubProblem *>("_subproblem") = _displaced_problem.get();
3619 24 : parameters.set<SystemBase *>("_sys") = &_displaced_problem->solverSys(nl_sys_num);
3620 12 : _reinit_displaced_neighbor = true;
3621 : }
3622 : else
3623 : {
3624 785 : if (_displaced_problem == nullptr && parameters.get<bool>("use_displaced_mesh"))
3625 : {
3626 : // We allow InterfaceKernels to request that they use_displaced_mesh,
3627 : // but then be overridden when no displacements variables are
3628 : // provided in the Mesh block. If that happened, update the value
3629 : // of use_displaced_mesh appropriately for this InterfaceKernel.
3630 0 : if (parameters.have_parameter<bool>("use_displaced_mesh"))
3631 0 : parameters.set<bool>("use_displaced_mesh") = false;
3632 : }
3633 :
3634 1570 : parameters.set<SubProblem *>("_subproblem") = this;
3635 2355 : parameters.set<SystemBase *>("_sys") = _nl[nl_sys_num].get();
3636 : }
3637 :
3638 797 : logAdd("InterfaceKernel", name, interface_kernel_name, parameters);
3639 797 : _nl[nl_sys_num]->addInterfaceKernel(interface_kernel_name, name, parameters);
3640 :
3641 797 : _has_internal_edge_residual_objects = true;
3642 797 : }
3643 :
3644 : void
3645 33709 : FEProblemBase::checkICRestartError(const std::string & ic_name,
3646 : const std::string & name,
3647 : const VariableName & var_name)
3648 : {
3649 33709 : if (!_allow_ics_during_restart)
3650 : {
3651 33630 : std::string restart_method = "";
3652 33630 : if (_app.isRestarting())
3653 : restart_method =
3654 0 : "a checkpoint restart, by IC object '" + ic_name + "' for variable '" + name + "'";
3655 33630 : else if (_app.getExReaderForRestart())
3656 : {
3657 3 : std::vector<std::string> restarted_vars = _app.getExReaderForRestart()->get_elem_var_names();
3658 3 : const auto nodal_vars = _app.getExReaderForRestart()->get_nodal_var_names();
3659 3 : const auto global_vars = _app.getExReaderForRestart()->get_global_var_names();
3660 3 : restarted_vars.insert(restarted_vars.end(), nodal_vars.begin(), nodal_vars.end());
3661 3 : restarted_vars.insert(restarted_vars.end(), global_vars.begin(), global_vars.end());
3662 :
3663 3 : if (std::find(restarted_vars.begin(), restarted_vars.end(), var_name) != restarted_vars.end())
3664 6 : restart_method = "an Exodus restart, by IC object '" + ic_name + "' for variable '" + name +
3665 3 : "' that is also being restarted";
3666 3 : }
3667 33630 : if (!restart_method.empty())
3668 3 : mooseError(
3669 : "Initial conditions have been specified during ",
3670 : restart_method,
3671 : ".\nThis is only allowed if you specify 'allow_initial_conditions_with_restart' to "
3672 : "the [Problem], as initial conditions can override restarted fields");
3673 33627 : }
3674 33706 : }
3675 :
3676 : void
3677 31443 : FEProblemBase::addInitialCondition(const std::string & ic_name,
3678 : const std::string & name,
3679 : InputParameters & parameters)
3680 : {
3681 : parallel_object_only();
3682 :
3683 : // before we start to mess with the initial condition, we need to check parameters for errors.
3684 31443 : parameters.checkParams(name);
3685 31440 : const std::string & var_name = parameters.get<VariableName>("variable");
3686 :
3687 : // Forbid initial conditions on a restarted problem, as they would override the restart
3688 31440 : checkICRestartError(ic_name, name, var_name);
3689 :
3690 62874 : parameters.set<SubProblem *>("_subproblem") = this;
3691 :
3692 : // field IC
3693 31437 : if (hasVariable(var_name))
3694 : {
3695 63201 : for (THREAD_ID tid = 0; tid < libMesh::n_threads(); ++tid)
3696 : {
3697 33324 : MooseVariableFEBase & var = getVariable(
3698 : tid, var_name, Moose::VarKindType::VAR_ANY, Moose::VarFieldType::VAR_FIELD_ANY);
3699 66648 : parameters.set<SystemBase *>("_sys") = &var.sys();
3700 33324 : std::shared_ptr<InitialConditionBase> ic;
3701 33324 : if (dynamic_cast<MooseVariable *>(&var))
3702 31203 : ic = _factory.create<InitialCondition>(ic_name, name, parameters, tid);
3703 2121 : else if (dynamic_cast<VectorMooseVariable *>(&var))
3704 250 : ic = _factory.create<VectorInitialCondition>(ic_name, name, parameters, tid);
3705 1871 : else if (dynamic_cast<ArrayMooseVariable *>(&var))
3706 1207 : ic = _factory.create<ArrayInitialCondition>(ic_name, name, parameters, tid);
3707 664 : else if (dynamic_cast<MooseVariableFVReal *>(&var))
3708 664 : ic = _factory.create<InitialCondition>(ic_name, name, parameters, tid);
3709 0 : else if (dynamic_cast<MooseLinearVariableFVReal *>(&var))
3710 0 : ic = _factory.create<InitialCondition>(ic_name, name, parameters, tid);
3711 : else
3712 0 : mooseError("Your FE variable in initial condition ",
3713 : name,
3714 : " must be either of scalar or vector type");
3715 33303 : logAdd("IC", name, ic_name, parameters);
3716 33303 : _ics.addObject(ic, tid);
3717 33288 : }
3718 : }
3719 :
3720 : // scalar IC
3721 1524 : else if (hasScalarVariable(var_name))
3722 : {
3723 1524 : MooseVariableScalar & var = getScalarVariable(0, var_name);
3724 3048 : parameters.set<SystemBase *>("_sys") = &var.sys();
3725 : std::shared_ptr<ScalarInitialCondition> ic =
3726 1524 : _factory.create<ScalarInitialCondition>(ic_name, name, parameters);
3727 1524 : logAdd("ScalarIC", name, ic_name, parameters);
3728 1524 : _scalar_ics.addObject(ic);
3729 1524 : }
3730 :
3731 : else
3732 0 : mooseError(
3733 : "Variable '", var_name, "' requested in initial condition '", name, "' does not exist.");
3734 31401 : }
3735 :
3736 : void
3737 2269 : FEProblemBase::addFVInitialCondition(const std::string & ic_name,
3738 : const std::string & name,
3739 : InputParameters & parameters)
3740 : {
3741 : parallel_object_only();
3742 :
3743 : // before we start to mess with the initial condition, we need to check parameters for errors.
3744 2269 : parameters.checkParams(name);
3745 2269 : const std::string & var_name = parameters.get<VariableName>("variable");
3746 :
3747 : // Forbid initial conditions on a restarted problem, as they would override the restart
3748 2269 : checkICRestartError(ic_name, name, var_name);
3749 :
3750 4538 : parameters.set<SubProblem *>("_subproblem") = this;
3751 :
3752 : // field IC
3753 2269 : if (hasVariable(var_name))
3754 : {
3755 4620 : for (THREAD_ID tid = 0; tid < libMesh::n_threads(); ++tid)
3756 : {
3757 2351 : auto & var = getVariable(
3758 : tid, var_name, Moose::VarKindType::VAR_ANY, Moose::VarFieldType::VAR_FIELD_ANY);
3759 4702 : parameters.set<SystemBase *>("_sys") = &var.sys();
3760 2351 : std::shared_ptr<FVInitialConditionBase> ic;
3761 2351 : if (var.isFV())
3762 2351 : ic = _factory.create<FVInitialCondition>(ic_name, name, parameters, tid);
3763 : else
3764 0 : mooseError(
3765 : "Your variable for an FVInitialCondition needs to be an a finite volume variable!");
3766 2351 : _fv_ics.addObject(ic, tid);
3767 2351 : }
3768 : }
3769 : else
3770 0 : mooseError("Variable '",
3771 : var_name,
3772 : "' requested in finite volume initial condition '",
3773 : name,
3774 : "' does not exist.");
3775 2269 : }
3776 :
3777 : void
3778 55839 : FEProblemBase::projectSolution()
3779 : {
3780 279195 : TIME_SECTION("projectSolution", 2, "Projecting Initial Solutions")
3781 :
3782 55839 : FloatingPointExceptionGuard fpe_guard(_app);
3783 :
3784 55839 : ComputeInitialConditionThread cic(*this);
3785 55839 : Threads::parallel_reduce(getCurrentAlgebraicElementRange(), cic);
3786 :
3787 55833 : if (haveFV())
3788 : {
3789 : using ElemInfoRange = StoredRange<MooseMesh::const_elem_info_iterator, const ElemInfo *>;
3790 3930 : ElemInfoRange elem_info_range(_mesh.ownedElemInfoBegin(), _mesh.ownedElemInfoEnd());
3791 :
3792 3930 : ComputeFVInitialConditionThread cfvic(*this);
3793 3930 : Threads::parallel_reduce(elem_info_range, cfvic);
3794 3930 : }
3795 :
3796 : // Need to close the solution vector here so that boundary ICs take precendence
3797 110897 : for (auto & nl : _nl)
3798 55064 : nl->solution().close();
3799 55833 : _aux->solution().close();
3800 :
3801 : // now run boundary-restricted initial conditions
3802 55833 : ComputeBoundaryInitialConditionThread cbic(*this);
3803 55833 : Threads::parallel_reduce(getCurrentAlgebraicBndNodeRange(), cbic);
3804 :
3805 110897 : for (auto & nl : _nl)
3806 55064 : nl->solution().close();
3807 55833 : _aux->solution().close();
3808 :
3809 : // Also, load values into the SCALAR dofs
3810 : // Note: We assume that all SCALAR dofs are on the
3811 : // processor with highest ID
3812 55833 : if (processor_id() == (n_processors() - 1) && _scalar_ics.hasActiveObjects())
3813 : {
3814 567 : const auto & ics = _scalar_ics.getActiveObjects();
3815 1561 : for (const auto & ic : ics)
3816 : {
3817 994 : MooseVariableScalar & var = ic->variable();
3818 994 : var.reinit();
3819 :
3820 994 : DenseVector<Number> vals(var.order());
3821 994 : ic->compute(vals);
3822 :
3823 994 : const unsigned int n_scalar_dofs = var.dofIndices().size();
3824 2323 : for (unsigned int i = 0; i < n_scalar_dofs; i++)
3825 : {
3826 1329 : const auto global_index = var.dofIndices()[i];
3827 1329 : var.sys().solution().set(global_index, vals(i));
3828 1329 : var.setValue(i, vals(i));
3829 : }
3830 994 : }
3831 : }
3832 :
3833 111895 : for (auto & sys : _solver_systems)
3834 : {
3835 56062 : sys->solution().close();
3836 56062 : sys->solution().localize(*sys->system().current_local_solution, sys->dofMap().get_send_list());
3837 : }
3838 :
3839 55833 : _aux->solution().close();
3840 55833 : _aux->solution().localize(*_aux->sys().current_local_solution, _aux->dofMap().get_send_list());
3841 55833 : }
3842 :
3843 : void
3844 2037 : FEProblemBase::projectInitialConditionOnCustomRange(
3845 : ConstElemRange & elem_range,
3846 : ConstBndNodeRange & bnd_nodes,
3847 : const std::optional<std::set<VariableName>> & target_vars)
3848 : {
3849 2037 : if (target_vars)
3850 : {
3851 2037 : ComputeInitialConditionThread cic(*this, &(*target_vars));
3852 2037 : Threads::parallel_reduce(elem_range, cic);
3853 : }
3854 : else
3855 : {
3856 0 : ComputeInitialConditionThread cic(*this);
3857 0 : Threads::parallel_reduce(elem_range, cic);
3858 : }
3859 :
3860 : // Need to close the solution vector here so that boundary ICs take precendence
3861 4074 : for (auto & nl : _nl)
3862 2037 : nl->solution().close();
3863 2037 : _aux->solution().close();
3864 :
3865 2037 : if (target_vars)
3866 : {
3867 2037 : ComputeBoundaryInitialConditionThread cbic(*this, &(*target_vars));
3868 2037 : Threads::parallel_reduce(bnd_nodes, cbic);
3869 2037 : }
3870 : else
3871 : {
3872 0 : ComputeBoundaryInitialConditionThread cbic(*this);
3873 0 : Threads::parallel_reduce(bnd_nodes, cbic);
3874 0 : }
3875 :
3876 4074 : for (auto & nl : _nl)
3877 2037 : nl->solution().close();
3878 2037 : _aux->solution().close();
3879 :
3880 : // Also, load values into the SCALAR dofs
3881 : // Note: We assume that all SCALAR dofs are on the
3882 : // processor with highest ID
3883 2037 : if (processor_id() == (n_processors() - 1) && _scalar_ics.hasActiveObjects())
3884 : {
3885 0 : const auto & ics = _scalar_ics.getActiveObjects();
3886 0 : for (const auto & ic : ics)
3887 : {
3888 0 : MooseVariableScalar & var = ic->variable();
3889 :
3890 0 : if (target_vars && !target_vars->count(var.name()))
3891 0 : continue;
3892 :
3893 0 : var.reinit();
3894 :
3895 0 : DenseVector<Number> vals(var.order());
3896 0 : ic->compute(vals);
3897 :
3898 0 : const unsigned int n_scalar_dofs = var.dofIndices().size();
3899 0 : for (unsigned int i = 0; i < n_scalar_dofs; i++)
3900 : {
3901 0 : const auto global_index = var.dofIndices()[i];
3902 0 : var.sys().solution().set(global_index, vals(i));
3903 0 : var.setValue(i, vals(i));
3904 : }
3905 0 : }
3906 : }
3907 :
3908 4074 : for (auto & nl : _nl)
3909 : {
3910 2037 : nl->solution().close();
3911 2037 : nl->solution().localize(*nl->system().current_local_solution, nl->dofMap().get_send_list());
3912 : }
3913 :
3914 2037 : _aux->solution().close();
3915 2037 : _aux->solution().localize(*_aux->sys().current_local_solution, _aux->dofMap().get_send_list());
3916 2037 : }
3917 :
3918 : void
3919 737 : FEProblemBase::projectFunctionOnCustomRange(ConstElemRange & elem_range,
3920 : Number (*func)(const Point &,
3921 : const libMesh::Parameters &,
3922 : const std::string &,
3923 : const std::string &),
3924 : Gradient (*func_grad)(const Point &,
3925 : const libMesh::Parameters &,
3926 : const std::string &,
3927 : const std::string &),
3928 : const libMesh::Parameters & params,
3929 : const std::vector<VariableName> & target_vars)
3930 : {
3931 : mooseAssert(!Threads::in_threads,
3932 : "We're performing a projection based on data from just the thread 0 variable, so any "
3933 : "modifications to the variable solution must have been thread joined already");
3934 :
3935 737 : std::unordered_map<unsigned int, std::vector<unsigned int>> sys_to_var_nums;
3936 :
3937 1474 : for (const auto & target_var : target_vars)
3938 : {
3939 737 : const auto sn = systemNumForVariable(target_var);
3940 737 : const auto & var = getStandardVariable(0, target_var);
3941 737 : sys_to_var_nums[sn].push_back(var.number());
3942 : }
3943 :
3944 1474 : for (const auto & [sys_num, var_nums] : sys_to_var_nums)
3945 : {
3946 737 : System & libmesh_sys = getSystemBase(sys_num).system();
3947 737 : libmesh_sys.project_solution(func, func_grad, params, elem_range, var_nums);
3948 : }
3949 737 : }
3950 :
3951 : std::shared_ptr<MaterialBase>
3952 252 : FEProblemBase::getMaterial(std::string name,
3953 : Moose::MaterialDataType type,
3954 : const THREAD_ID tid,
3955 : bool no_warn)
3956 : {
3957 252 : switch (type)
3958 : {
3959 65 : case Moose::NEIGHBOR_MATERIAL_DATA:
3960 65 : name += "_neighbor";
3961 65 : break;
3962 65 : case Moose::FACE_MATERIAL_DATA:
3963 65 : name += "_face";
3964 65 : break;
3965 122 : default:
3966 122 : break;
3967 : }
3968 :
3969 252 : std::shared_ptr<MaterialBase> material = _all_materials[type].getActiveObject(name, tid);
3970 657 : if (!no_warn && material->getParam<bool>("compute") && type == Moose::BLOCK_MATERIAL_DATA)
3971 3 : mooseWarning("You are retrieving a Material object (",
3972 3 : material->name(),
3973 : "), but its compute flag is set to true. This indicates that MOOSE is "
3974 : "computing this property which may not be desired and produce un-expected "
3975 : "results.");
3976 :
3977 246 : return material;
3978 : }
3979 :
3980 : MaterialData &
3981 33119542 : FEProblemBase::getMaterialData(Moose::MaterialDataType type,
3982 : const THREAD_ID tid,
3983 : const MooseObject * object) const
3984 : {
3985 33119542 : switch (type)
3986 : {
3987 845343 : case Moose::BLOCK_MATERIAL_DATA:
3988 845343 : if (object)
3989 258579 : _material_props.addConsumer(type, object);
3990 845343 : return _material_props.getMaterialData(tid);
3991 15162827 : case Moose::NEIGHBOR_MATERIAL_DATA:
3992 15162827 : if (object)
3993 22342 : _neighbor_material_props.addConsumer(type, object);
3994 15162827 : return _neighbor_material_props.getMaterialData(tid);
3995 17111372 : case Moose::BOUNDARY_MATERIAL_DATA:
3996 : case Moose::FACE_MATERIAL_DATA:
3997 : case Moose::INTERFACE_MATERIAL_DATA:
3998 17111372 : if (object)
3999 51840 : _bnd_material_props.addConsumer(type, object);
4000 17111372 : return _bnd_material_props.getMaterialData(tid);
4001 : }
4002 :
4003 0 : mooseError("FEProblemBase::getMaterialData(): Invalid MaterialDataType ", type);
4004 : }
4005 :
4006 : const std::set<const MooseObject *> &
4007 0 : FEProblemBase::getMaterialPropertyStorageConsumers(Moose::MaterialDataType type) const
4008 : {
4009 0 : switch (type)
4010 : {
4011 0 : case Moose::BLOCK_MATERIAL_DATA:
4012 0 : return _material_props.getConsumers(type);
4013 0 : case Moose::NEIGHBOR_MATERIAL_DATA:
4014 0 : return _neighbor_material_props.getConsumers(type);
4015 0 : case Moose::BOUNDARY_MATERIAL_DATA:
4016 : case Moose::FACE_MATERIAL_DATA:
4017 : case Moose::INTERFACE_MATERIAL_DATA:
4018 0 : return _bnd_material_props.getConsumers(type);
4019 : }
4020 :
4021 0 : mooseError("FEProblemBase::getMaterialPropertyStorageConsumers(): Invalid MaterialDataType ",
4022 : type);
4023 : }
4024 :
4025 : void
4026 0 : FEProblemBase::setPreserveMatrixSparsityPattern(bool preserve)
4027 : {
4028 0 : if (_ignore_zeros_in_jacobian && preserve)
4029 0 : paramWarning(
4030 : "ignore_zeros_in_jacobian",
4031 : "We likely cannot preserve the sparsity pattern if ignoring zeros in the Jacobian, which "
4032 : "leads to removing those entries from the Jacobian sparsity pattern");
4033 0 : _preserve_matrix_sparsity_pattern = preserve;
4034 0 : }
4035 :
4036 : bool
4037 309262 : FEProblemBase::acceptInvalidSolution() const
4038 : {
4039 618439 : return allowInvalidSolution() || // invalid solutions are always allowed
4040 618439 : !_app.solutionInvalidity().hasInvalidSolutionError(); // if not allowed, check for errors
4041 : }
4042 :
4043 : void
4044 964 : FEProblemBase::addFunctorMaterial(const std::string & functor_material_name,
4045 : const std::string & name,
4046 : InputParameters & parameters)
4047 : {
4048 : parallel_object_only();
4049 :
4050 964 : auto add_functor_materials = [&](const auto & parameters, const auto & name)
4051 : {
4052 2011 : for (THREAD_ID tid = 0; tid < libMesh::n_threads(); tid++)
4053 : {
4054 : // Create the general Block/Boundary MaterialBase object
4055 1047 : std::shared_ptr<MaterialBase> material =
4056 1047 : _factory.create<MaterialBase>(functor_material_name, name, parameters, tid);
4057 2094 : logAdd("FunctorMaterial", name, functor_material_name, parameters);
4058 1047 : _all_materials.addObject(material, tid);
4059 1047 : _materials.addObject(material, tid);
4060 : }
4061 964 : };
4062 :
4063 1928 : parameters.set<SubProblem *>("_subproblem") = this;
4064 964 : add_functor_materials(parameters, name);
4065 964 : if (_displaced_problem)
4066 : {
4067 0 : auto disp_params = parameters;
4068 0 : disp_params.set<SubProblem *>("_subproblem") = _displaced_problem.get();
4069 0 : add_functor_materials(disp_params, name + "_displaced");
4070 0 : }
4071 964 : }
4072 :
4073 : void
4074 12078 : FEProblemBase::addMaterial(const std::string & mat_name,
4075 : const std::string & name,
4076 : InputParameters & parameters)
4077 : {
4078 24156 : addMaterialHelper({&_materials}, mat_name, name, parameters);
4079 11980 : }
4080 :
4081 : void
4082 340 : FEProblemBase::addInterfaceMaterial(const std::string & mat_name,
4083 : const std::string & name,
4084 : InputParameters & parameters)
4085 : {
4086 680 : addMaterialHelper({&_interface_materials}, mat_name, name, parameters);
4087 340 : }
4088 :
4089 : void
4090 13360 : FEProblemBase::addMaterialHelper(std::vector<MaterialWarehouse *> warehouses,
4091 : const std::string & mat_name,
4092 : const std::string & name,
4093 : InputParameters & parameters)
4094 : {
4095 : parallel_object_only();
4096 :
4097 13360 : if (_displaced_problem && parameters.get<bool>("use_displaced_mesh"))
4098 : {
4099 252 : parameters.set<SubProblem *>("_subproblem") = _displaced_problem.get();
4100 126 : _reinit_displaced_elem = _reinit_displaced_face = _reinit_displaced_neighbor = true;
4101 : }
4102 : else
4103 : {
4104 13234 : if (_displaced_problem == nullptr && parameters.get<bool>("use_displaced_mesh"))
4105 : {
4106 : // We allow Materials to request that they use_displaced_mesh,
4107 : // but then be overridden when no displacements variables are
4108 : // provided in the Mesh block. If that happened, update the value
4109 : // of use_displaced_mesh appropriately for this Material.
4110 0 : if (parameters.have_parameter<bool>("use_displaced_mesh"))
4111 0 : parameters.set<bool>("use_displaced_mesh") = false;
4112 : }
4113 :
4114 39702 : parameters.set<SubProblem *>("_subproblem") = this;
4115 : }
4116 :
4117 13360 : unsigned int n_threads = libMesh::n_threads();
4118 :
4119 : #ifdef MOOSE_KOKKOS_ENABLED
4120 10010 : if (parameters.isKokkosObject())
4121 942 : n_threads = 1;
4122 : #endif
4123 :
4124 27802 : for (THREAD_ID tid = 0; tid < n_threads; tid++)
4125 : {
4126 : // Create the general Block/Boundary MaterialBase object
4127 : std::shared_ptr<MaterialBase> material =
4128 14548 : _factory.create<MaterialBase>(mat_name, name, parameters, tid);
4129 14442 : logAdd("Material", name, mat_name, parameters);
4130 28884 : bool discrete = !material->getParam<bool>("compute");
4131 :
4132 : // If the object is boundary restricted or if it is a functor material we do not create the
4133 : // neighbor and face objects
4134 14442 : if (material->boundaryRestricted() || dynamic_cast<FunctorMaterial *>(material.get()))
4135 : {
4136 2970 : _all_materials.addObject(material, tid);
4137 2970 : if (discrete)
4138 4 : _discrete_materials.addObject(material, tid);
4139 : else
4140 5932 : for (auto && warehouse : warehouses)
4141 2966 : warehouse->addObject(material, tid);
4142 : }
4143 :
4144 : // Non-boundary restricted require face and neighbor objects
4145 : else
4146 : {
4147 : // TODO: we only need to do this if we have needs for face materials (e.g.
4148 : // FV, DG, etc.) - but currently we always do it. Figure out how to fix
4149 : // this.
4150 :
4151 : // The name of the object being created, this is changed multiple times as objects are
4152 : // created below
4153 11472 : std::string object_name;
4154 :
4155 : // Create a copy of the supplied parameters to the setting for "_material_data_type" isn't
4156 : // used from a previous tid loop
4157 11472 : InputParameters current_parameters = parameters;
4158 :
4159 : // face material
4160 11472 : current_parameters.set<Moose::MaterialDataType>("_material_data_type") =
4161 : Moose::FACE_MATERIAL_DATA;
4162 11472 : object_name = name + "_face";
4163 : std::shared_ptr<MaterialBase> face_material =
4164 11472 : _factory.create<MaterialBase>(mat_name, object_name, current_parameters, tid);
4165 :
4166 : // neighbor material
4167 22944 : current_parameters.set<Moose::MaterialDataType>("_material_data_type") =
4168 : Moose::NEIGHBOR_MATERIAL_DATA;
4169 11472 : current_parameters.set<bool>("_neighbor") = true;
4170 11472 : object_name = name + "_neighbor";
4171 : std::shared_ptr<MaterialBase> neighbor_material =
4172 11472 : _factory.create<MaterialBase>(mat_name, object_name, current_parameters, tid);
4173 :
4174 : // Store the material objects
4175 11472 : _all_materials.addObjects(material, neighbor_material, face_material, tid);
4176 :
4177 11472 : if (discrete)
4178 73 : _discrete_materials.addObjects(material, neighbor_material, face_material, tid);
4179 : else
4180 22798 : for (auto && warehouse : warehouses)
4181 11399 : warehouse->addObjects(material, neighbor_material, face_material, tid);
4182 :
4183 : // Names of all controllable parameters for this Material object
4184 11472 : const std::string & base = parameters.getBase();
4185 34416 : MooseObjectParameterName name(MooseObjectName(base, material->name()), "*");
4186 : const auto param_names =
4187 11472 : _app.getInputParameterWarehouse().getControllableParameterNames(name);
4188 :
4189 : // Connect parameters of the primary Material object to those on the face and neighbor
4190 : // objects
4191 29203 : for (const auto & p_name : param_names)
4192 : {
4193 35462 : MooseObjectParameterName primary_name(MooseObjectName(base, material->name()),
4194 35462 : p_name.parameter());
4195 35462 : MooseObjectParameterName face_name(MooseObjectName(base, face_material->name()),
4196 35462 : p_name.parameter());
4197 35462 : MooseObjectParameterName neighbor_name(MooseObjectName(base, neighbor_material->name()),
4198 35462 : p_name.parameter());
4199 17731 : _app.getInputParameterWarehouse().addControllableParameterConnection(
4200 : primary_name, face_name, false);
4201 17731 : _app.getInputParameterWarehouse().addControllableParameterConnection(
4202 : primary_name, neighbor_name, false);
4203 17731 : }
4204 11472 : }
4205 14442 : }
4206 13254 : }
4207 :
4208 : void
4209 5071240 : FEProblemBase::prepareMaterials(const std::unordered_set<unsigned int> & consumer_needed_mat_props,
4210 : const SubdomainID blk_id,
4211 : const THREAD_ID tid)
4212 : {
4213 5071240 : std::set<MooseVariableFEBase *> needed_moose_vars;
4214 5071240 : std::unordered_set<unsigned int> needed_mat_props;
4215 :
4216 5071240 : if (_all_materials.hasActiveBlockObjects(blk_id, tid))
4217 : {
4218 607967 : _all_materials.updateVariableDependency(needed_moose_vars, tid);
4219 607967 : _all_materials.updateBlockMatPropDependency(blk_id, needed_mat_props, tid);
4220 : }
4221 :
4222 5071240 : const auto & ids = _mesh.getSubdomainBoundaryIds(blk_id);
4223 23510021 : for (const auto id : ids)
4224 : {
4225 18438781 : _materials.updateBoundaryVariableDependency(id, needed_moose_vars, tid);
4226 18438781 : _materials.updateBoundaryMatPropDependency(id, needed_mat_props, tid);
4227 : }
4228 :
4229 5071240 : const auto & current_active_elemental_moose_variables = getActiveElementalMooseVariables(tid);
4230 5071240 : needed_moose_vars.insert(current_active_elemental_moose_variables.begin(),
4231 : current_active_elemental_moose_variables.end());
4232 :
4233 5071240 : needed_mat_props.insert(consumer_needed_mat_props.begin(), consumer_needed_mat_props.end());
4234 :
4235 5071240 : setActiveElementalMooseVariables(needed_moose_vars, tid);
4236 5071240 : setActiveMaterialProperties(needed_mat_props, tid);
4237 5071240 : }
4238 :
4239 : void
4240 363331153 : FEProblemBase::reinitMaterials(SubdomainID blk_id, const THREAD_ID tid, bool swap_stateful)
4241 : {
4242 363331153 : if (hasActiveMaterialProperties(tid))
4243 : {
4244 15089682 : auto && elem = _assembly[tid][0]->elem();
4245 15089682 : unsigned int n_points = _assembly[tid][0]->qRule()->n_points();
4246 :
4247 15089682 : auto & material_data = _material_props.getMaterialData(tid);
4248 15089682 : material_data.resize(n_points);
4249 :
4250 : // Only swap if requested
4251 15089682 : if (swap_stateful)
4252 15083140 : material_data.swap(*elem);
4253 :
4254 15089682 : if (_discrete_materials.hasActiveBlockObjects(blk_id, tid))
4255 2748 : material_data.reset(_discrete_materials.getActiveBlockObjects(blk_id, tid));
4256 :
4257 15089679 : if (_materials.hasActiveBlockObjects(blk_id, tid))
4258 15071090 : material_data.reinit(_materials.getActiveBlockObjects(blk_id, tid));
4259 : }
4260 363331094 : }
4261 :
4262 : void
4263 5106440 : FEProblemBase::reinitMaterialsFace(const SubdomainID blk_id,
4264 : const THREAD_ID tid,
4265 : const bool swap_stateful,
4266 : const std::deque<MaterialBase *> * const reinit_mats)
4267 : {
4268 : // we reinit more often than needed here because we dont have a way to check whether
4269 : // we need to compute the face materials on a particular (possibly external) face
4270 5106440 : if (hasActiveMaterialProperties(tid))
4271 : {
4272 1045875 : auto && elem = _assembly[tid][0]->elem();
4273 1045875 : unsigned int side = _assembly[tid][0]->side();
4274 1045875 : unsigned int n_points = _assembly[tid][0]->qRuleFace()->n_points();
4275 :
4276 1045875 : auto & bnd_material_data = _bnd_material_props.getMaterialData(tid);
4277 1045875 : bnd_material_data.resize(n_points);
4278 :
4279 1045875 : if (swap_stateful && !bnd_material_data.isSwapped())
4280 1024401 : bnd_material_data.swap(*elem, side);
4281 :
4282 1045875 : if (_discrete_materials[Moose::FACE_MATERIAL_DATA].hasActiveBlockObjects(blk_id, tid))
4283 0 : bnd_material_data.reset(
4284 0 : _discrete_materials[Moose::FACE_MATERIAL_DATA].getActiveBlockObjects(blk_id, tid));
4285 :
4286 1045875 : if (reinit_mats)
4287 21474 : bnd_material_data.reinit(*reinit_mats);
4288 1024401 : else if (_materials[Moose::FACE_MATERIAL_DATA].hasActiveBlockObjects(blk_id, tid))
4289 1024401 : bnd_material_data.reinit(
4290 1024401 : _materials[Moose::FACE_MATERIAL_DATA].getActiveBlockObjects(blk_id, tid));
4291 : }
4292 5106440 : }
4293 :
4294 : void
4295 3809315 : FEProblemBase::reinitMaterialsFaceOnBoundary(const BoundaryID boundary_id,
4296 : const SubdomainID blk_id,
4297 : const THREAD_ID tid,
4298 : const bool swap_stateful,
4299 : const std::deque<MaterialBase *> * const reinit_mats)
4300 : {
4301 4140246 : if (hasActiveMaterialProperties(tid) && (needBoundaryMaterialOnSide(boundary_id, tid) ||
4302 330931 : needInterfaceMaterialOnSide(boundary_id, tid) ||
4303 330931 : needInternalNeighborSideMaterial(blk_id, tid)))
4304 : {
4305 407458 : const auto * const elem = _assembly[tid][0]->elem();
4306 407458 : unsigned int side = _assembly[tid][0]->side();
4307 407458 : unsigned int n_points = _assembly[tid][0]->qRuleFace()->n_points();
4308 :
4309 407458 : auto & bnd_material_data = _bnd_material_props.getMaterialData(tid);
4310 407458 : bnd_material_data.resize(n_points);
4311 :
4312 407458 : if (swap_stateful && !bnd_material_data.isSwapped())
4313 407458 : bnd_material_data.swap(*elem, side);
4314 :
4315 407458 : 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 407458 : if (reinit_mats)
4320 0 : bnd_material_data.reinit(*reinit_mats);
4321 407458 : else if (_materials[Moose::FACE_MATERIAL_DATA].hasActiveBlockObjects(blk_id, tid))
4322 393066 : bnd_material_data.reinit(
4323 393066 : _materials[Moose::FACE_MATERIAL_DATA].getActiveBlockObjects(blk_id, tid));
4324 : }
4325 3809315 : }
4326 :
4327 : void
4328 43931 : FEProblemBase::reinitMaterialsNeighborOnBoundary(
4329 : const BoundaryID boundary_id,
4330 : const SubdomainID blk_id,
4331 : const THREAD_ID tid,
4332 : const bool swap_stateful,
4333 : const std::deque<MaterialBase *> * const reinit_mats)
4334 : {
4335 : // Since objects don't declare whether they need the face or neighbor (side) material properties,
4336 : // we use the same criteria for skipping material property computations as for face material
4337 : // properties This could be a future optimization.
4338 48141 : if (hasActiveMaterialProperties(tid) && (needBoundaryMaterialOnSide(boundary_id, tid) ||
4339 4210 : needInterfaceMaterialOnSide(boundary_id, tid) ||
4340 4210 : needInternalNeighborSideMaterial(blk_id, tid)))
4341 35986 : reinitMaterialsNeighbor(blk_id, tid, swap_stateful, reinit_mats);
4342 43931 : }
4343 :
4344 : void
4345 3973331 : FEProblemBase::reinitMaterialsNeighbor(const SubdomainID blk_id,
4346 : const THREAD_ID tid,
4347 : const bool swap_stateful,
4348 : const std::deque<MaterialBase *> * const reinit_mats)
4349 : {
4350 3973331 : if (hasActiveMaterialProperties(tid))
4351 : {
4352 : // NOTE: this will not work with h-adaptivity
4353 : // lindsayad: why not?
4354 :
4355 887183 : const Elem * neighbor = _assembly[tid][0]->neighbor();
4356 887183 : unsigned int neighbor_side = neighbor->which_neighbor_am_i(_assembly[tid][0]->elem());
4357 :
4358 : mooseAssert(neighbor, "neighbor should be non-null");
4359 : mooseAssert(blk_id == neighbor->subdomain_id(),
4360 : "The provided blk_id " << blk_id << " and neighbor subdomain ID "
4361 : << neighbor->subdomain_id() << " do not match.");
4362 :
4363 887183 : unsigned int n_points = _assembly[tid][0]->qRuleNeighbor()->n_points();
4364 :
4365 887183 : auto & neighbor_material_data = _neighbor_material_props.getMaterialData(tid);
4366 887183 : neighbor_material_data.resize(n_points);
4367 :
4368 : // Only swap if requested
4369 887183 : if (swap_stateful)
4370 865709 : neighbor_material_data.swap(*neighbor, neighbor_side);
4371 :
4372 887183 : if (_discrete_materials[Moose::NEIGHBOR_MATERIAL_DATA].hasActiveBlockObjects(blk_id, tid))
4373 0 : neighbor_material_data.reset(
4374 0 : _discrete_materials[Moose::NEIGHBOR_MATERIAL_DATA].getActiveBlockObjects(blk_id, tid));
4375 :
4376 887183 : if (reinit_mats)
4377 21474 : neighbor_material_data.reinit(*reinit_mats);
4378 865709 : else if (_materials[Moose::NEIGHBOR_MATERIAL_DATA].hasActiveBlockObjects(blk_id, tid))
4379 865446 : neighbor_material_data.reinit(
4380 865446 : _materials[Moose::NEIGHBOR_MATERIAL_DATA].getActiveBlockObjects(blk_id, tid));
4381 : }
4382 3973331 : }
4383 :
4384 : void
4385 4063407 : FEProblemBase::reinitMaterialsBoundary(const BoundaryID boundary_id,
4386 : const THREAD_ID tid,
4387 : const bool swap_stateful,
4388 : const std::deque<MaterialBase *> * const reinit_mats)
4389 : {
4390 4063407 : if (hasActiveMaterialProperties(tid) && needBoundaryMaterialOnSide(boundary_id, tid))
4391 : {
4392 285970 : auto && elem = _assembly[tid][0]->elem();
4393 285970 : unsigned int side = _assembly[tid][0]->side();
4394 285970 : unsigned int n_points = _assembly[tid][0]->qRuleFace()->n_points();
4395 :
4396 285970 : auto & bnd_material_data = _bnd_material_props.getMaterialData(tid);
4397 285970 : bnd_material_data.resize(n_points);
4398 :
4399 285970 : if (swap_stateful && !bnd_material_data.isSwapped())
4400 238275 : bnd_material_data.swap(*elem, side);
4401 :
4402 285970 : if (_discrete_materials.hasActiveBoundaryObjects(boundary_id, tid))
4403 0 : bnd_material_data.reset(_discrete_materials.getActiveBoundaryObjects(boundary_id, tid));
4404 :
4405 285970 : if (reinit_mats)
4406 21474 : bnd_material_data.reinit(*reinit_mats);
4407 264496 : else if (_materials.hasActiveBoundaryObjects(boundary_id, tid))
4408 23154 : bnd_material_data.reinit(_materials.getActiveBoundaryObjects(boundary_id, tid));
4409 : }
4410 4063407 : }
4411 :
4412 : void
4413 46788 : FEProblemBase::reinitMaterialsInterface(BoundaryID boundary_id,
4414 : const THREAD_ID tid,
4415 : bool swap_stateful)
4416 : {
4417 46788 : if (hasActiveMaterialProperties(tid) && needInterfaceMaterialOnSide(boundary_id, tid))
4418 : {
4419 37022 : const Elem * const & elem = _assembly[tid][0]->elem();
4420 37022 : unsigned int side = _assembly[tid][0]->side();
4421 37022 : unsigned int n_points = _assembly[tid][0]->qRuleFace()->n_points();
4422 :
4423 37022 : auto & bnd_material_data = _bnd_material_props.getMaterialData(tid);
4424 37022 : bnd_material_data.resize(n_points);
4425 :
4426 37022 : if (swap_stateful && !bnd_material_data.isSwapped())
4427 35527 : bnd_material_data.swap(*elem, side);
4428 :
4429 37022 : if (_interface_materials.hasActiveBoundaryObjects(boundary_id, tid))
4430 1171 : bnd_material_data.reinit(_interface_materials.getActiveBoundaryObjects(boundary_id, tid));
4431 : }
4432 46788 : }
4433 :
4434 : void
4435 361712993 : FEProblemBase::swapBackMaterials(const THREAD_ID tid)
4436 : {
4437 361712993 : auto && elem = _assembly[tid][0]->elem();
4438 361712993 : _material_props.getMaterialData(tid).swapBack(*elem);
4439 361712993 : }
4440 :
4441 : void
4442 8661649 : FEProblemBase::swapBackMaterialsFace(const THREAD_ID tid)
4443 : {
4444 8661649 : auto && elem = _assembly[tid][0]->elem();
4445 8661649 : unsigned int side = _assembly[tid][0]->side();
4446 8661649 : _bnd_material_props.getMaterialData(tid).swapBack(*elem, side);
4447 8661649 : }
4448 :
4449 : void
4450 3630872 : FEProblemBase::swapBackMaterialsNeighbor(const THREAD_ID tid)
4451 : {
4452 : // NOTE: this will not work with h-adaptivity
4453 3630872 : const Elem * neighbor = _assembly[tid][0]->neighbor();
4454 : unsigned int neighbor_side =
4455 3630872 : neighbor ? neighbor->which_neighbor_am_i(_assembly[tid][0]->elem()) : libMesh::invalid_uint;
4456 :
4457 3630872 : if (!neighbor)
4458 : {
4459 0 : if (haveFV())
4460 : {
4461 : // If neighbor is null, then we're on the neighbor side of a mesh boundary, e.g. we're off
4462 : // the mesh in ghost-land. If we're using the finite volume method, then variable values and
4463 : // consequently material properties have well-defined values in this ghost region outside of
4464 : // the mesh and we really do want to reinit our neighbor materials in this case. Since we're
4465 : // off in ghost land it's safe to do swaps with `MaterialPropertyStorage` using the elem and
4466 : // elem_side keys
4467 0 : neighbor = _assembly[tid][0]->elem();
4468 0 : neighbor_side = _assembly[tid][0]->side();
4469 : mooseAssert(neighbor, "We should have an appropriate value for elem coming from Assembly");
4470 : }
4471 : else
4472 0 : mooseError("neighbor is null in Assembly!");
4473 : }
4474 :
4475 3630872 : _neighbor_material_props.getMaterialData(tid).swapBack(*neighbor, neighbor_side);
4476 3630872 : }
4477 :
4478 : void
4479 963663 : FEProblemBase::logAdd(const std::string & system,
4480 : const std::string & name,
4481 : const std::string & type,
4482 : const InputParameters & params) const
4483 : {
4484 963663 : if (_verbose_setup != "false")
4485 17453 : _console << "[DBG] Adding " << system << " '" << name << "' of type " << type << std::endl;
4486 963663 : if (_verbose_setup == "extra")
4487 0 : _console << params << std::endl;
4488 963663 : }
4489 :
4490 : void
4491 133720 : FEProblemBase::addObjectParamsHelper(InputParameters & parameters,
4492 : const std::string & object_name,
4493 : const std::string & var_param_name)
4494 : {
4495 : // Due to objects like SolutionUserObject which manipulate libmesh objects
4496 : // and variables directly at the back end, we need a default option here
4497 : // which is going to be the pointer to the first solver system within this
4498 : // problem
4499 133720 : unsigned int sys_num = 0;
4500 133720 : if (parameters.isParamValid(var_param_name))
4501 : {
4502 56482 : const auto variable_name = parameters.varName(var_param_name, object_name);
4503 56482 : if (this->hasVariable(variable_name) || this->hasScalarVariable(variable_name))
4504 50757 : sys_num = getSystem(variable_name).number();
4505 56482 : }
4506 267440 : if (parameters.isParamValid("solver_sys"))
4507 : {
4508 3447 : const auto var_sys_num = sys_num;
4509 3447 : sys_num = getSystemBase(parameters.get<SolverSystemName>("solver_sys")).number();
4510 3447 : if (sys_num != var_sys_num && parameters.isParamValid(var_param_name))
4511 0 : mooseError("We dont support setting 'variable' to a variable that is not set to the same "
4512 : "system as the 'solver_sys' parameter");
4513 : }
4514 :
4515 134884 : if (_displaced_problem && parameters.have_parameter<bool>("use_displaced_mesh") &&
4516 134884 : parameters.get<bool>("use_displaced_mesh"))
4517 : {
4518 1132 : parameters.set<SubProblem *>("_subproblem") = _displaced_problem.get();
4519 566 : if (sys_num == _aux->number())
4520 1104 : parameters.set<SystemBase *>("_sys") = &_displaced_problem->systemBaseAuxiliary();
4521 : else
4522 594 : parameters.set<SystemBase *>("_sys") = &_displaced_problem->solverSys(sys_num);
4523 : }
4524 : else
4525 : {
4526 : // The object requested use_displaced_mesh, but it was overridden
4527 : // due to there being no displacements variables in the [Mesh] block.
4528 : // If that happened, update the value of use_displaced_mesh appropriately.
4529 216543 : if (!_displaced_problem && parameters.have_parameter<bool>("use_displaced_mesh") &&
4530 216543 : parameters.get<bool>("use_displaced_mesh"))
4531 144 : parameters.set<bool>("use_displaced_mesh") = false;
4532 :
4533 266308 : parameters.set<SubProblem *>("_subproblem") = this;
4534 :
4535 133154 : if (sys_num == _aux->number())
4536 39885 : parameters.set<SystemBase *>("_sys") = _aux.get();
4537 : else
4538 359577 : parameters.set<SystemBase *>("_sys") = _solver_systems[sys_num].get();
4539 : }
4540 133720 : }
4541 :
4542 : void
4543 60593 : FEProblemBase::checkUserObjectNameCollision(const std::string & name,
4544 : const std::string & type) const
4545 : {
4546 60593 : if (hasUserObject(name))
4547 9 : mooseError("A ",
4548 9 : getUserObjectBase(name).typeAndName(),
4549 : " already exists. You may not add a ",
4550 : type,
4551 : " by the same name.");
4552 :
4553 : #ifdef MOOSE_KOKKOS_ENABLED
4554 45309 : if (hasKokkosUserObject(name))
4555 0 : mooseError("A ",
4556 0 : getKokkosUserObject<UserObjectBase>(name).typeAndName(),
4557 : " already exists. You may not add a ",
4558 : type,
4559 : " by the same name.");
4560 : #endif
4561 60584 : }
4562 :
4563 : void
4564 48136 : FEProblemBase::addPostprocessor(const std::string & pp_name,
4565 : const std::string & name,
4566 : InputParameters & parameters)
4567 : {
4568 48136 : checkUserObjectNameCollision(name, "Postprocessor");
4569 :
4570 48133 : addUserObject(pp_name, name, parameters);
4571 48104 : }
4572 :
4573 : void
4574 5683 : FEProblemBase::addVectorPostprocessor(const std::string & pp_name,
4575 : const std::string & name,
4576 : InputParameters & parameters)
4577 : {
4578 5683 : checkUserObjectNameCollision(name, "VectorPostprocessor");
4579 :
4580 5680 : addUserObject(pp_name, name, parameters);
4581 5650 : }
4582 :
4583 : void
4584 4681 : FEProblemBase::addReporter(const std::string & type,
4585 : const std::string & name,
4586 : InputParameters & parameters)
4587 : {
4588 4681 : checkUserObjectNameCollision(name, "Reporter");
4589 :
4590 4678 : addUserObject(type, name, parameters);
4591 4645 : }
4592 :
4593 : std::vector<std::shared_ptr<UserObject>>
4594 68457 : FEProblemBase::addUserObject(const std::string & user_object_name,
4595 : const std::string & name,
4596 : InputParameters & parameters)
4597 : {
4598 : parallel_object_only();
4599 :
4600 68457 : std::vector<std::shared_ptr<UserObject>> uos;
4601 :
4602 : // Add the _subproblem and _sys parameters depending on use_displaced_mesh
4603 68457 : addObjectParamsHelper(parameters, name);
4604 :
4605 111362 : for (const auto tid : make_range(libMesh::n_threads()))
4606 : {
4607 : // Create the UserObject
4608 : std::shared_ptr<UserObject> user_object =
4609 72183 : _factory.create<UserObject>(user_object_name, name, parameters, tid);
4610 71908 : logAdd("UserObject", name, user_object_name, parameters);
4611 71908 : uos.push_back(user_object);
4612 :
4613 71908 : if (tid != 0)
4614 3726 : user_object->setPrimaryThreadCopy(uos[0].get());
4615 :
4616 71908 : theWarehouse().add(user_object);
4617 :
4618 : // Attempt to create all the possible UserObject types
4619 71902 : auto euo = std::dynamic_pointer_cast<ElementUserObject>(user_object);
4620 71902 : auto suo = std::dynamic_pointer_cast<SideUserObject>(user_object);
4621 71902 : auto isuo = std::dynamic_pointer_cast<InternalSideUserObject>(user_object);
4622 71902 : auto iuo = std::dynamic_pointer_cast<InterfaceUserObjectBase>(user_object);
4623 71902 : auto nuo = std::dynamic_pointer_cast<NodalUserObject>(user_object);
4624 71902 : auto duo = std::dynamic_pointer_cast<DomainUserObject>(user_object);
4625 71902 : auto guo = std::dynamic_pointer_cast<GeneralUserObject>(user_object);
4626 71902 : auto tguo = std::dynamic_pointer_cast<ThreadedGeneralUserObject>(user_object);
4627 71902 : auto muo = std::dynamic_pointer_cast<MortarUserObject>(user_object);
4628 :
4629 : // Account for displaced mesh use
4630 71902 : if (_displaced_problem && parameters.get<bool>("use_displaced_mesh"))
4631 : {
4632 : // Whether to re-init or not depends on the attributes of the base classes.
4633 : // For example, InterfaceUOBase has "_current_side_elem" and "_neighbor_elem"
4634 : // so it needs to reinit on displaced neighbors and faces
4635 : // _reinit_displaced_elem -> _current_elem will be reinited
4636 : // _reinit_displaced_face -> _current_elem, lowerD if any and _current_side_elem to be
4637 : // reinited _reinit_displaced_neighbor -> _current_elem, lowerD if any and _current_neighbor
4638 : // to be reinited Note that as soon as you use materials on the displaced mesh, all three get
4639 : // turned on.
4640 615 : if (euo || nuo || duo)
4641 555 : _reinit_displaced_elem = true;
4642 615 : if (suo || duo || isuo || iuo)
4643 24 : _reinit_displaced_face = true;
4644 615 : if (iuo || duo || isuo)
4645 0 : _reinit_displaced_neighbor = true;
4646 : }
4647 :
4648 : // These objects only require one thread
4649 71902 : if ((guo && !tguo) || muo)
4650 28997 : break;
4651 332875 : }
4652 :
4653 : // Add as a Functor if it is one. We usually need to add the user object from thread 0 as the
4654 : // registered functor for all threads because when user objects are thread joined, generally only
4655 : // the primary thread copy ends up with all the data
4656 143507 : for (const auto tid : make_range(libMesh::n_threads()))
4657 : {
4658 75331 : const decltype(uos)::size_type uo_index = uos.front()->needThreadedCopy() ? tid : 0;
4659 75331 : if (const auto functor = dynamic_cast<Moose::FunctorBase<Real> *>(uos[uo_index].get()))
4660 : {
4661 58676 : this->addFunctor(name, *functor, tid);
4662 58676 : if (_displaced_problem)
4663 729 : _displaced_problem->addFunctor(name, *functor, tid);
4664 : }
4665 : }
4666 :
4667 68176 : return uos;
4668 2 : }
4669 :
4670 : void
4671 2002 : FEProblemBase::addFVInterpolationMethod(const std::string & method_type,
4672 : const std::string & name,
4673 : InputParameters & parameters)
4674 : {
4675 : parallel_object_only();
4676 :
4677 2002 : addObjectParamsHelper(parameters, name);
4678 :
4679 4004 : for (const auto tid : make_range(libMesh::n_threads()))
4680 : {
4681 2002 : auto method = _factory.create<FVInterpolationMethod>(method_type, name, parameters, tid);
4682 2002 : logAdd("FVInterpolationMethod", name, method_type, parameters);
4683 2002 : theWarehouse().add(method);
4684 2002 : }
4685 2002 : }
4686 :
4687 : const UserObject &
4688 285092 : FEProblemBase::getUserObjectBase(const std::string & name, const THREAD_ID tid /* = 0 */) const
4689 : {
4690 285092 : std::vector<UserObject *> objs;
4691 285092 : theWarehouse()
4692 570184 : .query()
4693 285092 : .condition<AttribSystem>("UserObject")
4694 285092 : .condition<AttribThread>(tid)
4695 285092 : .condition<AttribName>(name)
4696 285092 : .queryInto(objs);
4697 285092 : if (objs.empty())
4698 : {
4699 : mooseAssert(getMooseApp().actionWarehouse().isTaskComplete("add_user_object"),
4700 : "A UserObject getter was called before UserObjects have been constructed. The "
4701 : "requested UserObject '" +
4702 : name + "' may exist in the input file, but UserObjects are not available yet.");
4703 :
4704 0 : mooseError("Unable to find user object with name '" + name + "'");
4705 : }
4706 : mooseAssert(objs.size() == 1, "Should only find one UO");
4707 570184 : return *(objs[0]);
4708 285092 : }
4709 :
4710 : const Positions &
4711 1141 : FEProblemBase::getPositionsObject(const std::string & name) const
4712 : {
4713 1141 : std::vector<Positions *> objs;
4714 1141 : theWarehouse()
4715 2282 : .query()
4716 1141 : .condition<AttribSystem>("UserObject")
4717 1141 : .condition<AttribName>(name)
4718 1141 : .queryInto(objs);
4719 1141 : if (objs.empty())
4720 0 : mooseError("Unable to find Positions object with name '" + name + "'");
4721 : mooseAssert(objs.size() == 1, "Should only find one Positions");
4722 2282 : return *(objs[0]);
4723 1141 : }
4724 :
4725 : bool
4726 88539 : FEProblemBase::hasUserObject(const std::string & name) const
4727 : {
4728 88539 : std::vector<UserObject *> objs;
4729 88539 : theWarehouse()
4730 88539 : .query()
4731 88539 : .condition<AttribSystem>("UserObject")
4732 177078 : .condition<AttribThread>(0)
4733 88539 : .condition<AttribName>(name)
4734 88539 : .queryInto(objs);
4735 177078 : return !objs.empty();
4736 88539 : }
4737 :
4738 : const FVInterpolationMethod &
4739 571 : FEProblemBase::getFVInterpolationMethod(const InterpolationMethodName & name,
4740 : const THREAD_ID tid) const
4741 : {
4742 571 : std::vector<FVInterpolationMethod *> methods;
4743 571 : theWarehouse()
4744 1142 : .query()
4745 571 : .condition<AttribSystem>("FVInterpolationMethod")
4746 571 : .condition<AttribThread>(tid)
4747 571 : .condition<AttribName>(name)
4748 571 : .queryInto(methods);
4749 :
4750 571 : if (methods.empty())
4751 0 : mooseError("Unable to find FVInterpolationMethod with name '", name, "'");
4752 :
4753 : mooseAssert(methods.size() == 1, "Expected a single FVInterpolationMethod per thread");
4754 1142 : return *(methods[0]);
4755 571 : }
4756 :
4757 : const FVFaceInterpolationMethod &
4758 0 : FEProblemBase::getFVFaceInterpolationMethod(const InterpolationMethodName & name,
4759 : const THREAD_ID tid) const
4760 : {
4761 0 : const auto & method = getFVInterpolationMethod(name, tid);
4762 0 : const auto * face_method = dynamic_cast<const FVFaceInterpolationMethod *>(&method);
4763 :
4764 0 : if (!face_method)
4765 0 : mooseError("FVInterpolationMethod '",
4766 : name,
4767 : "' (",
4768 0 : method.type(),
4769 : ") is not a scalar face interpolation method.");
4770 :
4771 0 : return *face_method;
4772 : }
4773 :
4774 : const FVAdvectedInterpolationMethod &
4775 571 : FEProblemBase::getFVAdvectedInterpolationMethod(const InterpolationMethodName & name,
4776 : const THREAD_ID tid) const
4777 : {
4778 571 : const auto & method = getFVInterpolationMethod(name, tid);
4779 571 : const auto * advected_method = dynamic_cast<const FVAdvectedInterpolationMethod *>(&method);
4780 :
4781 571 : if (!advected_method)
4782 0 : mooseError("FVInterpolationMethod '",
4783 : name,
4784 : "' (",
4785 0 : method.type(),
4786 : ") is not an advected interpolation method.");
4787 :
4788 571 : return *advected_method;
4789 : }
4790 :
4791 : bool
4792 0 : FEProblemBase::hasFVInterpolationMethod(const InterpolationMethodName & name) const
4793 : {
4794 0 : std::vector<FVInterpolationMethod *> methods;
4795 0 : theWarehouse()
4796 0 : .query()
4797 0 : .condition<AttribSystem>("FVInterpolationMethod")
4798 0 : .condition<AttribThread>(0)
4799 0 : .condition<AttribName>(name)
4800 0 : .queryInto(methods);
4801 0 : return !methods.empty();
4802 0 : }
4803 :
4804 : bool
4805 308 : FEProblemBase::hasPostprocessorValueByName(const PostprocessorName & name) const
4806 : {
4807 308 : return _reporter_data.hasReporterValue<PostprocessorValue>(PostprocessorReporterName(name));
4808 : }
4809 :
4810 : const Postprocessor &
4811 2 : FEProblemBase::getPostprocessorObjectByName(const PostprocessorName & object_name,
4812 : const THREAD_ID tid) const
4813 : {
4814 2 : std::vector<Postprocessor *> objs;
4815 2 : theWarehouse()
4816 2 : .query()
4817 4 : .condition<AttribInterfaces>(Interfaces::Postprocessor)
4818 2 : .condition<AttribThread>(tid)
4819 2 : .condition<AttribName>(object_name)
4820 2 : .queryInto(objs);
4821 :
4822 2 : if (objs.empty())
4823 0 : mooseError("Unable to find Postprocessor with name '", object_name, "'");
4824 : mooseAssert(objs.size() == 1,
4825 : "We shouldn't find more than one postprocessor object for a given name");
4826 4 : return *(objs[0]);
4827 2 : }
4828 :
4829 : const PostprocessorValue &
4830 814501 : FEProblemBase::getPostprocessorValueByName(const PostprocessorName & name,
4831 : std::size_t t_index) const
4832 : {
4833 1629002 : return _reporter_data.getReporterValue<PostprocessorValue>(PostprocessorReporterName(name),
4834 1629002 : t_index);
4835 : }
4836 :
4837 : void
4838 566212 : FEProblemBase::setPostprocessorValueByName(const PostprocessorName & name,
4839 : const PostprocessorValue & value,
4840 : std::size_t t_index)
4841 : {
4842 566212 : _reporter_data.setReporterValue<PostprocessorValue>(
4843 1132424 : PostprocessorReporterName(name), value, t_index);
4844 566212 : }
4845 :
4846 : bool
4847 52 : FEProblemBase::hasPostprocessor(const std::string & name) const
4848 : {
4849 52 : mooseDeprecated("FEProblemBase::hasPostprocssor is being removed; use "
4850 : "hasPostprocessorValueByName instead.");
4851 52 : return hasPostprocessorValueByName(name);
4852 : }
4853 :
4854 : const VectorPostprocessorValue &
4855 50 : FEProblemBase::getVectorPostprocessorValueByName(const std::string & object_name,
4856 : const std::string & vector_name,
4857 : std::size_t t_index) const
4858 : {
4859 50 : return _reporter_data.getReporterValue<VectorPostprocessorValue>(
4860 100 : VectorPostprocessorReporterName(object_name, vector_name), t_index);
4861 : }
4862 :
4863 : void
4864 18 : FEProblemBase::setVectorPostprocessorValueByName(const std::string & object_name,
4865 : const std::string & vector_name,
4866 : const VectorPostprocessorValue & value,
4867 : std::size_t t_index)
4868 : {
4869 18 : _reporter_data.setReporterValue<VectorPostprocessorValue>(
4870 36 : VectorPostprocessorReporterName(object_name, vector_name), value, t_index);
4871 18 : }
4872 :
4873 : const VectorPostprocessor &
4874 9655 : FEProblemBase::getVectorPostprocessorObjectByName(const std::string & object_name,
4875 : const THREAD_ID tid) const
4876 : {
4877 9655 : std::vector<VectorPostprocessor *> objs;
4878 9655 : theWarehouse()
4879 9655 : .query()
4880 19310 : .condition<AttribInterfaces>(Interfaces::VectorPostprocessor)
4881 9655 : .condition<AttribThread>(tid)
4882 9655 : .condition<AttribName>(object_name)
4883 9655 : .queryInto(objs);
4884 :
4885 9655 : if (objs.empty())
4886 : {
4887 : mooseAssert(
4888 : getMooseApp().actionWarehouse().isTaskComplete("add_vector_postprocessor"),
4889 : "A VectorPostprocessor getter was called before VectorPostprocessors have been "
4890 : "constructed. The requested VectorPostprocessor '" +
4891 : object_name +
4892 : "' may exist in the input file, but VectorPostprocessors are not available yet.");
4893 :
4894 0 : mooseError("Unable to find VectorPostprocessor with name '", object_name, "'");
4895 : }
4896 : mooseAssert(objs.size() == 1,
4897 : "We shouldn't find more than one vector postprocessor object for a given name");
4898 19310 : return *(objs[0]);
4899 9655 : }
4900 :
4901 : void
4902 70 : FEProblemBase::parentOutputPositionChanged()
4903 : {
4904 1960 : for (const auto & it : _multi_apps)
4905 : {
4906 1890 : const auto & objects = it.second.getActiveObjects();
4907 1909 : for (const auto & obj : objects)
4908 19 : obj->parentOutputPositionChanged();
4909 : }
4910 70 : }
4911 :
4912 : void
4913 0 : FEProblemBase::computeIndicatorsAndMarkers()
4914 : {
4915 0 : computeIndicators();
4916 0 : computeMarkers();
4917 0 : }
4918 :
4919 : void
4920 220601 : FEProblemBase::computeIndicators()
4921 : {
4922 : // Initialize indicator aux variable fields
4923 220601 : if (_indicators.hasActiveObjects() || _internal_side_indicators.hasActiveObjects())
4924 : {
4925 11875 : TIME_SECTION("computeIndicators", 1, "Computing Indicators");
4926 :
4927 : // Internal side indicators may lead to creating a much larger sparsity pattern than dictated by
4928 : // the actual finite element scheme (e.g. CFEM)
4929 2375 : const auto old_do_derivatives = ADReal::do_derivatives;
4930 2375 : ADReal::do_derivatives = false;
4931 :
4932 2375 : std::vector<std::string> fields;
4933 :
4934 : // Indicator Fields
4935 2375 : const auto & indicators = _indicators.getActiveObjects();
4936 2521 : for (const auto & indicator : indicators)
4937 146 : fields.push_back(indicator->name());
4938 :
4939 : // InternalSideIndicator Fields
4940 2375 : const auto & internal_indicators = _internal_side_indicators.getActiveObjects();
4941 4706 : for (const auto & internal_indicator : internal_indicators)
4942 2331 : fields.push_back(internal_indicator->name());
4943 :
4944 2375 : _aux->zeroVariables(fields);
4945 :
4946 : // compute Indicators
4947 2375 : ComputeIndicatorThread cit(*this);
4948 2375 : Threads::parallel_reduce(getCurrentAlgebraicElementRange(), cit);
4949 2375 : _aux->solution().close();
4950 2375 : _aux->update();
4951 :
4952 2375 : ComputeIndicatorThread finalize_cit(*this, true);
4953 2375 : Threads::parallel_reduce(getCurrentAlgebraicElementRange(), finalize_cit);
4954 2375 : _aux->solution().close();
4955 2375 : _aux->update();
4956 :
4957 2375 : ADReal::do_derivatives = old_do_derivatives;
4958 2375 : }
4959 220601 : }
4960 :
4961 : void
4962 220623 : FEProblemBase::computeMarkers()
4963 : {
4964 220623 : if (_markers.hasActiveObjects())
4965 : {
4966 32385 : TIME_SECTION("computeMarkers", 1, "Computing Markers");
4967 :
4968 6477 : std::vector<std::string> fields;
4969 :
4970 : // Marker Fields
4971 6477 : const auto & markers = _markers.getActiveObjects();
4972 13933 : for (const auto & marker : markers)
4973 7456 : fields.push_back(marker->name());
4974 :
4975 6477 : _aux->zeroVariables(fields);
4976 :
4977 6477 : _adaptivity.updateErrorVectors();
4978 :
4979 13579 : for (THREAD_ID tid = 0; tid < libMesh::n_threads(); ++tid)
4980 : {
4981 7105 : const auto & markers = _markers.getActiveObjects(tid);
4982 15281 : for (const auto & marker : markers)
4983 8179 : marker->markerSetup();
4984 : }
4985 :
4986 6474 : ComputeMarkerThread cmt(*this);
4987 6474 : Threads::parallel_reduce(getCurrentAlgebraicElementRange(), cmt);
4988 :
4989 6474 : _aux->solution().close();
4990 6474 : _aux->update();
4991 6474 : }
4992 220620 : }
4993 :
4994 : const ExecFlagType &
4995 4957792 : FEProblemBase::getCurrentExecuteOnFlag() const
4996 : {
4997 4957792 : return _current_execute_on_flag;
4998 : }
4999 :
5000 : void
5001 6903978 : FEProblemBase::setCurrentExecuteOnFlag(const ExecFlagType & flag)
5002 : {
5003 6903978 : _current_execute_on_flag = flag;
5004 6903978 : }
5005 :
5006 : void
5007 72 : FEProblemBase::executeAllObjects(const ExecFlagType & /*exec_type*/)
5008 : {
5009 72 : }
5010 :
5011 : void
5012 1760901 : FEProblemBase::customSetup(const ExecFlagType & exec_type)
5013 : {
5014 1760901 : SubProblem::customSetup(exec_type);
5015 :
5016 1760901 : if (_line_search)
5017 0 : _line_search->customSetup(exec_type);
5018 :
5019 1760901 : unsigned int n_threads = libMesh::n_threads();
5020 3698212 : for (THREAD_ID tid = 0; tid < n_threads; tid++)
5021 : {
5022 1937311 : _all_materials.customSetup(exec_type, tid);
5023 1937311 : _functions.customSetup(exec_type, tid);
5024 : }
5025 :
5026 : #ifdef MOOSE_KOKKOS_ENABLED
5027 1289210 : _kokkos_functions.customSetup(exec_type);
5028 : #endif
5029 :
5030 1760901 : _aux->customSetup(exec_type);
5031 3548599 : for (auto & nl : _nl)
5032 1787698 : nl->customSetup(exec_type);
5033 :
5034 1760901 : if (_displaced_problem)
5035 145157 : _displaced_problem->customSetup(exec_type);
5036 :
5037 3698212 : for (THREAD_ID tid = 0; tid < n_threads; tid++)
5038 : {
5039 1937311 : _internal_side_indicators.customSetup(exec_type, tid);
5040 1937311 : _indicators.customSetup(exec_type, tid);
5041 1937311 : _markers.customSetup(exec_type, tid);
5042 : }
5043 :
5044 1760901 : std::vector<UserObject *> userobjs;
5045 1760901 : theWarehouse().query().condition<AttribSystem>("UserObject").queryIntoUnsorted(userobjs);
5046 4330428 : for (auto obj : userobjs)
5047 2569527 : obj->customSetup(exec_type);
5048 :
5049 : #ifdef MOOSE_KOKKOS_ENABLED
5050 : {
5051 1289210 : std::vector<UserObjectBase *> userobjs;
5052 1289210 : theWarehouse().query().condition<AttribSystem>("KokkosUserObject").queryIntoUnsorted(userobjs);
5053 1302653 : for (auto obj : userobjs)
5054 13443 : obj->customSetup(exec_type);
5055 1289210 : }
5056 : #endif
5057 :
5058 1760901 : _app.getOutputWarehouse().customSetup(exec_type);
5059 1760901 : }
5060 :
5061 : void
5062 2129254 : FEProblemBase::execute(const ExecFlagType & exec_type)
5063 : {
5064 : // Set the current flag
5065 2129254 : setCurrentExecuteOnFlag(exec_type);
5066 :
5067 2129254 : if (exec_type != EXEC_INITIAL)
5068 2074320 : executeControls(exec_type);
5069 :
5070 : // intentially call this after executing controls because the setups may rely on the controls
5071 : // FIXME: we skip the following flags because they have dedicated setup functions in
5072 : // SetupInterface and it may not be appropriate to call them here.
5073 3892608 : if (!(exec_type == EXEC_INITIAL || exec_type == EXEC_TIMESTEP_BEGIN ||
5074 1763372 : exec_type == EXEC_SUBDOMAIN || exec_type == EXEC_NONLINEAR || exec_type == EXEC_LINEAR))
5075 1760901 : customSetup(exec_type);
5076 :
5077 2129236 : executeSamplers(exec_type);
5078 :
5079 : // Pre-aux UserObjects
5080 2129212 : computeUserObjects(exec_type, Moose::PRE_AUX);
5081 :
5082 : // Systems (includes system time derivative and aux kernel calculations)
5083 2129212 : computeSystems(exec_type);
5084 : // With the auxiliary system solution computed, sync the displaced problem auxiliary solution
5085 : // before computation of post-aux user objects. The undisplaced auxiliary system current local
5086 : // solution is updated (via System::update) within the AuxiliarySystem class's variable
5087 : // computation methods (e.g. computeElementalVarsHelper, computeNodalVarsHelper), so it is safe to
5088 : // use it here
5089 2129179 : if (_displaced_problem)
5090 179606 : _displaced_problem->syncAuxSolution(*getAuxiliarySystem().currentSolution());
5091 :
5092 : // Post-aux UserObjects
5093 2129179 : computeUserObjects(exec_type, Moose::POST_AUX);
5094 :
5095 : // Return the current flag to None
5096 2129093 : setCurrentExecuteOnFlag(EXEC_NONE);
5097 :
5098 2129093 : if (_uo_aux_state_check && !_checking_uo_aux_state)
5099 : {
5100 : // we will only check aux variables and postprocessors
5101 : // checking more reporter data can be added in the future if needed
5102 559 : std::unique_ptr<NumericVector<Number>> x = _aux->currentSolution()->clone();
5103 559 : DenseVector<Real> pp_values = getReporterData().getAllRealReporterValues();
5104 :
5105 : // call THIS execute one more time for checking the possible states
5106 559 : _checking_uo_aux_state = true;
5107 559 : FEProblemBase::execute(exec_type);
5108 559 : _checking_uo_aux_state = false;
5109 :
5110 559 : const Real check_tol = 1e-8;
5111 :
5112 559 : const Real xnorm = x->l2_norm();
5113 559 : *x -= *_aux->currentSolution();
5114 559 : if (x->l2_norm() > check_tol * xnorm)
5115 : {
5116 3 : const auto & sys = _aux->system();
5117 3 : const unsigned int n_vars = sys.n_vars();
5118 3 : std::multimap<Real, std::string, std::greater<Real>> ordered_map;
5119 15 : for (const auto i : make_range(n_vars))
5120 : {
5121 12 : const Real vnorm = sys.calculate_norm(*x, i, DISCRETE_L2);
5122 12 : ordered_map.emplace(vnorm, sys.variable_name(i));
5123 : }
5124 :
5125 3 : std::ostringstream oss;
5126 15 : for (const auto & [error_norm, var_name] : ordered_map)
5127 12 : oss << " {" << var_name << ", " << error_norm << "},\n";
5128 :
5129 3 : mooseError("Aux kernels, user objects appear to have states for aux variables on ",
5130 : exec_type,
5131 : ".\nVariable error norms in descending order:\n",
5132 3 : oss.str());
5133 0 : }
5134 :
5135 556 : const DenseVector<Real> new_pp_values = getReporterData().getAllRealReporterValues();
5136 556 : if (pp_values.size() != new_pp_values.size())
5137 0 : mooseError("Second execution for uo/aux state check should not change the number of "
5138 : "real reporter values");
5139 :
5140 556 : const Real ppnorm = pp_values.l2_norm();
5141 556 : pp_values -= new_pp_values;
5142 556 : if (pp_values.l2_norm() > check_tol * ppnorm)
5143 : {
5144 3 : const auto pp_names = getReporterData().getAllRealReporterFullNames();
5145 3 : std::multimap<Real, std::string, std::greater<Real>> ordered_map;
5146 12 : for (const auto i : index_range(pp_names))
5147 9 : ordered_map.emplace(std::abs(pp_values(i)), pp_names[i]);
5148 :
5149 3 : std::ostringstream oss;
5150 12 : for (const auto & [error_norm, pp_name] : ordered_map)
5151 9 : oss << " {" << pp_name << ", " << error_norm << "},\n";
5152 :
5153 3 : mooseError("Aux kernels, user objects appear to have states for real reporter values on ",
5154 : exec_type,
5155 : ".\nErrors of real reporter values in descending order:\n",
5156 3 : oss.str());
5157 0 : }
5158 553 : }
5159 2129087 : }
5160 :
5161 : // Finalize, threadJoin, and update PP values of Elemental/Nodal/Side/InternalSideUserObjects
5162 : void
5163 1331801 : FEProblemBase::joinAndFinalize(TheWarehouse::Query query, bool isgen)
5164 : {
5165 1331801 : std::vector<UserObject *> objs;
5166 1331801 : query.queryInto(objs);
5167 1331801 : if (!isgen)
5168 : {
5169 : // join all threaded user objects (i.e. not regular general user objects) to the primary
5170 : // thread
5171 1415191 : for (auto obj : objs)
5172 368994 : if (obj->primaryThreadCopy())
5173 30647 : obj->primaryThreadCopy()->threadJoin(*obj);
5174 : }
5175 :
5176 1331801 : query.condition<AttribThread>(0).queryInto(objs);
5177 :
5178 : // finalize objects and retrieve/store any postprocessor values
5179 1891315 : for (auto obj : objs)
5180 : {
5181 559594 : if (isgen && dynamic_cast<ThreadedGeneralUserObject *>(obj))
5182 133 : continue;
5183 559461 : if (isgen)
5184 : {
5185 : // general user objects are not run in their own threaded loop object - so run them here
5186 221114 : if (shouldPrintExecution(0))
5187 724 : _console << "[DBG] Initializing, executing & finalizing general UO '" << obj->name()
5188 724 : << "' on " << _current_execute_on_flag.name() << std::endl;
5189 221114 : obj->initialize();
5190 221114 : obj->execute();
5191 : }
5192 :
5193 559411 : obj->finalize();
5194 :
5195 : // These have to be stored piecemeal (with every call to this function) because general
5196 : // postprocessors (which run last after other userobjects have been completed) might depend on
5197 : // them being stored. This wouldn't be a problem if all userobjects satisfied the dependency
5198 : // resolver interface and could be sorted appropriately with the general userobjects, but they
5199 : // don't.
5200 559396 : auto pp = dynamic_cast<const Postprocessor *>(obj);
5201 559396 : if (pp)
5202 : {
5203 490334 : _reporter_data.finalize(obj->name());
5204 490334 : setPostprocessorValueByName(obj->name(), pp->getValue());
5205 : }
5206 :
5207 559387 : auto vpp = dynamic_cast<VectorPostprocessor *>(obj);
5208 559387 : if (vpp)
5209 13514 : _reporter_data.finalize(obj->name());
5210 :
5211 : // Update Reporter data
5212 559387 : auto reporter = dynamic_cast<Reporter *>(obj);
5213 559387 : if (reporter)
5214 5061 : _reporter_data.finalize(obj->name());
5215 : }
5216 1331721 : }
5217 :
5218 : TheWarehouse::Query
5219 19823908 : FEProblemBase::getUOQuery(const std::string & system,
5220 : const ExecFlagType & type,
5221 : const Moose::AuxGroup & group) const
5222 : {
5223 : TheWarehouse::Query query =
5224 19823908 : theWarehouse().query().condition<AttribSystem>(system).condition<AttribExecOns>(type);
5225 :
5226 19823908 : if (group == Moose::PRE_IC)
5227 95566 : query.condition<AttribPreIC>(true);
5228 19728342 : else if (group == Moose::PRE_AUX)
5229 9863792 : query.condition<AttribPreAux>(type);
5230 9864550 : else if (group == Moose::POST_AUX)
5231 9864482 : query.condition<AttribPostAux>(type);
5232 :
5233 19823908 : return query;
5234 0 : }
5235 :
5236 : void
5237 19823908 : FEProblemBase::getUOExecutionGroups(TheWarehouse::Query & query,
5238 : std::set<int> & execution_groups) const
5239 : {
5240 19823908 : std::vector<UserObjectBase *> uos;
5241 19823908 : query.queryIntoUnsorted(uos);
5242 20416573 : for (const auto & uo : uos)
5243 1777995 : execution_groups.insert(uo->getParam<int>("execution_order_group"));
5244 19823908 : }
5245 :
5246 : void
5247 55071 : FEProblemBase::computeUserObjectByName(const ExecFlagType & type,
5248 : const Moose::AuxGroup & group,
5249 : const std::string & name)
5250 : {
5251 55071 : const auto old_exec_flag = _current_execute_on_flag;
5252 55071 : _current_execute_on_flag = type;
5253 :
5254 55071 : std::set<int> execution_groups;
5255 :
5256 : #ifdef MOOSE_KOKKOS_ENABLED
5257 : TheWarehouse::Query kokkos_query =
5258 39698 : getUOQuery("KokkosUserObject", type, group).condition<AttribName>(name);
5259 39698 : getUOExecutionGroups(kokkos_query, execution_groups);
5260 : #endif
5261 :
5262 55071 : TheWarehouse::Query query = getUOQuery("UserObject", type, group).condition<AttribName>(name);
5263 55071 : getUOExecutionGroups(query, execution_groups);
5264 :
5265 81022 : for (const auto execution_group : execution_groups)
5266 : {
5267 : #ifdef MOOSE_KOKKOS_ENABLED
5268 18721 : computeKokkosUserObjectsInternal(
5269 18721 : type, kokkos_query.clone().condition<AttribExecutionOrderGroup>(execution_group));
5270 : #endif
5271 :
5272 25951 : computeUserObjectsInternal(type,
5273 25951 : query.clone().condition<AttribExecutionOrderGroup>(execution_group));
5274 : }
5275 :
5276 55071 : _current_execute_on_flag = old_exec_flag;
5277 55071 : }
5278 :
5279 : void
5280 11408555 : FEProblemBase::computeUserObjects(const ExecFlagType & type, const Moose::AuxGroup & group)
5281 : {
5282 11408555 : std::set<int> execution_groups;
5283 :
5284 : #ifdef MOOSE_KOKKOS_ENABLED
5285 8320584 : TheWarehouse::Query kokkos_query = getUOQuery("KokkosUserObject", type, group);
5286 8320584 : getUOExecutionGroups(kokkos_query, execution_groups);
5287 : #endif
5288 :
5289 11408555 : TheWarehouse::Query query = getUOQuery("UserObject", type, group);
5290 11408555 : getUOExecutionGroups(query, execution_groups);
5291 :
5292 11669844 : for (const auto execution_group : execution_groups)
5293 : {
5294 : #ifdef MOOSE_KOKKOS_ENABLED
5295 190670 : computeKokkosUserObjectsInternal(
5296 190670 : type, kokkos_query.clone().condition<AttribExecutionOrderGroup>(execution_group));
5297 : #endif
5298 :
5299 261375 : computeUserObjectsInternal(type,
5300 261375 : query.clone().condition<AttribExecutionOrderGroup>(execution_group));
5301 : }
5302 11408469 : }
5303 :
5304 : void
5305 287326 : FEProblemBase::computeUserObjectsInternal(const ExecFlagType & type, TheWarehouse::Query & query)
5306 : {
5307 : try
5308 : {
5309 1436630 : TIME_SECTION("computeUserObjects", 1, "Computing User Objects");
5310 :
5311 287326 : std::vector<GeneralUserObject *> genobjs;
5312 287326 : query.clone().condition<AttribInterfaces>(Interfaces::GeneralUserObject).queryInto(genobjs);
5313 :
5314 287326 : std::vector<UserObject *> userobjs;
5315 287326 : query.clone()
5316 574652 : .condition<AttribInterfaces>(Interfaces::ElementUserObject | Interfaces::SideUserObject |
5317 : Interfaces::InternalSideUserObject |
5318 574652 : Interfaces::InterfaceUserObject | Interfaces::DomainUserObject)
5319 287326 : .queryInto(userobjs);
5320 :
5321 287326 : std::vector<UserObject *> tgobjs;
5322 287326 : query.clone()
5323 574652 : .condition<AttribInterfaces>(Interfaces::ThreadedGeneralUserObject)
5324 287326 : .queryInto(tgobjs);
5325 :
5326 287326 : std::vector<UserObject *> nodal;
5327 287326 : query.clone().condition<AttribInterfaces>(Interfaces::NodalUserObject).queryInto(nodal);
5328 :
5329 287326 : std::vector<MortarUserObject *> mortar;
5330 287326 : query.clone().condition<AttribInterfaces>(Interfaces::MortarUserObject).queryInto(mortar);
5331 :
5332 287326 : if (userobjs.empty() && genobjs.empty() && tgobjs.empty() && nodal.empty() && mortar.empty())
5333 1710 : return;
5334 :
5335 : // Start the timer here since we have at least one active user object
5336 285616 : std::string compute_uo_tag = "computeUserObjects(" + Moose::stringify(type) + ")";
5337 :
5338 : // Perform Residual/Jacobian setups
5339 285616 : if (type == EXEC_LINEAR)
5340 : {
5341 124318 : for (auto obj : userobjs)
5342 70719 : obj->residualSetup();
5343 58057 : for (auto obj : nodal)
5344 4458 : obj->residualSetup();
5345 53599 : for (auto obj : mortar)
5346 0 : obj->residualSetup();
5347 53608 : for (auto obj : tgobjs)
5348 9 : obj->residualSetup();
5349 64993 : for (auto obj : genobjs)
5350 11394 : obj->residualSetup();
5351 : }
5352 232017 : else if (type == EXEC_NONLINEAR)
5353 : {
5354 13576 : for (auto obj : userobjs)
5355 4076 : obj->jacobianSetup();
5356 9892 : for (auto obj : nodal)
5357 392 : obj->jacobianSetup();
5358 9500 : for (auto obj : mortar)
5359 0 : obj->jacobianSetup();
5360 9503 : for (auto obj : tgobjs)
5361 3 : obj->jacobianSetup();
5362 26145 : for (auto obj : genobjs)
5363 16645 : obj->jacobianSetup();
5364 : }
5365 :
5366 633895 : for (auto obj : userobjs)
5367 348279 : obj->initialize();
5368 :
5369 : // Execute Side/InternalSide/Interface/Elemental/DomainUserObjects
5370 285616 : if (!userobjs.empty())
5371 : {
5372 : // non-nodal user objects have to be run separately before the nodal user objects run
5373 : // because some nodal user objects (NodalNormal related) depend on elemental user objects
5374 : // :-(
5375 205946 : ComputeUserObjectsThread cppt(*this, query);
5376 205946 : Threads::parallel_reduce(getCurrentAlgebraicElementRange(), cppt);
5377 :
5378 : // There is one instance in rattlesnake where an elemental user object's finalize depends
5379 : // on a side user object having been finalized first :-(
5380 205940 : joinAndFinalize(query.clone().condition<AttribInterfaces>(Interfaces::SideUserObject));
5381 205937 : joinAndFinalize(
5382 411874 : query.clone().condition<AttribInterfaces>(Interfaces::InternalSideUserObject));
5383 205937 : joinAndFinalize(query.clone().condition<AttribInterfaces>(Interfaces::InterfaceUserObject));
5384 205937 : joinAndFinalize(query.clone().condition<AttribInterfaces>(Interfaces::ElementUserObject));
5385 205934 : joinAndFinalize(query.clone().condition<AttribInterfaces>(Interfaces::DomainUserObject));
5386 205934 : }
5387 :
5388 : // if any elemental user object may have written to variables we need to close the aux solution
5389 633795 : for (const auto & uo : userobjs)
5390 348224 : if (auto euo = dynamic_cast<const ElementUserObject *>(uo);
5391 348224 : euo && euo->hasWritableCoupledVariables())
5392 : {
5393 33 : _aux->solution().close();
5394 33 : _aux->system().update();
5395 33 : break;
5396 : }
5397 :
5398 : // Execute NodalUserObjects
5399 : // BISON has an axial reloc elemental user object that has a finalize func that depends on a
5400 : // nodal user object's prev value. So we can't initialize this until after elemental objects
5401 : // have been finalized :-(
5402 305910 : for (auto obj : nodal)
5403 20306 : obj->initialize();
5404 285604 : if (query.clone().condition<AttribInterfaces>(Interfaces::NodalUserObject).count() > 0)
5405 : {
5406 16379 : ComputeNodalUserObjectsThread cnppt(*this, query);
5407 16379 : Threads::parallel_reduce(getCurrentAlgebraicNodeRange(), cnppt);
5408 16379 : joinAndFinalize(query.clone().condition<AttribInterfaces>(Interfaces::NodalUserObject));
5409 16379 : }
5410 :
5411 : // if any nodal user object may have written to variables we need to close the aux solution
5412 305874 : for (const auto & uo : nodal)
5413 20292 : if (auto nuo = dynamic_cast<const NodalUserObject *>(uo);
5414 20292 : nuo && nuo->hasWritableCoupledVariables())
5415 : {
5416 22 : _aux->solution().close();
5417 22 : _aux->system().update();
5418 22 : break;
5419 : }
5420 :
5421 : // Execute MortarUserObjects
5422 : {
5423 285626 : for (auto obj : mortar)
5424 22 : obj->initialize();
5425 285604 : if (!mortar.empty())
5426 : {
5427 33 : auto create_and_run_mortar_functors = [this, type, &mortar](const bool displaced)
5428 : {
5429 : // go over mortar interfaces and construct functors
5430 33 : const auto & mortar_interfaces = getMortarInterfaces(displaced);
5431 55 : for (const auto & [primary_secondary_boundary_pair, mortar_generation_ptr] :
5432 88 : mortar_interfaces)
5433 : {
5434 : auto mortar_uos_to_execute =
5435 22 : getMortarUserObjects(primary_secondary_boundary_pair.first,
5436 22 : primary_secondary_boundary_pair.second,
5437 : displaced,
5438 22 : mortar);
5439 :
5440 : auto * const subproblem = displaced
5441 22 : ? static_cast<SubProblem *>(_displaced_problem.get())
5442 22 : : static_cast<SubProblem *>(this);
5443 : MortarUserObjectThread muot(mortar_uos_to_execute,
5444 22 : *mortar_generation_ptr,
5445 : *subproblem,
5446 : *this,
5447 : displaced,
5448 22 : subproblem->assembly(0, 0));
5449 :
5450 22 : muot();
5451 22 : }
5452 55 : };
5453 :
5454 22 : create_and_run_mortar_functors(false);
5455 22 : if (_displaced_problem)
5456 11 : create_and_run_mortar_functors(true);
5457 22 : }
5458 285626 : for (auto obj : mortar)
5459 22 : obj->finalize();
5460 : }
5461 :
5462 : // Execute threaded general user objects
5463 286045 : for (auto obj : tgobjs)
5464 441 : obj->initialize();
5465 285604 : std::vector<GeneralUserObject *> tguos_zero;
5466 285604 : query.clone()
5467 285604 : .condition<AttribThread>(0)
5468 571208 : .condition<AttribInterfaces>(Interfaces::ThreadedGeneralUserObject)
5469 285604 : .queryInto(tguos_zero);
5470 285737 : for (auto obj : tguos_zero)
5471 : {
5472 133 : std::vector<GeneralUserObject *> tguos;
5473 133 : auto q = query.clone()
5474 133 : .condition<AttribName>(obj->name())
5475 133 : .condition<AttribInterfaces>(Interfaces::ThreadedGeneralUserObject);
5476 133 : q.queryInto(tguos);
5477 :
5478 133 : ComputeThreadedGeneralUserObjectsThread ctguot(*this);
5479 133 : Threads::parallel_reduce(GeneralUserObjectRange(tguos.begin(), tguos.end()), ctguot);
5480 133 : joinAndFinalize(q);
5481 133 : }
5482 :
5483 : // Execute general user objects
5484 285604 : joinAndFinalize(query.clone().condition<AttribInterfaces>(Interfaces::GeneralUserObject), true);
5485 295790 : }
5486 0 : catch (...)
5487 : {
5488 0 : handleException("computeUserObjectsInternal");
5489 0 : }
5490 : }
5491 :
5492 : void
5493 5680862 : FEProblemBase::executeControls(const ExecFlagType & exec_type)
5494 : {
5495 5680862 : if (_control_warehouse[exec_type].hasActiveObjects())
5496 : {
5497 38765 : TIME_SECTION("executeControls", 1, "Executing Controls");
5498 :
5499 7753 : DependencyResolver<std::shared_ptr<Control>> resolver;
5500 :
5501 7753 : auto controls_wh = _control_warehouse[exec_type];
5502 : // Add all of the dependencies into the resolver and sort them
5503 19427 : for (const auto & it : controls_wh.getActiveObjects())
5504 : {
5505 : // Make sure an item with no dependencies comes out too!
5506 11677 : resolver.addItem(it);
5507 :
5508 11677 : std::vector<std::string> & dependent_controls = it->getDependencies();
5509 14569 : for (const auto & depend_name : dependent_controls)
5510 : {
5511 2895 : if (controls_wh.hasActiveObject(depend_name))
5512 : {
5513 2892 : auto dep_control = controls_wh.getActiveObject(depend_name);
5514 2892 : resolver.addEdge(dep_control, it);
5515 2892 : }
5516 : else
5517 3 : mooseError("The Control \"",
5518 : depend_name,
5519 : "\" was not created, did you make a "
5520 : "spelling mistake or forget to include it "
5521 : "in your input file?");
5522 : }
5523 : }
5524 :
5525 7750 : const auto & ordered_controls = resolver.getSortedValues();
5526 :
5527 7750 : if (!ordered_controls.empty())
5528 : {
5529 : // already called by initialSetup when exec_type == EXEC_INITIAL
5530 7750 : if (exec_type != EXEC_INITIAL)
5531 6878 : _control_warehouse.setup(exec_type);
5532 :
5533 : // Run the controls in the proper order
5534 19382 : for (const auto & control : ordered_controls)
5535 11674 : control->execute();
5536 : }
5537 7708 : }
5538 5680817 : }
5539 :
5540 : void
5541 2129236 : FEProblemBase::executeSamplers(const ExecFlagType & exec_type)
5542 : {
5543 : // TODO: This should be done in a threaded loop, but this should be super quick so for now
5544 : // do a serial loop.
5545 4471467 : for (THREAD_ID tid = 0; tid < libMesh::n_threads(); ++tid)
5546 : {
5547 2342255 : std::vector<Sampler *> objects;
5548 2342255 : theWarehouse()
5549 4684510 : .query()
5550 2342255 : .condition<AttribSystem>("Sampler")
5551 2342255 : .condition<AttribThread>(tid)
5552 2342255 : .condition<AttribExecOns>(exec_type)
5553 2342255 : .queryInto(objects);
5554 :
5555 2342255 : if (!objects.empty())
5556 : {
5557 1475 : TIME_SECTION("executeSamplers", 1, "Executing Samplers");
5558 295 : FEProblemBase::objectSetupHelper<Sampler>(objects, exec_type);
5559 295 : FEProblemBase::objectExecuteHelper<Sampler>(objects);
5560 271 : }
5561 2342231 : }
5562 2129212 : }
5563 :
5564 : void
5565 310917 : FEProblemBase::updateActiveObjects()
5566 : {
5567 1554585 : TIME_SECTION("updateActiveObjects", 5, "Updating Active Objects");
5568 :
5569 652404 : for (THREAD_ID tid = 0; tid < libMesh::n_threads(); ++tid)
5570 : {
5571 685490 : for (auto & nl : _nl)
5572 344003 : nl->updateActive(tid);
5573 341487 : _aux->updateActive(tid);
5574 341487 : _indicators.updateActive(tid);
5575 341487 : _internal_side_indicators.updateActive(tid);
5576 341487 : _markers.updateActive(tid);
5577 341487 : _all_materials.updateActive(tid);
5578 341487 : _materials.updateActive(tid);
5579 341487 : _discrete_materials.updateActive(tid);
5580 : }
5581 :
5582 310917 : _control_warehouse.updateActive();
5583 310917 : _multi_apps.updateActive();
5584 310917 : _transient_multi_apps.updateActive();
5585 310917 : _transfers.updateActive();
5586 310917 : _to_multi_app_transfers.updateActive();
5587 310917 : _from_multi_app_transfers.updateActive();
5588 310917 : _between_multi_app_transfers.updateActive();
5589 :
5590 : #ifdef MOOSE_KOKKOS_ENABLED
5591 227482 : _kokkos_materials.updateActive();
5592 : #endif
5593 310917 : }
5594 :
5595 : void
5596 0 : FEProblemBase::reportMooseObjectDependency(MooseObject * /*a*/, MooseObject * /*b*/)
5597 : {
5598 : //<< "Object " << a->name() << " -> " << b->name() << std::endl;
5599 0 : }
5600 :
5601 : void
5602 66972 : FEProblemBase::reinitBecauseOfGhostingOrNewGeomObjects(const bool mortar_changed)
5603 : {
5604 334860 : TIME_SECTION("reinitBecauseOfGhostingOrNewGeomObjects",
5605 : 3,
5606 : "Reinitializing Because of Geometric Search Objects");
5607 :
5608 : // Need to see if _any_ processor has ghosted elems or geometry objects.
5609 66972 : bool needs_reinit = !_ghosted_elems.empty();
5610 133474 : needs_reinit = needs_reinit || !_geometric_search_data._nearest_node_locators.empty() ||
5611 66502 : (_mortar_data->hasObjects() && mortar_changed);
5612 66972 : needs_reinit =
5613 135173 : needs_reinit || (_displaced_problem &&
5614 4423 : (!_displaced_problem->geomSearchData()._nearest_node_locators.empty() ||
5615 67680 : (_mortar_data->hasDisplacedObjects() && mortar_changed)));
5616 66972 : _communicator.max(needs_reinit);
5617 :
5618 66972 : if (needs_reinit)
5619 : {
5620 : // Call reinit to get the ghosted vectors correct now that some geometric search has been done
5621 2175 : es().reinit();
5622 :
5623 2175 : if (_displaced_mesh)
5624 1607 : _displaced_problem->es().reinit();
5625 : }
5626 66972 : }
5627 :
5628 : void
5629 177 : FEProblemBase::addDamper(const std::string & damper_name,
5630 : const std::string & name,
5631 : InputParameters & parameters)
5632 : {
5633 : parallel_object_only();
5634 :
5635 : const auto nl_sys_num =
5636 177 : parameters.isParamValid("variable")
5637 588 : ? determineSolverSystem(parameters.varName("variable", name), true).second
5638 174 : : (unsigned int)0;
5639 :
5640 174 : if (!isSolverSystemNonlinear(nl_sys_num))
5641 0 : mooseError("You are trying to add a DGKernel to a linear variable/system, which is not "
5642 : "supported at the moment!");
5643 :
5644 348 : parameters.set<SubProblem *>("_subproblem") = this;
5645 348 : parameters.set<SystemBase *>("_sys") = _nl[nl_sys_num].get();
5646 :
5647 174 : _has_dampers = true;
5648 174 : logAdd("Damper", name, damper_name, parameters);
5649 174 : _nl[nl_sys_num]->addDamper(damper_name, name, parameters);
5650 174 : }
5651 :
5652 : void
5653 162 : FEProblemBase::setupDampers()
5654 : {
5655 324 : for (auto & nl : _nl)
5656 162 : nl->setupDampers();
5657 162 : }
5658 :
5659 : void
5660 659 : FEProblemBase::addIndicator(const std::string & indicator_name,
5661 : const std::string & name,
5662 : InputParameters & parameters)
5663 : {
5664 : parallel_object_only();
5665 :
5666 659 : if (_displaced_problem && parameters.get<bool>("use_displaced_mesh"))
5667 : {
5668 0 : parameters.set<SubProblem *>("_subproblem") = _displaced_problem.get();
5669 0 : parameters.set<SystemBase *>("_sys") = &_displaced_problem->auxSys();
5670 0 : _reinit_displaced_elem = true;
5671 : }
5672 : else
5673 : {
5674 659 : if (_displaced_problem == nullptr && parameters.get<bool>("use_displaced_mesh"))
5675 : {
5676 : // We allow Indicators to request that they use_displaced_mesh,
5677 : // but then be overridden when no displacements variables are
5678 : // provided in the Mesh block. If that happened, update the value
5679 : // of use_displaced_mesh appropriately for this Indicator.
5680 0 : if (parameters.have_parameter<bool>("use_displaced_mesh"))
5681 0 : parameters.set<bool>("use_displaced_mesh") = false;
5682 : }
5683 :
5684 1318 : parameters.set<SubProblem *>("_subproblem") = this;
5685 1977 : parameters.set<SystemBase *>("_sys") = _aux.get();
5686 : }
5687 :
5688 1382 : for (THREAD_ID tid = 0; tid < libMesh::n_threads(); tid++)
5689 : {
5690 : std::shared_ptr<Indicator> indicator =
5691 723 : _factory.create<Indicator>(indicator_name, name, parameters, tid);
5692 723 : logAdd("Indicator", name, indicator_name, parameters);
5693 : std::shared_ptr<InternalSideIndicatorBase> isi =
5694 723 : std::dynamic_pointer_cast<InternalSideIndicatorBase>(indicator);
5695 723 : if (isi)
5696 622 : _internal_side_indicators.addObject(isi, tid);
5697 : else
5698 101 : _indicators.addObject(indicator, tid);
5699 723 : }
5700 659 : }
5701 :
5702 : void
5703 1950 : FEProblemBase::addMarker(const std::string & marker_name,
5704 : const std::string & name,
5705 : InputParameters & parameters)
5706 : {
5707 : parallel_object_only();
5708 :
5709 1950 : if (_displaced_problem && parameters.get<bool>("use_displaced_mesh"))
5710 : {
5711 0 : parameters.set<SubProblem *>("_subproblem") = _displaced_problem.get();
5712 0 : parameters.set<SystemBase *>("_sys") = &_displaced_problem->auxSys();
5713 0 : _reinit_displaced_elem = true;
5714 : }
5715 : else
5716 : {
5717 1950 : if (_displaced_problem == nullptr && parameters.get<bool>("use_displaced_mesh"))
5718 : {
5719 : // We allow Markers to request that they use_displaced_mesh,
5720 : // but then be overridden when no displacements variables are
5721 : // provided in the Mesh block. If that happened, update the value
5722 : // of use_displaced_mesh appropriately for this Marker.
5723 0 : if (parameters.have_parameter<bool>("use_displaced_mesh"))
5724 0 : parameters.set<bool>("use_displaced_mesh") = false;
5725 : }
5726 :
5727 3900 : parameters.set<SubProblem *>("_subproblem") = this;
5728 5850 : parameters.set<SystemBase *>("_sys") = _aux.get();
5729 : }
5730 :
5731 4074 : for (THREAD_ID tid = 0; tid < libMesh::n_threads(); tid++)
5732 : {
5733 2127 : std::shared_ptr<Marker> marker = _factory.create<Marker>(marker_name, name, parameters, tid);
5734 2124 : logAdd("Marker", name, marker_name, parameters);
5735 2124 : _markers.addObject(marker, tid);
5736 2124 : }
5737 1947 : }
5738 :
5739 : void
5740 8028 : FEProblemBase::addMultiApp(const std::string & multi_app_name,
5741 : const std::string & name,
5742 : InputParameters & parameters)
5743 : {
5744 : parallel_object_only();
5745 :
5746 16056 : parameters.set<MPI_Comm>("_mpi_comm") = _communicator.get();
5747 :
5748 8028 : if (_displaced_problem && parameters.get<bool>("use_displaced_mesh"))
5749 : {
5750 0 : parameters.set<SubProblem *>("_subproblem") = _displaced_problem.get();
5751 0 : parameters.set<SystemBase *>("_sys") = &_displaced_problem->auxSys();
5752 0 : _reinit_displaced_elem = true;
5753 : }
5754 : else
5755 : {
5756 8028 : if (_displaced_problem == nullptr && parameters.get<bool>("use_displaced_mesh"))
5757 : {
5758 : // We allow MultiApps to request that they use_displaced_mesh,
5759 : // but then be overridden when no displacements variables are
5760 : // provided in the Mesh block. If that happened, update the value
5761 : // of use_displaced_mesh appropriately for this MultiApp.
5762 42 : if (parameters.have_parameter<bool>("use_displaced_mesh"))
5763 84 : parameters.set<bool>("use_displaced_mesh") = false;
5764 : }
5765 :
5766 16056 : parameters.set<SubProblem *>("_subproblem") = this;
5767 24084 : parameters.set<SystemBase *>("_sys") = _aux.get();
5768 : }
5769 :
5770 8028 : std::shared_ptr<MultiApp> multi_app = _factory.create<MultiApp>(multi_app_name, name, parameters);
5771 8016 : logAdd("MultiApp", name, multi_app_name, parameters);
5772 8016 : multi_app->setupPositions();
5773 :
5774 7929 : _multi_apps.addObject(multi_app);
5775 :
5776 : // Store TransientMultiApp objects in another container, this is needed for calling computeDT
5777 : std::shared_ptr<TransientMultiApp> trans_multi_app =
5778 7929 : std::dynamic_pointer_cast<TransientMultiApp>(multi_app);
5779 7929 : if (trans_multi_app)
5780 5353 : _transient_multi_apps.addObject(trans_multi_app);
5781 7929 : }
5782 :
5783 : bool
5784 112534 : FEProblemBase::hasMultiApps(ExecFlagType type) const
5785 : {
5786 112534 : return _multi_apps[type].hasActiveObjects();
5787 : }
5788 :
5789 : bool
5790 0 : FEProblemBase::hasMultiApp(const std::string & multi_app_name) const
5791 : {
5792 0 : return _multi_apps.hasActiveObject(multi_app_name);
5793 : }
5794 :
5795 : std::shared_ptr<MultiApp>
5796 26192 : FEProblemBase::getMultiApp(const std::string & multi_app_name) const
5797 : {
5798 26192 : return _multi_apps.getObject(multi_app_name);
5799 : }
5800 :
5801 : void
5802 14405118 : FEProblemBase::execMultiAppTransfers(ExecFlagType type, Transfer::DIRECTION direction)
5803 : {
5804 14405118 : bool to_multiapp = direction == MultiAppTransfer::TO_MULTIAPP;
5805 14405118 : bool from_multiapp = direction == MultiAppTransfer::FROM_MULTIAPP;
5806 14405118 : std::string string_direction;
5807 14405118 : if (to_multiapp)
5808 4801760 : string_direction = " To ";
5809 9603358 : else if (from_multiapp)
5810 4801634 : string_direction = " From ";
5811 : else
5812 4801724 : string_direction = " Between ";
5813 :
5814 14405280 : const MooseObjectWarehouse<Transfer> & wh = to_multiapp ? _to_multi_app_transfers[type]
5815 24008386 : : from_multiapp ? _from_multi_app_transfers[type]
5816 33611906 : : _between_multi_app_transfers[type];
5817 :
5818 14405118 : if (wh.hasActiveObjects())
5819 : {
5820 537475 : TIME_SECTION("execMultiAppTransfers", 1, "Executing Transfers");
5821 :
5822 107495 : const auto & transfers = wh.getActiveObjects();
5823 :
5824 107495 : if (_verbose_multiapps)
5825 : {
5826 2454 : _console << COLOR_CYAN << "\nTransfers on " << Moose::stringify(type) << string_direction
5827 2454 : << "MultiApps" << COLOR_DEFAULT << ":" << std::endl;
5828 :
5829 : VariadicTable<std::string, std::string, std::string, std::string> table(
5830 4908 : {"Name", "Type", "From", "To"});
5831 :
5832 : // Build Table of Transfer Info
5833 5896 : for (const auto & transfer : transfers)
5834 : {
5835 3442 : auto multiapp_transfer = dynamic_cast<MultiAppTransfer *>(transfer.get());
5836 :
5837 3442 : table.addRow(multiapp_transfer->name(),
5838 3442 : multiapp_transfer->type(),
5839 6884 : multiapp_transfer->getFromName(),
5840 6884 : multiapp_transfer->getToName());
5841 : }
5842 :
5843 : // Print it
5844 2454 : table.print(_console);
5845 2454 : }
5846 :
5847 220031 : for (const auto & transfer : transfers)
5848 : {
5849 112633 : transfer->setCurrentDirection(direction);
5850 112633 : transfer->execute();
5851 : }
5852 :
5853 107398 : MooseUtils::parallelBarrierNotify(_communicator, _parallel_barrier_messaging);
5854 :
5855 107398 : if (_verbose_multiapps)
5856 4896 : _console << COLOR_CYAN << "Transfers on " << Moose::stringify(type) << " Are Finished\n"
5857 2448 : << COLOR_DEFAULT << std::endl;
5858 107398 : }
5859 14297623 : else if (_multi_apps[type].getActiveObjects().size())
5860 : {
5861 109376 : if (_verbose_multiapps)
5862 7684 : _console << COLOR_CYAN << "\nNo Transfers on " << Moose::stringify(type) << string_direction
5863 3842 : << "MultiApps\n"
5864 3842 : << COLOR_DEFAULT << std::endl;
5865 : }
5866 14405021 : }
5867 :
5868 : std::vector<std::shared_ptr<Transfer>>
5869 12 : FEProblemBase::getTransfers(ExecFlagType type, Transfer::DIRECTION direction) const
5870 : {
5871 12 : if (direction == MultiAppTransfer::TO_MULTIAPP)
5872 12 : return _to_multi_app_transfers[type].getActiveObjects();
5873 0 : else if (direction == MultiAppTransfer::FROM_MULTIAPP)
5874 0 : return _from_multi_app_transfers[type].getActiveObjects();
5875 : else
5876 0 : return _between_multi_app_transfers[type].getActiveObjects();
5877 : }
5878 :
5879 : std::vector<std::shared_ptr<Transfer>>
5880 0 : FEProblemBase::getTransfers(Transfer::DIRECTION direction) const
5881 : {
5882 0 : if (direction == MultiAppTransfer::TO_MULTIAPP)
5883 0 : return _to_multi_app_transfers.getActiveObjects();
5884 0 : else if (direction == MultiAppTransfer::FROM_MULTIAPP)
5885 0 : return _from_multi_app_transfers.getActiveObjects();
5886 : else
5887 0 : return _between_multi_app_transfers.getActiveObjects();
5888 : }
5889 :
5890 : const ExecuteMooseObjectWarehouse<Transfer> &
5891 0 : FEProblemBase::getMultiAppTransferWarehouse(Transfer::DIRECTION direction) const
5892 : {
5893 0 : if (direction == MultiAppTransfer::TO_MULTIAPP)
5894 0 : return _to_multi_app_transfers;
5895 0 : else if (direction == MultiAppTransfer::FROM_MULTIAPP)
5896 0 : return _from_multi_app_transfers;
5897 : else
5898 0 : return _between_multi_app_transfers;
5899 : }
5900 :
5901 : bool
5902 4801763 : FEProblemBase::execMultiApps(ExecFlagType type, bool auto_advance)
5903 : {
5904 : // Active MultiApps
5905 : const std::vector<MooseSharedPointer<MultiApp>> & multi_apps =
5906 4801763 : _multi_apps[type].getActiveObjects();
5907 :
5908 : // Do anything that needs to be done to Apps before transfers
5909 4866009 : for (const auto & multi_app : multi_apps)
5910 64249 : multi_app->preTransfer(_dt, _time);
5911 :
5912 : // Execute Transfers _to_ MultiApps
5913 4801760 : execMultiAppTransfers(type, MultiAppTransfer::TO_MULTIAPP);
5914 :
5915 : // Execute Transfers _between_ Multiapps
5916 4801724 : execMultiAppTransfers(type, MultiAppTransfer::BETWEEN_MULTIAPP);
5917 :
5918 : // Execute MultiApps
5919 4801724 : if (multi_apps.size())
5920 : {
5921 314955 : TIME_SECTION("execMultiApps", 1, "Executing MultiApps", false);
5922 :
5923 62991 : if (_verbose_multiapps)
5924 4080 : _console << COLOR_CYAN << "\nExecuting MultiApps on " << Moose::stringify(type)
5925 2040 : << COLOR_DEFAULT << std::endl;
5926 :
5927 62991 : bool success = true;
5928 :
5929 127112 : for (const auto & multi_app : multi_apps)
5930 : {
5931 64204 : success = multi_app->solveStep(_dt, _time, auto_advance);
5932 : // no need to finish executing the subapps if one fails
5933 64195 : if (!success)
5934 74 : break;
5935 : }
5936 :
5937 62982 : MooseUtils::parallelBarrierNotify(_communicator, _parallel_barrier_messaging);
5938 :
5939 62982 : _communicator.min(success);
5940 :
5941 62982 : if (!success)
5942 81 : return false;
5943 :
5944 62901 : if (_verbose_multiapps)
5945 4080 : _console << COLOR_CYAN << "Finished Executing MultiApps on " << Moose::stringify(type) << "\n"
5946 2040 : << COLOR_DEFAULT << std::endl;
5947 62982 : }
5948 :
5949 : // Execute Transfers _from_ MultiApps
5950 4801634 : execMultiAppTransfers(type, MultiAppTransfer::FROM_MULTIAPP);
5951 :
5952 : // If we made it here then everything passed
5953 4801573 : return true;
5954 : }
5955 :
5956 : void
5957 48110 : FEProblemBase::finalizeMultiApps()
5958 : {
5959 48110 : const auto & multi_apps = _multi_apps.getActiveObjects();
5960 :
5961 54954 : for (const auto & multi_app : multi_apps)
5962 6844 : multi_app->finalize();
5963 48110 : }
5964 :
5965 : void
5966 49767 : FEProblemBase::postExecute()
5967 : {
5968 49767 : const auto & multi_apps = _multi_apps.getActiveObjects();
5969 :
5970 56993 : for (const auto & multi_app : multi_apps)
5971 7226 : multi_app->postExecute();
5972 49767 : }
5973 :
5974 : void
5975 656088 : FEProblemBase::incrementMultiAppTStep(ExecFlagType type)
5976 : {
5977 656088 : const auto & multi_apps = _multi_apps[type].getActiveObjects();
5978 :
5979 656088 : if (multi_apps.size())
5980 26266 : for (const auto & multi_app : multi_apps)
5981 13304 : multi_app->incrementTStep(_time);
5982 656088 : }
5983 :
5984 : void
5985 36370 : FEProblemBase::finishMultiAppStep(ExecFlagType type, bool recurse_through_multiapp_levels)
5986 : {
5987 36370 : const auto & multi_apps = _multi_apps[type].getActiveObjects();
5988 :
5989 36370 : if (multi_apps.size())
5990 : {
5991 8584 : if (_verbose_multiapps)
5992 382 : _console << COLOR_CYAN << "\nAdvancing MultiApps on " << type.name() << COLOR_DEFAULT
5993 382 : << std::endl;
5994 :
5995 17174 : for (const auto & multi_app : multi_apps)
5996 8590 : multi_app->finishStep(recurse_through_multiapp_levels);
5997 :
5998 8584 : MooseUtils::parallelBarrierNotify(_communicator, _parallel_barrier_messaging);
5999 :
6000 8584 : if (_verbose_multiapps)
6001 382 : _console << COLOR_CYAN << "Finished Advancing MultiApps on " << type.name() << "\n"
6002 382 : << COLOR_DEFAULT << std::endl;
6003 : }
6004 36370 : }
6005 :
6006 : void
6007 1114450 : FEProblemBase::backupMultiApps(ExecFlagType type)
6008 : {
6009 1114450 : const auto & multi_apps = _multi_apps[type].getActiveObjects();
6010 :
6011 1114450 : if (multi_apps.size())
6012 : {
6013 102180 : TIME_SECTION("backupMultiApps", 5, "Backing Up MultiApp");
6014 :
6015 20436 : if (_verbose_multiapps)
6016 1041 : _console << COLOR_CYAN << "\nBacking Up MultiApps on " << type.name() << COLOR_DEFAULT
6017 1041 : << std::endl;
6018 :
6019 42061 : for (const auto & multi_app : multi_apps)
6020 21625 : multi_app->backup();
6021 :
6022 20436 : MooseUtils::parallelBarrierNotify(_communicator, _parallel_barrier_messaging);
6023 :
6024 20436 : if (_verbose_multiapps)
6025 1041 : _console << COLOR_CYAN << "Finished Backing Up MultiApps on " << type.name() << "\n"
6026 1041 : << COLOR_DEFAULT << std::endl;
6027 20436 : }
6028 1114450 : }
6029 :
6030 : void
6031 104526 : FEProblemBase::restoreMultiApps(ExecFlagType type, bool force)
6032 : {
6033 104526 : const auto & multi_apps = _multi_apps[type].getActiveObjects();
6034 :
6035 104526 : if (multi_apps.size())
6036 : {
6037 43043 : if (_verbose_multiapps)
6038 : {
6039 1002 : if (force)
6040 3 : _console << COLOR_CYAN << "\nRestoring Multiapps on " << type.name()
6041 3 : << " because of solve failure!" << COLOR_DEFAULT << std::endl;
6042 : else
6043 999 : _console << COLOR_CYAN << "\nRestoring MultiApps on " << type.name() << COLOR_DEFAULT
6044 999 : << std::endl;
6045 : }
6046 :
6047 86128 : for (const auto & multi_app : multi_apps)
6048 43088 : multi_app->restore(force);
6049 :
6050 43040 : MooseUtils::parallelBarrierNotify(_communicator, _parallel_barrier_messaging);
6051 :
6052 43040 : if (_verbose_multiapps)
6053 1002 : _console << COLOR_CYAN << "Finished Restoring MultiApps on " << type.name() << "\n"
6054 1002 : << COLOR_DEFAULT << std::endl;
6055 : }
6056 104523 : }
6057 :
6058 : Real
6059 678580 : FEProblemBase::computeMultiAppsDT(ExecFlagType type)
6060 : {
6061 678580 : const auto & multi_apps = _transient_multi_apps[type].getActiveObjects();
6062 :
6063 678580 : Real smallest_dt = std::numeric_limits<Real>::max();
6064 :
6065 695965 : for (const auto & multi_app : multi_apps)
6066 17385 : smallest_dt = std::min(smallest_dt, multi_app->computeDT());
6067 :
6068 678580 : return smallest_dt;
6069 : }
6070 :
6071 : void
6072 4748998 : FEProblemBase::execTransfers(ExecFlagType type)
6073 : {
6074 4748998 : if (_transfers[type].hasActiveObjects())
6075 : {
6076 0 : TIME_SECTION("execTransfers", 3, "Executing Transfers");
6077 :
6078 0 : const auto & transfers = _transfers[type].getActiveObjects();
6079 :
6080 0 : for (const auto & transfer : transfers)
6081 0 : transfer->execute();
6082 0 : }
6083 4748998 : }
6084 :
6085 : void
6086 13011 : FEProblemBase::addTransfer(const std::string & transfer_name,
6087 : const std::string & name,
6088 : InputParameters & parameters)
6089 : {
6090 : parallel_object_only();
6091 :
6092 13011 : if (_displaced_problem && parameters.get<bool>("use_displaced_mesh"))
6093 : {
6094 0 : parameters.set<SubProblem *>("_subproblem") = _displaced_problem.get();
6095 0 : parameters.set<SystemBase *>("_sys") = &_displaced_problem->auxSys();
6096 0 : _reinit_displaced_elem = true;
6097 : }
6098 : else
6099 : {
6100 13011 : if (_displaced_problem == nullptr && parameters.get<bool>("use_displaced_mesh"))
6101 : {
6102 : // We allow Transfers to request that they use_displaced_mesh,
6103 : // but then be overridden when no displacements variables are
6104 : // provided in the Mesh block. If that happened, update the value
6105 : // of use_displaced_mesh appropriately for this Transfer.
6106 0 : if (parameters.have_parameter<bool>("use_displaced_mesh"))
6107 0 : parameters.set<bool>("use_displaced_mesh") = false;
6108 : }
6109 :
6110 26022 : parameters.set<SubProblem *>("_subproblem") = this;
6111 39033 : parameters.set<SystemBase *>("_sys") = _aux.get();
6112 : }
6113 :
6114 : // Handle the "SAME_AS_MULTIAPP" execute option. The get method is used to test for the
6115 : // flag so the set by user flag is not reset, calling set with the true flag causes the set
6116 : // by user status to be reset, which should only be done if the EXEC_SAME_AS_MULTIAPP is
6117 : // being applied to the object.
6118 13011 : if (parameters.get<ExecFlagEnum>("execute_on").isValueSet(EXEC_SAME_AS_MULTIAPP))
6119 : {
6120 10884 : ExecFlagEnum & exec_enum = parameters.set<ExecFlagEnum>("execute_on", true);
6121 10884 : std::shared_ptr<MultiApp> multiapp;
6122 21768 : if (parameters.isParamValid("multi_app"))
6123 50 : multiapp = getMultiApp(parameters.get<MultiAppName>("multi_app"));
6124 : // This catches the sibling transfer case, where we want to be executing only as often as the
6125 : // receiving application. A transfer 'to' a multiapp is executed before that multiapp
6126 21668 : else if (parameters.isParamValid("to_multi_app"))
6127 5649 : multiapp = getMultiApp(parameters.get<MultiAppName>("to_multi_app"));
6128 10370 : else if (parameters.isParamValid("from_multi_app"))
6129 5179 : multiapp = getMultiApp(parameters.get<MultiAppName>("from_multi_app"));
6130 : // else do nothing because the user has provided invalid input. They should get a nice error
6131 : // about this during transfer construction. This necessitates checking for null in this next
6132 : // line, however
6133 10884 : if (multiapp)
6134 32634 : exec_enum = multiapp->getParam<ExecFlagEnum>("execute_on");
6135 10884 : }
6136 :
6137 : // Create the Transfer objects
6138 13011 : std::shared_ptr<Transfer> transfer = _factory.create<Transfer>(transfer_name, name, parameters);
6139 12954 : logAdd("Transfer", name, transfer_name, parameters);
6140 :
6141 : // Add MultiAppTransfer object
6142 : std::shared_ptr<MultiAppTransfer> multi_app_transfer =
6143 12954 : std::dynamic_pointer_cast<MultiAppTransfer>(transfer);
6144 12954 : if (multi_app_transfer)
6145 : {
6146 12954 : if (multi_app_transfer->directions().isValueSet(MultiAppTransfer::TO_MULTIAPP))
6147 5169 : _to_multi_app_transfers.addObject(multi_app_transfer);
6148 12954 : if (multi_app_transfer->directions().isValueSet(MultiAppTransfer::FROM_MULTIAPP))
6149 6316 : _from_multi_app_transfers.addObject(multi_app_transfer);
6150 12954 : if (multi_app_transfer->directions().isValueSet(MultiAppTransfer::BETWEEN_MULTIAPP))
6151 1469 : _between_multi_app_transfers.addObject(multi_app_transfer);
6152 : }
6153 : else
6154 0 : _transfers.addObject(transfer);
6155 12954 : }
6156 :
6157 : bool
6158 1428277 : FEProblemBase::hasVariable(const std::string & var_name) const
6159 : {
6160 2330970 : for (auto & sys : _solver_systems)
6161 1433594 : if (sys->hasVariable(var_name))
6162 530901 : return true;
6163 897376 : if (_aux->hasVariable(var_name))
6164 828708 : return true;
6165 :
6166 68668 : return false;
6167 : }
6168 :
6169 : bool
6170 65 : FEProblemBase::hasSolverVariable(const std::string & var_name) const
6171 : {
6172 78 : for (auto & sys : _solver_systems)
6173 65 : if (sys->hasVariable(var_name))
6174 52 : return true;
6175 :
6176 13 : return false;
6177 : }
6178 :
6179 : const MooseVariableFieldBase &
6180 4290138 : FEProblemBase::getVariable(const THREAD_ID tid,
6181 : const std::string & var_name,
6182 : Moose::VarKindType expected_var_type,
6183 : Moose::VarFieldType expected_var_field_type) const
6184 : {
6185 12870408 : return getVariableHelper(
6186 4290138 : tid, var_name, expected_var_type, expected_var_field_type, _solver_systems, *_aux);
6187 : }
6188 :
6189 : MooseVariable &
6190 7509 : FEProblemBase::getStandardVariable(const THREAD_ID tid, const std::string & var_name)
6191 : {
6192 11358 : for (auto & sys : _solver_systems)
6193 7509 : if (sys->hasVariable(var_name))
6194 3660 : return sys->getFieldVariable<Real>(tid, var_name);
6195 3849 : if (_aux->hasVariable(var_name))
6196 3846 : return _aux->getFieldVariable<Real>(tid, var_name);
6197 :
6198 3 : mooseError("Unknown variable " + var_name);
6199 : }
6200 :
6201 : MooseVariableFieldBase &
6202 581 : FEProblemBase::getActualFieldVariable(const THREAD_ID tid, const std::string & var_name)
6203 : {
6204 771 : for (auto & sys : _solver_systems)
6205 581 : if (sys->hasVariable(var_name))
6206 391 : return sys->getActualFieldVariable<Real>(tid, var_name);
6207 190 : if (_aux->hasVariable(var_name))
6208 190 : return _aux->getActualFieldVariable<Real>(tid, var_name);
6209 :
6210 0 : mooseError("Unknown variable " + var_name);
6211 : }
6212 :
6213 : VectorMooseVariable &
6214 0 : FEProblemBase::getVectorVariable(const THREAD_ID tid, const std::string & var_name)
6215 : {
6216 0 : for (auto & sys : _solver_systems)
6217 0 : if (sys->hasVariable(var_name))
6218 0 : return sys->getFieldVariable<RealVectorValue>(tid, var_name);
6219 0 : if (_aux->hasVariable(var_name))
6220 0 : return _aux->getFieldVariable<RealVectorValue>(tid, var_name);
6221 :
6222 0 : mooseError("Unknown variable " + var_name);
6223 : }
6224 :
6225 : ArrayMooseVariable &
6226 351 : FEProblemBase::getArrayVariable(const THREAD_ID tid, const std::string & var_name)
6227 : {
6228 611 : for (auto & sys : _solver_systems)
6229 351 : if (sys->hasVariable(var_name))
6230 91 : return sys->getFieldVariable<RealEigenVector>(tid, var_name);
6231 260 : if (_aux->hasVariable(var_name))
6232 260 : return _aux->getFieldVariable<RealEigenVector>(tid, var_name);
6233 :
6234 0 : mooseError("Unknown variable " + var_name);
6235 : }
6236 :
6237 : bool
6238 178263 : FEProblemBase::hasScalarVariable(const std::string & var_name) const
6239 : {
6240 335953 : for (auto & sys : _solver_systems)
6241 178827 : if (sys->hasScalarVariable(var_name))
6242 21137 : return true;
6243 157126 : if (_aux->hasScalarVariable(var_name))
6244 10613 : return true;
6245 :
6246 146513 : return false;
6247 : }
6248 :
6249 : MooseVariableScalar &
6250 44158 : FEProblemBase::getScalarVariable(const THREAD_ID tid, const std::string & var_name)
6251 : {
6252 56499 : for (auto & sys : _solver_systems)
6253 44158 : if (sys->hasScalarVariable(var_name))
6254 31817 : return sys->getScalarVariable(tid, var_name);
6255 12341 : if (_aux->hasScalarVariable(var_name))
6256 12341 : return _aux->getScalarVariable(tid, var_name);
6257 :
6258 0 : mooseError("Unknown variable " + var_name);
6259 : }
6260 :
6261 : System &
6262 58224 : FEProblemBase::getSystem(const std::string & var_name)
6263 : {
6264 58224 : const auto [var_in_sys, sys_num] = determineSolverSystem(var_name);
6265 58224 : if (var_in_sys)
6266 39465 : return _solver_systems[sys_num]->system();
6267 18759 : else if (_aux->hasVariable(var_name) || _aux->hasScalarVariable(var_name))
6268 18759 : return _aux->system();
6269 : else
6270 0 : mooseError("Unable to find a system containing the variable " + var_name);
6271 : }
6272 :
6273 : const RestartableEquationSystems &
6274 0 : FEProblemBase::getRestartableEquationSystems() const
6275 : {
6276 0 : return _req.get();
6277 : }
6278 :
6279 : void
6280 481872 : FEProblemBase::setActiveFEVariableCoupleableMatrixTags(std::set<TagID> & mtags, const THREAD_ID tid)
6281 : {
6282 481872 : SubProblem::setActiveFEVariableCoupleableMatrixTags(mtags, tid);
6283 :
6284 481872 : if (_displaced_problem)
6285 101844 : _displaced_problem->setActiveFEVariableCoupleableMatrixTags(mtags, tid);
6286 481872 : }
6287 :
6288 : void
6289 6598950 : FEProblemBase::setActiveFEVariableCoupleableVectorTags(std::set<TagID> & vtags, const THREAD_ID tid)
6290 : {
6291 6598950 : SubProblem::setActiveFEVariableCoupleableVectorTags(vtags, tid);
6292 :
6293 6598950 : if (_displaced_problem)
6294 359318 : _displaced_problem->setActiveFEVariableCoupleableVectorTags(vtags, tid);
6295 6598950 : }
6296 :
6297 : void
6298 47814 : FEProblemBase::setActiveScalarVariableCoupleableMatrixTags(std::set<TagID> & mtags,
6299 : const THREAD_ID tid)
6300 : {
6301 47814 : SubProblem::setActiveScalarVariableCoupleableMatrixTags(mtags, tid);
6302 :
6303 47814 : if (_displaced_problem)
6304 0 : _displaced_problem->setActiveScalarVariableCoupleableMatrixTags(mtags, tid);
6305 47814 : }
6306 :
6307 : void
6308 47814 : FEProblemBase::setActiveScalarVariableCoupleableVectorTags(std::set<TagID> & vtags,
6309 : const THREAD_ID tid)
6310 : {
6311 47814 : SubProblem::setActiveScalarVariableCoupleableVectorTags(vtags, tid);
6312 :
6313 47814 : if (_displaced_problem)
6314 0 : _displaced_problem->setActiveScalarVariableCoupleableVectorTags(vtags, tid);
6315 47814 : }
6316 :
6317 : void
6318 10259533 : FEProblemBase::setActiveElementalMooseVariables(const std::set<MooseVariableFEBase *> & moose_vars,
6319 : const THREAD_ID tid)
6320 : {
6321 10259533 : SubProblem::setActiveElementalMooseVariables(moose_vars, tid);
6322 :
6323 10259533 : if (_displaced_problem)
6324 511919 : _displaced_problem->setActiveElementalMooseVariables(moose_vars, tid);
6325 10259533 : }
6326 :
6327 : void
6328 4200204 : FEProblemBase::clearActiveElementalMooseVariables(const THREAD_ID tid)
6329 : {
6330 4200204 : SubProblem::clearActiveElementalMooseVariables(tid);
6331 :
6332 4200204 : if (_displaced_problem)
6333 186523 : _displaced_problem->clearActiveElementalMooseVariables(tid);
6334 4200204 : }
6335 :
6336 : void
6337 225643 : FEProblemBase::clearActiveFEVariableCoupleableMatrixTags(const THREAD_ID tid)
6338 : {
6339 225643 : SubProblem::clearActiveFEVariableCoupleableMatrixTags(tid);
6340 :
6341 225643 : if (_displaced_problem)
6342 45849 : _displaced_problem->clearActiveFEVariableCoupleableMatrixTags(tid);
6343 225643 : }
6344 :
6345 : void
6346 225643 : FEProblemBase::clearActiveFEVariableCoupleableVectorTags(const THREAD_ID tid)
6347 : {
6348 225643 : SubProblem::clearActiveFEVariableCoupleableVectorTags(tid);
6349 :
6350 225643 : if (_displaced_problem)
6351 45849 : _displaced_problem->clearActiveFEVariableCoupleableVectorTags(tid);
6352 225643 : }
6353 :
6354 : void
6355 47814 : FEProblemBase::clearActiveScalarVariableCoupleableMatrixTags(const THREAD_ID tid)
6356 : {
6357 47814 : SubProblem::clearActiveScalarVariableCoupleableMatrixTags(tid);
6358 :
6359 47814 : if (_displaced_problem)
6360 0 : _displaced_problem->clearActiveScalarVariableCoupleableMatrixTags(tid);
6361 47814 : }
6362 :
6363 : void
6364 47814 : FEProblemBase::clearActiveScalarVariableCoupleableVectorTags(const THREAD_ID tid)
6365 : {
6366 47814 : SubProblem::clearActiveScalarVariableCoupleableVectorTags(tid);
6367 :
6368 47814 : if (_displaced_problem)
6369 0 : _displaced_problem->clearActiveScalarVariableCoupleableVectorTags(tid);
6370 47814 : }
6371 :
6372 : void
6373 5251248 : FEProblemBase::setActiveMaterialProperties(const std::unordered_set<unsigned int> & mat_prop_ids,
6374 : const THREAD_ID tid)
6375 : {
6376 : // mark active properties in every material
6377 6379162 : for (auto & mat : _all_materials.getObjects(tid))
6378 1127914 : mat->setActiveProperties(mat_prop_ids);
6379 6150773 : for (auto & mat : _all_materials[Moose::FACE_MATERIAL_DATA].getObjects(tid))
6380 899525 : mat->setActiveProperties(mat_prop_ids);
6381 6150773 : for (auto & mat : _all_materials[Moose::NEIGHBOR_MATERIAL_DATA].getObjects(tid))
6382 899525 : mat->setActiveProperties(mat_prop_ids);
6383 :
6384 5251248 : _has_active_material_properties[tid] = !mat_prop_ids.empty();
6385 5251248 : }
6386 :
6387 : bool
6388 382059141 : FEProblemBase::hasActiveMaterialProperties(const THREAD_ID tid) const
6389 : {
6390 382059141 : return _has_active_material_properties[tid];
6391 : }
6392 :
6393 : void
6394 4294489 : FEProblemBase::clearActiveMaterialProperties(const THREAD_ID tid)
6395 : {
6396 4294489 : _has_active_material_properties[tid] = 0;
6397 4294489 : }
6398 :
6399 : void
6400 59425 : FEProblemBase::addAnyRedistributers()
6401 : {
6402 : #ifdef LIBMESH_ENABLE_AMR
6403 61678 : if ((_adaptivity.isOn() || _num_grid_steps) &&
6404 2253 : (_material_props.hasStatefulProperties() || _bnd_material_props.hasStatefulProperties() ||
6405 2190 : _neighbor_material_props.hasStatefulProperties()))
6406 : {
6407 : // Even on a serialized Mesh, we don't keep our material
6408 : // properties serialized, so we'll rely on the callback to
6409 : // redistribute() to redistribute properties at the same time
6410 : // libMesh is redistributing elements.
6411 63 : auto add_redistributer = [this](MooseMesh & mesh,
6412 : const std::string & redistributer_name,
6413 : const bool use_displaced_mesh)
6414 : {
6415 63 : InputParameters redistribute_params = RedistributeProperties::validParams();
6416 63 : redistribute_params.set<MooseApp *>(MooseBase::app_param) = &_app;
6417 126 : redistribute_params.set<std::string>("for_whom") = this->name();
6418 189 : redistribute_params.set<MooseMesh *>("mesh") = &mesh;
6419 63 : redistribute_params.set<Moose::RelationshipManagerType>("rm_type") =
6420 : Moose::RelationshipManagerType::GEOMETRIC;
6421 126 : redistribute_params.set<bool>("use_displaced_mesh") = use_displaced_mesh;
6422 63 : redistribute_params.setHitNode(*parameters().getHitNode(), {});
6423 :
6424 : std::shared_ptr<RedistributeProperties> redistributer =
6425 63 : _factory.create<RedistributeProperties>(
6426 126 : "RedistributeProperties", redistributer_name, redistribute_params);
6427 :
6428 63 : if (_material_props.hasStatefulProperties())
6429 63 : redistributer->addMaterialPropertyStorage(_material_props);
6430 :
6431 63 : if (_bnd_material_props.hasStatefulProperties())
6432 63 : redistributer->addMaterialPropertyStorage(_bnd_material_props);
6433 :
6434 63 : if (_neighbor_material_props.hasStatefulProperties())
6435 63 : redistributer->addMaterialPropertyStorage(_neighbor_material_props);
6436 :
6437 63 : mesh.getMesh().add_ghosting_functor(redistributer);
6438 126 : };
6439 :
6440 63 : add_redistributer(_mesh, "mesh_property_redistributer", false);
6441 63 : if (_displaced_problem)
6442 0 : add_redistributer(_displaced_problem->mesh(), "displaced_mesh_property_redistributer", true);
6443 : }
6444 : #endif // LIBMESH_ENABLE_AMR
6445 59425 : }
6446 :
6447 : void
6448 61270 : FEProblemBase::updateMaxQps()
6449 : {
6450 : // Find the maximum number of quadrature points
6451 : {
6452 61270 : MaxQpsThread mqt(*this);
6453 61270 : Threads::parallel_reduce(getCurrentAlgebraicElementRange(), mqt);
6454 61270 : _max_qps = mqt.max();
6455 :
6456 : // If we have more shape functions or more quadrature points on
6457 : // another processor, then we may need to handle those elements
6458 : // ourselves later after repartitioning.
6459 61270 : _communicator.max(_max_qps);
6460 : }
6461 :
6462 61270 : unsigned int max_qpts = getMaxQps();
6463 61270 : if (max_qpts > Moose::constMaxQpsPerElem)
6464 0 : mooseError("Max quadrature points per element assumptions made in some code (e.g. Coupleable ",
6465 : "and MaterialPropertyInterface classes) have been violated.\n",
6466 : "Complain to Moose developers to have constMaxQpsPerElem increased from ",
6467 : Moose::constMaxQpsPerElem,
6468 : " to ",
6469 : max_qpts);
6470 129098 : for (unsigned int tid = 0; tid < libMesh::n_threads(); ++tid)
6471 : {
6472 : // the highest available order in libMesh is 43
6473 67828 : _scalar_zero[tid].resize(FORTYTHIRD, 0);
6474 67828 : _zero[tid].resize(max_qpts, 0);
6475 67828 : _ad_zero[tid].resize(max_qpts, 0);
6476 67828 : _grad_zero[tid].resize(max_qpts, RealGradient(0.));
6477 67828 : _ad_grad_zero[tid].resize(max_qpts, ADRealGradient(0));
6478 67828 : _second_zero[tid].resize(max_qpts, RealTensor(0.));
6479 67828 : _ad_second_zero[tid].resize(max_qpts, ADRealTensorValue(0));
6480 67828 : _vector_zero[tid].resize(max_qpts, RealGradient(0.));
6481 67828 : _vector_curl_zero[tid].resize(max_qpts, RealGradient(0.));
6482 : }
6483 61270 : }
6484 :
6485 : void
6486 78 : FEProblemBase::bumpVolumeQRuleOrder(Order order, SubdomainID block)
6487 : {
6488 168 : for (unsigned int tid = 0; tid < libMesh::n_threads(); ++tid)
6489 180 : for (const auto i : index_range(_nl))
6490 90 : _assembly[tid][i]->bumpVolumeQRuleOrder(order, block);
6491 :
6492 78 : if (_displaced_problem)
6493 0 : _displaced_problem->bumpVolumeQRuleOrder(order, block);
6494 :
6495 78 : updateMaxQps();
6496 78 : }
6497 :
6498 : void
6499 13 : FEProblemBase::bumpAllQRuleOrder(Order order, SubdomainID block)
6500 : {
6501 28 : for (unsigned int tid = 0; tid < libMesh::n_threads(); ++tid)
6502 30 : for (const auto i : index_range(_nl))
6503 15 : _assembly[tid][i]->bumpAllQRuleOrder(order, block);
6504 :
6505 13 : if (_displaced_problem)
6506 0 : _displaced_problem->bumpAllQRuleOrder(order, block);
6507 :
6508 13 : updateMaxQps();
6509 13 : }
6510 :
6511 : void
6512 61179 : FEProblemBase::createQRules(QuadratureType type,
6513 : Order order,
6514 : Order volume_order,
6515 : Order face_order,
6516 : SubdomainID block,
6517 : const bool allow_negative_qweights)
6518 : {
6519 61179 : if (order == INVALID_ORDER)
6520 : {
6521 : // automatically determine the integration order
6522 60618 : order = _solver_systems[0]->getMinQuadratureOrder();
6523 60871 : for (const auto i : make_range(std::size_t(1), _solver_systems.size()))
6524 253 : if (order < _solver_systems[i]->getMinQuadratureOrder())
6525 0 : order = _solver_systems[i]->getMinQuadratureOrder();
6526 60618 : if (order < _aux->getMinQuadratureOrder())
6527 5983 : order = _aux->getMinQuadratureOrder();
6528 : }
6529 :
6530 61179 : if (volume_order == INVALID_ORDER)
6531 61027 : volume_order = order;
6532 :
6533 61179 : if (face_order == INVALID_ORDER)
6534 61027 : face_order = order;
6535 :
6536 128902 : for (unsigned int tid = 0; tid < libMesh::n_threads(); ++tid)
6537 135718 : for (const auto i : index_range(_solver_systems))
6538 67995 : _assembly[tid][i]->createQRules(
6539 : type, order, volume_order, face_order, block, allow_negative_qweights);
6540 :
6541 61179 : if (_displaced_problem)
6542 2022 : _displaced_problem->createQRules(
6543 : type, order, volume_order, face_order, block, allow_negative_qweights);
6544 :
6545 61179 : updateMaxQps();
6546 61179 : }
6547 :
6548 : void
6549 19471 : FEProblemBase::setCoupling(Moose::CouplingType type)
6550 : {
6551 19471 : if (_trust_user_coupling_matrix)
6552 : {
6553 3 : if (_coupling != Moose::COUPLING_CUSTOM)
6554 0 : mooseError("Someone told us (the FEProblemBase) to trust the user coupling matrix, but we "
6555 : "haven't been provided a coupling matrix!");
6556 :
6557 : // We've been told to trust the user coupling matrix, so we're going to leave things alone
6558 3 : return;
6559 : }
6560 :
6561 19468 : _coupling = type;
6562 : }
6563 :
6564 : void
6565 0 : FEProblemBase::setCouplingMatrix(CouplingMatrix * cm, const unsigned int i)
6566 : {
6567 : // TODO: Deprecate method
6568 0 : setCoupling(Moose::COUPLING_CUSTOM);
6569 0 : _cm[i].reset(cm);
6570 0 : }
6571 :
6572 : void
6573 13152 : FEProblemBase::setCouplingMatrix(std::unique_ptr<CouplingMatrix> cm, const unsigned int i)
6574 : {
6575 13152 : setCoupling(Moose::COUPLING_CUSTOM);
6576 13152 : _cm[i] = std::move(cm);
6577 13152 : }
6578 :
6579 : void
6580 3 : FEProblemBase::trustUserCouplingMatrix()
6581 : {
6582 3 : if (_coupling != Moose::COUPLING_CUSTOM)
6583 0 : mooseError("Someone told us (the FEProblemBase) to trust the user coupling matrix, but we "
6584 : "haven't been provided a coupling matrix!");
6585 :
6586 3 : _trust_user_coupling_matrix = true;
6587 3 : }
6588 :
6589 : void
6590 63 : FEProblemBase::setNonlocalCouplingMatrix()
6591 : {
6592 315 : TIME_SECTION("setNonlocalCouplingMatrix", 5, "Setting Nonlocal Coupling Matrix");
6593 :
6594 63 : if (_nl.size() > 1)
6595 0 : mooseError("Nonlocal kernels are weirdly stored on the FEProblem so we don't currently support "
6596 : "multiple nonlinear systems with nonlocal kernels.");
6597 :
6598 126 : for (const auto nl_sys_num : index_range(_nl))
6599 : {
6600 63 : auto & nl = _nl[nl_sys_num];
6601 63 : auto & nonlocal_cm = _nonlocal_cm[nl_sys_num];
6602 63 : unsigned int n_vars = nl->nVariables();
6603 63 : nonlocal_cm.resize(n_vars);
6604 63 : const auto & vars = nl->getVariables(0);
6605 63 : const auto & nonlocal_kernel = _nonlocal_kernels.getObjects();
6606 63 : const auto & nonlocal_integrated_bc = _nonlocal_integrated_bcs.getObjects();
6607 189 : for (const auto & ivar : vars)
6608 : {
6609 196 : for (const auto & kernel : nonlocal_kernel)
6610 : {
6611 140 : for (unsigned int i = ivar->number(); i < ivar->number() + ivar->count(); ++i)
6612 70 : if (i == kernel->variable().number())
6613 105 : for (const auto & jvar : vars)
6614 : {
6615 70 : const auto it = _var_dof_map.find(jvar->name());
6616 70 : if (it != _var_dof_map.end())
6617 : {
6618 62 : unsigned int j = jvar->number();
6619 62 : nonlocal_cm(i, j) = 1;
6620 : }
6621 : }
6622 : }
6623 182 : for (const auto & integrated_bc : nonlocal_integrated_bc)
6624 : {
6625 112 : for (unsigned int i = ivar->number(); i < ivar->number() + ivar->count(); ++i)
6626 56 : if (i == integrated_bc->variable().number())
6627 84 : for (const auto & jvar : vars)
6628 : {
6629 56 : const auto it = _var_dof_map.find(jvar->name());
6630 56 : if (it != _var_dof_map.end())
6631 : {
6632 28 : unsigned int j = jvar->number();
6633 28 : nonlocal_cm(i, j) = 1;
6634 : }
6635 : }
6636 : }
6637 : }
6638 : }
6639 63 : }
6640 :
6641 : bool
6642 624 : FEProblemBase::areCoupled(const unsigned int ivar,
6643 : const unsigned int jvar,
6644 : const unsigned int nl_sys) const
6645 : {
6646 624 : return (*_cm[nl_sys])(ivar, jvar);
6647 : }
6648 :
6649 : std::vector<std::pair<MooseVariableFEBase *, MooseVariableFEBase *>> &
6650 15117437 : FEProblemBase::couplingEntries(const THREAD_ID tid, const unsigned int nl_sys)
6651 : {
6652 15117437 : return _assembly[tid][nl_sys]->couplingEntries();
6653 : }
6654 :
6655 : std::vector<std::pair<MooseVariableFEBase *, MooseVariableFEBase *>> &
6656 4162 : FEProblemBase::nonlocalCouplingEntries(const THREAD_ID tid, const unsigned int nl_sys)
6657 : {
6658 4162 : return _assembly[tid][nl_sys]->nonlocalCouplingEntries();
6659 : }
6660 :
6661 : void
6662 59892 : FEProblemBase::init()
6663 : {
6664 59892 : if (_initialized)
6665 0 : return;
6666 :
6667 299460 : TIME_SECTION("init", 2, "Initializing");
6668 :
6669 : // call executioner's preProblemInit so that it can do some setups before problem init
6670 59892 : _app.getExecutioner()->preProblemInit();
6671 :
6672 : // If we have AD and we are doing global AD indexing, then we should by default set the matrix
6673 : // coupling to full. If the user has told us to trust their coupling matrix, then this call will
6674 : // not do anything
6675 59892 : if (haveADObjects() && Moose::globalADIndexing())
6676 6226 : setCoupling(Moose::COUPLING_FULL);
6677 :
6678 118999 : for (const auto i : index_range(_nl))
6679 : {
6680 59107 : auto & nl = _nl[i];
6681 59107 : auto & cm = _cm[i];
6682 :
6683 59107 : unsigned int n_vars = nl->nVariables();
6684 : {
6685 295535 : TIME_SECTION("fillCouplingMatrix", 3, "Filling Coupling Matrix");
6686 :
6687 59107 : switch (_coupling)
6688 : {
6689 44284 : case Moose::COUPLING_DIAG:
6690 44284 : cm = std::make_unique<CouplingMatrix>(n_vars);
6691 80461 : for (unsigned int i = 0; i < n_vars; i++)
6692 36177 : (*cm)(i, i) = 1;
6693 44284 : break;
6694 :
6695 : // for full jacobian
6696 6358 : case Moose::COUPLING_FULL:
6697 6358 : cm = std::make_unique<CouplingMatrix>(n_vars);
6698 16247 : for (unsigned int i = 0; i < n_vars; i++)
6699 28654 : for (unsigned int j = 0; j < n_vars; j++)
6700 18765 : (*cm)(i, j) = 1;
6701 6358 : break;
6702 :
6703 8465 : case Moose::COUPLING_CUSTOM:
6704 : // do nothing, _cm was already set through couplingMatrix() call
6705 8465 : break;
6706 : }
6707 59107 : }
6708 :
6709 59107 : nl->dofMap()._dof_coupling = cm.get();
6710 :
6711 : // If there are no variables, make sure to pass a nullptr coupling
6712 : // matrix, to avoid warnings about non-nullptr yet empty
6713 : // CouplingMatrices.
6714 59107 : if (n_vars == 0)
6715 13630 : nl->dofMap()._dof_coupling = nullptr;
6716 :
6717 59107 : nl->dofMap().attach_extra_sparsity_function(&extraSparsity, nl.get());
6718 59107 : nl->dofMap().attach_extra_send_list_function(&extraSendList, nl.get());
6719 59107 : _aux->dofMap().attach_extra_send_list_function(&extraSendList, _aux.get());
6720 :
6721 59107 : if (!_skip_nl_system_check && _solve && n_vars == 0)
6722 0 : mooseError("No variables specified in nonlinear system '", nl->name(), "'.");
6723 : }
6724 :
6725 59892 : ghostGhostedBoundaries(); // We do this again right here in case new boundaries have been added
6726 :
6727 : // We may have added element/nodes to the mesh in ghostGhostedBoundaries so we need to update
6728 : // all of our mesh information. We need to make sure that mesh information is up-to-date before
6729 : // EquationSystems::init because that will call through to updateGeomSearch (for sparsity
6730 : // augmentation) and if we haven't added back boundary node information before that latter call,
6731 : // then we're screwed. We'll get things like "Unable to find closest node!"
6732 59892 : _mesh.meshChanged();
6733 59892 : if (_displaced_problem)
6734 2022 : _displaced_mesh->meshChanged();
6735 :
6736 59892 : if (_mesh.doingPRefinement())
6737 : {
6738 240 : preparePRefinement();
6739 240 : if (_displaced_problem)
6740 0 : _displaced_problem->preparePRefinement();
6741 : }
6742 :
6743 : // do not assemble system matrix for JFNK solve
6744 118999 : for (auto & nl : _nl)
6745 59107 : if (solverParams(nl->number())._type == Moose::ST_JFNK)
6746 120 : nl->turnOffJacobian();
6747 :
6748 120031 : for (auto & sys : _solver_systems)
6749 60139 : sys->preInit();
6750 59892 : _aux->preInit();
6751 :
6752 : // Build the mortar segment meshes, if they haven't been already, for a couple reasons:
6753 : // 1) Get the ghosting correct for both static and dynamic meshes
6754 : // 2) Make sure the mortar mesh is built for mortar constraints that live on the static mesh
6755 : //
6756 : // It is worth-while to note that mortar meshes that live on a dynamic mesh will be built
6757 : // during residual and Jacobian evaluation because when displacements are solution variables
6758 : // the mortar mesh will move and change during the course of a non-linear solve. We DO NOT
6759 : // redo ghosting during non-linear solve, so for purpose 1) the below call has to be made
6760 59892 : if (!_mortar_data->initialized())
6761 44615 : updateMortarMesh();
6762 :
6763 : {
6764 299460 : TIME_SECTION("EquationSystems::Init", 2, "Initializing Equation Systems");
6765 59892 : es().init();
6766 59892 : }
6767 :
6768 120031 : for (auto & sys : _solver_systems)
6769 60139 : sys->postInit();
6770 59892 : _aux->postInit();
6771 :
6772 : // Now that the equation system and the dof distribution is done, we can generate the
6773 : // finite volume-related parts if needed.
6774 59892 : if (haveFV())
6775 4129 : _mesh.setupFiniteVolumeMeshData();
6776 :
6777 120031 : for (auto & sys : _solver_systems)
6778 60139 : sys->update();
6779 59892 : _aux->update();
6780 :
6781 125898 : for (THREAD_ID tid = 0; tid < libMesh::n_threads(); ++tid)
6782 131244 : for (const auto i : index_range(_nl))
6783 : {
6784 : mooseAssert(
6785 : _cm[i],
6786 : "Coupling matrix not set for system "
6787 : << i
6788 : << ". This should only happen if a preconditioner was not setup for this system");
6789 65238 : _assembly[tid][i]->init(_cm[i].get());
6790 : }
6791 :
6792 59892 : if (_displaced_problem)
6793 2022 : _displaced_problem->init();
6794 :
6795 : #ifdef MOOSE_KOKKOS_ENABLED
6796 45279 : if (_has_kokkos_objects)
6797 2265 : initKokkos();
6798 : #endif
6799 :
6800 59892 : _initialized = true;
6801 59892 : }
6802 :
6803 : unsigned int
6804 11889 : FEProblemBase::nlSysNum(const NonlinearSystemName & nl_sys_name) const
6805 : {
6806 11889 : std::istringstream ss(nl_sys_name);
6807 : unsigned int nl_sys_num;
6808 11889 : if (!(ss >> nl_sys_num) || !ss.eof())
6809 11889 : nl_sys_num = libmesh_map_find(_nl_sys_name_to_num, nl_sys_name);
6810 :
6811 11889 : return nl_sys_num;
6812 11889 : }
6813 :
6814 : unsigned int
6815 78396 : FEProblemBase::linearSysNum(const LinearSystemName & linear_sys_name) const
6816 : {
6817 78396 : std::istringstream ss(linear_sys_name);
6818 : unsigned int linear_sys_num;
6819 78396 : if (!(ss >> linear_sys_num) || !ss.eof())
6820 78396 : linear_sys_num = libmesh_map_find(_linear_sys_name_to_num, linear_sys_name);
6821 :
6822 78396 : return linear_sys_num;
6823 78396 : }
6824 :
6825 : unsigned int
6826 123064 : FEProblemBase::solverSysNum(const SolverSystemName & solver_sys_name) const
6827 : {
6828 123064 : std::istringstream ss(solver_sys_name);
6829 : unsigned int solver_sys_num;
6830 123064 : if (!(ss >> solver_sys_num) || !ss.eof())
6831 : {
6832 123064 : const auto & search = _solver_sys_name_to_num.find(solver_sys_name);
6833 123064 : if (search == _solver_sys_name_to_num.end())
6834 0 : mooseError("The solver system number was requested for system '" + solver_sys_name,
6835 : "' but this system does not exist in the Problem. Systems can be added to the "
6836 : "problem using the 'nl_sys_names'/'linear_sys_names' parameter.\nSystems in the "
6837 0 : "Problem: " +
6838 0 : Moose::stringify(_solver_sys_names));
6839 123064 : solver_sys_num = search->second;
6840 : }
6841 :
6842 123064 : return solver_sys_num;
6843 123064 : }
6844 :
6845 : unsigned int
6846 1644 : FEProblemBase::systemNumForVariable(const VariableName & variable_name) const
6847 : {
6848 1746 : for (const auto & solver_sys : _solver_systems)
6849 1644 : if (solver_sys->hasVariable(variable_name))
6850 1542 : return solver_sys->number();
6851 : mooseAssert(_aux, "Should have an auxiliary system");
6852 102 : if (_aux->hasVariable(variable_name))
6853 102 : return _aux->number();
6854 :
6855 0 : mooseError("Variable '",
6856 : variable_name,
6857 : "' was not found in any solver (nonlinear/linear) or auxiliary system");
6858 : }
6859 :
6860 : void
6861 318248 : FEProblemBase::solve(const unsigned int nl_sys_num)
6862 : {
6863 1591240 : TIME_SECTION("solve", 1, "Solving", false);
6864 :
6865 318248 : setCurrentNonlinearSystem(nl_sys_num);
6866 :
6867 : // This prevents stale dof indices from lingering around and possibly leading to invalid reads
6868 : // and writes. Dof indices may be made stale through operations like mesh adaptivity
6869 318248 : clearAllDofIndices();
6870 318248 : if (_displaced_problem)
6871 32837 : _displaced_problem->clearAllDofIndices();
6872 :
6873 : // Setup the output system for printing linear/nonlinear iteration information and some solver
6874 : // settings, including setting matrix prefixes. This must occur before petscSetOptions
6875 318248 : initPetscOutputAndSomeSolverSettings();
6876 :
6877 : #if PETSC_RELEASE_LESS_THAN(3, 12, 0)
6878 : Moose::PetscSupport::petscSetOptions(
6879 : _petsc_options, _solver_params); // Make sure the PETSc options are setup for this app
6880 : #else
6881 : // Now this database will be the default
6882 : // Each app should have only one database
6883 318248 : if (!_app.isUltimateMaster())
6884 82839 : LibmeshPetscCall(PetscOptionsPush(_petsc_option_data_base));
6885 : // We did not add PETSc options to database yet
6886 318248 : if (!_is_petsc_options_inserted)
6887 : {
6888 : // Insert options for all systems all at once
6889 38959 : Moose::PetscSupport::petscSetOptions(_petsc_options, _solver_params, this);
6890 38956 : _is_petsc_options_inserted = true;
6891 : }
6892 : #endif
6893 :
6894 : // set up DM which is required if use a field split preconditioner
6895 : // We need to setup DM every "solve()" because libMesh destroy SNES after solve()
6896 : // Do not worry, DM setup is very cheap
6897 318245 : _current_nl_sys->setupDM();
6898 :
6899 318245 : possiblyRebuildGeomSearchPatches();
6900 :
6901 : // reset flag so that residual evaluation does not get skipped
6902 : // and the next non-linear iteration does not automatically fail with
6903 : // "DIVERGED_NANORINF", when we throw an exception and stop solve
6904 318245 : _fail_next_system_convergence_check = false;
6905 :
6906 318245 : if (_solve)
6907 : {
6908 287722 : _current_nl_sys->solve();
6909 287667 : _current_nl_sys->update();
6910 : }
6911 :
6912 : // sync solutions in displaced problem
6913 318190 : if (_displaced_problem)
6914 32834 : _displaced_problem->syncSolutions();
6915 :
6916 : #if !PETSC_RELEASE_LESS_THAN(3, 12, 0)
6917 318190 : if (!_app.isUltimateMaster())
6918 82839 : LibmeshPetscCall(PetscOptionsPop());
6919 : #endif
6920 318190 : }
6921 :
6922 : void
6923 205 : FEProblemBase::setException(const std::string & message)
6924 : {
6925 205 : _has_exception = true;
6926 205 : _exception_message = message;
6927 205 : }
6928 :
6929 : void
6930 19882068 : FEProblemBase::checkExceptionAndStopSolve(bool print_message)
6931 : {
6932 19882068 : if (_skip_exception_check)
6933 216 : return;
6934 :
6935 59645556 : TIME_SECTION("checkExceptionAndStopSolve", 5);
6936 :
6937 : // See if any processor had an exception. If it did, get back the
6938 : // processor that the exception occurred on.
6939 : unsigned int processor_id;
6940 :
6941 19881852 : _communicator.maxloc(_has_exception, processor_id);
6942 :
6943 19881852 : if (_has_exception)
6944 : {
6945 302 : _communicator.broadcast(_exception_message, processor_id);
6946 :
6947 432 : if (_current_execute_on_flag == EXEC_LINEAR || _current_execute_on_flag == EXEC_NONLINEAR ||
6948 130 : _current_execute_on_flag == EXEC_POSTCHECK)
6949 : {
6950 : // Print the message
6951 302 : if (_communicator.rank() == 0 && print_message)
6952 : {
6953 184 : _console << "\n" << _exception_message << "\n";
6954 184 : if (isTransient())
6955 : _console
6956 : << "To recover, the solution will fail and then be re-attempted with a reduced time "
6957 172 : "step.\n"
6958 172 : << std::endl;
6959 : }
6960 :
6961 : // Stop the solve -- this entails setting
6962 : // SNESSetFunctionDomainError() or directly inserting NaNs in the
6963 : // residual vector to let PETSc >= 3.6 return DIVERGED_NANORINF.
6964 302 : if (_current_nl_sys)
6965 302 : _current_nl_sys->stopSolve(_current_execute_on_flag, _fe_vector_tags);
6966 :
6967 302 : if (_current_linear_sys)
6968 0 : _current_linear_sys->stopSolve(_current_execute_on_flag, _fe_vector_tags);
6969 :
6970 : // and close Aux system (we MUST do this here; see #11525)
6971 302 : _aux->solution().close();
6972 :
6973 : // We've handled this exception, so we no longer have one.
6974 302 : _has_exception = false;
6975 :
6976 : // Force the next non-linear convergence check to fail (and all further residual evaluation
6977 : // to be skipped).
6978 302 : _fail_next_system_convergence_check = true;
6979 :
6980 : // Repropagate the exception, so it can be caught at a higher level, typically
6981 : // this is NonlinearSystem::computeResidual().
6982 302 : throw MooseException(_exception_message);
6983 : }
6984 : else
6985 0 : mooseError("The following parallel-communicated exception was detected during " +
6986 0 : Moose::stringify(_current_execute_on_flag) + " evaluation:\n" +
6987 0 : _exception_message +
6988 : "\nBecause this did not occur during residual evaluation, there"
6989 : " is no way to handle this, so the solution is aborting.\n");
6990 : }
6991 19881852 : }
6992 :
6993 : void
6994 3527833 : FEProblemBase::resetState()
6995 : {
6996 : // Our default state is to allow computing derivatives
6997 3527833 : ADReal::do_derivatives = true;
6998 3527833 : _current_execute_on_flag = EXEC_NONE;
6999 :
7000 : // Clear the VectorTags and MatrixTags
7001 3527833 : clearCurrentResidualVectorTags();
7002 3527833 : clearCurrentJacobianMatrixTags();
7003 :
7004 3527833 : _safe_access_tagged_vectors = true;
7005 3527833 : _safe_access_tagged_matrices = true;
7006 :
7007 3527833 : setCurrentlyComputingResidual(false);
7008 3527833 : setCurrentlyComputingJacobian(false);
7009 3527833 : setCurrentlyComputingResidualAndJacobian(false);
7010 3527833 : if (_displaced_problem)
7011 : {
7012 145291 : _displaced_problem->setCurrentlyComputingResidual(false);
7013 145291 : _displaced_problem->setCurrentlyComputingJacobian(false);
7014 145291 : _displaced_problem->setCurrentlyComputingResidualAndJacobian(false);
7015 : }
7016 3527833 : }
7017 :
7018 : void
7019 26086 : FEProblemBase::solveLinearSystem(const unsigned int linear_sys_num,
7020 : const Moose::PetscSupport::PetscOptions * po)
7021 : {
7022 130430 : TIME_SECTION("solve", 1, "Solving", false);
7023 :
7024 26086 : setCurrentLinearSystem(linear_sys_num);
7025 :
7026 26086 : const Moose::PetscSupport::PetscOptions & options = po ? *po : _petsc_options;
7027 26086 : auto & solver_params = _solver_params[numNonlinearSystems() + linear_sys_num];
7028 :
7029 : // Set custom convergence criteria
7030 26086 : Moose::PetscSupport::petscSetDefaults(*this);
7031 :
7032 : #if PETSC_RELEASE_LESS_THAN(3, 12, 0)
7033 : LibmeshPetscCall(Moose::PetscSupport::petscSetOptions(
7034 : options, solver_params)); // Make sure the PETSc options are setup for this app
7035 : #else
7036 : // Now this database will be the default
7037 : // Each app should have only one database
7038 26086 : if (!_app.isUltimateMaster())
7039 195 : LibmeshPetscCall(PetscOptionsPush(_petsc_option_data_base));
7040 :
7041 : // We did not add PETSc options to database yet
7042 26086 : if (!_is_petsc_options_inserted)
7043 : {
7044 942 : Moose::PetscSupport::petscSetOptions(options, solver_params, this);
7045 942 : _is_petsc_options_inserted = true;
7046 : }
7047 : #endif
7048 :
7049 26086 : if (_solve)
7050 26076 : _current_linear_sys->solve();
7051 :
7052 : #if !PETSC_RELEASE_LESS_THAN(3, 12, 0)
7053 26086 : if (!_app.isUltimateMaster())
7054 195 : LibmeshPetscCall(PetscOptionsPop());
7055 : #endif
7056 26086 : }
7057 :
7058 : bool
7059 334906 : FEProblemBase::solverSystemConverged(const unsigned int sys_num)
7060 : {
7061 334906 : if (_solve)
7062 334884 : return _solver_systems[sys_num]->converged();
7063 : else
7064 22 : return true;
7065 : }
7066 :
7067 : unsigned int
7068 4901 : FEProblemBase::nNonlinearIterations(const unsigned int nl_sys_num) const
7069 : {
7070 4901 : return _nl[nl_sys_num]->nNonlinearIterations();
7071 : }
7072 :
7073 : unsigned int
7074 4051 : FEProblemBase::nLinearIterations(const unsigned int nl_sys_num) const
7075 : {
7076 4051 : return _nl[nl_sys_num]->nLinearIterations();
7077 : }
7078 :
7079 : Real
7080 242 : FEProblemBase::finalNonlinearResidual(const unsigned int nl_sys_num) const
7081 : {
7082 242 : return _nl[nl_sys_num]->finalNonlinearResidual();
7083 : }
7084 :
7085 : bool
7086 760320 : FEProblemBase::computingPreSMOResidual(const unsigned int nl_sys_num) const
7087 : {
7088 760320 : return _nl[nl_sys_num]->computingPreSMOResidual();
7089 : }
7090 :
7091 : void
7092 54435 : FEProblemBase::copySolutionsBackwards()
7093 : {
7094 272175 : TIME_SECTION("copySolutionsBackwards", 3, "Copying Solutions Backward");
7095 :
7096 109099 : for (auto & sys : _solver_systems)
7097 54664 : sys->copySolutionsBackwards();
7098 54435 : _aux->copySolutionsBackwards();
7099 54435 : }
7100 :
7101 : void
7102 152 : FEProblemBase::skipNextForwardSolutionCopyToOld()
7103 : {
7104 324 : for (auto & sys : _solver_systems)
7105 172 : sys->skipNextSolutionToOldCopy();
7106 152 : _aux->skipNextSolutionToOldCopy();
7107 152 : }
7108 :
7109 : void
7110 229029 : FEProblemBase::advanceState()
7111 : {
7112 1145145 : TIME_SECTION("advanceState", 5, "Advancing State");
7113 :
7114 461405 : for (auto & sys : _solver_systems)
7115 232376 : sys->copyOldSolutions();
7116 229029 : _aux->copyOldSolutions();
7117 :
7118 229029 : if (_displaced_problem)
7119 : {
7120 61858 : for (const auto i : index_range(_solver_systems))
7121 30929 : _displaced_problem->solverSys(i).copyOldSolutions();
7122 30929 : _displaced_problem->auxSys().copyOldSolutions();
7123 : }
7124 :
7125 229029 : _reporter_data.copyValuesBack();
7126 :
7127 229029 : getMooseApp().getChainControlDataSystem().copyValuesBack();
7128 :
7129 229029 : if (_material_props.hasStatefulProperties())
7130 1760 : _material_props.shift();
7131 :
7132 229029 : if (_bnd_material_props.hasStatefulProperties())
7133 1612 : _bnd_material_props.shift();
7134 :
7135 229029 : if (_neighbor_material_props.hasStatefulProperties())
7136 1496 : _neighbor_material_props.shift();
7137 :
7138 : #ifdef MOOSE_KOKKOS_ENABLED
7139 168094 : if (_kokkos_material_props.hasStatefulProperties())
7140 566 : _kokkos_material_props.shift();
7141 :
7142 168094 : if (_kokkos_bnd_material_props.hasStatefulProperties())
7143 641 : _kokkos_bnd_material_props.shift();
7144 :
7145 168094 : if (_kokkos_neighbor_material_props.hasStatefulProperties())
7146 566 : _kokkos_neighbor_material_props.shift();
7147 : #endif
7148 229029 : }
7149 :
7150 : void
7151 3299 : FEProblemBase::restoreSolutions()
7152 : {
7153 16495 : TIME_SECTION("restoreSolutions", 5, "Restoring Solutions");
7154 :
7155 3299 : if (!_not_zeroed_tagged_vectors.empty())
7156 0 : paramError("not_zeroed_tag_vectors",
7157 : "There is currently no way to restore not-zeroed vectors.");
7158 :
7159 6600 : for (auto & sys : _solver_systems)
7160 : {
7161 3301 : if (_verbose_restore)
7162 309 : _console << "Restoring solutions on system " << sys->name() << "..." << std::endl;
7163 3301 : sys->restoreSolutions();
7164 : }
7165 :
7166 3299 : if (_verbose_restore)
7167 308 : _console << "Restoring solutions on Auxiliary system..." << std::endl;
7168 3299 : _aux->restoreSolutions();
7169 :
7170 3299 : if (_verbose_restore)
7171 308 : _console << "Restoring postprocessor, vector-postprocessor, and reporter data..." << std::endl;
7172 3299 : _reporter_data.restoreState(_verbose_restore);
7173 :
7174 3299 : if (_displaced_problem)
7175 132 : _displaced_problem->updateMesh();
7176 3299 : }
7177 :
7178 : void
7179 100 : FEProblemBase::saveOldSolutions()
7180 : {
7181 500 : TIME_SECTION("saveOldSolutions", 5, "Saving Old Solutions");
7182 :
7183 200 : for (auto & sys : _solver_systems)
7184 100 : sys->saveOldSolutions();
7185 100 : _aux->saveOldSolutions();
7186 100 : }
7187 :
7188 : void
7189 100 : FEProblemBase::restoreOldSolutions()
7190 : {
7191 500 : TIME_SECTION("restoreOldSolutions", 5, "Restoring Old Solutions");
7192 :
7193 200 : for (auto & sys : _solver_systems)
7194 100 : sys->restoreOldSolutions();
7195 100 : _aux->restoreOldSolutions();
7196 100 : }
7197 :
7198 : void
7199 1229322 : FEProblemBase::outputStep(ExecFlagType type)
7200 : {
7201 6146610 : TIME_SECTION("outputStep", 1, "Outputting");
7202 :
7203 1229322 : setCurrentExecuteOnFlag(type);
7204 :
7205 2472754 : for (auto & sys : _solver_systems)
7206 1243432 : sys->update();
7207 1229322 : _aux->update();
7208 :
7209 1229322 : if (_displaced_problem)
7210 126253 : _displaced_problem->syncSolutions();
7211 1229322 : _app.getOutputWarehouse().outputStep(type);
7212 :
7213 1229313 : setCurrentExecuteOnFlag(EXEC_NONE);
7214 1229313 : }
7215 :
7216 : void
7217 83513 : FEProblemBase::allowOutput(bool state)
7218 : {
7219 83513 : _app.getOutputWarehouse().allowOutput(state);
7220 83513 : }
7221 :
7222 : void
7223 23 : FEProblemBase::forceOutput()
7224 : {
7225 23 : _app.getOutputWarehouse().forceOutput();
7226 23 : }
7227 :
7228 : void
7229 337273 : FEProblemBase::initPetscOutputAndSomeSolverSettings()
7230 : {
7231 337273 : _app.getOutputWarehouse().solveSetup();
7232 337273 : Moose::PetscSupport::petscSetDefaults(*this);
7233 337273 : }
7234 :
7235 : void
7236 235812 : FEProblemBase::onTimestepBegin()
7237 : {
7238 707436 : TIME_SECTION("onTimestepBegin", 2);
7239 :
7240 474665 : for (auto & nl : _nl)
7241 238853 : nl->onTimestepBegin();
7242 235812 : }
7243 :
7244 : void
7245 309095 : FEProblemBase::onTimestepEnd()
7246 : {
7247 309095 : }
7248 :
7249 : Real
7250 4628031 : FEProblemBase::getTimeFromStateArg(const Moose::StateArg & state) const
7251 : {
7252 4628031 : if (state.iteration_type != Moose::SolutionIterationType::Time)
7253 : // If we are any iteration type other than time (e.g. nonlinear), then temporally we are still
7254 : // in the present time
7255 0 : return time();
7256 :
7257 4628031 : switch (state.state)
7258 : {
7259 4628031 : case 0:
7260 4628031 : return time();
7261 :
7262 0 : case 1:
7263 0 : return timeOld();
7264 :
7265 0 : default:
7266 0 : mooseError("Unhandled state ", state.state, " in FEProblemBase::getTimeFromStateArg");
7267 : }
7268 : }
7269 :
7270 : void
7271 30038 : FEProblemBase::addTimeIntegrator(const std::string & type,
7272 : const std::string & name,
7273 : InputParameters & parameters)
7274 : {
7275 : parallel_object_only();
7276 :
7277 90114 : parameters.set<SubProblem *>("_subproblem") = this;
7278 30038 : logAdd("TimeIntegrator", name, type, parameters);
7279 30038 : _aux->addTimeIntegrator(type, name + ":aux", parameters);
7280 60103 : for (auto & sys : _solver_systems)
7281 30065 : sys->addTimeIntegrator(type, name + ":" + sys->name(), parameters);
7282 30038 : _has_time_integrator = true;
7283 :
7284 : // add vectors to store u_dot, u_dotdot, udot_old, u_dotdot_old and
7285 : // solution vectors older than 2 time steps, if requested by the time
7286 : // integrator
7287 30038 : _aux->addDotVectors();
7288 60072 : for (auto & nl : _nl)
7289 : {
7290 30034 : nl->addDotVectors();
7291 :
7292 30034 : auto tag_udot = nl->getTimeIntegrators()[0]->uDotFactorTag();
7293 30034 : if (!nl->hasVector(tag_udot))
7294 29998 : nl->associateVectorToTag(*nl->solutionUDot(), tag_udot);
7295 30034 : auto tag_udotdot = nl->getTimeIntegrators()[0]->uDotDotFactorTag();
7296 30034 : if (!nl->hasVector(tag_udotdot) && uDotDotRequested())
7297 150 : nl->associateVectorToTag(*nl->solutionUDotDot(), tag_udotdot);
7298 : }
7299 :
7300 30038 : if (_displaced_problem)
7301 : // Time integrator does not exist when displaced problem is created.
7302 1728 : _displaced_problem->addTimeIntegrator();
7303 30038 : }
7304 :
7305 : void
7306 22 : FEProblemBase::addPredictor(const std::string & type,
7307 : const std::string & name,
7308 : InputParameters & parameters)
7309 : {
7310 : parallel_object_only();
7311 :
7312 22 : if (!numNonlinearSystems() && numLinearSystems())
7313 0 : mooseError("Vector bounds cannot be used with LinearSystems!");
7314 :
7315 44 : parameters.set<SubProblem *>("_subproblem") = this;
7316 22 : std::shared_ptr<Predictor> predictor = _factory.create<Predictor>(type, name, parameters);
7317 22 : logAdd("Predictor", name, type, parameters);
7318 :
7319 44 : for (auto & nl : _nl)
7320 22 : nl->setPredictor(predictor);
7321 22 : }
7322 :
7323 : Real
7324 62579 : FEProblemBase::computeResidualL2Norm(NonlinearSystemBase & sys)
7325 : {
7326 62579 : _current_nl_sys = &sys;
7327 62579 : computeResidual(*sys.currentSolution(), sys.RHS(), sys.number());
7328 62579 : return sys.RHS().l2_norm();
7329 : }
7330 :
7331 : Real
7332 84 : FEProblemBase::computeResidualL2Norm(LinearSystem & sys)
7333 : {
7334 84 : _current_linear_sys = &sys;
7335 :
7336 : // We assemble the current system to check the current residual
7337 84 : computeLinearSystemSys(sys.linearImplicitSystem(),
7338 84 : *sys.linearImplicitSystem().matrix,
7339 84 : *sys.linearImplicitSystem().rhs,
7340 : /*compute fresh gradients*/ true);
7341 :
7342 : // Unfortunate, but we have to allocate a new vector for the residual
7343 84 : auto residual = sys.linearImplicitSystem().rhs->clone();
7344 84 : residual->scale(-1.0);
7345 84 : residual->add_vector(*sys.currentSolution(), *sys.linearImplicitSystem().matrix);
7346 168 : return residual->l2_norm();
7347 84 : }
7348 :
7349 : Real
7350 62633 : FEProblemBase::computeResidualL2Norm()
7351 : {
7352 313165 : TIME_SECTION("computeResidualL2Norm", 2, "Computing L2 Norm of Residual");
7353 :
7354 : // We use sum the squared norms of the individual systems and then take the square root of it
7355 62633 : Real l2_norm = 0.0;
7356 125212 : for (auto sys : _nl)
7357 : {
7358 62579 : const auto norm = computeResidualL2Norm(*sys);
7359 62579 : l2_norm += norm * norm;
7360 62579 : }
7361 :
7362 62717 : for (auto sys : _linear_systems)
7363 : {
7364 84 : const auto norm = computeResidualL2Norm(*sys);
7365 84 : l2_norm += norm * norm;
7366 84 : }
7367 :
7368 125266 : return std::sqrt(l2_norm);
7369 62633 : }
7370 :
7371 : void
7372 2940108 : FEProblemBase::computeResidualSys(NonlinearImplicitSystem & sys,
7373 : const NumericVector<Number> & soln,
7374 : NumericVector<Number> & residual)
7375 : {
7376 : parallel_object_only();
7377 :
7378 8820324 : TIME_SECTION("computeResidualSys", 5);
7379 : // Reset before residual setup, calculation & execution
7380 2940108 : _app.solutionInvalidity().resetIterationOccurences();
7381 :
7382 2940108 : computeResidual(soln, residual, sys.number());
7383 2940078 : }
7384 :
7385 : void
7386 0 : FEProblemBase::computeResidual(NonlinearImplicitSystem & sys,
7387 : const NumericVector<Number> & soln,
7388 : NumericVector<Number> & residual)
7389 : {
7390 0 : mooseDeprecated("Please use computeResidualSys");
7391 :
7392 0 : computeResidualSys(sys, soln, residual);
7393 0 : }
7394 :
7395 : void
7396 2999509 : FEProblemBase::computeResidual(const NumericVector<Number> & soln,
7397 : NumericVector<Number> & residual,
7398 : const unsigned int nl_sys_num)
7399 : {
7400 2999509 : setCurrentNonlinearSystem(nl_sys_num);
7401 :
7402 : // We associate the residual tag with the given residual vector to make sure we
7403 : // don't filter it out below
7404 2999509 : _current_nl_sys->associateVectorToTag(residual, _current_nl_sys->residualVectorTag());
7405 2999509 : const auto & residual_vector_tags = getVectorTags(Moose::VECTOR_TAG_RESIDUAL);
7406 :
7407 : mooseAssert(_fe_vector_tags.empty(), "This should be empty indicating a clean starting state");
7408 : // We filter out tags which do not have associated vectors in the current nonlinear
7409 : // system. This is essential to be able to use system-dependent residual tags.
7410 2999509 : selectVectorTagsFromSystem(*_current_nl_sys, residual_vector_tags, _fe_vector_tags);
7411 :
7412 2999509 : computeResidualInternal(soln, residual, _fe_vector_tags);
7413 2999479 : _fe_vector_tags.clear();
7414 2999479 : }
7415 :
7416 : void
7417 9598 : FEProblemBase::computeResidualAndJacobian(const NumericVector<Number> & soln,
7418 : NumericVector<Number> & residual,
7419 : SparseMatrix<Number> & jacobian)
7420 : {
7421 : try
7422 : {
7423 : try
7424 : {
7425 : // vector tags
7426 9598 : _current_nl_sys->associateVectorToTag(residual, _current_nl_sys->residualVectorTag());
7427 9598 : const auto & residual_vector_tags = getVectorTags(Moose::VECTOR_TAG_RESIDUAL);
7428 :
7429 : mooseAssert(_fe_vector_tags.empty(),
7430 : "This should be empty indicating a clean starting state");
7431 : // We filter out tags which do not have associated vectors in the current nonlinear
7432 : // system. This is essential to be able to use system-dependent residual tags.
7433 9598 : selectVectorTagsFromSystem(*_current_nl_sys, residual_vector_tags, _fe_vector_tags);
7434 :
7435 9598 : setCurrentResidualVectorTags(_fe_vector_tags);
7436 :
7437 : // matrix tags
7438 : {
7439 9598 : _fe_matrix_tags.clear();
7440 :
7441 9598 : auto & tags = getMatrixTags();
7442 28794 : for (auto & tag : tags)
7443 19196 : _fe_matrix_tags.insert(tag.second);
7444 : }
7445 :
7446 9598 : _current_nl_sys->setSolution(soln);
7447 :
7448 9598 : _current_nl_sys->associateVectorToTag(residual, _current_nl_sys->residualVectorTag());
7449 9598 : _current_nl_sys->associateMatrixToTag(jacobian, _current_nl_sys->systemMatrixTag());
7450 :
7451 28794 : for (const auto tag : _fe_matrix_tags)
7452 19196 : if (_current_nl_sys->hasMatrix(tag))
7453 : {
7454 9598 : auto & matrix = _current_nl_sys->getMatrix(tag);
7455 9598 : matrix.zero();
7456 9598 : if (haveADObjects() && !_current_nl_sys->system().has_static_condensation())
7457 : // PETSc algorithms require diagonal allocations regardless of whether there is non-zero
7458 : // diagonal dependence. With global AD indexing we only add non-zero
7459 : // dependence, so PETSc will scream at us unless we artificially add the diagonals.
7460 123018 : for (auto index : make_range(matrix.row_start(), matrix.row_stop()))
7461 120004 : matrix.add(index, index, 0);
7462 : }
7463 :
7464 9598 : _aux->zeroVariablesForResidual();
7465 :
7466 9598 : unsigned int n_threads = libMesh::n_threads();
7467 :
7468 9598 : _current_execute_on_flag = EXEC_LINEAR;
7469 :
7470 : // Random interface objects
7471 9598 : for (const auto & it : _random_data_objects)
7472 0 : it.second->updateSeeds(EXEC_LINEAR);
7473 :
7474 9598 : setCurrentlyComputingResidual(true);
7475 9598 : setCurrentlyComputingJacobian(true);
7476 9598 : setCurrentlyComputingResidualAndJacobian(true);
7477 9598 : if (_displaced_problem)
7478 : {
7479 1057 : _displaced_problem->setCurrentlyComputingResidual(true);
7480 1057 : _displaced_problem->setCurrentlyComputingJacobian(true);
7481 1057 : _displaced_problem->setCurrentlyComputingResidualAndJacobian(true);
7482 : }
7483 :
7484 9598 : execTransfers(EXEC_LINEAR);
7485 :
7486 9598 : execMultiApps(EXEC_LINEAR);
7487 :
7488 20599 : for (unsigned int tid = 0; tid < n_threads; tid++)
7489 11001 : reinitScalars(tid);
7490 :
7491 9598 : computeUserObjects(EXEC_LINEAR, Moose::PRE_AUX);
7492 :
7493 9598 : _aux->residualSetup();
7494 :
7495 9598 : if (_displaced_problem)
7496 : {
7497 1057 : computeSystems(EXEC_PRE_DISPLACE);
7498 1057 : _displaced_problem->updateMesh();
7499 1057 : if (_mortar_data->hasDisplacedObjects())
7500 1057 : updateMortarMesh();
7501 : }
7502 :
7503 20599 : for (THREAD_ID tid = 0; tid < n_threads; tid++)
7504 : {
7505 11001 : _all_materials.residualSetup(tid);
7506 11001 : _functions.residualSetup(tid);
7507 : }
7508 :
7509 : #ifdef MOOSE_KOKKOS_ENABLED
7510 8637 : _kokkos_functions.residualSetup();
7511 : #endif
7512 :
7513 9598 : computeSystems(EXEC_LINEAR);
7514 :
7515 9598 : computeUserObjects(EXEC_LINEAR, Moose::POST_AUX);
7516 :
7517 9598 : executeControls(EXEC_LINEAR);
7518 :
7519 9598 : _app.getOutputWarehouse().residualSetup();
7520 :
7521 9598 : _safe_access_tagged_vectors = false;
7522 9598 : _safe_access_tagged_matrices = false;
7523 :
7524 9598 : _current_nl_sys->computeResidualAndJacobianTags(_fe_vector_tags, _fe_matrix_tags);
7525 :
7526 9598 : _current_nl_sys->disassociateMatrixFromTag(jacobian, _current_nl_sys->systemMatrixTag());
7527 9598 : _current_nl_sys->disassociateVectorFromTag(residual, _current_nl_sys->residualVectorTag());
7528 : }
7529 0 : catch (...)
7530 : {
7531 0 : handleException("computeResidualAndJacobian");
7532 0 : }
7533 : }
7534 0 : catch (const MooseException &)
7535 : {
7536 : // The buck stops here, we have already handled the exception by
7537 : // calling the system's stopSolve() method, it is now up to PETSc to return a
7538 : // "diverged" reason during the next solve.
7539 0 : }
7540 0 : catch (...)
7541 : {
7542 0 : mooseError("Unexpected exception type");
7543 0 : }
7544 :
7545 9598 : resetState();
7546 9598 : _fe_vector_tags.clear();
7547 9598 : _fe_matrix_tags.clear();
7548 9598 : }
7549 :
7550 : void
7551 0 : FEProblemBase::computeResidualTag(const NumericVector<Number> & soln,
7552 : NumericVector<Number> & residual,
7553 : TagID tag)
7554 : {
7555 : try
7556 : {
7557 0 : _current_nl_sys->setSolution(soln);
7558 :
7559 0 : _current_nl_sys->associateVectorToTag(residual, tag);
7560 :
7561 0 : computeResidualTags({tag});
7562 :
7563 0 : _current_nl_sys->disassociateVectorFromTag(residual, tag);
7564 : }
7565 0 : catch (MooseException & e)
7566 : {
7567 : // If a MooseException propagates all the way to here, it means
7568 : // that it was thrown from a MOOSE system where we do not
7569 : // (currently) properly support the throwing of exceptions, and
7570 : // therefore we have no choice but to error out. It may be
7571 : // *possible* to handle exceptions from other systems, but in the
7572 : // meantime, we don't want to silently swallow any unhandled
7573 : // exceptions here.
7574 0 : mooseError("An unhandled MooseException was raised during residual computation. Please "
7575 : "contact the MOOSE team for assistance.");
7576 0 : }
7577 0 : }
7578 :
7579 : void
7580 3003093 : FEProblemBase::computeResidualInternal(const NumericVector<Number> & soln,
7581 : NumericVector<Number> & residual,
7582 : const std::set<TagID> & tags)
7583 : {
7584 : parallel_object_only();
7585 :
7586 9009279 : TIME_SECTION("computeResidualInternal", 1);
7587 :
7588 : try
7589 : {
7590 3003093 : _current_nl_sys->setSolution(soln);
7591 :
7592 3003093 : _current_nl_sys->associateVectorToTag(residual, _current_nl_sys->residualVectorTag());
7593 :
7594 3003093 : computeResidualTags(tags);
7595 :
7596 3003063 : _current_nl_sys->disassociateVectorFromTag(residual, _current_nl_sys->residualVectorTag());
7597 : }
7598 0 : catch (MooseException & e)
7599 : {
7600 : // If a MooseException propagates all the way to here, it means
7601 : // that it was thrown from a MOOSE system where we do not
7602 : // (currently) properly support the throwing of exceptions, and
7603 : // therefore we have no choice but to error out. It may be
7604 : // *possible* to handle exceptions from other systems, but in the
7605 : // meantime, we don't want to silently swallow any unhandled
7606 : // exceptions here.
7607 0 : mooseError("An unhandled MooseException was raised during residual computation. Please "
7608 : "contact the MOOSE team for assistance.");
7609 0 : }
7610 3003063 : }
7611 :
7612 : void
7613 0 : FEProblemBase::computeResidualType(const NumericVector<Number> & soln,
7614 : NumericVector<Number> & residual,
7615 : TagID tag)
7616 : {
7617 0 : TIME_SECTION("computeResidualType", 5);
7618 :
7619 : try
7620 : {
7621 0 : _current_nl_sys->setSolution(soln);
7622 :
7623 0 : _current_nl_sys->associateVectorToTag(residual, _current_nl_sys->residualVectorTag());
7624 :
7625 0 : computeResidualTags({tag, _current_nl_sys->residualVectorTag()});
7626 :
7627 0 : _current_nl_sys->disassociateVectorFromTag(residual, _current_nl_sys->residualVectorTag());
7628 : }
7629 0 : catch (MooseException & e)
7630 : {
7631 : // If a MooseException propagates all the way to here, it means
7632 : // that it was thrown from a MOOSE system where we do not
7633 : // (currently) properly support the throwing of exceptions, and
7634 : // therefore we have no choice but to error out. It may be
7635 : // *possible* to handle exceptions from other systems, but in the
7636 : // meantime, we don't want to silently swallow any unhandled
7637 : // exceptions here.
7638 0 : mooseError("An unhandled MooseException was raised during residual computation. Please "
7639 : "contact the MOOSE team for assistance.");
7640 0 : }
7641 0 : }
7642 :
7643 : void
7644 3 : FEProblemBase::handleException(const std::string & calling_method)
7645 : {
7646 : auto create_exception_message =
7647 3 : [&calling_method](const std::string & exception_type, const auto & exception)
7648 : {
7649 : return std::string("A " + exception_type + " was raised during FEProblemBase::" +
7650 6 : calling_method + "\n" + std::string(exception.what()));
7651 3 : };
7652 :
7653 : try
7654 : {
7655 3 : throw;
7656 : }
7657 3 : catch (const MooseException & e)
7658 : {
7659 0 : setException(create_exception_message("MooseException", e));
7660 0 : }
7661 0 : catch (const MetaPhysicL::LogicError & e)
7662 : {
7663 0 : moose::translateMetaPhysicLError(e);
7664 0 : }
7665 3 : catch (const libMesh::PetscSolverException & e)
7666 : {
7667 : // One PETSc solver exception that we cannot currently recover from are new nonzero errors. In
7668 : // particular I have observed the following scenario in a parallel test:
7669 : // - Both processes throw because of a new nonzero during MOOSE's computeJacobianTags
7670 : // - We potentially handle the exceptions nicely here
7671 : // - When the matrix is closed in libMesh's libmesh_petsc_snes_solver, there is a new nonzero
7672 : // throw which we do not catch here in MOOSE and the simulation terminates. This only appears
7673 : // in parallel (and not all the time; a test I was examining threw with distributed mesh, but
7674 : // not with replicated). In serial there are no new throws from libmesh_petsc_snes_solver.
7675 : // So for uniformity of behavior across serial/parallel, we will choose to abort here and always
7676 : // produce a non-zero exit code
7677 6 : mooseError(create_exception_message("libMesh::PetscSolverException", e));
7678 0 : }
7679 0 : catch (const std::exception & e)
7680 : {
7681 : // This might be libMesh detecting a degenerate Jacobian or matrix
7682 0 : if (strstr(e.what(), "Jacobian") || strstr(e.what(), "singular") ||
7683 0 : strstr(e.what(), "det != 0"))
7684 0 : setException(create_exception_message("libMesh DegenerateMap", e));
7685 : else
7686 : {
7687 0 : const auto message = create_exception_message("std::exception", e);
7688 0 : if (_regard_general_exceptions_as_errors)
7689 0 : mooseError(message);
7690 : else
7691 0 : setException(message);
7692 0 : }
7693 0 : }
7694 :
7695 0 : checkExceptionAndStopSolve();
7696 0 : }
7697 :
7698 : void
7699 3038494 : FEProblemBase::computeResidualTags(const std::set<TagID> & tags)
7700 : {
7701 : parallel_object_only();
7702 :
7703 : try
7704 : {
7705 : try
7706 : {
7707 15192470 : TIME_SECTION("computeResidualTags", 5, "Computing Residual");
7708 :
7709 3038494 : ADReal::do_derivatives = false;
7710 :
7711 3038494 : setCurrentResidualVectorTags(tags);
7712 :
7713 3038494 : _aux->zeroVariablesForResidual();
7714 :
7715 3038494 : unsigned int n_threads = libMesh::n_threads();
7716 :
7717 3038494 : _current_execute_on_flag = EXEC_LINEAR;
7718 :
7719 : // Random interface objects
7720 3051376 : for (const auto & it : _random_data_objects)
7721 12882 : it.second->updateSeeds(EXEC_LINEAR);
7722 :
7723 3038494 : execTransfers(EXEC_LINEAR);
7724 :
7725 3038494 : execMultiApps(EXEC_LINEAR);
7726 :
7727 6384435 : for (unsigned int tid = 0; tid < n_threads; tid++)
7728 3345941 : reinitScalars(tid);
7729 :
7730 3038494 : computeUserObjects(EXEC_LINEAR, Moose::PRE_AUX);
7731 :
7732 3038494 : _aux->residualSetup();
7733 :
7734 3038494 : if (_displaced_problem)
7735 : {
7736 123090 : computeSystems(EXEC_PRE_DISPLACE);
7737 123090 : _displaced_problem->updateMesh();
7738 123090 : if (_mortar_data->hasDisplacedObjects())
7739 2211 : updateMortarMesh();
7740 : }
7741 :
7742 6384435 : for (THREAD_ID tid = 0; tid < n_threads; tid++)
7743 : {
7744 3345941 : _all_materials.residualSetup(tid);
7745 3345941 : _functions.residualSetup(tid);
7746 : }
7747 :
7748 : #ifdef MOOSE_KOKKOS_ENABLED
7749 2209123 : _kokkos_functions.residualSetup();
7750 : #endif
7751 :
7752 3038494 : computeSystems(EXEC_LINEAR);
7753 :
7754 3038494 : computeUserObjects(EXEC_LINEAR, Moose::POST_AUX);
7755 :
7756 3038494 : executeControls(EXEC_LINEAR);
7757 :
7758 3038494 : _app.getOutputWarehouse().residualSetup();
7759 :
7760 3038494 : _safe_access_tagged_vectors = false;
7761 3038494 : _current_nl_sys->computeResidualTags(tags);
7762 3038464 : }
7763 0 : catch (...)
7764 : {
7765 0 : handleException("computeResidualTags");
7766 0 : }
7767 : }
7768 0 : catch (const MooseException &)
7769 : {
7770 : // The buck stops here, we have already handled the exception by
7771 : // calling the system's stopSolve() method, it is now up to PETSc to return a
7772 : // "diverged" reason during the next solve.
7773 0 : }
7774 0 : catch (...)
7775 : {
7776 0 : mooseError("Unexpected exception type");
7777 0 : }
7778 :
7779 3038464 : resetState();
7780 3038464 : }
7781 :
7782 : void
7783 471380 : FEProblemBase::computeJacobianSys(NonlinearImplicitSystem & sys,
7784 : const NumericVector<Number> & soln,
7785 : SparseMatrix<Number> & jacobian)
7786 : {
7787 : // Reset before Jacobian setup, calculation & execution
7788 471380 : _app.solutionInvalidity().resetIterationOccurences();
7789 471380 : computeJacobian(soln, jacobian, sys.number());
7790 471367 : }
7791 :
7792 : void
7793 4467 : FEProblemBase::computeJacobianTag(const NumericVector<Number> & soln,
7794 : SparseMatrix<Number> & jacobian,
7795 : TagID tag)
7796 : {
7797 4467 : _current_nl_sys->setSolution(soln);
7798 :
7799 4467 : _current_nl_sys->associateMatrixToTag(jacobian, tag);
7800 :
7801 8934 : computeJacobianTags({tag});
7802 :
7803 4467 : _current_nl_sys->disassociateMatrixFromTag(jacobian, tag);
7804 4467 : }
7805 :
7806 : void
7807 470536 : FEProblemBase::computeJacobian(const NumericVector<Number> & soln,
7808 : SparseMatrix<Number> & jacobian,
7809 : const unsigned int nl_sys_num)
7810 : {
7811 470536 : setCurrentNonlinearSystem(nl_sys_num);
7812 :
7813 470536 : _fe_matrix_tags.clear();
7814 :
7815 470536 : auto & tags = getMatrixTags();
7816 1411870 : for (auto & tag : tags)
7817 941334 : _fe_matrix_tags.insert(tag.second);
7818 :
7819 470536 : computeJacobianInternal(soln, jacobian, _fe_matrix_tags);
7820 470523 : }
7821 :
7822 : void
7823 470536 : FEProblemBase::computeJacobianInternal(const NumericVector<Number> & soln,
7824 : SparseMatrix<Number> & jacobian,
7825 : const std::set<TagID> & tags)
7826 : {
7827 1411608 : TIME_SECTION("computeJacobianInternal", 1);
7828 :
7829 470536 : _current_nl_sys->setSolution(soln);
7830 :
7831 470536 : _current_nl_sys->associateMatrixToTag(jacobian, _current_nl_sys->systemMatrixTag());
7832 :
7833 470536 : computeJacobianTags(tags);
7834 :
7835 470523 : _current_nl_sys->disassociateMatrixFromTag(jacobian, _current_nl_sys->systemMatrixTag());
7836 470523 : }
7837 :
7838 : void
7839 479784 : FEProblemBase::computeJacobianTags(const std::set<TagID> & tags)
7840 : {
7841 : try
7842 : {
7843 : try
7844 : {
7845 479784 : if (!_has_jacobian || !_const_jacobian)
7846 : {
7847 2366645 : TIME_SECTION("computeJacobianTags", 5, "Computing Jacobian");
7848 :
7849 1412657 : for (auto tag : tags)
7850 939328 : if (_current_nl_sys->hasMatrix(tag))
7851 : {
7852 475247 : auto & matrix = _current_nl_sys->getMatrix(tag);
7853 475247 : if (_restore_original_nonzero_pattern)
7854 7006 : matrix.restore_original_nonzero_pattern();
7855 : else
7856 468241 : matrix.zero();
7857 475247 : if (haveADObjects() && !_current_nl_sys->system().has_static_condensation())
7858 : // PETSc algorithms require diagonal allocations regardless of whether there is
7859 : // non-zero diagonal dependence. With global AD indexing we only add non-zero
7860 : // dependence, so PETSc will scream at us unless we artificially add the diagonals.
7861 4688718 : for (auto index : make_range(matrix.row_start(), matrix.row_stop()))
7862 4645468 : matrix.add(index, index, 0);
7863 : }
7864 :
7865 473329 : _aux->zeroVariablesForJacobian();
7866 :
7867 473329 : unsigned int n_threads = libMesh::n_threads();
7868 :
7869 : // Random interface objects
7870 475351 : for (const auto & it : _random_data_objects)
7871 2022 : it.second->updateSeeds(EXEC_NONLINEAR);
7872 :
7873 473329 : _current_execute_on_flag = EXEC_NONLINEAR;
7874 473329 : _currently_computing_jacobian = true;
7875 473329 : if (_displaced_problem)
7876 21147 : _displaced_problem->setCurrentlyComputingJacobian(true);
7877 :
7878 473329 : execTransfers(EXEC_NONLINEAR);
7879 473329 : execMultiApps(EXEC_NONLINEAR);
7880 :
7881 996704 : for (unsigned int tid = 0; tid < n_threads; tid++)
7882 523375 : reinitScalars(tid);
7883 :
7884 473329 : computeUserObjects(EXEC_NONLINEAR, Moose::PRE_AUX);
7885 :
7886 473329 : _aux->jacobianSetup();
7887 :
7888 473329 : if (_displaced_problem)
7889 : {
7890 21147 : computeSystems(EXEC_PRE_DISPLACE);
7891 21147 : _displaced_problem->updateMesh();
7892 : }
7893 :
7894 996697 : for (unsigned int tid = 0; tid < n_threads; tid++)
7895 : {
7896 523371 : _all_materials.jacobianSetup(tid);
7897 523371 : _functions.jacobianSetup(tid);
7898 : }
7899 :
7900 : #ifdef MOOSE_KOKKOS_ENABLED
7901 345224 : _kokkos_functions.jacobianSetup();
7902 : #endif
7903 :
7904 473326 : computeSystems(EXEC_NONLINEAR);
7905 :
7906 473326 : computeUserObjects(EXEC_NONLINEAR, Moose::POST_AUX);
7907 :
7908 473326 : executeControls(EXEC_NONLINEAR);
7909 :
7910 473326 : _app.getOutputWarehouse().jacobianSetup();
7911 :
7912 473326 : _safe_access_tagged_matrices = false;
7913 :
7914 473326 : _current_nl_sys->computeJacobianTags(tags);
7915 :
7916 : // For explicit Euler calculations for example we often compute the Jacobian one time and
7917 : // then re-use it over and over. If we're performing automatic scaling, we don't want to
7918 : // use that kernel, diagonal-block only Jacobian for our actual matrix when performing
7919 : // solves!
7920 473316 : if (!_current_nl_sys->computingScalingJacobian())
7921 472833 : _has_jacobian = true;
7922 473319 : }
7923 : }
7924 3 : catch (...)
7925 : {
7926 3 : handleException("computeJacobianTags");
7927 0 : }
7928 : }
7929 0 : catch (const MooseException &)
7930 : {
7931 : // The buck stops here, we have already handled the exception by
7932 : // calling the system's stopSolve() method, it is now up to PETSc to return a
7933 : // "diverged" reason during the next solve.
7934 0 : }
7935 0 : catch (...)
7936 : {
7937 0 : mooseError("Unexpected exception type");
7938 0 : }
7939 :
7940 479771 : resetState();
7941 479771 : }
7942 :
7943 : void
7944 263 : FEProblemBase::computeJacobianBlocks(std::vector<JacobianBlock *> & blocks,
7945 : const unsigned int nl_sys_num)
7946 : {
7947 789 : TIME_SECTION("computeTransientImplicitJacobian", 2);
7948 263 : setCurrentNonlinearSystem(nl_sys_num);
7949 :
7950 263 : if (_displaced_problem)
7951 : {
7952 0 : computeSystems(EXEC_PRE_DISPLACE);
7953 0 : _displaced_problem->updateMesh();
7954 : }
7955 :
7956 263 : computeSystems(EXEC_NONLINEAR);
7957 :
7958 263 : _currently_computing_jacobian = true;
7959 263 : _current_nl_sys->computeJacobianBlocks(blocks);
7960 263 : _currently_computing_jacobian = false;
7961 263 : }
7962 :
7963 : void
7964 0 : FEProblemBase::computeJacobianBlock(SparseMatrix<Number> & jacobian,
7965 : libMesh::System & precond_system,
7966 : unsigned int ivar,
7967 : unsigned int jvar)
7968 : {
7969 0 : JacobianBlock jac_block(precond_system, jacobian, ivar, jvar);
7970 0 : std::vector<JacobianBlock *> blocks = {&jac_block};
7971 : mooseAssert(_current_nl_sys, "This should be non-null");
7972 0 : computeJacobianBlocks(blocks, _current_nl_sys->number());
7973 0 : }
7974 :
7975 : void
7976 714 : FEProblemBase::computeBounds(NonlinearImplicitSystem & libmesh_dbg_var(sys),
7977 : NumericVector<Number> & lower,
7978 : NumericVector<Number> & upper)
7979 : {
7980 : try
7981 : {
7982 : try
7983 : {
7984 : mooseAssert(_current_nl_sys && (sys.number() == _current_nl_sys->number()),
7985 : "I expect these system numbers to be the same");
7986 :
7987 3570 : if (!_current_nl_sys->hasVector("lower_bound") || !_current_nl_sys->hasVector("upper_bound"))
7988 0 : return;
7989 :
7990 3570 : TIME_SECTION("computeBounds", 1, "Computing Bounds");
7991 :
7992 1428 : NumericVector<Number> & _lower = _current_nl_sys->getVector("lower_bound");
7993 1428 : NumericVector<Number> & _upper = _current_nl_sys->getVector("upper_bound");
7994 714 : _lower.swap(lower);
7995 714 : _upper.swap(upper);
7996 1492 : for (THREAD_ID tid = 0; tid < libMesh::n_threads(); tid++)
7997 778 : _all_materials.residualSetup(tid);
7998 :
7999 714 : _aux->residualSetup();
8000 714 : computeSystems(EXEC_LINEAR);
8001 714 : _lower.swap(lower);
8002 714 : _upper.swap(upper);
8003 714 : }
8004 0 : catch (...)
8005 : {
8006 0 : handleException("computeBounds");
8007 0 : }
8008 : }
8009 0 : catch (MooseException & e)
8010 : {
8011 0 : mooseError("Irrecoverable exception: " + std::string(e.what()));
8012 0 : }
8013 0 : catch (...)
8014 : {
8015 0 : mooseError("Unexpected exception type");
8016 0 : }
8017 : }
8018 :
8019 : void
8020 26160 : FEProblemBase::computeLinearSystemSys(LinearImplicitSystem & sys,
8021 : SparseMatrix<Number> & system_matrix,
8022 : NumericVector<Number> & rhs,
8023 : const bool compute_gradients)
8024 : {
8025 78480 : TIME_SECTION("computeLinearSystemSys", 5);
8026 :
8027 26160 : setCurrentLinearSystem(linearSysNum(sys.name()));
8028 :
8029 26160 : _current_linear_sys->associateVectorToTag(rhs, _current_linear_sys->rightHandSideVectorTag());
8030 26160 : _current_linear_sys->associateMatrixToTag(system_matrix, _current_linear_sys->systemMatrixTag());
8031 :
8032 : // We are using the residual tag system for right hand sides so we fetch everything
8033 26160 : const auto & vector_tags = getVectorTags(Moose::VECTOR_TAG_RESIDUAL);
8034 :
8035 : // We filter out tags which do not have associated vectors in the current
8036 : // system. This is essential to be able to use system-dependent vector tags.
8037 26160 : selectVectorTagsFromSystem(*_current_linear_sys, vector_tags, _linear_vector_tags);
8038 26160 : selectMatrixTagsFromSystem(*_current_linear_sys, getMatrixTags(), _linear_matrix_tags);
8039 :
8040 26160 : computeLinearSystemTags(*(_current_linear_sys->currentSolution()),
8041 26160 : _linear_vector_tags,
8042 26160 : _linear_matrix_tags,
8043 : compute_gradients);
8044 :
8045 26160 : _current_linear_sys->disassociateMatrixFromTag(system_matrix,
8046 26160 : _current_linear_sys->systemMatrixTag());
8047 26160 : _current_linear_sys->disassociateVectorFromTag(rhs,
8048 26160 : _current_linear_sys->rightHandSideVectorTag());
8049 : // We reset the tags to the default containers for further operations
8050 26160 : _current_linear_sys->associateVectorToTag(_current_linear_sys->getRightHandSideVector(),
8051 26160 : _current_linear_sys->rightHandSideVectorTag());
8052 26160 : _current_linear_sys->associateMatrixToTag(_current_linear_sys->getSystemMatrix(),
8053 26160 : _current_linear_sys->systemMatrixTag());
8054 26160 : }
8055 :
8056 : void
8057 26160 : FEProblemBase::computeLinearSystemTags(const NumericVector<Number> & soln,
8058 : const std::set<TagID> & vector_tags,
8059 : const std::set<TagID> & matrix_tags,
8060 : const bool compute_gradients)
8061 : {
8062 130800 : TIME_SECTION("computeLinearSystemTags", 5, "Computing Linear System");
8063 :
8064 26160 : _current_linear_sys->setSolution(soln);
8065 :
8066 52340 : for (auto tag : matrix_tags)
8067 : {
8068 26180 : auto & matrix = _current_linear_sys->getMatrix(tag);
8069 26180 : matrix.zero();
8070 : }
8071 :
8072 26160 : unsigned int n_threads = libMesh::n_threads();
8073 :
8074 26160 : _current_execute_on_flag = EXEC_NONLINEAR;
8075 :
8076 : // Random interface objects
8077 26160 : for (const auto & it : _random_data_objects)
8078 0 : it.second->updateSeeds(EXEC_NONLINEAR);
8079 :
8080 26160 : execTransfers(EXEC_NONLINEAR);
8081 26160 : execMultiApps(EXEC_NONLINEAR);
8082 :
8083 26160 : computeUserObjects(EXEC_NONLINEAR, Moose::PRE_AUX);
8084 :
8085 26160 : _aux->jacobianSetup();
8086 :
8087 52320 : for (THREAD_ID tid = 0; tid < n_threads; tid++)
8088 : {
8089 26160 : _functions.jacobianSetup(tid);
8090 : }
8091 :
8092 : #ifdef MOOSE_KOKKOS_ENABLED
8093 17995 : _kokkos_functions.jacobianSetup();
8094 : #endif
8095 :
8096 : try
8097 : {
8098 26160 : computeSystems(EXEC_NONLINEAR);
8099 : }
8100 0 : catch (MooseException & e)
8101 : {
8102 0 : _console << "\nA MooseException was raised during Auxiliary variable computation.\n"
8103 0 : << "The next solve will fail, the timestep will be reduced, and we will try again.\n"
8104 0 : << std::endl;
8105 :
8106 : // We know the next solve is going to fail, so there's no point in
8107 : // computing anything else after this. Plus, using incompletely
8108 : // computed AuxVariables in subsequent calculations could lead to
8109 : // other errors or unhandled exceptions being thrown.
8110 0 : return;
8111 0 : }
8112 :
8113 26160 : computeUserObjects(EXEC_NONLINEAR, Moose::POST_AUX);
8114 26160 : executeControls(EXEC_NONLINEAR);
8115 :
8116 26160 : _app.getOutputWarehouse().jacobianSetup();
8117 :
8118 26160 : _current_linear_sys->computeLinearSystemTags(vector_tags, matrix_tags, compute_gradients);
8119 :
8120 : // Reset execution flag as after this point we are no longer on LINEAR
8121 26160 : _current_execute_on_flag = EXEC_NONE;
8122 :
8123 : // These are the relevant parts of resetState()
8124 26160 : _safe_access_tagged_vectors = true;
8125 26160 : _safe_access_tagged_matrices = true;
8126 26160 : }
8127 :
8128 : void
8129 294851 : FEProblemBase::computeNearNullSpace(NonlinearImplicitSystem & libmesh_dbg_var(sys),
8130 : std::vector<NumericVector<Number> *> & sp)
8131 : {
8132 : mooseAssert(_current_nl_sys && (sys.number() == _current_nl_sys->number()),
8133 : "I expect these system numbers to be the same");
8134 :
8135 294851 : sp.clear();
8136 884553 : for (unsigned int i = 0; i < subspaceDim("NearNullSpace"); ++i)
8137 : {
8138 0 : std::stringstream postfix;
8139 0 : postfix << "_" << i;
8140 0 : std::string modename = "NearNullSpace" + postfix.str();
8141 0 : sp.push_back(&_current_nl_sys->getVector(modename));
8142 0 : }
8143 294851 : }
8144 :
8145 : void
8146 294851 : FEProblemBase::computeNullSpace(NonlinearImplicitSystem & libmesh_dbg_var(sys),
8147 : std::vector<NumericVector<Number> *> & sp)
8148 : {
8149 : mooseAssert(_current_nl_sys && (sys.number() == _current_nl_sys->number()),
8150 : "I expect these system numbers to be the same");
8151 294851 : sp.clear();
8152 884619 : for (unsigned int i = 0; i < subspaceDim("NullSpace"); ++i)
8153 : {
8154 22 : std::stringstream postfix;
8155 22 : postfix << "_" << i;
8156 22 : sp.push_back(&_current_nl_sys->getVector("NullSpace" + postfix.str()));
8157 22 : }
8158 294851 : }
8159 :
8160 : void
8161 294851 : FEProblemBase::computeTransposeNullSpace(NonlinearImplicitSystem & libmesh_dbg_var(sys),
8162 : std::vector<NumericVector<Number> *> & sp)
8163 : {
8164 : mooseAssert(_current_nl_sys && (sys.number() == _current_nl_sys->number()),
8165 : "I expect these system numbers to be the same");
8166 294851 : sp.clear();
8167 884586 : for (unsigned int i = 0; i < subspaceDim("TransposeNullSpace"); ++i)
8168 : {
8169 11 : std::stringstream postfix;
8170 11 : postfix << "_" << i;
8171 11 : sp.push_back(&_current_nl_sys->getVector("TransposeNullSpace" + postfix.str()));
8172 11 : }
8173 294851 : }
8174 :
8175 : void
8176 2128 : FEProblemBase::computePostCheck(NonlinearImplicitSystem & sys,
8177 : const NumericVector<Number> & old_soln,
8178 : NumericVector<Number> & search_direction,
8179 : NumericVector<Number> & new_soln,
8180 : bool & changed_search_direction,
8181 : bool & changed_new_soln)
8182 : {
8183 : mooseAssert(_current_nl_sys && (sys.number() == _current_nl_sys->number()),
8184 : "I expect these system numbers to be the same");
8185 :
8186 : // This function replaces the old PetscSupport::dampedCheck() function.
8187 : //
8188 : // 1.) Recreate code in PetscSupport::dampedCheck() for constructing
8189 : // ghosted "soln" and "update" vectors.
8190 : // 2.) Call FEProblemBase::computeDamping() with these ghost vectors.
8191 : // 3.) Recreate the code in PetscSupport::dampedCheck() to actually update
8192 : // the solution vector based on the damping, and set the "changed" flags
8193 : // appropriately.
8194 :
8195 10640 : TIME_SECTION("computePostCheck", 2, "Computing Post Check");
8196 :
8197 2128 : _current_execute_on_flag = EXEC_POSTCHECK;
8198 :
8199 : // MOOSE's FEProblemBase doesn't update the solution during the
8200 : // postcheck, but FEProblemBase-derived classes might.
8201 2128 : if (_has_dampers || shouldUpdateSolution())
8202 : {
8203 : // We need ghosted versions of new_soln and search_direction (the
8204 : // ones we get from libmesh/PETSc are PARALLEL vectors. To make
8205 : // our lives simpler, we use the same ghosting pattern as the
8206 : // system's current_local_solution to create new ghosted vectors.
8207 :
8208 : // Construct zeroed-out clones with the same ghosted dofs as the
8209 : // System's current_local_solution.
8210 : std::unique_ptr<NumericVector<Number>> ghosted_solution =
8211 1625 : sys.current_local_solution->zero_clone(),
8212 : ghosted_search_direction =
8213 1625 : sys.current_local_solution->zero_clone();
8214 :
8215 : // Copy values from input vectors into clones with ghosted values.
8216 1625 : *ghosted_solution = new_soln;
8217 1625 : *ghosted_search_direction = search_direction;
8218 :
8219 1625 : if (_has_dampers)
8220 : {
8221 : // Compute the damping coefficient using the ghosted vectors
8222 1625 : Real damping = computeDamping(*ghosted_solution, *ghosted_search_direction);
8223 :
8224 : // If some non-trivial damping was computed, update the new_soln
8225 : // vector accordingly.
8226 1625 : if (damping < 1.0)
8227 : {
8228 1222 : new_soln = old_soln;
8229 1222 : new_soln.add(-damping, search_direction);
8230 1222 : changed_new_soln = true;
8231 : }
8232 : }
8233 :
8234 1625 : if (shouldUpdateSolution())
8235 : {
8236 : // Update the ghosted copy of the new solution, if necessary.
8237 0 : if (changed_new_soln)
8238 0 : *ghosted_solution = new_soln;
8239 :
8240 0 : bool updated_solution = updateSolution(new_soln, *ghosted_solution);
8241 0 : if (updated_solution)
8242 0 : changed_new_soln = true;
8243 : }
8244 1625 : }
8245 :
8246 2128 : if (vectorTagExists(Moose::PREVIOUS_NL_SOLUTION_TAG))
8247 : {
8248 503 : _current_nl_sys->setPreviousNewtonSolution(old_soln);
8249 503 : _aux->copyCurrentIntoPreviousNL();
8250 : }
8251 :
8252 : // MOOSE doesn't change the search_direction
8253 2128 : changed_search_direction = false;
8254 :
8255 2128 : _current_execute_on_flag = EXEC_NONE;
8256 2128 : }
8257 :
8258 : Real
8259 1625 : FEProblemBase::computeDamping(const NumericVector<Number> & soln,
8260 : const NumericVector<Number> & update)
8261 : {
8262 : // Default to no damping
8263 1625 : Real damping = 1.0;
8264 :
8265 1625 : if (_has_dampers)
8266 : {
8267 8125 : TIME_SECTION("computeDamping", 1, "Computing Damping");
8268 :
8269 : // Save pointer to the current solution
8270 1625 : const NumericVector<Number> * _saved_current_solution = _current_nl_sys->currentSolution();
8271 :
8272 1625 : _current_nl_sys->setSolution(soln);
8273 : // For now, do not re-compute auxiliary variables. Doing so allows a wild solution increment
8274 : // to get to the material models, which may not be able to cope with drastically different
8275 : // values. Once more complete dependency checking is in place, auxiliary variables (and
8276 : // material properties) will be computed as needed by dampers.
8277 : // _aux.compute();
8278 1625 : damping = _current_nl_sys->computeDamping(soln, update);
8279 :
8280 : // restore saved solution
8281 1625 : _current_nl_sys->setSolution(*_saved_current_solution);
8282 1625 : }
8283 :
8284 1625 : return damping;
8285 : }
8286 :
8287 : bool
8288 289447 : FEProblemBase::shouldUpdateSolution()
8289 : {
8290 289447 : return false;
8291 : }
8292 :
8293 : bool
8294 0 : FEProblemBase::updateSolution(NumericVector<Number> & /*vec_solution*/,
8295 : NumericVector<Number> & /*ghosted_solution*/)
8296 : {
8297 0 : return false;
8298 : }
8299 :
8300 : void
8301 203 : FEProblemBase::predictorCleanup(NumericVector<Number> & /*ghosted_solution*/)
8302 : {
8303 203 : }
8304 :
8305 : void
8306 2022 : FEProblemBase::addDisplacedProblem(std::shared_ptr<DisplacedProblem> displaced_problem)
8307 : {
8308 : parallel_object_only();
8309 :
8310 2022 : _displaced_mesh = &displaced_problem->mesh();
8311 2022 : _displaced_problem = displaced_problem;
8312 2022 : }
8313 :
8314 : void
8315 119512 : FEProblemBase::updateGeomSearch(GeometricSearchData::GeometricSearchType type)
8316 : {
8317 597560 : TIME_SECTION("updateGeometricSearch", 3, "Updating Geometric Search");
8318 :
8319 119512 : _geometric_search_data.update(type);
8320 :
8321 119512 : if (_displaced_problem)
8322 4209 : _displaced_problem->updateGeomSearch(type);
8323 119512 : }
8324 :
8325 : void
8326 63274 : FEProblemBase::updateMortarMesh()
8327 : {
8328 316370 : TIME_SECTION("updateMortarMesh", 5, "Updating Mortar Mesh");
8329 :
8330 63274 : FloatingPointExceptionGuard fpe_guard(_app);
8331 :
8332 63274 : _mortar_data->update();
8333 63274 : }
8334 :
8335 : void
8336 1326 : FEProblemBase::createMortarInterface(
8337 : const std::pair<BoundaryID, BoundaryID> & primary_secondary_boundary_pair,
8338 : const std::pair<SubdomainID, SubdomainID> & primary_secondary_subdomain_pair,
8339 : bool on_displaced,
8340 : bool periodic,
8341 : const bool debug,
8342 : const bool correct_edge_dropping,
8343 : const Real minimum_projection_angle)
8344 : {
8345 1326 : _has_mortar = true;
8346 :
8347 1326 : if (on_displaced)
8348 254 : return _mortar_data->createMortarInterface(primary_secondary_boundary_pair,
8349 : primary_secondary_subdomain_pair,
8350 127 : *_displaced_problem,
8351 : on_displaced,
8352 : periodic,
8353 : debug,
8354 : correct_edge_dropping,
8355 127 : minimum_projection_angle);
8356 : else
8357 1199 : return _mortar_data->createMortarInterface(primary_secondary_boundary_pair,
8358 : primary_secondary_subdomain_pair,
8359 : *this,
8360 : on_displaced,
8361 : periodic,
8362 : debug,
8363 : correct_edge_dropping,
8364 1199 : minimum_projection_angle);
8365 : }
8366 :
8367 : const AutomaticMortarGeneration &
8368 0 : FEProblemBase::getMortarInterface(
8369 : const std::pair<BoundaryID, BoundaryID> & primary_secondary_boundary_pair,
8370 : const std::pair<SubdomainID, SubdomainID> & primary_secondary_subdomain_pair,
8371 : bool on_displaced) const
8372 : {
8373 0 : return _mortar_data->getMortarInterface(
8374 0 : primary_secondary_boundary_pair, primary_secondary_subdomain_pair, on_displaced);
8375 : }
8376 :
8377 : AutomaticMortarGeneration &
8378 165399 : FEProblemBase::getMortarInterface(
8379 : const std::pair<BoundaryID, BoundaryID> & primary_secondary_boundary_pair,
8380 : const std::pair<SubdomainID, SubdomainID> & primary_secondary_subdomain_pair,
8381 : bool on_displaced)
8382 : {
8383 165399 : return _mortar_data->getMortarInterface(
8384 165399 : primary_secondary_boundary_pair, primary_secondary_subdomain_pair, on_displaced);
8385 : }
8386 :
8387 : void
8388 318245 : FEProblemBase::possiblyRebuildGeomSearchPatches()
8389 : {
8390 318245 : if (_displaced_problem) // Only need to do this if things are moving...
8391 : {
8392 164185 : TIME_SECTION("possiblyRebuildGeomSearchPatches", 5, "Rebuilding Geometric Search Patches");
8393 :
8394 32837 : switch (_mesh.getPatchUpdateStrategy())
8395 : {
8396 31742 : case Moose::Never:
8397 31742 : break;
8398 365 : case Moose::Iteration:
8399 : // Update the list of ghosted elements at the start of the time step
8400 365 : _geometric_search_data.updateGhostedElems();
8401 365 : _mesh.updateActiveSemiLocalNodeRange(_ghosted_elems);
8402 :
8403 365 : _displaced_problem->geomSearchData().updateGhostedElems();
8404 365 : _displaced_mesh->updateActiveSemiLocalNodeRange(_ghosted_elems);
8405 :
8406 : // The commands below ensure that the sparsity of the Jacobian matrix is
8407 : // augmented at the start of the time step using neighbor nodes from the end
8408 : // of the previous time step.
8409 :
8410 365 : reinitBecauseOfGhostingOrNewGeomObjects();
8411 :
8412 : // This is needed to reinitialize PETSc output
8413 365 : initPetscOutputAndSomeSolverSettings();
8414 :
8415 365 : break;
8416 :
8417 331 : case Moose::Auto:
8418 : {
8419 331 : Real max = _displaced_problem->geomSearchData().maxPatchPercentage();
8420 331 : _communicator.max(max);
8421 :
8422 : // If we haven't moved very far through the patch
8423 331 : if (max < 0.4)
8424 298 : break;
8425 : }
8426 : libmesh_fallthrough();
8427 :
8428 : // Let this fall through if things do need to be updated...
8429 : case Moose::Always:
8430 : // Flush output here to see the message before the reinitialization, which could take a
8431 : // while
8432 432 : _console << "\n\nUpdating geometric search patches\n" << std::endl;
8433 :
8434 432 : _geometric_search_data.clearNearestNodeLocators();
8435 432 : _mesh.updateActiveSemiLocalNodeRange(_ghosted_elems);
8436 :
8437 432 : _displaced_problem->geomSearchData().clearNearestNodeLocators();
8438 432 : _displaced_mesh->updateActiveSemiLocalNodeRange(_ghosted_elems);
8439 :
8440 432 : reinitBecauseOfGhostingOrNewGeomObjects();
8441 :
8442 : // This is needed to reinitialize PETSc output
8443 432 : initPetscOutputAndSomeSolverSettings();
8444 : }
8445 32837 : }
8446 318245 : }
8447 :
8448 : #ifdef LIBMESH_ENABLE_AMR
8449 : void
8450 54933 : FEProblemBase::initialAdaptMesh()
8451 : {
8452 54933 : unsigned int n = adaptivity().getInitialSteps();
8453 54933 : _cycles_completed = 0;
8454 54933 : if (n)
8455 : {
8456 629 : if (!_mesh.interiorLowerDBlocks().empty() || !_mesh.boundaryLowerDBlocks().empty())
8457 3 : mooseError("HFEM does not support mesh adaptivity currently.");
8458 :
8459 3130 : TIME_SECTION("initialAdaptMesh", 2, "Performing Initial Adaptivity");
8460 :
8461 1506 : for (unsigned int i = 0; i < n; i++)
8462 : {
8463 1055 : computeIndicators();
8464 1055 : computeMarkers();
8465 :
8466 1055 : if (_adaptivity.initialAdaptMesh())
8467 : {
8468 880 : meshChanged(
8469 : /*intermediate_change=*/false, /*contract_mesh=*/true, /*clean_refinement_flags=*/true);
8470 :
8471 : // reproject the initial condition
8472 880 : projectSolution();
8473 :
8474 880 : _cycles_completed++;
8475 : }
8476 : else
8477 : {
8478 175 : _console << "Mesh unchanged, skipping remaining steps..." << std::endl;
8479 175 : return;
8480 : }
8481 : }
8482 626 : }
8483 : }
8484 :
8485 : bool
8486 164938 : FEProblemBase::adaptMesh()
8487 : {
8488 : // reset cycle counter
8489 164938 : _cycles_completed = 0;
8490 :
8491 164938 : if (!_adaptivity.isAdaptivityDue())
8492 160383 : return false;
8493 :
8494 22775 : TIME_SECTION("adaptMesh", 3, "Adapting Mesh");
8495 :
8496 4555 : unsigned int cycles_per_step = _adaptivity.getCyclesPerStep();
8497 :
8498 4555 : bool mesh_changed = false;
8499 :
8500 8012 : for (unsigned int i = 0; i < cycles_per_step; ++i)
8501 : {
8502 4707 : if (!_mesh.interiorLowerDBlocks().empty() || !_mesh.boundaryLowerDBlocks().empty())
8503 0 : mooseError("HFEM does not support mesh adaptivity currently.");
8504 :
8505 : // Markers were already computed once by Executioner
8506 4707 : if (_adaptivity.getRecomputeMarkersFlag() && i > 0)
8507 22 : computeMarkers();
8508 :
8509 : bool mesh_changed_this_step;
8510 4707 : mesh_changed_this_step = _adaptivity.adaptMesh();
8511 :
8512 4707 : if (mesh_changed_this_step)
8513 : {
8514 3457 : mesh_changed = true;
8515 :
8516 3457 : meshChanged(
8517 : /*intermediate_change=*/true, /*contract_mesh=*/true, /*clean_refinement_flags=*/true);
8518 3457 : _cycles_completed++;
8519 : }
8520 : else
8521 : {
8522 : // If the mesh didn't change, we still need to update the displaced mesh
8523 : // to undo the undisplacement performed in Adaptivity::adaptMesh
8524 1250 : if (_displaced_problem)
8525 44 : _displaced_problem->updateMesh();
8526 :
8527 1250 : _console << "Mesh unchanged, skipping remaining steps..." << std::endl;
8528 1250 : break;
8529 : }
8530 :
8531 : // Show adaptivity progress
8532 3457 : _console << std::flush;
8533 : }
8534 :
8535 : // We're done with all intermediate changes; now get systems ready
8536 : // for real if necessary.
8537 4555 : if (mesh_changed)
8538 3316 : es().reinit_systems();
8539 :
8540 : // Execute multi-apps that need to run after adaptivity, but before the next timestep.
8541 4555 : execMultiApps(EXEC_POST_ADAPTIVITY);
8542 :
8543 4555 : return mesh_changed;
8544 4555 : }
8545 : #endif // LIBMESH_ENABLE_AMR
8546 :
8547 : void
8548 0 : FEProblemBase::initXFEM(std::shared_ptr<XFEMInterface> xfem)
8549 : {
8550 0 : _xfem = xfem;
8551 0 : _xfem->setMesh(&_mesh);
8552 0 : if (_displaced_mesh)
8553 0 : _xfem->setDisplacedMesh(_displaced_mesh);
8554 :
8555 0 : auto fill_data = [](auto & storage)
8556 : {
8557 0 : std::vector<MaterialData *> data(libMesh::n_threads());
8558 0 : for (const auto tid : make_range(libMesh::n_threads()))
8559 0 : data[tid] = &storage.getMaterialData(tid);
8560 0 : return data;
8561 0 : };
8562 0 : _xfem->setMaterialData(fill_data(_material_props));
8563 0 : _xfem->setBoundaryMaterialData(fill_data(_bnd_material_props));
8564 :
8565 0 : unsigned int n_threads = libMesh::n_threads();
8566 0 : for (unsigned int i = 0; i < n_threads; ++i)
8567 0 : for (const auto nl_sys_num : index_range(_nl))
8568 : {
8569 0 : _assembly[i][nl_sys_num]->setXFEM(_xfem);
8570 0 : if (_displaced_problem)
8571 0 : _displaced_problem->assembly(i, nl_sys_num).setXFEM(_xfem);
8572 : }
8573 0 : }
8574 :
8575 : bool
8576 0 : FEProblemBase::updateMeshXFEM()
8577 : {
8578 0 : TIME_SECTION("updateMeshXFEM", 5, "Updating XFEM");
8579 :
8580 0 : bool updated = false;
8581 0 : if (haveXFEM())
8582 : {
8583 0 : if (_xfem->updateHeal())
8584 : // XFEM exodiff tests rely on a given numbering because they cannot use map = true due to
8585 : // having coincident elements. While conceptually speaking we do not need to contract the
8586 : // mesh, we need its call to renumber_nodes_and_elements in order to preserve these tests
8587 0 : meshChanged(
8588 : /*intermediate_change=*/false, /*contract_mesh=*/true, /*clean_refinement_flags=*/false);
8589 :
8590 0 : updated = _xfem->update(_time, _nl, *_aux);
8591 0 : if (updated)
8592 : {
8593 0 : meshChanged(
8594 : /*intermediate_change=*/false, /*contract_mesh=*/true, /*clean_refinement_flags=*/false);
8595 0 : _xfem->initSolution(_nl, *_aux);
8596 0 : restoreSolutions();
8597 0 : _console << "\nXFEM update complete: Mesh modified" << std::endl;
8598 : }
8599 : else
8600 0 : _console << "\nXFEM update complete: Mesh not modified" << std::endl;
8601 : }
8602 0 : return updated;
8603 0 : }
8604 :
8605 : void
8606 6998 : FEProblemBase::meshChanged(const bool intermediate_change,
8607 : const bool contract_mesh,
8608 : const bool clean_refinement_flags)
8609 : {
8610 34990 : TIME_SECTION("meshChanged", 3, "Handling Mesh Changes");
8611 :
8612 13788 : if (_material_props.hasStatefulProperties() || _bnd_material_props.hasStatefulProperties() ||
8613 6790 : _neighbor_material_props.hasStatefulProperties())
8614 208 : _mesh.cacheChangedLists(); // Currently only used with adaptivity and stateful material
8615 : // properties
8616 :
8617 : // Clear these out because they corresponded to the old mesh
8618 6998 : _ghosted_elems.clear();
8619 6998 : ghostGhostedBoundaries();
8620 :
8621 : // The mesh changed. We notify the MooseMesh first, because
8622 : // callbacks (e.g. for sparsity calculations) triggered by the
8623 : // EquationSystems reinit may require up-to-date MooseMesh caches.
8624 6998 : _mesh.meshChanged();
8625 :
8626 : // If we're just going to alter the mesh again, all we need to
8627 : // handle here is AMR and projections, not full system reinit
8628 6998 : if (intermediate_change)
8629 3488 : es().reinit_solutions();
8630 : else
8631 3510 : es().reinit();
8632 :
8633 6998 : if (contract_mesh)
8634 : // Once vectors are restricted, we can delete children of coarsened elements
8635 4428 : _mesh.getMesh().contract();
8636 6998 : if (clean_refinement_flags)
8637 : {
8638 : // Finally clear refinement flags so that if someone tries to project vectors again without
8639 : // an intervening mesh refinement to clear flags they won't run into trouble
8640 4428 : MeshRefinement refinement(_mesh.getMesh());
8641 4428 : refinement.clean_refinement_flags();
8642 4428 : }
8643 :
8644 6998 : if (!intermediate_change)
8645 : {
8646 : // Since the mesh has changed, we need to make sure that we update any of our
8647 : // MOOSE-system specific data.
8648 7020 : for (auto & sys : _solver_systems)
8649 3510 : sys->reinit();
8650 3510 : _aux->reinit();
8651 : }
8652 :
8653 : // Updating MooseMesh first breaks other adaptivity code, unless we
8654 : // then *again* update the MooseMesh caches. E.g. the definition of
8655 : // "active" and "local" may have been *changed* by refinement and
8656 : // repartitioning done in EquationSystems::reinit().
8657 6998 : _mesh.meshChanged();
8658 :
8659 : // If we have finite volume variables, we will need to recompute additional elemental/face
8660 : // quantities
8661 6998 : if (haveFV() && _mesh.isFiniteVolumeInfoDirty())
8662 351 : _mesh.setupFiniteVolumeMeshData();
8663 :
8664 : // Let the meshChangedInterface notify the mesh changed event before we update the active
8665 : // semilocal nodes, because the set of ghosted elements may potentially be updated during a mesh
8666 : // changed event.
8667 124895 : for (const auto & mci : _notify_when_mesh_changes)
8668 117897 : mci->meshChanged();
8669 :
8670 : // Since the Mesh changed, update the PointLocator object used by DiracKernels.
8671 6998 : _dirac_kernel_info.updatePointLocator(_mesh);
8672 :
8673 : // Need to redo ghosting
8674 6998 : _geometric_search_data.reinit();
8675 :
8676 6998 : if (_displaced_problem)
8677 : {
8678 569 : _displaced_problem->meshChanged(contract_mesh, clean_refinement_flags);
8679 569 : _displaced_mesh->updateActiveSemiLocalNodeRange(_ghosted_elems);
8680 : }
8681 :
8682 6998 : _mesh.updateActiveSemiLocalNodeRange(_ghosted_elems);
8683 :
8684 6998 : _evaluable_local_elem_range.reset();
8685 6998 : _nl_evaluable_local_elem_range.reset();
8686 :
8687 : // Just like we reinitialized our geometric search objects, we also need to reinitialize our
8688 : // mortar meshes. Note that this needs to happen after DisplacedProblem::meshChanged because the
8689 : // mortar mesh discretization will depend necessarily on the displaced mesh being re-displaced
8690 6998 : _mortar_data->meshChanged();
8691 :
8692 : // Nonlinear systems hold the mortar mesh functors. The domains of definition of the mortar
8693 : // functors might have changed when the mesh changed.
8694 13986 : for (auto & nl_sys : _nl)
8695 6988 : nl_sys->reinitMortarFunctors();
8696 :
8697 6998 : reinitBecauseOfGhostingOrNewGeomObjects(/*mortar_changed=*/true);
8698 :
8699 : // We need to create new storage for newly active elements, and copy
8700 : // stateful properties from the old elements.
8701 7206 : if (_has_initialized_stateful &&
8702 208 : (_material_props.hasStatefulProperties() || _bnd_material_props.hasStatefulProperties()))
8703 : {
8704 208 : if (havePRefinement())
8705 66 : _mesh.buildPRefinementAndCoarseningMaps(_assembly[0][0].get());
8706 :
8707 : // Prolong properties onto newly refined elements' children
8708 : {
8709 : ProjectMaterialProperties pmp(
8710 208 : /* refine = */ true, *this, _material_props, _bnd_material_props, _assembly);
8711 208 : const auto & range = *_mesh.refinedElementRange();
8712 208 : Threads::parallel_reduce(range, pmp);
8713 :
8714 : // Concurrent erasure from the shared hash map is not safe while we are reading from it in
8715 : // ProjectMaterialProperties, so we handle erasure here. Moreover, erasure based on key is
8716 : // not thread safe in and of itself because it is a read-write operation. Note that we do not
8717 : // do the erasure for p-refinement because the coarse level element is the same as our active
8718 : // refined level element
8719 208 : if (!doingPRefinement())
8720 3272 : for (const auto & elem : range)
8721 : {
8722 3130 : _material_props.eraseProperty(elem);
8723 3130 : _bnd_material_props.eraseProperty(elem);
8724 3130 : _neighbor_material_props.eraseProperty(elem);
8725 : }
8726 208 : }
8727 :
8728 : // Restrict properties onto newly coarsened elements
8729 : {
8730 : ProjectMaterialProperties pmp(
8731 208 : /* refine = */ false, *this, _material_props, _bnd_material_props, _assembly);
8732 208 : const auto & range = *_mesh.coarsenedElementRange();
8733 208 : Threads::parallel_reduce(range, pmp);
8734 : // Note that we do not do the erasure for p-refinement because the coarse level element is the
8735 : // same as our active refined level element
8736 208 : if (!doingPRefinement())
8737 1322 : for (const auto & elem : range)
8738 : {
8739 1180 : auto && coarsened_children = _mesh.coarsenedElementChildren(elem);
8740 7732 : for (auto && child : coarsened_children)
8741 : {
8742 6552 : _material_props.eraseProperty(child);
8743 6552 : _bnd_material_props.eraseProperty(child);
8744 6552 : _neighbor_material_props.eraseProperty(child);
8745 : }
8746 : }
8747 208 : }
8748 : }
8749 :
8750 6998 : if (_calculate_jacobian_in_uo)
8751 0 : setVariableAllDoFMap(_uo_jacobian_moose_vars[0]);
8752 :
8753 6998 : _has_jacobian = false; // we have to recompute jacobian when mesh changed
8754 :
8755 : // Now for backwards compatibility with user code that overrode the old no-arg meshChanged we must
8756 : // call it here
8757 6998 : meshChanged();
8758 6998 : }
8759 :
8760 : void
8761 911399 : FEProblemBase::notifyWhenMeshChanges(MeshChangedInterface * mci)
8762 : {
8763 911399 : _notify_when_mesh_changes.push_back(mci);
8764 911399 : }
8765 :
8766 : void
8767 74911 : FEProblemBase::notifyWhenMeshDisplaces(MeshDisplacedInterface * mdi)
8768 : {
8769 74911 : _notify_when_mesh_displaces.push_back(mdi);
8770 74911 : }
8771 :
8772 : void
8773 63048 : FEProblemBase::meshDisplaced()
8774 : {
8775 91725 : for (const auto & mdi : _notify_when_mesh_displaces)
8776 28677 : mdi->meshDisplaced();
8777 63048 : }
8778 :
8779 : void
8780 9663 : FEProblemBase::initElementStatefulProps(const ConstElemRange & elem_range, const bool threaded)
8781 : {
8782 : ComputeMaterialsObjectThread cmt(
8783 9663 : *this, _material_props, _bnd_material_props, _neighbor_material_props, _assembly);
8784 9663 : if (threaded)
8785 9663 : Threads::parallel_reduce(elem_range, cmt);
8786 : else
8787 0 : cmt(elem_range, true);
8788 :
8789 : #ifdef MOOSE_KOKKOS_ENABLED
8790 7291 : if (_has_kokkos_objects)
8791 781 : initKokkosStatefulProps();
8792 : #endif
8793 9663 : }
8794 :
8795 : void
8796 59840 : FEProblemBase::checkProblemIntegrity()
8797 : {
8798 179520 : TIME_SECTION("checkProblemIntegrity", 5);
8799 :
8800 : // Subdomains specified by the "Problem/block" parameter
8801 119680 : const auto & subdomain_names = getParam<std::vector<SubdomainName>>("block");
8802 59840 : auto mesh_subdomains_vec = MooseMeshUtils::getSubdomainIDs(_mesh, subdomain_names);
8803 59840 : std::set<SubdomainID> mesh_subdomains(mesh_subdomains_vec.begin(), mesh_subdomains_vec.end());
8804 :
8805 : // Check kernel coverage of subdomains (blocks) in the mesh
8806 59840 : if (!_skip_nl_system_check && _solve && _kernel_coverage_check != CoverageCheckMode::FALSE &&
8807 41164 : _kernel_coverage_check != CoverageCheckMode::OFF)
8808 : {
8809 41152 : std::set<SubdomainID> blocks;
8810 41152 : if (_kernel_coverage_check == CoverageCheckMode::TRUE ||
8811 231 : _kernel_coverage_check == CoverageCheckMode::ON)
8812 40921 : blocks = mesh_subdomains;
8813 231 : else if (_kernel_coverage_check == CoverageCheckMode::SKIP_LIST)
8814 : {
8815 12 : blocks = mesh_subdomains;
8816 24 : for (const auto & subdomain_name : _kernel_coverage_blocks)
8817 : {
8818 12 : const auto id = _mesh.getSubdomainID(subdomain_name);
8819 12 : if (id == Moose::INVALID_BLOCK_ID)
8820 0 : paramError("kernel_coverage_block_list",
8821 : "Subdomain \"",
8822 : subdomain_name,
8823 : "\" not found in mesh.");
8824 12 : blocks.erase(id);
8825 : }
8826 : }
8827 219 : else if (_kernel_coverage_check == CoverageCheckMode::ONLY_LIST)
8828 438 : for (const auto & subdomain_name : _kernel_coverage_blocks)
8829 : {
8830 219 : const auto id = _mesh.getSubdomainID(subdomain_name);
8831 219 : if (id == Moose::INVALID_BLOCK_ID)
8832 0 : paramError("kernel_coverage_block_list",
8833 : "Subdomain \"",
8834 : subdomain_name,
8835 : "\" not found in mesh.");
8836 219 : blocks.insert(id);
8837 : }
8838 41152 : if (!blocks.empty())
8839 81494 : for (auto & nl : _nl)
8840 40354 : nl->checkKernelCoverage(blocks);
8841 41140 : }
8842 :
8843 : // Check materials
8844 : {
8845 : #ifdef LIBMESH_ENABLE_AMR
8846 62081 : if ((_adaptivity.isOn() || _num_grid_steps) &&
8847 2253 : (_material_props.hasStatefulProperties() || _bnd_material_props.hasStatefulProperties() ||
8848 2190 : _neighbor_material_props.hasStatefulProperties()))
8849 : {
8850 63 : _console << "Using EXPERIMENTAL Stateful Material Property projection with Adaptivity!\n"
8851 63 : << std::flush;
8852 : }
8853 : #endif
8854 :
8855 59828 : std::set<SubdomainID> local_mesh_subs(mesh_subdomains);
8856 :
8857 59828 : if (_material_coverage_check != CoverageCheckMode::FALSE &&
8858 59744 : _material_coverage_check != CoverageCheckMode::OFF)
8859 : {
8860 : /**
8861 : * If a material is specified for any block in the simulation, then all blocks must
8862 : * have a material specified.
8863 : */
8864 59744 : bool check_material_coverage = false;
8865 59744 : std::set<SubdomainID> ids = _all_materials.getActiveBlocks();
8866 72263 : for (const auto & id : ids)
8867 : {
8868 12519 : local_mesh_subs.erase(id);
8869 12519 : check_material_coverage = true;
8870 : }
8871 :
8872 : // did the user limit the subdomains to be checked?
8873 59744 : if (_material_coverage_check == CoverageCheckMode::SKIP_LIST)
8874 : {
8875 24 : for (const auto & subdomain_name : _material_coverage_blocks)
8876 : {
8877 12 : const auto id = _mesh.getSubdomainID(subdomain_name);
8878 12 : if (id == Moose::INVALID_BLOCK_ID)
8879 0 : paramError("material_coverage_block_list",
8880 0 : "Subdomain \"" + subdomain_name + "\" not found in mesh.");
8881 12 : local_mesh_subs.erase(id);
8882 : }
8883 : }
8884 59732 : else if (_material_coverage_check == CoverageCheckMode::ONLY_LIST)
8885 : {
8886 219 : std::set<SubdomainID> blocks(local_mesh_subs);
8887 438 : for (const auto & subdomain_name : _material_coverage_blocks)
8888 : {
8889 219 : const auto id = _mesh.getSubdomainID(subdomain_name);
8890 219 : if (id == Moose::INVALID_BLOCK_ID)
8891 0 : paramError("material_coverage_block_list",
8892 0 : "Subdomain \"" + subdomain_name + "\" not found in mesh.");
8893 219 : blocks.erase(id);
8894 : }
8895 231 : for (const auto id : blocks)
8896 12 : local_mesh_subs.erase(id);
8897 219 : }
8898 :
8899 : // also exclude mortar spaces from the material check
8900 59744 : auto && mortar_subdomain_ids = _mortar_data->getMortarSubdomainIDs();
8901 61598 : for (auto subdomain_id : mortar_subdomain_ids)
8902 1854 : local_mesh_subs.erase(subdomain_id);
8903 :
8904 : // Check Material Coverage
8905 59744 : if (check_material_coverage && !local_mesh_subs.empty())
8906 : {
8907 6 : std::stringstream extra_subdomain_ids;
8908 : /// unsigned int is necessary to print SubdomainIDs in the statement below
8909 6 : std::copy(local_mesh_subs.begin(),
8910 : local_mesh_subs.end(),
8911 12 : std::ostream_iterator<unsigned int>(extra_subdomain_ids, " "));
8912 : /// vector is necessary to get the subdomain names
8913 : std::vector<SubdomainID> local_mesh_subs_vec(local_mesh_subs.begin(),
8914 6 : local_mesh_subs.end());
8915 :
8916 18 : mooseError("The following blocks from your input mesh do not contain an active material: " +
8917 12 : extra_subdomain_ids.str() +
8918 18 : "(names: " + Moose::stringify(_mesh.getSubdomainNames(local_mesh_subs_vec)) +
8919 : ")\nWhen ANY mesh block contains a Material object, "
8920 : "all blocks must contain a Material object.\n");
8921 0 : }
8922 59738 : }
8923 :
8924 : // Check material properties on blocks and boundaries
8925 59822 : checkBlockMatProps();
8926 59790 : checkBoundaryMatProps();
8927 :
8928 : // Check that material properties exist when requested by other properties on a given block
8929 59781 : const auto & materials = _all_materials.getActiveObjects();
8930 73678 : for (const auto & material : materials)
8931 13897 : material->checkStatefulSanity();
8932 :
8933 : // auto mats_to_check = _materials.getActiveBlockObjects();
8934 : // const auto & discrete_materials = _discrete_materials.getActiveBlockObjects();
8935 : // for (const auto & map_it : discrete_materials)
8936 : // for (const auto & container_element : map_it.second)
8937 : // mats_to_check[map_it.first].push_back(container_element);
8938 59781 : if (_material_dependency_check)
8939 59757 : checkDependMaterialsHelper(_all_materials.getActiveBlockObjects());
8940 59768 : }
8941 :
8942 59768 : checkUserObjects();
8943 :
8944 : // Verify that we don't have any Element type/Coordinate Type conflicts
8945 59768 : checkCoordinateSystems();
8946 :
8947 : // Coordinate transforms are only intended for use with MultiApps at this time. If you are not
8948 : // using multiapps but still require these, contact a moose developer
8949 59905 : if (_mesh.coordTransform().hasScalingOrRotationTransformation() && _app.isUltimateMaster() &&
8950 140 : !hasMultiApps())
8951 3 : mooseError("Coordinate transformation parameters, listed below, are only to be used in the "
8952 : "context of application to application field transfers at this time. The mesh is "
8953 : "not modified by these parameters within an application.\n"
8954 : "You should likely use a 'TransformGenerator' in the [Mesh] block to achieve the "
8955 : "desired mesh modification.\n\n",
8956 3 : Moose::stringify(MooseAppCoordTransform::validParams()));
8957 :
8958 : // If using displacements, verify that the order of the displacement
8959 : // variables matches the order of the elements in the displaced
8960 : // mesh.
8961 59762 : checkDisplacementOrders();
8962 :
8963 : // Check for postprocessor names with same name as a scalar variable
8964 59759 : checkDuplicatePostprocessorVariableNames();
8965 59759 : }
8966 :
8967 : void
8968 59762 : FEProblemBase::checkDisplacementOrders()
8969 : {
8970 59762 : if (_displaced_problem)
8971 : {
8972 2022 : bool mesh_has_second_order_elements = false;
8973 4044 : for (const auto & elem : as_range(_displaced_mesh->activeLocalElementsBegin(),
8974 464948 : _displaced_mesh->activeLocalElementsEnd()))
8975 : {
8976 229785 : if (elem->default_order() == SECOND)
8977 : {
8978 344 : mesh_has_second_order_elements = true;
8979 344 : break;
8980 : }
8981 2022 : }
8982 :
8983 : // We checked our local elements, so take the max over all processors.
8984 2022 : _displaced_mesh->comm().max(mesh_has_second_order_elements);
8985 :
8986 : // If the Mesh has second order elements, make sure the
8987 : // displacement variables are second-order.
8988 2022 : if (mesh_has_second_order_elements)
8989 : {
8990 : const std::vector<std::string> & displacement_variables =
8991 344 : _displaced_problem->getDisplacementVarNames();
8992 :
8993 1133 : for (const auto & var_name : displacement_variables)
8994 : {
8995 : MooseVariableFEBase & mv =
8996 792 : _displaced_problem->getVariable(/*tid=*/0,
8997 : var_name,
8998 : Moose::VarKindType::VAR_ANY,
8999 : Moose::VarFieldType::VAR_FIELD_STANDARD);
9000 792 : if (mv.order() != SECOND)
9001 3 : mooseError("Error: mesh has SECOND order elements, so all displacement variables must be "
9002 : "SECOND order.");
9003 : }
9004 : }
9005 : }
9006 59759 : }
9007 :
9008 : void
9009 59768 : FEProblemBase::checkUserObjects()
9010 : {
9011 : // Check user_objects block coverage
9012 59768 : std::set<SubdomainID> mesh_subdomains = _mesh.meshSubdomains();
9013 59768 : std::set<SubdomainID> user_objects_blocks;
9014 :
9015 : // gather names of all user_objects that were defined in the input file
9016 : // and the blocks that they are defined on
9017 59768 : std::set<std::string> names;
9018 :
9019 59768 : std::vector<UserObjectBase *> objects;
9020 59768 : theWarehouse().query().condition<AttribInterfaces>(Interfaces::UserObject).queryInto(objects);
9021 :
9022 132415 : for (const auto & obj : objects)
9023 72647 : names.insert(obj->name());
9024 :
9025 : // See if all referenced blocks are covered
9026 59768 : std::set<SubdomainID> difference;
9027 59768 : std::set_difference(user_objects_blocks.begin(),
9028 : user_objects_blocks.end(),
9029 : mesh_subdomains.begin(),
9030 : mesh_subdomains.end(),
9031 : std::inserter(difference, difference.end()));
9032 :
9033 59768 : if (!difference.empty())
9034 : {
9035 0 : std::ostringstream oss;
9036 0 : oss << "One or more UserObjects is referencing a nonexistent block:\n";
9037 0 : for (const auto & id : difference)
9038 0 : oss << id << "\n";
9039 0 : mooseError(oss.str());
9040 0 : }
9041 59768 : }
9042 :
9043 : void
9044 59757 : FEProblemBase::checkDependMaterialsHelper(
9045 : const std::map<SubdomainID, std::vector<std::shared_ptr<MaterialBase>>> & materials_map)
9046 : {
9047 72218 : for (const auto & it : materials_map)
9048 : {
9049 : /// These two sets are used to make sure that all dependent props on a block are actually supplied
9050 12469 : std::set<std::string> block_depend_props, block_supplied_props;
9051 :
9052 30921 : for (const auto & mat1 : it.second)
9053 : {
9054 18452 : auto & alldeps = mat1->getMatPropDependencies(); // includes requested stateful props
9055 20771 : for (auto & dep : alldeps)
9056 2319 : block_depend_props.insert(_material_prop_registry.getName(dep));
9057 :
9058 : // See if any of the active materials supply this property
9059 56736 : for (const auto & mat2 : it.second)
9060 : {
9061 38284 : const std::set<std::string> & supplied_props = mat2->MaterialBase::getSuppliedItems();
9062 38284 : block_supplied_props.insert(supplied_props.begin(), supplied_props.end());
9063 : }
9064 : }
9065 :
9066 : // Add zero material properties specific to this block and unrestricted
9067 12469 : block_supplied_props.insert(_zero_block_material_props[it.first].begin(),
9068 12469 : _zero_block_material_props[it.first].end());
9069 :
9070 : // Error check to make sure all properties consumed by materials are supplied on this block
9071 12469 : std::set<std::string> difference;
9072 12469 : std::set_difference(block_depend_props.begin(),
9073 : block_depend_props.end(),
9074 : block_supplied_props.begin(),
9075 : block_supplied_props.end(),
9076 : std::inserter(difference, difference.end()));
9077 :
9078 12469 : if (!difference.empty())
9079 : {
9080 8 : std::ostringstream oss;
9081 8 : oss << "One or more Material Properties were not supplied on block ";
9082 8 : const std::string & subdomain_name = _mesh.getSubdomainName(it.first);
9083 8 : if (subdomain_name.length() > 0)
9084 0 : oss << subdomain_name << " (" << it.first << ")";
9085 : else
9086 8 : oss << it.first;
9087 8 : oss << ":\n";
9088 16 : for (const auto & name : difference)
9089 8 : oss << name << "\n";
9090 8 : mooseError(oss.str());
9091 0 : }
9092 12461 : }
9093 :
9094 : // This loop checks that materials are not supplied by multiple Material objects
9095 72205 : for (const auto & it : materials_map)
9096 : {
9097 12461 : const auto & materials = it.second;
9098 12461 : std::set<std::string> inner_supplied, outer_supplied;
9099 :
9100 30893 : for (const auto & outer_mat : materials)
9101 : {
9102 : // Storage for properties for this material (outer) and all other materials (inner)
9103 18437 : outer_supplied = outer_mat->getSuppliedItems();
9104 18437 : inner_supplied.clear();
9105 :
9106 : // Property to material map for error reporting
9107 18437 : std::map<std::string, std::set<std::string>> prop_to_mat;
9108 39149 : for (const auto & name : outer_supplied)
9109 20712 : prop_to_mat[name].insert(outer_mat->name());
9110 :
9111 56697 : for (const auto & inner_mat : materials)
9112 : {
9113 38260 : if (outer_mat == inner_mat)
9114 18437 : continue;
9115 :
9116 : // Check whether these materials are an AD pair
9117 19823 : auto outer_mat_type = outer_mat->type();
9118 19823 : auto inner_mat_type = inner_mat->type();
9119 39646 : removeSubstring(outer_mat_type, "<RESIDUAL>");
9120 39646 : removeSubstring(outer_mat_type, "<JACOBIAN>");
9121 39646 : removeSubstring(inner_mat_type, "<RESIDUAL>");
9122 19823 : removeSubstring(inner_mat_type, "<JACOBIAN>");
9123 19823 : if (outer_mat_type == inner_mat_type && outer_mat_type != outer_mat->type() &&
9124 0 : inner_mat_type != inner_mat->type())
9125 0 : continue;
9126 :
9127 19823 : inner_supplied.insert(inner_mat->getSuppliedItems().begin(),
9128 19823 : inner_mat->getSuppliedItems().end());
9129 :
9130 114479 : for (const auto & inner_supplied_name : inner_supplied)
9131 94656 : prop_to_mat[inner_supplied_name].insert(inner_mat->name());
9132 19823 : }
9133 :
9134 : // Test that a property isn't supplied on multiple blocks
9135 18437 : std::set<std::string> intersection;
9136 18437 : std::set_intersection(outer_supplied.begin(),
9137 : outer_supplied.end(),
9138 : inner_supplied.begin(),
9139 : inner_supplied.end(),
9140 : std::inserter(intersection, intersection.end()));
9141 :
9142 18437 : if (!intersection.empty())
9143 : {
9144 5 : std::ostringstream oss;
9145 5 : oss << "The following material properties are declared on block " << it.first
9146 5 : << " by multiple materials:\n";
9147 10 : oss << ConsoleUtils::indent(2) << std::setw(30) << std::left << "Material Property"
9148 5 : << "Material Objects\n";
9149 20 : for (const auto & outer_name : intersection)
9150 : {
9151 15 : oss << ConsoleUtils::indent(2) << std::setw(30) << std::left << outer_name;
9152 45 : for (const auto & inner_name : prop_to_mat[outer_name])
9153 30 : oss << inner_name << " ";
9154 15 : oss << '\n';
9155 : }
9156 :
9157 5 : mooseError(oss.str());
9158 : break;
9159 0 : }
9160 18432 : }
9161 12456 : }
9162 59744 : }
9163 :
9164 : void
9165 59768 : FEProblemBase::checkCoordinateSystems()
9166 : {
9167 59768 : _mesh.checkCoordinateSystems();
9168 59765 : }
9169 :
9170 : void
9171 467 : FEProblemBase::setRestartFile(const std::string & file_name)
9172 : {
9173 467 : if (_app.isRecovering())
9174 : {
9175 23 : mooseInfo("Restart file ", file_name, " is NOT being used since we are performing recovery.");
9176 : }
9177 : else
9178 : {
9179 444 : _app.setRestart(true);
9180 444 : _app.setRestartRecoverFileBase(file_name);
9181 444 : mooseInfo("Using ", file_name, " for restart.");
9182 : }
9183 467 : }
9184 :
9185 : std::vector<VariableName>
9186 355480 : FEProblemBase::getVariableNames()
9187 : {
9188 355480 : std::vector<VariableName> names;
9189 :
9190 715072 : for (auto & sys : _solver_systems)
9191 : {
9192 359592 : const std::vector<VariableName> & var_names = sys->getVariableNames();
9193 359592 : names.insert(names.end(), var_names.begin(), var_names.end());
9194 : }
9195 :
9196 355480 : const std::vector<VariableName> & aux_var_names = _aux->getVariableNames();
9197 355480 : names.insert(names.end(), aux_var_names.begin(), aux_var_names.end());
9198 :
9199 355480 : return names;
9200 0 : }
9201 :
9202 : SolverParams &
9203 1610531 : FEProblemBase::solverParams(const unsigned int solver_sys_num)
9204 : {
9205 : mooseAssert(solver_sys_num < numSolverSystems(),
9206 : "Solver system number '" << solver_sys_num << "' is out of bounds. We have '"
9207 : << numSolverSystems() << "' solver systems");
9208 1610531 : return _solver_params[solver_sys_num];
9209 : }
9210 :
9211 : const SolverParams &
9212 14652 : FEProblemBase::solverParams(const unsigned int solver_sys_num) const
9213 : {
9214 14652 : return const_cast<FEProblemBase *>(this)->solverParams(solver_sys_num);
9215 : }
9216 :
9217 : void
9218 371 : FEProblemBase::registerRandomInterface(RandomInterface & random_interface, const std::string & name)
9219 : {
9220 371 : auto insert_pair = moose_try_emplace(
9221 371 : _random_data_objects, name, std::make_unique<RandomData>(*this, random_interface));
9222 :
9223 371 : auto random_data_ptr = insert_pair.first->second.get();
9224 371 : random_interface.setRandomDataPointer(random_data_ptr);
9225 371 : }
9226 :
9227 : bool
9228 1600790 : FEProblemBase::needBoundaryMaterialOnSide(BoundaryID bnd_id, const THREAD_ID tid)
9229 : {
9230 1600790 : if (_bnd_mat_side_cache[tid].find(bnd_id) == _bnd_mat_side_cache[tid].end())
9231 : {
9232 29129 : auto & bnd_mat_side_cache = _bnd_mat_side_cache[tid][bnd_id];
9233 29129 : bnd_mat_side_cache = false;
9234 :
9235 : // Check systems
9236 29129 : if (_aux->needMaterialOnSide(bnd_id))
9237 : {
9238 531 : bnd_mat_side_cache = true;
9239 531 : return true;
9240 : }
9241 54915 : for (auto & nl : _nl)
9242 28440 : if (nl->needBoundaryMaterialOnSide(bnd_id, tid))
9243 : {
9244 2123 : bnd_mat_side_cache = true;
9245 2123 : return true;
9246 : }
9247 :
9248 : // TODO: these objects should be checked for whether they actually consume materials
9249 : // NOTE: InterfaceUO can use use boundary properties too
9250 26475 : if (theWarehouse()
9251 52950 : .query()
9252 26475 : .condition<AttribThread>(tid)
9253 26475 : .condition<AttribInterfaces>(Interfaces::SideUserObject | Interfaces::DomainUserObject |
9254 : Interfaces::InterfaceUserObject)
9255 26475 : .condition<AttribBoundaries>(bnd_id)
9256 26475 : .count() > 0)
9257 : {
9258 579 : bnd_mat_side_cache = true;
9259 579 : return true;
9260 : }
9261 : }
9262 :
9263 1597557 : return _bnd_mat_side_cache[tid][bnd_id];
9264 : }
9265 :
9266 : bool
9267 386695 : FEProblemBase::needInterfaceMaterialOnSide(BoundaryID bnd_id, const THREAD_ID tid)
9268 : {
9269 386695 : if (_interface_mat_side_cache[tid].find(bnd_id) == _interface_mat_side_cache[tid].end())
9270 : {
9271 2812 : auto & interface_mat_side_cache = _interface_mat_side_cache[tid][bnd_id];
9272 2812 : interface_mat_side_cache = false;
9273 :
9274 : // Aux-system has not needed interface materials so far
9275 5394 : for (auto & nl : _nl)
9276 2812 : if (nl->needInterfaceMaterialOnSide(bnd_id, tid))
9277 : {
9278 230 : interface_mat_side_cache = true;
9279 230 : return true;
9280 : }
9281 :
9282 : // TODO: these objects should be checked for whether they actually consume materials
9283 2582 : if (theWarehouse()
9284 5164 : .query()
9285 2582 : .condition<AttribThread>(tid)
9286 2582 : .condition<AttribInterfaces>(Interfaces::InterfaceUserObject |
9287 : Interfaces::DomainUserObject)
9288 2582 : .condition<AttribBoundaries>(bnd_id)
9289 2582 : .count() > 0)
9290 : {
9291 79 : interface_mat_side_cache = true;
9292 79 : return true;
9293 : }
9294 2503 : else if (_interface_materials.hasActiveBoundaryObjects(bnd_id, tid))
9295 : {
9296 10 : interface_mat_side_cache = true;
9297 10 : return true;
9298 : }
9299 : }
9300 386376 : return _interface_mat_side_cache[tid][bnd_id];
9301 : }
9302 :
9303 : bool
9304 423177 : FEProblemBase::needInternalNeighborSideMaterial(SubdomainID subdomain_id, const THREAD_ID tid)
9305 : {
9306 423177 : if (_block_mat_side_cache[tid].find(subdomain_id) == _block_mat_side_cache[tid].end())
9307 : {
9308 12764 : _block_mat_side_cache[tid][subdomain_id] = false;
9309 :
9310 25047 : for (auto & nl : _nl)
9311 12723 : if (nl->needInternalNeighborSideMaterial(subdomain_id, tid))
9312 : {
9313 440 : _block_mat_side_cache[tid][subdomain_id] = true;
9314 440 : return true;
9315 : }
9316 :
9317 : // TODO: these objects should be checked for whether they actually consume materials
9318 12324 : if (theWarehouse()
9319 24648 : .query()
9320 12324 : .condition<AttribThread>(tid)
9321 12324 : .condition<AttribInterfaces>(Interfaces::InternalSideUserObject |
9322 : Interfaces::DomainUserObject)
9323 12324 : .condition<AttribSubdomains>(subdomain_id)
9324 12324 : .count() > 0)
9325 : {
9326 35 : _block_mat_side_cache[tid][subdomain_id] = true;
9327 35 : return true;
9328 : }
9329 : }
9330 :
9331 422702 : return _block_mat_side_cache[tid][subdomain_id];
9332 : }
9333 :
9334 : bool
9335 287319 : FEProblemBase::needsPreviousNewtonIteration() const
9336 : {
9337 287319 : return vectorTagExists(Moose::PREVIOUS_NL_SOLUTION_TAG);
9338 : }
9339 :
9340 : void
9341 76 : FEProblemBase::needsPreviousNewtonIteration(bool state)
9342 : {
9343 76 : if (state && !vectorTagExists(Moose::PREVIOUS_NL_SOLUTION_TAG))
9344 0 : mooseError("Previous nonlinear solution is required but not added through "
9345 : "Problem/previous_nl_solution_required=true");
9346 76 : }
9347 :
9348 : void
9349 52 : FEProblemBase::needsPreviousMultiAppFixedPointIterationSolution(bool needed,
9350 : const unsigned int solver_sys_num)
9351 : {
9352 52 : _previous_multiapp_fp_nl_solution_required[solver_sys_num] = needed;
9353 52 : }
9354 :
9355 : bool
9356 57782 : FEProblemBase::needsPreviousMultiAppFixedPointIterationSolution(
9357 : const unsigned int solver_sys_num) const
9358 : {
9359 57782 : return _previous_multiapp_fp_nl_solution_required[solver_sys_num];
9360 : }
9361 :
9362 : void
9363 13 : FEProblemBase::needsPreviousMultiAppFixedPointIterationAuxiliary(bool state)
9364 : {
9365 13 : _previous_multiapp_fp_aux_solution_required = state;
9366 13 : }
9367 :
9368 : bool
9369 57646 : FEProblemBase::needsPreviousMultiAppFixedPointIterationAuxiliary() const
9370 : {
9371 57646 : return _previous_multiapp_fp_aux_solution_required;
9372 : }
9373 :
9374 : bool
9375 7561278 : FEProblemBase::hasJacobian() const
9376 : {
9377 7561278 : return _has_jacobian;
9378 : }
9379 :
9380 : bool
9381 7076750 : FEProblemBase::constJacobian() const
9382 : {
9383 7076750 : return _const_jacobian;
9384 : }
9385 :
9386 : void
9387 285140 : FEProblemBase::addOutput(const std::string & object_type,
9388 : const std::string & object_name,
9389 : InputParameters & parameters)
9390 : {
9391 : parallel_object_only();
9392 :
9393 : // Get a reference to the OutputWarehouse
9394 285140 : OutputWarehouse & output_warehouse = _app.getOutputWarehouse();
9395 :
9396 : // Reject the reserved names for objects not built by MOOSE
9397 285140 : if (!parameters.get<bool>("_built_by_moose") && output_warehouse.isReservedName(object_name))
9398 6 : mooseError("The name '", object_name, "' is a reserved name for output objects");
9399 :
9400 : // Check that an object by the same name does not already exist; this must be done before the
9401 : // object is created to avoid getting misleading errors from the Parser
9402 285134 : if (output_warehouse.hasOutput(object_name))
9403 3 : mooseError("An output object named '", object_name, "' already exists");
9404 :
9405 : // Add a pointer to the FEProblemBase class
9406 570262 : parameters.addPrivateParam<FEProblemBase *>("_fe_problem_base", this);
9407 :
9408 : // --show-input should enable the display of the input file on the screen
9409 691023 : if (object_type == "Console" && _app.getParam<bool>("show_input") &&
9410 285158 : parameters.get<bool>("output_screen"))
9411 54 : parameters.set<ExecFlagEnum>("execute_input_on") = EXEC_INITIAL;
9412 :
9413 : // Apply only user-set parameters from the common [Outputs] block so that
9414 : // each output type's own defaults are not overridden by common defaults.
9415 285131 : const InputParameters * common = output_warehouse.getCommonParameters();
9416 285131 : if (common)
9417 285131 : parameters.applyCommonUserSetParameters(*common);
9418 :
9419 : // Set the correct value for the binary flag for XDA/XDR output
9420 285131 : if (object_type == "XDR")
9421 120 : parameters.set<bool>("_binary") = true;
9422 285071 : else if (object_type == "XDA")
9423 244 : parameters.set<bool>("_binary") = false;
9424 :
9425 : // Adjust the checkpoint suffix if auto recovery was enabled
9426 285131 : if (object_name == "auto_recovery_checkpoint")
9427 0 : parameters.set<std::string>("suffix") = "auto_recovery";
9428 :
9429 : // Create the object and add it to the warehouse
9430 285131 : std::shared_ptr<Output> output = _factory.create<Output>(object_type, object_name, parameters);
9431 285119 : logAdd("Output", object_name, object_type, parameters);
9432 285119 : output_warehouse.addOutput(output);
9433 285119 : }
9434 :
9435 : void
9436 22785 : FEProblemBase::haveADObjects(const bool have_ad_objects)
9437 : {
9438 22785 : _have_ad_objects = have_ad_objects;
9439 22785 : if (_displaced_problem)
9440 227 : _displaced_problem->SubProblem::haveADObjects(have_ad_objects);
9441 22785 : }
9442 :
9443 : const SystemBase &
9444 0 : FEProblemBase::getSystemBase(const unsigned int sys_num) const
9445 : {
9446 0 : if (sys_num < _solver_systems.size())
9447 0 : return *_solver_systems[sys_num];
9448 :
9449 0 : return *_aux;
9450 : }
9451 :
9452 : SystemBase &
9453 3447 : FEProblemBase::getSystemBase(const std::string & sys_name)
9454 : {
9455 3447 : if (std::find(_solver_sys_names.begin(), _solver_sys_names.end(), sys_name) !=
9456 6894 : _solver_sys_names.end())
9457 3447 : return getSystemBase(solverSysNum(sys_name));
9458 0 : else if (sys_name == "aux0")
9459 0 : return *_aux;
9460 : else
9461 0 : mooseError("System '" + sys_name + "' was requested from problem but does not exist.");
9462 : }
9463 :
9464 : SystemBase &
9465 5091 : FEProblemBase::getSystemBase(const unsigned int sys_num)
9466 : {
9467 5091 : if (sys_num < _solver_systems.size())
9468 4989 : return *_solver_systems[sys_num];
9469 :
9470 102 : return *_aux;
9471 : }
9472 :
9473 : const SystemBase &
9474 12422 : FEProblemBase::systemBaseNonlinear(const unsigned int sys_num) const
9475 : {
9476 : mooseAssert(sys_num < _nl.size(), "System number greater than the number of nonlinear systems");
9477 12422 : return *_nl[sys_num];
9478 : }
9479 :
9480 : SystemBase &
9481 1256935 : FEProblemBase::systemBaseNonlinear(const unsigned int sys_num)
9482 : {
9483 : mooseAssert(sys_num < _nl.size(), "System number greater than the number of nonlinear systems");
9484 1256935 : return *_nl[sys_num];
9485 : }
9486 :
9487 : const SystemBase &
9488 0 : FEProblemBase::systemBaseLinear(const unsigned int sys_num) const
9489 : {
9490 : mooseAssert(sys_num < _linear_systems.size(),
9491 : "System number greater than the number of linear systems");
9492 0 : return *_linear_systems[sys_num];
9493 : }
9494 :
9495 : SystemBase &
9496 0 : FEProblemBase::systemBaseLinear(const unsigned int sys_num)
9497 : {
9498 : mooseAssert(sys_num < _linear_systems.size(),
9499 : "System number greater than the number of linear systems");
9500 0 : return *_linear_systems[sys_num];
9501 : }
9502 :
9503 : const SystemBase &
9504 0 : FEProblemBase::systemBaseSolver(const unsigned int sys_num) const
9505 : {
9506 : mooseAssert(sys_num < _solver_systems.size(),
9507 : "System number greater than the number of solver systems");
9508 0 : return *_solver_systems[sys_num];
9509 : }
9510 :
9511 : SystemBase &
9512 6721557 : FEProblemBase::systemBaseSolver(const unsigned int sys_num)
9513 : {
9514 : mooseAssert(sys_num < _solver_systems.size(),
9515 : "System number greater than the number of solver systems");
9516 6721557 : return *_solver_systems[sys_num];
9517 : }
9518 :
9519 : const SystemBase &
9520 417 : FEProblemBase::systemBaseAuxiliary() const
9521 : {
9522 417 : return *_aux;
9523 : }
9524 :
9525 : SystemBase &
9526 8518492 : FEProblemBase::systemBaseAuxiliary()
9527 : {
9528 8518492 : return *_aux;
9529 : }
9530 :
9531 : void
9532 3887592 : FEProblemBase::computingNonlinearResid(bool computing_nonlinear_residual)
9533 : {
9534 : parallel_object_only();
9535 :
9536 3887592 : if (_displaced_problem)
9537 192292 : _displaced_problem->computingNonlinearResid(computing_nonlinear_residual);
9538 3887592 : _computing_nonlinear_residual = computing_nonlinear_residual;
9539 3887592 : }
9540 :
9541 : void
9542 9614536 : FEProblemBase::setCurrentlyComputingResidual(bool currently_computing_residual)
9543 : {
9544 9614536 : if (_displaced_problem)
9545 392528 : _displaced_problem->setCurrentlyComputingResidual(currently_computing_residual);
9546 9614536 : _currently_computing_residual = currently_computing_residual;
9547 9614536 : }
9548 :
9549 : void
9550 50 : FEProblemBase::uniformRefine()
9551 : {
9552 : // ResetDisplacedMeshThread::onNode looks up the reference mesh by ID, so we need to make sure
9553 : // we undisplace before adapting the reference mesh
9554 50 : if (_displaced_problem)
9555 34 : _displaced_problem->undisplaceMesh();
9556 :
9557 50 : Adaptivity::uniformRefine(&_mesh, 1);
9558 50 : if (_displaced_problem)
9559 34 : Adaptivity::uniformRefine(&_displaced_problem->mesh(), 1);
9560 :
9561 50 : meshChanged(
9562 : /*intermediate_change=*/false, /*contract_mesh=*/true, /*clean_refinement_flags=*/true);
9563 50 : }
9564 :
9565 : void
9566 59709 : FEProblemBase::automaticScaling(bool automatic_scaling)
9567 : {
9568 59709 : if (_displaced_problem)
9569 2022 : _displaced_problem->automaticScaling(automatic_scaling);
9570 :
9571 59709 : SubProblem::automaticScaling(automatic_scaling);
9572 59709 : }
9573 :
9574 : void
9575 254092 : FEProblemBase::reinitElemFaceRef(const Elem * elem,
9576 : unsigned int side,
9577 : Real tolerance,
9578 : const std::vector<Point> * const pts,
9579 : const std::vector<Real> * const weights,
9580 : const THREAD_ID tid)
9581 : {
9582 254092 : SubProblem::reinitElemFaceRef(elem, side, tolerance, pts, weights, tid);
9583 :
9584 254092 : if (_displaced_problem)
9585 20096 : _displaced_problem->reinitElemFaceRef(
9586 20096 : _displaced_mesh->elemPtr(elem->id()), side, tolerance, pts, weights, tid);
9587 254092 : }
9588 :
9589 : void
9590 254092 : FEProblemBase::reinitNeighborFaceRef(const Elem * neighbor_elem,
9591 : unsigned int neighbor_side,
9592 : Real tolerance,
9593 : const std::vector<Point> * const pts,
9594 : const std::vector<Real> * const weights,
9595 : const THREAD_ID tid)
9596 : {
9597 254092 : SubProblem::reinitNeighborFaceRef(neighbor_elem, neighbor_side, tolerance, pts, weights, tid);
9598 :
9599 254092 : if (_displaced_problem)
9600 20096 : _displaced_problem->reinitNeighborFaceRef(
9601 20096 : _displaced_mesh->elemPtr(neighbor_elem->id()), neighbor_side, tolerance, pts, weights, tid);
9602 254092 : }
9603 :
9604 : void
9605 3050021 : FEProblemBase::getFVMatsAndDependencies(
9606 : const SubdomainID blk_id,
9607 : std::vector<std::shared_ptr<MaterialBase>> & face_materials,
9608 : std::vector<std::shared_ptr<MaterialBase>> & neighbor_materials,
9609 : std::set<MooseVariableFieldBase *> & variables,
9610 : const THREAD_ID tid)
9611 : {
9612 3050021 : if (_materials[Moose::FACE_MATERIAL_DATA].hasActiveBlockObjects(blk_id, tid))
9613 : {
9614 : auto & this_face_mats =
9615 3560 : _materials[Moose::FACE_MATERIAL_DATA].getActiveBlockObjects(blk_id, tid);
9616 7306 : for (std::shared_ptr<MaterialBase> face_mat : this_face_mats)
9617 3746 : if (face_mat->ghostable())
9618 : {
9619 3746 : face_materials.push_back(face_mat);
9620 3746 : auto & var_deps = face_mat->getMooseVariableDependencies();
9621 4118 : for (auto * var : var_deps)
9622 : {
9623 372 : if (!var->isFV())
9624 0 : mooseError(
9625 : "Ghostable materials should only have finite volume variables coupled into them.");
9626 372 : else if (face_mat->hasStatefulProperties())
9627 0 : mooseError("Finite volume materials do not currently support stateful properties.");
9628 372 : variables.insert(var);
9629 : }
9630 3746 : }
9631 : }
9632 :
9633 3050021 : if (_materials[Moose::NEIGHBOR_MATERIAL_DATA].hasActiveBlockObjects(blk_id, tid))
9634 : {
9635 : auto & this_neighbor_mats =
9636 3560 : _materials[Moose::NEIGHBOR_MATERIAL_DATA].getActiveBlockObjects(blk_id, tid);
9637 7306 : for (std::shared_ptr<MaterialBase> neighbor_mat : this_neighbor_mats)
9638 3746 : if (neighbor_mat->ghostable())
9639 : {
9640 3746 : neighbor_materials.push_back(neighbor_mat);
9641 : #ifndef NDEBUG
9642 : auto & var_deps = neighbor_mat->getMooseVariableDependencies();
9643 : for (auto * var : var_deps)
9644 : {
9645 : if (!var->isFV())
9646 : mooseError(
9647 : "Ghostable materials should only have finite volume variables coupled into them.");
9648 : else if (neighbor_mat->hasStatefulProperties())
9649 : mooseError("Finite volume materials do not currently support stateful properties.");
9650 : auto pr = variables.insert(var);
9651 : mooseAssert(!pr.second,
9652 : "We should not have inserted any new variables dependencies from our "
9653 : "neighbor materials that didn't exist for our face materials");
9654 : }
9655 : #endif
9656 3746 : }
9657 : }
9658 3050021 : }
9659 :
9660 : void
9661 31842736 : FEProblemBase::resizeMaterialData(const Moose::MaterialDataType data_type,
9662 : const unsigned int nqp,
9663 : const THREAD_ID tid)
9664 : {
9665 31842736 : getMaterialData(data_type, tid).resize(nqp);
9666 31842736 : }
9667 :
9668 : void
9669 59649 : FEProblemBase::setNonlinearConvergenceNames(const std::vector<ConvergenceName> & convergence_names)
9670 : {
9671 59649 : if (convergence_names.size() != numNonlinearSystems())
9672 0 : paramError("nonlinear_convergence",
9673 : "There must be one convergence object per nonlinear system");
9674 59649 : _nonlinear_convergence_names = convergence_names;
9675 59649 : }
9676 :
9677 : void
9678 61000 : FEProblemBase::setMultiAppFixedPointConvergenceName(const ConvergenceName & convergence_name)
9679 : {
9680 61000 : _multiapp_fixed_point_convergence_name = convergence_name;
9681 61000 : }
9682 :
9683 : void
9684 29972 : FEProblemBase::setSteadyStateConvergenceName(const ConvergenceName & convergence_name)
9685 : {
9686 29972 : _steady_state_convergence_name = convergence_name;
9687 29972 : }
9688 :
9689 : const std::vector<ConvergenceName> &
9690 982215 : FEProblemBase::getNonlinearConvergenceNames() const
9691 : {
9692 982215 : if (_nonlinear_convergence_names)
9693 982215 : return *_nonlinear_convergence_names;
9694 0 : mooseError("The nonlinear system convergence name(s) have not been set.");
9695 : }
9696 :
9697 : bool
9698 26452 : FEProblemBase::hasLinearConvergenceObjects() const
9699 : {
9700 : // If false,this means we have not set one, not that we are querying this too early
9701 : // TODO: once there is a default linear CV object, error on the 'not set' case
9702 26452 : return _linear_convergence_names.has_value();
9703 : }
9704 :
9705 : void
9706 134 : FEProblemBase::setLinearConvergenceNames(const std::vector<ConvergenceName> & convergence_names)
9707 : {
9708 134 : if (convergence_names.size() != numLinearSystems())
9709 0 : paramError("linear_convergence", "There must be one convergence object per linear system");
9710 134 : _linear_convergence_names = convergence_names;
9711 134 : }
9712 :
9713 : const std::vector<ConvergenceName> &
9714 4635 : FEProblemBase::getLinearConvergenceNames() const
9715 : {
9716 4635 : if (_linear_convergence_names)
9717 4635 : return *_linear_convergence_names;
9718 0 : mooseError("The linear convergence name(s) have not been set.");
9719 : }
9720 :
9721 : const ConvergenceName &
9722 249089 : FEProblemBase::getMultiAppFixedPointConvergenceName() const
9723 : {
9724 249089 : if (_multiapp_fixed_point_convergence_name)
9725 249089 : return _multiapp_fixed_point_convergence_name.value();
9726 : else
9727 0 : mooseError("The fixed point convergence name has not been set.");
9728 : }
9729 :
9730 : const ConvergenceName &
9731 102009 : FEProblemBase::getSteadyStateConvergenceName() const
9732 : {
9733 102009 : if (_steady_state_convergence_name)
9734 102009 : return _steady_state_convergence_name.value();
9735 : else
9736 0 : mooseError("The steady convergence name has not been set.");
9737 : }
9738 :
9739 : void
9740 3048188 : FEProblemBase::residualSetup()
9741 : {
9742 3048188 : SubProblem::residualSetup();
9743 : // We need to setup all the nonlinear systems other than our current one which actually called
9744 : // this method (so we have to make sure we don't go in a circle)
9745 6182210 : for (const auto i : make_range(numNonlinearSystems()))
9746 3134022 : if (i != currentNlSysNum())
9747 85834 : _nl[i]->residualSetup();
9748 : // We don't setup the aux sys because that's been done elsewhere
9749 3048188 : if (_displaced_problem)
9750 124147 : _displaced_problem->residualSetup();
9751 3048188 : }
9752 :
9753 : void
9754 473326 : FEProblemBase::jacobianSetup()
9755 : {
9756 473326 : SubProblem::jacobianSetup();
9757 : // We need to setup all the nonlinear systems other than our current one which actually called
9758 : // this method (so we have to make sure we don't go in a circle)
9759 961410 : for (const auto i : make_range(numNonlinearSystems()))
9760 488084 : if (i != currentNlSysNum())
9761 14758 : _nl[i]->jacobianSetup();
9762 : // We don't setup the aux sys because that's been done elsewhere
9763 473326 : if (_displaced_problem)
9764 21144 : _displaced_problem->jacobianSetup();
9765 473326 : }
9766 :
9767 : MooseAppCoordTransform &
9768 95718 : FEProblemBase::coordTransform()
9769 : {
9770 95718 : return mesh().coordTransform();
9771 : }
9772 :
9773 : unsigned int
9774 476221220 : FEProblemBase::currentNlSysNum() const
9775 : {
9776 : // If we don't have nonlinear systems this should be an invalid number
9777 476221220 : unsigned int current_nl_sys_num = libMesh::invalid_uint;
9778 476221220 : if (_nl.size())
9779 476219108 : current_nl_sys_num = currentNonlinearSystem().number();
9780 :
9781 476221220 : return current_nl_sys_num;
9782 : }
9783 :
9784 : unsigned int
9785 0 : FEProblemBase::currentLinearSysNum() const
9786 : {
9787 : // If we don't have linear systems this should be an invalid number
9788 0 : unsigned int current_linear_sys_num = libMesh::invalid_uint;
9789 0 : if (_linear_systems.size())
9790 0 : current_linear_sys_num = currentLinearSystem().number();
9791 :
9792 0 : return current_linear_sys_num;
9793 : }
9794 :
9795 : bool
9796 124184284 : FEProblemBase::shouldPrintExecution(const THREAD_ID tid) const
9797 : {
9798 : // For now, only support printing from thread 0
9799 124184284 : if (tid != 0)
9800 8233713 : return false;
9801 :
9802 231681864 : if (_print_execution_on.isValueSet(_current_execute_on_flag) ||
9803 115731293 : _print_execution_on.isValueSet(EXEC_ALWAYS))
9804 312321 : return true;
9805 : else
9806 115638250 : return false;
9807 : }
9808 :
9809 : std::vector<MortarUserObject *>
9810 252918 : FEProblemBase::getMortarUserObjects(const BoundaryID primary_boundary_id,
9811 : const BoundaryID secondary_boundary_id,
9812 : const bool displaced,
9813 : const std::vector<MortarUserObject *> & mortar_uo_superset)
9814 : {
9815 252918 : std::vector<MortarUserObject *> mortar_uos;
9816 252918 : auto * const subproblem = displaced ? static_cast<SubProblem *>(_displaced_problem.get())
9817 252918 : : static_cast<SubProblem *>(this);
9818 252940 : for (auto * const obj : mortar_uo_superset)
9819 44 : if (obj->onInterface(primary_boundary_id, secondary_boundary_id) &&
9820 22 : (&obj->getSubProblem() == subproblem))
9821 22 : mortar_uos.push_back(obj);
9822 :
9823 252918 : return mortar_uos;
9824 0 : }
9825 :
9826 : std::vector<MortarUserObject *>
9827 252896 : FEProblemBase::getMortarUserObjects(const BoundaryID primary_boundary_id,
9828 : const BoundaryID secondary_boundary_id,
9829 : const bool displaced)
9830 : {
9831 252896 : std::vector<MortarUserObject *> mortar_uos;
9832 252896 : theWarehouse()
9833 252896 : .query()
9834 505792 : .condition<AttribInterfaces>(Interfaces::MortarUserObject)
9835 252896 : .queryInto(mortar_uos);
9836 505792 : return getMortarUserObjects(primary_boundary_id, secondary_boundary_id, displaced, mortar_uos);
9837 252896 : }
9838 :
9839 : void
9840 252896 : FEProblemBase::reinitMortarUserObjects(const BoundaryID primary_boundary_id,
9841 : const BoundaryID secondary_boundary_id,
9842 : const bool displaced)
9843 : {
9844 : const auto mortar_uos =
9845 252896 : getMortarUserObjects(primary_boundary_id, secondary_boundary_id, displaced);
9846 252896 : for (auto * const mortar_uo : mortar_uos)
9847 : {
9848 0 : mortar_uo->setNormals();
9849 0 : mortar_uo->reinit();
9850 : }
9851 252896 : }
9852 :
9853 : void
9854 1046 : FEProblemBase::setVerboseProblem(bool verbose)
9855 : {
9856 1046 : _verbose_setup = verbose ? "true" : "false";
9857 1046 : _verbose_multiapps = verbose;
9858 1046 : _verbose_restore = verbose;
9859 1046 : }
9860 :
9861 : void
9862 111834 : FEProblemBase::setCurrentLowerDElem(const Elem * const lower_d_elem, const THREAD_ID tid)
9863 : {
9864 111834 : SubProblem::setCurrentLowerDElem(lower_d_elem, tid);
9865 111834 : if (_displaced_problem)
9866 27619 : _displaced_problem->setCurrentLowerDElem(
9867 0 : lower_d_elem ? _displaced_mesh->elemPtr(lower_d_elem->id()) : nullptr, tid);
9868 111834 : }
9869 :
9870 : void
9871 121456041 : FEProblemBase::setCurrentBoundaryID(BoundaryID bid, const THREAD_ID tid)
9872 : {
9873 121456041 : SubProblem::setCurrentBoundaryID(bid, tid);
9874 121456041 : if (_displaced_problem)
9875 8992635 : _displaced_problem->setCurrentBoundaryID(bid, tid);
9876 121456041 : }
9877 :
9878 : void
9879 7396645 : FEProblemBase::setCurrentNonlinearSystem(const unsigned int nl_sys_num)
9880 : {
9881 : mooseAssert(nl_sys_num < _nl.size(),
9882 : "System number greater than the number of nonlinear systems");
9883 7396645 : _current_nl_sys = _nl[nl_sys_num].get();
9884 7396645 : _current_solver_sys = _current_nl_sys;
9885 7396645 : }
9886 :
9887 : void
9888 78406 : FEProblemBase::setCurrentLinearSystem(const unsigned int sys_num)
9889 : {
9890 : mooseAssert(sys_num < _linear_systems.size(),
9891 : "System number greater than the number of linear systems");
9892 78406 : _current_linear_sys = _linear_systems[sys_num].get();
9893 78406 : _current_solver_sys = _current_linear_sys;
9894 78406 : }
9895 :
9896 : void
9897 5823385 : FEProblemBase::computeSystems(const ExecFlagType & type)
9898 : {
9899 : // When performing an adjoint solve in the optimization module, the current solver system is the
9900 : // adjoint. However, the adjoint solve requires having accurate time derivative calculations for
9901 : // the forward system. The cleanest way to handle such uses is just to compute the time
9902 : // derivatives for all solver systems instead of trying to guess which ones we need and don't need
9903 11790319 : for (auto & solver_sys : _solver_systems)
9904 5966934 : solver_sys->compute(type);
9905 :
9906 5823385 : _aux->compute(type);
9907 5823352 : }
9908 :
9909 : const ConstElemRange &
9910 3926146 : FEProblemBase::getCurrentAlgebraicElementRange()
9911 : {
9912 3926146 : if (!_current_algebraic_elem_range)
9913 3926146 : return *_mesh.getActiveLocalElementRange();
9914 :
9915 0 : return *_current_algebraic_elem_range;
9916 : }
9917 : const ConstNodeRange &
9918 95478 : FEProblemBase::getCurrentAlgebraicNodeRange()
9919 : {
9920 95478 : if (!_current_algebraic_node_range)
9921 95478 : return *_mesh.getLocalNodeRange();
9922 :
9923 0 : return *_current_algebraic_node_range;
9924 : }
9925 : const ConstBndNodeRange &
9926 3476688 : FEProblemBase::getCurrentAlgebraicBndNodeRange()
9927 : {
9928 3476688 : if (!_current_algebraic_bnd_node_range)
9929 3476688 : return *_mesh.getBoundaryNodeRange();
9930 :
9931 0 : return *_current_algebraic_bnd_node_range;
9932 : }
9933 :
9934 : void
9935 0 : FEProblemBase::setCurrentAlgebraicElementRange(ConstElemRange * range)
9936 : {
9937 0 : if (!range)
9938 : {
9939 0 : _current_algebraic_elem_range = nullptr;
9940 0 : return;
9941 : }
9942 :
9943 0 : _current_algebraic_elem_range = std::make_unique<ConstElemRange>(*range);
9944 : }
9945 : void
9946 0 : FEProblemBase::setCurrentAlgebraicNodeRange(ConstNodeRange * range)
9947 : {
9948 0 : if (!range)
9949 : {
9950 0 : _current_algebraic_node_range = nullptr;
9951 0 : return;
9952 : }
9953 :
9954 0 : _current_algebraic_node_range = std::make_unique<ConstNodeRange>(*range);
9955 : }
9956 : void
9957 0 : FEProblemBase::setCurrentAlgebraicBndNodeRange(ConstBndNodeRange * range)
9958 : {
9959 0 : if (!range)
9960 : {
9961 0 : _current_algebraic_bnd_node_range = nullptr;
9962 0 : return;
9963 : }
9964 :
9965 0 : _current_algebraic_bnd_node_range = std::make_unique<ConstBndNodeRange>(*range);
9966 : }
9967 :
9968 : unsigned short
9969 63084 : FEProblemBase::getCurrentICState()
9970 : {
9971 63084 : return _current_ic_state;
9972 : }
9973 :
9974 : std::string
9975 53033 : FEProblemBase::solverTypeString(const unsigned int solver_sys_num)
9976 : {
9977 53033 : return Moose::stringify(solverParams(solver_sys_num)._type);
9978 : }
9979 :
9980 : SolverParams
9981 1032 : FEProblemBase::makeLinearSolverParams()
9982 : {
9983 1032 : SolverParams solver_params;
9984 1032 : solver_params._type = Moose::SolveType::ST_LINEAR;
9985 1032 : solver_params._line_search = Moose::LineSearchType::LS_NONE;
9986 1032 : return solver_params;
9987 : }
9988 :
9989 : const libMesh::CouplingMatrix &
9990 70983 : FEProblemBase::nonlocalCouplingMatrix(const unsigned i) const
9991 : {
9992 70983 : return _nonlocal_cm[i];
9993 : }
9994 :
9995 : bool
9996 90497066 : FEProblemBase::checkNonlocalCouplingRequirement() const
9997 : {
9998 90497066 : return _requires_nonlocal_coupling;
9999 : }
10000 :
10001 : const std::unordered_map<std::pair<BoundaryID, BoundaryID>,
10002 : std::unique_ptr<AutomaticMortarGeneration>> &
10003 116855 : FEProblemBase::getMortarInterfaces(bool on_displaced) const
10004 : {
10005 116855 : return _mortar_data->getMortarInterfaces(on_displaced);
10006 : }
|