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