Back to home page

EIC code displayed by LXR

 
 

    


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

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