21 "Solver class for subchannels in a square lattice assembly and bare fuel pins");
23 "Thermal diffusion coefficient used in turbulent crossflow.");
25 "default_friction_model",
27 "Boolean to define which friction model to use (default: Pang, B. et al. " 28 "KIT, 2013. / non-default: Todreas-Kazimi NUCLEAR SYSTEMS, second edition, Volume 1, 2011)");
32 "Boolean to define the use of a constant beta or beta correlation (Kim and Chung, 2001)");
39 _beta(getParam<
Real>(
"beta")),
40 _default_friction_model(getParam<bool>(
"default_friction_model")),
41 _constant_beta(getParam<bool>(
"constant_beta"))
51 Real standard_area, additional_area, wetted_perimeter, displaced_area;
57 for (
unsigned int iz = 0; iz <
_n_cells + 1; iz++)
59 for (
unsigned int i_ch = 0; i_ch <
_n_channels; i_ch++)
65 Real rod_perimeter = 0.0;
69 rod_area += 0.25 * 0.25 * M_PI * (*_Dpin_soln)(pin_node) * (*
_Dpin_soln)(pin_node);
70 rod_perimeter += 0.25 * M_PI * (*_Dpin_soln)(pin_node);
78 additional_area =
pitch * side_gap + side_gap * side_gap;
80 rod_perimeter +
pitch + 2 * side_gap + 2 * (*_displacement_soln)(node) /
sqrt(2);
85 additional_area =
pitch * side_gap;
86 displaced_area =
pitch * (*_displacement_soln)(node);
87 wetted_perimeter = rod_perimeter +
pitch;
93 additional_area = 0.0;
94 wetted_perimeter = rod_perimeter;
98 auto subchannel_area = displaced_area + standard_area + additional_area - rod_area;
101 auto overlapping_pin_area = 0.0;
102 auto overlapping_wetted_perimeter = 0.0;
106 auto pin_1 = gap_pins.first;
107 auto pin_2 = gap_pins.second;
110 auto Diameter1 = (*_Dpin_soln)(pin_node_1);
111 auto Radius1 = Diameter1 / 2.0;
112 auto Diameter2 = (*_Dpin_soln)(pin_node_2);
113 auto Radius2 = Diameter2 / 2.0;
116 if (
pitch < (Radius1 + Radius2))
118 mooseWarning(
" The gap of index : '", i_gap,
" at axial cell ", iz,
" ' is blocked.");
120 (
pitch *
pitch + Radius1 * Radius1 - Radius2 * Radius2) / (2 *
pitch * Radius1);
122 (
pitch *
pitch + Radius2 * Radius2 - Radius1 * Radius1) / (2 *
pitch * Radius2);
123 auto angle1 = 2.0 * acos(cos1);
124 auto angle2 = 2.0 * acos(cos2);
126 overlapping_wetted_perimeter += 0.5 * angle1 * Radius1 + 0.5 * angle2 * Radius2;
128 overlapping_pin_area +=
129 0.5 * Radius1 * Radius1 * acos(cos1) + 0.5 * Radius2 * Radius2 * acos(cos2) -
130 0.25 *
sqrt((-
pitch + Radius1 + Radius2) * (
pitch + Radius1 - Radius2) *
131 (
pitch - Radius1 + Radius2) * (
pitch + Radius1 + Radius2));
134 subchannel_area += overlapping_pin_area;
135 wetted_perimeter += -overlapping_wetted_perimeter;
139 for (
const auto & i_blockage : index_blockage)
141 if (i_ch == i_blockage && (
Z >= z_blockage.front() &&
Z <= z_blockage.back()))
143 subchannel_area *= reduction_blockage[index];
153 for (
unsigned int iz = 0; iz <
_n_cells + 1; iz++)
155 for (
unsigned int i_gap = 0; i_gap <
_n_gaps; i_gap++)
158 auto pin_1 = gap_pins.first;
159 auto pin_2 = gap_pins.second;
164 auto displacement = 0.0;
172 displacement += (*_displacement_soln)(node);
176 displacement = displacement / counter;
178 (
pitch - (*_Dpin_soln)(pin_node_1)) / 2.0 + side_gap + displacement;
183 pitch - (*_Dpin_soln)(pin_node_1) / 2.0 - (*
_Dpin_soln)(pin_node_2) / 2.0;
192 for (
unsigned int iz = 1; iz <
_n_cells + 1; iz++)
194 for (
unsigned int i_ch = 0; i_ch <
_n_channels; i_ch++)
204 _aux->solution().close();
210 auto Re = friction_args.
Re;
211 auto i_ch = friction_args.
i_ch;
220 else if (Re >= 1 and Re < 5000)
225 else if (Re >= 5000 and Re < 30000)
241 Real aT, b1T, b2T, cT;
247 auto w = (pin_diameter / 2.0) + (
pitch / 2.0) + side_gap;
248 auto p_over_d =
pitch / pin_diameter;
249 auto w_over_d = w / pin_diameter;
250 auto ReL =
std::pow(10, (p_over_d - 1)) * 320.0;
251 auto ReT =
std::pow(10, 0.7 * (p_over_d - 1)) * 1.0E+4;
252 auto psi = std::log(Re / ReL) / std::log(ReT / ReL);
254 const Real lambda = 7.0;
280 cL = aL + b1L * (p_over_d - 1) + b2L *
std::pow((p_over_d - 1), 2);
282 cT = aT + b1T * (p_over_d - 1) + b2T *
std::pow((p_over_d - 1), 2);
305 cL = aL + b1L * (w_over_d - 1) + b2L *
std::pow((w_over_d - 1), 2);
307 cT = aT + b1T * (w_over_d - 1) + b2T *
std::pow((w_over_d - 1), 2);
330 cL = aL + b1L * (w_over_d - 1) + b2L *
std::pow((w_over_d - 1), 2);
332 cT = aT + b1T * (w_over_d - 1) + b2T *
std::pow((w_over_d - 1), 2);
368 unsigned int i_ch = chans.first;
369 unsigned int j_ch = chans.second;
374 auto Si_in = (*_S_flow_soln)(node_in_i);
375 auto Sj_in = (*_S_flow_soln)(node_in_j);
376 auto Si_out = (*_S_flow_soln)(node_out_i);
377 auto Sj_out = (*_S_flow_soln)(node_out_j);
381 0.5 * (((*_mdot_soln)(node_in_i) + (*
_mdot_soln)(node_in_j)) / (Si_in + Sj_in) +
383 auto S_total = Si_in + Sj_in + Si_out + Sj_out;
384 auto Si = 0.5 * (Si_in + Si_out);
385 auto Sj = 0.5 * (Sj_in + Sj_out);
386 auto w_perim_i = 0.5 * ((*_w_perim_soln)(node_in_i) + (*
_w_perim_soln)(node_out_i));
387 auto w_perim_j = 0.5 * ((*_w_perim_soln)(node_in_j) + (*
_w_perim_soln)(node_out_j));
388 auto avg_mu = (1 / S_total) * ((*
_mu_soln)(node_out_i)*Si_out + (*
_mu_soln)(node_in_i)*Si_in +
390 auto avg_hD = 4.0 * (Si + Sj) / (w_perim_i + w_perim_j);
391 auto Re = avg_massflux * avg_hD / avg_mu;
397 auto k = (1 / S_total) *
402 auto cp = (1 / S_total) *
407 auto Pr = avg_mu *
cp /
k;
408 auto Pr_t = Pr * (Re / gamma) * std::sqrt(
f / 8.0);
410 auto L_x = sf *
delta;
411 auto lamda = gap / L_x;
412 auto a_x = 1.0 - 2.0 * lamda * lamda /
libMesh::pi;
413 auto z_FP_over_D = (2.0 * L_x / pin_diameter) *
414 (1 + (-0.5 * std::log(lamda) + 0.5 * std::log(4.0) - 0.25) * lamda * lamda);
415 auto Str = 1.0 / (0.822 * (gap / pin_diameter) + 0.144);
416 auto freq_factor = 2.0 /
std::pow(gamma, 2) * std::sqrt(
a / 8.0) * (avg_hD / gap);
417 auto rod_mixing = (1 / Pr_t) * lamda;
418 auto axial_mixing = a_x * z_FP_over_D * Str;
420 beta = freq_factor * (rod_mixing + axial_mixing) *
std::pow(Re, -
b / 2.0);
422 mooseAssert(beta > 0,
"beta should be positive");
441 auto heat_rate_in = 0.0;
442 auto heat_rate_out = 0.0;
447 heat_rate_out += 0.25 * (*_q_prime_soln)(node_out);
448 heat_rate_in += 0.25 * (*_q_prime_soln)(node_in);
450 return (heat_rate_in + heat_rate_out) * dz / 2.0;
475 mooseError(
"Channel is not a perimetric subchannel ");
481 unsigned int last_node = (iblock + 1) *
_block_size;
482 unsigned int first_node = iblock *
_block_size + 1;
485 for (
unsigned int i_ch = 0; i_ch <
_n_channels; i_ch++)
492 name(),
" : Calculation of negative Enthalpy h_out = : ", h_out,
" Axial Level= : ", 0);
500 for (
unsigned int iz = first_node; iz < last_node + 1; iz++)
503 for (
unsigned int i_ch = 0; i_ch <
_n_channels; i_ch++)
507 auto mdot_in = (*_mdot_soln)(node_in);
508 auto h_in = (*_h_soln)(node_in);
509 auto volume = dz * (*_S_flow_soln)(node_in);
510 auto mdot_out = (*_mdot_soln)(node_out);
513 Real sumWijPrimeDhij = 0.0;
516 unsigned int counter = 0;
520 unsigned int ii_ch = chans.first;
522 unsigned int jj_ch = chans.second;
527 if (
_Wij(i_gap, iz) > 0.0)
528 h_star = (*_h_soln)(node_in_i);
529 else if (
_Wij(i_gap, iz) < 0.0)
530 h_star = (*_h_soln)(node_in_j);
533 sumWijPrimeDhij +=
_WijPrime(i_gap, iz) * (2 * (*_h_soln)(node_in) -
537 h_out = (mdot_in * h_in - sumWijh - sumWijPrimeDhij + added_enthalpy +
543 " : Calculation of negative Enthalpy h_out = : ",
563 for (
unsigned int iz = first_node; iz < last_node + 1; iz++)
566 auto iz_ind = iz - first_node;
567 for (
unsigned int i_ch = 0; i_ch <
_n_channels; i_ch++)
571 auto S_in = (*_S_flow_soln)(node_in);
572 auto S_out = (*_S_flow_soln)(node_out);
574 auto volume = dz * S_interp;
580 if (iz == first_node)
582 PetscScalar value_vec_tt =
591 PetscInt col_tt = i_ch +
_n_channels * (iz_ind - 1);
593 LibmeshPetscCall(MatSetValues(
601 LibmeshPetscCall(MatSetValues(
605 PetscScalar rho_old_interp =
607 PetscScalar h_old_interp =
609 PetscScalar value_vec_tt =
_TR * rho_old_interp * h_old_interp *
volume /
_dt;
615 if (iz == first_node)
617 PetscScalar value_vec_at = (*_mdot_soln)(node_in) * (*
_h_soln)(node_in);
619 LibmeshPetscCall(VecSetValues(
625 PetscInt col_at = i_ch +
_n_channels * (iz_ind - 1);
626 PetscScalar value_at = -1.0 * (*_mdot_soln)(node_in);
627 LibmeshPetscCall(MatSetValues(
634 PetscScalar value_at = (*_mdot_soln)(node_out);
635 LibmeshPetscCall(MatSetValues(
639 unsigned int counter = 0;
640 unsigned int cross_index = iz;
644 unsigned int ii_ch = chans.first;
645 unsigned int jj_ch = chans.second;
650 if (
_Wij(i_gap, cross_index) > 0.0)
652 if (iz == first_node)
654 h_star = (*_h_soln)(node_in_i);
655 PetscScalar value_vec_ct = -1.0 *
alpha *
657 _Wij(i_gap, cross_index) * h_star;
659 LibmeshPetscCall(VecSetValues(
665 _Wij(i_gap, cross_index);
667 PetscInt col_ct = ii_ch +
_n_channels * (iz_ind - 1);
668 LibmeshPetscCall(MatSetValues(
671 PetscScalar value_ct = (1.0 -
alpha) *
673 _Wij(i_gap, cross_index);
676 LibmeshPetscCall(MatSetValues(
679 else if (
_Wij(i_gap, cross_index) < 0.0)
681 if (iz == first_node)
683 h_star = (*_h_soln)(node_in_j);
684 PetscScalar value_vec_ct = -1.0 *
alpha *
686 _Wij(i_gap, cross_index) * h_star;
688 LibmeshPetscCall(VecSetValues(
694 _Wij(i_gap, cross_index);
696 PetscInt col_ct = jj_ch +
_n_channels * (iz_ind - 1);
697 LibmeshPetscCall(MatSetValues(
700 PetscScalar value_ct = (1.0 -
alpha) *
702 _Wij(i_gap, cross_index);
705 LibmeshPetscCall(MatSetValues(
710 if (iz == first_node)
712 PetscScalar value_vec_ct =
714 value_vec_ct +=
alpha * (*_h_soln)(node_in_j)*
_WijPrime(i_gap, cross_index);
715 value_vec_ct +=
alpha * (*_h_soln)(node_in_i)*
_WijPrime(i_gap, cross_index);
722 PetscScalar value_center_ct = 2.0 *
alpha *
_WijPrime(i_gap, cross_index);
724 PetscInt col_ct = i_ch +
_n_channels * (iz_ind - 1);
725 LibmeshPetscCall(MatSetValues(
728 PetscScalar value_left_ct = -1.0 *
alpha *
_WijPrime(i_gap, cross_index);
731 LibmeshPetscCall(MatSetValues(
734 PetscScalar value_right_ct = -1.0 *
alpha *
_WijPrime(i_gap, cross_index);
737 LibmeshPetscCall(MatSetValues(
740 PetscScalar value_center_ct = 2.0 * (1.0 -
alpha) *
_WijPrime(i_gap, cross_index);
743 LibmeshPetscCall(MatSetValues(
746 PetscScalar value_left_ct = -1.0 * (1.0 -
alpha) *
_WijPrime(i_gap, cross_index);
749 LibmeshPetscCall(MatSetValues(
752 PetscScalar value_right_ct = -1.0 * (1.0 -
alpha) *
_WijPrime(i_gap, cross_index);
755 LibmeshPetscCall(MatSetValues(
774 LibmeshPetscCall(MatAssemblyBegin(
_hc_sys_h_mat, MAT_FINAL_ASSEMBLY));
775 LibmeshPetscCall(MatAssemblyEnd(
_hc_sys_h_mat, MAT_FINAL_ASSEMBLY));
777 #if !PETSC_VERSION_LESS_THAN(3, 15, 0) 779 LibmeshPetscCall(MatAssemblyBegin(
_hc_sys_h_mat, MAT_FINAL_ASSEMBLY));
780 LibmeshPetscCall(MatAssemblyEnd(
_hc_sys_h_mat, MAT_FINAL_ASSEMBLY));
783 LibmeshPetscCall(MatAssemblyBegin(
_hc_sys_h_mat, MAT_FINAL_ASSEMBLY));
784 LibmeshPetscCall(MatAssemblyEnd(
_hc_sys_h_mat, MAT_FINAL_ASSEMBLY));
790 LibmeshPetscCall(MatAssemblyBegin(
_hc_sys_h_mat, MAT_FINAL_ASSEMBLY));
791 LibmeshPetscCall(MatAssemblyEnd(
_hc_sys_h_mat, MAT_FINAL_ASSEMBLY));
794 LibmeshPetscCall(MatAssemblyBegin(
_hc_sys_h_mat, MAT_FINAL_ASSEMBLY));
795 LibmeshPetscCall(MatAssemblyEnd(
_hc_sys_h_mat, MAT_FINAL_ASSEMBLY));
799 LibmeshPetscCall(MatAssemblyBegin(
_hc_sys_h_mat, MAT_FINAL_ASSEMBLY));
800 LibmeshPetscCall(MatAssemblyEnd(
_hc_sys_h_mat, MAT_FINAL_ASSEMBLY));
802 _console <<
"Block: " << iblock <<
" - Enthalpy conservation matrix assembled" << std::endl;
816 LibmeshPetscCall(KSPCreate(PETSC_COMM_WORLD, &ksploc));
818 LibmeshPetscCall(KSPGetPC(ksploc, &pc));
819 LibmeshPetscCall(PCSetType(pc, PCJACOBI));
821 LibmeshPetscCall(KSPSetOptionsPrefix(ksploc,
"h_sys_"));
822 LibmeshPetscCall(KSPSetFromOptions(ksploc));
825 LibmeshPetscCall(VecGetArray(sol, &xx));
826 for (
unsigned int iz = first_node; iz < last_node + 1; iz++)
828 auto iz_ind = iz - first_node;
829 for (
unsigned int i_ch = 0; i_ch <
_n_channels; i_ch++)
836 " : Calculation of negative Enthalpy h_out = : ",
844 LibmeshPetscCall(KSPDestroy(&ksploc));
845 LibmeshPetscCall(VecDestroy(&sol));
virtual const Real & getCrossflowSign(unsigned int i_chan, unsigned int i_local) const override
Return a sign for the crossflow given a subchannel index and local neighbor index.
const bool _pin_mesh_exist
Flag that informs if there is a pin mesh or not.
virtual const Real & getPinDiameter() const
Return Pin diameter.
std::unique_ptr< SolutionHandle > _T_soln
virtual Node * getPinNode(unsigned int i_pin, unsigned iz) const override
Get the pin mesh node for a given pin index and elevation index.
std::unique_ptr< SolutionHandle > _h_soln
const PetscReal & _dtol
The divergence tolerance for the ksp linear solver.
const bool _monolithic_thermal_bool
Thermal monolithic bool.
T & getMesh(MooseMesh &mesh)
function to cast mesh
Real _TR
Flag that activates or deactivates the transient parts of the equations we solve by multiplication...
const PostprocessorValue & _P_out
Outlet Pressure.
virtual Real computeAddedHeatPin(unsigned int i_ch, unsigned int iz) override
Function that computes the added heat coming from the fuel pins, for channel i_ch and cell iz...
const bool _constant_beta
Flag that activates the use of constant beta.
static InputParameters validParams()
virtual const std::vector< unsigned int > & getChannelGaps(unsigned int i_chan) const override
Return a vector of gap indices for a given channel index.
std::unique_ptr< SolutionHandle > _S_flow_soln
Vec _hc_time_derivative_rhs
virtual const std::pair< unsigned int, unsigned int > & getGapPins(unsigned int i_gap) const override
Return a pair of pin indices for a given gap index.
const Real & getSideGap() const
Returns the side gap, not to be confused with the gap between pins, this refers to the gap next to th...
int delta(unsigned int i, unsigned int j)
Delta function, which returns zero if $i j$ and unity if $i=j$.
virtual void computeh(int iblock) override
Computes Enthalpy per channel for block iblock.
static InputParameters validParams()
Creates the mesh of subchannels in a quadrilateral lattice.
QuadSubChannelMesh & _subchannel_mesh
PetscScalar computeInterpolatedValue(PetscScalar topValue, PetscScalar botValue, PetscScalar Peclet=0.0)
const bool _segregated_bool
Segregated solve.
virtual Real computeBeta(unsigned int i_gap, unsigned int iz, bool) override
Computes turbulent mixing coefficient.
Vec _hc_cross_derivative_rhs
virtual Real getGapWidth(unsigned int axial_index, unsigned int gap_index) const override
Return gap width for a given gap index.
virtual const std::pair< unsigned int, unsigned int > & getGapChannels(unsigned int i_gap) const override
Return a pair of subchannel indices for a given gap index.
registerMooseObject("SubChannelApp", QuadSubChannel1PhaseProblem)
std::unique_ptr< SolutionHandle > _rho_soln
const bool _default_friction_model
Flag that activates one of the two friction models (default: f=a*Re^b, non-default: Todreas-Kazimi) ...
static const std::string cp
Vec _hc_added_heat_rhs
Enthalpy conservation - source and sink.
std::vector< Real > _z_grid
axial location of nodes
const std::string & name() const
virtual const Real & getHeatedLength() const
Return heated length.
Real f(Real x)
Test function for Brents method.
std::unique_ptr< SolutionHandle > _q_prime_soln
static const std::string pitch
const PetscReal & _atol
The absolute convergence tolerance for the ksp linear solver.
PetscScalar computeInterpolationCoefficients(PetscScalar Peclet=0.0)
Functions that computes the interpolation scheme given the Peclet number.
std::shared_ptr< AuxiliarySystem > _aux
Mat _hc_cross_derivative_mat
Enthalpy conservation - cross flux derivative.
bool absoluteFuzzyLessThan(const T &var1, const T2 &var2, const T3 &tol=libMesh::TOLERANCE *libMesh::TOLERANCE)
const PetscInt & _maxit
The maximum number of iterations to use for the ksp linear solver.
virtual Real computeFrictionFactor(FrictionStruct friction_args) override
Returns friction factor.
std::unique_ptr< SolutionHandle > _Dpin_soln
virtual const std::vector< Real > & getReductionBlockage() const
Get area reduction of blocked subchannels.
Quadrilateral subchannel solver.
const Real & _beta
Thermal diffusion coefficient used in turbulent crossflow.
Base class for the 1-phase steady-state/transient subchannel solver.
std::unique_ptr< SolutionHandle > _mdot_soln
virtual const Real & getPitch() const override
Return the pitch between 2 subchannels.
static const std::string Z
const PetscReal & _rtol
The relative convergence tolerance, (relative decrease) for the ksp linear solver.
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
std::unique_ptr< SolutionHandle > _displacement_soln
virtual const std::vector< Real > & getZBlockage() const
Get axial location of blockage (in,out) [m].
libMesh::DenseMatrix< Real > & _Wij
virtual Real getSubChannelPeripheralDuctWidth(unsigned int i_ch) override
Function that computes the width of the duct cell that the peripheral subchannel i_ch sees...
CTSub CT_OPERATOR_BINARY CTMul CTCompareLess CTCompareGreater CTCompareEqual _arg template * sqrt(_arg)) *_arg.template D< dtag >()) CT_SIMPLE_UNARY_FUNCTION(tanh
static const std::string alpha
virtual Node * getChannelNode(unsigned int i_chan, unsigned iz) const override
Get the subchannel mesh node for a given channel index and elevation index.
Vec _hc_advective_derivative_rhs
std::vector< std::vector< Real > > _gij_map
Vector to store gap size.
virtual const std::vector< unsigned int > & getPinChannels(unsigned int i_pin) const override
Return a vector of channel indices for a given Pin index.
void mooseWarning(Args &&... args) const
const bool _verbose_subchannel
Boolean to printout information related to subchannel solve.
void mooseError(Args &&... args) const
Mat _hc_advective_derivative_mat
Enthalpy conservation - advective (Eulerian) derivative;.
virtual const std::vector< unsigned int > & getIndexBlockage() const
Get index of blocked subchannels.
const bool _implicit_bool
Flag to define the usage of a implicit or explicit solution.
const ConsoleStream _console
virtual EChannelType getSubchannelType(unsigned int index) const override
Return the type of the subchannel for given subchannel index.
Mat _hc_time_derivative_mat
Enthalpy Enthalpy conservation - time derivative.
const bool _deformation
Flag that activates the effect of deformation (pin/duct) based on the auxvalues for displacement...
libMesh::DenseMatrix< Real > _WijPrime
virtual const std::vector< unsigned int > & getChannelPins(unsigned int i_chan) const override
Return a vector of pin indices for a given channel index.
MooseUnits pow(const MooseUnits &, int)
QuadSubChannel1PhaseProblem(const InputParameters ¶ms)
std::unique_ptr< SolutionHandle > _P_soln
virtual void initializeSolution() override
Function to initialize the solution & geometry fields.
static const std::string k
std::unique_ptr< SolutionHandle > _w_perim_soln
static const std::string cL
bool absoluteFuzzyGreaterThan(const T &var1, const T2 &var2, const T3 &tol=libMesh::TOLERANCE *libMesh::TOLERANCE)
virtual const Real & getHeatedLengthEntry() const
Return unheated length at entry.
const SinglePhaseFluidProperties * _fp
Solutions handles and link to TH tables properties.
Mat _hc_sys_h_mat
System matrices.
std::unique_ptr< SolutionHandle > _mu_soln