Skip to content

Commit

Permalink
Add CSG unit and unit builder (celeritas-project#1079)
Browse files Browse the repository at this point in the history
* Add CSG unit builder
* Add transform IO
* Redefine MaterialId as anonymous ID
* Move CSG-to-JSON to a separate helper function
* Add CSG unit builder test
* Add tolerance and constructed surface accessors
  • Loading branch information
sethrj committed Jan 23, 2024
1 parent 821110e commit 7887ba4
Show file tree
Hide file tree
Showing 20 changed files with 1,006 additions and 30 deletions.
3 changes: 0 additions & 3 deletions src/celeritas/Types.hh
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,6 @@ using EventId = OpaqueId<struct Event_>;
//! Opaque index to IsotopeRecord in a vector
using IsotopeId = OpaqueId<struct IsotopeRecord>;

//! Opaque index to MaterialRecord in a vector: represents a material ID
using MaterialId = OpaqueId<struct MaterialRecord>;

//! Opaque index of model in the list of physics processes
using ModelId = OpaqueId<class Model>;

Expand Down
6 changes: 3 additions & 3 deletions src/celeritas/mat/MaterialData.hh
Original file line number Diff line number Diff line change
Expand Up @@ -126,13 +126,13 @@ template<Ownership W, MemSpace M>
struct MaterialParamsData
{
template<class T>
using Items = celeritas::Collection<T, W, M>;
using Items = Collection<T, W, M>;

Items<IsotopeRecord> isotopes;
Items<ElementRecord> elements;
Items<ElIsotopeComponent> isocomponents;
Items<MatElementComponent> elcomponents;
Items<MaterialRecord> materials;
Collection<MaterialRecord, W, M, MaterialId> materials;
IsotopeComponentId::size_type max_isotope_components{};
ElementComponentId::size_type max_element_components{};

Expand Down Expand Up @@ -187,7 +187,7 @@ template<Ownership W, MemSpace M>
struct MaterialStateData
{
template<class T>
using Items = celeritas::StateCollection<T, W, M>;
using Items = StateCollection<T, W, M>;

Items<MaterialTrackState> state;
Items<real_type> element_scratch; // 2D array: [num states][max
Expand Down
2 changes: 1 addition & 1 deletion src/corecel/cont/VariantUtils.hh
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ class ContainerVisitor

//! Visit the functor upon the value at the given index
template<class F>
decltype(auto) operator()(F && func, U const& idx) const
decltype(auto) operator()(F&& func, U const& idx) const
{
auto&& value = container_[idx];
CELER_ASSUME(!value.valueless_by_exception());
Expand Down
2 changes: 2 additions & 0 deletions src/orange/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ list(APPEND SOURCES
detail/SurfacesRecordBuilder.cc
detail/UnitInserter.cc
detail/UniverseInserter.cc
orangeinp/detail/CsgUnitBuilder.cc
surf/ConeAligned.cc
surf/CylAligned.cc
surf/FaceNamer.cc
Expand All @@ -46,6 +47,7 @@ list(APPEND SOURCES
surf/detail/SurfaceTranslator.cc
surf/detail/SurfaceTransformer.cc
transform/SignedPermutation.cc
transform/TransformIO.cc
transform/Transformation.cc
transform/VariantTransform.cc
)
Expand Down
3 changes: 3 additions & 0 deletions src/orange/Types.hh
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,9 @@ using SquareMatrixReal3 = SquareMatrix<real_type, 3>;

//---------------------------------------------------------------------------//

//! Identifier for a material fill
using MaterialId = OpaqueId<struct Material_>;

//! Identifier for a surface (for surface-based geometries)
using SurfaceId = OpaqueId<struct Surface_>;

Expand Down
127 changes: 127 additions & 0 deletions src/orange/orangeinp/detail/CsgUnit.hh
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
//----------------------------------*-C++-*----------------------------------//
// Copyright 2023-2024 UT-Battelle, LLC, and other Celeritas developers.
// See the top-level COPYRIGHT file for details.
// SPDX-License-Identifier: (Apache-2.0 OR MIT)
//---------------------------------------------------------------------------//
//! \file orange/orangeinp/detail/CsgUnit.hh
//---------------------------------------------------------------------------//
#pragma once

#include <set>
#include <variant>
#include <vector>

#include "corecel/io/Label.hh"
#include "orange/BoundingBox.hh"
#include "orange/OrangeTypes.hh"
#include "orange/construct/CsgTree.hh"
#include "orange/construct/CsgTypes.hh"
#include "orange/surf/VariantSurface.hh"

namespace celeritas
{
namespace orangeinp
{
namespace detail
{
//---------------------------------------------------------------------------//
/*!
* Constructed CSG geometry data for a unit.
*
* This contains all the construction-time surfaces, volumes, and properties.
* These are stored in a way so that they can be remapped and/or optimized
* further before committing them to the constructed GPU data.
*
* The "exterior" is optional *only* in the degenerate case of an infinite
* global universe (TODO: prohibit this??)
*
* TODO: improve metadata (provenance, nicer container, mapping?, calculated
* volumes)
*/
struct CsgUnit
{
//// TYPES ////

using Metadata = Label;
using SetMd = std::set<Metadata>;
using NodeId = ::celeritas::csg::NodeId;
using BBox = ::celeritas::BoundingBox<>;
using Fill = std::variant<std::monostate, MaterialId, Daughter>;

//// DATA ////

//!@{
//! \name Surfaces
//! Vectors are indexed by LocalSurfaceId.
std::vector<VariantSurface> surfaces;
//!@}

//!@{
//! \name Nodes
//! Vectors are indexed by NodeId.
CsgTree tree; //!< CSG tree
std::vector<SetMd> metadata; //!< CSG node labels and provenance
std::vector<BBox> bboxes;
//!@}

//!@{
//! \name Volumes
//! Vectors are indexed by LocalVolumeId.
std::vector<NodeId> volumes; //!< CSG node of each volume
std::vector<Fill> fills; //!< Content of each volume
NodeId exterior;
//!@}

//!@{
//! \name Transforms
//! Vectors are indexed by TransformId.
std::vector<VariantTransform> transforms;
//!@}

//// FUNCTIONS ////

// Whether the processed unit is valid for use
explicit inline operator bool() const;

// Whether the unit has no constructed data
inline bool empty() const;
};

//---------------------------------------------------------------------------//
/*!
* Utility for telling whether a fill is assigned.
*/
inline constexpr bool is_filled(CsgUnit::Fill const& fill)
{
return !std::holds_alternative<std::monostate>(fill);
}

//---------------------------------------------------------------------------//
// INLINE DEFINITIONS
//---------------------------------------------------------------------------//
/*!
* Whether the processed unit is valid for use.
*/
CsgUnit::operator bool() const
{
return this->metadata.size() == this->tree.size()
&& this->bboxes.size() == this->tree.size() && !this->volumes.empty()
&& this->volumes.size() == this->fills.size();
}

//---------------------------------------------------------------------------//
/*!
* True if the unit has no constructed data.
*/
bool CsgUnit::empty() const
{
return this->surfaces.empty() && this->metadata.empty()
&& this->bboxes.empty() && this->volumes.empty()
&& this->fills.empty() && !this->exterior
&& this->transforms.empty();
}

//---------------------------------------------------------------------------//
} // namespace detail
} // namespace orangeinp
} // namespace celeritas
119 changes: 119 additions & 0 deletions src/orange/orangeinp/detail/CsgUnitBuilder.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
//----------------------------------*-C++-*----------------------------------//
// Copyright 2024 UT-Battelle, LLC, and other Celeritas developers.
// See the top-level COPYRIGHT file for details.
// SPDX-License-Identifier: (Apache-2.0 OR MIT)
//---------------------------------------------------------------------------//
//! \file orange/orangeinp/detail/CsgUnitBuilder.cc
//---------------------------------------------------------------------------//
#include "CsgUnitBuilder.hh"

namespace celeritas
{
namespace orangeinp
{
namespace detail
{
//---------------------------------------------------------------------------//
/*!
* Set a bounding box for a node.
*/
void CsgUnitBuilder::set_bbox(NodeId n, BBox const& bbox)
{
CELER_EXPECT(n < unit_->bboxes.size());
CELER_EXPECT(!unit_->bboxes[n.unchecked_get()]);

unit_->bboxes[n.unchecked_get()] = bbox;
}

//---------------------------------------------------------------------------//
/*!
* Mark a CSG node as a volume of real space.
*/
LocalVolumeId CsgUnitBuilder::insert_volume(NodeId n)
{
CELER_EXPECT(n < unit_->tree.size());

LocalVolumeId result{static_cast<size_type>(unit_->volumes.size())};

unit_->volumes.push_back(n);
unit_->fills.resize(unit_->volumes.size());

CELER_ENSURE(*unit_);
return result;
}

//---------------------------------------------------------------------------//
/*!
* Fill a volume node with a material.
*/
void CsgUnitBuilder::fill_volume(LocalVolumeId v, MaterialId m)
{
CELER_EXPECT(v < unit_->fills.size());
CELER_EXPECT(m);

unit_->fills[v.unchecked_get()] = m;
}

//---------------------------------------------------------------------------//
/*!
* Fill a volume node with a daughter.
*/
void CsgUnitBuilder::fill_volume(LocalVolumeId v,
UniverseId u,
VariantTransform&& vt)
{
CELER_EXPECT(v < unit_->fills.size());
CELER_EXPECT(!is_filled(unit_->fills[v.unchecked_get()]));
CELER_EXPECT(u);

Daughter new_daughter;
new_daughter.universe_id = u;
new_daughter.transform_id
= TransformId{static_cast<size_type>(unit_->transforms.size())};

// Add transform
unit_->transforms.push_back(std::move(vt));
// Save fill
unit_->fills[v.unchecked_get()] = std::move(new_daughter);

CELER_ENSURE(is_filled(unit_->fills[v.unchecked_get()]));
}

//---------------------------------------------------------------------------//
/*!
* Set an exterior node.
*
* This should be called only once (but this could be relaxed if needed).
*/
void CsgUnitBuilder::set_exterior(NodeId n)
{
CELER_EXPECT(n < unit_->tree.size());
CELER_EXPECT(!unit_->exterior);

unit_->exterior = n;
}

//---------------------------------------------------------------------------//
/*!
* Get a variant surface from a node ID.
*/
VariantSurface const& CsgUnitBuilder::get_surface_impl(NodeId nid) const
{
CELER_EXPECT(nid < unit_->tree.size());

using SurfaceNode = ::celeritas::csg::Surface;

// Get the surface ID from the tree
auto const& node = unit_->tree[nid];
CELER_ASSUME(std::holds_alternative<SurfaceNode>(node));
LocalSurfaceId lsid = std::get<SurfaceNode>(node).id;

// Get the variant surfaces from the unit
CELER_EXPECT(lsid < unit_->surfaces.size());
return unit_->surfaces[lsid.unchecked_get()];
}

//---------------------------------------------------------------------------//
} // namespace detail
} // namespace orangeinp
} // namespace celeritas

0 comments on commit 7887ba4

Please sign in to comment.