Line data Source code
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 :
15 95 : CSGBase::CSGBase()
16 95 : : _surface_list(CSGSurfaceList()), _cell_list(CSGCellList()), _universe_list(CSGUniverseList())
17 : {
18 95 : }
19 :
20 87 : CSGBase::~CSGBase() {}
21 :
22 : const CSGCell &
23 35 : CSGBase::createCell(const std::string & name,
24 : const std::string & mat_name,
25 : const CSGRegion & region,
26 : const CSGUniverse * add_to_univ)
27 : {
28 35 : checkRegionSurfaces(region);
29 35 : auto & cell = _cell_list.addMaterialCell(name, mat_name, region);
30 35 : if (add_to_univ)
31 2 : addCellToUniverse(*add_to_univ, cell);
32 : else
33 33 : addCellToUniverse(getRootUniverse(), cell);
34 35 : return cell;
35 : }
36 :
37 : const CSGCell &
38 60 : CSGBase::createCell(const std::string & name,
39 : const CSGRegion & region,
40 : const CSGUniverse * add_to_univ)
41 : {
42 60 : checkRegionSurfaces(region);
43 60 : auto & cell = _cell_list.addVoidCell(name, region);
44 58 : if (add_to_univ)
45 8 : addCellToUniverse(*add_to_univ, cell);
46 : else
47 50 : addCellToUniverse(getRootUniverse(), cell);
48 58 : return cell;
49 : }
50 :
51 : const CSGCell &
52 8 : CSGBase::createCell(const std::string & name,
53 : const CSGUniverse & fill_univ,
54 : const CSGRegion & region,
55 : const CSGUniverse * add_to_univ)
56 : {
57 8 : checkRegionSurfaces(region);
58 8 : if (add_to_univ && (&fill_univ == add_to_univ))
59 6 : mooseError("Cell " + name +
60 : " cannot be filled with the same universe to which it is being added.");
61 :
62 6 : auto & cell = _cell_list.addUniverseCell(name, fill_univ, region);
63 6 : if (add_to_univ)
64 2 : addCellToUniverse(*add_to_univ, cell);
65 : else
66 4 : addCellToUniverse(getRootUniverse(), cell);
67 6 : return cell;
68 : }
69 :
70 : void
71 13 : CSGBase::updateCellRegion(const CSGCell & cell, const CSGRegion & region)
72 : {
73 13 : checkRegionSurfaces(region);
74 13 : if (!checkCellInBase(cell))
75 10 : mooseError("The region of cell with name " + cell.getName() +
76 4 : " is being updated that is different " +
77 : "from the cell of the same name in the CSGBase instance.");
78 11 : auto & list_cell = _cell_list.getCell(cell.getName());
79 11 : list_cell.updateRegion(region);
80 11 : }
81 :
82 : const CSGUniverse &
83 10 : CSGBase::createUniverse(const std::string & name,
84 : std::vector<std::reference_wrapper<const CSGCell>> & cells)
85 : {
86 10 : auto & univ = _universe_list.addUniverse(name);
87 10 : addCellsToUniverse(univ, cells); // performs a check that cells are a part of this base
88 10 : return univ;
89 : }
90 :
91 : void
92 127 : CSGBase::addCellToUniverse(const CSGUniverse & universe, const CSGCell & cell)
93 : {
94 : // make sure cell is a part of this CSGBase instance
95 127 : if (!checkCellInBase(cell))
96 12 : mooseError("A cell named " + cell.getName() + " is being added to universe " +
97 8 : universe.getName() +
98 : " that is different from the cell of the same name in the CSGBase instance.");
99 : // make sure universe is a part of this CSGBase instance
100 125 : if (!checkUniverseInBase(universe))
101 10 : mooseError("Cells are being added to a universe named " + universe.getName() +
102 4 : " that is different " +
103 : "from the universe of the same name in the CSGBase instance.");
104 123 : auto & univ = _universe_list.getUniverse(universe.getName());
105 123 : univ.addCell(cell);
106 123 : }
107 :
108 : void
109 12 : CSGBase::addCellsToUniverse(const CSGUniverse & universe,
110 : std::vector<std::reference_wrapper<const CSGCell>> & cells)
111 : {
112 32 : for (auto & c : cells)
113 20 : addCellToUniverse(universe, c);
114 12 : }
115 :
116 : void
117 12 : CSGBase::removeCellFromUniverse(const CSGUniverse & universe, const CSGCell & cell)
118 : {
119 : // make sure cell is a part of this CSGBase instance
120 12 : if (!checkCellInBase(cell))
121 12 : mooseError("A cell named " + cell.getName() + " is being removed from universe " +
122 8 : universe.getName() +
123 : " that is different from the cell of the same name in the CSGBase instance.");
124 : // make sure universe is a part of this CSGBase instance
125 10 : if (!checkUniverseInBase(universe))
126 10 : mooseError("Cells are being removed from a universe named " + universe.getName() +
127 4 : " that is different " +
128 : "from the universe of the same name in the CSGBase instance.");
129 8 : auto & univ = _universe_list.getUniverse(universe.getName());
130 8 : univ.removeCell(cell.getName());
131 8 : }
132 :
133 : void
134 4 : CSGBase::removeCellsFromUniverse(const CSGUniverse & universe,
135 : std::vector<std::reference_wrapper<const CSGCell>> & cells)
136 : {
137 10 : for (auto & c : cells)
138 6 : removeCellFromUniverse(universe, c);
139 4 : }
140 :
141 : void
142 2 : CSGBase::joinOtherBase(std::unique_ptr<CSGBase> base)
143 : {
144 2 : joinSurfaceList(base->getSurfaceList());
145 2 : joinCellList(base->getCellList());
146 2 : joinUniverseList(base->getUniverseList());
147 2 : }
148 :
149 : void
150 2 : CSGBase::joinOtherBase(std::unique_ptr<CSGBase> base, std::string & new_root_name_join)
151 : {
152 2 : joinSurfaceList(base->getSurfaceList());
153 2 : joinCellList(base->getCellList());
154 2 : joinUniverseList(base->getUniverseList(), new_root_name_join);
155 2 : }
156 :
157 : void
158 2 : CSGBase::joinOtherBase(std::unique_ptr<CSGBase> base,
159 : const std::string & new_root_name_base,
160 : const std::string & new_root_name_join)
161 : {
162 2 : joinSurfaceList(base->getSurfaceList());
163 2 : joinCellList(base->getCellList());
164 2 : joinUniverseList(base->getUniverseList(), new_root_name_base, new_root_name_join);
165 2 : }
166 :
167 : void
168 6 : CSGBase::joinSurfaceList(CSGSurfaceList & surf_list)
169 : {
170 : // TODO: check if surface is a duplicate (by definition) and skip
171 : // adding if duplicate; must update references to the surface in cell
172 : // region definitions.
173 6 : auto & surf_list_map = surf_list.getSurfaceListMap();
174 12 : for (auto & s : surf_list_map)
175 6 : _surface_list.addSurface(std::move(s.second));
176 6 : }
177 :
178 : void
179 6 : CSGBase::joinCellList(CSGCellList & cell_list)
180 : {
181 6 : auto & cell_list_map = cell_list.getCellListMap();
182 18 : for (auto & c : cell_list_map)
183 12 : _cell_list.addCell(std::move(c.second));
184 6 : }
185 :
186 : void
187 2 : CSGBase::joinUniverseList(CSGUniverseList & univ_list)
188 : {
189 : // case 1: incoming root is joined into existing root; no new universes are created
190 2 : auto & univ_list_map = univ_list.getUniverseListMap();
191 2 : auto & root = getRootUniverse(); // this root universe
192 6 : for (auto & u : univ_list_map)
193 : {
194 4 : if (u.second->isRoot())
195 : {
196 : // add existing cells to current root instead of creating new universe
197 2 : auto all_cells = u.second->getAllCells();
198 4 : for (auto & cell : all_cells)
199 2 : addCellToUniverse(root, cell);
200 2 : }
201 : else // unique non-root universe to add to list
202 2 : _universe_list.addUniverse(std::move(u.second));
203 : }
204 2 : }
205 :
206 : void
207 2 : CSGBase::joinUniverseList(CSGUniverseList & univ_list, const std::string & new_root_name_incoming)
208 : {
209 : // case 2: incoming root is turned into new universe and existing root remains root
210 :
211 : // add incoming universes to current Base
212 2 : auto & all_univs = univ_list.getUniverseListMap();
213 6 : for (auto & u : all_univs)
214 : {
215 4 : if (u.second->isRoot())
216 : {
217 : // create new universe from incoming root universe
218 2 : auto all_cells = u.second->getAllCells();
219 2 : createUniverse(new_root_name_incoming, all_cells);
220 2 : }
221 : else // unique non-root universe to add to list
222 2 : _universe_list.addUniverse(std::move(u.second));
223 : }
224 2 : }
225 :
226 : void
227 2 : CSGBase::joinUniverseList(CSGUniverseList & univ_list,
228 : const std::string & new_root_name_base,
229 : const std::string & new_root_name_incoming)
230 : {
231 : // case 3: each root universe becomes a new universe and a new root is created
232 :
233 : // make a new universe from the existing root universe
234 2 : auto & root = getRootUniverse();
235 2 : auto root_cells = root.getAllCells();
236 2 : createUniverse(new_root_name_base, root_cells);
237 2 : removeCellsFromUniverse(root, root_cells);
238 :
239 : // add incoming universes to current Base
240 2 : auto & all_univs = univ_list.getUniverseListMap();
241 6 : for (auto & u : all_univs)
242 : {
243 4 : if (u.second->isRoot())
244 : {
245 : // create new universe from incoming root universe
246 2 : auto all_cells = u.second->getAllCells();
247 2 : createUniverse(new_root_name_incoming, all_cells);
248 2 : }
249 : else // unique non-root universe to add to list
250 2 : _universe_list.addUniverse(std::move(u.second));
251 : }
252 2 : }
253 :
254 : void
255 118 : CSGBase::checkRegionSurfaces(const CSGRegion & region) const
256 : {
257 118 : auto & surfs = region.getSurfaces();
258 376 : for (const CSGSurface & s : surfs)
259 : {
260 260 : auto sname = s.getName();
261 : // if there is no surface by this name at all, there will be an error from getSurface
262 260 : const auto & list_surf = _surface_list.getSurface(s.getName());
263 : // if there is a surface by the same name, check that it is actually the surface being used
264 : // (ie same surface points to same location in memory)
265 260 : if (&s != &list_surf)
266 6 : mooseError("Region is being set with a surface named " + sname +
267 : " that is different from the surface of the same name in the CSGBase instance.");
268 260 : }
269 116 : }
270 :
271 : bool
272 152 : CSGBase::checkCellInBase(const CSGCell & cell) const
273 : {
274 152 : auto name = cell.getName();
275 : // if no cell by this name exists, an error will be produced by getCell
276 152 : auto & list_cell = _cell_list.getCell(name);
277 : // return whether that the cell in the list is the same as the cell provided (in memory)
278 152 : return &cell == &list_cell;
279 152 : }
280 :
281 : bool
282 135 : CSGBase::checkUniverseInBase(const CSGUniverse & universe) const
283 : {
284 135 : auto name = universe.getName();
285 : // if no universe by this name exists, an error will be produced by getUniverse
286 135 : auto & list_univ = _universe_list.getUniverse(name);
287 : // return whether that the cell in the list is the same as the cell provided (in memory)
288 135 : return &universe == &list_univ;
289 135 : }
290 :
291 : void
292 31 : CSGBase::checkUniverseLinking() const
293 : {
294 31 : std::vector<std::string> linked_universe_names;
295 :
296 : // Recursively figure out which universe names are linked to root universe
297 31 : getLinkedUniverses(getRootUniverse(), linked_universe_names);
298 :
299 : // Iterate through all universes in universe list and check that they exist in universes linked
300 : // to root universe list
301 62 : for (const CSGUniverse & univ : getAllUniverses())
302 33 : if (std::find(linked_universe_names.begin(), linked_universe_names.end(), univ.getName()) ==
303 66 : linked_universe_names.end())
304 31 : mooseWarning("Universe with name ", univ.getName(), " is not linked to root universe.");
305 31 : }
306 :
307 : void
308 33 : CSGBase::getLinkedUniverses(const CSGUniverse & univ,
309 : std::vector<std::string> & linked_universe_names) const
310 : {
311 33 : linked_universe_names.push_back(univ.getName());
312 33 : const auto & univ_cells = univ.getAllCells();
313 62 : for (const CSGCell & cell : univ_cells)
314 29 : if (cell.getFillType() == "UNIVERSE")
315 2 : getLinkedUniverses(cell.getFillUniverse(), linked_universe_names);
316 33 : }
317 :
318 : nlohmann::json
319 27 : CSGBase::generateOutput() const
320 : {
321 : // Check that orphaned universes do not exist in universe list of CSGBase object
322 27 : checkUniverseLinking();
323 :
324 27 : nlohmann::json csg_json;
325 :
326 27 : csg_json["surfaces"] = {};
327 27 : csg_json["cells"] = {};
328 27 : csg_json["universes"] = {};
329 :
330 : // get all surfaces information
331 27 : auto all_surfs = getAllSurfaces();
332 153 : for (const CSGSurface & s : all_surfs)
333 : {
334 126 : const auto & surf_name = s.getName();
335 126 : const auto & coeffs = s.getCoeffs();
336 882 : csg_json["surfaces"][surf_name] = {{"type", s.getSurfaceType()}, {"coefficients", {}}};
337 630 : for (const auto & c : coeffs)
338 504 : csg_json["surfaces"][surf_name]["coefficients"][c.first] = c.second;
339 126 : }
340 :
341 : // Print out cell information
342 27 : auto all_cells = getAllCells();
343 54 : for (const CSGCell & c : all_cells)
344 : {
345 27 : const auto & cell_name = c.getName();
346 27 : const auto & cell_region = c.getRegionAsString();
347 27 : const auto & cell_filltype = c.getFillType();
348 27 : const auto & fill_name = c.getFillName();
349 27 : csg_json["cells"][cell_name]["filltype"] = cell_filltype;
350 27 : csg_json["cells"][cell_name]["region"] = cell_region;
351 27 : csg_json["cells"][cell_name]["fill"] = fill_name;
352 27 : }
353 :
354 : // Print out universe information
355 27 : auto all_univs = getAllUniverses();
356 54 : for (const CSGUniverse & u : all_univs)
357 : {
358 27 : const auto & univ_name = u.getName();
359 27 : const auto & univ_cells = u.getAllCells();
360 27 : csg_json["universes"][univ_name]["cells"] = {};
361 54 : for (const CSGCell & c : univ_cells)
362 27 : csg_json["universes"][univ_name]["cells"].push_back(c.getName());
363 27 : if (u.isRoot())
364 27 : csg_json["universes"][univ_name]["root"] = u.isRoot();
365 : }
366 :
367 54 : return csg_json;
368 783 : }
369 :
370 : } // namespace CSG
|