EIC Software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
G4JLeicBeamLineMagnetDetector.cc
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file G4JLeicBeamLineMagnetDetector.cc
3 
4 #include <phparameter/PHParameters.h>
5 
6 #include <g4main/PHG4Detector.h> // for PHG4Detector
7 #include <g4main/PHG4DisplayAction.h> // for PHG4DisplayAction
8 #include <g4main/PHG4Subsystem.h>
9 #include <g4main/PHG4Utils.h>
10 
11 #include <phool/phool.h>
12 
13 #include <Geant4/G4ChordFinder.hh>
14 #include <Geant4/G4ClassicalRK4.hh>
15 #include <Geant4/G4FieldManager.hh>
16 #include <Geant4/G4LogicalVolume.hh>
17 #include <Geant4/G4Mag_UsualEqRhs.hh>
18 #include <Geant4/G4MagneticField.hh>
19 #include <Geant4/G4Material.hh>
20 #include <Geant4/G4PVPlacement.hh>
21 #include <Geant4/G4PhysicalConstants.hh>
22 #include <Geant4/G4QuadrupoleMagField.hh>
23 #include <Geant4/G4RotationMatrix.hh>
24 #include <Geant4/G4String.hh> // for G4String
25 #include <Geant4/G4SystemOfUnits.hh>
26 #include <Geant4/G4ThreeVector.hh> // for G4ThreeVector
27 #include <Geant4/G4Transform3D.hh> // for G4Transform3D
28 #include <Geant4/G4Tubs.hh>
29 #include <Geant4/G4Types.hh> // for G4double, G4bool
30 #include <Geant4/G4UniformMagField.hh>
31 #include <Geant4/G4VisAttributes.hh>
32 
33 #include <CLHEP/Units/SystemOfUnits.h> // for cm, deg, tesla, twopi, meter
34 
35 #include <cstdlib> // for exit
36 #include <iostream> // for operator<<, basic_ostream
37 
38 class G4VSolid;
39 class PHCompositeNode;
40 class PHG4Subsystem;
41 
42 using namespace std;
43 
44 //_______________________________________________________________
46  : PHG4Detector(subsys, Node, dnam)
47  , params(parameters)
48  , magnet_physi(nullptr)
49  , magnet_iron_physi(nullptr)
50  , m_DisplayAction(dynamic_cast<G4JLeicBeamLineMagnetDisplayAction *>(subsys->GetDisplayAction()))
51  , layer(lyr)
52 {
53 }
54 
55 //_______________________________________________________________
56 int G4JLeicBeamLineMagnetDetector::IsInBeamLineMagnet(const G4VPhysicalVolume *volume) const
57 {
58  if (volume == magnet_physi)
59  {
60  return 1;
61  }
62  else if (volume == magnet_iron_physi)
63  {
64  return -1;
65  }
66  return false;
67 }
68 
69 //_______________________________________________________________
70 void G4JLeicBeamLineMagnetDetector::ConstructMe(G4LogicalVolume *logicMother)
71 {
72  /* Define origin vector (center of magnet) */
73  G4ThreeVector origin(params->get_double_param("place_x") * cm,
74  params->get_double_param("place_y") * cm,
75  params->get_double_param("place_z") * cm);
76 
77  /* Define magnet rotation matrix */
78  G4RotationMatrix *rotm = new G4RotationMatrix();
79  rotm->rotateX(params->get_double_param("rot_x") * deg);
80  rotm->rotateY(params->get_double_param("rot_y") * deg);
81  rotm->rotateZ(params->get_double_param("rot_z") * deg);
82 
83  /* Creating a magnetic field */
84  G4MagneticField *magField = nullptr;
85 
86  string magnettype = params->get_string_param("magtype");
87  if (magnettype == "DIPOLE")
88  {
89  G4ThreeVector field(params->get_double_param("field_x") * tesla,
90  params->get_double_param("field_y") * tesla,
91  params->get_double_param("field_z") * tesla);
92  // magnets can be rotated in y
93  field.rotateY(params->get_double_param("rot_y") * deg);
94  magField = new G4UniformMagField(field);
95  if (Verbosity() > 0)
96  {
97  cout << "Creating DIPOLE with field x: " << field.x() / tesla
98  << ", y: " << field.y() / tesla
99  << ", z: " << field.z() / tesla
100  << " and name " << GetName() << endl;
101  }
102  }
103  else if (magnettype == "QUADRUPOLE")
104  {
105  G4double fieldGradient = params->get_double_param("fieldgradient") * tesla / meter;
106 
107  /* G4MagneticField::GetFieldValue( pos*, B* ) uses GLOBAL coordinates, not local.
108  * Therefore, place magnetic field center at the correct location and angle for the
109  * magnet AND do the same transformations for the logical volume (see below). */
110  magField = new G4QuadrupoleMagField(fieldGradient, origin, rotm);
111 
112  if (Verbosity() > 0)
113  {
114  cout << "Creating QUADRUPOLE with gradient " << fieldGradient << " and name " << GetName() << endl;
115  cout << "at x, y, z = " << origin.x() << " , " << origin.y() << " , " << origin.z() << endl;
116  cout << "with rotation around x, y, z axis by: " << rotm->phiX() << ", " << rotm->phiY() << ", " << rotm->phiZ() << endl;
117  }
118  }
119 
120  if (!magField && Verbosity() > 0)
121  {
122  cout << PHWHERE << " No magnetic field specified for " << GetName()
123  << " of type " << magnettype << endl;
124  }
125 
126  /* Add volume with solid magnet material */
127  G4VSolid *magnet_iron_solid = new G4Tubs(G4String(GetName().append("_Solid").c_str()),
128  0,
129  params->get_double_param("outer_radius") * cm,
130  params->get_double_param("length") * cm / 2., 0, twopi);
131  G4LogicalVolume *magnet_iron_logic = new G4LogicalVolume(magnet_iron_solid,
132  G4Material::GetMaterial("G4_Fe"),
133  G4String(GetName().c_str()),
134  0, 0, 0);
135  m_DisplayAction->AddVolume(magnet_iron_logic, magnettype);
136  magnet_iron_physi = new G4PVPlacement(G4Transform3D(*rotm, origin),
137  magnet_iron_logic,
138  G4String(GetName().append("_Solid").c_str()),
139  logicMother, 0, false, OverlapCheck());
140 
141  G4VSolid *magnet_solid = new G4Tubs(G4String(GetName().c_str()),
142  0,
143  params->get_double_param("inner_radius") * cm,
144  params->get_double_param("length") * cm / 2., 0, twopi);
145 
146  G4LogicalVolume *magnet_logic = new G4LogicalVolume(magnet_solid,
147  G4Material::GetMaterial("G4_Galactic"),
148  G4String(GetName().c_str()),
149  0, 0, 0);
150 
151  /* Set field manager for logical volume */
152  if (magField)
153  {
154  /* Set up Geant4 field manager */
155  G4Mag_UsualEqRhs *localEquation = new G4Mag_UsualEqRhs(magField);
156  G4ClassicalRK4 *localStepper = new G4ClassicalRK4(localEquation);
157  G4double minStep = 0.25 * mm; // minimal step, 1 mm is default
158  G4ChordFinder *localChordFinder = new G4ChordFinder(magField, minStep, localStepper);
159 
160  G4FieldManager *fieldMgr = new G4FieldManager();
161  fieldMgr->SetDetectorField(magField);
162  fieldMgr->SetChordFinder(localChordFinder);
163  magnet_logic->SetFieldManager(fieldMgr, true);
164  }
165  m_DisplayAction->AddVolume(magnet_logic, "FIELDVOLUME");
166 
167  /* create magnet physical volume */
168 
169  magnet_physi = new G4PVPlacement(nullptr, G4ThreeVector(0, 0, 0),
170  magnet_logic,
171  G4String(GetName().c_str()),
172  magnet_iron_logic, 0, false, OverlapCheck());
173 }