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