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