Back to home page

EIC code displayed by LXR

 
 

    


Warning, file /include/VecGeom/volumes/PolyconeStruct.h was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).

0001 /*
0002  * PolyconeStruct.h
0003  *
0004  *  Created on: May 11, 2017
0005  *      Author: Raman Sehgal
0006  */
0007 #ifndef VECGEOM_POLYCONESTRUCT_H_
0008 #define VECGEOM_POLYCONESTRUCT_H_
0009 
0010 #include "VecGeom/base/Global.h"
0011 #include "VecGeom/volumes/Wedge_Evolution.h"
0012 #include "VecGeom/volumes/ConeStruct.h"
0013 #include "VecGeom/base/Vector.h"
0014 #include "VecGeom/volumes/PolyconeHistorical.h"
0015 #include "VecGeom/volumes/PolyconeSection.h"
0016 #include "VecGeom/base/Array.h"
0017 
0018 namespace vecgeom {
0019 
0020 inline namespace VECGEOM_IMPL_NAMESPACE {
0021 
0022 // a plain and lightweight struct to encapsulate data members of a Polycone
0023 template <typename T = double>
0024 struct PolyconeStruct {
0025 
0026   bool fEqualRmax{false};
0027   bool fContinuityOverAll{false};
0028   bool fConvexityPossible{false};
0029 
0030   evolution::Wedge fPhiWedge;
0031   Precision fStartPhi{0.};
0032   Precision fDeltaPhi{0.};
0033   unsigned int fNz{0};
0034 
0035   Vector<PolyconeSection> fSections;
0036   Vector<Precision> fZs;
0037   PolyconeHistorical *fOriginal_parameters{nullptr};
0038 
0039   // Data member to hold the line segment that form Polycone boundary
0040   Vector<Vector3D<Precision>> fRMinTwoDVec;
0041   Vector<Vector3D<Precision>> fRMaxTwoDVec;
0042   Vector<Vector3D<Precision>> fTwoDVec;
0043 
0044   VECGEOM_FORCE_INLINE
0045   VECCORE_ATT_HOST_DEVICE
0046   static bool ApproxEqual(const Precision &x, const Precision &y) { return vecCore::math::Abs(x - y) < kTolerance; }
0047 
0048   PolyconeStruct() = default;
0049 
0050   VECCORE_ATT_HOST_DEVICE
0051   PolyconeStruct(bool equalRmax, bool continuityOverAll, bool convexityPossible, Precision phiStart, Precision phiTotal,
0052                  unsigned int numSections, unsigned int numZPlanes, const Precision zPlaneR[],
0053                  const Precision rInnerR[], const Precision rOuterR[], AlignedAllocator &a)
0054       : fEqualRmax(equalRmax), fContinuityOverAll(continuityOverAll), fConvexityPossible(convexityPossible),
0055         fNz(numZPlanes), fSections(numSections, a), fZs(numSections + 1, a), fRMinTwoDVec(2 * numSections, a),
0056         fRMaxTwoDVec(2 * numSections, a), fTwoDVec(4 * numSections, a)
0057   {
0058     // These will set fStartPhi, fDeltaPhi and fPhiWedge
0059     SetAndCheckStartAndDeltaPhi(phiStart, phiTotal);
0060 
0061     // Create the sections
0062 
0063     // Calculate RMax of Polycone in order to determine convexity of sections
0064     Precision RMaxextent = rOuterR[0];
0065     for (unsigned int j = 1; j < numZPlanes; j++)
0066       if (rOuterR[j] > RMaxextent) RMaxextent = rOuterR[j];
0067 
0068     Precision prevZ = zPlaneR[0], prevRmax = 0., prevRmin = 0.;
0069     int dirZ = 1.;
0070     if (zPlaneR[1] < zPlaneR[0]) dirZ = -1.;
0071 
0072     size_t isection = 0, iz = 0;
0073     for (unsigned int i = 0; i < numZPlanes; ++i) {
0074       Precision rMin = rInnerR[i];
0075       Precision rMax = rOuterR[i];
0076       Precision z    = zPlaneR[i];
0077 
0078       // i has to be at least one to complete a section
0079       if (i > 0) {
0080         if (((z > prevZ + kTolerance) && (dirZ > 0)) || ((z < prevZ - kTolerance) && (dirZ < 0))) {
0081           Precision dz    = 0.5 * (z - prevZ);
0082           fZs[iz++]       = z;
0083           Precision shift = prevZ + dz;
0084 
0085           PolyconeSection &section = fSections[isection];
0086           section.fShift           = shift;
0087           section.fSolid.Init(prevRmin, prevRmax, rMin, rMax, dz, fStartPhi, fDeltaPhi);
0088 
0089           section.fConvex = !((rMax < prevRmax) || (rMax < RMaxextent) || (prevRmax < RMaxextent));
0090 
0091           fRMinTwoDVec[2 * isection + 0].Set(prevRmin, prevZ, 0.);
0092           fRMinTwoDVec[2 * isection + 1].Set(rMin, z, 0);
0093           fRMaxTwoDVec[2 * isection + 0].Set(prevRmax, prevZ, 0);
0094           fRMaxTwoDVec[2 * isection + 1].Set(rMax, z, 0.);
0095           isection++;
0096         }
0097       } else {
0098         fZs[iz++] = z;
0099       }
0100       prevZ    = z;
0101       prevRmin = rMin;
0102       prevRmax = rMax;
0103     }
0104     size_t counter = 0;
0105     for (auto val : fRMaxTwoDVec)
0106       fTwoDVec[counter++] = val;
0107 
0108     for (int k = fRMinTwoDVec.size() - 1; k >= 0; k--) {
0109       fTwoDVec[counter++] = fRMinTwoDVec[k];
0110     }
0111   }
0112 
0113   VECCORE_ATT_HOST_DEVICE
0114   VECGEOM_FORCE_INLINE
0115   static size_t aligned_sizeof_data(size_t numSections)
0116   {
0117     // Sections data
0118     size_t aligned_size = AlignedAllocator::aligned_sizeof<PolyconeSection>(numSections, 0);
0119     // fZs
0120     aligned_size += AlignedAllocator::aligned_sizeof<Precision>(numSections + 1, 0);
0121     // fRMinTwoDVec, fRMaxTwoDVec
0122     aligned_size += 2 * AlignedAllocator::aligned_sizeof<Vector3D<Precision>>(2 * numSections, 0);
0123     // fTwoDVec
0124     aligned_size += AlignedAllocator::aligned_sizeof<Vector3D<Precision>>(4 * numSections, 0);
0125     return aligned_size;
0126   }
0127 
0128   VECCORE_ATT_HOST_DEVICE
0129   bool CheckContinuity(const Precision rOuter[], const Precision rInner[], const Precision zPlane[],
0130                        Vector<Precision> &newROuter, Vector<Precision> &newRInner, Vector<Precision> &newZPlane)
0131   {
0132     Vector<Precision> rOut, rIn;
0133     Vector<Precision> zPl;
0134     rOut.push_back(rOuter[0]);
0135     rIn.push_back(rInner[0]);
0136     zPl.push_back(zPlane[0]);
0137     for (unsigned int j = 1; j < fNz; j++) {
0138 
0139       if (j == fNz - 1) {
0140         rOut.push_back(rOuter[j]);
0141         rIn.push_back(rInner[j]);
0142         zPl.push_back(zPlane[j]);
0143       } else {
0144         if ((zPlane[j] != zPlane[j + 1]) || (rOuter[j] != rOuter[j + 1])) {
0145           rOut.push_back(rOuter[j]);
0146           rOut.push_back(rOuter[j]);
0147 
0148           zPl.push_back(zPlane[j]);
0149           zPl.push_back(zPlane[j]);
0150 
0151           rIn.push_back(rInner[j]);
0152           rIn.push_back(rInner[j]);
0153 
0154         } else {
0155           rOut.push_back(rOuter[j]);
0156           zPl.push_back(zPlane[j]);
0157           rIn.push_back(rInner[j]);
0158         }
0159       }
0160     }
0161 
0162     if (rOut.size() % 2 != 0) {
0163       // fNz is odd, the adding of the last item did not happen in the loop.
0164       rOut.push_back(rOut[rOut.size() - 1]);
0165       rIn.push_back(rIn[rIn.size() - 1]);
0166       zPl.push_back(zPl[zPl.size() - 1]);
0167     }
0168 
0169     /* Creating a new temporary Reduced polycone with desired data elements,
0170      *  which makes sure that denominator will never be zero (hence avoiding FPE(division by zero)),
0171      *  while calculating slope.
0172      *
0173      *  This will be the minimum polycone,i.e. no extra section which
0174      *  affect its shape
0175      */
0176 
0177     for (size_t j = 0; j < rOut.size();) {
0178 
0179       if (zPl[j] != zPl[j + 1]) {
0180 
0181         newZPlane.push_back(zPl[j]);
0182         newZPlane.push_back(zPl[j + 1]);
0183         newROuter.push_back(rOut[j]);
0184         newROuter.push_back(rOut[j + 1]);
0185         newRInner.push_back(rIn[j]);
0186         newRInner.push_back(rIn[j + 1]);
0187       }
0188 
0189       j = j + 2;
0190     }
0191     // Minimum polycone construction over
0192 
0193     // Checking Slope continuity and Rmax Continuity
0194     bool contRmax  = CheckContinuityInRmax(newROuter);
0195     bool contSlope = CheckContinuityInSlope(newROuter, newZPlane);
0196 
0197     // If both are true then the polycone can be convex
0198     // but still final convexity depends on Inner Radius also.
0199     return (contRmax && contSlope);
0200   }
0201 
0202   VECCORE_ATT_HOST_DEVICE
0203   bool CheckContinuityInRmax(const Vector<Precision> &rOuter)
0204   {
0205     bool continuous  = true;
0206     unsigned int len = rOuter.size();
0207     if (len > 2) {
0208       for (unsigned int j = 1; j < len;) {
0209         if (j != (len - 1)) continuous &= (rOuter[j] == rOuter[j + 1]);
0210         j = j + 2;
0211       }
0212     }
0213     return continuous;
0214   }
0215 
0216   VECCORE_ATT_HOST_DEVICE
0217   bool CheckContinuityInSlope(const Vector<Precision> &rOuter, const Vector<Precision> &zPlane)
0218   {
0219 
0220     bool continuous      = true;
0221     Precision startSlope = kInfLength;
0222 
0223     // Doing the actual slope calculation here, and checking continuity,
0224     for (size_t j = 0; j < rOuter.size(); j = j + 2) {
0225       Precision currentSlope = (rOuter[j + 1] - rOuter[j]) / (zPlane[j + 1] - zPlane[j]);
0226       continuous &= (currentSlope <= startSlope);
0227       startSlope = currentSlope;
0228     }
0229     return continuous;
0230   }
0231 
0232   VECCORE_ATT_HOST_DEVICE
0233   void Dump()
0234   {
0235     printf("== PolyconeStruct at: %p", (void *)this);
0236     printf("   numZplanes: %u numSections: %lu, phiStart: %g phiDelta: %g\n", fNz, fSections.size(), fStartPhi,
0237            fDeltaPhi);
0238     printf("   fEqualRmax: %d fContinuityOverAll: %d fConvexityPossible: %d\n", fEqualRmax, fContinuityOverAll,
0239            fConvexityPossible);
0240     printf("   fZs: {");
0241     for (auto z : fZs)
0242       printf("  %g", z);
0243     printf("  }\n");
0244     auto dump_section = [](int isection, PolyconeSection const &section) {
0245       printf("   section %d  fShift: %g  fTubular: %d  fConvex: %d\n", isection, section.fShift, section.fTubular,
0246              section.fConvex);
0247       printf("      ");
0248       section.fSolid.Print();
0249       printf("\n");
0250     };
0251     int isection = 0;
0252     for (auto const &section : fSections)
0253       dump_section(isection++, section);
0254   }
0255 
0256   // a method to reconstruct "plane" section arrays for z, rmin and rmax
0257   template <typename PushableContainer>
0258   void ReconstructSectionArrays(PushableContainer &z_values, PushableContainer &rmin_values,
0259                                 PushableContainer &rmax_values) const
0260   {
0261     // loop sections
0262     Precision prevZ = 0., prevRmax = 0., prevRmin = 0.;
0263     int iplane = 0;
0264     for (auto const &section : fSections) {
0265       Precision zmin = section.fShift - section.fSolid.fDz;
0266       Precision zmax = section.fShift + section.fSolid.fDz;
0267       Precision rmin = section.fSolid.fRmin1;
0268       Precision rmax = section.fSolid.fOriginalRmax1;
0269       if (iplane == 0) {
0270         prevZ    = zmin;
0271         prevRmin = rmin;
0272         prevRmax = rmax;
0273         z_values.push_back(zmin);
0274         rmin_values.push_back(rmin);
0275         rmax_values.push_back(rmax);
0276         iplane++;
0277       }
0278       // Add bottom Z plane if there is a radial discontinuity
0279       if (!ApproxEqual(rmin, prevRmin) || !ApproxEqual(rmax, prevRmax)) {
0280         z_values.push_back(zmin);
0281         rmin_values.push_back(rmin);
0282         rmax_values.push_back(rmax);
0283         iplane++;
0284       }
0285       // Add top Z plane
0286       prevZ    = zmax;
0287       prevRmin = section.fSolid.fRmin2;
0288       prevRmax = section.fSolid.fOriginalRmax2;
0289       z_values.push_back(prevZ);
0290       rmin_values.push_back(prevRmin);
0291       rmax_values.push_back(prevRmax);
0292       iplane++;
0293     }
0294   }
0295 
0296   VECCORE_ATT_HOST_DEVICE
0297   void Init(Precision phiStart,       // initial phi starting angle
0298             Precision phiTotal,       // total phi angle
0299             unsigned int numZPlanes,  // number of z planes
0300             const Precision zPlane[], // position of z planes
0301             const Precision rInner[], // tangent distance to inner surface
0302             const Precision rOuter[])
0303   {
0304 
0305     SetAndCheckStartAndDeltaPhi(phiStart, phiTotal);
0306     fNz                = numZPlanes;
0307     Precision *zPlaneR = new Precision[numZPlanes];
0308     Precision *rInnerR = new Precision[numZPlanes];
0309     Precision *rOuterR = new Precision[numZPlanes];
0310     for (unsigned int i = 0; i < numZPlanes; i++) {
0311       zPlaneR[i] = zPlane[i];
0312       rInnerR[i] = rInner[i];
0313       rOuterR[i] = rOuter[i];
0314     }
0315     if (zPlane[0] > zPlane[numZPlanes - 1]) {
0316       // Reverse the arrays
0317       for (unsigned int i = 0; i < numZPlanes; i++) {
0318         zPlaneR[i] = zPlane[numZPlanes - 1 - i];
0319         rInnerR[i] = rInner[numZPlanes - 1 - i];
0320         rOuterR[i] = rOuter[numZPlanes - 1 - i];
0321       }
0322     }
0323 
0324     // Calculate RMax of Polycone in order to determine convexity of sections
0325     //
0326     Precision RMaxextent = rOuterR[0];
0327 
0328     Vector<Precision> newROuter, newZPlane, newRInner;
0329     fContinuityOverAll &= CheckContinuity(rOuterR, rInnerR, zPlaneR, newROuter, newRInner, newZPlane);
0330     fConvexityPossible &= (newRInner[0] == 0.);
0331 
0332     Precision startRmax = newROuter[0];
0333     for (unsigned int j = 1; j < newROuter.size(); j++) {
0334       fEqualRmax &= (startRmax == newROuter[j]);
0335       startRmax = newROuter[j];
0336       fConvexityPossible &= (newRInner[j] == 0.);
0337     }
0338 
0339     for (unsigned int j = 1; j < numZPlanes; j++) {
0340 
0341       if (rOuterR[j] > RMaxextent) RMaxextent = rOuterR[j];
0342 
0343       if (rInnerR[j] > rOuterR[j]) {
0344 #ifndef VECCORE_CUDA
0345         std::cerr << "Cannot create Polycone with rInner > rOuter for the same Z"
0346                   << "\n"
0347                   << "        rInner > rOuter for the same Z !\n"
0348                   << "        rMin[" << j << "] = " << rInner[j] << " -- rMax[" << j << "] = " << rOuter[j];
0349 #endif
0350       }
0351     }
0352 
0353     Precision prevZ = zPlaneR[0], prevRmax = 0, prevRmin = 0;
0354     int dirZ = 1;
0355     if (zPlaneR[1] < zPlaneR[0]) dirZ = -1;
0356 
0357     for (unsigned int i = 0; i < numZPlanes; ++i) {
0358       if ((i < numZPlanes - 1) && (zPlaneR[i] == zPlaneR[i + 1])) {
0359         if ((rInnerR[i] > rOuterR[i + 1]) || (rInnerR[i + 1] > rOuterR[i])) {
0360 #ifndef VECCORE_CUDA
0361           std::cerr << "Cannot create a Polycone with no contiguous segments." << std::endl
0362                     << "                Segments are not contiguous !" << std::endl
0363                     << "                rMin[" << i << "] = " << rInnerR[i] << " -- rMax[" << i + 1
0364                     << "] = " << rOuterR[i + 1] << std::endl
0365                     << "                rMin[" << i + 1 << "] = " << rInnerR[i + 1] << " -- rMax[" << i
0366                     << "] = " << rOuterR[i];
0367 #endif
0368         }
0369       }
0370 
0371       Precision rMin = rInnerR[i];
0372 
0373       Precision rMax = rOuterR[i];
0374       Precision z    = zPlaneR[i];
0375 
0376       // i has to be at least one to complete a section
0377       if (i > 0) {
0378         // GL: I had to add kTolerance here, otherwise this polycone would get an
0379         //     extra 0-length ZSection on the GPU -- see VECGEOM-578
0380         if (((z > prevZ + kTolerance) && (dirZ > 0)) || ((z < prevZ - kTolerance) && (dirZ < 0))) {
0381           if (dirZ * (z - prevZ) < 0) {
0382 #ifndef VECCORE_CUDA
0383             std::cerr << "Cannot create a Polycone with different Z directions.Use GenericPolycone." << std::endl
0384                       << "              ZPlane is changing direction  !" << std::endl
0385                       << "  zPlane[0] = " << zPlaneR[0] << " -- zPlane[1] = " << zPlaneR[1] << std::endl
0386                       << "  zPlane[" << i - 1 << "] = " << zPlaneR[i - 1] << " -- rPlane[" << i << "] = " << zPlaneR[i];
0387 #endif
0388           }
0389 
0390           Precision dz = (z - prevZ) / 2;
0391           fZs.push_back(z);
0392           int zi          = fZs.size() - 1;
0393           Precision shift = fZs[zi - 1] + 0.5 * (fZs[zi] - fZs[zi - 1]);
0394 
0395           PolyconeSection section;
0396           section.fShift = shift;
0397           section.fSolid.Init(prevRmin, prevRmax, rMin, rMax, dz, fStartPhi, fDeltaPhi);
0398 
0399           section.fConvex = !((rMax < prevRmax) || (rMax < RMaxextent) || (prevRmax < RMaxextent));
0400 
0401           fSections.push_back(section);
0402           fRMinTwoDVec.push_back(Vector3D<Precision>(prevRmin, prevZ, 0));
0403           fRMinTwoDVec.push_back(Vector3D<Precision>(rMin, z, 0));
0404           fRMaxTwoDVec.push_back(Vector3D<Precision>(prevRmax, prevZ, 0));
0405           fRMaxTwoDVec.push_back(Vector3D<Precision>(rMax, z, 0));
0406         }
0407       } else { // for i == 0 just push back first z plane
0408         fZs.push_back(z);
0409       }
0410 
0411       prevZ    = z;
0412       prevRmin = rMin;
0413       prevRmax = rMax;
0414     }
0415 
0416     for (auto val : fRMaxTwoDVec) {
0417       fTwoDVec.push_back(val);
0418     }
0419 
0420     for (int k = fRMinTwoDVec.size() - 1; k >= 0; k--) {
0421       fTwoDVec.push_back(fRMinTwoDVec[k]);
0422     }
0423     fOriginal_parameters                  = new PolyconeHistorical(numZPlanes);
0424     fOriginal_parameters->fHStart_angle   = phiStart;
0425     fOriginal_parameters->fHOpening_angle = phiTotal;
0426     for (unsigned int i = 0; i < numZPlanes; i++) {
0427       fOriginal_parameters->fHZ_values[i] = zPlaneR[i];
0428       fOriginal_parameters->fHRmin[i]     = rInnerR[i];
0429       fOriginal_parameters->fHRmax[i]     = rOuterR[i];
0430     }
0431 
0432     delete[] zPlaneR;
0433     delete[] rInnerR;
0434     delete[] rOuterR;
0435   }
0436 
0437   VECCORE_ATT_HOST_DEVICE
0438   PolyconeHistorical *GetOriginalParameters() const { return fOriginal_parameters; }
0439 
0440   VECCORE_ATT_HOST_DEVICE unsigned int GetNz() const { return fNz; }
0441 
0442   VECCORE_ATT_HOST_DEVICE
0443   int GetNSections() const { return fSections.size(); }
0444 
0445   VECCORE_ATT_HOST_DEVICE
0446   int GetSectionIndex(Precision zposition) const
0447   {
0448     // TODO: consider binary search
0449     // TODO: consider making these comparisons tolerant in case we need it
0450     if (zposition < fZs[0]) return -1;
0451     for (unsigned int i = 0; i < fSections.size(); ++i) {
0452       if (zposition >= fZs[i] && zposition <= fZs[i + 1]) return i;
0453     }
0454     return -2;
0455   }
0456 
0457   VECCORE_ATT_HOST_DEVICE
0458   PolyconeSection const &GetSection(Precision zposition) const
0459   {
0460     // TODO: consider binary search
0461     int i = GetSectionIndex(zposition);
0462     // i is negative if zposition is out of range
0463     if (i == -1)
0464       i = 0;
0465     else if (i == -2)
0466       i = fSections.size() - 1;
0467     return fSections[i];
0468   }
0469 
0470   VECCORE_ATT_HOST_DEVICE
0471   // GetSection if index is known
0472   PolyconeSection const &GetSection(int index) const { return fSections[index]; }
0473 
0474   VECCORE_ATT_HOST_DEVICE
0475   Precision GetRminAtPlane(int index) const
0476   {
0477     int nsect = fSections.size();
0478     VECGEOM_ASSERT(index >= 0 && index <= nsect);
0479     if (index == nsect)
0480       return fSections[index - 1].fSolid.fRmin2; // GetRmin2();
0481     else
0482       return fSections[index].fSolid.fRmin1; // GetRmin1();
0483   }
0484 
0485   VECCORE_ATT_HOST_DEVICE
0486   Precision GetRmaxAtPlane(int index) const
0487   {
0488     int nsect = fSections.size();
0489     VECGEOM_ASSERT(index >= 0 || index <= nsect);
0490     if (index == nsect)
0491       return fSections[index - 1].fSolid.fRmax2; // GetRmax2();
0492     else
0493       return fSections[index].fSolid.fRmax1; // GetRmax1();
0494   }
0495 
0496   VECCORE_ATT_HOST_DEVICE
0497   Precision GetZAtPlane(unsigned int index) const
0498   {
0499     VECGEOM_ASSERT(index <= fSections.size());
0500     return fZs[index];
0501   }
0502 
0503   VECCORE_ATT_HOST_DEVICE
0504   Precision GetRmin1AtSection(size_t index) const
0505   {
0506     VECGEOM_ASSERT(index < fSections.size());
0507     return fSections[index].fSolid.fRmin1;
0508   }
0509 
0510   VECCORE_ATT_HOST_DEVICE
0511   Precision GetRmin2AtSection(size_t index) const
0512   {
0513     VECGEOM_ASSERT(index < fSections.size());
0514     return fSections[index].fSolid.fRmin2;
0515   }
0516 
0517   VECCORE_ATT_HOST_DEVICE
0518   Precision GetRmax1AtSection(size_t index) const
0519   {
0520     VECGEOM_ASSERT(index < fSections.size());
0521     return fSections[index].fSolid.fRmax1;
0522   }
0523 
0524   VECCORE_ATT_HOST_DEVICE
0525   Precision GetRmax2AtSection(size_t index) const
0526   {
0527     VECGEOM_ASSERT(index < fSections.size());
0528     return fSections[index].fSolid.fRmax2;
0529   }
0530 
0531   VECCORE_ATT_HOST_DEVICE
0532   void SetAndCheckSPhiAngle(Precision sPhi)
0533   {
0534     // Ensure fSphi in [0, 2PI)
0535     fStartPhi = sPhi;
0536     while (fStartPhi < 0.)
0537       fStartPhi += kTwoPi;
0538     // Update Wedge
0539     fPhiWedge.SetStartPhi(fStartPhi);
0540     fPhiWedge.UpdateNormals();
0541   }
0542 
0543   VECCORE_ATT_HOST_DEVICE
0544   void SetAndCheckDPhiAngle(Precision dPhi)
0545   {
0546     if (dPhi <= 0. || dPhi > kTwoPi - kTolerance) {
0547       fStartPhi = 0;
0548       fDeltaPhi = kTwoPi;
0549     } else {
0550       fDeltaPhi = dPhi;
0551     }
0552     while (fStartPhi < 0)
0553       fStartPhi += kTwoPi;
0554     // Update Wedge
0555     fPhiWedge.SetDeltaPhi(fDeltaPhi);
0556     fPhiWedge.UpdateNormals();
0557   }
0558 
0559   VECCORE_ATT_HOST_DEVICE
0560   void SetAndCheckStartAndDeltaPhi(Precision sPhi, Precision dPhi)
0561   {
0562     fStartPhi = sPhi;
0563     while (fStartPhi < 0)
0564       fStartPhi += kTwoPi;
0565 
0566     fDeltaPhi = dPhi;
0567     if (dPhi <= 0. || dPhi > kTwoPi - kTolerance) {
0568       fStartPhi = 0.;
0569       fDeltaPhi = kTwoPi;
0570     }
0571     // Update Wedge
0572     fPhiWedge.Set(fDeltaPhi, fStartPhi);
0573     fPhiWedge.UpdateNormals();
0574   }
0575 };
0576 } // namespace VECGEOM_IMPL_NAMESPACE
0577 } // namespace vecgeom
0578 
0579 #endif