https://mooseframework.inl.gov
Loading...
Searching...
No Matches
SCMQuadPowerAux.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 "SCMQuadPowerAux.h"
11#include "Function.h"
12#include "QuadSubChannelMesh.h"
13#include "SCM.h"
14
16
19{
22 "Computes axial power rate (W/m) assigned to the fuel pins in a quadrilateral lattice "
23 "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 : AuxKernel(parameters),
37 _quadMesh(SCM::getConstMesh<QuadSubChannelMesh>(_mesh)),
38 _power(getPostprocessorValue("power")),
39 _numberoflines(0),
40 _filename(getParam<std::string>("filename")),
41 _axial_heat_rate(getFunction("axial_heat_rate"))
42{
43 if (processor_id() > 0)
44 return;
45
47 mooseError(name(), ": This object requires a pin mesh.");
48
49 auto n_pins = _quadMesh.getNumOfPins();
50 // Matrix sizing
51 _power_dis.resize(n_pins, 1);
52 _power_dis.setZero();
53 _pin_power_correction.resize(n_pins, 1);
54 _pin_power_correction.setOnes();
55
56 Real vin;
57 std::ifstream inFile;
58
59 inFile.open(_filename);
60 if (!inFile)
61 mooseError(name(), "unable to open file : ", _filename);
62
63 while (inFile >> vin)
64 _numberoflines += 1;
65
66 if (inFile.fail() && !inFile.eof())
67 mooseError(name(), " non numerical input at line : ", _numberoflines);
68
69 if (_numberoflines != n_pins)
70 mooseError(name(), " Radial profile file doesn't have correct size : ", n_pins);
71 inFile.close();
72
73 inFile.open(_filename);
74 int i(0);
75 while (inFile >> vin)
76 {
77 _power_dis(i, 0) = vin;
78 i++;
79 }
80 inFile.close();
81 _console << " Power distribution matrix :\n" << _power_dis << " \n";
82}
83
84void
86{
87 if (processor_id() > 0)
88 return;
89
90 auto n_pins = _quadMesh.getNumOfPins();
91 auto nz = _quadMesh.getNumOfAxialCells();
92 auto z_grid = _quadMesh.getZGrid();
93 auto heated_length = _quadMesh.getHeatedLength();
94 auto unheated_length_entry = _quadMesh.getHeatedLengthEntry();
95 auto sum = _power_dis.sum();
96
97 // full (100%) power of one pin [W]
98 auto fpin_power = _power / sum;
99 // actual pin power [W]
100 _ref_power = _power_dis * fpin_power;
101 // Convert the actual pin power to a linear heat rate [W/m]
102 _ref_qprime = _ref_power / heated_length;
103
104 _estimate_power.resize(n_pins, 1);
105 _estimate_power.setZero();
106 for (unsigned int iz = 1; iz < nz + 1; iz++)
107 {
108 // Compute axial location of nodes.
109 auto z2 = z_grid[iz];
110 auto z1 = z_grid[iz - 1];
111 Point p1(0, 0, z1 - unheated_length_entry);
112 Point p2(0, 0, z2 - unheated_length_entry);
113 auto heat1 = _axial_heat_rate.value(_t, p1);
114 auto heat2 = _axial_heat_rate.value(_t, p2);
115 if (MooseUtils::absoluteFuzzyGreaterThan(z2, unheated_length_entry) &&
116 MooseUtils::absoluteFuzzyLessThan(z1, unheated_length_entry + heated_length))
117 {
118 // cycle through pins
119 for (unsigned int i_pin = 0; i_pin < n_pins; i_pin++)
120 {
121 // Compute the height of this element.
122 auto dz = z2 - z1;
123
124 // calculation of power for the first heated segment if nodes don't align
125 if (MooseUtils::absoluteFuzzyGreaterThan(z2, unheated_length_entry) &&
126 MooseUtils::absoluteFuzzyLessThan(z1, unheated_length_entry))
127 {
128 heat1 = 0.0;
129 }
130
131 // calculation of power for the last heated segment if nodes don't align
132 if (MooseUtils::absoluteFuzzyGreaterThan(z2, unheated_length_entry + heated_length) &&
133 MooseUtils::absoluteFuzzyLessThan(z1, unheated_length_entry + heated_length))
134 {
135 heat2 = 0.0;
136 }
137
138 _estimate_power(i_pin) += _ref_qprime(i_pin) * (heat1 + heat2) * dz / 2.0;
139 }
140 }
141 }
142
143 // if a Pin has zero power (_ref_qprime(i_pin) = 0) then I need to avoid dividing by zero. I
144 // divide by a wrong non-zero number which is not correct but this error doesn't mess things
145 // cause _ref_qprime(i_pin) = 0.0
146 auto total_power = 0.0;
147 for (unsigned int i_pin = 0; i_pin < n_pins; i_pin++)
148 {
149 total_power += _estimate_power(i_pin);
150 if (_estimate_power(i_pin) == 0.0)
151 _estimate_power(i_pin) = 1.0;
152 }
153 // We need to correct the linear power assigned to the nodes of each pin
154 // so that the total power calculated by the trapezoidal rule agrees with the power assigned
155 // by the user.
157 _console << "###########################################" << std::endl;
158 _console << "Total power estimation by Aux kernel before correction: " << total_power << " [W] "
159 << std::endl;
160 _console << "Aux Power correction vector :\n" << _pin_power_correction << " \n";
161}
162
163Real
165{
166 Point p = *_current_node;
167 auto heated_length = _quadMesh.getHeatedLength();
168 auto unheated_length_entry = _quadMesh.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 = _quadMesh.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}
const Real p
registerMooseObject("SubChannelApp", SCMQuadPowerAux)
const Node *const & _current_node
static InputParameters validParams()
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
Creates the mesh of subchannels in a quadrilateral lattice.
unsigned int getPinIndexFromPoint(const Point &p) const override
Return a pin index for a given physical point p
unsigned int getNumOfPins() const override
Return the number of pins.
Sets the axial heat rate for each pin according to a radial power distribution and a user defined axi...
Eigen::MatrixXd _estimate_power
Matrix which will hold the total estimated power of each pin [W].
virtual void initialSetup() override
SCMQuadPowerAux(const InputParameters &params)
Eigen::MatrixXd _ref_power
Actual pin power [W].
const PostprocessorValue & _power
The total power of the assembly.
virtual Real computeValue() override
Eigen::MatrixXd _power_dis
Matrix that holds the relative pin power.
const QuadSubChannelMesh & _quadMesh
std::string _filename
The name of the radial power profile file.
unsigned int _numberoflines
The number of lines associated with the radial power profile .txt file.
static InputParameters validParams()
Eigen::MatrixXd _ref_qprime
Average linear heat rate over the whole pin [W/m].
Eigen::MatrixXd _pin_power_correction
The correction that will be applied to the estimated calculation [unitless].
const Function & _axial_heat_rate
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.
processor_id_type processor_id() const
Definition SCM.h:17