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  if (!mesh.preparation().has_cached_elem_data)
114  mesh.cache_elem_data();
115  std::set<subdomain_id_type> subdomain_ids_set;
116  mesh.subdomain_ids(subdomain_ids_set);
117 
118  if (*max_element(_trim_peripheral_region.begin(), _trim_peripheral_region.end()))
119  {
120  const boundary_id_type peripheral_trimming_section_boundary_id =
122  ? external_boundary_id
124  .front();
127  external_boundary_id,
128  peripheral_trimming_section_boundary_id,
129  subdomain_ids_set);
130  mesh.get_boundary_info().sideset_name(peripheral_trimming_section_boundary_id) =
132  }
133  else if (hasMeshProperty<Real>("pattern_pitch_meta", _input_name))
134  setMeshProperty("pattern_pitch_meta", getMeshProperty<Real>("pattern_pitch_meta", _input_name));
135 
137  {
138  const boundary_id_type center_trimming_section_boundary_id =
140  ? external_boundary_id
142  .front();
144  _num_sides,
147  external_boundary_id,
148  center_trimming_section_boundary_id,
149  subdomain_ids_set);
150  mesh.get_boundary_info().sideset_name(center_trimming_section_boundary_id) =
152  }
153 
156  mesh.prepare_for_use();
157 
158  return std::move(_input);
159 }
160 
161 void
163  const unsigned int num_sides,
164  const unsigned int center_trim_sector_number,
165  const unsigned int trimming_start_sector,
166  const boundary_id_type external_boundary_id,
167  const boundary_id_type center_trimming_section_boundary_id,
168  const std::set<subdomain_id_type> subdomain_ids_set)
169 {
170  const subdomain_id_type max_subdomain_id = *subdomain_ids_set.rbegin();
171  const subdomain_id_type block_id_to_remove = max_subdomain_id + 1;
172 
173  std::vector<std::vector<Real>> bdry_pars = {
174  {std::cos((Real)trimming_start_sector * M_PI / (Real)num_sides),
175  std::sin((Real)trimming_start_sector * M_PI / (Real)num_sides),
176  0.0},
177  {-std::cos((Real)(trimming_start_sector + center_trim_sector_number) * M_PI /
178  (Real)num_sides),
179  -std::sin((Real)(trimming_start_sector + center_trim_sector_number) * M_PI /
180  (Real)num_sides),
181  0.0}};
182 
183  for (unsigned int i = 0; i < bdry_pars.size(); i++)
184  try
185  {
187  bdry_pars[i],
188  block_id_to_remove,
189  subdomain_ids_set,
190  center_trimming_section_boundary_id,
191  external_boundary_id);
192  }
193  catch (MooseException & e)
194  {
195  if (((std::string)e.what())
196  .compare("The input mesh has degenerate quad element before trimming.") == 0)
197  paramError("input", "The input mesh has degenerate quad element before trimming.");
198  else if (((std::string)e.what())
199  .compare("The new subdomain name already exists in the mesh.") == 0)
200  paramError("tri_elem_subdomain_name_suffix",
201  "The new subdomain name already exists in the mesh.");
202  }
203 }
204 
205 void
207  ReplicatedMesh & mesh,
208  const std::vector<unsigned short> trim_peripheral_region,
209  const boundary_id_type external_boundary_id,
210  const boundary_id_type peripheral_trimming_section_boundary_id,
211  const std::set<subdomain_id_type> subdomain_ids_set)
212 {
213  const unsigned int num_sides = trim_peripheral_region.size();
214  const subdomain_id_type max_subdomain_id = *subdomain_ids_set.rbegin();
215  const subdomain_id_type block_id_to_remove = max_subdomain_id + 1;
216 
217  const Real unit_length = getMeshProperty<Real>("input_pitch_meta", _input_name) /
218  (num_sides == 6 ? std::sqrt(3.0) : 2.0);
219  // Add metadata to input
220  const Real multiplier = ((Real)getMeshProperty<unsigned int>("pattern_size", _input_name) - 1.0) *
221  (num_sides == 6 ? 0.75 : 1.0);
222  const Real ch_length = multiplier * unit_length;
223  setMeshProperty("pattern_pitch_meta", ch_length * 2.0);
224 
225  std::vector<std::vector<Real>> bdry_pars;
226  if (num_sides == 6)
227  bdry_pars = {{1.0 / std::sqrt(3.0), 1.0, -ch_length / std::sqrt(3.0) * 2.0},
228  {-1.0 / std::sqrt(3.0), 1.0, -ch_length / std::sqrt(3.0) * 2.0},
229  {-1.0, 0.0, -ch_length},
230  {-1.0 / std::sqrt(3.0), -1.0, -ch_length / std::sqrt(3.0) * 2.0},
231  {1.0 / std::sqrt(3.0), -1.0, -ch_length / std::sqrt(3.0) * 2.0},
232  {1.0, 0.0, -ch_length}};
233  else
234  bdry_pars = {{1.0, 0.0, -ch_length},
235  {0.0, 1.0, -ch_length},
236  {-1.0, 0.0, -ch_length},
237  {0.0, -1.0, -ch_length}};
238 
239  for (unsigned int i = 0; i < bdry_pars.size(); i++)
240  if (trim_peripheral_region[i])
241  try
242  {
244  bdry_pars[i],
245  block_id_to_remove,
246  subdomain_ids_set,
247  peripheral_trimming_section_boundary_id,
248  external_boundary_id,
249  std::vector<boundary_id_type>(),
250  true);
251  }
252  catch (MooseException & e)
253  {
254  if (((std::string)e.what())
255  .compare("The input mesh has degenerate quad element before trimming.") == 0)
256  paramError("input", "The input mesh has degenerate quad element before trimming.");
257  else if (((std::string)e.what())
258  .compare("The new subdomain name already exists in the mesh.") == 0)
259  paramError("tri_elem_subdomain_name_suffix",
260  "The new subdomain name already exists in the mesh.");
261  }
262 }
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)
void paramError(const std::string &param, Args... args) const
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)
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)