diff --git a/include/materials/GenericMoltresMaterial.h b/include/materials/GenericMoltresMaterial.h index 7a051116d4..9a5a538ff4 100644 --- a/include/materials/GenericMoltresMaterial.h +++ b/include/materials/GenericMoltresMaterial.h @@ -30,6 +30,9 @@ class GenericMoltresMaterial : public NuclearMaterial Real _peak_power_density_set_point; Real _controller_gain; + // Map of group constant names to file group constant names + std::map _file_map; + std::string _material; bool _perform_control; }; diff --git a/include/materials/MoltresJsonMaterial.h b/include/materials/MoltresJsonMaterial.h index 12b6d0ea30..03668b9361 100644 --- a/include/materials/MoltresJsonMaterial.h +++ b/include/materials/MoltresJsonMaterial.h @@ -14,5 +14,9 @@ class MoltresJsonMaterial : public NuclearMaterial void Construct(nlohmann::json xs_root); virtual void computeQpProperties() override; + // Vector of group constants to be loaded + std::vector _group_consts; + + // Material associated with the group constants to be loaded std::string _material_key; }; diff --git a/include/materials/NuclearMaterial.h b/include/materials/NuclearMaterial.h index 3ee126459d..3cb59f3179 100644 --- a/include/materials/NuclearMaterial.h +++ b/include/materials/NuclearMaterial.h @@ -64,6 +64,13 @@ class NuclearMaterial : public GenericConstantMaterial const VariableValue & _temperature; + // Number of neutron groups + unsigned int _num_groups; + + // Number of precursor groups + unsigned int _num_precursor_groups; + + // Group constant MaterialProperty(s) MaterialProperty> & _remxs; MaterialProperty> & _fissxs; MaterialProperty> & _nsf; @@ -91,30 +98,37 @@ class NuclearMaterial : public GenericConstantMaterial MaterialProperty & _d_beta_d_temp; MaterialProperty> & _d_decay_constant_d_temp; + // Group constant interpolation type MooseEnum _interp_type; - unsigned _num_groups; - unsigned _num_precursor_groups; + // Vector of group constant names + std::vector _xsec_names{"REMXS", + "FISSXS", + "NSF", + "FISSE", + "DIFFCOEF", + "RECIPVEL", + "CHI_T", + "CHI_P", + "CHI_D", + "GTRANSFXS", + "BETA_EFF", + "DECAY_CONSTANT"}; + + // Map of group constant names to group constant values std::map>> _xsec_map; + + // Group constant interpolators std::map> _xsec_spline_interpolators; std::map> _xsec_monotone_cubic_interpolators; std::map> _xsec_linear_interpolators; std::map> _xsec_bicubic_spline_interpolators; + + // Map of group constant names to number of neutron/precursor groups std::map _vec_lengths; - std::map _file_map; + + // Vector of temperature values std::vector _XsTemperature; - const std::vector _xsec_names{"REMXS", - "FISSXS", - "NSF", - "FISSE", - "DIFFCOEF", - "RECIPVEL", - "CHI_T", - "CHI_P", - "CHI_D", - "GTRANSFXS", - "BETA_EFF", - "DECAY_CONSTANT"}; std::vector> _remxs_consts = std::vector>(2); std::vector> _fissxs_consts = std::vector>(2); diff --git a/include/postprocessors/NeutronLeakage.h b/include/postprocessors/NeutronLeakage.h new file mode 100644 index 0000000000..fe297f4af1 --- /dev/null +++ b/include/postprocessors/NeutronLeakage.h @@ -0,0 +1,21 @@ +#pragma once + +#include "SideIntegralVariablePostprocessor.h" + +/** + * This postprocessor computes the neutron leakage rate of a given neutron group + * along a boundary + */ +class NeutronLeakage : public SideIntegralVariablePostprocessor +{ +public: + NeutronLeakage(const InputParameters & parameters); + + static InputParameters validParams(); + +protected: + Real computeQpIntegral() override; + + const MaterialProperty> & _diffcoef; + unsigned int _group; +}; diff --git a/include/postprocessors/TotalNeutronLeakage.h b/include/postprocessors/TotalNeutronLeakage.h new file mode 100644 index 0000000000..dd02ceb44a --- /dev/null +++ b/include/postprocessors/TotalNeutronLeakage.h @@ -0,0 +1,25 @@ +#pragma once + +#include "SideIntegralPostprocessor.h" +#include "ScalarTransportBase.h" + +/** + * This postprocess computes the total neutron leakage rate along a boundary for all neutron + * groups + */ +class TotalNeutronLeakage : public SideIntegralPostprocessor, public ScalarTransportBase +{ +public: + TotalNeutronLeakage(const InputParameters & parameters); + + static InputParameters validParams(); + +protected: + Real computeQpIntegral() override; + + std::vector _vars; + const MaterialProperty> & _diffcoef; + unsigned int _num_groups; + std::vector _group_fluxes; + std::vector _grad_group_fluxes; +}; diff --git a/src/materials/GenericMoltresMaterial.C b/src/materials/GenericMoltresMaterial.C index bead491626..8793e322cd 100644 --- a/src/materials/GenericMoltresMaterial.C +++ b/src/materials/GenericMoltresMaterial.C @@ -47,8 +47,6 @@ GenericMoltresMaterial::GenericMoltresMaterial(const InputParameters & parameter else _perform_control = false; - _num_groups = getParam("num_groups"); - _num_precursor_groups = getParam("num_precursor_groups"); std::string property_tables_root = getParam("property_tables_root"); _file_map["REMXS"] = "REMXS"; diff --git a/src/materials/MoltresJsonMaterial.C b/src/materials/MoltresJsonMaterial.C index 967d8a6a91..b31bf04e73 100644 --- a/src/materials/MoltresJsonMaterial.C +++ b/src/materials/MoltresJsonMaterial.C @@ -11,18 +11,30 @@ MoltresJsonMaterial::validParams() params.addRequiredParam("base_file", "The file containing macroscopic XS."); params.addRequiredParam("material_key", "The file key where the macroscopic XS can be found."); + params.addParam>( + "group_constants", + std::vector{"REMXS", + "FISSXS", + "NSF", + "FISSE", + "DIFFCOEF", + "RECIPVEL", + "CHI_T", + "CHI_P", + "CHI_D", + "GTRANSFXS", + "BETA_EFF", + "DECAY_CONSTANT"}, + "Group constants to be determined."); return params; } MoltresJsonMaterial::MoltresJsonMaterial(const InputParameters & parameters) - : NuclearMaterial(parameters) - + : NuclearMaterial(parameters), + _group_consts(getParam>("group_constants")), + _material_key(getParam("material_key")) { - - _num_groups = getParam("num_groups"); - _num_precursor_groups = getParam("num_precursor_groups"); std::string base_file = getParam("base_file"); - _material_key = getParam("material_key"); const std::string & file_name_ref = base_file; std::ifstream myfile(file_name_ref.c_str()); @@ -48,11 +60,10 @@ MoltresJsonMaterial::MoltresJsonMaterial(const InputParameters & parameters) void MoltresJsonMaterial::Construct(nlohmann::json xs_root) { - auto xsec_interpolators = _xsec_linear_interpolators; + std::set gc_set(_group_consts.begin(), _group_consts.end()); bool oneInfo = false; for (unsigned int j = 0; j < _xsec_names.size(); ++j) { - auto o = _vec_lengths[_xsec_names[j]]; auto L = _XsTemperature.size(); @@ -62,39 +73,45 @@ MoltresJsonMaterial::Construct(nlohmann::json xs_root) _xsec_map[_xsec_names[j]].resize(o); - for (decltype(_XsTemperature.size()) l = 0; l < L; ++l) + if (gc_set.find(_xsec_names[j]) != gc_set.end()) { - auto temp_key = std::to_string(static_cast(_XsTemperature[l])); - auto dataset = xs_root[_material_key][temp_key][_xsec_names[j]]; - if (_xsec_names[j] == "CHI_D" && dataset.empty()) + for (decltype(_XsTemperature.size()) l = 0; l < L; ++l) { - for (decltype(_num_groups) k = 1; k < _num_groups; ++k) - _xsec_map["CHI_D"][k].push_back(0.0); - _xsec_map["CHI_D"][0].push_back(1.0); - mooseWarning( - "CHI_D data missing -> assume delayed neutrons born in top group for material " + - _name); - continue; - } - if (dataset.empty()) - mooseError("Unable to open database " + _material_key + "/" + temp_key + "/" + - _file_map[_xsec_names[j]]); + auto temp_key = std::to_string(static_cast(_XsTemperature[l])); + auto dataset = xs_root[_material_key][temp_key][_xsec_names[j]]; + if (_xsec_names[j] == "CHI_D" && dataset.empty()) + { + for (decltype(_num_groups) k = 1; k < _num_groups; ++k) + _xsec_map["CHI_D"][k].push_back(0.0); + _xsec_map["CHI_D"][0].push_back(1.0); + mooseWarning( + "CHI_D data missing -> assume delayed neutrons born in top group for material " + + _name); + continue; + } + if (dataset.empty()) + mooseError("Unable to open database " + _material_key + "/" + temp_key + "/" + + _xsec_names[j]); - int dims = dataset.size(); - if (o == 0 and !oneInfo) - { - mooseInfo("Only precursor material data initialized (num_groups = 0) for material " + _name); - oneInfo = true; - } - if (o != dims && o != 0) - mooseError("The number of " + _material_key + "/" + temp_key + "/" + - _file_map[_xsec_names[j]] + " values does not match the " - "num_groups/num_precursor_groups parameter. " + - std::to_string(dims) + "!=" + std::to_string(o)); - for (auto k = 0; k < o; ++k) - { - _xsec_map[_xsec_names[j]][k].push_back(dataset[k].get()); + int dims = dataset.size(); + if (o == 0 and !oneInfo) + { + mooseInfo("Only precursor material data initialized (num_groups = 0) for material " + _name); + oneInfo = true; + } + if (o != dims && o != 0) + mooseError("The number of " + _material_key + "/" + temp_key + "/" + + _xsec_names[j] + " values does not match the " + "num_groups/num_precursor_groups parameter. " + + std::to_string(dims) + "!=" + std::to_string(o)); + for (auto k = 0; k < o; ++k) + _xsec_map[_xsec_names[j]][k].push_back(dataset[k].get()); } + } else + { + for (decltype(_XsTemperature.size()) l = 0; l < L; ++l) + for (auto k = 0; k < o; ++k) + _xsec_map[_xsec_names[j]][k].push_back(0.); } switch (_interp_type) { diff --git a/src/materials/NuclearMaterial.C b/src/materials/NuclearMaterial.C index a458b976c0..920a904447 100644 --- a/src/materials/NuclearMaterial.C +++ b/src/materials/NuclearMaterial.C @@ -8,19 +8,18 @@ InputParameters NuclearMaterial::validParams() { InputParameters params = GenericConstantMaterial::validParams(); - params.addRequiredParam("num_groups", + params.addRequiredParam("num_groups", "The number of groups the energy spectrum is divided into."); - params.addRequiredParam("num_precursor_groups", + params.addRequiredParam("num_precursor_groups", "The number of delayed neutron precursor groups."); params.addCoupledVar( "temperature", 937, "The temperature field for determining group constants."); params.addRequiredParam("interp_type", - GenericMoltresMaterial::interpTypes(), + NuclearMaterial::interpTypes(), "The type of interpolation to perform."); params.addParam( "sss2_input", true, "Whether serpent 2 was used to generate the input files."); params.set("constant_on") = "NONE"; - // the following two lines esentially make the two parameters optional params.set>("prop_names") = std::vector(); params.set>("prop_values") = std::vector(); @@ -30,6 +29,8 @@ NuclearMaterial::validParams() NuclearMaterial::NuclearMaterial(const InputParameters & parameters) : GenericConstantMaterial(parameters), _temperature(coupledValue("temperature")), + _num_groups(getParam("num_groups")), + _num_precursor_groups(getParam("num_precursor_groups")), _remxs(declareProperty>("remxs")), _fissxs(declareProperty>("fissxs")), _nsf(declareProperty>("nsf")), @@ -58,11 +59,7 @@ NuclearMaterial::NuclearMaterial(const InputParameters & parameters) _d_beta_d_temp(declareProperty("d_beta_d_temp")), _d_decay_constant_d_temp(declareProperty>("d_decay_constant_d_temp")), _interp_type(getParam("interp_type")) - { - _num_groups = getParam("num_groups"); - _num_precursor_groups = getParam("num_precursor_groups"); - auto n = _xsec_names.size(); for (decltype(n) j = 0; j < n; ++j) { @@ -73,19 +70,6 @@ NuclearMaterial::NuclearMaterial(const InputParameters & parameters) else _vec_lengths[_xsec_names[j]] = _num_groups; } - _file_map["REMXS"] = "REMXS"; - _file_map["NSF"] = "NSF"; - _file_map["DIFFCOEF"] = "DIFFCOEF"; - _file_map["BETA_EFF"] = "BETA_EFF"; - _file_map["FLUX"] = "FLUX"; - _file_map["FISSXS"] = "FISSXS"; - _file_map["FISSE"] = "FISSE"; - _file_map["RECIPVEL"] = "RECIPVEL"; - _file_map["CHI_T"] = "CHI_T"; - _file_map["CHI_P"] = "CHI_P"; - _file_map["CHI_D"] = "CHI_D"; - _file_map["GTRANSFXS"] = "GTRANSFXS"; - _file_map["DECAY_CONSTANT"] = "DECAY_CONSTANT"; } void diff --git a/src/postprocessors/NeutronLeakage.C b/src/postprocessors/NeutronLeakage.C new file mode 100644 index 0000000000..fbde2ee939 --- /dev/null +++ b/src/postprocessors/NeutronLeakage.C @@ -0,0 +1,31 @@ +#include "NeutronLeakage.h" + +registerMooseObject("MoltresApp", NeutronLeakage); + +InputParameters +NeutronLeakage::validParams() +{ + InputParameters params = SideIntegralVariablePostprocessor::validParams(); + params.addClassDescription("Postprocessor for computing neutron leakage along provided " + "boundaries"); + params.addRequiredParam("group_number", + "The group for which this postprocessor " + "calculates leakage"); + params.addCoupledVar("temperature", + "The temperature used to interpolate the diffusion coefficient"); + return params; +} + +NeutronLeakage::NeutronLeakage(const InputParameters & parameters) + : SideIntegralVariablePostprocessor(parameters), + _diffcoef(getMaterialProperty>("diffcoef")), + _group(getParam("group_number") - 1) +{ + addMooseVariableDependency(&mooseVariableField()); +} + +Real +NeutronLeakage::computeQpIntegral() +{ + return _u[_qp] / 4 - _normals[_qp] * _grad_u[_qp] * _diffcoef[_qp][_group] / 2; +} diff --git a/src/postprocessors/TotalNeutronLeakage.C b/src/postprocessors/TotalNeutronLeakage.C new file mode 100644 index 0000000000..cc9fc534af --- /dev/null +++ b/src/postprocessors/TotalNeutronLeakage.C @@ -0,0 +1,52 @@ +#include "TotalNeutronLeakage.h" + +registerMooseObject("MoltresApp", TotalNeutronLeakage); + +InputParameters +TotalNeutronLeakage::validParams() +{ + InputParameters params = SideIntegralPostprocessor::validParams(); + params += ScalarTransportBase::validParams(); + params.addClassDescription("Postprocessor for computing total neutron leakage along provided " + "boundaries for all neutron group fluxes"); + params.addRequiredParam("num_groups", "The total number of energy groups"); + params.addRequiredCoupledVar("group_fluxes", "All the variables that hold the group fluxes. " + "These MUST be listed by decreasing " + "energy/increasing group number."); + return params; +} + +TotalNeutronLeakage::TotalNeutronLeakage(const InputParameters & parameters) + : SideIntegralPostprocessor(parameters), + ScalarTransportBase(parameters), + _vars(getCoupledMooseVars()), + _diffcoef(getMaterialProperty>("diffcoef")), + _num_groups(getParam("num_groups")) +{ + addMooseVariableDependency(_vars); + unsigned int n = coupledComponents("group_fluxes"); + if (n != _num_groups) + { + mooseError("The number of coupled variables doesn't match the number of groups."); + } + _group_fluxes.resize(n); + _grad_group_fluxes.resize(n); + for (unsigned int i = 0; i < _group_fluxes.size(); ++i) + { + _group_fluxes[i] = &coupledValue("group_fluxes", i); + _grad_group_fluxes[i] = &coupledGradient("group_fluxes", i); + } +} + +Real +TotalNeutronLeakage::computeQpIntegral() +{ + Real value = 0; + for (unsigned int i = 0; i < _num_groups; ++i) + { + value += computeConcentration((*_group_fluxes[i]), _qp) / 4 - _normals[_qp] * + computeConcentrationGradient((*_group_fluxes[i]), (*_grad_group_fluxes[i]), _qp) * + _diffcoef[_qp][i] / 2; + } + return value; +} diff --git a/tests/postprocessors/gold/neutron_leakage_out.csv b/tests/postprocessors/gold/neutron_leakage_out.csv new file mode 100644 index 0000000000..b4aa4f334f --- /dev/null +++ b/tests/postprocessors/gold/neutron_leakage_out.csv @@ -0,0 +1,3 @@ +time,group1_leakage,group2_leakage,total_leakage +0,0,0,0 +1,1,10,11 diff --git a/tests/postprocessors/mat.json b/tests/postprocessors/mat.json new file mode 100644 index 0000000000..a7e7e5a765 --- /dev/null +++ b/tests/postprocessors/mat.json @@ -0,0 +1,13 @@ +{ + "mat1": { + "900": { + "DIFFCOEF": [ + 1.0, + 1.0 + ] + }, + "temp": [ + 900 + ] + } +} diff --git a/tests/postprocessors/neutron_leakage.i b/tests/postprocessors/neutron_leakage.i new file mode 100644 index 0000000000..bc2feebd77 --- /dev/null +++ b/tests/postprocessors/neutron_leakage.i @@ -0,0 +1,103 @@ +[GlobalParams] + group_fluxes = 'group1 group2' + num_groups = 2 + num_precursor_groups = 0 + use_exp_form = false + temperature = 900 + sss2_input = true +[] + +[Mesh] + [gmg] + type = GeneratedMeshGenerator + dim = 2 + nx = 2 + ny = 2 + xmax = 1 + ymax = 1 + [] +[] + +[Variables] + [group1] + [] + [group2] + [] +[] + +[Kernels] + [group1_diffusion] + type = GroupDiffusion + variable = group1 + group_number = 1 + [] + [group2_diffusion] + type = GroupDiffusion + variable = group2 + group_number = 2 + [] +[] + +[BCs] + [group1_left] + type = DirichletBC + variable = group1 + boundary = left + value = 3 + [] + [group1_right] + type = DirichletBC + variable = group1 + boundary = right + value = 2 + [] + [group2_left] + type = DirichletBC + variable = group2 + boundary = left + value = 30 + [] + [group2_right] + type = DirichletBC + variable = group2 + boundary = right + value = 20 + [] +[] + +[Materials] + [mat] + type = MoltresJsonMaterial + base_file = mat.json + material_key = 'mat1' + interp_type = 'none' + group_constants = 'DIFFCOEF' + [] +[] + +[Executioner] + type = Steady +[] + +[Postprocessors] + [group1_leakage] + type = NeutronLeakage + variable = group1 + boundary = 'right' + group_number = 1 + [] + [group2_leakage] + type = NeutronLeakage + variable = group2 + boundary = 'right' + group_number = 2 + [] + [total_leakage] + type = TotalNeutronLeakage + boundary = 'right' + [] +[] + +[Outputs] + csv = true +[] diff --git a/tests/postprocessors/tests b/tests/postprocessors/tests index 019113fee1..3f7e389682 100644 --- a/tests/postprocessors/tests +++ b/tests/postprocessors/tests @@ -1,16 +1,20 @@ [Tests] - [./side_weighted_integral] - type = 'Exodiff' + [side_weighted_integral] + type = Exodiff input = 'side_weighted_integral.i' exodiff = 'side_weighted_integral_out.e' - requirement = 'The system shall compute the weighted integral sum of a variable over a side.' - [../] - [./side_weighted_integral_RZ] - type = 'Exodiff' + [] + [side_weighted_integral_RZ] + type = Exodiff input = 'side_weighted_integral_RZ.i' exodiff = 'side_weighted_integral_RZ_out.e' - requirement = 'The system shall compute the weighted integral sum of a variable over a side in RZ coordinates.' - [../] + [] + [neutron_leakage] + type = CSVDiff + input = 'neutron_leakage.i' + csvdiff = 'neutron_leakage_out.csv' + requirement = 'The system shall compute group-wise and total neutron leakage' + [] []