LCOV - code coverage report
Current view: top level - src/base - TheWarehouse.C (source / functions) Hit Total Coverage
Test: idaholab/moose framework: 2bf808 Lines: 140 155 90.3 %
Date: 2025-07-17 01:28:37 Functions: 19 21 90.5 %
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       57256 :   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   203788248 : operator==(const std::unique_ptr<Attribute> & lhs, const std::unique_ptr<Attribute> & rhs)
      32             : {
      33   203788248 :   return (*lhs) == (*rhs);
      34             : }
      35             : 
      36   176472386 : Attribute::Attribute(TheWarehouse & w, const std::string name) : _id(w.attribID(name)) {}
      37             : 
      38             : void
      39      288412 : AttribSorted::initFrom(const MooseObject *)
      40             : {
      41      288412 : }
      42             : 
      43             : bool
      44    42985716 : AttribSorted::isMatch(const Attribute & other) const
      45             : {
      46    42985716 :   auto a = dynamic_cast<const AttribSorted *>(&other);
      47    42985716 :   return _initd && a && a->_initd && (a->_val == _val);
      48             : }
      49             : 
      50             : bool
      51    39800095 : AttribSorted::isEqual(const Attribute & other) const
      52             : {
      53    39800095 :   return isMatch(other);
      54             : }
      55             : 
      56             : class VecStore : public WarehouseStorage
      57             : {
      58             : public:
      59      288412 :   virtual void add(std::size_t obj_id, std::vector<std::unique_ptr<Attribute>> attribs) override
      60             :   {
      61      288412 :     std::lock_guard<std::mutex> l(_mutex);
      62      288412 :     if (obj_id != _data.size())
      63           0 :       throw std::runtime_error("object with id " + std::to_string(obj_id) + " already added");
      64      288412 :     _data.push_back(std::move(attribs));
      65      288412 :   }
      66             : 
      67             :   virtual std::vector<std::size_t>
      68     3254841 :   query(const std::vector<std::unique_ptr<Attribute>> & conds) override
      69             :   {
      70     3254841 :     std::vector<std::size_t> ids;
      71     3254841 :     std::lock_guard<std::mutex> l(_mutex);
      72    22331213 :     for (std::size_t i = 0; i < _data.size(); i++)
      73             :     {
      74    19076372 :       auto & data = _data[i];
      75    19076372 :       bool ismatch = true;
      76    33310028 :       for (auto & cond : conds)
      77             :       {
      78    32404424 :         if (!data[cond->id()]->isMatch(*cond))
      79             :         {
      80    18170768 :           ismatch = false;
      81    18170768 :           break;
      82             :         }
      83             :       }
      84    19076372 :       if (ismatch)
      85             :       {
      86             :         mooseAssert(std::find(ids.begin(), ids.end(), i) == ids.end(), "Duplicate object");
      87      905604 :         ids.push_back(i);
      88             :       }
      89             :     }
      90     6509682 :     return ids;
      91     3254841 :   }
      92             : 
      93       74165 :   virtual void set(std::size_t obj_id, std::vector<std::unique_ptr<Attribute>> attribs) override
      94             :   {
      95       74165 :     if (obj_id > _data.size())
      96           0 :       throw std::runtime_error("unknown object id " + std::to_string(obj_id));
      97             : 
      98       74165 :     std::lock_guard<std::mutex> l(_mutex);
      99             : 
     100       74165 :     auto & dst = _data[obj_id];
     101      148330 :     for (auto & attrib : attribs)
     102       74165 :       dst[attrib->id()] = std::move(attrib);
     103       74165 :   }
     104             : 
     105             : private:
     106             :   std::mutex _mutex;
     107             :   std::vector<std::vector<std::unique_ptr<Attribute>>> _data;
     108             : };
     109             : 
     110       62757 : TheWarehouse::TheWarehouse() : _store(std::make_unique<VecStore>()) {}
     111       57256 : TheWarehouse::~TheWarehouse() {}
     112             : 
     113             : void isValid(MooseObject * obj);
     114             : 
     115             : void
     116      288412 : TheWarehouse::add(std::shared_ptr<MooseObject> obj)
     117             : {
     118      288412 :   isValid(obj.get());
     119             : 
     120      288412 :   std::size_t obj_id = 0;
     121             :   {
     122      288412 :     std::lock_guard<std::mutex> lock(_obj_mutex);
     123             : 
     124             :     mooseAssert(!_obj_ids.count(obj.get()), obj->typeAndName() + " has already been added");
     125             : 
     126      288412 :     _objects.push_back(obj);
     127      288412 :     obj_id = _objects.size() - 1;
     128      288412 :     _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      288412 :     _obj_cache.clear();
     133      288412 :     _query_cache.clear();
     134      288412 :   }
     135             : 
     136      288412 :   std::vector<std::unique_ptr<Attribute>> attribs;
     137      288412 :   readAttribs(obj.get(), attribs);
     138      288412 :   _store->add(obj_id, std::move(attribs));
     139      288412 : }
     140             : 
     141             : void
     142       74165 : TheWarehouse::update(MooseObject * obj, const Attribute & extra)
     143             : {
     144       74165 :   std::vector<std::unique_ptr<Attribute>> attribs;
     145       74165 :   attribs.push_back(extra.clone());
     146       74165 :   _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       74165 :   _obj_cache.clear();
     150       74165 :   _query_cache.clear();
     151       74165 : }
     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     3254841 : TheWarehouse::prepare(std::vector<std::unique_ptr<Attribute>> conds)
     167             : {
     168     3254841 :   bool sort = false;
     169     3254841 :   std::unique_ptr<Attribute> sorted_attrib;
     170     3254841 :   if (!conds.empty() && dynamic_cast<AttribSorted *>(conds.back().get()))
     171             :   {
     172     3185621 :     sorted_attrib = std::move(conds.back());
     173     3185621 :     static const AttribSorted sorted_attrib_true(*this, true);
     174     3185621 :     sort = sorted_attrib->isMatch(sorted_attrib_true);
     175             :     // Remove the sorted condition temporarily
     176     3185621 :     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     3254841 :   auto obj_ids = _store->query(conds);
     186     3254841 :   if (sorted_attrib)
     187     3185621 :     conds.push_back(std::move(sorted_attrib));
     188             : 
     189     3254841 :   std::lock_guard<std::mutex> lock(_obj_cache_mutex);
     190     3254841 :   auto & vec = _obj_cache.emplace_back(obj_ids.size());
     191     3254841 :   const auto query_id = _obj_cache.size() - 1;
     192             :   {
     193     3254841 :     std::lock_guard<std::mutex> lock(_query_cache_mutex);
     194     3254841 :     _query_cache[std::move(conds)] = query_id;
     195     3254841 :   }
     196             : 
     197     3254841 :   std::lock_guard<std::mutex> o_lock(_obj_mutex);
     198     4160445 :   for (const auto i : index_range(obj_ids))
     199             :   {
     200      905604 :     auto obj = _objects[obj_ids[i]].get();
     201             :     mooseAssert(std::find(vec.begin(), vec.end(), obj) == vec.end(), "Duplicate object");
     202      905604 :     vec[i] = obj;
     203             :   }
     204             : 
     205     3254841 :   if (sort && !vec.empty() && dynamic_cast<DependencyResolverInterface *>(vec[0]))
     206             :   {
     207      230194 :     std::vector<DependencyResolverInterface *> dependers;
     208      685838 :     for (auto obj : vec)
     209             :     {
     210      455644 :       auto d = dynamic_cast<DependencyResolverInterface *>(obj);
     211      455644 :       if (!d)
     212             :       {
     213           0 :         dependers.clear();
     214           0 :         break;
     215             :       }
     216      455644 :       dependers.push_back(d);
     217             :     }
     218             : 
     219             :     try
     220             :     {
     221      230194 :       DependencyResolverInterface::sort(dependers);
     222             :     }
     223           0 :     catch (CyclicDependencyException<DependencyResolverInterface *> & e)
     224             :     {
     225           0 :       DependencyResolverInterface::cyclicDependencyError<UserObject *>(
     226             :           e, "Cyclic dependency detected in object ordering");
     227           0 :     }
     228             : 
     229             :     mooseAssert(dependers.size() == vec.size(), "Dependency resolution size mismatch");
     230      685838 :     for (unsigned int i = 0; i < dependers.size(); i++)
     231      455644 :       vec[i] = dynamic_cast<MooseObject *>(dependers[i]);
     232      230194 :   }
     233             : 
     234     3254841 :   return query_id;
     235     3254841 : }
     236             : 
     237             : const std::vector<MooseObject *> &
     238   137377105 : TheWarehouse::query(int query_id)
     239             : {
     240   137377105 :   if (static_cast<std::size_t>(query_id) >= _obj_cache.size())
     241           0 :     throw std::runtime_error("unknown query id");
     242   137377105 :   return _obj_cache[query_id];
     243             : }
     244             : 
     245             : std::size_t
     246    43275681 : TheWarehouse::queryID(const std::vector<std::unique_ptr<Attribute>> & conds)
     247             : {
     248             :   {
     249    43275681 :     std::lock_guard<std::mutex> lock(_query_cache_mutex);
     250    43275681 :     auto it = _query_cache.find(conds);
     251    43275681 :     if (it != _query_cache.end())
     252    40020840 :       return it->second;
     253    43275681 :   }
     254             : 
     255     3254841 :   std::vector<std::unique_ptr<Attribute>> conds_clone;
     256     3254841 :   conds_clone.resize(conds.size());
     257    18240007 :   for (std::size_t i = 0; i < conds.size(); i++)
     258    14985166 :     conds_clone[i] = conds[i]->clone();
     259     3254841 :   return prepare(std::move(conds_clone));
     260     3254841 : }
     261             : 
     262             : std::size_t
     263      288582 : TheWarehouse::count(const std::vector<std::unique_ptr<Attribute>> & conds)
     264             : {
     265      288582 :   auto query_id = queryID(conds);
     266      288582 :   std::lock_guard<std::mutex> lock(_obj_cache_mutex);
     267      288582 :   auto & objs = query(query_id);
     268      288582 :   std::size_t count = 0;
     269      309610 :   for (auto obj : objs)
     270       21028 :     if (obj->enabled())
     271       21028 :       count++;
     272      288582 :   return count;
     273      288582 : }
     274             : 
     275             : void
     276      288412 : TheWarehouse::readAttribs(const MooseObject * obj,
     277             :                           std::vector<std::unique_ptr<Attribute>> & attribs)
     278             : {
     279     5479780 :   for (auto & ref : _attrib_list)
     280             :   {
     281     5191368 :     attribs.emplace_back(ref->clone());
     282     5191368 :     attribs.back()->initFrom(obj);
     283             :   }
     284      288412 : }
     285             : 
     286             : void
     287      288412 : isValid(MooseObject * obj)
     288             : {
     289      288412 :   auto blk = dynamic_cast<BlockRestrictable *>(obj);
     290      288412 :   if (!blk)
     291      152561 :     return;
     292             : 
     293             :   // Check variables
     294      135851 :   auto c_ptr = dynamic_cast<Coupleable *>(obj);
     295      135851 :   if (c_ptr)
     296      174075 :     for (MooseVariableFEBase * var : c_ptr->getCoupledMooseVars())
     297       41206 :       blk->checkVariable(*var);
     298             : 
     299      135851 :   const InputParameters & parameters = obj->parameters();
     300             : 
     301      135851 :   SubProblem & problem = *parameters.get<SubProblem *>("_subproblem");
     302             : 
     303      135851 :   THREAD_ID tid = parameters.get<THREAD_ID>("_tid");
     304             : 
     305      135851 :   if (parameters.isParamValid("variable"))
     306             :   {
     307             :     // Try the scalar version first
     308      126846 :     std::string variable_name = parameters.getMooseType("variable");
     309      126846 :     if (variable_name == "")
     310             :       // When using vector variables, we are only going to use the first one in the list at the
     311             :       // interface level...
     312       27856 :       variable_name = parameters.getVecMooseType("variable")[0];
     313             : 
     314      126846 :     blk->checkVariable(problem.getVariable(
     315             :         tid, variable_name, Moose::VarKindType::VAR_ANY, Moose::VarFieldType::VAR_FIELD_ANY));
     316      126846 :   }
     317             : }

Generated by: LCOV version 1.14