198const G4double G4NucleiModel::small = 1.0e-9;
199const G4double G4NucleiModel::large = 1000.;
202const G4double G4NucleiModel::piTimes4thirds = pi*4./3.;
205const G4double G4NucleiModel::alfa3[3] = { 0.7, 0.3, 0.01 };
206const G4double G4NucleiModel::alfa6[6] = { 0.9, 0.6, 0.4, 0.2, 0.1, 0.05 };
209const G4double G4NucleiModel::pion_vp = 0.007;
210const G4double G4NucleiModel::pion_vp_small = 0.007;
211const G4double G4NucleiModel::kaon_vp = 0.015;
212const G4double G4NucleiModel::hyperon_vp = 0.030;
222 0.0, 0.0024, 0.0032, 0.0042, 0.0056, 0.0075, 0.01, 0.024, 0.075, 0.1,
223 0.13, 0.18, 0.24, 0.32, 0.42, 0.56, 0.75, 1.0, 1.3, 1.8,
224 2.4, 3.2, 4.2, 5.6, 7.5, 10.0, 13.0, 18.0, 24.0, 32.0 };
227 0.0, 0.7, 2.0, 2.2, 2.1, 1.8, 1.3, 0.4, 0.098, 0.071,
228 0.055, 0.055, 0.065, 0.045, 0.017, 0.007, 2.37e-3, 6.14e-4, 1.72e-4, 4.2e-5,
229 1.05e-5, 3.0e-6, 7.0e-7, 1.3e-7, 2.3e-8, 3.2e-9, 4.9e-10, 0.0, 0.0, 0.0 };
235 : verboseLevel(0), nuclei_radius(0.), nuclei_volume(0.), number_of_zones(0),
236 A(0), Z(0), theNucleus(0), neutronNumber(0), protonNumber(0),
237 neutronNumberCurrent(0), protonNumberCurrent(0), current_nucl1(0),
238 current_nucl2(0), dinucleonDensityScale(1.0), gammaQDinterp(kebins),
241 skinDepth(0.611207*radiusUnits),
249 potentialThickness(1.0),
253 : verboseLevel(0), nuclei_radius(0.), nuclei_volume(0.), number_of_zones(0),
254 A(0), Z(0), theNucleus(0), neutronNumber(0), protonNumber(0),
255 neutronNumberCurrent(0), protonNumberCurrent(0), current_nucl1(0),
256 current_nucl2(0), dinucleonDensityScale(1.0), gammaQDinterp(kebins),
259 skinDepth(0.611207*radiusUnits),
267 potentialThickness(1.0),
273 : verboseLevel(0), nuclei_radius(0.), nuclei_volume(0.), number_of_zones(0),
274 A(0), Z(0), theNucleus(0), neutronNumber(0), protonNumber(0),
275 neutronNumberCurrent(0), protonNumberCurrent(0), current_nucl1(0),
276 current_nucl2(0), dinucleonDensityScale(1.0), gammaQDinterp(kebins),
279 skinDepth(0.611207*radiusUnits),
287 potentialThickness(1.0),
301 const std::vector<G4ThreeVector>* hitPoints) {
302 neutronNumberCurrent = neutronNumber - nHitNeutrons;
303 protonNumberCurrent = protonNumber - nHitProtons;
306 if (!hitPoints || !hitPoints->empty()) collisionPts.clear();
307 else collisionPts = *hitPoints;
319 G4cout <<
" >>> G4NucleiModel::generateModel A " << a <<
" Z " << z
324 if (a == A && z == Z) {
325 if (verboseLevel > 1)
G4cout <<
" model already generated" << z <<
G4endl;
335 neutronNumber = A - Z;
339 if (verboseLevel > 3) {
340 G4cout <<
" crossSectionUnits = " << crossSectionUnits <<
G4endl
341 <<
" radiusUnits = " << radiusUnits <<
G4endl
342 <<
" skinDepth = " << skinDepth <<
G4endl
343 <<
" radiusScale = " << radiusScale <<
G4endl
344 <<
" radiusScale2 = " << radiusScale2 <<
G4endl
345 <<
" radiusForSmall = " << radiusForSmall <<
G4endl
346 <<
" radScaleAlpha = " << radScaleAlpha <<
G4endl
347 <<
" fermiMomentum = " << fermiMomentum <<
G4endl
348 <<
" piTimes4thirds = " << piTimes4thirds <<
G4endl;
352 if (A>4) nuclearRadius = radiusScale*
G4cbrt(A) + radiusScale2/
G4cbrt(A);
353 else nuclearRadius = radiusForSmall * (A==4 ? radScaleAlpha : 1.);
356 number_of_zones = (A < 5) ? 1 : (A < 100) ? 3 : 6;
359 binding_energies.clear();
360 nucleon_densities.clear();
361 zone_potentials.clear();
362 fermi_momenta.clear();
364 zone_volumes.clear();
375 const std::vector<G4double> vp(number_of_zones, (A>4)?pion_vp:pion_vp_small);
376 const std::vector<G4double> kp(number_of_zones, kaon_vp);
377 const std::vector<G4double> hp(number_of_zones, hyperon_vp);
379 zone_potentials.push_back(std::move(vp));
380 zone_potentials.push_back(std::move(kp));
381 zone_potentials.push_back(std::move(hp));
385 nuclei_radius = zone_radii.back();
386 nuclei_volume = std::accumulate(zone_volumes.begin(),zone_volumes.end(),0.);
395 if (verboseLevel > 1)
396 G4cout <<
" >>> G4NucleiModel::fillBindingEnergies" <<
G4endl;
402 binding_energies.push_back(std::fabs(
bindingEnergy(A-1,Z-1)-dm)/GeV);
403 binding_energies.push_back(std::fabs(
bindingEnergy(A-1,Z)-dm)/GeV);
409 if (verboseLevel > 1)
410 G4cout <<
" >>> G4NucleiModel::fillZoneRadii" <<
G4endl;
412 G4double skinRatio = nuclearRadius/skinDepth;
416 zone_radii.push_back(nuclearRadius);
420 G4double rSq = nuclearRadius * nuclearRadius;
421 G4double gaussRadius = std::sqrt(rSq * (1.0 - 1.0/A) + 6.4);
424 for (
G4int i = 0; i < number_of_zones; i++) {
426 zone_radii.push_back(gaussRadius * y);
429 }
else if (A < 100) {
431 for (
G4int i = 0; i < number_of_zones; i++) {
433 zone_radii.push_back(nuclearRadius + skinDepth * y);
438 for (
G4int i = 0; i < number_of_zones; i++) {
440 zone_radii.push_back(nuclearRadius + skinDepth * y);
449 if (verboseLevel > 1)
450 G4cout <<
" >>> G4NucleiModel::fillZoneVolumes" <<
G4endl;
456 tot_vol = zone_radii[0]*zone_radii[0]*zone_radii[0];
457 zone_volumes.push_back(tot_vol*piTimes4thirds);
462 PotentialType usePotential = (A < 12) ? Gaussian : WoodsSaxon;
464 for (
G4int i = 0; i < number_of_zones; i++) {
465 if (usePotential == WoodsSaxon) {
473 v1[i] = zone_radii[i]*zone_radii[i]*zone_radii[i];
474 if (i > 0) v1[i] -= zone_radii[i-1]*zone_radii[i-1]*zone_radii[i-1];
476 zone_volumes.push_back(v1[i]*piTimes4thirds);
484 if (verboseLevel > 1)
485 G4cout <<
" >>> G4NucleiModel::fillZoneVolumes(" << type <<
")" <<
G4endl;
492 const G4double dm = binding_energies[type-1];
494 rod.clear(); rod.reserve(number_of_zones);
495 pf.clear(); pf.reserve(number_of_zones);
496 vz.clear(); vz.reserve(number_of_zones);
498 G4int nNucleons = (type==
proton) ? protonNumber : neutronNumber;
499 G4double dd0 = nNucleons / tot_vol / piTimes4thirds;
501 for (
G4int i = 0; i < number_of_zones; i++) {
506 vz.push_back(0.5 * pff * pff / mass + dm);
509 nucleon_densities.push_back(rod);
510 fermi_momenta.push_back(pf);
511 zone_potentials.push_back(vz);
517 if (verboseLevel > 1) {
518 G4cout <<
" >>> G4NucleiModel::zoneIntegralWoodsSaxon" <<
G4endl;
522 const G4int itry_max = 1000;
524 G4double skinRatio = nuclearRadius / skinDepth;
537 while (itry < itry_max) {
544 for (
G4int i = 0; i < jc; i++) {
546 fi += r * (r + d2) / (1.0 +
G4Exp(r));
549 fun = 0.5 * fun1 + fi * dr;
551 if (std::fabs((fun - fun1) / fun) <=
epsilon)
break;
558 if (verboseLevel > 2 && itry == itry_max)
559 G4cout <<
" zoneIntegralWoodsSaxon-> n iter " << itry_max <<
G4endl;
561 G4double skinDepth3 = skinDepth*skinDepth*skinDepth;
563 return skinDepth3 * (fun + skinRatio*skinRatio*
G4Log((1.0 +
G4Exp(-r1)) / (1.0 +
G4Exp(-r2))));
570 if (verboseLevel > 1) {
571 G4cout <<
" >>> G4NucleiModel::zoneIntegralGaussian" <<
G4endl;
574 G4double gaussRadius = std::sqrt(nucRad*nucRad * (1.0 - 1.0/A) + 6.4);
577 const G4int itry_max = 1000;
589 while (itry < itry_max) {
595 for (
G4int i = 0; i < jc; i++) {
597 fi += r * r *
G4Exp(-r * r);
600 fun = 0.5 * fun1 + fi * dr;
602 if (std::fabs((fun - fun1) / fun) <=
epsilon)
break;
609 if (verboseLevel > 2 && itry == itry_max)
610 G4cerr <<
" zoneIntegralGaussian-> n iter " << itry_max <<
G4endl;
612 return gaussRadius*gaussRadius*gaussRadius * fun;
617 if (verboseLevel > 1) {
621 G4cout <<
" nuclei model for A " << A <<
" Z " << Z <<
G4endl
622 <<
" proton binding energy " << binding_energies[0]
623 <<
" neutron binding energy " << binding_energies[1] <<
G4endl
624 <<
" Nuclei radius " << nuclei_radius <<
" volume " << nuclei_volume
625 <<
" number of zones " << number_of_zones <<
G4endl;
627 for (
G4int i = 0; i < number_of_zones; i++)
628 G4cout <<
" zone " << i+1 <<
" radius " << zone_radii[i]
629 <<
" volume " << zone_volumes[i] <<
G4endl
630 <<
" protons: density " <<
getDensity(1,i) <<
" PF " <<
632 <<
" neutrons: density " <<
getDensity(2,i) <<
" PF " <<
641 if (ip < 3 && izone < number_of_zones) {
642 G4double pfermi = fermi_momenta[ip - 1][izone];
645 ekin = std::sqrt(pfermi*pfermi + mass*mass) - mass;
662 if (verboseLevel > 1) {
663 G4cout <<
" >>> G4NucleiModel::generateNucleon" <<
G4endl;
674 if (verboseLevel > 1) {
675 G4cout <<
" >>> G4NucleiModel::generateQuasiDeuteron" <<
G4endl;
689 if (type1*type2 ==
pro*
pro) dtype = 111;
690 else if (type1*type2 ==
pro*
neu) dtype = 112;
691 else if (type1*type2 ==
neu*
neu) dtype = 122;
699 if (verboseLevel > 1) {
700 G4cout <<
" >>> G4NucleiModel::generateInteractionPartners" <<
G4endl;
711 if (zone == number_of_zones) {
712 r_in = nuclei_radius;
714 }
else if (zone == 0) {
716 r_out = zone_radii[0];
718 r_in = zone_radii[zone - 1];
719 r_out = zone_radii[zone];
724 if (verboseLevel > 2) {
726 G4cout <<
" r_in " << r_in <<
" r_out " << r_out <<
" path " << path
732 G4cerr <<
" generateInteractionPartners-> negative path length" <<
G4endl;
736 if (std::fabs(path) < small) {
738 if (verboseLevel > 3)
739 G4cout <<
" generateInteractionPartners-> zero path" <<
G4endl;
745 if (zone >= number_of_zones)
746 zone = number_of_zones-1;
751 for (
G4int ip = 1; ip < 3; ip++) {
753 if (ip==
proton && protonNumberCurrent < 1)
continue;
754 if (ip==
neutron && neutronNumberCurrent < 1)
continue;
762 if (path<small || spath < path) {
763 if (verboseLevel > 3) {
771 if (verboseLevel > 2) {
777 if (verboseLevel > 2) {
778 G4cout <<
" trying quasi-deuterons with bullet: "
789 if (protonNumberCurrent >= 2 && ptype !=
pip) {
791 if (verboseLevel > 2)
792 G4cout <<
" ptype=" << ptype <<
" using pp target\n" << ppd <<
G4endl;
795 tot_invmfp += invmfp;
796 acsecs.push_back(invmfp);
797 qdeutrons.push_back(ppd);
801 if (protonNumberCurrent >= 1 && neutronNumberCurrent >= 1) {
803 if (verboseLevel > 2)
804 G4cout <<
" ptype=" << ptype <<
" using np target\n" << npd <<
G4endl;
807 tot_invmfp += invmfp;
808 acsecs.push_back(invmfp);
809 qdeutrons.push_back(npd);
813 if (neutronNumberCurrent >= 2 && ptype !=
pim && ptype !=
mum) {
815 if (verboseLevel > 2)
816 G4cout <<
" ptype=" << ptype <<
" using nn target\n" << nnd <<
G4endl;
819 tot_invmfp += invmfp;
820 acsecs.push_back(invmfp);
821 qdeutrons.push_back(nnd);
825 if (verboseLevel > 2) {
826 for (std::size_t i=0; i<qdeutrons.size(); i++) {
827 G4cout <<
" acsecs[" << qdeutrons[i].getDefinition()->GetParticleName()
828 <<
"] " << acsecs[i];
833 if (tot_invmfp > small) {
836 if (path<small || apath < path) {
840 for (std::size_t i = 0; i < qdeutrons.size(); i++) {
843 if (verboseLevel > 2)
854 if (verboseLevel > 2) {
871 std::vector<G4CascadParticle>& outgoing_cparticles) {
872 if (verboseLevel > 1)
873 G4cout <<
" >>> G4NucleiModel::generateParticleFate" <<
G4endl;
875 if (verboseLevel > 2)
G4cout <<
" cparticle: " << cparticle <<
G4endl;
878#ifdef G4CASCADE_CHECK_ECONS
883 outgoing_cparticles.clear();
888 G4cerr <<
" generateParticleFate-> got empty interaction-partners list "
896 if (verboseLevel > 1)
897 G4cout <<
" no interactions; moving to next zone" <<
G4endl;
902 outgoing_cparticles.push_back(cparticle);
904 if (verboseLevel > 2)
G4cout <<
" next zone \n" << cparticle <<
G4endl;
913 if (verboseLevel > 1)
914 G4cout <<
" processing " << npart-1 <<
" possible interactions" <<
G4endl;
918 G4bool no_interaction =
true;
921 for (std::size_t i=0; i<npart-1; ++i) {
926 if (verboseLevel > 3) {
928 G4cout <<
" target " << target.
type() <<
" bullet " << bullet.
type()
934 G4int massNumberCurrent = protonNumberCurrent+neutronNumberCurrent;
935 theEPCollider->
setNucleusState(massNumberCurrent, protonNumberCurrent);
936 theEPCollider->
collide(&bullet, &target, EPCoutput);
939 if (EPCoutput.numberOfOutgoingParticles() == 0)
break;
941 if (verboseLevel > 2) {
942 EPCoutput.printCollisionOutput();
943#ifdef G4CASCADE_CHECK_ECONS
944 balance.
collide(&bullet, &target, EPCoutput);
950 std::vector<G4InuclElementaryParticle>& outgoing_particles =
951 EPCoutput.getOutgoingParticles();
953 if (!
passFermi(outgoing_particles, zone))
continue;
960 collisionPts.push_back(new_position);
963 std::sort(outgoing_particles.begin(), outgoing_particles.end(),
966 if (verboseLevel > 2)
967 G4cout <<
" adding " << outgoing_particles.size()
968 <<
" output particles" <<
G4endl;
972 for (std::size_t ip = 0; ip < outgoing_particles.size(); ++ip) {
978 no_interaction =
false;
982#ifdef G4CASCADE_DEBUG_CHARGE
986 for (
G4int ip = 0; ip <
G4int(outgoing_particles.size()); ip++)
987 out_charge += outgoing_particles[ip].getCharge();
989 G4cout <<
" multiplicity " << outgoing_particles.size()
990 <<
" bul type " << bullet.
type()
991 <<
" targ type " << target.
type()
992 <<
"\n initial charge "
994 <<
" out charge " << out_charge <<
G4endl;
998 if (verboseLevel > 2)
1002 current_nucl1 = target.
type();
1004 if (verboseLevel > 2)
G4cout <<
" good absorption " <<
G4endl;
1005 current_nucl1 = (target.
type() - 100) / 10;
1006 current_nucl2 = target.
type() - 100 - 10 * current_nucl1;
1009 if (current_nucl1 == 1) {
1010 if (verboseLevel > 3)
G4cout <<
" decrement proton count" <<
G4endl;
1011 protonNumberCurrent--;
1013 if (verboseLevel > 3)
G4cout <<
" decrement neutron count" <<
G4endl;
1014 neutronNumberCurrent--;
1017 if (current_nucl2 == 1) {
1018 if (verboseLevel > 3)
G4cout <<
" decrement proton count" <<
G4endl;
1019 protonNumberCurrent--;
1020 }
else if (current_nucl2 == 2) {
1021 if (verboseLevel > 3)
G4cout <<
" decrement neutron count" <<
G4endl;
1022 neutronNumberCurrent--;
1028 if (no_interaction) {
1029 if (verboseLevel > 1)
G4cout <<
" no interaction " <<
G4endl;
1033 if (!prescatCP_G4MT_TLS_) {
1045 outgoing_cparticles.push_back(cparticle);
1048#ifdef G4CASCADE_CHECK_ECONS
1049 if (verboseLevel > 2) {
1050 balance.
collide(&prescatCP, 0, outgoing_cparticles);
1062 if (qdtype==
pn || qdtype==0)
1063 return (ptype==
pi0 || ptype==
pip || ptype==
pim || ptype==
gam || ptype==
mum);
1064 else if (qdtype==
pp)
1065 return (ptype==
pi0 || ptype==
pim || ptype==
gam || ptype==
mum);
1066 else if (qdtype==
nn)
1067 return (ptype==
pi0 || ptype==
pip || ptype==
gam);
1075 if (verboseLevel > 1) {
1080 for (
G4int i = 0; i <
G4int(particles.size()); i++) {
1081 if (!particles[i].
nucleon())
continue;
1083 G4int type = particles[i].type();
1084 G4double mom = particles[i].getMomModule();
1085 G4double pfermi = fermi_momenta[type-1][zone];
1087 if (verboseLevel > 2)
1088 G4cout <<
" type " << type <<
" p " << mom <<
" pf " << pfermi <<
G4endl;
1091 if (verboseLevel > 2)
G4cout <<
" rejected by Fermi" <<
G4endl;
1103 if (verboseLevel > 1)
1104 G4cout <<
" >>> G4NucleiModel::passTrailing " << hit_position <<
G4endl;
1107 for (
G4int i = 0; i <
G4int(collisionPts.size() ); i++) {
1108 dist = (collisionPts[i] - hit_position).mag();
1109 if (verboseLevel > 2)
G4cout <<
" dist " << dist <<
G4endl;
1110 if (dist < R_nucleon) {
1111 if (verboseLevel > 2)
G4cout <<
" rejected by Trailing" <<
G4endl;
1120 if (verboseLevel > 1) {
1121 G4cout <<
" >>> G4NucleiModel::boundaryTransition" <<
G4endl;
1127 if (verboseLevel)
G4cerr <<
" boundaryTransition-> in zone 0 " <<
G4endl;
1145 if (verboseLevel > 3) {
1146 G4cout <<
"Potentials for type " << type <<
" = "
1151 G4double qv = dv*dv + 2.0*dv*mom.
e() + pr*pr;
1157 G4double qperp = 2.0*pperp2*potentialThickness/r;
1159 if (verboseLevel > 3) {
1160 G4cout <<
" type " << type <<
" zone " << zone <<
" next " << next_zone
1161 <<
" qv " << qv <<
" dv " << dv <<
G4endl;
1164 G4bool adjustpperp =
false;
1168 if (qv <= 0.0 && qv+qperp <=0 ) {
1169 if (verboseLevel > 3)
G4cout <<
" reflects off boundary" <<
G4endl;
1174 }
else if (qv > 0.0) {
1175 if (verboseLevel > 3)
G4cout <<
" passes thru boundary" <<
G4endl;
1176 p1r = std::sqrt(qv);
1177 if (pr < 0.0) p1r = -p1r;
1182 if (verboseLevel > 3)
G4cout <<
" passes thru boundary due to angular momentum" <<
G4endl;
1183 p1r = smallish * pr;
1192 if (verboseLevel > 3) {
1193 G4cout <<
" prr " << prr <<
" delta px " << prr*pos.x() <<
" py "
1194 << prr*pos.y() <<
" pz " << prr*pos.z() <<
" mag "
1195 << std::fabs(prr*r) <<
G4endl;
1200 G4double new_pperp_mag = std::sqrt(std::max(0.0, pperp2 + qv - p1r*p1r) );
1202 mom.
setVect(old_pperp * new_pperp_mag/std::sqrt(pperp2));
1217 if (verboseLevel > 1)
1218 G4cout <<
" >>> G4NucleiModel::choosePointAlongTraj" <<
G4endl;
1230 if (verboseLevel > 3)
1231 G4cout <<
" pos " << pos <<
" phat " << phat <<
" rhat " << rhat <<
G4endl;
1236 if (prang < 1e-6) posout = -pos;
1240 if (verboseLevel > 3)
G4cout <<
" posrot " << posrot/deg <<
" deg";
1243 if (verboseLevel > 3)
G4cout <<
" posout " << posout <<
G4endl;
1248 G4double lenmid = (posout-pos).mag()/2.;
1250 G4int zoneout = number_of_zones-1;
1254 G4int ncross = (number_of_zones-zonemid)*2;
1256 if (verboseLevel > 3) {
1257 G4cout <<
" posmid " << posmid <<
" lenmid " << lenmid
1258 <<
" zoneout " << zoneout <<
" zonemid " << zonemid
1259 <<
" ncross " << ncross <<
G4endl;
1263 std::vector<G4double> wtlen(ncross,0.);
1264 std::vector<G4double> len(ncross,0.);
1268 for (i=0; i<ncross/2; i++) {
1269 G4int iz = zoneout-i;
1270 G4double ds = std::sqrt(zone_radii[iz]*zone_radii[iz]-r2mid);
1272 len[i] = lenmid - ds;
1273 len[ncross-1-i] = lenmid + ds;
1275 if (verboseLevel > 3) {
1276 G4cout <<
" i " << i <<
" iz " << iz <<
" ds " << ds
1277 <<
" len " << len[i] <<
G4endl;
1282 for (i=1; i<ncross; i++) {
1283 G4int iz = (i<ncross/2) ? zoneout-i+1 : zoneout-ncross+i+1;
1297 wtlen[i] = wtlen[i-1] + wt;
1299 if (verboseLevel > 3) {
1300 G4cout <<
" i " << i <<
" iz " << iz <<
" avg.mfp " << 1./invmfp
1301 <<
" dlen " << dlen <<
" wt " << wt <<
" wtlen " << wtlen[i]
1307 std::transform(wtlen.begin(), wtlen.end(), wtlen.begin(),
1308 std::bind(std::divides<G4double>(), std::placeholders::_1, wtlen.back()));
1310 if (verboseLevel > 3) {
1312 for (i=0; i<ncross; i++)
G4cout <<
" " << wtlen[i];
1318 G4long ir = std::upper_bound(wtlen.begin(),wtlen.end(),rand) - wtlen.begin();
1320 G4double frac = (rand-wtlen[ir-1]) / (wtlen[ir]-wtlen[ir-1]);
1321 G4double drand = (1.-frac)*len[ir-1] + frac*len[ir];
1323 if (verboseLevel > 3) {
1324 G4cout <<
" rand " << rand <<
" ir " << ir <<
" frac " << frac
1325 <<
" drand " << drand <<
G4endl;
1328 pos += drand * phat;
1334 if (verboseLevel > 2) {
1336 <<
" @ " << pos <<
G4endl;
1354 if (verboseLevel > 1) {
1355 G4cout <<
" >>> G4NucleiModel::worthToPropagate" <<
G4endl;
1372 if (verboseLevel > 3) {
1375 <<
" potential=" << ekin_cut
1376 <<
" : worth? " << worth <<
G4endl;
1385 if (verboseLevel > 4) {
1386 G4cout <<
" >>> G4NucleiModel::getRatio " << ip <<
G4endl;
1403 dinucleonDensityScale = 1.0;
1417 const G4double num_LDA_QDs {(Levinger_LDA*Z*(A-Z))/A};
1422 for (
G4int zone = 0; zone < number_of_zones; ++zone) {
1429 dinucleonDensityScale = num_LDA_QDs/num_Naive_QDs;
1431 if (verboseLevel > 4) {
1432 G4cout <<
" >>> G4NucleiModel::setDinucleonDensityScale()" <<
G4endl;
1433 G4cout <<
" >>> Naive number of quasi-deuterons in nucleus ("
1434 << Z <<
", " << A <<
") = " << num_Naive_QDs <<
G4endl;
1435 G4cout <<
" >>> Number of quasi-deuterons expected from Levinger LDA is "
1436 << num_LDA_QDs <<
G4endl;
1437 G4cout <<
"Rescaling dinucleon densities by " << dinucleonDensityScale <<
G4endl;
1443 const G4double combinatoric_factor =
1452 * dinucleonDensityScale * combinatoric_factor;
1456 * dinucleonDensityScale;
1460 * dinucleonDensityScale * combinatoric_factor;
1473 if (verboseLevel > 1) {
1474 G4cout <<
" >>> G4NucleiModel::initializeCascad(particle)" <<
G4endl;
1484 G4int zone = number_of_zones;
1501 G4cout <<
" >>> G4NucleiModel::initializeCascad(bullet,target,output)"
1505 const G4double max_a_for_cascad = 5.0;
1507 const G4double small_ekin = 1.0e-6;
1508 const G4double r_large2for3 = 62.0;
1511 const G4double r_large2for4 = 69.14;
1514 const G4int itry_max = 100;
1517 std::vector<G4CascadParticle>& casparticles = output.first;
1518 std::vector<G4InuclElementaryParticle>& particles = output.second;
1520 casparticles.clear();
1531 if (ab < max_a_for_cascad) {
1535 G4double ben = benb < bent ? bent : benb;
1541 while (casparticles.size() == 0 && itryg < itry_max) {
1546 coordinates.clear();
1552 coordinates.push_back(coord1);
1553 coordinates.push_back(-coord1);
1559 while (bad && itry < itry_max) {
1563 if (p*p / (p*p + 2079.36) / (p*p + 2079.36) > 1.2023e-4 *
G4UniformRand()
1564 && p*r > 312.0) bad =
false;
1567 if (itry == itry_max)
1568 if (verboseLevel > 2){
1569 G4cout <<
" deutron bullet generation-> itry = " << itry_max <<
G4endl;
1574 if (verboseLevel > 2){
1580 momentums.push_back(mom);
1582 momentums.push_back(-mom);
1591 while (badco && itry < itry_max) {
1592 if (itry > 0) coordinates.clear();
1596 for (i = 0; i < 2; i++) {
1601 while (itry1 < itry_max) {
1605 rho = std::sqrt(ss) *
G4Exp(-ss);
1607 if (rho > u && ss < s3max) {
1608 ss = r0forAeq3 * std::sqrt(ss);
1610 coordinates.push_back(coord1);
1612 if (verboseLevel > 2){
1619 if (itry1 == itry_max) {
1620 coord1.
set(10000.,10000.,10000.);
1621 coordinates.push_back(coord1);
1626 coord1 = -coordinates[0] - coordinates[1];
1627 if (verboseLevel > 2) {
1631 coordinates.push_back(coord1);
1633 G4bool large_dist =
false;
1635 for (i = 0; i < 2; i++) {
1636 for (
G4int j = i+1; j < 3; j++) {
1637 G4double r2 = (coordinates[i]-coordinates[j]).mag2();
1639 if (verboseLevel > 2) {
1640 G4cout <<
" i " << i <<
" j " << j <<
" r2 " << r2 <<
G4endl;
1643 if (r2 > r_large2for3) {
1650 if (large_dist)
break;
1653 if(!large_dist) badco =
false;
1660 G4double u = b1 + std::sqrt(b1 * b1 + b);
1663 while (badco && itry < itry_max) {
1665 if (itry > 0) coordinates.clear();
1669 for (i = 0; i < ab-1; i++) {
1673 while (itry1 < itry_max) {
1678 if (std::sqrt(ss) *
G4Exp(-ss) * (1.0 + ss/b) > u
1680 ss = r0forAeq4 * std::sqrt(ss);
1682 coordinates.push_back(coord1);
1684 if (verboseLevel > 2) {
1692 if (itry1 == itry_max) {
1693 coord1.
set(10000.,10000.,10000.);
1694 coordinates.push_back(coord1);
1700 for(
G4int j = 0; j < ab -1; j++) coord1 -= coordinates[j];
1702 coordinates.push_back(coord1);
1704 if (verboseLevel > 2){
1708 G4bool large_dist =
false;
1710 for (i = 0; i < ab-1; i++) {
1711 for (
G4int j = i+1; j < ab; j++) {
1713 G4double r2 = (coordinates[i]-coordinates[j]).mag2();
1715 if (verboseLevel > 2){
1716 G4cout <<
" i " << i <<
" j " << j <<
" r2 " << r2 <<
G4endl;
1719 if (r2 > r_large2for4) {
1726 if (large_dist)
break;
1729 if (!large_dist) badco =
false;
1734 G4cout <<
" can not generate the nucleons coordinates for a "
1737 casparticles.clear();
1746 for (
G4int i = 0; i < ab - 1; i++) {
1749 while(itry2 < itry_max) {
1755 p = std::sqrt(0.01953 * u);
1757 momentums.push_back(mom);
1763 if(itry2 == itry_max) {
1764 G4cout <<
" can not generate proper momentum for a "
1767 casparticles.clear();
1777 for(
G4int j=0; j< ab-1; j++) mom -= momentums[j];
1779 momentums.push_back(mom);
1787 for(i = 0; i <
G4int(coordinates.size()); i++) {
1788 G4double rp = coordinates[i].mag2();
1790 if(rp > rb) rb = rp;
1796 G4double rz = (nuclei_radius + rb) * s1;
1797 G4ThreeVector global_pos(rz*std::cos(phi), rz*std::sin(phi),
1798 -(nuclei_radius+rb)*std::sqrt(1.0-s1*s1));
1800 for (i = 0; i <
G4int(coordinates.size()); i++) {
1801 coordinates[i] += global_pos;
1805 raw_particles.clear();
1807 for (
G4int ipa = 0; ipa < ab; ipa++) {
1808 G4int knd = ipa < zb ? 1 : 2;
1818 for (ipart = raw_particles.begin(); ipart != raw_particles.end(); ipart++) {
1819 ipart->setMomentum(toTheBulletRestFrame.
backToTheLab(ipart->getMomentum()));
1824 for(
G4int ip = 0; ip <
G4int(raw_particles.size()); ip++) {
1828 G4double det = t0 * t0 + nuclei_radius * nuclei_radius
1829 - coordinates[ip].mag2();
1836 if(std::fabs(t1) <= std::fabs(t2)) {
1838 if(coordinates[ip].z() + mom.
z() * t1 / pmod <= 0.0) tr = t1;
1841 if(tr < 0.0 && t2 > 0.0) {
1843 if(coordinates[ip].z() + mom.
z() * t2 / pmod <= 0.0) tr = t2;
1849 if(coordinates[ip].z() + mom.
z() * t2 / pmod <= 0.0) tr = t2;
1852 if(tr < 0.0 && t1 > 0.0) {
1853 if(coordinates[ip].z() + mom.
z() * t1 / pmod <= 0.0) tr = t1;
1860 coordinates[ip] += mom.
vect()*tr / pmod;
1863 number_of_zones, large, 0));
1866 particles.push_back(raw_particles[ip]);
1871 if(casparticles.size() == 0) {
1874 G4cout <<
" can not generate proper distribution for " << itry_max
1880 if(verboseLevel > 2){
1883 G4cout <<
" cascad particles: " << casparticles.size() <<
G4endl;
1884 for(ip = 0; ip <
G4int(casparticles.size()); ip++)
1887 G4cout <<
" outgoing particles: " << particles.size() <<
G4endl;
1888 for(ip = 0; ip <
G4int(particles.size()); ip++)
1906 if (zone>=number_of_zones) zone = number_of_zones-1;
1913 dummy_convertor.setBullet(cparticle.
getParticle());
1914 dummy_convertor.setTarget(&target);
1915 dummy_convertor.toTheCenterOfMass();
1916 G4double ekin = dummy_convertor.getKinEnergyInTheTRS();
1922 if (verboseLevel > 2) {
1923 G4cout <<
" ip " << ip <<
" zone " << zone <<
" ekin " << ekin
1925 <<
" csec " << csec <<
G4endl;
1928 if (csec <= 0.)
return 0.;
1940 const G4double young_cut = std::sqrt(10.0) * 0.25;
1945 if (invmfp < small)
return spath;
1948 if (pw < -huge_num) pw = -huge_num;
1949 pw = 1.0 -
G4Exp(pw);
1951 if (verboseLevel > 2)
1952 G4cout <<
" mfp " << 1./invmfp <<
" pw " << pw <<
G4endl;
1957 if (cparticle.
young(young_cut, spath)) spath = large;
1959 if (verboseLevel > 2)
1960 G4cout <<
" spath " << spath <<
" path " << path <<
G4endl;
1971 G4cerr <<
"absorptionCrossSection() only valid for incident pions or gammas"
1982 if (ke < 0.3) csec = (0.1106 / std::sqrt(ke) - 0.8
1983 + 0.08 / ((ke-0.123)*(ke-0.123) + 0.0056) );
1984 else if (ke < 1.0) csec = 3.6735 * (1.0-ke)*(1.0-ke);
1988 csec = gammaQDinterp.interpolate(ke, gammaQDxsec) * gammaQDscale;
1991 if (csec < 0.0) csec = 0.0;
1993 if (verboseLevel > 2) {
1994 G4cout <<
" ekin " << ke <<
" abs. csec " << csec <<
" mb" <<
G4endl;
1997 return crossSectionUnits * csec;
2006 G4cerr <<
" unknown collison type = " << rtype <<
G4endl;
std::vector< G4InuclElementaryParticle >::iterator particleIterator
G4double epsilon(G4double density, G4double temperature)
G4double G4Exp(G4double initial_x)
Exponential Function double precision.
G4double G4Log(G4double x)
CLHEP::HepLorentzVector G4LorentzVector
CLHEP::Hep3Vector G4ThreeVector
G4GLOB_DLL std::ostream G4cerr
G4GLOB_DLL std::ostream G4cout
Hep3Vector cross(const Hep3Vector &) const
double angle(const Hep3Vector &) const
double dot(const Hep3Vector &) const
void set(double x, double y, double z)
Hep3Vector & rotate(double, const Hep3Vector &)
void setVect(const Hep3Vector &)
G4bool reflectedNow() const
G4int getGeneration() 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)
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)
void setNucleusState(G4int a, G4int z)
void collide(G4InuclParticle *bullet, G4InuclParticle *target, G4CollisionOutput &output)
static G4HadronicParameters * Instance()
G4bool IsBertiniNucleiModelAs11_2() const
G4bool quasi_deutron() const
static G4double getParticleMass(G4int type)
G4bool isNeutrino() const
G4double getKineticEnergy() const
G4double getEnergy() const
G4double getCharge() const
void toTheTargetRestFrame()
G4LorentzVector backToTheLab(const G4LorentzVector &mom) const
G4int getZone(G4double r) const
G4bool forceFirst(const G4CascadParticle &cparticle) const
G4double getRatio(G4int ip) const
G4double getDensity(G4int ip, G4int izone) const
G4CascadParticle initializeCascad(G4InuclElementaryParticle *particle)
G4bool worthToPropagate(const G4CascadParticle &cparticle) const
G4double generateInteractionLength(const G4CascadParticle &cparticle, G4double path, G4double invmfp) const
void generateParticleFate(G4CascadParticle &cparticle, G4ElementaryParticleCollider *theEPCollider, std::vector< G4CascadParticle > &cascade)
void setDinucleonDensityScale()
G4double inverseMeanFreePath(const G4CascadParticle &cparticle, const G4InuclElementaryParticle &target, G4int zone=-1)
void fillBindingEnergies()
G4double getCurrentDensity(G4int ip, G4int izone) const
std::pair< G4InuclElementaryParticle, G4double > partner
G4double fillZoneVolumes(G4double nuclearRadius)
G4InuclElementaryParticle generateNucleon(G4int type, G4int zone) const
void boundaryTransition(G4CascadParticle &cparticle)
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
G4bool passTrailing(const G4ThreeVector &hit_position)
static G4bool useQuasiDeuteron(G4int ptype, G4int qdtype=0)
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)
G4InuclElementaryParticle generateQuasiDeuteron(G4int type1, G4int type2, G4int zone) const
G4double zoneIntegralGaussian(G4double ur1, G4double ur2, G4double nuclearRadius) const
G4bool passFermi(const std::vector< G4InuclElementaryParticle > &particles, G4int zone)
std::pair< std::vector< G4CascadParticle >, std::vector< G4InuclElementaryParticle > > modelLists
G4double getFermiKinetic(G4int ip, G4int izone) const
std::vector< partner > thePartners
G4double zoneIntegralWoodsSaxon(G4double ur1, G4double ur2, G4double nuclearRadius) const
void fillZoneRadii(G4double nuclearRadius)
G4LorentzVector generateNucleonMomentum(G4int type, G4int zone) const
G4bool isProjectile(const G4CascadParticle &cparticle) const
static G4bool sortPartners(const partner &p1, const partner &p2)
void fillPotentials(G4int type, G4double tot_vol)
void generateInteractionPartners(G4CascadParticle &cparticle)
void choosePointAlongTraj(G4CascadParticle &cparticle)
static G4Pow * GetInstance()
G4double A13(G4double A) const
virtual void setVerboseLevel(G4int verbose=0)
G4bool nucleon(G4int ityp)
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)