25#include "libmesh/mesh_base.h"
26#include "libmesh/elem_range.h"
27#include "libmesh/parallel_algebra.h"
28#include "libmesh/remote_elem.h"
29#include "metaphysicl/metaphysicl_version.h"
30#include "metaphysicl/dualsemidynamicsparsenumberarray.h"
31#include "metaphysicl/parallel_dualnumber.h"
32#if METAPHYSICL_MAJOR_VERSION < 2
33#include "metaphysicl/parallel_dynamic_std_array_wrapper.h"
35#include "metaphysicl/parallel_dynamic_array_wrapper.h"
37#include "metaphysicl/parallel_semidynamicsparsenumberarray.h"
48 params.addParam<
bool>(
49 "pull_all_nonlocal_a",
51 "Whether to pull all nonlocal 'a' coefficient data to our process. Note that 'nonlocal' "
52 "means elements that we have access to (this may not be all the elements in the mesh if the "
53 "mesh is distributed) but that we do not own.");
54 params.addParamNamesToGroup(
"pull_all_nonlocal_a",
"Parallel Execution Tuning");
56 params.addParam<
bool>(
57 "correct_volumetric_force",
false,
"Flag to activate volume force corrections.");
58 MooseEnum volume_force_correction_method(
"force-consistent pressure-consistent",
61 "volume_force_correction_method",
62 volume_force_correction_method,
63 "The method used for correcting the Rhie-Chow coefficients for a volume force.");
64 params.addParam<std::vector<MooseFunctorName>>(
65 "volumetric_force_functors",
"The names of the functors with the volumetric force sources.");
69std::vector<std::string>
72 return {
"pull_all_nonlocal_a",
73 "correct_volumetric_force",
74 "volume_force_correction_method",
75 "volumetric_force_functors"};
84 params.addClassDescription(
85 "Computes the Rhie-Chow velocity based on gathered 'a' coefficient data.");
92 params.addParam<MooseFunctorName>(
94 "For simulations in which the advecting velocities are aux variables, this parameter must be "
95 "supplied. It represents the on-diagonal coefficients for the 'x' component velocity, solved "
96 "via the Navier-Stokes equations.");
97 params.addParam<MooseFunctorName>(
99 "For simulations in which the advecting velocities are aux variables, this parameter must be "
100 "supplied when the mesh dimension is greater than 1. It represents the on-diagonal "
101 "coefficients for the 'y' component velocity, solved via the Navier-Stokes equations.");
102 params.addParam<MooseFunctorName>(
104 "For simulations in which the advecting velocities are aux variables, this parameter must be "
105 "supplied when the mesh dimension is greater than 2. It represents the on-diagonal "
106 "coefficients for the 'z' component velocity, solved via the Navier-Stokes equations.");
107 params.addParam<VariableName>(
"disp_x",
"The x-component of displacement");
108 params.addParam<VariableName>(
"disp_y",
"The y-component of displacement");
109 params.addParam<VariableName>(
"disp_z",
"The z-component of displacement");
116 _a(_moose_mesh, blockIDs(),
"a", true),
120 _momentum_sys_number(_fe_problem.systemNumForVariable(getParam<VariableName>(
"u"))),
122 _a_data_provided(false),
123 _pull_all_nonlocal(getParam<bool>(
"pull_all_nonlocal_a")),
124 _bool_correct_vf(getParam<bool>(
"correct_volumetric_force")),
125 _volume_force_correction_method(getParam<
MooseEnum>(
"volume_force_correction_method")),
126 _volumetric_force_functors(
127 isParamValid(
"volumetric_force_functors")
128 ? &getParam<
std::vector<MooseFunctorName>>(
"volumetric_force_functors")
131 auto process_displacement = [
this](
const auto & disp_name,
auto & disp_container)
135 "Displacement provided but we are not running on the displaced mesh. If you "
136 "really want this object to run on the displaced mesh, then set "
137 "'use_displaced_mesh = true', otherwise remove this displacement parameter");
144 process_displacement(
"disp_x",
_disp_xs);
149 process_displacement(
"disp_y",
_disp_ys);
151 paramError(
"disp_y",
"If 'disp_x' is provided, then 'disp_y' must be as well");
157 process_displacement(
"disp_z",
_disp_zs);
159 paramError(
"disp_z",
"If 'disp_x' is provided, then 'disp_z' must be as well");
164 _vel[tid] = std::make_unique<PiecewiseByBlockLambdaFunctor<ADRealVectorValue>>(
165 name() + std::to_string(tid),
170 velocity(1) = (*
_vs[tid])(r, t);
172 velocity(2) = (*
_ws[tid])(r, t);
181 name() +
"_disp_" + std::to_string(tid),
191 "Rhie Chow coefficients may not be specified for average velocity interpolation");
198 "At least one volumetric force functor must be specified if "
199 "'correct_volumetric_force' is true.");
204 const unsigned int num_volume_forces = (*_volumetric_force_functors).size();
206 for (
const auto i :
make_range(num_volume_forces))
219 mooseError(
"If a_u is provided, then a_v must be provided");
222 mooseError(
"If a_u is provided, then a_w must be provided");
228 paramError(
"a_v",
"If the a_v coefficients are provided, then a_u must be provided");
230 paramError(
"a_w",
"If the a_w coefficients are provided, then a_u must be provided");
248 _a_aux[tid] = std::make_unique<Moose::VectorCompositeFunctor<ADReal>>(
278 std::vector<MooseObject *> var_objects;
281 .template condition<AttribVar>(
static_cast<int>(var_num))
282 .template condition<AttribResidualObject>(
true)
283 .template condition<AttribSysNum>(
_u->
sys().
number())
284 .queryInto(var_objects);
285 for (
auto *
const var_object : var_objects)
292 " is not a INSFVMomentumResidualObject. Make sure that all the objects applied "
293 "to the momentum equation are INSFV or derived objects.");
299 " is not a INSFVMomentumResidualObject. Make sure that all the objects applied "
300 "to the momentum equation are INSFV or derived objects.");
304 mooseError(
"No INSFVKernels detected for the velocity variables. If you are trying to use "
305 "auxiliary variables for advection, please specify the a_u/v/w coefficients. If "
306 "not, please specify INSFVKernels for the momentum equations.");
315 Real elem_value = 0.0;
332 std::make_unique<ConstElemRange>(
_mesh.active_local_subdomain_set_elements_begin(
blockIDs()),
359 for (
auto & pair :
_a)
362 for (
auto & pair :
_a)
364 auto & a_val = pair.second;
378 "a-coefficient data should not be provided if the velocity variables are in the "
379 "nonlinear system and we are running kernels that compute said a-coefficients");
386 TIME_SECTION(
"execute", 1,
"Computing Rhie-Chow coefficients");
392 const auto saved_do_derivatives = ADReal::do_derivatives;
393 ADReal::do_derivatives =
true;
412 ADReal::do_derivatives = saved_do_derivatives;
426 using Datum = std::pair<dof_id_type, VectorValue<ADReal>>;
427 std::unordered_map<processor_id_type, std::vector<Datum>> push_data;
428 std::unordered_map<processor_id_type, std::vector<dof_id_type>> pull_requests;
434 const auto id = elem->id();
435 const auto pid = elem->processor_id();
436 auto it =
_a.find(
id);
437 mooseAssert(it !=
_a.end(),
"We definitely should have found something");
438 push_data[pid].push_back(std::make_pair(
id, it->second));
444 for (
const auto *
const elem :
445 as_range(
_mesh.active_not_local_elements_begin(),
_mesh.active_not_local_elements_end()))
446 if (
blockIDs().count(elem->subdomain_id()))
447 pull_requests[elem->processor_id()].push_back(elem->id());
452 pull_requests[elem->processor_id()].push_back(elem->id());
457 auto action_functor =
458 [
this](
const processor_id_type libmesh_dbg_var(pid),
const std::vector<Datum> & sent_data)
460 mooseAssert(pid != this->
processor_id(),
"We do not send messages to ourself here");
461 for (
const auto & pr : sent_data)
462 _a[pr.first] += pr.second;
470 const std::vector<dof_id_type> & elem_ids,
471 std::vector<VectorValue<ADReal>> & data_to_fill)
473 mooseAssert(pid != this->
processor_id(),
"We shouldn't be gathering from ourselves.");
474 data_to_fill.resize(elem_ids.size());
477 const auto id = elem_ids[i];
478 auto it =
_a.find(
id);
479 mooseAssert(it !=
_a.end(),
"We should hold the value for this locally");
480 data_to_fill[i] = it->second;
485 const std::vector<dof_id_type> & elem_ids,
486 const std::vector<VectorValue<ADReal>> & filled_data)
488 mooseAssert(pid != this->
processor_id(),
"The request filler shouldn't have been ourselves");
489 mooseAssert(elem_ids.size() == filled_data.size(),
"I think these should be the same size");
491 _a[elem_ids[i]] = filled_data[i];
494 _communicator, pull_requests, gather_functor, action_functor, &example);
531 const bool subtract_mesh_velocity)
const
533 const Elem *
const elem = &fi.
elem();
536 auto &
p = *
_ps[tid];
537 auto *
const u =
_us[tid];
542 auto incorporate_mesh_velocity =
543 [
this, tid, subtract_mesh_velocity, &time](
const auto & space,
auto & velocity)
545 if (
_disps.size() && subtract_mesh_velocity)
546 velocity -=
_disps[tid]->dot(space, time);
553 Moose::FV::LimiterType::CentralDifference,
558 auto velocity =
vel(boundary_face, time);
559 incorporate_mesh_velocity(boundary_face, velocity);
571 &fi, Moose::FV::LimiterType::CentralDifference,
true, correct_skewness,
nullptr,
nullptr};
573 velocity(0) = (*u)(face, time);
575 velocity(1) = (*v)(face, time);
577 velocity(2) = (*w)(face, time);
579 incorporate_mesh_velocity(face, velocity);
586 if (m == Moose::FV::InterpMethod::Average ||
593 mooseDoOnce(
mooseWarning(
"Cannot compute Rhie Chow coefficients on initial. Returning linearly "
594 "interpolated velocities"););
599 mooseDoOnce(
mooseWarning(
"Cannot compute Rhie Chow coefficients if not solving. Returning "
600 "linearly interpolated velocities"););
604 mooseAssert(((m == Moose::FV::InterpMethod::RhieChow) &&
607 "The 'a' coefficients have not been generated or provided for "
608 "Rhie Chow velocity interpolation.");
611 "We should be on an internal face...");
616 const auto & grad_p =
p.adGradSln(fi, time, correct_skewness_p);
620 const auto & unc_grad_p =
p.uncorrectedAdGradSln(fi, time, correct_skewness_p);
628 auto vf_indicator_pressure_based =
629 [
this, &elem, &neighbor, &time, &fi, &correct_skewness](
const Point & unit_basis_vector)
633 Real uncorrected_interp_vf;
637 &fi, Moose::FV::LimiterType::CentralDifference,
true, correct_skewness,
nullptr,
nullptr};
647 Real elem_value = 0.0;
648 Real neigh_value = 0.0;
652 Real coord_multiplier;
654 const unsigned int rz_radial_coord =
666 fi_loc, Moose::FV::LimiterType::CentralDifference,
true, correct_skewness, elem,
nullptr};
669 elem->
vertex_average(), coord_multiplier, coord_type, rz_radial_coord);
684 elem_value += (*this->
_volumetric_force[i])(loc_face, time) * face_volume_contribution *
685 (fi_loc->
normal() * unit_basis_vector);
688 elem_value = elem_value / elem->
volume();
701 fi_loc, Moose::FV::LimiterType::CentralDifference,
true, correct_skewness, elem,
nullptr};
704 neighbor->
vertex_average(), coord_multiplier, coord_type, rz_radial_coord);
717 neigh_value += (*this->
_volumetric_force[i])(loc_face, time) * face_volume_contribution *
718 (fi_loc->
normal() * unit_basis_vector);
721 neigh_value = neigh_value / neighbor->
volume();
726 fi.
faceCentroid(), coord_multiplier, coord_type, rz_radial_coord);
728 Moose::FV::InterpMethod::Average, uncorrected_interp_vf, elem_value, neigh_value, fi,
true);
731 return MooseUtils::relativeFuzzyEqual(interp_vf, uncorrected_interp_vf, 1e-10) ? 0.0 : 1.0;
738 auto vf_indicator_force_based = [
this, &time, &fi, &correct_skewness](
Point & face_normal)
742 &fi, Moose::FV::LimiterType::CentralDifference,
true, correct_skewness,
nullptr,
nullptr};
762 "Coordinate systems must be the same between the two elements");
767 elem_volume *= coord;
772 mooseAssert(elem_a(i).value() != 0,
"We should not be dividing by zero");
773 elem_D(i) = elem_volume / elem_a(i);
781 neighbor_volume *= coord;
786 mooseAssert(neighbor_a(i).value() != 0,
"We should not be dividing by zero");
787 neighbor_D(i) = neighbor_volume / neighbor_a(i);
794 ? Moose::FV::InterpMethod::SkewCorrectedAverage
795 : Moose::FV::InterpMethod::Average;
799 const auto face_eps =
epsilon(tid)(face, time);
807 velocity(i) -= face_D(i) * face_eps * (grad_p(i) - unc_grad_p(i));
813 Point unit_basis_vector;
814 unit_basis_vector(i) = 1.0;
817 Real correction_indicator;
819 correction_indicator = vf_indicator_force_based(unit_basis_vector);
821 correction_indicator = vf_indicator_pressure_based(unit_basis_vector);
824 velocity(i) += face_D(i) * face_eps * (grad_p(i) - unc_grad_p(i)) * correction_indicator;
DualNumber< Real, DNDerivativeType, true > ADReal
void coordTransformFactor(const SubProblem &s, SubdomainID sub_id, const P &point, C &factor, SubdomainID neighbor_sub_id=libMesh::Elem::invalid_subdomain_id)
boundary_id_type BoundaryID
registerMooseObject("NavierStokesApp", INSFVRhieChowInterpolator)
const ExecFlagType EXEC_ALWAYS
const ExecFlagType EXEC_INITIAL
const ExecFlagType EXEC_PRE_KERNELS
bool hasBlocks(const SubdomainName &name) const
virtual const std::set< SubdomainID > & blockIDs() const
void addAvailableFlags(const ExecFlagType &flag, Args... flags)
const ExecFlagType & getCurrentExecuteOnFlag() const
virtual unsigned int currentNlSysNum() const override
TheWarehouse & theWarehouse() const
Real neighborVolume() const
const Point & normal() const
const Elem & elem() const
const Elem * neighborPtr() const
const Elem * elemPtr() const
const Point & neighborCentroid() const
const Point & elemCentroid() const
const Point & faceCentroid() const
static std::string deduceFunctorName(const std::string &name, const InputParameters ¶ms)
Moose::ElemArg makeElemArg(const Elem *elem, bool correct_skewnewss=false) const
A class that gathers body force data from elemental kernels contributing to the Navier-Stokes momentu...
A class that gathers 'a' coefficient data from flux kernels, boundary conditions, and interface kerne...
All objects that contribute to pressure-based (e.g.
This user-object gathers 'a' (on-diagonal velocity coefficients) data.
std::vector< std::unique_ptr< PiecewiseByBlockLambdaFunctor< ADRealVectorValue > > > _vel
A functor for computing the (non-RC corrected) velocity.
INSFVRhieChowInterpolator(const InputParameters ¶ms)
virtual void ghostADataOnBoundary(const BoundaryID boundary_id) override
makes sure coefficient data gets communicated on both sides of a given boundary
bool pressureSkewCorrection(THREAD_ID tid) const
Whether central differencing face interpolations of pressure should include a skewness correction.
virtual void initialSetup() override
virtual void finalize() override
std::unordered_set< const Elem * > _elements_to_push_pull
Non-local elements that we should push and pull data for across processes.
std::vector< std::unique_ptr< Moose::VectorCompositeFunctor< ADReal > > > _disps
A functor for computing the displacement.
virtual void execute() override
Moose::VectorComponentFunctor< ADReal > _ax
std::vector< MooseVariableField< Real > * > _disp_zs
All the thread copies of the z-displacement variable.
std::vector< MooseVariableField< Real > * > _disp_ys
All the thread copies of the y-displacement variable.
std::unique_ptr< ConstElemRange > _elem_range
All the active and elements local to this process that exist on this object's subdomains.
std::vector< MooseVariableField< Real > * > _disp_xs
All the thread copies of the x-displacement variable.
static InputParameters validParams()
const MooseEnum _volume_force_correction_method
– Method used for computing the properties average
const bool & _bool_correct_vf
Correct Rhie-Chow coefficients for volumetric force flag.
virtual void initialize() override
const unsigned int _momentum_sys_number
The number of the nonlinear system in which the monolithic momentum and continuity equations are loca...
bool velocitySkewCorrection(THREAD_ID tid) const
Whether central differencing face interpolations of velocity should include a skewness correction Als...
bool _a_data_provided
Whether 'a' data has been provided by the user.
Moose::VectorComponentFunctor< ADReal > _ay
The y-component of 'a'.
std::vector< std::unique_ptr< Moose::FunctorBase< VectorValue< ADReal > > > > _a_aux
A vector sized according to the number of threads that holds vector composites of 'a' component funct...
static InputParameters uniqueParams()
Parameters of this object that should be added to the NSFV action that are unique to this object.
Moose::VectorComponentFunctor< ADReal > _az
The z-component of 'a'.
bool needAComputation() const
Whether we need 'a' coefficient computation.
std::vector< const Moose::Functor< Real > * > _volumetric_force
Values of the functors storing the volumetric forces.
virtual void meshChanged() override
const std::vector< MooseFunctorName > * _volumetric_force_functors
Names of the functors storing the volumetric forces.
std::vector< const Moose::FunctorBase< VectorValue< ADReal > > * > _a_read
A vector sized according to the number of threads that holds the 'a' data we will read from when comp...
CellCenteredMapFunctor< ADRealVectorValue, std::unordered_map< dof_id_type, ADRealVectorValue > > _a
A map from element IDs to 'a' coefficient data.
virtual VectorValue< ADReal > getVelocity(const Moose::FV::InterpMethod m, const FaceInfo &fi, const Moose::StateArg &time, const THREAD_ID tid, bool subtract_mesh_velocity) const override
Retrieve a face velocity.
virtual void addToA(const libMesh::Elem *elem, unsigned int component, const ADReal &value) override
API that momentum residual objects that have on-diagonals for velocity call.
Real _baseline_volume_force
Minimum absolute RC force over the domain.
void insfvSetup()
perform the setup of this object
bool _pull_all_nonlocal
Whether we want to pull all nonlocal 'a' coefficient data.
void fillARead()
Fills the _a_read data member at construction time with the appropriate functors.
static std::vector< std::string > listOfCommonParams()
const Moose::ConstantFunctor< ADReal > _zero_functor
A zero functor potentially used in _a_read.
const std::string & name() const
void paramError(const std::string ¶m, Args... args) const
void mooseError(Args &&... args) const
void mooseWarning(Args &&... args) const
bool isParamValid(const std::string &name) const
std::unordered_set< dof_id_type > getBoundaryActiveSemiLocalElemIds(BoundaryID bid) const
face_info_iterator ownedFaceInfoEnd()
virtual Elem * elemPtr(const dof_id_type i)
face_info_iterator ownedFaceInfoBegin()
const std::vector< const FaceInfo * > & faceInfo() const
virtual Elem * queryElemPtr(const dof_id_type i)
std::unordered_set< dof_id_type > getBoundaryActiveNeighborElemIds(BoundaryID bid) const
const bool _displaced
Whether this object is operating on the displaced mesh.
Moose::FV::InterpMethod _velocity_interp_method
The interpolation method to use for the velocity.
INSFVVelocityVariable *const _w
The thread 0 copy of the z-velocity variable (null if the problem is not 3D)
std::vector< MooseVariableFVReal * > _ws
All the thread copies of the z-velocity variable.
void fillContainer(const std::string &var_name, Container &container)
Fill the passed-in variable container with the thread copies of var_name.
const INSFVVelocityVariable * vel() const
MooseMesh & _moose_mesh
The MooseMesh that this user object operates on.
const libMesh::MeshBase & _mesh
The libMesh mesh that this object acts on.
std::vector< unsigned int > _var_numbers
The velocity variable numbers.
std::vector< MooseVariableFVReal * > _vs
All the thread copies of the y-velocity variable.
static InputParameters validParams()
void checkBlocks(const VarType &var) const
Check the block consistency between the passed in var and us.
virtual const Moose::FunctorBase< ADReal > & epsilon(THREAD_ID tid) const
A virtual method that allows us to only implement getVelocity once for free and porous flows.
INSFVVelocityVariable *const _v
The thread 0 copy of the y-velocity variable (null if the problem is 1D)
std::vector< MooseVariableFVReal * > _us
All the thread copies of the x-velocity variable.
INSFVVelocityVariable *const _u
The thread 0 copy of the x-velocity variable.
const unsigned int _dim
The dimension of the mesh, e.g. 3 for hexes and tets, 2 for quads and tris.
std::vector< MooseVariableFVReal * > _ps
All the thread copies of the pressure variable.
const Moose::Functor< T > & getFunctor(const std::string &name, const THREAD_ID tid, const std::string &requestor_name, bool requestor_is_ad)
unsigned int getAxisymmetricRadialCoord() const
Moose::CoordinateSystemType getCoordSystem(SubdomainID sid) const
void addFunctor(const std::string &name, const Moose::FunctorBase< T > &functor, const THREAD_ID tid)
unsigned int number() const
void min(const T &r, T &o, Request &req) const
Moose::StateArg determineState() const
FEProblemBase & _fe_problem
unsigned int which_neighbor_am_i(const Elem *e) const
subdomain_id_type subdomain_id() const
virtual Real volume() const
virtual unsigned int n_sides() const=0
const Elem * neighbor_ptr(unsigned int i) const
Point vertex_average() const
const Parallel::Communicator & _communicator
processor_id_type processor_id() const
processor_id_type n_processors() const
void coordTransformFactor(const P &point, C &factor, const Moose::CoordinateSystemType coord_type, const unsigned int rz_radial_coord=libMesh::invalid_uint)
void interpolate(InterpMethod m, T &result, const T2 &value1, const T3 &value2, const FaceInfo &fi, const bool one_is_elem)
bool elemHasFaceInfo(const Elem &elem, const Elem *const neighbor)
bool onBoundary(const SubdomainRestrictable &obj, const FaceInfo &fi)
std::tuple< bool, T, T > isPorosityJumpFace(const Moose::FunctorBase< T > &porosity, const FaceInfo &fi, const Moose::StateArg &time)
Checks to see whether the porosity value jumps from one side to the other of the provided face.
void pull_parallel_vector_data(const Communicator &comm, const MapToVectors &queries, GatherFunctor &gather_data, const ActionFunctor &act_on_data, const datum *example)
void push_parallel_vector_data(const Communicator &comm, MapToVectors &&data, const ActionFunctor &act_on_data)
void parallel_reduce(const Range &range, Body &body, unsigned int n_threads=libMesh::n_threads())
The following methods are specializations for using the Parallel::packed_range_* routines for a vecto...
SimpleRange< IndexType > as_range(const std::pair< IndexType, IndexType > &p)
auto index_range(const T &sizable)
const unsigned int invalid_uint
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
uint8_t processor_id_type
IntRange< T > make_range(T beg, T end)