Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-09-16 09:03:17

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/Solid.hh
0006 //---------------------------------------------------------------------------//
0007 #pragma once
0008 
0009 #include <optional>
0010 #include <type_traits>
0011 #include <utility>
0012 
0013 #include "corecel/math/Turn.hh"
0014 
0015 #include "IntersectRegion.hh"
0016 #include "ObjectInterface.hh"
0017 
0018 namespace celeritas
0019 {
0020 namespace orangeinp
0021 {
0022 //---------------------------------------------------------------------------//
0023 /*!
0024  * Define the angular region of a solid.
0025  *
0026  * This is a pie slice infinite along the z axis and outward from it. Its cross
0027  * section is in the \em x-y plane, and a start
0028  * angle of zero corresponding to the \em +x axis. An interior angle of one
0029  * results in no radial excluded in the resulting solid. A interior angle of
0030  * more than 0.5 turns (180 degrees) results in a wedge being subtracted from
0031  * the solid, and an angle of less than or equal to 0.5 turns results in the
0032  * intersection of the solid with a wedge.
0033  *
0034  * \code
0035   // Truncates a solid to the east-facing quadrant:
0036   SolidEnclosedAngle{Turn{-0.125}, Turn{0.25}};
0037   // Removes the second quadrant (northwest) from a solid:
0038   SolidEnclosedAngle{Turn{0.50}, Turn{0.75}};
0039   \endcode
0040  */
0041 class SolidEnclosedAngle
0042 {
0043   public:
0044     //!@{
0045     //! \name Type aliases
0046     using SenseWedge = std::pair<Sense, InfWedge>;
0047     //!@}
0048 
0049   public:
0050     //! Default to "all angles"
0051     SolidEnclosedAngle() = default;
0052 
0053     // Construct from a starting angle and interior angle
0054     SolidEnclosedAngle(Turn start, Turn interior);
0055 
0056     // Construct a wedge shape to intersect (inside) or subtract (outside)
0057     SenseWedge make_wedge() const;
0058 
0059     // Whether the enclosed angle is not a full circle
0060     explicit inline operator bool() const;
0061 
0062     //! Starting angle
0063     Turn start() const { return start_; }
0064 
0065     //! Interior angle
0066     Turn interior() const { return interior_; }
0067 
0068   private:
0069     Turn start_{0};
0070     Turn interior_{1};
0071 };
0072 
0073 //---------------------------------------------------------------------------//
0074 /*!
0075  * Define a slab that is bound by the top/bottom z-cuts of the solid.
0076  */
0077 class SolidZSlab
0078 {
0079   public:
0080     //! Default to all space
0081     SolidZSlab() = default;
0082 
0083     // Construct from lower and upper z-plane
0084     SolidZSlab(real_type lower, real_type upper);
0085 
0086     // Construct an InfSlab shape to intersect with the solid
0087     InfSlab make_inf_slab() const;
0088 
0089     // Whether the z-slab is finite in z.
0090     explicit inline operator bool() const;
0091 
0092     //! Lower z-plane
0093     real_type lower() const { return lower_; }
0094 
0095     //! Upper z-plane
0096     real_type upper() const { return upper_; }
0097 
0098   private:
0099     real_type lower_{-std::numeric_limits<real_type>::infinity()};
0100     real_type upper_{std::numeric_limits<real_type>::infinity()};
0101 };
0102 
0103 //---------------------------------------------------------------------------//
0104 /*!
0105  * A hollow shape with an optional start and end angle.
0106  *
0107  * Solids are a shape with (optionally) the same *kind* of shape subtracted
0108  * from it, and (optionally) an azimuthal section removed from it.
0109  */
0110 class SolidBase : public ObjectInterface
0111 {
0112   public:
0113     // Construct a volume from this object
0114     NodeId build(VolumeBuilder&) const final;
0115 
0116     // Write the shape to JSON
0117     void output(JsonPimpl*) const final;
0118 
0119     //! Interior intersect region interface for construction and access
0120     virtual IntersectRegionInterface const& interior() const = 0;
0121 
0122     //! Optional excluded region
0123     virtual IntersectRegionInterface const* excluded() const = 0;
0124 
0125     //! Optional azimuthal angular restriction
0126     virtual SolidEnclosedAngle enclosed_angle() const = 0;
0127 
0128     //! Optional z-slab restriction
0129     virtual SolidZSlab z_slab() const = 0;
0130 
0131     ~SolidBase() override = default;
0132 
0133   protected:
0134     //!@{
0135     //! Allow construction and assignment only through daughter classes
0136     SolidBase() = default;
0137     CELER_DEFAULT_COPY_MOVE(SolidBase);
0138     //!@}
0139 };
0140 
0141 //---------------------------------------------------------------------------//
0142 /*!
0143  * A shape that has undergone an intersection or combination of intersections.
0144  *
0145  * This shape may be:
0146  * A) hollow (exluded interior),
0147  * B) truncated azimuthally (enclosed angle),
0148  * C) truncated in z (intersected with z-slab),
0149  * D) both A and B.
0150  *
0151  * Examples: \code
0152    // A cone with a thickness of 0.1
0153    Solid s{"cone", Cone{{1, 2}, 10.0}, Cone{{0.9, 1.9}, 10.0}};
0154    // A cylinder segment in z={-2.5, 2.5}, r={0.5, 0.75}, theta={-45, 45} deg
0155    Solid s{"cyl", Cylinder{0.75, 5.0}, Cylinder{0.5, 5.0},
0156            {Turn{0}, Turn{0.25}};
0157    // The east-facing quarter of a cone shape
0158    Solid s{"cone", Cone{{1, 2}, 10.0}, {Turn{-0.125}, Turn{0.25}};
0159  * \endcode
0160  */
0161 template<class T>
0162 class Solid final : public SolidBase
0163 {
0164     static_assert(std::is_base_of_v<IntersectRegionInterface, T>);
0165 
0166   public:
0167     //!@{
0168     //! \name Type aliases
0169     using OptionalRegion = std::optional<T>;
0170     //!@}
0171 
0172   public:
0173     // Return a solid *or* shape given an optional interior or enclosed angle
0174     static SPConstObject or_shape(std::string&& label,
0175                                   T&& interior,
0176                                   OptionalRegion&& excluded,
0177                                   SolidEnclosedAngle&& enclosed);
0178 
0179     // Construct with an excluded interior *and/or* enclosed angle
0180     Solid(std::string&& label,
0181           T&& interior,
0182           OptionalRegion&& excluded,
0183           SolidEnclosedAngle&& enclosed);
0184 
0185     // Construct with only an enclosed angle
0186     Solid(std::string&& label, T&& interior, SolidEnclosedAngle&& enclosed);
0187 
0188     // Construct with only an excluded interior
0189     Solid(std::string&& label, T&& interior, T&& excluded);
0190 
0191     // Construct with only a z-slab
0192     Solid(std::string&& label, T&& interior, SolidZSlab&& z_slab);
0193 
0194     //! Get the user-provided label
0195     std::string_view label() const final { return label_; }
0196 
0197     //! Interior intersect region interface for construction and access
0198     IntersectRegionInterface const& interior() const final
0199     {
0200         return interior_;
0201     }
0202 
0203     // Optional excluded
0204     IntersectRegionInterface const* excluded() const final;
0205 
0206     //! Optional angular restriction
0207     SolidEnclosedAngle enclosed_angle() const final { return enclosed_; }
0208 
0209     //! Optional z-slab intersection
0210     SolidZSlab z_slab() const final { return z_slab_; }
0211 
0212   private:
0213     std::string label_;
0214     T interior_;
0215     OptionalRegion exclusion_;
0216     SolidEnclosedAngle enclosed_;
0217     SolidZSlab z_slab_;
0218 };
0219 
0220 //---------------------------------------------------------------------------//
0221 // DEDUCTION GUIDES
0222 //---------------------------------------------------------------------------//
0223 
0224 template<class T, class... Us>
0225 Solid(std::string&&, T&&, Us...) -> Solid<T>;
0226 
0227 //---------------------------------------------------------------------------//
0228 // TYPE ALIASES
0229 //---------------------------------------------------------------------------//
0230 
0231 using ConeSolid = Solid<Cone>;
0232 using CylinderSolid = Solid<Cylinder>;
0233 using PrismSolid = Solid<Prism>;
0234 using SphereSolid = Solid<Sphere>;
0235 using EllipsoidSolid = Solid<Ellipsoid>;
0236 
0237 //---------------------------------------------------------------------------//
0238 // EXPLICIT INSTANTIATION
0239 //---------------------------------------------------------------------------//
0240 
0241 extern template class Solid<Cone>;
0242 extern template class Solid<Cylinder>;
0243 extern template class Solid<Prism>;
0244 extern template class Solid<Sphere>;
0245 extern template class Solid<Ellipsoid>;
0246 
0247 //---------------------------------------------------------------------------//
0248 // INLINE DEFINITIONS
0249 //---------------------------------------------------------------------------//
0250 /*!
0251  * Whether the enclosed angle is not a full circle.
0252  */
0253 SolidEnclosedAngle::operator bool() const
0254 {
0255     return interior_ != Turn{1};
0256 }
0257 
0258 //---------------------------------------------------------------------------//
0259 /*!
0260  * Whether the z-slab is finite in z.
0261  */
0262 SolidZSlab::operator bool() const
0263 {
0264     return std::isfinite(lower_) || std::isfinite(upper_);
0265 }
0266 
0267 //---------------------------------------------------------------------------//
0268 /*!
0269  * Access the optional excluded.
0270  */
0271 template<class T>
0272 IntersectRegionInterface const* Solid<T>::excluded() const
0273 {
0274     return exclusion_ ? &(*exclusion_) : nullptr;
0275 }
0276 
0277 //---------------------------------------------------------------------------//
0278 }  // namespace orangeinp
0279 }  // namespace celeritas