12 #include "libmesh/petsc_vector.h" 13 #include "libmesh/dense_matrix.h" 14 #include "libmesh/dense_vector.h" 31 const PetscScalar * xx;
41 for (PetscInt i = 0; i < size; i++)
42 solution_seed(i) = xx[i];
50 for (
int i = 0; i < size; i++)
51 ff[i] = Wij_residual_vector(i);
60 MooseEnum schemes(
"upwind downwind central_difference exponential",
"upwind");
63 params.
addRequiredParam<
unsigned int>(
"n_blocks",
"The number of blocks in the axial direction");
65 "Thermal diffusion coefficient used in turbulent crossflow");
67 params.
addParam<
Real>(
"P_tol", 1e-6,
"Pressure tolerance");
68 params.
addParam<
Real>(
"T_tol", 1e-6,
"Temperature tolerance");
69 params.
addParam<
int>(
"T_maxit", 10,
"Maximum number of iterations for inner temperature loop");
70 params.
addParam<PetscReal>(
"rtol", 1e-6,
"Relative tolerance for ksp solver");
71 params.
addParam<PetscReal>(
"atol", 1e-6,
"Absolute tolerance for ksp solver");
72 params.
addParam<PetscReal>(
"dtol", 1e5,
"Divergence tolerance for ksp solver");
73 params.
addParam<PetscInt>(
"maxit", 1e4,
"Maximum number of iterations for ksp solver");
75 "interpolation_scheme", schemes,
"Interpolation scheme used for the method.");
77 "implicit",
false,
"Boolean to define the use of explicit or implicit solution.");
78 params.
addParam<
bool>(
"staggered_pressure",
80 "Boolean to define the use of the staggered pressure formulation.");
84 "Boolean to define whether to use a segregated solver (physics solved independently).");
86 "monolithic_thermal",
false,
"Boolean to define whether to use thermal monolithic solve.");
87 params.
addRequiredParam<
bool>(
"compute_density",
"Flag that enables the calculation of density");
89 "Flag that enables the calculation of viscosity");
92 "Flag that informs whether we solve the Enthalpy/Temperature equations or not");
94 params.
addRequiredParam<UserObjectName>(
"fp",
"Fluid properties user object name");
101 _n_blocks(getParam<unsigned
int>(
"n_blocks")),
102 _Wij(declareRestartableData<
libMesh::DenseMatrix<
Real>>(
"Wij")),
104 _kij(_subchannel_mesh.getKij()),
105 _n_cells(_subchannel_mesh.getNumOfAxialCells()),
106 _n_gaps(_subchannel_mesh.getNumOfGapsPerLayer()),
107 _n_assemblies(_subchannel_mesh.getNumOfAssemblies()),
108 _n_channels(_subchannel_mesh.getNumOfChannels()),
109 _block_size(_n_cells / _n_blocks),
110 _z_grid(_subchannel_mesh.getZGrid()),
112 _TR(isTransient() ? 1. : 0.),
113 _compute_density(getParam<bool>(
"compute_density")),
114 _compute_viscosity(getParam<bool>(
"compute_viscosity")),
115 _compute_power(getParam<bool>(
"compute_power")),
116 _pin_mesh_exist(_subchannel_mesh.pinMeshExist()),
117 _dt(isTransient() ? dt() : _one),
118 _P_out(getParam<
Real>(
"P_out")),
119 _beta(getParam<
Real>(
"beta")),
120 _CT(getParam<
Real>(
"CT")),
121 _P_tol(getParam<
Real>(
"P_tol")),
122 _T_tol(getParam<
Real>(
"T_tol")),
123 _T_maxit(getParam<
int>(
"T_maxit")),
124 _rtol(getParam<PetscReal>(
"rtol")),
125 _atol(getParam<PetscReal>(
"atol")),
126 _dtol(getParam<PetscReal>(
"dtol")),
127 _maxit(getParam<PetscInt>(
"maxit")),
128 _interpolation_scheme(getParam<
MooseEnum>(
"interpolation_scheme")),
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")),
220 ": When implicit number of blocks can't be equal to number of cells. This will " 221 "cause problems with the subchannel interpolation scheme.");
229 _fp = &getUserObject<SinglePhaseFluidProperties>(getParam<UserObjectName>(
"fp"));
247 PetscErrorCode ierr =
cleanUp();
259 LibmeshPetscCall(VecDestroy(&
_Wij_vec));
260 LibmeshPetscCall(VecDestroy(&
_prod));
261 LibmeshPetscCall(VecDestroy(&
_prodp));
337 ": Interpolation scheme should be a string: upwind, downwind, central_difference, " 344 PetscScalar botValue,
348 return alpha * botValue + (1.0 -
alpha) * topValue;
355 LibmeshPetscCall(VecCreate(PETSC_COMM_WORLD, &
v));
356 LibmeshPetscCall(PetscObjectSetName((PetscObject)
v,
"Solution"));
357 LibmeshPetscCall(VecSetSizes(
v, PETSC_DECIDE, n));
358 LibmeshPetscCall(VecSetFromOptions(
v));
359 LibmeshPetscCall(VecZeroEntries(
v));
367 LibmeshPetscCall(MatCreate(PETSC_COMM_WORLD, &M));
368 LibmeshPetscCall(MatSetSizes(M, PETSC_DECIDE, PETSC_DECIDE, n, m));
369 LibmeshPetscCall(MatSetFromOptions(M));
370 LibmeshPetscCall(MatSetUp(M));
377 const T & loc_solution,
378 const unsigned int first_axial_level,
379 const unsigned int last_axial_level,
380 const unsigned int cross_dimension)
384 LibmeshPetscCall(VecGetArray(
x, &xx));
385 for (
unsigned int iz = first_axial_level; iz < last_axial_level; iz++)
387 unsigned int iz_ind = iz - first_axial_level;
388 for (
unsigned int i_l = 0; i_l < cross_dimension; i_l++)
390 xx[iz_ind * cross_dimension + i_l] = loc_solution(i_l, iz);
393 LibmeshPetscCall(VecRestoreArray(
x, &xx));
400 const T & loc_solution,
401 const unsigned int first_axial_level,
402 const unsigned int last_axial_level,
403 const unsigned int cross_dimension)
407 LibmeshPetscCall(VecGetArray(
x, &xx));
408 for (
unsigned int iz = first_axial_level; iz < last_axial_level + 1; iz++)
410 unsigned int iz_ind = iz - first_axial_level;
411 for (
unsigned int i_l = 0; i_l < cross_dimension; i_l++)
414 xx[iz_ind * cross_dimension + i_l] = loc_solution(loc_node);
417 LibmeshPetscCall(VecRestoreArray(
x, &xx));
425 const unsigned int first_axial_level,
426 const unsigned int last_axial_level,
427 const unsigned int cross_dimension)
431 LibmeshPetscCall(VecGetArray(
x, &xx));
433 for (
unsigned int iz = first_axial_level; iz < last_axial_level + 1; iz++)
435 unsigned int iz_ind = iz - first_axial_level;
436 for (
unsigned int i_l = 0; i_l < cross_dimension; i_l++)
439 loc_solution.set(loc_node, xx[iz_ind * cross_dimension + i_l]);
449 const unsigned int first_axial_level,
450 const unsigned int last_axial_level,
451 const unsigned int cross_dimension)
455 LibmeshPetscCall(VecGetArray(
x, &xx));
456 for (
unsigned int iz = first_axial_level; iz < last_axial_level + 1; iz++)
458 unsigned int iz_ind = iz - first_axial_level;
459 for (
unsigned int i_l = 0; i_l < cross_dimension; i_l++)
461 loc_solution(iz * cross_dimension + i_l) = xx[iz_ind * cross_dimension + i_l];
470 unsigned int last_node = (iblock + 1) *
_block_size;
471 unsigned int first_node = iblock *
_block_size + 1;
474 for (
unsigned int iz = first_node; iz < last_node + 1; iz++)
476 for (
unsigned int i_gap = 0; i_gap <
_n_gaps; i_gap++)
478 int i =
_n_gaps * (iz - first_node) + i_gap;
479 solution_seed(i) =
_Wij(i_gap, iz);
490 for (
unsigned int iz = first_node; iz < last_node + 1; iz++)
492 for (
unsigned int i_gap = 0; i_gap <
_n_gaps; i_gap++)
503 unsigned int last_node = (iblock + 1) *
_block_size;
504 unsigned int first_node = iblock *
_block_size + 1;
508 for (
unsigned int iz = first_node; iz < last_node + 1; iz++)
510 for (
unsigned int i_ch = 0; i_ch <
_n_channels; i_ch++)
515 unsigned int counter = 0;
529 for (
unsigned int iz = first_node; iz < last_node + 1; iz++)
531 unsigned int iz_ind = iz - first_node;
532 for (
unsigned int i_ch = 0; i_ch <
_n_channels; i_ch++)
535 unsigned int counter = 0;
539 PetscInt col = i_gap +
_n_gaps * iz_ind;
546 LibmeshPetscCall(MatAssemblyBegin(
_mc_sumWij_mat, MAT_FINAL_ASSEMBLY));
547 LibmeshPetscCall(MatAssemblyEnd(
_mc_sumWij_mat, MAT_FINAL_ASSEMBLY));
553 LibmeshPetscCall(VecDuplicate(
_Wij_vec, &loc_Wij));
555 loc_Wij,
_Wij, first_node, last_node + 1,
_n_gaps));
557 LibmeshPetscCall(populateSolutionChan<SolutionHandle>(
559 LibmeshPetscCall(VecDestroy(&loc_prod));
560 LibmeshPetscCall(VecDestroy(&loc_Wij));
568 unsigned int last_node = (iblock + 1) *
_block_size;
569 unsigned int first_node = iblock *
_block_size + 1;
572 for (
unsigned int iz = first_node; iz < last_node + 1; iz++)
575 for (
unsigned int i_ch = 0; i_ch <
_n_channels; i_ch++)
579 auto volume = dz * (*_S_flow_soln)(node_in);
582 auto mdot_out = (*_mdot_soln)(node_in) - (*
_SumWij_soln)(node_out)-time_term;
587 " : Calculation of negative mass flow mdot_out = : ",
591 " - Implicit solves are required for recirculating flow.");
599 for (
unsigned int iz = first_node; iz < last_node + 1; iz++)
602 auto iz_ind = iz - first_node;
603 for (
unsigned int i_ch = 0; i_ch <
_n_channels; i_ch++)
607 auto volume = dz * (*_S_flow_soln)(node_in);
612 PetscScalar value_vec = -1.0 * time_term;
617 if (iz == first_node)
619 PetscScalar value_vec = (*_mdot_soln)(node_in);
628 PetscScalar
value = -1.0;
636 PetscScalar
value = 1.0;
643 PetscScalar value_vec_2 = -1.0 * (*_SumWij_soln)(node_out);
652 _console <<
"Block: " << iblock <<
" - Mass conservation matrix assembled" << std::endl;
660 LibmeshPetscCall(KSPCreate(PETSC_COMM_WORLD, &ksploc));
662 LibmeshPetscCall(KSPGetPC(ksploc, &pc));
663 LibmeshPetscCall(PCSetType(pc, PCJACOBI));
665 LibmeshPetscCall(KSPSetOptionsPrefix(ksploc,
"mass_sys_"));
666 LibmeshPetscCall(KSPSetFromOptions(ksploc));
668 LibmeshPetscCall(populateSolutionChan<SolutionHandle>(
671 LibmeshPetscCall(KSPDestroy(&ksploc));
672 LibmeshPetscCall(VecDestroy(&sol));
680 unsigned int last_node = (iblock + 1) *
_block_size;
681 unsigned int first_node = iblock *
_block_size + 1;
685 for (
unsigned int iz = first_node; iz < last_node + 1; iz++)
688 for (
unsigned int i_gap = 0; i_gap <
_n_gaps; i_gap++)
691 unsigned int i_ch = chans.first;
692 unsigned int j_ch = chans.second;
697 auto Si_in = (*_S_flow_soln)(node_in_i);
698 auto Sj_in = (*_S_flow_soln)(node_in_j);
699 auto Si_out = (*_S_flow_soln)(node_out_i);
700 auto Sj_out = (*_S_flow_soln)(node_out_j);
706 (((*_mdot_soln)(node_in_i) + (*
_mdot_soln)(node_in_j)) / (Si_in + Sj_in) +
714 for (
unsigned int iz = first_node; iz < last_node + 1; iz++)
717 auto iz_ind = iz - first_node;
718 for (
unsigned int i_gap = 0; i_gap <
_n_gaps; i_gap++)
721 unsigned int i_ch = chans.first;
722 unsigned int j_ch = chans.second;
727 auto Si_in = (*_S_flow_soln)(node_in_i);
728 auto Sj_in = (*_S_flow_soln)(node_in_j);
729 auto Si_out = (*_S_flow_soln)(node_out_i);
730 auto Sj_out = (*_S_flow_soln)(node_out_j);
735 PetscScalar base_value =
_beta * 0.5 * Sij;
738 if (iz == first_node)
740 PetscScalar value_tl = -1.0 * base_value / (Si_in + Sj_in) *
742 PetscInt row = i_gap +
_n_gaps * iz_ind;
748 PetscScalar value_tl = base_value / (Si_in + Sj_in);
749 PetscInt row = i_gap +
_n_gaps * iz_ind;
751 PetscInt col_ich = i_ch +
_n_channels * (iz_ind - 1);
752 LibmeshPetscCall(MatSetValues(
755 PetscInt col_jch = j_ch +
_n_channels * (iz_ind - 1);
756 LibmeshPetscCall(MatSetValues(
761 PetscScalar value_bl = base_value / (Si_out + Sj_out);
762 PetscInt row = i_gap +
_n_gaps * iz_ind;
765 LibmeshPetscCall(MatSetValues(
769 LibmeshPetscCall(MatSetValues(
780 LibmeshPetscCall(VecDuplicate(
_Wij_vec, &loc_Wij));
781 LibmeshPetscCall(populateVectorFromHandle<SolutionHandle>(
787 LibmeshPetscCall(VecDestroy(&loc_prod));
788 LibmeshPetscCall(VecDestroy(&loc_Wij));
795 unsigned int last_node = (iblock + 1) *
_block_size;
796 unsigned int first_node = iblock *
_block_size + 1;
800 for (
unsigned int iz = first_node; iz < last_node + 1; iz++)
804 for (
unsigned int i_ch = 0; i_ch <
_n_channels; i_ch++)
808 auto rho_in = (*_rho_soln)(node_in);
809 auto rho_out = (*_rho_soln)(node_out);
810 auto mu_in = (*_mu_soln)(node_in);
811 auto S = (*_S_flow_soln)(node_in);
812 auto w_perim = (*_w_perim_soln)(node_in);
814 auto Dh_i = 4.0 *
S / w_perim;
815 auto time_term =
_TR * ((*_mdot_soln)(node_out)-
_mdot_soln->old(node_out)) * dz /
_dt -
820 auto mass_term2 = -2.0 * (*_mdot_soln)(node_out) * (*
_SumWij_soln)(node_out) /
S / rho_in;
821 auto crossflow_term = 0.0;
822 auto turbulent_term = 0.0;
823 unsigned int counter = 0;
827 unsigned int ii_ch = chans.first;
828 unsigned int jj_ch = chans.second;
833 auto rho_i = (*_rho_soln)(node_in_i);
834 auto rho_j = (*_rho_soln)(node_in_j);
835 auto Si = (*_S_flow_soln)(node_in_i);
836 auto Sj = (*_S_flow_soln)(node_in_j);
839 if (
_Wij(i_gap, iz) > 0.0)
840 u_star = (*_mdot_soln)(node_out_i) / Si / rho_i;
842 u_star = (*_mdot_soln)(node_out_j) / Sj / rho_j;
847 turbulent_term +=
_WijPrime(i_gap, iz) * (2 * (*_mdot_soln)(node_out) / rho_in /
S -
852 turbulent_term *=
_CT;
853 auto Re = (((*_mdot_soln)(node_in) /
S) * Dh_i / mu_in);
855 auto ki = k_grid[i_ch][iz - 1];
856 auto friction_term = (fi * dz / Dh_i + ki) * 0.5 *
859 auto gravity_term =
_g_grav * (*_rho_soln)(node_out)*dz *
S;
860 auto DP =
std::pow(
S, -1.0) * (time_term + mass_term1 + mass_term2 + crossflow_term +
861 turbulent_term + friction_term + gravity_term);
879 for (
unsigned int iz = first_node; iz < last_node + 1; iz++)
883 auto iz_ind = iz - first_node;
884 for (
unsigned int i_ch = 0; i_ch <
_n_channels; i_ch++)
891 PetscScalar Pe = 0.5;
895 auto rho_in = (*_rho_soln)(node_in);
896 auto rho_out = (*_rho_soln)(node_out);
900 auto mu_in = (*_mu_soln)(node_in);
901 auto mu_out = (*_mu_soln)(node_out);
905 auto S_in = (*_S_flow_soln)(node_in);
906 auto S_out = (*_S_flow_soln)(node_out);
910 auto w_perim_in = (*_w_perim_soln)(node_in);
911 auto w_perim_out = (*_w_perim_soln)(node_out);
915 auto Dh_i = 4.0 * S_interp / w_perim_interp;
918 if (iz == first_node)
920 PetscScalar value_vec_tt = -1.0 *
_TR *
alpha * (*_mdot_soln)(node_in)*dz /
_dt;
928 PetscInt col_tt = i_ch +
_n_channels * (iz_ind - 1);
930 LibmeshPetscCall(MatSetValues(
937 PetscScalar value_tt =
_TR * (1.0 -
alpha) * dz /
_dt;
938 LibmeshPetscCall(MatSetValues(
942 PetscScalar mdot_old_interp =
944 PetscScalar value_vec_tt =
_TR * mdot_old_interp * dz /
_dt;
950 if (iz == first_node)
954 LibmeshPetscCall(VecSetValues(
960 PetscInt col_at = i_ch +
_n_channels * (iz_ind - 1);
961 PetscScalar value_at = -1.0 * std::abs((*
_mdot_soln)(node_in)) / (S_in * rho_in);
962 LibmeshPetscCall(MatSetValues(
969 PetscScalar value_at = std::abs((*
_mdot_soln)(node_out)) / (S_out * rho_out);
970 LibmeshPetscCall(MatSetValues(
974 unsigned int counter = 0;
975 unsigned int cross_index = iz;
979 unsigned int ii_ch = chans.first;
980 unsigned int jj_ch = chans.second;
995 if (
_Wij(i_gap, cross_index) > 0.0)
997 if (iz == first_node)
999 u_star = (*_mdot_soln)(node_in_i) / S_i / rho_i;
1000 PetscScalar value_vec_ct = -1.0 *
alpha *
1002 _Wij(i_gap, cross_index) * u_star;
1003 PetscInt row_vec_ct = i_ch +
_n_channels * iz_ind;
1004 LibmeshPetscCall(VecSetValues(
1010 _Wij(i_gap, cross_index) / S_i / rho_i;
1012 PetscInt col_ct = ii_ch +
_n_channels * (iz_ind - 1);
1013 LibmeshPetscCall(MatSetValues(
1016 PetscScalar value_ct = (1.0 -
alpha) *
1018 _Wij(i_gap, cross_index) / S_i / rho_i;
1021 LibmeshPetscCall(MatSetValues(
1024 else if (
_Wij(i_gap, cross_index) < 0.0)
1026 if (iz == first_node)
1028 u_star = (*_mdot_soln)(node_in_j) / S_j / rho_j;
1029 PetscScalar value_vec_ct = -1.0 *
alpha *
1031 _Wij(i_gap, cross_index) * u_star;
1032 PetscInt row_vec_ct = i_ch +
_n_channels * iz_ind;
1033 LibmeshPetscCall(VecSetValues(
1039 _Wij(i_gap, cross_index) / S_j / rho_j;
1041 PetscInt col_ct = jj_ch +
_n_channels * (iz_ind - 1);
1042 LibmeshPetscCall(MatSetValues(
1045 PetscScalar value_ct = (1.0 -
alpha) *
1047 _Wij(i_gap, cross_index) / S_j / rho_j;
1050 LibmeshPetscCall(MatSetValues(
1054 if (iz == first_node)
1056 PetscScalar value_vec_ct = -2.0 *
alpha *
1057 (*_mdot_soln)(node_in)*
_WijPrime(i_gap, cross_index) /
1058 (rho_interp * S_interp);
1060 alpha * (*_mdot_soln)(node_in_j)*
_WijPrime(i_gap, cross_index) / (rho_j * S_j);
1062 alpha * (*_mdot_soln)(node_in_i)*
_WijPrime(i_gap, cross_index) / (rho_i * S_i);
1063 PetscInt row_vec_ct = i_ch +
_n_channels * iz_ind;
1069 PetscScalar value_center_ct =
1070 2.0 *
alpha *
_WijPrime(i_gap, cross_index) / (rho_interp * S_interp);
1072 PetscInt col_ct = i_ch +
_n_channels * (iz_ind - 1);
1073 LibmeshPetscCall(MatSetValues(
1076 PetscScalar value_left_ct =
1080 LibmeshPetscCall(MatSetValues(
1083 PetscScalar value_right_ct =
1087 LibmeshPetscCall(MatSetValues(
1091 PetscScalar value_center_ct =
1092 2.0 * (1.0 -
alpha) *
_WijPrime(i_gap, cross_index) / (rho_interp * S_interp);
1095 LibmeshPetscCall(MatSetValues(
1098 PetscScalar value_left_ct =
1099 -1.0 * (1.0 -
alpha) *
_WijPrime(i_gap, cross_index) / (rho_j * S_j);
1102 LibmeshPetscCall(MatSetValues(
1105 PetscScalar value_right_ct =
1106 -1.0 * (1.0 -
alpha) *
_WijPrime(i_gap, cross_index) / (rho_i * S_i);
1109 LibmeshPetscCall(MatSetValues(
1116 PetscScalar mdot_interp =
1118 auto Re = ((mdot_interp / S_interp) * Dh_i / mu_interp);
1121 auto coef = (fi * dz / Dh_i + ki) * 0.5 * std::abs((*
_mdot_soln)(node_out)) /
1122 (S_interp * rho_interp);
1123 if (iz == first_node)
1125 PetscScalar value_vec = -1.0 *
alpha * coef * (*_mdot_soln)(node_in);
1147 PetscScalar value_vec = -1.0 *
_g_grav * rho_interp * dz * S_interp;
1149 LibmeshPetscCall(VecSetValues(
_amc_gravity_rhs, 1, &row_vec, &value_vec, ADD_VALUES));
1166 #if !PETSC_VERSION_LESS_THAN(3, 15, 0) 1191 _console <<
"Block: " << iblock <<
" - Linear momentum conservation matrix assembled" 1202 LibmeshPetscCall(populateVectorFromHandle<SolutionHandle>(
1209 LibmeshPetscCall(VecGetArray(ls, &xx));
1210 for (
unsigned int iz = first_node; iz < last_node + 1; iz++)
1212 auto iz_ind = iz - first_node;
1213 for (
unsigned int i_ch = 0; i_ch <
_n_channels; i_ch++)
1220 auto S_in = (*_S_flow_soln)(node_in);
1221 auto S_out = (*_S_flow_soln)(node_out);
1237 LibmeshPetscCall(VecDestroy(&ls));
1245 unsigned int last_node = (iblock + 1) *
_block_size;
1246 unsigned int first_node = iblock *
_block_size + 1;
1251 for (
unsigned int iz = last_node; iz > first_node - 1; iz--)
1254 for (
unsigned int i_ch = 0; i_ch <
_n_channels; i_ch++)
1265 for (
unsigned int iz = last_node; iz > first_node - 1; iz--)
1268 for (
unsigned int i_ch = 0; i_ch <
_n_channels; i_ch++)
1276 PetscScalar Pe = 0.5;
1278 if (iz == last_node)
1297 for (
unsigned int iz = last_node; iz > first_node - 1; iz--)
1299 auto iz_ind = iz - first_node;
1301 for (
unsigned int i_ch = 0; i_ch <
_n_channels; i_ch++)
1307 auto S_in = (*_S_flow_soln)(node_in);
1308 auto S_out = (*_S_flow_soln)(node_out);
1314 PetscScalar
value = -1.0 * S_interp;
1318 if (iz == last_node)
1320 PetscScalar
value = -1.0 * (*_P_soln)(node_out)*S_interp;
1328 PetscScalar
value = 1.0 * S_interp;
1335 auto dp_out = (*_DP_soln)(node_out);
1336 PetscScalar value_v = -1.0 * dp_out * S_interp;
1352 LibmeshPetscCall(KSPCreate(PETSC_COMM_WORLD, &ksploc));
1354 LibmeshPetscCall(KSPGetPC(ksploc, &pc));
1355 LibmeshPetscCall(PCSetType(pc, PCJACOBI));
1357 LibmeshPetscCall(KSPSetOptionsPrefix(ksploc,
"pressure_sys_"));
1358 LibmeshPetscCall(KSPSetFromOptions(ksploc));
1361 LibmeshPetscCall(VecGetArray(sol, &xx));
1363 for (
unsigned int iz = last_node; iz > first_node - 1; iz--)
1365 auto iz_ind = iz - first_node;
1366 for (
unsigned int i_ch = 0; i_ch <
_n_channels; i_ch++)
1374 LibmeshPetscCall(KSPDestroy(&ksploc));
1375 LibmeshPetscCall(VecDestroy(&sol));
1381 for (
unsigned int iz = last_node; iz > first_node - 1; iz--)
1383 auto iz_ind = iz - first_node;
1385 for (
unsigned int i_ch = 0; i_ch <
_n_channels; i_ch++)
1391 auto S_in = (*_S_flow_soln)(node_in);
1392 auto S_out = (*_S_flow_soln)(node_out);
1398 PetscScalar
value = -1.0 * S_interp;
1402 if (iz == last_node)
1404 PetscScalar
value = -1.0 * (*_P_soln)(node_out)*S_interp;
1408 auto dp_out = (*_DP_soln)(node_out);
1409 PetscScalar value_v = -1.0 * dp_out / 2.0 * S_interp;
1418 PetscScalar
value = 1.0 * S_interp;
1424 auto dp_in = (*_DP_soln)(node_in);
1425 auto dp_out = (*_DP_soln)(node_out);
1427 PetscScalar value_v = -1.0 * dp_interp * S_interp;
1438 _console <<
"Block: " << iblock <<
" - Axial momentum pressure force matrix assembled" 1447 LibmeshPetscCall(KSPCreate(PETSC_COMM_WORLD, &ksploc));
1449 LibmeshPetscCall(KSPGetPC(ksploc, &pc));
1450 LibmeshPetscCall(PCSetType(pc, PCJACOBI));
1452 LibmeshPetscCall(KSPSetOptionsPrefix(ksploc,
"axial_mom_sys_"));
1453 LibmeshPetscCall(KSPSetFromOptions(ksploc));
1456 LibmeshPetscCall(VecGetArray(sol, &xx));
1458 for (
unsigned int iz = last_node; iz > first_node - 1; iz--)
1460 auto iz_ind = iz - first_node;
1461 for (
unsigned int i_ch = 0; i_ch <
_n_channels; i_ch++)
1469 LibmeshPetscCall(KSPDestroy(&ksploc));
1470 LibmeshPetscCall(VecDestroy(&sol));
1482 auto heat_rate_in = 0.0;
1483 auto heat_rate_out = 0.0;
1488 heat_rate_out += 0.25 * (*_q_prime_soln)(node_out);
1489 heat_rate_in += 0.25 * (*_q_prime_soln)(node_in);
1491 return (heat_rate_in + heat_rate_out) * dz / 2.0;
1504 unsigned int last_node = (iblock + 1) *
_block_size;
1505 unsigned int first_node = iblock *
_block_size + 1;
1509 for (
unsigned int i_ch = 0; i_ch <
_n_channels; i_ch++)
1516 name(),
" : Calculation of negative Enthalpy h_out = : ", h_out,
" Axial Level= : ", 0);
1524 for (
unsigned int iz = first_node; iz < last_node + 1; iz++)
1529 for (
unsigned int i_ch = 0; i_ch <
_n_channels; i_ch++)
1533 auto mdot_in = (*_mdot_soln)(node_in);
1534 auto h_in = (*_h_soln)(node_in);
1535 auto volume = dz * (*_S_flow_soln)(node_in);
1536 auto mdot_out = (*_mdot_soln)(node_out);
1539 Real sumWijPrimeDhij = 0.0;
1540 Real added_enthalpy;
1541 if (
_z_grid[iz] > unheated_length_entry &&
1542 _z_grid[iz] <= unheated_length_entry + heated_length)
1545 added_enthalpy = 0.0;
1548 unsigned int counter = 0;
1552 unsigned int ii_ch = chans.first;
1554 unsigned int jj_ch = chans.second;
1559 if (
_Wij(i_gap, iz) > 0.0)
1560 h_star = (*_h_soln)(node_in_i);
1561 else if (
_Wij(i_gap, iz) < 0.0)
1562 h_star = (*_h_soln)(node_in_j);
1565 sumWijPrimeDhij +=
_WijPrime(i_gap, iz) * (2 * (*_h_soln)(node_in) -
1570 h_out = (mdot_in * h_in - sumWijh - sumWijPrimeDhij + added_enthalpy +
1577 " : Calculation of negative Enthalpy h_out = : ",
1582 _h_soln->set(node_out, h_out);
1588 _console <<
"Setting matrices" << std::endl;
1599 _console <<
"Starting enthalpy assembly" << std::endl;
1600 for (
unsigned int iz = first_node; iz < last_node + 1; iz++)
1605 auto iz_ind = iz - first_node;
1606 for (
unsigned int i_ch = 0; i_ch <
_n_channels; i_ch++)
1610 auto volume = dz * (*_S_flow_soln)(node_in);
1613 PetscScalar Pe = 0.5;
1617 if (iz == first_node)
1619 PetscScalar value_vec_tt =
1621 PetscInt row_vec_tt = i_ch +
_n_channels * iz_ind;
1628 PetscInt col_tt = i_ch +
_n_channels * (iz_ind - 1);
1630 LibmeshPetscCall(MatSetValues(
1638 LibmeshPetscCall(MatSetValues(
1642 PetscScalar rho_old_interp =
1644 PetscScalar h_old_interp =
1647 PetscScalar value_vec_tt =
_TR * rho_old_interp * h_old_interp *
volume /
_dt;
1648 PetscInt row_vec_tt = i_ch +
_n_channels * iz_ind;
1653 if (iz == first_node)
1655 PetscScalar value_vec_at = (*_mdot_soln)(node_in) * (*
_h_soln)(node_in);
1656 PetscInt row_vec_at = i_ch +
_n_channels * iz_ind;
1657 LibmeshPetscCall(VecSetValues(
1663 PetscInt col_at = i_ch +
_n_channels * (iz_ind - 1);
1664 PetscScalar value_at = -1.0 * (*_mdot_soln)(node_in);
1665 LibmeshPetscCall(MatSetValues(
1672 PetscScalar value_at = (*_mdot_soln)(node_out);
1673 LibmeshPetscCall(MatSetValues(
1677 unsigned int counter = 0;
1678 unsigned int cross_index = iz;
1682 unsigned int ii_ch = chans.first;
1683 unsigned int jj_ch = chans.second;
1689 if (
_Wij(i_gap, cross_index) > 0.0)
1691 if (iz == first_node)
1693 h_star = (*_h_soln)(node_in_i);
1694 PetscScalar value_vec_ct = -1.0 *
alpha *
1696 _Wij(i_gap, cross_index) * h_star;
1697 PetscInt row_vec_ct = i_ch +
_n_channels * iz_ind;
1698 LibmeshPetscCall(VecSetValues(
1704 _Wij(i_gap, cross_index);
1706 PetscInt col_ct = ii_ch +
_n_channels * (iz_ind - 1);
1707 LibmeshPetscCall(MatSetValues(
1710 PetscScalar value_ct = (1.0 -
alpha) *
1712 _Wij(i_gap, cross_index);
1715 LibmeshPetscCall(MatSetValues(
1718 else if (
_Wij(i_gap, cross_index) < 0.0)
1720 if (iz == first_node)
1722 h_star = (*_h_soln)(node_in_j);
1723 PetscScalar value_vec_ct = -1.0 *
alpha *
1725 _Wij(i_gap, cross_index) * h_star;
1726 PetscInt row_vec_ct = i_ch +
_n_channels * iz_ind;
1727 LibmeshPetscCall(VecSetValues(
1733 _Wij(i_gap, cross_index);
1735 PetscInt col_ct = jj_ch +
_n_channels * (iz_ind - 1);
1736 LibmeshPetscCall(MatSetValues(
1739 PetscScalar value_ct = (1.0 -
alpha) *
1741 _Wij(i_gap, cross_index);
1744 LibmeshPetscCall(MatSetValues(
1749 if (iz == first_node)
1751 PetscScalar value_vec_ct =
1752 -2.0 *
alpha * (*_mdot_soln)(node_in)*
_WijPrime(i_gap, cross_index);
1753 value_vec_ct =
alpha * (*_mdot_soln)(node_in_j)*
_WijPrime(i_gap, cross_index);
1754 value_vec_ct +=
alpha * (*_mdot_soln)(node_in_i)*
_WijPrime(i_gap, cross_index);
1755 PetscInt row_vec_ct = i_ch +
_n_channels * iz_ind;
1761 PetscScalar value_center_ct = 2.0 *
alpha *
_WijPrime(i_gap, cross_index);
1763 PetscInt col_ct = i_ch +
_n_channels * (iz_ind - 1);
1764 LibmeshPetscCall(MatSetValues(
1767 PetscScalar value_left_ct = -1.0 *
alpha *
_WijPrime(i_gap, cross_index);
1770 LibmeshPetscCall(MatSetValues(
1773 PetscScalar value_right_ct = -1.0 *
alpha *
_WijPrime(i_gap, cross_index);
1776 LibmeshPetscCall(MatSetValues(
1780 PetscScalar value_center_ct = 2.0 * (1.0 -
alpha) *
_WijPrime(i_gap, cross_index);
1783 LibmeshPetscCall(MatSetValues(
1786 PetscScalar value_left_ct = -1.0 * (1.0 -
alpha) *
_WijPrime(i_gap, cross_index);
1789 LibmeshPetscCall(MatSetValues(
1792 PetscScalar value_right_ct = -1.0 * (1.0 -
alpha) *
_WijPrime(i_gap, cross_index);
1795 LibmeshPetscCall(MatSetValues(
1802 PetscScalar added_enthalpy;
1803 if (
_z_grid[iz] > unheated_length_entry &&
1804 _z_grid[iz] <= unheated_length_entry + heated_length)
1807 added_enthalpy = 0.0;
1809 PetscInt row_vec_ht = i_ch +
_n_channels * iz_ind;
1814 _console <<
"Done with enthalpy assembly" << std::endl;
1823 LibmeshPetscCall(MatAssemblyBegin(
_hc_sys_h_mat, MAT_FINAL_ASSEMBLY));
1824 LibmeshPetscCall(MatAssemblyEnd(
_hc_sys_h_mat, MAT_FINAL_ASSEMBLY));
1826 #if !PETSC_VERSION_LESS_THAN(3, 15, 0) 1828 LibmeshPetscCall(MatAssemblyBegin(
_hc_sys_h_mat, MAT_FINAL_ASSEMBLY));
1829 LibmeshPetscCall(MatAssemblyEnd(
_hc_sys_h_mat, MAT_FINAL_ASSEMBLY));
1832 LibmeshPetscCall(MatAssemblyBegin(
_hc_sys_h_mat, MAT_FINAL_ASSEMBLY));
1833 LibmeshPetscCall(MatAssemblyEnd(
_hc_sys_h_mat, MAT_FINAL_ASSEMBLY));
1839 LibmeshPetscCall(MatAssemblyBegin(
_hc_sys_h_mat, MAT_FINAL_ASSEMBLY));
1840 LibmeshPetscCall(MatAssemblyEnd(
_hc_sys_h_mat, MAT_FINAL_ASSEMBLY));
1843 LibmeshPetscCall(MatAssemblyBegin(
_hc_sys_h_mat, MAT_FINAL_ASSEMBLY));
1844 LibmeshPetscCall(MatAssemblyEnd(
_hc_sys_h_mat, MAT_FINAL_ASSEMBLY));
1848 LibmeshPetscCall(MatAssemblyBegin(
_hc_sys_h_mat, MAT_FINAL_ASSEMBLY));
1849 LibmeshPetscCall(MatAssemblyEnd(
_hc_sys_h_mat, MAT_FINAL_ASSEMBLY));
1850 _console <<
"Block: " << iblock <<
" - Enthalpy conservation matrix assembled" << std::endl;
1864 LibmeshPetscCall(KSPCreate(PETSC_COMM_WORLD, &ksploc));
1866 LibmeshPetscCall(KSPGetPC(ksploc, &pc));
1867 LibmeshPetscCall(PCSetType(pc, PCJACOBI));
1869 LibmeshPetscCall(KSPSetOptionsPrefix(ksploc,
"h_cons_sys_"));
1870 LibmeshPetscCall(KSPSetFromOptions(ksploc));
1873 LibmeshPetscCall(VecGetArray(sol, &xx));
1875 for (
unsigned int iz = first_node; iz < last_node + 1; iz++)
1877 auto iz_ind = iz - first_node;
1878 for (
unsigned int i_ch = 0; i_ch <
_n_channels; i_ch++)
1885 " : Calculation of negative Enthalpy h_out = : ",
1890 _h_soln->set(node_out, h_out);
1893 LibmeshPetscCall(KSPDestroy(&ksploc));
1894 LibmeshPetscCall(VecDestroy(&sol));
1902 unsigned int last_node = (iblock + 1) *
_block_size;
1903 unsigned int first_node = iblock *
_block_size + 1;
1905 for (
unsigned int iz = first_node; iz < last_node + 1; iz++)
1907 for (
unsigned int i_ch = 0; i_ch <
_n_channels; i_ch++)
1918 unsigned int last_node = (iblock + 1) *
_block_size;
1919 unsigned int first_node = iblock *
_block_size + 1;
1923 for (
unsigned int i_ch = 0; i_ch <
_n_channels; i_ch++)
1930 for (
unsigned int iz = first_node; iz < last_node + 1; iz++)
1932 for (
unsigned int i_ch = 0; i_ch <
_n_channels; i_ch++)
1943 unsigned int last_node = (iblock + 1) *
_block_size;
1944 unsigned int first_node = iblock *
_block_size + 1;
1948 for (
unsigned int i_ch = 0; i_ch <
_n_channels; i_ch++)
1955 for (
unsigned int iz = first_node; iz < last_node + 1; iz++)
1957 for (
unsigned int i_ch = 0; i_ch <
_n_channels; i_ch++)
1971 unsigned int last_node = (iblock + 1) *
_block_size;
1975 for (
unsigned int iz = first_node + 1; iz < last_node + 1; iz++)
1978 for (
unsigned int i_gap = 0; i_gap <
_n_gaps; i_gap++)
1981 unsigned int i_ch = chans.first;
1982 unsigned int j_ch = chans.second;
1987 auto rho_i = (*_rho_soln)(node_in_i);
1988 auto rho_j = (*_rho_soln)(node_in_j);
1989 auto Si = (*_S_flow_soln)(node_in_i);
1990 auto Sj = (*_S_flow_soln)(node_in_j);
1994 auto friction_term =
_kij *
_Wij(i_gap, iz) * std::abs(
_Wij(i_gap, iz));
1995 auto DPij = (*_P_soln)(node_in_i) - (*
_P_soln)(node_in_j);
1997 auto rho_star = 0.0;
1998 if (
_Wij(i_gap, iz) > 0.0)
2000 else if (
_Wij(i_gap, iz) < 0.0)
2003 rho_star = (rho_i + rho_j) / 2.0;
2005 auto mass_term_out =
2006 (*_mdot_soln)(node_out_i) / Si / rho_i + (*
_mdot_soln)(node_out_j) / Sj / rho_j;
2008 (*_mdot_soln)(node_in_i) / Si / rho_i + (*
_mdot_soln)(node_in_j) / Sj / rho_j;
2009 auto term_out = Sij * rho_star * (Lij / dz) * mass_term_out *
_Wij(i_gap, iz);
2010 auto term_in = Sij * rho_star * (Lij / dz) * mass_term_in *
_Wij(i_gap, iz - 1);
2011 auto inertia_term = term_out - term_in;
2012 auto pressure_term = 2 *
std::pow(Sij, 2.0) * DPij * rho_star;
2017 time_term + friction_term + inertia_term - pressure_term;
2036 unsigned int last_node = (iblock + 1) *
_block_size;
2040 for (
unsigned int iz = first_node + 1; iz < last_node + 1; iz++)
2043 auto iz_ind = iz - first_node - 1;
2044 for (
unsigned int i_gap = 0; i_gap <
_n_gaps; i_gap++)
2047 unsigned int i_ch = chans.first;
2048 unsigned int j_ch = chans.second;
2055 auto rho_i_in = (*_rho_soln)(node_in_i);
2056 auto rho_i_out = (*_rho_soln)(node_out_i);
2058 auto rho_j_in = (*_rho_soln)(node_in_j);
2059 auto rho_j_out = (*_rho_soln)(node_out_j);
2063 auto S_i_in = (*_S_flow_soln)(node_in_i);
2064 auto S_i_out = (*_S_flow_soln)(node_out_i);
2065 auto S_j_in = (*_S_flow_soln)(node_in_j);
2066 auto S_j_out = (*_S_flow_soln)(node_out_j);
2073 auto rho_star = 0.0;
2074 if (
_Wij(i_gap, iz) > 0.0)
2075 rho_star = rho_i_interp;
2076 else if (
_Wij(i_gap, iz) < 0.0)
2077 rho_star = rho_j_interp;
2079 rho_star = (rho_i_interp + rho_j_interp) / 2.0;
2082 PetscScalar time_factor =
_TR * Lij * Sij * rho_star /
_dt;
2083 PetscInt row_td = i_gap +
_n_gaps * iz_ind;
2084 PetscInt col_td = i_gap +
_n_gaps * iz_ind;
2085 PetscScalar value_td = time_factor;
2086 LibmeshPetscCall(MatSetValues(
2088 PetscScalar value_td_rhs = time_factor *
_Wij_old(i_gap, iz);
2094 auto mass_term_out = (*_mdot_soln)(node_out_i) / S_i_out / rho_i_out +
2095 (*
_mdot_soln)(node_out_j) / S_j_out / rho_j_out;
2096 auto mass_term_in = (*_mdot_soln)(node_in_i) / S_i_in / rho_i_in +
2097 (*
_mdot_soln)(node_in_j) / S_j_in / rho_j_in;
2098 auto term_out = Sij * rho_star * (Lij / dz) * mass_term_out / 2.0;
2099 auto term_in = Sij * rho_star * (Lij / dz) * mass_term_in / 2.0;
2100 if (iz == first_node + 1)
2102 PetscInt row_ad = i_gap +
_n_gaps * iz_ind;
2103 PetscScalar value_ad = term_in *
alpha *
_Wij(i_gap, iz - 1);
2107 PetscInt col_ad = i_gap +
_n_gaps * iz_ind;
2108 value_ad = -1.0 * term_in * (1.0 -
alpha) + term_out *
alpha;
2109 LibmeshPetscCall(MatSetValues(
2112 col_ad = i_gap +
_n_gaps * (iz_ind + 1);
2113 value_ad = term_out * (1.0 -
alpha);
2114 LibmeshPetscCall(MatSetValues(
2117 else if (iz == last_node)
2119 PetscInt row_ad = i_gap +
_n_gaps * iz_ind;
2120 PetscInt col_ad = i_gap +
_n_gaps * (iz_ind - 1);
2121 PetscScalar value_ad = -1.0 * term_in *
alpha;
2122 LibmeshPetscCall(MatSetValues(
2125 col_ad = i_gap +
_n_gaps * iz_ind;
2126 value_ad = -1.0 * term_in * (1.0 -
alpha) + term_out *
alpha;
2127 LibmeshPetscCall(MatSetValues(
2130 value_ad = -1.0 * term_out * (1.0 -
alpha) *
_Wij(i_gap, iz);
2136 PetscInt row_ad = i_gap +
_n_gaps * iz_ind;
2137 PetscInt col_ad = i_gap +
_n_gaps * (iz_ind - 1);
2138 PetscScalar value_ad = -1.0 * term_in *
alpha;
2139 LibmeshPetscCall(MatSetValues(
2142 col_ad = i_gap +
_n_gaps * iz_ind;
2143 value_ad = -1.0 * term_in * (1.0 -
alpha) + term_out *
alpha;
2144 LibmeshPetscCall(MatSetValues(
2147 col_ad = i_gap +
_n_gaps * (iz_ind + 1);
2148 value_ad = term_out * (1.0 -
alpha);
2149 LibmeshPetscCall(MatSetValues(
2153 PetscInt row_ff = i_gap +
_n_gaps * iz_ind;
2154 PetscInt col_ff = i_gap +
_n_gaps * iz_ind;
2155 PetscScalar value_ff =
_kij * std::abs(
_Wij(i_gap, iz)) / 2.0;
2156 LibmeshPetscCall(MatSetValues(
2164 PetscScalar pressure_factor =
std::pow(Sij, 2.0) * rho_star;
2165 PetscInt row_pf = i_gap +
_n_gaps * iz_ind;
2167 PetscScalar value_pf = -1.0 *
alpha * pressure_factor;
2171 value_pf =
alpha * pressure_factor;
2175 if (iz == last_node)
2177 PetscInt row_pf = i_gap +
_n_gaps * iz_ind;
2178 PetscScalar value_pf = (1.0 -
alpha) * pressure_factor * (*
_P_soln)(node_out_i);
2181 value_pf = -1.0 * (1.0 -
alpha) * pressure_factor * (*
_P_soln)(node_out_j);
2187 row_pf = i_gap +
_n_gaps * iz_ind;
2189 value_pf = -1.0 * (1.0 -
alpha) * pressure_factor;
2190 LibmeshPetscCall(MatSetValues(
2193 value_pf = (1.0 -
alpha) * pressure_factor;
2194 LibmeshPetscCall(MatSetValues(
2200 PetscScalar pressure_factor =
std::pow(Sij, 2.0) * rho_star;
2201 PetscInt row_pf = i_gap +
_n_gaps * iz_ind;
2203 PetscScalar value_pf = -1.0 * pressure_factor;
2207 value_pf = pressure_factor;
2227 #if !PETSC_VERSION_LESS_THAN(3, 15, 0) 2252 _console <<
"Block: " << iblock <<
" - Cross flow system matrix assembled" << std::endl;
2253 _console <<
"Block: " << iblock <<
" - Cross flow pressure force matrix assembled" << std::endl;
2268 LibmeshPetscCall(populateVectorFromHandle<SolutionHandle>(
2271 loc_holder_Wij,
_Wij, first_node, last_node,
_n_gaps));
2276 LibmeshPetscCall(VecAXPY(sol_holder_W, 1.0, sol_holder_P));
2278 LibmeshPetscCall(VecGetArray(sol_holder_W, &xx));
2279 for (
unsigned int iz = first_node + 1; iz < last_node + 1; iz++)
2281 auto iz_ind = iz - first_node - 1;
2282 for (
unsigned int i_gap = 0; i_gap <
_n_gaps; i_gap++)
2287 LibmeshPetscCall(VecDestroy(&sol_holder_P));
2288 LibmeshPetscCall(VecDestroy(&sol_holder_W));
2289 LibmeshPetscCall(VecDestroy(&loc_holder_Wij));
2297 unsigned int last_node = (iblock + 1) *
_block_size;
2302 for (
unsigned int iz = first_node + 1; iz < last_node + 1; iz++)
2304 for (
unsigned int i_gap = 0; i_gap <
_n_gaps; i_gap++)
2306 _Wij(i_gap, iz) = solution(i);
2327 for (
unsigned int i_gap = 0; i_gap <
_n_gaps; i_gap++)
2333 return Wij_residual_vector;
2349 PetscCallMPI(MPI_Comm_size(PETSC_COMM_WORLD, &size));
2351 SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_SUP,
"Example is only for sequential runs");
2352 LibmeshPetscCall(SNESCreate(PETSC_COMM_WORLD, &snes));
2353 LibmeshPetscCall(VecCreate(PETSC_COMM_WORLD, &
x));
2355 LibmeshPetscCall(VecSetFromOptions(
x));
2356 LibmeshPetscCall(VecDuplicate(
x, &r));
2358 #if PETSC_VERSION_LESS_THAN(3, 13, 0) 2359 LibmeshPetscCall(PetscOptionsSetValue(PETSC_NULL,
"-snes_mf", PETSC_NULL));
2361 LibmeshPetscCall(SNESSetUseMatrixFree(snes, PETSC_FALSE, PETSC_TRUE));
2368 LibmeshPetscCall(SNESGetKSP(snes, &ksp));
2369 LibmeshPetscCall(KSPGetPC(ksp, &pc));
2370 LibmeshPetscCall(PCSetType(pc, PCNONE));
2372 LibmeshPetscCall(SNESSetFromOptions(snes));
2373 LibmeshPetscCall(VecGetArray(
x, &xx));
2376 xx[i] = solution(i);
2378 LibmeshPetscCall(VecRestoreArray(
x, &xx));
2380 LibmeshPetscCall(SNESSolve(snes, NULL,
x));
2381 LibmeshPetscCall(VecGetArray(
x, &xx));
2385 LibmeshPetscCall(VecRestoreArray(
x, &xx));
2386 LibmeshPetscCall(VecDestroy(&
x));
2387 LibmeshPetscCall(VecDestroy(&r));
2388 LibmeshPetscCall(SNESDestroy(&snes));
2402 std::vector<Mat> mat_array(Q * Q);
2403 std::vector<Vec> vec_array(Q);
2406 bool _axial_mass_flow_tight_coupling =
true;
2407 bool _pressure_axial_momentum_tight_coupling =
true;
2408 bool _pressure_cross_momentum_tight_coupling =
true;
2409 unsigned int first_node = iblock *
_block_size + 1;
2410 unsigned int last_node = (iblock + 1) *
_block_size;
2429 _console <<
"Starting nested system." << std::endl;
2430 _console <<
"Number of simultaneous variables: " << Q << std::endl;
2432 PetscInt field_num = 0;
2435 LibmeshPetscCall(MatAssemblyBegin(mat_array[Q * field_num + 0], MAT_FINAL_ASSEMBLY));
2436 LibmeshPetscCall(MatAssemblyEnd(mat_array[Q * field_num + 0], MAT_FINAL_ASSEMBLY));
2437 mat_array[Q * field_num + 1] = NULL;
2438 if (_axial_mass_flow_tight_coupling)
2440 LibmeshPetscCall(MatDuplicate(
_mc_sumWij_mat, MAT_COPY_VALUES, &mat_array[Q * field_num + 2]));
2441 LibmeshPetscCall(MatAssemblyBegin(mat_array[Q * field_num + 2], MAT_FINAL_ASSEMBLY));
2442 LibmeshPetscCall(MatAssemblyEnd(mat_array[Q * field_num + 2], MAT_FINAL_ASSEMBLY));
2446 mat_array[Q * field_num + 2] = NULL;
2450 mat_array[Q * field_num + 3] = NULL;
2454 if (!_axial_mass_flow_tight_coupling)
2458 LibmeshPetscCall(VecSet(sumWij_loc, 0.0));
2459 for (
unsigned int iz = first_node; iz < last_node + 1; iz++)
2461 auto iz_ind = iz - first_node;
2462 for (
unsigned int i_ch = 0; i_ch <
_n_channels; i_ch++)
2466 PetscScalar value_vec_2 = -1.0 * (*_SumWij_soln)(node_out);
2468 LibmeshPetscCall(VecSetValues(sumWij_loc, 1, &row_vec_2, &value_vec_2, ADD_VALUES));
2471 LibmeshPetscCall(VecAXPY(vec_array[field_num], 1.0, sumWij_loc));
2472 LibmeshPetscCall(VecDestroy(&sumWij_loc));
2475 _console <<
"Mass ok." << std::endl;
2478 if (_pressure_axial_momentum_tight_coupling)
2481 MatDuplicate(
_amc_sys_mdot_mat, MAT_COPY_VALUES, &mat_array[Q * field_num + 0]));
2482 LibmeshPetscCall(MatAssemblyBegin(mat_array[Q * field_num + 0], MAT_FINAL_ASSEMBLY));
2483 LibmeshPetscCall(MatAssemblyEnd(mat_array[Q * field_num + 0], MAT_FINAL_ASSEMBLY));
2487 mat_array[Q * field_num + 0] = NULL;
2491 LibmeshPetscCall(MatAssemblyBegin(mat_array[Q * field_num + 1], MAT_FINAL_ASSEMBLY));
2492 LibmeshPetscCall(MatAssemblyEnd(mat_array[Q * field_num + 1], MAT_FINAL_ASSEMBLY));
2493 mat_array[Q * field_num + 2] = NULL;
2496 mat_array[Q * field_num + 3] = NULL;
2500 if (_pressure_axial_momentum_tight_coupling)
2506 unsigned int last_node = (iblock + 1) *
_block_size;
2507 unsigned int first_node = iblock *
_block_size + 1;
2508 LibmeshPetscCall(populateVectorFromHandle<SolutionHandle>(
2514 LibmeshPetscCall(VecAXPY(vec_array[field_num], -1.0, ls));
2515 LibmeshPetscCall(VecDestroy(&ls));
2518 _console <<
"Lin mom OK." << std::endl;
2522 mat_array[Q * field_num + 0] = NULL;
2523 if (_pressure_cross_momentum_tight_coupling)
2527 LibmeshPetscCall(MatAssemblyBegin(mat_array[Q * field_num + 1], MAT_FINAL_ASSEMBLY));
2528 LibmeshPetscCall(MatAssemblyEnd(mat_array[Q * field_num + 1], MAT_FINAL_ASSEMBLY));
2532 mat_array[Q * field_num + 1] = NULL;
2535 LibmeshPetscCall(MatDuplicate(
_cmc_sys_Wij_mat, MAT_COPY_VALUES, &mat_array[Q * field_num + 2]));
2536 LibmeshPetscCall(MatAssemblyBegin(mat_array[Q * field_num + 2], MAT_FINAL_ASSEMBLY));
2537 LibmeshPetscCall(MatAssemblyEnd(mat_array[Q * field_num + 2], MAT_FINAL_ASSEMBLY));
2540 mat_array[Q * field_num + 3] = NULL;
2545 if (_pressure_cross_momentum_tight_coupling)
2553 LibmeshPetscCall(populateVectorFromHandle<SolutionHandle>(
2558 LibmeshPetscCall(VecScale(sol_holder_P, 1.0));
2559 LibmeshPetscCall(VecAXPY(vec_array[field_num], 1.0, sol_holder_P));
2560 LibmeshPetscCall(VecDestroy(&sol_holder_P));
2563 _console <<
"Cross mom ok." << std::endl;
2569 mat_array[Q * field_num + 0] = NULL;
2570 mat_array[Q * field_num + 1] = NULL;
2571 mat_array[Q * field_num + 2] = NULL;
2572 LibmeshPetscCall(MatDuplicate(
_hc_sys_h_mat, MAT_COPY_VALUES, &mat_array[Q * field_num + 3]));
2573 LibmeshPetscCall(MatAssemblyBegin(mat_array[Q * field_num + 3], MAT_FINAL_ASSEMBLY));
2574 LibmeshPetscCall(MatAssemblyEnd(mat_array[Q * field_num + 3], MAT_FINAL_ASSEMBLY));
2575 LibmeshPetscCall(VecDuplicate(
_hc_sys_h_rhs, &vec_array[field_num]));
2576 LibmeshPetscCall(VecCopy(
_hc_sys_h_rhs, vec_array[field_num]));
2578 _console <<
"Energy ok." << std::endl;
2585 LibmeshPetscCall(populateVectorFromHandle<SolutionHandle>(
2595 LibmeshPetscCall(VecSet(unity_vec, 1.0));
2604 LibmeshPetscCall(VecSet(unity_vec_Wij, 1.0));
2607 Vec _Wij_old_loc_vec;
2609 LibmeshPetscCall(MatMult(mat_array[Q],
_prod, mdot_estimate));
2610 LibmeshPetscCall(MatGetDiagonal(mat_array[Q + 1], pmat_diag));
2611 LibmeshPetscCall(VecAXPY(pmat_diag, 1e-10, unity_vec));
2612 LibmeshPetscCall(VecPointwiseDivide(p_estimate, mdot_estimate, pmat_diag));
2613 LibmeshPetscCall(MatMult(mat_array[2 * Q + 1], p_estimate, sol_holder_P));
2615 LibmeshPetscCall(MatGetDiagonal(mat_array[2 * Q + 2], diag_Wij_loc));
2616 LibmeshPetscCall(VecAXPY(diag_Wij_loc, 1e-10, unity_vec_Wij));
2617 LibmeshPetscCall(VecPointwiseDivide(Wij_estimate, sol_holder_P, diag_Wij_loc));
2620 for (
unsigned int iz = first_node; iz < last_node + 1; iz++)
2622 auto iz_ind = iz - first_node;
2623 for (
unsigned int i_ch = 0; i_ch <
_n_channels; i_ch++)
2625 PetscScalar sumWij = 0.0;
2626 unsigned int counter = 0;
2630 unsigned int i_ch_loc = chans.first;
2631 PetscInt row_vec = i_ch_loc +
_n_channels * iz_ind;
2632 PetscScalar loc_Wij_value;
2633 LibmeshPetscCall(VecGetValues(sol_holder_P, 1, &row_vec, &loc_Wij_value));
2638 LibmeshPetscCall(VecSetValues(sumWij_loc, 1, &row_vec, &sumWij, INSERT_VALUES));
2642 PetscScalar min_mdot;
2643 LibmeshPetscCall(VecAbs(
_prod));
2644 LibmeshPetscCall(VecMin(
_prod, NULL, &min_mdot));
2645 _console <<
"Minimum estimated mdot: " << min_mdot << std::endl;
2647 LibmeshPetscCall(VecAbs(sumWij_loc));
2648 LibmeshPetscCall(VecMax(sumWij_loc, NULL, &
_max_sumWij));
2653 _Wij_loc_vec,
_Wij, first_node, last_node,
_n_gaps));
2654 LibmeshPetscCall(VecAbs(_Wij_loc_vec));
2657 LibmeshPetscCall(VecAbs(_Wij_old_loc_vec));
2658 LibmeshPetscCall(VecAXPY(_Wij_loc_vec, -1.0, _Wij_old_loc_vec));
2659 PetscScalar relax_factor;
2660 LibmeshPetscCall(VecAbs(_Wij_loc_vec));
2661 #if !PETSC_VERSION_LESS_THAN(3, 16, 0) 2662 LibmeshPetscCall(VecMean(_Wij_loc_vec, &relax_factor));
2664 LibmeshPetscCall(VecSum(_Wij_loc_vec, &relax_factor));
2668 _console <<
"Relax base value: " << relax_factor << std::endl;
2670 PetscScalar resistance_relaxation = 0.9;
2676 if (_added_K < 10 && _added_K >= 1.0)
2678 if (_added_K < 1.0 && _added_K >= 0.1)
2680 if (_added_K < 0.1 && _added_K >= 0.01)
2682 if (_added_K < 1e-2 && _added_K >= 1e-3)
2687 LibmeshPetscCall(VecScale(unity_vec_Wij,
_added_K));
2691 LibmeshPetscCall(MatDiagonalSet(mat_array[2 * Q + 2], unity_vec_Wij, ADD_VALUES));
2692 LibmeshPetscCall(VecDestroy(&mdot_estimate));
2693 LibmeshPetscCall(VecDestroy(&pmat_diag));
2694 LibmeshPetscCall(VecDestroy(&unity_vec));
2695 LibmeshPetscCall(VecDestroy(&p_estimate));
2696 LibmeshPetscCall(VecDestroy(&sol_holder_P));
2697 LibmeshPetscCall(VecDestroy(&diag_Wij_loc));
2698 LibmeshPetscCall(VecDestroy(&unity_vec_Wij));
2699 LibmeshPetscCall(VecDestroy(&Wij_estimate));
2700 LibmeshPetscCall(VecDestroy(&sumWij_loc));
2701 LibmeshPetscCall(VecDestroy(&_Wij_loc_vec));
2702 LibmeshPetscCall(VecDestroy(&_Wij_old_loc_vec));
2705 PetscScalar relaxation_factor_mdot, relaxation_factor_P, relaxation_factor_Wij;
2706 relaxation_factor_mdot = 1.0;
2707 relaxation_factor_P = 1.0;
2708 relaxation_factor_Wij = 0.1;
2710 _console <<
"Relax mdot: " << relaxation_factor_mdot << std::endl;
2711 _console <<
"Relax P: " << relaxation_factor_P << std::endl;
2712 _console <<
"Relax Wij: " << relaxation_factor_Wij << std::endl;
2714 PetscInt field_num = 0;
2716 LibmeshPetscCall(VecDuplicate(vec_array[field_num], &diag_mdot));
2717 LibmeshPetscCall(MatGetDiagonal(mat_array[Q * field_num + field_num], diag_mdot));
2718 LibmeshPetscCall(VecScale(diag_mdot, 1.0 / relaxation_factor_mdot));
2720 MatDiagonalSet(mat_array[Q * field_num + field_num], diag_mdot, INSERT_VALUES));
2721 LibmeshPetscCall(populateVectorFromHandle<SolutionHandle>(
2723 LibmeshPetscCall(VecScale(diag_mdot, (1.0 - relaxation_factor_mdot)));
2724 LibmeshPetscCall(VecPointwiseMult(
_prod,
_prod, diag_mdot));
2725 LibmeshPetscCall(VecAXPY(vec_array[field_num], 1.0,
_prod));
2726 LibmeshPetscCall(VecDestroy(&diag_mdot));
2728 _console <<
"mdot relaxed" << std::endl;
2732 LibmeshPetscCall(VecDuplicate(vec_array[field_num], &diag_P));
2733 LibmeshPetscCall(MatGetDiagonal(mat_array[Q * field_num + field_num], diag_P));
2734 LibmeshPetscCall(VecScale(diag_P, 1.0 / relaxation_factor_P));
2735 LibmeshPetscCall(MatDiagonalSet(mat_array[Q * field_num + field_num], diag_P, INSERT_VALUES));
2736 _console <<
"Mat assembled" << std::endl;
2737 LibmeshPetscCall(populateVectorFromHandle<SolutionHandle>(
2739 LibmeshPetscCall(VecScale(diag_P, (1.0 - relaxation_factor_P)));
2740 LibmeshPetscCall(VecPointwiseMult(
_prod,
_prod, diag_P));
2741 LibmeshPetscCall(VecAXPY(vec_array[field_num], 1.0,
_prod));
2742 LibmeshPetscCall(VecDestroy(&diag_P));
2744 _console <<
"P relaxed" << std::endl;
2748 LibmeshPetscCall(VecDuplicate(vec_array[field_num], &diag_Wij));
2749 LibmeshPetscCall(MatGetDiagonal(mat_array[Q * field_num + field_num], diag_Wij));
2750 LibmeshPetscCall(VecScale(diag_Wij, 1.0 / relaxation_factor_Wij));
2751 LibmeshPetscCall(MatDiagonalSet(mat_array[Q * field_num + field_num], diag_Wij, INSERT_VALUES));
2754 LibmeshPetscCall(VecScale(diag_Wij, (1.0 - relaxation_factor_Wij)));
2756 LibmeshPetscCall(VecAXPY(vec_array[field_num], 1.0,
_Wij_vec));
2757 LibmeshPetscCall(VecDestroy(&diag_Wij));
2759 _console <<
"Wij relaxed" << std::endl;
2761 _console <<
"Linear solver relaxed." << std::endl;
2764 LibmeshPetscCall(MatCreateNest(PETSC_COMM_WORLD, Q, NULL, Q, NULL, mat_array.data(), &A_nest));
2765 LibmeshPetscCall(VecCreateNest(PETSC_COMM_WORLD, Q, NULL, vec_array.data(), &b_nest));
2766 _console <<
"Nested system created." << std::endl;
2770 LibmeshPetscCall(KSPCreate(PETSC_COMM_WORLD, &ksp));
2771 LibmeshPetscCall(KSPSetType(ksp, KSPFGMRES));
2773 LibmeshPetscCall(KSPSetOperators(ksp, A_nest, A_nest));
2775 LibmeshPetscCall(KSPGetPC(ksp, &pc));
2776 LibmeshPetscCall(PCSetType(pc, PCFIELDSPLIT));
2779 std::vector<IS> rows(Q);
2782 LibmeshPetscCall(MatNestGetISs(A_nest, rows.data(), NULL));
2783 for (PetscInt
j = 0;
j < Q; ++
j)
2786 LibmeshPetscCall(ISDuplicate(rows[M], &expand1));
2788 LibmeshPetscCall(PCFieldSplitSetIS(pc, NULL, expand1));
2789 LibmeshPetscCall(ISDestroy(&expand1));
2791 _console <<
"Linear solver assembled." << std::endl;
2794 LibmeshPetscCall(VecDuplicate(b_nest, &x_nest));
2795 LibmeshPetscCall(VecSet(x_nest, 0.0));
2796 LibmeshPetscCall(KSPSolve(ksp, b_nest, x_nest));
2799 LibmeshPetscCall(VecDestroy(&b_nest));
2800 LibmeshPetscCall(MatDestroy(&A_nest));
2801 LibmeshPetscCall(KSPDestroy(&ksp));
2802 for (PetscInt i = 0; i < Q * Q; i++)
2804 LibmeshPetscCall(MatDestroy(&mat_array[i]));
2806 for (PetscInt i = 0; i < Q; i++)
2808 LibmeshPetscCall(VecDestroy(&vec_array[i]));
2812 Vec sol_mdot, sol_p, sol_Wij;
2813 _console <<
"Vectors created." << std::endl;
2816 LibmeshPetscCall(VecNestGetSubVecs(x_nest, &num_vecs, &loc_vecs));
2817 _console <<
"Starting extraction." << std::endl;
2819 LibmeshPetscCall(VecCopy(loc_vecs[0], sol_mdot));
2821 LibmeshPetscCall(VecCopy(loc_vecs[1], sol_p));
2823 LibmeshPetscCall(VecCopy(loc_vecs[2], sol_Wij));
2824 _console <<
"Getting individual field solutions from coupled solver." << std::endl;
2827 PetscScalar * sol_p_array;
2828 LibmeshPetscCall(VecGetArray(sol_p, &sol_p_array));
2829 PetscScalar * sol_Wij_array;
2830 LibmeshPetscCall(VecGetArray(sol_Wij, &sol_Wij_array));
2833 LibmeshPetscCall(populateSolutionChan<SolutionHandle>(
2837 for (
unsigned int iz = last_node; iz > first_node - 1; iz--)
2839 auto iz_ind = iz - first_node;
2840 for (
unsigned int i_ch = 0; i_ch <
_n_channels; i_ch++)
2850 sol_Wij,
_Wij, first_node, last_node - 1,
_n_gaps));
2857 LibmeshPetscCall(VecCopy(loc_vecs[3], sol_h));
2858 PetscScalar * sol_h_array;
2859 LibmeshPetscCall(VecGetArray(sol_h, &sol_h_array));
2860 for (
unsigned int iz = first_node; iz < last_node + 1; iz++)
2862 auto iz_ind = iz - first_node;
2863 for (
unsigned int i_ch = 0; i_ch <
_n_channels; i_ch++)
2866 auto h_out = sol_h_array[iz_ind *
_n_channels + i_ch];
2870 " : Calculation of negative Enthalpy h_out = : ",
2875 _h_soln->set(node_out, h_out);
2878 LibmeshPetscCall(VecDestroy(&sol_h));
2883 LibmeshPetscCall(populateSolutionChan<SolutionHandle>(
2888 LibmeshPetscCall(populateVectorFromHandle<SolutionHandle>(
2891 LibmeshPetscCall(VecAbs(
_prod));
2896 _console <<
"Solutions assigned to MOOSE variables." << std::endl;
2899 LibmeshPetscCall(VecDestroy(&x_nest));
2900 LibmeshPetscCall(VecDestroy(&sol_mdot));
2901 LibmeshPetscCall(VecDestroy(&sol_p));
2902 LibmeshPetscCall(VecDestroy(&sol_Wij));
2903 LibmeshPetscCall(VecDestroy(&sumWij_loc));
2904 _console <<
"Solutions destroyed." << std::endl;
2913 unsigned int first_node = 1;
2914 for (
unsigned int iz = first_node; iz < last_node + 1; iz++)
2916 for (
unsigned int i_ch = 0; i_ch <
_n_channels; i_ch++)
2929 _console <<
"Executing subchannel solver\n";
2931 _console <<
"Solution initialized" << std::endl;
2933 unsigned int P_it = 0;
2934 unsigned int P_it_max;
2944 while ((P_error >
_P_tol && P_it < P_it_max))
2949 _console <<
"Reached maximum number of axial pressure iterations" << std::endl;
2952 _console <<
"Solving Outer Iteration : " << P_it << std::endl;
2953 auto P_L2norm_old_axial =
_P_soln->L2norm();
2954 for (
unsigned int iblock = 0; iblock <
_n_blocks; iblock++)
2958 Real T_block_error = 1.0;
2960 _console <<
"Solving Block: " << iblock <<
" From first level: " << first_level
2961 <<
" to last level: " << last_level << std::endl;
2967 _console <<
"Reached maximum number of temperature iterations for block: " << iblock
2971 auto T_L2norm_old_block =
_T_soln->L2norm();
2980 _console <<
"Done with h solve" << std::endl;
2982 _console <<
"Done with T solve" << std::endl;
2990 _console <<
"Done with main solve." << std::endl;
3003 _console <<
"Done with thermal solve." << std::endl;
3013 _console <<
"Done updating thermophysical properties." << std::endl;
3017 _aux->solution().close();
3019 auto T_L2norm_new =
_T_soln->L2norm();
3021 std::abs((T_L2norm_new - T_L2norm_old_block) / (T_L2norm_old_block + 1E-14));
3022 _console <<
"T_block_error: " << T_block_error << std::endl;
3025 auto P_L2norm_new_axial =
_P_soln->L2norm();
3027 std::abs((P_L2norm_new_axial - P_L2norm_old_axial) / (P_L2norm_old_axial +
_P_out + 1E-14));
3028 _console <<
"P_error :" << P_error << std::endl;
3033 auto power_in = 0.0;
3034 auto power_out = 0.0;
3035 for (
unsigned int i_ch = 0; i_ch <
_n_channels; i_ch++)
3039 power_in += (*_mdot_soln)(node_in) * (*
_h_soln)(node_in);
3040 power_out += (*_mdot_soln)(node_out) * (*
_h_soln)(node_out);
3042 _console <<
"Power added to coolant is: " << power_out - power_in <<
" Watt" << std::endl;
3045 _console <<
"Commencing calculation of Pin surface temperature \n";
3046 for (
unsigned int i_pin = 0; i_pin <
_n_assemblies; i_pin++)
3048 for (
unsigned int iz = 0; iz <
_n_cells + 1; ++iz)
3057 auto mu = (*_mu_soln)(node);
3058 auto S = (*_S_flow_soln)(node);
3059 auto w_perim = (*_w_perim_soln)(node);
3060 auto Dh_i = 4.0 *
S / w_perim;
3061 auto Re = (((*_mdot_soln)(node) /
S) * Dh_i /
mu);
3065 auto Pr = (*_mu_soln)(node)*
cp /
k;
3068 auto hw = Nu *
k / Dh_i;
3071 sumTemp += (*_q_prime_soln)(pin_node) / (perimeter * hw) + (*_T_soln)(node);
3077 _aux->solution().close();
Vec _amc_time_derivative_rhs
virtual PetscScalar computeInterpolatedValue(PetscScalar topValue, PetscScalar botValue, PetscScalar Peclet=0.0)
static const std::string PRESSURE_DROP
pressure drop
Mat _amc_turbulent_cross_flows_mat
Mass conservation - density time derivative No implicit matrix.
const bool _compute_density
Flag that activates or deactivates the calculation of density.
Mat _cmc_friction_force_mat
Cross momentum conservation - friction force.
static const std::string MASS_FLOW_RATE
mass flow rate
virtual const std::vector< std::vector< Real > > & getKGrid() const
Get axial cell location and value of loss coefficient.
virtual const std::vector< unsigned int > & getChannelPins(unsigned int i_chan) const =0
Return a vector of pin indices for a given channel index.
std::unique_ptr< SolutionHandle > _w_perim_soln
const bool _segregated_bool
Segregated solve.
Vec _hc_advective_derivative_rhs
virtual void externalSolve() override
Real _TR
Flag that activates or deactivates the transient parts of the equations we solve by multiplication...
static const std::string DENSITY
density
Vec _amc_advective_derivative_rhs
std::unique_ptr< SolutionHandle > _S_flow_soln
std::unique_ptr< SolutionHandle > _P_soln
Mat _amc_advective_derivative_mat
Axial momentum conservation - advective (Eulerian) derivative.
virtual void computeSumWij(int iblock)
Computes net diversion crossflow per channel for block iblock.
const int & _T_maxit
Maximum iterations for the inner temperature loop.
const Real & _P_tol
Convergence tolerance for the pressure loop in external solve.
virtual void computeh(int iblock)
Computes Enthalpy per channel for block iblock.
Vec _amc_turbulent_cross_flows_rhs
virtual void computeDP(int iblock)
Computes Pressure Drop per channel for block iblock.
PetscErrorCode populateVectorFromHandle(Vec &x, const T &solution, const unsigned int first_axial_level, const unsigned int last_axial_level, const unsigned int cross_dimension)
virtual void syncSolutions(Direction direction) override
Vec _amc_pressure_force_rhs
std::unique_ptr< SolutionHandle > _Tpin_soln
virtual const Real & getSideX() const
Return side lengths of the assembly.
Base class for inter-wrapper meshes.
virtual const Real & getHeatedLength() const
Return heated length.
virtual void zero() override final
virtual void computeRho(int iblock)
Computes Density per channel for block iblock.
PetscScalar _added_K
Added resistances for monolithic convergence.
virtual const std::pair< unsigned int, unsigned int > & getGapChannels(unsigned int i_gap) const =0
Return a pair of inter-wrapper indices for a given gap index.
virtual void computeWijPrime(int iblock)
Computes turbulent crossflow per gap for block iblock.
virtual const Real & getHeatedLengthEntry() const
Return unheated length at entry.
virtual void computeT(int iblock)
Computes Temperature per channel for block iblock.
PetscScalar _correction_factor
Vec _mc_axial_convection_rhs
PetscScalar _max_sumWij_new
const bool _implicit_bool
Flag to define the usage of a implicit or explicit solution.
std::unique_ptr< SolutionHandle > _SumWij_soln
Mat _cmc_pressure_force_mat
Cross momentum conservation - pressure force.
const Real & _P_out
Outlet Pressure.
PetscErrorCode formFunctionIW(SNES, Vec x, Vec f, void *info)
creates the residual function to be used in the PETCs snes context
Mat _mc_sumWij_mat
Mass conservation Mass conservation - sum of cross fluxes.
static InputParameters validParams()
const PetscReal & _dtol
The divergence tolerance for the ksp linear solver.
static InputParameters validParams()
Base class for the 1-phase steady-state/transient interwrapper solver.
virtual PetscErrorCode createPetscVector(Vec &v, PetscInt n)
Petsc Functions.
Vec _cmc_friction_force_rhs
virtual PetscErrorCode implicitPetscSolve(int iblock)
Computes implicit solve using PetSc.
const Real & _dt
Time step.
Vec _cmc_time_derivative_rhs
std::unique_ptr< SolutionHandle > _rho_soln
const PetscReal & _rtol
The relative convergence tolerance, (relative decrease) for the ksp linear solver.
const unsigned int _n_cells
The following methods are specializations for using the Parallel::packed_range_* routines for a vecto...
const unsigned int _block_size
Mat _mc_axial_convection_mat
Mass conservation - axial convection.
std::unique_ptr< SolutionHandle > _mdot_soln
const unsigned int _n_assemblies
virtual void computeMdot(int iblock)
Computes mass flow per channel for block iblock.
bool isRestarting() const
const SinglePhaseFluidProperties * _fp
Solutions handles and link to TH tables properties.
PetscErrorCode populateDenseFromVector(const Vec &x, T &solution, const unsigned int first_axial_level, const unsigned int last_axial_level, const unsigned int cross_dimension)
virtual const std::string & name() const
const Real & _beta
Thermal diffusion coefficient used in turbulent crossflow.
Mat _hc_time_derivative_mat
Enthalpy Enthalpy conservation - time derivative.
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
Vec _hc_cross_derivative_rhs
Vec _amc_cross_derivative_rhs
const PetscInt & _maxit
The maximum number of iterations to use for the ksp linear solver.
std::vector< Real > _z_grid
axial location of nodes
const MooseEnum _interpolation_scheme
The interpolation method used in constructing the systems.
virtual const std::vector< unsigned int > & getPinChannels(unsigned int i_pin) const =0
Return a vector of channel indices for a given Pin index.
const bool _staggered_pressure_bool
Flag to define the usage of staggered or collocated pressure.
static const std::string WETTED_PERIMETER
wetted perimeter
PetscErrorCode populateSolutionGap(const Vec &x, T &solution, const unsigned int first_axial_level, const unsigned int last_axial_level, const unsigned int cross_dimension)
Mat _amc_cross_derivative_mat
Axial momentum conservation - cross flux derivative.
const unsigned int _n_gaps
InterWrapper1PhaseProblem * schp
static const std::string cp
static const std::string VISCOSITY
viscosity
virtual const Real & getSideY() const
static const std::string PIN_TEMPERATURE
pin temperature
virtual PetscErrorCode petscSnesSolver(int iblock, const libMesh::DenseVector< Real > &solution, libMesh::DenseVector< Real > &root)
Computes solution of nonlinear equation using snes.
static const std::string LINEAR_HEAT_RATE
linear heat rate
Real value(unsigned n, unsigned alpha, unsigned beta, Real x)
std::unique_ptr< SolutionHandle > _T_soln
const std::vector< double > x
static const std::string S
Vec _cmc_Wij_channel_dummy
Real f(Real x)
Test function for Brents method.
virtual Node * getPinNode(unsigned int i_pin, unsigned iz) const =0
Get the pin mesh node for a given pin index and elevation index.
Mat _hc_advective_derivative_mat
Enthalpy conservation - advective (Eulerian) derivative;.
virtual void computeP(int iblock)
Computes Pressure per channel for block iblock.
static const std::string mu
static const std::string pitch
virtual void initialSetup() override
const T & getConstMesh(const MooseMesh &mesh)
function to cast const mesh
virtual PetscErrorCode createPetscMatrix(Mat &M, PetscInt n, PetscInt m)
static const std::string ENTHALPY
enthalpy
const unsigned int _n_channels
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.
virtual ~InterWrapper1PhaseProblem()
std::shared_ptr< AuxiliarySystem > _aux
Mat _amc_time_derivative_mat
Axial momentum conservation - time derivative.
Vec _amc_friction_force_rhs
const bool _monolithic_thermal_bool
Thermal monolithic bool.
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 void computeWij(int iblock)
Computes cross fluxes for block iblock.
unsigned int _n_blocks
number of axial blocks
const InterWrapperMesh & _subchannel_mesh
virtual PetscScalar computeInterpolationCoefficients(PetscScalar Peclet=0.0)
Functions that computes the interpolation scheme given the Peclet number.
std::unique_ptr< SolutionHandle > _mu_soln
Mat _cmc_advective_derivative_mat
Cross momentum conservation - advective (Eulerian) derivative.
Vec _hc_added_heat_rhs
Enthalpy conservation - source and sink.
Mat _hc_sys_h_mat
System matrices.
std::unique_ptr< SolutionHandle > _DP_soln
const bool _compute_viscosity
Flag that activates or deactivates the calculation of viscosity.
static const std::string SUM_CROSSFLOW
sum of diversion crossflow
PetscErrorCode populateSolutionChan(const Vec &x, T &solution, const unsigned int first_axial_level, const unsigned int last_axial_level, const unsigned int cross_dimension)
Vec _hc_time_derivative_rhs
Vec _cmc_pressure_force_rhs
problem information to be used in the PETSc problem
LibmeshPetscCallQ(DMShellGetContext(dm, &ctx))
virtual bool solverSystemConverged(const unsigned int) override
virtual Node * getChannelNode(unsigned int i_chan, unsigned iz) const =0
Get the inter-wrapper mesh node for a given channel index and elevation index.
virtual Real getGapWidth(unsigned int gap_index) const =0
Return gap width for a given gap index.
virtual void computeWijFromSolve(int iblock)
Computes diversion crossflow per gap for block with index iblock Block is a partition of the whole do...
const Real & _T_tol
Convergence tolerance for the temperature loop in external solve.
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
static const std::string v
static const std::string PRESSURE
pressure
std::unique_ptr< SolutionHandle > _q_prime_soln
static const std::string alpha
virtual void initializeSolution()
Function to initialize the solution fields.
Mat _cmc_sys_Wij_mat
Lateral momentum system matrix.
Mat _amc_pressure_force_mat
Axial momentum conservation - pressure force.
static const std::string SURFACE_AREA
surface area
const bool _pin_mesh_exist
Flag that informs if there is a pin mesh or not.
virtual Real computeFrictionFactor(Real Re)=0
Returns friction factor.
void resize(const unsigned int new_m, const unsigned int new_n)
virtual void computeMu(int iblock)
Computes Viscosity per channel for block iblock.
void mooseError(Args &&... args) const
PetscErrorCode populateVectorFromDense(Vec &x, const T &solution, const unsigned int first_axial_level, const unsigned int last_axial_level, const unsigned int cross_dimension)
std::unique_ptr< SolutionHandle > _h_soln
virtual Real computeAddedHeat(unsigned int i_ch, unsigned int iz)
Computes added heat for channel i_ch and cell iz.
static const std::complex< double > j(0, 1)
Complex number "j" (also known as "i")
libMesh::DenseMatrix< Real > _Wij_old
const bool _compute_power
Flag that informs if we need to solve the Enthalpy/Temperature equations or not.
const ConsoleStream _console
libMesh::DenseMatrix< Real > & _Wij
bool _converged
Variable that informs whether we exited external solve with a converged solution or not...
Vec _cmc_advective_derivative_rhs
libMesh::DenseMatrix< Real > _WijPrime
PetscFunctionReturn(LIBMESH_PETSC_SUCCESS)
bool isRecovering() const
Mat _hc_cross_derivative_mat
Enthalpy conservation - cross flux derivative.
static const std::string TEMPERATURE
temperature
MooseUnits pow(const MooseUnits &, int)
libMesh::DenseMatrix< Real > _Wij_residual_matrix
virtual const Real & getPitch() const
Return the pitch between 2 inter-wrappers.
static const std::string k
virtual const std::vector< unsigned int > & getChannelGaps(unsigned int i_chan) const =0
Return a vector of gap indices for a given channel index.
void ErrorVector unsigned int
InterWrapper1PhaseProblem(const InputParameters ¶ms)
virtual libMesh::DenseVector< Real > residualFunction(int iblock, libMesh::DenseVector< Real > solution)
Computes Residual per gap for block iblock.
friend PetscErrorCode formFunctionIW(SNES snes, Vec x, Vec f, void *info)
creates the residual function to be used in the PETCs snes context
Vec _amc_gravity_rhs
Axial momentum conservation - buoyancy force No implicit matrix.
Mat _cmc_time_derivative_mat
Cross momentum Cross momentum conservation - time derivative.
const Real & _CT
Turbulent modeling parameter used in axial momentum equation.
Mat _amc_sys_mdot_mat
Axial momentum system matrix.
Mat _amc_friction_force_mat
Axial momentum conservation - friction force.
const PetscReal & _atol
The absolute convergence tolerance for the ksp linear solver.
virtual const Real & getCrossflowSign(unsigned int i_chan, unsigned int i_local) const =0
Return a signs for the cross flow given a inter-wrapper index and local neighbor index.