File indexing completed on 2025-01-30 10:26:20
0001
0002
0003
0004
0005
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
0023 template <typename T = double>
0024 struct PolyconeStruct {
0025
0026 bool fEqualRmax;
0027 bool fContinuityOverAll;
0028 bool fConvexityPossible;
0029
0030 evolution::Wedge fPhiWedge;
0031 Precision fStartPhi;
0032 Precision fDeltaPhi;
0033 unsigned int fNz;
0034
0035 Vector<PolyconeSection> fSections;
0036 Vector<Precision> fZs;
0037 PolyconeHistorical *fOriginal_parameters;
0038
0039
0040 Vector<Vector3D<Precision>> fRMinTwoDVec;
0041 Vector<Vector3D<Precision>> fRMaxTwoDVec;
0042 Vector<Vector3D<Precision>> fTwoDVec;
0043
0044 VECCORE_ATT_HOST_DEVICE
0045 bool CheckContinuity(const Precision rOuter[], const Precision rInner[], const Precision zPlane[],
0046 Vector<Precision> &newROuter, Vector<Precision> &newRInner, Vector<Precision> &newZPlane)
0047 {
0048 Vector<Precision> rOut, rIn;
0049 Vector<Precision> zPl;
0050 rOut.push_back(rOuter[0]);
0051 rIn.push_back(rInner[0]);
0052 zPl.push_back(zPlane[0]);
0053 for (unsigned int j = 1; j < fNz; j++) {
0054
0055 if (j == fNz - 1) {
0056 rOut.push_back(rOuter[j]);
0057 rIn.push_back(rInner[j]);
0058 zPl.push_back(zPlane[j]);
0059 } else {
0060 if ((zPlane[j] != zPlane[j + 1]) || (rOuter[j] != rOuter[j + 1])) {
0061 rOut.push_back(rOuter[j]);
0062 rOut.push_back(rOuter[j]);
0063
0064 zPl.push_back(zPlane[j]);
0065 zPl.push_back(zPlane[j]);
0066
0067 rIn.push_back(rInner[j]);
0068 rIn.push_back(rInner[j]);
0069
0070 } else {
0071 rOut.push_back(rOuter[j]);
0072 zPl.push_back(zPlane[j]);
0073 rIn.push_back(rInner[j]);
0074 }
0075 }
0076 }
0077
0078 if (rOut.size() % 2 != 0) {
0079
0080 rOut.push_back(rOut[rOut.size() - 1]);
0081 rIn.push_back(rIn[rIn.size() - 1]);
0082 zPl.push_back(zPl[zPl.size() - 1]);
0083 }
0084
0085
0086
0087
0088
0089
0090
0091
0092
0093 for (size_t j = 0; j < rOut.size();) {
0094
0095 if (zPl[j] != zPl[j + 1]) {
0096
0097 newZPlane.push_back(zPl[j]);
0098 newZPlane.push_back(zPl[j + 1]);
0099 newROuter.push_back(rOut[j]);
0100 newROuter.push_back(rOut[j + 1]);
0101 newRInner.push_back(rIn[j]);
0102 newRInner.push_back(rIn[j + 1]);
0103 }
0104
0105 j = j + 2;
0106 }
0107
0108
0109
0110 bool contRmax = CheckContinuityInRmax(newROuter);
0111 bool contSlope = CheckContinuityInSlope(newROuter, newZPlane);
0112
0113
0114
0115 return (contRmax && contSlope);
0116 }
0117
0118 VECCORE_ATT_HOST_DEVICE
0119 bool CheckContinuityInRmax(const Vector<Precision> &rOuter)
0120 {
0121 bool continuous = true;
0122 unsigned int len = rOuter.size();
0123 if (len > 2) {
0124 for (unsigned int j = 1; j < len;) {
0125 if (j != (len - 1)) continuous &= (rOuter[j] == rOuter[j + 1]);
0126 j = j + 2;
0127 }
0128 }
0129 return continuous;
0130 }
0131
0132 VECCORE_ATT_HOST_DEVICE
0133 bool CheckContinuityInSlope(const Vector<Precision> &rOuter, const Vector<Precision> &zPlane)
0134 {
0135
0136 bool continuous = true;
0137 Precision startSlope = kInfLength;
0138
0139
0140 for (size_t j = 0; j < rOuter.size(); j = j + 2) {
0141 Precision currentSlope = (rOuter[j + 1] - rOuter[j]) / (zPlane[j + 1] - zPlane[j]);
0142 continuous &= (currentSlope <= startSlope);
0143 startSlope = currentSlope;
0144 }
0145 return continuous;
0146 }
0147
0148 VECCORE_ATT_HOST_DEVICE
0149 void Init(Precision phiStart,
0150 Precision phiTotal,
0151 unsigned int numZPlanes,
0152 const Precision zPlane[],
0153 const Precision rInner[],
0154 const Precision rOuter[])
0155 {
0156
0157 SetAndCheckDPhiAngle(phiTotal);
0158 SetAndCheckSPhiAngle(phiStart);
0159 fNz = numZPlanes;
0160 Precision *zPlaneR = new Precision[numZPlanes];
0161 Precision *rInnerR = new Precision[numZPlanes];
0162 Precision *rOuterR = new Precision[numZPlanes];
0163 for (unsigned int i = 0; i < numZPlanes; i++) {
0164 zPlaneR[i] = zPlane[i];
0165 rInnerR[i] = rInner[i];
0166 rOuterR[i] = rOuter[i];
0167 }
0168 if (zPlane[0] > zPlane[numZPlanes - 1]) {
0169
0170 for (unsigned int i = 0; i < numZPlanes; i++) {
0171 zPlaneR[i] = zPlane[numZPlanes - 1 - i];
0172 rInnerR[i] = rInner[numZPlanes - 1 - i];
0173 rOuterR[i] = rOuter[numZPlanes - 1 - i];
0174 }
0175 }
0176
0177
0178 if (phiTotal <= 0. || phiTotal > kTwoPi - kTolerance) {
0179
0180 fStartPhi = 0;
0181 fDeltaPhi = kTwoPi;
0182 } else {
0183
0184
0185
0186 fStartPhi = phiStart;
0187 while (fStartPhi < 0)
0188 fStartPhi += kTwoPi;
0189 }
0190
0191
0192
0193 Precision RMaxextent = rOuterR[0];
0194
0195 Vector<Precision> newROuter, newZPlane, newRInner;
0196 fContinuityOverAll &= CheckContinuity(rOuterR, rInnerR, zPlaneR, newROuter, newRInner, newZPlane);
0197 fConvexityPossible &= (newRInner[0] == 0.);
0198
0199 Precision startRmax = newROuter[0];
0200 for (unsigned int j = 1; j < newROuter.size(); j++) {
0201 fEqualRmax &= (startRmax == newROuter[j]);
0202 startRmax = newROuter[j];
0203 fConvexityPossible &= (newRInner[j] == 0.);
0204 }
0205
0206 for (unsigned int j = 1; j < numZPlanes; j++) {
0207
0208 if (rOuterR[j] > RMaxextent) RMaxextent = rOuterR[j];
0209
0210 if (rInnerR[j] > rOuterR[j]) {
0211 #ifndef VECCORE_CUDA
0212 std::cerr << "Cannot create Polycone with rInner > rOuter for the same Z"
0213 << "\n"
0214 << " rInner > rOuter for the same Z !\n"
0215 << " rMin[" << j << "] = " << rInner[j] << " -- rMax[" << j << "] = " << rOuter[j];
0216 #endif
0217 }
0218 }
0219
0220 Precision prevZ = zPlaneR[0], prevRmax = 0, prevRmin = 0;
0221 int dirZ = 1;
0222 if (zPlaneR[1] < zPlaneR[0]) dirZ = -1;
0223
0224 for (unsigned int i = 0; i < numZPlanes; ++i) {
0225 if ((i < numZPlanes - 1) && (zPlaneR[i] == zPlaneR[i + 1])) {
0226 if ((rInnerR[i] > rOuterR[i + 1]) || (rInnerR[i + 1] > rOuterR[i])) {
0227 #ifndef VECCORE_CUDA
0228 std::cerr << "Cannot create a Polycone with no contiguous segments." << std::endl
0229 << " Segments are not contiguous !" << std::endl
0230 << " rMin[" << i << "] = " << rInnerR[i] << " -- rMax[" << i + 1
0231 << "] = " << rOuterR[i + 1] << std::endl
0232 << " rMin[" << i + 1 << "] = " << rInnerR[i + 1] << " -- rMax[" << i
0233 << "] = " << rOuterR[i];
0234 #endif
0235 }
0236 }
0237
0238 Precision rMin = rInnerR[i];
0239
0240 Precision rMax = rOuterR[i];
0241 Precision z = zPlaneR[i];
0242
0243
0244 if (i > 0) {
0245
0246
0247 if (((z > prevZ + kTolerance) && (dirZ > 0)) || ((z < prevZ - kTolerance) && (dirZ < 0))) {
0248 if (dirZ * (z - prevZ) < 0) {
0249 #ifndef VECCORE_CUDA
0250 std::cerr << "Cannot create a Polycone with different Z directions.Use GenericPolycone." << std::endl
0251 << " ZPlane is changing direction !" << std::endl
0252 << " zPlane[0] = " << zPlaneR[0] << " -- zPlane[1] = " << zPlaneR[1] << std::endl
0253 << " zPlane[" << i - 1 << "] = " << zPlaneR[i - 1] << " -- rPlane[" << i << "] = " << zPlaneR[i];
0254 #endif
0255 }
0256
0257 ConeStruct<Precision> *solid;
0258
0259 Precision dz = (z - prevZ) / 2;
0260
0261 solid = new ConeStruct<Precision>(prevRmin, prevRmax, rMin, rMax, dz, phiStart, phiTotal);
0262
0263 fZs.push_back(z);
0264 int zi = fZs.size() - 1;
0265 Precision shift = fZs[zi - 1] + 0.5 * (fZs[zi] - fZs[zi - 1]);
0266
0267 PolyconeSection section;
0268 section.fShift = shift;
0269 section.fSolid = solid;
0270
0271 section.fConvex = !((rMax < prevRmax) || (rMax < RMaxextent) || (prevRmax < RMaxextent));
0272
0273 fSections.push_back(section);
0274 fRMinTwoDVec.push_back(Vector3D<Precision>(prevRmin, prevZ, 0));
0275 fRMinTwoDVec.push_back(Vector3D<Precision>(rMin, z, 0));
0276 fRMaxTwoDVec.push_back(Vector3D<Precision>(prevRmax, prevZ, 0));
0277 fRMaxTwoDVec.push_back(Vector3D<Precision>(rMax, z, 0));
0278 }
0279 } else {
0280 fZs.push_back(z);
0281 }
0282
0283 prevZ = z;
0284 prevRmin = rMin;
0285 prevRmax = rMax;
0286 }
0287 for (auto val : fRMaxTwoDVec) {
0288 fTwoDVec.push_back(val);
0289 }
0290
0291 for (int k = fRMinTwoDVec.size() - 1; k >= 0; k--) {
0292 fTwoDVec.push_back(fRMinTwoDVec[k]);
0293 }
0294 fOriginal_parameters = new PolyconeHistorical(numZPlanes);
0295 fOriginal_parameters->fHStart_angle = phiStart;
0296 fOriginal_parameters->fHOpening_angle = phiTotal;
0297 for (unsigned int i = 0; i < numZPlanes; i++) {
0298 fOriginal_parameters->fHZ_values[i] = zPlaneR[i];
0299 fOriginal_parameters->fHRmin[i] = rInnerR[i];
0300 fOriginal_parameters->fHRmax[i] = rOuterR[i];
0301 }
0302
0303 delete[] zPlaneR;
0304 delete[] rInnerR;
0305 delete[] rOuterR;
0306 }
0307
0308 VECCORE_ATT_HOST_DEVICE
0309 PolyconeHistorical *GetOriginalParameters() const { return fOriginal_parameters; }
0310
0311 VECCORE_ATT_HOST_DEVICE unsigned int GetNz() const { return fNz; }
0312
0313 VECCORE_ATT_HOST_DEVICE
0314 int GetNSections() const { return fSections.size(); }
0315
0316 VECCORE_ATT_HOST_DEVICE
0317 int GetSectionIndex(Precision zposition) const
0318 {
0319
0320
0321 if (zposition < fZs[0]) return -1;
0322 for (unsigned int i = 0; i < fSections.size(); ++i) {
0323 if (zposition >= fZs[i] && zposition <= fZs[i + 1]) return i;
0324 }
0325 return -2;
0326 }
0327
0328 VECCORE_ATT_HOST_DEVICE
0329 PolyconeSection const &GetSection(Precision zposition) const
0330 {
0331
0332 int i = GetSectionIndex(zposition);
0333 return fSections[i];
0334 }
0335
0336 VECCORE_ATT_HOST_DEVICE
0337
0338 PolyconeSection const &GetSection(int index) const { return fSections[index]; }
0339
0340 VECCORE_ATT_HOST_DEVICE
0341 Precision GetRminAtPlane(int index) const
0342 {
0343 int nsect = fSections.size();
0344 assert(index >= 0 && index <= nsect);
0345 if (index == nsect)
0346 return fSections[index - 1].fSolid->fRmin2;
0347 else
0348 return fSections[index].fSolid->fRmin1;
0349 }
0350
0351 VECCORE_ATT_HOST_DEVICE
0352 Precision GetRmaxAtPlane(int index) const
0353 {
0354 int nsect = fSections.size();
0355 assert(index >= 0 || index <= nsect);
0356 if (index == nsect)
0357 return fSections[index - 1].fSolid->fRmax2;
0358 else
0359 return fSections[index].fSolid->fRmax1;
0360 }
0361
0362 VECCORE_ATT_HOST_DEVICE
0363 Precision GetZAtPlane(unsigned int index) const
0364 {
0365 assert(index <= fSections.size());
0366 return fZs[index];
0367 }
0368
0369 VECCORE_ATT_HOST_DEVICE
0370 void SetAndCheckSPhiAngle(Precision sPhi)
0371 {
0372
0373 if (sPhi < 0) {
0374 fStartPhi = kTwoPi - std::fmod(std::fabs(sPhi), kTwoPi);
0375 } else {
0376 fStartPhi = std::fmod(sPhi, kTwoPi);
0377 }
0378 if (fStartPhi + fDeltaPhi > kTwoPi) {
0379 fStartPhi -= kTwoPi;
0380 }
0381
0382
0383 fPhiWedge.SetStartPhi(fStartPhi);
0384 fPhiWedge.UpdateNormals();
0385 }
0386
0387 VECCORE_ATT_HOST_DEVICE
0388 void SetAndCheckDPhiAngle(Precision dPhi)
0389 {
0390 if (dPhi >= kTwoPi - 0.5 * kAngTolerance) {
0391 fDeltaPhi = kTwoPi;
0392 fStartPhi = 0;
0393 } else {
0394 if (dPhi > 0) {
0395 fDeltaPhi = dPhi;
0396 } else {
0397
0398
0399
0400
0401 }
0402 }
0403
0404 fPhiWedge.SetDeltaPhi(fDeltaPhi);
0405 fPhiWedge.UpdateNormals();
0406 }
0407
0408 VECCORE_ATT_HOST_DEVICE
0409 PolyconeStruct() {}
0410 };
0411 }
0412 }
0413
0414 #endif