LCOV - code coverage report
Current view: top level - src/functions - PiecewiseMultilinear.C (source / functions) Hit Total Coverage
Test: idaholab/moose framework: 2bf808 Lines: 37 54 68.5 %
Date: 2025-07-17 01:28:37 Functions: 5 11 45.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 "PiecewiseMultilinear.h"
      11             : #include "GriddedData.h"
      12             : 
      13             : registerMooseObject("MooseApp", PiecewiseMultilinear);
      14             : 
      15             : InputParameters
      16       14700 : PiecewiseMultilinear::validParams()
      17             : {
      18       14700 :   InputParameters params = PiecewiseMultiInterpolation::validParams();
      19       14700 :   params.addClassDescription(
      20             :       "PiecewiseMultilinear performs linear interpolation on 1D, 2D, 3D or 4D "
      21             :       "data.  The data_file specifies the axes directions and the function "
      22             :       "values.  If a point lies outside the data range, the appropriate end "
      23             :       "value is used.");
      24       44100 :   params.addParam<Real>(
      25       29400 :       "epsilon", 1e-12, "Finite differencing parameter for gradient and time derivative");
      26       14700 :   return params;
      27           0 : }
      28             : 
      29         243 : PiecewiseMultilinear::PiecewiseMultilinear(const InputParameters & parameters)
      30         243 :   : PiecewiseMultiInterpolation(parameters), _epsilon(getParam<Real>("epsilon"))
      31             : {
      32         208 : }
      33             : 
      34             : Real
      35     1200976 : PiecewiseMultilinear::sample(const GridPoint & pt) const
      36             : {
      37     1200976 :   return sampleInternal<false>(pt);
      38             : }
      39             : 
      40             : ADReal
      41           0 : PiecewiseMultilinear::sample(const ADGridPoint & pt) const
      42             : {
      43           0 :   return sampleInternal<true>(pt);
      44             : }
      45             : 
      46             : template <bool is_ad>
      47             : Moose::GenericType<Real, is_ad>
      48     1200976 : PiecewiseMultilinear::sampleInternal(const Moose::GenericType<GridPoint, is_ad> pt) const
      49             : {
      50             :   /*
      51             :    * left contains the indices of the point to the 'left', 'down', etc, of pt
      52             :    * right contains the indices of the point to the 'right', 'up', etc, of pt
      53             :    * Hence, left and right define the vertices of the hypercube containing pt
      54             :    */
      55     1200976 :   GridIndex left(_dim);
      56     1200976 :   GridIndex right(_dim);
      57     4797136 :   for (unsigned int i = 0; i < _dim; ++i)
      58     3596160 :     getNeighborIndices(_grid[i], MetaPhysicL::raw_value(pt[i]), left[i], right[i]);
      59             : 
      60             :   /*
      61             :    * The following just loops through all the vertices of the
      62             :    * hypercube containing pt, evaluating the function at all
      63             :    * those vertices, and weighting the contributions to the
      64             :    * final result depending on the distance of pt from the vertex
      65             :    */
      66     1200976 :   Moose::GenericType<Real, is_ad> f = 0;
      67           0 :   Moose::GenericType<Real, is_ad> weight;
      68     1200976 :   GridIndex arg(_dim);
      69             :   // number of points in hypercube = 2^_dim
      70    10809296 :   for (unsigned int i = 0; i < (1u << _dim); ++i)
      71             :   {
      72     9608320 :     weight = 1;
      73    38478656 :     for (unsigned int j = 0; j < _dim; ++j)
      74             :       // shift i j-bits to the right and see if the result has a 0 as its right-most bit
      75    28870336 :       if ((i >> j) % 2 == 0)
      76             :       {
      77    14435168 :         arg[j] = left[j];
      78    14435168 :         if (left[j] != right[j])
      79     7681920 :           weight *= std::abs(pt[j] - _grid[j][right[j]]);
      80             :         else
      81             :           // unusual "end condition" case. weight by 0.5 because we will encounter this twice
      82     6753248 :           weight *= 0.5;
      83             :       }
      84             :       else
      85             :       {
      86    14435168 :         arg[j] = right[j];
      87    14435168 :         if (left[j] != right[j])
      88     7681920 :           weight *= std::abs(pt[j] - _grid[j][left[j]]);
      89             :         else
      90             :           // unusual "end condition" case. weight by 0.5 because we will encounter this twice
      91     6753248 :           weight *= 0.5;
      92             :       }
      93     9608320 :     f += _gridded_data->evaluateFcn(arg) * weight;
      94             :   }
      95             : 
      96             :   /*
      97             :    * finally divide by the volume of the hypercube
      98             :    */
      99     1200976 :   weight = 1;
     100     4797136 :   for (unsigned int dim = 0; dim < pt.size(); ++dim)
     101     3596160 :     if (left[dim] != right[dim])
     102     1916912 :       weight *= _grid[dim][right[dim]] - _grid[dim][left[dim]];
     103             :     else
     104             :       // unusual "end condition" case. weight by 1 to cancel the two 0.5 encountered previously
     105     1679248 :       weight *= 1;
     106             : 
     107     1200976 :   return f / weight;
     108           0 : }
     109             : 
     110             : RealGradient
     111           0 : PiecewiseMultilinear::gradient(Real t, const Point & p) const
     112             : {
     113           0 :   RealGradient grad;
     114             : 
     115             :   // sample center point
     116           0 :   auto s1 = sample(pointInGrid<false>(t, p));
     117             : 
     118             :   // sample epsilon steps in all directions
     119           0 :   for (const auto dir : _axes)
     120           0 :     if (dir < 3)
     121             :     {
     122           0 :       Point pp = p;
     123           0 :       pp(dir) += _epsilon;
     124           0 :       grad(dir) = (sample(pointInGrid<false>(t, pp)) - s1) / _epsilon;
     125             :     }
     126             : 
     127           0 :   return grad;
     128             : }
     129             : 
     130             : Real
     131           0 : PiecewiseMultilinear::timeDerivative(Real t, const Point & p) const
     132             : {
     133           0 :   return (sample(pointInGrid<false>(t + _epsilon, p)) - sample(pointInGrid<false>(t, p))) /
     134           0 :          _epsilon;
     135             : }

Generated by: LCOV version 1.14