31#include "libmesh/mesh_base.h"
32#include "libmesh/elem.h"
33#include "libmesh/elem_range.h"
34#include "libmesh/petsc_matrix.h"
46 params.addClassDescription(
"Computes H/A and 1/A together with face mass fluxes for segregated "
47 "momentum-pressure equations using linear systems.");
49 params.addRequiredParam<VariableName>(
NS::pressure,
"The pressure variable.");
50 params.addRequiredParam<VariableName>(
"u",
"The x-component of velocity");
51 params.addParam<VariableName>(
"v",
"The y-component of velocity");
52 params.addParam<VariableName>(
"w",
"The z-component of velocity");
53 params.addRequiredParam<std::string>(
55 "The LinearFVPressureCorrectionDiffusion kernel acting on the pressure.");
57 params.addRequiredParam<MooseFunctorName>(
NS::density,
"Density functor");
67 params.addParam<
MooseEnum>(
"pressure_projection_method",
68 MooseEnum(
"standard consistent",
"standard"),
69 "The method to use in the pressure projection for Ainv - "
70 "standard (SIMPLE) or consistent (SIMPLEC)");
72 "pressure_diffusion_interpolation",
74 "The face interpolation method for Ainv in the pressure correction diffusion term.");
82 _mesh(_moose_mesh.getMesh()),
83 _dim(blocksMaxDimension()),
85 &
UserObject::_subproblem.getVariable(0, getParam<VariableName>(
NS::pressure)))),
87 _HbyA_flux(_moose_mesh, blockIDs(),
"HbyA_flux"),
88 _Ainv(_moose_mesh, blockIDs(),
"Ainv"),
91 "face_flux", _moose_mesh, blockIDs(),
"face_values")),
92 _rho(getFunctor<Real>(
NS::density)),
93 _pressure_system(nullptr),
94 _pressure_gradient_field(nullptr),
95 _base_pressure_gradient_field(nullptr),
96 _global_pressure_system_number(0),
97 _pressure_projection_method(getParam<
MooseEnum>(
"pressure_projection_method")),
98 _pressure_diffusion_interp_method(getParam<
MooseEnum>(
"pressure_diffusion_interpolation") ==
100 ?
Moose::FV::InterpMethod::HarmonicAverage
101 :
Moose::FV::InterpMethod::Average)
107 std::vector<std::string> vel_names = {
"u",
"v",
"w"};
108 for (
const auto i : index_range(
_vel))
114 paramError(vel_names[i],
"the velocity must be a MOOSELinearVariableFVReal.");
128 " should only be used with a linear segregated thermal-hydraulics solver!");
133 const std::vector<LinearSystem *> & momentum_systems,
135 const std::vector<unsigned int> & momentum_system_numbers)
142 auto *
const pressure_var =
145 mooseError(
"The pressure variable in system '",
147 "' must be a MooseLinearVariableFVReal.");
153 std::vector<std::vector<const LinearFVMomentumPressure *>> applicable_kernels(
154 momentum_systems.size());
155 for (
const auto system_index : index_range(momentum_systems))
157 std::vector<LinearFVElementalKernel *> kernels;
160 .template condition<AttribThread>(
_tid)
161 .template condition<AttribSystem>(
"LinearFVElementalKernel")
162 .template condition<AttribSysNum>(momentum_system_numbers[system_index])
165 for (
const auto *
const kernel : kernels)
168 if (candidate && MooseUtils::setsIntersect(candidate->blockIDs(),
blockIDs()))
169 applicable_kernels[system_index].push_back(candidate);
173 for (
const auto system_index : index_range(momentum_systems))
175 const auto & kernels = applicable_kernels[system_index];
176 const auto & system_name = momentum_systems[system_index]->
name();
179 std::set<SubdomainID> covered_blocks;
180 for (
const auto *
const kernel : kernels)
181 covered_blocks.insert(kernel->blockIDs().begin(), kernel->blockIDs().end());
183 std::set<SubdomainID> missing_blocks;
184 std::set_difference(
blockIDs().begin(),
186 covered_blocks.begin(),
187 covered_blocks.end(),
188 std::inserter(missing_blocks, missing_blocks.end()));
190 if (!missing_blocks.empty())
193 "' found no applicable LinearFVMomentumPressure kernel for momentum system '",
200 for (
const auto i : index_range(kernels))
202 if (kernels[i]->momentumComponent() != system_index)
203 mooseError(
"LinearFVMomentumPressure kernel '",
205 "' declares momentum component ",
206 kernels[i]->momentumComponent(),
207 " but is linked to momentum system '",
211 ") through RhieChowMassFlux '",
215 for (
const auto j : make_range(i + 1, kernels.size()))
217 std::set<SubdomainID> overlap;
218 for (
const auto block : kernels[i]->blockIDs())
219 if (
hasBlocks(block) && kernels[j]->blockIDs().count(block))
220 overlap.insert(block);
221 if (!overlap.empty())
224 "' has more than one LinearFVMomentumPressure kernel contributing a "
225 "pressure source on the same block(s) for RhieChowMassFlux '",
231 "' overlap on block(s) ",
241 std::vector<const LinearFVMomentumPressure *> momentum_pressure_kernels;
242 for (
auto & kernels : applicable_kernels)
243 momentum_pressure_kernels.insert(
244 momentum_pressure_kernels.end(), kernels.begin(), kernels.end());
246 const auto *
const coupling_kernel = momentum_pressure_kernels.front();
247 const auto & coupling_reader = coupling_kernel->pressureGradientField();
250 coupling_kernel->pressureVariableNumber() !=
_p->
number())
251 mooseError(
"FVReconstructedPressureGradient can only be used for the pressure variable "
252 "registered on RhieChowMassFlux '",
256 for (
const auto *
const kernel : momentum_pressure_kernels)
258 const auto & reader = kernel->pressureGradientField();
260 if (&reader.system() != &coupling_reader.system() ||
261 reader.systemNumber() != coupling_reader.systemNumber())
264 "': momentum pressure kernels '",
265 coupling_kernel->name(),
272 ") must use pressure gradients from the same system.");
274 if (reader.variableNumber() != coupling_reader.variableNumber())
277 "': momentum pressure kernels '",
278 coupling_kernel->name(),
279 "' (pressure variable number ",
280 coupling_reader.variableNumber(),
283 "' (pressure variable number ",
284 reader.variableNumber(),
285 ") must use the same pressure variable.");
287 if (&reader.method() != &coupling_reader.method())
290 "': momentum pressure kernels '",
291 coupling_kernel->name(),
294 "' must use the same pressure gradient method.");
296 if (&reader.components() != &coupling_reader.components())
299 "': momentum pressure kernels '",
300 coupling_kernel->name(),
303 "' must share the same registered pressure gradient field.");
311 const auto & base_reader =
316 "Reconstructed and base pressure gradient readers must be distinct when "
317 "FVReconstructedPressureGradient is active.");
336 "FVReconstructedPressureGradient with nonorthogonal pressure diffusion requires "
337 "the consistent pressure projection.");
342 std::set<BoundaryID> velocity_boundary_ids;
343 for (
const auto dim_i : make_range(
_dim))
344 for (
const auto & [boundary_id, _] :
_vel[dim_i]->getBoundaryConditionMap())
345 velocity_boundary_ids.insert(boundary_id);
347 const auto is_dirichlet =
356 for (
const auto boundary_id : velocity_boundary_ids)
362 const bool velocity_is_dirichlet = is_dirichlet(*
_vel[0], boundary_id);
363 for (
const auto dim_i : make_range(
_dim))
364 if (is_dirichlet(*
_vel[dim_i], boundary_id) != velocity_is_dirichlet)
365 mooseError(
"All velocity components must either have Dirichlet boundary conditions or "
366 "non-Dirichlet boundary conditions on boundary '",
368 "' when the pressure boundary condition is not a LinearFVPressureFluxBC.");
404 "The pressure gradient field must be linked before preparing momentum.");
425 "A momentum predictor must be prepared before another PISO corrector.");
427 for (
const auto component : make_range(
dimension()))
474 std::vector<LinearFVFluxKernel *> flux_kernel;
477 .template condition<AttribThread>(
_tid)
478 .template condition<AttribSysNum>(
_p->
sys().
number())
479 .template condition<AttribSystem>(
"LinearFVFluxKernel")
480 .template condition<AttribName>(getParam<std::string>(
"p_diffusion_kernel"))
481 .queryInto(flux_kernel);
482 if (flux_kernel.size() != 1)
484 "p_diffusion_kernel",
485 "The kernel with the given name could not be found or multiple instances were identified.");
489 "The provided diffusion kernel must be of type "
490 "LinearFVPressureCorrectionDiffusion.");
502 if (
hasBlocks(elem_info->subdomain_id()))
505 _cell_volumes->set(elem_dof, elem_info->volume() * elem_info->coordFactor());
512 if (
hasBlocks(fi->elemPtr()->subdomain_id()) ||
513 (fi->neighborPtr() &&
hasBlocks(fi->neighborPtr()->subdomain_id())))
517template <
typename GradientComponent>
524 auto working_vector =
_Ainv_raw[system_i]->clone();
525 working_vector->pointwise_mult(*working_vector, *pressure_gradient[system_i]);
526 working_vector->add(*
_HbyA_raw[system_i]);
527 working_vector->scale(-1.0);
537 auto defect =
_Ainv_raw[system_i]->clone();
538 defect->pointwise_mult(*defect, *pressure_gradient[system_i]);
541 mooseAssert(MooseUtils::absoluteFuzzyEqual(defect->linfty_norm(), 0.0, 1e-10),
542 "RhieChowMassFlux: cell-velocity update violates the momentum-coupling "
543 "identity u + H/A + Ainv*grad(p) = 0.");
559 for (
const auto & pair :
_Ainv)
560 _Ainv[pair.first] = 0;
574 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 *
607 raw_value((*
_vel[dim_i])(boundary_face, time_arg));
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 ",
651 Moose::FV::LimiterType::CentralDifference,
657 if (!std::isfinite(face_rho) || face_rho <= 0.0)
660 "' requires finite, positive density for corrected face flux reconstruction, but "
665 " adjacent to cell ID ",
667 " and neighbor cell ID ",
671 const Real volumetric_flux = face_flux->second / face_rho;
672 if (!std::isfinite(volumetric_flux))
675 "' computed non-finite volumetric flux ",
679 " adjacent to cell ID ",
681 " and neighbor cell ID ",
685 return volumetric_flux;
693 "The pressure gradient field has not been registered for RhieChowMassFlux '",
name(),
"'.");
702 mooseError(
"The base pressure gradient field has not been registered for RhieChowMassFlux '",
709const std::vector<std::unique_ptr<NumericVector<Number>>> &
712 mooseAssert(!
_HbyA_raw.empty(),
"HbyA data is not ready.");
717const std::vector<std::unique_ptr<NumericVector<Number>>> &
720 mooseAssert(!
_Ainv_raw.empty(),
"Ainv data is not ready.");
725const std::vector<NumericVector<Number> *> &
742 bool libmesh_dbg_var(subtract_mesh_velocity))
const
744 mooseAssert(!subtract_mesh_velocity,
"RhieChowMassFlux does not support moving meshes yet!");
746 if (m != Moose::FV::InterpMethod::RhieChow)
747 mooseError(
"Interpolation methods other than Rhie-Chow are not supported!");
749 mooseError(
"Older interpolation times are not supported!");
775 Real p_grad_flux = 0.0;
778 const auto & elem_info = *fi->
elemInfo();
786 const auto p_elem_value = p_reader(elem_dof);
787 const auto p_neighbor_value = p_reader(neighbor_dof);
791 const auto neighbor_matrix_contribution =
793 const auto elem_rhs_contribution =
797 p_grad_flux = (p_neighbor_value * neighbor_matrix_contribution +
798 p_elem_value * elem_matrix_contribution) -
799 elem_rhs_contribution;
803 mooseAssert(fi->
boundaryIDs().size() == 1,
"We should only have one boundary on every face.");
805 bc_pointer->setupFaceData(
811 const auto matrix_contribution =
813 const auto rhs_contribution =
817 p_grad_flux = (p_elem_value * matrix_contribution - rhs_contribution);
841 const std::vector<std::unique_ptr<NumericVector<Number>>> & raw_hbya,
842 const std::vector<std::unique_ptr<NumericVector<Number>>> & raw_Ainv)
850 std::vector<PetscVectorReader> hbya_reader;
851 for (
const auto dim_i : index_range(raw_hbya))
852 hbya_reader.emplace_back(*raw_hbya[dim_i]);
854 std::vector<PetscVectorReader> ainv_reader;
855 for (
const auto dim_i : index_range(raw_Ainv))
856 ainv_reader.emplace_back(*raw_Ainv[dim_i]);
862 RealVectorValue face_hbya;
868 if (
_vel[0]->isInternalFace(*fi))
871 const auto & elem_info = *fi->
elemInfo();
882 interpolate(Moose::FV::InterpMethod::Average, face_rho, elem_rho, neighbor_rho, *fi,
true);
883 for (
const auto dim_i : index_range(raw_hbya))
885 interpolate(Moose::FV::InterpMethod::Average,
887 hbya_reader[dim_i](elem_dof),
888 hbya_reader[dim_i](neighbor_dof),
893 elem_rho * ainv_reader[dim_i](elem_dof),
894 neighbor_rho * ainv_reader[dim_i](neighbor_dof),
904 const Real boundary_normal_multiplier = elem_is_fluid ? 1.0 : -1.0;
909 mooseAssert(fi->
boundaryIDs().size() == 1,
"We should only have one boundary on every face.");
916 if (
_vel[0]->isDirichletBoundaryFace(*fi) &&
920 fi, Moose::FV::LimiterType::CentralDifference,
true,
false, elem_info.
elem(),
nullptr};
923 for (
const auto dim_i : make_range(
_dim))
928 face_hbya(dim_i) *= boundary_normal_multiplier;
937 for (
const auto dim_i : make_range(
_dim))
938 face_hbya(dim_i) = boundary_normal_multiplier * hbya_reader[dim_i](elem_dof);
943 for (
const auto dim_i : index_range(raw_Ainv))
944 Ainv(dim_i) = elem_rho * ainv_reader[dim_i](elem_dof);
956 _console <<
"************************************" << std::endl;
957 _console <<
"Computing HbyA" << std::endl;
958 _console <<
"************************************" << std::endl;
961 "The momentum system shall be linked before calling this function!");
964 "A coupling pressure-gradient snapshot must exist before computing H/A.");
966 "The coupling pressure-gradient snapshot must have one component per momentum "
974 mooseAssert(snapshot.size() == momentum_layout.size() &&
975 snapshot.local_size() == momentum_layout.local_size() &&
976 snapshot.first_local_index() == momentum_layout.first_local_index() &&
977 snapshot.last_local_index() == momentum_layout.last_local_index(),
978 "The coupling pressure-gradient snapshot layout must match its momentum system.");
991 NumericVector<Number> & rhs = *(momentum_system->rhs);
992 NumericVector<Number> & current_local_solution = *(momentum_system->current_local_solution);
993 NumericVector<Number> & solution = *(momentum_system->solution);
994 PetscMatrix<Number> * mmat =
dynamic_cast<PetscMatrix<Number> *
>(momentum_system->matrix);
996 "The matrices used in the segregated INSFVRhieChow objects need to be convertable "
1001 _console <<
"Matrix in rc object" << std::endl;
1006 _Ainv_raw.push_back(current_local_solution.zero_clone());
1007 NumericVector<Number> & Ainv = *(
_Ainv_raw.back());
1009 mmat->get_diagonal(Ainv);
1013 _console <<
"Velocity solution in H(u)" << std::endl;
1018 _HbyA_raw.push_back(current_local_solution.zero_clone());
1019 NumericVector<Number> & HbyA = *(
_HbyA_raw.back());
1028 auto working_vector = momentum_system->current_local_solution->zero_clone();
1029 PetscVector<Number> * working_vector_petsc =
1030 dynamic_cast<PetscVector<Number> *
>(working_vector.get());
1031 mooseAssert(working_vector_petsc,
1032 "The vectors used in the RhieChowMassFlux objects need to be convertable "
1033 "to PetscVectors!");
1035 mmat->vector_mult(HbyA, solution);
1036 working_vector_petsc->pointwise_mult(Ainv, solution);
1037 HbyA.add(-1.0, *working_vector_petsc);
1046 HbyA.add(-1.0, rhs);
1051 working_vector_petsc->pointwise_mult(*coupling_pressure_gradient[system_i], *
_cell_volumes);
1052 HbyA.add(-1.0, *working_vector_petsc);
1056 _console <<
"total RHS" << std::endl;
1058 _console <<
"pressure RHS" << std::endl;
1059 coupling_pressure_gradient[system_i]->print();
1060 _console <<
" H(u)-rhs-relaxation_source" << std::endl;
1065 *working_vector_petsc = 1.0;
1066 Ainv.pointwise_divide(*working_vector_petsc, Ainv);
1069 HbyA.pointwise_mult(HbyA, Ainv);
1073 _console <<
" (H(u)-rhs)/A" << std::endl;
1085 _console <<
"Performing SIMPLEC projection." << std::endl;
1088 auto get_row_sum = [mmat](NumericVector<Number> & sum_vector)
1094 const auto local_size = mmat->local_m();
1096 for (
const auto row_i : make_range(local_size))
1099 const auto global_index = mmat->row_start() + row_i;
1100 std::vector<numeric_index_type> indices;
1101 std::vector<Real>
values;
1102 mmat->get_row(global_index, indices,
values);
1105 const Real row_sum = std::accumulate(
values.cbegin(),
values.cend(), 0.0);
1108 sum_vector.add(global_index, row_sum);
1114 auto row_sum = current_local_solution.zero_clone();
1115 get_row_sum(*row_sum);
1118 auto Ainv_full = current_local_solution.zero_clone();
1119 *working_vector_petsc = 1.0;
1120 Ainv_full->pointwise_divide(*working_vector_petsc, *row_sum);
1121 const auto Ainv_full_old = Ainv_full->clone();
1124 Ainv_full->add(-1.0, Ainv);
1125 working_vector_petsc->pointwise_mult(*Ainv_full, *coupling_pressure_gradient[system_i]);
1126 working_vector_petsc->pointwise_mult(*working_vector_petsc, *
_cell_volumes);
1127 HbyA.add(-1.0, *working_vector_petsc);
1130 Ainv = *Ainv_full_old;
1147 _console <<
"************************************" << std::endl;
1148 _console <<
"DONE Computing HbyA " << std::endl;
1149 _console <<
"************************************" << std::endl;
1153const std::vector<NumericVector<Number> *> &
1169 "reconstructedGradientMethod() should only be called when reconstructed "
1170 "pressure gradients are active.");
1180 "The registered writable gradient method must match the pressure-gradient reader.");
1191 "' is missing a required pressure system, pressure-gradient field, base-gradient "
1192 "field, or pressure-correction diffusion kernel for reconstructed pressure "
1201 "' requires one linked momentum system per spatial component for reconstructed "
1202 "pressure gradients.");
1206 "FVReconstructedPressureGradient assumes the pressure and momentum systems each have "
1207 "exactly one variable so their DOF indices can be used in vector operations. Pressure "
1210 "' has variables: ",
1219 "' has an invalid momentum-system layout for component ",
1223 if (momentum_system->nVariables() != 1)
1224 mooseError(
"FVReconstructedPressureGradient assumes the pressure and momentum systems each "
1225 "have exactly one variable so their DOF indices can be used in vector operations. "
1226 "Momentum system '",
1227 momentum_system->name(),
1228 "' 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
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.
const LinearFVGradientReader * _pressure_gradient_field
Registered pressure gradient field used by Rhie-Chow and compatible momentum pressure kernels.
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.
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.
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.
std::unique_ptr< NumericVector< Number > > _cell_volumes
We will hold a vector of cell volumes to make sure we can do volume corrections rapidly.
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...
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...
void computeHbyA(const bool verbose)
Computes the inverse of the diagonal (1/A) of the system matrix plus the H/A components for the press...
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.
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}...
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)
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