20#include "libmesh/dense_matrix.h"
21#include "libmesh/dense_vector.h"
22#include "libmesh/elem.h"
37 "Reconstructs and relaxes the pressure gradient used for Rhie-Chow momentum coupling.");
39 "base_gradient_method",
41 "Gradient method used before Rhie-Chow has computed reconstructed gradients.");
45 "gradient_relaxation",
47 "0.0<gradient_relaxation<=1.0",
48 "Relaxation factor applied when updating the reconstructed pressure-coupling gradient.");
55 _base_gradient_method_name(getParam<GradientMethodName>(
"base_gradient_method")),
56 _gradient_relaxation(getParam<
Real>(
"gradient_relaxation"))
65 "First binding must use the pressure system owned by the RhieChowMassFlux.");
68 "First binding must use the pressure variable registered on the RhieChowMassFlux.");
86 mooseError(
"FVReconstructedPressureGradient '",
88 "' is already bound to RhieChowMassFlux '",
90 "' and cannot also be used by RhieChowMassFlux '",
95 mooseError(
"FVReconstructedPressureGradient '",
97 "' is already bound to pressure system '",
99 "' and cannot also be used by pressure system '",
104 mooseError(
"FVReconstructedPressureGradient '",
106 "' is already bound to pressure variable number ",
108 " and cannot also be used by pressure variable number ",
113 mooseError(
"FVReconstructedPressureGradient '",
115 "' cannot be reused with a different set of momentum systems.");
119 mooseError(
"FVReconstructedPressureGradient '",
121 "' cannot be reused with a different set of momentum systems.");
128 "FVReconstructedPressureGradient must be bound to one RhieChowMassFlux before it "
132 "FVReconstructedPressureGradient is bound to a single RhieChowMassFlux and cannot "
133 "be used by another.");
143 "FVReconstructedPressureGradient must be linked to the pressure field owned by its "
144 "bound RhieChowMassFlux.");
147 if (pressure_variable.blockIDs() != rc.
blockIDs())
148 mooseError(
"FVReconstructedPressureGradient '",
150 "' requires pressure variable '",
151 pressure_variable.name(),
152 "' and RhieChowMassFlux '",
154 "' to have identical block restrictions. Pressure blocks: ",
156 "; Rhie-Chow blocks: ",
162 "One momentum system and velocity-gradient field must be registered per spatial "
168 "Momentum system linkage must match the RhieChowMassFlux for every spatial "
172 if (velocity_variable.blockIDs() != rc.
blockIDs())
173 mooseError(
"FVReconstructedPressureGradient '",
175 "' requires velocity variable '",
176 velocity_variable.name(),
177 "' and RhieChowMassFlux '",
179 "' to have identical block restrictions. Velocity blocks: ",
181 "; Rhie-Chow blocks: ",
186 mooseAssert(velocity_gradient &&
189 "Velocity-gradient field linkage must match the RhieChowMassFlux for every "
190 "momentum component.");
198 mooseError(
"FVReconstructedPressureGradient '",
200 "' cannot use itself as its base_gradient_method.");
220 const std::unordered_set<unsigned int> & variable_numbers)
const
229 "resolveGradientMethodDependencies() must run before gradients are computed.");
235 "FVReconstructedPressureGradient can only compute gradients for the pressure "
236 "system it is bound to.");
239 "FVReconstructedPressureGradient can only compute the pressure variable to which "
247 "resolveGradientMethodDependencies() must run before gradients are computed.");
253 "Coupling and destination gradients must have equal component counts.");
256 mooseAssert(gradient[component]->
type() ==
GHOSTED,
257 "Linear FV gradient storage must be ghosted.");
270 if (destination.empty())
272 destination.reserve(source.size());
274 destination.push_back(source[component]->clone());
278 mooseAssert(source.size() == destination.size(),
279 "Source and destination gradients must have equal component counts.");
283 source[component]->size() == destination[component]->size() &&
284 source[component]->local_size() == destination[component]->local_size() &&
285 source[component]->first_local_index() == destination[component]->first_local_index() &&
286 source[component]->last_local_index() == destination[component]->last_local_index(),
287 "Source and destination gradient component vectors must have matching parallel "
289 *destination[component] = *source[component];
300 "Reconstruction-cycle transition requested from an unexpected state.");
352 "A velocity gradient field must be registered for every momentum component.");
360 for (
const auto component :
make_range(dimension))
370 const bool elem_has_info,
371 const unsigned int velocity_component)
const
379 return elem_gradient;
384 for (
const auto direction :
make_range(dimension))
385 neighbor_gradient(direction) =
387 neighbor_info->
dofIndices()[system_number][velocity.number()]);
397 return face_gradient;
404 const std::vector<RealVectorValue> & elem_velocity_gradients,
406 const Point & surface_vector,
407 const bool elem_has_info,
411 mooseAssert(fi,
"FaceInfo must be available while reconstructing a cell.");
413 const Real surface_area = surface_vector.
norm();
416 if (surface_area == 0.0)
419 const auto pressure_face_type =
424 const Real normal_alignment =
425 pressure_face_type == FaceInfo::VarFaceNeighbors::BOTH && !elem_has_info ? -1.0 : 1.0;
427 mooseAssert(std::isfinite(face_flux),
"Corrected face flux must be finite.");
428 Real face_normal_reconstructed_quantity = face_flux * normal_alignment;
435 Real gradient_flux_correction = 0.0;
439 rc, elem_velocity_gradients[component], *fi, elem_has_info, component);
441 mooseAssert(std::isfinite(velocity_gradient(direction)),
442 "Lagged velocity gradient must be finite.");
444 gradient_flux_correction += (velocity_gradient * d_pf) * surface_vector(component);
447 face_normal_reconstructed_quantity -= gradient_flux_correction / surface_area;
454 projection_rhs(i) += face_normal_reconstructed_quantity * surface_vector(i);
456 matrix(i, j) += surface_vector(i) * surface_vector(j) / surface_area;
464 const auto dimension = projection_rhs.
size();
467 reconstructed_quantity(0) = projection_rhs(0) / matrix(0, 0);
473 solve_matrix.
cholesky_solve(projection_rhs, reconstructed_quantity);
476 return reconstructed_quantity;
483 const unsigned int component,
484 const Real reconstructed_velocity)
const
486 mooseAssert(std::isfinite(reconstructed_velocity),
487 "Reconstructed velocity component must be finite.");
492 if (!std::isfinite(HbyA) || !std::isfinite(Ainv) || Ainv == 0.0)
493 mooseError(
"FVReconstructedPressureGradient '",
495 "' found invalid momentum-coupling data for component ",
508 const Real reconstructed_gradient = (-reconstructed_velocity - HbyA) / Ainv;
509 mooseAssert(std::isfinite(reconstructed_gradient),
510 "Reconstructed pressure-gradient component must be finite.");
512 return reconstructed_gradient;
525 mooseAssert(base_pressure_gradient.size() == dimension,
526 "A base pressure-gradient component must exist for every spatial dimension.");
529 "The current pressure corrector must produce a new face flux before "
533 for (
const auto component :
make_range(dimension))
539 pressure_gradient->zero();
542 const auto rz_radial_coord =
mesh.getAxisymmetricRadialCoord();
543 std::vector<RealVectorValue> elem_velocity_gradients(dimension);
545 for (
const auto & elem_info :
mesh.elemInfoVector())
547 if (!rc.
hasBlocks(elem_info->subdomain_id()))
550 const Elem & elem = *elem_info->elem();
554 projection_rhs.
zero();
556 for (
const auto component :
make_range(dimension))
560 const auto velocity_dof = elem_info->dofIndices()[system_number][velocity.number()];
561 for (
const auto direction :
make_range(dimension))
563 const auto gradient =
565 mooseAssert(std::isfinite(gradient),
"Lagged velocity gradient must be finite.");
566 elem_velocity_gradients[component](direction) = gradient;
572 auto act = [&](
const Elem &,
575 const Point & surface_vector,
577 const bool elem_has_info)
581 elem_velocity_gradients,
594 const auto pressure_dof =
596 for (
const auto component :
make_range(dimension))
598 const auto reconstructed_gradient =
605 pressure_gradient->close();
615 "No reconstructed pressure-gradient candidate is ready for the conservative "
616 "cell-velocity correction.");
626 mooseAssert(!base_gradient.empty() && reconstructed_candidate.size() == base_gradient.size(),
627 "Base and reconstructed gradients must have equal nonzero component counts.");
636 for (
const auto & elem_info :
mesh.elemInfoVector())
638 if (!rc.
hasBlocks(elem_info->subdomain_id()))
641 const auto pressure_dof =
645 const auto updated_gradient =
registerMooseObject("NavierStokesApp", FVReconstructedPressureGradient)
bool hasBlocks(const SubdomainName &name) const
virtual const std::set< SubdomainID > & blockIDs() const
SubdomainID subdomain_id() const
const Elem * elem() const
const std::vector< std::vector< dof_id_type > > & dofIndices() const
const Point & centroid() const
virtual void addFVGradientMethod(const std::string &method_type, const std::string &name, InputParameters ¶meters)
FVGradientMethod & getFVGradientMethod(const GradientMethodName &name, const THREAD_ID tid=0)
bool hasFVGradientMethod(const GradientMethodName &name) const
virtual MooseMesh & mesh() override
static InputParameters validParams()
void computeGradient(SystemBase &system, GradientContainer &gradient, const std::unordered_set< unsigned int > &variable_numbers) const
Gradient method that reconstructs and relaxes the pressure gradient used for Rhie-Chow momentum-press...
virtual void meshChanged() override
void updateCouplingPressureGradient(const RhieChowMassFlux &rc, const GradientView &base_gradient, const GradientContainer &reconstructed_candidate)
Blend a reconstructed candidate into the persistent coupling pressure gradient.
void finalizeCouplingPressureGradient(const RhieChowMassFlux &rc, const GradientView &base_gradient)
Relax and publish the current candidate as the coupling pressure gradient.
LinearFVGradientReader::GradientContainer GradientView
std::vector< std::vector< std::unique_ptr< NumericVector< Number > > > > _lagged_reconstruction_velocity_gradient
Lagged velocity gradients indexed by velocity component and spatial direction.
void resolveGradientMethodDependencies(FEProblemBase &fe_problem) override
DenseVector< Real > solveFaceProjection(const DenseMatrix< Real > &matrix, const DenseVector< Real > &projection_rhs) const
Solve a cell's velocity-projection system.
void validateSetup(const RhieChowMassFlux &rc) const
Validate the one-time Rhie-Chow linkage and field layouts required by reconstruction.
Real reconstructPressureGradient(const RhieChowMassFlux &rc, const ElemInfo &elem_info, unsigned int component, Real reconstructed_velocity) const
Invert one diagonal momentum equation to recover a pressure-gradient component.
FVReconstructedPressureGradient(const InputParameters ¶ms)
static InputParameters validParams()
PressureGradientReconstructionState _reconstruction_state
Current position in the pressure-gradient reconstruction cycle.
void linkFlowSystem(RhieChowMassFlux &rc, const LinearFVGradientReader &pressure_gradient)
Link this stateful method to one Rhie-Chow flow-system configuration.
void transition(PressureGradientReconstructionEvent event)
Apply and validate one reconstruction-cycle transition.
void assembleFaceProjection(const RhieChowMassFlux &rc, const ElemInfo &elem_info, const std::vector< RealVectorValue > &elem_velocity_gradients, const FaceInfo *fi, const Point &surface_vector, bool elem_has_info, DenseMatrix< Real > &matrix, DenseVector< Real > &projection_rhs) const
Add one face's contribution to the area-weighted least-squares system that reconstructs the cell velo...
const GradientMethodName _base_gradient_method_name
Gradient method used before the reconstructed coupling pressure gradient exists.
GradientContainer _reconstructed_pressure_gradient
Reconstructed pressure-gradient candidate.
dof_id_type _last_reconstructed_face_flux_iteration
Corrected face-flux iteration used by the previous reconstruction.
RealVectorValue reconstructionVelocityGradient(const RhieChowMassFlux &rc, const RealVectorValue &elem_gradient, const FaceInfo &fi, bool elem_has_info, unsigned int velocity_component) const
Interpolate a lagged velocity-component gradient to a face.
void saveLaggedVelocityGradient(RhieChowMassFlux &rc)
Save the lagged cell velocity gradient used by the reconstruction.
const GradientContainer & reconstructedCandidate(const RhieChowMassFlux &rc) const
Get the conservative candidate produced by the current pressure corrector.
void copyGradient(const GradientView &source, GradientContainer &destination)
Copy gradient values while reusing compatible destination storage.
const FVGradientMethod * _base_gradient_method
Resolved method used before the reconstructed coupling pressure gradient exists.
void computeCandidateFromCorrectedFlux(const RhieChowMassFlux &rc)
Reconstruct the conservative pressure-gradient candidate from the corrected face flux.
void checkFlowSystem(const RhieChowMassFlux &rc) const
Check that a stateful operation is requested by the bound Rhie-Chow object.
void computeGradientWithoutLimiter(SystemBase &system, GradientContainer &gradient, const std::unordered_set< unsigned int > &variable_numbers) const override
GradientContainer _coupling_pressure_gradient
Persistent coupling pressure gradient.
PressureGradientReconstructionEvent
Operations that advance or reset the pressure-gradient reconstruction cycle.
@ Reset
Reset the cycle to require a new lagged velocity-gradient snapshot.
@ ReconstructCandidate
Record that a pressure-gradient candidate has been reconstructed.
@ PublishCandidate
Record that the reconstructed candidate has been published.
@ SaveLaggedVelocityGradient
Record that the lagged velocity-gradient snapshot has been saved.
std::vector< const SystemBase * > _momentum_systems
Momentum systems coupled through the owning Rhie-Chow object.
std::vector< const LinearFVGradientReader * > _velocity_gradient_fields
Ordinary gradient fields for the velocity components.
FVGradientMethod::GradientContainer GradientContainer
const Real _gradient_relaxation
Relaxation factor applied to reconstructed pressure gradients.
const SystemBase * _pressure_system
Pressure system that owns the reconstructed pressure variable.
const RhieChowMassFlux * _rhie_chow
Rhie-Chow object that owns this stateful reconstruction method.
unsigned int _pressure_variable_number
Pressure variable reconstructed by this method.
PressureGradientReconstructionState
Current stage of the pressure-gradient reconstruction cycle.
@ CandidateReady
The reconstructed candidate is available and ready to be published.
@ NeedLaggedVelocityGradient
The next reconstruction cycle requires a lagged velocity-gradient snapshot.
@ NeedCandidate
The lagged velocity gradient is available and a reconstructed candidate is required.
void resetForTimeStep(const RhieChowMassFlux &rc)
Prepare solver-iteration state for a new time-step attempt.
VarFaceNeighbors faceType(const std::pair< unsigned int, unsigned int > &var_sys) const
const ElemInfo * elemInfo() const
const ElemInfo * neighborInfo() const
const Point & faceCentroid() const
const GradientContainer & components() const
const SystemBase & system() const
unsigned int variableNumber() const
static InputParameters validParams()
const std::string & type() const
const std::string & name() const
void mooseError(Args &&... args) const
MooseApp & getMooseApp() const
const LinearFVGradientReader & requestCellGradients(unsigned int oldest_state=0)
unsigned int number() const
User object responsible for determining the face fluxes using the Rhie-Chow interpolation in a segreg...
MooseLinearVariableFVReal & velocityVariable(unsigned int component)
Velocity variable for one spatial component.
const LinearSystem & pressureSystem() const
Pressure linear system.
Real getVolumetricFaceFlux(const FaceInfo &fi) const
Get the volumetric face flux (used in advection terms)
const std::vector< std::unique_ptr< NumericVector< Number > > > & HbyAComponents() const
Get the momentum-layout H/A component vectors.
dof_id_type faceMassFluxGeneration() const
Producer counter for the conservative face mass flux: incremented every time computeFaceMassFlux() ru...
LinearSystem & momentumSystem(unsigned int component)
Momentum linear system for one spatial component.
unsigned int pressureVariableNumber() const
Variable number of the pressure variable reconstructed by this object.
const std::vector< NumericVector< Number > * > & basePressureGradientComponents() const
Get the base-pressure gradient component vectors used to seed reconstructed updates.
const std::vector< std::unique_ptr< NumericVector< Number > > > & AinvComponents() const
Get the momentum-layout 1/A component vectors.
const LinearFVGradientReader & pressureGradientField() const
Get the registered pressure gradient field used by compatible momentum pressure kernels.
unsigned int dimension() const
Number of spatial dimensions of the coupled momentum/pressure systems.
MooseVariableFieldBase & getVariable(THREAD_ID tid, const std::string &var_name) const
unsigned int number() const
FEProblemBase & feProblem()
virtual const std::string & name() const
void cholesky_solve(const DenseVector< T2 > &b, DenseVector< T2 > &x)
virtual void zero() override final
virtual void zero() override final
virtual unsigned int size() const override final
subdomain_id_type subdomain_id() const
void interpolate(InterpMethod m, T &result, const T2 &value1, const T3 &value2, const FaceInfo &fi, const bool one_is_elem)
void loopOverElemFaceInfo(const Elem &elem, const MooseMesh &mesh, ActionFunctor &act, const Moose::CoordinateSystemType coord_type, const unsigned int rz_radial_coord=libMesh::invalid_uint)
std::string stringify(const T &t)
The following methods are specializations for using the Parallel::packed_range_* routines for a vecto...
auto index_range(const T &sizable)
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
IntRange< T > make_range(T beg, T end)