LCOV - code coverage report
Current view: top level - src/interfaces - DiscreteLineSegmentInterface.C (source / functions) Hit Total Coverage
Test: idaholab/moose thermal_hydraulics: #31039 (75bfb3) with base bb0a08 Lines: 106 124 85.5 %
Date: 2025-11-03 14:57:48 Functions: 13 17 76.5 %
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 "DiscreteLineSegmentInterface.h"
      11             : #include "MooseObject.h"
      12             : #include "MooseEnum.h"
      13             : #include "MooseUtils.h"
      14             : #include "Numerics.h"
      15             : 
      16             : InputParameters
      17       11893 : DiscreteLineSegmentInterface::validParams()
      18             : {
      19       11893 :   InputParameters params = emptyInputParameters();
      20             : 
      21       23786 :   params.addRequiredParam<Point>("position", "Start position of axis in 3-D space [m]");
      22       23786 :   params.addRequiredParam<RealVectorValue>(
      23             :       "orientation",
      24             :       "Direction of axis from start position to end position (no need to normalize)");
      25       23786 :   params.addParam<Real>("rotation", 0.0, "Angle of rotation about the x-axis [degrees]");
      26       23786 :   params.addRequiredParam<std::vector<Real>>("length", "Length of each axial section [m]");
      27       23786 :   params.addRequiredParam<std::vector<unsigned int>>("n_elems",
      28             :                                                      "Number of elements in each axial section");
      29             : 
      30       11893 :   return params;
      31           0 : }
      32             : 
      33        5952 : DiscreteLineSegmentInterface::DiscreteLineSegmentInterface(const MooseObject * moose_object)
      34        5952 :   : _position(moose_object->parameters().get<Point>("position")),
      35        5952 :     _dir_unnormalized(moose_object->parameters().get<RealVectorValue>("orientation")),
      36        5952 :     _dir(initializeDirectionVector(_dir_unnormalized)),
      37        5952 :     _rotation(moose_object->parameters().get<Real>("rotation")),
      38        5952 :     _lengths(moose_object->parameters().get<std::vector<Real>>("length")),
      39        5952 :     _length(std::accumulate(_lengths.begin(), _lengths.end(), 0.0)),
      40        5952 :     _end_point(_position + _dir * _length),
      41        5952 :     _n_elems(moose_object->parameters().get<std::vector<unsigned int>>("n_elems")),
      42        5952 :     _n_elem(std::accumulate(_n_elems.begin(), _n_elems.end(), 0)),
      43        5952 :     _n_sections(_lengths.size()),
      44        5952 :     _section_end(_n_sections),
      45        5952 :     _x_centers(_n_elem),
      46        5952 :     _R(computeDirectionTransformationTensor(_dir)),
      47        5952 :     _Rx(computeXRotationTransformationTensor(_rotation)),
      48        5952 :     _R_inv(_R.inverse()),
      49        5952 :     _Rx_inv(_Rx.inverse()),
      50       11904 :     _moose_object_name_dlsi(moose_object->name())
      51             : {
      52        5952 :   std::partial_sum(_lengths.begin(), _lengths.end(), _section_end.begin());
      53             : 
      54        5952 :   if (_lengths.size() != _n_elems.size())
      55           2 :     mooseError("The parameters 'length' and 'n_elems' must have the same number of entries.");
      56             : 
      57             :   // Compute the axial coordinates of the centers of each element
      58             :   unsigned int k_section_begin = 0;
      59             :   Real x_begin = 0.0;
      60        5950 :   _dx_min = std::numeric_limits<Real>::max();
      61       12427 :   for (unsigned int j = 0; j < _n_sections; j++)
      62             :   {
      63        6477 :     const Real dx = _lengths[j] / _n_elems[j];
      64        6477 :     _dx_min = std::min(dx, _dx_min);
      65      148646 :     for (unsigned int i = 0; i < _n_elems[j]; i++)
      66             :     {
      67      142169 :       const unsigned int k = k_section_begin + i;
      68      142169 :       _x_centers[k] = x_begin + 0.5 * dx;
      69      142169 :       x_begin += dx;
      70             :     }
      71        6477 :     k_section_begin += _n_elems[j];
      72             :   }
      73        5950 : }
      74             : 
      75             : RealVectorValue
      76        5952 : DiscreteLineSegmentInterface::initializeDirectionVector(const RealVectorValue & dir_unnormalized)
      77             : {
      78        5952 :   if (!MooseUtils::absoluteFuzzyEqual(dir_unnormalized.norm(), 0.0))
      79        5952 :     return dir_unnormalized / dir_unnormalized.norm();
      80             :   else
      81           0 :     mooseError("The parameter 'orientation' must not be the zero vector.");
      82             : }
      83             : 
      84             : RealTensorValue
      85        6006 : DiscreteLineSegmentInterface::computeDirectionTransformationTensor(const RealVectorValue & dir)
      86             : {
      87        6006 :   if (MooseUtils::absoluteFuzzyEqual(dir.norm(), 0.0))
      88           0 :     mooseError("The direction vector must not be the zero vector.");
      89             : 
      90        6006 :   const auto dir_normalized = dir / dir.norm();
      91        6006 :   const Real theta = acos(dir_normalized(2));
      92        6006 :   const Real aphi = atan2(dir_normalized(1), dir_normalized(0));
      93             :   return RealTensorValue(
      94        6006 :       RealVectorValue(cos(aphi) * sin(theta), -sin(aphi), -cos(aphi) * cos(theta)),
      95        6006 :       RealVectorValue(sin(aphi) * sin(theta), cos(aphi), -sin(aphi) * cos(theta)),
      96        6006 :       RealVectorValue(cos(theta), 0.0, sin(theta)));
      97             : }
      98             : 
      99             : RealTensorValue
     100        6006 : DiscreteLineSegmentInterface::computeXRotationTransformationTensor(const Real & rotation)
     101             : {
     102        6006 :   const Real rotation_rad = M_PI * rotation / 180.;
     103             :   const RealVectorValue Rx_x(1., 0., 0.);
     104        6006 :   const RealVectorValue Rx_y(0., cos(rotation_rad), -sin(rotation_rad));
     105             :   const RealVectorValue Rx_z(0., sin(rotation_rad), cos(rotation_rad));
     106        6006 :   return RealTensorValue(Rx_x, Rx_y, Rx_z);
     107             : }
     108             : 
     109             : Real
     110        6086 : DiscreteLineSegmentInterface::computeAxialCoordinate(const Point & p) const
     111             : {
     112        6086 :   const Real ax_coord = _dir * (p - _position);
     113        6086 :   if (MooseUtils::absoluteFuzzyLessThan(ax_coord, 0.0) ||
     114             :       MooseUtils::absoluteFuzzyGreaterThan(ax_coord, _length))
     115           2 :     mooseError(_moose_object_name_dlsi,
     116             :                ": The point ",
     117             :                p,
     118             :                " has an invalid axial coordinate (",
     119             :                ax_coord,
     120             :                "). Valid axial coordinates are in the range (0,",
     121           2 :                _length,
     122             :                ").");
     123             :   else
     124        6084 :     return ax_coord;
     125             : }
     126             : 
     127             : Real
     128        1995 : DiscreteLineSegmentInterface::computeRadialCoordinate(const Point & p) const
     129             : {
     130        1995 :   const RealVectorValue v = (p - _position);
     131        1995 :   return v.cross(_dir).norm();
     132             : }
     133             : 
     134             : unsigned int
     135        1995 : DiscreteLineSegmentInterface::getAxialSectionIndex(const Point & p) const
     136             : {
     137        1995 :   const Real axial_coordinate = computeAxialCoordinate(p);
     138        4465 :   for (unsigned int i = 0; i < _n_sections; ++i)
     139        4465 :     if (MooseUtils::absoluteFuzzyLessEqual(axial_coordinate, _section_end[i]))
     140        1995 :       return i;
     141             : 
     142           0 :   mooseError("No axial section index was found.");
     143             : }
     144             : 
     145             : unsigned int
     146        1600 : DiscreteLineSegmentInterface::getAxialElementIndex(const Point & p_center) const
     147             : {
     148        1600 :   const Real axial_coordinate = computeAxialCoordinate(p_center);
     149       16800 :   for (unsigned int i = 0; i < _n_elem; ++i)
     150       16800 :     if (MooseUtils::absoluteFuzzyEqual(axial_coordinate, _x_centers[i]))
     151        1600 :       return i;
     152             : 
     153           0 :   mooseError("No axial element index was found.");
     154             : }
     155             : 
     156             : Point
     157      374437 : DiscreteLineSegmentInterface::computeRealPointFromReferencePoint(const Point & p,
     158             :                                                                  const RealVectorValue & position,
     159             :                                                                  const RealTensorValue & R,
     160             :                                                                  const RealTensorValue & Rx)
     161             : {
     162      374437 :   return R * (Rx * p) + position;
     163             : }
     164             : 
     165             : Point
     166      373843 : DiscreteLineSegmentInterface::computeRealPointFromReferencePoint(const Point & p) const
     167             : {
     168      373843 :   return computeRealPointFromReferencePoint(p, _position, _R, _Rx);
     169             : }
     170             : 
     171             : Point
     172           0 : DiscreteLineSegmentInterface::computeReferencePointFromRealPoint(const Point & p,
     173             :                                                                  const RealVectorValue & position,
     174             :                                                                  const RealTensorValue & R_inv,
     175             :                                                                  const RealTensorValue & Rx_inv)
     176             : {
     177           0 :   return Rx_inv * R_inv * (p - position);
     178             : }
     179             : 
     180             : Point
     181           0 : DiscreteLineSegmentInterface::computeReferencePointFromRealPoint(const Point & p) const
     182             : {
     183           0 :   return computeReferencePointFromRealPoint(p, _position, _R_inv, _Rx_inv);
     184             : }
     185             : 
     186             : MooseEnum
     187         272 : DiscreteLineSegmentInterface::getAlignmentAxis(const RealVectorValue & dir)
     188             : {
     189         544 :   MooseEnum axis("x y z");
     190         272 :   if (THM::areParallelVectors(dir, RealVectorValue(1, 0, 0)))
     191           0 :     axis = "x";
     192         272 :   else if (THM::areParallelVectors(dir, RealVectorValue(0, 1, 0)))
     193         540 :     axis = "y";
     194           2 :   else if (THM::areParallelVectors(dir, RealVectorValue(0, 0, 1)))
     195           0 :     axis = "z";
     196             : 
     197         272 :   return axis;
     198           0 : }
     199             : 
     200             : MooseEnum
     201           0 : DiscreteLineSegmentInterface::getAlignmentAxis() const
     202             : {
     203           0 :   return getAlignmentAxis(_dir);
     204             : }
     205             : 
     206             : std::vector<Real>
     207          54 : DiscreteLineSegmentInterface::getElementBoundaryCoordinates(
     208             :     const RealVectorValue & position,
     209             :     const RealVectorValue & orientation,
     210             :     const Real & rotation,
     211             :     const std::vector<Real> & lengths,
     212             :     const std::vector<unsigned int> & n_elems)
     213             : {
     214          54 :   const auto axis = getAlignmentAxis(orientation);
     215             : 
     216             :   unsigned int d;
     217          54 :   if (axis == "x")
     218             :     d = 0;
     219          54 :   else if (axis == "y")
     220             :     d = 1;
     221           0 :   else if (axis == "z")
     222             :     d = 2;
     223             :   else
     224           0 :     mooseError("Invalid axis.");
     225             : 
     226          54 :   const auto R = computeDirectionTransformationTensor(orientation);
     227          54 :   const auto Rx = computeXRotationTransformationTensor(rotation);
     228             : 
     229          54 :   const unsigned int n_elems_total = std::accumulate(n_elems.begin(), n_elems.end(), 0);
     230          54 :   const unsigned int n_sections = lengths.size();
     231             : 
     232             :   unsigned int i_section_start = 0;
     233             :   Real section_start_ref_position = 0.0;
     234          54 :   std::vector<Real> element_boundary_coordinates(n_elems_total + 1);
     235          54 :   element_boundary_coordinates[0] =
     236          54 :       computeRealPointFromReferencePoint(Point(0, 0, 0), position, R, Rx)(d);
     237         108 :   for (unsigned int j = 0; j < n_sections; ++j)
     238             :   {
     239          54 :     const Real section_dx = lengths[j] / n_elems[j];
     240         594 :     for (unsigned int k = 0; k < n_elems[j]; ++k)
     241             :     {
     242         540 :       const unsigned int i = i_section_start + k + 1;
     243         540 :       const Real ref_position = section_start_ref_position + section_dx * k;
     244             :       const Point ref_point = Point(ref_position, 0, 0);
     245         540 :       element_boundary_coordinates[i] =
     246         540 :           computeRealPointFromReferencePoint(ref_point, position, R, Rx)(d);
     247             :     }
     248             : 
     249          54 :     section_start_ref_position += lengths[j];
     250          54 :     i_section_start += n_elems[j];
     251             :   }
     252             : 
     253          54 :   return element_boundary_coordinates;
     254          54 : }
     255             : 
     256             : std::vector<Real>
     257           0 : DiscreteLineSegmentInterface::getElementBoundaryCoordinates() const
     258             : {
     259           0 :   return getElementBoundaryCoordinates(_position, _dir, _rotation, _lengths, _n_elems);
     260             : }

Generated by: LCOV version 1.14