LCOV - code coverage report
Current view: top level - src/auxkernels - NearestNodeValueAux.C (source / functions) Hit Total Coverage
Test: idaholab/moose framework: 3501bd Lines: 25 52 48.1 %
Date: 2025-09-04 20:01:23 Functions: 3 3 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 "NearestNodeValueAux.h"
      11             : 
      12             : #include "SystemBase.h"
      13             : #include "NearestNodeLocator.h"
      14             : 
      15             : registerMooseObject("MooseApp", NearestNodeValueAux);
      16             : 
      17             : InputParameters
      18       14292 : NearestNodeValueAux::validParams()
      19             : {
      20       14292 :   InputParameters params = AuxKernel::validParams();
      21       28584 :   params.addClassDescription("Retrieves a field value from the closest node on the paired boundary "
      22             :                              "and stores it on this boundary or block.");
      23       28584 :   params.set<bool>("_dual_restrictable") = true;
      24       57168 :   params.addRequiredParam<BoundaryName>("paired_boundary", "The boundary to get the value from.");
      25       57168 :   params.addRequiredCoupledVar("paired_variable", "The variable to get the value of.");
      26       14292 :   params.set<bool>("use_displaced_mesh") = true;
      27       14292 :   return params;
      28           0 : }
      29             : 
      30          14 : NearestNodeValueAux::NearestNodeValueAux(const InputParameters & parameters)
      31             :   : AuxKernel(parameters),
      32          14 :     _nearest_node(
      33          14 :         getNearestNodeLocator(parameters.get<BoundaryName>("paired_boundary"), boundaryNames()[0])),
      34          14 :     _serialized_solution(_nl_sys.currentSolution()),
      35          42 :     _paired_variable(coupled("paired_variable"))
      36             : {
      37          14 :   if (boundaryNames().size() > 1)
      38           0 :     paramError("boundary", "NearestNodeValueAux can only be used with one boundary at a time!");
      39          14 :   if (boundaryNames().empty())
      40           0 :     paramError("boundary", "Should be specified on a boundary");
      41             : 
      42             :   // Check that the paired variable is from the solution system
      43          42 :   if (_subproblem.hasAuxiliaryVariable("paired_variable"))
      44           0 :     paramError("paired_variable", "Paired variable should not be auxiliary");
      45             :   // Check that the paired variable has degrees of freedom on nodes (and thus can be sampled
      46             :   // directly at the dof index of the node)
      47          42 :   if (!getVar("paired_variable", 0)->hasDoFsOnNodes())
      48           0 :     paramError("paired_variable", "Paired variable does not have degrees of freedom on nodes");
      49             : 
      50             :   // TODO: avoid the runtime checks by making sure the paired variable is defined on the boundaries
      51          14 : }
      52             : 
      53             : Real
      54         476 : NearestNodeValueAux::computeValue()
      55             : {
      56         476 :   if (isNodal())
      57             :   {
      58             :     // Assumes the variable you are coupling to is from the nonlinear system for now.
      59         476 :     const Node * nearest = _nearest_node.nearestNode(_current_node->id());
      60         476 :     if (nearest == nullptr)
      61           0 :       mooseError("Could not locate the nearest node from node: ", _current_node->get_info());
      62         476 :     dof_id_type dof_number = nearest->dof_number(_nl_sys.number(), _paired_variable, 0);
      63         476 :     if (dof_number == libMesh::DofObject::invalid_id)
      64           0 :       mooseError("Paired variable does not seem to be defined on nearest node: ",
      65           0 :                  nearest->get_info());
      66         476 :     return (*_serialized_solution)(dof_number);
      67             :   }
      68             :   else
      69             :   {
      70             :     // Get a value for all the nodes on the boundary, then average them for the centroid value
      71           0 :     Real average = 0;
      72           0 :     Real sum_inv_dist = 0;
      73           0 :     for (const auto & node : _current_elem->node_ref_range())
      74             :     {
      75           0 :       const Node * nearest = _nearest_node.nearestNode(node.id());
      76             :       // Some of the element's nodes wont be on the boundary
      77           0 :       if (!nearest)
      78           0 :         continue;
      79           0 :       const auto dof_number = nearest->dof_number(_nl_sys.number(), _paired_variable, 0);
      80           0 :       const auto distance = _nearest_node.distance(node.id());
      81             : 
      82           0 :       if (dof_number == libMesh::DofObject::invalid_id)
      83           0 :         mooseError("Paired variable does not seem to be defined on nearest node: ",
      84           0 :                    nearest->get_info());
      85             : 
      86             :       // inverse distance weighting should be a fine default
      87           0 :       if (distance > 0)
      88             :       {
      89           0 :         average += (*_serialized_solution)(dof_number) / distance;
      90           0 :         sum_inv_dist += 1. / distance;
      91             :       }
      92             :       // if node and nearest nodes coincide, weight with 1
      93             :       else
      94             :       {
      95           0 :         average += (*_serialized_solution)(dof_number);
      96           0 :         sum_inv_dist += 1.;
      97             :       }
      98             :     }
      99             : 
     100           0 :     if (sum_inv_dist > 0)
     101           0 :       return average / sum_inv_dist;
     102             :     else
     103           0 :       return 0.;
     104             :   }
     105             : }

Generated by: LCOV version 1.14