diff --git a/modules/reactor/include/meshgenerators/HexIDPatternedMeshGenerator.h b/modules/reactor/include/meshgenerators/HexIDPatternedMeshGenerator.h new file mode 100644 index 000000000000..7e6927bb4520 --- /dev/null +++ b/modules/reactor/include/meshgenerators/HexIDPatternedMeshGenerator.h @@ -0,0 +1,50 @@ +//* This file is part of the MOOSE framework +//* https://www.mooseframework.org +//* +//* All rights reserved, see COPYRIGHT for full restrictions +//* https://github.com/idaholab/moose/blob/master/COPYRIGHT +//* +//* Licensed under LGPL 2.1, please see LICENSE for details +//* https://www.gnu.org/licenses/lgpl-2.1.html + +#pragma once + +#include "PatternedHexMeshGenerator.h" +#include "MooseEnum.h" +#include "MeshMetaDataInterface.h" + +/** + * Generates patterned hexagonal meshes with a reporting ID + */ +class HexIDPatternedMeshGenerator : public PatternedHexMeshGenerator +{ +public: + static InputParameters validParams(); + + HexIDPatternedMeshGenerator(const InputParameters & parameters); + + std::unique_ptr generate() override; + +protected: + /// assign IDs for each component in lattice in sequential order + std::vector getCellwiseIntegerIDs() const; + /// assign IDs for each input component type + std::vector getPatternIntegerIDs() const; + /// Assign IDs based on user-defined mapping defined in id_pattern + std::vector getManualIntegerIDs() const; + /// get list of block IDs in input mesh cells + std::set getCellBlockIDs() const; + /// get list of block IDs for duck regions + std::map getDuckBlockIDs(std::unique_ptr & mesh, + std::set & blks) const; + /// name of integer ID + const std::string _element_id_name; + /// integer ID assignment type + const std::string _assign_type; + /// flag to indicate if exclude_id is defined + const bool _use_exclude_id; + /// flag to indicate if exclude_id is used for each input + std::vector _exclude_ids; + /// hold integer ID for each input pattern cell + std::vector> _id_pattern; +}; diff --git a/modules/reactor/src/meshgenerators/HexIDPatternedMeshGenerator.C b/modules/reactor/src/meshgenerators/HexIDPatternedMeshGenerator.C new file mode 100644 index 000000000000..aff333192bd3 --- /dev/null +++ b/modules/reactor/src/meshgenerators/HexIDPatternedMeshGenerator.C @@ -0,0 +1,217 @@ +#include "PatternedHexMeshGenerator.h" +#include "HexIDPatternedMeshGenerator.h" + +registerMooseObject("ReactorApp", HexIDPatternedMeshGenerator); + +defineLegacyParams(HexIDPatternedMeshGenerator); + +InputParameters +HexIDPatternedMeshGenerator::validParams() +{ + InputParameters params = PatternedHexMeshGenerator::validParams(); + params.addRequiredParam("id_name", "Reporting_id_name"); + params.addParam>( + "exclude_id", "Name of inputs to be excluded in ID generation."); + MooseEnum option("cell pattern manual", "cell"); + params.addParam("assign_type", option, "Type of integer id assignment"); + params.addParam>>( + "id_pattern", + "User-defined element IDs. A double-indexed array starting with the upper-left corner"); + params.addClassDescription("This HexIDPatternedMeshGenerator source code is to generate " + "patterned hexagonal meshes with Reporting ID"); + return params; +} + +HexIDPatternedMeshGenerator::HexIDPatternedMeshGenerator(const InputParameters & parameters) + : PatternedHexMeshGenerator(parameters), + _element_id_name(getParam("id_name")), + _assign_type(getParam("assign_type")), + _use_exclude_id(isParamValid("exclude_id")) +{ + if (_use_exclude_id && _assign_type != "cell") + paramError("exclude_id", "works only when \"assign_type\" is equal 'cell'"); + if (!isParamValid("id_pattern") && _assign_type == "manual") + paramError("id_pattern", "required when \"assign_type\" is equal to 'manual'"); + + if (_assign_type == "manual") + _id_pattern = getParam>>("id_pattern"); + _exclude_ids.resize(_input_names.size()); + if (_use_exclude_id) + { + std::vector exclude_id_name = + getParam>("exclude_id"); + for (unsigned int i = 0; i < _input_names.size(); ++i) + { + _exclude_ids[i] = false; + for (auto input_name : exclude_id_name) + if (_input_names[i] == input_name) + { + _exclude_ids[i] = true; + break; + } + } + } + else + { + for (unsigned int i = 0; i < _input_names.size(); ++i) + _exclude_ids[i] = false; + } +} + +std::unique_ptr +HexIDPatternedMeshGenerator::generate() +{ + auto mesh = PatternedHexMeshGenerator::generate(); + std::vector integer_ids; + if (_assign_type == "cell") + integer_ids = getCellwiseIntegerIDs(); + else if (_assign_type == "pattern") + integer_ids = getPatternIntegerIDs(); + else if (_assign_type == "manual") + integer_ids = getManualIntegerIDs(); + + std::set blks = getCellBlockIDs(); + unsigned int duct_boundary_id = *std::max_element(integer_ids.begin(), integer_ids.end()) + 1; + + std::map blks_duct = getDuckBlockIDs(mesh, blks); + + unsigned int extra_id_index = mesh->add_elem_integer(_element_id_name); + + unsigned int i = 0; + unsigned int id = integer_ids[i]; + unsigned old_id = id; + for (auto elem : mesh->element_ptr_range()) + { + auto blk = elem->subdomain_id(); + auto it = blks.find(blk); + if (it == blks.end()) + { + if (_has_assembly_duct) + { + auto it2 = blks_duct.find(blk); + if (it2 == blks_duct.end()) + elem->set_extra_integer(extra_id_index, old_id); + else + elem->set_extra_integer(extra_id_index, duct_boundary_id + it2->second); + } + else + elem->set_extra_integer(extra_id_index, old_id); + } + else + { + elem->set_extra_integer(extra_id_index, id); + ++i; + old_id = id; + id = integer_ids[i]; + } + } + return dynamic_pointer_cast(mesh); +} + +std::vector +HexIDPatternedMeshGenerator::getCellwiseIntegerIDs() const +{ + std::vector integer_ids; + dof_id_type id = 0; + for (MooseIndex(_pattern) i = 0; i < _pattern.size(); ++i) + { + for (MooseIndex(_pattern[i]) j = 0; j < _pattern[i].size(); ++j) + { + ReplicatedMesh & cell_mesh = *_meshes[_pattern[i][j]]; + unsigned int n_cell_elem = cell_mesh.n_elem(); + bool exclude_id = false; + if (_use_exclude_id) + if (_exclude_ids[_pattern[i][j]]) + exclude_id = true; + if (!exclude_id) + { + for (unsigned int k = 0; k < n_cell_elem; ++k) + integer_ids.push_back(id); + ++id; + } + else + for (unsigned int k = 0; k < n_cell_elem; ++k) + integer_ids.push_back(DofObject::invalid_id); + } + } + return integer_ids; +} + +std::vector +HexIDPatternedMeshGenerator::getPatternIntegerIDs() const +{ + std::vector integer_ids; + for (MooseIndex(_pattern) i = 0; i < _pattern.size(); ++i) + { + for (MooseIndex(_pattern[i]) j = 0; j < _pattern[i].size(); ++j) + { + const ReplicatedMesh & cell_mesh = *_meshes[_pattern[i][j]]; + unsigned int n_cell_elem = cell_mesh.n_elem(); + for (unsigned int k = 0; k < n_cell_elem; ++k) + integer_ids.push_back(_pattern[i][j]); + } + } + return integer_ids; +} +std::vector +HexIDPatternedMeshGenerator::getManualIntegerIDs() const +{ + std::vector integer_ids; + for (MooseIndex(_pattern) i = 0; i < _pattern.size(); ++i) + { + for (MooseIndex(_pattern[i]) j = 0; j < _pattern[i].size(); ++j) + { + unsigned int id = _id_pattern[i][j]; + const ReplicatedMesh & cell_mesh = *_meshes[_pattern[i][j]]; + unsigned int n_cell_elem = cell_mesh.n_elem(); + for (unsigned int k = 0; k < n_cell_elem; ++k) + integer_ids.push_back(id); + } + } + return integer_ids; +} + +std::set +HexIDPatternedMeshGenerator::getCellBlockIDs() const +{ + std::set blks; + for (MooseIndex(_pattern) i = 0; i < _pattern.size(); ++i) + { + for (MooseIndex(_pattern[i]) j = 0; j < _pattern[i].size(); ++j) + { + const ReplicatedMesh & cell_mesh = *_meshes[_pattern[i][j]]; + for (auto elem : cell_mesh.element_ptr_range()) + { + auto blk = elem->subdomain_id(); + auto it = blks.find(blk); + if (it == blks.end()) + blks.insert(blk); + } + } + } + return blks; +} + +std::map +HexIDPatternedMeshGenerator::getDuckBlockIDs(std::unique_ptr & mesh, + std::set & blks) const +{ + unsigned int i = 0; + std::map blks_duct; + if (_has_assembly_duct) + { + for (auto elem : mesh->element_ptr_range()) + { + auto blk = elem->subdomain_id(); + auto it1 = blks.find(blk); + if (it1 == blks.end()) + { + auto it2 = blks_duct.find(blk); + if (it2 == blks_duct.end()) + blks_duct[blk] = i++; + } + } + blks_duct.erase(blks_duct.begin()); + } + return blks_duct; +} diff --git a/modules/reactor/test/tests/meshgenerators/reporting_id/hexagonal_id/assembly_reporting_id.i b/modules/reactor/test/tests/meshgenerators/reporting_id/hexagonal_id/assembly_reporting_id.i new file mode 100644 index 000000000000..2992efa400e7 --- /dev/null +++ b/modules/reactor/test/tests/meshgenerators/reporting_id/hexagonal_id/assembly_reporting_id.i @@ -0,0 +1,65 @@ +[Mesh] + [pin1] + type = PolygonConcentricCircleMeshGenerator + preserve_volumes = true + ring_radii = 0.4 + ring_intervals = 1 + background_intervals = 1 + num_sides = 6 + num_sectors_per_side = '2 2 2 2 2 2' + polygon_size = 0.5 + [] + [pin2] + type = PolygonConcentricCircleMeshGenerator + preserve_volumes = true + ring_radii = 0.4 + ring_intervals = 1 + background_intervals = 1 + num_sides = 6 + num_sectors_per_side = '2 2 2 2 2 2' + polygon_size = 0.5 + [] + [assembly] + type = HexIDPatternedMeshGenerator + inputs = 'pin1 pin2' + pattern_boundary = hexagon + pattern = ' 1 0 1; + 0 0 0 0; + 1 0 1 0 1; + 0 0 0 0; + 1 0 1' + hexagon_size = 2.6 + duct_sizes = '2.4 2.5' + duct_intervals = '1 1' + assign_type = 'cell' + id_name = 'pin_id' + [] +[] + +[Executioner] + type = Steady +[] + +[Problem] + solve = false +[] + +[AuxVariables] + [pin_id] + family = MONOMIAL + order = CONSTANT + [] +[] + +[AuxKernels] + [set_pin_id] + type = ElemExtraIDAux + variable = pin_id + extra_id_name = pin_id + [] +[] + +[Outputs] + exodus = true + execute_on = timestep_end +[] diff --git a/modules/reactor/test/tests/meshgenerators/reporting_id/hexagonal_id/core_reporting_id.i b/modules/reactor/test/tests/meshgenerators/reporting_id/hexagonal_id/core_reporting_id.i new file mode 100644 index 000000000000..7eaad2548e19 --- /dev/null +++ b/modules/reactor/test/tests/meshgenerators/reporting_id/hexagonal_id/core_reporting_id.i @@ -0,0 +1,100 @@ +[Mesh] + [pin1] + type = PolygonConcentricCircleMeshGenerator + preserve_volumes = true + ring_radii = 0.4 + ring_intervals = 1 + background_intervals = 1 + num_sides = 6 + num_sectors_per_side = '2 2 2 2 2 2' + polygon_size = 0.5 + [] + [pin2] + type = PolygonConcentricCircleMeshGenerator + preserve_volumes = true + ring_radii = 0.4 + ring_intervals = 1 + background_intervals = 1 + num_sides = 6 + num_sectors_per_side = '2 2 2 2 2 2' + polygon_size = 0.5 + [] + [assembly1] + type = HexIDPatternedMeshGenerator + inputs = 'pin1 pin2' + pattern_boundary = hexagon + pattern = ' 1 0 1; + 0 0 0 0; + 1 0 1 0 1; + 0 0 0 0; + 1 0 1' + hexagon_size = 2.6 + duct_sizes = '2.4 2.5' + duct_intervals = '1 1' + id_name = 'pin_id' + assign_type = 'cell' + [] + [assembly2] + type = HexIDPatternedMeshGenerator + inputs = 'pin1 pin2' + pattern_boundary = hexagon + pattern = ' 0 0 0; + 0 1 1 0; + 0 1 0 1 0; + 0 1 1 0; + 0 0 0' + hexagon_size = 2.6 + duct_sizes = '2.4 2.5' + duct_intervals = '1 1' + id_name = 'pin_id' + assign_type = 'cell' + [] + [core] + type = HexIDPatternedMeshGenerator + inputs = 'assembly1 assembly2' + pattern_boundary = none + pattern = '1 1; + 1 0 1; + 1 1' + generate_core_metadata = true + id_name = 'assembly_id' + assign_type = 'cell' + [] +[] + +[Executioner] + type = Steady +[] + +[Problem] + solve = false +[] + +[AuxVariables] + [pin_id] + family = MONOMIAL + order = CONSTANT + [] + [assembly_id] + family = MONOMIAL + order = CONSTANT + [] +[] + +[AuxKernels] + [set_pin_id] + type = ElemExtraIDAux + variable = pin_id + extra_id_name = pin_id + [] + [set_assembly_id] + type = ElemExtraIDAux + variable = assembly_id + extra_id_name = assembly_id + [] +[] + +[Outputs] + exodus = true + execute_on = timestep_end +[] diff --git a/modules/reactor/test/tests/meshgenerators/reporting_id/hexagonal_id/core_reporting_id_exclude.i b/modules/reactor/test/tests/meshgenerators/reporting_id/hexagonal_id/core_reporting_id_exclude.i new file mode 100644 index 000000000000..2aced091b916 --- /dev/null +++ b/modules/reactor/test/tests/meshgenerators/reporting_id/hexagonal_id/core_reporting_id_exclude.i @@ -0,0 +1,63 @@ +[Mesh] + [assembly] + type = SimpleHexagonGenerator + hexagon_size = 5.0 + hexagon_size_style = 'apothem' + block_id = '1' + [] + [dummy] + type = SimpleHexagonGenerator + hexagon_size = 5.0 + hexagon_size_style = 'apothem' + block_id = '2' + [] + + [core] + type = HexIDPatternedMeshGenerator + inputs = 'assembly dummy' + pattern_boundary = none + pattern = ' 1 0 1; + 0 0 0 0; + 1 0 0 0 1; + 0 0 0 0; + 1 0 1' + assign_type = 'cell' + id_name = 'assembly_id' + exclude_id = 'dummy' + [] + + [del_dummy] + type = BlockDeletionGenerator + block = 2 + input = core + new_boundary = core_out + [] +[] + +[Executioner] + type = Steady +[] + +[Problem] + solve = false +[] + +[AuxVariables] + [assembly_id] + family = MONOMIAL + order = CONSTANT + [] +[] + +[AuxKernels] + [set_assembly_id] + type = ElemExtraIDAux + variable = assembly_id + extra_id_name = assembly_id + [] +[] + +[Outputs] + exodus = true + execute_on = timestep_end +[] diff --git a/modules/reactor/test/tests/meshgenerators/reporting_id/hexagonal_id/gold/assembly_reporting_id_cell_out.e b/modules/reactor/test/tests/meshgenerators/reporting_id/hexagonal_id/gold/assembly_reporting_id_cell_out.e new file mode 100644 index 000000000000..c1488058904b Binary files /dev/null and b/modules/reactor/test/tests/meshgenerators/reporting_id/hexagonal_id/gold/assembly_reporting_id_cell_out.e differ diff --git a/modules/reactor/test/tests/meshgenerators/reporting_id/hexagonal_id/gold/assembly_reporting_id_manual_out.e b/modules/reactor/test/tests/meshgenerators/reporting_id/hexagonal_id/gold/assembly_reporting_id_manual_out.e new file mode 100644 index 000000000000..e6c56425ee66 Binary files /dev/null and b/modules/reactor/test/tests/meshgenerators/reporting_id/hexagonal_id/gold/assembly_reporting_id_manual_out.e differ diff --git a/modules/reactor/test/tests/meshgenerators/reporting_id/hexagonal_id/gold/assembly_reporting_id_pattern_out.e b/modules/reactor/test/tests/meshgenerators/reporting_id/hexagonal_id/gold/assembly_reporting_id_pattern_out.e new file mode 100644 index 000000000000..4a7494248e04 Binary files /dev/null and b/modules/reactor/test/tests/meshgenerators/reporting_id/hexagonal_id/gold/assembly_reporting_id_pattern_out.e differ diff --git a/modules/reactor/test/tests/meshgenerators/reporting_id/hexagonal_id/gold/core_reporting_id_exclude_out.e b/modules/reactor/test/tests/meshgenerators/reporting_id/hexagonal_id/gold/core_reporting_id_exclude_out.e new file mode 100644 index 000000000000..7ad8ca884036 Binary files /dev/null and b/modules/reactor/test/tests/meshgenerators/reporting_id/hexagonal_id/gold/core_reporting_id_exclude_out.e differ diff --git a/modules/reactor/test/tests/meshgenerators/reporting_id/hexagonal_id/gold/core_reporting_id_out.e b/modules/reactor/test/tests/meshgenerators/reporting_id/hexagonal_id/gold/core_reporting_id_out.e new file mode 100644 index 000000000000..6e7a9aedbb1a Binary files /dev/null and b/modules/reactor/test/tests/meshgenerators/reporting_id/hexagonal_id/gold/core_reporting_id_out.e differ diff --git a/modules/reactor/test/tests/meshgenerators/reporting_id/hexagonal_id/tests b/modules/reactor/test/tests/meshgenerators/reporting_id/hexagonal_id/tests new file mode 100644 index 000000000000..2edabee88be5 --- /dev/null +++ b/modules/reactor/test/tests/meshgenerators/reporting_id/hexagonal_id/tests @@ -0,0 +1,40 @@ +[Tests] + [assembly.cell] + type = 'Exodiff' + input = 'assembly_reporting_id.i' + exodiff = 'assembly_reporting_id_cell_out.e' + cli_args = "Outputs/file_base='assembly_reporting_id_cell_out'" + requirement = 'The system shall generate pin reporting IDs for hexagonal assembly with assign_type=cell (default)' + recover = false + [] + [assembly.pattern] + type = 'Exodiff' + input = 'assembly_reporting_id.i' + exodiff = 'assembly_reporting_id_pattern_out.e' + cli_args = "Mesh/assembly/assign_type='pattern' Outputs/file_base='assembly_reporting_id_pattern_out'" + requirement = 'The system shall generate pin reporting IDs for hexagonal assembly with assign_type=pattern' + recover = false + [] + [assembly.manual] + type = 'Exodiff' + input = 'assembly_reporting_id.i' + exodiff = 'assembly_reporting_id_manual_out.e' + cli_args = "Mesh/assembly/assign_type='manual' Mesh/assembly/id_pattern='2 2 2;2 1 1 2;2 1 0 1 2;2 1 1 2;2 2 2' Outputs/file_base='assembly_reporting_id_manual_out'" + requirement = 'The system shall generate pin reporting IDs for hexagonal assembly with assign_type=manual' + recover = false + [] + [core] + type = 'Exodiff' + input = 'core_reporting_id.i' + exodiff = 'core_reporting_id_out.e' + requirement = 'The system shall generate pin and assembly reporting IDs for hexagonal core' + recover = false + [] + [core_exclude_id] + type = 'Exodiff' + input = 'core_reporting_id_exclude.i' + exodiff = 'core_reporting_id_exclude_out.e' + requirement = 'The system shall generate assembly reporting IDs for hexagonal core with exclude_id option' + recover = false + [] +[]