Project
Loading...
Searching...
No Matches
GeometryManager.cxx
Go to the documentation of this file.
1// Copyright 2019-2020 CERN and copyright holders of ALICE O2.
2// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders.
3// All rights not expressly granted are reserved.
4//
5// This software is distributed under the terms of the GNU General Public
6// License v3 (GPL Version 3), copied verbatim in the file "COPYING".
7//
8// In applying this license CERN does not waive the privileges and immunities
9// granted to it by virtue of its status as an Intergovernmental Organization
10// or submit itself to any jurisdiction.
11
14
15#include <fairlogger/Logger.h> // for LOG
16#include <TCollection.h> // for TIter
17#include <TFile.h>
18#include <TGeoMatrix.h> // for TGeoHMatrix
19#include <TGeoNavigator.h> // for TGeoNavigator
20#include <TGeoNode.h> // for TGeoNode
21#include <TGeoPhysicalNode.h> // for TGeoPhysicalNode, TGeoPNEntry
22#include <string>
23#include <cassert>
24#include <cstddef> // for NULL
25#include <numeric>
26
32
33#ifdef O2_WITH_VECGEOM
34#include "TGeo2VecGeom/RootGeoManager.h"
35#include <VecGeom/management/GeoManager.h>
36#include <VecGeom/management/ABBoxManager.h>
37#include <VecGeom/management/BVHManager.h>
38#include <VecGeom/navigation/GlobalLocator.h>
39#include <VecGeom/navigation/NavigationState.h>
40#include <VecGeom/navigation/NewSimpleNavigator.h>
41#include <VecGeom/navigation/BVHNavigator.h>
42#include <VecGeom/navigation/SimpleLevelLocator.h>
43#include <VecGeom/navigation/BVHLevelLocator.h>
44#include <VecGeom/navigation/VNavigator.h>
45#include <VecGeom/volumes/LogicalVolume.h>
46#include <mutex>
47#endif
48
49using namespace o2::detectors;
50using namespace o2::base;
51
55std::mutex GeometryManager::sTGMutex;
56
57//______________________________________________________________________
58Bool_t GeometryManager::getOriginalMatrix(const char* symname, TGeoHMatrix& m)
59{
60 m.Clear();
61 if (!gGeoManager || !gGeoManager->IsClosed()) {
62 LOG(error) << "No active geometry or geometry not yet closed!";
63 ;
64 return kFALSE;
65 }
66 std::lock_guard<std::mutex> guard(sTGMutex);
67 if (!gGeoManager->GetListOfPhysicalNodes()) {
68 LOG(warning) << "gGeoManager doesn't contain any aligned nodes!";
69
70 if (!gGeoManager->cd(symname)) {
71 LOG(error) << "Volume path " << symname << " not valid!";
72 return kFALSE;
73 } else {
74 m = *gGeoManager->GetCurrentMatrix();
75 return kTRUE;
76 }
77 }
78
79 TGeoPNEntry* pne = gGeoManager->GetAlignableEntry(symname);
80 const char* path = nullptr;
81
82 if (pne) {
83 m = *pne->GetGlobalOrig();
84 return kTRUE;
85 } else {
86 LOG(warning) << "The symbolic volume name " << symname
87 << "does not correspond to a physical entry. Using it as a volume path!";
88 path = symname;
89 }
90
91 return getOriginalMatrixFromPath(path, m);
92}
93
94//______________________________________________________________________
95Bool_t GeometryManager::getOriginalMatrixFromPath(const char* path, TGeoHMatrix& m)
96{
97 m.Clear();
98
99 if (!gGeoManager || !gGeoManager->IsClosed()) {
100 LOG(error) << "Can't get the original global matrix! gGeoManager doesn't exist or it is still opened!";
101 return kFALSE;
102 }
103 std::lock_guard<std::mutex> guard(sTGMutex);
104 if (!gGeoManager->CheckPath(path)) {
105 LOG(error) << "Volume path " << path << " not valid!";
106 return kFALSE;
107 }
108
109 TIter next(gGeoManager->GetListOfPhysicalNodes());
110 gGeoManager->cd(path);
111
112 while (gGeoManager->GetLevel()) {
113 TGeoPhysicalNode* physNode = nullptr;
114 next.Reset();
115 TGeoNode* node = gGeoManager->GetCurrentNode();
116
117 while ((physNode = (TGeoPhysicalNode*)next())) {
118 if (physNode->GetNode() == node) {
119 break;
120 }
121 }
122
123 TGeoMatrix* lm = nullptr;
124 if (physNode) {
125 lm = physNode->GetOriginalMatrix();
126 if (!lm) {
127 lm = node->GetMatrix();
128 }
129 } else {
130 lm = node->GetMatrix();
131 }
132
133 m.MultiplyLeft(lm);
134
135 gGeoManager->CdUp();
136 }
137 return kTRUE;
138}
139
140//______________________________________________________________________
141TGeoHMatrix* GeometryManager::getMatrix(TGeoPNEntry* pne)
142{
143 // Get the global transformation matrix for a given PNEntry
144 // by quering the TGeoManager
145
146 if (!gGeoManager || !gGeoManager->IsClosed()) {
147 LOG(error) << "Can't get the global matrix! gGeoManager doesn't exist or it is still opened!";
148 return nullptr;
149 }
150
151 // if matrix already known --> return it
152 TGeoPhysicalNode* pnode = pne->GetPhysicalNode();
153 if (pnode) {
154 return pnode->GetMatrix();
155 }
156
157 // otherwise calculate it from title and attach via TGeoPhysicalNode
158 pne->SetPhysicalNode(new TGeoPhysicalNode(pne->GetTitle()));
159 return pne->GetPhysicalNode()->GetMatrix();
160}
161
162//______________________________________________________________________
163TGeoHMatrix* GeometryManager::getMatrix(const char* symname)
164{
165 // Get the global transformation matrix for a given alignable volume
166 // identified by its symbolic name 'symname' by quering the TGeoManager
167
168 if (!gGeoManager || !gGeoManager->IsClosed()) {
169 LOG(error) << "No active geometry or geometry not yet closed!";
170 return nullptr;
171 }
172
173 TGeoPNEntry* pne = gGeoManager->GetAlignableEntry(symname);
174 if (!pne) {
175 return nullptr;
176 }
177
178 return getMatrix(pne);
179}
180
181//______________________________________________________________________
182const char* GeometryManager::getSymbolicName(DetID detid, int sensid)
183{
187 int id = getSensID(detid, sensid);
188 TGeoPNEntry* pne = gGeoManager->GetAlignableEntryByUID(id);
189 if (!pne) {
190 LOG(error) << "Failed to find alignable entry with index " << id << ": Det" << detid << " Sens.Vol:" << sensid << ") !";
191 return nullptr;
192 }
193 return pne->GetName();
194}
195
196TGeoPNEntry* GeometryManager::getPNEntry(DetID detid, Int_t sensid)
197{
201 int id = getSensID(detid, sensid);
202 TGeoPNEntry* pne = gGeoManager->GetAlignableEntryByUID(id);
203 if (!pne) {
204 LOG(error) << "The sens.vol " << sensid << " of det " << detid << " does not correspond to a physical entry!";
205 }
206 return pne;
207}
208
209//______________________________________________________________________
210TGeoHMatrix* GeometryManager::getMatrix(DetID detid, Int_t sensid)
211{
215 static TGeoHMatrix matTmp;
216 TGeoPNEntry* pne = getPNEntry(detid, sensid);
217 if (!pne) {
218 return nullptr;
219 }
220
221 TGeoPhysicalNode* pnode = pne->GetPhysicalNode();
222 if (pnode) {
223 return pnode->GetMatrix();
224 }
225
226 const char* path = pne->GetTitle();
227 gGeoManager->PushPath(); // Preserve the modeler state.
228 if (!gGeoManager->cd(path)) {
229 gGeoManager->PopPath();
230 LOG(error) << "Volume path " << path << " not valid!";
231 return nullptr;
232 }
233 matTmp = *gGeoManager->GetCurrentMatrix();
234 gGeoManager->PopPath();
235 return &matTmp;
236}
237
238//______________________________________________________________________
239Bool_t GeometryManager::getOriginalMatrix(DetID detid, int sensid, TGeoHMatrix& m)
240{
244 m.Clear();
245
246 const char* symname = getSymbolicName(detid, sensid);
247 if (!symname) {
248 return kFALSE;
249 }
250
251 return getOriginalMatrix(symname, m);
252}
253
254//______________________________________________________________________
255bool GeometryManager::applyAlignment(const std::vector<const std::vector<o2::detectors::AlignParam>*> algPars)
256{
258 for (auto dv : algPars) {
259 if (dv && !applyAlignment(*dv)) {
260 return false;
261 }
262 }
263 return true;
264}
265
266//______________________________________________________________________
267bool GeometryManager::applyAlignment(const std::vector<o2::detectors::AlignParam>& algPars)
268{
270 int nvols = algPars.size();
271 std::vector<int> ord(nvols);
272 std::iota(std::begin(ord), std::end(ord), 0); // sort to apply alignment in correct hierarchy
273 std::sort(std::begin(ord), std::end(ord), [&algPars](int a, int b) { return algPars[a].getLevel() < algPars[b].getLevel(); });
274
275 bool res = true;
276 for (int i = 0; i < nvols; i++) {
277 if (!algPars[ord[i]].applyToGeometry(GeometryManagerParam::Instance().printLevel)) {
278 res = false;
279 LOG(error) << "Error applying alignment object for volume" << algPars[ord[i]].getSymName();
280 }
281 }
282 return res;
283}
284
285// ================= methods for nested MatBudgetExt class ================
286
287//______________________________________________________________________
289{
290 double nrm = 1. / step;
291 meanRho *= nrm;
292 meanA *= nrm;
293 meanZ *= nrm;
294 meanZ2A *= nrm;
295 if (nrm > 0.) {
296 length = step;
297 }
298}
299
300//______________________________________________________________________
301void GeometryManager::accountMaterial(const TGeoMaterial* material, GeometryManager::MatBudgetExt& bd)
302{
303 bd.meanRho = material->GetDensity();
304 bd.meanX2X0 = material->GetRadLen();
305 bd.meanA = material->GetA();
306 bd.meanZ = material->GetZ();
307 if (material->IsMixture()) {
308 TGeoMixture* mixture = (TGeoMixture*)material;
309 Double_t norm = 0.;
310 bd.meanZ2A = 0.;
311 for (Int_t iel = 0; iel < mixture->GetNelements(); iel++) {
312 norm += mixture->GetWmixt()[iel];
313 bd.meanZ2A += mixture->GetZmixt()[iel] * mixture->GetWmixt()[iel] / mixture->GetAmixt()[iel];
314 }
315 bd.meanZ2A /= norm;
316 } else {
317 bd.meanZ2A = bd.meanZ / bd.meanA;
318 }
319}
320
321//_____________________________________________________________________________________
322GeometryManager::MatBudgetExt GeometryManager::meanMaterialBudgetExt(float x0, float y0, float z0, float x1, float y1, float z1)
323{
324 //
325 // TODO? It seems there is no real nead for extended material budget, consider eliminating it
326 //
327 // Calculate mean material budget and material properties (extended version) between
328 // the points "0" and "1".
329 //
330 // see MatBudgetExt data members for provided information
331 //
332 // Origin: Marian Ivanov, Marian.Ivanov@cern.ch
333 //
334 // Corrections and improvements by
335 // Andrea Dainese, Andrea.Dainese@lnl.infn.it,
336 // Andrei Gheata, Andrei.Gheata@cern.ch
337 //
338 // Ported to O2: ruben.shahoyan@cern.ch
339 //
340 if (!gGeoManager) {
341 throw std::runtime_error("meanMaterialBudgetExt requires geometry loaded");
342 }
343 double length, startD[3] = {x0, y0, z0};
344 double dir[3] = {x1 - x0, y1 - y0, z1 - z0};
345 if ((length = dir[0] * dir[0] + dir[1] * dir[1] + dir[2] * dir[2]) < TGeoShape::Tolerance() * TGeoShape::Tolerance()) {
346 return MatBudgetExt(); // return empty struct
347 }
348 length = TMath::Sqrt(length);
349 double invlen = 1. / length;
350 for (int i = 3; i--;) {
351 dir[i] *= invlen;
352 }
353 std::lock_guard<std::mutex> guard(sTGMutex);
354 // Initialize start point and direction
355 TGeoNode* currentnode = gGeoManager->InitTrack(startD, dir);
356 if (!currentnode) {
357 LOG(error) << "start point out of geometry: " << x0 << ':' << y0 << ':' << z0;
358 return MatBudgetExt(); // return empty struct
359 }
360
361 MatBudgetExt budTotal, budStep;
362 accountMaterial(currentnode->GetVolume()->GetMedium()->GetMaterial(), budStep);
363 budStep.length = length;
364
365 // Locate next boundary within length without computing safety.
366 // Propagate either with length (if no boundary found) or just cross boundary
367 gGeoManager->FindNextBoundaryAndStep(length, kFALSE);
368 Double_t stepTot = 0.0; // Step made
369 Double_t step = gGeoManager->GetStep();
370 // If no boundary within proposed length, return current step data
371 if (!gGeoManager->IsOnBoundary()) {
372 budStep.meanX2X0 = budStep.length / budStep.meanX2X0;
373 return MatBudgetExt(budStep);
374 }
375 // Try to cross the boundary and see what is next
376 Int_t nzero = 0;
377 while (length > TGeoShape::Tolerance()) {
378 if (step < 2. * TGeoShape::Tolerance()) {
379 nzero++;
380 } else {
381 nzero = 0;
382 }
383 if (nzero > 3) {
384 // This means navigation has problems on one boundary
385 // Try to cross by making a small step
386 const double* curPos = gGeoManager->GetCurrentPoint();
387 LOG(warning) << "Cannot cross boundary at (" << curPos[0] << ',' << curPos[1] << ',' << curPos[2] << ')';
388 budTotal.normalize(stepTot);
389 budTotal.nCross = -1; // flag failed navigation
390 return MatBudgetExt(budTotal);
391 }
392 stepTot += step;
393
394 budTotal.meanRho += step * budStep.meanRho;
395 budTotal.meanX2X0 += step / budStep.meanX2X0;
396 budTotal.meanA += step * budStep.meanA;
397 budTotal.meanZ += step * budStep.meanZ;
398 budTotal.meanZ2A += step * budStep.meanZ2A;
399 budTotal.nCross++;
400
401 if (step >= length) {
402 break;
403 }
404 currentnode = gGeoManager->GetCurrentNode();
405 if (!currentnode) {
406 break;
407 }
408 length -= step;
409 accountMaterial(currentnode->GetVolume()->GetMedium()->GetMaterial(), budStep);
410 gGeoManager->FindNextBoundaryAndStep(length, kFALSE);
411 step = gGeoManager->GetStep();
412 }
413 budTotal.normalize(stepTot);
414 return MatBudgetExt(budTotal);
415}
416
417//_____________________________________________________________________________________
418o2::base::MatBudget GeometryManager::meanMaterialBudget(float x0, float y0, float z0, float x1, float y1, float z1,
419 TGeoNavigator* nav)
420{
421 //
422 // Calculate mean material budget and material properties between
423 // the points "0" and "1".
424 //
425 // see MatBudget data members for provided information
426 //
427 // Origin: Marian Ivanov, Marian.Ivanov@cern.ch
428 //
429 // Corrections and improvements by
430 // Andrea Dainese, Andrea.Dainese@lnl.infn.it,
431 // Andrei Gheata, Andrei.Gheata@cern.ch
432 //
433 // Ported to O2: ruben.shahoyan@cern.ch
434 //
435 // Multi-threaded execution: pass a navigator owned by the calling thread.
436 //
437
438 double length, startD[3] = {x0, y0, z0};
439 double dir[3] = {x1 - x0, y1 - y0, z1 - z0};
440 if ((length = dir[0] * dir[0] + dir[1] * dir[1] + dir[2] * dir[2]) < TGeoShape::Tolerance() * TGeoShape::Tolerance()) {
441 return o2::base::MatBudget(); // return empty struct
442 }
443 length = TMath::Sqrt(length);
444 double invlen = 1. / length;
445 for (int i = 3; i--;) {
446 dir[i] *= invlen;
447 }
448 // A caller that passes its own navigator owns it exclusively, so no locking is needed. A caller
449 // that passes none shares gGeoManager's current navigator and must still serialize. Deciding
450 // this from the argument keeps the choice local: it does not depend on -- and cannot be broken
451 // by -- process-global state such as TGeoManager::GetMaxThreads().
452 std::unique_lock<std::mutex> guard(sTGMutex, std::defer_lock);
453 if (!nav) {
454 guard.lock();
455 nav = gGeoManager->GetCurrentNavigator();
456 }
457 // Initialize start point and direction
458 TGeoNode* currentnode = nav->InitTrack(startD, dir);
459 if (!currentnode) {
460 LOG(error) << "start point out of geometry: " << x0 << ':' << y0 << ':' << z0;
461 return o2::base::MatBudget(); // return empty struct
462 }
463
464 o2::base::MatBudget budTotal, budStep;
465 accountMaterial(currentnode->GetVolume()->GetMedium()->GetMaterial(), budStep);
466 budStep.length = length;
467
468 // Locate next boundary within length without computing safety.
469 // Propagate either with length (if no boundary found) or just cross boundary
470 nav->FindNextBoundaryAndStep(length, kFALSE);
471 Double_t stepTot = 0.0; // Step made
472 Double_t step = nav->GetStep();
473 // If no boundary within proposed length, return current step data
474 if (!nav->IsOnBoundary()) {
475 budStep.meanX2X0 = budStep.length / budStep.meanX2X0;
476 return o2::base::MatBudget(budStep);
477 }
478 // Try to cross the boundary and see what is next
479 Int_t nzero = 0;
480 while (length > TGeoShape::Tolerance()) {
481 if (step < 2. * TGeoShape::Tolerance()) {
482 nzero++;
483 } else {
484 nzero = 0;
485 }
486 if (nzero > 3) {
487 // This means navigation has problems on one boundary
488 // Try to cross by making a small step
489 const double* curPos = nav->GetCurrentPoint();
490 LOG(warning) << "Cannot cross boundary at (" << curPos[0] << ',' << curPos[1] << ',' << curPos[2] << ')';
491 budTotal.meanRho /= stepTot;
492 budTotal.length = stepTot;
493 return o2::base::MatBudget(budTotal);
494 }
495 stepTot += step;
496
497 budTotal.meanRho += step * budStep.meanRho;
498 budTotal.meanX2X0 += step / budStep.meanX2X0;
499
500 if (step >= length) {
501 break;
502 }
503 currentnode = nav->GetCurrentNode();
504 if (!currentnode) {
505 break;
506 }
507 length -= step;
508 accountMaterial(currentnode->GetVolume()->GetMedium()->GetMaterial(), budStep);
509 nav->FindNextBoundaryAndStep(length, kFALSE);
510 step = nav->GetStep();
511 }
512 budTotal.meanRho /= stepTot;
513 budTotal.length = stepTot;
514 return o2::base::MatBudget(budTotal);
515}
516
517//_________________________________
518void GeometryManager::applyMisalignent(bool applyMisalignment)
519{
521 if (!isGeometryLoaded()) {
522 LOG(fatal) << "geometry is not loaded";
523 }
524 if (applyMisalignment) {
525 auto& aligner = Aligner::Instance();
526 aligner.applyAlignment();
527 }
528}
529
530//_________________________________
531void GeometryManager::loadGeometry(std::string_view simPrefix, bool applyMisalignment, bool preferAlignedFile)
532{
533 auto loadGeom = [](const std::string_view fname) {
534 LOG(info) << "Loading geometry from " << fname;
535 TFile flGeom(fname.data());
536 if (flGeom.IsZombie()) {
537 LOG(fatal) << "Failed to open file " << fname;
538 }
539 // try under the standard CCDB name
540 if (!flGeom.Get(std::string(o2::base::NameConf::CCDBOBJECT).c_str()) &&
541 !flGeom.Get(std::string(o2::base::NameConf::GEOMOBJECTNAME_FAIR).c_str())) {
542 LOG(fatal) << "Did not find geometry named " << o2::base::NameConf::CCDBOBJECT << " or " << o2::base::NameConf::GEOMOBJECTNAME_FAIR;
543 }
544 };
545
546 if (preferAlignedFile) {
549 } else {
551 loadGeom(o2::base::NameConf::getGeomFileName(simPrefix));
552 applyMisalignent(applyMisalignment);
553 }
554}
555
556#ifdef O2_WITH_VECGEOM
557
558namespace
559{
563void ensureVecGeomWorldBuilt()
564{
565 static std::once_flag onceFlag;
566 std::call_once(onceFlag, []() {
567 if (!gGeoManager) {
568 LOG(fatal) << "Cannot build VecGeom geometry: no TGeo geometry loaded (call GeometryManager::loadGeometry() first)";
569 }
570 // Translate geometry and material pointers, then build acceleration structures.
571 tgeo2vecgeom::RootGeoManager::Instance().SetMaterialConversionHook([](TGeoMaterial const* m) { return (void*)m; });
572 tgeo2vecgeom::RootGeoManager::Instance().SetFlattenAssemblies(true);
573 tgeo2vecgeom::RootGeoManager::Instance().LoadRootGeometry();
574
575 // Acceleration structures must be built before the navigators/locators reference them.
576 vecgeom::ABBoxManager::Instance().InitABBoxesForCompleteGeometry();
577 // Builds a BVH per logical volume from the ABBoxes computed above.
578 vecgeom::BVHManager::Init();
579
580 // For each logical volume, set both a navigator (used for ComputeStep) and a matched
581 // level locator (used for point relocation after a boundary crossing via GlobalLocator);
582 // volumes with very few daughters are cheaper to brute-force than to accelerate.
583 for (auto& lvol : vecgeom::GeoManager::Instance().GetLogicalVolumesMap()) {
584 auto* vol = lvol.second;
585 if (vol->GetDaughtersp()->size() <= 2) {
586 vol->SetNavigator(vecgeom::NewSimpleNavigator<>::Instance());
587 vol->SetLevelLocator(vecgeom::SimpleLevelLocator::GetInstance());
588 } else {
589 vol->SetNavigator(vecgeom::BVHNavigator<>::Instance());
590 vol->SetLevelLocator(vecgeom::BVHLevelLocator::GetInstance());
591 }
592 }
593 });
594}
595} // namespace
596
597//_____________________________________________________________________________________
598o2::base::MatBudget GeometryManager::vecGeomMaterialBudget(float x0, float y0, float z0, float x1, float y1, float z1)
599{
600 // Mean material budget between "0" and "1" via VecGeom's BVH-accelerated ray/boundary
601 // intersection, instead of TGeo.
602 ensureVecGeomWorldBuilt();
603
604 using Vector3D = vecgeom::Vector3D<vecgeom::Precision>;
605
606 double length, start[3] = {x0, y0, z0};
607 double dir[3] = {x1 - x0, y1 - y0, z1 - z0};
608 if ((length = dir[0] * dir[0] + dir[1] * dir[1] + dir[2] * dir[2]) < TGeoShape::Tolerance() * TGeoShape::Tolerance()) {
609 return o2::base::MatBudget(); // return empty struct
610 }
611 length = std::sqrt(length);
612 double invlen = 1. / length;
613 for (int i = 3; i--;) {
614 dir[i] *= invlen;
615 }
616
617 thread_local static vecgeom::NavigationState* newnavstate = vecgeom::NavigationState::MakeInstance(vecgeom::GeoManager::Instance().getMaxDepth());
618 thread_local static vecgeom::NavigationState* currnavstate = vecgeom::NavigationState::MakeInstance(vecgeom::GeoManager::Instance().getMaxDepth());
619 thread_local static vecgeom::NavigationState* startCache = vecgeom::NavigationState::MakeInstance(vecgeom::GeoManager::Instance().getMaxDepth());
620 thread_local static bool startCacheValid = false;
621
622 Vector3D currPoint(x0, y0, z0);
623 Vector3D dirr(dir[0], dir[1], dir[2]);
624 constexpr double kPush = 1.E-6; // mimick the nudging of TGeo's FindNextBoundaryAndStep
625 auto world = vecgeom::GeoManager::Instance().GetWorld();
626 o2::base::MatBudget budTot, budStep;
627 budStep.length = length;
628
629 // Locate the starting volume, reusing the path from the previous call when still valid.
630 if (startCacheValid && !startCache->IsOutside()) {
631 startCache->CopyTo(currnavstate);
632 vecgeom::Transformation3D m;
633 currnavstate->TopMatrix(m);
634 vecgeom::GlobalLocator::RelocatePointFromPath(m.Transform(currPoint), *currnavstate);
635 } else {
636 currnavstate->Clear();
637 vecgeom::GlobalLocator::LocateGlobalPoint(world, currPoint, *currnavstate, true);
638 }
639 if (currnavstate->IsOutside() || currnavstate->Top() == nullptr) {
640 LOG(error) << "start point out of geometry: " << x0 << ':' << y0 << ':' << z0;
641 startCacheValid = false;
642 return o2::base::MatBudget();
643 }
644 currnavstate->CopyTo(startCache);
645 startCacheValid = true;
646
647 double stepTot = 0.;
648 double remainingDist = length;
649 Int_t nzero = 0;
650 while (remainingDist > 1.E-10) {
651 auto* lvol = currnavstate->Top()->GetLogicalVolume();
652 accountMaterial(static_cast<TGeoMaterial*>(lvol->GetMaterialPtr()), budStep);
653 vecgeom::VNavigator const* navigator = lvol->GetNavigator();
654 double step = static_cast<double>(navigator->ComputeStepAndPropagatedState(currPoint, dirr, remainingDist, *currnavstate, *newnavstate));
655 if (step < 2.E-10) {
656 nzero++;
657 } else {
658 nzero = 0;
659 }
660 if (nzero > 3) {
661 // This means navigation has problems on one boundary
662 LOG(warning) << "Cannot cross boundary at (" << currPoint[0] << ',' << currPoint[1] << ',' << currPoint[2] << ')';
663 budTot.meanRho /= stepTot;
664 budTot.length = stepTot;
665 return o2::base::MatBudget(budTot);
666 }
667
668 remainingDist -= step;
669 stepTot += step;
670 budTot.meanRho += step * budStep.meanRho;
671 budTot.meanX2X0 += step / budStep.meanX2X0;
672 currPoint = currPoint + (step + kPush) * dirr;
673 std::swap(currnavstate, newnavstate);
674 }
675 budTot.meanRho /= stepTot;
676 budTot.length = stepTot;
677 return o2::base::MatBudget(budTot);
678}
679
680#endif // O2_WITH_VECGEOM
Definition of the base alignment parameters class.
Definition of the GeometryManager class.
std::unique_ptr< expressions::Node > node
int32_t i
Definition of the Names Generator class.
uint32_t res
Definition RawData.h:0
static const char * getSymbolicName(o2::detectors::DetID detid, int sensid)
static Bool_t getOriginalMatrix(o2::detectors::DetID detid, int sensid, TGeoHMatrix &m)
static void loadGeometry(std::string_view geomFilePath="", bool applyMisalignment=false, bool preferAlignedFile=true)
static bool applyAlignment(const std::vector< o2::detectors::AlignParam > &algPars)
misalign geometry with alignment objects from the array, optionaly check overlaps
static o2::base::MatBudget meanMaterialBudget(float x0, float y0, float z0, float x1, float y1, float z1, TGeoNavigator *nav=nullptr)
static MatBudgetExt meanMaterialBudgetExt(float x0, float y0, float z0, float x1, float y1, float z1)
static int getSensID(o2::detectors::DetID detid, int sensid)
static TGeoHMatrix * getMatrix(const char *symname)
static TGeoPNEntry * getPNEntry(o2::detectors::DetID detid, Int_t sensid)
static void applyMisalignent(bool applyMisalignment=true)
static std::string getAlignedGeomFileName(const std::string_view prefix="")
Definition NameConf.cxx:46
static std::string getGeomFileName(const std::string_view prefix="")
Definition NameConf.cxx:40
static constexpr std::string_view CCDBOBJECT
Definition NameConf.h:66
static constexpr std::string_view GEOMOBJECTNAME_FAIR
Definition NameConf.h:83
Static class with identifiers, bitmasks and names for ALICE detectors.
Definition DetID.h:58
const GLfloat * m
Definition glcorearb.h:4066
GLuint GLfloat GLfloat GLfloat GLfloat y1
Definition glcorearb.h:5034
GLuint GLfloat GLfloat GLfloat x1
Definition glcorearb.h:5034
GLboolean GLboolean GLboolean b
Definition glcorearb.h:1233
GLuint GLsizei GLsizei * length
Definition glcorearb.h:790
GLuint GLfloat x0
Definition glcorearb.h:5034
GLsizei const GLchar *const * path
Definition glcorearb.h:3591
GLuint start
Definition glcorearb.h:469
GLboolean GLboolean GLboolean GLboolean a
Definition glcorearb.h:1233
GLuint GLfloat GLfloat y0
Definition glcorearb.h:5034
const int const float z1
ROOT::Math::DisplacementVector3D< ROOT::Math::Cartesian3D< T >, ROOT::Math::DefaultCoordinateSystemTag > Vector3D
value_T step
Definition TrackUtils.h:42
float length
length in material
Definition MatCell.h:55
float meanRho
mean density, g/cm^3
Definition MatCell.h:30
float meanX2X0
fraction of radiaton lenght
Definition MatCell.h:31
LOG(info)<< "Compressed in "<< sw.CpuTime()<< " s"