LCOV - code coverage report
Current view: top level - src/loops - ComputeNodalUserObjectsThread.C (source / functions) Hit Total Coverage
Test: idaholab/moose framework: 2bf808 Lines: 84 84 100.0 %
Date: 2025-07-17 01:28:37 Functions: 8 8 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             : #include "ComputeNodalUserObjectsThread.h"
      11             : 
      12             : // MOOSE includes
      13             : #include "FEProblem.h"
      14             : #include "MooseMesh.h"
      15             : #include "NodalUserObject.h"
      16             : #include "AuxiliarySystem.h"
      17             : 
      18             : #include "libmesh/threads.h"
      19             : 
      20             : Threads::spin_mutex ComputeNodalUserObjectsThread::writable_variable_mutex;
      21             : 
      22       14943 : ComputeNodalUserObjectsThread::ComputeNodalUserObjectsThread(FEProblemBase & fe_problem,
      23       14943 :                                                              const TheWarehouse::Query & query)
      24             :   : ThreadedNodeLoop<ConstNodeRange, ConstNodeRange::const_iterator>(fe_problem),
      25       14943 :     _query(query),
      26       14943 :     _aux_sys(fe_problem.getAuxiliarySystem())
      27             : {
      28       14943 : }
      29             : 
      30             : // Splitting Constructor
      31        1357 : ComputeNodalUserObjectsThread::ComputeNodalUserObjectsThread(ComputeNodalUserObjectsThread & x,
      32        1357 :                                                              Threads::split split)
      33             :   : ThreadedNodeLoop<ConstNodeRange, ConstNodeRange::const_iterator>(x, split),
      34        1357 :     _query(x._query),
      35        1357 :     _aux_sys(x._aux_sys)
      36             : {
      37        1357 : }
      38             : 
      39       17657 : ComputeNodalUserObjectsThread::~ComputeNodalUserObjectsThread() {}
      40             : 
      41             : void
      42       33650 : ComputeNodalUserObjectsThread::subdomainChanged()
      43             : {
      44       33650 :   std::vector<NodalUserObject *> objs;
      45       33650 :   _query.clone()
      46       33650 :       .condition<AttribThread>(_tid)
      47       67300 :       .condition<AttribInterfaces>(Interfaces::NodalUserObject)
      48       33650 :       .queryInto(objs);
      49             : 
      50       33650 :   std::set<TagID> needed_vector_tags;
      51       79032 :   for (const auto obj : objs)
      52             :   {
      53       45382 :     auto & vector_tags = obj->getFEVariableCoupleableVectorTags();
      54       45382 :     needed_vector_tags.insert(vector_tags.begin(), vector_tags.end());
      55             :   }
      56       33650 :   _fe_problem.setActiveFEVariableCoupleableVectorTags(needed_vector_tags, _tid);
      57       33650 : }
      58             : 
      59             : void
      60     1378639 : ComputeNodalUserObjectsThread::onNode(ConstNodeRange::const_iterator & node_it)
      61             : {
      62     1378639 :   const Node * node = *node_it;
      63             : 
      64     1378639 :   const auto & block_ids = _aux_sys.mesh().getNodeBlockIds(*node);
      65     1378639 :   if (_block_ids != block_ids)
      66             :   {
      67       33650 :     _block_ids.clear();
      68       33650 :     _block_ids.insert(block_ids.begin(), block_ids.end());
      69       33650 :     subdomainChanged();
      70             :   }
      71             : 
      72     1378639 :   _fe_problem.reinitNode(node, _tid);
      73             : 
      74     1378639 :   std::vector<NodalUserObject *> objs;
      75             : 
      76             :   // Boundary Restricted
      77     1378639 :   std::vector<BoundaryID> nodeset_ids;
      78     1378639 :   _fe_problem.mesh().getMesh().get_boundary_info().boundary_ids(node, nodeset_ids);
      79     1838214 :   for (const auto & bnd : nodeset_ids)
      80             :   {
      81      459575 :     _query.clone()
      82      459575 :         .condition<AttribThread>(_tid)
      83      459575 :         .condition<AttribInterfaces>(Interfaces::NodalUserObject)
      84      919150 :         .condition<AttribBoundaries>(bnd, true)
      85      459575 :         .queryInto(objs);
      86      536786 :     for (const auto & uo : objs)
      87             :     {
      88       77211 :       uo->execute();
      89             : 
      90             :       // update the aux solution vector if writable coupled variables are used
      91       77211 :       if (uo->hasWritableCoupledVariables())
      92             :       {
      93          64 :         Threads::spin_mutex::scoped_lock lock(writable_variable_mutex);
      94         128 :         for (auto * var : uo->getWritableCoupledVariables())
      95          64 :           var->insert(_aux_sys.solution());
      96          64 :       }
      97             :     }
      98             :   }
      99             : 
     100             :   // Block Restricted
     101             :   // NodalUserObjects may be block restricted, in this case by default the execute() method is
     102             :   // called for each subdomain that the node "belongs". This may be disabled in the NodalUserObject
     103             :   // by setting "unique_node_execute = true".
     104             : 
     105             :   // To enforce the unique execution this vector is populated and checked if the unique flag is
     106             :   // enabled.
     107     1378639 :   std::set<NodalUserObject *> computed;
     108     2768801 :   for (const auto & block : block_ids)
     109             :   {
     110     1390162 :     _query.clone()
     111     1390162 :         .condition<AttribThread>(_tid)
     112     2780324 :         .condition<AttribInterfaces>(Interfaces::NodalUserObject)
     113     1390162 :         .condition<AttribSubdomains>(block)
     114     1390162 :         .queryInto(objs);
     115             : 
     116     2629507 :     for (const auto & uo : objs)
     117     1239345 :       if (!uo->isUniqueNodeExecute() || computed.count(uo) == 0)
     118             :       {
     119     1239249 :         uo->execute();
     120             : 
     121             :         // update the aux solution vector if writable coupled variables are used
     122     1239249 :         if (uo->hasWritableCoupledVariables())
     123             :         {
     124          32 :           Threads::spin_mutex::scoped_lock lock(writable_variable_mutex);
     125          64 :           for (auto * var : uo->getWritableCoupledVariables())
     126          32 :             var->insert(_aux_sys.solution());
     127          32 :         }
     128             : 
     129     1239249 :         computed.insert(uo);
     130             :       }
     131             :   }
     132     1378639 : }
     133             : 
     134             : void
     135        1357 : ComputeNodalUserObjectsThread::join(const ComputeNodalUserObjectsThread & /*y*/)
     136             : {
     137        1357 : }
     138             : 
     139             : void
     140       16300 : ComputeNodalUserObjectsThread::printGeneralExecutionInformation() const
     141             : {
     142       16300 :   if (!_fe_problem.shouldPrintExecution(_tid))
     143       16210 :     return;
     144             : 
     145             :   // Get all nodal UOs
     146          90 :   std::vector<MooseObject *> nodal_uos;
     147          90 :   _query.clone()
     148          90 :       .condition<AttribThread>(_tid)
     149         180 :       .condition<AttribInterfaces>(Interfaces::NodalUserObject)
     150          90 :       .queryInto(nodal_uos);
     151             : 
     152          90 :   if (nodal_uos.size())
     153             :   {
     154          90 :     const auto & console = _fe_problem.console();
     155          90 :     const auto & execute_on = _fe_problem.getCurrentExecuteOnFlag();
     156          90 :     console << "[DBG] Computing nodal user objects on " << execute_on << std::endl;
     157          90 :     mooseDoOnce(
     158             :         console << "[DBG] Ordering on nodes:" << std::endl;
     159             :         console << "[DBG] - boundary restricted user objects" << std::endl;
     160             :         console << "[DBG] - block restricted user objects" << std::endl;
     161             :         console << "[DBG] Nodal UOs executed on each node will differ based on these restrictions"
     162             :                 << std::endl;);
     163             : 
     164          90 :     auto message = ConsoleUtils::mooseObjectVectorToString(nodal_uos);
     165          90 :     message = "Order of execution:\n" + message;
     166          90 :     console << ConsoleUtils::formatString(message, "[DBG]") << std::endl;
     167          90 :   }
     168          90 : }

Generated by: LCOV version 1.14