Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
95 commits
Select commit Hold shift + click to select a range
06ae298
Implement get_pdf functionality
Aug 27, 2025
78d841e
Update include/openmc/distribution.h
itay-space Aug 28, 2025
33a27a9
Update include/openmc/particle_data.h
itay-space Aug 28, 2025
d968875
Update include/openmc/particle_data.h
itay-space Aug 28, 2025
3b896c0
Update src/physics.cpp
itay-space Aug 28, 2025
c034bff
Update src/physics.cpp
itay-space Aug 28, 2025
a5d2f4c
Update src/physics.cpp
itay-space Aug 28, 2025
ca5b44e
Cleaning some code
Aug 31, 2025
eed8b1c
Resolving conversations
Aug 31, 2025
f2ecdd4
cosmetic fixes
GuySten Aug 31, 2025
71d5fa2
Merge branch 'develop' into get_pdf
GuySten Aug 31, 2025
c3b4d82
simplified code significantly
GuySten Aug 31, 2025
78a33cc
Update src/distribution_angle.cpp
itay-space Aug 31, 2025
6d70d39
ran clang format
GuySten Aug 31, 2025
acfd402
fixes
GuySten Aug 31, 2025
98ca32e
cosmetics
GuySten Aug 31, 2025
26d2a56
using openmc's fatal_error
Sep 1, 2025
7abe69c
Use accessors in powerlaw
Sep 1, 2025
d183cce
clausing error for different distributions
Sep 1, 2025
37b41c4
fixing function signature
Sep 1, 2025
007dcf5
Update include/openmc/angle_energy.h
Eliezer214 Sep 2, 2025
ebebb7a
Update include/openmc/distribution_angle.h
Eliezer214 Sep 2, 2025
0239c1f
Update include/openmc/secondary_thermal.h
Eliezer214 Sep 2, 2025
225f837
Update include/openmc/angle_energy.h
Eliezer214 Sep 2, 2025
fa22e14
Update include/openmc/reaction_product.h
Eliezer214 Sep 2, 2025
a0678c9
Update src/reaction_product.cpp
itay-space Sep 2, 2025
e590d82
Update src/thermal.cpp
itay-space Sep 2, 2025
1b1134e
Update include/openmc/secondary_thermal.h
itay-space Sep 2, 2025
5c348f1
Update src/secondary_uncorrelated.cpp
itay-space Sep 2, 2025
203a191
Update src/secondary_thermal.cpp
itay-space Sep 2, 2025
c4d8aa6
Update include/openmc/secondary_thermal.h
itay-space Sep 2, 2025
e9b6860
Update src/reaction_product.cpp
itay-space Sep 2, 2025
ee1f2c5
Apply suggestion from @GuySten
itay-space Sep 2, 2025
e07e312
Apply suggestion from @GuySten
itay-space Sep 2, 2025
1ab0da1
Update src/thermal.cpp
itay-space Sep 2, 2025
c98566a
Update src/thermal.cpp
itay-space Sep 2, 2025
de3fc79
Update include/openmc/reaction_product.h
itay-space Sep 2, 2025
978bf74
remove gsl-lite
GuySten Sep 2, 2025
eb8389d
few fixes to signature
Sep 2, 2025
220f099
more signature fixes
Sep 2, 2025
d9a2b53
more signature fixes
Sep 2, 2025
8271e15
ran clang format
GuySten Sep 2, 2025
d0d8494
Restore PDF calculation block in secondary_kalbach.cpp after accident…
Sep 2, 2025
f2418d2
cleaning
Sep 2, 2025
9a5d701
remove gsl-lite
GuySten Sep 2, 2025
3f91b0d
clean
Sep 2, 2025
e1d069c
Update src/secondary_correlated.cpp
itay-space Sep 2, 2025
f9e4693
Update include/openmc/secondary_thermal.h
GuySten Sep 2, 2025
b45dcfd
ran clang format
GuySten Sep 2, 2025
a85365c
Update src/secondary_kalbach.cpp
GuySten Sep 2, 2025
d782013
returning pdf assuming data in lab
Sep 2, 2025
c72bb02
cleaning
Sep 2, 2025
3cb6821
remove gsl-lite
GuySten Sep 2, 2025
47e96a6
Apply suggestions from code review
GuySten Sep 2, 2025
f97f4ad
Update secondary_nbody.cpp
GuySten Sep 2, 2025
1e4b763
ran clang format
GuySten Sep 2, 2025
3bc4698
Update src/secondary_kalbach.cpp
itay-space Sep 3, 2025
4e85033
returning pdf
Sep 3, 2025
6727a03
Update src/secondary_nbody.cpp
itay-space Sep 3, 2025
c5a737b
isotropic and no lab yet
Sep 3, 2025
186ad34
Update src/distribution_angle.cpp
itay-space Sep 3, 2025
108fa52
remove gsl-lite
GuySten Sep 2, 2025
0f40022
ran clang format
GuySten Sep 3, 2025
4bf8f23
Update include/openmc/distribution_angle.h
GuySten Sep 3, 2025
ca7cd85
returning pdf in uncorrelated
Sep 3, 2025
d7b1621
fix access to get_pdf
GuySten Sep 3, 2025
7cb99e8
ran clang format
GuySten Sep 3, 2025
e2de1c4
cosmetics
GuySten Sep 3, 2025
d5ea1c0
WIP: trying new approach until reaction_product.cpp
GuySten Sep 4, 2025
dc87a7f
fix additional signatures
GuySten Sep 4, 2025
ad86823
wip
GuySten Sep 4, 2025
4500491
reverted most of the changes in the new approach
GuySten Sep 4, 2025
7a1b5cc
bugfix
GuySten Sep 4, 2025
ae2a0fb
bugfix
GuySten Sep 4, 2025
f3aa6dc
bugfix
GuySten Sep 4, 2025
52feef7
another fix for mixed elastic
GuySten Sep 4, 2025
12d5372
guarantee every AngleEnergy has sample_energy_and_pdf
GuySten Sep 4, 2025
ff83fc4
fix for decay photons
GuySten Sep 4, 2025
f859882
replace pdf->evaluate
GuySten Sep 6, 2025
b0613dc
Merge branch 'develop' into get_pdf
GuySten Nov 3, 2025
8bb4356
Merge branch 'develop' into get_pdf
GuySten Nov 3, 2025
cc7c3a5
added evaluate for SphericalUnitDistribution
GuySten Nov 3, 2025
758a01f
Merge branch 'develop' into get_pdf
GuySten Dec 3, 2025
481901e
simplify PR significantly
GuySten Dec 3, 2025
b067e7f
Merge branch 'develop' into get_pdf
GuySten Dec 23, 2025
43a6fbb
some fixes
GuySten Jan 12, 2026
c52ad4f
further simplification
GuySten Jan 16, 2026
f9d6d0f
further simplification
GuySten Jan 16, 2026
dc38dc5
further simplification
GuySten Jan 16, 2026
02aea31
reserve vector sizes
GuySten Jan 16, 2026
f14005a
Fix mu_vector reservation size in secondary_thermal.cpp
GuySten Jan 17, 2026
903af78
clang format
GuySten Jan 17, 2026
20ec56b
Merge branch 'develop' into get_pdf
GuySten Jan 29, 2026
64e23e3
fix for invalid energy distribution in elastic scattering case
GuySten Jan 29, 2026
1f36c89
Refactor probability sampling logic in reaction_product
GuySten Jan 29, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions include/openmc/angle_energy.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ class AngleEnergy {
public:
virtual void sample(
double E_in, double& E_out, double& mu, uint64_t* seed) const = 0;
virtual double sample_energy_and_pdf(
double E_in, double mu, double& E_out, uint64_t* seed) const = 0;
virtual ~AngleEnergy() = default;
};

Expand Down
2 changes: 2 additions & 0 deletions include/openmc/chain.h
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,8 @@ class DecayPhotonAngleEnergy : public AngleEnergy {
//! \param[inout] seed Pseudorandom seed pointer
void sample(
double E_in, double& E_out, double& mu, uint64_t* seed) const override;
double sample_energy_and_pdf(
double E_in, double mu, double& E_out, uint64_t* seed) const override;

private:
const Distribution* photon_energy_;
Expand Down
1 change: 1 addition & 0 deletions include/openmc/distribution_angle.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ class AngleDistribution {
//! \param[inout] seed pseudorandom number seed pointer
//! \return Cosine of the angle in the range [-1,1]
double sample(double E, uint64_t* seed) const;
double evaluate(double E, double mu) const;

//! Determine whether angle distribution is empty
//! \return Whether distribution is empty
Expand Down
10 changes: 10 additions & 0 deletions include/openmc/distribution_multi.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#include "pugixml.hpp"

#include "openmc/distribution.h"
#include "openmc/error.h"
#include "openmc/position.h"

namespace openmc {
Expand All @@ -29,6 +30,11 @@ class UnitSphereDistribution {
//! \return (sampled Direction, sample weight)
virtual std::pair<Direction, double> sample(uint64_t* seed) const = 0;

virtual double evaluate(Direction u) const
{
fatal_error("evaluate not available for this UnitSphereDistribution type");
}

Direction u_ref_ {0.0, 0.0, 1.0}; //!< reference direction
};

Expand All @@ -52,6 +58,8 @@ class PolarAzimuthal : public UnitSphereDistribution {
//! \return (sampled Direction, value of the PDF at this Direction)
std::pair<Direction, double> sample_as_bias(uint64_t* seed) const;

double evaluate(Direction u) const override;

// Observing pointers
Distribution* mu() const { return mu_.get(); }
Distribution* phi() const { return phi_.get(); }
Expand Down Expand Up @@ -87,6 +95,8 @@ class Isotropic : public UnitSphereDistribution {
//! \return (sampled direction, sample weight)
std::pair<Direction, double> sample(uint64_t* seed) const override;

double evaluate(Direction u) const override;

// Set or get bias distribution
void set_bias(std::unique_ptr<PolarAzimuthal> bias)
{
Expand Down
5 changes: 5 additions & 0 deletions include/openmc/reaction_product.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,11 @@ class ReactionProduct {
//! \param[inout] seed Pseudorandom seed pointer
void sample(double E_in, double& E_out, double& mu, uint64_t* seed) const;

AngleEnergy& sample_dist(double E_in, uint64_t* seed) const;

double sample_energy_and_pdf(
double E_in, double mu, double& E_out, uint64_t* seed) const;

ParticleType particle_; //!< Particle type
EmissionMode emission_mode_; //!< Emission mode
double decay_rate_; //!< Decay rate (for delayed neutron precursors) in [1/s]
Expand Down
3 changes: 3 additions & 0 deletions include/openmc/secondary_correlated.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,9 @@ class CorrelatedAngleEnergy : public AngleEnergy {
//! \param[inout] seed Pseudorandom seed pointer
void sample(
double E_in, double& E_out, double& mu, uint64_t* seed) const override;
Distribution& sample_dist(double E_in, double& E_out, uint64_t* seed) const;
double sample_energy_and_pdf(
double E_in, double mu, double& E_out, uint64_t* seed) const override;

// energy property
vector<double>& energy() { return energy_; }
Expand Down
4 changes: 4 additions & 0 deletions include/openmc/secondary_kalbach.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,10 @@ class KalbachMann : public AngleEnergy {
//! \param[inout] seed Pseudorandom seed pointer
void sample(
double E_in, double& E_out, double& mu, uint64_t* seed) const override;
void sample_params(double E_in, double& E_out, double& km_a, double& km_r,
uint64_t* seed) const;
double sample_energy_and_pdf(
double E_in, double mu, double& E_out, uint64_t* seed) const override;

private:
//! Outgoing energy/angle at a single incoming energy
Expand Down
3 changes: 3 additions & 0 deletions include/openmc/secondary_nbody.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@ class NBodyPhaseSpace : public AngleEnergy {
//! \param[inout] seed Pseudorandom seed pointer
void sample(
double E_in, double& E_out, double& mu, uint64_t* seed) const override;
double sample_energy(double E_in, uint64_t* seed) const;
double sample_energy_and_pdf(
double E_in, double mu, double& E_out, uint64_t* seed) const override;

private:
int n_bodies_; //!< Number of particles distributed
Expand Down
63 changes: 63 additions & 0 deletions include/openmc/secondary_thermal.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

#include "openmc/angle_energy.h"
#include "openmc/endf.h"
#include "openmc/search.h"
#include "openmc/secondary_correlated.h"
#include "openmc/vector.h"

Expand All @@ -32,6 +33,8 @@ class CoherentElasticAE : public AngleEnergy {
//! \param[inout] seed Pseudorandom seed pointer
void sample(
double E_in, double& E_out, double& mu, uint64_t* seed) const override;
double sample_energy_and_pdf(
double E_in, double mu, double& E_out, uint64_t* seed) const override;

private:
const CoherentElasticXS& xs_; //!< Coherent elastic scattering cross section
Expand All @@ -55,6 +58,8 @@ class IncoherentElasticAE : public AngleEnergy {
//! \param[inout] seed Pseudorandom number seed pointer
void sample(
double E_in, double& E_out, double& mu, uint64_t* seed) const override;
double sample_energy_and_pdf(
double E_in, double mu, double& E_out, uint64_t* seed) const override;

private:
double debye_waller_;
Expand All @@ -80,6 +85,8 @@ class IncoherentElasticAEDiscrete : public AngleEnergy {
//! \param[inout] seed Pseudorandom number seed pointer
void sample(
double E_in, double& E_out, double& mu, uint64_t* seed) const override;
double sample_energy_and_pdf(
double E_in, double mu, double& E_out, uint64_t* seed) const override;

private:
const vector<double>& energy_; //!< Energies at which cosines are tabulated
Expand All @@ -106,6 +113,9 @@ class IncoherentInelasticAEDiscrete : public AngleEnergy {
//! \param[inout] seed Pseudorandom number seed pointer
void sample(
double E_in, double& E_out, double& mu, uint64_t* seed) const override;
void sample_params(double E_in, double& E_out, int& j, uint64_t* seed) const;
double sample_energy_and_pdf(
double E_in, double mu, double& E_out, uint64_t* seed) const override;

private:
const vector<double>& energy_; //!< Incident energies
Expand Down Expand Up @@ -134,6 +144,10 @@ class IncoherentInelasticAE : public AngleEnergy {
//! \param[inout] seed Pseudorandom number seed pointer
void sample(
double E_in, double& E_out, double& mu, uint64_t* seed) const override;
void sample_params(double E_in, double& E_out, double& f, int& l, int& j,
uint64_t* seed) const;
double sample_energy_and_pdf(
double E_in, double mu, double& E_out, uint64_t* seed) const override;

private:
//! Secondary energy/angle distribution
Expand Down Expand Up @@ -169,6 +183,9 @@ class MixedElasticAE : public AngleEnergy {
//! \param[inout] seed Pseudorandom number seed pointer
void sample(
double E_in, double& E_out, double& mu, uint64_t* seed) const override;
const AngleEnergy& sample_dist(double E_in, uint64_t* seed) const;
double sample_energy_and_pdf(
double E_in, double mu, double& E_out, uint64_t* seed) const override;

private:
CoherentElasticAE coherent_dist_; //!< Coherent distribution
Expand All @@ -178,6 +195,52 @@ class MixedElasticAE : public AngleEnergy {
const Function1D& incoherent_xs_; //!< Polymorphic ref. to incoherent XS
};

struct DoubleVector {
double data;
const double& operator[](size_t index) const { return data; }
};

template<typename T>
double get_pdf_discrete(const vector<double>& mu, const T& w, double mu_0)
{
// Make sure mu is in range [-1,1]
if (std::abs(mu_0) > 1.0)
mu_0 = std::copysign(1.0, mu_0);
double a0;
double a1;
double b0;
double b1;
int32_t ai = -1;
int32_t bi = -1;
if (mu_0 > mu[0]) {
ai = lower_bound_index(mu.begin(), mu.end(), mu_0);
a0 = mu[ai];
a1 = (ai > 1) ? mu[ai - 1] : -1.0;
} else {
a0 = -1.0;
a1 = -1.0;
}
if (mu_0 < mu[mu.size() - 1]) {
bi = upper_bound_index(mu.begin(), mu.end(), mu_0);
b0 = mu[bi];
b1 = (bi < mu.size() - 1) ? mu[bi + 1] : 1.0;
} else {
b0 = 1.0;
b1 = 1.0;
}

// Calculate Delta_a and Delta_b
double delta_a = 0.5 * std::min(b0 - a0, a0 - a1);
double delta_b = 0.5 * std::min(b1 - b0, b0 - a0);

if (mu_0 < a0 + delta_a)
return w[ai] / (2.0 * delta_a);
else if (mu_0 + delta_b < b0)
return w[bi] / (2.0 * delta_b);
else
return 0.0;
}

} // namespace openmc

#endif // OPENMC_SECONDARY_THERMAL_H
2 changes: 2 additions & 0 deletions include/openmc/secondary_uncorrelated.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ class UncorrelatedAngleEnergy : public AngleEnergy {
//! \param[inout] seed Pseudorandom seed pointer
void sample(
double E_in, double& E_out, double& mu, uint64_t* seed) const override;
double sample_energy_and_pdf(
double E_in, double mu, double& E_out, uint64_t* seed) const override;

// Accessors
AngleDistribution& angle() { return angle_; }
Expand Down
6 changes: 5 additions & 1 deletion include/openmc/thermal.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,11 @@ class ThermalData {
//! \param[out] mu Outgoing scattering angle cosine
//! \param[inout] seed Pseudorandom seed pointer
void sample(const NuclideMicroXS& micro_xs, double E_in, double* E_out,
double* mu, uint64_t* seed);
double* mu, uint64_t* seed) const;
AngleEnergy& sample_dist(
const NuclideMicroXS& micro_xs, double E, uint64_t* seed) const;
double sample_energy_and_pdf(const NuclideMicroXS& micro_xs, double E_in,
double mu, double& E_out, uint64_t* seed) const;

private:
struct Reaction {
Expand Down
7 changes: 7 additions & 0 deletions src/chain.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,13 @@ void DecayPhotonAngleEnergy::sample(
mu = Uniform(-1., 1.).sample(seed).first;
}

double DecayPhotonAngleEnergy::sample_energy_and_pdf(
double E_in, double mu, double& E_out, uint64_t* seed) const
{
E_out = photon_energy_->sample(seed).first;
return 0.5;
}

//==============================================================================
// Global variables
//==============================================================================
Expand Down
15 changes: 15 additions & 0 deletions src/distribution_angle.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -83,4 +83,19 @@ double AngleDistribution::sample(double E, uint64_t* seed) const
return mu;
}

double AngleDistribution::evaluate(double E, double mu) const
{
// Find energy bin and calculate interpolation factor
int i;
double r;
get_energy_index(energy_, E, i, r);

double pdf = 0.0;
if (r > 0.0)
pdf += r * distribution_[i + 1]->evaluate(mu);
if (r < 1.0)
pdf += (1.0 - r) * distribution_[i]->evaluate(mu);
return pdf;
}

} // namespace openmc
14 changes: 14 additions & 0 deletions src/distribution_multi.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ UnitSphereDistribution::UnitSphereDistribution(pugi::xml_node node)
fatal_error("Angular distribution reference direction must have "
"three parameters specified.");
u_ref_ = Direction(u_ref.data());
u_ref_ /= u_ref_.norm();
}
}

Expand All @@ -65,6 +66,7 @@ PolarAzimuthal::PolarAzimuthal(pugi::xml_node node)
fatal_error("Angular distribution reference v direction must have "
"three parameters specified.");
v_ref_ = Direction(v_ref.data());
v_ref_ /= v_ref_.norm();
}
w_ref_ = u_ref_.cross(v_ref_);
if (check_for_node(node, "mu")) {
Expand Down Expand Up @@ -116,6 +118,13 @@ std::pair<Direction, double> PolarAzimuthal::sample_impl(
weight};
}

double PolarAzimuthal::evaluate(Direction u) const
{
double mu = u.dot(u_ref_);
double phi = std::acos(u.dot(v_ref_) / std::sqrt(1 - mu * mu));
return mu_->evaluate(mu) * phi_->evaluate(phi);
}

//==============================================================================
// Isotropic implementation
//==============================================================================
Expand Down Expand Up @@ -157,6 +166,11 @@ std::pair<Direction, double> Isotropic::sample(uint64_t* seed) const
}
}

double Isotropic::evaluate(Direction u) const
{
return 1.0 / (4.0 * PI);
}

//==============================================================================
// Monodirectional implementation
//==============================================================================
Expand Down
23 changes: 16 additions & 7 deletions src/reaction_product.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -106,8 +106,7 @@ ReactionProduct::ReactionProduct(const ChainNuclide::Product& product)
make_unique<DecayPhotonAngleEnergy>(chain_nuc->photon_energy()));
}

void ReactionProduct::sample(
double E_in, double& E_out, double& mu, uint64_t* seed) const
AngleEnergy& ReactionProduct::sample_dist(double E_in, uint64_t* seed) const
{
auto n = applicability_.size();
if (n > 1) {
Expand All @@ -118,15 +117,25 @@ void ReactionProduct::sample(
prob += applicability_[i](E_in);

// If i-th distribution is sampled, sample energy from the distribution
if (c <= prob) {
distribution_[i]->sample(E_in, E_out, mu, seed);
break;
}
if (c <= prob)
return *distribution_[i];
}
} else {
// If only one distribution is present, go ahead and sample it
distribution_[0]->sample(E_in, E_out, mu, seed);
return *distribution_[0];
}
}

void ReactionProduct::sample(
double E_in, double& E_out, double& mu, uint64_t* seed) const
{
sample_dist(E_in, seed).sample(E_in, E_out, mu, seed);
}

double ReactionProduct::sample_energy_and_pdf(
double E_in, double mu, double& E_out, uint64_t* seed) const
{
return sample_dist(E_in, seed).sample_energy_and_pdf(E_in, mu, E_out, seed);
}

} // namespace openmc
Loading
Loading