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

Generated by: LCOV version 1.14