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