196const G4double G4NucleiModel::small = 1.0e-9;
197const G4double G4NucleiModel::large = 1000.;
200const G4double G4NucleiModel::piTimes4thirds = pi*4./3.;
203const G4double G4NucleiModel::alfa3[3] = { 0.7, 0.3, 0.01 };
204const G4double G4NucleiModel::alfa6[6] = { 0.9, 0.6, 0.4, 0.2, 0.1, 0.05 };
207const G4double G4NucleiModel::pion_vp = 0.007;
208const G4double G4NucleiModel::pion_vp_small = 0.007;
209const G4double G4NucleiModel::kaon_vp = 0.015;
210const G4double G4NucleiModel::hyperon_vp = 0.030;
220 0.0, 0.0024, 0.0032, 0.0042, 0.0056, 0.0075, 0.01, 0.024, 0.075, 0.1,
221 0.13, 0.18, 0.24, 0.32, 0.42, 0.56, 0.75, 1.0, 1.3, 1.8,
222 2.4, 3.2, 4.2, 5.6, 7.5, 10.0, 13.0, 18.0, 24.0, 32.0 };
225 0.0, 0.7, 2.0, 2.2, 2.1, 1.8, 1.3, 0.4, 0.098, 0.071,
226 0.055, 0.055, 0.065, 0.045, 0.017, 0.007, 2.37e-3, 6.14e-4, 1.72e-4, 4.2e-5,
227 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 };
233 : verboseLevel(0), nuclei_radius(0.), nuclei_volume(0.), number_of_zones(0),
234 A(0), Z(0), theNucleus(0), neutronNumber(0), protonNumber(0),
235 neutronNumberCurrent(0), protonNumberCurrent(0), current_nucl1(0),
236 current_nucl2(0), gammaQDinterp(kebins),
239 skinDepth(0.611207*radiusUnits),
247 potentialThickness(1.0),
251 : verboseLevel(0), nuclei_radius(0.), nuclei_volume(0.), number_of_zones(0),
252 A(0), Z(0), theNucleus(0), neutronNumber(0), protonNumber(0),
253 neutronNumberCurrent(0), protonNumberCurrent(0), current_nucl1(0),
254 current_nucl2(0), gammaQDinterp(kebins),
257 skinDepth(0.611207*radiusUnits),
265 potentialThickness(1.0),
271 : verboseLevel(0), nuclei_radius(0.), nuclei_volume(0.), number_of_zones(0),
272 A(0), Z(0), theNucleus(0), neutronNumber(0), protonNumber(0),
273 neutronNumberCurrent(0), protonNumberCurrent(0), current_nucl1(0),
274 current_nucl2(0), gammaQDinterp(kebins),
277 skinDepth(0.611207*radiusUnits),
285 potentialThickness(1.0),
299 const std::vector<G4ThreeVector>* hitPoints) {
300 neutronNumberCurrent = neutronNumber - nHitNeutrons;
301 protonNumberCurrent = protonNumber - nHitProtons;
304 if (!hitPoints || !hitPoints->empty()) collisionPts.clear();
305 else collisionPts = *hitPoints;
317 G4cout <<
" >>> G4NucleiModel::generateModel A " << a <<
" Z " << z
322 if (a == A && z == Z) {
323 if (verboseLevel > 1)
G4cout <<
" model already generated" << z <<
G4endl;
333 neutronNumber = A - Z;
337 if (verboseLevel > 3) {
338 G4cout <<
" crossSectionUnits = " << crossSectionUnits <<
G4endl
339 <<
" radiusUnits = " << radiusUnits <<
G4endl
340 <<
" skinDepth = " << skinDepth <<
G4endl
341 <<
" radiusScale = " << radiusScale <<
G4endl
342 <<
" radiusScale2 = " << radiusScale2 <<
G4endl
343 <<
" radiusForSmall = " << radiusForSmall <<
G4endl
344 <<
" radScaleAlpha = " << radScaleAlpha <<
G4endl
345 <<
" fermiMomentum = " << fermiMomentum <<
G4endl
346 <<
" piTimes4thirds = " << piTimes4thirds <<
G4endl;
350 if (A>4) nuclearRadius = radiusScale*
G4cbrt(A) + radiusScale2/
G4cbrt(A);
351 else nuclearRadius = radiusForSmall * (A==4 ? radScaleAlpha : 1.);
354 number_of_zones = (
A < 5) ? 1 : (
A < 100) ? 3 : 6;
357 binding_energies.clear();
358 nucleon_densities.clear();
359 zone_potentials.clear();
360 fermi_momenta.clear();
362 zone_volumes.clear();
373 const std::vector<G4double> vp(number_of_zones, (
A>4)?pion_vp:pion_vp_small);
374 const std::vector<G4double> kp(number_of_zones, kaon_vp);
375 const std::vector<G4double> hp(number_of_zones, hyperon_vp);
377 zone_potentials.push_back(vp);
378 zone_potentials.push_back(kp);
379 zone_potentials.push_back(hp);
381 nuclei_radius = zone_radii.back();
382 nuclei_volume = std::accumulate(zone_volumes.begin(),zone_volumes.end(),0.);
391 if (verboseLevel > 1)
392 G4cout <<
" >>> G4NucleiModel::fillBindingEnergies" <<
G4endl;
398 binding_energies.push_back(std::fabs(
bindingEnergy(A-1,Z-1)-dm)/GeV);
399 binding_energies.push_back(std::fabs(
bindingEnergy(A-1,Z)-dm)/GeV);
405 if (verboseLevel > 1)
406 G4cout <<
" >>> G4NucleiModel::fillZoneRadii" <<
G4endl;
408 G4double skinRatio = nuclearRadius/skinDepth;
412 zone_radii.push_back(nuclearRadius);
416 G4double rSq = nuclearRadius * nuclearRadius;
417 G4double gaussRadius = std::sqrt(rSq * (1.0 - 1.0/A) + 6.4);
420 for (
G4int i = 0; i < number_of_zones; i++) {
422 zone_radii.push_back(gaussRadius * y);
425 }
else if (A < 100) {
427 for (
G4int i = 0; i < number_of_zones; i++) {
429 zone_radii.push_back(nuclearRadius + skinDepth * y);
434 for (
G4int i = 0; i < number_of_zones; i++) {
436 zone_radii.push_back(nuclearRadius + skinDepth * y);
445 if (verboseLevel > 1)
446 G4cout <<
" >>> G4NucleiModel::fillZoneVolumes" <<
G4endl;
452 tot_vol = zone_radii[0]*zone_radii[0]*zone_radii[0];
453 zone_volumes.push_back(tot_vol*piTimes4thirds);
458 PotentialType usePotential = (A < 12) ? Gaussian : WoodsSaxon;
460 for (
G4int i = 0; i < number_of_zones; i++) {
461 if (usePotential == WoodsSaxon) {
469 v1[i] = zone_radii[i]*zone_radii[i]*zone_radii[i];
470 if (i > 0) v1[i] -= zone_radii[i-1]*zone_radii[i-1]*zone_radii[i-1];
472 zone_volumes.push_back(v1[i]*piTimes4thirds);
480 if (verboseLevel > 1)
481 G4cout <<
" >>> G4NucleiModel::fillZoneVolumes(" << type <<
")" <<
G4endl;
488 const G4double dm = binding_energies[type-1];
490 rod.clear(); rod.reserve(number_of_zones);
491 pf.clear(); pf.reserve(number_of_zones);
492 vz.clear(); vz.reserve(number_of_zones);
494 G4int nNucleons = (type==
proton) ? protonNumber : neutronNumber;
495 G4double dd0 = nNucleons / tot_vol / piTimes4thirds;
497 for (
G4int i = 0; i < number_of_zones; i++) {
502 vz.push_back(0.5 * pff * pff / mass + dm);
505 nucleon_densities.push_back(rod);
506 fermi_momenta.push_back(pf);
507 zone_potentials.push_back(vz);
513 if (verboseLevel > 1) {
514 G4cout <<
" >>> G4NucleiModel::zoneIntegralWoodsSaxon" <<
G4endl;
518 const G4int itry_max = 1000;
520 G4double skinRatio = nuclearRadius / skinDepth;
533 while (itry < itry_max) {
540 for (
G4int i = 0; i < jc; i++) {
542 fi += r * (r + d2) / (1.0 +
G4Exp(r));
545 fun = 0.5 * fun1 + fi * dr;
547 if (std::fabs((fun - fun1) / fun) <=
epsilon)
break;
554 if (verboseLevel > 2 && itry == itry_max)
555 G4cout <<
" zoneIntegralWoodsSaxon-> n iter " << itry_max <<
G4endl;
557 G4double skinDepth3 = skinDepth*skinDepth*skinDepth;
559 return skinDepth3 * (fun + skinRatio*skinRatio*
G4Log((1.0 +
G4Exp(-r1)) / (1.0 +
G4Exp(-r2))));
566 if (verboseLevel > 1) {
567 G4cout <<
" >>> G4NucleiModel::zoneIntegralGaussian" <<
G4endl;
570 G4double gaussRadius = std::sqrt(nucRad*nucRad * (1.0 - 1.0/A) + 6.4);
573 const G4int itry_max = 1000;
585 while (itry < itry_max) {
591 for (
G4int i = 0; i < jc; i++) {
593 fi += r * r *
G4Exp(-r * r);
596 fun = 0.5 * fun1 + fi * dr;
598 if (std::fabs((fun - fun1) / fun) <=
epsilon)
break;
605 if (verboseLevel > 2 && itry == itry_max)
606 G4cerr <<
" zoneIntegralGaussian-> n iter " << itry_max <<
G4endl;
608 return gaussRadius*gaussRadius*gaussRadius * fun;
613 if (verboseLevel > 1) {
617 G4cout <<
" nuclei model for A " << A <<
" Z " << Z <<
G4endl
618 <<
" proton binding energy " << binding_energies[0]
619 <<
" neutron binding energy " << binding_energies[1] <<
G4endl
620 <<
" Nuclei radius " << nuclei_radius <<
" volume " << nuclei_volume
621 <<
" number of zones " << number_of_zones <<
G4endl;
623 for (
G4int i = 0; i < number_of_zones; i++)
624 G4cout <<
" zone " << i+1 <<
" radius " << zone_radii[i]
625 <<
" volume " << zone_volumes[i] <<
G4endl
626 <<
" protons: density " <<
getDensity(1,i) <<
" PF " <<
628 <<
" neutrons: density " <<
getDensity(2,i) <<
" PF " <<
637 if (ip < 3 && izone < number_of_zones) {
638 G4double pfermi = fermi_momenta[ip - 1][izone];
641 ekin = std::sqrt(pfermi*pfermi + mass*mass) - mass;
658 if (verboseLevel > 1) {
659 G4cout <<
" >>> G4NucleiModel::generateNucleon" <<
G4endl;
670 if (verboseLevel > 1) {
671 G4cout <<
" >>> G4NucleiModel::generateQuasiDeuteron" <<
G4endl;
685 if (type1*type2 ==
pro*
pro) dtype = 111;
686 else if (type1*type2 ==
pro*
neu) dtype = 112;
687 else if (type1*type2 ==
neu*
neu) dtype = 122;
695 if (verboseLevel > 1) {
696 G4cout <<
" >>> G4NucleiModel::generateInteractionPartners" <<
G4endl;
707 if (zone == number_of_zones) {
708 r_in = nuclei_radius;
710 }
else if (zone == 0) {
712 r_out = zone_radii[0];
714 r_in = zone_radii[zone - 1];
715 r_out = zone_radii[zone];
720 if (verboseLevel > 2) {
722 G4cout <<
" r_in " << r_in <<
" r_out " << r_out <<
" path " << path
728 G4cerr <<
" generateInteractionPartners-> negative path length" <<
G4endl;
732 if (std::fabs(path) < small) {
734 if (verboseLevel > 3)
735 G4cout <<
" generateInteractionPartners-> zero path" <<
G4endl;
741 if (zone >= number_of_zones)
742 zone = number_of_zones-1;
747 for (
G4int ip = 1; ip < 3; ip++) {
749 if (ip==
proton && protonNumberCurrent < 1)
continue;
750 if (ip==
neutron && neutronNumberCurrent < 1)
continue;
758 if (path<small || spath < path) {
759 if (verboseLevel > 3) {
767 if (verboseLevel > 2) {
773 if (verboseLevel > 2) {
774 G4cout <<
" trying quasi-deuterons with bullet: "
785 if (protonNumberCurrent >= 2 && ptype !=
pip) {
787 if (verboseLevel > 2)
788 G4cout <<
" ptype=" << ptype <<
" using pp target\n" << ppd <<
G4endl;
791 tot_invmfp += invmfp;
792 acsecs.push_back(invmfp);
793 qdeutrons.push_back(ppd);
797 if (protonNumberCurrent >= 1 && neutronNumberCurrent >= 1) {
799 if (verboseLevel > 2)
800 G4cout <<
" ptype=" << ptype <<
" using np target\n" << npd <<
G4endl;
803 tot_invmfp += invmfp;
804 acsecs.push_back(invmfp);
805 qdeutrons.push_back(npd);
809 if (neutronNumberCurrent >= 2 && ptype !=
pim && ptype !=
mum) {
811 if (verboseLevel > 2)
812 G4cout <<
" ptype=" << ptype <<
" using nn target\n" << nnd <<
G4endl;
815 tot_invmfp += invmfp;
816 acsecs.push_back(invmfp);
817 qdeutrons.push_back(nnd);
821 if (verboseLevel > 2) {
822 for (std::size_t i=0; i<qdeutrons.size(); i++) {
823 G4cout <<
" acsecs[" << qdeutrons[i].getDefinition()->GetParticleName()
824 <<
"] " << acsecs[i];
829 if (tot_invmfp > small) {
832 if (path<small || apath < path) {
836 for (std::size_t i = 0; i < qdeutrons.size(); i++) {
839 if (verboseLevel > 2)
850 if (verboseLevel > 2) {
867 std::vector<G4CascadParticle>& outgoing_cparticles) {
868 if (verboseLevel > 1)
869 G4cout <<
" >>> G4NucleiModel::generateParticleFate" <<
G4endl;
871 if (verboseLevel > 2)
G4cout <<
" cparticle: " << cparticle <<
G4endl;
874#ifdef G4CASCADE_CHECK_ECONS
879 outgoing_cparticles.clear();
884 G4cerr <<
" generateParticleFate-> got empty interaction-partners list "
892 if (verboseLevel > 1)
893 G4cout <<
" no interactions; moving to next zone" <<
G4endl;
898 outgoing_cparticles.push_back(cparticle);
900 if (verboseLevel > 2)
G4cout <<
" next zone \n" << cparticle <<
G4endl;
909 if (verboseLevel > 1)
910 G4cout <<
" processing " << npart-1 <<
" possible interactions" <<
G4endl;
914 G4bool no_interaction =
true;
917 for (std::size_t i=0; i<npart-1; ++i) {
922 if (verboseLevel > 3) {
924 G4cout <<
" target " << target.
type() <<
" bullet " << bullet.
type()
930 G4int massNumberCurrent = protonNumberCurrent+neutronNumberCurrent;
931 theEPCollider->
setNucleusState(massNumberCurrent, protonNumberCurrent);
932 theEPCollider->
collide(&bullet, &target, EPCoutput);
937 if (verboseLevel > 2) {
939#ifdef G4CASCADE_CHECK_ECONS
940 balance.
collide(&bullet, &target, EPCoutput);
946 std::vector<G4InuclElementaryParticle>& outgoing_particles =
949 if (!
passFermi(outgoing_particles, zone))
continue;
956 collisionPts.push_back(new_position);
959 std::sort(outgoing_particles.begin(), outgoing_particles.end(),
962 if (verboseLevel > 2)
963 G4cout <<
" adding " << outgoing_particles.size()
964 <<
" output particles" <<
G4endl;
968 for (std::size_t ip = 0; ip < outgoing_particles.size(); ++ip) {
974 no_interaction =
false;
978#ifdef G4CASCADE_DEBUG_CHARGE
982 for (
G4int ip = 0; ip <
G4int(outgoing_particles.size()); ip++)
983 out_charge += outgoing_particles[ip].getCharge();
985 G4cout <<
" multiplicity " << outgoing_particles.size()
986 <<
" bul type " << bullet.
type()
987 <<
" targ type " << target.
type()
988 <<
"\n initial charge "
990 <<
" out charge " << out_charge <<
G4endl;
994 if (verboseLevel > 2)
998 current_nucl1 = target.
type();
1000 if (verboseLevel > 2)
G4cout <<
" good absorption " <<
G4endl;
1001 current_nucl1 = (target.
type() - 100) / 10;
1002 current_nucl2 = target.
type() - 100 - 10 * current_nucl1;
1005 if (current_nucl1 == 1) {
1006 if (verboseLevel > 3)
G4cout <<
" decrement proton count" <<
G4endl;
1007 protonNumberCurrent--;
1009 if (verboseLevel > 3)
G4cout <<
" decrement neutron count" <<
G4endl;
1010 neutronNumberCurrent--;
1013 if (current_nucl2 == 1) {
1014 if (verboseLevel > 3)
G4cout <<
" decrement proton count" <<
G4endl;
1015 protonNumberCurrent--;
1016 }
else if (current_nucl2 == 2) {
1017 if (verboseLevel > 3)
G4cout <<
" decrement neutron count" <<
G4endl;
1018 neutronNumberCurrent--;
1024 if (no_interaction) {
1025 if (verboseLevel > 1)
G4cout <<
" no interaction " <<
G4endl;
1029 if (!prescatCP_G4MT_TLS_) {
1041 outgoing_cparticles.push_back(cparticle);
1044#ifdef G4CASCADE_CHECK_ECONS
1045 if (verboseLevel > 2) {
1046 balance.
collide(&prescatCP, 0, outgoing_cparticles);
1058 if (qdtype==
pn || qdtype==0)
1059 return (ptype==
pi0 || ptype==
pip || ptype==
pim || ptype==
gam || ptype==
mum);
1060 else if (qdtype==
pp)
1061 return (ptype==
pi0 || ptype==
pim || ptype==
gam || ptype==
mum);
1062 else if (qdtype==
nn)
1063 return (ptype==
pi0 || ptype==
pip || ptype==
gam);
1071 if (verboseLevel > 1) {
1076 for (
G4int i = 0; i <
G4int(particles.size()); i++) {
1077 if (!particles[i].
nucleon())
continue;
1079 G4int type = particles[i].type();
1080 G4double mom = particles[i].getMomModule();
1081 G4double pfermi = fermi_momenta[type-1][zone];
1083 if (verboseLevel > 2)
1084 G4cout <<
" type " << type <<
" p " << mom <<
" pf " << pfermi <<
G4endl;
1087 if (verboseLevel > 2)
G4cout <<
" rejected by Fermi" <<
G4endl;
1099 if (verboseLevel > 1)
1100 G4cout <<
" >>> G4NucleiModel::passTrailing " << hit_position <<
G4endl;
1103 for (
G4int i = 0; i <
G4int(collisionPts.size() ); i++) {
1104 dist = (collisionPts[i] - hit_position).mag();
1105 if (verboseLevel > 2)
G4cout <<
" dist " << dist <<
G4endl;
1106 if (dist < R_nucleon) {
1107 if (verboseLevel > 2)
G4cout <<
" rejected by Trailing" <<
G4endl;
1116 if (verboseLevel > 1) {
1117 G4cout <<
" >>> G4NucleiModel::boundaryTransition" <<
G4endl;
1123 if (verboseLevel)
G4cerr <<
" boundaryTransition-> in zone 0 " <<
G4endl;
1141 if (verboseLevel > 3) {
1142 G4cout <<
"Potentials for type " << type <<
" = "
1147 G4double qv = dv*dv + 2.0*dv*mom.
e() + pr*pr;
1153 G4double qperp = 2.0*pperp2*potentialThickness/r;
1155 if (verboseLevel > 3) {
1156 G4cout <<
" type " << type <<
" zone " << zone <<
" next " << next_zone
1157 <<
" qv " << qv <<
" dv " << dv <<
G4endl;
1160 G4bool adjustpperp =
false;
1164 if (qv <= 0.0 && qv+qperp <=0 ) {
1165 if (verboseLevel > 3)
G4cout <<
" reflects off boundary" <<
G4endl;
1170 }
else if (qv > 0.0) {
1171 if (verboseLevel > 3)
G4cout <<
" passes thru boundary" <<
G4endl;
1172 p1r = std::sqrt(qv);
1173 if (pr < 0.0) p1r = -p1r;
1178 if (verboseLevel > 3)
G4cout <<
" passes thru boundary due to angular momentum" <<
G4endl;
1179 p1r = smallish * pr;
1188 if (verboseLevel > 3) {
1189 G4cout <<
" prr " << prr <<
" delta px " << prr*
pos.x() <<
" py "
1190 << prr*
pos.y() <<
" pz " << prr*
pos.z() <<
" mag "
1191 << std::fabs(prr*r) <<
G4endl;
1196 G4double new_pperp_mag = std::sqrt(std::max(0.0, pperp2 + qv - p1r*p1r) );
1198 mom.
setVect(old_pperp * new_pperp_mag/std::sqrt(pperp2));
1213 if (verboseLevel > 1)
1214 G4cout <<
" >>> G4NucleiModel::choosePointAlongTraj" <<
G4endl;
1226 if (verboseLevel > 3)
1227 G4cout <<
" pos " <<
pos <<
" phat " << phat <<
" rhat " << rhat <<
G4endl;
1232 if (prang < 1e-6) posout = -
pos;
1236 if (verboseLevel > 3)
G4cout <<
" posrot " << posrot/deg <<
" deg";
1239 if (verboseLevel > 3)
G4cout <<
" posout " << posout <<
G4endl;
1246 G4int zoneout = number_of_zones-1;
1250 G4int ncross = (number_of_zones-zonemid)*2;
1252 if (verboseLevel > 3) {
1253 G4cout <<
" posmid " << posmid <<
" lenmid " << lenmid
1254 <<
" zoneout " << zoneout <<
" zonemid " << zonemid
1255 <<
" ncross " << ncross <<
G4endl;
1259 std::vector<G4double> wtlen(ncross,0.);
1260 std::vector<G4double> len(ncross,0.);
1264 for (i=0; i<ncross/2; i++) {
1265 G4int iz = zoneout-i;
1266 G4double ds = std::sqrt(zone_radii[iz]*zone_radii[iz]-r2mid);
1268 len[i] = lenmid - ds;
1269 len[ncross-1-i] = lenmid + ds;
1271 if (verboseLevel > 3) {
1272 G4cout <<
" i " << i <<
" iz " << iz <<
" ds " << ds
1273 <<
" len " << len[i] <<
G4endl;
1278 for (i=1; i<ncross; i++) {
1279 G4int iz = (i<ncross/2) ? zoneout-i+1 : zoneout-ncross+i+1;
1293 wtlen[i] = wtlen[i-1] + wt;
1295 if (verboseLevel > 3) {
1296 G4cout <<
" i " << i <<
" iz " << iz <<
" avg.mfp " << 1./invmfp
1297 <<
" dlen " << dlen <<
" wt " << wt <<
" wtlen " << wtlen[i]
1303 std::transform(wtlen.begin(), wtlen.end(), wtlen.begin(),
1304 std::bind(std::divides<G4double>(), std::placeholders::_1, wtlen.back()));
1306 if (verboseLevel > 3) {
1308 for (i=0; i<ncross; i++)
G4cout <<
" " << wtlen[i];
1314 G4long ir = std::upper_bound(wtlen.begin(),wtlen.end(),rand) - wtlen.begin();
1316 G4double frac = (rand-wtlen[ir-1]) / (wtlen[ir]-wtlen[ir-1]);
1317 G4double drand = (1.-frac)*len[ir-1] + frac*len[ir];
1319 if (verboseLevel > 3) {
1320 G4cout <<
" rand " << rand <<
" ir " << ir <<
" frac " << frac
1321 <<
" drand " << drand <<
G4endl;
1324 pos += drand * phat;
1330 if (verboseLevel > 2) {
1350 if (verboseLevel > 1) {
1351 G4cout <<
" >>> G4NucleiModel::worthToPropagate" <<
G4endl;
1368 if (verboseLevel > 3) {
1371 <<
" potential=" << ekin_cut
1372 <<
" : worth? " << worth <<
G4endl;
1381 if (verboseLevel > 4) {
1382 G4cout <<
" >>> G4NucleiModel::getRatio " << ip <<
G4endl;
1426 if (verboseLevel > 1) {
1427 G4cout <<
" >>> G4NucleiModel::initializeCascad(particle)" <<
G4endl;
1437 G4int zone = number_of_zones;
1454 G4cout <<
" >>> G4NucleiModel::initializeCascad(bullet,target,output)"
1458 const G4double max_a_for_cascad = 5.0;
1460 const G4double small_ekin = 1.0e-6;
1461 const G4double r_large2for3 = 62.0;
1464 const G4double r_large2for4 = 69.14;
1467 const G4int itry_max = 100;
1470 std::vector<G4CascadParticle>& casparticles = output.first;
1471 std::vector<G4InuclElementaryParticle>& particles = output.second;
1473 casparticles.clear();
1484 if (ab < max_a_for_cascad) {
1488 G4double ben = benb < bent ? bent : benb;
1494 while (casparticles.size() == 0 && itryg < itry_max) {
1499 coordinates.clear();
1505 coordinates.push_back(coord1);
1506 coordinates.push_back(-coord1);
1512 while (bad && itry < itry_max) {
1516 if (p * p / (p * p + 2079.36) / (p * p + 2079.36) > 1.2023e-4 *
inuclRndm() &&
1517 p * r > 312.0) bad =
false;
1520 if (itry == itry_max)
1521 if (verboseLevel > 2){
1522 G4cout <<
" deutron bullet generation-> itry = " << itry_max <<
G4endl;
1527 if (verboseLevel > 2){
1533 momentums.push_back(mom);
1535 momentums.push_back(-mom);
1544 while (badco && itry < itry_max) {
1545 if (itry > 0) coordinates.clear();
1549 for (i = 0; i < 2; i++) {
1554 while (itry1 < itry_max) {
1558 rho = std::sqrt(ss) *
G4Exp(-ss);
1560 if (rho > u && ss < s3max) {
1561 ss = r0forAeq3 * std::sqrt(ss);
1563 coordinates.push_back(coord1);
1565 if (verboseLevel > 2){
1572 if (itry1 == itry_max) {
1573 coord1.
set(10000.,10000.,10000.);
1574 coordinates.push_back(coord1);
1579 coord1 = -coordinates[0] - coordinates[1];
1580 if (verboseLevel > 2) {
1584 coordinates.push_back(coord1);
1586 G4bool large_dist =
false;
1588 for (i = 0; i < 2; i++) {
1589 for (
G4int j = i+1; j < 3; j++) {
1590 G4double r2 = (coordinates[i]-coordinates[j]).mag2();
1592 if (verboseLevel > 2) {
1593 G4cout <<
" i " << i <<
" j " << j <<
" r2 " << r2 <<
G4endl;
1596 if (r2 > r_large2for3) {
1603 if (large_dist)
break;
1606 if(!large_dist) badco =
false;
1613 G4double u = b1 + std::sqrt(b1 * b1 + b);
1616 while (badco && itry < itry_max) {
1618 if (itry > 0) coordinates.clear();
1622 for (i = 0; i < ab-1; i++) {
1626 while (itry1 < itry_max) {
1631 if (std::sqrt(ss) *
G4Exp(-ss) * (1.0 + ss/b) > u
1633 ss = r0forAeq4 * std::sqrt(ss);
1635 coordinates.push_back(coord1);
1637 if (verboseLevel > 2) {
1645 if (itry1 == itry_max) {
1646 coord1.
set(10000.,10000.,10000.);
1647 coordinates.push_back(coord1);
1653 for(
G4int j = 0; j < ab -1; j++) coord1 -= coordinates[j];
1655 coordinates.push_back(coord1);
1657 if (verboseLevel > 2){
1661 G4bool large_dist =
false;
1663 for (i = 0; i < ab-1; i++) {
1664 for (
G4int j = i+1; j < ab; j++) {
1666 G4double r2 = (coordinates[i]-coordinates[j]).mag2();
1668 if (verboseLevel > 2){
1669 G4cout <<
" i " << i <<
" j " << j <<
" r2 " << r2 <<
G4endl;
1672 if (r2 > r_large2for4) {
1679 if (large_dist)
break;
1682 if (!large_dist) badco =
false;
1687 G4cout <<
" can not generate the nucleons coordinates for a "
1690 casparticles.clear();
1699 for (
G4int i = 0; i < ab - 1; i++) {
1702 while(itry2 < itry_max) {
1708 p = std::sqrt(0.01953 * u);
1710 momentums.push_back(mom);
1716 if(itry2 == itry_max) {
1717 G4cout <<
" can not generate proper momentum for a "
1720 casparticles.clear();
1730 for(
G4int j=0; j< ab-1; j++) mom -= momentums[j];
1732 momentums.push_back(mom);
1740 for(i = 0; i <
G4int(coordinates.size()); i++) {
1741 G4double rp = coordinates[i].mag2();
1743 if(rp > rb) rb = rp;
1749 G4double rz = (nuclei_radius + rb) * s1;
1750 G4ThreeVector global_pos(rz*std::cos(phi), rz*std::sin(phi),
1751 -(nuclei_radius+rb)*std::sqrt(1.0-s1*s1));
1753 for (i = 0; i <
G4int(coordinates.size()); i++) {
1754 coordinates[i] += global_pos;
1758 raw_particles.clear();
1760 for (
G4int ipa = 0; ipa < ab; ipa++) {
1761 G4int knd = ipa < zb ? 1 : 2;
1771 for (ipart = raw_particles.begin(); ipart != raw_particles.end(); ipart++) {
1772 ipart->setMomentum(toTheBulletRestFrame.
backToTheLab(ipart->getMomentum()));
1777 for(
G4int ip = 0; ip <
G4int(raw_particles.size()); ip++) {
1781 G4double det = t0 * t0 + nuclei_radius * nuclei_radius
1782 - coordinates[ip].mag2();
1789 if(std::fabs(t1) <= std::fabs(t2)) {
1791 if(coordinates[ip].z() + mom.
z() * t1 / pmod <= 0.0) tr = t1;
1794 if(tr < 0.0 && t2 > 0.0) {
1796 if(coordinates[ip].z() + mom.
z() * t2 / pmod <= 0.0) tr = t2;
1802 if(coordinates[ip].z() + mom.
z() * t2 / pmod <= 0.0) tr = t2;
1805 if(tr < 0.0 && t1 > 0.0) {
1806 if(coordinates[ip].z() + mom.
z() * t1 / pmod <= 0.0) tr = t1;
1813 coordinates[ip] += mom.
vect()*tr / pmod;
1816 number_of_zones, large, 0));
1819 particles.push_back(raw_particles[ip]);
1824 if(casparticles.size() == 0) {
1827 G4cout <<
" can not generate proper distribution for " << itry_max
1833 if(verboseLevel > 2){
1836 G4cout <<
" cascad particles: " << casparticles.size() <<
G4endl;
1837 for(ip = 0; ip <
G4int(casparticles.size()); ip++)
1840 G4cout <<
" outgoing particles: " << particles.size() <<
G4endl;
1841 for(ip = 0; ip <
G4int(particles.size()); ip++)
1859 if (zone>=number_of_zones) zone = number_of_zones-1;
1875 if (verboseLevel > 2) {
1876 G4cout <<
" ip " << ip <<
" zone " << zone <<
" ekin " << ekin
1878 <<
" csec " << csec <<
G4endl;
1881 if (csec <= 0.)
return 0.;
1893 const G4double young_cut = std::sqrt(10.0) * 0.25;
1898 if (invmfp < small)
return spath;
1901 if (pw < -huge_num) pw = -huge_num;
1902 pw = 1.0 -
G4Exp(pw);
1904 if (verboseLevel > 2)
1905 G4cout <<
" mfp " << 1./invmfp <<
" pw " << pw <<
G4endl;
1910 if (cparticle.
young(young_cut, spath)) spath = large;
1912 if (verboseLevel > 2)
1913 G4cout <<
" spath " << spath <<
" path " << path <<
G4endl;
1924 G4cerr <<
"absorptionCrossSection() only valid for incident pions or gammas"
1935 if (ke < 0.3) csec = (0.1106 / std::sqrt(ke) - 0.8
1936 + 0.08 / ((ke-0.123)*(ke-0.123) + 0.0056) );
1937 else if (ke < 1.0) csec = 3.6735 * (1.0-ke)*(1.0-ke);
1941 csec = gammaQDinterp.
interpolate(ke, gammaQDxsec) * gammaQDscale;
1944 if (csec < 0.0) csec = 0.0;
1946 if (verboseLevel > 2) {
1947 G4cout <<
" ekin " << ke <<
" abs. csec " << csec <<
" mb" <<
G4endl;
1950 return crossSectionUnits * csec;
1959 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)
std::vector< G4InuclElementaryParticle >::iterator particleIterator
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)
G4double interpolate(const G4double x, const G4double(&yb)[nBins]) const
G4int numberOfOutgoingParticles() const
void printCollisionOutput(std::ostream &os=G4cout) const
const std::vector< G4InuclElementaryParticle > & getOutgoingParticles() const
void setNucleusState(G4int a, G4int z)
void collide(G4InuclParticle *bullet, G4InuclParticle *target, G4CollisionOutput &output)
G4bool quasi_deutron() const
static G4double getParticleMass(G4int type)
G4bool isNeutrino() const
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)
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)
G4double inverseMeanFreePath(const G4CascadParticle &cparticle, const G4InuclElementaryParticle &target, G4int zone=-1)
void fillBindingEnergies()
G4double getCurrentDensity(G4int ip, G4int izone) const
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)
std::pair< G4InuclElementaryParticle, G4double > partner
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
std::pair< std::vector< G4CascadParticle >, std::vector< G4InuclElementaryParticle > > modelLists
G4double zoneIntegralGaussian(G4double ur1, G4double ur2, G4double nuclearRadius) const
G4bool passFermi(const std::vector< G4InuclElementaryParticle > &particles, G4int zone)
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)
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)