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

Generated by: LCOV version 1.14