32 [&particles](
const ParticleData &
p) { return particles.is_valid(p); });
50 " is pauli-blocked with f = ", f);
71 std::vector<ThreeVector> propagated_positions;
74 part.position().threevec() +
76 propagated_positions.push_back(propagated_position);
77 interaction_point += propagated_position;
92 const ThreeVector r = propagated_positions[0] - propagated_positions[1];
93 for (
int i = 0; i < 3; i++) {
94 const double d = std::abs(r[i]);
125 return std::make_pair(UB, UI3);
129 assert(id_process != 0);
130 double energy_violation = 0.;
134 p.set_history(
p.get_history().collisions_per_particle + 1, id_process,
146 logg[
LAction].debug(
"Particle map now has ", particles->
size(),
" elements.");
154 return energy_violation;
161 double scale_B = 0.0;
164 double scale_I3 = 0.0;
169 : std::make_pair(0.0, 0));
170 scale_B += scale.first;
171 scale_I3 += scale.second * p_in.type().isospin3_rel();
177 : std::make_pair(0.0, 0));
178 scale_B -= scale.first;
185 potentials.second * scale_I3;
192 ParticleList::iterator last_formed_in_part;
193 bool all_incoming_same_formation_time =
196 return std::abs(incoming_particles_[0].formation_time() -
197 data_comp.formation_time()) < really_small;
199 if (all_incoming_same_formation_time) {
200 last_formed_in_part =
203 return a.initial_xsec_scaling_factor() <
204 b.initial_xsec_scaling_factor();
207 last_formed_in_part =
210 return a.formation_time() < b.formation_time();
214 const double form_time_begin = last_formed_in_part->begin_formation_time();
215 const double sc = last_formed_in_part->initial_xsec_scaling_factor();
219 if (new_particle.initial_xsec_scaling_factor() < 1.0) {
224 double sc_out = new_particle.initial_xsec_scaling_factor();
225 new_particle.set_cross_section_scaling_factor(sc * sc_out);
226 if (last_formed_in_part->formation_time() >
227 new_particle.formation_time()) {
231 new_particle.set_slow_formation_times(
236 new_particle.set_slow_formation_times(
237 form_time_begin, last_formed_in_part->formation_time());
238 new_particle.set_cross_section_scaling_factor(sc);
243 if (new_particle.initial_xsec_scaling_factor() == 1.0) {
251 const double kinetic_energy_cm)
const {
255 std::pair<double, double> masses = {t_a.
mass(), t_b.
mass()};
262 reaction +
": not enough energy, " + std::to_string(kinetic_energy_cm) +
280 const double kinetic_energy_cm) {
284 const double pcm =
pCM(kinetic_energy_cm, masses.first, masses.second);
287 logg[
LAction].warn(
"Ektot: ", kinetic_energy_cm,
" m_a: ", masses.first,
288 " m_b: ", masses.second);
299 logg[
LAction].debug(
"p_a: ", *p_a,
"\np_b: ", *p_b);
306 const double cm_kin_energy = p_tot.
abs();
308 const std::pair<double, double> masses =
sample_masses(cm_kin_energy);
314 double sqrts,
const std::vector<double> &m,
315 std::vector<FourVector> &sampled_momenta) {
332 const size_t n = m.size();
334 sampled_momenta.resize(
n);
337 std::vector<double> msum(
n);
338 std::partial_sum(m.begin(), m.end(), msum.begin());
339 const double msum_all = msum[
n - 1];
340 int rejection_counter = -1;
341 if (sqrts <= msum_all) {
343 <<
"An interaction requiring " << sqrts
344 <<
"GeV was attempted below the minimum energy threshold" << msum_all
345 <<
" GeV, but was ignored.\nThis is a known internal error which does "
346 "not significantly affect physical results, and will be fixed in a "
347 "near-future release.";
352 std::vector<double> Minv(
n);
354 double weight_sqr_max = 1;
355 const double Ekin_share = (sqrts - msum_all) / (
n - 1);
356 for (
size_t i = 1; i <
n; i++) {
359 weight_sqr_max *=
pCM_sqr(i * Ekin_share + msum[i],
360 (i - 1) * Ekin_share + msum[i - 1], m[i]);
364 const double safety_factor = 1.1 + (
n - 2) * 0.2;
365 weight_sqr_max *= (safety_factor * safety_factor);
366 bool first_warning =
true;
372 Minv[
n - 1] = sqrts - msum_all;
373 for (
size_t i = 1; i <
n - 1; i++) {
376 std::sort(Minv.begin(), Minv.end());
377 for (
size_t i = 0; i <
n; i++) {
381 double weight_sqr = 1;
382 for (
size_t i = 1; i <
n; i++) {
383 weight_sqr *=
pCM_sqr(Minv[i], Minv[i - 1], m[i]);
388 w = weight_sqr / weight_sqr_max;
391 <<
"sample_manybody_phasespace_impl: alarm, weight > 1, w^2 = " << w
392 <<
". Increase safety factor." << std::endl;
394 if (rejection_counter > 20 && first_warning) {
395 logg[
LAction].warn() <<
"sample_manybody_phasespace_impl: "
396 <<
"likely hanging, way too many rejections,"
397 <<
" n = " <<
n <<
", sqrts = " << sqrts
398 <<
", msum = " << msum_all;
399 first_warning =
false;
401 }
while (w < r01 * r01);
404 std::vector<ThreeVector>
beta(
n);
405 for (
size_t i =
n - 1; i > 0; i--) {
406 const double pcm =
pCM(Minv[i], Minv[i - 1], m[i]);
410 sampled_momenta[i] =
FourVector(std::sqrt(m[i] * m[i] + pcm * pcm),
411 pcm * isotropic_unitvector);
413 beta[i - 2] = pcm * isotropic_unitvector /
414 std::sqrt(pcm * pcm + Minv[i - 1] * Minv[i - 1]);
417 sampled_momenta[0] =
FourVector(std::sqrt(m[0] * m[0] + pcm * pcm),
418 -pcm * isotropic_unitvector);
422 for (
size_t i = 0; i <
n - 2; i++) {
425 for (
size_t j = 0; j <= i + 1; j++) {
426 ptot += sampled_momenta[j];
428 logg[
LAction].debug() <<
"Total momentum of 0.." << i + 1 <<
" = "
429 << ptot.
threevec() <<
" and should be (0, 0, 0). "
433 for (
size_t j = 0; j <= i + 1; j++) {
434 sampled_momenta[j] = sampled_momenta[j].lorentz_boost(
beta[i]);
439 for (
size_t j = 0; j <
n; j++) {
440 ptot_all += sampled_momenta[j];
442 logg[
LAction].debug() <<
"Total 4-momentum = " << ptot_all <<
", should be ("
443 << sqrts <<
", 0, 0, 0)" << std::endl;
449 throw std::invalid_argument(
450 "sample_manybody_phasespace: number of outgoing particles should be 3 "
453 bool all_stable =
true;
454 for (
size_t i = 0; i <
n; i++) {
458 throw std::invalid_argument(
459 "sample_manybody_phasespace: Found resonance in to be sampled outgoing "
460 "particles, but assumes stable particles.");
463 std::vector<double> m(
n);
464 for (
size_t i = 0; i <
n; i++) {
467 std::vector<FourVector>
p(
n);
470 for (
size_t i = 0; i <
n; i++) {
478 double energy_violation = 0.;
479 if (before != after) {
480 std::stringstream particle_names;
482 particle_names <<
p.type().name();
484 particle_names <<
" vs. ";
486 particle_names <<
p.type().name();
488 particle_names <<
"\n";
494 logg[
LAction].warn() <<
"Conservation law violations due to Pythia\n"
495 << particle_names.str() << err_msg;
497 return energy_violation;
505 <<
"Conservation law violations of strong interaction in weak or "
507 << particle_names.str() << err_msg;
508 return energy_violation;
515 <<
"Conservation law violation, but we want it (Freeforall Action).\n"
516 << particle_names.str() << err_msg;
517 return energy_violation;
519 logg[
LAction].error() <<
"Conservation law violations detected\n"
520 << particle_names.str() << err_msg;
522 throw std::runtime_error(
"Conservation laws violated in photon process");
524 throw std::runtime_error(
"Conservation laws violated in process " +
525 std::to_string(id_process));
528 return energy_violation;
531 std::ostream &
operator<<(std::ostream &out,
const ActionList &actions) {
532 out <<
"ActionList {\n";
533 for (
const auto &a : actions) {
534 out <<
"- " << a <<
'\n';
Exception for a temporary bugfix for when multiparticle interactions do not have the necessary energy...
void sample_2body_phasespace()
Sample the full 2-body phase-space (masses, momenta, angles) in the center-of-mass frame for the fina...
FourVector total_momentum_of_outgoing_particles() const
Calculate the total kinetic momentum of the outgoing particles.
void assign_formation_time_to_outgoing_particles()
Assign the formation time to the outgoing particles.
virtual ~Action()
Virtual Destructor.
int stochastic_position_idx_
This stores a randomly-chosen index to an incoming particle.
std::pair< FourVector, FourVector > get_potential_at_interaction_point() const
Get the skyrme and asymmetry potential at the interaction point.
virtual void sample_angles(std::pair< double, double > masses, double kinetic_energy_cm)
Sample final-state momenta in general X->2 processes (here: using an isotropical angular distribution...
ParticleList outgoing_particles_
Initially this stores only the PDG codes of final-state particles.
const ParticleType & type_of_pout(const ParticleData &p_out) const
Get the type of a given particle.
FourVector total_momentum() const
Sum of 4-momenta of incoming particles.
virtual void sample_manybody_phasespace()
Sample the full n-body phase-space (masses, momenta, angles) in the center-of-mass frame for the fina...
const double time_of_execution_
Time at which the action is supposed to be performed (absolute time in the lab frame in fm).
virtual double perform(Particles *particles, uint32_t id_process)
Actually perform the action, e.g.
void update_incoming(const Particles &particles)
Update the incoming particles that are stored in this action to the state they have in the global par...
virtual double check_conservation(const uint32_t id_process) const
Check various conservation laws.
const ParticleList & incoming_particles() const
Get the list of particles that go into the action.
double sqrt_s() const
Determine the total energy in the center-of-mass frame [GeV].
double box_length_
Box length: needed to determine coordinates of collision correctly in case of collision through the w...
ParticleList incoming_particles_
List with data of incoming particles.
FourVector get_interaction_point() const
Get the interaction point.
virtual std::pair< double, double > sample_masses(double kinetic_energy_cm) const
Sample final-state masses in general X->2 processes (thus also fixing the absolute c....
ProcessType process_type_
type of process
bool is_valid(const Particles &particles) const
Check whether the action still applies.
static void sample_manybody_phasespace_impl(double sqrts, const std::vector< double > &m, std::vector< FourVector > &sampled_momenta)
Implementation of the full n-body phase-space sampling (masses, momenta, angles) in the center-of-mas...
bool is_pauli_blocked(const std::vector< Particles > &ensembles, const PauliBlocker &p_bl) const
Check if the action is Pauli-blocked.
Angles provides a common interface for generating directions: i.e., two angles that should be interpr...
ThreeVector threevec() const
void distribute_isotropically()
Populate the object with a new direction.
The FourVector class holds relevant values in Minkowski spacetime with (+, −, −, −) metric signature.
double abs() const
calculate the lorentz invariant absolute value
ThreeVector threevec() const
ParticleData contains the dynamic information of a certain particle.
PdgCode pdgcode() const
Get the pdgcode of the particle.
void set_4momentum(const FourVector &momentum_vector)
Set the particle's 4-momentum directly.
Particle type contains the static properties of a particle species.
double sample_resonance_mass(const double mass_stable, const double cms_energy, int L=0) const
Resonance mass sampling for 2-particle final state with one resonance (type given by 'this') and one ...
double min_mass_kinematic() const
The minimum mass of the resonance that is kinematically allowed.
const std::string & name() const
double isospin3_rel() const
std::pair< double, double > sample_resonance_masses(const ParticleType &t2, const double cms_energy, int L=0) const
Resonance mass sampling for 2-particle final state with two resonances.
The Particles class abstracts the storage and manipulation of particles.
void update(const ParticleList &old_state, ParticleList &new_state, bool do_replace)
Updates the Particles object, replacing the particles in old_state with the particles in new_state.
const ParticleData & lookup(const ParticleData &old_state) const
Returns the particle that is currently stored in this object given an old copy of that particle.
A class that stores parameters needed for Pauli blocking, tabulates necessary integrals and computes ...
double phasespace_dens(const ThreeVector &r, const ThreeVector &p, const std::vector< Particles > &ensembles, const PdgCode pdg, const ParticleList &disregard) const
Calculate phase-space density of a particle species at the point (r,p).
static std::pair< double, int > force_scale(const ParticleType &data)
Evaluates the scaling factor of the forces acting on the particles.
A container for storing conserved values.
FourVector momentum() const
std::string report_deviations(const std::vector< Particles > &ensembles) const
Checks if the current particle list has still the same values and reports about differences.
The ThreeVector class represents a physical three-vector with the components .
Collection of useful constants that are known at compile time.
std::ostream & operator<<(std::ostream &out, const ActionPtr &action)
Convenience: dereferences the ActionPtr to Action.
std::array< einhard::Logger<>, std::tuple_size< LogArea::AreaTuple >::value > logg
An array that stores all pre-configured Logger objects.
T beta(T a, T b)
Draws a random number from a beta-distribution, where probability density of is .
static constexpr int LPauliBlocking
T pCM(const T sqrts, const T mass_a, const T mass_b) noexcept
T pCM_sqr(const T sqrts, const T mass_a, const T mass_b) noexcept
constexpr std::uint32_t ID_PROCESS_PHOTON
Process ID for any photon process.
static constexpr int LAction
@ Freeforall
See here for a short description.
@ Decay
See here for a short description.
@ Wall
See here for a short description.
@ Elastic
See here for a short description.
@ StringHard
See here for a short description.
bool all_of(Container &&c, UnaryPredicate &&p)
Convenience wrapper for std::all_of that operates on a complete container.
Potentials * pot_pointer
Pointer to a Potential class.
RectangularLattice< FourVector > * UB_lat_pointer
Pointer to the skyrme potential on the lattice.
bool is_string_soft_process(ProcessType p)
Check if a given process type is a soft string excitation.
RectangularLattice< FourVector > * UI3_lat_pointer
Pointer to the symmmetry potential on the lattice.