42 std::stringstream msg;
43 msg <<
"\n------------------------------------------------------------------------------------";
44 msg <<
"\n Material budget map creator";
46 msg <<
"\n !! To run it with the full speed, set: \"export OMP_NUM_THREADS=<n CPUs>\" before running !!";
50 const char* env = std::getenv(
"OMP_NUM_THREADS");
53 msg <<
"\n found environment variable OMP_NUM_THREADS = \"" << env <<
"\", read as integer: " <<
fNthreads;
63 msg <<
"\n Maps will be created using " <<
fNthreads <<
" CPU threads";
65 msg <<
"\n It might crash because of a ROOT bug. In this case do one of the following: ";
67 msg <<
"\n - fix illegal overlaps in the geometry via gGeoManager->CheckOverlaps()";
68 msg <<
"\n - run with CbmL1::SetSafeMaterialInitialization() option. ";
69 msg <<
"\n It fixes the crash, but slows down the initialization significantly.";
70 msg <<
"\n - manually disable voxel finders for problematic volumes in CaToolsMaterialMapFactory.cxx";
72 msg <<
"\n------------------------------------------------------------------------------------";
73 LOG_IF(info,
fVerbose > 0) << msg.str();
91 TObjArray* volumes = gGeoManager->GetListOfVolumes();
93 for (
int iv = 0; iv < volumes->GetEntriesFast(); iv++) {
94 TGeoVolume* vol =
dynamic_cast<TGeoVolume*
>(volumes->At(iv));
98 TGeoVoxelFinder* finder = vol->GetVoxels();
100 finder->SetInvalid();
109 bool isAlignmentApplied =
false;
111 TObjArray* nodes = gGeoManager->GetListOfPhysicalNodes();
113 for (
int in = 0; in < nodes->GetEntriesFast(); in++) {
114 TGeoPhysicalNode* node =
dynamic_cast<TGeoPhysicalNode*
>(nodes->At(in));
116 if (node->IsAligned()) {
117 isAlignmentApplied =
true;
126 if (isAlignmentApplied) {
127 TObjArray* volumes = gGeoManager->GetListOfVolumes();
129 for (
int iv = 0; iv < volumes->GetEntriesFast(); iv++) {
130 TGeoVolumeAssembly* vol =
dynamic_cast<TGeoVolumeAssembly*
>(volumes->At(iv));
134 TGeoVoxelFinder* finder = vol->GetVoxels();
136 finder->SetInvalid();
233MaterialMap MaterialMapFactory::GenerateMaterialMap(
double zRef,
double zMin,
double zMax,
double xyMax,
int nBinsDim)
238 <<
"kf::tools::MaterialMapFactory: the material reference z-coordinate must be at least 0.1 cm downstream "
239 "the target. Shifting the reference z-coordinate to the lower limit: target Z = "
240 <<
fTargetZ <<
", material reference z = " << zRef;
242 zRef = std::max(zRef,
fTargetZ + 0.05);
244 zMax = std::max(zMax, zRef + 0.05);
247 if (!(zMin <= zRef && zRef <= zMax)) {
248 LOG(fatal) <<
"kf::tools::MaterialMapFactory: the material parameters are inconsistent. It must be: zMin " << zMin
249 <<
" <= zRef " << zRef <<
" <= zMax " << zMax;
252 MaterialMap matBudget(nBinsDim, xyMax, zRef, zMin, zMax);
253 double binSizeX = 2. * xyMax / nBinsDim;
254 double binSizeY = 2. * xyMax / nBinsDim;
263 nThreadCrosses[i] = 0;
267 LOG_IF(info,
fVerbose > -1) <<
"kf::tools::MaterialMapFactory: Generate material map using " <<
fNthreads
270 auto naviThread = [&](
int iThread) {
274 for (
int iBinX = iThread; iBinX < nBinsDim; iBinX +=
fNthreads) {
275 for (
int iBinY = 0; iBinY < nBinsDim; ++iBinY) {
276 double radThick = 0.;
283 double rayX = -xyMax + (iBinX + d * (iStepX + 0.5)) * binSizeX;
284 double rayY = -xyMax + (iBinY + d * (iStepY + 0.5)) * binSizeY;
293 t =
sqrt(1. + tx * tx + ty * ty);
298 double x = rayX + tx * (z - zRef);
299 double y = rayY + ty * (z - zRef);
300 LOG_IF(info,
fVerbose > 2) <<
"ray at " <<
x <<
" " <<
y <<
" " << z <<
" zMin " << zMin <<
" zMax "
303 TGeoNode* node = navi->InitTrack(
x,
y, z, tx / t, ty / t, 1. / t);
306 for (
int iStep = 0; doContinue; iStep++) {
310 LOG(warning) <<
"kf::tools::MaterialMapFactory: TGeoNavigator can not find the geo node";
314 TGeoMedium* medium = node->GetMedium();
316 LOG(fatal) <<
"kf::tools::MaterialMapFactory: TGeoNavigator can not find the geo medium";
319 TGeoMaterial* material = medium->GetMaterial();
321 LOG(fatal) <<
"kf::tools::MaterialMapFactory: TGeoNavigator can not find the geo material";
324 double radLen = material->GetRadLen();
327 LOG(fatal) <<
"kf::tools::MaterialMapFactory: failed assertion! "
328 <<
" TGeoNavigator returns a suspicious material with an unrealistic "
329 <<
"radiation length of " << radLen <<
" cm. "
330 <<
" The allowed minimum is 0.56 cm (Lead has 0.5612 cm). Check your material! "
331 "Modify this assertion if necessary."
332 <<
" TGeoNode \"" << node->GetName() <<
"\", TGeoMedium \"" << medium->GetName()
333 <<
"\", TGeoMaterial \"" << material->GetName() <<
"\"";
337 node = navi->FindNextBoundaryAndStep();
338 nThreadCrosses[iThread]++;
340 LOG_IF(info,
fVerbose > 2) <<
" RL " << radLen <<
" next pt " << navi->GetCurrentPoint()[0] <<
" "
341 << navi->GetCurrentPoint()[1] <<
" " << navi->GetCurrentPoint()[2];
343 double zNew = navi->GetCurrentPoint()[2];
351 double dz = zNew - z;
353 if (iStep == 0 && dz > -1.e-8) {
360 <<
"kf::tools::MaterialMapFactory: TGeoNavigator propagates the ray upstream. Something is wrong."
361 <<
" z old " << z <<
" z new " << zNew <<
", dz " << dz;
364 radThick += dz / radLen;
369 nThreadRays[iThread]++;
370 if (
fVerbose > 2 && nThreadRays[iThread] % 1000000 == 0) {
371 LOG(info) <<
"kf::tools::MaterialMapFactory: report from thread " << iThread <<
": material map is "
372 << 100. * nThreadRays[iThread] / nThreadRaysExpected <<
" \% done";
377 LOG_IF(info,
fVerbose > 2) <<
" radThick " << radThick;
384 std::vector<std::thread> threads(
fNthreads);
388 threads[i] = std::thread(naviThread, i);
392 for (
auto& th : threads) {
400 nRays += nThreadRays[i];
401 nCrosses += nThreadCrosses[i];
404 LOG_IF(info,
fVerbose > 0) <<
"kf::tools::MaterialMapFactory: shooted " << nRays <<
" rays. Each ray crossed "
405 << nCrosses * 1. / nRays <<
" material boundaries in average";