Magnetic field not working for Logical Volume

Please fill out the following information to help in answering your question, and also see tips for posting code snippets. If you don’t provide this information it will take more time to help with your problem!

Geant4 Version: 11.2
Operating System: Debian 11
Compiler/Version:
CMake Version:


Hello Geant4 experts,
I have another question regarding my detector set up, but this time I am stuck on the magnetic field for my set up. I want to create a homogeneous magnetic field only for a small part of my world volume. Therefore I define my magnet as a cylinder pointing along the z axis, as the z axis is my beam axis. Just before the magnet the target should be placed, such that the beam is deflected after the interaction in the target.
My beam starts at -50cm and the target is positioned at (0,0,0). The Magnet starts at (0,0,0)m and extends to (0,0,1)m. Now the beam spot that I record with my ECal is not deflected if I place the beam at -1mm in front of the target, however it is deflected if I place the beam -50cm in front of the target. Why is that so? Should the beam position not be irrelevant, as the magnetic field starts after the target and only deflects particles then?

I have created the magnetic field and magnet the same way as described in the G4 book for application developers and simply cannot find the error.

This is the part in my DetectorConstruction.cc file with the magnetic field and magnet:

G4ThreeVector magFieldValue = G4ThreeVector(0, 0.9*tesla, 0); // defines the field strength; 
  G4UniformMagField* magField = new G4UniformMagField(magFieldValue); // created magnetic field
  G4FieldManager* fieldManager = G4TransportationManager::GetTransportationManager()->GetFieldManager(); // create a field manager 
  fieldManager->SetDetectorField(magField); // and set field here
  G4Mag_UsualEqRhs* equation = new G4Mag_UsualEqRhs(magField); // create EoM
  G4ChordFinder* chordFinder = new G4ChordFinder(magField, 1.0e-2*mm, new G4ClassicalRK4(equation)); // create chord finder
  fieldManager->SetChordFinder(chordFinder);



// Magnet
  G4double innerR = 50*cm;
  G4double outerR = 90*cm;
  G4double height =  1.0*m; // magnet will be in total this 'long'
  G4double startAngle = 2.86*deg;
  G4double spanningAngle = (360-2.86)*deg;
  G4Tubs* solidMagnet = new G4Tubs("magnet", innerR, outerR, height/2, startAngle, spanningAngle);
  //G4NistManager* nist = G4NistManager::Instance();
  G4Material* iron = nist->FindOrBuildMaterial("G4_Fe");
  G4LogicalVolume* magnetLogical= new G4LogicalVolume(solidMagnet, iron, "LogicalMagnet");
  G4ThreeVector magnPosition = G4ThreeVector(0,0,height/2);
  new G4PVPlacement(0, magnPosition, magnetLogical, "magnet", worldLogical, false, 0, true);
  magnetLogical->SetFieldManager(fieldManager, true);

And see my DetectorConstruction.cc attached.
DetectorConstruction.cc (16.6 KB)

I would be very happy for any kind of help!
Thanks in advance & kind regards,
Laney Klipphahn

What does this look like in UI mode and what particles are you using (and energy)? Your magnetic field is currently constrained to your Tubs logical volume, not its interior (r=0 to r=50 cm).

Thanks for the reply. Of course I want the magnetic field to be inside the magnet not outside. So if I have a cylindrical shaped magnet along the z axis, then the magnetic field should act on particles traversing the inside of the magnet. How can I make this change?

Three options. One is cleaner than the others. Right now your iron material isn’t doing anything unless particles hit it.

  1. Make your iron “magnet” a daughter of an air mother volume that encloses it (Tubs with same dimensions but with rmin = 0). Set the magnetic field to that air mother volume. Cleanest long term.
  2. Place an “air volume” inside your iron volume (rmin=0, rmax=50*cm). Use that as the logical volume for the field. Overlap checking might be more annoying.
  3. Replace the iron with air and set rmin = 0. Simplest but no iron volume which might matter at some future point.

Thank you very much, I will try this out and if any other questions arise, I will let you know!

Hi, I have another question regarding this topic. I was able to update my code, such that the magnetic field is in the mother volume of the iron magnet volume (option 1 suggested above):

  G4ThreeVector magFieldValue = G4ThreeVector(0,0.9*tesla, 0); 
  G4UniformMagField* magField = new G4UniformMagField(magFieldValue); 
  G4FieldManager* fieldManager = G4TransportationManager::GetTransportationManager()->GetFieldManager();
  fieldManager->SetDetectorField(magField);
  G4Mag_UsualEqRhs* equation = new G4Mag_UsualEqRhs(magField); 
  G4ChordFinder* chordFinder = new G4ChordFinder(magField, 1.0e-2*mm, new G4ClassicalRK4(equation)); /
  fieldManager->SetChordFinder(chordFinder);
 
  G4double innerR2 = 0*cm;
  G4double innerR = 50*cm;
  G4double outerR = 90*cm;
  G4double height =  1.0*m; // magnet will be in total this 'long'
  G4double startAngle = 2.86*deg;
  G4double startAngle2 = 0*deg;
  G4double spanningAngle = (360-2.86)*deg;
  G4double spanningAngle2 = 360*deg;
  G4Tubs* MagnetBox = new G4Tubs("magnetBox", innerR2, outerR, height/2, startAngle2, spanningAngle2);
  G4Tubs* solidMagnet = new G4Tubs("magnet", innerR, outerR, height/2, startAngle, spanningAngle);
  G4Material* iron = nist->FindOrBuildMaterial("G4_Fe");
  G4LogicalVolume* magnetBoxLogical = new G4LogicalVolume(MagnetBox, air, "LogicalMagnetBox");
  G4LogicalVolume* magnetLogical= new G4LogicalVolume(solidMagnet, iron, "LogicalMagnet");
  G4ThreeVector magnPosition = G4ThreeVector(0,0,height/2);
  new G4PVPlacement(0, magnPosition, magnetBoxLogical, "magnetBox", worldLogical, false, 0, true);
  new G4PVPlacement(0, magnPosition, magnetLogical, "magnet", worldLogical, false, 0, true);
  magnetBoxLogical->SetFieldManager(fieldManager, true);

However the behavior is still the same. Just for context: my target is positioned at (0,0,0) in the world volume and thus spans from -0.01cm to 0.01cm and the magnet starts at (0,0,0) and spans to (0,0,1m).
Now if I start my beam at position (0,0,50cm) the beam is deflected in the magnet as expected. However if I start it directly in front of the target (0,0,-1cm) then the beam is not deflected at all in the magnet. But this should not make a difference, as the magnetic field starts behind the position of the beam at any point and should thus deflect the beam indepentend of its starting position, as long as this position is outside of the magnetic field, correct?
Placing the beam position between 0 and -50cm the beam gets deflected with different strengths…this does not make any sense to me.
If anyone could help again, that would be super kind!
Best wishes,
Laney

How are you sensing if it is deflected? Can you post images of the visual GUI showing this?

I have an ECal placed 3.5m downstream of the target. The Hits collection from the ECal I simply plot in a 2D histogram. If I place the beam at 5cm before the target (beampos1) the beam is not deflected whatsoever. If I place the beam at 50cm before the target (beampos2) then the beam gets deflected. I do not understand how and why that should make sense.
The magnet starts just after the target and should deflect the beam no matter where I start it, right?
ECalPosXY-beampos1.pdf (17.9 KB)
ECalPosXY-beampos2.pdf (17.1 KB)

Thanks for your help!

It could be related to step sizes. Again, the clearest way to debug this would be to see it with the visual UI. Otherwise you’d probably have to provide the primary generator and physics list as well.

I have found out that the magnetic field is not restricted to the logical volume I defined it to, but rather is applied in the whole world volume. This I have done by evaluating magField->GetFieldValue(point, field) for different points in the world volume. How can this be? Or rather how can I restrict the magnetic field to only the magnetBoxLogical.
Just a reminder, this is my current code to create my magnetic field:

// Magnet 
  G4double innerR2 = 0*cm;
  G4double innerR = 50*cm;
  G4double outerR = 90*cm;
  G4double height =  1.0*m; // magnet will be in total this 'long'
  G4double startAngle = 2.86*deg;
  G4double startAngle2 = 0*deg;
  G4double spanningAngle = (360-2.86)*deg;
  G4double spanningAngle2 = 360*deg;
  G4Tubs* MagnetBox = new G4Tubs("magnetBox", innerR2, innerR, height/2, startAngle2, spanningAngle2);
  G4Tubs* solidMagnet = new G4Tubs("magnet", innerR, outerR, height/2, startAngle, spanningAngle);
  G4Material* iron = nist->FindOrBuildMaterial("G4_Fe");
  G4LogicalVolume* magnetBoxLogical = new G4LogicalVolume(MagnetBox, air, "LogicalMagnetBox");
  G4LogicalVolume* magnetLogical= new G4LogicalVolume(solidMagnet, iron, "LogicalMagnet");
  G4ThreeVector magnPosition = G4ThreeVector(0,0,height/2);
  new G4PVPlacement(0, magnPosition, magnetBoxLogical, "magnetBox", worldLogical, false, 0, true);
  new G4PVPlacement(0, magnPosition, magnetLogical, "magnet", worldLogical, false, 0, true);
// Magnetic field
  G4ThreeVector magFieldValue = G4ThreeVector(0,0.9*tesla, 0); // defines the field strength; 
  G4UniformMagField* magField = new G4UniformMagField(magFieldValue); // created magnetic field
  auto localFieldManager = new G4FieldManager(magField); //G4TransportationManager::GetTransportationManager()->GetFieldManager(); // create a field manager 
  localFieldManager->SetDetectorField(magField); // and set field here
  G4Mag_UsualEqRhs* equation = new G4Mag_UsualEqRhs(magField); // create EoM
  G4ChordFinder* chordFinder = new G4ChordFinder(magField, 1.0e-2*mm, new G4ClassicalRK4(equation)); // create chord finder
  localFieldManager->SetChordFinder(chordFinder);
  magnetBoxLogical->SetFieldManager(localFieldManager, true);

Dear Laney,

Dealing first just with where the magnetic field is defined, and what value it will return if called with other locations - and whether this is correct in the Geant4 sense.

I think that there is a misunderstanding regarding what the field object will know about, and how Geant4 will use it.

The magnetic field object itself does not know its extent. This is typical, but also clearest for this case, of a uniform magnetic field. When you call the field object you created, which is a G4UniformMagField, it will never check the position - it will always return its value, as it is constant.

[ As a side note, it is possible to create a field class which checks the position and provides a value only within a restricted part of the (global) coordinate system. I believe that there is an example that demonstrates this. But it is not necessary for your case - there is nothing broken. ]

There are Geant4 classes which undertake the ‘propagation’ of curved tracks in the model geometry, by integrating the equation of motion. These classes, primarily G4PropagatorInField, are responsible for deciding at what positions to call the Magnetic Field, in order to integrate this motion. The classes which G4PropagatorInField calls (including G4ChordFinder) will evaluate the field primarily in points which are inside the volume (please recall they will be using global coordinates and requesting the field value in the same global coordinate system.)

But beyond this there is a more subtle issue of exactly where the magnetic field will evaluated (during the tracking of particles) versus the extent of the real-world volume in which it is assigned is a bit convoluted.

When travelling inside this volume (or those volumes) the Geant4 module must evaluate it at points which would fall outside that volume in order to integrate its motion all the way to the volume’s boundary.

In addition that, as the field (through a manger) is assigned to one or more logical volumes, it could be used in multiple physical volumes which are created from this logical volume. This is not relevant for your current simpler setup.

I hope that this helps you to understand this part.

Best regards,
John Apostolakis

Dear John,
thank you very much for your answer, I think I understand and I got it to work.
Kind regards,
Laney

This topic was automatically closed 7 days after the last reply. New replies are no longer allowed.