Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-11-15 10:34:44

0001 #ifndef UNPLACEDBOOLEANVOLUME_H_
0002 #define UNPLACEDBOOLEANVOLUME_H_
0003 
0004 #include "VecGeom/base/Cuda.h"
0005 #include "VecGeom/base/Global.h"
0006 #include "VecGeom/base/AlignedBase.h"
0007 #include "VecGeom/base/Vector3D.h"
0008 #include "VecGeom/volumes/UnplacedVolume.h"
0009 #include "VecGeom/volumes/PlacedVolume.h"
0010 #include "VecGeom/volumes/BooleanStruct.h"
0011 #include "VecGeom/volumes/kernel/BooleanImplementation.h"
0012 #include "VecGeom/volumes/UnplacedVolumeImplHelper.h"
0013 #ifndef VECCORE_CUDA
0014 #include "VecGeom/volumes/UnplacedMultiUnion.h"
0015 #endif
0016 
0017 #include <string>
0018 
0019 namespace vecgeom {
0020 
0021 VECGEOM_DEVICE_DECLARE_CONV_TEMPLATE_1v(class, UnplacedBooleanVolume, BooleanOperation, Arg1);
0022 
0023 inline namespace VECGEOM_IMPL_NAMESPACE {
0024 
0025 #ifndef VECCORE_CUDA
0026 namespace BooleanHelper {
0027 
0028 VECCORE_ATT_HOST_DEVICE
0029 BooleanStruct const *GetBooleanStruct(VUnplacedVolume const *unplaced);
0030 
0031 bool ContainsHalfSpace(VUnplacedVolume const *unplaced);
0032 
0033 bool HasRootUnsupportedHalfSpaceUnion(VUnplacedVolume const *unplaced);
0034 
0035 bool IsFiniteBody(VPlacedVolume const *placed);
0036 
0037 bool IsFiniteBody(VUnplacedVolume const *unplaced);
0038 
0039 VECCORE_ATT_HOST_DEVICE
0040 size_t CountBooleanNodes(VUnplacedVolume const *unplaced, size_t &nunion, size_t &nintersection, size_t &nsubtraction);
0041 
0042 UnplacedMultiUnion *Flatten(VUnplacedVolume const *unplaced, size_t min_unions = 3,
0043                             Transformation3D const *trbase = nullptr, UnplacedMultiUnion *munion = nullptr);
0044 } // namespace BooleanHelper
0045 #endif
0046 
0047 /**
0048  * A class representing a simple UNPLACED boolean volume A-B
0049  * It takes two template arguments:
0050  * 1.: the mother (or left) volume A in unplaced form
0051  * 2.: the (or right) volume B in placed form, acting on A with a boolean operation;
0052  * the placement is with respect to the left volume
0053  *
0054  *
0055  *
0056  * will be a boolean solid where two boxes are subtracted
0057  * and B is only translated (not rotated) with respect to A
0058  *
0059  */
0060 template <BooleanOperation Op>
0061 class UnplacedBooleanVolume : public UnplacedVolumeImplHelper<BooleanImplementation<Op>>, public AlignedBase {
0062 
0063 public:
0064   BooleanStruct fBoolean;
0065   using UnplacedVolumeImplHelper<BooleanImplementation<Op>>::fGlobalConvexity;
0066 
0067   // the constructor
0068   VECCORE_ATT_HOST_DEVICE
0069   UnplacedBooleanVolume(BooleanOperation op, VPlacedVolume const *left, VPlacedVolume const *right
0070 #ifdef VECCORE_CUDA
0071                         ,
0072                         std::uint16_t leftScore = 1, std::uint16_t rightScore = 1, std::uint8_t identityMask = 0
0073 #endif
0074                         )
0075       : fBoolean(op, left, right)
0076   {
0077     fGlobalConvexity = false;
0078 #ifndef VECCORE_CUDA
0079     VUnplacedVolume::ComputeBBox();
0080     if (fBoolean.fLeftVolume->IsAssembly() || fBoolean.fRightVolume->IsAssembly()) {
0081       throw std::runtime_error("Trying to make boolean out of assembly which is not supported\n");
0082     }
0083 #else
0084     // Copy host metadata without inspecting device children during construction.
0085     // Direct device construction defaults to unscreened, fully transformed queries.
0086     fBoolean.fLeftScore    = leftScore;
0087     fBoolean.fRightScore   = rightScore;
0088     fBoolean.fIdentityMask = identityMask;
0089     VUnplacedVolume::ComputeBBox();
0090 #endif
0091   }
0092 
0093   VECCORE_ATT_HOST_DEVICE
0094   VECGEOM_FORCE_INLINE
0095   virtual bool IsBoolean() const override { return true; }
0096 
0097   VECCORE_ATT_HOST_DEVICE
0098   virtual ESolidType GetType() const override { return ESolidType::boolean; }
0099 
0100 #ifdef VECGEOM_CUDA_INTERFACE
0101   virtual size_t DeviceSizeOf() const override { return DevicePtr<cuda::UnplacedBooleanVolume<Op>>::SizeOf(); }
0102   virtual DevicePtr<cuda::VUnplacedVolume> CopyToGpu() const override;
0103   virtual DevicePtr<cuda::VUnplacedVolume> CopyToGpu(DevicePtr<cuda::VUnplacedVolume> const gpu_ptr) const override;
0104 #endif
0105 
0106   VECCORE_ATT_HOST_DEVICE
0107   VECGEOM_FORCE_INLINE
0108   BooleanOperation GetOp() const { return fBoolean.fOp; }
0109 
0110   VECCORE_ATT_HOST_DEVICE
0111   BooleanStruct const &GetStruct() const { return fBoolean; }
0112 
0113   VECCORE_ATT_HOST_DEVICE
0114   bool Normal(Vector3D<Precision> const &point, Vector3D<Precision> &normal) const override;
0115 
0116   Precision Capacity() const override
0117   {
0118     if (fBoolean.fCapacity < 0.) {
0119       fBoolean.fCapacity = VUnplacedVolume::EstimateCapacity(1000000);
0120     }
0121     return fBoolean.fCapacity;
0122   }
0123 
0124   Precision SurfaceArea() const override
0125   {
0126     if (fBoolean.fSurfaceArea < 0.) {
0127       fBoolean.fSurfaceArea = VUnplacedVolume::EstimateSurfaceArea(1000000);
0128     }
0129     return fBoolean.fSurfaceArea;
0130   }
0131 
0132   VECCORE_ATT_HOST_DEVICE
0133   void Extent(Vector3D<Precision> &aMin, Vector3D<Precision> &aMax) const override;
0134 
0135 #ifndef VECCORE_CUDA
0136   /// @brief Calculate a conservative clipped extent by combining operand extents.
0137   /// @param axis Mother-frame axis queried after applying `transform`.
0138   /// @param limits Mother-frame voxel limits used to clip the extent.
0139   /// @param transform Boolean local-to-mother transform.
0140   /// @param[out] min Lower extent along `axis` when the clipped envelope exists.
0141   /// @param[out] max Upper extent along `axis` when the clipped envelope exists.
0142   /// @return True when the conservative Boolean result intersects `limits`.
0143   bool CalculateClippedExtent(Axis axis, VoxelLimits const &limits, Transformation3D const &transform, Precision &min,
0144                               Precision &max) const override;
0145 #endif
0146 
0147   Vector3D<Precision> SamplePointOnSurface() const override;
0148 
0149   std::string GetEntityType() const { return "BooleanVolume"; }
0150 
0151   VECCORE_ATT_HOST_DEVICE
0152   virtual void Print() const override
0153   {
0154 #ifndef VECCORE_CUDA
0155     auto op            = this->GetOp();
0156     const char *opname = (op == kUnion ? "Union" : (op == kIntersection ? "Intersection" : "Subtraction"));
0157     printf("UnplacedBooleanVol<%s>{fLeft=[%i]<%s>, fRight=[%i]<%s>}", opname, this->GetLeft()->id(),
0158            this->GetLeft()->GetName(), this->GetRight()->id(), this->GetRight()->GetName());
0159 #else
0160     printf("UnplacedBooleanVol<%i>{fLeft=[%i], fRight=[%i]}", this->GetOp(), this->GetLeft()->id(),
0161            this->GetRight()->id());
0162 #endif
0163     printf("\n\t----------------------------------------");
0164     printf("\n\tfLeft:  [%i] ", this->GetLeft()->id());
0165     this->GetLeft()->GetUnplacedVolume()->Print();
0166     printf("\n\tfRight: [%i] ", this->GetRight()->id());
0167     this->GetRight()->GetUnplacedVolume()->Print();
0168     printf("\n\t----------------------------------------\n");
0169   }
0170 
0171   virtual void Print(std::ostream &os) const override
0172   {
0173 #ifndef VECCORE_CUDA
0174     auto op = this->GetOp();
0175     os << "UnplacedBooleanVol<" << (op == kUnion ? "Union" : (op == kIntersection ? "Intersection" : "Subtraction"))
0176        << ">{fLeft=<" << this->GetLeft()->id() << ">, fRight=<" << this->GetRight()->id() << ">}\n";
0177 #endif
0178     os << "fLeft:  [" << this->GetLeft()->id() << "] ";
0179     this->GetLeft()->GetUnplacedVolume()->Print(os);
0180     os << "fRight: [" << this->GetRight()->id() << "] ";
0181     this->GetRight()->GetUnplacedVolume()->Print(os);
0182     os << "\n";
0183   }
0184 
0185   VECCORE_ATT_DEVICE
0186   static VPlacedVolume *Create(LogicalVolume const *const logical_volume, Transformation3D const *const transformation,
0187 #ifdef VECCORE_CUDA
0188                                const int id, const int copy_no, const int child_id,
0189 #endif
0190                                VPlacedVolume *const placement = NULL);
0191 
0192   VECCORE_ATT_HOST_DEVICE
0193   VPlacedVolume const *GetLeft() const { return fBoolean.fLeftVolume; }
0194   VECCORE_ATT_HOST_DEVICE
0195   VPlacedVolume const *GetRight() const { return fBoolean.fRightVolume; }
0196 
0197 #ifndef VECCORE_CUDA
0198   /** @brief Count number of Boolean nodes of different types under this Boolean volume */
0199   VECCORE_ATT_HOST_DEVICE
0200   size_t CountNodes(size_t &nunion, size_t &nintersection, size_t &nsubtraction) const
0201   {
0202     return BooleanHelper::CountBooleanNodes(this, nunion, nintersection, nsubtraction);
0203   }
0204 
0205   /** @brief Flatten the Boolean node structure and create multiple union volumes if possible */
0206   UnplacedMultiUnion *Flatten(size_t min_unions = 1, Transformation3D const *trbase = nullptr,
0207                               UnplacedMultiUnion *munion = nullptr)
0208   {
0209     return BooleanHelper::Flatten(this, min_unions, trbase, munion);
0210   }
0211 #endif
0212 
0213 private:
0214   VECCORE_ATT_DEVICE
0215   virtual VPlacedVolume *SpecializedVolume(LogicalVolume const *const volume,
0216                                            Transformation3D const *const transformation,
0217 #ifdef VECCORE_CUDA
0218                                            const int id, const int copy_no, const int child_id,
0219 #endif
0220                                            VPlacedVolume *const placement = NULL) const override;
0221 
0222   void SetLeft(VPlacedVolume const *pvol)
0223   {
0224     fBoolean.fLeftVolume = pvol;
0225     fBoolean.UpdatePlacementFlags();
0226   }
0227   void SetRight(VPlacedVolume const *pvol)
0228   {
0229     fBoolean.fRightVolume = pvol;
0230     fBoolean.UpdatePlacementFlags();
0231   }
0232 
0233   friend class vecgeom::GeoManager;
0234 }; // End class
0235 
0236 } // namespace VECGEOM_IMPL_NAMESPACE
0237 
0238 } // namespace vecgeom
0239 
0240 #endif /* UNPLACEDBOOLEANVOLUME_H_ */