https://mooseframework.inl.gov
Loading...
Searching...
No Matches
CSGBase.C
Go to the documentation of this file.
1//* This file is part of the MOOSE framework
2//* https://www.mooseframework.org
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 "CSGBase.h"
11#include "CSGUtils.h"
12#include "JsonIO.h"
13
14namespace CSG
15{
16
18 : _surface_list(CSGSurfaceList()),
19 _cell_list(CSGCellList()),
20 _universe_list(CSGUniverseList()),
21 _lattice_list(CSGLatticeList())
22{
23}
24
25CSGBase::CSGBase(const CSGBase & other_base)
26 : _surface_list(other_base.getSurfaceList()),
27 _cell_list(CSGCellList()),
28 _universe_list(CSGUniverseList()),
29 _lattice_list(CSGLatticeList())
30{
31 // Add all engineering units first so the recursive addCellToList / addUniverseToList calls
32 // below can find them via hasCell() / hasUniverse() and return early without erroring.
33 // Cell engineering units do not have universes and universe engineering units do not contain
34 // cells in the same way that the plain objects do, so we do not need to worry about recursion.
35
36 // Bypass addCellToList because it doesn't properly handle engineering units and also bypass
37 // addEngUnit for cells to avoid erroneously adding it to the root universe if it is not
38 // necessary.
39 for (const auto & eng_unit : other_base.getAllCellEngUnits())
40 _cell_list.addCell(eng_unit.get().clone());
41
42 for (const auto & eng_unit : other_base.getAllUniverseEngUnits())
43 addEngUnit(eng_unit.get().clone());
44
45 // Iterate through all non-eng unit cell references from the other CSGBase instance and
46 // create new CSGCell pointers based on these references. This is done
47 // recursively to properly handle cells with universe fills.
48 for (const auto & [name, cell] : other_base.getCellList().getCellListMap())
49 if (!cellToEngUnit(*cell))
50 addCellToList(*cell);
51
52 // Link all cells in other_base root universe to current root universe
53 for (auto & root_cell : other_base.getRootUniverse().getAllCells())
54 {
55 const auto & list_cell = _cell_list.getCell(root_cell.get().getName());
57 }
58
59 // Iterate through all non-eng unit universe references from the other CSGBase instance and
60 // create new CSGUniverse pointers based on these references. This is done in case
61 // any universe exist in the universe list that are not connected to the cell list.
62 for (const auto & [name, univ] : other_base.getUniverseList().getUniverseListMap())
63 if (!universeToEngUnit(*univ))
64 addUniverseToList(*univ);
65
66 // Iterate through all lattice references from the other CSGBase instance and
67 // create new CSGLattice pointers based on these references.
68 for (const auto & [name, lattice] : other_base.getLatticeList().getLatticeListMap())
69 addLatticeToList(*lattice);
70
71 // Rebuild the eng unit index from the now-complete surface, cell, and universe lists.
73}
74
76
77std::unique_ptr<CSGBase>
79{
80 std::unique_ptr<CSGBase> clone = std::make_unique<CSGBase>(*this);
81
82 // Store list of surface names to surface references in clone to update region definitions
83 std::map<std::string, std::reference_wrapper<const CSGSurface>> identical_surface_refs;
84 auto & surf_list_map = clone->getSurfaceList().getSurfaceListMap();
85 for (const auto & [surf_name, surf_ptr] : surf_list_map)
86 identical_surface_refs.insert({surf_name, clone->getSurfaceByName(surf_name)});
87
88 // Update surface references of cell regions to those of clone
89 for (auto & [cell_name, cell_ptr] : clone->getCellList().getCellListMap())
90 cell_ptr->updateCellRegionSurfaces(identical_surface_refs);
91
92 return clone;
93}
94
95const CSGSurface &
96CSGBase::addSurface(std::unique_ptr<CSGSurface> surf)
97{
98 if (surfaceToEngUnit(*surf))
99 mooseError("Surface '",
100 surf->getName(),
101 "' is a CSGSurfaceEngUnit and must be added via addEngUnit(), not addSurface().");
102 return _surface_list.addSurface(std::move(surf));
103}
104
105void
106CSGBase::prepareSurfaceDeletion(const CSGSurface & surface) const
107{
108 for (const auto & cell_ref : _cell_list.getAllCells())
109 {
110 const auto & cell = cell_ref.get();
111 for (const auto & region_surf : cell.getRegion().getSurfaces())
112 if (region_surf.get() == surface)
113 mooseError("Cannot delete surface with name ",
114 surface.getName(),
115 " as it is used in region definition of cell with name ",
116 cell.getName());
117 }
118}
119
120void
121CSGBase::deleteSurface(const CSGSurface & surface)
122{
123 if (!checkSurfaceInBase(surface))
124 mooseError("Surface with name ",
125 surface.getName(),
126 " cannot be deleted as it is different from the surface of the same name in the "
127 "CSGBase instance.");
128
129 prepareSurfaceDeletion(surface);
130 if (const auto * eng_unit = surfaceToEngUnit(surface))
131 _eng_unit_list.removeEngUnit(*eng_unit);
132 _surface_list.getSurfaceListMap().erase(surface.getName());
133}
134
135const CSGCell &
136CSGBase::addCellToList(const CSGCell & cell)
137{
138 // If cell has already been created, we just return a reference to it
139 const auto name = cell.getName();
140 if (_cell_list.hasCell(name))
141 return _cell_list.getCell(name);
142
143 // Engineering unit cells must be registered via addEngUnit(), not addCellToList()
144 if (cellToEngUnit(cell))
145 mooseError("Cell '",
146 name,
147 "' is a CSGCellEngUnit and must be added via addEngUnit(), not addCellToList().");
148
149 // Otherwise if the cell has material or void cell, we can create it directly
150 const auto fill_type = cell.getFillType();
151 const auto region = cell.getRegion();
152 if (fill_type == "VOID")
153 return _cell_list.addVoidCell(name, region);
154 else if (fill_type == "CSG_MATERIAL")
155 {
156 const auto mat_name = cell.getFillMaterial();
157 return _cell_list.addMaterialCell(name, mat_name, region);
158 }
159 else if (fill_type == "LATTICE")
160 {
161 // add lattice recursively to capture all linked universes in the lattice
162 const CSGLattice & lattice = addLatticeToList(cell.getFillLattice());
163 return _cell_list.addLatticeCell(name, lattice, region);
164 }
165 // Otherwise if the cell has a universe fill, we need to recursively define
166 // all linked universes and cells first before defining this cell
167 else if (fill_type == "UNIVERSE")
168 {
169 const auto & univ = addUniverseToList(cell.getFillUniverse());
170 return _cell_list.addUniverseCell(name, univ, region);
171 }
172 else
173 mooseError("Cell " + name + " has unrecognized fill type " + fill_type);
174}
175
176const CSGUniverse &
177CSGBase::addUniverseToList(const CSGUniverse & univ)
178{
179 // If universe has already been created, we just return a reference to it
180 const auto name = univ.getName();
181 if (_universe_list.hasUniverse(name))
182 return _universe_list.getUniverse(name);
183
184 // Engineering unit universes must be registered via addEngUnit(), not addUniverseToList()
185 if (universeToEngUnit(univ))
186 mooseError("Universe '",
187 name,
188 "' is a CSGUniverseEngUnit and must be added via addEngUnit(), not "
189 "addUniverseToList().");
190
191 // Otherwise we create a new universe based on its associated cells.
192 // addCellToList is called recursively in case associated cells have not
193 // been added to the cell list yet.
194 const auto univ_cells = univ.getAllCells();
195 std::vector<std::reference_wrapper<const CSGCell>> current_univ_cells;
196 for (const auto & univ_cell : univ_cells)
197 current_univ_cells.push_back(addCellToList(univ_cell));
198 return createUniverse(name, current_univ_cells);
199}
200
201const CSGLattice &
202CSGBase::addLatticeToList(const CSGLattice & lattice)
203{
204 // If lattice has already been created, we just return a reference to it
205 const auto name = lattice.getName();
206 if (_lattice_list.hasLattice(name))
207 return _lattice_list.getLattice(name);
208
209 // Clone the lattice (associated universes need to be transferred and set)
210 auto cloned_lattice = lattice.clone();
211
212 // If lattice has associated universes, we need to add them to this CSGBase instance as well.
213 // addUniverseToList is called recursively in case associated universes have not been added to
214 // the universe list yet.
215 std::vector<std::vector<std::reference_wrapper<const CSGUniverse>>> current_univ_map;
216 for (const auto & univ_list : lattice.getUniverses())
217 {
218 std::vector<std::reference_wrapper<const CSGUniverse>> current_univ_list;
219 for (const auto & univ_ref : univ_list)
220 current_univ_list.push_back(addUniverseToList(univ_ref.get()));
221 current_univ_map.push_back(current_univ_list);
222 }
223
224 // Set universes only if lattice has universes defined
225 if (current_univ_map.size() > 0)
226 cloned_lattice->setUniverses(current_univ_map);
227
228 // Update reference to outer universe if it exists
229 if (lattice.getOuterType() == "UNIVERSE")
230 {
231 const auto & outer_univ_ref = addUniverseToList(lattice.getOuterUniverse());
232 cloned_lattice->updateOuter(outer_univ_ref);
233 }
234
235 // Use addLattice to add the cloned lattice
236 return addLattice(std::move(cloned_lattice));
237}
238
239void
240CSGBase::deleteLattice(const CSGLattice & lattice)
241{
242 if (!checkLatticeInBase(lattice))
243 mooseError("Lattice with name ",
244 lattice.getName(),
245 " cannot be deleted as it is different from the lattice of the same name in the "
246 "CSGBase instance.");
247
248 // Check if lattice is used as fill in existing cells
249 for (const auto & cell_ref : _cell_list.getAllCells())
250 {
251 const auto & cell = cell_ref.get();
252 if ((cell.getFillType() == "LATTICE") && (cell.getFillLattice() == lattice))
253 mooseError("Cannot delete lattice with name ",
254 lattice.getName(),
255 " as it is used as the fill of cell with name ",
256 cell.getName());
257 }
258
259 _lattice_list.getLatticeListMap().erase(lattice.getName());
260}
261
262const CSGCell &
263CSGBase::createCell(const std::string & name,
264 const std::string & mat_name,
265 const CSGRegion & region,
266 const CSGUniverse * add_to_univ)
267{
268 checkRegionSurfaces(region);
269 auto & cell = _cell_list.addMaterialCell(name, mat_name, region);
270 if (add_to_univ)
271 addCellToUniverse(*add_to_univ, cell);
272 else
273 addCellToUniverse(getRootUniverse(), cell);
274 return cell;
275}
276
277const CSGCell &
278CSGBase::createCell(const std::string & name,
279 const CSGRegion & region,
280 const CSGUniverse * add_to_univ)
281{
282 checkRegionSurfaces(region);
283 auto & cell = _cell_list.addVoidCell(name, region);
284 if (add_to_univ)
285 addCellToUniverse(*add_to_univ, cell);
286 else
287 addCellToUniverse(getRootUniverse(), cell);
288 return cell;
289}
290
291const CSGCell &
292CSGBase::createCell(const std::string & name,
293 const CSGUniverse & fill_univ,
294 const CSGRegion & region,
295 const CSGUniverse * add_to_univ)
296{
297 checkRegionSurfaces(region);
298 if (add_to_univ && (&fill_univ == add_to_univ))
299 mooseError("Cell " + name +
300 " cannot be filled with the same universe to which it is being added.");
301
302 auto & cell = _cell_list.addUniverseCell(name, fill_univ, region);
303 if (add_to_univ)
304 addCellToUniverse(*add_to_univ, cell);
305 else
306 addCellToUniverse(getRootUniverse(), cell);
307 return cell;
308}
309
310const CSGCell &
311CSGBase::createCell(const std::string & name,
312 const CSGLattice & fill_lattice,
313 const CSGRegion & region,
314 const CSGUniverse * add_to_univ)
315{
316 checkRegionSurfaces(region);
317
318 // check that cell is not being added to a universe that exists in the lattice itself
319 if (add_to_univ)
320 for (auto univ_list : fill_lattice.getUniverses())
321 for (const auto & univ_ref : univ_list)
322 {
323 const CSGUniverse & univ_in_lattice = univ_ref.get();
324 if (&univ_in_lattice == add_to_univ)
325 mooseError("Cell " + name +
326 " cannot be filled with a lattice containing the same universe to which it is "
327 "being added.");
328 }
329
330 auto & cell = _cell_list.addLatticeCell(name, fill_lattice, region);
331 if (add_to_univ)
332 addCellToUniverse(*add_to_univ, cell);
333 else
334 addCellToUniverse(getRootUniverse(), cell);
335 return cell;
336}
337
338void
339CSGBase::prepareCellDeletion(const CSGCell & cell)
340{
341 for (const auto & univ_ref : _universe_list.getAllUniverses())
342 {
343 const auto & univ = univ_ref.get();
344 for (const auto & univ_cell : univ.getAllCells())
345 if (cell == univ_cell.get())
346 {
347 // must remove from root intentionally too, but don't warn in this case (too noisy for
348 // expected behavior)
349 if (univ != getRootUniverse())
350 mooseWarning("Removing cell ",
351 cell.getName(),
352 " from universe with name ",
353 univ.getName(),
354 " before cell deletion.");
355 _universe_list.getUniverse(univ.getName()).removeCell(cell.getName());
356 }
357 }
358}
359
360void
361CSGBase::deleteCell(const CSGCell & cell)
362{
363 if (!checkCellInBase(cell))
364 mooseError("Cell with name ",
365 cell.getName(),
366 " cannot be deleted as it is different from the cell of the same name in the "
367 "CSGBase instance.");
368
369 prepareCellDeletion(cell);
370 if (const auto * eng_unit = cellToEngUnit(cell))
371 _eng_unit_list.removeEngUnit(*eng_unit);
372 _cell_list.getCellListMap().erase(cell.getName());
373}
374
375void
376CSGBase::updateCellRegion(const CSGCell & cell, const CSGRegion & region)
377{
378 // cannot update region for a cell that is actually an engineering unit
379 if (cellToEngUnit(cell))
380 mooseError("Region cannot be updated for cell '" + cell.getName() +
381 "' because it is a CSGCellEngUnit.");
382
383 checkRegionSurfaces(region);
384 if (!checkCellInBase(cell))
385 mooseError("The region of cell with name " + cell.getName() +
386 " that is being updated is different " +
387 "from the cell of the same name in the CSGBase instance.");
388 auto & list_cell = _cell_list.getCell(cell.getName());
389 list_cell.updateRegion(region);
390}
391
392void
393CSGBase::resetCellFill(const CSGCell & cell)
394{
395 // cannot update region for a cell that is actually an engineering unit
396 if (cellToEngUnit(cell))
397 mooseError("Fill cannot be reset for cell '" + cell.getName() +
398 "' because it is a CSGCellEngUnit.");
399
400 if (!checkCellInBase(cell))
401 mooseError("The fill of cell with name " + cell.getName() +
402 " that is being updated is different " +
403 "from the cell of the same name in the CSGBase instance.");
404 auto & list_cell = _cell_list.getCell(cell.getName());
405 list_cell.resetCellFill();
406}
407
408void
409CSGBase::updateCellFill(const CSGCell & cell, const std::string & mat_name)
410{
411 // cannot update region for a cell that is actually an engineering unit
412 if (cellToEngUnit(cell))
413 mooseError("Fill cannot be updated for cell '" + cell.getName() +
414 "' because it is a CSGCellEngUnit.");
415
416 if (!checkCellInBase(cell))
417 mooseError("The region of cell with name " + cell.getName() +
418 " that is being updated is different " +
419 "from the cell of the same name in the CSGBase instance.");
420 auto & list_cell = _cell_list.getCell(cell.getName());
421 list_cell.updateCellFill(mat_name);
422}
423
424void
425CSGBase::updateCellFill(const CSGCell & cell, const CSGUniverse * univ)
426{
427 // cannot update region for a cell that is actually an engineering unit
428 if (cellToEngUnit(cell))
429 mooseError("Fill cannot be updated for cell '" + cell.getName() +
430 "' because it is a CSGCellEngUnit.");
431
432 if (!checkUniverseInBase(*univ))
433 mooseError("Universe with name ",
434 univ->getName(),
435 " is being used as a cell fill that is different from the universe of the same name "
436 "in the CSGBase instance.");
437 if (!checkCellInBase(cell))
438 mooseError("The fill of cell with name " + cell.getName() +
439 " that is being updated is different " +
440 "from the cell of the same name in the CSGBase instance.");
441 auto & list_cell = _cell_list.getCell(cell.getName());
442 list_cell.updateCellFill(univ);
443}
444
445void
446CSGBase::updateCellFill(const CSGCell & cell, const CSGLattice * lattice)
447{
448 // cannot update region for a cell that is actually an engineering unit
449 if (cellToEngUnit(cell))
450 mooseError("Fill cannot be updated for cell '" + cell.getName() +
451 "' because it is a CSGCellEngUnit.");
452
453 if (!checkLatticeInBase(*lattice))
454 mooseError("Lattice with name ",
455 lattice->getName(),
456 " is being used as a cell fill that is different from the lattice of the same name "
457 "in the CSGBase instance.");
458 if (!checkCellInBase(cell))
459 mooseError("The fill of cell with name " + cell.getName() +
460 " that is being updated is different " +
461 "from the cell of the same name in the CSGBase instance.");
462 auto & list_cell = _cell_list.getCell(cell.getName());
463 list_cell.updateCellFill(lattice);
464}
465
466const CSGUniverse &
467CSGBase::createUniverse(const std::string & name,
468 std::vector<std::reference_wrapper<const CSGCell>> & cells)
469{
470 auto & univ = _universe_list.addUniverse(name);
471 addCellsToUniverse(univ, cells); // performs a check that cells are a part of this base
472 return univ;
473}
474
475void
476CSGBase::prepareUniverseDeletion(const CSGUniverse & univ) const
477{
478 if (univ == getRootUniverse())
479 mooseError("Cannot delete root universe from CSGBase instance");
480
481 // Check if universe is used in any existing lattices
482 for (const auto & lat : _lattice_list.getAllLattices())
483 {
484 for (const auto & lat_univ : lat.get().getUniqueUniverses())
485 if (univ == lat_univ.get())
486 mooseError("Cannot delete universe with name ",
487 univ.getName(),
488 " as it is used in lattice with name ",
489 lat.get().getName());
490 if ((lat.get().getOuterType() == "UNIVERSE") && (lat.get().getOuterUniverse() == univ))
491 mooseError("Cannot delete universe with name ",
492 univ.getName(),
493 " as it is used as the outer universe of lattice with name ",
494 lat.get().getName());
495 }
496
497 // Check if universe is used as fill in existing cells
498 for (const auto & cell_ref : _cell_list.getAllCells())
499 {
500 const auto & cell = cell_ref.get();
501 if ((cell.getFillType() == "UNIVERSE") && (cell.getFillUniverse() == univ))
502 mooseError("Cannot delete universe with name ",
503 univ.getName(),
504 " as it is used as the fill of cell with name ",
505 cell.getName());
506 }
507}
508
509void
510CSGBase::deleteUniverse(const CSGUniverse & univ)
511{
512 if (!checkUniverseInBase(univ))
513 mooseError("Universe with name ",
514 univ.getName(),
515 " cannot be deleted as it is different from the universe of the same name in the "
516 "CSGBase instance.");
517
518 prepareUniverseDeletion(univ);
519 if (const auto * eng_unit = universeToEngUnit(univ))
520 _eng_unit_list.removeEngUnit(*eng_unit);
521 _universe_list.getUniverseListMap().erase(univ.getName());
522}
523
524void
525CSGBase::addCellToUniverse(const CSGUniverse & universe, const CSGCell & cell)
526{
527 // if universe is actually engineering unit, cannot add cells
528 if (universeToEngUnit(universe))
529 mooseError("Universe '" + universe.getName() +
530 "' cannot add cells because it is a CSGUniverseEngUnit.");
531
532 // make sure cell is a part of this CSGBase instance
533 if (!checkCellInBase(cell))
534 mooseError("A cell named " + cell.getName() + " is being added to universe " +
535 universe.getName() +
536 " that is different from the cell of the same name in the CSGBase instance.");
537 // make sure universe is a part of this CSGBase instance
538 if (!checkUniverseInBase(universe))
539 mooseError("Cells are being added to a universe named " + universe.getName() +
540 " that is different " +
541 "from the universe of the same name in the CSGBase instance.");
542 auto & univ = _universe_list.getUniverse(universe.getName());
543 univ.addCell(cell);
544}
545
546void
547CSGBase::addCellsToUniverse(const CSGUniverse & universe,
548 std::vector<std::reference_wrapper<const CSGCell>> & cells)
549{
550 for (auto & c : cells)
551 addCellToUniverse(universe, c);
552}
553
554void
555CSGBase::removeCellFromUniverse(const CSGUniverse & universe, const CSGCell & cell)
556{
557 // make sure cell is a part of this CSGBase instance
558 if (!checkCellInBase(cell))
559 mooseError("A cell named " + cell.getName() + " is being removed from universe " +
560 universe.getName() +
561 " that is different from the cell of the same name in the CSGBase instance.");
562 // make sure universe is a part of this CSGBase instance
563 if (!checkUniverseInBase(universe))
564 mooseError("Cells are being removed from a universe named " + universe.getName() +
565 " that is different " +
566 "from the universe of the same name in the CSGBase instance.");
567 auto & univ = _universe_list.getUniverse(universe.getName());
568 // removeCell will produce error that cell is not found in the case that the universe is actually
569 // an engineering unit, so we don't need to check that.
570 univ.removeCell(cell.getName());
571}
572
573void
574CSGBase::removeCellsFromUniverse(const CSGUniverse & universe,
575 std::vector<std::reference_wrapper<const CSGCell>> & cells)
576{
577 for (auto & c : cells)
578 removeCellFromUniverse(universe, c);
579}
580
581void
582CSGBase::setLatticeOuter(const CSGLattice & lattice, const std::string & outer_name)
583{
584 auto name = lattice.getName();
585 if (!checkLatticeInBase(lattice))
586 mooseError("Cannot set outer for lattice " + name +
587 ". Lattice is different from the lattice of the same name in the "
588 "CSGBase instance.");
589 _lattice_list.getLattice(name).updateOuter(outer_name);
590}
591
592void
593CSGBase::setLatticeOuter(const CSGLattice & lattice, const CSGUniverse & outer_univ)
594{
595 auto name = lattice.getName();
596 if (!checkLatticeInBase(lattice))
597 mooseError("Cannot set outer universe for lattice " + name +
598 ". Lattice is different from the lattice of the same name in the "
599 "CSGBase instance.");
600 if (!checkUniverseInBase(outer_univ))
601 mooseError("Cannot set outer universe for lattice " + name + ". Outer universe " +
602 outer_univ.getName() + " is not in the CSGBase instance.");
603 _lattice_list.getLattice(name).updateOuter(outer_univ);
604}
605
606void
607CSGBase::resetLatticeOuter(const CSGLattice & lattice)
608{
609 auto name = lattice.getName();
610 if (!checkLatticeInBase(lattice))
611 mooseError("Cannot reset outer for lattice " + name +
612 ". Lattice is different from the lattice of the same name in the "
613 "CSGBase instance.");
614 _lattice_list.getLattice(name).resetOuter();
615}
616
617void
618CSGBase::setUniverseAtLatticeIndex(const CSGLattice & lattice,
619 const CSGUniverse & universe,
620 std::pair<int, int> index)
621{
622 auto name = lattice.getName();
623 if (!checkLatticeInBase(lattice))
624 mooseError("Cannot set universe at index for lattice " + name +
625 ". Lattice is different from the lattice of the same name in the "
626 "CSGBase instance.");
627 if (!checkUniverseInBase(universe))
628 mooseError("Cannot add universe " + universe.getName() + " to lattice " + lattice.getName() +
629 ". Universe is not in the CSGBase instance.");
630 _lattice_list.getLattice(name).setUniverseAtIndex(universe, index);
631}
632
633void
634CSGBase::setLatticeUniverses(
635 const CSGLattice & lattice,
636 std::vector<std::vector<std::reference_wrapper<const CSGUniverse>>> & universes)
637{
638 auto name = lattice.getName();
639 if (!checkLatticeInBase(lattice))
640 mooseError("Cannot set universes for lattice " + name +
641 ". Lattice is different from the lattice of the same name in the "
642 "CSGBase instance.");
643 // make sure all universes are a part of this base instance
644 for (auto univ_list : universes)
645 for (const CSGUniverse & univ : univ_list)
646 if (!checkUniverseInBase(univ))
647 mooseError("Cannot set universes for lattice " + name + ". Universe " + univ.getName() +
648 " is not in the CSGBase instance.");
649 _lattice_list.getLattice(name).setUniverses(universes);
650}
651
652void
653CSGBase::addTransformation(const CSGObjectVariant & csg_object,
655 const std::tuple<Real, Real, Real> & values)
656{
657 // Use std::visit to handle each type in the variant
658 std::visit(
659 [&](const auto & obj)
660 {
661 using T = std::decay_t<decltype(obj.get())>;
662
663 // Handle each CSG object type differently because each needs to check that it exists in
664 // this base instance
665 if constexpr (std::is_same_v<T, CSGCell>)
666 {
667 const CSGCell & cell = obj.get();
668 if (!checkCellInBase(cell))
669 mooseError("Cannot apply transformation to cell ",
670 cell.getName(),
671 " that is not in this CSGBase instance.");
672
673 // Get non-const reference and apply transformation
674 CSGCell & mutable_cell = _cell_list.getCell(cell.getName());
675 mooseAssert(mutable_cell == cell, "Mutable cell does not match const cell passed in.");
676 mutable_cell.addTransformation(type, values);
677 }
678 else if constexpr (std::is_same_v<T, CSGSurface>)
679 {
680 const CSGSurface & surface = obj.get();
681 if (!checkSurfaceInBase(surface))
682 mooseError("Cannot apply transformation to surface ",
683 surface.getName(),
684 " that is not in this CSGBase instance.");
685
686 // Get non-const reference and apply transformation
687 CSGSurface & mutable_surface = _surface_list.getSurface(surface.getName());
688 mooseAssert(mutable_surface == surface,
689 "Mutable surface does not match const surface passed in.");
690 mutable_surface.addTransformation(type, values);
691 }
692 else if constexpr (std::is_same_v<T, CSGUniverse>)
693 {
694 const CSGUniverse & universe = obj.get();
695 if (!checkUniverseInBase(universe))
696 mooseError("Cannot apply transformation to universe ",
697 universe.getName(),
698 " that is not in this CSGBase instance.");
699
700 // Get non-const reference and apply transformation
701 CSGUniverse & mutable_universe = _universe_list.getUniverse(universe.getName());
702 mooseAssert(mutable_universe == universe,
703 "Mutable universe does not match const universe passed in.");
704 mutable_universe.addTransformation(type, values);
705 }
706 else if constexpr (std::is_same_v<T, CSGLattice>)
707 {
708 const CSGLattice & lattice = obj.get();
709 if (!checkLatticeInBase(lattice))
710 mooseError("Cannot apply transformation to lattice ",
711 lattice.getName(),
712 " that is not in this CSGBase instance.");
713
714 // Get non-const reference and apply transformation
715 CSGLattice & mutable_lattice = _lattice_list.getLattice(lattice.getName());
716 mooseAssert(mutable_lattice == lattice,
717 "Mutable lattice does not match const lattice passed in.");
718 mutable_lattice.addTransformation(type, values);
719 }
720 else if constexpr (std::is_same_v<T, CSGRegion>)
721 {
722 // iterate on the surfaces of the region and apply the transformation to those surfaces
723 const CSGRegion & region = obj.get();
724 const auto surfaces = region.getSurfaces();
725 for (const CSGSurface & surface : surfaces)
726 {
727 if (!checkSurfaceInBase(surface))
728 mooseError("Cannot apply transformation to region with surface ",
729 surface.getName(),
730 " that is not in this CSGBase instance.");
731 addTransformation(surface, type, values);
732 }
733 }
734 else if constexpr (std::is_same_v<T, CSGEngUnit>)
735 {
736 const CSGEngUnit & eng_unit = obj.get();
737 if (!checkEngUnitInBase(eng_unit))
738 mooseError("Cannot apply transformation to engineering unit ",
739 eng_unit.getName(),
740 " that is not in this CSGBase instance.");
741
742 CSGEngUnit & mutable_eng = _eng_unit_list.getEngUnit(eng_unit.getName());
743 if (auto * s = dynamic_cast<CSGSurfaceEngUnit *>(&mutable_eng))
744 s->addTransformation(type, values);
745 else if (auto * c = dynamic_cast<CSGCellEngUnit *>(&mutable_eng))
746 c->addTransformation(type, values);
747 else if (auto * u = dynamic_cast<CSGUniverseEngUnit *>(&mutable_eng))
748 u->addTransformation(type, values);
749 else
750 mooseError("Engineering unit '",
751 eng_unit.getName(),
752 "' has an unrecognized type for transformation.");
753 }
754 else
755 mooseError("Transformation not implemented for this object type: ", typeid(T).name());
756 },
757 csg_object);
758}
759
760void
761CSGBase::applyAxisRotation(const CSGObjectVariant & csg_object,
762 RotationAxisType axis,
763 const Real angle)
764{
765 // convert to the Euler angles (phi, theta, psi) based on axis
766 Real phi = 0.0;
767 Real theta = 0.0;
768 Real psi = 0.0;
769
770 switch (axis)
771 {
772 case RotationAxisType::X:
773 theta = angle;
774 break;
775 case RotationAxisType::Y:
776 phi = 90.0;
777 theta = angle;
778 psi = -90.0;
779 break;
780 case RotationAxisType::Z:
781 phi = angle;
782 break;
783 default:
784 mooseError("Invalid axis type provided for axis rotation.");
785 }
786
787 addTransformation(csg_object, TransformationType::ROTATION, std::make_tuple(phi, theta, psi));
788}
789
790void
791CSGBase::joinOtherBase(std::unique_ptr<CSGBase> base, const bool ignore_identical_components)
792{
793 // If we are ignoring identical incoming CSG components, we need to update any references
794 // stored by these components to point to the references of the pre-existing CSGBase object
795 if (ignore_identical_components)
796 updateIncomingCSGReferences(*base);
797 joinSurfaceList(base->getSurfaceList(), ignore_identical_components);
798 joinCellList(base->getCellList(), ignore_identical_components);
799 joinLatticeList(base->getLatticeList(), ignore_identical_components);
800 joinUniverseList(base->getUniverseList(), ignore_identical_components);
801 rebuildEngUnitList(); // finds all engineering units again, allowing us to keep any ignored
802 // surfaces that were removed from the surface list out of this list
803}
804
805void
806CSGBase::joinOtherBase(std::unique_ptr<CSGBase> base,
807 const bool ignore_identical_components,
808 const std::string & new_root_name_join)
809{
810 // If we are ignoring identical incoming CSG components, we need to update any references
811 // stored by these components to point to the references of the pre-existing CSGBase object
812 if (ignore_identical_components)
813 updateIncomingCSGReferences(*base);
814 joinSurfaceList(base->getSurfaceList(), ignore_identical_components);
815 joinCellList(base->getCellList(), ignore_identical_components);
816 joinLatticeList(base->getLatticeList(), ignore_identical_components);
817 joinUniverseList(base->getUniverseList(), ignore_identical_components, new_root_name_join);
818 rebuildEngUnitList(); // finds all engineering units again, allowing us to keep any ignored
819 // surfaces that were removed from the surface list out of this list
820}
821
822void
823CSGBase::joinOtherBase(std::unique_ptr<CSGBase> base,
824 const bool ignore_identical_components,
825 const std::string & new_root_name_base,
826 const std::string & new_root_name_join)
827{
828 // If we are ignoring identical incoming CSG components, we need to update any references
829 // stored by these components to point to the references of the pre-existing CSGBase object
830 if (ignore_identical_components)
831 updateIncomingCSGReferences(*base);
832 joinSurfaceList(base->getSurfaceList(), ignore_identical_components);
833 joinCellList(base->getCellList(), ignore_identical_components);
834 joinLatticeList(base->getLatticeList(), ignore_identical_components);
835 joinUniverseList(
836 base->getUniverseList(), ignore_identical_components, new_root_name_base, new_root_name_join);
837 rebuildEngUnitList(); // finds all engineering units again, allowing us to keep any ignored
838 // surfaces that were removed from the surface list out of this list
839}
840
841void
842CSGBase::updateIncomingCSGReferences(CSGBase & incoming_base)
843{
844 // Iterate through all incoming surfaces and track which ones have names already
845 // defined within this CSGSurfaceList object
846 std::map<std::string, std::reference_wrapper<const CSGSurface>> identical_surface_refs;
847 auto & surf_list_map = incoming_base.getSurfaceList().getSurfaceListMap();
848 for (const auto & [surf_name, surf_ptr] : surf_list_map)
849 if (hasSurface(surf_name))
850 identical_surface_refs.insert({surf_name, getSurfaceByName(surf_name)});
851
852 // Iterate through all incoming cells and track which ones have names already
853 // defined within this CSGCellList object
854 std::map<std::string, std::reference_wrapper<const CSGCell>> identical_cell_refs;
855 auto & cell_list_map = incoming_base.getCellList().getCellListMap();
856 for (const auto & [cell_name, cell_ptr] : cell_list_map)
857 if (hasCell(cell_name))
858 identical_cell_refs.insert({cell_name, getCellByName(cell_name)});
859
860 // Iterate through all incoming universes and track which ones have names already
861 // defined within this CSGUniverseList object
862 std::map<std::string, std::reference_wrapper<const CSGUniverse>> identical_universe_refs;
863 auto & universe_list_map = incoming_base.getUniverseList().getUniverseListMap();
864 for (const auto & [univ_name, univ_ptr] : universe_list_map)
865 if (hasUniverse(univ_name))
866 identical_universe_refs.insert({univ_name, getUniverseByName(univ_name)});
867
868 // Iterate through all incoming lattices and track which ones have names already
869 // defined within this CSGLatticeList object
870 std::map<std::string, std::reference_wrapper<const CSGLattice>> identical_lattice_refs;
871 auto & lattice_list_map = incoming_base.getLatticeList().getLatticeListMap();
872 for (const auto & [lat_name, lat_ptr] : lattice_list_map)
873 if (hasLattice(lat_name))
874 identical_lattice_refs.insert({lat_name, getLatticeByName(lat_name)});
875
876 // Update all surface, cell, universe, and lattice references of incoming base to those of this
877 // base
878 if (!identical_surface_refs.empty())
879 replaceSurfaceRefsByName(identical_surface_refs, incoming_base);
880
881 if (!identical_cell_refs.empty())
882 replaceCellRefsByName(identical_cell_refs, incoming_base);
883
884 if (!identical_universe_refs.empty())
885 replaceUniverseRefsByName(identical_universe_refs, incoming_base);
886
887 if (!identical_lattice_refs.empty())
888 replaceLatticeRefsByName(identical_lattice_refs, incoming_base);
889}
890
891void
892CSGBase::replaceSurfaceRefsByName(
893 std::map<std::string, std::reference_wrapper<const CSGSurface>> & identical_surface_refs,
894 CSGBase & base)
895{
896 // Update surface references of cell regions to those of this base
897 for (auto & [cell_name, cell_ptr] : base.getCellList().getCellListMap())
898 cell_ptr->updateCellRegionSurfaces(identical_surface_refs);
899}
900
901void
902CSGBase::replaceCellRefsByName(
903 std::map<std::string, std::reference_wrapper<const CSGCell>> & identical_cell_refs,
904 CSGBase & base)
905{
906 // Update cell references of universes to those of this base
907 for (auto & [univ_name, univ_ptr] : base.getUniverseList().getUniverseListMap())
908 for (auto & [cell_name, cell_ref] : identical_cell_refs)
909 if (univ_ptr->hasCell(cell_name))
910 {
911 univ_ptr->removeCell(cell_name);
912 univ_ptr->addCell(cell_ref);
913 }
914}
915
916void
917CSGBase::replaceUniverseRefsByName(
918 std::map<std::string, std::reference_wrapper<const CSGUniverse>> & identical_universe_refs,
919 CSGBase & base)
920{
921 // Update universe references of cells to those of this base
922 for (auto & [cell_name, cell_ptr] : base.getCellList().getCellListMap())
923 {
924 const auto fill_type = cell_ptr->getFillType();
925 const auto fill_name = cell_ptr->getFillName();
926 if ((fill_type == "UNIVERSE") &&
927 (identical_universe_refs.find(fill_name) != identical_universe_refs.end()))
928 {
929 const CSGUniverse * univ_ptr = &identical_universe_refs.at(fill_name).get();
930 cell_ptr->updateCellFill(univ_ptr);
931 }
932 }
933
934 // Update universe references of lattices to those of this base
935 for (auto & [lat_name, lat_ptr] : base.getLatticeList().getLatticeListMap())
936 for (auto & [univ_name, univ_ref] : identical_universe_refs)
937 {
938 // Check if universe belongs to lattice
939 if (lat_ptr->hasUniverse(univ_name))
940 {
941 // If so, replace all instances of this universe in the lattice
942 const auto univ_indices = lat_ptr->getUniverseIndices(univ_name);
943 for (const auto & index : univ_indices)
944 lat_ptr->setUniverseAtIndex(univ_ref, index);
945 }
946 // Check if universe belongs to lattice outer
947 if ((lat_ptr->getOuterType() == "UNIVERSE") &&
948 (lat_ptr->getOuterUniverse().getName() == univ_name))
949 lat_ptr->updateOuter(univ_ref);
950 }
951}
952
953void
954CSGBase::replaceLatticeRefsByName(
955 std::map<std::string, std::reference_wrapper<const CSGLattice>> & identical_lattice_refs,
956 CSGBase & base)
957{
958 // Update lattice references of cells to those of this base
959 for (auto & [cell_name, cell_ptr] : base.getCellList().getCellListMap())
960 {
961 const auto fill_type = cell_ptr->getFillType();
962 const auto fill_name = cell_ptr->getFillName();
963 if ((fill_type == "LATTICE") &&
964 (identical_lattice_refs.find(fill_name) != identical_lattice_refs.end()))
965 {
966 const CSGLattice * lat_ptr = &identical_lattice_refs.at(fill_name).get();
967 cell_ptr->updateCellFill(lat_ptr);
968 }
969 }
970}
971
972void
973CSGBase::joinSurfaceList(CSGSurfaceList & surf_list, const bool ignore_identical_surfaces)
974{
975 auto & surf_list_map = surf_list.getSurfaceListMap();
976 for (auto & s : surf_list_map)
977 _surface_list.addSurface(std::move(s.second), ignore_identical_surfaces);
978}
979
980void
981CSGBase::joinCellList(CSGCellList & cell_list, const bool ignore_identical_cells)
982{
983 auto & cell_list_map = cell_list.getCellListMap();
984 for (auto & c : cell_list_map)
985 _cell_list.addCell(std::move(c.second), ignore_identical_cells);
986}
987
988void
989CSGBase::joinLatticeList(CSGLatticeList & lattice_list, const bool ignore_identical_lattices)
990{
991 auto & lat_list_map = lattice_list.getLatticeListMap();
992 for (auto & lat : lat_list_map)
993 _lattice_list.addLattice(std::move(lat.second), ignore_identical_lattices);
994}
995
996void
997CSGBase::rebuildEngUnitList()
998{
999 _eng_unit_list = CSGEngUnitList(); // reset to empty
1000
1001 // iterate through all existing lists to find all CSGEngUnit types and store the pointers to the
1002 // rebuilt engineering unit list
1003 for (auto & [name, surf] : _surface_list.getSurfaceListMap())
1004 if (auto * eu = dynamic_cast<CSGSurfaceEngUnit *>(surf.get()))
1005 _eng_unit_list.addEngUnit(*eu);
1006 for (auto & [name, cell] : _cell_list.getCellListMap())
1007 if (auto * eu = dynamic_cast<CSGCellEngUnit *>(cell.get()))
1008 _eng_unit_list.addEngUnit(*eu);
1009 for (auto & [name, univ] : _universe_list.getUniverseListMap())
1010 if (auto * eu = dynamic_cast<CSGUniverseEngUnit *>(univ.get()))
1011 _eng_unit_list.addEngUnit(*eu);
1012}
1013
1014void
1015CSGBase::joinUniverseList(CSGUniverseList & univ_list, const bool ignore_identical_universes)
1016{
1017 // case 1: incoming root is joined into existing root; no new universes are created
1018 auto & univ_list_map = univ_list.getUniverseListMap();
1019 auto & root = getRootUniverse(); // this root universe
1020 for (auto & u : univ_list_map)
1021 {
1022 if (u.second->isRoot())
1023 {
1024 // add existing cells to current root instead of creating new universe
1025 auto all_cells = u.second->getAllCells();
1026 for (auto & cell : all_cells)
1027 addCellToUniverse(root, cell);
1028 }
1029 else // unique non-root universe to add to list
1030 _universe_list.addUniverse(std::move(u.second), ignore_identical_universes);
1031 }
1032}
1033
1034void
1035CSGBase::joinUniverseList(CSGUniverseList & univ_list,
1036 const bool ignore_identical_universes,
1037 const std::string & new_root_name_incoming)
1038{
1039 // case 2: incoming root is turned into new universe and existing root remains root
1040
1041 // add incoming universes to current Base
1042 auto & all_univs = univ_list.getUniverseListMap();
1043 for (auto & u : all_univs)
1044 {
1045 if (u.second->isRoot())
1046 {
1047 // create new universe from incoming root universe
1048 auto all_cells = u.second->getAllCells();
1049 createUniverse(new_root_name_incoming, all_cells);
1050 }
1051 else // unique non-root universe to add to list
1052 _universe_list.addUniverse(std::move(u.second), ignore_identical_universes);
1053 }
1054}
1055
1056void
1057CSGBase::joinUniverseList(CSGUniverseList & univ_list,
1058 const bool ignore_identical_universes,
1059 const std::string & new_root_name_base,
1060 const std::string & new_root_name_incoming)
1061{
1062 // case 3: each root universe becomes a new universe and a new root is created
1063
1064 // make a new universe from the existing root universe
1065 auto & root = getRootUniverse();
1066 auto root_cells = root.getAllCells();
1067 createUniverse(new_root_name_base, root_cells);
1068 removeCellsFromUniverse(root, root_cells);
1069
1070 // add incoming universes to current Base
1071 auto & all_univs = univ_list.getUniverseListMap();
1072 for (auto & u : all_univs)
1073 {
1074 if (u.second->isRoot())
1075 {
1076 // create new universe from incoming root universe
1077 auto all_cells = u.second->getAllCells();
1078 createUniverse(new_root_name_incoming, all_cells);
1079 }
1080 else // unique non-root universe to add to list
1081 _universe_list.addUniverse(std::move(u.second), ignore_identical_universes);
1082 }
1083}
1084
1085void
1086CSGBase::checkRegionSurfaces(const CSGRegion & region) const
1087{
1088 const auto surfs = region.getSurfaces();
1089 for (const CSGSurface & s : surfs)
1090 {
1091 if (!checkSurfaceInBase(s))
1092 mooseError("Region is being set with a surface named " + s.getName() +
1093 " that is different from the surface of the same name in the CSGBase instance.");
1094 }
1095}
1096
1097bool
1098CSGBase::checkSurfaceInBase(const CSGSurface & surface) const
1099{
1100 auto name = surface.getName();
1101 // if no surface by this name exists, an error will be produced by getSurface
1102 auto & list_surf = _surface_list.getSurface(name);
1103 // return whether the surface in the list is the same object as the one provided
1104 return &surface == &list_surf;
1105}
1106
1107bool
1108CSGBase::checkCellInBase(const CSGCell & cell) const
1109{
1110 auto name = cell.getName();
1111 // if no cell by this name exists, an error will be produced by getCell
1112 auto & list_cell = _cell_list.getCell(name);
1113 // return whether the cell in the list is the same object as the one provided
1114 return &cell == &list_cell;
1115}
1116
1117bool
1118CSGBase::checkUniverseInBase(const CSGUniverse & universe) const
1119{
1120 auto name = universe.getName();
1121 // if no universe by this name exists, an error will be produced by getUniverse
1122 auto & list_univ = _universe_list.getUniverse(name);
1123 // return whether the universe in the list is the same object as the one provided
1124 return &universe == &list_univ;
1125}
1126
1127bool
1128CSGBase::checkLatticeInBase(const CSGLattice & lattice) const
1129{
1130 auto name = lattice.getName();
1131 // if no lattice by this name exists, an error will be produced by getLattice
1132 auto & list_lattice = _lattice_list.getLattice(name);
1133 // return whether that the lattice in the list is the same as the lattice provided (in memory)
1134 return &lattice == &list_lattice;
1135}
1136
1137bool
1138CSGBase::checkEngUnitInBase(const CSGEngUnit & unit) const
1139{
1140 const auto & name = unit.getName();
1141 // if no engineering unit by this name exists, an error will be produced by getEngUnit
1142 const auto & list_unit = _eng_unit_list.getEngUnit(name);
1143 // compare CSGEngUnit subobject addresses
1144 return &unit == &list_unit;
1145}
1146
1147void
1148CSGBase::renameEngUnit(const CSGEngUnit & unit, const std::string & name)
1149{
1150 // Rename in the owning type list (updates the object's name and the type list map key).
1151 // The EngUnit index stores raw pointers; because the object's name is updated in-place,
1152 // no index update is needed.
1153 if (const auto * surf = dynamic_cast<const CSGSurfaceEngUnit *>(&unit))
1154 renameSurface(*surf, name);
1155 else if (const auto * cell = dynamic_cast<const CSGCellEngUnit *>(&unit))
1156 renameCell(*cell, name);
1157 else if (const auto * univ = dynamic_cast<const CSGUniverseEngUnit *>(&unit))
1158 renameUniverse(*univ, name);
1159 else
1160 mooseError(
1161 "Engineering unit '", unit.getName(), "' has an unrecognized type and cannot be renamed.");
1162}
1163
1164void
1165CSGBase::renameSurface(const CSGSurface & surface, const std::string & name)
1166{
1167 // if surface is actually an engineering unit, we have to also check that no other units have the
1168 // same name already
1169 if (surfaceToEngUnit(surface))
1170 if (_eng_unit_list.hasEngUnit(name))
1171 mooseError("Cannot rename surface " + surface.getName() + " to " + name + ". " +
1172 surface.getName() + " is an engineering unit and a unit with name " + name +
1173 " already exists.");
1174
1175 _surface_list.renameSurface(surface, name);
1176}
1177
1178void
1179CSGBase::renameCell(const CSGCell & cell, const std::string & name)
1180{
1181 // if cell is actually an engineering unit, we have to also check that no other units have the
1182 // same name already
1183 if (cellToEngUnit(cell))
1184 if (_eng_unit_list.hasEngUnit(name))
1185 mooseError("Cannot rename cell " + cell.getName() + " to " + name + ". " + cell.getName() +
1186 " is an engineering unit and a unit with name " + name + " already exists.");
1187
1188 _cell_list.renameCell(cell, name);
1189}
1190
1191void
1192CSGBase::renameUniverse(const CSGUniverse & universe, const std::string & name)
1193{
1194 // if universe is actually an engineering unit, we have to also check that no other units have the
1195 // same name already
1196 if (universeToEngUnit(universe))
1197 if (_eng_unit_list.hasEngUnit(name))
1198 mooseError("Cannot rename universe " + universe.getName() + " to " + name + ". " +
1199 universe.getName() + " is an engineering unit and a unit with name " + name +
1200 " already exists.");
1201
1202 _universe_list.renameUniverse(universe, name);
1203}
1204
1205void
1206CSGBase::checkUniverseLinking() const
1207{
1208 std::set<std::string> linked_universe_names;
1209 std::set<std::string> linked_cell_names;
1210 std::set<std::string> linked_surf_names;
1211
1212 // Recursively figure out which CSG objects are linked to root universe
1213 getLinkedCSGObjects(
1214 getRootUniverse(), linked_universe_names, linked_cell_names, linked_surf_names);
1215
1216 // Iterate through all universes in universe list and check that they exist in universes linked
1217 // to root universe list. Universe list includes CSGUniverseEngUnits.
1218 for (const CSGUniverse & univ : getAllUniverses())
1219 if (linked_universe_names.find(univ.getName()) == linked_universe_names.end())
1220 mooseWarning("Universe with name ", univ.getName(), " is not linked to root universe.");
1221
1222 // Iterate through all cells in cell list and check that they exist in cells linked
1223 // to root universe
1224 for (const CSGCell & cell : getAllCells())
1225 if (linked_cell_names.find(cell.getName()) == linked_cell_names.end())
1226 mooseWarning("Cell with name ", cell.getName(), " is not linked to root universe.");
1227
1228 // Iterate through all surfaces in surface list and check that they exist in surfaces linked
1229 // to root universe
1230 for (const CSGSurface & surf : getAllSurfaces())
1231 if (linked_surf_names.find(surf.getName()) == linked_surf_names.end())
1232 mooseWarning("Surface with name ", surf.getName(), " is not linked to root universe.");
1233}
1234
1235bool
1236CSGBase::areCSGObjectsLinked() const
1237{
1238 std::set<std::string> linked_univs, linked_cells, linked_surfs;
1239 getLinkedCSGObjects(getRootUniverse(), linked_univs, linked_cells, linked_surfs);
1240
1241 for (const CSGUniverse & univ : getAllUniverses())
1242 if (linked_univs.find(univ.getName()) == linked_univs.end())
1243 return false;
1244
1245 for (const CSGCell & cell : getAllCells())
1246 if (linked_cells.find(cell.getName()) == linked_cells.end())
1247 return false;
1248
1249 for (const CSGSurface & surf : getAllSurfaces())
1250 if (linked_surfs.find(surf.getName()) == linked_surfs.end())
1251 return false;
1252
1253 return true;
1254}
1255
1256void
1257CSGBase::getLinkedCSGObjects(const CSGUniverse & univ,
1258 std::set<std::string> & linked_universe_names,
1259 std::set<std::string> & linked_cell_names,
1260 std::set<std::string> & linked_surface_names) const
1261{
1262 linked_universe_names.insert(univ.getName());
1263 const auto & univ_cells = univ.getAllCells();
1264 for (const CSGCell & cell : univ_cells)
1265 {
1266 linked_cell_names.insert(cell.getName());
1267 for (const CSGSurface & cell_surf : cell.getRegion().getSurfaces())
1268 linked_surface_names.insert(cell_surf.getName());
1269
1270 if (cell.getFillType() == "UNIVERSE")
1271 getLinkedCSGObjects(
1272 cell.getFillUniverse(), linked_universe_names, linked_cell_names, linked_surface_names);
1273 else if (cell.getFillType() == "LATTICE")
1274 {
1275 const auto & lattice = cell.getFillLattice();
1276 for (const auto & univ_list : lattice.getUniverses())
1277 for (const auto & univ_ref : univ_list)
1278 {
1279 const CSGUniverse & lattice_univ = univ_ref.get();
1280 getLinkedCSGObjects(
1281 lattice_univ, linked_universe_names, linked_cell_names, linked_surface_names);
1282 }
1283
1284 if (lattice.getOuterType() == "UNIVERSE")
1285 {
1286 const CSGUniverse & outer_univ = lattice.getOuterUniverse();
1287 getLinkedCSGObjects(
1288 outer_univ, linked_universe_names, linked_cell_names, linked_surface_names);
1289 }
1290 }
1291 }
1292}
1293
1294void
1295CSGBase::deleteEngUnit(const CSGEngUnit & unit)
1296{
1297 if (!checkEngUnitInBase(unit))
1298 mooseError("Engineering unit with name ",
1299 unit.getName(),
1300 " cannot be deleted as it is different from the engineering unit of the same name "
1301 "in the CSGBase instance.");
1302
1303 // Delegate to the typed delete method which handles EngUnit index cleanup and type list erasure
1304 if (const auto * surf_unit = dynamic_cast<const CSGSurfaceEngUnit *>(&unit))
1305 deleteSurface(cast_ref<const CSGSurface &>(*surf_unit));
1306 else if (const auto * cell_unit = dynamic_cast<const CSGCellEngUnit *>(&unit))
1307 deleteCell(cast_ref<const CSGCell &>(*cell_unit));
1308 else if (const auto * univ_unit = dynamic_cast<const CSGUniverseEngUnit *>(&unit))
1309 deleteUniverse(cast_ref<const CSGUniverse &>(*univ_unit));
1310 else
1311 mooseError(
1312 "Engineering unit '", unit.getName(), "' has an unrecognized type and cannot be deleted.");
1313}
1314
1315void
1316CSGBase::expandAllEngUnits()
1317{
1318 std::set<std::set<std::string>> all_type_sets;
1319 expandAllEngUnitsCycle(all_type_sets);
1320}
1321
1322void
1323CSGBase::expandAllEngUnitsCycle(std::set<std::set<std::string>> & all_type_sets)
1324{
1325 // One call to this function is one pass: collect all current eng units, expand them, then
1326 // recurse if expansion created new units. Units created during a pass are not in this pass's
1327 // snapshot; they are handled in the next pass.
1328 //
1329 // Cycle check: if the same combination of unit types appeared at the start of a prior pass,
1330 // expansion is stuck repeating the same configuration. Tracking the full type-set (not
1331 // individual types) prevents false positives when a type reappears because it was produced
1332 // by a different type's expansion rather than its own.
1333 std::set<std::string> current_types;
1334 for (const auto & u : getAllEngUnits())
1335 current_types.insert(u.get().getUnitType());
1336
1337 if (all_type_sets.count(
1338 current_types)) // this expansion set was already captured which means we are cycling
1339 mooseError("Circular dependency detected in engineering unit expansion");
1340
1341 all_type_sets.insert(current_types);
1342
1343 // Snapshot raw pointers before expanding. Units are destroyed after expansion so iterating live
1344 // references would dangle.
1345 std::vector<const CSGSurfaceEngUnit *> surfs;
1346 std::vector<const CSGCellEngUnit *> cells;
1347 std::vector<const CSGUniverseEngUnit *> univs;
1348 for (const auto & u : getAllSurfaceEngUnits())
1349 surfs.push_back(&u.get());
1350 for (const auto & u : getAllCellEngUnits())
1351 cells.push_back(&u.get());
1352 for (const auto & u : getAllUniverseEngUnits())
1353 univs.push_back(&u.get());
1354
1355 // Expand all units in this pass
1356 for (const auto * s : surfs)
1357 expandEngUnit(*s);
1358 for (const auto * c : cells)
1359 expandEngUnit(*c);
1360 for (const auto * u : univs)
1361 expandEngUnit(*u);
1362
1363 // if engineering units exist after completion of all expansions above, then start the next "pass"
1364 // through this expansion process. This will create a new set of "current_types" to check.
1365 if (!getAllEngUnits().empty())
1366 expandAllEngUnitsCycle(all_type_sets);
1367}
1368
1370CSGBase::expandEngUnit(const CSGSurfaceEngUnit & unit)
1371{
1372 // unit is const because the eng-unit API exposes only const references; re-fetch a mutable
1373 // reference to the same object from the owning surface list to perform the expansion, which
1374 // mutates and consumes the unit (expandUnit() is non-const).
1375 auto & mutable_unit = cast_ref<CSGSurfaceEngUnit &>(_surface_list.getSurface(unit.getName()));
1376
1377 // Derived class creates the CSGSurface object(s) in the unit's base object and sets
1378 // _expanded_region
1379 mutable_unit.expandUnit();
1380
1381 // check that the base object that was generated has only surfaces and no cells or universes
1382 // (except root).
1383 auto unit_base = mutable_unit.getBase();
1384 if ((unit_base.getAllCells().size() > 0) || (unit_base.getAllUniverses().size() > 1))
1385 mooseError("CSGSurfaceEngineering unit ",
1386 mutable_unit.getName(),
1387 " of type ",
1388 mutable_unit.getUnitType(),
1389 " contains either cells or universes (beyond the root universe) after expansion, "
1390 "but should only contain surfaces.");
1391
1392 // Join the unit's base object into this; transfers surfaces (and any other objects) during merge.
1393 joinOtherBase(mutable_unit.releaseBase(), false);
1394
1395 // Derived class provides the expanded region formed by the expanded surfaces
1396 CSGRegion expanded_region = mutable_unit.getExpandedRegion();
1397
1398 // Propagate any stored transformations from the EngUnit to all new expanded surfaces
1399 const auto & trans = cast_ref<const CSGSurface &>(mutable_unit).getTransformations();
1400 if (!trans.empty())
1401 for (const auto & surf_ref : expanded_region.getSurfaces())
1402 {
1403 CSGSurface & mutable_surf = _surface_list.getSurface(surf_ref.get().getName());
1404 for (const auto & [trans_type, values] : trans)
1405 mutable_surf.addTransformation(trans_type, values);
1406 }
1407
1408 // Replace every CSGSurfaceEngUnit reference in regions of CSGCells with the expanded sub-region
1409 replaceSurfaceRefsWithRegion(cast_ref<const CSGSurface &>(mutable_unit), expanded_region);
1410
1411 // Remove the EngUnit (destroyed here, no more references to it after
1412 // replaceSurfaceRefsWithRegion)
1413 deleteEngUnit(unit);
1414 return expanded_region;
1415}
1416
1417const CSGCell &
1418CSGBase::expandEngUnit(const CSGCellEngUnit & unit)
1419{
1420 // unit is const because the eng-unit API exposes only const references; re-fetch a mutable
1421 // reference to the same object from the owning cell list to perform the expansion, which
1422 // mutates and consumes the unit (expandUnit() is non-const).
1423 auto & mutable_unit = cast_ref<CSGCellEngUnit &>(_cell_list.getCell(unit.getName()));
1424
1425 // Derived class populates an internal base object (owned by the unit) with the expanded cell (in
1426 // root) and any supports
1427 mutable_unit.expandUnit();
1428
1429 // Capture a reference to the expanded cell before the join. joinOtherBase transfers ownership
1430 // of the cell's unique_ptr but does not relocate the object, so the reference stays valid.
1431 // getExpandedCell also validates that root has exactly 1 cell.
1432 const CSGCell & expanded_cell = mutable_unit.getExpandedCell();
1433
1434 // Join the unit's base object: 1-param merges root cells into this root
1435 joinOtherBase(mutable_unit.releaseBase(), false);
1436
1437 // Propagate any stored transformations from the EngUnit to the expanded cell
1438 const auto & trans = cast_ref<const CSGCell &>(mutable_unit).getTransformations();
1439 if (!trans.empty())
1440 {
1441 CSGCell & mutable_cell = _cell_list.getCell(expanded_cell.getName());
1442 for (const auto & [trans_type, values] : trans)
1443 mutable_cell.addTransformation(trans_type, values);
1444 }
1445
1446 // The join added the expanded cell to this root via root-merge; remove it so
1447 // replaceCellRefs() can place it in the correct universe(s)
1448 if (getRootUniverse().hasCell(expanded_cell.getName()))
1449 removeCellFromUniverse(getRootUniverse(), expanded_cell);
1450
1451 // Replace all references to the CSGCellEngUnit in universes with the new expanded CSGCell
1452 replaceCellRefs(cast_ref<const CSGCell &>(mutable_unit), expanded_cell);
1453
1454 // Remove the EngUnit (destroyed here, no more references to it after replaceCellRefs)
1455 deleteEngUnit(unit);
1456 return expanded_cell;
1457}
1458
1459const CSGUniverse &
1460CSGBase::expandEngUnit(const CSGUniverseEngUnit & unit)
1461{
1462 auto unit_name = unit.getName();
1463
1464 // unit is const because the eng-unit API exposes only const references; re-fetch a mutable
1465 // reference to the same object from the owning universe list to perform the expansion, which
1466 // mutates and consumes the unit (expandUnit() is non-const).
1467 auto & mutable_unit = cast_ref<CSGUniverseEngUnit &>(_universe_list.getUniverse(unit_name));
1468
1469 // Derived class populates the unit's base object; the root of this base is the expanded universe
1470 // that will be used to replace this universe unit
1471 mutable_unit.expandUnit();
1472
1473 // Capture the name of the expanded universe (the unit base's root universe) before the join
1474 // getExpandedUniverse will validate that the root contains cells and was properly
1475 // implemented/expanded such that incoming cells and universes are all linked to the root.
1476 auto & pre_join_univ = mutable_unit.getExpandedUniverse();
1477 auto expanded_name = pre_join_univ.getName();
1478
1479 // Check that the expanded name for the new root universe has been updated to something other than
1480 // ROOT_UNIVERSE. If name was not already updated, issue a warning (debug) and update the name
1481 // automatically. This only matters if the current root universe is also named ROOT_UNIVERSE
1482 // so we only need to check if the name matches the root universe name (rather than explicitly
1483 // checking for the name ROOT_UNIVERSE).
1484
1485 // release the incoming base object to be able to rename if necessary
1486 auto unit_base = mutable_unit.releaseBase();
1487 if (expanded_name == getRootUniverse().getName())
1488 {
1489 // root universe must be renamed
1490 auto new_expanded_name = unit_name + "_expanded_root";
1491#ifdef DEBUG
1492 mooseInfoRepeated("Universe engineering unit " + unit_name +
1493 " has an expanded root universe named " + expanded_name +
1494 ", which is identical to the name of the current root universe. The expanded "
1495 "universe will be renamed " +
1496 new_expanded_name + ".");
1497#endif
1498
1499 unit_base->renameRootUniverse(new_expanded_name);
1500 expanded_name = new_expanded_name;
1501 }
1502
1503 // Join the unit's base into this: all objects are transferred and the incoming root is added as
1504 // a named non-root universe (expanded_name). If the root universe's name is not unique (i.e. it
1505 // was left named ROOT_UNIVERSE), this will throw an error.
1506 joinOtherBase(std::move(unit_base), false, expanded_name);
1507
1508 // must get this by name after joining because the join method rebuilds the universe and the
1509 // previous reference from getExpandedUniverse is not valid anymore.
1510 const CSGUniverse & expanded_univ = getUniverseByName(expanded_name);
1511
1512 // Propagate any stored transformations from the EngUnit to the new expanded universe
1513 const auto & trans = cast_ref<const CSGUniverse &>(mutable_unit).getTransformations();
1514 if (!trans.empty())
1515 {
1516 CSGUniverse & mutable_univ = _universe_list.getUniverse(expanded_univ.getName());
1517 for (const auto & [trans_type, values] : trans)
1518 mutable_univ.addTransformation(trans_type, values);
1519 }
1520
1521 // Replace references in cell fills, lattice maps and outers, and the root universe
1522 replaceUniverseRefs(cast_ref<const CSGUniverse &>(mutable_unit), expanded_univ);
1523
1524 // Remove the EngUnit (destroyed here, no more references to it after replaceUniverseRefs)
1525 deleteEngUnit(unit);
1526 return expanded_univ;
1527}
1528
1529void
1530CSGBase::replaceUniverseRefs(const CSGUniverse & old_univ, const CSGUniverse & new_univ)
1531{
1532 // 1. Cell fills
1533 for (const auto & cell_ref : getAllCells())
1534 {
1535 const CSGCell & cell = cell_ref.get();
1536 if (cell.getFillType() == "UNIVERSE" && cell.getFillUniverse() == old_univ)
1537 updateCellFill(cell, &new_univ);
1538 }
1539
1540 // 2. Lattice universe maps and outer fills
1541 for (const auto & lat_ref : getAllLattices())
1542 {
1543 const CSGLattice & lat = lat_ref.get();
1544 if (lat.getOuterType() == "UNIVERSE" && lat.getOuterUniverse() == old_univ)
1545 setLatticeOuter(lat, new_univ);
1546
1547 auto lat_map = lat.getUniverses();
1548 for (std::size_t row = 0; row < lat_map.size(); ++row)
1549 for (std::size_t col = 0; col < lat_map[row].size(); ++col)
1550 if (lat_map[row][col].get() == old_univ)
1551 setUniverseAtLatticeIndex(lat, new_univ, {static_cast<int>(row), static_cast<int>(col)});
1552 }
1553
1554 // 3. Root universe pointer in universe list
1555 if (getRootUniverse() == old_univ)
1556 _universe_list._root_universe = &new_univ;
1557}
1558
1559void
1560CSGBase::replaceCellRefs(const CSGCell & old_cell, const CSGCell & new_cell)
1561{
1562 for (const auto & univ_ref : getAllUniverses())
1563 {
1564 const CSGUniverse & univ = univ_ref.get();
1565 for (const auto & cell_ref : univ.getAllCells())
1566 if (&cell_ref.get() == &old_cell)
1567 {
1568 removeCellFromUniverse(univ, old_cell);
1569 addCellToUniverse(univ, new_cell);
1570 }
1571 }
1572}
1573
1574void
1575CSGBase::replaceSurfaceRefsWithRegion(const CSGSurface & old_surf, const CSGRegion & sub_region)
1576{
1577 for (const auto & cell_ref : getAllCells())
1578 {
1579 const CSGCell & cell = cell_ref.get();
1580 CSGRegion new_region = cell.getRegion();
1581 if (new_region.getRegionType() == CSGRegion::RegionType::EMPTY)
1582 continue; // cell units do not have a region so skip (can also skip if a regular cell has an
1583 // empty region)
1584 new_region.replaceWithSubRegion(old_surf, sub_region);
1585 updateCellRegion(cell, new_region);
1586 }
1587}
1588
1589nlohmann::json
1590CSGBase::generateOutput() const
1591{
1592 // Check that orphaned universes do not exist in universe list of CSGBase object
1593 checkUniverseLinking();
1594
1595 nlohmann::json csg_json;
1596
1597 csg_json["surfaces"] = {}; // if empty (all are eng units), this will be deleted later
1598 csg_json["cells"] = {}; // if empty (all are eng units), this will be deleted later
1599 csg_json["universes"] = {}; // root universe always exists, so this does not get deleted later
1600
1601 // get all surfaces information
1602 auto all_surfs = getAllSurfaces();
1603 for (const CSGSurface & s : all_surfs)
1604 {
1605 if (surfaceToEngUnit(s))
1606 continue; // engineering units are written in a separate section
1607 const auto & surf_name = s.getName();
1608 const auto & coeffs = s.getCoeffs();
1609 csg_json["surfaces"][surf_name] = {{"type", s.getSurfaceType()}, {"coefficients", {}}};
1610 for (const auto & c : coeffs)
1611 csg_json["surfaces"][surf_name]["coefficients"][c.first] = c.second;
1612 // include any information about transformations if present
1613 if (s.getTransformations().size() > 0)
1614 csg_json["surfaces"][surf_name]["transformations"] = s.getTransformationsAsStrings();
1615 }
1616
1617 // Drop the surfaces section if nothing was written (e.g. all surfaces were engineering units,
1618 // which are output in the units section instead)
1619 if (csg_json["surfaces"].empty())
1620 csg_json.erase("surfaces");
1621
1622 // Print out cell information
1623 auto all_cells = getAllCells();
1624 for (const CSGCell & c : all_cells)
1625 {
1626 if (cellToEngUnit(c))
1627 continue; // engineering units are written in a separate section
1628 const auto & cell_name = c.getName();
1629 const auto & cell_region_infix = c.getRegion().toInfixJSON();
1630 const auto & cell_region_postfix = c.getRegion().toPostfixStringList();
1631 const auto & cell_filltype = c.getFillType();
1632 const auto & fill_name = c.getFillName();
1633 csg_json["cells"][cell_name]["filltype"] = cell_filltype;
1634 csg_json["cells"][cell_name]["region_infix"] = cell_region_infix;
1635 csg_json["cells"][cell_name]["region_postfix"] = cell_region_postfix;
1636 csg_json["cells"][cell_name]["fill"] = fill_name;
1637 // include any information about transformations if present
1638 if (c.getTransformations().size())
1639 csg_json["cells"][cell_name]["transformations"] = c.getTransformationsAsStrings();
1640 }
1641
1642 // Drop the cells section if nothing was written (e.g. all cells were engineering units,
1643 // which are output in the units section instead)
1644 if (csg_json["cells"].empty())
1645 csg_json.erase("cells");
1646
1647 // Print out universe information
1648 auto all_univs = getAllUniverses();
1649 for (const CSGUniverse & u : all_univs)
1650 {
1651 if (universeToEngUnit(u))
1652 continue; // engineering units are written in a separate section
1653 const auto & univ_name = u.getName();
1654 const auto & univ_cells = u.getAllCells();
1655 csg_json["universes"][univ_name]["cells"] = {};
1656 for (const CSGCell & c : univ_cells)
1657 csg_json["universes"][univ_name]["cells"].push_back(c.getName());
1658 if (u.isRoot())
1659 csg_json["universes"][univ_name]["root"] = u.isRoot();
1660 // include any information about transformations if present
1661 if (u.getTransformations().size())
1662 csg_json["universes"][univ_name]["transformations"] = u.getTransformationsAsStrings();
1663 }
1664
1665 // print out lattice information if lattices exist
1666 auto all_lats = getAllLattices();
1667 if (all_lats.size())
1668 {
1669 csg_json["lattices"] = {};
1670 for (const CSGLattice & lat : all_lats)
1671 {
1672 const auto & lat_name = lat.getName();
1673 csg_json["lattices"][lat_name] = {};
1674 csg_json["lattices"][lat_name]["type"] = lat.getType();
1675 const auto & outer_type = lat.getOuterType();
1676 csg_json["lattices"][lat_name]["outertype"] = outer_type;
1677 if (outer_type == "UNIVERSE")
1678 csg_json["lattices"][lat_name]["outer"] = lat.getOuterUniverse().getName();
1679 else if (outer_type == "CSG_MATERIAL")
1680 csg_json["lattices"][lat_name]["outer"] = lat.getOuterMaterial();
1681 // write out any additional attributes
1682 csg_json["lattices"][lat_name]["attributes"] = {};
1683 const auto & lat_attrs = lat.getAttributes();
1684 for (const auto & attr : lat_attrs)
1685 csg_json["lattices"][lat_name]["attributes"][attr.first] = attr.second;
1686 // write the map of universe names: list of lists
1687 csg_json["lattices"][lat_name]["universes"] = lat.getUniverseNameMap();
1688 // include any information about transformations if present
1689 if (lat.getTransformations().size())
1690 csg_json["lattices"][lat_name]["transformations"] = lat.getTransformationsAsStrings();
1691 }
1692 }
1693
1694 // include engineering units if they exist
1695 auto all_units = getAllEngUnits();
1696 if (all_units.size())
1697 {
1698 csg_json["units"] = {};
1699 for (const CSGEngUnit & unit : all_units)
1700 {
1701 const auto & unit_name = unit.getName();
1702 csg_json["units"][unit_name] = {};
1703 // behavior and type
1704 csg_json["units"][unit_name]["unit_type"] = unit.getUnitType();
1705 csg_json["units"][unit_name]["behavior"] = unit.getBehavior();
1706 // any unit-specific attributes
1707 csg_json["units"][unit_name]["attributes"] = {};
1708 const auto & unit_attrs = unit.getAttributes();
1709 for (const auto & attr : unit_attrs)
1710 csg_json["units"][unit_name]["attributes"][attr.first] = attr.second;
1711 if (unit.getTransformations().size())
1712 csg_json["units"][unit_name]["transformations"] = unit.getTransformationsAsStrings();
1713 }
1714 }
1715
1716 return csg_json;
1717}
1718
1719bool
1720CSGBase::operator==(const CSGBase & other) const
1721{
1722 const auto & surf_list = this->getSurfaceList();
1723 const auto & other_surf_list = other.getSurfaceList();
1724 const auto & cell_list = this->getCellList();
1725 const auto & other_cell_list = other.getCellList();
1726 const auto & univ_list = this->getUniverseList();
1727 const auto & other_univ_list = other.getUniverseList();
1728 const auto & lat_list = this->getLatticeList();
1729 const auto & other_lat_list = other.getLatticeList();
1730 const auto & eng_unit_list = this->getEngUnitList();
1731 const auto & other_eng_unit_list = other.getEngUnitList();
1732 return (surf_list == other_surf_list) && (cell_list == other_cell_list) &&
1733 (univ_list == other_univ_list) && (lat_list == other_lat_list) &&
1734 (eng_unit_list == other_eng_unit_list);
1735}
1736
1737bool
1738CSGBase::operator!=(const CSGBase & other) const
1739{
1740 return !(*this == other);
1741}
1742} // namespace CSG
void mooseInfoRepeated(Args &&... args)
Emit an informational message with the given stringified, concatenated args.
Definition MooseError.h:409
void mooseWarning(Args &&... args)
Emit a warning message with the given stringified, concatenated args.
Definition MooseError.h:345
void mooseError(Args &&... args)
Emit an error message with the given stringified, concatenated args and terminate the application.
Definition MooseError.h:311
std::array< Real, 2 > values
Definition MortarUtils.C:52
if(!dmm->_nl) SETERRQ(PETSC_COMM_WORLD
CSGBase creates an internal representation of a Constructive Solid Geometry (CSG) model.
Definition CSGBase.h:54
const CSGSurfaceList & getSurfaceList() const
Get a const reference to the CSGSurfaceList object.
Definition CSGBase.h:972
const CSGCell & addCellToList(const CSGCell &cell)
Add a new cell to the cell list based on a cell reference.
Definition CSGBase.C:136
const CSGCellList & getCellList() const
Get a const reference to the CSGCellList object.
Definition CSGBase.h:986
CSGCellList _cell_list
List of cells associated with CSG object.
Definition CSGBase.h:1264
std::unique_ptr< CSGBase > clone() const
Create a deep copy of this CSGBase instance.
Definition CSGBase.C:78
const CSGLattice & addLatticeToList(const CSGLattice &lattice)
Add a new lattice to the lattice list based on a lattice reference.
Definition CSGBase.C:202
const CSGUniverse & addUniverseToList(const CSGUniverse &univ)
Add a new universe to the universe list based on a universe reference.
Definition CSGBase.C:177
std::vector< std::reference_wrapper< const CSGUniverseEngUnit > > getAllUniverseEngUnits() const
Get all universe-like engineering units.
Definition CSGBase.h:659
const CSGUniverseList & getUniverseList() const
Get a const reference to the CSGUniverseList object.
Definition CSGBase.h:1000
void rebuildEngUnitList()
rebuilds the list of raw pointers to engineering units by iterating through the surface,...
Definition CSGBase.C:997
const CSGLatticeList & getLatticeList() const
Get a const reference to the CSGLatticeList object.
Definition CSGBase.h:1014
const CSGEngUnitList & getEngUnitList() const
Get a const reference to the CSGEngUnitList object.
Definition CSGBase.h:1086
const CSGUniverse & getRootUniverse() const
Get the Root Universe object.
Definition CSGBase.h:277
const CSGUniverseEngUnit * universeToEngUnit(const CSGUniverse &univ) const
Returns the CSGUniverseEngUnit pointer if univ is an eng unit, nullptr otherwise.
Definition CSGBase.h:1231
std::vector< std::reference_wrapper< const CSGCellEngUnit > > getAllCellEngUnits() const
Get all cell-like engineering units in CSGBase.
Definition CSGBase.h:649
~CSGBase()
Destructor.
Definition CSGBase.C:75
void addCellToUniverse(const CSGUniverse &universe, const CSGCell &cell)
Add a cell to an existing universe.
Definition CSGBase.C:525
const T & addEngUnit(std::unique_ptr< T > unit, const CSGUniverse *add_to_univ=nullptr)
Add an engineering unit (surface-, cell-, or universe-like object) to this CSGBase.
Definition CSGBase.h:539
CSGBase()
Default constructor.
Definition CSGBase.C:17
const CSGCellEngUnit * cellToEngUnit(const CSGCell &cell) const
Returns the CSGCellEngUnit pointer if cell is an eng unit, nullptr otherwise.
Definition CSGBase.h:1219
CSGCellEngUnit is an abstract base class for "engineering units" that are cell-like.
const std::string & getName() const override
Satisfy CSGEngUnit::getName() (resolved via CSGCell::getName())
CSGCellList creates a container for CSGCell objects to pass to CSGBase object.
Definition CSGCellList.h:21
std::unordered_map< std::string, std::unique_ptr< CSGCell > > & getCellListMap()
Get non-const map of all names to cells in cell list.
Definition CSGCellList.h:92
CSGCell & getCell(const std::string &name) const
Get the CSGCell by name.
Definition CSGCellList.C:44
CSGCell & addCell(std::unique_ptr< CSGCell > cell, const bool ignore_identical_cell=false)
add a cell to the CellList.
Definition CSGCellList.C:18
CSGCell creates an internal representation of a Constructive Solid Geometry (CSG) cell,...
Definition CSGCell.h:30
const CSGRegion & getRegion() const
Get the cell region.
Definition CSGCell.h:119
const std::string & getName() const
Get the cell name.
Definition CSGCell.h:112
const CSGLattice & getFillLattice() const
Get the cell fill if fill type is LATTICE.
Definition CSGCell.C:77
const std::string getFillType() const
Get the type of fill for the cell.
Definition CSGCell.h:77
const CSGUniverse & getFillUniverse() const
Get the cell fill if fill type is UNIVERSE.
Definition CSGCell.C:59
const std::string & getFillMaterial() const
Get the cell fill material name if fill fype is CSG_MATERIAL.
Definition CSGCell.C:68
CSGEngUnitList is a non-owning index of CSGEngUnit objects stored in the type lists (CSGSurfaceList,...
CSGEngUnit is the abstract base class for all "engineering unit" types in the CSG system.
Definition CSGEngUnit.h:33
virtual const std::string & getName() const =0
Get the unique instance name of this engineering unit.
CSGLatticeList creates a container for CSGLattice objects to pass to CSGBase.
std::unordered_map< std::string, std::unique_ptr< CSGLattice > > & getLatticeListMap()
Get map of all names to lattices in lattice list.
CSGLattice is the abstract class for defining lattices.
Definition CSGLattice.h:35
std::vector< std::vector< std::reference_wrapper< const CSGUniverse > > > getUniverses() const
Get the arrangement of CSGUniverses in the lattice.
Definition CSGLattice.h:98
virtual std::unique_ptr< CSGLattice > clone() const =0
const std::string & getName() const
Get the name of lattice.
Definition CSGLattice.h:60
const std::string getOuterType() const
Get the type of outer that fills the space around the lattice elements.
Definition CSGLattice.h:77
const CSGUniverse & getOuterUniverse() const
Get the outer universe if outer type is UNIVERSE.
Definition CSGLattice.C:109
CSGRegions creates an internal representation of a CSG region, which can refer to an intersection,...
Definition CSGRegion.h:23
RegionType getRegionType() const
Get the region type.
Definition CSGRegion.h:123
void replaceWithSubRegion(const CSGSurface &old_surf, const CSGRegion &sub_region)
Replace all occurrences of old_surf in this region's postfix token stream with the tokens of sub_regi...
Definition CSGRegion.C:366
std::vector< std::reference_wrapper< const CSGSurface > > getSurfaces() const
Get the list of surfaces associated with the region.
Definition CSGRegion.C:289
CSGSurfaceEngUnit is an abstract base class for "engineering units" that can be used as surfaces in c...
const std::string & getName() const override
Satisfy CSGEngUnit::getName() – resolved via CSGSurface::getName()
CSGSurfaceList is a container for storing CSGSurface objects in the CSGBase object.
std::unordered_map< std::string, std::unique_ptr< CSGSurface > > & getSurfaceListMap()
Get non-const map of all names to surfaces in surface list.
CSGSurface creates an internal representation of a Constructive Solid Geometry (CSG) surface,...
Definition CSGSurface.h:27
const std::string & getName() const
Get the name of surface.
Definition CSGSurface.h:90
void addTransformation(TransformationType type, const std::tuple< Real, Real, Real > &values)
Add a transformation to the list of transformations.
CSGUniverseEngUnit is an abstract base class for "engineering units" that are universe-like.
const std::string & getName() const override
Satisfy CSGEngUnit::getName() (resolved via CSGUniverse::getName())
CSGUniverseList creates a container for CSGUniverse objects to pass to CSGBase.
std::unordered_map< std::string, std::unique_ptr< CSGUniverse > > & getUniverseListMap()
Get non-const map of all names to universes in universe list.
CSGUniverse creates an internal representation of a Constructive Solid Geometry (CSG) universe,...
Definition CSGUniverse.h:28
const std::string & getName() const
Get the name of the universe.
Definition CSGUniverse.h:80
const std::vector< std::reference_wrapper< const CSGCell > > & getAllCells() const
Get list of the all cells in the universe.
Definition CSGUniverse.h:73
std::variant< std::reference_wrapper< const CSGSurface >, std::reference_wrapper< const CSGCell >, std::reference_wrapper< const CSGUniverse >, std::reference_wrapper< const CSGRegion >, std::reference_wrapper< const CSGLattice >, std::reference_wrapper< const CSGEngUnit > > CSGObjectVariant
Define a variant type that can hold references to different CSG object types.
Definition CSGBase.h:47
TransformationType
Enumeration of transformation types that can be applied to CSG objects.
RotationAxisType
Enumeration of axis types for rotations.
Definition CSGBase.h:32