155const G4double G4NucleiModel::skinDepth = 0.611207*radiusUnits;
160const G4double G4NucleiModel::radiusScale =
162const G4double G4NucleiModel::radiusScale2 =
181const G4double G4NucleiModel::alfa3[3] = { 0.7, 0.3, 0.01 };
182const G4double G4NucleiModel::alfa6[6] = { 0.9, 0.6, 0.4, 0.2, 0.1, 0.05 };
185const G4double G4NucleiModel::pion_vp = 0.007;
186const G4double G4NucleiModel::pion_vp_small = 0.007;
187const G4double G4NucleiModel::kaon_vp = 0.015;
188const G4double G4NucleiModel::hyperon_vp = 0.030;
190const G4double G4NucleiModel::piTimes4thirds =
pi*4./3.;
195 : verboseLevel(0), nuclei_radius(0.), nuclei_volume(0.), number_of_zones(0),
196 A(0), Z(0), theNucleus(0), neutronNumber(0), protonNumber(0),
197 neutronNumberCurrent(0), protonNumberCurrent(0), current_nucl1(0),
201 : verboseLevel(0), nuclei_radius(0.), nuclei_volume(0.), number_of_zones(0),
202 A(0), Z(0), theNucleus(0), neutronNumber(0), protonNumber(0),
203 neutronNumberCurrent(0), protonNumberCurrent(0), current_nucl1(0),
209 : verboseLevel(0), nuclei_radius(0.), nuclei_volume(0.), number_of_zones(0),
210 A(0), Z(0), theNucleus(0), neutronNumber(0), protonNumber(0),
211 neutronNumberCurrent(0), protonNumberCurrent(0), current_nucl1(0),
225 const std::vector<G4ThreeVector>* hitPoints) {
226 neutronNumberCurrent = neutronNumber - nHitNeutrons;
227 protonNumberCurrent = protonNumber - nHitProtons;
230 if (!hitPoints || !hitPoints->empty()) collisionPts.clear();
231 else collisionPts = *hitPoints;
243 G4cout <<
" >>> G4NucleiModel::generateModel A " << a <<
" Z " << z
248 if (a == A && z == Z) {
249 if (verboseLevel > 1)
G4cout <<
" model already generated" << z <<
G4endl;
259 neutronNumber = A - Z;
263 if (verboseLevel > 3) {
264 G4cout <<
" crossSectionUnits = " << crossSectionUnits <<
G4endl
265 <<
" radiusUnits = " << radiusUnits <<
G4endl
266 <<
" skinDepth = " << skinDepth <<
G4endl
267 <<
" radiusScale = " << radiusScale <<
G4endl
268 <<
" radiusScale2 = " << radiusScale2 <<
G4endl
269 <<
" radiusForSmall = " << radiusForSmall <<
G4endl
270 <<
" radScaleAlpha = " << radScaleAlpha <<
G4endl
271 <<
" fermiMomentum = " << fermiMomentum <<
G4endl
272 <<
" piTimes4thirds = " << piTimes4thirds <<
G4endl;
276 if (A>4) nuclearRadius = radiusScale*
G4cbrt(A) + radiusScale2/
G4cbrt(A);
277 else nuclearRadius = radiusForSmall * (A==4 ? radScaleAlpha : 1.);
280 number_of_zones = (A < 5) ? 1 : (A < 100) ? 3 : 6;
283 binding_energies.clear();
284 nucleon_densities.clear();
285 zone_potentials.clear();
286 fermi_momenta.clear();
288 zone_volumes.clear();
290 fillBindingEnergies();
291 fillZoneRadii(nuclearRadius);
293 G4double tot_vol = fillZoneVolumes(nuclearRadius);
295 fillPotentials(
proton, tot_vol);
296 fillPotentials(
neutron, tot_vol);
299 const std::vector<G4double> vp(number_of_zones, (A>4)?pion_vp:pion_vp_small);
300 const std::vector<G4double> kp(number_of_zones, kaon_vp);
301 const std::vector<G4double> hp(number_of_zones, hyperon_vp);
303 zone_potentials.push_back(vp);
304 zone_potentials.push_back(kp);
305 zone_potentials.push_back(hp);
307 nuclei_radius = zone_radii.back();
308 nuclei_volume = std::accumulate(zone_volumes.begin(),zone_volumes.end(),0.);
316void G4NucleiModel::fillBindingEnergies() {
317 if (verboseLevel > 1)
318 G4cout <<
" >>> G4NucleiModel::fillBindingEnergies" <<
G4endl;
324 binding_energies.push_back(std::fabs(
bindingEnergy(A-1,Z-1)-dm)/GeV);
325 binding_energies.push_back(std::fabs(
bindingEnergy(A-1,Z)-dm)/GeV);
330void G4NucleiModel::fillZoneRadii(
G4double nuclearRadius) {
331 if (verboseLevel > 1)
332 G4cout <<
" >>> G4NucleiModel::fillZoneRadii" <<
G4endl;
334 G4double skinRatio = nuclearRadius/skinDepth;
335 G4double skinDecay = std::exp(-skinRatio);
338 zone_radii.push_back(nuclearRadius);
342 G4double rSq = nuclearRadius * nuclearRadius;
343 G4double gaussRadius = std::sqrt(rSq * (1.0 - 1.0/A) + 6.4);
346 for (
G4int i = 0; i < number_of_zones; i++) {
347 G4double y = std::sqrt(-std::log(alfa3[i]));
348 zone_radii.push_back(gaussRadius * y);
351 }
else if (A < 100) {
353 for (
G4int i = 0; i < number_of_zones; i++) {
354 G4double y = std::log((1.0 + skinDecay)/alfa3[i] - 1.0);
355 zone_radii.push_back(nuclearRadius + skinDepth * y);
360 for (
G4int i = 0; i < number_of_zones; i++) {
361 G4double y = std::log((1.0 + skinDecay)/alfa6[i] - 1.0);
362 zone_radii.push_back(nuclearRadius + skinDepth * y);
371 if (verboseLevel > 1)
372 G4cout <<
" >>> G4NucleiModel::fillZoneVolumes" <<
G4endl;
378 tot_vol = zone_radii[0]*zone_radii[0]*zone_radii[0];
379 zone_volumes.push_back(tot_vol*piTimes4thirds);
384 PotentialType usePotential = (A < 12) ? Gaussian : WoodsSaxon;
386 for (
G4int i = 0; i < number_of_zones; i++) {
387 if (usePotential == WoodsSaxon) {
388 v[i] = zoneIntegralWoodsSaxon(ur[i], ur[i+1], nuclearRadius);
390 v[i] = zoneIntegralGaussian(ur[i], ur[i+1], nuclearRadius);
395 v1[i] = zone_radii[i]*zone_radii[i]*zone_radii[i];
396 if (i > 0) v1[i] -= zone_radii[i-1]*zone_radii[i-1]*zone_radii[i-1];
398 zone_volumes.push_back(v1[i]*piTimes4thirds);
405void G4NucleiModel::fillPotentials(
G4int type,
G4double tot_vol) {
406 if (verboseLevel > 1)
407 G4cout <<
" >>> G4NucleiModel::fillZoneVolumes(" << type <<
")" <<
G4endl;
414 const G4double dm = binding_energies[type-1];
416 rod.clear(); rod.reserve(number_of_zones);
417 pf.clear(); pf.reserve(number_of_zones);
418 vz.clear(); vz.reserve(number_of_zones);
420 G4int nNucleons = (type==
proton) ? protonNumber : neutronNumber;
421 G4double dd0 = nNucleons / tot_vol / piTimes4thirds;
423 for (
G4int i = 0; i < number_of_zones; i++) {
428 vz.push_back(0.5 * pff * pff / mass + dm);
431 nucleon_densities.push_back(rod);
432 fermi_momenta.push_back(pf);
433 zone_potentials.push_back(vz);
439 if (verboseLevel > 1) {
440 G4cout <<
" >>> G4NucleiModel::zoneIntegralWoodsSaxon" <<
G4endl;
444 const G4int itry_max = 1000;
446 G4double skinRatio = nuclearRadius / skinDepth;
450 G4double fr1 = r1 * (r1 + d2) / (1.0 + std::exp(r1));
451 G4double fr2 = r2 * (r2 + d2) / (1.0 + std::exp(r2));
459 while (itry < itry_max) {
465 G4int jc1 =
G4int(std::pow(2.0, jc - 1) + 0.1);
467 for (
G4int i = 0; i < jc1; i++) {
469 fi += r * (r + d2) / (1.0 + std::exp(r));
472 fun = 0.5 * fun1 + fi * dr;
474 if (std::fabs((fun - fun1) / fun) <= epsilon)
break;
481 if (verboseLevel > 2 && itry == itry_max)
482 G4cout <<
" zoneIntegralWoodsSaxon-> n iter " << itry_max <<
G4endl;
484 G4double skinDepth3 = skinDepth*skinDepth*skinDepth;
486 return skinDepth3 * (fun + skinRatio*skinRatio*std::log((1.0 + std::exp(-r1)) / (1.0 + std::exp(-r2))));
493 if (verboseLevel > 1) {
494 G4cout <<
" >>> G4NucleiModel::zoneIntegralGaussian" <<
G4endl;
497 G4double gaussRadius = std::sqrt(nucRad*nucRad * (1.0 - 1.0/A) + 6.4);
500 const G4int itry_max = 1000;
503 G4double fr1 = r1 * r1 * std::exp(-r1 * r1);
504 G4double fr2 = r2 * r2 * std::exp(-r2 * r2);
512 while (itry < itry_max) {
517 G4int jc1 = int(std::pow(2.0, jc - 1) + 0.1);
519 for (
G4int i = 0; i < jc1; i++) {
521 fi += r * r * std::exp(-r * r);
524 fun = 0.5 * fun1 + fi * dr;
526 if (std::fabs((fun - fun1) / fun) <= epsilon)
break;
533 if (verboseLevel > 2 && itry == itry_max)
534 G4cerr <<
" zoneIntegralGaussian-> n iter " << itry_max <<
G4endl;
536 return gaussRadius*gaussRadius*gaussRadius * fun;
541 if (verboseLevel > 1) {
545 G4cout <<
" nuclei model for A " << A <<
" Z " << Z <<
G4endl
546 <<
" proton binding energy " << binding_energies[0]
547 <<
" neutron binding energy " << binding_energies[1] <<
G4endl
548 <<
" Nuclei radius " << nuclei_radius <<
" volume " << nuclei_volume
549 <<
" number of zones " << number_of_zones <<
G4endl;
551 for (
G4int i = 0; i < number_of_zones; i++)
552 G4cout <<
" zone " << i+1 <<
" radius " << zone_radii[i]
553 <<
" volume " << zone_volumes[i] <<
G4endl
554 <<
" protons: density " <<
getDensity(1,i) <<
" PF " <<
556 <<
" neutrons: density " <<
getDensity(2,i) <<
" PF " <<
565 if (ip < 3 && izone < number_of_zones) {
566 G4double pfermi = fermi_momenta[ip - 1][izone];
569 ekin = std::sqrt(pfermi*pfermi + mass*mass) - mass;
586 if (verboseLevel > 1) {
587 G4cout <<
" >>> G4NucleiModel::generateNucleon" <<
G4endl;
596G4NucleiModel::generateQuasiDeutron(
G4int type1,
G4int type2,
598 if (verboseLevel > 1) {
599 G4cout <<
" >>> G4NucleiModel::generateQuasiDeutron" <<
G4endl;
613 if (type1*type2 ==
pro*
pro) dtype = 111;
614 else if (type1*type2 ==
pro*
neu) dtype = 112;
615 else if (type1*type2 ==
neu*
neu) dtype = 122;
623 if (verboseLevel > 1) {
624 G4cout <<
" >>> G4NucleiModel::generateInteractionPartners" <<
G4endl;
637 if (zone == number_of_zones) {
638 r_in = nuclei_radius;
640 }
else if (zone == 0) {
642 r_out = zone_radii[0];
644 r_in = zone_radii[zone - 1];
645 r_out = zone_radii[zone];
650 if (verboseLevel > 2) {
652 G4cout <<
" r_in " << r_in <<
" r_out " << r_out <<
" path " << path
658 G4cerr <<
" generateInteractionPartners-> negative path length" <<
G4endl;
662 if (std::fabs(path) < small) {
663 if (verboseLevel > 3)
664 G4cout <<
" generateInteractionPartners-> zero path" <<
G4endl;
666 thePartners.push_back(partner());
675 for (
G4int ip = 1; ip < 3; ip++) {
677 if (ip==
proton && protonNumberCurrent < 1)
continue;
678 if (ip==
neutron && neutronNumberCurrent < 1)
continue;
682 invmfp = inverseMeanFreePath(cparticle, particle);
683 spath = generateInteractionLength(cparticle, path, invmfp);
686 if (verboseLevel > 3) {
687 G4cout <<
" adding partner[" << thePartners.size() <<
"]: "
690 thePartners.push_back(partner(particle, spath));
694 if (verboseLevel > 2) {
695 G4cout <<
" after nucleons " << thePartners.size() <<
" path " << path <<
G4endl;
700 if (verboseLevel > 2) {
701 G4cout <<
" trying quasi-deuterons with bullet: "
712 if (protonNumberCurrent >= 2 && ptype !=
pip) {
714 if (verboseLevel > 2)
715 G4cout <<
" ptype=" << ptype <<
" using pp target\n" << ppd <<
G4endl;
717 invmfp = inverseMeanFreePath(cparticle, ppd);
718 tot_invmfp += invmfp;
719 acsecs.push_back(invmfp);
720 qdeutrons.push_back(ppd);
724 if (protonNumberCurrent >= 1 && neutronNumberCurrent >= 1) {
726 if (verboseLevel > 2)
727 G4cout <<
" ptype=" << ptype <<
" using np target\n" << npd <<
G4endl;
729 invmfp = inverseMeanFreePath(cparticle, npd);
730 tot_invmfp += invmfp;
731 acsecs.push_back(invmfp);
732 qdeutrons.push_back(npd);
736 if (neutronNumberCurrent >= 2 && ptype !=
pim) {
738 if (verboseLevel > 2)
739 G4cout <<
" ptype=" << ptype <<
" using nn target\n" << nnd <<
G4endl;
741 invmfp = inverseMeanFreePath(cparticle, nnd);
742 tot_invmfp += invmfp;
743 acsecs.push_back(invmfp);
744 qdeutrons.push_back(nnd);
748 if (verboseLevel > 2) {
749 for (
size_t i=0; i<qdeutrons.size(); i++) {
750 G4cout <<
" acsecs[" << qdeutrons[i].getDefinition()->GetParticleName()
751 <<
"] " << acsecs[i];
756 if (tot_invmfp > small) {
757 G4double apath = generateInteractionLength(cparticle, path, tot_invmfp);
763 for (
size_t i = 0; i < qdeutrons.size(); i++) {
766 if (verboseLevel > 2)
G4cout <<
" deut type " << i <<
G4endl;
767 thePartners.push_back(partner(qdeutrons[i], apath));
775 if (verboseLevel > 2) {
776 G4cout <<
" after deuterons " << thePartners.size() <<
" partners"
780 if (thePartners.size() > 1) {
781 std::sort(thePartners.begin(), thePartners.end(), sortPartners);
785 thePartners.push_back(partner(particle, path));
792 std::vector<G4CascadParticle>& outgoing_cparticles) {
793 if (verboseLevel > 1)
794 G4cout <<
" >>> G4NucleiModel::generateParticleFate" <<
G4endl;
796 if (verboseLevel > 2)
G4cout <<
" cparticle: " << cparticle <<
G4endl;
799#ifdef G4CASCADE_CHECK_ECONS
804 outgoing_cparticles.clear();
805 generateInteractionPartners(cparticle);
807 if (thePartners.empty()) {
809 G4cerr <<
" generateParticleFate-> got empty interaction-partners list "
814 G4int npart = thePartners.size();
819 boundaryTransition(cparticle);
820 outgoing_cparticles.push_back(cparticle);
822 if (verboseLevel > 2)
G4cout <<
" next zone \n" << cparticle <<
G4endl;
824 if (verboseLevel > 1)
825 G4cout <<
" processing " << npart-1 <<
" possible interactions" <<
G4endl;
829 G4bool no_interaction =
true;
832 for (
G4int i=0; i<npart-1; i++) {
837 if (verboseLevel > 3) {
839 G4cout <<
" target " << target.
type() <<
" bullet " << bullet.
type()
844 theEPCollider->
collide(&bullet, &target, EPCoutput);
849 if (verboseLevel > 2) {
851#ifdef G4CASCADE_CHECK_ECONS
852 balance.
collide(&bullet, &target, EPCoutput);
858 std::vector<G4InuclElementaryParticle>& outgoing_particles =
861 if (!passFermi(outgoing_particles, zone))
continue;
867 if (!passTrailing(new_position))
continue;
868 collisionPts.push_back(new_position);
871 std::sort(outgoing_particles.begin(), outgoing_particles.end(),
874 if (verboseLevel > 2)
875 G4cout <<
" adding " << outgoing_particles.size()
876 <<
" output particles" <<
G4endl;
879 for (
G4int ip = 0; ip <
G4int(outgoing_particles.size()); ip++) {
885 no_interaction =
false;
889#ifdef G4CASCADE_DEBUG_CHARGE
893 for (
G4int ip = 0; ip <
G4int(outgoing_particles.size()); ip++)
894 out_charge += outgoing_particles[ip].getCharge();
896 G4cout <<
" multiplicity " << outgoing_particles.size()
897 <<
" bul type " << bullet.
type()
898 <<
" targ type " << target.
type()
899 <<
"\n initial charge "
901 <<
" out charge " << out_charge <<
G4endl;
905 if (verboseLevel > 2)
909 current_nucl1 = target.
type();
911 if (verboseLevel > 2)
G4cout <<
" good absorption " <<
G4endl;
912 current_nucl1 = (target.
type() - 100) / 10;
913 current_nucl2 = target.
type() - 100 - 10 * current_nucl1;
916 if (current_nucl1 == 1) {
917 if (verboseLevel > 3)
G4cout <<
" decrement proton count" <<
G4endl;
918 protonNumberCurrent--;
920 if (verboseLevel > 3)
G4cout <<
" decrement neutron count" <<
G4endl;
921 neutronNumberCurrent--;
924 if (current_nucl2 == 1) {
925 if (verboseLevel > 3)
G4cout <<
" decrement proton count" <<
G4endl;
926 protonNumberCurrent--;
927 }
else if (current_nucl2 == 2) {
928 if (verboseLevel > 3)
G4cout <<
" decrement neutron count" <<
G4endl;
929 neutronNumberCurrent--;
935 if (no_interaction) {
936 if (verboseLevel > 1)
G4cout <<
" no interaction " <<
G4endl;
946 boundaryTransition(cparticle);
947 outgoing_cparticles.push_back(cparticle);
950#ifdef G4CASCADE_CHECK_ECONS
951 if (verboseLevel > 2) {
952 balance.
collide(&prescatCP, 0, outgoing_cparticles);
962G4bool G4NucleiModel::passFermi(
const std::vector<G4InuclElementaryParticle>& particles,
964 if (verboseLevel > 1) {
969 for (
G4int i = 0; i <
G4int(particles.size()); i++) {
970 if (!particles[i].nucleon())
continue;
972 G4int type = particles[i].type();
973 G4double mom = particles[i].getMomModule();
974 G4double pfermi = fermi_momenta[type-1][zone];
976 if (verboseLevel > 2)
977 G4cout <<
" type " << type <<
" p " << mom <<
" pf " << pfermi <<
G4endl;
980 if (verboseLevel > 2)
G4cout <<
" rejected by Fermi" <<
G4endl;
992 if (verboseLevel > 1)
993 G4cout <<
" >>> G4NucleiModel::passTrailing " << hit_position <<
G4endl;
996 for (
G4int i = 0; i <
G4int(collisionPts.size() ); i++) {
997 dist = (collisionPts[i] - hit_position).mag();
998 if (verboseLevel > 2)
G4cout <<
" dist " << dist <<
G4endl;
999 if (dist < R_nucleon) {
1000 if (verboseLevel > 2)
G4cout <<
" rejected by Trailing" <<
G4endl;
1009 if (verboseLevel > 1) {
1010 G4cout <<
" >>> G4NucleiModel::boundaryTransition" <<
G4endl;
1016 G4cerr <<
" boundaryTransition-> in zone 0 " <<
G4endl;
1031 if (verboseLevel > 3) {
1032 G4cout <<
"Potentials for type " << type <<
" = "
1037 G4double qv = dv * dv - 2.0 * dv * mom.
e() + pr * pr;
1041 if (verboseLevel > 3) {
1042 G4cout <<
" type " << type <<
" zone " << zone <<
" next " << next_zone
1043 <<
" qv " << qv <<
" dv " << dv <<
G4endl;
1047 if (verboseLevel > 3)
G4cout <<
" reflects off boundary" <<
G4endl;
1051 if (verboseLevel > 3)
G4cout <<
" passes thru boundary" <<
G4endl;
1052 p1r = std::sqrt(qv);
1053 if(pr < 0.0) p1r = -p1r;
1060 if (verboseLevel > 3) {
1061 G4cout <<
" prr " << prr <<
" delta px " << prr*pos.
x() <<
" py "
1062 << prr*pos.
y() <<
" pz " << prr*pos.
z() <<
" mag "
1063 << std::fabs(prr*r) <<
G4endl;
1072 if (verboseLevel > 2) {
1073 G4cout <<
" isProjectile(cparticle): zone "
1089 if (verboseLevel > 1) {
1090 G4cout <<
" >>> G4NucleiModel::worthToPropagate" <<
G4endl;
1107 if (verboseLevel > 3) {
1110 <<
" potential=" << ekin_cut
1111 <<
" : worth? " << worth <<
G4endl;
1120 if (verboseLevel > 3) {
1121 G4cout <<
" >>> G4NucleiModel::getRatio " << ip <<
G4endl;
1159 return getRatio(ip) * dens;
1165 if (verboseLevel > 1) {
1166 G4cout <<
" >>> G4NucleiModel::initializeCascad(particle)" <<
G4endl;
1188 G4cout <<
" >>> G4NucleiModel::initializeCascad(bullet,target,output)"
1193 const G4double max_a_for_cascad = 5.0;
1195 const G4double small_ekin = 1.0e-6;
1196 const G4double r_large2for3 = 62.0;
1199 const G4double r_large2for4 = 69.14;
1202 const G4int itry_max = 100;
1205 std::vector<G4CascadParticle>& casparticles = output.first;
1206 std::vector<G4InuclElementaryParticle>& particles = output.second;
1208 casparticles.clear();
1219 if (ab < max_a_for_cascad) {
1223 G4double ben = benb < bent ? bent : benb;
1228 while (casparticles.size() == 0 && itryg < itry_max) {
1233 coordinates.clear();
1239 coordinates.push_back(coord1);
1240 coordinates.push_back(-coord1);
1246 while (bad && itry < itry_max) {
1250 if (p * p / (p * p + 2079.36) / (p * p + 2079.36) > 1.2023e-4 *
inuclRndm() &&
1251 p * r > 312.0) bad =
false;
1254 if (itry == itry_max)
1255 if (verboseLevel > 2){
1256 G4cout <<
" deutron bullet generation-> itry = " << itry_max <<
G4endl;
1261 if (verboseLevel > 2){
1267 momentums.push_back(mom);
1269 momentums.push_back(-mom);
1278 while (badco && itry < itry_max) {
1279 if (itry > 0) coordinates.clear();
1283 for (i = 0; i < 2; i++) {
1286 G4double fmax = std::exp(-0.5) / std::sqrt(0.5);
1288 while (itry1 < itry_max) {
1292 rho = std::sqrt(ss) * std::exp(-ss);
1294 if (rho > u && ss < s3max) {
1295 ss = r0forAeq3 * std::sqrt(ss);
1297 coordinates.push_back(coord1);
1299 if (verboseLevel > 2){
1306 if (itry1 == itry_max) {
1307 coord1.
set(10000.,10000.,10000.);
1308 coordinates.push_back(coord1);
1313 coord1 = -coordinates[0] - coordinates[1];
1314 if (verboseLevel > 2) {
1318 coordinates.push_back(coord1);
1320 G4bool large_dist =
false;
1322 for (i = 0; i < 2; i++) {
1323 for (
G4int j = i+1; j < 3; j++) {
1324 G4double r2 = (coordinates[i]-coordinates[j]).mag2();
1326 if (verboseLevel > 2) {
1327 G4cout <<
" i " << i <<
" j " << j <<
" r2 " << r2 <<
G4endl;
1330 if (r2 > r_large2for3) {
1337 if (large_dist)
break;
1340 if(!large_dist) badco =
false;
1347 G4double u = b1 + std::sqrt(b1 * b1 + b);
1348 G4double fmax = (1.0 + u/b) * u * std::exp(-u);
1350 while (badco && itry < itry_max) {
1352 if (itry > 0) coordinates.clear();
1356 for (i = 0; i < ab-1; i++) {
1360 while (itry1 < itry_max) {
1365 if (std::sqrt(ss) * std::exp(-ss) * (1.0 + ss/b) > u
1367 ss = r0forAeq4 * std::sqrt(ss);
1369 coordinates.push_back(coord1);
1371 if (verboseLevel > 2) {
1379 if (itry1 == itry_max) {
1380 coord1.
set(10000.,10000.,10000.);
1381 coordinates.push_back(coord1);
1387 for(
G4int j = 0; j < ab -1; j++) coord1 -= coordinates[j];
1389 coordinates.push_back(coord1);
1391 if (verboseLevel > 2){
1395 G4bool large_dist =
false;
1397 for (i = 0; i < ab-1; i++) {
1398 for (
G4int j = i+1; j < ab; j++) {
1400 G4double r2 = (coordinates[i]-coordinates[j]).mag2();
1402 if (verboseLevel > 2){
1403 G4cout <<
" i " << i <<
" j " << j <<
" r2 " << r2 <<
G4endl;
1406 if (r2 > r_large2for4) {
1413 if (large_dist)
break;
1416 if (!large_dist) badco =
false;
1421 G4cout <<
" can not generate the nucleons coordinates for a "
1424 casparticles.clear();
1433 for (
G4int i = 0; i < ab - 1; i++) {
1436 while(itry2 < itry_max) {
1438 u = -std::log(0.879853 - 0.8798502 *
inuclRndm());
1439 x = u * std::exp(-u);
1442 p = std::sqrt(0.01953 * u);
1444 momentums.push_back(mom);
1450 if(itry2 == itry_max) {
1451 G4cout <<
" can not generate proper momentum for a "
1454 casparticles.clear();
1464 for(
G4int j=0; j< ab-1; j++) mom -= momentums[j];
1466 momentums.push_back(mom);
1474 for(i = 0; i <
G4int(coordinates.size()); i++) {
1475 G4double rp = coordinates[i].mag2();
1477 if(rp > rb) rb = rp;
1483 G4double rz = (nuclei_radius + rb) * s1;
1484 G4ThreeVector global_pos(rz*std::cos(phi), rz*std::sin(phi),
1485 -(nuclei_radius+rb)*std::sqrt(1.0-s1*s1));
1487 for (i = 0; i <
G4int(coordinates.size()); i++) {
1488 coordinates[i] += global_pos;
1492 raw_particles.clear();
1494 for (
G4int ipa = 0; ipa < ab; ipa++) {
1495 G4int knd = ipa < zb ? 1 : 2;
1505 for (ipart = raw_particles.begin(); ipart != raw_particles.end(); ipart++) {
1506 ipart->setMomentum(toTheBulletRestFrame.
backToTheLab(ipart->getMomentum()));
1511 for(
G4int ip = 0; ip <
G4int(raw_particles.size()); ip++) {
1515 G4double det = t0 * t0 + nuclei_radius * nuclei_radius
1516 - coordinates[ip].mag2();
1523 if(std::fabs(t1) <= std::fabs(t2)) {
1525 if(coordinates[ip].z() + mom.
z() * t1 / pmod <= 0.0) tr = t1;
1528 if(tr < 0.0 && t2 > 0.0) {
1530 if(coordinates[ip].z() + mom.
z() * t2 / pmod <= 0.0) tr = t2;
1536 if(coordinates[ip].z() + mom.
z() * t2 / pmod <= 0.0) tr = t2;
1539 if(tr < 0.0 && t1 > 0.0) {
1540 if(coordinates[ip].z() + mom.
z() * t1 / pmod <= 0.0) tr = t1;
1547 coordinates[ip] += mom.
vect()*tr / pmod;
1550 number_of_zones, large, 0));
1553 particles.push_back(raw_particles[ip]);
1558 if(casparticles.size() == 0) {
1561 G4cout <<
" can not generate proper distribution for " << itry_max
1567 if(verboseLevel > 2){
1570 G4cout <<
" cascad particles: " << casparticles.size() <<
G4endl;
1571 for(ip = 0; ip <
G4int(casparticles.size()); ip++)
1574 G4cout <<
" outgoing particles: " << particles.size() <<
G4endl;
1575 for(ip = 0; ip <
G4int(particles.size()); ip++)
1600 if(verboseLevel > 2) {
1601 G4cout <<
" ip " << ip <<
" ekin " << ekin <<
" csec " << csec <<
G4endl;
1604 if (csec <= 0.)
return 0.;
1607 return csec * getCurrentDensity(ip, zone);
1616 const G4double young_cut = std::sqrt(10.0) * 0.25;
1620 if (invmfp < small)
return path;
1623 if (pw < -huge_num) pw = -huge_num;
1624 pw = 1.0 - std::exp(pw);
1626 if (verboseLevel > 2)
1627 G4cout <<
" mfp " << 1./invmfp <<
" pw " << pw <<
G4endl;
1633 spath = -std::log(1.0 - pw *
inuclRndm()) / invmfp;
1634 if (cparticle.
young(young_cut, spath)) spath = path;
1636 if (verboseLevel > 2)
1637 G4cout <<
" spath " << spath <<
" path " << path <<
G4endl;
1649 G4cerr <<
" absorptionCrossSection only valid for incident pions" <<
G4endl;
1657 if (ke < 0.3) csec = (0.1106 / std::sqrt(ke) - 0.8
1658 + 0.08 / ((ke-0.123)*(ke-0.123) + 0.0056) );
1659 else if (ke < 1.0) csec = 3.6735 * (1.0-ke)*(1.0-ke);
1666 { 0.0, 0.01, 0.013, 0.018, 0.024, 0.032, 0.042, 0.056, 0.075, 0.1,
1667 0.13, 0.18, 0.24, 0.32, 0.42, 0.56, 0.75, 1.0, 1.3, 1.8,
1668 2.4, 3.2, 4.2, 5.6, 7.5, 10.0, 13.0, 18.0, 24.0, 32.0 };
1670 { 2.8, 1.3, 0.89, 0.56, 0.38, 0.27, 0.19, 0.14, 0.098,
1671 0.071, 0.054, 0.0003, 0.0007, 0.0027, 0.0014, 0.001, 0.0012, 0.0005,
1672 0.0003, 0.0002,0.0002, 0.0002, 0.0002, 0.0002, 0.0001, 0.0001, 0.0001,
1673 0.0001, 0.0001, 0.0001 };
1675 csec = interp.
interpolate(ke, gammaD) * gammaQDscale;
1678 if (csec < 0.0) csec = 0.0;
1680 if (verboseLevel > 2) {
1681 G4cout <<
" ekin " << ke <<
" abs. csec " << csec <<
" mb" <<
G4endl;
1684 return crossSectionUnits * csec;
1693 G4cerr <<
" unknown collison type = " << rtype <<
G4endl;
std::vector< G4InuclElementaryParticle >::iterator particleIterator
std::vector< G4InuclElementaryParticle >::iterator particleIterator
G4DLLIMPORT std::ostream G4cerr
G4DLLIMPORT std::ostream G4cout
double dot(const Hep3Vector &) const
void set(double x, double y, double z)
void setVect(const Hep3Vector &)
G4bool reflectedNow() const
G4double getCurrentPath() const
void updateZone(G4int izone)
void incrementCurrentPath(G4double npath)
const G4InuclElementaryParticle & getParticle() const
void updateParticleMomentum(const G4LorentzVector &mom)
void updatePosition(const G4ThreeVector &pos)
G4bool movingInsideNuclei() const
void propagateAlongThePath(G4double path)
G4int getNumberOfReflections() const
G4LorentzVector getMomentum() const
G4bool young(G4double young_path_cut, G4double cpath) const
void incrementReflectionCounter()
G4int getCurrentZone() const
G4double getPathToTheNextZone(G4double rz_in, G4double rz_out)
const G4ThreeVector & getPosition() const
static const G4CascadeChannel * GetTable(G4int initialState)
virtual G4double getCrossSection(double ke) const =0
void collide(G4InuclParticle *bullet, G4InuclParticle *target, G4CollisionOutput &output)
G4double interpolate(const G4double x, const G4double(&yb)[nBins]) const
static G4double xsecScale()
static G4double radiusScale()
static G4bool useTwoParam()
static G4double gammaQDScale()
static G4double radiusAlpha()
static G4double radiusSmall()
static G4double fermiScale()
static G4double radiusTrailing()
G4int numberOfOutgoingParticles() const
void printCollisionOutput(std::ostream &os=G4cout) const
const std::vector< G4InuclElementaryParticle > & getOutgoingParticles() const
void collide(G4InuclParticle *bullet, G4InuclParticle *target, G4CollisionOutput &output)
G4bool quasi_deutron() const
static G4double getParticleMass(G4int type)
G4double getKineticEnergy() const
G4double getEnergy() const
G4double getCharge() const
void toTheTargetRestFrame()
void setBullet(const G4InuclParticle *bullet)
G4LorentzVector backToTheLab(const G4LorentzVector &mom) const
G4double getKinEnergyInTheTRS() const
void setTarget(const G4InuclParticle *target)
G4double getDensity(G4int ip, G4int izone) const
G4CascadParticle initializeCascad(G4InuclElementaryParticle *particle)
G4bool worthToPropagate(const G4CascadParticle &cparticle) const
void generateParticleFate(G4CascadParticle &cparticle, G4ElementaryParticleCollider *theEPCollider, std::vector< G4CascadParticle > &cascade)
G4InuclElementaryParticle generateNucleon(G4int type, G4int zone) const
G4double getVolume(G4int izone) const
G4double totalCrossSection(G4double ke, G4int rtype) const
G4double getPotential(G4int ip, G4int izone) const
G4double getFermiMomentum(G4int ip, G4int izone) const
void reset(G4int nHitNeutrons=0, G4int nHitProtons=0, const std::vector< G4ThreeVector > *hitPoints=0)
G4double absorptionCrossSection(G4double e, G4int type) const
void generateModel(G4InuclNuclei *nuclei)
std::pair< std::vector< G4CascadParticle >, std::vector< G4InuclElementaryParticle > > modelLists
G4double getFermiKinetic(G4int ip, G4int izone) const
G4LorentzVector generateNucleonMomentum(G4int type, G4int zone) const
G4bool isProjectile(const G4CascadParticle &cparticle) const
virtual void setVerboseLevel(G4int verbose=0)
G4LorentzVector generateWithFixedTheta(G4double ct, G4double p, G4double mass=0.)
G4double bindingEnergy(G4int A, G4int Z)
G4LorentzVector generateWithRandomAngles(G4double p, G4double mass=0.)
G4double G4cbrt(G4double x)