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

Generated by: LCOV version 1.14