12 #include "libmesh/petsc_vector.h" 13 #include "libmesh/dense_matrix.h" 14 #include "libmesh/dense_vector.h" 29 const PetscScalar * xx;
39 for (PetscInt i = 0; i < size; i++)
40 solution_seed(i) = xx[i];
48 for (
int i = 0; i < size; i++)
49 ff[i] = Wij_residual_vector(i);
58 MooseEnum schemes(
"upwind downwind central_difference exponential",
"central_difference");
59 MooseEnum gravity_direction(
"counter_flow co_flow none",
"counter_flow");
63 params.
addRequiredParam<
unsigned int>(
"n_blocks",
"The number of blocks in the axial direction");
65 params.
addParam<
Real>(
"P_tol", 1e-6,
"Pressure tolerance");
66 params.
addParam<
Real>(
"T_tol", 1e-6,
"Temperature tolerance");
67 params.
addParam<
int>(
"T_maxit", 100,
"Maximum number of iterations for inner temperature loop");
68 params.
addParam<PetscReal>(
"rtol", 1e-6,
"Relative tolerance for ksp solver");
69 params.
addParam<PetscReal>(
"atol", 1e-6,
"Absolute tolerance for ksp solver");
70 params.
addParam<PetscReal>(
"dtol", 1e5,
"Divergence tolerance or ksp solver");
71 params.
addParam<PetscInt>(
"maxit", 1e4,
"Maximum number of iterations for ksp solver");
74 "Interpolation scheme used for the method. Default is exponential");
76 "gravity", gravity_direction,
"Direction of gravity. Default is counter_flow");
78 "implicit",
false,
"Boolean to define the use of explicit or implicit solution.");
80 "staggered_pressure",
false,
"Boolean to define the use of explicit or implicit solution.");
82 "segregated",
true,
"Boolean to define whether to use a segregated solution.");
84 "monolithic_thermal",
false,
"Boolean to define whether to use thermal monolithic solve.");
86 "verbose_subchannel",
false,
"Boolean to print out information related to subchannel solve.");
90 "Boolean that activates the deformation effect based on values for: displacement, Dpin");
91 params.
addRequiredParam<
bool>(
"compute_density",
"Flag that enables the calculation of density");
93 "Flag that enables the calculation of viscosity");
96 "Flag that informs whether we solve the Enthalpy/Temperature equations or not");
98 "P_out",
"The postprocessor (or scalar) that provides the value of outlet pressure [Pa]");
99 params.
addRequiredParam<UserObjectName>(
"fp",
"Fluid properties user object name");
107 _n_blocks(getParam<unsigned
int>(
"n_blocks")),
108 _Wij(declareRestartableData<
libMesh::DenseMatrix<
Real>>(
"Wij")),
110 _kij(_subchannel_mesh.getKij()),
112 _compute_density(getParam<bool>(
"compute_density")),
113 _compute_viscosity(getParam<bool>(
"compute_viscosity")),
114 _compute_power(getParam<bool>(
"compute_power")),
115 _pin_mesh_exist(_subchannel_mesh.pinMeshExist()),
116 _duct_mesh_exist(_subchannel_mesh.ductMeshExist()),
117 _P_out(getPostprocessorValue(
"P_out")),
118 _CT(getParam<
Real>(
"CT")),
119 _P_tol(getParam<
Real>(
"P_tol")),
120 _T_tol(getParam<
Real>(
"T_tol")),
121 _T_maxit(getParam<
int>(
"T_maxit")),
122 _rtol(getParam<PetscReal>(
"rtol")),
123 _atol(getParam<PetscReal>(
"atol")),
124 _dtol(getParam<PetscReal>(
"dtol")),
125 _maxit(getParam<PetscInt>(
"maxit")),
126 _interpolation_scheme(getParam<
MooseEnum>(
"interpolation_scheme")),
127 _gravity_direction(getParam<
MooseEnum>(
"gravity")),
128 _dir_grav(computeGravityDir(_gravity_direction)),
129 _implicit_bool(getParam<bool>(
"implicit")),
130 _staggered_pressure_bool(getParam<bool>(
"staggered_pressure")),
131 _segregated_bool(getParam<bool>(
"segregated")),
132 _monolithic_thermal_bool(getParam<bool>(
"monolithic_thermal")),
133 _verbose_subchannel(getParam<bool>(
"verbose_subchannel")),
134 _deformation(getParam<bool>(
"deformation")),
137 _duct_heat_flux_soln(nullptr),
142 mooseError(
"Cannot use more than one MPI process.");
232 ": When implicit number of blocks can't be equal to number of cells. This will " 233 "cause problems with the subchannel interpolation scheme.");
241 _fp = &getUserObject<SinglePhaseFluidProperties>(getParam<UserObjectName>(
"fp"));
270 PetscErrorCode ierr =
cleanUp();
282 LibmeshPetscCall(VecDestroy(&
_Wij_vec));
283 LibmeshPetscCall(VecDestroy(&
_prod));
284 LibmeshPetscCall(VecDestroy(&
_prodp));
352 ": Interpolation scheme should be a string: upwind, downwind, central_difference, " 359 PetscScalar botValue,
363 return alpha * botValue + (1.0 -
alpha) * topValue;
369 unsigned int last_node = (iblock + 1) *
_block_size;
370 unsigned int first_node = iblock *
_block_size + 1;
373 for (
unsigned int iz = first_node; iz < last_node + 1; iz++)
375 for (
unsigned int i_gap = 0; i_gap <
_n_gaps; i_gap++)
377 int i =
_n_gaps * (iz - first_node) + i_gap;
378 solution_seed(i) =
_Wij(i_gap, iz);
389 for (
unsigned int iz = first_node; iz < last_node + 1; iz++)
391 for (
unsigned int i_gap = 0; i_gap <
_n_gaps; i_gap++)
402 unsigned int last_node = (iblock + 1) *
_block_size;
403 unsigned int first_node = iblock *
_block_size + 1;
407 for (
unsigned int iz = first_node; iz < last_node + 1; iz++)
409 for (
unsigned int i_ch = 0; i_ch <
_n_channels; i_ch++)
414 unsigned int counter = 0;
428 for (
unsigned int iz = first_node; iz < last_node + 1; iz++)
430 unsigned int iz_ind = iz - first_node;
431 for (
unsigned int i_ch = 0; i_ch <
_n_channels; i_ch++)
434 unsigned int counter = 0;
438 PetscInt col = i_gap +
_n_gaps * iz_ind;
445 LibmeshPetscCall(MatAssemblyBegin(
_mc_sumWij_mat, MAT_FINAL_ASSEMBLY));
446 LibmeshPetscCall(MatAssemblyEnd(
_mc_sumWij_mat, MAT_FINAL_ASSEMBLY));
452 LibmeshPetscCall(VecDuplicate(
_Wij_vec, &loc_Wij));
456 LibmeshPetscCall(populateSolutionChan<SolutionHandle>(
458 LibmeshPetscCall(VecDestroy(&loc_prod));
459 LibmeshPetscCall(VecDestroy(&loc_Wij));
467 unsigned int last_node = (iblock + 1) *
_block_size;
468 unsigned int first_node = iblock *
_block_size + 1;
471 for (
unsigned int iz = first_node; iz < last_node + 1; iz++)
474 for (
unsigned int i_ch = 0; i_ch <
_n_channels; i_ch++)
478 auto volume = dz * (*_S_flow_soln)(node_in);
481 auto mdot_out = (*_mdot_soln)(node_in) - (*
_SumWij_soln)(node_out)-time_term;
486 " : Calculation of negative mass flow mdot_out = : ",
490 " - Implicit solves are required for recirculating flow.");
498 for (
unsigned int iz = first_node; iz < last_node + 1; iz++)
501 auto iz_ind = iz - first_node;
502 for (
unsigned int i_ch = 0; i_ch <
_n_channels; i_ch++)
506 auto volume = dz * (*_S_flow_soln)(node_in);
511 PetscScalar value_vec = -1.0 * time_term;
516 if (iz == first_node)
518 PetscScalar value_vec = (*_mdot_soln)(node_in);
527 PetscScalar
value = -1.0;
535 PetscScalar
value = 1.0;
542 PetscScalar value_vec_2 = -1.0 * (*_SumWij_soln)(node_out);
558 LibmeshPetscCall(KSPCreate(PETSC_COMM_WORLD, &ksploc));
560 LibmeshPetscCall(KSPGetPC(ksploc, &pc));
561 LibmeshPetscCall(PCSetType(pc, PCJACOBI));
563 LibmeshPetscCall(KSPSetFromOptions(ksploc));
565 LibmeshPetscCall(populateSolutionChan<SolutionHandle>(
568 LibmeshPetscCall(KSPDestroy(&ksploc));
569 LibmeshPetscCall(VecDestroy(&sol));
577 unsigned int last_node = (iblock + 1) *
_block_size;
578 unsigned int first_node = iblock *
_block_size + 1;
581 for (
unsigned int iz = first_node; iz < last_node + 1; iz++)
585 for (
unsigned int i_ch = 0; i_ch <
_n_channels; i_ch++)
589 auto rho_in = (*_rho_soln)(node_in);
590 auto rho_out = (*_rho_soln)(node_out);
591 auto mu_in = (*_mu_soln)(node_in);
592 auto S = (*_S_flow_soln)(node_in);
593 auto w_perim = (*_w_perim_soln)(node_in);
595 auto Dh_i = 4.0 *
S / w_perim;
596 auto time_term =
_TR * ((*_mdot_soln)(node_out)-
_mdot_soln->old(node_out)) * dz /
_dt -
601 auto mass_term2 = -2.0 * (*_mdot_soln)(node_out) * (*
_SumWij_soln)(node_out) /
S / rho_in;
602 auto crossflow_term = 0.0;
603 auto turbulent_term = 0.0;
604 unsigned int counter = 0;
608 unsigned int ii_ch = chans.first;
609 unsigned int jj_ch = chans.second;
614 auto rho_i = (*_rho_soln)(node_in_i);
615 auto rho_j = (*_rho_soln)(node_in_j);
616 auto Si = (*_S_flow_soln)(node_in_i);
617 auto Sj = (*_S_flow_soln)(node_in_j);
620 if (
_Wij(i_gap, iz) > 0.0)
621 u_star = (*_mdot_soln)(node_out_i) / Si / rho_i;
623 u_star = (*_mdot_soln)(node_out_j) / Sj / rho_j;
628 turbulent_term +=
_WijPrime(i_gap, iz) * (2 * (*_mdot_soln)(node_out) / rho_in /
S -
633 turbulent_term *=
_CT;
634 auto Re = (((*_mdot_soln)(node_in) /
S) * Dh_i / mu_in);
643 ki = k_grid[i_ch][iz - 1];
645 ki = k_grid[i_ch][iz];
646 auto friction_term = (fi * dz / Dh_i + ki) * 0.5 *
648 (
S * (*_rho_soln)(node_out));
650 auto DP =
std::pow(
S, -1.0) * (time_term + mass_term1 + mass_term2 + crossflow_term +
651 turbulent_term + friction_term + gravity_term);
669 for (
unsigned int iz = first_node; iz < last_node + 1; iz++)
673 auto iz_ind = iz - first_node;
674 for (
unsigned int i_ch = 0; i_ch <
_n_channels; i_ch++)
681 PetscScalar Pe = 0.5;
685 auto S_in = (*_S_flow_soln)(node_in);
686 auto S_out = (*_S_flow_soln)(node_out);
688 auto w_perim_in = (*_w_perim_soln)(node_in);
689 auto w_perim_out = (*_w_perim_soln)(node_out);
693 auto mu_in = (*_mu_soln)(node_in);
694 auto mu_out = (*_mu_soln)(node_out);
696 auto Dh_i = 4.0 * S_interp / w_perim_interp;
698 auto Re = ((mdot_loc / S_interp) * Dh_i / mu_interp);
707 ki = k_grid[i_ch][iz - 1];
709 ki = k_grid[i_ch][iz];
710 Pe = 1.0 / ((fi * dz / Dh_i + ki) * 0.5) * mdot_loc / std::abs(mdot_loc);
715 auto rho_in = (*_rho_soln)(node_in);
716 auto rho_out = (*_rho_soln)(node_out);
720 auto mu_in = (*_mu_soln)(node_in);
721 auto mu_out = (*_mu_soln)(node_out);
725 auto S_in = (*_S_flow_soln)(node_in);
726 auto S_out = (*_S_flow_soln)(node_out);
730 auto w_perim_in = (*_w_perim_soln)(node_in);
731 auto w_perim_out = (*_w_perim_soln)(node_out);
735 auto Dh_i = 4.0 * S_interp / w_perim_interp;
738 if (iz == first_node)
740 PetscScalar value_vec_tt = -1.0 *
_TR *
alpha * (*_mdot_soln)(node_in)*dz /
_dt;
748 PetscInt col_tt = i_ch +
_n_channels * (iz_ind - 1);
750 LibmeshPetscCall(MatSetValues(
757 PetscScalar value_tt =
_TR * (1.0 -
alpha) * dz /
_dt;
758 LibmeshPetscCall(MatSetValues(
762 PetscScalar mdot_old_interp =
764 PetscScalar value_vec_tt =
_TR * mdot_old_interp * dz /
_dt;
770 if (iz == first_node)
774 LibmeshPetscCall(VecSetValues(
780 PetscInt col_at = i_ch +
_n_channels * (iz_ind - 1);
781 PetscScalar value_at = -1.0 * std::abs((*
_mdot_soln)(node_in)) / (S_in * rho_in);
782 LibmeshPetscCall(MatSetValues(
789 PetscScalar value_at = std::abs((*
_mdot_soln)(node_out)) / (S_out * rho_out);
790 LibmeshPetscCall(MatSetValues(
794 unsigned int counter = 0;
795 unsigned int cross_index = iz;
799 unsigned int ii_ch = chans.first;
800 unsigned int jj_ch = chans.second;
815 if (
_Wij(i_gap, cross_index) > 0.0)
817 if (iz == first_node)
819 u_star = (*_mdot_soln)(node_in_i) / S_i / rho_i;
820 PetscScalar value_vec_ct = -1.0 *
alpha *
822 _Wij(i_gap, cross_index) * u_star;
824 LibmeshPetscCall(VecSetValues(
830 _Wij(i_gap, cross_index) / S_i / rho_i;
832 PetscInt col_ct = ii_ch +
_n_channels * (iz_ind - 1);
833 LibmeshPetscCall(MatSetValues(
836 PetscScalar value_ct = (1.0 -
alpha) *
838 _Wij(i_gap, cross_index) / S_i / rho_i;
841 LibmeshPetscCall(MatSetValues(
844 else if (
_Wij(i_gap, cross_index) < 0.0)
846 if (iz == first_node)
848 u_star = (*_mdot_soln)(node_in_j) / S_j / rho_j;
849 PetscScalar value_vec_ct = -1.0 *
alpha *
851 _Wij(i_gap, cross_index) * u_star;
853 LibmeshPetscCall(VecSetValues(
859 _Wij(i_gap, cross_index) / S_j / rho_j;
861 PetscInt col_ct = jj_ch +
_n_channels * (iz_ind - 1);
862 LibmeshPetscCall(MatSetValues(
865 PetscScalar value_ct = (1.0 -
alpha) *
867 _Wij(i_gap, cross_index) / S_j / rho_j;
870 LibmeshPetscCall(MatSetValues(
874 if (iz == first_node)
876 PetscScalar value_vec_ct = -2.0 *
alpha * (*_mdot_soln)(node_in)*
_CT *
877 _WijPrime(i_gap, cross_index) / (rho_interp * S_interp);
878 value_vec_ct +=
alpha * (*_mdot_soln)(node_in_j)*
_CT *
_WijPrime(i_gap, cross_index) /
880 value_vec_ct +=
alpha * (*_mdot_soln)(node_in_i)*
_CT *
_WijPrime(i_gap, cross_index) /
888 PetscScalar value_center_ct =
891 PetscInt col_ct = i_ch +
_n_channels * (iz_ind - 1);
892 LibmeshPetscCall(MatSetValues(
895 PetscScalar value_left_ct =
899 LibmeshPetscCall(MatSetValues(
902 PetscScalar value_right_ct =
906 LibmeshPetscCall(MatSetValues(
910 PetscScalar value_center_ct =
911 2.0 * (1.0 -
alpha) *
_CT *
_WijPrime(i_gap, cross_index) / (rho_interp * S_interp);
914 LibmeshPetscCall(MatSetValues(
917 PetscScalar value_left_ct =
921 LibmeshPetscCall(MatSetValues(
924 PetscScalar value_right_ct =
928 LibmeshPetscCall(MatSetValues(
934 PetscScalar mdot_interp =
936 auto Re = ((mdot_interp / S_interp) * Dh_i / mu_interp);
945 ki = k_grid[i_ch][iz - 1];
947 ki = k_grid[i_ch][iz];
948 auto coef = (fi * dz / Dh_i + ki) * 0.5 * std::abs((*
_mdot_soln)(node_out)) /
949 (S_interp * rho_interp);
950 if (iz == first_node)
952 PetscScalar value_vec = -1.0 *
alpha * coef * (*_mdot_soln)(node_in);
974 PetscScalar value_vec =
_dir_grav * -1.0 *
_g_grav * rho_interp * dz * S_interp;
976 LibmeshPetscCall(VecSetValues(
_amc_gravity_rhs, 1, &row_vec, &value_vec, ADD_VALUES));
993 #if !PETSC_VERSION_LESS_THAN(3, 15, 0) 1035 LibmeshPetscCall(populateVectorFromHandle<SolutionHandle>(
1042 LibmeshPetscCall(VecGetArray(ls, &xx));
1043 for (
unsigned int iz = first_node; iz < last_node + 1; iz++)
1045 auto iz_ind = iz - first_node;
1046 for (
unsigned int i_ch = 0; i_ch <
_n_channels; i_ch++)
1053 auto S_in = (*_S_flow_soln)(node_in);
1054 auto S_out = (*_S_flow_soln)(node_out);
1070 LibmeshPetscCall(VecDestroy(&ls));
1078 unsigned int last_node = (iblock + 1) *
_block_size;
1079 unsigned int first_node = iblock *
_block_size + 1;
1084 for (
unsigned int iz = last_node; iz > first_node - 1; iz--)
1087 for (
unsigned int i_ch = 0; i_ch <
_n_channels; i_ch++)
1098 for (
unsigned int iz = last_node; iz > first_node - 1; iz--)
1101 for (
unsigned int i_ch = 0; i_ch <
_n_channels; i_ch++)
1109 PetscScalar Pe = 0.5;
1111 if (iz == last_node)
1130 for (
unsigned int iz = last_node; iz > first_node - 1; iz--)
1132 auto iz_ind = iz - first_node;
1134 for (
unsigned int i_ch = 0; i_ch <
_n_channels; i_ch++)
1140 auto S_in = (*_S_flow_soln)(node_in);
1141 auto S_out = (*_S_flow_soln)(node_out);
1147 PetscScalar
value = -1.0 * S_interp;
1151 if (iz == last_node)
1153 PetscScalar
value = -1.0 * (*_P_soln)(node_out)*S_interp;
1161 PetscScalar
value = 1.0 * S_interp;
1168 auto dp_out = (*_DP_soln)(node_out);
1169 PetscScalar value_v = -1.0 * dp_out * S_interp;
1185 LibmeshPetscCall(KSPCreate(PETSC_COMM_WORLD, &ksploc));
1187 LibmeshPetscCall(KSPGetPC(ksploc, &pc));
1188 LibmeshPetscCall(PCSetType(pc, PCJACOBI));
1190 LibmeshPetscCall(KSPSetFromOptions(ksploc));
1193 LibmeshPetscCall(VecGetArray(sol, &xx));
1195 for (
unsigned int iz = last_node; iz > first_node - 1; iz--)
1197 auto iz_ind = iz - first_node;
1198 for (
unsigned int i_ch = 0; i_ch <
_n_channels; i_ch++)
1206 LibmeshPetscCall(KSPDestroy(&ksploc));
1207 LibmeshPetscCall(VecDestroy(&sol));
1213 for (
unsigned int iz = last_node; iz > first_node - 1; iz--)
1215 auto iz_ind = iz - first_node;
1217 for (
unsigned int i_ch = 0; i_ch <
_n_channels; i_ch++)
1223 auto S_in = (*_S_flow_soln)(node_in);
1224 auto S_out = (*_S_flow_soln)(node_out);
1230 PetscScalar
value = -1.0 * S_interp;
1234 if (iz == last_node)
1236 PetscScalar
value = -1.0 * (*_P_soln)(node_out)*S_interp;
1240 auto dp_out = (*_DP_soln)(node_out);
1241 PetscScalar value_v = -1.0 * dp_out / 2.0 * S_interp;
1250 PetscScalar
value = 1.0 * S_interp;
1256 auto dp_in = (*_DP_soln)(node_in);
1257 auto dp_out = (*_DP_soln)(node_out);
1259 PetscScalar value_v = -1.0 * dp_interp * S_interp;
1271 _console <<
"Block: " << iblock <<
" - Axial momentum pressure force matrix assembled" 1280 LibmeshPetscCall(KSPCreate(PETSC_COMM_WORLD, &ksploc));
1282 LibmeshPetscCall(KSPGetPC(ksploc, &pc));
1283 LibmeshPetscCall(PCSetType(pc, PCJACOBI));
1285 LibmeshPetscCall(KSPSetFromOptions(ksploc));
1288 LibmeshPetscCall(VecGetArray(sol, &xx));
1290 for (
unsigned int iz = last_node; iz > first_node - 1; iz--)
1292 auto iz_ind = iz - first_node;
1293 for (
unsigned int i_ch = 0; i_ch <
_n_channels; i_ch++)
1301 LibmeshPetscCall(KSPDestroy(&ksploc));
1302 LibmeshPetscCall(VecDestroy(&sol));
1311 unsigned int last_node = (iblock + 1) *
_block_size;
1312 unsigned int first_node = iblock *
_block_size + 1;
1313 for (
unsigned int iz = first_node; iz < last_node + 1; iz++)
1315 for (
unsigned int i_ch = 0; i_ch <
_n_channels; i_ch++)
1326 unsigned int last_node = (iblock + 1) *
_block_size;
1327 unsigned int first_node = iblock *
_block_size + 1;
1330 for (
unsigned int i_ch = 0; i_ch <
_n_channels; i_ch++)
1336 for (
unsigned int iz = first_node; iz < last_node + 1; iz++)
1338 for (
unsigned int i_ch = 0; i_ch <
_n_channels; i_ch++)
1349 unsigned int last_node = (iblock + 1) *
_block_size;
1350 unsigned int first_node = iblock *
_block_size + 1;
1353 for (
unsigned int i_ch = 0; i_ch <
_n_channels; i_ch++)
1359 for (
unsigned int iz = first_node; iz < last_node + 1; iz++)
1361 for (
unsigned int i_ch = 0; i_ch <
_n_channels; i_ch++)
1375 unsigned int last_node = (iblock + 1) *
_block_size;
1376 unsigned int first_node = iblock *
_block_size + 1;
1378 for (
unsigned int iz = first_node; iz < last_node + 1; iz++)
1381 for (
unsigned int i_gap = 0; i_gap <
_n_gaps; i_gap++)
1384 unsigned int i_ch = chans.first;
1385 unsigned int j_ch = chans.second;
1390 auto rho_i = (*_rho_soln)(node_in_i);
1391 auto rho_j = (*_rho_soln)(node_in_j);
1392 auto Si = (*_S_flow_soln)(node_in_i);
1393 auto Sj = (*_S_flow_soln)(node_in_j);
1397 auto friction_term =
_kij *
_Wij(i_gap, iz) * std::abs(
_Wij(i_gap, iz));
1398 auto DPij = (*_P_soln)(node_in_i) - (*
_P_soln)(node_in_j);
1400 auto rho_star = 0.0;
1401 if (
_Wij(i_gap, iz) > 0.0)
1403 else if (
_Wij(i_gap, iz) < 0.0)
1406 rho_star = (rho_i + rho_j) / 2.0;
1407 auto mass_term_out =
1408 (*_mdot_soln)(node_out_i) / Si / rho_i + (*
_mdot_soln)(node_out_j) / Sj / rho_j;
1410 (*_mdot_soln)(node_in_i) / Si / rho_i + (*
_mdot_soln)(node_in_j) / Sj / rho_j;
1411 auto term_out = Sij * rho_star * (Lij / dz) * mass_term_out *
_Wij(i_gap, iz);
1412 auto term_in = Sij * rho_star * (Lij / dz) * mass_term_in *
_Wij(i_gap, iz - 1);
1413 auto inertia_term = term_out - term_in;
1414 auto pressure_term = 2 *
std::pow(Sij, 2.0) * DPij * rho_star;
1419 time_term + friction_term + inertia_term - pressure_term;
1436 unsigned int last_node = (iblock + 1) *
_block_size;
1437 unsigned int first_node = iblock *
_block_size + 1;
1439 for (
unsigned int iz = first_node; iz < last_node + 1; iz++)
1442 auto iz_ind = iz - first_node;
1443 for (
unsigned int i_gap = 0; i_gap <
_n_gaps; i_gap++)
1446 unsigned int i_ch = chans.first;
1447 unsigned int j_ch = chans.second;
1454 auto rho_i_in = (*_rho_soln)(node_in_i);
1455 auto rho_i_out = (*_rho_soln)(node_out_i);
1457 auto rho_j_in = (*_rho_soln)(node_in_j);
1458 auto rho_j_out = (*_rho_soln)(node_out_j);
1462 auto S_i_in = (*_S_flow_soln)(node_in_i);
1463 auto S_i_out = (*_S_flow_soln)(node_out_i);
1464 auto S_j_in = (*_S_flow_soln)(node_in_j);
1465 auto S_j_out = (*_S_flow_soln)(node_out_j);
1472 auto rho_star = 0.0;
1473 if (
_Wij(i_gap, iz) > 0.0)
1474 rho_star = rho_i_interp;
1475 else if (
_Wij(i_gap, iz) < 0.0)
1476 rho_star = rho_j_interp;
1478 rho_star = (rho_i_interp + rho_j_interp) / 2.0;
1481 PetscScalar time_factor =
_TR * Lij * Sij * rho_star /
_dt;
1482 PetscInt row_td = i_gap +
_n_gaps * iz_ind;
1483 PetscInt col_td = i_gap +
_n_gaps * iz_ind;
1484 PetscScalar value_td = time_factor;
1485 LibmeshPetscCall(MatSetValues(
1487 PetscScalar value_td_rhs = time_factor *
_Wij_old(i_gap, iz);
1492 PetscScalar Pe = 0.5;
1494 auto mass_term_out = (*_mdot_soln)(node_out_i) / S_i_out / rho_i_out +
1495 (*
_mdot_soln)(node_out_j) / S_j_out / rho_j_out;
1496 auto mass_term_in = (*_mdot_soln)(node_in_i) / S_i_in / rho_i_in +
1497 (*
_mdot_soln)(node_in_j) / S_j_in / rho_j_in;
1498 auto term_out = Sij * rho_star * (Lij / dz) * mass_term_out / 2.0;
1499 auto term_in = Sij * rho_star * (Lij / dz) * mass_term_in / 2.0;
1500 if (iz == first_node)
1502 PetscInt row_ad = i_gap +
_n_gaps * iz_ind;
1503 PetscScalar value_ad = term_in *
alpha *
_Wij(i_gap, iz - 1);
1507 PetscInt col_ad = i_gap +
_n_gaps * iz_ind;
1508 value_ad = -1.0 * term_in * (1.0 -
alpha) + term_out *
alpha;
1509 LibmeshPetscCall(MatSetValues(
1512 col_ad = i_gap +
_n_gaps * (iz_ind + 1);
1513 value_ad = term_out * (1.0 -
alpha);
1514 LibmeshPetscCall(MatSetValues(
1517 else if (iz == last_node)
1519 PetscInt row_ad = i_gap +
_n_gaps * iz_ind;
1520 PetscInt col_ad = i_gap +
_n_gaps * (iz_ind - 1);
1521 PetscScalar value_ad = -1.0 * term_in *
alpha;
1522 LibmeshPetscCall(MatSetValues(
1525 col_ad = i_gap +
_n_gaps * iz_ind;
1526 value_ad = -1.0 * term_in * (1.0 -
alpha) + term_out *
alpha;
1527 LibmeshPetscCall(MatSetValues(
1530 value_ad = -1.0 * term_out * (1.0 -
alpha) *
_Wij(i_gap, iz);
1536 PetscInt row_ad = i_gap +
_n_gaps * iz_ind;
1537 PetscInt col_ad = i_gap +
_n_gaps * (iz_ind - 1);
1538 PetscScalar value_ad = -1.0 * term_in *
alpha;
1539 LibmeshPetscCall(MatSetValues(
1542 col_ad = i_gap +
_n_gaps * iz_ind;
1543 value_ad = -1.0 * term_in * (1.0 -
alpha) + term_out *
alpha;
1544 LibmeshPetscCall(MatSetValues(
1547 col_ad = i_gap +
_n_gaps * (iz_ind + 1);
1548 value_ad = term_out * (1.0 -
alpha);
1549 LibmeshPetscCall(MatSetValues(
1553 PetscInt row_ff = i_gap +
_n_gaps * iz_ind;
1554 PetscInt col_ff = i_gap +
_n_gaps * iz_ind;
1555 PetscScalar value_ff =
_kij * std::abs(
_Wij(i_gap, iz)) / 2.0;
1556 LibmeshPetscCall(MatSetValues(
1564 PetscScalar pressure_factor =
std::pow(Sij, 2.0) * rho_star;
1565 PetscInt row_pf = i_gap +
_n_gaps * iz_ind;
1567 PetscScalar value_pf = -1.0 *
alpha * pressure_factor;
1571 value_pf =
alpha * pressure_factor;
1575 if (iz == last_node)
1577 PetscInt row_pf = i_gap +
_n_gaps * iz_ind;
1578 PetscScalar value_pf = (1.0 -
alpha) * pressure_factor * (*
_P_soln)(node_out_i);
1581 value_pf = -1.0 * (1.0 -
alpha) * pressure_factor * (*
_P_soln)(node_out_j);
1587 row_pf = i_gap +
_n_gaps * iz_ind;
1589 value_pf = -1.0 * (1.0 -
alpha) * pressure_factor;
1590 LibmeshPetscCall(MatSetValues(
1593 value_pf = (1.0 -
alpha) * pressure_factor;
1594 LibmeshPetscCall(MatSetValues(
1600 PetscScalar pressure_factor =
std::pow(Sij, 2.0) * rho_star;
1601 PetscInt row_pf = i_gap +
_n_gaps * iz_ind;
1603 PetscScalar value_pf = -1.0 * pressure_factor;
1607 value_pf = pressure_factor;
1627 #if !PETSC_VERSION_LESS_THAN(3, 15, 0) 1664 LibmeshPetscCall(populateVectorFromHandle<SolutionHandle>(
1670 LibmeshPetscCall(VecAXPY(sol_holder_W, 1.0, sol_holder_P));
1672 LibmeshPetscCall(VecGetArray(sol_holder_W, &xx));
1673 for (
unsigned int iz = first_node; iz < last_node + 1; iz++)
1675 auto iz_ind = iz - first_node;
1676 for (
unsigned int i_gap = 0; i_gap <
_n_gaps; i_gap++)
1681 LibmeshPetscCall(VecDestroy(&sol_holder_P));
1682 LibmeshPetscCall(VecDestroy(&sol_holder_W));
1690 unsigned int last_node = (iblock + 1) *
_block_size;
1691 unsigned int first_node = iblock *
_block_size + 1;
1692 for (
unsigned int iz = first_node; iz < last_node + 1; iz++)
1695 for (
unsigned int i_gap = 0; i_gap <
_n_gaps; i_gap++)
1698 unsigned int i_ch = chans.first;
1699 unsigned int j_ch = chans.second;
1704 auto Si_in = (*_S_flow_soln)(node_in_i);
1705 auto Sj_in = (*_S_flow_soln)(node_in_j);
1706 auto Si_out = (*_S_flow_soln)(node_out_i);
1707 auto Sj_out = (*_S_flow_soln)(node_out_j);
1709 auto Sij = dz * gap;
1711 0.5 * (((*_mdot_soln)(node_in_i) + (*
_mdot_soln)(node_in_j)) / (Si_in + Sj_in) +
1717 _WijPrime(i_gap, iz) = beta * avg_massflux * Sij;
1721 auto iz_ind = iz - first_node;
1722 PetscScalar base_value = beta * 0.5 * Sij;
1725 if (iz == first_node)
1727 PetscScalar value_tl = -1.0 * base_value / (Si_in + Sj_in) *
1729 PetscInt row = i_gap +
_n_gaps * iz_ind;
1735 PetscScalar value_tl = base_value / (Si_in + Sj_in);
1736 PetscInt row = i_gap +
_n_gaps * iz_ind;
1738 PetscInt col_ich = i_ch +
_n_channels * (iz_ind - 1);
1739 LibmeshPetscCall(MatSetValues(
1742 PetscInt col_jch = j_ch +
_n_channels * (iz_ind - 1);
1743 LibmeshPetscCall(MatSetValues(
1748 PetscScalar value_bl = base_value / (Si_out + Sj_out);
1749 PetscInt row = i_gap +
_n_gaps * iz_ind;
1752 LibmeshPetscCall(MatSetValues(
1756 LibmeshPetscCall(MatSetValues(
1771 LibmeshPetscCall(VecDuplicate(
_Wij_vec, &loc_Wij));
1772 LibmeshPetscCall(populateVectorFromHandle<SolutionHandle>(
1778 LibmeshPetscCall(VecDestroy(&loc_prod));
1779 LibmeshPetscCall(VecDestroy(&loc_Wij));
1786 unsigned int last_node = (iblock + 1) *
_block_size;
1787 unsigned int first_node = iblock *
_block_size + 1;
1791 for (
unsigned int iz = first_node; iz < last_node + 1; iz++)
1793 for (
unsigned int i_gap = 0; i_gap <
_n_gaps; i_gap++)
1795 _Wij(i_gap, iz) = solution(i);
1816 for (
unsigned int i_gap = 0; i_gap <
_n_gaps; i_gap++)
1822 return Wij_residual_vector;
1838 PetscCallMPI(MPI_Comm_size(PETSC_COMM_WORLD, &size));
1840 SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_SUP,
"Example is only for sequential runs");
1841 LibmeshPetscCall(SNESCreate(PETSC_COMM_WORLD, &snes));
1842 LibmeshPetscCall(VecCreate(PETSC_COMM_WORLD, &
x));
1844 LibmeshPetscCall(VecSetFromOptions(
x));
1845 LibmeshPetscCall(VecDuplicate(
x, &r));
1847 #if PETSC_VERSION_LESS_THAN(3, 13, 0) 1848 LibmeshPetscCall(PetscOptionsSetValue(PETSC_NULL,
"-snes_mf", PETSC_NULL));
1850 LibmeshPetscCall(SNESSetUseMatrixFree(snes, PETSC_FALSE, PETSC_TRUE));
1853 ctx.iblock = iblock;
1856 LibmeshPetscCall(SNESGetKSP(snes, &ksp));
1857 LibmeshPetscCall(KSPGetPC(ksp, &pc));
1858 LibmeshPetscCall(PCSetType(pc, PCNONE));
1860 LibmeshPetscCall(SNESSetFromOptions(snes));
1861 LibmeshPetscCall(VecGetArray(
x, &xx));
1864 xx[i] = solution(i);
1866 LibmeshPetscCall(VecRestoreArray(
x, &xx));
1868 LibmeshPetscCall(SNESSolve(snes, NULL,
x));
1869 LibmeshPetscCall(VecGetArray(
x, &xx));
1873 LibmeshPetscCall(VecRestoreArray(
x, &xx));
1874 LibmeshPetscCall(VecDestroy(&
x));
1875 LibmeshPetscCall(VecDestroy(&r));
1876 LibmeshPetscCall(SNESDestroy(&snes));
1883 mooseAssert(iz > 0,
"Trapezoidal rule requires starting at index 1 at least");
1894 auto heat_rate_in = (*_duct_heat_flux_soln)(node_in_duct);
1895 auto heat_rate_out = (*_duct_heat_flux_soln)(node_out_duct);
1897 return 0.5 * (heat_rate_in + heat_rate_out) * dz * width;
1913 bool lag_block_thermal_solve =
true;
1921 std::vector<Mat> mat_array(Q * Q);
1922 std::vector<Vec> vec_array(Q);
1925 bool _axial_mass_flow_tight_coupling =
true;
1926 bool _pressure_axial_momentum_tight_coupling =
true;
1927 bool _pressure_cross_momentum_tight_coupling =
true;
1928 unsigned int first_node = iblock *
_block_size + 1;
1929 unsigned int last_node = (iblock + 1) *
_block_size;
1950 _console <<
"Starting nested system." << std::endl;
1951 _console <<
"Number of simultaneous variables: " << Q << std::endl;
1954 PetscInt field_num = 0;
1957 LibmeshPetscCall(MatAssemblyBegin(mat_array[Q * field_num + 0], MAT_FINAL_ASSEMBLY));
1958 LibmeshPetscCall(MatAssemblyEnd(mat_array[Q * field_num + 0], MAT_FINAL_ASSEMBLY));
1959 mat_array[Q * field_num + 1] = NULL;
1960 if (_axial_mass_flow_tight_coupling)
1962 LibmeshPetscCall(MatDuplicate(
_mc_sumWij_mat, MAT_COPY_VALUES, &mat_array[Q * field_num + 2]));
1963 LibmeshPetscCall(MatAssemblyBegin(mat_array[Q * field_num + 2], MAT_FINAL_ASSEMBLY));
1964 LibmeshPetscCall(MatAssemblyEnd(mat_array[Q * field_num + 2], MAT_FINAL_ASSEMBLY));
1968 mat_array[Q * field_num + 2] = NULL;
1972 mat_array[Q * field_num + 3] = NULL;
1976 if (!_axial_mass_flow_tight_coupling)
1980 LibmeshPetscCall(VecSet(sumWij_loc, 0.0));
1981 for (
unsigned int iz = first_node; iz < last_node + 1; iz++)
1983 auto iz_ind = iz - first_node;
1984 for (
unsigned int i_ch = 0; i_ch <
_n_channels; i_ch++)
1988 PetscScalar value_vec_2 = -1.0 * (*_SumWij_soln)(node_out);
1990 LibmeshPetscCall(VecSetValues(sumWij_loc, 1, &row_vec_2, &value_vec_2, ADD_VALUES));
1993 LibmeshPetscCall(VecAXPY(vec_array[field_num], 1.0, sumWij_loc));
1994 LibmeshPetscCall(VecDestroy(&sumWij_loc));
1998 _console <<
"Mass ok." << std::endl;
2001 if (_pressure_axial_momentum_tight_coupling)
2004 MatDuplicate(
_amc_sys_mdot_mat, MAT_COPY_VALUES, &mat_array[Q * field_num + 0]));
2005 LibmeshPetscCall(MatAssemblyBegin(mat_array[Q * field_num + 0], MAT_FINAL_ASSEMBLY));
2006 LibmeshPetscCall(MatAssemblyEnd(mat_array[Q * field_num + 0], MAT_FINAL_ASSEMBLY));
2010 mat_array[Q * field_num + 0] = NULL;
2014 LibmeshPetscCall(MatAssemblyBegin(mat_array[Q * field_num + 1], MAT_FINAL_ASSEMBLY));
2015 LibmeshPetscCall(MatAssemblyEnd(mat_array[Q * field_num + 1], MAT_FINAL_ASSEMBLY));
2016 mat_array[Q * field_num + 2] = NULL;
2019 mat_array[Q * field_num + 3] = NULL;
2023 if (_pressure_axial_momentum_tight_coupling)
2029 unsigned int last_node = (iblock + 1) *
_block_size;
2030 unsigned int first_node = iblock *
_block_size + 1;
2031 LibmeshPetscCall(populateVectorFromHandle<SolutionHandle>(
2037 LibmeshPetscCall(VecAXPY(vec_array[field_num], -1.0, ls));
2038 LibmeshPetscCall(VecDestroy(&ls));
2042 _console <<
"Lin mom OK." << std::endl;
2046 mat_array[Q * field_num + 0] = NULL;
2047 if (_pressure_cross_momentum_tight_coupling)
2051 LibmeshPetscCall(MatAssemblyBegin(mat_array[Q * field_num + 1], MAT_FINAL_ASSEMBLY));
2052 LibmeshPetscCall(MatAssemblyEnd(mat_array[Q * field_num + 1], MAT_FINAL_ASSEMBLY));
2056 mat_array[Q * field_num + 1] = NULL;
2059 LibmeshPetscCall(MatDuplicate(
_cmc_sys_Wij_mat, MAT_COPY_VALUES, &mat_array[Q * field_num + 2]));
2060 LibmeshPetscCall(MatAssemblyBegin(mat_array[Q * field_num + 2], MAT_FINAL_ASSEMBLY));
2061 LibmeshPetscCall(MatAssemblyEnd(mat_array[Q * field_num + 2], MAT_FINAL_ASSEMBLY));
2064 mat_array[Q * field_num + 3] = NULL;
2069 if (_pressure_cross_momentum_tight_coupling)
2077 LibmeshPetscCall(populateVectorFromHandle<SolutionHandle>(
2082 LibmeshPetscCall(VecScale(sol_holder_P, 1.0));
2083 LibmeshPetscCall(VecAXPY(vec_array[field_num], 1.0, sol_holder_P));
2084 LibmeshPetscCall(VecDestroy(&sol_holder_P));
2088 _console <<
"Cross mom ok." << std::endl;
2094 mat_array[Q * field_num + 0] = NULL;
2095 mat_array[Q * field_num + 1] = NULL;
2096 mat_array[Q * field_num + 2] = NULL;
2097 LibmeshPetscCall(MatDuplicate(
_hc_sys_h_mat, MAT_COPY_VALUES, &mat_array[Q * field_num + 3]));
2098 if (lag_block_thermal_solve)
2100 LibmeshPetscCall(MatZeroEntries(mat_array[Q * field_num + 3]));
2101 LibmeshPetscCall(MatShift(mat_array[Q * field_num + 3], 1.0));
2103 LibmeshPetscCall(MatAssemblyBegin(mat_array[Q * field_num + 3], MAT_FINAL_ASSEMBLY));
2104 LibmeshPetscCall(MatAssemblyEnd(mat_array[Q * field_num + 3], MAT_FINAL_ASSEMBLY));
2105 LibmeshPetscCall(VecDuplicate(
_hc_sys_h_rhs, &vec_array[field_num]));
2106 LibmeshPetscCall(VecCopy(
_hc_sys_h_rhs, vec_array[field_num]));
2107 if (lag_block_thermal_solve)
2109 LibmeshPetscCall(VecZeroEntries(vec_array[field_num]));
2110 LibmeshPetscCall(VecShift(vec_array[field_num], 1.0));
2114 _console <<
"Energy ok." << std::endl;
2122 LibmeshPetscCall(populateVectorFromHandle<SolutionHandle>(
2132 LibmeshPetscCall(VecSet(unity_vec, 1.0));
2141 LibmeshPetscCall(VecSet(unity_vec_Wij, 1.0));
2144 Vec _Wij_old_loc_vec;
2146 LibmeshPetscCall(MatMult(mat_array[Q],
_prod, mdot_estimate));
2147 LibmeshPetscCall(MatGetDiagonal(mat_array[Q + 1], pmat_diag));
2148 LibmeshPetscCall(VecAXPY(pmat_diag, 1e-10, unity_vec));
2149 LibmeshPetscCall(VecPointwiseDivide(p_estimate, mdot_estimate, pmat_diag));
2150 LibmeshPetscCall(MatMult(mat_array[2 * Q + 1], p_estimate, sol_holder_P));
2152 LibmeshPetscCall(MatGetDiagonal(mat_array[2 * Q + 2], diag_Wij_loc));
2153 LibmeshPetscCall(VecAXPY(diag_Wij_loc, 1e-10, unity_vec_Wij));
2154 LibmeshPetscCall(VecPointwiseDivide(Wij_estimate, sol_holder_P, diag_Wij_loc));
2157 for (
unsigned int iz = first_node; iz < last_node + 1; iz++)
2159 auto iz_ind = iz - first_node;
2160 for (
unsigned int i_ch = 0; i_ch <
_n_channels; i_ch++)
2162 PetscScalar sumWij = 0.0;
2163 unsigned int counter = 0;
2167 unsigned int i_ch_loc = chans.first;
2168 PetscInt row_vec = i_ch_loc +
_n_channels * iz_ind;
2169 PetscScalar loc_Wij_value;
2170 LibmeshPetscCall(VecGetValues(sol_holder_P, 1, &row_vec, &loc_Wij_value));
2175 LibmeshPetscCall(VecSetValues(sumWij_loc, 1, &row_vec, &sumWij, INSERT_VALUES));
2179 PetscScalar min_mdot;
2180 LibmeshPetscCall(VecAbs(
_prod));
2181 LibmeshPetscCall(VecMin(
_prod, NULL, &min_mdot));
2183 _console <<
"Minimum estimated mdot: " << min_mdot << std::endl;
2185 LibmeshPetscCall(VecAbs(sumWij_loc));
2186 LibmeshPetscCall(VecMax(sumWij_loc, NULL, &
_max_sumWij));
2192 _Wij_loc_vec,
_Wij, first_node, last_node,
_n_gaps));
2193 LibmeshPetscCall(VecAbs(_Wij_loc_vec));
2196 LibmeshPetscCall(VecAbs(_Wij_old_loc_vec));
2197 LibmeshPetscCall(VecAXPY(_Wij_loc_vec, -1.0, _Wij_old_loc_vec));
2198 PetscScalar relax_factor;
2199 LibmeshPetscCall(VecAbs(_Wij_loc_vec));
2200 #if !PETSC_VERSION_LESS_THAN(3, 16, 0) 2201 LibmeshPetscCall(VecMean(_Wij_loc_vec, &relax_factor));
2203 VecSum(_Wij_loc_vec, &relax_factor);
2208 _console <<
"Relax base value: " << relax_factor << std::endl;
2210 PetscScalar resistance_relaxation = 0.9;
2218 if (_added_K < 10 && _added_K >= 1.0)
2220 if (_added_K < 1.0 && _added_K >= 0.1)
2222 if (_added_K < 0.1 && _added_K >= 0.01)
2224 if (_added_K < 1e-2 && _added_K >= 1e-3)
2230 LibmeshPetscCall(VecScale(unity_vec_Wij,
_added_K));
2234 LibmeshPetscCall(MatDiagonalSet(mat_array[2 * Q + 2], unity_vec_Wij, ADD_VALUES));
2235 LibmeshPetscCall(VecDestroy(&mdot_estimate));
2236 LibmeshPetscCall(VecDestroy(&pmat_diag));
2237 LibmeshPetscCall(VecDestroy(&unity_vec));
2238 LibmeshPetscCall(VecDestroy(&p_estimate));
2239 LibmeshPetscCall(VecDestroy(&sol_holder_P));
2240 LibmeshPetscCall(VecDestroy(&diag_Wij_loc));
2241 LibmeshPetscCall(VecDestroy(&unity_vec_Wij));
2242 LibmeshPetscCall(VecDestroy(&Wij_estimate));
2243 LibmeshPetscCall(VecDestroy(&sumWij_loc));
2244 LibmeshPetscCall(VecDestroy(&_Wij_loc_vec));
2245 LibmeshPetscCall(VecDestroy(&_Wij_old_loc_vec));
2248 PetscScalar relaxation_factor_mdot, relaxation_factor_P, relaxation_factor_Wij;
2249 relaxation_factor_mdot = 1.0;
2250 relaxation_factor_P = 1.0;
2251 relaxation_factor_Wij = 0.1;
2255 _console <<
"Relax mdot: " << relaxation_factor_mdot << std::endl;
2256 _console <<
"Relax P: " << relaxation_factor_P << std::endl;
2257 _console <<
"Relax Wij: " << relaxation_factor_Wij << std::endl;
2260 PetscInt field_num = 0;
2262 LibmeshPetscCall(VecDuplicate(vec_array[field_num], &diag_mdot));
2263 LibmeshPetscCall(MatGetDiagonal(mat_array[Q * field_num + field_num], diag_mdot));
2264 LibmeshPetscCall(VecScale(diag_mdot, 1.0 / relaxation_factor_mdot));
2266 MatDiagonalSet(mat_array[Q * field_num + field_num], diag_mdot, INSERT_VALUES));
2267 LibmeshPetscCall(populateVectorFromHandle<SolutionHandle>(
2269 LibmeshPetscCall(VecScale(diag_mdot, (1.0 - relaxation_factor_mdot)));
2270 LibmeshPetscCall(VecPointwiseMult(
_prod,
_prod, diag_mdot));
2271 LibmeshPetscCall(VecAXPY(vec_array[field_num], 1.0,
_prod));
2272 LibmeshPetscCall(VecDestroy(&diag_mdot));
2275 _console <<
"mdot relaxed" << std::endl;
2279 LibmeshPetscCall(VecDuplicate(vec_array[field_num], &diag_P));
2280 LibmeshPetscCall(MatGetDiagonal(mat_array[Q * field_num + field_num], diag_P));
2281 LibmeshPetscCall(VecScale(diag_P, 1.0 / relaxation_factor_P));
2282 LibmeshPetscCall(MatDiagonalSet(mat_array[Q * field_num + field_num], diag_P, INSERT_VALUES));
2284 _console <<
"Mat assembled" << std::endl;
2285 LibmeshPetscCall(populateVectorFromHandle<SolutionHandle>(
2287 LibmeshPetscCall(VecScale(diag_P, (1.0 - relaxation_factor_P)));
2288 LibmeshPetscCall(VecPointwiseMult(
_prod,
_prod, diag_P));
2289 LibmeshPetscCall(VecAXPY(vec_array[field_num], 1.0,
_prod));
2290 LibmeshPetscCall(VecDestroy(&diag_P));
2293 _console <<
"P relaxed" << std::endl;
2297 LibmeshPetscCall(VecDuplicate(vec_array[field_num], &diag_Wij));
2298 LibmeshPetscCall(MatGetDiagonal(mat_array[Q * field_num + field_num], diag_Wij));
2299 LibmeshPetscCall(VecScale(diag_Wij, 1.0 / relaxation_factor_Wij));
2300 LibmeshPetscCall(MatDiagonalSet(mat_array[Q * field_num + field_num], diag_Wij, INSERT_VALUES));
2303 LibmeshPetscCall(VecScale(diag_Wij, (1.0 - relaxation_factor_Wij)));
2305 LibmeshPetscCall(VecAXPY(vec_array[field_num], 1.0,
_Wij_vec));
2306 LibmeshPetscCall(VecDestroy(&diag_Wij));
2309 _console <<
"Wij relaxed" << std::endl;
2312 _console <<
"Linear solver relaxed." << std::endl;
2315 LibmeshPetscCall(MatCreateNest(PETSC_COMM_WORLD, Q, NULL, Q, NULL, mat_array.data(), &A_nest));
2316 LibmeshPetscCall(VecCreateNest(PETSC_COMM_WORLD, Q, NULL, vec_array.data(), &b_nest));
2318 _console <<
"Nested system created." << std::endl;
2322 LibmeshPetscCall(KSPCreate(PETSC_COMM_WORLD, &ksp));
2323 LibmeshPetscCall(KSPSetType(ksp, KSPFGMRES));
2325 LibmeshPetscCall(KSPSetOperators(ksp, A_nest, A_nest));
2327 LibmeshPetscCall(KSPGetPC(ksp, &pc));
2328 LibmeshPetscCall(PCSetType(pc, PCFIELDSPLIT));
2331 std::vector<IS> rows(Q);
2334 LibmeshPetscCall(MatNestGetISs(A_nest, rows.data(), NULL));
2335 for (PetscInt
j = 0;
j < Q; ++
j)
2338 LibmeshPetscCall(ISDuplicate(rows[M], &expand1));
2340 LibmeshPetscCall(PCFieldSplitSetIS(pc, NULL, expand1));
2341 LibmeshPetscCall(ISDestroy(&expand1));
2344 _console <<
"Linear solver assembled." << std::endl;
2347 LibmeshPetscCall(VecDuplicate(b_nest, &x_nest));
2348 LibmeshPetscCall(VecSet(x_nest, 0.0));
2349 LibmeshPetscCall(KSPSolve(ksp, b_nest, x_nest));
2352 LibmeshPetscCall(VecDestroy(&b_nest));
2353 LibmeshPetscCall(MatDestroy(&A_nest));
2354 LibmeshPetscCall(KSPDestroy(&ksp));
2355 for (PetscInt i = 0; i < Q * Q; i++)
2357 LibmeshPetscCall(MatDestroy(&mat_array[i]));
2359 for (PetscInt i = 0; i < Q; i++)
2361 LibmeshPetscCall(VecDestroy(&vec_array[i]));
2364 _console <<
"Solver elements destroyed." << std::endl;
2367 Vec sol_mdot, sol_p, sol_Wij;
2369 _console <<
"Vectors created." << std::endl;
2372 LibmeshPetscCall(VecNestGetSubVecs(x_nest, &num_vecs, &loc_vecs));
2374 _console <<
"Starting extraction." << std::endl;
2376 LibmeshPetscCall(VecCopy(loc_vecs[0], sol_mdot));
2378 LibmeshPetscCall(VecCopy(loc_vecs[1], sol_p));
2380 LibmeshPetscCall(VecCopy(loc_vecs[2], sol_Wij));
2382 _console <<
"Getting individual field solutions from coupled solver." << std::endl;
2385 PetscScalar * sol_p_array;
2386 LibmeshPetscCall(VecGetArray(sol_p, &sol_p_array));
2387 PetscScalar * sol_Wij_array;
2388 LibmeshPetscCall(VecGetArray(sol_Wij, &sol_Wij_array));
2391 LibmeshPetscCall(populateSolutionChan<SolutionHandle>(
2395 for (
unsigned int iz = last_node; iz > first_node - 1; iz--)
2397 auto iz_ind = iz - first_node;
2398 for (
unsigned int i_ch = 0; i_ch <
_n_channels; i_ch++)
2408 sol_Wij,
_Wij, first_node, last_node - 1,
_n_gaps));
2413 if (lag_block_thermal_solve)
2419 LibmeshPetscCall(KSPCreate(PETSC_COMM_WORLD, &ksploc));
2421 LibmeshPetscCall(KSPGetPC(ksploc, &pc));
2422 LibmeshPetscCall(PCSetType(pc, PCJACOBI));
2424 LibmeshPetscCall(KSPSetFromOptions(ksploc));
2427 LibmeshPetscCall(VecGetArray(sol, &xx));
2428 for (
unsigned int iz = first_node; iz < last_node + 1; iz++)
2430 auto iz_ind = iz - first_node;
2431 for (
unsigned int i_ch = 0; i_ch <
_n_channels; i_ch++)
2438 " : Calculation of negative Enthalpy h_out = : ",
2443 _h_soln->set(node_out, h_out);
2446 LibmeshPetscCall(KSPDestroy(&ksploc));
2447 LibmeshPetscCall(VecDestroy(&sol));
2453 LibmeshPetscCall(VecCopy(loc_vecs[3], sol_h));
2454 PetscScalar * sol_h_array;
2455 LibmeshPetscCall(VecGetArray(sol_h, &sol_h_array));
2456 for (
unsigned int iz = first_node; iz < last_node + 1; iz++)
2458 auto iz_ind = iz - first_node;
2459 for (
unsigned int i_ch = 0; i_ch <
_n_channels; i_ch++)
2462 auto h_out = sol_h_array[iz_ind *
_n_channels + i_ch];
2466 " : Calculation of negative Enthalpy h_out = : ",
2471 _h_soln->set(node_out, h_out);
2474 LibmeshPetscCall(VecDestroy(&sol_h));
2480 LibmeshPetscCall(populateSolutionChan<SolutionHandle>(
2485 LibmeshPetscCall(populateVectorFromHandle<SolutionHandle>(
2488 LibmeshPetscCall(VecAbs(
_prod));
2496 _console <<
"Solutions assigned to MOOSE variables." << std::endl;
2499 LibmeshPetscCall(VecDestroy(&x_nest));
2500 LibmeshPetscCall(VecDestroy(&sol_mdot));
2501 LibmeshPetscCall(VecDestroy(&sol_p));
2502 LibmeshPetscCall(VecDestroy(&sol_Wij));
2503 LibmeshPetscCall(VecDestroy(&sumWij_loc));
2505 _console <<
"Solutions destroyed." << std::endl;
2513 _console <<
"Executing subchannel solver\n";
2518 _console <<
"Solution initialized" << std::endl;
2520 unsigned int P_it = 0;
2521 unsigned int P_it_max;
2531 while ((P_error >
_P_tol && P_it < P_it_max))
2536 _console <<
"Reached maximum number of axial pressure iterations" << std::endl;
2539 _console <<
"Solving Outer Iteration : " << P_it << std::endl;
2540 auto P_L2norm_old_axial =
_P_soln->L2norm();
2541 for (
unsigned int iblock = 0; iblock <
_n_blocks; iblock++)
2545 Real T_block_error = 1.0;
2547 _console <<
"Solving Block: " << iblock <<
" From first level: " << first_level
2548 <<
" to last level: " << last_level << std::endl;
2554 _console <<
"Reached maximum number of temperature iterations for block: " << iblock
2558 auto T_L2norm_old_block =
_T_soln->L2norm();
2575 _console <<
"Done with main solve." << std::endl;
2584 _console <<
"Starting thermal solve." << std::endl;
2591 _console <<
"Done with thermal solve." << std::endl;
2596 _console <<
"Start updating thermophysical properties." << std::endl;
2605 _console <<
"Done updating thermophysical properties." << std::endl;
2609 _aux->solution().close();
2611 auto T_L2norm_new =
_T_soln->L2norm();
2613 std::abs((T_L2norm_new - T_L2norm_old_block) / (T_L2norm_old_block + 1E-14));
2614 _console <<
"T_block_error: " << T_block_error << std::endl;
2617 auto P_L2norm_new_axial =
_P_soln->L2norm();
2619 std::abs((P_L2norm_new_axial - P_L2norm_old_axial) / (P_L2norm_old_axial +
_P_out + 1E-14));
2620 _console <<
"P_error :" << P_error << std::endl;
2623 _console <<
"Iteration: " << P_it << std::endl;
2624 _console <<
"Maximum iterations: " << P_it_max << std::endl;
2629 _console <<
"Finished executing subchannel solver\n";
2634 _console <<
"Commencing calculation of Pin surface temperature \n";
2635 for (
unsigned int i_pin = 0; i_pin <
_n_pins; i_pin++)
2637 for (
unsigned int iz = 0; iz <
_n_cells + 1; ++iz)
2641 Real rod_counter = 0.0;
2646 auto mu = (*_mu_soln)(node);
2647 auto S = (*_S_flow_soln)(node);
2648 auto w_perim = (*_w_perim_soln)(node);
2649 auto Dh_i = 4.0 *
S / w_perim;
2650 auto Re = (((*_mdot_soln)(node) /
S) * Dh_i /
mu);
2653 auto Pr = (*_mu_soln)(node)*
cp /
k;
2655 auto hw = Nu *
k / Dh_i;
2657 mooseError(
"Dpin should not be null or negative when computing pin powers: ",
2660 (*_q_prime_soln)(pin_node) / ((*
_Dpin_soln)(pin_node)*M_PI * hw) + (*_T_soln)(node);
2663 if (rod_counter > 0)
2664 _Tpin_soln->set(pin_node, sumTemp / rod_counter);
2666 mooseError(
"Pin was not found for pin index: " + std::to_string(i_pin));
2674 _console <<
"Commencing calculation of duct surface temperature " << std::endl;
2676 for (Node * dn : duct_nodes)
2679 auto mu = (*_mu_soln)(node_chan);
2680 auto S = (*_S_flow_soln)(node_chan);
2681 auto w_perim = (*_w_perim_soln)(node_chan);
2682 auto Dh_i = 4.0 *
S / w_perim;
2683 auto Re = (((*_mdot_soln)(node_chan) /
S) * Dh_i /
mu);
2686 auto Pr = (*_mu_soln)(node_chan)*
cp /
k;
2689 auto hw = Nu *
k / Dh_i;
2690 auto T_chan = (*_duct_heat_flux_soln)(dn) / hw + (*
_T_soln)(node_chan);
2694 _aux->solution().close();
2697 Real power_in = 0.0;
2698 Real power_out = 0.0;
2699 Real Total_surface_area = 0.0;
2700 Real Total_wetted_perimeter = 0.0;
2701 Real mass_flow_in = 0.0;
2702 Real mass_flow_out = 0.0;
2703 for (
unsigned int i_ch = 0; i_ch <
_n_channels; i_ch++)
2707 Total_surface_area += (*_S_flow_soln)(node_in);
2708 Total_wetted_perimeter += (*_w_perim_soln)(node_in);
2709 power_in += (*_mdot_soln)(node_in) * (*
_h_soln)(node_in);
2710 power_out += (*_mdot_soln)(node_out) * (*
_h_soln)(node_out);
2711 mass_flow_in += (*_mdot_soln)(node_in);
2712 mass_flow_out += (*_mdot_soln)(node_out);
2714 auto h_bulk_out = power_out / mass_flow_out;
2715 auto T_bulk_out =
_fp->T_from_p_h(
_P_out, h_bulk_out);
2717 Real bulk_Dh = 4.0 * Total_surface_area / Total_wetted_perimeter;
2719 Real bulk_Re = mass_flow_in * bulk_Dh / (inlet_mu * Total_surface_area);
2722 _console <<
" ======================================= " << std::endl;
2723 _console <<
" ======== Subchannel Print Outs ======== " << std::endl;
2724 _console <<
" ======================================= " << std::endl;
2725 _console <<
"Total flow area :" << Total_surface_area <<
" m^2" << std::endl;
2726 _console <<
"Assembly hydraulic diameter :" << bulk_Dh <<
" m" << std::endl;
2727 _console <<
"Assembly Re number :" << bulk_Re <<
" [-]" << std::endl;
2728 _console <<
"Bulk coolant temperature at outlet :" << T_bulk_out <<
" K" << std::endl;
2729 _console <<
"Power added to coolant is : " << power_out - power_in <<
" Watt" << std::endl;
2730 _console <<
"Mass flow rate in is : " << mass_flow_in <<
" kg/sec" << std::endl;
2731 _console <<
"Mass balance is : " << mass_flow_out - mass_flow_in <<
" kg/sec" << std::endl;
2732 _console <<
"User defined outlet pressure is : " <<
_P_out <<
" Pa" << std::endl;
2733 _console <<
" ======================================= " << std::endl;
2738 "Energy conservation equation might not be solved correctly, Power added to coolant: " +
2739 std::to_string(power_out - power_in) +
" Watt ");
Vec _amc_friction_force_rhs
Mat _amc_sys_mdot_mat
Axial momentum system matrix.
static const std::string PRESSURE_DROP
pressure drop
static const std::string MASS_FLOW_RATE
mass flow rate
const bool _pin_mesh_exist
Flag that informs if there is a pin mesh or not.
void computeRho(int iblock)
Computes Density per channel for block iblock.
Vec _amc_gravity_rhs
Axial momentum conservation - buoyancy force No implicit matrix.
virtual const unsigned int & getNumOfChannels() const =0
Return the number of channels per layer.
std::unique_ptr< SolutionHandle > _Tduct_soln
std::unique_ptr< SolutionHandle > _duct_heat_flux_soln
static const std::string DENSITY
density
void computeSumWij(int iblock)
Computes net diversion crossflow per channel for block iblock.
unsigned int _n_blocks
number of axial blocks
const bool _compute_power
Flag that informs if we need to solve the Enthalpy/Temperature equations or not.
static InputParameters validParams()
std::unique_ptr< SolutionHandle > _T_soln
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.
virtual const std::vector< unsigned int > & getPinChannels(unsigned int i_pin) const =0
Return a vector of channel indices for a given Pin index.
virtual Node * getChannelNodeFromDuct(Node *channel_node)=0
Function that gets the channel node from the duct node.
T & getMesh(MooseMesh &mesh)
function to cast mesh
PetscScalar _max_sumWij_new
Mat _cmc_friction_force_mat
Cross momentum conservation - friction force.
void computeP(int iblock)
Computes Pressure per channel for block iblock.
Real _TR
Flag that activates or deactivates the transient parts of the equations we solve by multiplication...
libMesh::DenseMatrix< Real > _Wij_old
const PostprocessorValue & _P_out
Outlet Pressure.
SubChannelMesh & _subchannel_mesh
void computeT(int iblock)
Computes Temperature per channel for block iblock.
virtual void zero() override final
virtual const std::vector< Real > & getZGrid() const
Get axial location of layers.
Vec _amc_pressure_force_rhs
void computeMdot(int iblock)
Computes mass flow per channel for block iblock.
virtual const Real & getPitch() const
Return the pitch between 2 subchannels.
virtual EChannelType getSubchannelType(unsigned int index) const =0
Return the type of the subchannel for given subchannel index.
std::unique_ptr< SolutionHandle > _S_flow_soln
Vec _hc_time_derivative_rhs
const bool _compute_density
Flag that activates or deactivates the calculation of density.
Vec _mc_axial_convection_rhs
Mat _amc_friction_force_mat
Axial momentum conservation - friction force.
static const std::string PIN_DIAMETER
pin diameter
PetscScalar _added_K
Added resistances for monolithic convergence.
PetscErrorCode createPetscVector(Vec &v, PetscInt n)
Petsc Functions.
static InputParameters validParams()
Vec _cmc_advective_derivative_rhs
const bool _duct_mesh_exist
Flag that informs if there is a pin mesh or not.
static InputParameters validParams()
const Real & _T_tol
Convergence tolerance for the temperature loop in external solve.
Vec _amc_time_derivative_rhs
void computeMu(int iblock)
Computes Viscosity per channel for block iblock.
The following methods are specializations for using the Parallel::packed_range_* routines for a vecto...
virtual Node * getPinNode(unsigned int i_pin, unsigned iz) const =0
Get the pin mesh node for a given pin index and elevation index.
PetscScalar computeInterpolatedValue(PetscScalar topValue, PetscScalar botValue, PetscScalar Peclet=0.0)
bool isRestarting() const
const bool _segregated_bool
Segregated solve.
Mat _cmc_sys_Wij_mat
Lateral momentum system matrix.
Vec _amc_advective_derivative_rhs
bool _converged
Variable that informs whether we exited external solve with a converged solution or not...
virtual const std::vector< unsigned int > & getChannelGaps(unsigned int i_chan) const =0
Return a vector of gap indices for a given channel index.
Vec _hc_cross_derivative_rhs
const bool _staggered_pressure_bool
Flag to define the usage of staggered or collocated pressure.
virtual void initializeSolution()=0
Function to initialize the solution & geometry fields.
virtual const MooseVariableFieldBase & getVariable(const THREAD_ID tid, const std::string &var_name, Moose::VarKindType expected_var_type=Moose::VarKindType::VAR_ANY, Moose::VarFieldType expected_var_field_type=Moose::VarFieldType::VAR_FIELD_ANY) const override
Real computeAddedHeatDuct(unsigned int i_ch, unsigned int iz)
Function that computes the heat added by the duct, for channel i_ch and cell iz.
Mat _mc_sumWij_mat
Matrices and vectors to be used in implicit assembly Mass conservation Mass conservation - sum of cro...
PetscErrorCode populateVectorFromDense(Vec &x, const T &solution, const unsigned int first_axial_level, const unsigned int last_axial_level, const unsigned int cross_dimension)
static const std::string DUCT_HEAT_FLUX
duct linear heat rate
static const std::string DUCT_TEMPERATURE
duct temperature
SubChannel1PhaseProblem * schp
const Real & _CT
Turbulent modeling parameter used in axial momentum equation.
virtual Node * getChannelNode(unsigned int i_chan, unsigned iz) const =0
Get the subchannel mesh node for a given channel index and elevation index.
static const std::string WETTED_PERIMETER
wetted perimeter
virtual void computeh(int iblock)=0
Computes Enthalpy per channel for block iblock.
std::unique_ptr< SolutionHandle > _rho_soln
Mat _amc_turbulent_cross_flows_mat
Mass conservation - density time derivative No implicit matrix.
static const std::string cp
Mat _amc_advective_derivative_mat
Axial momentum conservation - advective (Eulerian) derivative.
static const std::string VISCOSITY
viscosity
Vec _hc_added_heat_rhs
Enthalpy conservation - source and sink.
processor_id_type n_processors() const
std::vector< Real > _z_grid
axial location of nodes
const std::string & name() const
static const std::string PIN_TEMPERATURE
pin temperature
Vec _cmc_time_derivative_rhs
const int & _T_maxit
Maximum iterations for the inner temperature loop.
Mat _amc_pressure_force_mat
Axial momentum conservation - pressure force.
static const std::string LINEAR_HEAT_RATE
linear heat rate
Real value(unsigned n, unsigned alpha, unsigned beta, Real x)
void computeWijResidual(int iblock)
Computes Residual Matrix based on the lateral momentum conservation equation for block iblock...
const std::vector< double > x
static const std::string S
Real f(Real x)
Test function for Brents method.
std::unique_ptr< SolutionHandle > _q_prime_soln
virtual void syncSolutions(Direction direction) override
static const std::string mu
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.
static const std::string ENTHALPY
enthalpy
Real root(std::function< Real(Real)> const &f, Real x1, Real x2, Real tol=1.0e-12)
Finds the root of a function using Brent's method.
std::shared_ptr< AuxiliarySystem > _aux
virtual const unsigned int & getNumOfPins() const =0
Return the number of pins.
Mat _hc_cross_derivative_mat
Enthalpy conservation - cross flux derivative.
Mat _mc_axial_convection_mat
Mass conservation - axial convection.
virtual Node * getDuctNodeFromChannel(Node *channel_node)=0
Function that gets the duct node from the channel node.
void initialSetup() override
auto Peclet(const T1 &volume_fraction, const T2 &cp, const T3 &rho, const T4 &vel, const T5 &D_h, const T6 &k)
Compute Peclet number.
virtual Real computeFrictionFactor(FrictionStruct friction_args)=0
Returns friction factor.
virtual ~SubChannel1PhaseProblem()
const PetscInt & _maxit
The maximum number of iterations to use for the ksp linear solver.
PetscErrorCode createPetscMatrix(Mat &M, PetscInt n, PetscInt m)
friend PetscErrorCode formFunction(SNES snes, Vec x, Vec f, void *ctx)
This is the residual Vector function in a form compatible with the SNES PETC solvers.
virtual const std::vector< std::vector< Real > > & getKGrid() const
Get axial cell location and value of loss coefficient.
const MooseEnum _interpolation_scheme
The interpolation method used in constructing the systems.
std::unique_ptr< SolutionHandle > _Dpin_soln
virtual Real getSubChannelPeripheralDuctWidth(unsigned int i_ch)=0
Function that computes the width of the duct cell that the peripheral subchannel i_ch sees...
Base class for the 1-phase steady-state/transient subchannel solver.
libMesh::DenseMatrix< Real > _Wij_residual_matrix
std::unique_ptr< SolutionHandle > _mdot_soln
PetscErrorCode populateDenseFromVector(const Vec &x, T &solution, const unsigned int first_axial_level, const unsigned int last_axial_level, const unsigned int cross_dimension)
static const std::string SUM_CROSSFLOW
sum of diversion crossflow
virtual const unsigned int & getNumOfAxialCells() const
Return the number of axial cells.
virtual Real getGapWidth(unsigned int axial_index, unsigned int gap_index) const =0
Return gap width for a given gap index.
LibmeshPetscCallQ(DMShellGetContext(dm, &ctx))
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
PetscErrorCode formFunction(SNES, Vec x, Vec f, void *ctx)
virtual const std::vector< Node * > getDuctNodes() const =0
Function that return the vector with the maps to the nodes if they exist.
std::unique_ptr< SolutionHandle > _DP_soln
const bool _compute_viscosity
Flag that activates or deactivates the calculation of viscosity.
static const std::string PRESSURE
pressure
libMesh::DenseMatrix< Real > & _Wij
virtual void externalSolve() override
void computeWijPrime(int iblock)
Computes turbulent crossflow per gap for block iblock.
static const std::string alpha
virtual const Real & getCrossflowSign(unsigned int i_chan, unsigned int i_local) const =0
Return a sign for the crossflow given a subchannel index and local neighbor index.
std::unique_ptr< SolutionHandle > _SumWij_soln
PetscErrorCode petscSnesSolver(int iblock, const libMesh::DenseVector< Real > &solution, libMesh::DenseVector< Real > &root)
Computes solution of nonlinear equation using snes and provided a residual in a formFunction.
Vec _hc_advective_derivative_rhs
libMesh::DenseVector< Real > residualFunction(int iblock, libMesh::DenseVector< Real > solution)
Computes Residual Vector based on the lateral momentum conservation equation for block iblock & updat...
static const std::string SURFACE_AREA
surface area
bool absoluteFuzzyLessEqual(const T &var1, const T2 &var2, const T3 &tol=libMesh::TOLERANCE *libMesh::TOLERANCE)
void mooseWarning(Args &&... args) const
void resize(const unsigned int new_m, const unsigned int new_n)
const bool _verbose_subchannel
Boolean to printout information related to subchannel solve.
PetscScalar _correction_factor
Mat _amc_cross_derivative_mat
Axial momentum conservation - cross flux derivative.
void mooseError(Args &&... args) const
const Real & _P_tol
Convergence tolerance for the pressure loop in external solve.
virtual Real computeBeta(unsigned int i_gap, unsigned int iz, bool enthalpy)=0
Computes turbulent mixing coefficient.
virtual bool solverSystemConverged(const unsigned int) override
virtual const unsigned int & getNumOfGapsPerLayer() const =0
Return the number of gaps per layer.
struct SubChannel1PhaseProblem::FrictionStruct _friction_args
static const std::complex< double > j(0, 1)
Complex number "j" (also known as "i")
Mat _hc_advective_derivative_mat
Enthalpy conservation - advective (Eulerian) derivative;.
Base class for subchannel meshes.
void computeWijFromSolve(int iblock)
Computes diversion crossflow per gap for block iblock.
const bool _implicit_bool
Flag to define the usage of a implicit or explicit solution.
Mat _amc_time_derivative_mat
Axial momentum conservation - time derivative.
const ConsoleStream _console
static const std::string DISPLACEMENT
subchannel displacement
Mat _hc_time_derivative_mat
Enthalpy Enthalpy conservation - time derivative.
virtual bool isTransient() const override
PetscErrorCode implicitPetscSolve(int iblock)
Computes implicit solve using PetSc.
void computeDP(int iblock)
Computes Pressure Drop per channel for block iblock.
SubChannel1PhaseProblem(const InputParameters ¶ms)
Mat _cmc_time_derivative_mat
Cross momentum Cross momentum conservation - time derivative.
libMesh::DenseMatrix< Real > _WijPrime
virtual void initialSetup() override
PetscFunctionReturn(LIBMESH_PETSC_SUCCESS)
Vec _cmc_friction_force_rhs
bool isRecovering() const
static const std::string TEMPERATURE
temperature
Mat _cmc_pressure_force_mat
Cross momentum conservation - pressure force.
virtual Real & dt() const
Vec _amc_turbulent_cross_flows_rhs
MooseUnits pow(const MooseUnits &, int)
std::unique_ptr< SolutionHandle > _P_soln
static const std::string k
std::unique_ptr< SolutionHandle > _w_perim_soln
void ErrorVector unsigned int
Vec _cmc_pressure_force_rhs
Vec _amc_cross_derivative_rhs
Mat _cmc_advective_derivative_mat
Cross momentum conservation - advective (Eulerian) derivative.
const SinglePhaseFluidProperties * _fp
Solutions handles and link to TH tables properties.
Mat _hc_sys_h_mat
System matrices.
std::unique_ptr< SolutionHandle > _mu_soln
virtual const std::pair< unsigned int, unsigned int > & getGapChannels(unsigned int i_gap) const =0
Return a pair of subchannel indices for a given gap index.
std::unique_ptr< SolutionHandle > _Tpin_soln