32#include "libmesh/mesh_base.h"
33#include "libmesh/elem.h"
34#include "libmesh/elem_range.h"
35#include "libmesh/petsc_matrix.h"
47 params.addClassDescription(
"Computes H/A and 1/A together with face mass fluxes for segregated "
48 "momentum-pressure equations using linear systems.");
50 params.addRequiredParam<VariableName>(
NS::pressure,
"The pressure variable.");
51 params.addRequiredParam<VariableName>(
"u",
"The x-component of velocity");
52 params.addParam<VariableName>(
"v",
"The y-component of velocity");
53 params.addParam<VariableName>(
"w",
"The z-component of velocity");
54 params.addRequiredParam<std::string>(
56 "The LinearFVPressureCorrectionDiffusion kernel acting on the pressure.");
58 params.addRequiredParam<MooseFunctorName>(
NS::density,
"Density functor");
68 params.addParam<
MooseEnum>(
"pressure_projection_method",
69 MooseEnum(
"standard consistent",
"standard"),
70 "The method to use in the pressure projection for Ainv - "
71 "standard (SIMPLE) or consistent (SIMPLEC)");
73 "pressure_diffusion_interpolation",
75 "The face interpolation method for Ainv in the pressure correction diffusion term.");
83 _mesh(_moose_mesh.getMesh()),
84 _dim(blocksMaxDimension()),
86 &
UserObject::_subproblem.getVariable(0, getParam<VariableName>(
NS::pressure)))),
88 _HbyA_flux(_moose_mesh, blockIDs(),
"HbyA_flux"),
89 _Ainv(_moose_mesh, blockIDs(),
"Ainv"),
92 "face_flux", _moose_mesh, blockIDs(),
"face_values")),
93 _rho(getFunctor<Real>(
NS::density)),
94 _pressure_system(nullptr),
95 _pressure_gradient_field(nullptr),
96 _base_pressure_gradient_field(nullptr),
97 _global_pressure_system_number(0),
98 _pressure_projection_method(getParam<
MooseEnum>(
"pressure_projection_method")),
99 _pressure_diffusion_interp_method(getParam<
MooseEnum>(
"pressure_diffusion_interpolation") ==
101 ?
Moose::FV::InterpMethod::HarmonicAverage
102 :
Moose::FV::InterpMethod::Average)
108 std::vector<std::string> vel_names = {
"u",
"v",
"w"};
109 for (
const auto i : index_range(
_vel))
115 paramError(vel_names[i],
"the velocity must be a MOOSELinearVariableFVReal.");
129 " should only be used with a linear segregated thermal-hydraulics solver!");
134 const std::vector<LinearSystem *> & momentum_systems,
136 const std::vector<unsigned int> & momentum_system_numbers)
143 auto *
const pressure_var =
146 mooseError(
"The pressure variable in system '",
148 "' must be a MooseLinearVariableFVReal.");
154 std::vector<std::vector<const LinearFVMomentumPressure *>> applicable_kernels(
155 momentum_systems.size());
156 for (
const auto system_index : index_range(momentum_systems))
158 std::vector<LinearFVElementalKernel *> kernels;
161 .template condition<AttribThread>(
_tid)
162 .template condition<AttribSystem>(
"LinearFVElementalKernel")
163 .template condition<AttribSysNum>(momentum_system_numbers[system_index])
166 for (
const auto *
const kernel : kernels)
169 if (candidate && MooseUtils::setsIntersect(candidate->blockIDs(),
blockIDs()))
170 applicable_kernels[system_index].push_back(candidate);
174 for (
const auto system_index : index_range(momentum_systems))
176 const auto & kernels = applicable_kernels[system_index];
177 const auto & system_name = momentum_systems[system_index]->
name();
180 std::set<SubdomainID> covered_blocks;
181 for (
const auto *
const kernel : kernels)
182 covered_blocks.insert(kernel->blockIDs().begin(), kernel->blockIDs().end());
184 std::set<SubdomainID> missing_blocks;
185 std::set_difference(
blockIDs().begin(),
187 covered_blocks.begin(),
188 covered_blocks.end(),
189 std::inserter(missing_blocks, missing_blocks.end()));
191 if (!missing_blocks.empty())
194 "' found no applicable LinearFVMomentumPressure kernel for momentum system '",
201 for (
const auto i : index_range(kernels))
203 if (kernels[i]->momentumComponent() != system_index)
204 mooseError(
"LinearFVMomentumPressure kernel '",
206 "' declares momentum component ",
207 kernels[i]->momentumComponent(),
208 " but is linked to momentum system '",
212 ") through RhieChowMassFlux '",
216 for (
const auto j : make_range(i + 1, kernels.size()))
218 std::set<SubdomainID> overlap;
219 for (
const auto block : kernels[i]->blockIDs())
220 if (
hasBlocks(block) && kernels[j]->blockIDs().count(block))
221 overlap.insert(block);
222 if (!overlap.empty())
225 "' has more than one LinearFVMomentumPressure kernel contributing a "
226 "pressure source on the same block(s) for RhieChowMassFlux '",
232 "' overlap on block(s) ",
242 std::vector<const LinearFVMomentumPressure *> momentum_pressure_kernels;
243 for (
auto & kernels : applicable_kernels)
244 momentum_pressure_kernels.insert(
245 momentum_pressure_kernels.end(), kernels.begin(), kernels.end());
247 const auto *
const coupling_kernel = momentum_pressure_kernels.front();
248 const auto & coupling_reader = coupling_kernel->pressureGradientField();
251 coupling_kernel->pressureVariableNumber() !=
_p->
number())
252 mooseError(
"FVReconstructedPressureGradient can only be used for the pressure variable "
253 "registered on RhieChowMassFlux '",
257 for (
const auto *
const kernel : momentum_pressure_kernels)
259 const auto & reader = kernel->pressureGradientField();
261 if (&reader.system() != &coupling_reader.system() ||
262 reader.systemNumber() != coupling_reader.systemNumber())
265 "': momentum pressure kernels '",
266 coupling_kernel->name(),
273 ") must use pressure gradients from the same system.");
275 if (reader.variableNumber() != coupling_reader.variableNumber())
278 "': momentum pressure kernels '",
279 coupling_kernel->name(),
280 "' (pressure variable number ",
281 coupling_reader.variableNumber(),
284 "' (pressure variable number ",
285 reader.variableNumber(),
286 ") must use the same pressure variable.");
288 if (&reader.method() != &coupling_reader.method())
291 "': momentum pressure kernels '",
292 coupling_kernel->name(),
295 "' must use the same pressure gradient method.");
297 if (&reader.components() != &coupling_reader.components())
300 "': momentum pressure kernels '",
301 coupling_kernel->name(),
304 "' must share the same registered pressure gradient field.");
312 const auto & base_reader =
317 "Reconstructed and base pressure gradient readers must be distinct when "
318 "FVReconstructedPressureGradient is active.");
337 "FVReconstructedPressureGradient with nonorthogonal pressure diffusion requires "
338 "the consistent pressure projection.");
343 std::set<BoundaryID> velocity_boundary_ids;
344 for (
const auto dim_i : make_range(
_dim))
345 for (
const auto & [boundary_id, _] :
_vel[dim_i]->getBoundaryConditionMap())
346 velocity_boundary_ids.insert(boundary_id);
348 const auto is_dirichlet =
357 for (
const auto boundary_id : velocity_boundary_ids)
363 const bool velocity_is_dirichlet = is_dirichlet(*
_vel[0], boundary_id);
364 for (
const auto dim_i : make_range(
_dim))
365 if (is_dirichlet(*
_vel[dim_i], boundary_id) != velocity_is_dirichlet)
366 mooseError(
"All velocity components must either have Dirichlet boundary conditions or "
367 "non-Dirichlet boundary conditions on boundary '",
369 "' when the pressure boundary condition is not a LinearFVPressureFluxBC.");
405 "The pressure gradient field must be linked before preparing momentum.");
426 "A momentum predictor must be prepared before another PISO corrector.");
428 for (
const auto component : make_range(
dimension()))
475 std::vector<LinearFVFluxKernel *> flux_kernel;
478 .template condition<AttribThread>(
_tid)
479 .template condition<AttribSysNum>(
_p->
sys().
number())
480 .template condition<AttribSystem>(
"LinearFVFluxKernel")
481 .template condition<AttribName>(getParam<std::string>(
"p_diffusion_kernel"))
482 .queryInto(flux_kernel);
483 if (flux_kernel.size() != 1)
485 "p_diffusion_kernel",
486 "The kernel with the given name could not be found or multiple instances were identified.");
490 "The provided diffusion kernel must be of type "
491 "LinearFVPressureCorrectionDiffusion.");
503 if (
hasBlocks(elem_info->subdomain_id()))
513 if (
hasBlocks(fi->elemPtr()->subdomain_id()) ||
514 (fi->neighborPtr() &&
hasBlocks(fi->neighborPtr()->subdomain_id())))
518template <
typename GradientComponent>
525 auto working_vector =
_Ainv_raw[system_i]->clone();
526 working_vector->pointwise_mult(*working_vector, *pressure_gradient[system_i]);
527 working_vector->add(*
_HbyA_raw[system_i]);
528 working_vector->scale(-1.0);
538 auto defect =
_Ainv_raw[system_i]->clone();
539 defect->pointwise_mult(*defect, *pressure_gradient[system_i]);
542 mooseAssert(MooseUtils::absoluteFuzzyEqual(defect->linfty_norm(), 0.0, 1e-10),
543 "RhieChowMassFlux: cell-velocity update violates the momentum-coupling "
544 "identity u + H/A + Ainv*grad(p) = 0.");
560 for (
const auto & pair :
_Ainv)
561 _Ainv[pair.first] = 0;
575 RealVectorValue density_times_velocity;
577 if (
_vel[0]->isInternalFace(*fi))
579 const auto & elem_info = *fi->elemInfo();
580 const auto & neighbor_info = *fi->neighborInfo();
585 for (
const auto dim_i : index_range(
_vel))
586 interpolate(InterpMethod::Average,
587 density_times_velocity(dim_i),
588 _vel[dim_i]->getElemValue(elem_info, time_arg) * elem_rho,
589 _vel[dim_i]->getElemValue(neighbor_info, time_arg) * neighbor_rho,
596 const bool elem_is_fluid =
hasBlocks(fi->elemPtr()->subdomain_id());
597 const Elem *
const boundary_elem = elem_is_fluid ? fi->elemPtr() : fi->neighborPtr();
600 const Real boundary_normal_multiplier = elem_is_fluid ? 1.0 : -1.0;
602 fi, Moose::FV::LimiterType::CentralDifference,
true,
false, boundary_elem,
nullptr};
604 const Real face_rho =
_rho(boundary_face, time_arg);
605 for (
const auto dim_i : index_range(
_vel))
606 density_times_velocity(dim_i) = boundary_normal_multiplier * face_rho *
623 const std::string neighbor_cell_id =
629 "' has no corrected mass flux for face ID ",
631 " adjacent to cell ID ",
633 " and neighbor cell ID ",
637 if (!std::isfinite(face_flux->second))
640 "' has non-finite corrected mass flux ",
644 " adjacent to cell ID ",
646 " and neighbor cell ID ",
652 const Elem * face_side = fi.
elemPtr();
657 Moose::FV::LimiterType::CentralDifference,
663 if (!std::isfinite(face_rho) || face_rho <= 0.0)
666 "' requires finite, positive density for corrected face flux reconstruction, but "
671 " adjacent to cell ID ",
673 " and neighbor cell ID ",
677 const Real volumetric_flux = face_flux->second / face_rho;
678 if (!std::isfinite(volumetric_flux))
681 "' computed non-finite volumetric flux ",
685 " adjacent to cell ID ",
687 " and neighbor cell ID ",
691 return volumetric_flux;
699 "The pressure gradient field has not been registered for RhieChowMassFlux '",
name(),
"'.");
708 mooseError(
"The base pressure gradient field has not been registered for RhieChowMassFlux '",
715const std::vector<std::unique_ptr<NumericVector<Number>>> &
718 mooseAssert(!
_HbyA_raw.empty(),
"HbyA data is not ready.");
723const std::vector<std::unique_ptr<NumericVector<Number>>> &
726 mooseAssert(!
_Ainv_raw.empty(),
"Ainv data is not ready.");
731const std::vector<NumericVector<Number> *> &
748 bool libmesh_dbg_var(subtract_mesh_velocity))
const
750 mooseAssert(!subtract_mesh_velocity,
"RhieChowMassFlux does not support moving meshes yet!");
752 if (m != Moose::FV::InterpMethod::RhieChow)
753 mooseError(
"Interpolation methods other than Rhie-Chow are not supported!");
755 mooseError(
"Older interpolation times are not supported!");
774 const Real face_flux = -
_HbyA_flux[fi->
id()] + p_grad_flux;
791 if (
auto *
const bc_pointer =
_vel[component]->getBoundaryCondition(bnd_id))
795 mooseAssert(!dirichlet_bc,
796 "Face " + std::to_string(fi.
id()) +
797 " carries more than one Dirichlet velocity boundary condition.");
798 dirichlet_bc = bc_pointer;
820 Real p_grad_flux = 0.0;
823 const auto & elem_info = *fi.
elemInfo();
831 const auto p_elem_value = p_reader(elem_dof);
832 const auto p_neighbor_value = p_reader(neighbor_dof);
836 const auto neighbor_matrix_contribution =
841 p_grad_flux = (p_neighbor_value * neighbor_matrix_contribution +
842 p_elem_value * elem_matrix_contribution) -
843 elem_rhs_contribution;
847 mooseAssert(fi.
boundaryIDs().size() == 1,
"We should only have one boundary on every face.");
848 bc_pointer->setupFaceData(
855 const auto matrix_contribution =
860 p_grad_flux = p_elem_value * matrix_contribution - rhs_contribution;
881 const std::vector<std::unique_ptr<NumericVector<Number>>> & raw_hbya,
882 const std::vector<std::unique_ptr<NumericVector<Number>>> & raw_Ainv)
890 std::vector<PetscVectorReader> hbya_reader;
891 for (
const auto dim_i : index_range(raw_hbya))
892 hbya_reader.emplace_back(*raw_hbya[dim_i]);
894 std::vector<PetscVectorReader> ainv_reader;
895 for (
const auto dim_i : index_range(raw_Ainv))
896 ainv_reader.emplace_back(*raw_Ainv[dim_i]);
902 RealVectorValue face_hbya;
908 if (
_vel[0]->isInternalFace(*fi))
911 const auto & elem_info = *fi->
elemInfo();
922 interpolate(Moose::FV::InterpMethod::Average, face_rho, elem_rho, neighbor_rho, *fi,
true);
923 for (
const auto dim_i : index_range(raw_hbya))
925 interpolate(Moose::FV::InterpMethod::Average,
927 hbya_reader[dim_i](elem_dof),
928 hbya_reader[dim_i](neighbor_dof),
933 elem_rho * ainv_reader[dim_i](elem_dof),
934 neighbor_rho * ainv_reader[dim_i](neighbor_dof),
944 const Real boundary_normal_multiplier = elem_is_fluid ? 1.0 : -1.0;
949 mooseAssert(fi->
boundaryIDs().size() == 1,
"We should only have one boundary on every face.");
956 if (
_vel[0]->isDirichletBoundaryFace(*fi) &&
960 fi, Moose::FV::LimiterType::CentralDifference,
true,
false, elem_info.
elem(),
nullptr};
963 for (
const auto dim_i : make_range(
_dim))
968 face_hbya(dim_i) *= boundary_normal_multiplier;
977 for (
const auto dim_i : make_range(
_dim))
978 face_hbya(dim_i) = boundary_normal_multiplier * hbya_reader[dim_i](elem_dof);
983 for (
const auto dim_i : index_range(raw_Ainv))
984 Ainv(dim_i) = elem_rho * ainv_reader[dim_i](elem_dof);
996 _console <<
"************************************" << std::endl;
997 _console <<
"Computing HbyA" << std::endl;
998 _console <<
"************************************" << std::endl;
1001 "The momentum system shall be linked before calling this function!");
1004 "A coupling pressure-gradient snapshot must exist before computing H/A.");
1006 "The coupling pressure-gradient snapshot must have one component per momentum "
1014 mooseAssert(snapshot.size() == momentum_layout.size() &&
1015 snapshot.local_size() == momentum_layout.local_size() &&
1016 snapshot.first_local_index() == momentum_layout.first_local_index() &&
1017 snapshot.last_local_index() == momentum_layout.last_local_index(),
1018 "The coupling pressure-gradient snapshot layout must match its momentum system.");
1031 NumericVector<Number> & rhs = *(momentum_system->rhs);
1032 NumericVector<Number> & current_local_solution = *(momentum_system->current_local_solution);
1033 NumericVector<Number> & solution = *(momentum_system->solution);
1034 PetscMatrix<Number> * mmat =
dynamic_cast<PetscMatrix<Number> *
>(momentum_system->matrix);
1036 "The matrices used in the segregated INSFVRhieChow objects need to be convertable "
1041 _console <<
"Matrix in rc object" << std::endl;
1046 _Ainv_raw.push_back(current_local_solution.zero_clone());
1047 NumericVector<Number> & Ainv = *(
_Ainv_raw.back());
1049 mmat->get_diagonal(Ainv);
1053 _console <<
"Velocity solution in H(u)" << std::endl;
1058 _HbyA_raw.push_back(current_local_solution.zero_clone());
1059 NumericVector<Number> & HbyA = *(
_HbyA_raw.back());
1068 auto working_vector = momentum_system->current_local_solution->zero_clone();
1069 PetscVector<Number> * working_vector_petsc =
1070 dynamic_cast<PetscVector<Number> *
>(working_vector.get());
1071 mooseAssert(working_vector_petsc,
1072 "The vectors used in the RhieChowMassFlux objects need to be convertable "
1073 "to PetscVectors!");
1075 mmat->vector_mult(HbyA, solution);
1076 working_vector_petsc->pointwise_mult(Ainv, solution);
1077 HbyA.add(-1.0, *working_vector_petsc);
1086 HbyA.add(-1.0, rhs);
1091 working_vector_petsc->pointwise_mult(*coupling_pressure_gradient[system_i],
1093 HbyA.add(-1.0, *working_vector_petsc);
1097 _console <<
"total RHS" << std::endl;
1099 _console <<
"pressure RHS" << std::endl;
1100 coupling_pressure_gradient[system_i]->print();
1101 _console <<
" H(u)-rhs-relaxation_source" << std::endl;
1106 *working_vector_petsc = 1.0;
1107 Ainv.pointwise_divide(*working_vector_petsc, Ainv);
1110 HbyA.pointwise_mult(HbyA, Ainv);
1114 _console <<
" (H(u)-rhs)/A" << std::endl;
1126 _console <<
"Performing SIMPLEC projection." << std::endl;
1129 auto get_row_sum = [mmat](NumericVector<Number> & sum_vector)
1135 const auto local_size = mmat->local_m();
1137 for (
const auto row_i : make_range(local_size))
1140 const auto global_index = mmat->row_start() + row_i;
1141 std::vector<numeric_index_type> indices;
1142 std::vector<Real>
values;
1143 mmat->get_row(global_index, indices,
values);
1146 const Real row_sum = std::accumulate(
values.cbegin(),
values.cend(), 0.0);
1149 sum_vector.add(global_index, row_sum);
1155 auto row_sum = current_local_solution.zero_clone();
1156 get_row_sum(*row_sum);
1159 auto Ainv_full = current_local_solution.zero_clone();
1160 *working_vector_petsc = 1.0;
1161 Ainv_full->pointwise_divide(*working_vector_petsc, *row_sum);
1162 const auto Ainv_full_old = Ainv_full->clone();
1165 Ainv_full->add(-1.0, Ainv);
1166 working_vector_petsc->pointwise_mult(*Ainv_full, *coupling_pressure_gradient[system_i]);
1168 HbyA.add(-1.0, *working_vector_petsc);
1171 Ainv = *Ainv_full_old;
1188 _console <<
"************************************" << std::endl;
1189 _console <<
"DONE Computing HbyA " << std::endl;
1190 _console <<
"************************************" << std::endl;
1194const std::vector<NumericVector<Number> *> &
1210 "reconstructedGradientMethod() should only be called when reconstructed "
1211 "pressure gradients are active.");
1221 "The registered writable gradient method must match the pressure-gradient reader.");
1232 "' is missing a required pressure system, pressure-gradient field, base-gradient "
1233 "field, or pressure-correction diffusion kernel for reconstructed pressure "
1242 "' requires one linked momentum system per spatial component for reconstructed "
1243 "pressure gradients.");
1247 "FVReconstructedPressureGradient assumes the pressure and momentum systems each have "
1248 "exactly one variable so their DOF indices can be used in vector operations. Pressure "
1251 "' has variables: ",
1260 "' has an invalid momentum-system layout for component ",
1264 if (momentum_system->nVariables() != 1)
1265 mooseError(
"FVReconstructedPressureGradient assumes the pressure and momentum systems each "
1266 "have exactly one variable so their DOF indices can be used in vector operations. "
1267 "Momentum system '",
1268 momentum_system->name(),
1269 "' has variables: ",
boundary_id_type BoundaryID
const ExecFlagType EXEC_NONE
std::array< Real, 2 > values
registerMooseObject("NavierStokesApp", RhieChowMassFlux)
bool hasBlocks(const SubdomainName &name) const
virtual const std::set< SubdomainID > & blockIDs() const
const ConsoleStream _console
const Elem * elem() const
const std::vector< std::vector< dof_id_type > > & dofIndices() const
void addAvailableFlags(const ExecFlagType &flag, Args... flags)
FVGradientMethod & getFVGradientMethod(const GradientMethodName &name, const THREAD_ID tid=0)
virtual MooseMesh & mesh() override
TheWarehouse & theWarehouse() const
Gradient method that reconstructs and relaxes the pressure gradient used for Rhie-Chow momentum-press...
void finalizeCouplingPressureGradient(const RhieChowMassFlux &rc, const GradientView &base_gradient)
Relax and publish the current candidate as the coupling pressure gradient.
void validateSetup(const RhieChowMassFlux &rc) const
Validate the one-time Rhie-Chow linkage and field layouts required by reconstruction.
void linkFlowSystem(RhieChowMassFlux &rc, const LinearFVGradientReader &pressure_gradient)
Link this stateful method to one Rhie-Chow flow-system configuration.
void saveLaggedVelocityGradient(RhieChowMassFlux &rc)
Save the lagged cell velocity gradient used by the reconstruction.
void computeCandidateFromCorrectedFlux(const RhieChowMassFlux &rc)
Reconstruct the conservative pressure-gradient candidate from the corrected face flux.
void resetForTimeStep(const RhieChowMassFlux &rc)
Prepare solver-iteration state for a new time-step attempt.
A functor whose evaluation relies on querying a map where the keys are face info ids and the values c...
ValueType evaluate(const FaceInfo *const fi) const
Evaluate the face functor using a FaceInfo argument.
const Point & normal() const
VarFaceNeighbors faceType(const std::pair< unsigned int, unsigned int > &var_sys) const
const std::set< BoundaryID > & boundaryIDs() const
const Elem & elem() const
const Elem * neighborPtr() const
const ElemInfo * elemInfo() const
const ElemInfo * neighborInfo() const
const Elem * elemPtr() const
Moose::ElemArg makeElemArg(const Elem *elem, bool correct_skewnewss=false) const
virtual Real computeBoundaryRHSContribution(const LinearFVBoundaryCondition &bc) override
bool useNonorthogonalCorrection() const
virtual Real computeElemMatrixContribution() override
virtual Real computeNeighborMatrixContribution() override
virtual Real computeElemRightHandSideContribution() override
virtual Real computeBoundaryMatrixContribution(const LinearFVBoundaryCondition &bc) override
void setupFaceData(const FaceInfo *face_info, const FaceInfo::VarFaceNeighbors face_type)
virtual Real computeBoundaryValue() const=0
virtual void setupFaceData(const FaceInfo *face_info)
void setCurrentFaceArea(const Real area)
const GradientContainer & components() const
const FVGradientMethod & method() const
Kernel that adds the component of the pressure gradient in the momentum equations to the right hand s...
Pressure correction diffusion kernel for the linear finite volume SIMPLE algorithm.
Class implementing a flux boundary condition for linear finite volume pressure variables used in the ...
void computeGradientsExcept(const LinearFVGradientReader &excluded_reader)
void updateFVGradient(const LinearFVGradientReader &reader)
virtual System & system() override
Executioner * getExecutioner() const
const std::string & name() const
void paramError(const std::string ¶m, Args... args) const
void mooseError(Args &&... args) const
MooseApp & getMooseApp() const
const LinearFVGradientReader & requestCellGradients(unsigned int oldest_state=0)
Real getElemValue(const ElemInfo &elem_info, const StateArg &state) const
LinearFVBoundaryCondition * getBoundaryCondition(const BoundaryID bd_id) const
const std::string & getBoundaryName(const BoundaryID boundary_id) const
const std::vector< const FaceInfo * > & faceInfo() const
const std::vector< const ElemInfo * > & elemInfoVector() const
unsigned int number() const
bool isInternalFace(const FaceInfo &) const
static InputParameters validParams()
Executioner set up to solve a transient thermal-hydraulics problem using the PIMPLE algorithm.
static InputParameters validParams()
User object responsible for determining the face fluxes using the Rhie-Chow interpolation in a segreg...
const MooseMesh & _moose_mesh
The MooseMesh that this user object operates on.
void updateCellVelocity(const std::vector< GradientComponent > &pressure_gradient)
Update cell velocity from the supplied momentum-coupling pressure gradient.
const Moose::FV::InterpMethod _pressure_diffusion_interp_method
Interpolation method used for the pressure diffusion coefficient on faces.
MooseLinearVariableFVReal & velocityVariable(unsigned int component)
Velocity variable for one spatial component.
const LinearFVGradientReader & basePressureGradientField() const
Get the base pressure gradient field used to seed reconstructed gradient updates.
std::vector< std::unique_ptr< NumericVector< Number > > > _grad_p_current
Coupling pressure gradient captured before the current momentum predictor is assembled.
virtual void computeHbyA(bool verbose)
Computes the inverse of the diagonal (1/A) of the system matrix plus the H/A components for the press...
const LinearFVGradientReader * _pressure_gradient_field
Registered pressure gradient field used by Rhie-Chow and compatible momentum pressure kernels.
virtual void linkMomentumPressureSystems(const std::vector< LinearSystem * > &momentum_systems, LinearSystem &pressure_system, const std::vector< unsigned int > &momentum_system_numbers)
Update the momentum system-related information.
virtual void initFaceMassFlux()
Initialize the container for face velocities.
LinearFVPressureCorrectionDiffusion * _p_diffusion_kernel
Pointer to the pressure diffusion term in the pressure Poisson equation.
const std::vector< NumericVector< Number > * > & pressureGradientComponents() const
Get the registered pressure gradient component vectors.
Real velocityBoundaryValue(unsigned int component, const FaceInfo &fi, const Moose::FaceArg &boundary_face) const
Get the prescribed velocity value on a Dirichlet boundary face.
std::vector< unsigned int > _momentum_system_numbers
Numbers of the momentum system(s)
virtual void initialize() override
virtual void timestepSetup() override
Prepare reconstructed-gradient state once per attempted time step.
unsigned int _global_pressure_system_number
Global number of the pressure system.
const MooseLinearVariableFVReal *const _p
The thread 0 copy of the pressure variable.
Real getMassFlux(const FaceInfo &fi) const
Get the face velocity times density (used in advection terms)
std::vector< LinearSystem * > _momentum_systems
Pointers to the linear system(s) in moose corresponding to the momentum equation(s)
void finalizePressureCorrector()
After pressure relaxation, refresh every registered pressure gradient and publish relaxed reconstruct...
void preparePISOCorrector()
Capture the lagged velocity gradient for another corrector using the current predictor.
virtual void meshChanged() override
void populateCouplingFunctors(const std::vector< std::unique_ptr< NumericVector< Number > > > &raw_hbya, const std::vector< std::unique_ptr< NumericVector< Number > > > &raw_Ainv)
Populate the face values of the H/A and 1/A fields.
virtual void initialSetup() override
Real getVolumetricFaceFlux(const FaceInfo &fi) const
Get the volumetric face flux (used in advection terms)
std::vector< MooseLinearVariableFVReal * > _vel
Thread 0 copies of the velocity variables; non-const to allow writing cell velocities in updateCellVe...
void checkReconstructedPressureGradientCompatibility() const
Check the single-variable system layout assumed by reconstructed pressure-gradient vector ops.
void finalizeMomentumPredictor()
Capture the lagged velocity gradients computed while assembling the momentum predictor.
LinearSystem * _pressure_system
Pointer to the pressure system.
dof_id_type _face_mass_flux_generation
Producer counter for the conservative face mass flux: incremented every time computeFaceMassFlux() ru...
virtual void computeFaceMassFlux()
Update the values of the face velocities in the containers.
std::vector< std::unique_ptr< NumericVector< Number > > > _Ainv_raw
We hold on to the cell-based 1/A vectors so that we can easily reconstruct the cell velocities as wel...
const std::vector< std::unique_ptr< NumericVector< Number > > > & HbyAComponents() const
Get the momentum-layout H/A component vectors.
std::vector< const FaceInfo * > _flow_face_info
The subset of the FaceInfo objects that actually cover the subdomains which the flow field is defined...
void initPressureGradient()
Compute every registered pressure gradient once, before the first momentum predictor of a SIMPLE iter...
std::vector< std::unique_ptr< NumericVector< Number > > > _HbyA_raw
We hold on to the cell-based HbyA vectors so that we can easily reconstruct the cell velocities as we...
void checkBlocks(const VarType &var) const
Check the block consistency between the passed in var and us.
LinearSystem & momentumSystem(unsigned int component)
Momentum linear system for one spatial component.
FVReconstructedPressureGradient & reconstructedGradientMethod()
Access the reconstructed gradient method when it is selected.
void setupMeshInformation()
Compute the cell volumes on the mesh.
const Moose::Functor< Real > & _rho
Functor describing the density of the fluid.
std::vector< libMesh::LinearImplicitSystem * > _momentum_implicit_systems
Pointers to the momentum equation implicit system(s) from libmesh.
unsigned int pressureVariableNumber() const
Variable number of the pressure variable reconstructed by this object.
virtual void initCouplingField()
Initialize the coupling fields (HbyA and Ainv)
void preparePressureRelaxation()
Before pressure relaxation, form the conservative reconstructed candidate from the corrected face flu...
const std::vector< NumericVector< Number > * > & basePressureGradientComponents() const
Get the base-pressure gradient component vectors used to seed reconstructed updates.
FaceCenteredMapFunctor< RealVectorValue, std::unordered_map< dof_id_type, RealVectorValue > > _Ainv
A map functor from faces to $(1/A)_f$.
bool usingReconstructedPressureGradientMethod() const
Whether the registered pressure gradient field is produced by the reconstructed method.
const LinearFVGradientReader * _base_pressure_gradient_field
Base pressure gradient field used to seed reconstructed gradient updates.
void prepareMomentumPredictor()
Snapshot the fields read by the next momentum predictor.
const unsigned int _dim
The dimension of the mesh, e.g. 3 for hexes and tets, 2 for quads and tris.
RhieChowMassFlux(const InputParameters ¶ms)
const std::vector< std::unique_ptr< NumericVector< Number > > > & AinvComponents() const
Get the momentum-layout 1/A component vectors.
FaceCenteredMapFunctor< Real, std::unordered_map< dof_id_type, Real > > & _face_mass_flux
A map functor from faces to mass fluxes which are used in the advection terms.
const LinearFVGradientReader & pressureGradientField() const
Get the registered pressure gradient field used by compatible momentum pressure kernels.
static InputParameters validParams()
FaceCenteredMapFunctor< Real, std::unordered_map< dof_id_type, Real > > _HbyA_flux
A map functor from faces to $HbyA_{ij} = (A_{offdiag}*\mathrm{(predicted~velocity)} - \mathrm{Source}...
std::unique_ptr< NumericVector< Number > > _cell_fluid_volumes
Fluid volume of each cell, used to rapidly scale the pressure-gradient force in H/A and 1/A.
unsigned int dimension() const
Number of spatial dimensions of the coupled momentum/pressure systems.
const MooseEnum _pressure_projection_method
Enumerator for the method used for pressure projection.
std::vector< unsigned int > _global_momentum_system_numbers
Global numbers of the momentum system(s)
Real computeFacePressureGradientFlux(const FaceInfo &fi, PetscVectorReader &p_reader)
Compute the pressure-gradient flux contribution for a single face.
Executioner set up to solve a thermal-hydraulics problem using the SIMPLE algorithm.
virtual const NumericVector< Number > *const & currentSolution() const override final
virtual const MooseVariableFieldBase & getVariable(const THREAD_ID tid, const std::string &var_name, Moose::VarKindType expected_var_type=Moose::VarKindType::VAR_ANY, Moose::VarFieldType expected_var_field_type=Moose::VarFieldType::VAR_FIELD_ANY) const=0
void addFunctor(const std::string &name, const Moose::FunctorBase< T > &functor, const THREAD_ID tid)
virtual unsigned int nVariables() const
MooseVariableFieldBase & getVariable(THREAD_ID tid, const std::string &var_name) const
unsigned int number() const
const std::vector< VariableName > & getVariableNames() const
virtual const std::string & name() const
FEProblemBase & _fe_problem
virtual std::unique_ptr< NumericVector< T > > zero_clone() const=0
std::string stringify(const T &t)
static const std::string density
static const std::string pressure