Project
Loading...
Searching...
No Matches
G4LocalFieldConstruction.cxx
Go to the documentation of this file.
1// Copyright 2019-2026 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
13#include "SimConfig/G4Params.h"
14
15#include "TG4GeometryManager.h"
16
17#include <G4UIcommandTree.hh>
18#include <G4UImanager.hh>
19#include <TGeoManager.h>
20#include <TVirtualMC.h>
21#include <fairlogger/Logger.h>
22
23#include <string>
24#include <unordered_set>
25
26namespace o2::g4config
27{
28
29namespace
30{
31// First volume in the subtree of vol whose medium has no magnetic field (ifield = 0)
32const TGeoVolume* findZeroFieldVolume(const TGeoVolume* vol, std::unordered_set<const TGeoVolume*>& visited)
33{
34 if (!visited.insert(vol).second) {
35 return nullptr;
36 }
37 auto med = vol->GetMedium();
38 if (med && !vol->IsAssembly() && med->GetParam(1) == 0) {
39 return vol;
40 }
41 for (int i = 0; i < vol->GetNdaughters(); ++i) {
42 if (auto nf = findZeroFieldVolume(vol->GetNode(i)->GetVolume(), visited)) {
43 return nf;
44 }
45 }
46 return nullptr;
47}
48} // namespace
49
51{
52 if (mNext) {
53 mNext->Construct();
54 }
55 auto tree = G4UImanager::GetUIpointer()->GetTree()->FindCommandTree("/mcMagField/");
56 auto field = TVirtualMC::GetMC()->GetMagField();
57 if (!tree || !field) {
58 return;
59 }
60 int nattached = 0;
61 for (int i = 1; i <= tree->GetTreeEntry(); ++i) {
62 std::string path = tree->GetTree(i)->GetPathName(); // "/mcMagField/<vol>/"
63 auto name = path.substr(12, path.size() - 13);
64 auto vol = gGeoManager->GetVolume(name.c_str());
65 if (!vol) {
66 LOG(warn) << "local field: no volume " << name << "; its field parameters are unused";
67 continue;
68 }
69 // Geant4 VMC forces a local field onto all daughters, which would override zero-field media
70 std::unordered_set<const TGeoVolume*> visited;
71 if (auto nf = findZeroFieldVolume(vol, visited)) {
72 LOG(warn) << "local field: volume " << name << " contains the zero-field volume " << nf->GetName() << "; skipped";
73 continue;
74 }
75 vol->SetField(field);
76 LOG(info) << "local field: volume " << name << " uses the parameters in /mcMagField/" << name << "/";
77 ++nattached;
78 }
79 if (nattached > 0) {
80 TG4GeometryManager::Instance()->SetIsLocalField(true);
82 LOG(warn) << "local field: Geant4 VMC builds local fields only with TGeo navigation; the global field applies everywhere";
83 }
84 }
85}
86
87} // namespace o2::g4config
int32_t i
GLuint const GLchar * name
Definition glcorearb.h:781
GLsizei const GLchar *const * path
Definition glcorearb.h:3591
LOG(info)<< "Compressed in "<< sw.CpuTime()<< " s"
std::unique_ptr< TTree > tree((TTree *) flIn.Get(std::string(o2::base::NameConf::CTFTREENAME).c_str()))