LCOV - code coverage report
Current view: top level - src/problems - FEProblemBase.C (source / functions) Hit Total Coverage
Test: idaholab/moose framework: fef103 Lines: 4105 4732 86.7 %
Date: 2025-09-03 20:01:23 Functions: 357 401 89.0 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.14