File indexing completed on 2025-01-18 10:14:06
0001
0002
0003
0004
0005
0006
0007 #ifndef VECGEOM_CONESTRUCT_H_
0008 #define VECGEOM_CONESTRUCT_H_
0009
0010 #include "VecGeom/base/Global.h"
0011 #include "VecGeom/volumes/Wedge_Evolution.h"
0012
0013 namespace vecgeom {
0014
0015 VECGEOM_DEVICE_DECLARE_CONV_TEMPLATE(struct, ConeStruct, typename);
0016
0017 inline namespace VECGEOM_IMPL_NAMESPACE {
0018
0019
0020 template <typename T = double>
0021 struct ConeStruct {
0022
0023 T fRmin1;
0024 T fRmax1;
0025 T fRmin2;
0026 T fRmax2;
0027 T fDz;
0028 T fSPhi;
0029 T fDPhi;
0030
0031
0032
0033
0034
0035
0036 T _frmin1;
0037 T _frmin2;
0038 T _frmax1;
0039 T _frmax2;
0040
0041 evolution::Wedge fPhiWedge;
0042
0043
0044
0045 Vector3D<Precision> fNormalPhi1;
0046 Vector3D<Precision> fNormalPhi2;
0047 Precision fAlongPhi1x;
0048 Precision fAlongPhi1y;
0049 Precision fAlongPhi2x;
0050 Precision fAlongPhi2y;
0051
0052
0053
0054 Precision fInnerSlope;
0055 Precision fOuterSlope;
0056 Precision fInnerOffset;
0057 Precision fOuterOffset;
0058 Precision fInnerTolerance;
0059 Precision fOuterTolerance;
0060
0061 Precision fSqRmin1, fSqRmin2;
0062 Precision fSqRmax1, fSqRmax2;
0063 Precision fTolIz, fTolOz;
0064 Precision fInnerConeApex;
0065 Precision fTanInnerApexAngle;
0066 Precision fOuterConeApex;
0067 Precision fTanOuterApexAngle;
0068
0069 Precision fSecRMin;
0070 Precision fSecRMax;
0071 Precision fInvSecRMin;
0072 Precision fInvSecRMax;
0073 Precision fTanRMin;
0074 Precision fTanRMax;
0075 Precision fZNormInner;
0076 Precision fZNormOuter;
0077 Precision fConeTolerance;
0078
0079
0080
0081
0082 Precision fOriginalRmax1;
0083 Precision fOriginalRmax2;
0084
0085 VECCORE_ATT_HOST_DEVICE
0086 Precision Capacity() const
0087 {
0088 return (fDz * fDPhi / 3.) *
0089 (fRmax1 * fRmax1 + fRmax2 * fRmax2 + fRmax1 * fRmax2 - fRmin1 * fRmin1 - fRmin2 * fRmin2 - fRmin1 * fRmin2);
0090 }
0091
0092 VECCORE_ATT_HOST_DEVICE
0093 void CalculateCached()
0094 {
0095 fOriginalRmax1 = fRmax1;
0096 fOriginalRmax2 = fRmax2;
0097
0098 if (fRmin1 == fRmax1) {
0099 fRmax1 += kConeTolerance;
0100 }
0101
0102 if (fRmin2 == fRmax2) {
0103 fRmax2 += kConeTolerance;
0104 }
0105
0106 fSqRmin1 = fRmin1 * fRmin1;
0107 fSqRmax1 = fRmax1 * fRmax1;
0108 fSqRmin2 = fRmin2 * fRmin2;
0109 fSqRmax2 = fRmax2 * fRmax2;
0110 fConeTolerance = 1e-7;
0111
0112 fTanRMin = (fRmin2 - fRmin1) * 0.5 / fDz;
0113 fSecRMin = std::sqrt(1.0 + fTanRMin * fTanRMin);
0114 fInvSecRMin = 1. / NonZero(fSecRMin);
0115 fTanRMax = (fRmax2 - fRmax1) * 0.5 / fDz;
0116
0117 fSecRMax = std::sqrt(1.0 + fTanRMax * fTanRMax);
0118 fInvSecRMax = 1. / NonZero(fSecRMax);
0119
0120
0121 fInnerSlope = -(fRmin1 - fRmin2) / (2. * fDz);
0122 fOuterSlope = -(fRmax1 - fRmax2) / (2. * fDz);
0123 fInnerOffset = fRmin2 - fInnerSlope * fDz;
0124 fOuterOffset = fRmax2 - fOuterSlope * fDz;
0125 fInnerTolerance = kConeTolerance * fSecRMin;
0126 fOuterTolerance = kConeTolerance * fSecRMax;
0127
0128 if (fRmin2 > fRmin1) {
0129 fInnerConeApex = 2 * fDz * fRmin1 / (fRmin2 - fRmin1);
0130 fTanInnerApexAngle = fRmin2 / (2 * fDz + fInnerConeApex);
0131 } else {
0132 fInnerConeApex = 2 * fDz * fRmin2 / NonZero(fRmin1 - fRmin2);
0133 fTanInnerApexAngle = fRmin1 / (2 * fDz + fInnerConeApex);
0134 }
0135
0136 if (fRmin1 == 0. || fRmin2 == 0.) fInnerConeApex = 0.;
0137
0138 if (fRmin1 == 0.) fTanInnerApexAngle = fRmin2 / (2 * fDz);
0139 if (fRmin2 == 0.) fTanInnerApexAngle = fRmin1 / (2 * fDz);
0140
0141 if (fRmax2 > fRmax1) {
0142 fOuterConeApex = 2 * fDz * fRmax1 / (fRmax2 - fRmax1);
0143 fTanOuterApexAngle = fRmax2 / (2 * fDz + fOuterConeApex);
0144 } else {
0145 fOuterConeApex = 2 * fDz * fRmax2 / NonZero(fRmax1 - fRmax2);
0146 fTanOuterApexAngle = fRmax1 / (2 * fDz + fOuterConeApex);
0147 }
0148
0149 if (fRmax1 == 0. || fRmax2 == 0.) fOuterConeApex = 0.;
0150
0151 if (fRmax1 == 0.) fTanOuterApexAngle = fRmax2 / (2 * fDz);
0152 if (fRmax2 == 0.) fTanOuterApexAngle = fRmax1 / (2 * fDz);
0153
0154 fZNormInner = fTanRMin / NonZero(fSecRMin);
0155 fZNormOuter = -fTanRMax / NonZero(fSecRMax);
0156
0157 fTolIz = fDz - kHalfTolerance;
0158 fTolOz = fDz + kHalfTolerance;
0159
0160
0161 }
0162
0163 VECCORE_ATT_HOST_DEVICE
0164 void Print() const
0165 {
0166 printf("ConeStruct : {rmin1 %.2f, rmax1 %.2f, rmin2 %.2f, "
0167 "rmax2 %.2f, dz %.2f, phistart %.2f, deltaphi %.2f}",
0168 fRmin1, fRmax1, fRmin2, fRmax2, fDz, fSPhi, fDPhi);
0169 }
0170
0171 void Print(std::ostream &os) const { os << "UnplacedCone; please implement Print to outstream\n"; }
0172
0173 VECCORE_ATT_HOST_DEVICE
0174 bool IsFullPhi() const { return fDPhi == kTwoPi; }
0175
0176 VECCORE_ATT_HOST_DEVICE
0177 bool Normal(Vector3D<Precision> const &p, Vector3D<Precision> &norm) const
0178 {
0179 int noSurfaces = 0;
0180 Precision rho, pPhi;
0181 Precision distZ, distRMin, distRMax;
0182 Precision distSPhi = kInfLength, distEPhi = kInfLength;
0183 Precision pRMin, widRMin;
0184 Precision pRMax, widRMax;
0185
0186
0187
0188 Vector3D<Precision> sumnorm(0., 0., 0.), nZ = Vector3D<Precision>(0., 0., 1.);
0189 Vector3D<Precision> nR, nr(0., 0., 0.), nPs, nPe;
0190 norm = sumnorm;
0191
0192
0193 distZ = vecCore::math::Abs(p.z()) - fDz;
0194 rho = vecCore::math::Sqrt(p.x() * p.x() + p.y() * p.y());
0195
0196 pRMin = rho - p.z() * fTanRMin;
0197 widRMin = fRmin2 - fDz * fTanRMin;
0198 if (vecCore::math::Abs(_frmin1 - _frmin2) < fInnerTolerance)
0199 distRMin = (rho - _frmin2);
0200 else
0201 distRMin = (pRMin - widRMin) / fSecRMin;
0202
0203 pRMax = rho - p.z() * fTanRMax;
0204 widRMax = fRmax2 - fDz * fTanRMax;
0205 if (vecCore::math::Abs(_frmax1 - _frmax2) < fOuterTolerance)
0206 distRMax = (rho - _frmax2);
0207 else
0208 distRMax = (pRMax - widRMax) / fSecRMax;
0209
0210 bool inside = distZ < kTolerance && distRMax < fOuterTolerance;
0211 if (fRmin1 || fRmin2) inside &= distRMin > -fInnerTolerance;
0212
0213 distZ = std::fabs(distZ);
0214 distRMax = std::fabs(distRMax);
0215 distRMin = std::fabs(distRMin);
0216
0217
0218 Precision distNearest = distZ;
0219 Vector3D<Precision> normNearest = nZ;
0220 if (p.z() < 0.) normNearest.Set(0, 0, -1.);
0221
0222 if (!IsFullPhi()) {
0223 if (rho) {
0224 pPhi = vecCore::math::ATan2(p.y(), p.x());
0225
0226 if (pPhi < fSPhi - kHalfTolerance)
0227 pPhi += 2 * kPi;
0228 else if (pPhi > fSPhi + fDPhi + kHalfTolerance)
0229 pPhi -= 2 * kPi;
0230
0231 distSPhi = rho * (pPhi - fSPhi);
0232 distEPhi = rho * (pPhi - fSPhi - fDPhi);
0233 inside = inside && (distSPhi > -kTolerance) && (distEPhi < kTolerance);
0234 distSPhi = vecCore::math::Abs(distSPhi);
0235 distEPhi = vecCore::math::Abs(distEPhi);
0236 }
0237
0238 else if (!(fRmin1) || !(fRmin2)) {
0239 distSPhi = 0.;
0240 distEPhi = 0.;
0241 }
0242 nPs = Vector3D<Precision>(vecCore::math::Sin(fSPhi), -vecCore::math::Cos(fSPhi), 0);
0243 nPe = Vector3D<Precision>(-vecCore::math::Sin(fSPhi + fDPhi), vecCore::math::Cos(fSPhi + fDPhi), 0);
0244 }
0245
0246 if (rho > kHalfTolerance) {
0247 nR = Vector3D<Precision>(p.x() / rho / fSecRMax, p.y() / rho / fSecRMax, -fTanRMax / fSecRMax);
0248 if (fRmin1 || fRmin2) {
0249 nr = Vector3D<Precision>(-p.x() / rho / fSecRMin, -p.y() / rho / fSecRMin, fTanRMin / fSecRMin);
0250 }
0251 }
0252
0253 if (inside && distZ <= kHalfTolerance) {
0254 noSurfaces++;
0255 if (p.z() >= 0.)
0256 sumnorm += nZ;
0257 else
0258 sumnorm.Set(0, 0, -1.);
0259 }
0260
0261 if (inside && distRMax <= fOuterTolerance) {
0262 noSurfaces++;
0263 sumnorm += nR;
0264 } else if (noSurfaces == 0 && distRMax < distNearest) {
0265 distNearest = distRMax;
0266 normNearest = nR;
0267 }
0268
0269 if (fRmin1 || fRmin2) {
0270 if (inside && distRMin <= fInnerTolerance) {
0271 noSurfaces++;
0272 sumnorm += nr;
0273 } else if (noSurfaces == 0 && distRMin < distNearest) {
0274 distNearest = distRMin;
0275 normNearest = nr;
0276 }
0277 }
0278
0279 if (!IsFullPhi()) {
0280 if (inside && distSPhi <= kHalfTolerance) {
0281 noSurfaces++;
0282 sumnorm += nPs;
0283 } else if (noSurfaces == 0 && distSPhi < distNearest) {
0284 distNearest = distSPhi;
0285 normNearest = nPs;
0286 }
0287 if (inside && distEPhi <= kHalfTolerance) {
0288 noSurfaces++;
0289 sumnorm += nPe;
0290 } else if (noSurfaces == 0 && distEPhi < distNearest) {
0291
0292
0293 normNearest = nPe;
0294 }
0295 }
0296
0297 if (noSurfaces == 0)
0298 norm = normNearest;
0299 else if (noSurfaces == 1)
0300 norm = sumnorm;
0301 else
0302 norm = sumnorm.Unit();
0303
0304 bool valid = noSurfaces != 0;
0305 if (noSurfaces > 2) {
0306
0307 valid = false;
0308 }
0309
0310 return valid;
0311 }
0312
0313 VECCORE_ATT_HOST_DEVICE
0314 void SetAndCheckSPhiAngle(Precision sPhi)
0315 {
0316
0317 if (sPhi < 0) {
0318 fSPhi = kTwoPi - std::fmod(std::fabs(sPhi), kTwoPi);
0319 } else {
0320 fSPhi = std::fmod(sPhi, kTwoPi);
0321 }
0322 if (fSPhi + fDPhi > kTwoPi) {
0323 fSPhi -= kTwoPi;
0324 }
0325
0326
0327 fPhiWedge.SetStartPhi(fSPhi);
0328
0329 GetAlongVectorToPhiSector(fSPhi, fAlongPhi1x, fAlongPhi1y);
0330 GetAlongVectorToPhiSector(fSPhi + fDPhi, fAlongPhi2x, fAlongPhi2y);
0331 }
0332
0333 VECCORE_ATT_HOST_DEVICE
0334 void SetAndCheckDPhiAngle(Precision dPhi)
0335 {
0336 if (dPhi >= kTwoPi - 0.5 * kAngTolerance) {
0337 fDPhi = kTwoPi;
0338 fSPhi = 0;
0339 } else {
0340 if (dPhi > 0) {
0341 fDPhi = dPhi;
0342 } else {
0343
0344
0345
0346
0347 }
0348 }
0349
0350 fPhiWedge.SetDeltaPhi(fDPhi);
0351
0352 GetAlongVectorToPhiSector(fSPhi, fAlongPhi1x, fAlongPhi1y);
0353 GetAlongVectorToPhiSector(fSPhi + fDPhi, fAlongPhi2x, fAlongPhi2y);
0354 }
0355
0356 VECCORE_ATT_HOST_DEVICE
0357 static void GetAlongVectorToPhiSector(Precision phi, Precision &x, Precision &y)
0358 {
0359 x = std::cos(phi);
0360 y = std::sin(phi);
0361 }
0362
0363 void SetRmin1(Precision const &arg)
0364 {
0365 fRmin1 = arg;
0366 CalculateCached();
0367 }
0368 void SetRmax1(Precision const &arg)
0369 {
0370 fRmax1 = arg;
0371 CalculateCached();
0372 }
0373 void SetRmin2(Precision const &arg)
0374 {
0375 fRmin2 = arg;
0376 CalculateCached();
0377 }
0378 void SetRmax2(Precision const &arg)
0379 {
0380 fRmax2 = arg;
0381 CalculateCached();
0382 }
0383 void SetDz(Precision const &arg)
0384 {
0385 fDz = arg;
0386 CalculateCached();
0387 }
0388 void SetSPhi(Precision const &arg)
0389 {
0390 fSPhi = arg;
0391 SetAndCheckSPhiAngle(fSPhi);
0392
0393 }
0394 void SetDPhi(Precision const &arg)
0395 {
0396 fDPhi = arg;
0397 SetAndCheckDPhiAngle(fDPhi);
0398
0399 }
0400
0401 VECCORE_ATT_HOST_DEVICE
0402 Precision GetTolIz() const { return fTolIz; }
0403 VECCORE_ATT_HOST_DEVICE
0404 Precision GetTolOz() const { return fTolOz; }
0405
0406 VECCORE_ATT_HOST_DEVICE
0407 Precision GetConeTolerane() const { return fConeTolerance; }
0408
0409 VECCORE_ATT_HOST_DEVICE
0410 evolution::Wedge const &GetWedge() const { return fPhiWedge; }
0411
0412
0413 VECCORE_ATT_HOST_DEVICE
0414 ConeStruct(T const &_rmin1, T const &_rmax1, T const &_rmin2, T const &_rmax2, T const &_z, T const &_sphi,
0415 T const &_dphi)
0416 : fRmin1(_rmin1 < 0.0 ? 0.0 : _rmin1), fRmax1(_rmax1), fRmin2(_rmin2 < 0.0 ? 0.0 : _rmin2), fRmax2(_rmax2),
0417 fDz(_z), fSPhi(_sphi), fDPhi(_dphi), _frmin1(_rmin1), _frmin2(_rmin2), _frmax1(_rmax1), _frmax2(_rmax2),
0418 fPhiWedge(_dphi, _sphi)
0419 {
0420
0421 SetAndCheckDPhiAngle(_dphi);
0422 SetAndCheckSPhiAngle(_sphi);
0423 CalculateCached();
0424
0425
0426 }
0427 };
0428 }
0429 }
0430
0431 #endif