Line data Source code
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"
11 : #include "MooseMeshXYCuttingUtils.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 :
18 : InputParameters
19 676 : PolygonMeshTrimmerBase::validParams()
20 : {
21 676 : InputParameters params = PolygonMeshGeneratorBase::validParams();
22 1352 : params.addRequiredParam<MeshGeneratorName>("input", "The input mesh that needs to be trimmed.");
23 1352 : params.addParam<BoundaryName>("peripheral_trimming_section_boundary",
24 : "Boundary formed by peripheral trimming.");
25 1352 : 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 1352 : 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 1352 : 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 1352 : params.addParam<BoundaryName>("external_boundary",
36 : "External boundary of the input mesh prior to the trimming.");
37 1352 : 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 1352 : params.addParam<subdomain_id_type>(
43 : "tri_elem_subdomain_shift",
44 : "Customized id shift to define subdomain ids of the converted triangular elements.");
45 :
46 1352 : params.addParamNamesToGroup(
47 : "center_trim_starting_index center_trim_ending_index center_trimming_section_boundary",
48 : "Center Trimming");
49 1352 : params.addParamNamesToGroup("peripheral_trimming_section_boundary", "Peripheral Trimming");
50 1352 : params.addParamNamesToGroup("tri_elem_subdomain_name_suffix tri_elem_subdomain_shift",
51 : "Trimmed Boundary Repair");
52 :
53 676 : params.addClassDescription("This PolygonMeshTrimmerBase is the base class for "
54 : "CartesianMeshTrimmer and HexagonMeshTrimmer.");
55 :
56 676 : return params;
57 0 : }
58 :
59 346 : PolygonMeshTrimmerBase::PolygonMeshTrimmerBase(const InputParameters & parameters)
60 : : PolygonMeshGeneratorBase(parameters),
61 0 : _input_name(getParam<MeshGeneratorName>("input")),
62 692 : _trim_peripheral_region(getParam<std::vector<unsigned short>>("trim_peripheral_region")),
63 552 : _peripheral_trimming_section_boundary(
64 346 : isParamValid("peripheral_trimming_section_boundary")
65 346 : ? getParam<BoundaryName>("peripheral_trimming_section_boundary")
66 : : BoundaryName()),
67 478 : _center_trimming_section_boundary(
68 346 : isParamValid("center_trimming_section_boundary")
69 346 : ? getParam<BoundaryName>("center_trimming_section_boundary")
70 : : BoundaryName()),
71 696 : _external_boundary_name(isParamValid("external_boundary")
72 346 : ? getParam<BoundaryName>("external_boundary")
73 : : BoundaryName()),
74 346 : _tri_elem_subdomain_name_suffix(getParam<SubdomainName>("tri_elem_subdomain_name_suffix")),
75 346 : _tri_elem_subdomain_shift(isParamValid("tri_elem_subdomain_shift")
76 346 : ? getParam<subdomain_id_type>("tri_elem_subdomain_shift")
77 : : Moose::INVALID_BLOCK_ID),
78 692 : _input(getMeshByName(_input_name))
79 : {
80 346 : declareMeshProperty("pattern_pitch_meta", 0.0);
81 346 : declareMeshProperty("input_pitch_meta", 0.0);
82 692 : declareMeshProperty("is_control_drum_meta", false);
83 346 : if (std::accumulate(_trim_peripheral_region.begin(), _trim_peripheral_region.end(), 0) == 0 &&
84 : !_peripheral_trimming_section_boundary.empty())
85 4 : paramError("peripheral_trimming_section_boundary",
86 : "this input parameter is not used if peripheral trimming is not performed.");
87 342 : }
88 :
89 : std::unique_ptr<MeshBase>
90 318 : PolygonMeshTrimmerBase::generate()
91 : {
92 318 : auto replicated_mesh_ptr = dynamic_cast<ReplicatedMesh *>(_input.get());
93 318 : if (!replicated_mesh_ptr)
94 0 : paramError("input", "Input is not a replicated mesh, which is required");
95 :
96 : ReplicatedMesh & mesh = *replicated_mesh_ptr;
97 :
98 : // Passing metadata
99 636 : if (hasMeshProperty<Real>("input_pitch_meta", _input_name))
100 564 : setMeshProperty("input_pitch_meta", getMeshProperty<Real>("input_pitch_meta", _input_name));
101 636 : if (hasMeshProperty<bool>("is_control_drum_meta", _input_name))
102 600 : setMeshProperty("is_control_drum_meta",
103 : getMeshProperty<bool>("is_control_drum_meta", _input_name));
104 :
105 : const boundary_id_type external_boundary_id =
106 : _external_boundary_name.empty()
107 318 : ? (boundary_id_type)OUTER_SIDESET_ID
108 4 : : MooseMeshUtils::getBoundaryID(_external_boundary_name, mesh);
109 318 : if (external_boundary_id == libMesh::BoundaryInfo::invalid_id)
110 4 : 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 314 : mesh.subdomain_ids(subdomain_ids_set);
115 :
116 314 : if (*max_element(_trim_peripheral_region.begin(), _trim_peripheral_region.end()))
117 : {
118 : const boundary_id_type peripheral_trimming_section_boundary_id =
119 : _peripheral_trimming_section_boundary.empty()
120 398 : ? external_boundary_id
121 596 : : (MooseMeshUtils::getBoundaryIDs(mesh, {_peripheral_trimming_section_boundary}, true))
122 : .front();
123 200 : peripheralTrimmer(mesh,
124 200 : _trim_peripheral_region,
125 : external_boundary_id,
126 : peripheral_trimming_section_boundary_id,
127 : subdomain_ids_set);
128 200 : mesh.get_boundary_info().sideset_name(peripheral_trimming_section_boundary_id) =
129 200 : _peripheral_trimming_section_boundary;
130 : }
131 228 : else if (hasMeshProperty<Real>("pattern_pitch_meta", _input_name))
132 192 : setMeshProperty("pattern_pitch_meta", getMeshProperty<Real>("pattern_pitch_meta", _input_name));
133 :
134 314 : if (_center_trim_sector_number < _num_sides * 2)
135 : {
136 : const boundary_id_type center_trimming_section_boundary_id =
137 : _center_trimming_section_boundary.empty()
138 260 : ? external_boundary_id
139 388 : : (MooseMeshUtils::getBoundaryIDs(mesh, {_center_trimming_section_boundary}, true))
140 : .front();
141 268 : centerTrimmer(mesh,
142 : _num_sides,
143 132 : _center_trim_sector_number,
144 132 : _trimming_start_sector,
145 : external_boundary_id,
146 : center_trimming_section_boundary_id,
147 : subdomain_ids_set);
148 132 : mesh.get_boundary_info().sideset_name(center_trimming_section_boundary_id) =
149 132 : _center_trimming_section_boundary;
150 : }
151 :
152 310 : if (MooseMeshXYCuttingUtils::quasiTriElementsFixer(
153 314 : mesh, subdomain_ids_set, _tri_elem_subdomain_shift, _tri_elem_subdomain_name_suffix))
154 81 : mesh.prepare_for_use();
155 :
156 306 : return std::move(_input);
157 : }
158 :
159 : void
160 132 : PolygonMeshTrimmerBase::centerTrimmer(ReplicatedMesh & mesh,
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 132 : const subdomain_id_type max_subdomain_id = *subdomain_ids_set.rbegin();
169 132 : const subdomain_id_type block_id_to_remove = max_subdomain_id + 1;
170 :
171 : std::vector<std::vector<Real>> bdry_pars = {
172 132 : {std::cos((Real)trimming_start_sector * M_PI / (Real)num_sides),
173 132 : std::sin((Real)trimming_start_sector * M_PI / (Real)num_sides),
174 : 0.0},
175 132 : {-std::cos((Real)(trimming_start_sector + center_trim_sector_number) * M_PI /
176 : (Real)num_sides),
177 132 : -std::sin((Real)(trimming_start_sector + center_trim_sector_number) * M_PI /
178 : (Real)num_sides),
179 396 : 0.0}};
180 :
181 396 : for (unsigned int i = 0; i < bdry_pars.size(); i++)
182 : try
183 : {
184 264 : MooseMeshXYCuttingUtils::lineRemoverMoveNode(mesh,
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 0 : catch (MooseException & e)
192 : {
193 0 : if (((std::string)e.what())
194 0 : .compare("The input mesh has degenerate quad element before trimming.") == 0)
195 0 : paramError("input", "The input mesh has degenerate quad element before trimming.");
196 0 : else if (((std::string)e.what())
197 0 : .compare("The new subdomain name already exists in the mesh.") == 0)
198 0 : paramError("tri_elem_subdomain_name_suffix",
199 : "The new subdomain name already exists in the mesh.");
200 0 : }
201 396 : }
202 :
203 : void
204 200 : PolygonMeshTrimmerBase::peripheralTrimmer(
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 200 : const unsigned int num_sides = trim_peripheral_region.size();
212 200 : const subdomain_id_type max_subdomain_id = *subdomain_ids_set.rbegin();
213 200 : const subdomain_id_type block_id_to_remove = max_subdomain_id + 1;
214 :
215 200 : const Real unit_length = getMeshProperty<Real>("input_pitch_meta", _input_name) /
216 308 : (num_sides == 6 ? std::sqrt(3.0) : 2.0);
217 : // Add metadata to input
218 200 : const Real multiplier = ((Real)getMeshProperty<unsigned int>("pattern_size", _input_name) - 1.0) *
219 308 : (num_sides == 6 ? 0.75 : 1.0);
220 200 : const Real ch_length = multiplier * unit_length;
221 400 : setMeshProperty("pattern_pitch_meta", ch_length * 2.0);
222 :
223 : std::vector<std::vector<Real>> bdry_pars;
224 200 : if (num_sides == 6)
225 644 : 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 644 : {1.0, 0.0, -ch_length}};
231 : else
232 540 : bdry_pars = {{1.0, 0.0, -ch_length},
233 : {0.0, 1.0, -ch_length},
234 : {-1.0, 0.0, -ch_length},
235 540 : {0.0, -1.0, -ch_length}};
236 :
237 1184 : for (unsigned int i = 0; i < bdry_pars.size(); i++)
238 984 : if (trim_peripheral_region[i])
239 : try
240 : {
241 663 : MooseMeshXYCuttingUtils::lineRemoverMoveNode(mesh,
242 : bdry_pars[i],
243 : block_id_to_remove,
244 : subdomain_ids_set,
245 : peripheral_trimming_section_boundary_id,
246 : external_boundary_id,
247 663 : std::vector<boundary_id_type>(),
248 : true);
249 : }
250 0 : catch (MooseException & e)
251 : {
252 0 : if (((std::string)e.what())
253 0 : .compare("The input mesh has degenerate quad element before trimming.") == 0)
254 0 : paramError("input", "The input mesh has degenerate quad element before trimming.");
255 0 : else if (((std::string)e.what())
256 0 : .compare("The new subdomain name already exists in the mesh.") == 0)
257 0 : paramError("tri_elem_subdomain_name_suffix",
258 : "The new subdomain name already exists in the mesh.");
259 0 : }
260 600 : }
|