LCOV - code coverage report
Current view: top level - include/interfaces - SlopeReconstruction1DInterface.h (source / functions) Hit Total Coverage
Test: idaholab/moose thermal_hydraulics: #31653 (2d163b) with base 0cc44f Lines: 81 85 95.3 %
Date: 2025-11-04 20:43:51 Functions: 6 11 54.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             : #pragma once
      11             : 
      12             : #include "MooseObject.h"
      13             : #include "MooseEnum.h"
      14             : #include "MooseTypes.h"
      15             : #include "InputParameters.h"
      16             : #include "THMEnums.h"
      17             : 
      18             : #include "libmesh/elem.h"
      19             : #include "libmesh/vector_value.h"
      20             : #include "libmesh/point.h"
      21             : 
      22             : /**
      23             :  * Interface class for 1-D slope reconstruction
      24             :  *
      25             :  * This class provides interfaces for generating slopes for an arbitrary set
      26             :  * of variables. A number of reconstruction options are provided, including a
      27             :  * number of TVD slope limiters.
      28             :  */
      29             : template <bool is_ad>
      30             : class SlopeReconstruction1DInterface
      31             : {
      32             : public:
      33             :   SlopeReconstruction1DInterface(const MooseObject * moose_object);
      34             : 
      35             :   /// Slope reconstruction type
      36             :   enum ESlopeReconstructionType
      37             :   {
      38             :     None,    ///< No reconstruction; Godunov scheme
      39             :     Full,    ///< Full reconstruction; no limitation
      40             :     Minmod,  ///< Minmod slope limiter
      41             :     MC,      ///< Monotonized Central-Difference slope limiter
      42             :     Superbee ///< Superbee slope limiter
      43             :   };
      44             :   /// Map of slope reconstruction type string to enum
      45             :   static const std::map<std::string, ESlopeReconstructionType> _slope_reconstruction_type_to_enum;
      46             : 
      47             :   /**
      48             :    * Gets a MooseEnum for slope reconstruction type
      49             :    *
      50             :    * @param[in] name   default value
      51             :    * @returns MooseEnum for slope reconstruction type
      52             :    */
      53             :   static MooseEnum getSlopeReconstructionMooseEnum(const std::string & name = "");
      54             : 
      55             : protected:
      56             :   /**
      57             :    * Gets the primitive solution vector and position of neighbor(s)
      58             :    *
      59             :    * @param[in] elem   Element for which to get slopes
      60             :    * @param[in] W_neighbor   Primitive solution vector for each neighbor
      61             :    * @param[in] x_neighbor   Position for each neighbor
      62             :    */
      63             :   virtual void
      64             :   getNeighborPrimitiveVariables(const Elem * elem,
      65             :                                 std::vector<std::vector<GenericReal<is_ad>>> & W_neighbor,
      66             :                                 std::vector<Point> & x_neighbor) const;
      67             : 
      68             :   /**
      69             :    * Gets limited slopes for the primitive variables in the 1-D direction
      70             :    *
      71             :    * @param[in] elem   Element for which to get slopes
      72             :    *
      73             :    * @returns Vector of slopes for the element in the 1-D direction
      74             :    */
      75             :   std::vector<GenericReal<is_ad>> getElementSlopes(const Elem * elem) const;
      76             : 
      77             :   /**
      78             :    * Gets limited slopes for the primitive variables in the 1-D direction for boundary element
      79             :    *
      80             :    * @param[in] W_elem       Primitive solution for element
      81             :    * @param[in] x_elem       Position for element
      82             :    * @param[in] dir          Direction for element
      83             :    * @param[in] W_neighbor   Primitive solution vector for each neighbor
      84             :    * @param[in] x_neighbor   Position for each neighbor
      85             :    * @param[in] W_boundary   Primitive solution vector for boundary
      86             :    *
      87             :    * @returns Vector of slopes for the element in the 1-D direction
      88             :    */
      89             :   std::vector<GenericReal<is_ad>>
      90             :   getBoundaryElementSlopes(const std::vector<GenericReal<is_ad>> & W_elem,
      91             :                            const Point & x_elem,
      92             :                            const RealVectorValue & dir,
      93             :                            std::vector<std::vector<GenericReal<is_ad>>> W_neighbor,
      94             :                            std::vector<Point> x_neighbor,
      95             :                            const std::vector<GenericReal<is_ad>> & W_boundary) const;
      96             : 
      97             :   /**
      98             :    * Gets limited slopes for the primitive variables in the 1-D direction
      99             :    *
     100             :    * @param[in] W_elem       Primitive solution for element
     101             :    * @param[in] x_elem       Position for element
     102             :    * @param[in] dir          Direction for element
     103             :    * @param[in] W_neighbor   Primitive solution vector for each neighbor
     104             :    * @param[in] x_neighbor   Position for each neighbor
     105             :    *
     106             :    * @returns Vector of slopes for the element in the 1-D direction
     107             :    */
     108             :   std::vector<GenericReal<is_ad>>
     109             :   getElementSlopes(const std::vector<GenericReal<is_ad>> & W_elem,
     110             :                    const Point & x_elem,
     111             :                    const RealVectorValue & dir,
     112             :                    const std::vector<std::vector<GenericReal<is_ad>>> & W_neighbor,
     113             :                    const std::vector<Point> & x_neighbor) const;
     114             : 
     115             :   /**
     116             :    * Computes the cell-average primitive variable values for an element
     117             :    *
     118             :    * @param[in] elem   Element for which to get values
     119             :    *
     120             :    * @returns Vector of values on element
     121             :    */
     122             :   virtual std::vector<GenericReal<is_ad>>
     123             :   computeElementPrimitiveVariables(const Elem * elem) const = 0;
     124             : 
     125             :   /// MooseObject this interface is extending
     126             :   const MooseObject * const _moose_object;
     127             : 
     128             :   /// Slope reconstruction scheme
     129             :   const ESlopeReconstructionType _scheme;
     130             : 
     131             : public:
     132             :   static InputParameters validParams();
     133             : 
     134             : protected:
     135             :   /// Number of sides
     136             :   static const unsigned int _n_side;
     137             :   /// Number of elemental values in stencil for computing slopes
     138             :   static const unsigned int _n_sten;
     139             : };
     140             : 
     141             : namespace THM
     142             : {
     143             : template <>
     144             : SlopeReconstruction1DInterface<true>::ESlopeReconstructionType
     145             : stringToEnum<SlopeReconstruction1DInterface<true>::ESlopeReconstructionType>(const std::string & s);
     146             : 
     147             : template <>
     148             : SlopeReconstruction1DInterface<false>::ESlopeReconstructionType
     149             : stringToEnum<SlopeReconstruction1DInterface<false>::ESlopeReconstructionType>(
     150             :     const std::string & s);
     151             : }
     152             : 
     153             : template <bool is_ad>
     154             : const std::map<std::string,
     155             :                typename SlopeReconstruction1DInterface<is_ad>::ESlopeReconstructionType>
     156             :     SlopeReconstruction1DInterface<is_ad>::_slope_reconstruction_type_to_enum{
     157             :         {"NONE", None}, {"FULL", Full}, {"MINMOD", Minmod}, {"MC", MC}, {"SUPERBEE", Superbee}};
     158             : 
     159             : template <bool is_ad>
     160             : MooseEnum
     161             : SlopeReconstruction1DInterface<is_ad>::getSlopeReconstructionMooseEnum(const std::string & name)
     162             : {
     163             :   return THM::getMooseEnum<SlopeReconstruction1DInterface<is_ad>::ESlopeReconstructionType>(
     164       28194 :       name, _slope_reconstruction_type_to_enum);
     165             : }
     166             : 
     167             : template <bool is_ad>
     168             : const unsigned int SlopeReconstruction1DInterface<is_ad>::_n_side = 2;
     169             : 
     170             : template <bool is_ad>
     171             : const unsigned int SlopeReconstruction1DInterface<is_ad>::_n_sten = 3;
     172             : 
     173             : template <bool is_ad>
     174             : InputParameters
     175       19453 : SlopeReconstruction1DInterface<is_ad>::validParams()
     176             : {
     177       19453 :   InputParameters params = emptyInputParameters();
     178             : 
     179       77812 :   params.addRequiredParam<MooseEnum>(
     180             :       "scheme",
     181             :       SlopeReconstruction1DInterface::getSlopeReconstructionMooseEnum("None"),
     182             :       "Slope reconstruction scheme");
     183             : 
     184       19453 :   return params;
     185           0 : }
     186             : 
     187             : template <bool is_ad>
     188       15044 : SlopeReconstruction1DInterface<is_ad>::SlopeReconstruction1DInterface(
     189             :     const MooseObject * moose_object)
     190       15044 :   : _moose_object(moose_object),
     191       15044 :     _scheme(THM::stringToEnum<ESlopeReconstructionType>(
     192       15044 :         moose_object->parameters().get<MooseEnum>("scheme")))
     193             : {
     194       15044 : }
     195             : 
     196             : template <bool is_ad>
     197             : void
     198     4709918 : SlopeReconstruction1DInterface<is_ad>::getNeighborPrimitiveVariables(
     199             :     const Elem * elem,
     200             :     std::vector<std::vector<GenericReal<is_ad>>> & W_neighbor,
     201             :     std::vector<Point> & x_neighbor) const
     202             : {
     203     4709918 :   W_neighbor.clear();
     204     4709918 :   x_neighbor.clear();
     205    14129754 :   for (unsigned int i_side = 0; i_side < _n_side; i_side++)
     206             :   {
     207             :     auto neighbor = elem->neighbor_ptr(i_side);
     208     9419836 :     if (neighbor && (neighbor->processor_id() == _moose_object->processor_id()))
     209             :     {
     210     8935490 :       x_neighbor.push_back(neighbor->vertex_average());
     211    17870980 :       W_neighbor.push_back(computeElementPrimitiveVariables(neighbor));
     212             :     }
     213             :   }
     214     4709918 : }
     215             : 
     216             : template <bool is_ad>
     217             : std::vector<GenericReal<is_ad>>
     218     4653824 : SlopeReconstruction1DInterface<is_ad>::getElementSlopes(const Elem * elem) const
     219             : {
     220             :   mooseAssert(elem, "The supplied element is a nullptr.");
     221             : 
     222     4653824 :   const auto W_elem = computeElementPrimitiveVariables(elem);
     223     4653824 :   const Point x_elem = elem->vertex_average();
     224     4653824 :   const RealVectorValue dir = (elem->node_ref(1) - elem->node_ref(0)).unit();
     225             : 
     226             :   std::vector<Point> x_neighbor;
     227             :   std::vector<std::vector<GenericReal<is_ad>>> W_neighbor;
     228     4653824 :   getNeighborPrimitiveVariables(elem, W_neighbor, x_neighbor);
     229             : 
     230     9307648 :   return getElementSlopes(W_elem, x_elem, dir, W_neighbor, x_neighbor);
     231     4653824 : }
     232             : 
     233             : template <bool is_ad>
     234             : std::vector<GenericReal<is_ad>>
     235       65038 : SlopeReconstruction1DInterface<is_ad>::getBoundaryElementSlopes(
     236             :     const std::vector<GenericReal<is_ad>> & W_elem,
     237             :     const Point & x_elem,
     238             :     const RealVectorValue & dir,
     239             :     std::vector<std::vector<GenericReal<is_ad>>> W_neighbor,
     240             :     std::vector<Point> x_neighbor,
     241             :     const std::vector<GenericReal<is_ad>> & W_boundary) const
     242             : {
     243       65038 :   if (W_neighbor.size() == 1)
     244             :   {
     245       64974 :     W_neighbor.push_back(W_boundary);
     246             : 
     247             :     // The boundary point will be assumed to be the same distance away as neighbor
     248             :     const Point dx = x_elem - x_neighbor[0];
     249             :     const Point x_boundary = x_elem + dx;
     250       64974 :     x_neighbor.push_back(x_boundary);
     251             :   }
     252             : 
     253       65038 :   return getElementSlopes(W_elem, x_elem, dir, W_neighbor, x_neighbor);
     254             : }
     255             : 
     256             : template <bool is_ad>
     257             : std::vector<GenericReal<is_ad>>
     258     4718862 : SlopeReconstruction1DInterface<is_ad>::getElementSlopes(
     259             :     const std::vector<GenericReal<is_ad>> & W_elem,
     260             :     const Point & x_elem,
     261             :     const RealVectorValue & dir,
     262             :     const std::vector<std::vector<GenericReal<is_ad>>> & W_neighbor,
     263             :     const std::vector<Point> & x_neighbor) const
     264             : {
     265             :   mooseAssert(x_neighbor.size() == W_neighbor.size(),
     266             :               "Neighbor positions size must equal neighbor solutions size.");
     267             : 
     268             :   using std::abs, std::min, std::max;
     269             : 
     270             :   // get the number of slopes to be stored
     271     4718862 :   const unsigned int n_slopes = W_elem.size();
     272             : 
     273             :   // compute one-sided slope(s)
     274             :   std::vector<std::vector<GenericReal<is_ad>>> slopes_one_sided;
     275    13728246 :   for (unsigned int i = 0; i < W_neighbor.size(); i++)
     276             :   {
     277     9009384 :     const Real dx = (x_elem - x_neighbor[i]) * dir;
     278             : 
     279     9009384 :     std::vector<GenericReal<is_ad>> slopes(n_slopes, 0.0);
     280    36037536 :     for (unsigned int m = 0; m < n_slopes; m++)
     281    54056304 :       slopes[m] = (W_elem[m] - W_neighbor[i][m]) / dx;
     282             : 
     283     9009384 :     slopes_one_sided.push_back(slopes);
     284             :   }
     285             : 
     286             :   // Fill in any missing one-sided slopes and compute central slope
     287     4718862 :   std::vector<GenericReal<is_ad>> slopes_central(n_slopes, 0.0);
     288     4718862 :   if (W_neighbor.size() == 2)
     289             :   {
     290     4290586 :     const Real dx = (x_neighbor[0] - x_neighbor[1]) * dir;
     291    17162344 :     for (unsigned int m = 0; m < n_slopes; m++)
     292    25743516 :       slopes_central[m] = (W_neighbor[0][m] - W_neighbor[1][m]) / dx;
     293             :   }
     294      428276 :   else if (W_neighbor.size() == 1)
     295             :   {
     296      428212 :     slopes_one_sided.push_back(slopes_one_sided[0]);
     297      428212 :     slopes_central = slopes_one_sided[0];
     298             :   }
     299             :   else // only one element; use zero slopes
     300             :   {
     301          64 :     slopes_one_sided.push_back(slopes_central);
     302          64 :     slopes_one_sided.push_back(slopes_central);
     303             :   }
     304             : 
     305             :   // vector for the (possibly limited) slopes
     306     4718862 :   std::vector<GenericReal<is_ad>> slopes_limited(n_slopes, 0.0);
     307             : 
     308             :   // limit the slopes
     309     4718862 :   switch (_scheme)
     310             :   {
     311             :     // first-order, zero slope
     312             :     case None:
     313             :       break;
     314             : 
     315             :     // full reconstruction; no limitation
     316        1030 :     case Full:
     317             : 
     318        1030 :       slopes_limited = slopes_central;
     319             :       break;
     320             : 
     321             :     // minmod limiter
     322             :     case Minmod:
     323             : 
     324    17155736 :       for (unsigned int m = 0; m < n_slopes; m++)
     325             :       {
     326    25733604 :         if ((slopes_one_sided[0][m] * slopes_one_sided[1][m]) > 0.0)
     327             :         {
     328    10749859 :           if (abs(slopes_one_sided[0][m]) < abs(slopes_one_sided[1][m]))
     329     4366878 :             slopes_limited[m] = slopes_one_sided[0][m];
     330             :           else
     331     6382981 :             slopes_limited[m] = slopes_one_sided[1][m];
     332             :         }
     333             :       }
     334             :       break;
     335             : 
     336             :     // MC (monotonized central-difference) limiter
     337             :     case MC:
     338             : 
     339      780800 :       for (unsigned int m = 0; m < n_slopes; m++)
     340             :       {
     341      585600 :         if (slopes_central[m] > 0.0 && slopes_one_sided[0][m] > 0.0 && slopes_one_sided[1][m] > 0.0)
     342        3856 :           slopes_limited[m] =
     343        3856 :               min(slopes_central[m], 2.0 * min(slopes_one_sided[0][m], slopes_one_sided[1][m]));
     344      583672 :         else if (slopes_central[m] < 0.0 && slopes_one_sided[0][m] < 0.0 &&
     345           0 :                  slopes_one_sided[1][m] < 0.0)
     346        3408 :           slopes_limited[m] =
     347        3408 :               max(slopes_central[m], 2.0 * max(slopes_one_sided[0][m], slopes_one_sided[1][m]));
     348             :       }
     349             :       break;
     350             : 
     351             :     // superbee limiter
     352             :     case Superbee:
     353             : 
     354      780800 :       for (unsigned int m = 0; m < n_slopes; m++)
     355             :       {
     356      585600 :         GenericReal<is_ad> slope1 = 0.0;
     357      585600 :         GenericReal<is_ad> slope2 = 0.0;
     358             : 
     359             :         // calculate slope1 with minmod
     360      585600 :         if (slopes_one_sided[1][m] > 0.0 && slopes_one_sided[0][m] > 0.0)
     361        2992 :           slope1 = min(slopes_one_sided[1][m], 2.0 * slopes_one_sided[0][m]);
     362      584104 :         else if (slopes_one_sided[1][m] < 0.0 && slopes_one_sided[0][m] < 0.0)
     363        3776 :           slope1 = max(slopes_one_sided[1][m], 2.0 * slopes_one_sided[0][m]);
     364             : 
     365             :         // calculate slope2 with minmod
     366      585600 :         if (slopes_one_sided[1][m] > 0.0 && slopes_one_sided[0][m] > 0.0)
     367        2992 :           slope2 = min(2.0 * slopes_one_sided[1][m], slopes_one_sided[0][m]);
     368      584104 :         else if (slopes_one_sided[1][m] < 0.0 && slopes_one_sided[0][m] < 0.0)
     369        3776 :           slope2 = max(2.0 * slopes_one_sided[1][m], slopes_one_sided[0][m]);
     370             : 
     371             :         // calculate slope with maxmod
     372      585600 :         if (slope1 > 0.0 && slope2 > 0.0)
     373        1496 :           slopes_limited[m] = max(slope1, slope2);
     374      584104 :         else if (slope1 < 0.0 && slope2 < 0.0)
     375        1888 :           slopes_limited[m] = min(slope1, slope2);
     376             :       }
     377             :       break;
     378             : 
     379           0 :     default:
     380           0 :       mooseError("Unknown slope reconstruction scheme");
     381             :       break;
     382             :   }
     383     4718862 :   return slopes_limited;
     384     4718862 : }

Generated by: LCOV version 1.14