LCOV - code coverage report
Current view: top level - include/userobjects - NearestPointBase.h (source / functions) Hit Total Coverage
Test: idaholab/moose framework: 2bf808 Lines: 93 97 95.9 %
Date: 2025-07-17 01:28:37 Functions: 89 117 76.1 %
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 "SpatialUserObjectFunctor.h"
      14             : #include "Enumerate.h"
      15             : #include "DelimitedFileReader.h"
      16             : #include "LayeredBase.h"
      17             : 
      18             : // Forward Declarations
      19             : class UserObject;
      20             : 
      21             : /**
      22             :  * This UserObject computes averages of a variable storing partial
      23             :  * sums for the specified number of intervals in a direction (x,y,z).
      24             :  *
      25             :  * Given a list of points this object computes the layered average
      26             :  * closest to each one of those points.
      27             :  */
      28             : template <typename UserObjectType, typename BaseType>
      29             : class NearestPointBase : public SpatialUserObjectFunctor<BaseType>
      30             : {
      31             : public:
      32             :   static InputParameters validParams();
      33             : 
      34             :   NearestPointBase(const InputParameters & parameters);
      35             :   ~NearestPointBase();
      36             : 
      37             :   virtual void initialize() override;
      38             :   virtual void execute() override;
      39             :   virtual void finalize() override;
      40             :   virtual void threadJoin(const UserObject & y) override;
      41             : 
      42             :   /**
      43             :    * Given a Point return the integral value associated with the layer
      44             :    * that point falls in for the layered average closest to that
      45             :    * point.
      46             :    *
      47             :    * @param p The point to look for in the layers.
      48             :    */
      49             :   virtual Real spatialValue(const Point & p) const override;
      50             : 
      51             :   /**
      52             :    * Get the points at which the nearest operation is performed
      53             :    * @return points
      54             :    */
      55          12 :   virtual const std::vector<Point> & getPoints() const { return _points; }
      56             : 
      57             :   virtual const std::vector<Point> spatialPoints() const override;
      58             : 
      59             : protected:
      60             :   /**
      61             :    * Fills in the `_points` variable from either 'points' or 'points_file' parameter.
      62             :    * Also performs error checking.
      63             :    */
      64             :   void fillPoints();
      65             : 
      66             :   /**
      67             :    * Get the UserObject that is closest to the point.
      68             :    *
      69             :    * @param p The point.
      70             :    * @return The UserObject closest to p.
      71             :    */
      72             :   UserObjectType & nearestUserObject(const Point & p) const;
      73             : 
      74             :   std::vector<Point> _points;
      75             :   std::vector<std::unique_ptr<UserObjectType>> _user_objects;
      76             : 
      77             :   // To specify whether the distance is defined based on point or radius
      78             :   const unsigned int _dist_norm;
      79             :   // The axis around which the radius is determined
      80             :   const unsigned int _axis;
      81             : 
      82             :   using BaseType::_communicator;
      83             :   using BaseType::_current_elem;
      84             :   using BaseType::isParamValid;
      85             :   using BaseType::processor_id;
      86             :   using MooseBase::name;
      87             : };
      88             : 
      89             : template <typename UserObjectType, typename BaseType>
      90             : InputParameters
      91      157808 : NearestPointBase<UserObjectType, BaseType>::validParams()
      92             : {
      93      157808 :   InputParameters params = SpatialUserObjectFunctor<BaseType>::validParams();
      94             : 
      95      157808 :   params.addParam<std::vector<Point>>("points",
      96             :                                       "Computations will be lumped into values at these points.");
      97      157808 :   params.addParam<FileName>("points_file",
      98             :                             "A filename that should be looked in for points. Each "
      99             :                             "set of 3 values in that file will represent a Point. "
     100             :                             "This and 'points' cannot be both supplied.");
     101             : 
     102      157808 :   MooseEnum distnorm("point=0 radius=1", "point");
     103      157808 :   params.addParam<MooseEnum>(
     104             :       "dist_norm", distnorm, "To specify whether the distance is defined based on point or radius");
     105      157808 :   MooseEnum axis("x=0 y=1 z=2", "z");
     106      157808 :   params.addParam<MooseEnum>("axis", axis, "The axis around which the radius is determined");
     107             : 
     108      157808 :   params.addParamNamesToGroup("points points_file dist_norm axis", "Points and distance to points");
     109             : 
     110             :   // Add in the valid parameters
     111      157808 :   params += UserObjectType::validParams();
     112             : 
     113      315616 :   return params;
     114      157808 : }
     115             : 
     116             : template <typename UserObjectType, typename BaseType>
     117         477 : NearestPointBase<UserObjectType, BaseType>::NearestPointBase(const InputParameters & parameters)
     118             :   : SpatialUserObjectFunctor<BaseType>(parameters),
     119         477 :     _dist_norm(this->template getParam<MooseEnum>("dist_norm")),
     120         954 :     _axis(this->template getParam<MooseEnum>("axis"))
     121             : {
     122        1405 :   if (this->template getParam<MooseEnum>("dist_norm") != "radius" &&
     123         928 :       parameters.isParamSetByUser("axis"))
     124           0 :     this->paramError("axis", "'axis' should only be set if 'dist_norm' is set to 'radius'");
     125             : 
     126         477 :   fillPoints();
     127             : 
     128         465 :   _user_objects.resize(_points.size());
     129             : 
     130             :   // Build each of the UserObject objects that we will manage manually
     131             :   // If you're looking at this in the future and want to replace this behavior,
     132             :   // _please_ don't do it. MOOSE should manage these objects.
     133        1918 :   for (MooseIndex(_points) i = 0; i < _points.size(); ++i)
     134             :   {
     135        1465 :     const auto uo_type = MooseUtils::prettyCppType<UserObjectType>();
     136        1465 :     auto sub_params = this->_app.getFactory().getValidParams(uo_type);
     137        1465 :     sub_params.applyParameters(parameters, {}, true);
     138             : 
     139        1465 :     const auto sub_name = name() + "_sub" + std::to_string(i);
     140        1465 :     auto uo = this->_app.getFactory().template createUnique<UserObjectType>(
     141        1465 :         uo_type, sub_name, sub_params, this->_tid);
     142        1453 :     _user_objects[i] = std::move(uo);
     143             :   }
     144         453 : }
     145             : 
     146             : template <typename UserObjectType, typename BaseType>
     147         438 : NearestPointBase<UserObjectType, BaseType>::~NearestPointBase()
     148             : {
     149         438 : }
     150             : 
     151             : template <typename UserObjectType, typename BaseType>
     152             : void
     153         477 : NearestPointBase<UserObjectType, BaseType>::fillPoints()
     154             : {
     155         477 :   if (isParamValid("points") && isParamValid("points_file"))
     156           4 :     mooseError(name(), ": Both 'points' and 'points_file' cannot be specified simultaneously.");
     157             : 
     158         473 :   if (isParamValid("points"))
     159             :   {
     160         413 :     _points = this->template getParam<std::vector<Point>>("points");
     161             :   }
     162          60 :   else if (isParamValid("points_file"))
     163             :   {
     164          56 :     const FileName & points_file = this->template getParam<FileName>("points_file");
     165             : 
     166          56 :     MooseUtils::DelimitedFileReader file(points_file, &_communicator);
     167          56 :     file.setFormatFlag(MooseUtils::DelimitedFileReader::FormatFlag::ROWS);
     168          56 :     file.read();
     169          56 :     _points = file.getDataAsPoints();
     170          52 :   }
     171             :   else
     172           4 :     mooseError(name(), ": You need to supply either 'points' or 'points_file' parameter.");
     173         465 : }
     174             : 
     175             : template <typename UserObjectType, typename BaseType>
     176             : void
     177         925 : NearestPointBase<UserObjectType, BaseType>::initialize()
     178             : {
     179        4274 :   for (auto & user_object : _user_objects)
     180        3349 :     user_object->initialize();
     181         925 : }
     182             : 
     183             : template <typename UserObjectType, typename BaseType>
     184             : void
     185      737142 : NearestPointBase<UserObjectType, BaseType>::execute()
     186             : {
     187      737142 :   nearestUserObject(_current_elem->vertex_average()).execute();
     188      737142 : }
     189             : 
     190             : template <typename UserObjectType, typename BaseType>
     191             : void
     192         672 : NearestPointBase<UserObjectType, BaseType>::finalize()
     193             : {
     194        3302 :   for (auto & user_object : _user_objects)
     195        2630 :     user_object->finalize();
     196         672 : }
     197             : 
     198             : template <typename UserObjectType, typename BaseType>
     199             : void
     200          77 : NearestPointBase<UserObjectType, BaseType>::threadJoin(const UserObject & y)
     201             : {
     202          77 :   auto & npla = static_cast<const NearestPointBase &>(y);
     203             : 
     204         356 :   for (MooseIndex(_user_objects) i = 0; i < _user_objects.size(); ++i)
     205         279 :     _user_objects[i]->threadJoin(*npla._user_objects[i]);
     206          77 : }
     207             : 
     208             : template <typename UserObjectType, typename BaseType>
     209             : Real
     210      765508 : NearestPointBase<UserObjectType, BaseType>::spatialValue(const Point & p) const
     211             : {
     212      765508 :   return nearestUserObject(p).spatialValue(p);
     213             : }
     214             : 
     215             : template <typename UserObjectType, typename BaseType>
     216             : UserObjectType &
     217     1502650 : NearestPointBase<UserObjectType, BaseType>::nearestUserObject(const Point & p) const
     218             : {
     219     1502650 :   unsigned int closest = 0;
     220     1502650 :   Real closest_distance = std::numeric_limits<Real>::max();
     221             : 
     222     8277470 :   for (auto it : Moose::enumerate(_points))
     223             :   {
     224     5272170 :     const auto & current_point = it.value();
     225             : 
     226             :     Real current_distance;
     227     5272170 :     if (_dist_norm == 0)
     228             :       // the distance is computed using standard norm
     229     4165150 :       current_distance = (p - current_point).norm();
     230             :     else
     231             :     {
     232             :       // the distance is to be computed based on radii
     233             :       // in that case, we need to determine the 2 coordinate indices
     234             :       // that define the radius
     235     1107020 :       unsigned int i = 0;
     236     1107020 :       unsigned int j = 1;
     237             : 
     238     1107020 :       if (_axis == 0)
     239           0 :         i = 2;
     240     1107020 :       else if (_axis == 1)
     241           0 :         j = 2;
     242             : 
     243     1107020 :       current_distance = std::abs(
     244     1107020 :           std::sqrt(p(i) * p(i) + p(j) * p(j)) -
     245     1107020 :           std::sqrt(current_point(i) * current_point(i) + current_point(j) * current_point(j)));
     246             :     }
     247             : 
     248     5272170 :     if (current_distance < closest_distance)
     249             :     {
     250     2967538 :       closest_distance = current_distance;
     251     2967538 :       closest = it.index();
     252             :     }
     253             :   }
     254             : 
     255     1502650 :   return *_user_objects[closest];
     256             : }
     257             : 
     258             : template <typename UserObjectType, typename BaseType>
     259             : const std::vector<Point>
     260          36 : NearestPointBase<UserObjectType, BaseType>::spatialPoints() const
     261             : {
     262          36 :   std::vector<Point> points;
     263             : 
     264         192 :   for (MooseIndex(_points) i = 0; i < _points.size(); ++i)
     265             :   {
     266         156 :     auto layered_base = dynamic_cast<LayeredBase *>(_user_objects[i].get());
     267         156 :     if (layered_base)
     268             :     {
     269         156 :       const auto & layers = layered_base->getLayerCenters();
     270         156 :       auto direction = layered_base->direction();
     271             : 
     272         564 :       for (const auto & l : layers)
     273             :       {
     274         408 :         Point pt = _points[i];
     275         408 :         pt(direction) = l;
     276         408 :         points.push_back(pt);
     277             :       }
     278             :     }
     279             :   }
     280             : 
     281          36 :   return points;
     282           0 : }

Generated by: LCOV version 1.14