https://mooseframework.inl.gov
PolygonMeshTrimmerBase.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 "PolygonMeshTrimmerBase.h"
12 #include "MooseMeshUtils.h"
13 #include "MathUtils.h"
14 
15 // C++ includes
16 #include <cmath> // provides round, not std::round (see http://www.cplusplus.com/reference/cmath/round/)
17 
20 {
22  params.addRequiredParam<MeshGeneratorName>("input", "The input mesh that needs to be trimmed.");
23  params.addParam<BoundaryName>("peripheral_trimming_section_boundary",
24  "Boundary formed by peripheral trimming.");
25  params.addRangeCheckedParam<short>(
26  "center_trim_starting_index",
27  "center_trim_starting_index>=0 & center_trim_starting_index<12",
28  "Index of the starting center trimming position.");
29  params.addRangeCheckedParam<short>("center_trim_ending_index",
30  "center_trim_ending_index>=0 & center_trim_ending_index<12",
31  "Index of the ending center trimming position.");
32  params.addParam<BoundaryName>("center_trimming_section_boundary",
33  "Boundary formed by center trimming (external_boundary will be "
34  "assigned if this parameter is not provided).");
35  params.addParam<BoundaryName>("external_boundary",
36  "External boundary of the input mesh prior to the trimming.");
37  params.addParam<SubdomainName>(
38  "tri_elem_subdomain_name_suffix",
39  "trimmer_tri",
40  "Suffix to the block name used for quad elements that are trimmed/converted into "
41  "triangular elements to avert degenerate quad elements");
43  "tri_elem_subdomain_shift",
44  "Customized id shift to define subdomain ids of the converted triangular elements.");
45 
46  params.addParamNamesToGroup(
47  "center_trim_starting_index center_trim_ending_index center_trimming_section_boundary",
48  "Center Trimming");
49  params.addParamNamesToGroup("peripheral_trimming_section_boundary", "Peripheral Trimming");
50  params.addParamNamesToGroup("tri_elem_subdomain_name_suffix tri_elem_subdomain_shift",
51  "Trimmed Boundary Repair");
52 
53  params.addClassDescription("This PolygonMeshTrimmerBase is the base class for "
54  "CartesianMeshTrimmer and HexagonMeshTrimmer.");
55 
56  return params;
57 }
58 
60  : PolygonMeshGeneratorBase(parameters),
61  _input_name(getParam<MeshGeneratorName>("input")),
62  _trim_peripheral_region(getParam<std::vector<unsigned short>>("trim_peripheral_region")),
63  _peripheral_trimming_section_boundary(
64  isParamValid("peripheral_trimming_section_boundary")
65  ? getParam<BoundaryName>("peripheral_trimming_section_boundary")
66  : BoundaryName()),
67  _center_trimming_section_boundary(
68  isParamValid("center_trimming_section_boundary")
69  ? getParam<BoundaryName>("center_trimming_section_boundary")
70  : BoundaryName()),
71  _external_boundary_name(isParamValid("external_boundary")
72  ? getParam<BoundaryName>("external_boundary")
73  : BoundaryName()),
74  _tri_elem_subdomain_name_suffix(getParam<SubdomainName>("tri_elem_subdomain_name_suffix")),
75  _tri_elem_subdomain_shift(isParamValid("tri_elem_subdomain_shift")
76  ? getParam<subdomain_id_type>("tri_elem_subdomain_shift")
78  _input(getMeshByName(_input_name))
79 {
80  declareMeshProperty("pattern_pitch_meta", 0.0);
81  declareMeshProperty("input_pitch_meta", 0.0);
82  declareMeshProperty("is_control_drum_meta", false);
83  if (std::accumulate(_trim_peripheral_region.begin(), _trim_peripheral_region.end(), 0) == 0 &&
85  paramError("peripheral_trimming_section_boundary",
86  "this input parameter is not used if peripheral trimming is not performed.");
87 }
88 
89 std::unique_ptr<MeshBase>
91 {
92  auto replicated_mesh_ptr = dynamic_cast<ReplicatedMesh *>(_input.get());
93  if (!replicated_mesh_ptr)
94  paramError("input", "Input is not a replicated mesh, which is required");
95 
96  ReplicatedMesh & mesh = *replicated_mesh_ptr;
97 
98  // Passing metadata
99  if (hasMeshProperty<Real>("input_pitch_meta", _input_name))
100  setMeshProperty("input_pitch_meta", getMeshProperty<Real>("input_pitch_meta", _input_name));
101  if (hasMeshProperty<bool>("is_control_drum_meta", _input_name))
102  setMeshProperty("is_control_drum_meta",
103  getMeshProperty<bool>("is_control_drum_meta", _input_name));
104 
105  const boundary_id_type external_boundary_id =
109  if (external_boundary_id == libMesh::BoundaryInfo::invalid_id)
110  paramError("external_boundary",
111  "the provided external boundary does not exist in the input mesh.");
112 
113  std::set<subdomain_id_type> subdomain_ids_set;
114  mesh.subdomain_ids(subdomain_ids_set);
115 
116  if (*max_element(_trim_peripheral_region.begin(), _trim_peripheral_region.end()))
117  {
118  const boundary_id_type peripheral_trimming_section_boundary_id =
120  ? external_boundary_id
122  .front();
125  external_boundary_id,
126  peripheral_trimming_section_boundary_id,
127  subdomain_ids_set);
128  mesh.get_boundary_info().sideset_name(peripheral_trimming_section_boundary_id) =
130  }
131  else if (hasMeshProperty<Real>("pattern_pitch_meta", _input_name))
132  setMeshProperty("pattern_pitch_meta", getMeshProperty<Real>("pattern_pitch_meta", _input_name));
133 
135  {
136  const boundary_id_type center_trimming_section_boundary_id =
138  ? external_boundary_id
140  .front();
142  _num_sides,
145  external_boundary_id,
146  center_trimming_section_boundary_id,
147  subdomain_ids_set);
148  mesh.get_boundary_info().sideset_name(center_trimming_section_boundary_id) =
150  }
151 
154  mesh.prepare_for_use();
155 
156  return std::move(_input);
157 }
158 
159 void
161  const unsigned int num_sides,
162  const unsigned int center_trim_sector_number,
163  const unsigned int trimming_start_sector,
164  const boundary_id_type external_boundary_id,
165  const boundary_id_type center_trimming_section_boundary_id,
166  const std::set<subdomain_id_type> subdomain_ids_set)
167 {
168  const subdomain_id_type max_subdomain_id = *subdomain_ids_set.rbegin();
169  const subdomain_id_type block_id_to_remove = max_subdomain_id + 1;
170 
171  std::vector<std::vector<Real>> bdry_pars = {
172  {std::cos((Real)trimming_start_sector * M_PI / (Real)num_sides),
173  std::sin((Real)trimming_start_sector * M_PI / (Real)num_sides),
174  0.0},
175  {-std::cos((Real)(trimming_start_sector + center_trim_sector_number) * M_PI /
176  (Real)num_sides),
177  -std::sin((Real)(trimming_start_sector + center_trim_sector_number) * M_PI /
178  (Real)num_sides),
179  0.0}};
180 
181  for (unsigned int i = 0; i < bdry_pars.size(); i++)
182  try
183  {
185  bdry_pars[i],
186  block_id_to_remove,
187  subdomain_ids_set,
188  center_trimming_section_boundary_id,
189  external_boundary_id);
190  }
191  catch (MooseException & e)
192  {
193  if (((std::string)e.what())
194  .compare("The input mesh has degenerate quad element before trimming.") == 0)
195  paramError("input", "The input mesh has degenerate quad element before trimming.");
196  else if (((std::string)e.what())
197  .compare("The new subdomain name already exists in the mesh.") == 0)
198  paramError("tri_elem_subdomain_name_suffix",
199  "The new subdomain name already exists in the mesh.");
200  }
201 }
202 
203 void
205  ReplicatedMesh & mesh,
206  const std::vector<unsigned short> trim_peripheral_region,
207  const boundary_id_type external_boundary_id,
208  const boundary_id_type peripheral_trimming_section_boundary_id,
209  const std::set<subdomain_id_type> subdomain_ids_set)
210 {
211  const unsigned int num_sides = trim_peripheral_region.size();
212  const subdomain_id_type max_subdomain_id = *subdomain_ids_set.rbegin();
213  const subdomain_id_type block_id_to_remove = max_subdomain_id + 1;
214 
215  const Real unit_length = getMeshProperty<Real>("input_pitch_meta", _input_name) /
216  (num_sides == 6 ? std::sqrt(3.0) : 2.0);
217  // Add metadata to input
218  const Real multiplier = ((Real)getMeshProperty<unsigned int>("pattern_size", _input_name) - 1.0) *
219  (num_sides == 6 ? 0.75 : 1.0);
220  const Real ch_length = multiplier * unit_length;
221  setMeshProperty("pattern_pitch_meta", ch_length * 2.0);
222 
223  std::vector<std::vector<Real>> bdry_pars;
224  if (num_sides == 6)
225  bdry_pars = {{1.0 / std::sqrt(3.0), 1.0, -ch_length / std::sqrt(3.0) * 2.0},
226  {-1.0 / std::sqrt(3.0), 1.0, -ch_length / std::sqrt(3.0) * 2.0},
227  {-1.0, 0.0, -ch_length},
228  {-1.0 / std::sqrt(3.0), -1.0, -ch_length / std::sqrt(3.0) * 2.0},
229  {1.0 / std::sqrt(3.0), -1.0, -ch_length / std::sqrt(3.0) * 2.0},
230  {1.0, 0.0, -ch_length}};
231  else
232  bdry_pars = {{1.0, 0.0, -ch_length},
233  {0.0, 1.0, -ch_length},
234  {-1.0, 0.0, -ch_length},
235  {0.0, -1.0, -ch_length}};
236 
237  for (unsigned int i = 0; i < bdry_pars.size(); i++)
238  if (trim_peripheral_region[i])
239  try
240  {
242  bdry_pars[i],
243  block_id_to_remove,
244  subdomain_ids_set,
245  peripheral_trimming_section_boundary_id,
246  external_boundary_id,
247  std::vector<boundary_id_type>(),
248  true);
249  }
250  catch (MooseException & e)
251  {
252  if (((std::string)e.what())
253  .compare("The input mesh has degenerate quad element before trimming.") == 0)
254  paramError("input", "The input mesh has degenerate quad element before trimming.");
255  else if (((std::string)e.what())
256  .compare("The new subdomain name already exists in the mesh.") == 0)
257  paramError("tri_elem_subdomain_name_suffix",
258  "The new subdomain name already exists in the mesh.");
259  }
260 }
std::vector< unsigned short > _trim_peripheral_region
Index of the peripheral regions to be trimmed (see moosedocs for indexing scheme) ...
const subdomain_id_type _tri_elem_subdomain_shift
Customized id shift to define subdomain ids of the converted triangular elements. ...
virtual const char * what() const
T & setMeshProperty(const std::string &data_name, Args &&... args)
unsigned int _num_sides
Number of polygon sides.
void addParam(const std::string &name, const std::initializer_list< typename T::value_type > &value, const std::string &doc_string)
void peripheralTrimmer(ReplicatedMesh &mesh, const std::vector< unsigned short > trim_peripheral_region, const boundary_id_type external_boundary_id, const boundary_id_type peripheral_trimming_section_boundary_id, const std::set< subdomain_id_type > subdomain_ids_set)
Performs peripheral trimming on the input mesh.
std::unique_ptr< MeshBase > & _input
Reference to input mesh pointer.
MeshBase & mesh
static InputParameters validParams()
void lineRemoverMoveNode(libMesh::ReplicatedMesh &mesh, const std::vector< Real > &bdry_pars, const subdomain_id_type block_id_to_remove, const std::set< subdomain_id_type > &subdomain_ids_set, const boundary_id_type trimming_section_boundary_id, const boundary_id_type external_boundary_id, const std::vector< boundary_id_type > &other_boundaries_to_conform=std::vector< boundary_id_type >(), const bool assign_ext_to_new=false, const bool side_to_remove=true)
const BoundaryName _center_trimming_section_boundary
Name of the section formed by center trimming.
std::unique_ptr< MeshBase > generate() override
void addRequiredParam(const std::string &name, const std::string &doc_string)
const SubdomainID INVALID_BLOCK_ID
BoundaryID getBoundaryID(const BoundaryName &boundary_name, const MeshBase &mesh)
static InputParameters validParams()
int8_t boundary_id_type
static const boundary_id_type invalid_id
unsigned short _center_trim_sector_number
Number of remaining sectors.
bool quasiTriElementsFixer(libMesh::ReplicatedMesh &mesh, const std::set< subdomain_id_type > &subdomain_ids_set, const subdomain_id_type tri_elem_subdomain_shift=Moose::INVALID_BLOCK_ID, const SubdomainName tri_elem_subdomain_name_suffix="tri")
std::vector< BoundaryID > getBoundaryIDs(const libMesh::MeshBase &mesh, const std::vector< BoundaryName > &boundary_name, bool generate_unknown, const std::set< BoundaryID > &mesh_boundary_ids)
void paramError(const std::string &param, Args... args) const
const BoundaryName _peripheral_trimming_section_boundary
Name of the section formed by peripheral trimming.
const BoundaryName _external_boundary_name
Name/ID of external boundary.
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
PolygonMeshTrimmerBase(const InputParameters &parameters)
A base class that contains common members for Reactor module mesh generators.
const MeshGeneratorName _input_name
Input mesh to be modified.
const SubdomainName _tri_elem_subdomain_name_suffix
SubdomainName suffix used to rename the converted triangular elements.
void addClassDescription(const std::string &doc_string)
T & declareMeshProperty(const std::string &data_name, Args &&... args)
void addRangeCheckedParam(const std::string &name, const T &value, const std::string &parsed_function, const std::string &doc_string)
short _trimming_start_sector
Index of the sector to start trimming from (counter-clockwise direction)
void centerTrimmer(ReplicatedMesh &mesh, const unsigned int num_sides, const unsigned int center_trim_sector_number, const unsigned int trimming_start_sector, const boundary_id_type external_boundary_id, const boundary_id_type center_trimming_section_boundary_id, const std::set< subdomain_id_type > subdomain_ids_set)
Performs center trimming on the input mesh.
void addParamNamesToGroup(const std::string &space_delim_names, const std::string group_name)