File indexing completed on 2025-03-13 09:29:30
0001
0002
0003
0004
0005
0006
0007
0008 #ifndef VECGEOM_SPHERESTRUCT_H_
0009 #define VECGEOM_SPHERESTRUCT_H_
0010
0011 #include "VecGeom/volumes/Wedge_Evolution.h"
0012
0013
0014 #include "VecGeom/volumes/ThetaCone_Evolution.h"
0015 #include "VecGeom/base/Global.h"
0016
0017 namespace vecgeom {
0018
0019 inline namespace VECGEOM_IMPL_NAMESPACE {
0020
0021 template <typename T = double>
0022 struct SphereStruct {
0023 T fRmin;
0024 T fRmax;
0025 T fSPhi;
0026 T fDPhi;
0027 T fSTheta;
0028 T fDTheta;
0029
0030
0031 Precision fRminTolerance, mkTolerance,
0032 fEpsilon;
0033
0034
0035 Precision sinCPhi, cosCPhi, cosHDPhiOT, cosHDPhiIT, sinSPhi, cosSPhi, sinEPhi, cosEPhi, hDPhi, cPhi, ePhi;
0036
0037
0038 Precision sinSTheta, cosSTheta, sinETheta, cosETheta, tanSTheta, tanSTheta2, tanETheta, tanETheta2, eTheta;
0039
0040 Precision fabsTanSTheta, fabsTanETheta;
0041
0042
0043 bool fFullPhiSphere, fFullThetaSphere, fFullSphere;
0044
0045 Precision fCubicVolume, fSurfaceArea;
0046
0047
0048 evolution::Wedge fPhiWedge;
0049 ThetaCone fThetaCone;
0050
0051 Precision kAngTolerance;
0052
0053 VECCORE_ATT_HOST_DEVICE
0054 VECGEOM_FORCE_INLINE
0055 void InitializePhiTrigonometry()
0056 {
0057 hDPhi = 0.5 * fDPhi;
0058 cPhi = fSPhi + hDPhi;
0059 ePhi = fSPhi + fDPhi;
0060
0061 sinCPhi = std::sin(cPhi);
0062 cosCPhi = vecCore::math::Cos(cPhi);
0063 cosHDPhiIT = vecCore::math::Cos(hDPhi - 0.5 * kAngTolerance);
0064 cosHDPhiOT = vecCore::math::Cos(hDPhi + 0.5 * kAngTolerance);
0065 sinSPhi = std::sin(fSPhi);
0066 cosSPhi = vecCore::math::Cos(fSPhi);
0067 sinEPhi = std::sin(ePhi);
0068 cosEPhi = vecCore::math::Cos(ePhi);
0069 }
0070
0071 VECCORE_ATT_HOST_DEVICE
0072 VECGEOM_FORCE_INLINE
0073 void InitializeThetaTrigonometry()
0074 {
0075 eTheta = fSTheta + fDTheta;
0076
0077 sinSTheta = std::sin(fSTheta);
0078 cosSTheta = vecCore::math::Cos(fSTheta);
0079 sinETheta = std::sin(eTheta);
0080 cosETheta = vecCore::math::Cos(eTheta);
0081
0082 tanSTheta = sinSTheta / cosSTheta;
0083 fabsTanSTheta = std::fabs(tanSTheta);
0084 tanSTheta2 = tanSTheta * tanSTheta;
0085 tanETheta = sinETheta / cosETheta;
0086 fabsTanETheta = std::fabs(tanETheta);
0087 tanETheta2 = tanETheta * tanETheta;
0088 }
0089
0090 VECCORE_ATT_HOST_DEVICE
0091 VECGEOM_FORCE_INLINE
0092 void CheckThetaAngles(Precision sTheta, Precision dTheta)
0093 {
0094 if ((sTheta < 0) || (sTheta > kPi)) {
0095
0096
0097
0098
0099
0100
0101 } else {
0102 fSTheta = sTheta;
0103 }
0104 if (dTheta + sTheta >= kPi) {
0105 fDTheta = kPi - sTheta;
0106 } else if (dTheta > 0) {
0107 fDTheta = dTheta;
0108 } else {
0109
0110
0111
0112
0113
0114
0115
0116
0117
0118 }
0119 if (fDTheta - fSTheta < kPi) {
0120 fFullThetaSphere = false;
0121 } else {
0122 fFullThetaSphere = true;
0123 }
0124 fFullSphere = fFullPhiSphere && fFullThetaSphere;
0125
0126 InitializeThetaTrigonometry();
0127 }
0128
0129 VECCORE_ATT_HOST_DEVICE
0130 VECGEOM_FORCE_INLINE
0131 void CheckSPhiAngle(Precision sPhi)
0132 {
0133
0134
0135 if (sPhi < 0) {
0136 fSPhi = 2 * kPi - std::fmod(std::fabs(sPhi), 2 * kPi);
0137 } else {
0138 fSPhi = std::fmod(sPhi, 2 * kPi);
0139 }
0140 if (fSPhi + fDPhi > 2 * kPi) {
0141 fSPhi -= 2 * kPi;
0142 }
0143 }
0144
0145 VECCORE_ATT_HOST_DEVICE
0146 VECGEOM_FORCE_INLINE
0147 void CheckDPhiAngle(Precision dPhi)
0148 {
0149 if (dPhi >= 2 * kPi - kAngTolerance * 0.5) {
0150
0151 fDPhi = 2 * kPi;
0152 fSPhi = 0;
0153 fFullPhiSphere = true;
0154
0155 } else {
0156 fFullPhiSphere = false;
0157 if (dPhi > 0) {
0158 fDPhi = dPhi;
0159 } else {
0160
0161
0162
0163
0164
0165
0166
0167
0168
0169
0170 }
0171 }
0172 }
0173
0174 VECCORE_ATT_HOST_DEVICE
0175 VECGEOM_FORCE_INLINE
0176 void CheckPhiAngles(Precision sPhi, Precision dPhi)
0177 {
0178 CheckDPhiAngle(dPhi);
0179
0180 if (!fFullPhiSphere) {
0181 CheckSPhiAngle(sPhi);
0182 }
0183 fFullSphere = fFullPhiSphere && fFullThetaSphere;
0184
0185 InitializePhiTrigonometry();
0186 }
0187
0188
0189
0190 void SetInsideRadius(Precision newRmin)
0191 {
0192 fRmin = newRmin;
0193 fRminTolerance = (fRmin) ? std::max(kRadTolerance, fEpsilon * fRmin) : 0;
0194 Initialize();
0195 #ifndef VECCORE_CUDA
0196 CalcCapacity();
0197 CalcSurfaceArea();
0198 #endif
0199 }
0200
0201
0202
0203 void SetInnerRadius(Precision newRmin) { SetInsideRadius(newRmin); }
0204
0205
0206
0207 void SetOuterRadius(Precision newRmax)
0208 {
0209 fRmax = newRmax;
0210 mkTolerance = std::max(kRadTolerance,
0211 fEpsilon * fRmax);
0212 Initialize();
0213 #ifndef VECCORE_CUDA
0214 CalcCapacity();
0215 CalcSurfaceArea();
0216 #endif
0217 }
0218
0219
0220
0221 void SetStartPhiAngle(Precision newSPhi, bool compute = true)
0222 {
0223
0224
0225
0226 CheckSPhiAngle(newSPhi);
0227 fFullPhiSphere = false;
0228 if (compute) {
0229 InitializePhiTrigonometry();
0230 }
0231 Initialize();
0232 #ifndef VECCORE_CUDA
0233 CalcCapacity();
0234 CalcSurfaceArea();
0235 #endif
0236 }
0237
0238
0239
0240 void SetDeltaPhiAngle(Precision newDPhi)
0241 {
0242 CheckPhiAngles(fSPhi, newDPhi);
0243 Initialize();
0244 #ifndef VECCORE_CUDA
0245 CalcCapacity();
0246 CalcSurfaceArea();
0247 #endif
0248 }
0249
0250
0251
0252 void SetStartThetaAngle(Precision newSTheta)
0253 {
0254 CheckThetaAngles(newSTheta, fDTheta);
0255 Initialize();
0256 #ifndef VECCORE_CUDA
0257 CalcCapacity();
0258 CalcSurfaceArea();
0259 #endif
0260 }
0261
0262
0263
0264 void SetDeltaThetaAngle(Precision newDTheta)
0265 {
0266 CheckThetaAngles(fSTheta, newDTheta);
0267 Initialize();
0268 #ifndef VECCORE_CUDA
0269 CalcCapacity();
0270 CalcSurfaceArea();
0271 #endif
0272 }
0273
0274 VECCORE_ATT_HOST_DEVICE
0275 VECGEOM_FORCE_INLINE
0276 void Initialize()
0277 {
0278 fCubicVolume = 0.;
0279 fSurfaceArea = 0.;
0280 }
0281
0282
0283 VECCORE_ATT_HOST_DEVICE
0284 VECGEOM_FORCE_INLINE
0285 SphereStruct(T pRmin, T pRmax, T pSPhi, T pDPhi, T pSTheta, T pDTheta)
0286 : fRmin(pRmin), fRmax(pRmax), fSPhi(pSPhi), fDPhi(pDPhi), fSTheta(pSTheta), fDTheta(pDTheta), fRminTolerance(0),
0287 mkTolerance(0), fEpsilon(kEpsilon), sinCPhi(0), cosCPhi(0), cosHDPhiOT(0), cosHDPhiIT(0), sinSPhi(0),
0288 cosSPhi(0), sinEPhi(0), cosEPhi(0), hDPhi(0), cPhi(0), ePhi(0), sinSTheta(0), cosSTheta(0), sinETheta(0),
0289 cosETheta(0), tanSTheta(0), tanSTheta2(0), tanETheta(0), tanETheta2(0), eTheta(0), fFullPhiSphere(true),
0290 fFullThetaSphere(true), fFullSphere(true), fCubicVolume(0.), fSurfaceArea(0.), fPhiWedge(pDPhi, pSPhi),
0291 fThetaCone(pSTheta, pDTheta)
0292 {
0293
0294 kAngTolerance = 1e-9;
0295 fRminTolerance = (fRmin) ? Max(kRadTolerance, fEpsilon * fRmin) : 0;
0296 mkTolerance = Max(kRadTolerance, fEpsilon * fRmax);
0297
0298 CheckPhiAngles(pSPhi, pDPhi);
0299 CheckThetaAngles(pSTheta, pDTheta);
0300 #ifndef VECCORE_CUDA
0301 CalcCapacity();
0302 CalcSurfaceArea();
0303 #endif
0304 }
0305
0306 VECCORE_ATT_HOST_DEVICE
0307 VECGEOM_FORCE_INLINE
0308 SphereStruct() {}
0309
0310
0311 VECCORE_ATT_HOST_DEVICE
0312 VECGEOM_FORCE_INLINE
0313 void CalcCapacity()
0314 {
0315 if (fCubicVolume != 0.) {
0316 ;
0317 } else {
0318 fCubicVolume = fDPhi * (vecCore::math::Cos(fSTheta) - vecCore::math::Cos(fSTheta + fDTheta)) *
0319 (fRmax * fRmax * fRmax - fRmin * fRmin * fRmin) / 3.;
0320 }
0321 }
0322 VECCORE_ATT_HOST_DEVICE
0323 VECGEOM_FORCE_INLINE
0324 void CalcSurfaceArea()
0325 {
0326
0327 if (fSurfaceArea != 0.) {
0328 ;
0329 } else {
0330 Precision Rsq = fRmax * fRmax;
0331 Precision rsq = fRmin * fRmin;
0332
0333 fSurfaceArea = fDPhi * (rsq + Rsq) * (cosSTheta - cosETheta);
0334 if (!fFullPhiSphere) {
0335 fSurfaceArea = fSurfaceArea + fDTheta * (Rsq - rsq);
0336 }
0337 if (fSTheta > 0) {
0338 Precision acos1 = 0.;
0339 if (fDPhi != kTwoPi)
0340 acos1 = vecCore::math::ACos((sinSTheta * sinSTheta) * vecCore::math::Cos(fDPhi) + (cosSTheta * cosSTheta));
0341 if (fDPhi > kPi) {
0342 fSurfaceArea = fSurfaceArea + 0.5 * (Rsq - rsq) * (2 * kPi - acos1);
0343 } else {
0344 fSurfaceArea = fSurfaceArea + 0.5 * (Rsq - rsq) * acos1;
0345 }
0346 }
0347 if (eTheta < kPi) {
0348 Precision acos2 = 0.;
0349 if (fDPhi != kTwoPi)
0350 acos2 = vecCore::math::ACos((sinETheta * sinETheta) * vecCore::math::Cos(fDPhi) + (cosETheta * cosETheta));
0351 if (fDPhi > kPi) {
0352 fSurfaceArea = fSurfaceArea + 0.5 * (Rsq - rsq) * (2 * kPi - acos2);
0353 } else {
0354 fSurfaceArea = fSurfaceArea + 0.5 * (Rsq - rsq) * acos2;
0355 }
0356 }
0357 }
0358 }
0359
0360 };
0361 }
0362 }
0363
0364 #endif