LCOV - code coverage report
Current view: top level - src/problems - SubProblem.C (source / functions) Hit Total Coverage
Test: idaholab/moose framework: d8769b Lines: 598 666 89.8 %
Date: 2025-11-07 20:01:30 Functions: 97 105 92.4 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : //* This file is part of the MOOSE framework
       2             : //* https://mooseframework.inl.gov
       3             : //*
       4             : //* All rights reserved, see COPYRIGHT for full restrictions
       5             : //* https://github.com/idaholab/moose/blob/master/COPYRIGHT
       6             : //*
       7             : //* Licensed under LGPL 2.1, please see LICENSE for details
       8             : //* https://www.gnu.org/licenses/lgpl-2.1.html
       9             : 
      10             : #include "SubProblem.h"
      11             : #include "Factory.h"
      12             : #include "MooseMesh.h"
      13             : #include "Conversion.h"
      14             : #include "Function.h"
      15             : #include "MooseApp.h"
      16             : #include "MooseVariableFE.h"
      17             : #include "MooseArray.h"
      18             : #include "Assembly.h"
      19             : #include "MooseObjectName.h"
      20             : #include "RelationshipManager.h"
      21             : #include "MooseUtils.h"
      22             : #include "DisplacedSystem.h"
      23             : #include "NonlinearSystemBase.h"
      24             : #include "LinearSystem.h"
      25             : 
      26             : #include "libmesh/equation_systems.h"
      27             : #include "libmesh/system.h"
      28             : #include "libmesh/dof_map.h"
      29             : #include "libmesh/string_to_enum.h"
      30             : 
      31             : #include <regex>
      32             : 
      33             : using namespace libMesh;
      34             : 
      35             : InputParameters
      36      374006 : SubProblem::validParams()
      37             : {
      38      374006 :   InputParameters params = Problem::validParams();
      39             : 
      40     1122018 :   params.addParam<bool>(
      41             :       "default_ghosting",
      42      748012 :       false,
      43             :       "Whether or not to use libMesh's default amount of algebraic and geometric ghosting");
      44             : 
      45     1122018 :   params.addParamNamesToGroup("default_ghosting", "Advanced");
      46             : 
      47      374006 :   return params;
      48           0 : }
      49             : 
      50             : const std::unordered_set<FEFamily> SubProblem::_default_families_without_p_refinement = {
      51             :     libMesh::LAGRANGE,
      52             :     libMesh::NEDELEC_ONE,
      53             :     libMesh::RAVIART_THOMAS,
      54             :     libMesh::LAGRANGE_VEC,
      55             :     libMesh::CLOUGH,
      56             :     libMesh::BERNSTEIN,
      57             :     libMesh::RATIONAL_BERNSTEIN};
      58             : 
      59             : // SubProblem /////
      60       67070 : SubProblem::SubProblem(const InputParameters & parameters)
      61             :   : Problem(parameters),
      62       67070 :     _factory(_app.getFactory()),
      63      134140 :     _default_ghosting(getParam<bool>("default_ghosting")),
      64       67070 :     _currently_computing_jacobian(false),
      65       67070 :     _currently_computing_residual_and_jacobian(false),
      66       67070 :     _computing_nonlinear_residual(false),
      67       67070 :     _currently_computing_residual(false),
      68       67070 :     _safe_access_tagged_matrices(false),
      69       67070 :     _safe_access_tagged_vectors(false),
      70       67070 :     _have_ad_objects(false),
      71       67070 :     _show_functors(false),
      72       67070 :     _show_chain_control_data(false),
      73      134140 :     _typed_vector_tags(2),
      74      268280 :     _have_p_refinement(false)
      75             : {
      76       67070 :   unsigned int n_threads = libMesh::n_threads();
      77       67070 :   _active_elemental_moose_variables.resize(n_threads);
      78       67070 :   _has_active_elemental_moose_variables.resize(n_threads);
      79             : 
      80       67070 :   _active_fe_var_coupleable_matrix_tags.resize(n_threads);
      81       67070 :   _active_fe_var_coupleable_vector_tags.resize(n_threads);
      82       67070 :   _active_sc_var_coupleable_matrix_tags.resize(n_threads);
      83       67070 :   _active_sc_var_coupleable_vector_tags.resize(n_threads);
      84             : 
      85       67070 :   _functors.resize(n_threads);
      86       67070 :   _pbblf_functors.resize(n_threads);
      87       67070 :   _functor_to_request_info.resize(n_threads);
      88       67070 : }
      89             : 
      90       62566 : SubProblem::~SubProblem() {}
      91             : 
      92             : TagID
      93      432507 : SubProblem::addVectorTag(const TagName & tag_name,
      94             :                          const Moose::VectorTagType type /* = Moose::VECTOR_TAG_RESIDUAL */)
      95             : {
      96      432507 :   if (type == Moose::VECTOR_TAG_ANY)
      97           0 :     mooseError("Vector tag type cannot be VECTOR_TAG_ANY");
      98             : 
      99      432507 :   const auto tag_name_upper = MooseUtils::toUpper(tag_name);
     100             : 
     101             :   // First, see if the tag exists already
     102     1688359 :   for (const auto & vector_tag : _vector_tags)
     103             :   {
     104             :     mooseAssert(_vector_tags[vector_tag._id] == vector_tag, "Vector tags index mismatch");
     105     1356912 :     if (vector_tag._name == tag_name_upper)
     106             :     {
     107      101060 :       if (vector_tag._type != type)
     108           0 :         mooseError("While attempting to add vector tag with name '",
     109             :                    tag_name_upper,
     110             :                    "' and type ",
     111             :                    type,
     112             :                    ",\na tag with the same name but type ",
     113           0 :                    vector_tag._type,
     114             :                    " was found.\n\nA tag can only exist with one type.");
     115             : 
     116      101060 :       return vector_tag._id;
     117             :     }
     118             :   }
     119             : 
     120             :   // Doesn't exist - create it
     121      331447 :   const TagID new_tag_id = _vector_tags.size();
     122      331447 :   const TagTypeID new_tag_type_id = _typed_vector_tags[type].size();
     123             :   // Primary storage for all tags where the index in the vector == the tag ID
     124      331447 :   _vector_tags.emplace_back(new_tag_id, new_tag_type_id, tag_name_upper, type);
     125             :   // Secondary storage for each type so that we can have quick access to all tags of a type
     126      331447 :   _typed_vector_tags[type].emplace_back(new_tag_id, new_tag_type_id, tag_name_upper, type);
     127             :   // Name map storage for quick name access
     128      331447 :   _vector_tags_name_map.emplace(tag_name_upper, new_tag_id);
     129             : 
     130             :   // Make sure that _vector_tags, _typed_vector_tags, and _vector_tags_name_map are sane
     131      331447 :   verifyVectorTags();
     132             : 
     133      331447 :   return new_tag_id;
     134      432507 : }
     135             : 
     136             : bool
     137      340575 : SubProblem::vectorTagExists(const TagName & tag_name) const
     138             : {
     139             :   mooseAssert(verifyVectorTags(), "Vector tag storage invalid");
     140             : 
     141      340575 :   const auto tag_name_upper = MooseUtils::toUpper(tag_name);
     142     2806104 :   for (const auto & vector_tag : _vector_tags)
     143     2487953 :     if (vector_tag._name == tag_name_upper)
     144       22424 :       return true;
     145             : 
     146      318151 :   return false;
     147      340575 : }
     148             : 
     149             : void
     150          12 : SubProblem::addNotZeroedVectorTag(const TagID tag)
     151             : {
     152          12 :   _not_zeroed_tagged_vectors.insert(tag);
     153          12 : }
     154             : 
     155             : bool
     156     9670503 : SubProblem::vectorTagNotZeroed(const TagID tag) const
     157             : {
     158     9670503 :   return _not_zeroed_tagged_vectors.count(tag);
     159             : }
     160             : 
     161             : const VectorTag &
     162   941108755 : SubProblem::getVectorTag(const TagID tag_id) const
     163             : {
     164             :   mooseAssert(verifyVectorTags(), "Vector tag storage invalid");
     165             : 
     166   941108755 :   if (!vectorTagExists(tag_id))
     167           0 :     mooseError("Vector tag with ID ", tag_id, " does not exist");
     168             : 
     169   941108755 :   return _vector_tags[tag_id];
     170             : }
     171             : 
     172             : std::vector<VectorTag>
     173     6711840 : SubProblem::getVectorTags(const std::set<TagID> & tag_ids) const
     174             : {
     175             :   mooseAssert(verifyVectorTags(), "Vector tag storage invalid");
     176             : 
     177     6711840 :   std::vector<VectorTag> tags;
     178     6711840 :   tags.reserve(tag_ids.size());
     179    26070441 :   for (const auto & tag_id : tag_ids)
     180    19358601 :     tags.push_back(getVectorTag(tag_id));
     181     6711840 :   return tags;
     182           0 : }
     183             : 
     184             : const std::vector<VectorTag> &
     185    11831472 : SubProblem::getVectorTags(const Moose::VectorTagType type /* = Moose::VECTOR_TAG_ANY */) const
     186             : {
     187             :   mooseAssert(verifyVectorTags(), "Vector tag storage invalid");
     188             : 
     189    11831472 :   if (type == Moose::VECTOR_TAG_ANY)
     190      563829 :     return _vector_tags;
     191             :   else
     192    11267643 :     return _typed_vector_tags[type];
     193             : }
     194             : 
     195             : unsigned int
     196     8347729 : SubProblem::numVectorTags(const Moose::VectorTagType type /* = Moose::VECTOR_TAG_ANY */) const
     197             : {
     198             :   mooseAssert(verifyVectorTags(), "Vector tag storage invalid");
     199             : 
     200     8347729 :   return getVectorTags(type).size();
     201             : }
     202             : 
     203             : TagID
     204     6878160 : SubProblem::getVectorTagID(const TagName & tag_name) const
     205             : {
     206             :   mooseAssert(verifyVectorTags(), "Vector tag storage invalid");
     207             : 
     208     6878160 :   const auto tag_name_upper = MooseUtils::toUpper(tag_name);
     209     6878160 :   const auto search = _vector_tags_name_map.find(tag_name_upper);
     210     6878160 :   if (search != _vector_tags_name_map.end())
     211    13756288 :     return search->second;
     212             : 
     213             :   std::string message =
     214          16 :       tag_name_upper == "TIME"
     215             :           ? ".\n\nThis may occur if "
     216             :             "you have a TimeKernel in your problem but did not specify a transient executioner."
     217          16 :           : "";
     218          16 :   mooseError("Vector tag '", tag_name_upper, "' does not exist", message);
     219     6878144 : }
     220             : 
     221             : TagName
     222      169607 : SubProblem::vectorTagName(const TagID tag_id) const
     223             : {
     224             :   mooseAssert(verifyVectorTags(), "Vector tag storage invalid");
     225      169607 :   if (!vectorTagExists(tag_id))
     226           0 :     mooseError("Vector tag with ID ", tag_id, " does not exist");
     227             : 
     228      169607 :   return _vector_tags[tag_id]._name;
     229             : }
     230             : 
     231             : Moose::VectorTagType
     232  2459775016 : SubProblem::vectorTagType(const TagID tag_id) const
     233             : {
     234             :   mooseAssert(verifyVectorTags(), "Vector tag storage invalid");
     235  2459775016 :   if (!vectorTagExists(tag_id))
     236           0 :     mooseError("Vector tag with ID ", tag_id, " does not exist");
     237             : 
     238  2459775016 :   return _vector_tags[tag_id]._type;
     239             : }
     240             : 
     241             : bool
     242      331447 : SubProblem::verifyVectorTags() const
     243             : {
     244     1504429 :   for (TagID tag_id = 0; tag_id < _vector_tags.size(); ++tag_id)
     245             :   {
     246     1172982 :     const auto & vector_tag = _vector_tags[tag_id];
     247             : 
     248     1172982 :     if (vector_tag._id != tag_id)
     249           0 :       mooseError("Vector tag ", vector_tag._id, " id mismatch in _vector_tags");
     250     1172982 :     if (vector_tag._type == Moose::VECTOR_TAG_ANY)
     251           0 :       mooseError("Vector tag '", vector_tag._name, "' has type VECTOR_TAG_ANY");
     252             : 
     253     1172982 :     const auto search = _vector_tags_name_map.find(vector_tag._name);
     254     1172982 :     if (search == _vector_tags_name_map.end())
     255           0 :       mooseError("Vector tag ", vector_tag._id, " is not in _vector_tags_name_map");
     256     1172982 :     else if (search->second != tag_id)
     257           0 :       mooseError("Vector tag ", vector_tag._id, " has incorrect id in _vector_tags_name_map");
     258             : 
     259     1172982 :     unsigned int found_in_type = 0;
     260     4396096 :     for (TagTypeID tag_type_id = 0; tag_type_id < _typed_vector_tags[vector_tag._type].size();
     261             :          ++tag_type_id)
     262             :     {
     263     3223114 :       const auto & vector_tag_type = _typed_vector_tags[vector_tag._type][tag_type_id];
     264     3223114 :       if (vector_tag_type == vector_tag)
     265             :       {
     266     1172982 :         ++found_in_type;
     267     1172982 :         if (vector_tag_type._type_id != tag_type_id)
     268           0 :           mooseError("Type ID for Vector tag ", tag_id, " is incorrect");
     269             :       }
     270             :     }
     271             : 
     272     1172982 :     if (found_in_type == 0)
     273           0 :       mooseError("Vector tag ", tag_id, " not found in _typed_vector_tags");
     274     1172982 :     if (found_in_type > 1)
     275           0 :       mooseError("Vector tag ", tag_id, " found multiple times in _typed_vector_tags");
     276             :   }
     277             : 
     278      331447 :   unsigned int num_typed_vector_tags = 0;
     279      994341 :   for (const auto & typed_vector_tags : _typed_vector_tags)
     280      662894 :     num_typed_vector_tags += typed_vector_tags.size();
     281      331447 :   if (num_typed_vector_tags != _vector_tags.size())
     282           0 :     mooseError("Size mismatch between _vector_tags and _typed_vector_tags");
     283      331447 :   if (_vector_tags_name_map.size() != _vector_tags.size())
     284           0 :     mooseError("Size mismatch between _vector_tags and _vector_tags_name_map");
     285             : 
     286      331447 :   return true;
     287             : }
     288             : 
     289             : void
     290     3320664 : SubProblem::selectVectorTagsFromSystem(const SystemBase & system,
     291             :                                        const std::vector<VectorTag> & input_vector_tags,
     292             :                                        std::set<TagID> & selected_tags)
     293             : {
     294     3320664 :   selected_tags.clear();
     295    12937253 :   for (const auto & vector_tag : input_vector_tags)
     296     9616589 :     if (system.hasVector(vector_tag._id))
     297     9614443 :       selected_tags.insert(vector_tag._id);
     298     3320664 : }
     299             : 
     300             : void
     301        5738 : SubProblem::selectMatrixTagsFromSystem(const SystemBase & system,
     302             :                                        const std::map<TagName, TagID> & input_matrix_tags,
     303             :                                        std::set<TagID> & selected_tags)
     304             : {
     305        5738 :   selected_tags.clear();
     306       11985 :   for (const auto & matrix_tag_pair : input_matrix_tags)
     307        6247 :     if (system.hasMatrix(matrix_tag_pair.second))
     308        5762 :       selected_tags.insert(matrix_tag_pair.second);
     309        5738 : }
     310             : 
     311             : TagID
     312      131122 : SubProblem::addMatrixTag(TagName tag_name)
     313             : {
     314      131122 :   auto tag_name_upper = MooseUtils::toUpper(tag_name);
     315      131122 :   auto existing_tag = _matrix_tag_name_to_tag_id.find(tag_name_upper);
     316      131122 :   if (existing_tag == _matrix_tag_name_to_tag_id.end())
     317             :   {
     318      130579 :     auto tag_id = _matrix_tag_name_to_tag_id.size();
     319             : 
     320      130579 :     _matrix_tag_name_to_tag_id[tag_name_upper] = tag_id;
     321             : 
     322      130579 :     _matrix_tag_id_to_tag_name[tag_id] = tag_name_upper;
     323             :   }
     324             : 
     325      262244 :   return _matrix_tag_name_to_tag_id.at(tag_name_upper);
     326      131122 : }
     327             : 
     328             : bool
     329      309122 : SubProblem::matrixTagExists(const TagName & tag_name) const
     330             : {
     331      309122 :   auto tag_name_upper = MooseUtils::toUpper(tag_name);
     332             : 
     333      618244 :   return _matrix_tag_name_to_tag_id.find(tag_name_upper) != _matrix_tag_name_to_tag_id.end();
     334      309122 : }
     335             : 
     336             : bool
     337     1674288 : SubProblem::matrixTagExists(TagID tag_id) const
     338             : {
     339     1674288 :   return _matrix_tag_id_to_tag_name.find(tag_id) != _matrix_tag_id_to_tag_name.end();
     340             : }
     341             : 
     342             : TagID
     343      307203 : SubProblem::getMatrixTagID(const TagName & tag_name) const
     344             : {
     345      307203 :   auto tag_name_upper = MooseUtils::toUpper(tag_name);
     346             : 
     347      307203 :   if (!matrixTagExists(tag_name))
     348           4 :     mooseError("Matrix tag: ",
     349             :                tag_name,
     350             :                " does not exist. ",
     351             :                "If this is a TimeKernel then this may have happened because you didn't "
     352             :                "specify a Transient Executioner.");
     353             : 
     354      614398 :   return _matrix_tag_name_to_tag_id.at(tag_name_upper);
     355      307199 : }
     356             : 
     357             : TagName
     358         444 : SubProblem::matrixTagName(TagID tag)
     359             : {
     360         444 :   return _matrix_tag_id_to_tag_name[tag];
     361             : }
     362             : 
     363             : void
     364      656299 : SubProblem::setActiveFEVariableCoupleableMatrixTags(std::set<TagID> & mtags, const THREAD_ID tid)
     365             : {
     366      656299 :   _active_fe_var_coupleable_matrix_tags[tid] = mtags;
     367      656299 : }
     368             : 
     369             : void
     370     7669424 : SubProblem::setActiveFEVariableCoupleableVectorTags(std::set<TagID> & vtags, const THREAD_ID tid)
     371             : {
     372     7669424 :   _active_fe_var_coupleable_vector_tags[tid] = vtags;
     373    15471904 :   for (const auto sys_num : make_range(numSolverSystems()))
     374     7802480 :     systemBaseSolver(sys_num).setActiveVariableCoupleableVectorTags(vtags, tid);
     375     7669424 :   systemBaseAuxiliary().setActiveVariableCoupleableVectorTags(vtags, tid);
     376     7669424 : }
     377             : 
     378             : void
     379      299357 : SubProblem::clearActiveFEVariableCoupleableVectorTags(const THREAD_ID tid)
     380             : {
     381      299357 :   _active_fe_var_coupleable_vector_tags[tid].clear();
     382      299357 : }
     383             : 
     384             : void
     385      299357 : SubProblem::clearActiveFEVariableCoupleableMatrixTags(const THREAD_ID tid)
     386             : {
     387      299357 :   _active_fe_var_coupleable_matrix_tags[tid].clear();
     388      299357 : }
     389             : 
     390             : const std::set<TagID> &
     391  1925073865 : SubProblem::getActiveFEVariableCoupleableMatrixTags(const THREAD_ID tid) const
     392             : {
     393  1925073865 :   return _active_fe_var_coupleable_matrix_tags[tid];
     394             : }
     395             : 
     396             : const std::set<TagID> &
     397         334 : SubProblem::getActiveFEVariableCoupleableVectorTags(const THREAD_ID tid) const
     398             : {
     399         334 :   return _active_fe_var_coupleable_vector_tags[tid];
     400             : }
     401             : 
     402             : void
     403       56031 : SubProblem::setActiveScalarVariableCoupleableMatrixTags(std::set<TagID> & mtags,
     404             :                                                         const THREAD_ID tid)
     405             : {
     406       56031 :   _active_sc_var_coupleable_matrix_tags[tid] = mtags;
     407       56031 : }
     408             : 
     409             : void
     410       56031 : SubProblem::setActiveScalarVariableCoupleableVectorTags(std::set<TagID> & vtags,
     411             :                                                         const THREAD_ID tid)
     412             : {
     413       56031 :   _active_sc_var_coupleable_vector_tags[tid] = vtags;
     414      112062 :   for (const auto nl_sys_num : make_range(numNonlinearSystems()))
     415       56031 :     systemBaseNonlinear(nl_sys_num).setActiveScalarVariableCoupleableVectorTags(vtags, tid);
     416       56031 :   systemBaseAuxiliary().setActiveScalarVariableCoupleableVectorTags(vtags, tid);
     417       56031 : }
     418             : 
     419             : void
     420       56031 : SubProblem::clearActiveScalarVariableCoupleableVectorTags(const THREAD_ID tid)
     421             : {
     422       56031 :   _active_sc_var_coupleable_vector_tags[tid].clear();
     423       56031 : }
     424             : 
     425             : void
     426       56031 : SubProblem::clearActiveScalarVariableCoupleableMatrixTags(const THREAD_ID tid)
     427             : {
     428       56031 :   _active_sc_var_coupleable_matrix_tags[tid].clear();
     429       56031 : }
     430             : 
     431             : const std::set<TagID> &
     432      569980 : SubProblem::getActiveScalarVariableCoupleableMatrixTags(const THREAD_ID tid) const
     433             : {
     434      569980 :   return _active_sc_var_coupleable_matrix_tags[tid];
     435             : }
     436             : 
     437             : const std::set<TagID> &
     438           0 : SubProblem::getActiveScalarVariableCoupleableVectorTags(const THREAD_ID tid) const
     439             : {
     440           0 :   return _active_sc_var_coupleable_vector_tags[tid];
     441             : }
     442             : 
     443             : void
     444    11862332 : SubProblem::setActiveElementalMooseVariables(const std::set<MooseVariableFEBase *> & moose_vars,
     445             :                                              const THREAD_ID tid)
     446             : {
     447    11862332 :   if (!moose_vars.empty())
     448             :   {
     449    11415840 :     _has_active_elemental_moose_variables[tid] = 1;
     450    11415840 :     _active_elemental_moose_variables[tid] = moose_vars;
     451             :   }
     452    11862332 : }
     453             : 
     454             : const std::set<MooseVariableFEBase *> &
     455  1282806667 : SubProblem::getActiveElementalMooseVariables(const THREAD_ID tid) const
     456             : {
     457  1282806667 :   return _active_elemental_moose_variables[tid];
     458             : }
     459             : 
     460             : bool
     461  1328140674 : SubProblem::hasActiveElementalMooseVariables(const THREAD_ID tid) const
     462             : {
     463  1328140674 :   return _has_active_elemental_moose_variables[tid];
     464             : }
     465             : 
     466             : void
     467     4902201 : SubProblem::clearActiveElementalMooseVariables(const THREAD_ID tid)
     468             : {
     469     4902201 :   _has_active_elemental_moose_variables[tid] = 0;
     470     4902201 :   _active_elemental_moose_variables[tid].clear();
     471     4902201 : }
     472             : 
     473             : std::set<SubdomainID>
     474           8 : SubProblem::getMaterialPropertyBlocks(const std::string & prop_name)
     475             : {
     476           8 :   std::set<SubdomainID> blocks;
     477             : 
     478          24 :   for (const auto & it : _map_block_material_props)
     479             :   {
     480          16 :     const std::set<std::string> & prop_names = it.second;
     481          16 :     std::set<std::string>::iterator name_it = prop_names.find(prop_name);
     482          16 :     if (name_it != prop_names.end())
     483          16 :       blocks.insert(it.first);
     484             :   }
     485             : 
     486           8 :   return blocks;
     487           0 : }
     488             : 
     489             : std::vector<SubdomainName>
     490           8 : SubProblem::getMaterialPropertyBlockNames(const std::string & prop_name)
     491             : {
     492           8 :   std::set<SubdomainID> blocks = getMaterialPropertyBlocks(prop_name);
     493           8 :   std::vector<SubdomainName> block_names;
     494           8 :   block_names.reserve(blocks.size());
     495          24 :   for (const auto & block_id : blocks)
     496             :   {
     497          16 :     SubdomainName name;
     498          16 :     name = mesh().getMesh().subdomain_name(block_id);
     499          16 :     if (name.empty())
     500             :     {
     501           8 :       std::ostringstream oss;
     502           8 :       oss << block_id;
     503           8 :       name = oss.str();
     504           8 :     }
     505          16 :     block_names.push_back(name);
     506          16 :   }
     507             : 
     508          16 :   return block_names;
     509           8 : }
     510             : 
     511             : bool
     512         360 : SubProblem::hasBlockMaterialProperty(SubdomainID bid, const std::string & prop_name)
     513             : {
     514         360 :   auto it = _map_block_material_props.find(bid);
     515         360 :   if (it == _map_block_material_props.end())
     516           0 :     return false;
     517             : 
     518         360 :   if (it->second.count(prop_name) > 0)
     519         270 :     return true;
     520             :   else
     521          90 :     return false;
     522             : }
     523             : 
     524             : // TODO: remove code duplication by templating
     525             : std::set<BoundaryID>
     526           8 : SubProblem::getMaterialPropertyBoundaryIDs(const std::string & prop_name)
     527             : {
     528           8 :   std::set<BoundaryID> boundaries;
     529             : 
     530          20 :   for (const auto & it : _map_boundary_material_props)
     531             :   {
     532          12 :     const std::set<std::string> & prop_names = it.second;
     533          12 :     std::set<std::string>::iterator name_it = prop_names.find(prop_name);
     534          12 :     if (name_it != prop_names.end())
     535          12 :       boundaries.insert(it.first);
     536             :   }
     537             : 
     538           8 :   return boundaries;
     539           0 : }
     540             : 
     541             : std::vector<BoundaryName>
     542           8 : SubProblem::getMaterialPropertyBoundaryNames(const std::string & prop_name)
     543             : {
     544           8 :   std::set<BoundaryID> boundaries = getMaterialPropertyBoundaryIDs(prop_name);
     545           8 :   std::vector<BoundaryName> boundary_names;
     546           8 :   boundary_names.reserve(boundaries.size());
     547           8 :   const BoundaryInfo & boundary_info = mesh().getMesh().get_boundary_info();
     548             : 
     549          20 :   for (const auto & bnd_id : boundaries)
     550             :   {
     551          12 :     BoundaryName name;
     552          12 :     if (bnd_id == Moose::ANY_BOUNDARY_ID)
     553           4 :       name = "ANY_BOUNDARY_ID";
     554             :     else
     555             :     {
     556           8 :       name = boundary_info.get_sideset_name(bnd_id);
     557           8 :       if (name.empty())
     558             :       {
     559           0 :         std::ostringstream oss;
     560           0 :         oss << bnd_id;
     561           0 :         name = oss.str();
     562           0 :       }
     563             :     }
     564          12 :     boundary_names.push_back(name);
     565          12 :   }
     566             : 
     567          16 :   return boundary_names;
     568           8 : }
     569             : 
     570             : bool
     571           0 : SubProblem::hasBoundaryMaterialProperty(BoundaryID bid, const std::string & prop_name)
     572             : {
     573           0 :   auto it = _map_boundary_material_props.find(bid);
     574           0 :   if (it == _map_boundary_material_props.end())
     575           0 :     return false;
     576             : 
     577           0 :   if (it->second.count(prop_name) > 0)
     578           0 :     return true;
     579             :   else
     580           0 :     return false;
     581             : }
     582             : 
     583             : void
     584       71572 : SubProblem::storeSubdomainMatPropName(SubdomainID block_id, const std::string & name)
     585             : {
     586       71572 :   _map_block_material_props[block_id].insert(name);
     587       71572 : }
     588             : 
     589             : void
     590       67548 : SubProblem::storeBoundaryMatPropName(BoundaryID boundary_id, const std::string & name)
     591             : {
     592       67548 :   _map_boundary_material_props[boundary_id].insert(name);
     593       67548 : }
     594             : 
     595             : void
     596        9522 : SubProblem::storeSubdomainZeroMatProp(SubdomainID block_id, const MaterialPropertyName & name)
     597             : {
     598        9522 :   _zero_block_material_props[block_id].insert(name);
     599        9522 : }
     600             : 
     601             : void
     602        9522 : SubProblem::storeBoundaryZeroMatProp(BoundaryID boundary_id, const MaterialPropertyName & name)
     603             : {
     604        9522 :   _zero_boundary_material_props[boundary_id].insert(name);
     605        9522 : }
     606             : 
     607             : void
     608       46860 : SubProblem::storeSubdomainDelayedCheckMatProp(const std::string & requestor,
     609             :                                               SubdomainID block_id,
     610             :                                               const std::string & name)
     611             : {
     612       46860 :   _map_block_material_props_check[block_id].insert(std::make_pair(requestor, name));
     613       46860 : }
     614             : 
     615             : void
     616        6354 : SubProblem::storeBoundaryDelayedCheckMatProp(const std::string & requestor,
     617             :                                              BoundaryID boundary_id,
     618             :                                              const std::string & name)
     619             : {
     620        6354 :   _map_boundary_material_props_check[boundary_id].insert(std::make_pair(requestor, name));
     621        6354 : }
     622             : 
     623             : void
     624       62704 : SubProblem::checkBlockMatProps()
     625             : {
     626             :   // Variable for storing all available blocks/boundaries from the mesh
     627       62704 :   std::set<SubdomainID> all_ids(mesh().meshSubdomains());
     628             : 
     629       62704 :   std::stringstream errors;
     630             : 
     631             :   // Loop through the properties to check
     632       69472 :   for (const auto & check_it : _map_block_material_props_check)
     633             :   {
     634             :     // The current id for the property being checked (BoundaryID || BlockID)
     635        6768 :     SubdomainID check_id = check_it.first;
     636             : 
     637       13536 :     std::set<SubdomainID> check_ids = {check_id};
     638             : 
     639             :     // Loop through all the block/boundary ids
     640       13536 :     for (const auto & id : check_ids)
     641             :     {
     642             :       // Loop through all the stored properties
     643       51401 :       for (const auto & prop_it : check_it.second)
     644             :       {
     645             :         // Produce an error if the material property is not defined on the current block/boundary
     646             :         // and any block/boundary
     647             :         // and not is not a zero material property.
     648       44742 :         if (_map_block_material_props[id].count(prop_it.second) == 0 &&
     649       44742 :             _zero_block_material_props[id].count(prop_it.second) == 0)
     650             :         {
     651          53 :           std::string check_name = restrictionSubdomainCheckName(id);
     652          53 :           if (check_name.empty())
     653          48 :             check_name = std::to_string(id);
     654         106 :           errors << "Material property '" << prop_it.second << "', requested by '" << prop_it.first
     655          53 :                  << "' is not defined on block " << check_name << "\n";
     656          53 :         }
     657             :       }
     658             :     }
     659        6768 :   }
     660             : 
     661       62704 :   if (!errors.str().empty())
     662          42 :     mooseError(errors.str());
     663       62662 : }
     664             : 
     665             : void
     666       62662 : SubProblem::checkBoundaryMatProps()
     667             : {
     668             :   // Variable for storing the value for ANY_BOUNDARY_ID
     669       62662 :   BoundaryID any_id = Moose::ANY_BOUNDARY_ID;
     670             : 
     671             :   // Variable for storing all available blocks/boundaries from the mesh
     672       62662 :   std::set<BoundaryID> all_ids(mesh().getBoundaryIDs());
     673             : 
     674       62662 :   std::stringstream errors;
     675             : 
     676             :   // Loop through the properties to check
     677       65398 :   for (const auto & check_it : _map_boundary_material_props_check)
     678             :   {
     679             :     // The current id for the property being checked (BoundaryID || BlockID)
     680        2736 :     BoundaryID check_id = check_it.first;
     681             : 
     682             :     // In the case when the material being checked has an ID is set to ANY, then loop through all
     683             :     // the possible ids and verify that the material property is defined.
     684        5472 :     std::set<BoundaryID> check_ids{check_id};
     685        2736 :     if (check_id == any_id)
     686           0 :       check_ids = all_ids;
     687             : 
     688             :     // Loop through all the block/boundary ids
     689        5472 :     for (const auto & id : check_ids)
     690             :     {
     691             :       // Loop through all the stored properties
     692        9090 :       for (const auto & prop_it : check_it.second)
     693             :       {
     694             :         // Produce an error if the material property is not defined on the current block/boundary
     695             :         // and any block/boundary
     696             :         // and not is not a zero material property.
     697        6354 :         if (_map_boundary_material_props[id].count(prop_it.second) == 0 &&
     698        5041 :             _map_boundary_material_props[any_id].count(prop_it.second) == 0 &&
     699       24118 :             _zero_boundary_material_props[id].count(prop_it.second) == 0 &&
     700        6369 :             _zero_boundary_material_props[any_id].count(prop_it.second) == 0)
     701             :         {
     702          15 :           std::string check_name = restrictionBoundaryCheckName(id);
     703          15 :           if (check_name.empty())
     704           0 :             check_name = std::to_string(id);
     705          30 :           errors << "Material property '" << prop_it.second << "', requested by '" << prop_it.first
     706          15 :                  << "' is not defined on boundary " << check_name << "\n";
     707          15 :         }
     708             :       }
     709             :     }
     710        2736 :   }
     711             : 
     712       62662 :   if (!errors.str().empty())
     713          12 :     mooseError(errors.str());
     714       62650 : }
     715             : 
     716             : bool
     717           0 : SubProblem::nlConverged(const unsigned int nl_sys_num)
     718             : {
     719             :   mooseAssert(nl_sys_num < numNonlinearSystems(),
     720             :               "The nonlinear system number is higher than the number of systems we have!");
     721           0 :   return solverSystemConverged(nl_sys_num);
     722             : }
     723             : 
     724             : void
     725       66788 : SubProblem::markMatPropRequested(const std::string & prop_name)
     726             : {
     727       66788 :   _material_property_requested.insert(prop_name);
     728       66788 : }
     729             : 
     730             : bool
     731           0 : SubProblem::isMatPropRequested(const std::string & prop_name) const
     732             : {
     733           0 :   return _material_property_requested.find(prop_name) != _material_property_requested.end();
     734             : }
     735             : 
     736             : void
     737       51752 : SubProblem::addConsumedPropertyName(const MooseObjectName & obj_name, const std::string & prop_name)
     738             : {
     739       51752 :   _consumed_material_properties[obj_name].insert(prop_name);
     740       51752 : }
     741             : 
     742             : const std::map<MooseObjectName, std::set<std::string>> &
     743         248 : SubProblem::getConsumedPropertyMap() const
     744             : {
     745         248 :   return _consumed_material_properties;
     746             : }
     747             : 
     748             : DiracKernelInfo &
     749        1024 : SubProblem::diracKernelInfo()
     750             : {
     751        1024 :   return _dirac_kernel_info;
     752             : }
     753             : 
     754             : Real
     755           0 : SubProblem::finalNonlinearResidual(unsigned int) const
     756             : {
     757           0 :   return 0;
     758             : }
     759             : 
     760             : unsigned int
     761           0 : SubProblem::nNonlinearIterations(unsigned int) const
     762             : {
     763           0 :   return 0;
     764             : }
     765             : 
     766             : unsigned int
     767           0 : SubProblem::nLinearIterations(unsigned int) const
     768             : {
     769           0 :   return 0;
     770             : }
     771             : 
     772             : std::string
     773          53 : SubProblem::restrictionSubdomainCheckName(SubdomainID check_id)
     774             : {
     775             :   // TODO: Put a better a interface in MOOSE
     776          53 :   std::map<subdomain_id_type, std::string> & name_map = mesh().getMesh().set_subdomain_name_map();
     777          53 :   std::map<subdomain_id_type, std::string>::const_iterator pos = name_map.find(check_id);
     778          53 :   if (pos != name_map.end())
     779           5 :     return pos->second;
     780          96 :   return "";
     781             : }
     782             : 
     783             : std::string
     784          15 : SubProblem::restrictionBoundaryCheckName(BoundaryID check_id)
     785             : {
     786          15 :   return mesh().getMesh().get_boundary_info().sideset_name(check_id);
     787             : }
     788             : 
     789             : void
     790   146038405 : SubProblem::setCurrentBoundaryID(BoundaryID bid, const THREAD_ID tid)
     791             : {
     792   293377461 :   for (const auto nl_sys_num : make_range(numNonlinearSystems()))
     793   147339056 :     assembly(tid, nl_sys_num).setCurrentBoundaryID(bid);
     794   146038405 : }
     795             : 
     796             : unsigned int
     797         216 : SubProblem::getAxisymmetricRadialCoord() const
     798             : {
     799         216 :   return mesh().getAxisymmetricRadialCoord();
     800             : }
     801             : 
     802             : bool
     803           4 : SubProblem::hasLinearVariable(const std::string & var_name) const
     804             : {
     805           4 :   for (const auto i : make_range(numLinearSystems()))
     806           0 :     if (systemBaseLinear(i).hasVariable(var_name))
     807           0 :       return true;
     808           4 :   return false;
     809             : }
     810             : 
     811             : bool
     812          18 : SubProblem::hasAuxiliaryVariable(const std::string & var_name) const
     813             : {
     814          18 :   return systemBaseAuxiliary().hasVariable(var_name);
     815             : }
     816             : 
     817             : template <typename T>
     818             : MooseVariableFEBase &
     819     4811952 : SubProblem::getVariableHelper(const THREAD_ID tid,
     820             :                               const std::string & var_name,
     821             :                               Moose::VarKindType expected_var_type,
     822             :                               Moose::VarFieldType expected_var_field_type,
     823             :                               const std::vector<T> & systems,
     824             :                               const SystemBase & aux) const
     825             : {
     826             :   // Eventual return value
     827     4811952 :   MooseVariableFEBase * var = nullptr;
     828             : 
     829     4811952 :   const auto [var_in_sys, sys_num] = determineSolverSystem(var_name);
     830             : 
     831             :   // First check that the variable is found on the expected system.
     832     4811952 :   if (expected_var_type == Moose::VarKindType::VAR_ANY)
     833             :   {
     834     2637124 :     if (var_in_sys)
     835     1217694 :       var = &(systems[sys_num]->getVariable(tid, var_name));
     836     1419430 :     else if (aux.hasVariable(var_name))
     837     1419430 :       var = &(aux.getVariable(tid, var_name));
     838             :     else
     839           0 :       mooseError("Unknown variable " + var_name);
     840             :   }
     841     2373959 :   else if (expected_var_type == Moose::VarKindType::VAR_SOLVER && var_in_sys &&
     842      199131 :            systems[sys_num]->hasVariable(var_name))
     843      199131 :     var = &(systems[sys_num]->getVariable(tid, var_name));
     844     1975697 :   else if (expected_var_type == Moose::VarKindType::VAR_AUXILIARY && aux.hasVariable(var_name))
     845     1975697 :     var = &(aux.getVariable(tid, var_name));
     846             :   else
     847             :   {
     848           0 :     std::string expected_var_type_string =
     849             :         (expected_var_type == Moose::VarKindType::VAR_SOLVER ? "nonlinear" : "auxiliary");
     850           0 :     mooseError("No ",
     851             :                expected_var_type_string,
     852             :                " variable named ",
     853             :                var_name,
     854             :                " found. "
     855             :                "Did you specify an auxiliary variable when you meant to specify a nonlinear "
     856             :                "variable (or vice-versa)?");
     857           0 :   }
     858             : 
     859             :   // Now make sure the var found has the expected field type.
     860     7050256 :   if ((expected_var_field_type == Moose::VarFieldType::VAR_FIELD_ANY) ||
     861     2238304 :       (expected_var_field_type == var->fieldType()))
     862     4811944 :     return *var;
     863             :   else
     864             :   {
     865           8 :     std::string expected_var_field_type_string =
     866             :         MooseUtils::toLower(Moose::stringify(expected_var_field_type));
     867           8 :     std::string var_field_type_string = MooseUtils::toLower(Moose::stringify(var->fieldType()));
     868             : 
     869           8 :     mooseError("No ",
     870             :                expected_var_field_type_string,
     871             :                " variable named ",
     872             :                var_name,
     873             :                " found. "
     874             :                "Did you specify a ",
     875             :                var_field_type_string,
     876             :                " variable when you meant to specify a ",
     877             :                expected_var_field_type_string,
     878             :                " variable?");
     879           0 :   }
     880             : }
     881             : 
     882             : void
     883      307207 : SubProblem::reinitElemFaceRef(const Elem * elem,
     884             :                               unsigned int side,
     885             :                               Real tolerance,
     886             :                               const std::vector<Point> * const pts,
     887             :                               const std::vector<Real> * const weights,
     888             :                               const THREAD_ID tid)
     889             : {
     890      614414 :   for (const auto nl_sys_num : make_range(numNonlinearSystems()))
     891             :   {
     892             :     // - Set our _current_elem for proper dof index getting in the moose variables
     893             :     // - Reinitialize all of our FE objects so we have current phi, dphi, etc. data
     894             :     // Note that our number of shape functions will reflect the number of shapes associated with the
     895             :     // interior element while the number of quadrature points will be determined by the passed pts
     896             :     // parameter (which presumably will have a number of pts reflective of a facial quadrature rule)
     897      307207 :     assembly(tid, nl_sys_num).reinitElemFaceRef(elem, side, tolerance, pts, weights);
     898             : 
     899      307207 :     auto & nl = systemBaseNonlinear(nl_sys_num);
     900             : 
     901             :     // Actually get the dof indices in the moose variables
     902      307207 :     nl.prepare(tid);
     903             : 
     904             :     // Let's finally compute our variable values!
     905      307207 :     nl.reinitElemFace(elem, side, tid);
     906             :   }
     907             : 
     908             :   // do same for aux as for nl
     909      307207 :   systemBaseAuxiliary().prepare(tid);
     910      307207 :   systemBaseAuxiliary().reinitElemFace(elem, side, tid);
     911             : 
     912             :   // With the dof indices set in the moose variables, now let's properly size
     913             :   // our local residuals/Jacobians
     914      307207 :   auto & current_assembly = assembly(tid, currentNlSysNum());
     915      307207 :   if (currentlyComputingJacobian() || currentlyComputingResidualAndJacobian())
     916      101316 :     current_assembly.prepareJacobianBlock();
     917      307207 :   if (!currentlyComputingJacobian())
     918      205891 :     current_assembly.prepareResidual();
     919      307207 : }
     920             : 
     921             : void
     922      307207 : SubProblem::reinitNeighborFaceRef(const Elem * neighbor_elem,
     923             :                                   unsigned int neighbor_side,
     924             :                                   Real tolerance,
     925             :                                   const std::vector<Point> * const pts,
     926             :                                   const std::vector<Real> * const weights,
     927             :                                   const THREAD_ID tid)
     928             : {
     929      614414 :   for (const auto nl_sys_num : make_range(numNonlinearSystems()))
     930             :   {
     931             :     // - Set our _current_neighbor_elem for proper dof index getting in the moose variables
     932             :     // - Reinitialize all of our FE objects so we have current phi, dphi, etc. data
     933             :     // Note that our number of shape functions will reflect the number of shapes associated with the
     934             :     // interior element while the number of quadrature points will be determined by the passed pts
     935             :     // parameter (which presumably will have a number of pts reflective of a facial quadrature rule)
     936      307207 :     assembly(tid, nl_sys_num)
     937      307207 :         .reinitNeighborFaceRef(neighbor_elem, neighbor_side, tolerance, pts, weights);
     938             : 
     939      307207 :     auto & nl = systemBaseNonlinear(nl_sys_num);
     940             : 
     941             :     // Actually get the dof indices in the moose variables
     942      307207 :     nl.prepareNeighbor(tid);
     943             : 
     944             :     // Let's finally compute our variable values!
     945      307207 :     nl.reinitNeighborFace(neighbor_elem, neighbor_side, tid);
     946             :   }
     947             : 
     948             :   // do same for aux as for nl
     949      307207 :   systemBaseAuxiliary().prepareNeighbor(tid);
     950      307207 :   systemBaseAuxiliary().reinitNeighborFace(neighbor_elem, neighbor_side, tid);
     951             : 
     952             :   // With the dof indices set in the moose variables, now let's properly size
     953             :   // our local residuals/Jacobians
     954      307207 :   assembly(tid, currentNlSysNum()).prepareNeighbor();
     955      307207 : }
     956             : 
     957             : void
     958      324608 : SubProblem::reinitLowerDElem(const Elem * elem,
     959             :                              const THREAD_ID tid,
     960             :                              const std::vector<Point> * const pts,
     961             :                              const std::vector<Real> * const weights)
     962             : {
     963      649216 :   for (const auto nl_sys_num : make_range(numNonlinearSystems()))
     964             :   {
     965             :     // - Set our _current_lower_d_elem for proper dof index getting in the moose variables
     966             :     // - Reinitialize all of our lower-d FE objects so we have current phi, dphi, etc. data
     967      324608 :     assembly(tid, nl_sys_num).reinitLowerDElem(elem, pts, weights);
     968             : 
     969      324608 :     auto & nl = systemBaseNonlinear(nl_sys_num);
     970             : 
     971             :     // Actually get the dof indices in the moose variables
     972      324608 :     nl.prepareLowerD(tid);
     973             : 
     974             :     // With the dof indices set in the moose variables, now let's properly size
     975             :     // our local residuals/Jacobians
     976      324608 :     assembly(tid, nl_sys_num).prepareLowerD();
     977             : 
     978             :     // Let's finally compute our variable values!
     979      324608 :     nl.reinitLowerD(tid);
     980             :   }
     981             : 
     982             :   // do same for aux as for nl
     983      324608 :   systemBaseAuxiliary().prepareLowerD(tid);
     984      324608 :   systemBaseAuxiliary().reinitLowerD(tid);
     985      324608 : }
     986             : 
     987             : void
     988      284429 : SubProblem::reinitNeighborLowerDElem(const Elem * elem, const THREAD_ID tid)
     989             : {
     990      568858 :   for (const auto nl_sys_num : make_range(numNonlinearSystems()))
     991      284429 :     assembly(tid, nl_sys_num).reinitNeighborLowerDElem(elem);
     992      284429 : }
     993             : 
     994             : void
     995      568858 : SubProblem::reinitMortarElem(const Elem * elem, const THREAD_ID tid)
     996             : {
     997     1137716 :   for (const auto nl_sys_num : make_range(numNonlinearSystems()))
     998      568858 :     assembly(tid, nl_sys_num).reinitMortarElem(elem);
     999      568858 : }
    1000             : 
    1001             : void
    1002       34648 : SubProblem::cloneAlgebraicGhostingFunctor(GhostingFunctor & algebraic_gf, bool to_mesh)
    1003             : {
    1004       34648 :   EquationSystems & eq = es();
    1005       34648 :   const auto n_sys = eq.n_systems();
    1006             : 
    1007       34648 :   auto pr = _root_alg_gf_to_sys_clones.emplace(
    1008       34648 :       &algebraic_gf, std::vector<std::shared_ptr<GhostingFunctor>>(n_sys - 1));
    1009             :   mooseAssert(pr.second, "We are adding a duplicate algebraic ghosting functor");
    1010       34648 :   auto & clones_vec = pr.first->second;
    1011             : 
    1012       69536 :   for (MooseIndex(n_sys) i = 1; i < n_sys; ++i)
    1013             :   {
    1014       34888 :     DofMap & dof_map = eq.get_system(i).get_dof_map();
    1015       34888 :     std::shared_ptr<GhostingFunctor> clone_alg_gf = algebraic_gf.clone();
    1016       69776 :     std::dynamic_pointer_cast<RelationshipManager>(clone_alg_gf)
    1017       34888 :         ->init(mesh(), *algebraic_gf.get_mesh(), &dof_map);
    1018       34888 :     dof_map.add_algebraic_ghosting_functor(clone_alg_gf, to_mesh);
    1019       34888 :     clones_vec[i - 1] = clone_alg_gf;
    1020       34888 :   }
    1021       34648 : }
    1022             : 
    1023             : void
    1024       34648 : SubProblem::addAlgebraicGhostingFunctor(GhostingFunctor & algebraic_gf, bool to_mesh)
    1025             : {
    1026       34648 :   EquationSystems & eq = es();
    1027       34648 :   const auto n_sys = eq.n_systems();
    1028       34648 :   if (!n_sys)
    1029           0 :     return;
    1030             : 
    1031       34648 :   eq.get_system(0).get_dof_map().add_algebraic_ghosting_functor(algebraic_gf, to_mesh);
    1032       34648 :   cloneAlgebraicGhostingFunctor(algebraic_gf, to_mesh);
    1033             : }
    1034             : 
    1035             : void
    1036       47120 : SubProblem::cloneCouplingGhostingFunctor(GhostingFunctor & coupling_gf, bool to_mesh)
    1037             : {
    1038       47120 :   const std::size_t num_nl_sys = numNonlinearSystems();
    1039             : 
    1040       47120 :   auto pr = _root_coupling_gf_to_sys_clones.emplace(
    1041       47120 :       &coupling_gf, std::vector<std::shared_ptr<GhostingFunctor>>(num_nl_sys - 1));
    1042             :   mooseAssert(pr.second, "We are adding a duplicate coupling functor");
    1043       47120 :   auto & clones_vec = pr.first->second;
    1044             : 
    1045       47319 :   for (const auto i : make_range(std::size_t(1), num_nl_sys))
    1046             :   {
    1047         199 :     DofMap & dof_map = systemBaseNonlinear(i).system().get_dof_map();
    1048         199 :     std::shared_ptr<GhostingFunctor> clone_coupling_gf = coupling_gf.clone();
    1049         398 :     std::dynamic_pointer_cast<RelationshipManager>(clone_coupling_gf)
    1050         199 :         ->init(mesh(), *coupling_gf.get_mesh(), &dof_map);
    1051         199 :     dof_map.add_coupling_functor(clone_coupling_gf, to_mesh);
    1052         199 :     clones_vec[i - 1] = clone_coupling_gf;
    1053         199 :   }
    1054       47120 : }
    1055             : 
    1056             : void
    1057       48384 : SubProblem::addCouplingGhostingFunctor(GhostingFunctor & coupling_gf, bool to_mesh)
    1058             : {
    1059       48384 :   const auto num_nl_sys = numNonlinearSystems();
    1060       48384 :   if (!num_nl_sys)
    1061        1264 :     return;
    1062             : 
    1063       47120 :   systemBaseNonlinear(0).system().get_dof_map().add_coupling_functor(coupling_gf, to_mesh);
    1064       47120 :   cloneCouplingGhostingFunctor(coupling_gf, to_mesh);
    1065             : }
    1066             : 
    1067             : void
    1068          30 : SubProblem::removeAlgebraicGhostingFunctor(GhostingFunctor & algebraic_gf)
    1069             : {
    1070          30 :   EquationSystems & eq = es();
    1071          30 :   const auto n_sys = eq.n_systems();
    1072          30 :   DofMap & nl_dof_map = eq.get_system(0).get_dof_map();
    1073             : 
    1074             :   const bool found_in_root_sys =
    1075          30 :       std::find(nl_dof_map.algebraic_ghosting_functors_begin(),
    1076             :                 nl_dof_map.algebraic_ghosting_functors_end(),
    1077          60 :                 &algebraic_gf) != nl_dof_map.algebraic_ghosting_functors_end();
    1078             : 
    1079             : #ifndef NDEBUG
    1080             :   const bool found_in_our_map =
    1081             :       _root_alg_gf_to_sys_clones.find(&algebraic_gf) != _root_alg_gf_to_sys_clones.end();
    1082             :   mooseAssert(found_in_root_sys == found_in_our_map,
    1083             :               "If the ghosting functor exists in the root DofMap, then we need to have a key for "
    1084             :               "it in our gf to clones map");
    1085             : #endif
    1086             : 
    1087          30 :   if (found_in_root_sys) // libMesh yells if we try to remove
    1088             :                          // something that's not there
    1089           0 :     nl_dof_map.remove_algebraic_ghosting_functor(algebraic_gf);
    1090             : 
    1091          30 :   auto it = _root_alg_gf_to_sys_clones.find(&algebraic_gf);
    1092          30 :   if (it == _root_alg_gf_to_sys_clones.end())
    1093          30 :     return;
    1094             : 
    1095           0 :   auto & clones_vec = it->second;
    1096             :   mooseAssert((n_sys - 1) == clones_vec.size(),
    1097             :               "The size of the gf clones vector doesn't match the number of systems minus one");
    1098           0 :   if (clones_vec.empty())
    1099             :   {
    1100             :     mooseAssert(n_sys == 1, "The clones vector should only be empty if there is only one system");
    1101           0 :     return;
    1102             :   }
    1103             : 
    1104           0 :   for (const auto i : make_range(n_sys))
    1105           0 :     eq.get_system(i + 1).get_dof_map().remove_algebraic_ghosting_functor(*clones_vec[i]);
    1106             : 
    1107           0 :   _root_alg_gf_to_sys_clones.erase(it->first);
    1108             : }
    1109             : 
    1110             : void
    1111          30 : SubProblem::removeCouplingGhostingFunctor(GhostingFunctor & coupling_gf)
    1112             : {
    1113          30 :   EquationSystems & eq = es();
    1114          30 :   const auto num_nl_sys = numNonlinearSystems();
    1115          30 :   if (!num_nl_sys)
    1116          30 :     return;
    1117             : 
    1118          30 :   DofMap & nl_dof_map = eq.get_system(0).get_dof_map();
    1119          30 :   const bool found_in_root_sys = std::find(nl_dof_map.coupling_functors_begin(),
    1120             :                                            nl_dof_map.coupling_functors_end(),
    1121          60 :                                            &coupling_gf) != nl_dof_map.coupling_functors_end();
    1122             : 
    1123             : #ifndef NDEBUG
    1124             :   const bool found_in_our_map =
    1125             :       _root_coupling_gf_to_sys_clones.find(&coupling_gf) != _root_coupling_gf_to_sys_clones.end();
    1126             :   mooseAssert(found_in_root_sys == found_in_our_map,
    1127             :               "If the ghosting functor exists in the root DofMap, then we need to have a key for "
    1128             :               "it in our gf to clones map");
    1129             : #endif
    1130             : 
    1131          30 :   if (found_in_root_sys) // libMesh yells if we try to remove
    1132             :                          // something that's not there
    1133          30 :     nl_dof_map.remove_coupling_functor(coupling_gf);
    1134             : 
    1135          30 :   auto it = _root_coupling_gf_to_sys_clones.find(&coupling_gf);
    1136          30 :   if (it == _root_coupling_gf_to_sys_clones.end())
    1137           0 :     return;
    1138             : 
    1139          30 :   auto & clones_vec = it->second;
    1140             :   mooseAssert((num_nl_sys - 1) == clones_vec.size(),
    1141             :               "The size of the gf clones vector doesn't match the number of systems minus one");
    1142          30 :   if (clones_vec.empty())
    1143             :   {
    1144             :     mooseAssert(num_nl_sys == 1,
    1145             :                 "The clones vector should only be empty if there is only one nonlinear system");
    1146          30 :     return;
    1147             :   }
    1148             : 
    1149           0 :   for (const auto i : make_range(num_nl_sys))
    1150           0 :     eq.get_system(i + 1).get_dof_map().remove_coupling_functor(*clones_vec[i]);
    1151             : 
    1152           0 :   _root_coupling_gf_to_sys_clones.erase(it->first);
    1153             : }
    1154             : 
    1155             : void
    1156       68438 : SubProblem::automaticScaling(bool automatic_scaling)
    1157             : {
    1158      135835 :   for (const auto nl_sys_num : make_range(numNonlinearSystems()))
    1159       67397 :     systemBaseNonlinear(nl_sys_num).automaticScaling(automatic_scaling);
    1160       68438 : }
    1161             : 
    1162             : bool
    1163       15184 : SubProblem::automaticScaling() const
    1164             : {
    1165             :   // Currently going to assume that we are applying or not applying automatic scaling consistently
    1166             :   // across nonlinear systems
    1167       15184 :   return systemBaseNonlinear(0).automaticScaling();
    1168             : }
    1169             : 
    1170             : void
    1171         363 : SubProblem::hasScalingVector(const unsigned int nl_sys_num)
    1172             : {
    1173         786 :   for (const THREAD_ID tid : make_range(libMesh::n_threads()))
    1174         423 :     assembly(tid, nl_sys_num).hasScalingVector();
    1175         363 : }
    1176             : 
    1177             : void
    1178      384581 : SubProblem::clearAllDofIndices()
    1179             : {
    1180      782066 :   for (const auto nl_sys_num : make_range(numNonlinearSystems()))
    1181      397485 :     systemBaseNonlinear(nl_sys_num).clearAllDofIndices();
    1182      384581 :   systemBaseAuxiliary().clearAllDofIndices();
    1183      384581 : }
    1184             : 
    1185             : void
    1186      323803 : SubProblem::timestepSetup()
    1187             : {
    1188      676262 :   for (auto & map : _pbblf_functors)
    1189      364164 :     for (auto & pr : map)
    1190       11705 :       pr.second->timestepSetup();
    1191      323803 :   if (_show_chain_control_data)
    1192          36 :     _console << _app.getChainControlDataSystem().outputChainControlMap() << std::flush;
    1193      323803 : }
    1194             : 
    1195             : void
    1196     2083667 : SubProblem::customSetup(const ExecFlagType & exec_type)
    1197             : {
    1198     4353407 :   for (auto & map : _pbblf_functors)
    1199     2352069 :     for (auto & pr : map)
    1200       82329 :       pr.second->customSetup(exec_type);
    1201     2083667 : }
    1202             : 
    1203             : void
    1204     3487928 : SubProblem::residualSetup()
    1205             : {
    1206     7289027 :   for (auto & map : _pbblf_functors)
    1207     3900244 :     for (auto & pr : map)
    1208       99145 :       pr.second->residualSetup();
    1209     3487928 : }
    1210             : 
    1211             : void
    1212      552481 : SubProblem::jacobianSetup()
    1213             : {
    1214     1155966 :   for (auto & map : _pbblf_functors)
    1215      621094 :     for (auto & pr : map)
    1216       17609 :       pr.second->jacobianSetup();
    1217      552481 : }
    1218             : 
    1219             : void
    1220       64426 : SubProblem::initialSetup()
    1221             : {
    1222       64426 :   if (_show_functors)
    1223             :   {
    1224          36 :     showFunctors();
    1225          36 :     showFunctorRequestors();
    1226             :   }
    1227       64426 :   if (_show_chain_control_data)
    1228          13 :     _console << _app.getChainControlDataSystem().outputChainControlMap() << std::flush;
    1229             : 
    1230      134822 :   for (const auto & functors : _functors)
    1231      388060 :     for (const auto & [functor_wrapper_name, functor_wrapper] : functors)
    1232             :     {
    1233      317664 :       const auto & [true_functor_type, non_ad_functor, ad_functor] = functor_wrapper;
    1234             :       mooseAssert(non_ad_functor->wrapsNull() == ad_functor->wrapsNull(), "These must agree");
    1235      317664 :       const auto functor_name = removeSubstring(functor_wrapper_name, "wraps_");
    1236      317664 :       if (non_ad_functor->wrapsNull())
    1237           0 :         mooseError(
    1238             :             "No functor ever provided with name '",
    1239             :             functor_name,
    1240             :             "', which was requested by '",
    1241           0 :             MooseUtils::join(libmesh_map_find(_functor_to_requestors, functor_wrapper_name), ","),
    1242             :             "'.");
    1243      508463 :       if (true_functor_type == TrueFunctorIs::NONAD ? non_ad_functor->ownsWrappedFunctor()
    1244      190799 :                                                     : ad_functor->ownsWrappedFunctor())
    1245           0 :         mooseError("Functor envelopes should not own the functors they wrap, but '",
    1246             :                    functor_name,
    1247             :                    "' is owned by the wrapper. Please open a MOOSE issue for help resolving this.");
    1248      317664 :     }
    1249       64426 : }
    1250             : 
    1251             : void
    1252          36 : SubProblem::showFunctors() const
    1253             : {
    1254          36 :   _console << "[DBG] Wrapped functors found in Subproblem" << std::endl;
    1255          36 :   std::string functor_names = "[DBG] ";
    1256         284 :   for (const auto & functor_pair : _functors[0])
    1257         248 :     functor_names += std::regex_replace(functor_pair.first, std::regex("wraps_"), "") + " ";
    1258          36 :   if (functor_names.size())
    1259          36 :     functor_names.pop_back();
    1260          36 :   _console << functor_names << std::endl;
    1261          36 : }
    1262             : 
    1263             : void
    1264          36 : SubProblem::showFunctorRequestors() const
    1265             : {
    1266         128 :   for (const auto & [functor, requestors] : _functor_to_requestors)
    1267             :   {
    1268          92 :     _console << "[DBG] Requestors for wrapped functor "
    1269          92 :              << std::regex_replace(functor, std::regex("wraps_"), "") << std::endl;
    1270         276 :     _console << "[DBG] " << MooseUtils::join(requestors, " ") << std::endl;
    1271             :   }
    1272          36 : }
    1273             : 
    1274             : bool
    1275         550 : SubProblem::hasFunctor(const std::string & name, const THREAD_ID tid) const
    1276             : {
    1277             :   mooseAssert(tid < _functors.size(), "Too large a thread ID");
    1278         550 :   auto & functors = _functors[tid];
    1279         550 :   return (functors.find("wraps_" + name) != functors.end());
    1280             : }
    1281             : 
    1282             : Moose::CoordinateSystemType
    1283   478657854 : SubProblem::getCoordSystem(SubdomainID sid) const
    1284             : {
    1285   478657854 :   return mesh().getCoordSystem(sid);
    1286             : }
    1287             : 
    1288             : void
    1289    25457406 : SubProblem::reinitFVFace(const THREAD_ID tid, const FaceInfo & fi)
    1290             : {
    1291    52006746 :   for (const auto nl : make_range(numNonlinearSystems()))
    1292    26549340 :     assembly(tid, nl).reinitFVFace(fi);
    1293    25457406 : }
    1294             : 
    1295             : void
    1296   376637267 : SubProblem::cacheResidual(const THREAD_ID tid)
    1297             : {
    1298   376637267 :   assembly(tid, currentNlSysNum())
    1299   376637267 :       .cacheResidual(Assembly::GlobalDataKey{}, currentResidualVectorTags());
    1300   376637267 : }
    1301             : 
    1302             : void
    1303    38457458 : SubProblem::cacheResidualNeighbor(const THREAD_ID tid)
    1304             : {
    1305    38457458 :   assembly(tid, currentNlSysNum())
    1306    38457458 :       .cacheResidualNeighbor(Assembly::GlobalDataKey{}, currentResidualVectorTags());
    1307    38457458 : }
    1308             : 
    1309             : void
    1310    57872050 : SubProblem::addCachedResidual(const THREAD_ID tid)
    1311             : {
    1312    57872050 :   assembly(tid, currentNlSysNum())
    1313    57872050 :       .addCachedResiduals(Assembly::GlobalDataKey{}, currentResidualVectorTags());
    1314    57872050 : }
    1315             : 
    1316             : void
    1317    57305117 : SubProblem::cacheJacobian(const THREAD_ID tid)
    1318             : {
    1319    57305117 :   assembly(tid, currentNlSysNum()).cacheJacobian(Assembly::GlobalDataKey{});
    1320    57305117 :   if (hasNonlocalCoupling())
    1321        5880 :     assembly(tid, currentNlSysNum()).cacheJacobianNonlocal(Assembly::GlobalDataKey{});
    1322    57305117 : }
    1323             : 
    1324             : void
    1325       10576 : SubProblem::cacheJacobianNeighbor(const THREAD_ID tid)
    1326             : {
    1327       10576 :   assembly(tid, currentNlSysNum()).cacheJacobianNeighbor(Assembly::GlobalDataKey{});
    1328       10576 : }
    1329             : 
    1330             : void
    1331     4247452 : SubProblem::addCachedJacobian(const THREAD_ID tid)
    1332             : {
    1333     4247452 :   assembly(tid, currentNlSysNum()).addCachedJacobian(Assembly::GlobalDataKey{});
    1334     4247448 : }
    1335             : 
    1336             : void
    1337         234 : SubProblem::preparePRefinement()
    1338             : {
    1339         234 :   std::unordered_set<FEFamily> disable_families;
    1340         663 :   for (const auto & [family, flag] : _family_for_p_refinement)
    1341         429 :     if (flag)
    1342         195 :       disable_families.insert(family);
    1343             : 
    1344         486 :   for (const auto tid : make_range(libMesh::n_threads()))
    1345         504 :     for (const auto s : make_range(numNonlinearSystems()))
    1346         252 :       assembly(tid, s).havePRefinement(disable_families);
    1347             : 
    1348         234 :   auto & eq = es();
    1349         429 :   for (const auto family : disable_families)
    1350         585 :     for (const auto i : make_range(eq.n_systems()))
    1351             :     {
    1352         390 :       auto & system = eq.get_system(i);
    1353         390 :       auto & dof_map = system.get_dof_map();
    1354         936 :       for (const auto vg : make_range(system.n_variable_groups()))
    1355             :       {
    1356         546 :         const auto & var_group = system.variable_group(vg);
    1357         546 :         if (var_group.type().family == family)
    1358         195 :           dof_map.should_p_refine(vg, false);
    1359             :       }
    1360             :     }
    1361             : 
    1362         234 :   _have_p_refinement = true;
    1363         234 : }
    1364             : 
    1365             : bool
    1366         464 : SubProblem::doingPRefinement() const
    1367             : {
    1368         464 :   return mesh().doingPRefinement();
    1369             : }
    1370             : 
    1371             : void
    1372      161769 : SubProblem::markFamilyPRefinement(const InputParameters & params)
    1373             : {
    1374      161769 :   auto family = Utility::string_to_enum<FEFamily>(params.get<MooseEnum>("family"));
    1375      161769 :   bool flag = _default_families_without_p_refinement.count(family);
    1376      323538 :   if (params.isParamValid("disable_p_refinement"))
    1377         143 :     flag = params.get<bool>("disable_p_refinement");
    1378             : 
    1379      161769 :   auto [it, inserted] = _family_for_p_refinement.emplace(family, flag);
    1380      161769 :   if (!inserted && flag != it->second)
    1381           0 :     mooseError("'disable_p_refinement' not set consistently for variables in ", family);
    1382      161769 : }
    1383             : 
    1384             : void
    1385      157505 : SubProblem::setCurrentLowerDElem(const Elem * const lower_d_elem, const THREAD_ID tid)
    1386             : {
    1387      315010 :   for (const auto nl_sys_num : make_range(numNonlinearSystems()))
    1388      157505 :     assembly(tid, nl_sys_num).setCurrentLowerDElem(lower_d_elem);
    1389      157505 : }
    1390             : 
    1391             : template MooseVariableFEBase &
    1392             : SubProblem::getVariableHelper(const THREAD_ID tid,
    1393             :                               const std::string & var_name,
    1394             :                               Moose::VarKindType expected_var_type,
    1395             :                               Moose::VarFieldType expected_var_field_type,
    1396             :                               const std::vector<std::shared_ptr<SolverSystem>> & nls,
    1397             :                               const SystemBase & aux) const;
    1398             : template MooseVariableFEBase &
    1399             : SubProblem::getVariableHelper(const THREAD_ID tid,
    1400             :                               const std::string & var_name,
    1401             :                               Moose::VarKindType expected_var_type,
    1402             :                               Moose::VarFieldType expected_var_field_type,
    1403             :                               const std::vector<std::unique_ptr<DisplacedSystem>> & nls,
    1404             :                               const SystemBase & aux) const;

Generated by: LCOV version 1.14