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