Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-30 10:17:11

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