LCOV - code coverage report
Current view: top level - include/loops - ComputeUserObjectsThread.h (source / functions) Hit Total Coverage
Test: idaholab/moose framework: 8601ad Lines: 41 41 100.0 %
Date: 2025-07-18 13:27:08 Functions: 10 10 100.0 %
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             : #pragma once
      11             : 
      12             : // MOOSE includes
      13             : #include "ThreadedElementLoop.h"
      14             : #include "ExecFlagEnum.h"
      15             : #include "AuxiliarySystem.h"
      16             : 
      17             : #include "libmesh/elem_range.h"
      18             : 
      19             : #include <map>
      20             : 
      21             : class InternalSideUserObject;
      22             : class ElementUserObject;
      23             : class ShapeElementUserObject;
      24             : class InterfaceUserObject;
      25             : class DomainUserObject;
      26             : 
      27             : // libMesh forward declarations
      28             : namespace libMesh
      29             : {
      30             : template <typename T>
      31             : class NumericVector;
      32             : }
      33             : 
      34             : /**
      35             :  * Class for threaded computation of UserObjects.
      36             :  */
      37             : class ComputeUserObjectsThread : public ThreadedElementLoop<ConstElemRange>
      38             : {
      39             : public:
      40             :   ComputeUserObjectsThread(FEProblemBase & problem, const TheWarehouse::Query & query);
      41             :   // Splitting Constructor
      42             :   ComputeUserObjectsThread(ComputeUserObjectsThread & x, Threads::split);
      43             : 
      44             :   virtual ~ComputeUserObjectsThread();
      45             : 
      46             :   virtual void onElement(const Elem * elem) override;
      47             :   virtual void onBoundary(const Elem * elem,
      48             :                           unsigned int side,
      49             :                           BoundaryID bnd_id,
      50             :                           const Elem * lower_d_elem = nullptr) override;
      51             :   virtual void onInternalSide(const Elem * elem, unsigned int side) override;
      52             :   virtual void onExternalSide(const Elem * elem, unsigned int side) override;
      53             :   virtual void onInterface(const Elem * elem, unsigned int side, BoundaryID bnd_id) override;
      54             :   virtual void post() override;
      55             :   virtual void subdomainChanged() override;
      56             : 
      57             :   void join(const ComputeUserObjectsThread & /*y*/);
      58             : 
      59             : protected:
      60             :   /// Print general information about the loop, like the ordering of class of objects
      61             :   void printGeneralExecutionInformation() const override;
      62             : 
      63             :   /// Print information about the loop, mostly order of execution of particular objects
      64             :   void printBlockExecutionInformation() const override;
      65             : 
      66             :   /// Format output of vector of UOs
      67             :   template <typename T>
      68             :   void printVectorOrdering(std::vector<T *> uos, const std::string & name) const;
      69             : 
      70             : private:
      71             :   template <typename T>
      72     1513395 :   void querySubdomain(Interfaces iface, std::vector<T> & results)
      73             :   {
      74     1513395 :     _query_subdomain.queryInto(results, _tid, _subdomain, iface);
      75     1513395 :   }
      76             :   template <typename T>
      77     5963286 :   void queryBoundary(Interfaces iface, BoundaryID bnd, std::vector<T> & results)
      78             :   {
      79     5963286 :     _query_boundary.queryInto(results, _tid, std::make_tuple(bnd, false), iface);
      80     5963286 :   }
      81             : 
      82             :   const TheWarehouse::Query _query;
      83             :   TheWarehouse::QueryCache<AttribThread, AttribSubdomains, AttribInterfaces> _query_subdomain;
      84             :   TheWarehouse::QueryCache<AttribThread, AttribBoundaries, AttribInterfaces> _query_boundary;
      85             :   std::vector<InternalSideUserObject *> _internal_side_objs;
      86             :   std::vector<InterfaceUserObject *> _interface_user_objects;
      87             :   std::vector<ElementUserObject *> _element_objs;
      88             :   std::vector<ShapeElementUserObject *> _shape_element_objs;
      89             :   std::vector<DomainUserObject *> _domain_objs;
      90             :   std::vector<DomainUserObject *> _all_domain_objs;
      91             : 
      92             :   AuxiliarySystem & _aux_sys;
      93             : };
      94             : 
      95             : // determine when we need to run user objects based on whether any initial conditions or aux
      96             : // kernels depend on the user objects.  If so we need to run them either before ics, before aux
      97             : // kernels, or after aux kernels (if nothing depends on them).  Mark/store this information as
      98             : // attributes in the warehouse for later reference.
      99             : template <typename T>
     100             : void
     101       55548 : groupUserObjects(TheWarehouse & w,
     102             :                  AuxiliarySystem & aux,
     103             :                  const ExecFlagEnum & execute_flags,
     104             :                  const std::vector<T *> & objs,
     105             :                  const std::set<std::string> & ic_deps)
     106             : {
     107             :   // These flags indicate when a user object will be executed for a given exec flag time.
     108             :   // The attributes are set by this function and their values are queried in
     109             :   // FEProblemBase::computeUserObjectsInternal(). If a UO is found to be in one of the
     110             :   // three groups: PRE_IC, PRE_AUX, or POST_AUX, then that UO is executed with that group.
     111             :   //
     112             :   // PRE_IC objects are run before initial conditions during the "INITIAL" exec flag time.
     113             :   // On any other exec flag time, they are run in POST_AUX by default or if there is
     114             :   // an dependency for some exec flag or if force_preaux is set, they are run in
     115             :   // PRE_AUX
     116             :   //
     117             :   // PRE_AUX objects are run before the dependent AuxKernels exec flag
     118             :   //
     119             :   // POST_AUX objects are run after AuxKernels on any given exec flag time, and is the
     120             :   // default group for UOs. Dependencies that would otherwise move a UO into the
     121             :   // PRE_AUX group can be overridden by specifying the parameter force_postaux
     122             :   //
     123             :   // This function attempts to sort a UO based on any ICs or AuxKernels which depend on
     124             :   // it. Alternatively, a user may select which group to execute their object with by
     125             :   // controlling the force_preic, force_preaux and force_postaux input parameters.
     126             :   //
     127             : 
     128       55548 :   std::map<T *, std::set<int>> pre_aux_dependencies;
     129       55548 :   std::map<T *, std::set<int>> post_aux_dependencies;
     130             :   // This map is used to indicate, after all dependencies have
     131             :   // been looked through, whether the UO has been flagged to
     132             :   // execute on EXEC_INITIAL, either through a dependency or
     133             :   // because force_preic was indicated. If neither of these
     134             :   // are true, the UO needs to be run in POST_AUX for EXEC_INITIAL
     135       55548 :   std::map<T *, bool> is_pre_ic;
     136             : 
     137      126850 :   for (const auto obj : objs)
     138       71302 :     is_pre_ic[obj] = false;
     139             : 
     140     1499785 :   for (const ExecFlagType & flag : execute_flags.items())
     141             :   {
     142     1444237 :     std::set<std::string> depend_objects_aux = aux.getDependObjects(flag);
     143     3298087 :     for (const auto obj : objs)
     144             :     {
     145     1853850 :       if (depend_objects_aux.count(obj->name()) > 0)
     146             :       {
     147        3620 :         pre_aux_dependencies[obj].insert(flag);
     148        3620 :         if (flag == EXEC_INITIAL)
     149        1076 :           is_pre_ic.at(obj) = true;
     150             :       }
     151     1850230 :       else if (flag != EXEC_INITIAL)
     152             :         // default is for UO to be post_aux. If EXEC_INITIAL, check first if UO
     153             :         // will be dependent on IC or have force_preic before deciding to put in
     154             :         // post_aux
     155     1780004 :         post_aux_dependencies[obj].insert(flag);
     156             :     }
     157             :   }
     158             : 
     159      126850 :   for (const auto obj : objs)
     160             :   {
     161      142470 :     if (ic_deps.count(obj->name()) > 0 ||
     162      142470 :         (obj->isParamValid("force_preic") && obj->template getParam<bool>("force_preic")))
     163             :     {
     164         291 :       w.update(obj, AttribPreIC(w, true));
     165         291 :       is_pre_ic.at(obj) = true;
     166             :     }
     167             : 
     168       71302 :     if ((obj->isParamValid("force_preaux") && obj->template getParam<bool>("force_preaux")))
     169             :     {
     170         516 :       post_aux_dependencies[obj].clear();
     171       13932 :       for (const ExecFlagType & flag : execute_flags.items())
     172       13416 :         pre_aux_dependencies[obj].insert(flag);
     173             :     }
     174       70786 :     else if (obj->isParamValid("force_postaux") && obj->template getParam<bool>("force_postaux"))
     175             :     {
     176          39 :       pre_aux_dependencies[obj].clear();
     177        1053 :       for (const ExecFlagType & flag : execute_flags.items())
     178        1014 :         post_aux_dependencies[obj].insert(flag);
     179             :     }
     180             :     else
     181             :     {
     182             :       // If at this point, then check if the UO has already been set to execute
     183             :       // by either the force_preic param, an IC dependency, or a dependency
     184             :       // already found for exec flage EXEC_INITIAL. If none of these are true,
     185             :       // then is_pre_ic.at(obj) is false and the UO is added to the default
     186             :       // post_aux group for the EXEC_INITIAL flag
     187       70747 :       if (!is_pre_ic.at(obj))
     188       69432 :         post_aux_dependencies[obj].insert(EXEC_INITIAL);
     189             :     }
     190             :   }
     191             : 
     192       58456 :   for (auto & item : pre_aux_dependencies)
     193        2908 :     w.update(item.first, AttribPreAux(w, item.second));
     194             : 
     195      126850 :   for (auto & item : post_aux_dependencies)
     196       71302 :     w.update(item.first, AttribPostAux(w, item.second));
     197       55548 : }

Generated by: LCOV version 1.14