File indexing completed on 2024-06-26 07:05:01
0001 #include <cassert>
0002 #include <cmath>
0003 #include <iostream>
0004 #include <map>
0005
0006 #include <CLHEP/Vector/Boost.h>
0007 #include <CLHEP/Vector/LorentzRotation.h>
0008 #include <CLHEP/Vector/LorentzVector.h>
0009 #include <CLHEP/Vector/Rotation.h>
0010 #include <CLHEP/Vector/ThreeVector.h>
0011
0012 #include "Afterburner.hh"
0013
0014
0015 static void RotY(double theta, double xin, double yin, double zin, double *xout, double *yout, double *zout) {
0016
0017 *xout = xin*cos(theta) + zin*sin(theta);
0018 *yout = yin;
0019 *zout = zin*cos(theta) - xin*sin(theta);
0020 }
0021
0022
0023 static void RotXY(double theta, double phi, double xin, double yin, double zin, double *xout, double *yout, double *zout) {
0024
0025 *xout = xin*cos(theta) + zin*sin(theta);
0026 *yout = xin*sin(phi)*sin(theta) + yin*cos(phi) - zin*sin(phi)*cos(theta);
0027 *zout = yin*sin(phi) - xin*cos(phi)*sin(theta) + zin*cos(phi)*cos(theta);
0028 }
0029
0030
0031 ab::Afterburner::Afterburner() : _smear(1) {}
0032
0033 CLHEP::HepLorentzVector ab::Afterburner::move_vertex(const CLHEP::HepLorentzVector &init_vtx) {
0034
0035 double x = init_vtx.x() + _smear.smear(_cfg.vertex_shift_x, _cfg.vertex_smear_width_x, _cfg.vertex_smear_func);
0036 double y = init_vtx.y() + _smear.smear(_cfg.vertex_shift_y, _cfg.vertex_smear_width_y, _cfg.vertex_smear_func);
0037 double z = init_vtx.z() + _smear.smear(_cfg.vertex_shift_z, _cfg.vertex_smear_width_z, _cfg.vertex_smear_func);
0038 double t = init_vtx.t() + _smear.smear(_cfg.vertex_shift_t, _cfg.vertex_smear_width_t, _cfg.vertex_smear_func);
0039 return CLHEP::HepLorentzVector {x, y, z, t};
0040 }
0041
0042
0043
0044
0045 double ab::Afterburner::get_collision_width(const double widthA, const double widthB)
0046 {
0047 return widthA * widthB / sqrt(widthA * widthA + widthB * widthB);
0048 }
0049
0050
0051
0052
0053
0054 ab::BunchInteractionResult ab::Afterburner::generate_vertx_with_bunch_interaction()
0055 {
0056 using namespace std;
0057
0058
0059 double hadron_z = _smear.gauss(_cfg.hadron_beam.rms_bunch_length);
0060 double lepton_z = _smear.gauss(_cfg.lepton_beam.rms_bunch_length);
0061 double crossing_angle = _cfg.crossing_angle_hor;
0062
0063 double had_bunch_rms_hor = sqrt(_cfg.hadron_beam.beta_star_hor * _cfg.hadron_beam.rms_emittance_hor);
0064 double had_bunch_rms_ver = sqrt(_cfg.hadron_beam.beta_star_ver * _cfg.hadron_beam.rms_emittance_ver);
0065 double lep_bunch_rms_hor = sqrt(_cfg.lepton_beam.beta_star_hor * _cfg.lepton_beam.rms_emittance_hor);
0066 double lep_bunch_rms_ver = sqrt(_cfg.lepton_beam.beta_star_ver * _cfg.lepton_beam.rms_emittance_ver);
0067 double sigma_hor = get_collision_width(had_bunch_rms_hor, lep_bunch_rms_hor);
0068 double sigma_ver = get_collision_width(had_bunch_rms_ver, lep_bunch_rms_ver);
0069
0070
0071
0072
0073
0074
0075
0076
0077
0078
0079
0080 double c_c = cos(crossing_angle/2.0);
0081 double s_c = sin(crossing_angle/2.0);
0082 double t_c = tan(crossing_angle/2.0);
0083
0084 double t_int = (lepton_z - hadron_z)/(2.0*c_c);
0085 double z_int = (lepton_z + hadron_z)/2.0;
0086 double z_bunch_int = c_c*t_int;
0087 double x_int = z_bunch_int*t_c;
0088
0089
0090
0091 double y_int = 0.;
0092 if(abs(sigma_hor) > 1e-9)
0093 {
0094 x_int += _smear.gauss(sigma_hor);
0095 }
0096
0097 if(abs(sigma_ver) > 1e-9)
0098 {
0099 y_int += _smear.gauss(sigma_ver);
0100 }
0101
0102
0103
0104 double tmpVtxX, tmpVtxY, tmpVtxZ;
0105 tmpVtxX = tmpVtxY = tmpVtxZ = 0.;
0106
0107 RotY(crossing_angle/2.0,x_int,y_int,z_int,&tmpVtxX,&tmpVtxY,&tmpVtxZ);
0108
0109 CLHEP::Hep3Vector collision_center(tmpVtxX, tmpVtxY, tmpVtxZ);
0110 ab::BunchInteractionResult result;
0111 result.vertex.set(collision_center, t_int);
0112 result.bunch_one_z = hadron_z;
0113 result.bunch_two_z = lepton_z;
0114
0115
0116
0117
0118
0119
0120
0121
0122
0123
0124
0125
0126
0127
0128
0129
0130
0131
0132
0133
0134
0135
0136
0137
0138
0139
0140
0141
0142
0143
0144
0145
0146
0147
0148
0149
0150
0151
0152
0153
0154
0155
0156
0157
0158
0159
0160
0161
0162
0163
0164
0165
0166
0167
0168
0169
0170
0171
0172
0173
0174
0175
0176
0177
0178
0179
0180
0181
0182
0183
0184 return result;
0185 }
0186
0187
0188 CLHEP::Hep3Vector ab::Afterburner::spherical_to_cartesian(const double theta, const double phi) {
0189 return {sin(theta) * cos(phi),
0190 sin(theta) * sin(phi),
0191 cos(theta)};
0192 }
0193
0194
0195 CLHEP::Hep3Vector ab::Afterburner::smear_beam_divergence(const CLHEP::Hep3Vector &beam_dir, const ab::BeamConfig& beam_cfg, const double vtx_z, const double crab_hor, const double crab_ver) {
0196
0197
0198 static const CLHEP::Hep3Vector accelerator_plane(0, 1, 0);
0199
0200
0201 double horizontal_angle = vtx_z * crab_hor;
0202 horizontal_angle = _smear.smear(horizontal_angle, beam_cfg.divergence_hor, SmearFuncs::Gauss);
0203 CLHEP::HepRotation x_smear_in_accelerator_plane(accelerator_plane, horizontal_angle);
0204
0205
0206
0207
0208
0209
0210
0211
0212
0213
0214
0215
0216
0217
0218
0219
0220
0221
0222
0223
0224
0225 double vertical_angle = -vtx_z * crab_ver;
0226 vertical_angle = _smear.smear(vertical_angle, beam_cfg.divergence_ver, SmearFuncs::Gauss);
0227 auto out_accelerator_plane = accelerator_plane.cross(beam_dir);
0228 CLHEP::HepRotation y_smear_out_accelerator_plane(out_accelerator_plane, vertical_angle);
0229
0230
0231 return y_smear_out_accelerator_plane * x_smear_in_accelerator_plane * beam_dir;
0232 }
0233
0234
0235 ab::AfterburnerEventResult ab::Afterburner::process_event() {
0236 return process_event(CLHEP::HepLorentzVector(0,0,0,0));
0237 }
0238
0239
0240 ab::AfterburnerEventResult ab::Afterburner::process_event(const CLHEP::HepLorentzVector &init_vtx) {
0241 using namespace std;
0242
0243 if (m_verbosity) {
0244 print();
0245 }
0246
0247 AfterburnerEventResult result;
0248
0249
0250
0251 double bunch_one_z;
0252 double bunch_two_z;
0253 if (_cfg.use_beam_bunch_sim)
0254 {
0255
0256 auto bunch_interaction = generate_vertx_with_bunch_interaction();
0257 result.vertex = bunch_interaction.vertex;
0258 bunch_one_z = bunch_interaction.bunch_one_z;
0259 bunch_two_z = bunch_interaction.bunch_two_z;
0260 }
0261 else
0262 {
0263
0264
0265
0266 result.vertex = move_vertex(init_vtx);
0267 bunch_one_z = bunch_two_z = result.vertex.z();
0268 }
0269
0270
0271 const static CLHEP::Hep3Vector z_axis(0, 0, 1);
0272 const static CLHEP::Hep3Vector y_axis(0, 1, 0);
0273
0274
0275
0276 CLHEP::Hep3Vector ideal_lepton_dir(0, 0, -1);
0277 CLHEP::Hep3Vector ideal_hadron_dir = CLHEP::Hep3Vector(z_axis).rotateY(_cfg.crossing_angle_hor).rotateX(_cfg.crossing_angle_ver);
0278
0279
0280
0281 if (m_verbosity) {
0282 cout << __PRETTY_FUNCTION__ << ": " << endl;
0283 cout << "ideal_hadron_dir = " << ideal_hadron_dir << endl;
0284 cout << "ideal_lepton_dir = " << ideal_lepton_dir << endl;
0285 cout << "crossing_angle_hor = " << _cfg.crossing_angle_hor << endl;
0286 cout << "crossing_angle_ver = " << _cfg.crossing_angle_ver << endl;
0287 }
0288
0289 assert(fabs(ideal_hadron_dir.mag2() - 1) < CLHEP::Hep3Vector::getTolerance());
0290 assert(fabs(ideal_lepton_dir.mag2() - 1) < CLHEP::Hep3Vector::getTolerance());
0291
0292 if (ideal_hadron_dir.dot(ideal_lepton_dir) > -0.5) {
0293 cout << "PHHepMCGenHelper::process_event - WARNING -"
0294 << "Beam A and Beam B are not near back to back. "
0295 << "Please double check beam direction setting at set_beam_direction_theta_phi()."
0296 << "beamA_center = " << ideal_hadron_dir << ","
0297 << "beamB_center = " << ideal_lepton_dir << ","
0298 << " Current setting:";
0299
0300 print();
0301 }
0302
0303
0304 double hadron_crab_hor = _cfg.crossing_angle_hor / 2.0 / sqrt(_cfg.hadron_beam.beta_crab_hor * _cfg.hadron_beam.beta_star_hor);
0305 double hadron_crab_ver = 0;
0306
0307 double lepton_crab_hor = _cfg.crossing_angle_hor / 2.0 / sqrt(_cfg.lepton_beam.beta_crab_hor * _cfg.lepton_beam.beta_star_hor);
0308 double lepton_crab_ver = 0;
0309
0310 CLHEP::Hep3Vector real_hadron_dir = smear_beam_divergence(ideal_hadron_dir, _cfg.hadron_beam, bunch_one_z, hadron_crab_hor, hadron_crab_ver);
0311 CLHEP::Hep3Vector real_lepton_dir = smear_beam_divergence(ideal_lepton_dir, _cfg.lepton_beam, bunch_two_z, lepton_crab_hor, lepton_crab_ver);
0312
0313 if (m_verbosity) {
0314 cout << __PRETTY_FUNCTION__ << ": " << endl;
0315 cout << "beamA_vec = " << real_hadron_dir << endl;
0316 cout << "beamB_vec = " << real_lepton_dir << endl;
0317 }
0318
0319 assert(fabs(real_hadron_dir.mag2() - 1) < CLHEP::Hep3Vector::getTolerance());
0320 assert(fabs(real_lepton_dir.mag2() - 1) < CLHEP::Hep3Vector::getTolerance());
0321
0322
0323 CLHEP::Hep3Vector boost_axis = real_hadron_dir + real_lepton_dir;
0324 if (boost_axis.mag2() > CLHEP::Hep3Vector::getTolerance()) {
0325
0326
0327
0328 result.boost = CLHEP::HepBoost(0.5 * boost_axis);
0329
0330 if (m_verbosity) {
0331 cout << __PRETTY_FUNCTION__ << ": non-zero boost " << endl;
0332 }
0333 }
0334 else {
0335 result.boost = CLHEP::HepBoost(CLHEP::Hep3Vector(0, 0, 0));
0336 if (m_verbosity) {
0337 cout << __PRETTY_FUNCTION__ << ": zero boost " << endl;
0338 }
0339 }
0340
0341
0342 CLHEP::Hep3Vector beamDiffAxis = (real_hadron_dir - real_lepton_dir);
0343 if (beamDiffAxis.mag2() < CLHEP::Hep3Vector::getTolerance()) {
0344 cout << "PHHepMCGenHelper::process_event - Fatal error -"
0345 << "Beam A and Beam B are too close to each other in direction "
0346 << "Please double check beam direction and divergence setting. "
0347 << "real_hadron_dir = " << real_hadron_dir << ","
0348 << "real_lepton_dir = " << real_lepton_dir << ","
0349 << " Current setting:";
0350
0351 print();
0352
0353 throw std::runtime_error("Beam A and Beam B are too close to each other in direction ");
0354 }
0355
0356 beamDiffAxis = beamDiffAxis / beamDiffAxis.mag();
0357 double cos_rotation_angle_to_z = beamDiffAxis.dot(z_axis);
0358 if (m_verbosity) {
0359 cout << __PRETTY_FUNCTION__ << ": check rotation ";
0360 cout << "cos_rotation_angle_to_z= " << cos_rotation_angle_to_z << endl;
0361 }
0362
0363 if (1 - cos_rotation_angle_to_z < CLHEP::Hep3Vector::getTolerance()) {
0364
0365
0366 result.rotation = CLHEP::HepRotation(z_axis, 0);
0367
0368 if (m_verbosity) {
0369 cout << __PRETTY_FUNCTION__ << ": no rotation " << endl;
0370 }
0371 } else if (cos_rotation_angle_to_z + 1 < CLHEP::Hep3Vector::getTolerance()) {
0372
0373 result.rotation = CLHEP::HepRotation(CLHEP::Hep3Vector(0, 1, 0), M_PI);
0374 if (m_verbosity) {
0375 cout << __PRETTY_FUNCTION__ << ": reverse beam direction " << endl;
0376 }
0377 } else {
0378
0379 CLHEP::Hep3Vector rotation_axis = (real_hadron_dir - real_lepton_dir).cross(z_axis);
0380 const double rotation_angle_to_z = acos(cos_rotation_angle_to_z);
0381
0382 result.rotation = CLHEP::HepRotation(rotation_axis, rotation_angle_to_z);
0383
0384 if (m_verbosity) {
0385 cout << __PRETTY_FUNCTION__ << ": has rotation " << endl;
0386 }
0387 }
0388
0389
0390
0391
0392 CLHEP::Hep3Vector beamCenterDiffAxis = (ideal_hadron_dir - ideal_lepton_dir);
0393 beamCenterDiffAxis = beamCenterDiffAxis / beamCenterDiffAxis.mag();
0394
0395 double cos_rotation_center_angle_to_z = beamCenterDiffAxis.dot(z_axis);
0396
0397 if (1 - fabs(cos_rotation_center_angle_to_z) < CLHEP::Hep3Vector::getTolerance()) {
0398
0399
0400 if (m_verbosity) {
0401 cout << __PRETTY_FUNCTION__
0402 << ": collision longitudinal axis is very close to z-axis. No additional rotation of vertexes: "
0403 << "cos_rotation_center_angle_to_z = " << cos_rotation_center_angle_to_z
0404 << endl;
0405 }
0406 } else {
0407
0408 CLHEP::Hep3Vector rotation_axis = beamCenterDiffAxis.cross(z_axis);
0409 const double rotation_angle_to_z = -acos(cos_rotation_center_angle_to_z);
0410 const CLHEP::HepRotation rotation(rotation_axis, rotation_angle_to_z);
0411
0412
0413 CLHEP::Hep3Vector init_3vertex(
0414 result.vertex.x(),
0415 result.vertex.y(),
0416 result.vertex.z());
0417
0418 CLHEP::Hep3Vector final_3vertex = init_3vertex;
0419
0420 result.vertex = CLHEP::HepLorentzVector(
0421 final_3vertex.x(),
0422 final_3vertex.y(),
0423 final_3vertex.z(),
0424 result.vertex.t());
0425
0426 if (m_verbosity) {
0427 cout << __PRETTY_FUNCTION__
0428 << ": collision longitudinal axis is rotated: "
0429 << "cos_rotation_center_angle_to_z = " << cos_rotation_center_angle_to_z << ", "
0430 << "rotation_axis = " << rotation_axis << ", "
0431 << "init_3vertex = " << init_3vertex << ", "
0432 << "final_3vertex = " << final_3vertex << ", "
0433 << endl;
0434 }
0435 }
0436
0437
0438 if (m_verbosity) {
0439 cout << __PRETTY_FUNCTION__ << ": final boost rotation shift of the collision" << endl;
0440 }
0441 return result;
0442 }
0443
0444
0445
0446
0447 void ab::Afterburner::print() const {
0448 using namespace std;
0449
0450 cout << "AFTERBURNER CONFIGURATION\n";
0451 cout << "=========================\n";
0452
0453 cout << "Crossing angle hor: " << _cfg.crossing_angle_hor << endl;
0454 cout << "Crossing angle ver: " << _cfg.crossing_angle_ver << endl;
0455
0456 cout << "Vertex distribution width"
0457 " x: " << _cfg.vertex_smear_width_x
0458 << ", y: " << _cfg.vertex_smear_width_y
0459 << ", z: " << _cfg.vertex_smear_width_z
0460 << ", t: " << _cfg.vertex_smear_width_t
0461 << endl;
0462
0463 cout << "Vertex distribution function: " << smear_func_to_str(_cfg.vertex_smear_func) << endl;
0464 cout << "Vertex simulation is: " << (_cfg.use_beam_bunch_sim ? string("on") : std::string("off")) << endl;
0465 cout << "Hadron beam:\n";
0466 cout << " rms emittance : hor = " << _cfg.hadron_beam.rms_emittance_hor << ", ver = " << _cfg.hadron_beam.rms_emittance_ver << endl;
0467 cout << " beta star : hor = " << _cfg.hadron_beam.beta_star_hor << ", ver = " << _cfg.hadron_beam.beta_star_ver << endl;
0468 cout << " beta crab : hor = " << _cfg.hadron_beam.beta_crab_hor << endl;
0469 cout << " rms bunch length: " << _cfg.hadron_beam.rms_bunch_length << endl;
0470
0471 cout << "Lepton beam:\n";
0472 cout << " rms emittance : hor = " << _cfg.lepton_beam.rms_emittance_hor << ", ver = " << _cfg.lepton_beam.rms_emittance_ver << endl;
0473 cout << " beta star : hor = " << _cfg.lepton_beam.beta_star_hor << ", ver = " << _cfg.lepton_beam.beta_star_ver << endl;
0474 cout << " beta crab : hor = " << _cfg.lepton_beam.beta_crab_hor << endl;
0475 cout << " rms bunch length: " << _cfg.lepton_beam.rms_bunch_length << endl;
0476
0477 cout << "=========================\n";
0478 }
0479