https://mooseframework.inl.gov
SCMTriPowerAux.C
Go to the documentation of this file.
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 "SCMTriPowerAux.h"
11 #include "Function.h"
12 #include "TriSubChannelMesh.h"
13 #include "SCM.h"
14 
15 registerMooseObject("SubChannelApp", SCMTriPowerAux);
16 registerMooseObjectRenamed("SubChannelApp", TriPowerAux, "06/30/2025 24:00", SCMTriPowerAux);
17 
20 {
22  params.addClassDescription(
23  "Computes axial power rate (W/m) that goes into the subchannel cells "
24  "or is assigned to the fuel pins, in a triangular lattice arrangement");
25  params.addRequiredParam<PostprocessorName>(
26  "power", "The postprocessor or Real to use for the total power of the subassembly [W]");
27  params.addRequiredParam<std::string>(
28  "filename", "name of radial power profile .txt file (should be a single column) [UnitLess].");
29  params.addParam<FunctionName>("axial_heat_rate",
30  "1.0",
31  "user provided normalized function of axial heat rate [Unitless]. "
32  "The integral over pin length should equal the heated length");
33  return params;
34 }
35 
37  : AuxKernel(parameters),
38  _triMesh(SCM::getConstMesh<TriSubChannelMesh>(_mesh)),
39  _power(getPostprocessorValue("power")),
40  _numberoflines(0),
41  _filename(getParam<std::string>("filename")),
42  _axial_heat_rate(getFunction("axial_heat_rate"))
43 {
44  auto n_pins = _triMesh.getNumOfPins();
45  // Matrix sizing
46  _power_dis.resize(n_pins, 1);
47  _power_dis.setZero();
48  _pin_power_correction.resize(n_pins, 1);
49  _pin_power_correction.setOnes();
50 
51  Real vin;
52  std::ifstream inFile;
53 
54  inFile.open(_filename);
55  if (!inFile)
56  mooseError(name(), ": Unable to open file: ", _filename);
57 
58  while (inFile >> vin)
59  _numberoflines += 1;
60 
61  if (inFile.fail() && !inFile.eof())
62  mooseError(name(), ": Non numerical input at line: ", _numberoflines);
63 
64  if (_numberoflines != n_pins)
65  mooseError(name(), ": Radial profile file doesn't have correct size: ", n_pins);
66  inFile.close();
67 
68  inFile.open(_filename);
69  int i = 0;
70  while (inFile >> vin)
71  {
72  _power_dis(i, 0) = vin;
73  i++;
74  }
75  inFile.close();
76 }
77 
78 void
80 {
81  auto heated_length = _triMesh.getHeatedLength();
82  auto sum = _power_dis.sum();
83  // full (100%) power of one pin [W]
84  auto fpin_power = _power / sum;
85  // actual pin power [W]
86  _ref_power = _power_dis * fpin_power;
87  // Convert the actual pin power to a linear heat rate [W/m]
88  _ref_qprime = _ref_power / heated_length;
89 
90  auto n_pins = _triMesh.getNumOfPins();
91  auto nz = _triMesh.getNumOfAxialCells();
92  auto z_grid = _triMesh.getZGrid();
93  auto unheated_length_entry = _triMesh.getHeatedLengthEntry();
94 
95  _estimate_power.resize(n_pins, 1);
96  _estimate_power.setZero();
97  for (unsigned int iz = 1; iz < nz + 1; iz++)
98  {
99  // Compute axial location of nodes.
100  auto z2 = z_grid[iz];
101  auto z1 = z_grid[iz - 1];
102  Point p1(0, 0, z1 - unheated_length_entry);
103  Point p2(0, 0, z2 - unheated_length_entry);
104  auto heat1 = _axial_heat_rate.value(_t, p1);
105  auto heat2 = _axial_heat_rate.value(_t, p2);
106  if (MooseUtils::absoluteFuzzyGreaterThan(z2, unheated_length_entry) &&
107  MooseUtils::absoluteFuzzyLessThan(z1, unheated_length_entry + heated_length))
108  {
109  // cycle through pins
110  for (unsigned int i_pin = 0; i_pin < n_pins; i_pin++)
111  {
112  // Compute the height of this element.
113  auto dz = z2 - z1;
114 
115  // calculation of power for the first heated segment if nodes don't align
116  if (MooseUtils::absoluteFuzzyGreaterThan(z2, unheated_length_entry) &&
117  MooseUtils::absoluteFuzzyLessThan(z1, unheated_length_entry))
118  {
119  heat1 = 0.0;
120  }
121 
122  // calculation of power for the last heated segment if nodes don't align
123  if (MooseUtils::absoluteFuzzyGreaterThan(z2, unheated_length_entry + heated_length) &&
124  MooseUtils::absoluteFuzzyLessThan(z1, unheated_length_entry + heated_length))
125  {
126  heat2 = 0.0;
127  }
128  _estimate_power(i_pin) += _ref_qprime(i_pin) * (heat1 + heat2) * dz / 2.0;
129  }
130  }
131  }
132 
133  // if a Pin has zero power (_ref_qprime(i_pin) = 0) then I need to avoid dividing by zero. I
134  // divide by a wrong non-zero number which is not correct but this error doesn't mess things cause
135  // _ref_qprime(i_pin) = 0.0
136  auto total_power = 0.0;
137  for (unsigned int i_pin = 0; i_pin < n_pins; i_pin++)
138  {
139  total_power += _estimate_power(i_pin);
140  if (_estimate_power(i_pin) == 0.0)
141  _estimate_power(i_pin) = 1.0;
142  }
143  // We need to correct the linear power assigned to the nodes of each pin
144  // so that the total power calculated by the trapezoidal rule agrees with the power assigned by
145  // the user.
147  _console << "###########################################" << std::endl;
148  _console << "Total power estimation by Aux kernel before correction: " << total_power << " [W] "
149  << std::endl;
150  _console << "Aux Power correction vector :\n" << _pin_power_correction << " \n";
151 }
152 
153 Real
155 {
156  Point p = *_current_node;
157  auto heat_rate = 0.0;
158  auto heated_length = _triMesh.getHeatedLength();
159  auto unheated_length_entry = _triMesh.getHeatedLengthEntry();
160  Point p1(0, 0, unheated_length_entry);
161  Point P = p - p1;
162  auto pin_triMesh_exist = _triMesh.pinMeshExist();
163 
165  if (MooseUtils::absoluteFuzzyGreaterEqual(p(2), unheated_length_entry) &&
166  MooseUtils::absoluteFuzzyLessEqual(p(2), unheated_length_entry + heated_length))
167  {
168  if (pin_triMesh_exist)
169  {
170  // project axial heat rate on pins
171  auto i_pin = _triMesh.getPinIndexFromPoint(p);
172  return _ref_qprime(i_pin) * _pin_power_correction(i_pin) * _axial_heat_rate.value(_t, P);
173  }
174  else
175  {
176  // Determine which subchannel this point is in.
177  auto i_ch = _triMesh.getSubchannelIndexFromPoint(p);
178  auto subch_type = _triMesh.getSubchannelType(i_ch);
179  // project axial heat rate on subchannels
180  {
181  double factor;
182  switch (subch_type)
183  {
185  factor = 1.0 / 6.0;
186  break;
187  case EChannelType::EDGE:
188  factor = 1.0 / 4.0;
189  break;
191  factor = 1.0 / 6.0;
192  break;
193  default:
194  return 0.0; // handle invalid subch_type if needed
195  }
196  for (auto i_pin : _triMesh.getChannelPins(i_ch))
197  {
198  heat_rate += factor * _ref_qprime(i_pin) * _pin_power_correction(i_pin) *
200  }
201  return heat_rate;
202  }
203  }
204  }
205  else
206  return 0.0;
207 }
Eigen::MatrixXd _power_dis
matrix that holds the values of the relative pin power
virtual bool pinMeshExist() const override
Return if Pin Mesh exists or not.
virtual EChannelType getSubchannelType(unsigned int index) const override
Return the type of the subchannel for given subchannel index.
unsigned int _numberoflines
The number of lines associated with the radial power profile .txt file.
void addParam(const std::string &name, const std::initializer_list< typename T::value_type > &value, const std::string &doc_string)
virtual const std::vector< Real > & getZGrid() const
Get axial location of layers.
const Node *const & _current_node
virtual unsigned int getSubchannelIndexFromPoint(const Point &p) const override
Return a subchannel index for a given physical point p
registerMooseObjectRenamed("SubChannelApp", TriPowerAux, "06/30/2025 24:00", SCMTriPowerAux)
const Function & _axial_heat_rate
virtual Real computeValue() override
registerMooseObject("SubChannelApp", SCMTriPowerAux)
static InputParameters validParams()
virtual const std::string & name() const
void addRequiredParam(const std::string &name, const std::string &doc_string)
const TriSubChannelMesh & _triMesh
virtual const Real & getHeatedLength() const
Return heated length.
const T & getConstMesh(const MooseMesh &mesh)
function to cast const mesh
Definition: SCM.h:21
virtual void initialSetup() override
bool absoluteFuzzyLessThan(const T &var1, const T2 &var2, const T3 &tol=libMesh::TOLERANCE *libMesh::TOLERANCE)
virtual unsigned int getPinIndexFromPoint(const Point &p) const override
Return a pin index for a given physical point p
Eigen::MatrixXd _ref_qprime
Average linear heat rate over the whole pin [W/m].
Mesh class for triangular, edge and corner subchannels for hexagonal lattice fuel assemblies...
virtual const unsigned int & getNumOfAxialCells() const
Return the number of axial cells.
Sets the axial heat rate for each pin according to a radial power distribution and a user defined axi...
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
Eigen::MatrixXd _ref_power
Actual pin power [W].
bool absoluteFuzzyLessEqual(const T &var1, const T2 &var2, const T3 &tol=libMesh::TOLERANCE *libMesh::TOLERANCE)
virtual const unsigned int & getNumOfPins() const override
Return the number of pins.
std::string _filename
The name of the radial power profile file.
const PostprocessorValue & _power
The total power of the assembly.
bool absoluteFuzzyGreaterEqual(const T &var1, const T2 &var2, const T3 &tol=libMesh::TOLERANCE *libMesh::TOLERANCE)
void mooseError(Args &&... args) const
void addClassDescription(const std::string &doc_string)
static InputParameters validParams()
const ConsoleStream _console
virtual Real value(Real t, const Point &p) const
virtual const std::vector< unsigned int > & getChannelPins(unsigned int i_chan) const override
Return a vector of pin indices for a given channel index.
Eigen::MatrixXd _pin_power_correction
The correction that will be applied to the estimated calculation [unitless].
SCMTriPowerAux(const InputParameters &params)
Definition: SCM.h:16
bool absoluteFuzzyGreaterThan(const T &var1, const T2 &var2, const T3 &tol=libMesh::TOLERANCE *libMesh::TOLERANCE)
virtual const Real & getHeatedLengthEntry() const
Return unheated length at entry.
Eigen::MatrixXd _estimate_power
Matrix which will hold the total estimated power of each pin [W].