LCOV - code coverage report
Current view: top level - src/csg - CSGBase.C (source / functions) Hit Total Coverage
Test: idaholab/moose framework: #31613 (c7d555) with base 7323e9 Lines: 194 194 100.0 %
Date: 2025-11-06 14:13:52 Functions: 25 25 100.0 %
Legend: Lines: hit not hit

          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

Generated by: LCOV version 1.14