Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 10:05:55

0001 //----------------------------------*-C++-*----------------------------------//
0002 // Copyright 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/detail/DeMorganSimplifier.hh
0007 //---------------------------------------------------------------------------//
0008 #pragma once
0009 
0010 #include <utility>
0011 #include <vector>
0012 
0013 #include "orange/orangeinp/CsgTree.hh"
0014 #include "orange/orangeinp/CsgTypes.hh"
0015 
0016 namespace celeritas
0017 {
0018 namespace orangeinp
0019 {
0020 namespace detail
0021 {
0022 //---------------------------------------------------------------------------//
0023 /*!
0024  * Implement DeMorgan transformations on a \c CsgTree.
0025  *
0026  * This class serves as a helper for \c
0027  * celeritas::orangeinp::transform_negated_joins implementation. It applies
0028  * DeMorgan's law on a \c CsgTree so that all negations of a set operator are
0029  * removed and transformed into their equivalent operation.
0030  *
0031  * The simplification preserves subtrees referred to by \c CsgTree::volumes
0032  *
0033  * Instances of this class shouldn't outlive the \c CsgTree used to construct
0034  * it as we keep a reference to it.
0035  *
0036  * It is currently single-use: calling operator() twice on the same instance
0037  * isn't supported.
0038  *
0039  * The \c CsgTree being simplified shouldn't contain alias nodes or double
0040  * negations.
0041  */
0042 class DeMorganSimplifier
0043 {
0044   public:
0045     // Construct a simplifier for the given tree
0046     explicit DeMorganSimplifier(CsgTree const&);
0047 
0048     // Perform the simplification
0049     CsgTree operator()();
0050 
0051   private:
0052     //! CsgTree node 0 is always True{} and can't be the parent of any node
0053     //! so reuse that bit to tell that a given node is a volume
0054     static constexpr auto is_volume_index_{NodeId{0}};
0055     //! CsgTree node 1 is always a Negated node parent of node 0, so we can
0056     //! reuse that bit to tell if a node has a parent as it's never set for
0057     //! node id >= 2
0058     static constexpr auto has_parents_index_{NodeId{1}};
0059 
0060     //! First meaningfull node id in a CsgTree
0061     static constexpr auto first_node_id_{NodeId{2}};
0062 
0063     //! Helper struct to translate ids from the original tree to ids in the
0064     //! simplified tree
0065     struct MatchingNodes
0066     {
0067         //! Set if a node has the exact same node in the simplified tree
0068         NodeId unmodified;
0069 
0070         //! Indirections to new simplified join following DeMorgan's law
0071         //! Set if the original node is a negated node.
0072         NodeId simplified_to;
0073         //! If a join node has been negated, this points to the opposite join
0074         //! Set if the original node is a joined node.
0075         NodeId opposite_join;
0076 
0077         //! Set if we need to insert a new negation of that node
0078         //! Set if the original node is a leaf node.
0079         NodeId new_negation;
0080 
0081         //! Whether any matching node id is set
0082         explicit operator bool() const noexcept
0083         {
0084             return unmodified || simplified_to || opposite_join || new_negation;
0085         }
0086 
0087         // Lookup a node an equal node in the simplified tree
0088         NodeId equivalent_node() const;
0089     };
0090 
0091     //! Rudimentary 2D square matrix view of a vector<bool>
0092     class Matrix2D
0093     {
0094       public:
0095         using indices = std::pair<NodeId, NodeId>;
0096 
0097         // Create the matrix view with the given extent size
0098         explicit Matrix2D(size_type) noexcept;
0099         // Access the element at the given index
0100         std::vector<bool>::reference operator[](indices);
0101         // The extent along one dimension
0102         size_type extent() const noexcept;
0103 
0104       private:
0105         // TODO: sparse storage
0106         std::vector<bool> data_;
0107         size_type extent_;
0108     };
0109 
0110     // Dereference Aliased nodes
0111     NodeId dealias(NodeId) const;
0112 
0113     // First pass to find negated set operations
0114     void find_join_negations();
0115 
0116     // Declare negated nodes to add in the simplified tree
0117     void add_negation_for_operands(NodeId);
0118 
0119     // Second pass to build the simplified tree
0120     CsgTree build_simplified_tree();
0121 
0122     // Special handling for a Joined or Negated node
0123     bool process_negated_joined_nodes(NodeId, CsgTree&);
0124 
0125     // Create an opposite Joined node
0126     Joined build_negated_node(Joined const&) const;
0127 
0128     // Check if this join node should be inserted in the simplified tree
0129     bool should_insert_join(NodeId);
0130 
0131     //! the tree to simplify
0132     CsgTree const& tree_;
0133 
0134     //! Set when we must insert a \c Negated parent for the given index
0135     std::vector<bool> new_negated_nodes_;
0136 
0137     //! Set when \c Joined nodes have a \c Negated parent, so we need to insert
0138     //! an opposite join node with negated operands
0139     std::vector<bool> negated_join_nodes_;
0140 
0141     //! Parents matrix. For nodes n1, n2, if n1 * tree_.size() + n2 is set, it
0142     //! means that n2 is a parent of n1
0143     Matrix2D parents_;
0144 
0145     //! Used during construction of the simplified tree to map replaced nodes
0146     //! in the original tree to their new id in the simplified tree
0147     std::vector<MatchingNodes> node_ids_translation_;
0148 };
0149 
0150 //---------------------------------------------------------------------------//
0151 }  // namespace detail
0152 }  // namespace orangeinp
0153 }  // namespace celeritas