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 * gap + gap * gap;
80 rod_perimeter +
pitch + 2 * gap + 2 * (*_displacement_soln)(node) /
sqrt(2);
85 additional_area =
pitch * 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 + 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) + 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");
432 auto heat_rate_in = 0.0;
433 auto heat_rate_out = 0.0;
438 heat_rate_out += 0.25 * (*_q_prime_soln)(node_out);
439 heat_rate_in += 0.25 * (*_q_prime_soln)(node_in);
441 return (heat_rate_in + heat_rate_out) * dz / 2.0;
454 unsigned int last_node = (iblock + 1) *
_block_size;
455 unsigned int first_node = iblock *
_block_size + 1;
458 for (
unsigned int i_ch = 0; i_ch <
_n_channels; i_ch++)
465 name(),
" : Calculation of negative Enthalpy h_out = : ", h_out,
" Axial Level= : ", 0);
473 for (
unsigned int iz = first_node; iz < last_node + 1; iz++)
478 for (
unsigned int i_ch = 0; i_ch <
_n_channels; i_ch++)
482 auto mdot_in = (*_mdot_soln)(node_in);
483 auto h_in = (*_h_soln)(node_in);
484 auto volume = dz * (*_S_flow_soln)(node_in);
485 auto mdot_out = (*_mdot_soln)(node_out);
488 Real sumWijPrimeDhij = 0.0;
490 if (
_z_grid[iz] > unheated_length_entry &&
491 _z_grid[iz] <= unheated_length_entry + heated_length)
494 added_enthalpy = 0.0;
496 unsigned int counter = 0;
500 unsigned int ii_ch = chans.first;
502 unsigned int jj_ch = chans.second;
507 if (
_Wij(i_gap, iz) > 0.0)
508 h_star = (*_h_soln)(node_in_i);
509 else if (
_Wij(i_gap, iz) < 0.0)
510 h_star = (*_h_soln)(node_in_j);
513 sumWijPrimeDhij +=
_WijPrime(i_gap, iz) * (2 * (*_h_soln)(node_in) -
517 h_out = (mdot_in * h_in - sumWijh - sumWijPrimeDhij + added_enthalpy +
523 " : Calculation of negative Enthalpy h_out = : ",
543 for (
unsigned int iz = first_node; iz < last_node + 1; iz++)
548 auto iz_ind = iz - first_node;
549 for (
unsigned int i_ch = 0; i_ch <
_n_channels; i_ch++)
553 auto S_in = (*_S_flow_soln)(node_in);
554 auto S_out = (*_S_flow_soln)(node_out);
556 auto volume = dz * S_interp;
562 if (iz == first_node)
564 PetscScalar value_vec_tt =
573 PetscInt col_tt = i_ch +
_n_channels * (iz_ind - 1);
575 LibmeshPetscCall(MatSetValues(
583 LibmeshPetscCall(MatSetValues(
587 PetscScalar rho_old_interp =
589 PetscScalar h_old_interp =
591 PetscScalar value_vec_tt =
_TR * rho_old_interp * h_old_interp *
volume /
_dt;
597 if (iz == first_node)
599 PetscScalar value_vec_at = (*_mdot_soln)(node_in) * (*
_h_soln)(node_in);
601 LibmeshPetscCall(VecSetValues(
607 PetscInt col_at = i_ch +
_n_channels * (iz_ind - 1);
608 PetscScalar value_at = -1.0 * (*_mdot_soln)(node_in);
609 LibmeshPetscCall(MatSetValues(
616 PetscScalar value_at = (*_mdot_soln)(node_out);
617 LibmeshPetscCall(MatSetValues(
621 unsigned int counter = 0;
622 unsigned int cross_index = iz;
626 unsigned int ii_ch = chans.first;
627 unsigned int jj_ch = chans.second;
632 if (
_Wij(i_gap, cross_index) > 0.0)
634 if (iz == first_node)
636 h_star = (*_h_soln)(node_in_i);
637 PetscScalar value_vec_ct = -1.0 *
alpha *
639 _Wij(i_gap, cross_index) * h_star;
641 LibmeshPetscCall(VecSetValues(
647 _Wij(i_gap, cross_index);
649 PetscInt col_ct = ii_ch +
_n_channels * (iz_ind - 1);
650 LibmeshPetscCall(MatSetValues(
653 PetscScalar value_ct = (1.0 -
alpha) *
655 _Wij(i_gap, cross_index);
658 LibmeshPetscCall(MatSetValues(
661 else if (
_Wij(i_gap, cross_index) < 0.0)
663 if (iz == first_node)
665 h_star = (*_h_soln)(node_in_j);
666 PetscScalar value_vec_ct = -1.0 *
alpha *
668 _Wij(i_gap, cross_index) * h_star;
670 LibmeshPetscCall(VecSetValues(
676 _Wij(i_gap, cross_index);
678 PetscInt col_ct = jj_ch +
_n_channels * (iz_ind - 1);
679 LibmeshPetscCall(MatSetValues(
682 PetscScalar value_ct = (1.0 -
alpha) *
684 _Wij(i_gap, cross_index);
687 LibmeshPetscCall(MatSetValues(
692 if (iz == first_node)
694 PetscScalar value_vec_ct =
696 value_vec_ct +=
alpha * (*_h_soln)(node_in_j)*
_WijPrime(i_gap, cross_index);
697 value_vec_ct +=
alpha * (*_h_soln)(node_in_i)*
_WijPrime(i_gap, cross_index);
704 PetscScalar value_center_ct = 2.0 *
alpha *
_WijPrime(i_gap, cross_index);
706 PetscInt col_ct = i_ch +
_n_channels * (iz_ind - 1);
707 LibmeshPetscCall(MatSetValues(
710 PetscScalar value_left_ct = -1.0 *
alpha *
_WijPrime(i_gap, cross_index);
713 LibmeshPetscCall(MatSetValues(
716 PetscScalar value_right_ct = -1.0 *
alpha *
_WijPrime(i_gap, cross_index);
719 LibmeshPetscCall(MatSetValues(
722 PetscScalar value_center_ct = 2.0 * (1.0 -
alpha) *
_WijPrime(i_gap, cross_index);
725 LibmeshPetscCall(MatSetValues(
728 PetscScalar value_left_ct = -1.0 * (1.0 -
alpha) *
_WijPrime(i_gap, cross_index);
731 LibmeshPetscCall(MatSetValues(
734 PetscScalar value_right_ct = -1.0 * (1.0 -
alpha) *
_WijPrime(i_gap, cross_index);
737 LibmeshPetscCall(MatSetValues(
743 PetscScalar added_enthalpy;
744 if (
_z_grid[iz] > unheated_length_entry &&
745 _z_grid[iz] <= unheated_length_entry + heated_length)
748 added_enthalpy = 0.0;
761 LibmeshPetscCall(MatAssemblyBegin(
_hc_sys_h_mat, MAT_FINAL_ASSEMBLY));
762 LibmeshPetscCall(MatAssemblyEnd(
_hc_sys_h_mat, MAT_FINAL_ASSEMBLY));
764 #if !PETSC_VERSION_LESS_THAN(3, 15, 0) 766 LibmeshPetscCall(MatAssemblyBegin(
_hc_sys_h_mat, MAT_FINAL_ASSEMBLY));
767 LibmeshPetscCall(MatAssemblyEnd(
_hc_sys_h_mat, MAT_FINAL_ASSEMBLY));
770 LibmeshPetscCall(MatAssemblyBegin(
_hc_sys_h_mat, MAT_FINAL_ASSEMBLY));
771 LibmeshPetscCall(MatAssemblyEnd(
_hc_sys_h_mat, MAT_FINAL_ASSEMBLY));
777 LibmeshPetscCall(MatAssemblyBegin(
_hc_sys_h_mat, MAT_FINAL_ASSEMBLY));
778 LibmeshPetscCall(MatAssemblyEnd(
_hc_sys_h_mat, MAT_FINAL_ASSEMBLY));
781 LibmeshPetscCall(MatAssemblyBegin(
_hc_sys_h_mat, MAT_FINAL_ASSEMBLY));
782 LibmeshPetscCall(MatAssemblyEnd(
_hc_sys_h_mat, MAT_FINAL_ASSEMBLY));
786 LibmeshPetscCall(MatAssemblyBegin(
_hc_sys_h_mat, MAT_FINAL_ASSEMBLY));
787 LibmeshPetscCall(MatAssemblyEnd(
_hc_sys_h_mat, MAT_FINAL_ASSEMBLY));
789 _console <<
"Block: " << iblock <<
" - Enthalpy conservation matrix assembled" << std::endl;
803 LibmeshPetscCall(KSPCreate(PETSC_COMM_WORLD, &ksploc));
805 LibmeshPetscCall(KSPGetPC(ksploc, &pc));
806 LibmeshPetscCall(PCSetType(pc, PCJACOBI));
808 LibmeshPetscCall(KSPSetOptionsPrefix(ksploc,
"h_sys_"));
809 LibmeshPetscCall(KSPSetFromOptions(ksploc));
812 LibmeshPetscCall(VecGetArray(sol, &xx));
813 for (
unsigned int iz = first_node; iz < last_node + 1; iz++)
815 auto iz_ind = iz - first_node;
816 for (
unsigned int i_ch = 0; i_ch <
_n_channels; i_ch++)
823 " : Calculation of negative Enthalpy h_out = : ",
831 LibmeshPetscCall(KSPDestroy(&ksploc));
832 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.
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 const std::string & name() const
Vec _hc_cross_derivative_rhs
void mooseWarning(Args &&... args) const
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 Real & getGap() const
Returns the gap, not to be confused with the gap between pins, this refers to the gap next to the duc...
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
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.
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 Real computeBeta(unsigned int i_gap, unsigned int iz) override
Computes turbulent mixing coefficient.
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.
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
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