150 G4NistManager* nist = G4NistManager::Instance();
152 G4double pow_thres, ecor, b, dn, zthird, winfty, w_med_appr, wsatur, sigfac;
159 dn = 1.54 * nist->GetA27(Z);
161 zthird = 1. / nist->GetZ13(Z);
162 winfty = b * zthird *
mfcp_ / (dn * electron_mass_c2);
163 w_med_appr = 1. / (4. * dn * SQRTE *
mfcp_);
164 wsatur = winfty / w_med_appr;
165 sigfac = 4. * fine_structure_const * Z * Z *
rc_ *
rc_;
166 pow_thres = 1.479 + 0.00799 * dn;
167 ecor = -18. + 4347. / (b * zthird);
169 G4double cor_fuc = 1. + .04 * G4Log(1. + ecor / Egam);
170 G4double eg = G4Exp(G4Log(1. - 4. *
mfcp_ / Egam) * pow_thres) *
171 G4Exp(G4Log(G4Exp(G4Log(wsatur) * POW_SAT) +
172 G4Exp(G4Log(Egam) * POW_SAT)) /
175 G4double cross_section =
176 7. / 9. * sigfac * G4Log(1. + w_med_appr * cor_fuc * eg);
178 return cross_section;
189 const G4Step& aStep) {
190 ldmx_log(debug) <<
"A' -> fcp+ fcp- conversion starting!";
191 aParticleChange.Initialize(aTrack);
192 const G4Material* a_material = aTrack.GetMaterial();
194 ldmx_log(debug) <<
"Conversion in material: " << a_material->GetName();
195 ldmx_log(debug) <<
"A' Track ID: " << aTrack.GetTrackID()
196 <<
", Parent ID: " << aTrack.GetParentID();
199 const G4DynamicParticle* a_dynamic_a_prime = aTrack.GetDynamicParticle();
200 G4double egam = a_dynamic_a_prime->GetKineticEnergy();
202 G4ThreeVector pos = aTrack.GetPosition();
203 ldmx_log(debug) <<
"A' kinetic energy: " << egam / CLHEP::MeV <<
" MeV";
204 ldmx_log(debug) <<
"A' position: (" << pos.x() / CLHEP::mm <<
", "
205 << pos.y() / CLHEP::mm <<
", " << pos.z() / CLHEP::mm
207 ldmx_log(debug) <<
"A' momentum direction: "
208 << a_dynamic_a_prime->GetMomentumDirection();
211 ldmx_log(warn) <<
"A' energy (" << egam / CLHEP::MeV
212 <<
" MeV) below threshold ("
214 <<
" MeV), skipping conversion!";
215 return G4VDiscreteProcess::PostStepDoIt(aTrack, aStep);
219 ldmx_log(debug) <<
"Killing incident A' and creating fcp+/fcp- pair...";
220 aParticleChange.ProposeMomentumDirection(0., 0., 0.);
221 aParticleChange.ProposeEnergy(0.);
222 aParticleChange.ProposeTrackStatus(fStopAndKill);
224 G4ParticleMomentum a_prime_direction =
225 a_dynamic_a_prime->GetMomentumDirection();
228 const G4Element* an_element =
selectRandomAtom(a_dynamic_a_prime, a_material);
229 G4int z = G4lrint(an_element->GetZ());
233 G4EventManager::GetEventManager()->GetUserInformation());
234 if (event_info !=
nullptr) {
235 event_info->setAPrimeConversionMaterialZ(z);
238 G4NistManager* nist = G4NistManager::Instance();
241 G4double a027 = nist->GetA27(z);
250 G4double zthird = 1. / nist->GetZ13(z);
251 G4double winfty = b * zthird *
mfcp_ / (dn * electron_mass_c2);
253 G4double c1_num = 0.138 * a027;
254 G4double c1_num2 = c1_num * c1_num;
255 G4double c2_term2 = electron_mass_c2 / (183. * zthird *
mfcp_);
257 G4double gamma_fcp_inv =
mfcp_ / egam;
261 (egam <=
limit_energy_) ? 0.5 : 0.5 - std::sqrt(0.25 - gamma_fcp_inv);
262 G4double xmax = 1. - xmin;
264 G4double ds2 = (dn * SQRTE - 2.);
265 G4double s_bz = SQRTE * b * zthird / electron_mass_c2;
266 G4double log_wmax_inv = 1. / G4Log(winfty * (1. + 2. * ds2 * gamma_fcp_inv) /
267 (1. + 2. * s_bz *
mfcp_ * gamma_fcp_inv));
268 G4double x_plus = 0.5;
269 G4double x_minus = 0.5;
270 G4double x_pm = 0.25;
273 const G4int nmax = 1000;
279 x_plus = xmin + G4UniformRand() * (xmax - xmin);
280 x_minus = 1. - x_plus;
281 x_pm = x_plus * x_minus;
282 G4double del =
mfcp_ *
mfcp_ / (2. * egam * x_pm);
283 w = winfty * (1. + ds2 * del /
mfcp_) / (1. + s_bz * del);
284 G4double xxp = 1. - 4. / 3. * x_pm;
285 result = (xxp > 0.) ? xxp * G4Log(w) * log_wmax_inv : 0.0;
287 ldmx_log(warn) <<
"APrimeConversionToFCPs::PostStepDoIt WARNING:"
288 <<
" in dSigxPlusGen, result=" << result <<
" > 1";
294 }
while (G4UniformRand() > result);
302 G4double a3 = (gamma_fcp_inv / (2. * x_pm));
303 G4double a33 = a3 * a3;
305 G4double b1 = 1. / (4. * c1_num2);
306 G4double b3 = b1 * b1 * b1;
307 G4double a21 = a33 + b1;
310 -(1. - x_pm) * (2. * b1 + (a21 + a33) * G4Log(a33 / a21)) / (2 * b3);
312 G4double theta_plus, theta_minus, phi_half;
321 G4double a34 = a33 / (t * t);
322 G4double a22 = a34 + b1;
323 if (std::abs(b1) < 0.0001 * a34) {
324 f1 = (1. - 2. * x_pm + 4. * x_pm * t * (1. - t)) /
325 (12. * a34 * a34 * a34 * a34);
327 f1 = -(1. - 2. * x_pm + 4. * x_pm * t * (1. - t)) *
328 (2. * b1 + (a22 + a34) * G4Log(a34 / a22)) / (2 * b3);
330 if (f1 < 0.0 || f1 > f1_max) {
336 }
while (G4UniformRand() * f1_max > f1);
339 G4double f2_max = 1. - 2. * x_pm * (1. - 4. * t * (1. - t));
343 psi = CLHEP::twopi * G4UniformRand();
345 1. - 2. * x_pm + 4. * x_pm * t * (1. - t) * (1. + std::cos(2. * psi));
346 if (f2 < 0 || f2 > f2_max) {
352 }
while (G4UniformRand() * f2_max > f2);
355 G4double c2_term1 = gamma_fcp_inv / (2. * x_pm * t);
356 G4double c22 = c2_term1 * c2_term1 + c2_term2 * c2_term2;
357 G4double c2 = 4. * c22 * c22 / std::sqrt(x_pm);
358 G4double rhomax = (1. / t - 1.) * 1.9 / a027;
359 G4double beta = G4Log((c2 + rhomax * rhomax * rhomax * rhomax) / c2);
360 rho = G4Exp(G4Log(c2 * (G4Exp(beta * G4UniformRand()) - 1.)) * 0.25);
363 G4double u = std::sqrt(1. / t - 1.);
364 G4double xi_half = 0.5 * rho * std::cos(psi);
365 phi_half = 0.5 * rho / u * std::sin(psi);
367 theta_plus = gamma_fcp_inv * (u + xi_half) / x_plus;
368 theta_minus = gamma_fcp_inv * (u - xi_half) / x_minus;
372 if (std::abs(theta_plus) > CLHEP::pi) {
375 if (std::abs(theta_minus) > CLHEP::pi) {
379 }
while (std::abs(theta_plus) > CLHEP::pi ||
380 std::abs(theta_minus) > CLHEP::pi);
384 G4double phi0 = CLHEP::twopi * G4UniformRand();
385 G4double e_plus = x_plus * egam;
386 G4double e_minus = x_minus * egam;
389 G4ThreeVector fcp_plus_direction(
390 std::sin(theta_plus) * std::cos(phi0 + phi_half),
391 std::sin(theta_plus) * std::sin(phi0 + phi_half), std::cos(theta_plus));
392 G4ThreeVector fcp_minus_direction(
393 -std::sin(theta_minus) * std::cos(phi0 - phi_half),
394 -std::sin(theta_minus) * std::sin(phi0 - phi_half),
395 std::cos(theta_minus));
398 fcp_plus_direction.rotateUz(a_prime_direction);
399 fcp_minus_direction.rotateUz(a_prime_direction);
404 aParticleChange.AddSecondary(a_particle1);
406 ldmx_log(debug) <<
"Created FCP+ with:";
407 ldmx_log(debug) <<
" - Kinetic energy: " << (e_plus -
mfcp_) / CLHEP::MeV
409 ldmx_log(debug) <<
" - Total energy: " << e_plus / CLHEP::MeV <<
" MeV";
410 ldmx_log(debug) <<
" - Direction: " << fcp_plus_direction;
413 auto a_particle2 =
new G4DynamicParticle(
the_fcp_minus_, fcp_minus_direction,
415 aParticleChange.AddSecondary(a_particle2);
417 ldmx_log(debug) <<
"Created FCP- with:";
418 ldmx_log(debug) <<
" - Kinetic energy: " << (e_minus -
mfcp_) / CLHEP::MeV
420 ldmx_log(debug) <<
" - Total energy: " << e_minus / CLHEP::MeV <<
" MeV";
421 ldmx_log(debug) <<
" - Direction: " << fcp_minus_direction;
423 ldmx_log(debug) <<
"=== A' -> fcp+ fcp- CONVERSION COMPLETE ===";
425 return G4VDiscreteProcess::PostStepDoIt(aTrack, aStep);