LCOV - code coverage report
Current view: top level - src/problems - TriSubChannel1PhaseProblem.C (source / functions) Hit Total Coverage
Test: idaholab/moose subchannel: #32971 (54bef8) with base c6cf66 Lines: 592 611 96.9 %
Date: 2026-05-29 20:40:47 Functions: 8 9 88.9 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : //* This file is part of the MOOSE framework
       2             : //* https://mooseframework.inl.gov
       3             : //*
       4             : //* All rights reserved, see COPYRIGHT for full restrictions
       5             : //* https://github.com/idaholab/moose/blob/master/COPYRIGHT
       6             : //*
       7             : //* Licensed under LGPL 2.1, please see LICENSE for details
       8             : //* https://www.gnu.org/licenses/lgpl-2.1.html
       9             : 
      10             : #include "TriSubChannel1PhaseProblem.h"
      11             : #include "AuxiliarySystem.h"
      12             : #include "TriSubChannelMesh.h"
      13             : #include "SubChannel1PhaseProblem.h"
      14             : #include "SinglePhaseFluidProperties.h"
      15             : #include "SCM.h"
      16             : #include <limits> // for std::numeric_limits
      17             : #include <cmath>  // for std::isnan
      18             : #include "SCMMixingClosureBase.h"
      19             : 
      20             : registerMooseObject("SubChannelApp", TriSubChannel1PhaseProblem);
      21             : 
      22             : InputParameters
      23         310 : TriSubChannel1PhaseProblem::validParams()
      24             : {
      25         310 :   InputParameters params = SubChannel1PhaseProblem::validParams();
      26         310 :   params.addClassDescription("Solver class for subchannels in a triangular lattice assembly and "
      27             :                              "bare/wire-wrapped fuel pins");
      28         310 :   return params;
      29           0 : }
      30             : 
      31         155 : TriSubChannel1PhaseProblem::TriSubChannel1PhaseProblem(const InputParameters & params)
      32             :   : SubChannel1PhaseProblem(params),
      33         155 :     _tri_sch_mesh(SCM::getMesh<TriSubChannelMesh>(_subchannel_mesh))
      34             : {
      35             :   // Initializing heat conduction system
      36         155 :   LibmeshPetscCall(createPetscMatrix(
      37             :       _hc_axial_heat_conduction_mat, _block_size * _n_channels, _block_size * _n_channels));
      38         155 :   LibmeshPetscCall(createPetscVector(_hc_axial_heat_conduction_rhs, _block_size * _n_channels));
      39         155 :   LibmeshPetscCall(createPetscMatrix(
      40             :       _hc_radial_heat_conduction_mat, _block_size * _n_channels, _block_size * _n_channels));
      41         155 :   LibmeshPetscCall(createPetscVector(_hc_radial_heat_conduction_rhs, _block_size * _n_channels));
      42         155 :   LibmeshPetscCall(createPetscMatrix(
      43             :       _hc_sweep_enthalpy_mat, _block_size * _n_channels, _block_size * _n_channels));
      44         155 :   LibmeshPetscCall(createPetscVector(_hc_sweep_enthalpy_rhs, _block_size * _n_channels));
      45         155 : }
      46             : 
      47         152 : TriSubChannel1PhaseProblem::~TriSubChannel1PhaseProblem()
      48             : {
      49         152 :   PetscErrorCode ierr = cleanUp();
      50         152 :   if (ierr)
      51           0 :     mooseError(name(), ": Error in memory cleanup");
      52         152 : }
      53             : 
      54             : PetscErrorCode
      55         152 : TriSubChannel1PhaseProblem::cleanUp()
      56             : {
      57             :   PetscFunctionBegin;
      58             :   // Clean up heat conduction system
      59         152 :   LibmeshPetscCall(MatDestroy(&_hc_axial_heat_conduction_mat));
      60         152 :   LibmeshPetscCall(VecDestroy(&_hc_axial_heat_conduction_rhs));
      61         152 :   LibmeshPetscCall(MatDestroy(&_hc_radial_heat_conduction_mat));
      62         152 :   LibmeshPetscCall(VecDestroy(&_hc_radial_heat_conduction_rhs));
      63         152 :   LibmeshPetscCall(MatDestroy(&_hc_sweep_enthalpy_mat));
      64         152 :   LibmeshPetscCall(VecDestroy(&_hc_sweep_enthalpy_rhs));
      65         152 :   PetscFunctionReturn(LIBMESH_PETSC_SUCCESS);
      66             : }
      67             : 
      68             : void
      69         151 : TriSubChannel1PhaseProblem::initializeSolution()
      70             : {
      71         151 :   detectDeformation();
      72             : 
      73         151 :   if (_deformation)
      74             :   {
      75             :     // update surface area, wetted perimeter based on: Dpin, displacement
      76             :     Real standard_area, wire_area, additional_area, wetted_perimeter, displaced_area;
      77           5 :     auto flat_to_flat = _tri_sch_mesh.getFlatToFlat();
      78           5 :     auto n_rings = _tri_sch_mesh.getNumOfRings();
      79           5 :     auto pitch = _subchannel_mesh.getPitch();
      80           5 :     auto pin_diameter = _subchannel_mesh.getPinDiameter();
      81           5 :     auto wire_diameter = _tri_sch_mesh.getWireDiameter();
      82           5 :     auto wire_lead_length = _tri_sch_mesh.getWireLeadLength();
      83           5 :     auto gap = _tri_sch_mesh.getDuctToPinGap();
      84           5 :     auto z_blockage = _subchannel_mesh.getZBlockage();
      85           5 :     auto index_blockage = _subchannel_mesh.getIndexBlockage();
      86           5 :     auto reduction_blockage = _subchannel_mesh.getReductionBlockage();
      87             :     auto theta =
      88           5 :         std::acos(wire_lead_length /
      89           5 :                   std::sqrt(Utility::pow<2>(wire_lead_length) +
      90           5 :                             Utility::pow<2>(libMesh::pi * (pin_diameter + wire_diameter))));
      91          35 :     for (unsigned int iz = 0; iz < _n_cells + 1; iz++)
      92             :     {
      93        1290 :       for (unsigned int i_ch = 0; i_ch < _n_channels; i_ch++)
      94             :       {
      95        1260 :         auto subch_type = _subchannel_mesh.getSubchannelType(i_ch);
      96        1260 :         auto * node = _subchannel_mesh.getChannelNode(i_ch, iz);
      97        1260 :         auto Z = _z_grid[iz];
      98             :         Real rod_area = 0.0;
      99             :         Real rod_perimeter = 0.0;
     100        4320 :         for (auto i_pin : _subchannel_mesh.getChannelPins(i_ch))
     101             :         {
     102        3060 :           auto * pin_node = _subchannel_mesh.getPinNode(i_pin, iz);
     103        3060 :           if (subch_type == EChannelType::CENTER || subch_type == EChannelType::CORNER)
     104             :           {
     105        2340 :             rod_area +=
     106        2340 :                 (1.0 / 6.0) * 0.25 * M_PI * (*_Dpin_soln)(pin_node) * (*_Dpin_soln)(pin_node);
     107        2340 :             rod_perimeter += (1.0 / 6.0) * M_PI * (*_Dpin_soln)(pin_node);
     108             :           }
     109             :           else
     110             :           {
     111         720 :             rod_area +=
     112         720 :                 (1.0 / 4.0) * 0.25 * M_PI * (*_Dpin_soln)(pin_node) * (*_Dpin_soln)(pin_node);
     113         720 :             rod_perimeter += (1.0 / 4.0) * M_PI * (*_Dpin_soln)(pin_node);
     114             :           }
     115             :         }
     116             : 
     117        1260 :         if (subch_type == EChannelType::CENTER)
     118             :         {
     119         720 :           standard_area = Utility::pow<2>(pitch) * std::sqrt(3.0) / 4.0;
     120             :           additional_area = 0.0;
     121             :           displaced_area = 0.0;
     122         720 :           wire_area = libMesh::pi * Utility::pow<2>(wire_diameter) / 8.0 / std::cos(theta);
     123         720 :           wetted_perimeter = rod_perimeter + 0.5 * libMesh::pi * wire_diameter / std::cos(theta);
     124             :         }
     125         540 :         else if (subch_type == EChannelType::EDGE)
     126             :         {
     127         360 :           standard_area = pitch * (pin_diameter / 2.0 + gap);
     128             :           additional_area = 0.0;
     129         360 :           displaced_area = (*_displacement_soln)(node)*pitch;
     130         360 :           wire_area = libMesh::pi * Utility::pow<2>(wire_diameter) / 8.0 / std::cos(theta);
     131         360 :           wetted_perimeter =
     132         360 :               rod_perimeter + 0.5 * libMesh::pi * wire_diameter / std::cos(theta) + pitch;
     133             :         }
     134             :         else
     135             :         {
     136         180 :           standard_area = 1.0 / std::sqrt(3.0) * Utility::pow<2>(pin_diameter / 2.0 + gap);
     137             :           additional_area = 0.0;
     138         180 :           displaced_area = 1.0 / std::sqrt(3.0) *
     139         180 :                            (pin_diameter + 2.0 * gap + (*_displacement_soln)(node)) *
     140         180 :                            (*_displacement_soln)(node);
     141         180 :           wire_area = libMesh::pi / 24.0 * Utility::pow<2>(wire_diameter) / std::cos(theta);
     142         180 :           wetted_perimeter =
     143         180 :               rod_perimeter + libMesh::pi * wire_diameter / std::cos(theta) / 6.0 +
     144         180 :               2.0 / std::sqrt(3.0) * (pin_diameter / 2.0 + gap + (*_displacement_soln)(node));
     145             :         }
     146             : 
     147             :         // Calculate subchannel area
     148        1260 :         auto subchannel_area =
     149        1260 :             standard_area + additional_area + displaced_area - rod_area - wire_area;
     150             : 
     151             :         // Correct subchannel area and wetted perimeter in case of overlapping pins
     152             :         auto overlapping_pin_area = 0.0;
     153             :         auto overlapping_wetted_perimeter = 0.0;
     154        4860 :         for (auto i_gap : _subchannel_mesh.getChannelGaps(i_ch))
     155             :         {
     156        3600 :           auto gap_pins = _subchannel_mesh.getGapPins(i_gap);
     157             :           auto pin_1 = gap_pins.first;
     158             :           auto pin_2 = gap_pins.second;
     159        3600 :           auto * pin_node_1 = _subchannel_mesh.getPinNode(pin_1, iz);
     160        3600 :           auto * pin_node_2 = _subchannel_mesh.getPinNode(pin_2, iz);
     161        3600 :           auto Diameter1 = (*_Dpin_soln)(pin_node_1);
     162        3600 :           auto Radius1 = Diameter1 / 2.0;
     163        3600 :           auto Diameter2 = (*_Dpin_soln)(pin_node_2);
     164        3600 :           auto Radius2 = Diameter2 / 2.0;
     165        3600 :           auto pitch = _subchannel_mesh.getPitch();
     166             : 
     167        3600 :           if (pitch < (Radius1 + Radius2)) // overlapping pins
     168             :           {
     169           0 :             mooseWarning(" The gap of index : '", i_gap, " at axial cell ", iz, " ' is blocked.");
     170           0 :             auto cos1 =
     171           0 :                 (pitch * pitch + Radius1 * Radius1 - Radius2 * Radius2) / (2 * pitch * Radius1);
     172           0 :             auto cos2 =
     173           0 :                 (pitch * pitch + Radius2 * Radius2 - Radius1 * Radius1) / (2 * pitch * Radius2);
     174           0 :             auto angle1 = 2.0 * acos(cos1);
     175           0 :             auto angle2 = 2.0 * acos(cos2);
     176             :             // half of the intersecting arc-length
     177           0 :             overlapping_wetted_perimeter += 0.5 * angle1 * Radius1 + 0.5 * angle2 * Radius2;
     178             :             // Half of the overlapping area
     179           0 :             overlapping_pin_area +=
     180           0 :                 0.5 * Radius1 * Radius1 * acos(cos1) + 0.5 * Radius2 * Radius2 * acos(cos2) -
     181           0 :                 0.25 * sqrt((-pitch + Radius1 + Radius2) * (pitch + Radius1 - Radius2) *
     182           0 :                             (pitch - Radius1 + Radius2) * (pitch + Radius1 + Radius2));
     183             :           }
     184             :         }
     185        1260 :         subchannel_area += overlapping_pin_area;           // correct surface area
     186        1260 :         wetted_perimeter += -overlapping_wetted_perimeter; // correct wetted perimeter
     187             : 
     188             :         // Apply area reduction on subchannels affected by blockage
     189             :         auto index = 0;
     190        2520 :         for (const auto & i_blockage : index_blockage)
     191             :         {
     192        1260 :           if (i_ch == i_blockage && (Z >= z_blockage.front() && Z <= z_blockage.back()))
     193             :           {
     194           5 :             subchannel_area *= reduction_blockage[index];
     195             :           }
     196        1260 :           index++;
     197             :         }
     198        1260 :         _S_flow_soln->set(node, subchannel_area);
     199             :         _w_perim_soln->set(node, wetted_perimeter);
     200             :       }
     201             :     }
     202             :     // update map of gap between pins (gij) based on: Dpin, displacement
     203          35 :     for (unsigned int iz = 0; iz < _n_cells + 1; iz++)
     204             :     {
     205        1830 :       for (unsigned int i_gap = 0; i_gap < _n_gaps; i_gap++)
     206             :       {
     207        1800 :         auto gap_pins = _subchannel_mesh.getGapPins(i_gap);
     208             :         auto pin_1 = gap_pins.first;
     209             :         auto pin_2 = gap_pins.second;
     210        1800 :         auto * pin_node_1 = _subchannel_mesh.getPinNode(pin_1, iz);
     211        1800 :         auto * pin_node_2 = _subchannel_mesh.getPinNode(pin_2, iz);
     212             : 
     213        1800 :         if (pin_1 == pin_2) // Corner or edge gap
     214             :         {
     215             :           auto displacement = 0.0;
     216             :           auto counter = 0.0;
     217        3240 :           for (auto i_ch : _subchannel_mesh.getPinChannels(pin_1))
     218             :           {
     219        2700 :             auto subch_type = _subchannel_mesh.getSubchannelType(i_ch);
     220        2700 :             auto * node = _subchannel_mesh.getChannelNode(i_ch, iz);
     221        2700 :             if (subch_type == EChannelType::EDGE || subch_type == EChannelType::CORNER)
     222             :             {
     223        1440 :               displacement += (*_displacement_soln)(node);
     224        1440 :               counter += 1.0;
     225             :             }
     226             :           }
     227         540 :           displacement = displacement / counter;
     228         540 :           _tri_sch_mesh._gij_map[iz][i_gap] =
     229         540 :               0.5 * (flat_to_flat - (n_rings - 1) * pitch * std::sqrt(3.0) -
     230         540 :                      (*_Dpin_soln)(pin_node_1)) +
     231             :               displacement;
     232             :         }
     233             :         else // center gap
     234             :         {
     235        1260 :           _tri_sch_mesh._gij_map[iz][i_gap] =
     236        1260 :               pitch - (*_Dpin_soln)(pin_node_1) / 2.0 - (*_Dpin_soln)(pin_node_2) / 2.0;
     237             :         }
     238             :         // if pins come in contact, the gap is zero
     239        1800 :         if (_tri_sch_mesh._gij_map[iz][i_gap] <= 0.0)
     240           0 :           _tri_sch_mesh._gij_map[iz][i_gap] = 0.0;
     241             :       }
     242             :     }
     243           5 :   }
     244             : 
     245        3331 :   for (unsigned int iz = 1; iz < _n_cells + 1; iz++)
     246             :   {
     247      230220 :     for (unsigned int i_ch = 0; i_ch < _n_channels; i_ch++)
     248             :     {
     249      227040 :       auto * node_out = _subchannel_mesh.getChannelNode(i_ch, iz);
     250      227040 :       auto * node_in = _subchannel_mesh.getChannelNode(i_ch, iz - 1);
     251      227040 :       _mdot_soln->set(node_out, (*_mdot_soln)(node_in));
     252             :     }
     253             :   }
     254             : 
     255             :   // We must do a global assembly to make sure data is parallel consistent before we do things
     256             :   // like compute L2 norms
     257         151 :   _aux->solution().close();
     258         151 : }
     259             : 
     260             : Real
     261     3240330 : TriSubChannel1PhaseProblem::computeAddedHeatPin(unsigned int i_ch, unsigned int iz) const
     262             : {
     263             :   // Compute axial location of nodes.
     264     3240330 :   auto z2 = _z_grid[iz];
     265     3240330 :   auto z1 = _z_grid[iz - 1];
     266     3240330 :   auto heated_length = _subchannel_mesh.getHeatedLength();
     267     3240330 :   auto unheated_length_entry = _subchannel_mesh.getHeatedLengthEntry();
     268     3240330 :   if (MooseUtils::absoluteFuzzyGreaterThan(z2, unheated_length_entry) &&
     269     2740194 :       MooseUtils::absoluteFuzzyLessThan(z1, unheated_length_entry + heated_length))
     270             :   {
     271             :     // Compute the height of this element.
     272     1910652 :     auto dz = z2 - z1;
     273     1910652 :     if (_pin_mesh_exist)
     274             :     {
     275             :       double factor;
     276     1020936 :       auto subch_type = _subchannel_mesh.getSubchannelType(i_ch);
     277     1020936 :       switch (subch_type)
     278             :       {
     279             :         case EChannelType::CENTER:
     280             :           factor = 1.0 / 6.0;
     281             :           break;
     282      205344 :         case EChannelType::EDGE:
     283             :           factor = 1.0 / 4.0;
     284      205344 :           break;
     285             :         case EChannelType::CORNER:
     286             :           factor = 1.0 / 6.0;
     287             :           break;
     288             :         default:
     289             :           return 0.0; // handle invalid subch_type if needed
     290             :       }
     291             :       double heat_rate_in = 0.0;
     292             :       double heat_rate_out = 0.0;
     293     3759408 :       for (auto i_pin : _subchannel_mesh.getChannelPins(i_ch))
     294             :       {
     295     2738472 :         auto * node_in = _subchannel_mesh.getPinNode(i_pin, iz - 1);
     296     2738472 :         auto * node_out = _subchannel_mesh.getPinNode(i_pin, iz);
     297     2738472 :         heat_rate_out += factor * (*_q_prime_soln)(node_out);
     298     2738472 :         heat_rate_in += factor * (*_q_prime_soln)(node_in);
     299             :       }
     300     1020936 :       return (heat_rate_in + heat_rate_out) * dz / 2.0;
     301             :     }
     302             :     else
     303             :     {
     304      889716 :       auto * node_in = _subchannel_mesh.getChannelNode(i_ch, iz - 1);
     305      889716 :       auto * node_out = _subchannel_mesh.getChannelNode(i_ch, iz);
     306      889716 :       return ((*_q_prime_soln)(node_out) + (*_q_prime_soln)(node_in)) * dz / 2.0;
     307             :     }
     308             :   }
     309             :   else
     310             :     return 0.0;
     311             : }
     312             : 
     313             : Real
     314      279600 : TriSubChannel1PhaseProblem::getSubChannelPeripheralDuctWidth(unsigned int i_ch) const
     315             : {
     316      279600 :   auto subch_type = _subchannel_mesh.getSubchannelType(i_ch);
     317      279600 :   if (subch_type == EChannelType::EDGE || subch_type == EChannelType::CORNER)
     318             :   {
     319      279600 :     auto width = _subchannel_mesh.getPitch();
     320      279600 :     if (subch_type == EChannelType::CORNER)
     321       57600 :       width = 2.0 / std::sqrt(3.0) *
     322       57600 :               (_subchannel_mesh.getPinDiameter() / 2.0 + _tri_sch_mesh.getDuctToPinGap());
     323      279600 :     return width;
     324             :   }
     325             :   else
     326           0 :     mooseError("Channel is not a perimetric subchannel ");
     327             : }
     328             : 
     329             : void
     330        1581 : TriSubChannel1PhaseProblem::computeh(int iblock)
     331             : {
     332        1581 :   unsigned int last_node = (iblock + 1) * _block_size;
     333        1581 :   unsigned int first_node = iblock * _block_size + 1;
     334        1581 :   const Real & wire_lead_length = _tri_sch_mesh.getWireLeadLength();
     335             :   const Real & wire_diameter = _tri_sch_mesh.getWireDiameter();
     336        1581 :   const Real & pitch = _subchannel_mesh.getPitch();
     337        1581 :   const Real & pin_diameter = _subchannel_mesh.getPinDiameter();
     338             : 
     339        1581 :   if (iblock == 0)
     340             :   {
     341      115203 :     for (unsigned int i_ch = 0; i_ch < _n_channels; i_ch++)
     342             :     {
     343      113622 :       auto * node = _subchannel_mesh.getChannelNode(i_ch, 0);
     344      113622 :       auto h_out = _fp->h_from_p_T((*_P_soln)(node) + _P_out, (*_T_soln)(node));
     345      113622 :       if (h_out < 0)
     346             :       {
     347           0 :         mooseError(
     348           0 :             name(), " : Calculation of negative Enthalpy h_out = : ", h_out, " Axial Level= : ", 0);
     349             :       }
     350      113622 :       _h_soln->set(node, h_out);
     351             :     }
     352             :   }
     353             : 
     354        1581 :   if (!_implicit_bool)
     355             :   {
     356          90 :     for (unsigned int iz = first_node; iz < last_node + 1; iz++)
     357             :     {
     358          75 :       auto z_grid = _subchannel_mesh.getZGrid();
     359          75 :       auto dz = z_grid[iz] - z_grid[iz - 1];
     360             :       // Calculation of average mass flux of all periphery subchannels
     361             :       Real edge_flux_ave = 0.0;
     362             :       Real mdot_sum = 0.0;
     363             :       Real si_sum = 0.0;
     364        3225 :       for (unsigned int i_ch = 0; i_ch < _n_channels; i_ch++)
     365             :       {
     366        3150 :         auto subch_type = _subchannel_mesh.getSubchannelType(i_ch);
     367        3150 :         if (subch_type == EChannelType::EDGE || subch_type == EChannelType::CORNER)
     368             :         {
     369        1350 :           auto * node_in = _subchannel_mesh.getChannelNode(i_ch, iz - 1);
     370        1350 :           auto Si = (*_S_flow_soln)(node_in);
     371        1350 :           auto mdot_in = (*_mdot_soln)(node_in);
     372        1350 :           mdot_sum = mdot_sum + mdot_in;
     373        1350 :           si_sum = si_sum + Si;
     374             :         }
     375             :       }
     376          75 :       edge_flux_ave = mdot_sum / si_sum;
     377             : 
     378        3225 :       for (unsigned int i_ch = 0; i_ch < _n_channels; i_ch++)
     379             :       {
     380        3150 :         auto * node_in = _subchannel_mesh.getChannelNode(i_ch, iz - 1);
     381        3150 :         auto * node_out = _subchannel_mesh.getChannelNode(i_ch, iz);
     382        3150 :         auto mdot_in = (*_mdot_soln)(node_in);
     383        3150 :         auto h_in = (*_h_soln)(node_in); // J/kg
     384        3150 :         auto volume = dz * (*_S_flow_soln)(node_in);
     385        3150 :         auto mdot_out = (*_mdot_soln)(node_out);
     386        3150 :         auto h_out = 0.0;
     387             :         Real sumWijh = 0.0;
     388             :         Real sumWijPrimeDhij = 0.0;
     389             :         Real sweep_enthalpy = 0.0;
     390             :         Real e_cond = 0.0;
     391             : 
     392             :         // Calculate added enthalpy from heatflux (Pin, Duct)
     393        3150 :         Real added_enthalpy = computeAddedHeatPin(i_ch, iz);
     394        3150 :         added_enthalpy += computeAddedHeatDuct(i_ch, iz);
     395             : 
     396             :         // Calculate net sum of enthalpy into/out-of channel i from channels j around i
     397             :         // (Turbulent diffusion, Diversion Crossflow, Sweep flow Enthalpy, Radial heat conduction)
     398             :         unsigned int counter = 0;
     399       12150 :         for (auto i_gap : _subchannel_mesh.getChannelGaps(i_ch))
     400             :         {
     401        9000 :           auto chans = _subchannel_mesh.getGapChannels(i_gap);
     402        9000 :           auto gap = _subchannel_mesh.getGapWidth(iz, i_gap);
     403        9000 :           auto Sij = dz * gap;
     404             :           unsigned int ii_ch = chans.first;  // the first subchannel next to gap i_gap
     405             :           unsigned int jj_ch = chans.second; // the second subchannel next to gap i_gap
     406        9000 :           auto * node_in_i = _subchannel_mesh.getChannelNode(ii_ch, iz - 1);
     407        9000 :           auto * node_in_j = _subchannel_mesh.getChannelNode(jj_ch, iz - 1);
     408        9000 :           auto subch_type_i = _subchannel_mesh.getSubchannelType(ii_ch);
     409        9000 :           auto subch_type_j = _subchannel_mesh.getSubchannelType(jj_ch);
     410             :           // Define donor enthalpy
     411             :           auto h_star = 0.0;
     412        9000 :           if (_Wij(i_gap, iz) > 0.0)
     413        7650 :             h_star = (*_h_soln)(node_in_i);
     414        1350 :           else if (_Wij(i_gap, iz) < 0.0)
     415        1350 :             h_star = (*_h_soln)(node_in_j);
     416             :           // Diversion crossflow
     417             :           // take care of the sign by applying the map, use donor cell
     418        9000 :           sumWijh += _subchannel_mesh.getCrossflowSign(i_ch, counter) * _Wij(i_gap, iz) * h_star;
     419        9000 :           counter++;
     420             :           // SWEEP FLOW is calculated if i_gap is located in the periphery
     421             :           // and we have a wire-wrap (if i_gap is in the periphery then i_ch is in the periphery)
     422             :           // There are two gaps per periphery subchannel that this is true.
     423        9000 :           if ((subch_type_i == EChannelType::CORNER || subch_type_i == EChannelType::EDGE) &&
     424        2700 :               (subch_type_j == EChannelType::CORNER || subch_type_j == EChannelType::EDGE) &&
     425        2700 :               (wire_lead_length != 0) && (wire_diameter != 0))
     426             :           {
     427             :             // donor subchannel and node of sweep flow. The donor subchannel is the subchannel next
     428             :             // to i_ch that sweep flow, flows from and into i_ch
     429        2700 :             auto sweep_donor = _tri_sch_mesh.getSweepFlowChans(i_ch).first;
     430        2700 :             auto * node_sweep_donor = _subchannel_mesh.getChannelNode(sweep_donor, iz - 1);
     431             :             // if one of the neighbor subchannels of the periphery gap is the donor subchannel
     432             :             //(the other would be the i_ch) sweep enthalpy flows into i_ch
     433        2700 :             if ((ii_ch == sweep_donor) || (jj_ch == sweep_donor))
     434             :             {
     435        1350 :               sweep_enthalpy += computeSweepFlowMixingParameter(i_gap, iz) * edge_flux_ave * Sij *
     436        1350 :                                 (*_h_soln)(node_sweep_donor);
     437             :             }
     438             :             // else sweep enthalpy flows out of i_ch
     439             :             else
     440             :             {
     441        1350 :               sweep_enthalpy -= computeSweepFlowMixingParameter(i_gap, iz) * edge_flux_ave * Sij *
     442        1350 :                                 (*_h_soln)(node_in);
     443             :             }
     444             :           }
     445             :           // Inner gap
     446             :           // Turbulent Diffusion
     447             :           else
     448             :           {
     449        6300 :             sumWijPrimeDhij +=
     450        6300 :                 _WijPrime(i_gap, iz) * (2 * h_in - (*_h_soln)(node_in_j) - (*_h_soln)(node_in_i));
     451             :           }
     452             : 
     453             :           // compute the radial heat conduction through the gaps
     454             :           Real dist_ij = pitch;
     455             : 
     456        9000 :           if (subch_type_i == EChannelType::EDGE && subch_type_j == EChannelType::EDGE)
     457             :           {
     458         900 :             dist_ij = pitch;
     459             :           }
     460        8100 :           else if ((subch_type_i == EChannelType::CORNER && subch_type_j == EChannelType::EDGE) ||
     461        7950 :                    (subch_type_i == EChannelType::EDGE && subch_type_j == EChannelType::CORNER))
     462             :           {
     463        1800 :             dist_ij = pitch;
     464             :           }
     465             :           else
     466             :           {
     467        6300 :             dist_ij = pitch / std::sqrt(3);
     468             :           }
     469             : 
     470        9000 :           auto thcon_i = _fp->k_from_p_T((*_P_soln)(node_in_i) + _P_out, (*_T_soln)(node_in_i));
     471        9000 :           auto thcon_j = _fp->k_from_p_T((*_P_soln)(node_in_j) + _P_out, (*_T_soln)(node_in_j));
     472             :           auto shape_factor =
     473        9000 :               0.66 * (pitch / pin_diameter) *
     474        9000 :               std::pow((_subchannel_mesh.getGapWidth(iz, i_gap) / pin_diameter), -0.3);
     475        9000 :           if (ii_ch == i_ch)
     476             :           {
     477        4500 :             e_cond += 0.5 * (thcon_i + thcon_j) * Sij * shape_factor *
     478        4500 :                       ((*_T_soln)(node_in_j) - (*_T_soln)(node_in_i)) / dist_ij;
     479             :           }
     480             :           else
     481             :           {
     482        4500 :             e_cond += -0.5 * (thcon_i + thcon_j) * Sij * shape_factor *
     483        4500 :                       ((*_T_soln)(node_in_j) - (*_T_soln)(node_in_i)) / dist_ij;
     484             :           }
     485             :         }
     486             : 
     487             :         // compute the axial heat conduction between current and lower axial node
     488        3150 :         auto * node_in_i = _subchannel_mesh.getChannelNode(i_ch, iz);
     489        3150 :         auto * node_in_j = _subchannel_mesh.getChannelNode(i_ch, iz - 1);
     490        3150 :         auto thcon_i = _fp->k_from_p_T((*_P_soln)(node_in_i) + _P_out, (*_T_soln)(node_in_i));
     491        3150 :         auto thcon_j = _fp->k_from_p_T((*_P_soln)(node_in_j) + _P_out, (*_T_soln)(node_in_j));
     492        3150 :         auto Si = (*_S_flow_soln)(node_in_i);
     493        3150 :         auto dist_ij = z_grid[iz] - z_grid[iz - 1];
     494             : 
     495        3150 :         e_cond += 0.5 * (thcon_i + thcon_j) * Si * ((*_T_soln)(node_in_j) - (*_T_soln)(node_in_i)) /
     496             :                   dist_ij;
     497             : 
     498        3150 :         unsigned int nz = _subchannel_mesh.getNumOfAxialCells();
     499             :         // compute the axial heat conduction between current and upper axial node
     500        3150 :         if (iz < nz)
     501             :         {
     502        2520 :           auto * node_in_i = _subchannel_mesh.getChannelNode(i_ch, iz);
     503        2520 :           auto * node_in_j = _subchannel_mesh.getChannelNode(i_ch, iz + 1);
     504        2520 :           auto thcon_i = _fp->k_from_p_T((*_P_soln)(node_in_i) + _P_out, (*_T_soln)(node_in_i));
     505        2520 :           auto thcon_j = _fp->k_from_p_T((*_P_soln)(node_in_j) + _P_out, (*_T_soln)(node_in_j));
     506        2520 :           auto Si = (*_S_flow_soln)(node_in_i);
     507        2520 :           auto dist_ij = z_grid[iz + 1] - z_grid[iz];
     508        2520 :           e_cond += 0.5 * (thcon_i + thcon_j) * Si *
     509        2520 :                     ((*_T_soln)(node_in_j) - (*_T_soln)(node_in_i)) / dist_ij;
     510             :         }
     511             : 
     512             :         // end of radial heat conduction calc.
     513        3150 :         h_out =
     514        6300 :             (mdot_in * h_in - sumWijh - sumWijPrimeDhij + added_enthalpy + e_cond + sweep_enthalpy +
     515        3150 :              _TR * _rho_soln->old(node_out) * _h_soln->old(node_out) * volume / _dt) /
     516        3150 :             (mdot_out + _TR * (*_rho_soln)(node_out)*volume / _dt);
     517        3150 :         if (h_out < 0)
     518             :         {
     519           0 :           mooseError(name(),
     520             :                      " : Calculation of negative Enthalpy h_out = : ",
     521             :                      h_out,
     522             :                      " Axial Level= : ",
     523             :                      iz);
     524             :         }
     525        3150 :         _h_soln->set(node_out, h_out); // J/kg
     526             :       }
     527          75 :     }
     528             :   }
     529             :   else
     530             :   {
     531        1566 :     LibmeshPetscCall(MatZeroEntries(_hc_time_derivative_mat));
     532        1566 :     LibmeshPetscCall(MatZeroEntries(_hc_advective_derivative_mat));
     533        1566 :     LibmeshPetscCall(MatZeroEntries(_hc_cross_derivative_mat));
     534        1566 :     LibmeshPetscCall(MatZeroEntries(_hc_axial_heat_conduction_mat));
     535        1566 :     LibmeshPetscCall(MatZeroEntries(_hc_radial_heat_conduction_mat));
     536        1566 :     LibmeshPetscCall(MatZeroEntries(_hc_sweep_enthalpy_mat));
     537             : 
     538        1566 :     LibmeshPetscCall(VecZeroEntries(_hc_time_derivative_rhs));
     539        1566 :     LibmeshPetscCall(VecZeroEntries(_hc_advective_derivative_rhs));
     540        1566 :     LibmeshPetscCall(VecZeroEntries(_hc_cross_derivative_rhs));
     541        1566 :     LibmeshPetscCall(VecZeroEntries(_hc_added_heat_rhs));
     542        1566 :     LibmeshPetscCall(VecZeroEntries(_hc_axial_heat_conduction_rhs));
     543        1566 :     LibmeshPetscCall(VecZeroEntries(_hc_radial_heat_conduction_rhs));
     544        1566 :     LibmeshPetscCall(VecZeroEntries(_hc_sweep_enthalpy_rhs));
     545             : 
     546        1566 :     LibmeshPetscCall(MatZeroEntries(_hc_sys_h_mat));
     547        1566 :     LibmeshPetscCall(VecZeroEntries(_hc_sys_h_rhs));
     548             : 
     549       51606 :     for (unsigned int iz = first_node; iz < last_node + 1; iz++)
     550             :     {
     551       50040 :       auto dz = _z_grid[iz] - _z_grid[iz - 1];
     552       50040 :       auto pitch = _subchannel_mesh.getPitch();
     553       50040 :       auto pin_diameter = _subchannel_mesh.getPinDiameter();
     554       50040 :       auto iz_ind = iz - first_node;
     555             : 
     556     3257400 :       for (unsigned int i_ch = 0; i_ch < _n_channels; i_ch++)
     557             :       {
     558     3207360 :         auto * node_in = _subchannel_mesh.getChannelNode(i_ch, iz - 1);
     559     3207360 :         auto * node_out = _subchannel_mesh.getChannelNode(i_ch, iz);
     560     3207360 :         auto S_in = (*_S_flow_soln)(node_in);
     561     3207360 :         auto S_out = (*_S_flow_soln)(node_out);
     562     3207360 :         auto S_interp = computeInterpolatedValue(S_out, S_in, 0.5);
     563     3207360 :         auto volume = dz * S_interp;
     564             : 
     565             :         PetscScalar Pe = 0.5;
     566     3207360 :         if (_interpolation_scheme == 3)
     567             :         {
     568             :           // Compute the Peclet number
     569      785820 :           auto w_perim_in = (*_w_perim_soln)(node_in);
     570      785820 :           auto w_perim_out = (*_w_perim_soln)(node_out);
     571      785820 :           auto w_perim_interp = this->computeInterpolatedValue(w_perim_out, w_perim_in, 0.5);
     572      785820 :           auto K_in = _fp->k_from_p_T((*_P_soln)(node_in) + _P_out, (*_T_soln)(node_in));
     573      785820 :           auto K_out = _fp->k_from_p_T((*_P_soln)(node_out) + _P_out, (*_T_soln)(node_out));
     574      785820 :           auto K = this->computeInterpolatedValue(K_out, K_in, 0.5);
     575      785820 :           auto cp_in = _fp->cp_from_p_T((*_P_soln)(node_in) + _P_out, (*_T_soln)(node_in));
     576      785820 :           auto cp_out = _fp->cp_from_p_T((*_P_soln)(node_out) + _P_out, (*_T_soln)(node_out));
     577      785820 :           auto cp = this->computeInterpolatedValue(cp_out, cp_in, 0.5);
     578             :           auto mdot_loc =
     579      785820 :               this->computeInterpolatedValue((*_mdot_soln)(node_out), (*_mdot_soln)(node_in), 0.5);
     580             :           // hydraulic diameter in the i direction
     581      785820 :           auto Dh_i = 4.0 * S_interp / w_perim_interp;
     582      785820 :           Pe = mdot_loc * Dh_i * cp / (K * S_interp) * (mdot_loc / std::abs(mdot_loc));
     583             :         }
     584     3207360 :         auto alpha = computeInterpolationCoefficients(Pe);
     585             : 
     586             :         // Time derivative term
     587     3207360 :         if (iz == first_node)
     588             :         {
     589             :           PetscScalar value_vec_tt =
     590      112992 :               -1.0 * _TR * alpha * (*_rho_soln)(node_in) * (*_h_soln)(node_in)*volume / _dt;
     591      112992 :           PetscInt row_vec_tt = i_ch + _n_channels * iz_ind;
     592      112992 :           LibmeshPetscCall(
     593             :               VecSetValues(_hc_time_derivative_rhs, 1, &row_vec_tt, &value_vec_tt, ADD_VALUES));
     594             :         }
     595             :         else
     596             :         {
     597     3094368 :           PetscInt row_tt = i_ch + _n_channels * iz_ind;
     598     3094368 :           PetscInt col_tt = i_ch + _n_channels * (iz_ind - 1);
     599     3094368 :           PetscScalar value_tt = _TR * alpha * (*_rho_soln)(node_in)*volume / _dt;
     600     3094368 :           LibmeshPetscCall(MatSetValues(
     601             :               _hc_time_derivative_mat, 1, &row_tt, 1, &col_tt, &value_tt, INSERT_VALUES));
     602             :         }
     603             : 
     604             :         // Adding diagonal elements
     605     3207360 :         PetscInt row_tt = i_ch + _n_channels * iz_ind;
     606     3207360 :         PetscInt col_tt = i_ch + _n_channels * iz_ind;
     607     3207360 :         PetscScalar value_tt = _TR * (1.0 - alpha) * (*_rho_soln)(node_out)*volume / _dt;
     608     3207360 :         LibmeshPetscCall(MatSetValues(
     609             :             _hc_time_derivative_mat, 1, &row_tt, 1, &col_tt, &value_tt, INSERT_VALUES));
     610             : 
     611             :         // Adding RHS elements
     612             :         PetscScalar rho_old_interp =
     613     3207360 :             computeInterpolatedValue(_rho_soln->old(node_out), _rho_soln->old(node_in), Pe);
     614             :         PetscScalar h_old_interp =
     615     3207360 :             computeInterpolatedValue(_h_soln->old(node_out), _h_soln->old(node_in), Pe);
     616     3207360 :         PetscScalar value_vec_tt = _TR * rho_old_interp * h_old_interp * volume / _dt;
     617     3207360 :         PetscInt row_vec_tt = i_ch + _n_channels * iz_ind;
     618     3207360 :         LibmeshPetscCall(
     619             :             VecSetValues(_hc_time_derivative_rhs, 1, &row_vec_tt, &value_vec_tt, ADD_VALUES));
     620             : 
     621             :         // Advective derivative term
     622     3207360 :         if (iz == first_node)
     623             :         {
     624      112992 :           PetscInt row_at = i_ch + _n_channels * iz_ind;
     625      112992 :           PetscScalar value_at = alpha * (*_mdot_soln)(node_in) * (*_h_soln)(node_in);
     626      112992 :           LibmeshPetscCall(
     627             :               VecSetValues(_hc_advective_derivative_rhs, 1, &row_at, &value_at, ADD_VALUES));
     628             : 
     629      112992 :           value_at = alpha * (*_mdot_soln)(node_out) - (1 - alpha) * (*_mdot_soln)(node_in);
     630      112992 :           PetscInt col_at = i_ch + _n_channels * iz_ind;
     631      112992 :           LibmeshPetscCall(MatSetValues(
     632             :               _hc_advective_derivative_mat, 1, &row_at, 1, &col_at, &value_at, ADD_VALUES));
     633             : 
     634      112992 :           value_at = (1 - alpha) * (*_mdot_soln)(node_out);
     635      112992 :           col_at = i_ch + _n_channels * (iz_ind + 1);
     636      112992 :           LibmeshPetscCall(MatSetValues(
     637             :               _hc_advective_derivative_mat, 1, &row_at, 1, &col_at, &value_at, ADD_VALUES));
     638             :         }
     639     3094368 :         else if (iz == last_node)
     640             :         {
     641      112992 :           PetscInt row_at = i_ch + _n_channels * iz_ind;
     642      112992 :           PetscScalar value_at = 1.0 * (*_mdot_soln)(node_out);
     643      112992 :           PetscInt col_at = i_ch + _n_channels * iz_ind;
     644      112992 :           LibmeshPetscCall(MatSetValues(
     645             :               _hc_advective_derivative_mat, 1, &row_at, 1, &col_at, &value_at, ADD_VALUES));
     646             : 
     647      112992 :           value_at = -1.0 * (*_mdot_soln)(node_in);
     648      112992 :           col_at = i_ch + _n_channels * (iz_ind - 1);
     649      112992 :           LibmeshPetscCall(MatSetValues(
     650             :               _hc_advective_derivative_mat, 1, &row_at, 1, &col_at, &value_at, ADD_VALUES));
     651             :         }
     652             :         else
     653             :         {
     654     2981376 :           PetscInt row_at = i_ch + _n_channels * iz_ind;
     655             :           PetscInt col_at;
     656             : 
     657     2981376 :           PetscScalar value_at = -alpha * (*_mdot_soln)(node_in);
     658     2981376 :           col_at = i_ch + _n_channels * (iz_ind - 1);
     659     2981376 :           LibmeshPetscCall(MatSetValues(
     660             :               _hc_advective_derivative_mat, 1, &row_at, 1, &col_at, &value_at, ADD_VALUES));
     661             : 
     662     2981376 :           value_at = alpha * (*_mdot_soln)(node_out) - (1 - alpha) * (*_mdot_soln)(node_in);
     663     2981376 :           col_at = i_ch + _n_channels * iz_ind;
     664     2981376 :           LibmeshPetscCall(MatSetValues(
     665             :               _hc_advective_derivative_mat, 1, &row_at, 1, &col_at, &value_at, ADD_VALUES));
     666             : 
     667     2981376 :           value_at = (1 - alpha) * (*_mdot_soln)(node_out);
     668     2981376 :           col_at = i_ch + _n_channels * (iz_ind + 1);
     669     2981376 :           LibmeshPetscCall(MatSetValues(
     670             :               _hc_advective_derivative_mat, 1, &row_at, 1, &col_at, &value_at, ADD_VALUES));
     671             :         }
     672             : 
     673             :         // Axial heat conduction
     674     3207360 :         auto * node_center = _subchannel_mesh.getChannelNode(i_ch, iz);
     675     3207360 :         auto K_center = _fp->k_from_p_T((*_P_soln)(node_center) + _P_out, (*_T_soln)(node_center));
     676             :         auto cp_center =
     677     3207360 :             _fp->cp_from_p_T((*_P_soln)(node_center) + _P_out, (*_T_soln)(node_center));
     678     3207360 :         auto diff_center = K_center / (cp_center + 1e-15);
     679             : 
     680     3207360 :         if (iz == first_node)
     681             :         {
     682      112992 :           auto * node_top = _subchannel_mesh.getChannelNode(i_ch, iz + 1);
     683      112992 :           auto * node_bottom = _subchannel_mesh.getChannelNode(i_ch, iz - 1);
     684             :           auto K_bottom =
     685      112992 :               _fp->k_from_p_T((*_P_soln)(node_bottom) + _P_out, (*_T_soln)(node_bottom));
     686      112992 :           auto K_top = _fp->k_from_p_T((*_P_soln)(node_top) + _P_out, (*_T_soln)(node_top));
     687             :           auto cp_bottom =
     688      112992 :               _fp->cp_from_p_T((*_P_soln)(node_bottom) + _P_out, (*_T_soln)(node_bottom));
     689      112992 :           auto cp_top = _fp->cp_from_p_T((*_P_soln)(node_top) + _P_out, (*_T_soln)(node_top));
     690      112992 :           auto diff_bottom = K_bottom / (cp_bottom + 1e-15);
     691      112992 :           auto diff_top = K_top / (cp_top + 1e-15);
     692             : 
     693      112992 :           auto dz_up = _z_grid[iz + 1] - _z_grid[iz];
     694      112992 :           auto dz_down = _z_grid[iz] - _z_grid[iz - 1];
     695             :           auto S_up =
     696      112992 :               computeInterpolatedValue((*_S_flow_soln)(node_top), (*_S_flow_soln)(node_center));
     697             :           auto S_down =
     698      112992 :               computeInterpolatedValue((*_S_flow_soln)(node_center), (*_S_flow_soln)(node_bottom));
     699      112992 :           auto diff_up = computeInterpolatedValue(diff_top, diff_center);
     700      112992 :           auto diff_down = computeInterpolatedValue(diff_center, diff_bottom);
     701             : 
     702             :           // Diagonal  value
     703      112992 :           PetscInt row_at = i_ch + _n_channels * iz_ind;
     704      112992 :           PetscInt col_at = i_ch + _n_channels * iz_ind;
     705      112992 :           PetscScalar value_at = diff_up * S_up / dz_up + diff_down * S_down / dz_down;
     706      112992 :           LibmeshPetscCall(MatSetValues(
     707             :               _hc_axial_heat_conduction_mat, 1, &row_at, 1, &col_at, &value_at, INSERT_VALUES));
     708             : 
     709             :           // Bottom value
     710      112992 :           value_at = 1.0 * diff_down * S_down / dz_down * (*_h_soln)(node_bottom);
     711      112992 :           LibmeshPetscCall(
     712             :               VecSetValues(_hc_axial_heat_conduction_rhs, 1, &row_at, &value_at, ADD_VALUES));
     713             : 
     714             :           // Top value
     715      112992 :           col_at = i_ch + _n_channels * (iz_ind + 1);
     716      112992 :           value_at = -diff_up * S_up / dz_up;
     717      112992 :           LibmeshPetscCall(MatSetValues(
     718             :               _hc_axial_heat_conduction_mat, 1, &row_at, 1, &col_at, &value_at, INSERT_VALUES));
     719             :         }
     720     3094368 :         else if (iz == last_node)
     721             :         {
     722      112992 :           auto * node_bottom = _subchannel_mesh.getChannelNode(i_ch, iz - 1);
     723             :           auto K_bottom =
     724      112992 :               _fp->k_from_p_T((*_P_soln)(node_bottom) + _P_out, (*_T_soln)(node_bottom));
     725             :           auto cp_bottom =
     726      112992 :               _fp->cp_from_p_T((*_P_soln)(node_bottom) + _P_out, (*_T_soln)(node_bottom));
     727      112992 :           auto diff_bottom = K_bottom / (cp_bottom + 1e-15);
     728             : 
     729      112992 :           auto dz_down = _z_grid[iz] - _z_grid[iz - 1];
     730      112992 :           auto S_down = 0.5 * ((*_S_flow_soln)(node_center) + (*_S_flow_soln)(node_bottom));
     731      112992 :           auto diff_down = 0.5 * (diff_center + diff_bottom);
     732             : 
     733             :           // Diagonal  value
     734      112992 :           PetscInt row_at = i_ch + _n_channels * iz_ind;
     735      112992 :           PetscInt col_at = i_ch + _n_channels * iz_ind;
     736      112992 :           PetscScalar value_at = diff_down * S_down / dz_down;
     737      112992 :           LibmeshPetscCall(MatSetValues(
     738             :               _hc_axial_heat_conduction_mat, 1, &row_at, 1, &col_at, &value_at, INSERT_VALUES));
     739             : 
     740             :           // Bottom value
     741      112992 :           col_at = i_ch + _n_channels * (iz_ind - 1);
     742      112992 :           value_at = -diff_down * S_down / dz_down;
     743      112992 :           LibmeshPetscCall(MatSetValues(
     744             :               _hc_axial_heat_conduction_mat, 1, &row_at, 1, &col_at, &value_at, INSERT_VALUES));
     745             : 
     746             :           // Outflow derivative
     747             :           /// TODO: Current axial derivative is zero - check if outflow conditions may make a difference
     748             :           // value_at = -1.0 * (*_mdot_soln)(node_center) * (*_h_soln)(node_center);
     749             :           // VecSetValues(_hc_axial_heat_conduction_rhs, 1, &row_at, &value_at, ADD_VALUES);
     750             :         }
     751             :         else
     752             :         {
     753     2981376 :           auto * node_top = _subchannel_mesh.getChannelNode(i_ch, iz + 1);
     754     2981376 :           auto * node_bottom = _subchannel_mesh.getChannelNode(i_ch, iz - 1);
     755             :           auto K_bottom =
     756     2981376 :               _fp->k_from_p_T((*_P_soln)(node_bottom) + _P_out, (*_T_soln)(node_bottom));
     757     2981376 :           auto K_top = _fp->k_from_p_T((*_P_soln)(node_top) + _P_out, (*_T_soln)(node_top));
     758             :           auto cp_bottom =
     759     2981376 :               _fp->cp_from_p_T((*_P_soln)(node_bottom) + _P_out, (*_T_soln)(node_bottom));
     760     2981376 :           auto cp_top = _fp->cp_from_p_T((*_P_soln)(node_top) + _P_out, (*_T_soln)(node_top));
     761     2981376 :           auto diff_bottom = K_bottom / (cp_bottom + 1e-15);
     762     2981376 :           auto diff_top = K_top / (cp_top + 1e-15);
     763             : 
     764     2981376 :           auto dz_up = _z_grid[iz + 1] - _z_grid[iz];
     765     2981376 :           auto dz_down = _z_grid[iz] - _z_grid[iz - 1];
     766             :           auto S_up =
     767     2981376 :               computeInterpolatedValue((*_S_flow_soln)(node_top), (*_S_flow_soln)(node_center));
     768             :           auto S_down =
     769     2981376 :               computeInterpolatedValue((*_S_flow_soln)(node_center), (*_S_flow_soln)(node_bottom));
     770     2981376 :           auto diff_up = computeInterpolatedValue(diff_top, diff_center);
     771     2981376 :           auto diff_down = computeInterpolatedValue(diff_center, diff_bottom);
     772             : 
     773             :           // Diagonal value
     774     2981376 :           PetscInt row_at = i_ch + _n_channels * iz_ind;
     775     2981376 :           PetscInt col_at = i_ch + _n_channels * iz_ind;
     776     2981376 :           PetscScalar value_at = diff_up * S_up / dz_up + diff_down * S_down / dz_down;
     777     2981376 :           LibmeshPetscCall(MatSetValues(
     778             :               _hc_axial_heat_conduction_mat, 1, &row_at, 1, &col_at, &value_at, INSERT_VALUES));
     779             : 
     780             :           // Bottom value
     781     2981376 :           col_at = i_ch + _n_channels * (iz_ind - 1);
     782     2981376 :           value_at = -diff_down * S_down / dz_down;
     783     2981376 :           LibmeshPetscCall(MatSetValues(
     784             :               _hc_axial_heat_conduction_mat, 1, &row_at, 1, &col_at, &value_at, INSERT_VALUES));
     785             : 
     786             :           // Top value
     787     2981376 :           col_at = i_ch + _n_channels * (iz_ind + 1);
     788     2981376 :           value_at = -diff_up * S_up / dz_up;
     789     2981376 :           LibmeshPetscCall(MatSetValues(
     790             :               _hc_axial_heat_conduction_mat, 1, &row_at, 1, &col_at, &value_at, INSERT_VALUES));
     791             :         }
     792             : 
     793             :         // Radial Terms
     794             :         unsigned int counter = 0;
     795             :         unsigned int cross_index = iz;
     796             :         // Real radial_heat_conduction(0.0);
     797    12529200 :         for (auto i_gap : _subchannel_mesh.getChannelGaps(i_ch))
     798             :         {
     799     9321840 :           auto chans = _subchannel_mesh.getGapChannels(i_gap);
     800             :           unsigned int ii_ch = chans.first;
     801             :           unsigned int jj_ch = chans.second;
     802     9321840 :           auto * node_in_i = _subchannel_mesh.getChannelNode(ii_ch, iz - 1);
     803     9321840 :           auto * node_in_j = _subchannel_mesh.getChannelNode(jj_ch, iz - 1);
     804             :           PetscScalar h_star;
     805             :           // figure out donor axial velocity
     806     9321840 :           if (_Wij(i_gap, cross_index) > 0.0)
     807             :           {
     808     6566710 :             if (iz == first_node)
     809             :             {
     810      245094 :               h_star = (*_h_soln)(node_in_i);
     811      490188 :               PetscScalar value_vec_ct = -1.0 * alpha *
     812      245094 :                                          _subchannel_mesh.getCrossflowSign(i_ch, counter) *
     813      245094 :                                          _Wij(i_gap, cross_index) * h_star;
     814      245094 :               PetscInt row_vec_ct = i_ch + _n_channels * iz_ind;
     815      245094 :               LibmeshPetscCall(VecSetValues(
     816             :                   _hc_cross_derivative_rhs, 1, &row_vec_ct, &value_vec_ct, ADD_VALUES));
     817             :             }
     818             :             else
     819             :             {
     820     6321616 :               PetscScalar value_ct = alpha * _subchannel_mesh.getCrossflowSign(i_ch, counter) *
     821     6321616 :                                      _Wij(i_gap, cross_index);
     822     6321616 :               PetscInt row_ct = i_ch + _n_channels * iz_ind;
     823     6321616 :               PetscInt col_ct = ii_ch + _n_channels * (iz_ind - 1);
     824     6321616 :               LibmeshPetscCall(MatSetValues(
     825             :                   _hc_cross_derivative_mat, 1, &row_ct, 1, &col_ct, &value_ct, ADD_VALUES));
     826             :             }
     827     6566710 :             PetscScalar value_ct = (1.0 - alpha) *
     828     6566710 :                                    _subchannel_mesh.getCrossflowSign(i_ch, counter) *
     829     6566710 :                                    _Wij(i_gap, cross_index);
     830     6566710 :             PetscInt row_ct = i_ch + _n_channels * iz_ind;
     831     6566710 :             PetscInt col_ct = ii_ch + _n_channels * iz_ind;
     832     6566710 :             LibmeshPetscCall(MatSetValues(
     833             :                 _hc_cross_derivative_mat, 1, &row_ct, 1, &col_ct, &value_ct, ADD_VALUES));
     834             :           }
     835     2755130 :           else if (_Wij(i_gap, cross_index) < 0.0) // _Wij=0 operations not necessary
     836             :           {
     837     2677658 :             if (iz == first_node)
     838             :             {
     839       80754 :               h_star = (*_h_soln)(node_in_j);
     840      161508 :               PetscScalar value_vec_ct = -1.0 * alpha *
     841       80754 :                                          _subchannel_mesh.getCrossflowSign(i_ch, counter) *
     842       80754 :                                          _Wij(i_gap, cross_index) * h_star;
     843       80754 :               PetscInt row_vec_ct = i_ch + _n_channels * iz_ind;
     844       80754 :               LibmeshPetscCall(VecSetValues(
     845             :                   _hc_cross_derivative_rhs, 1, &row_vec_ct, &value_vec_ct, ADD_VALUES));
     846             :             }
     847             :             else
     848             :             {
     849     2596904 :               PetscScalar value_ct = alpha * _subchannel_mesh.getCrossflowSign(i_ch, counter) *
     850     2596904 :                                      _Wij(i_gap, cross_index);
     851     2596904 :               PetscInt row_ct = i_ch + _n_channels * iz_ind;
     852     2596904 :               PetscInt col_ct = jj_ch + _n_channels * (iz_ind - 1);
     853     2596904 :               LibmeshPetscCall(MatSetValues(
     854             :                   _hc_cross_derivative_mat, 1, &row_ct, 1, &col_ct, &value_ct, ADD_VALUES));
     855             :             }
     856     2677658 :             PetscScalar value_ct = (1.0 - alpha) *
     857     2677658 :                                    _subchannel_mesh.getCrossflowSign(i_ch, counter) *
     858     2677658 :                                    _Wij(i_gap, cross_index);
     859     2677658 :             PetscInt row_ct = i_ch + _n_channels * iz_ind;
     860     2677658 :             PetscInt col_ct = jj_ch + _n_channels * iz_ind;
     861     2677658 :             LibmeshPetscCall(MatSetValues(
     862             :                 _hc_cross_derivative_mat, 1, &row_ct, 1, &col_ct, &value_ct, ADD_VALUES));
     863             :           }
     864             : 
     865             :           // Turbulent cross flows
     866     9321840 :           if (iz == first_node)
     867             :           {
     868             :             PetscScalar value_vec_ct =
     869      329580 :                 -2.0 * alpha * (*_h_soln)(node_in)*_WijPrime(i_gap, cross_index);
     870      329580 :             value_vec_ct += alpha * (*_h_soln)(node_in_j)*_WijPrime(i_gap, cross_index);
     871      329580 :             value_vec_ct += alpha * (*_h_soln)(node_in_i)*_WijPrime(i_gap, cross_index);
     872      329580 :             PetscInt row_vec_ct = i_ch + _n_channels * iz_ind;
     873      329580 :             LibmeshPetscCall(
     874             :                 VecSetValues(_hc_cross_derivative_rhs, 1, &row_vec_ct, &value_vec_ct, ADD_VALUES));
     875             :           }
     876             :           else
     877             :           {
     878     8992260 :             PetscScalar value_center_ct = 2.0 * alpha * _WijPrime(i_gap, cross_index);
     879     8992260 :             PetscInt row_ct = i_ch + _n_channels * iz_ind;
     880     8992260 :             PetscInt col_ct = i_ch + _n_channels * (iz_ind - 1);
     881     8992260 :             LibmeshPetscCall(MatSetValues(
     882             :                 _hc_cross_derivative_mat, 1, &row_ct, 1, &col_ct, &value_center_ct, ADD_VALUES));
     883             : 
     884     8992260 :             PetscScalar value_left_ct = -1.0 * alpha * _WijPrime(i_gap, cross_index);
     885     8992260 :             row_ct = i_ch + _n_channels * iz_ind;
     886     8992260 :             col_ct = jj_ch + _n_channels * (iz_ind - 1);
     887     8992260 :             LibmeshPetscCall(MatSetValues(
     888             :                 _hc_cross_derivative_mat, 1, &row_ct, 1, &col_ct, &value_left_ct, ADD_VALUES));
     889             : 
     890     8992260 :             PetscScalar value_right_ct = -1.0 * alpha * _WijPrime(i_gap, cross_index);
     891     8992260 :             row_ct = i_ch + _n_channels * iz_ind;
     892     8992260 :             col_ct = ii_ch + _n_channels * (iz_ind - 1);
     893     8992260 :             LibmeshPetscCall(MatSetValues(
     894             :                 _hc_cross_derivative_mat, 1, &row_ct, 1, &col_ct, &value_right_ct, ADD_VALUES));
     895             :           }
     896     9321840 :           PetscScalar value_center_ct = 2.0 * (1.0 - alpha) * _WijPrime(i_gap, cross_index);
     897     9321840 :           PetscInt row_ct = i_ch + _n_channels * iz_ind;
     898     9321840 :           PetscInt col_ct = i_ch + _n_channels * iz_ind;
     899     9321840 :           LibmeshPetscCall(MatSetValues(
     900             :               _hc_cross_derivative_mat, 1, &row_ct, 1, &col_ct, &value_center_ct, ADD_VALUES));
     901             : 
     902     9321840 :           PetscScalar value_left_ct = -1.0 * (1.0 - alpha) * _WijPrime(i_gap, cross_index);
     903     9321840 :           row_ct = i_ch + _n_channels * iz_ind;
     904     9321840 :           col_ct = jj_ch + _n_channels * iz_ind;
     905     9321840 :           LibmeshPetscCall(MatSetValues(
     906             :               _hc_cross_derivative_mat, 1, &row_ct, 1, &col_ct, &value_left_ct, ADD_VALUES));
     907             : 
     908     9321840 :           PetscScalar value_right_ct = -1.0 * (1.0 - alpha) * _WijPrime(i_gap, cross_index);
     909     9321840 :           row_ct = i_ch + _n_channels * iz_ind;
     910     9321840 :           col_ct = ii_ch + _n_channels * iz_ind;
     911     9321840 :           LibmeshPetscCall(MatSetValues(
     912             :               _hc_cross_derivative_mat, 1, &row_ct, 1, &col_ct, &value_right_ct, ADD_VALUES));
     913             : 
     914             :           // Radial heat conduction
     915     9321840 :           auto subch_type_i = _subchannel_mesh.getSubchannelType(ii_ch);
     916     9321840 :           auto subch_type_j = _subchannel_mesh.getSubchannelType(jj_ch);
     917             :           Real dist_ij = pitch;
     918             : 
     919     9321840 :           if (subch_type_i == EChannelType::EDGE && subch_type_j == EChannelType::EDGE)
     920             :           {
     921             :             dist_ij = pitch;
     922             :           }
     923     8401200 :           else if ((subch_type_i == EChannelType::CORNER && subch_type_j == EChannelType::EDGE) ||
     924     8301120 :                    (subch_type_i == EChannelType::EDGE && subch_type_j == EChannelType::CORNER))
     925             :           {
     926             :             dist_ij = pitch;
     927             :           }
     928             :           else
     929             :           {
     930     7200240 :             dist_ij = pitch / std::sqrt(3);
     931             :           }
     932             : 
     933     9321840 :           auto Sij = dz * _subchannel_mesh.getGapWidth(iz, i_gap);
     934     9321840 :           auto K_i = _fp->k_from_p_T((*_P_soln)(node_in_i) + _P_out, (*_T_soln)(node_in_i));
     935     9321840 :           auto K_j = _fp->k_from_p_T((*_P_soln)(node_in_j) + _P_out, (*_T_soln)(node_in_j));
     936     9321840 :           auto cp_i = _fp->cp_from_p_T((*_P_soln)(node_in_i) + _P_out, (*_T_soln)(node_in_i));
     937     9321840 :           auto cp_j = _fp->cp_from_p_T((*_P_soln)(node_in_j) + _P_out, (*_T_soln)(node_in_j));
     938     9321840 :           auto A_i = K_i / cp_i;
     939     9321840 :           auto A_j = K_j / cp_j;
     940     9321840 :           auto harm_A = 2.0 * A_i * A_j / (A_i + A_j);
     941             :           auto shape_factor =
     942     9321840 :               0.66 * (pitch / pin_diameter) *
     943     9321840 :               std::pow((_subchannel_mesh.getGapWidth(iz, i_gap) / pin_diameter), -0.3);
     944             :           // auto base_value =  0.5 * (A_i + A_j) * Sij * shape_factor / dist_ij;
     945     9321840 :           auto base_value = harm_A * shape_factor * Sij / dist_ij;
     946     9321840 :           auto neg_base_value = -1.0 * base_value;
     947             : 
     948     9321840 :           row_ct = ii_ch + _n_channels * iz_ind;
     949     9321840 :           col_ct = ii_ch + _n_channels * iz_ind;
     950     9321840 :           LibmeshPetscCall(MatSetValues(
     951             :               _hc_radial_heat_conduction_mat, 1, &row_ct, 1, &col_ct, &base_value, ADD_VALUES));
     952             : 
     953     9321840 :           row_ct = jj_ch + _n_channels * iz_ind;
     954     9321840 :           col_ct = jj_ch + _n_channels * iz_ind;
     955     9321840 :           LibmeshPetscCall(MatSetValues(
     956             :               _hc_radial_heat_conduction_mat, 1, &row_ct, 1, &col_ct, &base_value, ADD_VALUES));
     957             : 
     958     9321840 :           row_ct = ii_ch + _n_channels * iz_ind;
     959     9321840 :           col_ct = jj_ch + _n_channels * iz_ind;
     960     9321840 :           LibmeshPetscCall(MatSetValues(
     961             :               _hc_radial_heat_conduction_mat, 1, &row_ct, 1, &col_ct, &neg_base_value, ADD_VALUES));
     962             : 
     963     9321840 :           row_ct = jj_ch + _n_channels * iz_ind;
     964     9321840 :           col_ct = ii_ch + _n_channels * iz_ind;
     965     9321840 :           LibmeshPetscCall(MatSetValues(
     966             :               _hc_radial_heat_conduction_mat, 1, &row_ct, 1, &col_ct, &neg_base_value, ADD_VALUES));
     967     9321840 :           counter++;
     968             :         }
     969             : 
     970             :         // Compute the sweep flow enthalpy change
     971             :         // Calculation of average mass flux of all periphery subchannels
     972             :         Real edge_flux_ave = 0.0;
     973             :         Real mdot_sum = 0.0;
     974             :         Real si_sum = 0.0;
     975   272946720 :         for (unsigned int i_ch = 0; i_ch < _n_channels; i_ch++)
     976             :         {
     977   269739360 :           auto subch_type = _subchannel_mesh.getSubchannelType(i_ch);
     978   269739360 :           if (subch_type == EChannelType::EDGE || subch_type == EChannelType::CORNER)
     979             :           {
     980    77188320 :             auto * node_in = _subchannel_mesh.getChannelNode(i_ch, iz - 1);
     981    77188320 :             auto Si = (*_S_flow_soln)(node_in);
     982    77188320 :             auto mdot_in = (*_mdot_soln)(node_in);
     983    77188320 :             mdot_sum = mdot_sum + mdot_in;
     984    77188320 :             si_sum = si_sum + Si;
     985             :           }
     986             :         }
     987     3207360 :         edge_flux_ave = mdot_sum / si_sum;
     988     3207360 :         auto subch_type = _subchannel_mesh.getSubchannelType(i_ch);
     989             :         PetscScalar sweep_enthalpy = 0.0;
     990     3207360 :         if ((subch_type == EChannelType::EDGE || subch_type == EChannelType::CORNER) &&
     991     1060800 :             (wire_diameter != 0.0) && (wire_lead_length != 0.0))
     992             :         {
     993             :           auto beta_in = std::numeric_limits<double>::quiet_NaN();
     994             :           auto beta_out = std::numeric_limits<double>::quiet_NaN();
     995             :           // donor sweep channel for i_ch
     996      970800 :           auto sweep_donor = _tri_sch_mesh.getSweepFlowChans(i_ch).first;
     997      970800 :           auto * node_sweep_donor = _subchannel_mesh.getChannelNode(sweep_donor, iz - 1);
     998             :           // Calculation of turbulent mixing parameter
     999     3612960 :           for (auto i_gap : _subchannel_mesh.getChannelGaps(i_ch))
    1000             :           {
    1001     2642160 :             auto chans = _subchannel_mesh.getGapChannels(i_gap);
    1002             :             unsigned int ii_ch = chans.first;
    1003             :             unsigned int jj_ch = chans.second;
    1004     2642160 :             auto subch_type_i = _subchannel_mesh.getSubchannelType(ii_ch);
    1005     2642160 :             auto subch_type_j = _subchannel_mesh.getSubchannelType(jj_ch);
    1006     2642160 :             if ((subch_type_i == EChannelType::CORNER || subch_type_i == EChannelType::EDGE) &&
    1007     1941600 :                 (subch_type_j == EChannelType::CORNER || subch_type_j == EChannelType::EDGE))
    1008             :             {
    1009     1941600 :               if ((ii_ch == sweep_donor) || (jj_ch == sweep_donor))
    1010             :               {
    1011      970800 :                 beta_in = computeSweepFlowMixingParameter(i_gap, iz);
    1012             :               }
    1013             :               else
    1014             :               {
    1015      970800 :                 beta_out = computeSweepFlowMixingParameter(i_gap, iz);
    1016             :               }
    1017             :             }
    1018             :           }
    1019             :           // Abort execution if required values are unset
    1020             :           mooseAssert(!std::isnan(beta_in),
    1021             :                       "beta_in was not set. Check gap logic for i_ch = " + std::to_string(i_ch) +
    1022             :                           ", iz = " + std::to_string(iz));
    1023             :           mooseAssert(!std::isnan(beta_out),
    1024             :                       "beta_out was not set. Check gap logic for i_ch = " + std::to_string(i_ch) +
    1025             :                           ", iz = " + std::to_string(iz));
    1026             : 
    1027      970800 :           auto gap = _tri_sch_mesh.getDuctToPinGap();
    1028      970800 :           auto Sij = dz * gap;
    1029      970800 :           auto wsweep_in = edge_flux_ave * beta_in * Sij;
    1030      970800 :           auto wsweep_out = edge_flux_ave * beta_out * Sij;
    1031      970800 :           auto sweep_hin = (*_h_soln)(node_sweep_donor);
    1032      970800 :           auto sweep_hout = (*_h_soln)(node_in);
    1033      970800 :           sweep_enthalpy = (wsweep_in * sweep_hin - wsweep_out * sweep_hout);
    1034             : 
    1035      970800 :           if (iz == first_node)
    1036             :           {
    1037       33240 :             PetscInt row_sh = i_ch + _n_channels * iz_ind;
    1038       33240 :             PetscScalar value_hs = -sweep_enthalpy;
    1039       33240 :             LibmeshPetscCall(
    1040             :                 VecSetValues(_hc_sweep_enthalpy_rhs, 1, &row_sh, &value_hs, ADD_VALUES));
    1041             :           }
    1042             :           else
    1043             :           {
    1044             :             // coefficient of sweep_hin
    1045      937560 :             PetscInt row_sh = i_ch + _n_channels * (iz_ind - 1);
    1046      937560 :             PetscInt col_sh = i_ch + _n_channels * (iz_ind - 1);
    1047      937560 :             LibmeshPetscCall(MatSetValues(
    1048             :                 _hc_sweep_enthalpy_mat, 1, &row_sh, 1, &col_sh, &wsweep_out, ADD_VALUES));
    1049      937560 :             PetscInt col_sh_l = sweep_donor + _n_channels * (iz_ind - 1);
    1050      937560 :             PetscScalar neg_sweep_in = -1.0 * wsweep_in;
    1051             :             // coefficient of sweep_hout
    1052      937560 :             LibmeshPetscCall(MatSetValues(
    1053             :                 _hc_sweep_enthalpy_mat, 1, &row_sh, 1, &col_sh_l, &(neg_sweep_in), ADD_VALUES));
    1054             :           }
    1055             :         }
    1056             : 
    1057             :         // Add heat enthalpy from pin and/or duct
    1058     3207360 :         PetscScalar added_enthalpy = computeAddedHeatPin(i_ch, iz);
    1059     3207360 :         added_enthalpy += computeAddedHeatDuct(i_ch, iz);
    1060     3207360 :         PetscInt row_vec_ht = i_ch + _n_channels * iz_ind;
    1061     3207360 :         LibmeshPetscCall(
    1062             :             VecSetValues(_hc_added_heat_rhs, 1, &row_vec_ht, &added_enthalpy, ADD_VALUES));
    1063             :       }
    1064             :     }
    1065             :     // Assembling system
    1066        1566 :     LibmeshPetscCall(MatAssemblyBegin(_hc_time_derivative_mat, MAT_FINAL_ASSEMBLY));
    1067        1566 :     LibmeshPetscCall(MatAssemblyEnd(_hc_time_derivative_mat, MAT_FINAL_ASSEMBLY));
    1068        1566 :     LibmeshPetscCall(MatAssemblyBegin(_hc_advective_derivative_mat, MAT_FINAL_ASSEMBLY));
    1069        1566 :     LibmeshPetscCall(MatAssemblyEnd(_hc_advective_derivative_mat, MAT_FINAL_ASSEMBLY));
    1070        1566 :     LibmeshPetscCall(MatAssemblyBegin(_hc_cross_derivative_mat, MAT_FINAL_ASSEMBLY));
    1071        1566 :     LibmeshPetscCall(MatAssemblyEnd(_hc_cross_derivative_mat, MAT_FINAL_ASSEMBLY));
    1072        1566 :     LibmeshPetscCall(MatAssemblyBegin(_hc_axial_heat_conduction_mat, MAT_FINAL_ASSEMBLY));
    1073        1566 :     LibmeshPetscCall(MatAssemblyEnd(_hc_axial_heat_conduction_mat, MAT_FINAL_ASSEMBLY));
    1074        1566 :     LibmeshPetscCall(MatAssemblyBegin(_hc_radial_heat_conduction_mat, MAT_FINAL_ASSEMBLY));
    1075        1566 :     LibmeshPetscCall(MatAssemblyEnd(_hc_radial_heat_conduction_mat, MAT_FINAL_ASSEMBLY));
    1076        1566 :     LibmeshPetscCall(MatAssemblyBegin(_hc_sweep_enthalpy_mat, MAT_FINAL_ASSEMBLY));
    1077        1566 :     LibmeshPetscCall(MatAssemblyEnd(_hc_sweep_enthalpy_mat, MAT_FINAL_ASSEMBLY));
    1078        1566 :     LibmeshPetscCall(MatAssemblyBegin(_hc_sys_h_mat, MAT_FINAL_ASSEMBLY));
    1079        1566 :     LibmeshPetscCall(MatAssemblyEnd(_hc_sys_h_mat, MAT_FINAL_ASSEMBLY));
    1080             :     // Add all matrices together
    1081        1566 :     LibmeshPetscCall(
    1082             :         MatAXPY(_hc_sys_h_mat, 1.0, _hc_time_derivative_mat, DIFFERENT_NONZERO_PATTERN));
    1083        1566 :     LibmeshPetscCall(MatAssemblyBegin(_hc_sys_h_mat, MAT_FINAL_ASSEMBLY));
    1084        1566 :     LibmeshPetscCall(MatAssemblyEnd(_hc_sys_h_mat, MAT_FINAL_ASSEMBLY));
    1085        1566 :     LibmeshPetscCall(
    1086             :         MatAXPY(_hc_sys_h_mat, 1.0, _hc_advective_derivative_mat, DIFFERENT_NONZERO_PATTERN));
    1087        1566 :     LibmeshPetscCall(MatAssemblyBegin(_hc_sys_h_mat, MAT_FINAL_ASSEMBLY));
    1088        1566 :     LibmeshPetscCall(MatAssemblyEnd(_hc_sys_h_mat, MAT_FINAL_ASSEMBLY));
    1089        1566 :     LibmeshPetscCall(
    1090             :         MatAXPY(_hc_sys_h_mat, 1.0, _hc_cross_derivative_mat, DIFFERENT_NONZERO_PATTERN));
    1091        1566 :     LibmeshPetscCall(MatAssemblyBegin(_hc_sys_h_mat, MAT_FINAL_ASSEMBLY));
    1092        1566 :     LibmeshPetscCall(MatAssemblyEnd(_hc_sys_h_mat, MAT_FINAL_ASSEMBLY));
    1093        1566 :     LibmeshPetscCall(
    1094             :         MatAXPY(_hc_sys_h_mat, 1.0, _hc_axial_heat_conduction_mat, DIFFERENT_NONZERO_PATTERN));
    1095        1566 :     LibmeshPetscCall(MatAssemblyBegin(_hc_sys_h_mat, MAT_FINAL_ASSEMBLY));
    1096        1566 :     LibmeshPetscCall(MatAssemblyEnd(_hc_sys_h_mat, MAT_FINAL_ASSEMBLY));
    1097        1566 :     LibmeshPetscCall(
    1098             :         MatAXPY(_hc_sys_h_mat, 1.0, _hc_radial_heat_conduction_mat, DIFFERENT_NONZERO_PATTERN));
    1099        1566 :     LibmeshPetscCall(MatAssemblyBegin(_hc_sys_h_mat, MAT_FINAL_ASSEMBLY));
    1100        1566 :     LibmeshPetscCall(MatAssemblyEnd(_hc_sys_h_mat, MAT_FINAL_ASSEMBLY));
    1101        1566 :     LibmeshPetscCall(
    1102             :         MatAXPY(_hc_sys_h_mat, 1.0, _hc_sweep_enthalpy_mat, DIFFERENT_NONZERO_PATTERN));
    1103        1566 :     LibmeshPetscCall(MatAssemblyBegin(_hc_sys_h_mat, MAT_FINAL_ASSEMBLY));
    1104        1566 :     LibmeshPetscCall(MatAssemblyEnd(_hc_sys_h_mat, MAT_FINAL_ASSEMBLY));
    1105        1566 :     if (_verbose_subchannel)
    1106        1337 :       _console << "Block: " << iblock << " - Enthalpy conservation matrix assembled" << std::endl;
    1107             :     // RHS
    1108        1566 :     LibmeshPetscCall(VecAXPY(_hc_sys_h_rhs, 1.0, _hc_time_derivative_rhs));
    1109        1566 :     LibmeshPetscCall(VecAXPY(_hc_sys_h_rhs, 1.0, _hc_advective_derivative_rhs));
    1110        1566 :     LibmeshPetscCall(VecAXPY(_hc_sys_h_rhs, 1.0, _hc_cross_derivative_rhs));
    1111        1566 :     LibmeshPetscCall(VecAXPY(_hc_sys_h_rhs, 1.0, _hc_added_heat_rhs));
    1112        1566 :     LibmeshPetscCall(VecAXPY(_hc_sys_h_rhs, 1.0, _hc_axial_heat_conduction_rhs));
    1113        1566 :     LibmeshPetscCall(VecAXPY(_hc_sys_h_rhs, 1.0, _hc_radial_heat_conduction_rhs));
    1114        1566 :     LibmeshPetscCall(VecAXPY(_hc_sys_h_rhs, 1.0, _hc_sweep_enthalpy_rhs));
    1115             : 
    1116             :     // Use system to solve for and populate enthalpy
    1117        1566 :     LibmeshPetscCall(this->solveAndPopulateEnthalpy(
    1118             :         _hc_sys_h_mat, _hc_sys_h_rhs, first_node, last_node, "h_sys_"));
    1119             :   }
    1120        1581 : }

Generated by: LCOV version 1.14