https://mooseframework.inl.gov
Loading...
Searching...
No Matches
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
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");
42 params.addParam<subdomain_id_type>(
43 "tri_elem_subdomain_shift",
44 "Customized id shift to define subdomain ids of the converted triangular elements.");
45
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")
77 : Moose::INVALID_BLOCK_ID),
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
89std::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 =
107 ? (boundary_id_type)OUTER_SIDESET_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();
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
161void
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
205void
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}
void addParamNamesToGroup(const std::string &space_delim_names, const std::string group_name)
void addRequiredParam(const std::string &name, const std::string &doc_string)
void addParam(const std::string &name, const std::initializer_list< typename T::value_type > &value, const std::string &doc_string)
void addClassDescription(const std::string &doc_string)
void addRangeCheckedParam(const std::string &name, const T &value, const std::string &parsed_function, const std::string &doc_string)
T & setMeshProperty(const std::string &data_name, Args &&... args)
T & declareMeshProperty(const std::string &data_name, Args &&... args)
void paramError(const std::string &param, Args... args) const
virtual const char * what() const
A base class that contains common members for Reactor module mesh generators.
static InputParameters validParams()
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.
unsigned short _center_trim_sector_number
Number of remaining sectors.
const SubdomainName _tri_elem_subdomain_name_suffix
SubdomainName suffix used to rename the converted triangular elements.
const MeshGeneratorName _input_name
Input mesh to be modified.
const BoundaryName _center_trimming_section_boundary
Name of the section formed by center trimming.
unsigned int _num_sides
Number of polygon sides.
std::unique_ptr< MeshBase > generate() override
std::vector< unsigned short > _trim_peripheral_region
Index of the peripheral regions to be trimmed (see moosedocs for indexing scheme)
const BoundaryName _peripheral_trimming_section_boundary
Name of the section formed by peripheral trimming.
const BoundaryName _external_boundary_name
Name/ID of external boundary.
PolygonMeshTrimmerBase(const InputParameters &parameters)
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.
short _trimming_start_sector
Index of the sector to start trimming from (counter-clockwise direction)
const subdomain_id_type _tri_elem_subdomain_shift
Customized id shift to define subdomain ids of the converted triangular elements.
static InputParameters validParams()
std::unique_ptr< MeshBase > & _input
Reference to input mesh pointer.
static const boundary_id_type invalid_id
MeshBase & mesh
std::vector< BoundaryID > getBoundaryIDs(const libMesh::MeshBase &mesh, const std::vector< BoundaryName > &boundary_name, bool generate_unknown, const std::set< BoundaryID > &mesh_boundary_ids)
BoundaryID getBoundaryID(const BoundaryName &boundary_name, const MeshBase &mesh)
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)
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")