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;
466 unsigned int last_node = (iblock + 1) *
_block_size;
467 unsigned int first_node = iblock *
_block_size + 1;
470 for (
unsigned int i_ch = 0; i_ch <
_n_channels; i_ch++)
477 name(),
" : Calculation of negative Enthalpy h_out = : ", h_out,
" Axial Level= : ", 0);
485 for (
unsigned int iz = first_node; iz < last_node + 1; iz++)
488 for (
unsigned int i_ch = 0; i_ch <
_n_channels; i_ch++)
492 auto mdot_in = (*_mdot_soln)(node_in);
493 auto h_in = (*_h_soln)(node_in);
494 auto volume = dz * (*_S_flow_soln)(node_in);
495 auto mdot_out = (*_mdot_soln)(node_out);
498 Real sumWijPrimeDhij = 0.0;
501 unsigned int counter = 0;
505 unsigned int ii_ch = chans.first;
507 unsigned int jj_ch = chans.second;
512 if (
_Wij(i_gap, iz) > 0.0)
513 h_star = (*_h_soln)(node_in_i);
514 else if (
_Wij(i_gap, iz) < 0.0)
515 h_star = (*_h_soln)(node_in_j);
518 sumWijPrimeDhij +=
_WijPrime(i_gap, iz) * (2 * (*_h_soln)(node_in) -
522 h_out = (mdot_in * h_in - sumWijh - sumWijPrimeDhij + added_enthalpy +
528 " : Calculation of negative Enthalpy h_out = : ",
548 for (
unsigned int iz = first_node; iz < last_node + 1; iz++)
551 auto iz_ind = iz - first_node;
552 for (
unsigned int i_ch = 0; i_ch <
_n_channels; i_ch++)
556 auto S_in = (*_S_flow_soln)(node_in);
557 auto S_out = (*_S_flow_soln)(node_out);
559 auto volume = dz * S_interp;
565 if (iz == first_node)
567 PetscScalar value_vec_tt =
576 PetscInt col_tt = i_ch +
_n_channels * (iz_ind - 1);
578 LibmeshPetscCall(MatSetValues(
586 LibmeshPetscCall(MatSetValues(
590 PetscScalar rho_old_interp =
592 PetscScalar h_old_interp =
594 PetscScalar value_vec_tt =
_TR * rho_old_interp * h_old_interp *
volume /
_dt;
600 if (iz == first_node)
602 PetscScalar value_vec_at = (*_mdot_soln)(node_in) * (*
_h_soln)(node_in);
604 LibmeshPetscCall(VecSetValues(
610 PetscInt col_at = i_ch +
_n_channels * (iz_ind - 1);
611 PetscScalar value_at = -1.0 * (*_mdot_soln)(node_in);
612 LibmeshPetscCall(MatSetValues(
619 PetscScalar value_at = (*_mdot_soln)(node_out);
620 LibmeshPetscCall(MatSetValues(
624 unsigned int counter = 0;
625 unsigned int cross_index = iz;
629 unsigned int ii_ch = chans.first;
630 unsigned int jj_ch = chans.second;
635 if (
_Wij(i_gap, cross_index) > 0.0)
637 if (iz == first_node)
639 h_star = (*_h_soln)(node_in_i);
640 PetscScalar value_vec_ct = -1.0 *
alpha *
642 _Wij(i_gap, cross_index) * h_star;
644 LibmeshPetscCall(VecSetValues(
650 _Wij(i_gap, cross_index);
652 PetscInt col_ct = ii_ch +
_n_channels * (iz_ind - 1);
653 LibmeshPetscCall(MatSetValues(
656 PetscScalar value_ct = (1.0 -
alpha) *
658 _Wij(i_gap, cross_index);
661 LibmeshPetscCall(MatSetValues(
664 else if (
_Wij(i_gap, cross_index) < 0.0)
666 if (iz == first_node)
668 h_star = (*_h_soln)(node_in_j);
669 PetscScalar value_vec_ct = -1.0 *
alpha *
671 _Wij(i_gap, cross_index) * h_star;
673 LibmeshPetscCall(VecSetValues(
679 _Wij(i_gap, cross_index);
681 PetscInt col_ct = jj_ch +
_n_channels * (iz_ind - 1);
682 LibmeshPetscCall(MatSetValues(
685 PetscScalar value_ct = (1.0 -
alpha) *
687 _Wij(i_gap, cross_index);
690 LibmeshPetscCall(MatSetValues(
695 if (iz == first_node)
697 PetscScalar value_vec_ct =
699 value_vec_ct +=
alpha * (*_h_soln)(node_in_j)*
_WijPrime(i_gap, cross_index);
700 value_vec_ct +=
alpha * (*_h_soln)(node_in_i)*
_WijPrime(i_gap, cross_index);
707 PetscScalar value_center_ct = 2.0 *
alpha *
_WijPrime(i_gap, cross_index);
709 PetscInt col_ct = i_ch +
_n_channels * (iz_ind - 1);
710 LibmeshPetscCall(MatSetValues(
713 PetscScalar value_left_ct = -1.0 *
alpha *
_WijPrime(i_gap, cross_index);
716 LibmeshPetscCall(MatSetValues(
719 PetscScalar value_right_ct = -1.0 *
alpha *
_WijPrime(i_gap, cross_index);
722 LibmeshPetscCall(MatSetValues(
725 PetscScalar value_center_ct = 2.0 * (1.0 -
alpha) *
_WijPrime(i_gap, cross_index);
728 LibmeshPetscCall(MatSetValues(
731 PetscScalar value_left_ct = -1.0 * (1.0 -
alpha) *
_WijPrime(i_gap, cross_index);
734 LibmeshPetscCall(MatSetValues(
737 PetscScalar value_right_ct = -1.0 * (1.0 -
alpha) *
_WijPrime(i_gap, cross_index);
740 LibmeshPetscCall(MatSetValues(
759 LibmeshPetscCall(MatAssemblyBegin(
_hc_sys_h_mat, MAT_FINAL_ASSEMBLY));
760 LibmeshPetscCall(MatAssemblyEnd(
_hc_sys_h_mat, MAT_FINAL_ASSEMBLY));
762 #if !PETSC_VERSION_LESS_THAN(3, 15, 0) 764 LibmeshPetscCall(MatAssemblyBegin(
_hc_sys_h_mat, MAT_FINAL_ASSEMBLY));
765 LibmeshPetscCall(MatAssemblyEnd(
_hc_sys_h_mat, MAT_FINAL_ASSEMBLY));
768 LibmeshPetscCall(MatAssemblyBegin(
_hc_sys_h_mat, MAT_FINAL_ASSEMBLY));
769 LibmeshPetscCall(MatAssemblyEnd(
_hc_sys_h_mat, MAT_FINAL_ASSEMBLY));
775 LibmeshPetscCall(MatAssemblyBegin(
_hc_sys_h_mat, MAT_FINAL_ASSEMBLY));
776 LibmeshPetscCall(MatAssemblyEnd(
_hc_sys_h_mat, MAT_FINAL_ASSEMBLY));
779 LibmeshPetscCall(MatAssemblyBegin(
_hc_sys_h_mat, MAT_FINAL_ASSEMBLY));
780 LibmeshPetscCall(MatAssemblyEnd(
_hc_sys_h_mat, MAT_FINAL_ASSEMBLY));
784 LibmeshPetscCall(MatAssemblyBegin(
_hc_sys_h_mat, MAT_FINAL_ASSEMBLY));
785 LibmeshPetscCall(MatAssemblyEnd(
_hc_sys_h_mat, MAT_FINAL_ASSEMBLY));
787 _console <<
"Block: " << iblock <<
" - Enthalpy conservation matrix assembled" << std::endl;
801 LibmeshPetscCall(KSPCreate(PETSC_COMM_WORLD, &ksploc));
803 LibmeshPetscCall(KSPGetPC(ksploc, &pc));
804 LibmeshPetscCall(PCSetType(pc, PCJACOBI));
806 LibmeshPetscCall(KSPSetOptionsPrefix(ksploc,
"h_sys_"));
807 LibmeshPetscCall(KSPSetFromOptions(ksploc));
810 LibmeshPetscCall(VecGetArray(sol, &xx));
811 for (
unsigned int iz = first_node; iz < last_node + 1; iz++)
813 auto iz_ind = iz - first_node;
814 for (
unsigned int i_ch = 0; i_ch <
_n_channels; i_ch++)
821 " : Calculation of negative Enthalpy h_out = : ",
829 LibmeshPetscCall(KSPDestroy(&ksploc));
830 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
Computes added heat 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
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