22#include "libmesh/mesh_base.h"
23#include "libmesh/elem_range.h"
24#include "metaphysicl/dualsemidynamicsparsenumberarray.h"
27#include "libmesh/petsc_matrix.h"
28#include "libmesh/petsc_vector.h"
37 params.addClassDescription(
"Computes H/A and 1/A together with face velocities for segregated "
38 "momentum-pressure equations.");
53 _HbyA(_moose_mesh, blockIDs(),
"HbyA"),
54 _Ainv(_moose_mesh, blockIDs(),
"Ainv", false),
61 velocity(1) = (*_v)(r, t);
63 velocity(2) = (*_w)(r, t);
69 _face_velocity(_moose_mesh, blockIDs(),
"face_values")
72 paramError(
"use_displaced_mesh",
73 "The segregated Rhie-Chow user object does not currently support operation on a "
83 if (_velocity_interp_method == Moose::FV::InterpMethod::Average)
84 paramError(
"velocity_interp_method",
85 "Segregated momentum-pressure solvers do not allow average interpolation methods!");
88 mooseError(this->
name(),
" should only be used with a segregated thermal-hydraulics solver!");
93 std::vector<NonlinearSystemBase *> momentum_systems,
94 const std::vector<unsigned int> & momentum_system_numbers,
95 const TagID pressure_gradient_tag)
104 dynamic_cast<NonlinearImplicitSystem *
>(&system->system()));
118 for (
const auto & pair :
_HbyA)
119 _HbyA[pair.first] = 0;
121 for (
const auto & pair :
_Ainv)
122 _Ainv[pair.first] = 0;
130 if (
hasBlocks(fi->elemPtr()->subdomain_id()) ||
131 (fi->neighborPtr() &&
hasBlocks(fi->neighborPtr()->subdomain_id())))
137 fi, Moose::FV::LimiterType::CentralDifference,
true,
false,
nullptr,
nullptr};
144 const Elem *
const boundary_elem =
145 hasBlocks(fi->elemPtr()->subdomain_id()) ? fi->elemPtr() : fi->neighborPtr();
148 fi, Moose::FV::LimiterType::CentralDifference,
true,
false, boundary_elem,
nullptr};
164 if (m != Moose::FV::InterpMethod::RhieChow)
165 mooseError(
"Segregated solution algorithms only support Rhie-Chow interpolation!");
176 if (
hasBlocks(fi->elemPtr()->subdomain_id()) ||
177 (fi->neighborPtr() &&
hasBlocks(fi->neighborPtr()->subdomain_id())))
186 fi, Moose::FV::LimiterType::CentralDifference,
true,
false,
nullptr,
nullptr};
188 RealVectorValue Ainv;
191 interpolate(Moose::FV::InterpMethod::Average,
199 for (
const auto comp_index : make_range(
_dim))
201 -HbyA(comp_index) - Ainv(comp_index) * grad_p(comp_index);
205 const Elem *
const boundary_elem =
206 hasBlocks(fi->elemPtr()->subdomain_id()) ? fi->elemPtr() : fi->neighborPtr();
208 fi, Moose::FV::LimiterType::CentralDifference,
true,
false, boundary_elem,
nullptr};
218 const RealVectorValue & grad_p =
220 for (
const auto comp_index : make_range(
_dim))
222 -HbyA(comp_index) - Ainv(comp_index) * grad_p(comp_index);
241 as_range(
_mesh.active_local_elements_begin(),
_mesh.active_local_elements_end()))
246 const RealVectorValue Ainv =
_Ainv(elem_arg, time_arg);
247 const RealVectorValue & grad_p = raw_value(
_p->
gradient(elem_arg, time_arg));
249 for (
auto comp_index : make_range(
_dim))
254 const auto index = elem->dof_number(system_number, var_nums[comp_index], 0);
259 index, -(*
_HbyA_raw[comp_index])(index)-Ainv(comp_index) * grad_p(comp_index));
275 const std::vector<std::unique_ptr<NumericVector<Number>>> & raw_hbya,
276 const std::vector<unsigned int> & var_nums)
280 if (
hasBlocks(fi->elemPtr()->subdomain_id()) ||
281 (fi->neighborPtr() &&
hasBlocks(fi->neighborPtr()->subdomain_id())))
288 const Elem * elem = fi->elemPtr();
289 const Elem * neighbor = fi->neighborPtr();
290 for (
auto comp_index : make_range(
_dim))
293 const auto dof_index_elem = elem->dof_number(system_number, var_nums[comp_index], 0);
294 const auto dof_index_neighbor =
295 neighbor->dof_number(system_number, var_nums[comp_index], 0);
297 interpolate(Moose::FV::InterpMethod::Average,
298 _HbyA[fi->id()](comp_index),
299 (*raw_hbya[comp_index])(dof_index_elem),
300 (*raw_hbya[comp_index])(dof_index_neighbor),
307 const Elem *
const boundary_elem =
308 hasBlocks(fi->elemPtr()->subdomain_id()) ? fi->elemPtr() : fi->neighborPtr();
311 fi, Moose::FV::LimiterType::CentralDifference,
true,
false, boundary_elem,
nullptr};
316 for (
const auto comp_index : make_range(
_dim))
319 const auto dof_index_elem =
320 boundary_elem->dof_number(system_number, var_nums[comp_index], 0);
321 _HbyA[fi->id()](comp_index) = (*raw_hbya[comp_index])(dof_index_elem);
333 _console <<
"************************************" << std::endl;
334 _console <<
"Computing HbyA" << std::endl;
335 _console <<
"************************************" << std::endl;
338 "The momentum system shall be linked before calling this function!");
355 NumericVector<Number> & rhs = *(momentum_system->rhs);
356 NumericVector<Number> & current_local_solution = *(momentum_system->current_local_solution);
357 NumericVector<Number> & solution = *(momentum_system->solution);
358 PetscMatrix<Number> * mmat =
dynamic_cast<PetscMatrix<Number> *
>(momentum_system->matrix);
360 "The matrices used in the segregated INSFVRhieChow objects need to be convertable "
365 _console <<
"Matrix in rc object" << std::endl;
369 auto Ainv = current_local_solution.zero_clone();
370 PetscVector<Number> * Ainv_petsc =
dynamic_cast<PetscVector<Number> *
>(Ainv.get());
372 mmat->get_diagonal(*Ainv_petsc);
374 auto working_vector = momentum_system->current_local_solution->zero_clone();
375 PetscVector<Number> * working_vector_petsc =
376 dynamic_cast<PetscVector<Number> *
>(working_vector.get());
377 mooseAssert(working_vector_petsc,
378 "The vectors used in the segregated INSFVRhieChow objects need to be convertable "
381 *working_vector_petsc = 1.0;
382 Ainv_petsc->pointwise_divide(*working_vector_petsc, *Ainv_petsc);
384 _HbyA_raw.push_back(current_local_solution.zero_clone());
385 NumericVector<Number> & HbyA = *(
_HbyA_raw.back());
389 _console <<
"Velocity solution in H(u)" << std::endl;
394 auto active_local_begin =
395 _mesh.evaluable_elements_begin(momentum_system->get_dof_map(), var_nums[system_i]);
396 auto active_local_end =
397 _mesh.evaluable_elements_end(momentum_system->get_dof_map(), var_nums[system_i]);
400 for (
auto it = active_local_begin; it != active_local_end; ++it)
402 const Elem * elem = *it;
403 if (this->
hasBlocks(elem->subdomain_id()))
406 Real coord_multiplier;
408 const unsigned int rz_radial_coord =
412 elem->vertex_average(), coord_multiplier, coord_type, rz_radial_coord);
415 const auto dof_index = elem->dof_number(momentum_system->number(), var_nums[system_i], 0);
417 (*Ainv_petsc)(dof_index)*volume * coord_multiplier;
423 *working_vector_petsc = 0.0;
424 LibmeshPetscCall(MatDiagonalSet(mmat->mat(), working_vector_petsc->vec(), INSERT_VALUES));
447 _console <<
"total RHS" << std::endl;
449 _console <<
"pressure RHS" << std::endl;
464 mmat->vector_mult(*working_vector_petsc, solution);
469 working_vector_petsc->print();
473 HbyA.add(*working_vector_petsc);
477 _console <<
" H(u)-rhs-relaxation_source" << std::endl;
482 HbyA.pointwise_mult(HbyA, *Ainv);
486 _console <<
" (H(u)-rhs)/A" << std::endl;
495 _console <<
"************************************" << std::endl;
496 _console <<
"DONE Computing HbyA " << std::endl;
497 _console <<
"************************************" << std::endl;
registerMooseObject("NavierStokesApp", INSFVRhieChowInterpolatorSegregated)
void mooseError(Args &&... args)
const ExecFlagType EXEC_ALWAYS
const ExecFlagType EXEC_NONE
bool hasBlocks(const SubdomainName &name) const
const ConsoleStream _console
void addAvailableFlags(const ExecFlagType &flag, Args... flags)
void setCurrentNonlinearSystem(const unsigned int nl_sys_num)
virtual MooseMesh & mesh() override
virtual void computeResidualTag(const NumericVector< libMesh::Number > &soln, NumericVector< libMesh::Number > &residual, TagID tag)
ValueType evaluate(const FaceInfo *const fi) const
Evaluate the face functor using a FaceInfo argument.
Moose::ElemArg makeElemArg(const Elem *elem, bool correct_skewnewss=false) const
A user object which implements the Rhie Chow interpolation for segregated momentum-pressure systems.
void computeHbyA(bool verbose)
Computes the inverse of the digaonal (1/A) of the system matrix plus the H/A components for the press...
std::vector< NonlinearSystemBase * > _momentum_systems
Pointers to the nonlinear system(s) corresponding to the momentum equation(s)
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
Get the face velocity (used in advection terms)
INSFVRhieChowInterpolatorSegregated(const InputParameters ¶ms)
void meshChanged() override
void computeFaceVelocity()
Update the values of the face velocities in the containers.
TagID _pressure_gradient_tag
Residual tag corresponding to the pressure gradient contribution.
void populateHbyA(const std::vector< std::unique_ptr< NumericVector< Number > > > &raw_hbya, const std::vector< unsigned int > &var_nums)
Populate the face values of the H/A field.
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...
std::vector< unsigned int > _momentum_system_numbers
Numbers of the momentum system(s)
void initFaceVelocities()
Initialize the container for face velocities.
void initialize() override
std::unique_ptr< PiecewiseByBlockLambdaFunctor< ADRealVectorValue > > _vel
A functor for computing the (non-RC corrected) velocity.
void linkMomentumSystem(std::vector< NonlinearSystemBase * > momentum_systems, const std::vector< unsigned int > &momentum_system_numbers, const TagID pressure_gradient_tag)
Update the momentum system-related information.
FaceCenteredMapFunctor< RealVectorValue, std::unordered_map< dof_id_type, RealVectorValue > > _face_velocity
A map functor from faces to face velocities which are used in the advection terms.
CellCenteredMapFunctor< RealVectorValue, std::unordered_map< dof_id_type, RealVectorValue > > _Ainv
A map functor from element IDs to $1/A_i$.
std::vector< libMesh::NonlinearImplicitSystem * > _momentum_implicit_systems
Pointers to the momentum equation implicit system(s)
void computeCellVelocity()
Update the cell values of the velocity variables.
FaceCenteredMapFunctor< RealVectorValue, std::unordered_map< dof_id_type, RealVectorValue > > _HbyA
A map functor from faces to $HbyA_{ij} = (A_{offdiag}*\mathrm{(predicted~velocity)} - \mathrm{Source}...
static InputParameters validParams()
const std::string & name() const
void mooseError(Args &&... args) const
const std::vector< const FaceInfo * > & faceInfo() const
const ElemInfo & elemInfo(const dof_id_type id) const
virtual bool isDirichletBoundaryFace(const FaceInfo &fi, const Elem *elem, const Moose::StateArg &state) const
bool isInternalFace(const FaceInfo &) const
GradientType gradient(const ElemArg &elem, const StateArg &state) const
INSFVPressureVariable *const _p
The thread 0 copy of the pressure variable.
INSFVVelocityVariable *const _w
The thread 0 copy of the z-velocity variable (null if the problem is not 3D)
MooseMesh & _moose_mesh
The MooseMesh that this user object operates on.
const libMesh::MeshBase & _mesh
The libMesh mesh that this object acts on.
static InputParameters validParams()
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)
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.
Executioner set up to solve a thermal-hydraulics problem using the SIMPLENonlinearAssembly algorithm.
virtual TagName vectorTagName(const TagID tag) const
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)
FEProblemBase & _fe_problem
void coordTransformFactor(const P &point, C &factor, const Moose::CoordinateSystemType coord_type, const unsigned int rz_radial_coord=libMesh::invalid_uint)
The following methods are specializations for using the Parallel::packed_range_* routines for a vecto...
const unsigned int invalid_uint
IntRange< T > make_range(T beg, T end)