https://mooseframework.inl.gov
SimpleHexagonGenerator.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 "SimpleHexagonGenerator.h"
11 
12 // C++ includes
13 #include <cmath>
14 
16 
19 {
21  MooseEnum element_type("TRI QUAD HYBRID", "TRI");
22  params.addParam<MooseEnum>("element_type",
23  element_type,
24  "Whether the simple hexagon mesh is made of TRI or QUAD elements.");
26  "hexagon_size", "hexagon_size>0.0", "Size of the hexagon to be generated.");
27  MooseEnum hexagon_size_style("apothem radius", "apothem");
28  params.addParam<MooseEnum>(
29  "hexagon_size_style",
30  hexagon_size_style,
31  "Style in which the hexagon size is given (default: apothem i.e. half-pitch). Option: " +
32  hexagon_size_style.getRawNames());
33  params.addRangeCheckedParam<unsigned int>(
34  "radial_intervals",
35  "radial_intervals>1",
36  "Number of pin radial meshing rings (only applicable when 'element_type' is 'HYBRID').");
37  params.addRangeCheckedParam<std::vector<subdomain_id_type>>(
38  "block_id",
39  "block_id>=0",
40  "Optional customized block id; two ids are needed for HYBRID 'element_type'.");
41  params.addParam<std::vector<SubdomainName>>(
42  "block_name",
43  "Optional customized block name; two names are needed for HYBRID 'element_type'.");
44  params.addRangeCheckedParam<boundary_id_type>("external_boundary_id",
45  "external_boundary_id>=0",
46  "Optional customized external boundary id.");
47  params.addParam<BoundaryName>("external_boundary_name",
48  "Optional customized external boundary name.");
49  params.addParamNamesToGroup("block_id block_name external_boundary_id external_boundary_name",
50  "Customized Subdomain/Boundary");
51  params.addClassDescription(
52  "This SimpleHexagonGenerator object is designed to generate a simple hexagonal mesh that "
53  "only contains six simple azimuthal triangular elements, two quadrilateral elements, or six "
54  "central azimuthal triangular elements plus a several layers of quadrilateral elements.");
55 
56  return params;
57 }
58 
60  : PolygonMeshGeneratorBase(parameters),
61  _element_type(getParam<MooseEnum>("element_type").template getEnum<ElemType>()),
62  _hexagon_size(getParam<Real>("hexagon_size")),
63  _hexagon_size_style(
64  getParam<MooseEnum>("hexagon_size_style").template getEnum<PolygonSizeStyle>()),
65  _radial_intervals(isParamValid("radial_intervals")
66  ? getParam<unsigned int>("radial_intervals")
67  : (_element_type == ElemType::HYBRID ? 2 : 1)),
68  _block_id(isParamValid("block_id") ? getParam<std::vector<subdomain_id_type>>("block_id")
69  : std::vector<subdomain_id_type>()),
70  _block_name(isParamValid("block_name") ? getParam<std::vector<SubdomainName>>("block_name")
71  : std::vector<SubdomainName>()),
72  _boundary_id_valid(isParamValid("external_boundary_id")),
73  _external_boundary_id(isParamValid("external_boundary_id")
74  ? getParam<boundary_id_type>("external_boundary_id")
75  : 0),
76  _external_boundary_name(isParamValid("external_boundary_name")
77  ? getParam<BoundaryName>("external_boundary_name")
78  : BoundaryName())
79 {
81  paramError(
82  "radial_intervals",
83  "A non-unity 'radial_intervals' value is only supported when 'element_type' is 'HYBRID'.");
86  : _hexagon_size * std::cos(M_PI / (Real)HEXAGON_NUM_SIDES));
87  if ((_block_id.size() > 1) && _element_type != ElemType::HYBRID)
88  paramError(
89  "block_id",
90  "if provided, the size of this parameter must be one if 'element_type' is TRI or QUAD.");
91  if ((_block_id.size() != 0 && _block_id.size() != 2) && _element_type == ElemType::HYBRID)
92  paramError("block_id",
93  "if provided, the size of this parameter must be two if 'element_type' is HYBRID.");
94  if (_block_name.size() != 0 && _block_name.size() != _block_id.size())
95  paramError("block_name", "if provided, this parameter must have the same size as 'block_id'.");
96  declareMeshProperty<unsigned int>("background_intervals_meta", _radial_intervals);
97  declareMeshProperty<dof_id_type>("node_id_background_meta",
99  declareMeshProperty<Real>("max_radius_meta", 0.0);
100  declareMeshProperty<std::vector<unsigned int>>("num_sectors_per_side_meta", {1, 1, 1, 1, 1, 1});
101  declareMeshProperty<Real>("pitch_meta", _pitch);
102 }
103 
104 std::unique_ptr<MeshBase>
106 {
107  const Real radius = _pitch / std::sqrt(3.0);
108  auto mesh = buildReplicatedMesh(2);
109  BoundaryInfo & boundary_info = mesh->get_boundary_info();
110  // In the ElemType::TRI mode, total nodes number is 6 * _radial_intervals + 1, while
111  // _radial_intervals must be trivial (1);
112  // In the ElemType::QUAD model, total nodes number is 6 * _radial_intervals, while
113  // _radial_intervals must be trivial (1);
114  // In the ElemType::HYBRID mode, total nodes number is 6 * _radial_intervals + 1.
115  std::vector<Node *> nodes(HEXAGON_NUM_SIDES * _radial_intervals +
118  {
119  // The trivial center node with node_id = 6 (HEXAGON_NUM_SIDES) * _radial_intervals
120  Point center_p = Point(0.0, 0.0, 0.0);
122  mesh->add_point(center_p, HEXAGON_NUM_SIDES * _radial_intervals);
123  }
124  // loop to create nodes by radial layers
125  for (unsigned int j = 0; j < _radial_intervals; j++)
126  // loop to create the six nodes in each layer
127  for (unsigned int i = 0; i < HEXAGON_NUM_SIDES; i++)
128  {
129  Point side_p = Point(radius * (Real)(_radial_intervals - j) / (Real)_radial_intervals *
130  sin(M_PI / ((Real)HEXAGON_NUM_SIDES / 2.0) * (Real)i),
132  cos(M_PI / ((Real)HEXAGON_NUM_SIDES / 2.0) * (Real)i),
133  0.0);
134  nodes[j * HEXAGON_NUM_SIDES + i] = mesh->add_point(side_p, j * HEXAGON_NUM_SIDES + i);
135  }
136 
138  {
139  // loop to create outer layer QUAD elements
140  // Note that the direction is from outer to inner
141  for (unsigned int j = 0; j < _radial_intervals - 1; j++)
142  {
143  // loop to create the six QUAD elements for each layer
144  for (unsigned int i = 0; i < HEXAGON_NUM_SIDES; i++)
145  {
146  Elem * elem = mesh->add_elem(new Quad4);
147  elem->set_node(0, nodes[HEXAGON_NUM_SIDES * j + i]);
148  elem->set_node(1, nodes[HEXAGON_NUM_SIDES * j + (i + 1) % HEXAGON_NUM_SIDES]);
149  elem->set_node(2, nodes[HEXAGON_NUM_SIDES * (j + 1) + (i + 1) % HEXAGON_NUM_SIDES]);
150  elem->set_node(3, nodes[HEXAGON_NUM_SIDES * (j + 1) + i]);
151  // Assign the default external boundary id if applicable so that the mesh can be used as
152  // input of `PatterneHexMeshGenerator`.
153  if (j == 0)
154  boundary_info.add_side(elem, 0, OUTER_SIDESET_ID);
155  // Default subdomain id
156  elem->subdomain_id() = 2;
157  }
158  }
159  // loop to create the six TRI elements
160  for (unsigned int i = 0; i < HEXAGON_NUM_SIDES; i++)
161  {
162  Elem * elem = mesh->add_elem(new Tri3);
163  elem->set_node(0, nodes[HEXAGON_NUM_SIDES * _radial_intervals]);
164  elem->set_node(2, nodes[HEXAGON_NUM_SIDES * (_radial_intervals - 1) + i]);
165  elem->set_node(
166  1, nodes[HEXAGON_NUM_SIDES * (_radial_intervals - 1) + (i + 1) % HEXAGON_NUM_SIDES]);
167  // Assign the default external boundary id if applicable so that the mesh can be used as input
168  // of `PatterneHexMeshGenerator`.
170  boundary_info.add_side(elem, 1, OUTER_SIDESET_ID);
171  // Default subdomain id
172  elem->subdomain_id() = 1;
173  }
174  }
175  else
176  // loop to create the two elements
177  for (unsigned int i = 0; i < HEXAGON_NUM_SIDES / 3; i++)
178  {
179  Elem * elem = mesh->add_elem(new Quad4);
180  elem->set_node(0, nodes[i * 3]);
181  elem->set_node(1, nodes[(i * 3 + 3) % HEXAGON_NUM_SIDES]);
182  elem->set_node(2, nodes[i * 3 + 2]);
183  elem->set_node(3, nodes[i * 3 + 1]);
184  // Assign the default external boundary id so that the mesh can be used as input of
185  // `PatterneHexMeshGenerator`.
186  boundary_info.add_side(elem, 1, OUTER_SIDESET_ID);
187  boundary_info.add_side(elem, 2, OUTER_SIDESET_ID);
188  boundary_info.add_side(elem, 3, OUTER_SIDESET_ID);
189  // Default subdomain id
190  elem->subdomain_id() = 1;
191  }
192 
193  // Assign customized (optional) subdomain id/name and external boundary id/name.
194  if (!_block_id.empty())
195  for (const auto & elem : mesh->active_element_ptr_range())
196  {
197  if (elem->subdomain_id() == 1)
198  elem->subdomain_id() = _block_id.front();
199  else
200  elem->subdomain_id() = _block_id.back();
201  }
202  if (!_block_name.empty())
203  for (unsigned int i = 0; i < _block_name.size(); i++)
204  mesh->subdomain_name(_block_id[i]) = _block_name[i];
205 
206  if (_boundary_id_valid)
208  if (!_external_boundary_name.empty())
209  {
210  mesh->get_boundary_info().sideset_name(
213  mesh->get_boundary_info().nodeset_name(
216  }
217 
218  mesh->prepare_for_use();
219  return dynamic_pointer_cast<MeshBase>(mesh);
220 }
static InputParameters validParams()
void addRequiredRangeCheckedParam(const std::string &name, const std::string &parsed_function, const std::string &doc_string)
CTSub CT_OPERATOR_BINARY CTMul CTCompareLess CTCompareGreater CTCompareEqual _arg template * sin(_arg) *_arg.template D< dtag >()) CT_SIMPLE_UNARY_FUNCTION(tan
const Real radius
const Real _hexagon_size
Size parameter of the hexagon.
std::unique_ptr< ReplicatedMesh > buildReplicatedMesh(unsigned int dim=libMesh::invalid_uint)
void addParam(const std::string &name, const std::initializer_list< typename T::value_type > &value, const std::string &doc_string)
const boundary_id_type _external_boundary_id
Boundary ID of the external boundary.
MeshBase & mesh
std::unique_ptr< T_DEST, T_DELETER > dynamic_pointer_cast(std::unique_ptr< T_SRC, T_DELETER > &src)
const std::vector< subdomain_id_type > _block_id
Subdomain ID of the mesh.
void changeBoundaryId(const boundary_id_type old_id, const boundary_id_type new_id, bool delete_prev)
std::string getRawNames() const
const std::vector< SubdomainName > _block_name
Subdomain Name of the mesh.
const BoundaryName _external_boundary_name
Boundary Name of the external boundary.
std::unique_ptr< MeshBase > generate() override
SimpleHexagonGenerator(const InputParameters &parameters)
static InputParameters validParams()
const PolygonSizeStyle _hexagon_size_style
Style of the size parameter.
int8_t boundary_id_type
CTSub CT_OPERATOR_BINARY CTMul CTCompareLess CTCompareGreater CTCompareEqual _arg template cos(_arg) *_arg.template D< dtag >()) CT_SIMPLE_UNARY_FUNCTION(cos
enum SimpleHexagonGenerator::ElemType _element_type
Real _pitch
Pitch size of the hexagon.
void paramError(const std::string &param, Args... args) const
This SimpleHexagonGenerator object is designed to generate a simple hexagonal mesh that only contains...
ElemType
Type of elements to build the mesh.
registerMooseObject("ReactorApp", SimpleHexagonGenerator)
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
A base class that contains common members for Reactor module mesh generators.
void addClassDescription(const std::string &doc_string)
static const std::complex< double > j(0, 1)
Complex number "j" (also known as "i")
void addRangeCheckedParam(const std::string &name, const T &value, const std::string &parsed_function, const std::string &doc_string)
const bool _boundary_id_valid
Whether external_boundary_id is provided.
const unsigned int _radial_intervals
Number of radial meshing intervals.
void ErrorVector unsigned int
void addParamNamesToGroup(const std::string &space_delim_names, const std::string group_name)
PolygonSizeStyle
An enum class for style of input polygon size.