LCOV - code coverage report
Current view: top level - src/fvkernels - INSFVAdvectionKernel.C (source / functions) Hit Total Coverage
Test: idaholab/moose navier_stokes: ba1ead Lines: 42 47 89.4 %
Date: 2025-08-13 06:50:25 Functions: 5 5 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 "INSFVAdvectionKernel.h"
      11             : #include "NS.h"
      12             : #include "MooseVariableFV.h"
      13             : #include "RelationshipManager.h"
      14             : #include "NSFVUtils.h"
      15             : #include "FVBoundaryScalarLagrangeMultiplierConstraint.h"
      16             : #include "Limiter.h"
      17             : #include "Steady.h"
      18             : 
      19             : InputParameters
      20       55066 : INSFVAdvectionKernel::validParams()
      21             : {
      22       55066 :   InputParameters params = FVFluxKernel::validParams();
      23       55066 :   params += Moose::FV::interpolationParameters();
      24      110132 :   params.addRequiredParam<UserObjectName>("rhie_chow_user_object", "The rhie-chow user-object");
      25             :   // We need 2 ghost layers for the Rhie-Chow interpolation
      26       55066 :   params.set<unsigned short>("ghost_layers") = 2;
      27             : 
      28             :   // We currently do not have a need for this, boundary conditions tell us where to execute
      29             :   // advection kernels
      30      110132 :   params.suppressParameter<bool>("force_boundary_execution");
      31             : 
      32             :   // We add the relationship manager here, this will select the right number of
      33             :   // ghosting layers depending on the chosen interpolation method
      34      110132 :   params.addRelationshipManager(
      35             :       "ElementSideNeighborLayers",
      36             :       Moose::RelationshipManagerType::GEOMETRIC | Moose::RelationshipManagerType::ALGEBRAIC |
      37             :           Moose::RelationshipManagerType::COUPLING,
      38             :       [](const InputParameters & obj_params, InputParameters & rm_params)
      39       59222 :       { FVRelationshipManagerInterface::setRMParamsAdvection(obj_params, rm_params, 3); });
      40             : 
      41       55066 :   return params;
      42           0 : }
      43             : 
      44       29135 : INSFVAdvectionKernel::INSFVAdvectionKernel(const InputParameters & params)
      45             :   : FVFluxKernel(params),
      46       29135 :     _rc_vel_provider(getUserObject<RhieChowInterpolatorBase>("rhie_chow_user_object"))
      47             : {
      48             :   const bool need_more_ghosting =
      49       29135 :       Moose::FV::setInterpolationMethods(*this, _advected_interp_method, _velocity_interp_method);
      50       29135 :   if (need_more_ghosting && _tid == 0)
      51             :   {
      52             :     // If we need more ghosting, then we are a second-order nonlinear limiting scheme whose stencil
      53             :     // is liable to change upon wind-direction change. Consequently we need to tell our problem that
      54             :     // it's ok to have new nonzeros which may crop-up after PETSc has shrunk the matrix memory
      55             :     getCheckedPointerParam<FEProblemBase *>("_fe_problem_base")
      56         324 :         ->setErrorOnJacobianNonzeroReallocation(false);
      57             :   }
      58             : 
      59       29135 :   auto param_check = [&params, this](const auto & param_name)
      60             :   {
      61       58270 :     if (params.isParamSetByUser(param_name))
      62           0 :       paramError(
      63           0 :           param_name, "This parameter is not honored by INSFVAdvectionKernels like '", name(), "'");
      64       29135 :   };
      65             : 
      66       29135 :   param_check("force_boundary_execution");
      67             : 
      68       29135 :   if (_var.getTwoTermBoundaryExpansion() &&
      69       23249 :       !(_advected_interp_method == Moose::FV::InterpMethod::Upwind ||
      70          66 :         _advected_interp_method == Moose::FV::InterpMethod::Average ||
      71             :         _advected_interp_method == Moose::FV::InterpMethod::HarmonicAverage ||
      72             :         _advected_interp_method == Moose::FV::InterpMethod::SkewCorrectedAverage))
      73           0 :     mooseWarning(
      74             :         "Second order upwind limiting is not supported when `two_term_boundary_expansion "
      75             :         "= true` for the limited variable. Use at your own risk or please consider "
      76             :         "setting `two_term_boundary_expansion = false` in the advected variable parameters or "
      77             :         "changing your "
      78             :         "'advected_interp_method' of the kernel to first order methods (`upwind`, `average`)");
      79             : 
      80       29135 :   if (dynamic_cast<Steady *>(_app.getExecutioner()))
      81             :   {
      82       43614 :     const MooseEnum not_available_with_steady("sou min_mod vanLeer quick venkatakrishnan");
      83             :     const std::string chosen_scheme =
      84       21807 :         static_cast<std::string>(getParam<MooseEnum>("advected_interp_method"));
      85       21807 :     if (not_available_with_steady.find(chosen_scheme) != not_available_with_steady.items().end())
      86           0 :       paramError("advected_interp_method",
      87             :                  "The given advected interpolation cannot be used with steady-state runs!");
      88       21807 :   }
      89       29135 : }
      90             : 
      91             : void
      92       38942 : INSFVAdvectionKernel::initialSetup()
      93             : {
      94       38942 :   INSFVBCInterface::initialSetup(*this);
      95       38942 : }
      96             : 
      97             : bool
      98   278279156 : INSFVAdvectionKernel::skipForBoundary(const FaceInfo & fi) const
      99             : {
     100             :   // Boundaries to avoid come first, since they are always obeyed
     101   278279156 :   if (avoidBoundary(fi))
     102             :     return true;
     103             : 
     104             :   // We get this to check if we are on a kernel boundary or not
     105   278279156 :   const bool on_boundary = onBoundary(fi);
     106             : 
     107             :   // We are either on a kernel boundary or on an internal sideset
     108             :   // which is handled as a boundary
     109   278279156 :   if (on_boundary || !fi.boundaryIDs().empty())
     110             :   {
     111             :     // Selected boundaries to force
     112    24925082 :     for (const auto bnd_to_force : _boundaries_to_force)
     113             :       if (fi.boundaryIDs().count(bnd_to_force))
     114       28604 :         return false;
     115             : 
     116             :     // If we have flux bcs then we do skip
     117    24739858 :     const auto & [have_flux_bcs, flux_bcs] = _var.getFluxBCs(fi);
     118             :     libmesh_ignore(have_flux_bcs);
     119    24741478 :     for (const auto * const flux_bc : flux_bcs)
     120             :       // If we have something like an average-value pressure constraint on a flow boundary, then we
     121             :       // still want to execute this advection kernel on the boundary to ensure we're enforcing local
     122             :       // conservation (mass in this example)
     123     4953182 :       if (!dynamic_cast<const FVBoundaryScalarLagrangeMultiplierConstraint *>(flux_bc))
     124             :         return true;
     125             : 
     126             :     // If we have a flow boundary without a replacement flux BC, then we must not skip. Mass and
     127             :     // momentum are transported via advection across boundaries
     128    35638849 :     for (const auto bc_id : fi.boundaryIDs())
     129    20327671 :       if (_flow_boundaries.find(bc_id) != _flow_boundaries.end())
     130     4477118 :         return false;
     131             :   }
     132             : 
     133             :   // If not a flow boundary, then there should be no advection/flow in the normal direction, e.g. we
     134             :   // should not contribute any advective flux. If we are on an internal face though, we still
     135             :   // execute.
     136             :   return on_boundary;
     137             : }

Generated by: LCOV version 1.14