Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-10-27 09:40:41

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/detail/BuildLogic.hh
0006 //---------------------------------------------------------------------------//
0007 #pragma once
0008 
0009 #include <functional>
0010 #include <type_traits>
0011 #include <vector>
0012 
0013 #include "corecel/cont/VariantUtils.hh"
0014 #include "orange/OrangeTypes.hh"
0015 #include "orange/orangeinp/CsgTree.hh"
0016 #include "orange/orangeinp/CsgTypes.hh"
0017 
0018 namespace celeritas
0019 {
0020 namespace orangeinp
0021 {
0022 namespace detail
0023 {
0024 //---------------------------------------------------------------------------//
0025 /*!
0026  * Result of building a logic representation of a node.
0027  */
0028 struct BuildLogicResult
0029 {
0030     using VecLogic = std::vector<logic_int>;
0031     using VecSurface = std::vector<LocalSurfaceId>;
0032 
0033     VecSurface faces;
0034     VecLogic logic;
0035 };
0036 
0037 //---------------------------------------------------------------------------//
0038 /*!
0039  * Construct a logic representation of a node.
0040  *
0041  * The result is a pair of vectors: the sorted surface IDs comprising the faces
0042  * of this volume, and the logical representation using \em face IDs, i.e. with
0043  * the surfaces remapped to the index of the surface in the face vector.
0044  *
0045  * The function is templated on a policy class that determines the logic
0046  * representation. The policy acts as a factory that creates a visitor to build
0047  * the logic expression.
0048  *
0049  * The per-node local surfaces (faces) are sorted in ascending order of ID, not
0050  * of access, since they're always evaluated sequentially rather than as part
0051  * of the logic evaluation itself.
0052  */
0053 template<class LogicPolicy>
0054 BuildLogicResult build_logic(LogicPolicy const& policy, NodeId n);
0055 
0056 //---------------------------------------------------------------------------//
0057 // BUILDERS
0058 //---------------------------------------------------------------------------//
0059 /*!
0060  * Base class for logic builder visitors following CRTP pattern.
0061  *
0062  * Visitors recursively traverse the CSG tree and append to a logic vector.
0063  * The call operator for Negated and Joined are not implemented in the base
0064  * visitor and must be provided by the derived class.
0065  */
0066 template<class VisitorImpl>
0067 class BaseLogicBuilder
0068 {
0069   public:
0070     //!@{
0071     //! \name Type aliases
0072     using VecLogic = std::vector<logic_int>;
0073     using VecSurface = std::vector<LocalSurfaceId>;
0074     //!@}
0075 
0076     static_assert(std::is_same_v<LocalSurfaceId::size_type, logic_int>,
0077                   "unsupported: add enum logic conversion for different-sized "
0078                   "face and surface ints");
0079 
0080   public:
0081     // Construct with optional mapping pointer
0082     BaseLogicBuilder(
0083         CsgTree const& tree, VecLogic& logic, VecSurface const* vs = nullptr);
0084     //! Build from a node ID
0085     void operator()(NodeId const& n);
0086 
0087     //!@{
0088     //! \name Visit a node directly
0089     // Append 'true'
0090     void operator()(True const&);
0091     // False is never explicitly part of the node tree
0092     void operator()(False const&);
0093     // Append a surface ID
0094     void operator()(Surface const&);
0095     // Aliased nodes should never be reachable explicitly
0096     void operator()(Aliased const&);
0097     //!@}
0098 
0099   protected:
0100     //! Append a logic token
0101     void push_back(logic_int lgc) { logic_.push_back(lgc); }
0102 
0103   private:
0104     VecLogic& logic_;
0105     ContainerVisitor<CsgTree const&, NodeId> visit_node_;
0106     VecSurface const* mapping_{nullptr};
0107 };
0108 
0109 //---------------------------------------------------------------------------//
0110 /*!
0111  * Visitor for constructing logic in postfix notation.
0112  *
0113  * Example: \verbatim
0114     all(1, 3, 5) -> "0 1 & 2 & &"
0115     all(1, 3, !all(2, 4)) -> "0 2 & 1 3 & ~ &"
0116  * \endverbatim
0117  */
0118 class PostfixLogicBuilder : public BaseLogicBuilder<PostfixLogicBuilder>
0119 {
0120   public:
0121     using BaseLogicBuilder::BaseLogicBuilder;
0122 
0123     //!@{
0124     //! \name Visit a node directly
0125     using BaseLogicBuilder::operator();
0126 
0127     // Visit a negated node and append 'not'.
0128     void operator()(Negated const& n);
0129 
0130     // Visit daughter nodes and append the conjunction.
0131     void operator()(Joined const& n);
0132     //!@}
0133 };
0134 
0135 //---------------------------------------------------------------------------//
0136 /*!
0137  * Visitor for constructing logic in infix notation.
0138  *
0139  * Example: \verbatim
0140     all(1, 3, 5) -> "(0 & 1 & 2)"
0141     all(1, 3, any(~(2), ~(4))) -> "0 & 2 & (~1 | ~3)"
0142  * \endverbatim
0143  */
0144 class InfixLogicBuilder : public BaseLogicBuilder<InfixLogicBuilder>
0145 {
0146   public:
0147     using BaseLogicBuilder::BaseLogicBuilder;
0148 
0149     //!@{
0150     //! \name Visit a node directly
0151     using BaseLogicBuilder::operator();
0152 
0153     // Append 'not' and visit a negated node.
0154     void operator()(Negated const& n);
0155 
0156     // Visit daughter nodes and append the conjunction.
0157     void operator()(Joined const& n);
0158     //!@}
0159 
0160   private:
0161     int depth_{0};
0162 };
0163 
0164 //---------------------------------------------------------------------------//
0165 // POLICIES
0166 //---------------------------------------------------------------------------//
0167 /*!
0168  * Policy for building logic expressions.
0169  * \tparam LogicBuilder Visitor that constructs an input logic vector.
0170  *
0171  * This immutable factory creates visitors that construct logic expressions
0172  * from node IDs. It can be passed by const reference to \c build_logic.
0173  */
0174 template<class LogicBuilder>
0175 class StaticBuildLogicPolicy
0176 {
0177     static_assert(std::is_invocable_v<LogicBuilder, NodeId>);
0178 
0179   public:
0180     //!@{
0181     //! \name Type aliases
0182     using VecLogic = std::vector<logic_int>;
0183     using VecSurface = std::vector<LocalSurfaceId>;
0184     //!@}
0185 
0186   public:
0187     // Construct without mapping
0188     explicit StaticBuildLogicPolicy(CsgTree const& tree) : tree_{tree} {}
0189     // Construct with mapping
0190     StaticBuildLogicPolicy(CsgTree const& tree, VecSurface const& vs)
0191         : tree_{tree}, mapping_{&vs}
0192     {
0193     }
0194 
0195     //! Create a visitor for building logic
0196     auto operator()(VecLogic& logic) const
0197     {
0198         return LogicBuilder{tree_, logic, mapping_};
0199     }
0200 
0201   private:
0202     CsgTree const& tree_;
0203     VecSurface const* mapping_{nullptr};
0204 };
0205 
0206 //---------------------------------------------------------------------------//
0207 
0208 using PostfixBuildLogicPolicy = StaticBuildLogicPolicy<PostfixLogicBuilder>;
0209 using InfixBuildLogicPolicy = StaticBuildLogicPolicy<InfixLogicBuilder>;
0210 
0211 //---------------------------------------------------------------------------//
0212 /*!
0213  * Runtime-dispatching policy for building logic expressions.
0214  *
0215  * This policy class selects between postfix and infix notation at runtime
0216  * based on the input \c LogicNotation enum value.
0217  */
0218 class DynamicBuildLogicPolicy
0219 {
0220   public:
0221     //!@{
0222     //! \name Type aliases
0223     using VecLogic = std::vector<logic_int>;
0224     using VecSurface = std::vector<LocalSurfaceId>;
0225     using Builder = std::function<void(NodeId)>;
0226     //!@}
0227 
0228   public:
0229     // Construct with optional mapping
0230     DynamicBuildLogicPolicy(LogicNotation notation,
0231                             CsgTree const& tree,
0232                             VecSurface const* mapping);
0233 
0234     // Create a visitor for building logic
0235     Builder operator()(VecLogic& logic) const;
0236 
0237   private:
0238     LogicNotation notation_;
0239     CsgTree const& tree_;
0240     VecSurface const* mapping_{nullptr};
0241 };
0242 
0243 //---------------------------------------------------------------------------//
0244 // TEMPLATE INSTANTIATION
0245 //---------------------------------------------------------------------------//
0246 
0247 extern template class BaseLogicBuilder<PostfixLogicBuilder>;
0248 extern template class BaseLogicBuilder<InfixLogicBuilder>;
0249 
0250 extern template BuildLogicResult build_logic(PostfixBuildLogicPolicy const&,
0251                                              NodeId);
0252 extern template BuildLogicResult build_logic(InfixBuildLogicPolicy const&,
0253                                              NodeId);
0254 extern template BuildLogicResult build_logic(DynamicBuildLogicPolicy const&,
0255                                              NodeId);
0256 
0257 //---------------------------------------------------------------------------//
0258 }  // namespace detail
0259 }  // namespace orangeinp
0260 }  // namespace celeritas