Skip to content

Commit 399d3ac

Browse files
author
Marco Giacalone
committed
Add ITS monopoles response + data format for monopoles
1 parent 8bcf38a commit 399d3ac

4 files changed

Lines changed: 59 additions & 8 deletions

File tree

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
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+
12+
/// \file MonopoleParticles.h
13+
/// \brief Identification of the BSM magnetic monopoles across the simulation
14+
/// @author M. Giacalone - September 2026
15+
///
16+
/// The monopole PDG codes are defined in O2MCApplication::AddParticles() and in
17+
/// O2DatabasePDG. They are collected here for better syncing inside the simulation code
18+
///
19+
/// To do: add dyons and other monopoles configurations when needed
20+
21+
#ifndef ALICEO2_SIMULATION_MONOPOLEPARTICLES_H_
22+
#define ALICEO2_SIMULATION_MONOPOLEPARTICLES_H_
23+
24+
namespace o2::sim
25+
{
26+
27+
/// monopole carrying equal electric and magnetic charge
28+
constexpr int MonopolePdgSymm = 4110000;
29+
/// monopole carrying opposite electric and magnetic charge
30+
constexpr int MonopolePdgAsymm = 4120000;
31+
32+
/// true for the monopole and antimonopole of both species
33+
constexpr bool isMonopole(int pdg) noexcept
34+
{
35+
const int abspdg = pdg < 0 ? -pdg : pdg;
36+
return abspdg == MonopolePdgSymm || abspdg == MonopolePdgAsymm;
37+
}
38+
39+
} // namespace o2::sim
40+
41+
#endif

Detectors/ITSMFT/ITS/simulation/src/Detector.cxx

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424

2525
#include "DetectorsBase/Stack.h"
2626
#include "SimulationDataFormat/TrackReference.h"
27+
#include "SimulationDataFormat/MonopoleParticles.h"
2728
#include "fairlogger/Logger.h" // for LOG, LOG_IF
2829

2930
// FairRoot includes
@@ -318,7 +319,11 @@ void Detector::InitializeO2Detector()
318319
Bool_t Detector::ProcessHits(FairVolume* vol)
319320
{
320321
// This method is called from the MC stepping
321-
if (!(fMC->TrackCharge())) {
322+
// Electrically neutral magnetic monopoles deposit energy in the
323+
// silicon through G4mplIonisation (Ahlen stopping power), so they must not be
324+
// rejected by the electric-charge gate
325+
const bool isMonopole = o2::sim::isMonopole(fMC->TrackPid());
326+
if (!(fMC->TrackCharge()) && !isMonopole) {
322327
return kFALSE;
323328
}
324329

@@ -386,6 +391,12 @@ Bool_t Detector::ProcessHits(FairVolume* vol)
386391
mTrackData.mHitStarted = true;
387392
}
388393
if (stopHit) {
394+
// A monopole reaches this point even when no ionisation process is attached to
395+
// it (G4.monopole=0), in which case it crosses the sensor depositing nothing.
396+
// Storing such empty hits would only inflate the hit file, so they are skipped
397+
if (isMonopole && mTrackData.mEnergyLoss <= 0.) {
398+
return kFALSE;
399+
}
389400
TLorentzVector positionStop;
390401
fMC->TrackPosition(positionStop);
391402
// Retrieve the indices with the volume path

Detectors/TPC/simulation/src/Detector.cxx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717

1818
#include "DetectorsBase/Stack.h"
1919
#include "SimulationDataFormat/TrackReference.h"
20+
#include "SimulationDataFormat/MonopoleParticles.h"
2021

2122
#include "FairVolume.h" // for FairVolume
2223

@@ -115,7 +116,7 @@ Bool_t Detector::ProcessHits(FairVolume* vol)
115116
// Magnetic monopoles have zero electric charge but ionise the gas through
116117
// their magnetic charge energy loss (G4mplIonisation).
117118
const int trackPdg = fMC->TrackPid();
118-
const bool isMonopole = (TMath::Abs(trackPdg) == 4110000 || TMath::Abs(trackPdg) == 4120000);
119+
const bool isMonopole = o2::sim::isMonopole(trackPdg);
119120
if (static_cast<int>(trackCharge) == 0) {
120121
// Fall through only for monopoles when ionisation is enabled.
121122
// The behaviour for the other neutral particles remains as before.

Detectors/gconfig/src/O2MonopolePhysics.cxx

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030

3131
#include "SimSetup/O2MonopolePhysics.h"
3232
#include "CommonUtils/ConfigurableParam.h"
33+
#include "SimulationDataFormat/MonopoleParticles.h"
3334

3435
#include <boost/property_tree/ptree.hpp> // needed to instantiate getValueAs<>
3536

@@ -79,13 +80,10 @@ namespace
7980
// O2MCApplication::AddParticles() and O2DatabasePDG:
8081
// +-4110000 : "symmetric" monopoles
8182
// +-4120000 : "asymmetric" monopoles
82-
constexpr std::array<int, 4> gMonopolePDGs = {4110000, -4110000, 4120000, -4120000};
83+
constexpr std::array<int, 4> gMonopolePDGs = {o2::sim::MonopolePdgSymm, -o2::sim::MonopolePdgSymm,
84+
o2::sim::MonopolePdgAsymm, -o2::sim::MonopolePdgAsymm};
8385

84-
inline bool isMonopolePDG(int pdg)
85-
{
86-
const int abspdg = std::abs(pdg);
87-
return abspdg == 4110000 || abspdg == 4120000;
88-
}
86+
inline bool isMonopolePDG(int pdg) { return o2::sim::isMonopole(pdg); }
8987

9088
/// GEANT4 only queries the magnetic field when a particle has non-zero electric
9189
/// charge or non-zero magnetic moment (μ) and the monopole has neither. So this is a workaround

0 commit comments

Comments
 (0)