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