Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-09-18 09:24:49

0001 //------------------------------- -*- C++ -*- -------------------------------//
0002 // Copyright Celeritas contributors: see top-level COPYRIGHT file for details
0003 // SPDX-License-Identifier: (Apache-2.0 OR MIT)
0004 //---------------------------------------------------------------------------//
0005 //! \file orange/orangeinp/CsgTree.hh
0006 //---------------------------------------------------------------------------//
0007 #pragma once
0008 
0009 #include <iostream>
0010 #include <optional>
0011 #include <unordered_map>
0012 #include <variant>
0013 #include <vector>
0014 
0015 #include "corecel/OpaqueId.hh"
0016 #include "corecel/math/HashUtils.hh"
0017 
0018 #include "CsgTypes.hh"
0019 
0020 namespace celeritas
0021 {
0022 namespace orangeinp
0023 {
0024 //---------------------------------------------------------------------------//
0025 /*!
0026  * DAG of constructed CSG nodes within a universe.
0027  *
0028  * Inserting a new node performs one local simplification for "join" types
0029  * (removing duplicates, replacing zero- and one- entry special cases); and all
0030  * nodes are inserted into a deduplicated map of nodes that may be further
0031  * simplified later (see \c CsgAlgorithms).
0032  *
0033  * The tree is a topologically sorted graph where the leaves are the lower node
0034  * indices. The intent is for higher nodes to be simplified to boolean values,
0035  * e.g., by representing that all points in space are inside a cylinder by
0036  * replacing a \c Joined node with \c True . To facilitate this while
0037  * preserving node indices, \c True and \c False nodes are automatically
0038  * inserted as the first two node IDs. Because \c False is represented as "not
0039  * true" during evaluation, it actually stores \c Negated{true_node_id()} and
0040  * the deduplication table maps \c False to \c false_node_id() .
0041  *
0042  * \note The node classes use aggregate initialization so cannot be created
0043  * directly as \c Node variant classes using \c std::in_place_type .
0044  */
0045 class CsgTree
0046 {
0047   public:
0048     //!@{
0049     //! \name Type aliases
0050     using Node = orangeinp::Node;
0051     using NodeId = orangeinp::NodeId;
0052     using size_type = NodeId::size_type;
0053     using Insertion = std::pair<NodeId, bool>;
0054     using Simplification = std::optional<Node>;
0055     using VecNodeId = std::vector<NodeId>;
0056     //!@}
0057 
0058   public:
0059     // Construct with no nodes except "true" and "false"
0060     CsgTree();
0061 
0062     // Add a node and return the new ID and whether it's unique
0063     Insertion insert(Node&& n);
0064 
0065     // Add a surface ID and return the new ID
0066     inline Insertion insert(LocalSurfaceId s);
0067 
0068     //! Number of nodes
0069     NodeId::size_type size() const { return nodes_.size(); }
0070 
0071     // Get a node
0072     inline Node const& operator[](NodeId node_id) const;
0073 
0074     // Replace a node with a logically equivalent one, simplifying
0075     Node exchange(NodeId node_id, Node&& n);
0076 
0077     // Simplify a single node in-place [O(1)]
0078     Simplification simplify(NodeId);
0079 
0080     // Insert a new volume which root is the node id
0081     inline void insert_volume(NodeId);
0082 
0083     //! List of volumes defined in this tree
0084     VecNodeId const& volumes() const { return volumes_; }
0085 
0086     //// STATIC HELPERS ////
0087 
0088     //! Special ID of a node that's always 'true'
0089     static constexpr NodeId true_node_id() { return NodeId{0}; }
0090     //! Special ID of a node that's always 'false'
0091     static constexpr NodeId false_node_id() { return NodeId{1}; }
0092 
0093   private:
0094     // Tree structure: nodes may have been simplified
0095     std::vector<Node> nodes_;
0096 
0097     // Hashed nodes, both original and simplified
0098     std::unordered_map<Node, NodeId> ids_;
0099 
0100     // CSG node of each volume
0101     VecNodeId volumes_;
0102 
0103     //// HELPER FUNCTIONS ////
0104 
0105     // Get a node (only this class can modify the node once added)
0106     Node& at(NodeId node_id);
0107 };
0108 
0109 //---------------------------------------------------------------------------//
0110 // FREE FUNCTIONS
0111 //---------------------------------------------------------------------------//
0112 // Print the tree's contents
0113 std::ostream& operator<<(std::ostream& os, CsgTree const&);
0114 
0115 //---------------------------------------------------------------------------//
0116 // INLINE DEFINITIONS
0117 //---------------------------------------------------------------------------//
0118 /*!
0119  * Add a surface.
0120  */
0121 auto CsgTree::insert(LocalSurfaceId s) -> Insertion
0122 {
0123     return this->insert(orangeinp::Surface{s});
0124 }
0125 
0126 //---------------------------------------------------------------------------//
0127 /*!
0128  * Insert a new volume which root is the node id.
0129  */
0130 void CsgTree::insert_volume(NodeId node_id)
0131 {
0132     CELER_EXPECT(node_id < nodes_.size());
0133     volumes_.push_back(std::move(node_id));
0134 }
0135 
0136 //---------------------------------------------------------------------------//
0137 /*!
0138  * Get a node by ID.
0139  */
0140 auto CsgTree::operator[](NodeId node_id) const -> Node const&
0141 {
0142     CELER_EXPECT(node_id < nodes_.size());
0143     return nodes_[node_id.unchecked_get()];
0144 }
0145 
0146 //---------------------------------------------------------------------------//
0147 }  // namespace orangeinp
0148 }  // namespace celeritas