141 G4NistManager* nist = G4NistManager::Instance();
143 G4double pow_thres, ecor, b, dn, zthird, winfty, w_med_appr, wsatur, sigfac;
150 dn = 1.54 * nist->GetA27(Z);
152 zthird = 1. / nist->GetZ13(Z);
153 winfty = b * zthird *
mfcp_ / (dn * electron_mass_c2);
154 w_med_appr = 1. / (4. * dn * SQRTE *
mfcp_);
155 wsatur = winfty / w_med_appr;
156 sigfac = 4. * fine_structure_const * Z * Z *
rc_ *
rc_;
157 pow_thres = 1.479 + 0.00799 * dn;
158 ecor = -18. + 4347. / (b * zthird);
160 G4double cor_fuc = 1. + .04 * G4Log(1. + ecor / Egam);
161 G4double eg = G4Exp(G4Log(1. - 4. *
mfcp_ / Egam) * pow_thres) *
162 G4Exp(G4Log(G4Exp(G4Log(wsatur) * POW_SAT) +
163 G4Exp(G4Log(Egam) * POW_SAT)) /
166 G4double cross_section =
167 7. / 9. * sigfac * G4Log(1. + w_med_appr * cor_fuc * eg);
169 return cross_section;
180 const G4Step& aStep) {
181 ldmx_log(debug) <<
"gamma -> fcp+ fcp- conversion starting!";
182 aParticleChange.Initialize(aTrack);
183 const G4Material* a_material = aTrack.GetMaterial();
185 ldmx_log(debug) <<
"Conversion in material: " << a_material->GetName();
186 ldmx_log(debug) <<
"Gamma Track ID: " << aTrack.GetTrackID()
187 <<
", Parent ID: " << aTrack.GetParentID();
190 const G4DynamicParticle* a_dynamic_gamma = aTrack.GetDynamicParticle();
191 G4double egam = a_dynamic_gamma->GetKineticEnergy();
193 G4ThreeVector pos = aTrack.GetPosition();
194 ldmx_log(debug) <<
"Gamma kinetic energy: " << egam / CLHEP::MeV <<
" MeV";
195 ldmx_log(debug) <<
"Gamma position: (" << pos.x() / CLHEP::mm <<
", "
196 << pos.y() / CLHEP::mm <<
", " << pos.z() / CLHEP::mm
198 ldmx_log(debug) <<
"Gamma momentum direction: "
199 << a_dynamic_gamma->GetMomentumDirection();
202 ldmx_log(warn) <<
"Gamma energy (" << egam / CLHEP::MeV
203 <<
" MeV) below threshold ("
205 <<
" MeV), skipping conversion!";
206 return G4VDiscreteProcess::PostStepDoIt(aTrack, aStep);
210 ldmx_log(debug) <<
"Killing incident gamma and creating fcp+/fcp- pair...";
211 aParticleChange.ProposeMomentumDirection(0., 0., 0.);
212 aParticleChange.ProposeEnergy(0.);
213 aParticleChange.ProposeTrackStatus(fStopAndKill);
215 G4ParticleMomentum gamma_direction = a_dynamic_gamma->GetMomentumDirection();
218 const G4Element* an_element =
selectRandomAtom(a_dynamic_gamma, a_material);
219 G4int z = G4lrint(an_element->GetZ());
221 G4NistManager* nist = G4NistManager::Instance();
224 G4double a027 = nist->GetA27(z);
233 G4double zthird = 1. / nist->GetZ13(z);
234 G4double winfty = b * zthird *
mfcp_ / (dn * electron_mass_c2);
236 G4double c1_num = 0.138 * a027;
237 G4double c1_num2 = c1_num * c1_num;
238 G4double c2_term2 = electron_mass_c2 / (183. * zthird *
mfcp_);
240 G4double gamma_fcp_inv =
mfcp_ / egam;
244 (egam <=
limit_energy_) ? 0.5 : 0.5 - std::sqrt(0.25 - gamma_fcp_inv);
245 G4double xmax = 1. - xmin;
247 G4double ds2 = (dn * SQRTE - 2.);
248 G4double s_bz = SQRTE * b * zthird / electron_mass_c2;
249 G4double log_wmax_inv = 1. / G4Log(winfty * (1. + 2. * ds2 * gamma_fcp_inv) /
250 (1. + 2. * s_bz *
mfcp_ * gamma_fcp_inv));
251 G4double x_plus = 0.5;
252 G4double x_minus = 0.5;
253 G4double x_pm = 0.25;
256 const G4int nmax = 1000;
262 x_plus = xmin + G4UniformRand() * (xmax - xmin);
263 x_minus = 1. - x_plus;
264 x_pm = x_plus * x_minus;
265 G4double del =
mfcp_ *
mfcp_ / (2. * egam * x_pm);
266 w = winfty * (1. + ds2 * del /
mfcp_) / (1. + s_bz * del);
267 G4double xxp = 1. - 4. / 3. * x_pm;
268 result = (xxp > 0.) ? xxp * G4Log(w) * log_wmax_inv : 0.0;
270 ldmx_log(warn) <<
"GammaConversionToFCPs::PostStepDoIt WARNING:"
271 <<
" in dSigxPlusGen, result=" << result <<
" > 1";
277 }
while (G4UniformRand() > result);
285 G4double a3 = (gamma_fcp_inv / (2. * x_pm));
286 G4double a33 = a3 * a3;
288 G4double b1 = 1. / (4. * c1_num2);
289 G4double b3 = b1 * b1 * b1;
290 G4double a21 = a33 + b1;
293 -(1. - x_pm) * (2. * b1 + (a21 + a33) * G4Log(a33 / a21)) / (2 * b3);
295 G4double theta_plus, theta_minus, phi_half;
304 G4double a34 = a33 / (t * t);
305 G4double a22 = a34 + b1;
306 if (std::abs(b1) < 0.0001 * a34) {
307 f1 = (1. - 2. * x_pm + 4. * x_pm * t * (1. - t)) /
308 (12. * a34 * a34 * a34 * a34);
310 f1 = -(1. - 2. * x_pm + 4. * x_pm * t * (1. - t)) *
311 (2. * b1 + (a22 + a34) * G4Log(a34 / a22)) / (2 * b3);
313 if (f1 < 0.0 || f1 > f1_max) {
319 }
while (G4UniformRand() * f1_max > f1);
322 G4double f2_max = 1. - 2. * x_pm * (1. - 4. * t * (1. - t));
326 psi = CLHEP::twopi * G4UniformRand();
328 1. - 2. * x_pm + 4. * x_pm * t * (1. - t) * (1. + std::cos(2. * psi));
329 if (f2 < 0 || f2 > f2_max) {
335 }
while (G4UniformRand() * f2_max > f2);
338 G4double c2_term1 = gamma_fcp_inv / (2. * x_pm * t);
339 G4double c22 = c2_term1 * c2_term1 + c2_term2 * c2_term2;
340 G4double c2 = 4. * c22 * c22 / std::sqrt(x_pm);
341 G4double rhomax = (1. / t - 1.) * 1.9 / a027;
342 G4double beta = G4Log((c2 + rhomax * rhomax * rhomax * rhomax) / c2);
343 rho = G4Exp(G4Log(c2 * (G4Exp(beta * G4UniformRand()) - 1.)) * 0.25);
346 G4double u = std::sqrt(1. / t - 1.);
347 G4double xi_half = 0.5 * rho * std::cos(psi);
348 phi_half = 0.5 * rho / u * std::sin(psi);
350 theta_plus = gamma_fcp_inv * (u + xi_half) / x_plus;
351 theta_minus = gamma_fcp_inv * (u - xi_half) / x_minus;
355 if (std::abs(theta_plus) > CLHEP::pi) {
358 if (std::abs(theta_minus) > CLHEP::pi) {
362 }
while (std::abs(theta_plus) > CLHEP::pi ||
363 std::abs(theta_minus) > CLHEP::pi);
367 G4double phi0 = CLHEP::twopi * G4UniformRand();
368 G4double e_plus = x_plus * egam;
369 G4double e_minus = x_minus * egam;
372 G4ThreeVector fcp_plus_direction(
373 std::sin(theta_plus) * std::cos(phi0 + phi_half),
374 std::sin(theta_plus) * std::sin(phi0 + phi_half), std::cos(theta_plus));
375 G4ThreeVector fcp_minus_direction(
376 -std::sin(theta_minus) * std::cos(phi0 - phi_half),
377 -std::sin(theta_minus) * std::sin(phi0 - phi_half),
378 std::cos(theta_minus));
381 fcp_plus_direction.rotateUz(gamma_direction);
382 fcp_minus_direction.rotateUz(gamma_direction);
387 aParticleChange.AddSecondary(a_particle1);
389 ldmx_log(debug) <<
"Created FCP+ with:";
390 ldmx_log(debug) <<
" - Kinetic energy: " << (e_plus -
mfcp_) / CLHEP::MeV
392 ldmx_log(debug) <<
" - Total energy: " << e_plus / CLHEP::MeV <<
" MeV";
393 ldmx_log(debug) <<
" - Direction: " << fcp_plus_direction;
396 auto a_particle2 =
new G4DynamicParticle(
the_fcp_minus_, fcp_minus_direction,
398 aParticleChange.AddSecondary(a_particle2);
400 ldmx_log(debug) <<
"Created FCP- with:";
401 ldmx_log(debug) <<
" - Kinetic energy: " << (e_minus -
mfcp_) / CLHEP::MeV
403 ldmx_log(debug) <<
" - Total energy: " << e_minus / CLHEP::MeV <<
" MeV";
404 ldmx_log(debug) <<
" - Direction: " << fcp_minus_direction;
406 ldmx_log(debug) <<
"=== gamma -> fcp+ fcp- CONVERSION COMPLETE ===";
408 return G4VDiscreteProcess::PostStepDoIt(aTrack, aStep);