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 "SCMTriInterWrapperMeshGenerator.h"
11 : #include "TriInterWrapperMesh.h"
12 : #include <cmath>
13 : #include "libmesh/edge_edge2.h"
14 : #include "libmesh/unstructured_mesh.h"
15 :
16 : registerMooseObject("SubChannelApp", SCMTriInterWrapperMeshGenerator);
17 : registerMooseObjectRenamed("SubChannelApp",
18 : TriInterWrapperMeshGenerator,
19 : "06/30/2025 24:00",
20 : SCMTriInterWrapperMeshGenerator);
21 :
22 : InputParameters
23 96 : SCMTriInterWrapperMeshGenerator::validParams()
24 : {
25 96 : InputParameters params = MeshGenerator::validParams();
26 96 : params.addClassDescription(
27 : "Creates a mesh for the inter-wrapper around triangular subassemblies");
28 192 : params.addRequiredParam<unsigned int>("n_cells", "The number of cells in the axial direction");
29 192 : params.addRequiredParam<Real>("assembly_pitch", "Pitch [m]");
30 192 : params.addParam<Real>("unheated_length_entry", 0.0, "Unheated length at entry [m]");
31 192 : params.addRequiredParam<Real>("heated_length", "Heated length [m]");
32 192 : params.addParam<Real>("unheated_length_exit", 0.0, "Unheated length at exit [m]");
33 192 : params.addRequiredParam<unsigned int>("nrings", "Number of fuel Pin rings per assembly [-]");
34 192 : params.addRequiredParam<Real>("flat_to_flat",
35 : "Flat to flat distance for the hexagonal assembly [m]");
36 192 : params.addParam<Real>("Kij", 0.5, "Lateral form loss coefficient [-]");
37 192 : params.addRequiredParam<Real>("side_bypass",
38 : "Extra size of the bypass for the side assemblies [m]");
39 192 : params.addParam<bool>(
40 : "tight_side_bypass",
41 192 : false,
42 : "Whether the side bypass shape follows the hexagonal shape of the assemblies");
43 96 : return params;
44 0 : }
45 :
46 48 : SCMTriInterWrapperMeshGenerator::SCMTriInterWrapperMeshGenerator(const InputParameters & params)
47 : : MeshGenerator(params),
48 48 : _unheated_length_entry(getParam<Real>("unheated_length_entry")),
49 96 : _heated_length(getParam<Real>("heated_length")),
50 96 : _unheated_length_exit(getParam<Real>("unheated_length_exit")),
51 96 : _kij(getParam<Real>("Kij")),
52 96 : _assembly_pitch(getParam<Real>("assembly_pitch")),
53 96 : _n_cells(getParam<unsigned int>("n_cells")),
54 96 : _n_rings(getParam<unsigned int>("nrings")),
55 96 : _flat_to_flat(getParam<Real>("flat_to_flat")),
56 96 : _duct_to_pin_gap(getParam<Real>("side_bypass")),
57 144 : _tight_side_bypass(getParam<bool>("tight_side_bypass"))
58 : {
59 :
60 48 : InterWrapperMesh::generateZGrid(
61 48 : _unheated_length_entry, _heated_length, _unheated_length_exit, _n_cells, _z_grid);
62 :
63 : // compute the hex mesh variables
64 : // -------------------------------------------
65 :
66 : // x coordinate for the first position
67 : Real x0 = 0.0;
68 : // y coordinate for the first position
69 : Real y0 = 0.0;
70 : // x coordinate for the second position
71 : Real x1 = 0.0;
72 : // y coordinate for the second position dummy variable
73 : Real y1 = 0.0;
74 : // dummy variable
75 : Real a1 = 0.0;
76 : // dummy variable
77 : Real a2 = 0.0;
78 : // average x coordinate
79 : Real avg_coor_x = 0.0;
80 : // average y coordinate
81 : Real avg_coor_y = 0.0;
82 : // distance between two points
83 : Real dist = 0.0;
84 : // distance between two points
85 : Real dist0 = 0.0;
86 : // integer counter
87 48 : unsigned int kgap = 0;
88 : // dummy integer
89 : unsigned int icorner = 0;
90 : // used to defined global direction of the cross_flow_map coefficients for each subchannel and gap
91 48 : const Real positive_flow = 1.0;
92 : // used to defined global direction of the cross_flow_map coefficients for each subchannel and gap
93 : const Real negative_flow = -1.0;
94 : // the indicator used while setting _gap_to_chan_map array
95 : std::vector<std::pair<unsigned int, unsigned int>> gap_fill;
96 48 : TriInterWrapperMesh::rodPositions(_pin_position, _n_rings, _assembly_pitch, Point(0, 0));
97 48 : _n_assemblies = _pin_position.size();
98 : // assign the assemblies to the corresponding rings
99 : // TODO: add corner to the hexagonal assemblies
100 : unsigned int k = 0; // initialize the fuel assembly counter index
101 48 : _pins_in_rings.resize(_n_rings);
102 48 : _pins_in_rings[0].push_back(k++);
103 153 : for (unsigned int i = 1; i < _n_rings; i++)
104 1131 : for (unsigned int j = 0; j < i * 6; j++)
105 1026 : _pins_in_rings[i].push_back(k++);
106 : // Given the number of pins and number of fuel Pin rings, the number of subchannels can be
107 : // computed as follows:
108 : unsigned int chancount = 0.0;
109 153 : for (unsigned int j = 0; j < _n_rings - 1; j++)
110 105 : chancount += j * 6;
111 48 : _n_channels = chancount + _n_assemblies - 1 + (_n_rings - 1) * 6 + 6;
112 :
113 : // Defining the array for axial resistances
114 48 : _k_grid.resize(_n_channels, std::vector<Real>(_n_cells + 1));
115 :
116 : /// Re-sizing the object lists with the right number of channels
117 48 : _chan_to_pin_map.resize(_n_channels);
118 48 : _subch_type.resize(_n_channels);
119 48 : _n_gaps = _n_channels + _n_assemblies - 1; /// initial assignment
120 48 : _gap_to_chan_map.resize(_n_gaps);
121 48 : gap_fill.resize(_n_gaps);
122 48 : _chan_to_gap_map.resize(_n_channels);
123 48 : _gap_pairs_sf.resize(_n_channels);
124 48 : _chan_pairs_sf.resize(_n_channels);
125 48 : _gij_map.resize(_n_gaps);
126 48 : _sign_id_crossflow_map.resize(_n_channels);
127 48 : _gap_to_pin_map.resize(_n_gaps);
128 48 : _gap_type.resize(_n_gaps);
129 48 : _subchannel_position.resize(_n_channels);
130 :
131 2388 : for (unsigned int i = 0; i < _n_channels; i++)
132 : {
133 2340 : _chan_to_pin_map[i].reserve(3);
134 2340 : _chan_to_gap_map[i].reserve(3);
135 2340 : _sign_id_crossflow_map[i].reserve(3);
136 2340 : _subchannel_position[i].reserve(3);
137 9360 : for (unsigned int j = 0; j < 3; j++)
138 : {
139 7020 : _sign_id_crossflow_map.at(i).push_back(positive_flow);
140 7020 : _subchannel_position.at(i).push_back(0.0);
141 : }
142 : } // i
143 :
144 : // create the subchannels
145 : k = 0; // initialize the subchannel counter index
146 : kgap = 0;
147 : // for each ring we trace the subchannels by pairing up to neighbor pins and looking for the third
148 : // Pin at inner or outer ring compared to the current ring.
149 153 : for (unsigned int i = 1; i < _n_rings; i++)
150 : {
151 : // find the closest Pin at back ring
152 1131 : for (unsigned int j = 0; j < _pins_in_rings[i].size(); j++)
153 : {
154 1026 : if (j == _pins_in_rings[i].size() - 1)
155 : {
156 105 : _chan_to_pin_map[k].push_back(_pins_in_rings[i][j]);
157 105 : _chan_to_pin_map[k].push_back(_pins_in_rings[i][0]);
158 105 : avg_coor_x =
159 105 : 0.5 * (_pin_position[_pins_in_rings[i][j]](0) + _pin_position[_pins_in_rings[i][0]](0));
160 105 : avg_coor_y =
161 105 : 0.5 * (_pin_position[_pins_in_rings[i][j]](1) + _pin_position[_pins_in_rings[i][0]](1));
162 105 : _gap_to_pin_map[kgap].first = _pins_in_rings[i][0];
163 105 : _gap_to_pin_map[kgap].second = _pins_in_rings[i][j];
164 105 : _gap_type[kgap] = EChannelType::CENTER;
165 105 : kgap = kgap + 1;
166 : }
167 : else
168 : {
169 921 : _chan_to_pin_map[k].push_back(_pins_in_rings[i][j]);
170 921 : _chan_to_pin_map[k].push_back(_pins_in_rings[i][j + 1]);
171 921 : avg_coor_x = 0.5 * (_pin_position[_pins_in_rings[i][j]](0) +
172 921 : _pin_position[_pins_in_rings[i][j + 1]](0));
173 921 : avg_coor_y = 0.5 * (_pin_position[_pins_in_rings[i][j]](1) +
174 921 : _pin_position[_pins_in_rings[i][j + 1]](1));
175 921 : _gap_to_pin_map[kgap].first = _pins_in_rings[i][j];
176 921 : _gap_to_pin_map[kgap].second = _pins_in_rings[i][j + 1];
177 921 : _gap_type[kgap] = EChannelType::CENTER;
178 921 : kgap = kgap + 1;
179 : }
180 :
181 : dist0 = 1.0e+5;
182 :
183 1026 : _chan_to_pin_map[k].push_back(_pins_in_rings[i - 1][0]);
184 : unsigned int l0 = 0;
185 :
186 6714 : for (unsigned int l = 0; l < _pins_in_rings[i - 1].size(); l++)
187 : {
188 5688 : dist = std::sqrt(pow(_pin_position[_pins_in_rings[i - 1][l]](0) - avg_coor_x, 2) +
189 5688 : pow(_pin_position[_pins_in_rings[i - 1][l]](1) - avg_coor_y, 2));
190 :
191 5688 : if (dist < dist0)
192 : {
193 2508 : _chan_to_pin_map[k][2] = _pins_in_rings[i - 1][l];
194 : l0 = l;
195 : dist0 = dist;
196 : } // if
197 : } // l
198 :
199 1026 : _gap_to_pin_map[kgap].first = _pins_in_rings[i][j];
200 1026 : _gap_to_pin_map[kgap].second = _pins_in_rings[i - 1][l0];
201 1026 : _gap_type[kgap] = EChannelType::CENTER;
202 1026 : kgap = kgap + 1;
203 1026 : _subch_type[k] = EChannelType::CENTER;
204 1026 : k = k + 1;
205 :
206 : } // for j
207 :
208 : // find the closest Pin at front ring
209 :
210 1131 : for (unsigned int j = 0; j < _pins_in_rings[i].size(); j++)
211 : {
212 1026 : if (j == _pins_in_rings[i].size() - 1)
213 : {
214 105 : _chan_to_pin_map[k].push_back(_pins_in_rings[i][j]);
215 105 : _chan_to_pin_map[k].push_back(_pins_in_rings[i][0]);
216 105 : avg_coor_x =
217 105 : 0.5 * (_pin_position[_pins_in_rings[i][j]](0) + _pin_position[_pins_in_rings[i][0]](0));
218 105 : avg_coor_y =
219 105 : 0.5 * (_pin_position[_pins_in_rings[i][j]](1) + _pin_position[_pins_in_rings[i][0]](1));
220 : }
221 : else
222 : {
223 921 : _chan_to_pin_map[k].push_back(_pins_in_rings[i][j]);
224 921 : _chan_to_pin_map[k].push_back(_pins_in_rings[i][j + 1]);
225 921 : avg_coor_x = 0.5 * (_pin_position[_pins_in_rings[i][j]](0) +
226 921 : _pin_position[_pins_in_rings[i][j + 1]](0));
227 921 : avg_coor_y = 0.5 * (_pin_position[_pins_in_rings[i][j]](1) +
228 921 : _pin_position[_pins_in_rings[i][j + 1]](1));
229 : }
230 :
231 : // if the outermost ring, set the edge subchannels first... then the corner subchannels
232 1026 : if (i == _n_rings - 1)
233 : {
234 : // add edges
235 630 : _subch_type[k] = EChannelType::EDGE; // an edge subchannel is created
236 630 : _gap_to_pin_map[kgap].first = _pins_in_rings[i][j];
237 630 : _gap_to_pin_map[kgap].second = _pins_in_rings[i][j];
238 630 : _gap_type[kgap] = EChannelType::EDGE;
239 630 : _chan_to_gap_map[k].push_back(kgap);
240 630 : kgap = kgap + 1;
241 630 : k = k + 1;
242 :
243 630 : if (j % i == 0)
244 : {
245 : // generate a corner subchannel, generate the additional gap and fix chan_to_gap_map
246 288 : _gap_to_pin_map[kgap].first = _pins_in_rings[i][j];
247 288 : _gap_to_pin_map[kgap].second = _pins_in_rings[i][j];
248 288 : _gap_type[kgap] = EChannelType::CORNER;
249 :
250 : // corner subchannel
251 288 : _chan_to_pin_map[k].push_back(_pins_in_rings[i][j]);
252 : // corner subchannel-dummy added to hinder array size violations
253 288 : _chan_to_pin_map[k].push_back(_pins_in_rings[i][j]);
254 288 : _chan_to_gap_map[k].push_back(kgap - 1);
255 288 : _chan_to_gap_map[k].push_back(kgap);
256 288 : _subch_type[k] = EChannelType::CORNER;
257 :
258 288 : kgap = kgap + 1;
259 288 : k = k + 1;
260 : }
261 : // if not the outer most ring
262 : }
263 : else
264 : {
265 : dist0 = 1.0e+5;
266 : unsigned int l0 = 0;
267 396 : _chan_to_pin_map[k].push_back(_pins_in_rings[i + 1][0]);
268 5796 : for (unsigned int l = 0; l < _pins_in_rings[i + 1].size(); l++)
269 : {
270 5400 : dist = std::sqrt(pow(_pin_position[_pins_in_rings[i + 1][l]](0) - avg_coor_x, 2) +
271 5400 : pow(_pin_position[_pins_in_rings[i + 1][l]](1) - avg_coor_y, 2));
272 5400 : if (dist < dist0)
273 : {
274 1896 : _chan_to_pin_map[k][2] = _pins_in_rings[i + 1][l];
275 : dist0 = dist;
276 : l0 = l;
277 : } // if
278 : } // l
279 :
280 396 : _gap_to_pin_map[kgap].first = _pins_in_rings[i][j];
281 396 : _gap_to_pin_map[kgap].second = _pins_in_rings[i + 1][l0];
282 396 : _gap_type[kgap] = EChannelType::CENTER;
283 396 : kgap = kgap + 1;
284 396 : _subch_type[k] = EChannelType::CENTER;
285 396 : k = k + 1;
286 : } // if
287 : } // for j
288 : } // for i
289 :
290 : // find the _gap_to_chan_map and _chan_to_gap_map using the gap_to_rod and subchannel_to_rod_maps
291 :
292 2388 : for (unsigned int i = 0; i < _n_channels; i++)
293 : {
294 2340 : if (_subch_type[i] == EChannelType::CENTER)
295 : {
296 112986 : for (unsigned int j = 0; j < _n_gaps; j++)
297 : {
298 111564 : if (_gap_type[j] == EChannelType::CENTER)
299 : {
300 86688 : if (((_chan_to_pin_map[i][0] == _gap_to_pin_map[j].first) &&
301 83052 : (_chan_to_pin_map[i][1] == _gap_to_pin_map[j].second)) ||
302 81792 : ((_chan_to_pin_map[i][0] == _gap_to_pin_map[j].second) &&
303 3348 : (_chan_to_pin_map[i][1] == _gap_to_pin_map[j].first)))
304 : {
305 1422 : _chan_to_gap_map[i].push_back(j);
306 : }
307 :
308 86688 : if (((_chan_to_pin_map[i][0] == _gap_to_pin_map[j].first) &&
309 83052 : (_chan_to_pin_map[i][2] == _gap_to_pin_map[j].second)) ||
310 81630 : ((_chan_to_pin_map[i][0] == _gap_to_pin_map[j].second) &&
311 3348 : (_chan_to_pin_map[i][2] == _gap_to_pin_map[j].first)))
312 : {
313 1422 : _chan_to_gap_map[i].push_back(j);
314 : }
315 :
316 86688 : if (((_chan_to_pin_map[i][1] == _gap_to_pin_map[j].first) &&
317 83052 : (_chan_to_pin_map[i][2] == _gap_to_pin_map[j].second)) ||
318 82422 : ((_chan_to_pin_map[i][1] == _gap_to_pin_map[j].second) &&
319 3348 : (_chan_to_pin_map[i][2] == _gap_to_pin_map[j].first)))
320 : {
321 1422 : _chan_to_gap_map[i].push_back(j);
322 : }
323 : }
324 : } // for j
325 : }
326 918 : else if (_subch_type[i] == EChannelType::EDGE)
327 : {
328 47178 : for (unsigned int j = 0; j < _n_gaps; j++)
329 : {
330 46548 : if (_gap_type[j] == EChannelType::CENTER)
331 : {
332 35496 : if (((_chan_to_pin_map[i][0] == _gap_to_pin_map[j].first) &&
333 34236 : (_chan_to_pin_map[i][1] == _gap_to_pin_map[j].second)) ||
334 33654 : ((_chan_to_pin_map[i][0] == _gap_to_pin_map[j].second) &&
335 972 : (_chan_to_pin_map[i][1] == _gap_to_pin_map[j].first)))
336 : {
337 630 : _chan_to_gap_map[i].push_back(j);
338 : }
339 : }
340 : }
341 :
342 : icorner = 0;
343 29997 : for (unsigned int k = 0; k < _n_channels; k++)
344 : {
345 29655 : if (_subch_type[k] == EChannelType::CORNER &&
346 3060 : _chan_to_pin_map[i][1] == _chan_to_pin_map[k][0])
347 : {
348 288 : _chan_to_gap_map[i].push_back(_chan_to_gap_map[k][1]);
349 : icorner = 1;
350 : break;
351 : } // if
352 : } // for
353 :
354 29997 : for (unsigned int k = 0; k < _n_channels; k++)
355 : {
356 29655 : if (_subch_type[k] == EChannelType::CORNER &&
357 3060 : _chan_to_pin_map[i][0] == _chan_to_pin_map[k][0])
358 : {
359 288 : _chan_to_gap_map[i].push_back(_chan_to_gap_map[k][1] + 1);
360 : icorner = 1;
361 : break;
362 : }
363 : }
364 :
365 342 : if (icorner == 0)
366 : {
367 54 : _chan_to_gap_map[i].push_back(_chan_to_gap_map[i][0] + 1);
368 : }
369 : }
370 : }
371 :
372 : // find gap_to_chan_map pair
373 :
374 3414 : for (unsigned int j = 0; j < _n_gaps; j++)
375 : {
376 181674 : for (unsigned int i = 0; i < _n_channels; i++)
377 : {
378 178308 : if (_subch_type[i] == EChannelType::CENTER || _subch_type[i] == EChannelType::EDGE)
379 : {
380 158112 : if ((j == _chan_to_gap_map[i][0]) || (j == _chan_to_gap_map[i][1]) ||
381 154008 : (j == _chan_to_gap_map[i][2]))
382 : {
383 6156 : if (_gap_to_chan_map[j].first == 0 && gap_fill[j].first == 0)
384 : {
385 3318 : _gap_to_chan_map[j].first = i;
386 3318 : gap_fill[j].first = 1;
387 : }
388 2838 : else if (_gap_to_chan_map[j].second == 0 && gap_fill[j].second == 0)
389 : {
390 2838 : _gap_to_chan_map[j].second = i;
391 2838 : gap_fill[j].second = 1;
392 : }
393 : else
394 : {
395 : }
396 : }
397 : }
398 20196 : else if (_subch_type[i] == EChannelType::CORNER)
399 : {
400 20196 : if ((j == _chan_to_gap_map[i][0]) || (j == _chan_to_gap_map[i][1]))
401 : {
402 576 : if (_gap_to_chan_map[j].first == 0 && gap_fill[j].first == 0)
403 : {
404 48 : _gap_to_chan_map[j].first = i;
405 48 : gap_fill[j].first = 1;
406 : }
407 528 : else if (_gap_to_chan_map[j].second == 0 && gap_fill[j].second == 0)
408 : {
409 528 : _gap_to_chan_map[j].second = i;
410 528 : gap_fill[j].second = 1;
411 : }
412 : else
413 : {
414 : }
415 : }
416 : }
417 : } // i
418 : } // j
419 :
420 2388 : for (unsigned int k = 0; k < _n_channels; k++)
421 : {
422 2340 : if (_subch_type[k] == EChannelType::EDGE)
423 : {
424 630 : _gap_pairs_sf[k].first = _chan_to_gap_map[k][0];
425 630 : _gap_pairs_sf[k].second = _chan_to_gap_map[k][2];
426 : auto k1 = _gap_pairs_sf[k].first;
427 : auto k2 = _gap_pairs_sf[k].second;
428 630 : if (_gap_to_chan_map[k1].first == k)
429 : {
430 288 : _chan_pairs_sf[k].first = _gap_to_chan_map[k1].second;
431 : }
432 : else
433 : {
434 342 : _chan_pairs_sf[k].first = _gap_to_chan_map[k1].first;
435 : }
436 :
437 630 : if (_gap_to_chan_map[k2].first == k)
438 : {
439 582 : _chan_pairs_sf[k].second = _gap_to_chan_map[k2].second;
440 : }
441 : else
442 : {
443 48 : _chan_pairs_sf[k].second = _gap_to_chan_map[k2].first;
444 : }
445 : }
446 1710 : else if (_subch_type[k] == EChannelType::CORNER)
447 : {
448 288 : _gap_pairs_sf[k].first = _chan_to_gap_map[k][1];
449 288 : _gap_pairs_sf[k].second = _chan_to_gap_map[k][0];
450 :
451 : auto k1 = _gap_pairs_sf[k].first;
452 : auto k2 = _gap_pairs_sf[k].second;
453 :
454 288 : if (_gap_to_chan_map[k1].first == k)
455 : {
456 48 : _chan_pairs_sf[k].first = _gap_to_chan_map[k1].second;
457 : }
458 : else
459 : {
460 240 : _chan_pairs_sf[k].first = _gap_to_chan_map[k1].first;
461 : }
462 :
463 288 : if (_gap_to_chan_map[k2].first == k)
464 : {
465 0 : _chan_pairs_sf[k].second = _gap_to_chan_map[k2].second;
466 : }
467 : else
468 : {
469 288 : _chan_pairs_sf[k].second = _gap_to_chan_map[k2].first;
470 : }
471 : }
472 : }
473 :
474 : // set the _gij_map
475 :
476 3414 : for (unsigned int j = 0; j < _n_gaps; j++)
477 : {
478 3366 : if (_gap_type[j] == EChannelType::CENTER)
479 : {
480 2448 : _gij_map[j] = _assembly_pitch - _flat_to_flat;
481 : }
482 918 : else if (_gap_type[j] == EChannelType::EDGE || _gap_type[j] == EChannelType::CORNER)
483 : {
484 918 : _gij_map[j] = _duct_to_pin_gap;
485 : }
486 : }
487 2388 : for (unsigned int i = 0; i < _n_channels; i++)
488 : {
489 2340 : if (_subch_type[i] == EChannelType::CENTER || _subch_type[i] == EChannelType::EDGE)
490 : {
491 8208 : for (unsigned int k = 0; k < 3; k++)
492 : {
493 480492 : for (unsigned int j = 0; j < _n_gaps; j++)
494 : {
495 474336 : if (_chan_to_gap_map[i][k] == j && i == _gap_to_chan_map[j].first)
496 : {
497 3318 : if (i > _gap_to_chan_map[j].second)
498 : {
499 0 : _sign_id_crossflow_map[i][k] = negative_flow;
500 : }
501 : else
502 : {
503 3318 : _sign_id_crossflow_map[i][k] = positive_flow;
504 : }
505 : }
506 471018 : else if (_chan_to_gap_map[i][k] == j && i == _gap_to_chan_map[j].second)
507 : {
508 2838 : if (i > _gap_to_chan_map[j].first)
509 : {
510 2838 : _sign_id_crossflow_map[i][k] = negative_flow;
511 : }
512 : else
513 : {
514 0 : _sign_id_crossflow_map[i][k] = positive_flow;
515 : }
516 : }
517 : } // j
518 : } // k
519 : }
520 288 : else if (_subch_type[i] == EChannelType::CORNER)
521 : {
522 864 : for (unsigned int k = 0; k < 2; k++)
523 : {
524 40968 : for (unsigned int j = 0; j < _n_gaps; j++)
525 : {
526 40392 : if (_chan_to_gap_map[i][k] == j && i == _gap_to_chan_map[j].first)
527 : {
528 48 : if (i > _gap_to_chan_map[j].second)
529 : {
530 0 : _sign_id_crossflow_map[i][k] = negative_flow;
531 : }
532 : else
533 : {
534 48 : _sign_id_crossflow_map[i][k] = positive_flow;
535 : }
536 : }
537 40344 : else if (_chan_to_gap_map[i][k] == j && i == _gap_to_chan_map[j].second)
538 : {
539 528 : if (i > _gap_to_chan_map[j].first)
540 : {
541 528 : _sign_id_crossflow_map[i][k] = negative_flow;
542 : }
543 : else
544 : {
545 0 : _sign_id_crossflow_map[i][k] = positive_flow;
546 : }
547 : }
548 : } // j
549 : } // k
550 : } // subch_type =2
551 : } // i
552 :
553 : // set the subchannel positions
554 2388 : for (unsigned int i = 0; i < _n_channels; i++)
555 : {
556 2340 : if (_subch_type[i] == EChannelType::CENTER)
557 : {
558 1422 : _subchannel_position[i][0] =
559 1422 : (_pin_position[_chan_to_pin_map[i][0]](0) + _pin_position[_chan_to_pin_map[i][1]](0) +
560 1422 : _pin_position[_chan_to_pin_map[i][2]](0)) /
561 : 3.0;
562 1422 : _subchannel_position[i][1] =
563 1422 : (_pin_position[_chan_to_pin_map[i][0]](1) + _pin_position[_chan_to_pin_map[i][1]](1) +
564 1422 : _pin_position[_chan_to_pin_map[i][2]](1)) /
565 : 3.0;
566 : }
567 918 : else if (_subch_type[i] == EChannelType::EDGE)
568 : {
569 32922 : for (unsigned int j = 0; j < _n_channels; j++)
570 : {
571 32292 : if (_subch_type[j] == EChannelType::CENTER &&
572 19980 : ((_chan_to_pin_map[i][0] == _chan_to_pin_map[j][0] &&
573 630 : _chan_to_pin_map[i][1] == _chan_to_pin_map[j][1]) ||
574 19350 : (_chan_to_pin_map[i][0] == _chan_to_pin_map[j][1] &&
575 630 : _chan_to_pin_map[i][1] == _chan_to_pin_map[j][0])))
576 : {
577 630 : x0 = _pin_position[_chan_to_pin_map[j][2]](0);
578 630 : y0 = _pin_position[_chan_to_pin_map[j][2]](1);
579 : }
580 31662 : else if (_subch_type[j] == EChannelType::CENTER &&
581 19350 : ((_chan_to_pin_map[i][0] == _chan_to_pin_map[j][0] &&
582 0 : _chan_to_pin_map[i][1] == _chan_to_pin_map[j][2]) ||
583 19350 : (_chan_to_pin_map[i][0] == _chan_to_pin_map[j][2] &&
584 342 : _chan_to_pin_map[i][1] == _chan_to_pin_map[j][0])))
585 : {
586 0 : x0 = _pin_position[_chan_to_pin_map[j][1]](0);
587 0 : y0 = _pin_position[_chan_to_pin_map[j][1]](1);
588 : }
589 31662 : else if (_subch_type[j] == EChannelType::CENTER &&
590 19350 : ((_chan_to_pin_map[i][0] == _chan_to_pin_map[j][1] &&
591 630 : _chan_to_pin_map[i][1] == _chan_to_pin_map[j][2]) ||
592 19350 : (_chan_to_pin_map[i][0] == _chan_to_pin_map[j][2] &&
593 342 : _chan_to_pin_map[i][1] == _chan_to_pin_map[j][1])))
594 : {
595 0 : x0 = _pin_position[_chan_to_pin_map[j][0]](0);
596 0 : y0 = _pin_position[_chan_to_pin_map[j][0]](1);
597 : }
598 32292 : x1 = 0.5 *
599 32292 : (_pin_position[_chan_to_pin_map[i][0]](0) + _pin_position[_chan_to_pin_map[i][1]](0));
600 32292 : y1 = 0.5 *
601 32292 : (_pin_position[_chan_to_pin_map[i][0]](1) + _pin_position[_chan_to_pin_map[i][1]](1));
602 32292 : if (_tight_side_bypass)
603 3024 : a1 = _flat_to_flat * std::tan(libMesh::pi / 6.0) / 2.0 + _duct_to_pin_gap / 2.0;
604 : else
605 29268 : a1 = _flat_to_flat / 2.0 + _duct_to_pin_gap / 2.0;
606 32292 : a2 = std::sqrt((x1 - x0) * (x1 - x0) + (y1 - y0) * (y1 - y0)) + a1;
607 32292 : _subchannel_position[i][0] = (a2 * x1 - a1 * x0) / (a2 - a1);
608 32292 : _subchannel_position[i][1] = (a2 * y1 - a1 * y0) / (a2 - a1);
609 : } // j
610 : }
611 288 : else if (_subch_type[i] == EChannelType::CORNER)
612 : {
613 288 : x0 = _pin_position[0](0);
614 288 : y0 = _pin_position[0](1);
615 288 : x1 = _pin_position[_chan_to_pin_map[i][0]](0);
616 288 : y1 = _pin_position[_chan_to_pin_map[i][0]](1);
617 288 : a1 = _flat_to_flat / 2.0 + _duct_to_pin_gap / 2.0;
618 288 : a2 = std::sqrt((x1 - x0) * (x1 - x0) + (y1 - y0) * (y1 - y0)) + a1;
619 288 : _subchannel_position[i][0] = (a2 * x1 - a1 * x0) / (a2 - a1);
620 288 : _subchannel_position[i][1] = (a2 * y1 - a1 * y0) / (a2 - a1);
621 : }
622 : } // i
623 : // Reduce reserved memory in the channel-to-gap map.
624 2388 : for (auto & gap : _chan_to_gap_map)
625 : {
626 : gap.shrink_to_fit();
627 : }
628 48 : }
629 :
630 : std::unique_ptr<MeshBase>
631 48 : SCMTriInterWrapperMeshGenerator::generate()
632 : {
633 48 : auto mesh_base = buildMeshBaseObject();
634 :
635 : BoundaryInfo & boundary_info = mesh_base->get_boundary_info();
636 48 : mesh_base->set_spatial_dimension(3);
637 48 : mesh_base->reserve_elem(_n_cells * _n_channels);
638 48 : mesh_base->reserve_nodes((_n_cells + 1) * _n_channels);
639 48 : _nodes.resize(_n_channels);
640 : // Add the points for the give x,y subchannel positions. The grid is hexagonal.
641 : // The grid along
642 : // z is irregular to account for Pin spacers. Store pointers in the _nodes
643 : // array so we can keep track of which points are in which channels.
644 : unsigned int node_id = 0;
645 2388 : for (unsigned int i = 0; i < _n_channels; i++)
646 : {
647 2340 : _nodes[i].reserve(_n_cells + 1);
648 56160 : for (unsigned int iz = 0; iz < _n_cells + 1; iz++)
649 : {
650 53820 : _nodes[i].push_back(mesh_base->add_point(
651 107640 : Point(_subchannel_position[i][0], _subchannel_position[i][1], _z_grid[iz]), node_id++));
652 : }
653 : }
654 :
655 : // Add the elements which in this case are 2-node edges that link each
656 : // subchannel's nodes vertically.
657 : unsigned int elem_id = 0;
658 2388 : for (unsigned int i = 0; i < _n_channels; i++)
659 : {
660 53820 : for (unsigned int iz = 0; iz < _n_cells; iz++)
661 : {
662 51480 : Elem * elem = new Edge2;
663 51480 : elem->set_id(elem_id++);
664 51480 : elem = mesh_base->add_elem(elem);
665 51480 : const int indx1 = (_n_cells + 1) * i + iz;
666 51480 : const int indx2 = (_n_cells + 1) * i + (iz + 1);
667 51480 : elem->set_node(0, mesh_base->node_ptr(indx1));
668 51480 : elem->set_node(1, mesh_base->node_ptr(indx2));
669 :
670 51480 : if (iz == 0)
671 2340 : boundary_info.add_side(elem, 0, 0);
672 51480 : if (iz == _n_cells - 1)
673 2340 : boundary_info.add_side(elem, 1, 1);
674 : }
675 : }
676 48 : boundary_info.sideset_name(0) = "inlet";
677 48 : boundary_info.sideset_name(1) = "outlet";
678 48 : boundary_info.nodeset_name(0) = "inlet";
679 48 : boundary_info.nodeset_name(1) = "outlet";
680 :
681 48 : mesh_base->prepare_for_use();
682 :
683 : // move the meta data into TriInterWrapperMesh
684 48 : auto & sch_mesh = static_cast<TriInterWrapperMesh &>(*_mesh);
685 48 : sch_mesh._unheated_length_entry = _unheated_length_entry;
686 48 : sch_mesh._heated_length = _heated_length;
687 48 : sch_mesh._unheated_length_exit = _unheated_length_exit;
688 48 : sch_mesh._z_grid = _z_grid;
689 48 : sch_mesh._k_grid = _k_grid;
690 48 : sch_mesh._kij = _kij;
691 48 : sch_mesh._assembly_pitch = _assembly_pitch;
692 48 : sch_mesh._n_cells = _n_cells;
693 48 : sch_mesh._n_rings = _n_rings;
694 48 : sch_mesh._n_channels = _n_channels;
695 48 : sch_mesh._flat_to_flat = _flat_to_flat;
696 48 : sch_mesh._duct_to_pin_gap = _duct_to_pin_gap;
697 48 : sch_mesh._nodes = _nodes;
698 48 : sch_mesh._gap_to_chan_map = _gap_to_chan_map;
699 48 : sch_mesh._gap_to_pin_map = _gap_to_pin_map;
700 48 : sch_mesh._chan_to_gap_map = _chan_to_gap_map;
701 48 : sch_mesh._sign_id_crossflow_map = _sign_id_crossflow_map;
702 48 : sch_mesh._gij_map = _gij_map;
703 48 : sch_mesh._subchannel_position = _subchannel_position;
704 48 : sch_mesh._pin_position = _pin_position;
705 48 : sch_mesh._pins_in_rings = _pins_in_rings;
706 48 : sch_mesh._chan_to_pin_map = _chan_to_pin_map;
707 48 : sch_mesh._n_assemblies = _n_assemblies;
708 48 : sch_mesh._n_gaps = _n_gaps;
709 48 : sch_mesh._subch_type = _subch_type;
710 48 : sch_mesh._gap_type = _gap_type;
711 48 : sch_mesh._gap_pairs_sf = _gap_pairs_sf;
712 48 : sch_mesh._chan_pairs_sf = _chan_pairs_sf;
713 48 : sch_mesh._tight_side_bypass = _tight_side_bypass;
714 :
715 : // Overloading assembly sides with flat_to_flat distance
716 48 : sch_mesh._assembly_side_x = _flat_to_flat;
717 48 : sch_mesh._assembly_side_y = _flat_to_flat;
718 :
719 48 : return mesh_base;
720 0 : }
|