LCOV - code coverage report
Current view: top level - src/loops - ComputeNodalUserObjectsThread.C (source / functions) Hit Total Coverage
Test: idaholab/moose framework: 419b9d Lines: 84 84 100.0 %
Date: 2025-08-08 20:01:16 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       16407 : ComputeNodalUserObjectsThread::ComputeNodalUserObjectsThread(FEProblemBase & fe_problem,
      23       16407 :                                                              const TheWarehouse::Query & query)
      24             :   : ThreadedNodeLoop<ConstNodeRange, ConstNodeRange::const_iterator>(fe_problem),
      25       16407 :     _query(query),
      26       16407 :     _aux_sys(fe_problem.getAuxiliarySystem())
      27             : {
      28       16407 : }
      29             : 
      30             : // Splitting Constructor
      31        1361 : ComputeNodalUserObjectsThread::ComputeNodalUserObjectsThread(ComputeNodalUserObjectsThread & x,
      32        1361 :                                                              Threads::split split)
      33             :   : ThreadedNodeLoop<ConstNodeRange, ConstNodeRange::const_iterator>(x, split),
      34        1361 :     _query(x._query),
      35        1361 :     _aux_sys(x._aux_sys)
      36             : {
      37        1361 : }
      38             : 
      39       19129 : ComputeNodalUserObjectsThread::~ComputeNodalUserObjectsThread() {}
      40             : 
      41             : void
      42       36729 : ComputeNodalUserObjectsThread::subdomainChanged()
      43             : {
      44       36729 :   std::vector<NodalUserObject *> objs;
      45       36729 :   _query.clone()
      46       36729 :       .condition<AttribThread>(_tid)
      47       73458 :       .condition<AttribInterfaces>(Interfaces::NodalUserObject)
      48       36729 :       .queryInto(objs);
      49             : 
      50       36729 :   std::set<TagID> needed_vector_tags;
      51       85428 :   for (const auto obj : objs)
      52             :   {
      53       48699 :     auto & vector_tags = obj->getFEVariableCoupleableVectorTags();
      54       48699 :     needed_vector_tags.insert(vector_tags.begin(), vector_tags.end());
      55             :   }
      56       36729 :   _fe_problem.setActiveFEVariableCoupleableVectorTags(needed_vector_tags, _tid);
      57       36729 : }
      58             : 
      59             : void
      60     1556430 : ComputeNodalUserObjectsThread::onNode(ConstNodeRange::const_iterator & node_it)
      61             : {
      62     1556430 :   const Node * node = *node_it;
      63             : 
      64     1556430 :   const auto & block_ids = _aux_sys.mesh().getNodeBlockIds(*node);
      65     1556430 :   if (_block_ids != block_ids)
      66             :   {
      67       36729 :     _block_ids.clear();
      68       36729 :     _block_ids.insert(block_ids.begin(), block_ids.end());
      69       36729 :     subdomainChanged();
      70             :   }
      71             : 
      72     1556430 :   _fe_problem.reinitNode(node, _tid);
      73             : 
      74     1556430 :   std::vector<NodalUserObject *> objs;
      75             : 
      76             :   // Boundary Restricted
      77     1556430 :   std::vector<BoundaryID> nodeset_ids;
      78     1556430 :   _fe_problem.mesh().getMesh().get_boundary_info().boundary_ids(node, nodeset_ids);
      79     2076023 :   for (const auto & bnd : nodeset_ids)
      80             :   {
      81      519593 :     _query.clone()
      82      519593 :         .condition<AttribThread>(_tid)
      83      519593 :         .condition<AttribInterfaces>(Interfaces::NodalUserObject)
      84     1039186 :         .condition<AttribBoundaries>(bnd, true)
      85      519593 :         .queryInto(objs);
      86      606286 :     for (const auto & uo : objs)
      87             :     {
      88       86693 :       uo->execute();
      89             : 
      90             :       // update the aux solution vector if writable coupled variables are used
      91       86693 :       if (uo->hasWritableCoupledVariables())
      92             :       {
      93          72 :         Threads::spin_mutex::scoped_lock lock(writable_variable_mutex);
      94         144 :         for (auto * var : uo->getWritableCoupledVariables())
      95          72 :           var->insert(_aux_sys.solution());
      96          72 :       }
      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     1556430 :   std::set<NodalUserObject *> computed;
     108     3125226 :   for (const auto & block : block_ids)
     109             :   {
     110     1568796 :     _query.clone()
     111     1568796 :         .condition<AttribThread>(_tid)
     112     3137592 :         .condition<AttribInterfaces>(Interfaces::NodalUserObject)
     113     1568796 :         .condition<AttribSubdomains>(block)
     114     1568796 :         .queryInto(objs);
     115             : 
     116     2959452 :     for (const auto & uo : objs)
     117     1390656 :       if (!uo->isUniqueNodeExecute() || computed.count(uo) == 0)
     118             :       {
     119     1390548 :         uo->execute();
     120             : 
     121             :         // update the aux solution vector if writable coupled variables are used
     122     1390548 :         if (uo->hasWritableCoupledVariables())
     123             :         {
     124          36 :           Threads::spin_mutex::scoped_lock lock(writable_variable_mutex);
     125          72 :           for (auto * var : uo->getWritableCoupledVariables())
     126          36 :             var->insert(_aux_sys.solution());
     127          36 :         }
     128             : 
     129     1390548 :         computed.insert(uo);
     130             :       }
     131             :   }
     132     1556430 : }
     133             : 
     134             : void
     135        1361 : ComputeNodalUserObjectsThread::join(const ComputeNodalUserObjectsThread & /*y*/)
     136             : {
     137        1361 : }
     138             : 
     139             : void
     140       17768 : ComputeNodalUserObjectsThread::printGeneralExecutionInformation() const
     141             : {
     142       17768 :   if (!_fe_problem.shouldPrintExecution(_tid))
     143       17678 :     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