LCOV - code coverage report
Current view: top level - src/base - TheWarehouse.C (source / functions) Hit Total Coverage
Test: idaholab/moose framework: 39a256 Lines: 140 158 88.6 %
Date: 2026-07-14 14:36:17 Functions: 19 22 86.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 "TheWarehouse.h"
      11             : 
      12             : #include "Attributes.h"
      13             : #include "MooseObject.h"
      14             : #include "SubProblem.h"
      15             : #include "GeneralUserObject.h"
      16             : #include "DependencyResolverInterface.h"
      17             : #include "BlockRestrictable.h"
      18             : 
      19             : #include <memory>
      20             : 
      21             : class WarehouseStorage
      22             : {
      23             : public:
      24       63543 :   virtual ~WarehouseStorage() = default;
      25             :   virtual void add(std::size_t obj_id, std::vector<std::unique_ptr<Attribute>> attribs) = 0;
      26             :   virtual std::vector<std::size_t> query(const std::vector<std::unique_ptr<Attribute>> & conds) = 0;
      27             :   virtual void set(std::size_t obj_id, std::vector<std::unique_ptr<Attribute>> attribs) = 0;
      28             : };
      29             : 
      30             : bool
      31   243346339 : operator==(const std::unique_ptr<Attribute> & lhs, const std::unique_ptr<Attribute> & rhs)
      32             : {
      33   243346339 :   return (*lhs) == (*rhs);
      34             : }
      35             : 
      36   214182266 : Attribute::Attribute(TheWarehouse & w, const std::string name) : _id(w.attribID(name)) {}
      37             : 
      38             : void
      39      307499 : AttribSorted::initFrom(const MooseObject *)
      40             : {
      41      307499 : }
      42             : 
      43             : bool
      44    54641592 : AttribSorted::isMatch(const Attribute & other) const
      45             : {
      46    54641592 :   auto a = dynamic_cast<const AttribSorted *>(&other);
      47    54641592 :   return _initd && a && a->_initd && (a->_val == _val);
      48             : }
      49             : 
      50             : bool
      51    50133631 : AttribSorted::isEqual(const Attribute & other) const
      52             : {
      53    50133631 :   return isMatch(other);
      54             : }
      55             : 
      56             : class VecStore : public WarehouseStorage
      57             : {
      58             : public:
      59      307499 :   virtual void add(std::size_t obj_id, std::vector<std::unique_ptr<Attribute>> attribs) override
      60             :   {
      61      307499 :     std::lock_guard<std::mutex> l(_mutex);
      62      307499 :     if (obj_id != _data.size())
      63           0 :       throw std::runtime_error("object with id " + std::to_string(obj_id) + " already added");
      64      307499 :     _data.push_back(std::move(attribs));
      65      307499 :   }
      66             : 
      67             :   virtual std::vector<std::size_t>
      68     4585710 :   query(const std::vector<std::unique_ptr<Attribute>> & conds) override
      69             :   {
      70     4585710 :     std::vector<std::size_t> ids;
      71     4585710 :     std::lock_guard<std::mutex> l(_mutex);
      72    30265245 :     for (std::size_t i = 0; i < _data.size(); i++)
      73             :     {
      74    25679535 :       auto & data = _data[i];
      75    25679535 :       bool ismatch = true;
      76    40051488 :       for (auto & cond : conds)
      77             :       {
      78    39151361 :         if (!data[cond->id()]->isMatch(*cond))
      79             :         {
      80    24779408 :           ismatch = false;
      81    24779408 :           break;
      82             :         }
      83             :       }
      84    25679535 :       if (ismatch)
      85             :       {
      86             :         mooseAssert(std::find(ids.begin(), ids.end(), i) == ids.end(), "Duplicate object");
      87      900127 :         ids.push_back(i);
      88             :       }
      89             :     }
      90     9171420 :     return ids;
      91     4585710 :   }
      92             : 
      93       76894 :   virtual void set(std::size_t obj_id, std::vector<std::unique_ptr<Attribute>> attribs) override
      94             :   {
      95       76894 :     if (obj_id > _data.size())
      96           0 :       throw std::runtime_error("unknown object id " + std::to_string(obj_id));
      97             : 
      98       76894 :     std::lock_guard<std::mutex> l(_mutex);
      99             : 
     100       76894 :     auto & dst = _data[obj_id];
     101      153788 :     for (auto & attrib : attribs)
     102       76894 :       dst[attrib->id()] = std::move(attrib);
     103       76894 :   }
     104             : 
     105             : private:
     106             :   std::mutex _mutex;
     107             :   std::vector<std::vector<std::unique_ptr<Attribute>>> _data;
     108             : };
     109             : 
     110       67675 : TheWarehouse::TheWarehouse() : _store(std::make_unique<VecStore>()) {}
     111       63543 : TheWarehouse::~TheWarehouse() {}
     112             : 
     113             : void isValid(MooseObject * obj);
     114             : 
     115             : void
     116      307505 : TheWarehouse::add(std::shared_ptr<MooseObject> obj)
     117             : {
     118      307505 :   isValid(obj.get());
     119             : 
     120      307499 :   std::size_t obj_id = 0;
     121             :   {
     122      307499 :     std::lock_guard<std::mutex> lock(_obj_mutex);
     123             : 
     124             :     mooseAssert(!_obj_ids.count(obj.get()), obj->typeAndName() + " has already been added");
     125             : 
     126      307499 :     _objects.push_back(obj);
     127      307499 :     obj_id = _objects.size() - 1;
     128      307499 :     _obj_ids[obj.get()] = obj_id;
     129             : 
     130             :     // reset/invalidate the query cache since query results may have been affected by this warehouse
     131             :     // insertion.
     132      307499 :     _obj_cache.clear();
     133      307499 :     _query_cache.clear();
     134      307499 :   }
     135             : 
     136      307499 :   std::vector<std::unique_ptr<Attribute>> attribs;
     137      307499 :   readAttribs(obj.get(), attribs);
     138      307499 :   _store->add(obj_id, std::move(attribs));
     139      307499 : }
     140             : 
     141             : void
     142       76894 : TheWarehouse::update(MooseObject * obj, const Attribute & extra)
     143             : {
     144       76894 :   std::vector<std::unique_ptr<Attribute>> attribs;
     145       76894 :   attribs.push_back(extra.clone());
     146       76894 :   _store->set(_obj_ids[obj], std::move(attribs));
     147             :   // reset/invalidate the query cache since query results may have been affected by this object
     148             :   // attribute modification.
     149       76894 :   _obj_cache.clear();
     150       76894 :   _query_cache.clear();
     151       76894 : }
     152             : 
     153             : void
     154           0 : TheWarehouse::update(MooseObject * obj)
     155             : {
     156           0 :   std::vector<std::unique_ptr<Attribute>> attribs;
     157           0 :   readAttribs(obj, attribs);
     158           0 :   _store->set(_obj_ids[obj], std::move(attribs));
     159             :   // reset/invalidate the query cache since query results may have been affected by this object
     160             :   // attribute modification.
     161           0 :   _obj_cache.clear();
     162           0 :   _query_cache.clear();
     163           0 : }
     164             : 
     165             : int
     166     4585710 : TheWarehouse::prepare(std::vector<std::unique_ptr<Attribute>> conds)
     167             : {
     168     4585710 :   bool sort = false;
     169     4585710 :   std::unique_ptr<Attribute> sorted_attrib;
     170     4585710 :   if (!conds.empty() && dynamic_cast<AttribSorted *>(conds.back().get()))
     171             :   {
     172     4507961 :     sorted_attrib = std::move(conds.back());
     173     4507961 :     static const AttribSorted sorted_attrib_true(*this, true);
     174     4507961 :     sort = sorted_attrib->isMatch(sorted_attrib_true);
     175             :     // Remove the sorted condition temporarily
     176     4507961 :     conds.pop_back();
     177             :   }
     178             : 
     179             : #ifdef DEBUG
     180             :   for (auto & cond : conds)
     181             :     mooseAssert(!dynamic_cast<AttribSorted *>(cond.get()),
     182             :                 "There should be no sorted attributes in this container.");
     183             : #endif
     184             : 
     185     4585710 :   auto obj_ids = _store->query(conds);
     186     4585710 :   if (sorted_attrib)
     187     4507961 :     conds.push_back(std::move(sorted_attrib));
     188             : 
     189     4585710 :   std::lock_guard<std::mutex> lock(_obj_cache_mutex);
     190     4585710 :   auto & vec = _obj_cache.emplace_back(obj_ids.size());
     191     4585710 :   const auto query_id = _obj_cache.size() - 1;
     192             :   {
     193     4585710 :     std::lock_guard<std::mutex> lock(_query_cache_mutex);
     194     4585710 :     _query_cache[std::move(conds)] = query_id;
     195     4585710 :   }
     196             : 
     197     4585710 :   std::lock_guard<std::mutex> o_lock(_obj_mutex);
     198     5485837 :   for (const auto i : index_range(obj_ids))
     199             :   {
     200      900127 :     auto obj = _objects[obj_ids[i]].get();
     201             :     mooseAssert(std::find(vec.begin(), vec.end(), obj) == vec.end(), "Duplicate object");
     202      900127 :     vec[i] = obj;
     203             :   }
     204             : 
     205     4585710 :   if (sort && !vec.empty() && dynamic_cast<DependencyResolverInterface *>(vec[0]))
     206             :   {
     207      241785 :     std::vector<DependencyResolverInterface *> dependers;
     208      710514 :     for (auto obj : vec)
     209             :     {
     210      468729 :       auto d = dynamic_cast<DependencyResolverInterface *>(obj);
     211      468729 :       if (!d)
     212             :       {
     213           0 :         dependers.clear();
     214           0 :         break;
     215             :       }
     216      468729 :       dependers.push_back(d);
     217             :     }
     218             : 
     219             :     try
     220             :     {
     221      241785 :       DependencyResolverInterface::sort(dependers);
     222             :     }
     223           0 :     catch (CyclicDependencyException<DependencyResolverInterface *> & e)
     224             :     {
     225           0 :       DependencyResolverInterface::cyclicDependencyError<MooseObject *>(
     226             :           e,
     227             :           "Cyclic dependency detected in object ordering",
     228           0 :           [](DependencyResolverInterface * obj)
     229             :           {
     230           0 :             auto * moose_obj = dynamic_cast<MooseObject *>(obj);
     231             :             mooseAssert(moose_obj, "Failed to cast dependency object to MooseObject");
     232           0 :             return moose_obj->name();
     233             :           });
     234           0 :     }
     235             : 
     236             :     mooseAssert(dependers.size() == vec.size(), "Dependency resolution size mismatch");
     237      710514 :     for (unsigned int i = 0; i < dependers.size(); i++)
     238      468729 :       vec[i] = dynamic_cast<MooseObject *>(dependers[i]);
     239      241785 :   }
     240             : 
     241     4585710 :   return query_id;
     242     4585710 : }
     243             : 
     244             : const std::vector<MooseObject *> &
     245   117958346 : TheWarehouse::query(int query_id)
     246             : {
     247   117958346 :   if (static_cast<std::size_t>(query_id) >= _obj_cache.size())
     248           0 :     throw std::runtime_error("unknown query id");
     249   117958346 :   return _obj_cache[query_id];
     250             : }
     251             : 
     252             : std::size_t
     253    54974958 : TheWarehouse::queryID(const std::vector<std::unique_ptr<Attribute>> & conds)
     254             : {
     255             :   {
     256    54974958 :     std::lock_guard<std::mutex> lock(_query_cache_mutex);
     257    54974958 :     auto it = _query_cache.find(conds);
     258    54974958 :     if (it != _query_cache.end())
     259    50389248 :       return it->second;
     260    54974958 :   }
     261             : 
     262     4585710 :   std::vector<std::unique_ptr<Attribute>> conds_clone;
     263     4585710 :   conds_clone.resize(conds.size());
     264    24553400 :   for (std::size_t i = 0; i < conds.size(); i++)
     265    19967690 :     conds_clone[i] = conds[i]->clone();
     266     4585710 :   return prepare(std::move(conds_clone));
     267     4585710 : }
     268             : 
     269             : std::size_t
     270      331615 : TheWarehouse::count(const std::vector<std::unique_ptr<Attribute>> & conds)
     271             : {
     272      331615 :   auto query_id = queryID(conds);
     273      331615 :   std::lock_guard<std::mutex> lock(_obj_cache_mutex);
     274      331615 :   auto & objs = query(query_id);
     275      331615 :   std::size_t count = 0;
     276      354075 :   for (auto obj : objs)
     277       22460 :     if (obj->enabled())
     278       22460 :       count++;
     279      331615 :   return count;
     280      331615 : }
     281             : 
     282             : void
     283      307499 : TheWarehouse::readAttribs(const MooseObject * obj,
     284             :                           std::vector<std::unique_ptr<Attribute>> & attribs)
     285             : {
     286     5842381 :   for (auto & ref : _attrib_list)
     287             :   {
     288     5534882 :     attribs.emplace_back(ref->clone());
     289     5534882 :     attribs.back()->initFrom(obj);
     290             :   }
     291      307499 : }
     292             : 
     293             : void
     294      307505 : isValid(MooseObject * obj)
     295             : {
     296      307505 :   auto blk = dynamic_cast<BlockRestrictable *>(obj);
     297      307505 :   if (!blk)
     298      171681 :     return;
     299             : 
     300             :   // Check variables
     301      135824 :   auto c_ptr = dynamic_cast<Coupleable *>(obj);
     302      135824 :   if (c_ptr)
     303      177643 :     for (MooseVariableFEBase * var : c_ptr->getCoupledMooseVars())
     304       44124 :       blk->checkVariable(*var);
     305             : 
     306      135818 :   const InputParameters & parameters = obj->parameters();
     307             : 
     308      135818 :   SubProblem & problem = *parameters.get<SubProblem *>("_subproblem");
     309             : 
     310      135818 :   THREAD_ID tid = parameters.get<THREAD_ID>("_tid");
     311             : 
     312      271636 :   if (parameters.isParamValid("variable"))
     313             :   {
     314             :     // Try the scalar version first
     315      127608 :     std::string variable_name = parameters.getMooseType("variable");
     316      127608 :     if (variable_name == "")
     317             :       // When using vector variables, we are only going to use the first one in the list at the
     318             :       // interface level...
     319       60270 :       variable_name = parameters.getVecMooseType("variable")[0];
     320             : 
     321      127608 :     blk->checkVariable(problem.getVariable(
     322             :         tid, variable_name, Moose::VarKindType::VAR_ANY, Moose::VarFieldType::VAR_FIELD_ANY));
     323      127608 :   }
     324             : }

Generated by: LCOV version 1.14