https://mooseframework.inl.gov
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 
12 namespace CSG
13 {
14 
16  : _surface_list(CSGSurfaceList()), _cell_list(CSGCellList()), _universe_list(CSGUniverseList())
17 {
18 }
19 
20 CSGBase::CSGBase(const CSGBase & other_base)
21  : _surface_list(other_base.getSurfaceList()),
22  _cell_list(CSGCellList()),
23  _universe_list(CSGUniverseList())
24 {
25  // Iterate through all cell references from the other CSGBase instance and
26  // create new CSGCell pointers based on these references. This is done
27  // recursively to properly handle cells with universe fills
28  for (const auto & [name, cell] : other_base.getCellList().getCellListMap())
29  addCellToList(*cell);
30 
31  // Link all cells in other_base root universe to current root universe
32  for (auto & root_cell : other_base.getRootUniverse().getAllCells())
33  {
34  const auto & list_cell = _cell_list.getCell(root_cell.get().getName());
35  addCellToUniverse(getRootUniverse(), list_cell);
36  }
37 
38  // Iterate through all universe references from the other CSGBase instance and
39  // create new CSGUniverse pointers based on these references. This is done in case
40  // any universe exist in the universe list that are not connected to the cell list.
41  for (const auto & [name, univ] : other_base.getUniverseList().getUniverseListMap())
42  addUniverseToList(*univ);
43 }
44 
46 
47 const CSGCell &
49 {
50  // If cell has already been created, we just return a reference to it
51  const auto name = cell.getName();
52  if (_cell_list.hasCell(name))
53  return _cell_list.getCell(name);
54 
55  // Otherwise if the cell has material or void cell, we can create it directly
56  const auto fill_type = cell.getFillType();
57  const auto region = cell.getRegion();
58  if (fill_type == "VOID")
59  return _cell_list.addVoidCell(name, region);
60  else if (fill_type == "CSG_MATERIAL")
61  {
62  const auto mat_name = cell.getFillMaterial();
63  return _cell_list.addMaterialCell(name, mat_name, region);
64  }
65  // Otherwise if the cell has a universe fill, we need to recursively define
66  // all linked universes and cells first before defining this cell
67  else
68  {
69  const auto & univ = addUniverseToList(cell.getFillUniverse());
70  return _cell_list.addUniverseCell(name, univ, region);
71  }
72 }
73 
74 const CSGUniverse &
76 {
77  // If universe has already been created, we just return a reference to it
78  const auto name = univ.getName();
81 
82  // Otherwise we create a new universe based on its associated cells.
83  // addCellToList is called recursively in case associated cells have not
84  // been added to the cell list yet.
85  const auto univ_cells = univ.getAllCells();
86  std::vector<std::reference_wrapper<const CSGCell>> current_univ_cells;
87  for (const auto & univ_cell : univ_cells)
88  current_univ_cells.push_back(addCellToList(univ_cell));
89  return createUniverse(name, current_univ_cells);
90 }
91 
92 const CSGCell &
93 CSGBase::createCell(const std::string & name,
94  const std::string & mat_name,
95  const CSGRegion & region,
96  const CSGUniverse * add_to_univ)
97 {
98  checkRegionSurfaces(region);
99  auto & cell = _cell_list.addMaterialCell(name, mat_name, region);
100  if (add_to_univ)
101  addCellToUniverse(*add_to_univ, cell);
102  else
104  return cell;
105 }
106 
107 const CSGCell &
108 CSGBase::createCell(const std::string & name,
109  const CSGRegion & region,
110  const CSGUniverse * add_to_univ)
111 {
112  checkRegionSurfaces(region);
113  auto & cell = _cell_list.addVoidCell(name, region);
114  if (add_to_univ)
115  addCellToUniverse(*add_to_univ, cell);
116  else
118  return cell;
119 }
120 
121 const CSGCell &
122 CSGBase::createCell(const std::string & name,
123  const CSGUniverse & fill_univ,
124  const CSGRegion & region,
125  const CSGUniverse * add_to_univ)
126 {
127  checkRegionSurfaces(region);
128  if (add_to_univ && (&fill_univ == add_to_univ))
129  mooseError("Cell " + name +
130  " cannot be filled with the same universe to which it is being added.");
131 
132  auto & cell = _cell_list.addUniverseCell(name, fill_univ, region);
133  if (add_to_univ)
134  addCellToUniverse(*add_to_univ, cell);
135  else
137  return cell;
138 }
139 
140 void
141 CSGBase::updateCellRegion(const CSGCell & cell, const CSGRegion & region)
142 {
143  checkRegionSurfaces(region);
144  if (!checkCellInBase(cell))
145  mooseError("The region of cell with name " + cell.getName() +
146  " is being updated that is different " +
147  "from the cell of the same name in the CSGBase instance.");
148  auto & list_cell = _cell_list.getCell(cell.getName());
149  list_cell.updateRegion(region);
150 }
151 
152 const CSGUniverse &
153 CSGBase::createUniverse(const std::string & name,
154  std::vector<std::reference_wrapper<const CSGCell>> & cells)
155 {
156  auto & univ = _universe_list.addUniverse(name);
157  addCellsToUniverse(univ, cells); // performs a check that cells are a part of this base
158  return univ;
159 }
160 
161 void
162 CSGBase::addCellToUniverse(const CSGUniverse & universe, const CSGCell & cell)
163 {
164  // make sure cell is a part of this CSGBase instance
165  if (!checkCellInBase(cell))
166  mooseError("A cell named " + cell.getName() + " is being added to universe " +
167  universe.getName() +
168  " that is different from the cell of the same name in the CSGBase instance.");
169  // make sure universe is a part of this CSGBase instance
170  if (!checkUniverseInBase(universe))
171  mooseError("Cells are being added to a universe named " + universe.getName() +
172  " that is different " +
173  "from the universe of the same name in the CSGBase instance.");
174  auto & univ = _universe_list.getUniverse(universe.getName());
175  univ.addCell(cell);
176 }
177 
178 void
180  std::vector<std::reference_wrapper<const CSGCell>> & cells)
181 {
182  for (auto & c : cells)
183  addCellToUniverse(universe, c);
184 }
185 
186 void
187 CSGBase::removeCellFromUniverse(const CSGUniverse & universe, const CSGCell & cell)
188 {
189  // make sure cell is a part of this CSGBase instance
190  if (!checkCellInBase(cell))
191  mooseError("A cell named " + cell.getName() + " is being removed from universe " +
192  universe.getName() +
193  " that is different from the cell of the same name in the CSGBase instance.");
194  // make sure universe is a part of this CSGBase instance
195  if (!checkUniverseInBase(universe))
196  mooseError("Cells are being removed from a universe named " + universe.getName() +
197  " that is different " +
198  "from the universe of the same name in the CSGBase instance.");
199  auto & univ = _universe_list.getUniverse(universe.getName());
200  univ.removeCell(cell.getName());
201 }
202 
203 void
205  std::vector<std::reference_wrapper<const CSGCell>> & cells)
206 {
207  for (auto & c : cells)
208  removeCellFromUniverse(universe, c);
209 }
210 
211 void
212 CSGBase::joinOtherBase(std::unique_ptr<CSGBase> base)
213 {
214  joinSurfaceList(base->getSurfaceList());
215  joinCellList(base->getCellList());
216  joinUniverseList(base->getUniverseList());
217 }
218 
219 void
220 CSGBase::joinOtherBase(std::unique_ptr<CSGBase> base, std::string & new_root_name_join)
221 {
222  joinSurfaceList(base->getSurfaceList());
223  joinCellList(base->getCellList());
224  joinUniverseList(base->getUniverseList(), new_root_name_join);
225 }
226 
227 void
228 CSGBase::joinOtherBase(std::unique_ptr<CSGBase> base,
229  const std::string & new_root_name_base,
230  const std::string & new_root_name_join)
231 {
232  joinSurfaceList(base->getSurfaceList());
233  joinCellList(base->getCellList());
234  joinUniverseList(base->getUniverseList(), new_root_name_base, new_root_name_join);
235 }
236 
237 void
239 {
240  // TODO: check if surface is a duplicate (by definition) and skip
241  // adding if duplicate; must update references to the surface in cell
242  // region definitions.
243  auto & surf_list_map = surf_list.getSurfaceListMap();
244  for (auto & s : surf_list_map)
245  _surface_list.addSurface(std::move(s.second));
246 }
247 
248 void
250 {
251  auto & cell_list_map = cell_list.getCellListMap();
252  for (auto & c : cell_list_map)
253  _cell_list.addCell(std::move(c.second));
254 }
255 
256 void
258 {
259  // case 1: incoming root is joined into existing root; no new universes are created
260  auto & univ_list_map = univ_list.getUniverseListMap();
261  auto & root = getRootUniverse(); // this root universe
262  for (auto & u : univ_list_map)
263  {
264  if (u.second->isRoot())
265  {
266  // add existing cells to current root instead of creating new universe
267  auto all_cells = u.second->getAllCells();
268  for (auto & cell : all_cells)
269  addCellToUniverse(root, cell);
270  }
271  else // unique non-root universe to add to list
272  _universe_list.addUniverse(std::move(u.second));
273  }
274 }
275 
276 void
277 CSGBase::joinUniverseList(CSGUniverseList & univ_list, const std::string & new_root_name_incoming)
278 {
279  // case 2: incoming root is turned into new universe and existing root remains root
280 
281  // add incoming universes to current Base
282  auto & all_univs = univ_list.getUniverseListMap();
283  for (auto & u : all_univs)
284  {
285  if (u.second->isRoot())
286  {
287  // create new universe from incoming root universe
288  auto all_cells = u.second->getAllCells();
289  createUniverse(new_root_name_incoming, all_cells);
290  }
291  else // unique non-root universe to add to list
292  _universe_list.addUniverse(std::move(u.second));
293  }
294 }
295 
296 void
298  const std::string & new_root_name_base,
299  const std::string & new_root_name_incoming)
300 {
301  // case 3: each root universe becomes a new universe and a new root is created
302 
303  // make a new universe from the existing root universe
304  auto & root = getRootUniverse();
305  auto root_cells = root.getAllCells();
306  createUniverse(new_root_name_base, root_cells);
307  removeCellsFromUniverse(root, root_cells);
308 
309  // add incoming universes to current Base
310  auto & all_univs = univ_list.getUniverseListMap();
311  for (auto & u : all_univs)
312  {
313  if (u.second->isRoot())
314  {
315  // create new universe from incoming root universe
316  auto all_cells = u.second->getAllCells();
317  createUniverse(new_root_name_incoming, all_cells);
318  }
319  else // unique non-root universe to add to list
320  _universe_list.addUniverse(std::move(u.second));
321  }
322 }
323 
324 void
326 {
327  auto & surfs = region.getSurfaces();
328  for (const CSGSurface & s : surfs)
329  {
330  auto sname = s.getName();
331  // if there is no surface by this name at all, there will be an error from getSurface
332  const auto & list_surf = _surface_list.getSurface(s.getName());
333  // if there is a surface by the same name, check that it is actually the surface being used
334  // (ie same surface points to same location in memory)
335  if (&s != &list_surf)
336  mooseError("Region is being set with a surface named " + sname +
337  " that is different from the surface of the same name in the CSGBase instance.");
338  }
339 }
340 
341 bool
343 {
344  auto name = cell.getName();
345  // if no cell by this name exists, an error will be produced by getCell
346  auto & list_cell = _cell_list.getCell(name);
347  // return whether that the cell in the list is the same as the cell provided (in memory)
348  return &cell == &list_cell;
349 }
350 
351 bool
353 {
354  auto name = universe.getName();
355  // if no universe by this name exists, an error will be produced by getUniverse
356  auto & list_univ = _universe_list.getUniverse(name);
357  // return whether that the cell in the list is the same as the cell provided (in memory)
358  return &universe == &list_univ;
359 }
360 
361 void
363 {
364  std::vector<std::string> linked_universe_names;
365 
366  // Recursively figure out which universe names are linked to root universe
367  getLinkedUniverses(getRootUniverse(), linked_universe_names);
368 
369  // Iterate through all universes in universe list and check that they exist in universes linked
370  // to root universe list
371  for (const CSGUniverse & univ : getAllUniverses())
372  if (std::find(linked_universe_names.begin(), linked_universe_names.end(), univ.getName()) ==
373  linked_universe_names.end())
374  mooseWarning("Universe with name ", univ.getName(), " is not linked to root universe.");
375 }
376 
377 void
379  std::vector<std::string> & linked_universe_names) const
380 {
381  linked_universe_names.push_back(univ.getName());
382  const auto & univ_cells = univ.getAllCells();
383  for (const CSGCell & cell : univ_cells)
384  if (cell.getFillType() == "UNIVERSE")
385  getLinkedUniverses(cell.getFillUniverse(), linked_universe_names);
386 }
387 
388 nlohmann::json
390 {
391  // Check that orphaned universes do not exist in universe list of CSGBase object
393 
394  nlohmann::json csg_json;
395 
396  csg_json["surfaces"] = {};
397  csg_json["cells"] = {};
398  csg_json["universes"] = {};
399 
400  // get all surfaces information
401  auto all_surfs = getAllSurfaces();
402  for (const CSGSurface & s : all_surfs)
403  {
404  const auto & surf_name = s.getName();
405  const auto & coeffs = s.getCoeffs();
406  csg_json["surfaces"][surf_name] = {{"type", s.getSurfaceType()}, {"coefficients", {}}};
407  for (const auto & c : coeffs)
408  csg_json["surfaces"][surf_name]["coefficients"][c.first] = c.second;
409  }
410 
411  // Print out cell information
412  auto all_cells = getAllCells();
413  for (const CSGCell & c : all_cells)
414  {
415  const auto & cell_name = c.getName();
416  const auto & cell_region = c.getRegionAsString();
417  const auto & cell_filltype = c.getFillType();
418  const auto & fill_name = c.getFillName();
419  csg_json["cells"][cell_name]["filltype"] = cell_filltype;
420  csg_json["cells"][cell_name]["region"] = cell_region;
421  csg_json["cells"][cell_name]["fill"] = fill_name;
422  }
423 
424  // Print out universe information
425  auto all_univs = getAllUniverses();
426  for (const CSGUniverse & u : all_univs)
427  {
428  const auto & univ_name = u.getName();
429  const auto & univ_cells = u.getAllCells();
430  csg_json["universes"][univ_name]["cells"] = {};
431  for (const CSGCell & c : univ_cells)
432  csg_json["universes"][univ_name]["cells"].push_back(c.getName());
433  if (u.isRoot())
434  csg_json["universes"][univ_name]["root"] = u.isRoot();
435  }
436 
437  return csg_json;
438 }
439 
440 bool
441 CSGBase::operator==(const CSGBase & other) const
442 {
443  const auto & surf_list = this->getSurfaceList();
444  const auto & other_surf_list = other.getSurfaceList();
445  const auto & cell_list = this->getCellList();
446  const auto & other_cell_list = other.getCellList();
447  const auto & univ_list = this->getUniverseList();
448  const auto & other_univ_list = other.getUniverseList();
449  return (surf_list == other_surf_list) && (cell_list == other_cell_list) &&
450  (univ_list == other_univ_list);
451 }
452 
453 bool
454 CSGBase::operator!=(const CSGBase & other) const
455 {
456  return !(*this == other);
457 }
458 
459 } // namespace CSG
std::string name(const ElemQuality q)
CSGCell & addCell(std::unique_ptr< CSGCell > cell)
add a cell to the CellList.
Definition: CSGCellList.C:18
void joinCellList(CSGCellList &cell_list)
join a separate CSGCellList object to this one
Definition: CSGBase.C:249
KOKKOS_INLINE_FUNCTION const T * find(const T &target, const T *const begin, const T *const end)
Find a value in an array.
Definition: KokkosUtils.h:42
const CSGUniverse & getFillUniverse() const
Get the cell fill if fill type is UNIVERSE.
Definition: CSGCell.C:34
CSGCell & getCell(const std::string &name) const
Get the CSGCell by name.
Definition: CSGCellList.C:28
const std::string & getName() const
Get the cell name.
Definition: CSGCell.h:94
std::vector< std::reference_wrapper< const CSGUniverse > > getAllUniverses() const
Get all universe objects.
Definition: CSGBase.h:262
CSGUniverseList _universe_list
List of universes associated with CSG object.
Definition: CSGBase.h:473
const std::string getFillType() const
Get the type of fill for the cell.
Definition: CSGCell.h:66
void updateRegion(const CSGRegion &region)
Definition: CSGCell.h:123
CSGRegions creates an internal representation of a CSG region, which can refer to an intersection...
Definition: CSGRegion.h:21
CSGCellList creates a container for CSGCell objects to pass to CSGBase object.
Definition: CSGCellList.h:20
void mooseError(Args &&... args)
Emit an error message with the given stringified, concatenated args and terminate the application...
Definition: MooseError.h:323
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:80
void mooseWarning(Args &&... args)
Emit a warning message with the given stringified, concatenated args.
Definition: MooseError.h:357
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:93
void joinUniverseList(CSGUniverseList &univ_list)
join a separate CSGUniverseList object to this one; root universes from univ_list will be combined in...
Definition: CSGBase.C:257
void joinOtherBase(std::unique_ptr< CSGBase > base)
Join another CSGBase object to this one.
Definition: CSGBase.C:212
CSGCell & addVoidCell(const std::string &name, const CSGRegion &region)
Add a Void Cell object cell list.
Definition: CSGCellList.C:37
CSGUniverse creates an internal representation of a Constructive Solid Geometry (CSG) universe...
Definition: CSGUniverse.h:26
bool operator==(const CSGBase &other) const
Operator overload for checking if two CSGBase objects are equal.
Definition: CSGBase.C:441
const std::vector< std::reference_wrapper< const CSGCell > > & getAllCells() const
Get list of the all cells in the universe.
Definition: CSGUniverse.h:72
CSGSurface & getSurface(const std::string &name) const
Get a surface by name.
CSGSurfaceList _surface_list
List of surfaces associated with CSG object.
Definition: CSGBase.h:467
void getLinkedUniverses(const CSGUniverse &univ, std::vector< std::string > &linked_universe_names) const
Recursive method to retrieve all universes linked to current universe.
Definition: CSGBase.C:378
nlohmann::json generateOutput() const
generate the JSON representation output for the CSG object
Definition: CSGBase.C:389
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:43
void removeCell(const std::string &name)
remove a cell of the specified name from the universe
Definition: CSGUniverse.C:56
CSGCell & addUniverseCell(const std::string &name, const CSGUniverse &univ, const CSGRegion &region)
Add a Universe Cell object to cell list.
Definition: CSGCellList.C:51
CSGUniverse & getUniverse(const std::string &name) const
Get a Universe from the list by its name.
const std::string & getName() const
Get the name of the universe.
Definition: CSGUniverse.h:79
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:179
const CSGUniverse & getRootUniverse() const
Get the Root Universe object.
Definition: CSGBase.h:179
void updateCellRegion(const CSGCell &cell, const CSGRegion &region)
change the region of the specified cell
Definition: CSGBase.C:141
CSGUniverseList creates a container for CSGUniverse objects to pass to CSGBase.
const std::vector< std::reference_wrapper< const CSGSurface > > & getSurfaces() const
Get the list of surfaces associated with the region.
Definition: CSGRegion.h:97
const CSGUniverse & addUniverseToList(const CSGUniverse &univ)
Add a new universe to the universe list based on a universe reference.
Definition: CSGBase.C:75
void joinSurfaceList(CSGSurfaceList &surf_list)
join a separate CSGSurfaceList object to this one
Definition: CSGBase.C:238
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:204
CSGUniverse & addUniverse(const std::string &name)
create an empty universe
bool checkUniverseInBase(const CSGUniverse &universe) const
Definition: CSGBase.C:352
CSGCell creates an internal representation of a Constructive Solid Geometry (CSG) cell...
Definition: CSGCell.h:27
bool operator!=(const CSGBase &other) const
Operator overload for checking if two CSGBase objects are not equal.
Definition: CSGBase.C:454
void checkRegionSurfaces(const CSGRegion &region) const
Definition: CSGBase.C:325
CSGCellList _cell_list
List of cells associated with CSG object.
Definition: CSGBase.h:470
std::unordered_map< std::string, std::unique_ptr< CSGSurface > > & getSurfaceListMap()
Get non-const map of all names to surfaces in surface list.
const CSGSurfaceList & getSurfaceList() const
Get a const reference to the CSGSurfaceList object.
Definition: CSGBase.h:356
bool checkCellInBase(const CSGCell &cell) const
Definition: CSGBase.C:342
CSGSurfaceList is a container for storing CSGSurface objects in the CSGBase object.
CSGSurface creates an internal representation of a Constructive Solid Geometry (CSG) surface...
Definition: CSGSurface.h:26
const CSGRegion & getRegion() const
Get the cell region.
Definition: CSGCell.h:101
bool hasUniverse(const std::string &name) const
return whether universe with given name exists in universe list
CSGBase()
Default constructor.
Definition: CSGBase.C:15
CSGSurface & addSurface(std::unique_ptr< CSGSurface > surf)
add a surface object to existing SurfaceList.
const CSGCell & addCellToList(const CSGCell &cell)
Add a new cell to the cell list based on a cell reference.
Definition: CSGBase.C:48
const CSGUniverse & createUniverse(const std::string &name)
Create an empty Universe object.
Definition: CSGBase.h:208
const CSGCellList & getCellList() const
Get a const reference to the CSGCellList object.
Definition: CSGBase.h:370
void addCellToUniverse(const CSGUniverse &universe, const CSGCell &cell)
Add a cell to an existing universe.
Definition: CSGBase.C:162
const std::string & getFillMaterial() const
Get the cell fill material name if fill fype is CSG_MATERIAL.
Definition: CSGCell.C:43
void checkUniverseLinking() const
Check universes linked to root universe match universes defined in _universe_list.
Definition: CSGBase.C:362
std::vector< std::reference_wrapper< const CSGCell > > getAllCells() const
Get all cell objects.
Definition: CSGBase.h:142
~CSGBase()
Destructor.
Definition: CSGBase.C:45
CSGBase creates an internal representation of a Constructive Solid Geometry (CSG) model...
Definition: CSGBase.h:29
const CSGUniverseList & getUniverseList() const
Get a const reference to the CSGUniverseList object.
Definition: CSGBase.h:384
bool hasCell(const std::string &name) const
return whether cell with given name exists in cell list
Definition: CSGCellList.h:73
void removeCellFromUniverse(const CSGUniverse &universe, const CSGCell &cell)
Remove a cell from an existing universe.
Definition: CSGBase.C:187
void addCell(const CSGCell &cell)
add cell to universe
Definition: CSGUniverse.C:25
std::vector< std::reference_wrapper< const CSGSurface > > getAllSurfaces() const
Get all surface objects.
Definition: CSGBase.h:67
std::unordered_map< std::string, std::unique_ptr< CSGUniverse > > & getUniverseListMap()
Get non-const map of all names to universes in universe list.