File indexing completed on 2025-12-17 09:24:00
0001 #ifndef MACRO_G4BEAMLINE_C
0002 #define MACRO_G4BEAMLINE_C
0003
0004 #include <GlobalVariables.C>
0005
0006 #include <G4_Pipe.C>
0007
0008 #include <g4detectors/BeamLineMagnetSubsystem.h>
0009 #include <g4detectors/PHG4BlockSubsystem.h>
0010 #include <g4detectors/PHG4ConeSubsystem.h>
0011 #include <g4detectors/PHG4CylinderSubsystem.h>
0012 #include <g4detectors/PHG4DetectorSubsystem.h>
0013 #include <g4detectors/PHG4ZDCSubsystem.h>
0014
0015 #include <g4main/PHG4Reco.h>
0016
0017 #include <Rtypes.h> // resolves R__LOAD_LIBRARY for clang-tidy
0018
0019 #include <algorithm>
0020 #include <fstream>
0021 #include <set>
0022
0023 R__LOAD_LIBRARY(libg4detectors.so)
0024
0025 float PosFlip(float pos);
0026 float AngleFlip(float angle);
0027 float MagFieldFlip(float Bfield);
0028
0029
0030 namespace Enable
0031 {
0032 bool BEAMLINE = false;
0033 bool BEAMLINE_ABSORBER = false;
0034 bool BEAMLINE_BLACKHOLE = false;
0035 bool BEAMLINE_OVERLAPCHECK = false;
0036 int BEAMLINE_VERBOSITY = 0;
0037
0038 }
0039
0040 namespace G4BEAMLINE
0041 {
0042
0043
0044 double starting_z{0};
0045 double enclosure_z_max{0};
0046 double enclosure_r_max = 30.;
0047 double enclosure_center{0};
0048 double skin_thickness = 0.;
0049 int pipe_id_offset = 100;
0050 int roman_pot_pipe_id_offset = 200;
0051 PHG4CylinderSubsystem *ForwardBeamLineEnclosure(nullptr);
0052 PHG4CylinderSubsystem *BackwardBeamLineEnclosure(nullptr);
0053
0054 }
0055
0056 void BeamLineInit()
0057 {
0058 int verbosity = std::max(Enable::VERBOSITY, Enable::BEAMLINE_VERBOSITY);
0059
0060
0061
0062
0063
0064 G4BEAMLINE::starting_z = std::max(std::abs(G4PIPE::max_z_north), std::abs(G4PIPE::max_z_south));
0065 if (Enable::MVTX_APPLYMISALIGNMENT && !Enable::PIPE)
0066 {
0067 if (verbosity > 0)
0068 {
0069 std::cout << "G4BEAMLINE: pipe misaligned but pipe disabled - applying zshift" << std::endl;
0070 }
0071 G4BEAMLINE::starting_z += G4PIPE::pipe_zshift_2024;
0072 }
0073 G4BEAMLINE::enclosure_z_max = 2050. + (800 - G4BEAMLINE::starting_z);
0074 G4BEAMLINE::enclosure_center = 0.5 * (G4BEAMLINE::starting_z + G4BEAMLINE::enclosure_z_max);
0075
0076 BlackHoleGeometry::min_z = std::min(BlackHoleGeometry::min_z, -G4BEAMLINE::enclosure_z_max);
0077 BlackHoleGeometry::max_z = std::max(BlackHoleGeometry::max_z, G4BEAMLINE::enclosure_z_max);
0078 BlackHoleGeometry::max_radius = std::max(BlackHoleGeometry::max_radius, G4BEAMLINE::enclosure_r_max);
0079 }
0080
0081 void BeamLineDefineMagnets(PHG4Reco *g4Reco)
0082 {
0083 bool overlapCheck = Enable::OVERLAPCHECK || Enable::BEAMLINE_OVERLAPCHECK;
0084 bool AbsorberActive = Enable::ABSORBER || Enable::BEAMLINE_ABSORBER;
0085 int verbosity = std::max(Enable::VERBOSITY, Enable::BEAMLINE_VERBOSITY);
0086
0087 G4BEAMLINE::ForwardBeamLineEnclosure = new PHG4CylinderSubsystem("ForwardBeamLineEnclosure");
0088 G4BEAMLINE::ForwardBeamLineEnclosure->set_double_param("place_z", G4BEAMLINE::enclosure_center);
0089 G4BEAMLINE::ForwardBeamLineEnclosure->set_double_param("radius", 0);
0090 G4BEAMLINE::ForwardBeamLineEnclosure->set_double_param("thickness", G4BEAMLINE::enclosure_r_max);
0091 G4BEAMLINE::ForwardBeamLineEnclosure->set_double_param("length", G4BEAMLINE::enclosure_z_max - G4BEAMLINE::starting_z);
0092 G4BEAMLINE::ForwardBeamLineEnclosure->set_string_param("material", "G4_Galactic");
0093 G4BEAMLINE::ForwardBeamLineEnclosure->set_color(.5, .5, .5, 0.2);
0094 G4BEAMLINE::ForwardBeamLineEnclosure->OverlapCheck(overlapCheck);
0095 if (verbosity)
0096 {
0097 G4BEAMLINE::ForwardBeamLineEnclosure->Verbosity(verbosity);
0098 }
0099 g4Reco->registerSubsystem(G4BEAMLINE::ForwardBeamLineEnclosure);
0100
0101 G4BEAMLINE::BackwardBeamLineEnclosure = new PHG4CylinderSubsystem("BackwardBeamLineEnclosure");
0102 G4BEAMLINE::BackwardBeamLineEnclosure->set_double_param("place_z", -G4BEAMLINE::enclosure_center);
0103 G4BEAMLINE::BackwardBeamLineEnclosure->set_double_param("radius", 0);
0104 G4BEAMLINE::BackwardBeamLineEnclosure->set_double_param("thickness", G4BEAMLINE::enclosure_r_max);
0105 G4BEAMLINE::BackwardBeamLineEnclosure->set_double_param("length", G4BEAMLINE::enclosure_z_max - G4BEAMLINE::starting_z);
0106 G4BEAMLINE::BackwardBeamLineEnclosure->set_string_param("material", "G4_Galactic");
0107 G4BEAMLINE::BackwardBeamLineEnclosure->set_color(.5, .5, .5, 0.2);
0108 G4BEAMLINE::BackwardBeamLineEnclosure->OverlapCheck(overlapCheck);
0109 if (verbosity)
0110 {
0111 G4BEAMLINE::BackwardBeamLineEnclosure->Verbosity(verbosity);
0112 }
0113 g4Reco->registerSubsystem(G4BEAMLINE::BackwardBeamLineEnclosure);
0114
0115 std::string magFile = std::string(getenv("CALIBRATIONROOT")) + "/Beam/D0DXMagnets.dat";
0116
0117
0118 std::set<int> magnetlist;
0119
0120
0121 BeamLineMagnetSubsystem *bl = nullptr;
0122 std::ifstream infile(magFile);
0123 if (infile.is_open())
0124 {
0125 double biggest_z = 0.;
0126 int imagnet = 0;
0127 std::string line;
0128 while (std::getline(infile, line))
0129 {
0130 if (!line.compare(0, 1, "B") ||
0131 !line.compare(0, 1, "Q") ||
0132 !line.compare(0, 1, "S"))
0133 {
0134 std::istringstream iss(line);
0135 std::string magname;
0136 double x;
0137 double y;
0138 double z;
0139 double inner_radius_zin;
0140 double inner_radius_zout;
0141 double outer_magnet_diameter;
0142 double length;
0143 double angle;
0144 double dipole_field_x;
0145 double fieldgradient;
0146 if (!(iss >> magname >> x >> y >> z >> inner_radius_zin >> inner_radius_zout >> outer_magnet_diameter >> length >> angle >> dipole_field_x >> fieldgradient))
0147 {
0148 std::cout << "could not decode " << line << std::endl;
0149 gSystem->Exit(1);
0150 }
0151 else
0152 {
0153
0154
0155 std::string magtype;
0156 if (inner_radius_zin != inner_radius_zout)
0157 {
0158 std::cout << "inner radius at front of magnet " << inner_radius_zin
0159 << " not equal radius at back of magnet " << inner_radius_zout
0160 << " needs change in code (replace tube by cone for beamline)" << std::endl;
0161 gSystem->Exit(1);
0162 }
0163 if (verbosity > 0)
0164 {
0165 std::cout << std::endl
0166 << std::endl
0167 << "\tID number " << imagnet << std::endl;
0168 std::cout << "magname: " << magname << std::endl;
0169 std::cout << "x: " << x << std::endl;
0170 std::cout << "y: " << y << std::endl;
0171 std::cout << "z: " << z << std::endl;
0172 std::cout << "inner_radius_zin: " << inner_radius_zin << std::endl;
0173 std::cout << "inner_radius_zout: " << inner_radius_zout << std::endl;
0174 std::cout << "outer_magnet_diameter: " << outer_magnet_diameter << std::endl;
0175 std::cout << "length: " << length << std::endl;
0176 std::cout << "angle: " << angle << std::endl;
0177 std::cout << "dipole_field_x: " << dipole_field_x << std::endl;
0178 std::cout << "fieldgradient: " << fieldgradient << std::endl;
0179 }
0180 if (!magname.compare(0, 1, "B"))
0181 {
0182 magtype = "DIPOLE";
0183 }
0184 else if (!magname.compare(0, 1, "Q"))
0185 {
0186 magtype = "QUADRUPOLE";
0187 }
0188 else if (!magname.compare(0, 1, "S"))
0189 {
0190 magtype = "SEXTUPOLE";
0191 }
0192 else
0193 {
0194 std::cout << "cannot decode magnet name " << magname << std::endl;
0195 gSystem->Exit(1);
0196 }
0197
0198 x *= 100.;
0199 y *= 100.;
0200 z *= 100.;
0201 length *= 100.;
0202 inner_radius_zin *= 100.;
0203 outer_magnet_diameter *= 100.;
0204 angle = (angle / M_PI * 180.) / 1000.;
0205
0206
0207
0208 if (magnetlist.empty() || magnetlist.contains(imagnet))
0209 {
0210 bl = new BeamLineMagnetSubsystem("BEAMLINEMAGNET", imagnet);
0211 bl->set_double_param("field_y", MagFieldFlip(dipole_field_x));
0212 bl->set_double_param("fieldgradient", MagFieldFlip(fieldgradient));
0213 bl->set_string_param("magtype", magtype);
0214 bl->set_double_param("length", length);
0215 bl->set_double_param("place_x", PosFlip(x));
0216 bl->set_double_param("place_y", y);
0217 if (z > 0)
0218 {
0219 bl->set_double_param("place_z", z - G4BEAMLINE::enclosure_center);
0220 }
0221 else
0222 {
0223 bl->set_double_param("place_z", z + G4BEAMLINE::enclosure_center);
0224 }
0225 bl->set_double_param("field_global_position_x", PosFlip(x));
0226 bl->set_double_param("field_global_position_y", y);
0227 bl->set_double_param("field_global_position_z", z);
0228 bl->set_double_param("rot_y", AngleFlip(angle));
0229 bl->set_double_param("field_global_rot_y", AngleFlip(angle));
0230 bl->set_double_param("inner_radius", inner_radius_zin);
0231 bl->set_double_param("outer_radius", outer_magnet_diameter / 2.);
0232 bl->set_double_param("skin_thickness", G4BEAMLINE::skin_thickness);
0233 bl->SetActive(AbsorberActive);
0234 bl->SetAbsorberActive(AbsorberActive);
0235 if (Enable::BEAMLINE_BLACKHOLE) bl->BlackHole();
0236 if (z > 0)
0237 {
0238 bl->SetMotherSubsystem(G4BEAMLINE::ForwardBeamLineEnclosure);
0239 }
0240 else
0241 {
0242 bl->SetMotherSubsystem(G4BEAMLINE::BackwardBeamLineEnclosure);
0243 }
0244 bl->OverlapCheck(overlapCheck);
0245 bl->SuperDetector("BEAMLINEMAGNET");
0246 bl->Verbosity(verbosity);
0247 g4Reco->registerSubsystem(bl);
0248 }
0249 imagnet++;
0250 biggest_z = std::max(std::abs(z) + length, biggest_z);
0251 }
0252 }
0253 }
0254 infile.close();
0255 }
0256 }
0257
0258 void BeamLineDefineBeamPipe(PHG4Reco *g4Reco)
0259 {
0260 bool OverlapCheck = Enable::OVERLAPCHECK || Enable::BEAMLINE_OVERLAPCHECK;
0261 bool AbsorberActive = Enable::ABSORBER || Enable::BEAMLINE_ABSORBER;
0262 int verbosity = std::max(Enable::VERBOSITY, Enable::BEAMLINE_VERBOSITY);
0263
0264 const int ntube = 10;
0265 const std::string nm[ntube] = {"B00", "B01", "B10", "B11", "B20", "B21", "B30", "B31", "B32", "B33"};
0266 const double qlen[ntube] = {233.8, 233.8, 118.7, 118.7, 217.16, 217.16, 182.5, 182.5, 182.5, 182.5};
0267 const double qir[ntube] = {6.08, 6.08, 14.60, 14.60, 20.0, 20.0, 6.07, 6.07, 6.07, 6.07};
0268 const double qor[ntube] = {6.35, 6.35, 15.24, 15.24, 20.96, 20.96, 6.35, 6.35, 6.35, 6.35};
0269 const double qrot[ntube] = {0, 0, 0, 0, 0, 0, 1.074, -1.074, -1.074, 1.074};
0270 const double qxC[ntube] = {0, 0, 0, 0, 0, 0, 12.820, -12.820, 12.820, -12.820};
0271 const double qyC[ntube] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
0272 const double qzC[ntube] = {863.1, -863.1, 1474.470, -1474.470, 1642.4, -1642.4, 1843.2, 1843.2, -1843.2, -1843.2};
0273 for (int i = 0; i < ntube; i++)
0274 {
0275 std::string name = "beamPipe" + nm[i];
0276 PHG4CylinderSubsystem *pipe = new PHG4CylinderSubsystem(name, G4BEAMLINE::pipe_id_offset + i);
0277 if (Enable::BEAMLINE_BLACKHOLE) pipe->BlackHole();
0278 pipe->set_color(1, 0, 0, 1.);
0279 pipe->set_double_param("radius", qir[i]);
0280 pipe->set_double_param("thickness", qor[i] - qir[i]);
0281 pipe->set_double_param("length", qlen[i]);
0282 pipe->set_double_param("rot_y", qrot[i]);
0283 pipe->set_string_param("material", "G4_STAINLESS-STEEL");
0284 pipe->set_double_param("place_x", PosFlip(qxC[i]));
0285 pipe->set_double_param("place_y", qyC[i]);
0286 if (qzC[i] > 0)
0287 {
0288 pipe->set_double_param("place_z", qzC[i] - G4BEAMLINE::enclosure_center);
0289 }
0290 else
0291 {
0292 pipe->set_double_param("place_z", qzC[i] + G4BEAMLINE::enclosure_center);
0293 }
0294 if (AbsorberActive) pipe->SetActive();
0295 pipe->SuperDetector("PIPE");
0296 if (qzC[i] > 0)
0297 {
0298 pipe->SetMotherSubsystem(G4BEAMLINE::ForwardBeamLineEnclosure);
0299 }
0300 else
0301 {
0302 pipe->SetMotherSubsystem(G4BEAMLINE::BackwardBeamLineEnclosure);
0303 }
0304
0305 pipe->OverlapCheck(OverlapCheck);
0306 pipe->Verbosity(verbosity);
0307 g4Reco->registerSubsystem(pipe);
0308 }
0309
0310
0311 const int nSec = 2;
0312 const double len[nSec] = {20.87, 20.87};
0313 const double ir1[nSec] = {7.14, 14.60};
0314 const double or1[nSec] = {7.77, 15.24};
0315 const double ir2[nSec] = {14.60, 7.14};
0316 const double or2[nSec] = {15.24, 7.77};
0317 const double xC[nSec] = {0, 0};
0318 const double yC[nSec] = {0, 0};
0319 const double zC[nSec] = {1394.25, -1394.25};
0320 for (int i = 0; i < nSec; i++)
0321 {
0322 std::string name = "beamPipeRP" + std::to_string(i);
0323 PHG4ConeSubsystem *pipe = new PHG4ConeSubsystem(name, G4BEAMLINE::roman_pot_pipe_id_offset + i);
0324 pipe->set_string_param("material", "G4_STAINLESS-STEEL");
0325 pipe->set_double_param("place_x", PosFlip(xC[i]));
0326 pipe->set_double_param("place_y", yC[i]);
0327 if (zC[i] > 0)
0328 {
0329 pipe->set_double_param("place_z", zC[i] - G4BEAMLINE::enclosure_center);
0330 }
0331 else
0332 {
0333 pipe->set_double_param("place_z", zC[i] + G4BEAMLINE::enclosure_center);
0334 }
0335 pipe->set_double_param("length", len[i]);
0336 pipe->set_double_param("rmin1", ir1[i]);
0337 pipe->set_double_param("rmin2", ir2[i]);
0338 pipe->set_double_param("rmax1", or1[i]);
0339 pipe->set_double_param("rmax2", or2[i]);
0340 if (zC[i] > 0)
0341 {
0342 pipe->SetMotherSubsystem(G4BEAMLINE::ForwardBeamLineEnclosure);
0343 }
0344 else
0345 {
0346 pipe->SetMotherSubsystem(G4BEAMLINE::BackwardBeamLineEnclosure);
0347 }
0348 if (AbsorberActive)
0349 {
0350 pipe->SetActive();
0351 }
0352 if (Enable::BEAMLINE_BLACKHOLE)
0353 {
0354 pipe->BlackHole();
0355 }
0356 pipe->set_color(1, 0, 0, 1.);
0357 pipe->SuperDetector("PIPE");
0358 pipe->OverlapCheck(OverlapCheck);
0359 pipe->Verbosity(verbosity);
0360 g4Reco->registerSubsystem(pipe);
0361 }
0362 }
0363
0364 float PosFlip(float pos)
0365 {
0366 return pos;
0367 };
0368 float AngleFlip(float angle)
0369 {
0370 return angle;
0371 };
0372 float MagFieldFlip(float Bfield)
0373 {
0374 return Bfield;
0375 };
0376
0377 #endif