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