Commit de01eb121bb85f19300bad41b0d41bfba80bab14
1 parent
af442cad
Resolved issues in MC generation for GModelSpectralSmoothBrokenPlaw (#1948)
Previously neglecting the appropriate handling in the CDF computation of the different indices above and below the break energy. Now appropriately handles the case where (Emax < Ebreak) and (Emin > Ebreak).
Showing
2 changed files
with
51 additions
and
39 deletions
include/GModelSpectralSmoothBrokenPlaw.hpp
| ... | ... | @@ -40,7 +40,6 @@ class GRan; |
| 40 | 40 | class GTime; |
| 41 | 41 | class GXmlElement; |
| 42 | 42 | |
| 43 | -// TODO: Updated class documentation | |
| 44 | 43 | /***********************************************************************//** |
| 45 | 44 | * @class GModelSpectralSmoothBrokenPlaw |
| 46 | 45 | * |
| ... | ... | @@ -50,17 +49,18 @@ class GXmlElement; |
| 50 | 49 | * defined by |
| 51 | 50 | * |
| 52 | 51 | * \f[ |
| 53 | - * S_{\rm E}(E | t) = k_0 \times \left \{ | |
| 54 | - * \left( \frac{E}{E_b} \right)^{\gamma_2} & {\rm otherwise} | |
| 55 | - * \right . | |
| 52 | + * S_{\rm E}(E | t) = k_0 \left( \frac{E}{E_0} \right)^{\gamma_1} | |
| 53 | + * \left[ 1 + \left( \frac{E}{E_b} \right)^{\frac{\gamma_1 - \gamma_2}{\beta}} | |
| 54 | + * \right]^{-\beta} | |
| 56 | 55 | * \f] |
| 57 | 56 | * |
| 58 | 57 | * where |
| 59 | 58 | * \f$k_0\f$ is the normalization or prefactor, |
| 60 | 59 | * \f$\gamma_1\f$ is the spectral index before the break, |
| 61 | - * \f$\gamma_2\f$ is the spectral index after the break, and | |
| 62 | - * \f$E_b\f$ is the break energy. | |
| 63 | - * \f$\beta\f$ defines the break smoothness | |
| 60 | + * \f$\gamma_2\f$ is the spectral index after the break, | |
| 61 | + * \f$E_0\f$ is the pivot energy, | |
| 62 | + * \f$E_b\f$ is the break energy, and | |
| 63 | + * \f$\beta\f$ defines the break smoothness (larger = smoother transition) | |
| 64 | 64 | ***************************************************************************/ |
| 65 | 65 | class GModelSpectralSmoothBrokenPlaw : public GModelSpectral { |
| 66 | 66 | |
| ... | ... | @@ -159,12 +159,12 @@ protected: |
| 159 | 159 | |
| 160 | 160 | // Members |
| 161 | 161 | protected: |
| 162 | - double m_prefactor; //!< Normalization | |
| 163 | - double m_index1; //!< Spectral index1 | |
| 164 | - double m_index2; //!< Spectral index2 | |
| 165 | - GEnergy m_pivot; //!< Pivot energy | |
| 166 | - GEnergy m_breakenergy; //!< Break energy | |
| 167 | - double m_beta; //!< Break smoothness parameter | |
| 162 | + double m_prefactor; //!< Normalization | |
| 163 | + double m_index1; //!< Spectral index1 | |
| 164 | + double m_index2; //!< Spectral index2 | |
| 165 | + GEnergy m_pivot; //!< Pivot energy | |
| 166 | + GEnergy m_breakenergy; //!< Break energy | |
| 167 | + double m_beta; //!< Break smoothness parameter | |
| 168 | 168 | }; |
| 169 | 169 | |
| 170 | 170 | // Class to determine the integral energy flux, derivation of flux_kern |
| ... | ... | @@ -216,6 +216,9 @@ protected: |
| 216 | 216 | mutable double m_mc_exponentH; //!< Exponent (index+1) for harder index |
| 217 | 217 | mutable double m_mc_pow_ewidth_low; //!< width of energy range below break |
| 218 | 218 | mutable double m_mc_norm; //!< Normalization term for energy generation |
| 219 | + mutable double m_mc_exponent_ratio; //!< Ratio of (m_mc_exponentS/m_mc_exponentH) | |
| 220 | + mutable double m_mc_ebreak; //!< Break energy (depending on the energy range, | |
| 221 | + //!< this may not actually be the break energy) | |
| 219 | 222 | }; |
| 220 | 223 | |
| 221 | 224 | ... | ... |
src/model/GModelSpectralSmoothBrokenPlaw.cpp
| ... | ... | @@ -318,12 +318,9 @@ GModelSpectralSmoothBrokenPlaw* GModelSpectralSmoothBrokenPlaw::clone(void) cons |
| 318 | 318 | * Evaluates |
| 319 | 319 | * |
| 320 | 320 | * \f[ |
| 321 | - * S_{\rm E}(E | t) = k_0 \times \left \{ | |
| 322 | - * \begin{eqnarray} | |
| 323 | - * \left( \frac{E}{E_b} \right)^{\gamma_1} & {\rm if\,\,} E < E_b \\ | |
| 324 | - * \left( \frac{E}{E_b} \right)^{\gamma_2} & {\rm otherwise} | |
| 325 | - * \end{eqnarray} | |
| 326 | - * \right . | |
| 321 | + * S_{\rm E}(E | t) = k_0 \left( \frac{E}{E_0} \right)^{\gamma_1} | |
| 322 | + * \left[ 1 + \left( \frac{E}{E_b} \right)^{\frac{\gamma_1 - \gamma_2}{\beta}} | |
| 323 | + * \right]^{-\beta} | |
| 327 | 324 | * \f] |
| 328 | 325 | * |
| 329 | 326 | * where |
| ... | ... | @@ -394,11 +391,6 @@ double GModelSpectralSmoothBrokenPlaw::eval(const GEnergy& srcEng, |
| 394 | 391 | ? value * m_index1.scale() * (m_last_log_epivot_norm - |
| 395 | 392 | ((m_last_ebreak_pow * m_last_log_ebreak_norm) / |
| 396 | 393 | (m_last_ebreak_pow + 1.0))) |
| 397 | - /* | |
| 398 | - value * m_index1.scale() / (1.0+m_last_ebreak_pow) * | |
| 399 | - (m_last_log_epivot_norm+(m_last_log_epivot_norm-m_last_log_ebreak_norm)* | |
| 400 | - m_last_ebreak_pow) | |
| 401 | - */ | |
| 402 | 394 | : 0.0; |
| 403 | 395 | double g_index2 = (m_index2.is_free()) |
| 404 | 396 | ? value * m_index2.scale() * m_last_log_ebreak_norm * |
| ... | ... | @@ -622,15 +614,18 @@ GEnergy GModelSpectralSmoothBrokenPlaw::mc(const GEnergy& emin, |
| 622 | 614 | plaw = m_mc_plaw_prefactor * std::pow(e_norm, m_mc_exponentH-1.0); |
| 623 | 615 | |
| 624 | 616 | } |
| 617 | + | |
| 625 | 618 | // Case 2: indices are different (things are more complicated) |
| 626 | 619 | else { |
| 627 | 620 | |
| 621 | + double break_u = m_mc_pow_ewidth_low/m_mc_norm; | |
| 622 | + | |
| 628 | 623 | // Case 2A: Random number suggests energy less than breakenergy |
| 629 | 624 | if (u <= (m_mc_pow_ewidth_low/m_mc_norm)) { |
| 630 | 625 | |
| 631 | 626 | // Case 2A-1: Hard index is not -1 |
| 632 | 627 | if (m_mc_exponentH != 0.0) { |
| 633 | - eng = std::exp(std::log(u * m_mc_norm + | |
| 628 | + eng = std::exp(std::log(u * m_mc_norm / m_mc_exponent_ratio + | |
| 634 | 629 | std::pow(m_mc_emin, m_mc_exponentH)) / m_mc_exponentH); |
| 635 | 630 | } |
| 636 | 631 | |
| ... | ... | @@ -649,13 +644,13 @@ GEnergy GModelSpectralSmoothBrokenPlaw::mc(const GEnergy& emin, |
| 649 | 644 | // Case 2B-1: Soft index is not -1 |
| 650 | 645 | if (m_mc_exponentS != 0.0) { |
| 651 | 646 | eng = std::exp(std::log(u * m_mc_norm + |
| 652 | - std::pow(breakenergy().MeV(), m_mc_exponentS) - | |
| 647 | + std::pow(m_mc_ebreak, m_mc_exponentS) - | |
| 653 | 648 | m_mc_pow_ewidth_low) / m_mc_exponentS) ; |
| 654 | 649 | } |
| 655 | 650 | // Case 2B-2: Soft index is -1 |
| 656 | 651 | else { |
| 657 | 652 | eng = std::exp(u * m_mc_norm + |
| 658 | - std::log(breakenergy().MeV()) - | |
| 653 | + std::log(m_mc_ebreak) - | |
| 659 | 654 | m_mc_pow_ewidth_low); |
| 660 | 655 | } |
| 661 | 656 | |
| ... | ... | @@ -894,6 +889,7 @@ void GModelSpectralSmoothBrokenPlaw::init_members(void) |
| 894 | 889 | m_mc_exponentH = 0.0; |
| 895 | 890 | m_mc_pow_ewidth_low = 0.0; |
| 896 | 891 | m_mc_norm = 0.0; |
| 892 | + m_mc_exponent_ratio = 1.0; | |
| 897 | 893 | |
| 898 | 894 | // Return |
| 899 | 895 | return; |
| ... | ... | @@ -947,6 +943,7 @@ void GModelSpectralSmoothBrokenPlaw::copy_members(const GModelSpectralSmoothBrok |
| 947 | 943 | m_mc_exponentH = model.m_mc_exponentH; |
| 948 | 944 | m_mc_pow_ewidth_low = model.m_mc_pow_ewidth_low; |
| 949 | 945 | m_mc_norm = model.m_mc_norm; |
| 946 | + m_mc_exponent_ratio = model.m_mc_exponent_ratio; | |
| 950 | 947 | |
| 951 | 948 | // Return |
| 952 | 949 | return; |
| ... | ... | @@ -1044,14 +1041,24 @@ void GModelSpectralSmoothBrokenPlaw::update_mc_cache(const GEnergy& emin, |
| 1044 | 1041 | |
| 1045 | 1042 | // CASE: index1 is harder |
| 1046 | 1043 | if (index1() > index2()) { |
| 1047 | - m_mc_exponentH = index1() + 1.0 ; // Hard index + 1 | |
| 1048 | - m_mc_exponentS = index2() + 1.0 ; // Soft index + 1 | |
| 1049 | - | |
| 1044 | + m_mc_exponentH = index1() + 1.0; // Hard index + 1 | |
| 1045 | + m_mc_exponentS = index2() + 1.0; // Soft index + 1 | |
| 1050 | 1046 | } |
| 1051 | 1047 | // CASE: index2 is harder, or index1==index2 |
| 1052 | 1048 | else { |
| 1053 | - m_mc_exponentH = index2() + 1.0 ; // Hard index + 1 | |
| 1054 | - m_mc_exponentS = index1() + 1.0 ; // Soft index + 1 | |
| 1049 | + m_mc_exponentH = index2() + 1.0; // Hard index + 1 | |
| 1050 | + m_mc_exponentS = index1() + 1.0; // Soft index + 1 | |
| 1051 | + } | |
| 1052 | + | |
| 1053 | + // Store the ratio of the two exponents | |
| 1054 | + m_mc_exponent_ratio = m_mc_exponentS / m_mc_exponentH; | |
| 1055 | + | |
| 1056 | + // Create a break energy variable that select the appropriate range | |
| 1057 | + m_mc_ebreak = breakenergy().MeV(); | |
| 1058 | + if (m_mc_emax <= m_mc_ebreak) { | |
| 1059 | + m_mc_ebreak = m_mc_emax; | |
| 1060 | + } else if (m_mc_emin >= m_mc_ebreak) { | |
| 1061 | + m_mc_ebreak = m_mc_emin; | |
| 1055 | 1062 | } |
| 1056 | 1063 | |
| 1057 | 1064 | // Now handle the cases where the hard exponent is -1 |
| ... | ... | @@ -1064,29 +1071,31 @@ void GModelSpectralSmoothBrokenPlaw::update_mc_cache(const GEnergy& emin, |
| 1064 | 1071 | } |
| 1065 | 1072 | // CASE: Only harder exponent is -1 |
| 1066 | 1073 | else { |
| 1067 | - m_mc_pow_ewidth_low = std::log(breakenergy().MeV()/m_mc_emin); | |
| 1074 | + m_mc_pow_ewidth_low = std::log(m_mc_ebreak/m_mc_emin); | |
| 1068 | 1075 | m_mc_norm = m_mc_pow_ewidth_low + std::pow(m_mc_emax,m_mc_exponentS) - |
| 1069 | - std::pow(breakenergy().MeV(),m_mc_exponentS); | |
| 1076 | + std::pow(m_mc_ebreak,m_mc_exponentS); | |
| 1070 | 1077 | } |
| 1071 | 1078 | } |
| 1072 | 1079 | |
| 1073 | 1080 | // CASE: Only softer exponent is -1 |
| 1074 | 1081 | else if (m_mc_exponentS == 0.0) { |
| 1075 | - m_mc_pow_ewidth_low = std::pow(breakenergy().MeV(),m_mc_exponentH) - | |
| 1082 | + m_mc_pow_ewidth_low = std::pow(m_mc_ebreak,m_mc_exponentH) - | |
| 1076 | 1083 | std::pow(m_mc_emin, m_mc_exponentH) ; |
| 1077 | 1084 | m_mc_norm = m_mc_pow_ewidth_low + std::log(m_mc_emax) - |
| 1078 | - std::log(breakenergy().MeV()) ; | |
| 1085 | + std::log(m_mc_ebreak) ; | |
| 1079 | 1086 | } |
| 1080 | 1087 | |
| 1081 | 1088 | // CASE: Neither exponent is -1. |
| 1082 | 1089 | else { |
| 1090 | + | |
| 1083 | 1091 | // Get the width of the energy range below the break energy |
| 1084 | - m_mc_pow_ewidth_low = std::pow(breakenergy().MeV(), m_mc_exponentH) - | |
| 1085 | - std::pow(m_mc_emin, m_mc_exponentH); | |
| 1092 | + m_mc_pow_ewidth_low = m_mc_exponent_ratio * | |
| 1093 | + (std::pow(m_mc_ebreak, m_mc_exponentH) - | |
| 1094 | + std::pow(m_mc_emin, m_mc_exponentH)); | |
| 1086 | 1095 | |
| 1087 | 1096 | // Get the normalization term |
| 1088 | 1097 | m_mc_norm = m_mc_pow_ewidth_low + (std::pow(m_mc_emax,m_mc_exponentS) - |
| 1089 | - std::pow(breakenergy().MeV(),m_mc_exponentS)); | |
| 1098 | + std::pow(m_mc_ebreak,m_mc_exponentS)); | |
| 1090 | 1099 | } |
| 1091 | 1100 | } // endif: Update was required |
| 1092 | 1101 | ... | ... |