Line data Source code
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 "HeatSourceFromTotalPower.h" 11 : #include "HeatStructureCylindricalBase.h" 12 : #include "HeatStructurePlate.h" 13 : #include "TotalPowerBase.h" 14 : 15 : registerMooseObject("ThermalHydraulicsApp", HeatSourceFromTotalPower); 16 : 17 : InputParameters 18 432 : HeatSourceFromTotalPower::validParams() 19 : { 20 432 : InputParameters params = HeatSourceBase::validParams(); 21 864 : params.addRequiredParam<std::string>("power", "Component that provides total power"); 22 864 : params.addParam<Real>( 23 864 : "power_fraction", 1., "Fraction of the total power that goes into the heat structure [-]"); 24 864 : params.addParam<FunctionName>("power_shape_function", "Axial power shape [-]"); 25 864 : params.declareControllable("power_fraction"); 26 432 : params.addClassDescription("Heat generation from total power"); 27 432 : return params; 28 0 : } 29 : 30 216 : HeatSourceFromTotalPower::HeatSourceFromTotalPower(const InputParameters & parameters) 31 : : HeatSourceBase(parameters), 32 432 : _power_fraction(getParam<Real>("power_fraction")), 33 432 : _has_psf(isParamValid("power_shape_function")), 34 432 : _power_shape_func(_has_psf ? getParam<FunctionName>("power_shape_function") : "") 35 : { 36 216 : checkSizeGreaterThan<std::string>("regions", 0); 37 216 : } 38 : 39 : void 40 216 : HeatSourceFromTotalPower::init() 41 : { 42 216 : HeatSourceBase::init(); 43 : 44 432 : if (hasComponent<TotalPowerBase>("power")) 45 : { 46 214 : const TotalPowerBase & rp = getComponent<TotalPowerBase>("power"); 47 214 : _power_var_name = rp.getPowerVariableName(); 48 : } 49 216 : } 50 : 51 : void 52 216 : HeatSourceFromTotalPower::check() const 53 : { 54 216 : HeatSourceBase::check(); 55 : 56 216 : checkComponentOfTypeExists<TotalPowerBase>("power"); 57 216 : } 58 : 59 : void 60 208 : HeatSourceFromTotalPower::addMooseObjects() 61 : { 62 : /// The heat structure component we work with 63 208 : const HeatStructureInterface & hs = getComponent<HeatStructureInterface>("hs"); 64 208 : const HeatStructureBase * hs_base = dynamic_cast<const HeatStructureBase *>(&hs); 65 : 66 : Real n_units, length; 67 208 : if (hs_base) 68 : { 69 : n_units = hs_base->getNumberOfUnits(); 70 200 : length = hs_base->getLength(); 71 : } 72 : else // HeatStructureFromFile3D 73 : { 74 : n_units = 1.0; 75 : length = 1.0; 76 : } 77 : 78 : const HeatStructureCylindricalBase * hs_cyl = 79 208 : dynamic_cast<const HeatStructureCylindricalBase *>(&hs); 80 : const bool is_cylindrical = hs_cyl != nullptr; 81 : 82 208 : const HeatStructurePlate * hs_plate = dynamic_cast<const HeatStructurePlate *>(&hs); 83 : const bool is_plate = hs_plate != nullptr; 84 : 85 208 : if (!_has_psf) 86 : { 87 234 : _power_shape_func = genName(name(), "power_shape_fn"); 88 117 : std::string class_name = "ConstantFunction"; 89 117 : InputParameters pars = _factory.getValidParams(class_name); 90 117 : pars.set<Real>("value") = 1. / length; 91 117 : getTHMProblem().addFunction(class_name, _power_shape_func, pars); 92 117 : } 93 : 94 208 : const std::string power_shape_integral_name = _has_psf 95 208 : ? genName(name(), _power_shape_func, "integral") 96 442 : : genName(_power_shape_func, "integral"); 97 : 98 : { 99 : const std::string class_name = 100 242 : is_cylindrical ? "FunctionElementIntegralRZ" : "FunctionElementIntegral"; 101 208 : InputParameters pars = _factory.getValidParams(class_name); 102 208 : pars.set<std::vector<SubdomainName>>("block") = _subdomain_names; 103 208 : pars.set<FunctionName>("function") = _power_shape_func; 104 208 : if (is_cylindrical) 105 : { 106 174 : pars.set<Point>("axis_point") = hs_cyl->getPosition(); 107 174 : pars.set<RealVectorValue>("axis_dir") = hs_cyl->getDirection(); 108 : } 109 624 : pars.set<ExecFlagEnum>("execute_on") = {EXEC_INITIAL}; 110 : // TODO: This seems to produce incorrect output files, even though this is the line 111 : // that should be here, becuase we don't want this PPS to be in any output. The effect 112 : // of this line is correct, but for some reason, MOOSE will start output scalar variables 113 : // even though we did not ask it to do so. Refs idaholab/thm# 114 : // pars.set<std::vector<OutputName>>("outputs") = getTHMProblem().getOutputsVector("none"); 115 208 : getTHMProblem().addPostprocessor(class_name, power_shape_integral_name, pars); 116 208 : } 117 : 118 : { 119 : const std::string class_name = 120 242 : is_cylindrical ? "ADHeatStructureHeatSourceRZ" : "ADHeatStructureHeatSource"; 121 208 : InputParameters pars = _factory.getValidParams(class_name); 122 416 : pars.set<NonlinearVariableName>("variable") = HeatConductionModel::TEMPERATURE; 123 208 : pars.set<std::vector<SubdomainName>>("block") = _subdomain_names; 124 208 : pars.set<Real>("num_units") = n_units; 125 208 : pars.set<Real>("power_fraction") = _power_fraction; 126 208 : pars.set<FunctionName>("power_shape_function") = _power_shape_func; 127 208 : pars.set<std::vector<VariableName>>("total_power") = 128 416 : std::vector<VariableName>(1, _power_var_name); 129 208 : if (is_cylindrical) 130 : { 131 174 : pars.set<Point>("axis_point") = hs_cyl->getPosition(); 132 174 : pars.set<RealVectorValue>("axis_dir") = hs_cyl->getDirection(); 133 : } 134 34 : else if (is_plate) 135 : { 136 : // For plate heat structure, the element integral of the power shape only 137 : // integrates over x and y, not z, so the depth still needs to be applied. 138 26 : pars.set<Real>("scale") = 1.0 / hs_plate->getDepth(); 139 : } 140 416 : pars.set<PostprocessorName>("power_shape_integral_pp") = power_shape_integral_name; 141 416 : std::string mon = genName(name(), "heat_src"); 142 208 : getTHMProblem().addKernel(class_name, mon, pars); 143 416 : connectObject(pars, mon, "power_fraction"); 144 208 : } 145 416 : }