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
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{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
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
0059 SetAndCheckStartAndDeltaPhi(phiStart, phiTotal);
0060
0061
0062
0063
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
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 §ion = 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
0118 size_t aligned_size = AlignedAllocator::aligned_sizeof<PolyconeSection>(numSections, 0);
0119
0120 aligned_size += AlignedAllocator::aligned_sizeof<Precision>(numSections + 1, 0);
0121
0122 aligned_size += 2 * AlignedAllocator::aligned_sizeof<Vector3D<Precision>>(2 * numSections, 0);
0123
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
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
0170
0171
0172
0173
0174
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
0192
0193
0194 bool contRmax = CheckContinuityInRmax(newROuter);
0195 bool contSlope = CheckContinuityInSlope(newROuter, newZPlane);
0196
0197
0198
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
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 §ion) {
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 §ion : fSections)
0253 dump_section(isection++, section);
0254 }
0255
0256
0257 template <typename PushableContainer>
0258 void ReconstructSectionArrays(PushableContainer &z_values, PushableContainer &rmin_values,
0259 PushableContainer &rmax_values) const
0260 {
0261
0262 Precision prevZ = 0., prevRmax = 0., prevRmin = 0.;
0263 int iplane = 0;
0264 for (auto const §ion : 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
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
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,
0298 Precision phiTotal,
0299 unsigned int numZPlanes,
0300 const Precision zPlane[],
0301 const Precision rInner[],
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
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
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
0377 if (i > 0) {
0378
0379
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 {
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
0449
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
0461 int i = GetSectionIndex(zposition);
0462
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
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;
0481 else
0482 return fSections[index].fSolid.fRmin1;
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;
0492 else
0493 return fSections[index].fSolid.fRmax1;
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
0535 fStartPhi = sPhi;
0536 while (fStartPhi < 0.)
0537 fStartPhi += kTwoPi;
0538
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
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
0572 fPhiWedge.Set(fDeltaPhi, fStartPhi);
0573 fPhiWedge.UpdateNormals();
0574 }
0575 };
0576 }
0577 }
0578
0579 #endif