LCOV - code coverage report
Current view: top level - src/base - TheWarehouse.C (source / functions) Hit Total Coverage
Test: idaholab/moose framework: #32971 (54bef8) with base c6cf66 Lines: 140 158 88.6 %
Date: 2026-05-29 20:35: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       62880 :   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   239944552 : operator==(const std::unique_ptr<Attribute> & lhs, const std::unique_ptr<Attribute> & rhs)
      32             : {
      33   239944552 :   return (*lhs) == (*rhs);
      34             : }
      35             : 
      36   210651482 : Attribute::Attribute(TheWarehouse & w, const std::string name) : _id(w.attribID(name)) {}
      37             : 
      38             : void
      39      301831 : AttribSorted::initFrom(const MooseObject *)
      40             : {
      41      301831 : }
      42             : 
      43             : bool
      44    53633154 : AttribSorted::isMatch(const Attribute & other) const
      45             : {
      46    53633154 :   auto a = dynamic_cast<const AttribSorted *>(&other);
      47    53633154 :   return _initd && a && a->_initd && (a->_val == _val);
      48             : }
      49             : 
      50             : bool
      51    49153422 : AttribSorted::isEqual(const Attribute & other) const
      52             : {
      53    49153422 :   return isMatch(other);
      54             : }
      55             : 
      56             : class VecStore : public WarehouseStorage
      57             : {
      58             : public:
      59      301831 :   virtual void add(std::size_t obj_id, std::vector<std::unique_ptr<Attribute>> attribs) override
      60             :   {
      61      301831 :     std::lock_guard<std::mutex> l(_mutex);
      62      301831 :     if (obj_id != _data.size())
      63           0 :       throw std::runtime_error("object with id " + std::to_string(obj_id) + " already added");
      64      301831 :     _data.push_back(std::move(attribs));
      65      301831 :   }
      66             : 
      67             :   virtual std::vector<std::size_t>
      68     4558399 :   query(const std::vector<std::unique_ptr<Attribute>> & conds) override
      69             :   {
      70     4558399 :     std::vector<std::size_t> ids;
      71     4558399 :     std::lock_guard<std::mutex> l(_mutex);
      72    30175278 :     for (std::size_t i = 0; i < _data.size(); i++)
      73             :     {
      74    25616879 :       auto & data = _data[i];
      75    25616879 :       bool ismatch = true;
      76    40042338 :       for (auto & cond : conds)
      77             :       {
      78    39150671 :         if (!data[cond->id()]->isMatch(*cond))
      79             :         {
      80    24725212 :           ismatch = false;
      81    24725212 :           break;
      82             :         }
      83             :       }
      84    25616879 :       if (ismatch)
      85             :       {
      86             :         mooseAssert(std::find(ids.begin(), ids.end(), i) == ids.end(), "Duplicate object");
      87      891667 :         ids.push_back(i);
      88             :       }
      89             :     }
      90     9116798 :     return ids;
      91     4558399 :   }
      92             : 
      93       75320 :   virtual void set(std::size_t obj_id, std::vector<std::unique_ptr<Attribute>> attribs) override
      94             :   {
      95       75320 :     if (obj_id > _data.size())
      96           0 :       throw std::runtime_error("unknown object id " + std::to_string(obj_id));
      97             : 
      98       75320 :     std::lock_guard<std::mutex> l(_mutex);
      99             : 
     100       75320 :     auto & dst = _data[obj_id];
     101      150640 :     for (auto & attrib : attribs)
     102       75320 :       dst[attrib->id()] = std::move(attrib);
     103       75320 :   }
     104             : 
     105             : private:
     106             :   std::mutex _mutex;
     107             :   std::vector<std::vector<std::unique_ptr<Attribute>>> _data;
     108             : };
     109             : 
     110       66999 : TheWarehouse::TheWarehouse() : _store(std::make_unique<VecStore>()) {}
     111       62880 : TheWarehouse::~TheWarehouse() {}
     112             : 
     113             : void isValid(MooseObject * obj);
     114             : 
     115             : void
     116      301837 : TheWarehouse::add(std::shared_ptr<MooseObject> obj)
     117             : {
     118      301837 :   isValid(obj.get());
     119             : 
     120      301831 :   std::size_t obj_id = 0;
     121             :   {
     122      301831 :     std::lock_guard<std::mutex> lock(_obj_mutex);
     123             : 
     124             :     mooseAssert(!_obj_ids.count(obj.get()), obj->typeAndName() + " has already been added");
     125             : 
     126      301831 :     _objects.push_back(obj);
     127      301831 :     obj_id = _objects.size() - 1;
     128      301831 :     _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      301831 :     _obj_cache.clear();
     133      301831 :     _query_cache.clear();
     134      301831 :   }
     135             : 
     136      301831 :   std::vector<std::unique_ptr<Attribute>> attribs;
     137      301831 :   readAttribs(obj.get(), attribs);
     138      301831 :   _store->add(obj_id, std::move(attribs));
     139      301831 : }
     140             : 
     141             : void
     142       75320 : TheWarehouse::update(MooseObject * obj, const Attribute & extra)
     143             : {
     144       75320 :   std::vector<std::unique_ptr<Attribute>> attribs;
     145       75320 :   attribs.push_back(extra.clone());
     146       75320 :   _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       75320 :   _obj_cache.clear();
     150       75320 :   _query_cache.clear();
     151       75320 : }
     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     4558399 : TheWarehouse::prepare(std::vector<std::unique_ptr<Attribute>> conds)
     167             : {
     168     4558399 :   bool sort = false;
     169     4558399 :   std::unique_ptr<Attribute> sorted_attrib;
     170     4558399 :   if (!conds.empty() && dynamic_cast<AttribSorted *>(conds.back().get()))
     171             :   {
     172     4479732 :     sorted_attrib = std::move(conds.back());
     173     4479732 :     static const AttribSorted sorted_attrib_true(*this, true);
     174     4479732 :     sort = sorted_attrib->isMatch(sorted_attrib_true);
     175             :     // Remove the sorted condition temporarily
     176     4479732 :     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     4558399 :   auto obj_ids = _store->query(conds);
     186     4558399 :   if (sorted_attrib)
     187     4479732 :     conds.push_back(std::move(sorted_attrib));
     188             : 
     189     4558399 :   std::lock_guard<std::mutex> lock(_obj_cache_mutex);
     190     4558399 :   auto & vec = _obj_cache.emplace_back(obj_ids.size());
     191     4558399 :   const auto query_id = _obj_cache.size() - 1;
     192             :   {
     193     4558399 :     std::lock_guard<std::mutex> lock(_query_cache_mutex);
     194     4558399 :     _query_cache[std::move(conds)] = query_id;
     195     4558399 :   }
     196             : 
     197     4558399 :   std::lock_guard<std::mutex> o_lock(_obj_mutex);
     198     5450066 :   for (const auto i : index_range(obj_ids))
     199             :   {
     200      891667 :     auto obj = _objects[obj_ids[i]].get();
     201             :     mooseAssert(std::find(vec.begin(), vec.end(), obj) == vec.end(), "Duplicate object");
     202      891667 :     vec[i] = obj;
     203             :   }
     204             : 
     205     4558399 :   if (sort && !vec.empty() && dynamic_cast<DependencyResolverInterface *>(vec[0]))
     206             :   {
     207      241197 :     std::vector<DependencyResolverInterface *> dependers;
     208      707729 :     for (auto obj : vec)
     209             :     {
     210      466532 :       auto d = dynamic_cast<DependencyResolverInterface *>(obj);
     211      466532 :       if (!d)
     212             :       {
     213           0 :         dependers.clear();
     214           0 :         break;
     215             :       }
     216      466532 :       dependers.push_back(d);
     217             :     }
     218             : 
     219             :     try
     220             :     {
     221      241197 :       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      707729 :     for (unsigned int i = 0; i < dependers.size(); i++)
     238      466532 :       vec[i] = dynamic_cast<MooseObject *>(dependers[i]);
     239      241197 :   }
     240             : 
     241     4558399 :   return query_id;
     242     4558399 : }
     243             : 
     244             : const std::vector<MooseObject *> &
     245   116897612 : TheWarehouse::query(int query_id)
     246             : {
     247   116897612 :   if (static_cast<std::size_t>(query_id) >= _obj_cache.size())
     248           0 :     throw std::runtime_error("unknown query id");
     249   116897612 :   return _obj_cache[query_id];
     250             : }
     251             : 
     252             : std::size_t
     253    53961685 : TheWarehouse::queryID(const std::vector<std::unique_ptr<Attribute>> & conds)
     254             : {
     255             :   {
     256    53961685 :     std::lock_guard<std::mutex> lock(_query_cache_mutex);
     257    53961685 :     auto it = _query_cache.find(conds);
     258    53961685 :     if (it != _query_cache.end())
     259    49403286 :       return it->second;
     260    53961685 :   }
     261             : 
     262     4558399 :   std::vector<std::unique_ptr<Attribute>> conds_clone;
     263     4558399 :   conds_clone.resize(conds.size());
     264    24462615 :   for (std::size_t i = 0; i < conds.size(); i++)
     265    19904216 :     conds_clone[i] = conds[i]->clone();
     266     4558399 :   return prepare(std::move(conds_clone));
     267     4558399 : }
     268             : 
     269             : std::size_t
     270      326978 : TheWarehouse::count(const std::vector<std::unique_ptr<Attribute>> & conds)
     271             : {
     272      326978 :   auto query_id = queryID(conds);
     273      326978 :   std::lock_guard<std::mutex> lock(_obj_cache_mutex);
     274      326978 :   auto & objs = query(query_id);
     275      326978 :   std::size_t count = 0;
     276      349506 :   for (auto obj : objs)
     277       22528 :     if (obj->enabled())
     278       22528 :       count++;
     279      326978 :   return count;
     280      326978 : }
     281             : 
     282             : void
     283      301831 : TheWarehouse::readAttribs(const MooseObject * obj,
     284             :                           std::vector<std::unique_ptr<Attribute>> & attribs)
     285             : {
     286     5734689 :   for (auto & ref : _attrib_list)
     287             :   {
     288     5432858 :     attribs.emplace_back(ref->clone());
     289     5432858 :     attribs.back()->initFrom(obj);
     290             :   }
     291      301831 : }
     292             : 
     293             : void
     294      301837 : isValid(MooseObject * obj)
     295             : {
     296      301837 :   auto blk = dynamic_cast<BlockRestrictable *>(obj);
     297      301837 :   if (!blk)
     298      167977 :     return;
     299             : 
     300             :   // Check variables
     301      133860 :   auto c_ptr = dynamic_cast<Coupleable *>(obj);
     302      133860 :   if (c_ptr)
     303      175259 :     for (MooseVariableFEBase * var : c_ptr->getCoupledMooseVars())
     304       43704 :       blk->checkVariable(*var);
     305             : 
     306      133854 :   const InputParameters & parameters = obj->parameters();
     307             : 
     308      133854 :   SubProblem & problem = *parameters.get<SubProblem *>("_subproblem");
     309             : 
     310      133854 :   THREAD_ID tid = parameters.get<THREAD_ID>("_tid");
     311             : 
     312      267708 :   if (parameters.isParamValid("variable"))
     313             :   {
     314             :     // Try the scalar version first
     315      125923 :     std::string variable_name = parameters.getMooseType("variable");
     316      125923 :     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       59414 :       variable_name = parameters.getVecMooseType("variable")[0];
     320             : 
     321      125923 :     blk->checkVariable(problem.getVariable(
     322             :         tid, variable_name, Moose::VarKindType::VAR_ANY, Moose::VarFieldType::VAR_FIELD_ANY));
     323      125923 :   }
     324             : }

Generated by: LCOV version 1.14