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 = [¶ms, 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 : }