LCOV - code coverage report
Current view: top level - src/postprocessors - FindValueOnLine.C (source / functions) Hit Total Coverage
Test: idaholab/moose framework: 2bf808 Lines: 85 87 97.7 %
Date: 2025-07-17 01:28:37 Functions: 9 9 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 "FindValueOnLine.h"
      11             : 
      12             : // MOOSE includes
      13             : #include "MooseMesh.h"
      14             : #include "MooseUtils.h"
      15             : #include "MooseVariable.h"
      16             : 
      17             : registerMooseObject("MooseApp", FindValueOnLine);
      18             : 
      19             : InputParameters
      20       14417 : FindValueOnLine::validParams()
      21             : {
      22       14417 :   InputParameters params = GeneralPostprocessor::validParams();
      23       14417 :   params.addClassDescription("Find a specific target value along a sampling line. The variable "
      24             :                              "values along the line should change monotonically. The target value "
      25             :                              "is searched using a bisection algorithm.");
      26       14417 :   params.addParam<Point>("start_point", "Start point of the sampling line.");
      27       14417 :   params.addParam<Point>("end_point", "End point of the sampling line.");
      28       14417 :   params.addParam<Real>("target", "Target value to locate.");
      29       43251 :   params.addParam<bool>(
      30             :       "error_if_not_found",
      31       28834 :       true,
      32             :       "If true, stop with error if target value is not found on the line. If false, "
      33             :       "return default_value.");
      34       43251 :   params.addParam<Real>("default_value",
      35       28834 :                         -1,
      36             :                         "Value to return if target value is not found on line and "
      37             :                         "error_if_not_found is false.");
      38       14417 :   params.addParam<unsigned int>("depth", 36, "Maximum number of bisections to perform.");
      39       43251 :   params.addParam<Real>(
      40             :       "tol",
      41       28834 :       1e-10,
      42             :       "Stop search if a value is found that is equal to the target with this tolerance applied.");
      43       14417 :   params.addCoupledVar("v", "Variable to inspect");
      44       14417 :   return params;
      45           0 : }
      46             : 
      47          76 : FindValueOnLine::FindValueOnLine(const InputParameters & parameters)
      48             :   : GeneralPostprocessor(parameters),
      49             :     Coupleable(this, false),
      50          76 :     _start_point(getParam<Point>("start_point")),
      51          76 :     _end_point(getParam<Point>("end_point")),
      52          76 :     _length((_end_point - _start_point).norm()),
      53          76 :     _target(getParam<Real>("target")),
      54          76 :     _error_if_not_found(getParam<bool>("error_if_not_found")),
      55          76 :     _default_value(getParam<Real>("default_value")),
      56          76 :     _depth(getParam<unsigned int>("depth")),
      57          76 :     _tol(getParam<Real>("tol")),
      58          76 :     _coupled_var(*getVar("v", 0)),
      59          76 :     _position(0.0),
      60          76 :     _mesh(_subproblem.mesh()),
      61         152 :     _point_vec(1)
      62             : {
      63          76 : }
      64             : 
      65             : void
      66         346 : FindValueOnLine::initialize()
      67             : {
      68             :   // We do this here just in case it's been destroyed and recreated becaue of mesh adaptivity.
      69         346 :   _pl = _mesh.getPointLocator();
      70         346 :   _pl->enable_out_of_mesh_mode();
      71         346 : }
      72             : 
      73             : void
      74         346 : FindValueOnLine::execute()
      75             : {
      76             :   Real s;
      77         346 :   Real s_left = 0.0;
      78         346 :   Real left = getValueAtPoint(_start_point);
      79         346 :   Real s_right = 1.0;
      80         346 :   Real right = getValueAtPoint(_end_point);
      81             : 
      82             :   // Helper for erroring; won't error if error_if_not_found=false
      83         332 :   const auto error = [this](auto &&... message)
      84             :   {
      85         166 :     if (_error_if_not_found)
      86          12 :       mooseError(std::scientific, std::setprecision(4), message...);
      87         154 :     _position = _default_value;
      88         496 :   };
      89             : 
      90             :   /**
      91             :    * Here we determine the direction of the solution. i.e. the left might be the high value
      92             :    * while the right might be the low value.
      93             :    */
      94         342 :   bool left_to_right = left < right;
      95             :   // Initial bounds check
      96         342 :   if ((left_to_right && _target < left) || (!left_to_right && _target < right))
      97             :   {
      98         136 :     error("Target value ",
      99         136 :           _target,
     100             :           " is less than the minimum sampled value ",
     101             :           std::min(left, right));
     102         154 :     return;
     103             :   }
     104         206 :   if ((left_to_right && _target > right) || (!left_to_right && _target > left))
     105             :   {
     106          26 :     error("Target value ",
     107          26 :           _target,
     108             :           " is greater than the maximum sampled value ",
     109             :           std::max(left, right));
     110          22 :     return;
     111             :   }
     112             : 
     113         180 :   bool found_it = false;
     114         180 :   Real value = 0;
     115        5982 :   for (unsigned int i = 0; i < _depth; ++i)
     116             :   {
     117             :     // find midpoint
     118        5978 :     s = (s_left + s_right) / 2.0;
     119        5978 :     Point p = s * (_end_point - _start_point) + _start_point;
     120             : 
     121             :     // sample value
     122        5978 :     value = getValueAtPoint(p);
     123             : 
     124             :     // have we hit the target value yet?
     125        5978 :     if (MooseUtils::absoluteFuzzyEqual(value, _target, _tol))
     126             :     {
     127         176 :       found_it = true;
     128         176 :       break;
     129             :     }
     130             : 
     131             :     // bisect
     132        5802 :     if ((left_to_right && _target < value) || (!left_to_right && _target > value))
     133             :       // to the left
     134        2707 :       s_right = s;
     135             :     else
     136             :       // to the right
     137        3095 :       s_left = s;
     138             :   }
     139             : 
     140             :   // Return error if target value (within tol) was not found within depth bisections
     141         180 :   if (!found_it)
     142             :   {
     143           4 :     error("Target value ",
     144           4 :           _target,
     145             :           " not found on line within tolerance.\nLast sample: ",
     146             :           value,
     147             :           ", difference from target: ",
     148           4 :           std::abs(_target - value));
     149           0 :     return;
     150             :   }
     151             : 
     152         176 :   _position = s * _length;
     153             : }
     154             : 
     155             : Real
     156        6670 : FindValueOnLine::getValueAtPoint(const Point & p)
     157             : {
     158        6670 :   const Elem * elem = (*_pl)(p);
     159             : 
     160             :   processor_id_type elem_proc_id =
     161        6670 :       elem ? elem->processor_id() : libMesh::DofObject::invalid_processor_id;
     162        6670 :   _communicator.min(elem_proc_id);
     163             : 
     164        6670 :   if (elem_proc_id == libMesh::DofObject::invalid_processor_id)
     165             :   {
     166             :     // there is no element
     167           4 :     mooseError("No element found at the current search point. Please make sure the sampling line "
     168             :                "stays inside the mesh completely.");
     169             :   }
     170             : 
     171        6666 :   Real value = 0;
     172             : 
     173        6666 :   if (elem)
     174             :   {
     175        6115 :     if (elem->processor_id() == processor_id())
     176             :     {
     177             :       // element is local
     178        4872 :       _point_vec[0] = p;
     179        4872 :       _subproblem.reinitElemPhys(elem, _point_vec, 0);
     180        4872 :       value = _coupled_var.sln()[0];
     181             :     }
     182             :   }
     183             : 
     184             :   // broadcast value
     185        6666 :   _communicator.broadcast(value, elem_proc_id);
     186        6666 :   return value;
     187             : }
     188             : 
     189             : PostprocessorValue
     190         330 : FindValueOnLine::getValue() const
     191             : {
     192         330 :   return _position;
     193             : }

Generated by: LCOV version 1.14