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

Generated by: LCOV version 1.14