LCOV - code coverage report
Current view: top level - src/userobjects - PINSFVRhieChowInterpolator.C (source / functions) Hit Total Coverage
Test: idaholab/moose navier_stokes: 9fc4b0 Lines: 76 85 89.4 %
Date: 2025-08-14 10:14:56 Functions: 8 9 88.9 %
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 "PINSFVRhieChowInterpolator.h"
      11             : #include "Reconstructions.h"
      12             : #include "NS.h"
      13             : #include "Assembly.h"
      14             : #include "BernoulliPressureVariable.h"
      15             : 
      16             : registerMooseObject("NavierStokesApp", PINSFVRhieChowInterpolator);
      17             : 
      18             : InputParameters
      19        5890 : PINSFVRhieChowInterpolator::validParams()
      20             : {
      21        5890 :   auto params = INSFVRhieChowInterpolator::validParams();
      22        5890 :   params.addClassDescription("Performs interpolations and reconstructions of porosity and computes "
      23             :                              "the Rhie-Chow face velocities.");
      24        5890 :   ExecFlagEnum & exec_enum = params.set<ExecFlagEnum>("execute_on", /*quiet=*/true);
      25        5890 :   exec_enum.setAdditionalValue(EXEC_INITIAL);
      26        5890 :   params.addRequiredParam<MooseFunctorName>(NS::porosity, "The porosity");
      27       17670 :   params.addParam<unsigned short>(
      28             :       "smoothing_layers",
      29       11780 :       0,
      30             :       "The number of interpolation-reconstruction operations to perform on the porosity");
      31       11780 :   params.addRelationshipManager("ElementSideNeighborLayers",
      32             :                                 Moose::RelationshipManagerType::GEOMETRIC,
      33        6311 :                                 [](const InputParameters & obj_params, InputParameters & rm_params)
      34             :                                 {
      35        6311 :                                   rm_params.set<unsigned short>("layers") =
      36       12622 :                                       obj_params.get<unsigned short>("smoothing_layers");
      37        6311 :                                   rm_params.set<bool>("use_displaced_mesh") =
      38        6311 :                                       obj_params.get<bool>("use_displaced_mesh");
      39        6311 :                                 });
      40        5890 :   return params;
      41           0 : }
      42             : 
      43        2946 : PINSFVRhieChowInterpolator::PINSFVRhieChowInterpolator(const InputParameters & params)
      44             :   : INSFVRhieChowInterpolator(params),
      45        5892 :     _eps(getFunctor<ADReal>(NS::porosity)),
      46        2946 :     _smoothed_eps(_moose_mesh, NS::smoothed_porosity, /*extrapolated_boundary*/ true),
      47        2946 :     _epss(libMesh::n_threads(), nullptr),
      48        2946 :     _smoothed_epss(libMesh::n_threads(), nullptr),
      49        8838 :     _smoothing_layers(getParam<unsigned short>("smoothing_layers"))
      50             : {
      51        2946 :   if (_smoothing_layers && _eps.wrapsType<MooseVariableBase>())
      52           2 :     paramError(
      53             :         NS::porosity,
      54             :         "If we are reconstructing porosity, then the input porosity to this user object cannot "
      55             :         "be a Moose variable. There are issues with reconstructing Moose variables: 1) initial "
      56             :         "conditions are run after user objects initial setup 2) reconstructing from a variable "
      57             :         "requires ghosting the solution vectors 3) it's difficult to restrict the face "
      58             :         "informations we evaluate interpolations and reconstructions on such that we never query "
      59             :         "an algebraically remote element due to things like two-term extrapolated boundary faces "
      60             :         "which trigger gradient evaluations which trigger neighbor element evaluation");
      61             : 
      62        2944 :   const auto porosity_name = deduceFunctorName(NS::porosity);
      63             : 
      64        6133 :   for (const auto tid : make_range(libMesh::n_threads()))
      65             :   {
      66        3189 :     _epss[tid] = &UserObject::_subproblem.getFunctor<ADReal>(porosity_name, tid, name(), true);
      67             : 
      68        3189 :     if (_smoothing_layers > 0)
      69             :     {
      70         593 :       if (!UserObject::_subproblem.hasFunctor(NS::smoothed_porosity, tid))
      71             :         // Smoothed porosity is only an envelope at this point, it will be set during pinsfvSetup()
      72         593 :         UserObject::_subproblem.addFunctor(NS::smoothed_porosity, _smoothed_eps, tid);
      73             : 
      74         593 :       _smoothed_epss[tid] =
      75         593 :           &UserObject::_subproblem.getFunctor<ADReal>(NS::smoothed_porosity, tid, name(), true);
      76             :     }
      77             :   }
      78        2944 : }
      79             : 
      80             : void
      81           0 : PINSFVRhieChowInterpolator::meshChanged()
      82             : {
      83           0 :   INSFVRhieChowInterpolator::meshChanged();
      84           0 :   pinsfvSetup();
      85           0 : }
      86             : 
      87             : void
      88        2566 : PINSFVRhieChowInterpolator::pinsfvSetup()
      89             : {
      90        2566 :   if (!_smoothing_layers)
      91             :     return;
      92             : 
      93         582 :   if (dynamic_cast<BernoulliPressureVariable *>(_p))
      94           0 :     paramError(
      95             :         NS::pressure,
      96             :         "If 'smoothing_layers' is non-zero, e.g. if the porosity is smooth(ed), "
      97             :         "then the pressure drop should be computed automatically. The "
      98             :         "'BernoulliPressureVariable' class enforces a pressure drop according to the Bernoulli "
      99             :         "equation on any face which has different pressure values on either side. This is "
     100             :         "undesirable when the porosity is varying smoothing and there may be pressure drops "
     101             :         "corresponding to viscous effects. Please just use the 'INSFVPressureVariable' "
     102             :         "class for pressure when the porosity is smooth.");
     103             : 
     104         582 :   const auto & all_fi = _moose_mesh.allFaceInfo();
     105         582 :   _geometric_fi.reserve(all_fi.size());
     106             : 
     107     3568618 :   for (const auto & fi : all_fi)
     108     3568036 :     if (isFaceGeometricallyRelevant(fi))
     109     3567904 :       _geometric_fi.push_back(&fi);
     110             : 
     111             :   _geometric_fi.shrink_to_fit();
     112             : 
     113         582 :   const auto saved_do_derivatives = ADReal::do_derivatives;
     114         582 :   ADReal::do_derivatives = true;
     115         582 :   Moose::FV::interpolateReconstruct(
     116         582 :       _smoothed_eps, _eps, _smoothing_layers, false, _geometric_fi, determineState());
     117         582 :   ADReal::do_derivatives = saved_do_derivatives;
     118             : 
     119             :   // Assign the new functor to all
     120         588 :   for (const auto tid : make_range((unsigned int)(1), libMesh::n_threads()))
     121             :   {
     122             :     auto & other_smoothed_epss = const_cast<Moose::Functor<ADReal> &>(
     123           6 :         UserObject::_subproblem.getFunctor<ADReal>(NS::smoothed_porosity, tid, name(), true));
     124           6 :     other_smoothed_epss.assign(_smoothed_eps);
     125             :   }
     126             : }
     127             : 
     128             : bool
     129     3568036 : PINSFVRhieChowInterpolator::isFaceGeometricallyRelevant(const FaceInfo & fi) const
     130             : {
     131     3568036 :   if (&fi.elem() == libMesh::remote_elem)
     132             :     return false;
     133             : 
     134     7136072 :   bool on_us = blockIDs().count(fi.elem().subdomain_id());
     135             : 
     136     3484572 :   if (fi.neighborPtr())
     137             :   {
     138     3484572 :     if (&fi.neighbor() == libMesh::remote_elem)
     139             :       return false;
     140             : 
     141     3484572 :     on_us = on_us || blockIDs().count(fi.neighbor().subdomain_id());
     142             :   }
     143             : 
     144       83464 :   if (!on_us)
     145             :     // Neither the element nor neighbor has a subdomain id on which we are active, so this face is
     146             :     // not relevant
     147           0 :     return false;
     148             : 
     149             :   //
     150             :   // Ok, we've established that either the element or neighbor is active on our subdomains and
     151             :   // neither of them are remote elements, so this face is still in the running to be considered
     152             :   // relevant. There is one more caveat to be considered. In the case that we are a boundary face,
     153             :   // we will generally need a two term expansion to compute our value, which will require a
     154             :   // cell-gradient evaluation. If that is the case, then all of our surrounding neighbors cannot be
     155             :   // remote. If we are not a boundary face, then at this point we're safe
     156             :   //
     157             : 
     158     3568036 :   if (!Moose::FV::onBoundary(blockIDs(), fi))
     159             :     return true;
     160             : 
     161           0 :   const auto & boundary_elem = (fi.neighborPtr() && blockIDs().count(fi.neighbor().subdomain_id()))
     162           0 :                                    ? fi.neighbor()
     163             :                                    : fi.elem();
     164             : 
     165      417056 :   for (auto * const neighbor : boundary_elem.neighbor_ptr_range())
     166             :   {
     167      333724 :     if (!neighbor)
     168       87982 :       continue;
     169             : 
     170      245742 :     if ((neighbor == libMesh::remote_elem))
     171         132 :       return false;
     172             :   }
     173             : 
     174             :   // We made it through all the tests!
     175       83332 :   return true;
     176             : }
     177             : 
     178             : void
     179       32019 : PINSFVRhieChowInterpolator::initialize()
     180             : {
     181       32019 :   if (_current_execute_flag == EXEC_INITIAL)
     182        2566 :     pinsfvSetup();
     183             :   else
     184             :     // Cannot compute Rhie Chow coefficients on initial
     185       29453 :     INSFVRhieChowInterpolator::initialize();
     186       32019 : }
     187             : 
     188             : void
     189       32019 : PINSFVRhieChowInterpolator::execute()
     190             : {
     191             :   // Cannot compute Rhie Chow coefficients on initial
     192       32019 :   if (_current_execute_flag != EXEC_INITIAL)
     193       29453 :     INSFVRhieChowInterpolator::execute();
     194       32019 : }
     195             : 
     196             : void
     197       32019 : PINSFVRhieChowInterpolator::finalize()
     198             : {
     199             :   // Cannot compute Rhie Chow coefficients on initial
     200       32019 :   if (_current_execute_flag != EXEC_INITIAL)
     201       29453 :     INSFVRhieChowInterpolator::finalize();
     202       32019 : }

Generated by: LCOV version 1.14