Commit 0a0628b475a93ea29f67bf8eee289a127dfe3bdc
1 parent
86b32056
Remove small angle approximation (always compute in spherical system).
Showing
5 changed files
with
42 additions
and
135 deletions
ChangeLog
| 1 | -2015-07-03 Juergen Knoedlseder <jurgen.knodlseder@irap.omp.eu> | |
| 1 | +2015-08-30 Juergen Knoedlseder <jurgen.knodlseder@irap.omp.eu> | |
| 2 | 2 | |
| 3 | 3 | * Version 0.11.0 released |
| 4 | 4 | ========================= |
| 5 | 5 | |
| 6 | + Remove small angle approximation from GModelSpatialRadialShell | |
| 6 | 7 | Rename GSkymap to GSkyMap |
| 7 | 8 | Add binary operators to GSkymap class |
| 8 | 9 | GSkymap::operator/=(GSkymap) operator now ignores division by zero | ... | ... |
NEWS
| ... | ... | @@ -2,7 +2,7 @@ New Features and Important Changes in GammaLib 0.11.0 |
| 2 | 2 | |
| 3 | 3 | Author(s) : Juergen Knoedlseder |
| 4 | 4 | |
| 5 | -3 July 2015 | |
| 5 | +30 August 2015 | |
| 6 | 6 | |
| 7 | 7 | |
| 8 | 8 | 1. Introduction |
| ... | ... | @@ -20,6 +20,8 @@ optimizer. |
| 20 | 20 | The GSkymap class has been renamed to GSkyMap to be consistent with the other |
| 21 | 21 | classes in the sky module. |
| 22 | 22 | |
| 23 | +The small angle approximation has been removed from GModelSpatialRadialShell. | |
| 24 | + | |
| 23 | 25 | |
| 24 | 26 | 3. Configuration |
| 25 | 27 | ----------------- |
| ... | ... | @@ -62,6 +64,9 @@ The algorithm used to draw random numbers in GModelSpatialDiffuseConst::mc() |
| 62 | 64 | was wrong (sky directions were not distributed isotropically on the sky). This |
| 63 | 65 | has now been fixed (#1480). |
| 64 | 66 | |
| 67 | +The small angle approximation has been removed from GModelSpatialRadialShell | |
| 68 | +as this complexifies the class and the approximation is not really needed. | |
| 69 | + | |
| 65 | 70 | |
| 66 | 71 | 9. Numerics module |
| 67 | 72 | ------------------ | ... | ... |
include/GModelSpatialRadialShell.hpp
| ... | ... | @@ -61,8 +61,7 @@ public: |
| 61 | 61 | GModelSpatialRadialShell(void); |
| 62 | 62 | GModelSpatialRadialShell(const GSkyDir& dir, |
| 63 | 63 | const double& radius, |
| 64 | - const double& width, | |
| 65 | - const bool& small_angle = true); | |
| 64 | + const double& width); | |
| 66 | 65 | explicit GModelSpatialRadialShell(const GXmlElement& xml); |
| 67 | 66 | GModelSpatialRadialShell(const GModelSpatialRadialShell& model); |
| 68 | 67 | virtual ~GModelSpatialRadialShell(void); |
| ... | ... | @@ -92,12 +91,10 @@ public: |
| 92 | 91 | virtual std::string print(const GChatter& chatter = NORMAL) const; |
| 93 | 92 | |
| 94 | 93 | // Other methods |
| 95 | - double radius(void) const; | |
| 96 | - double width(void) const; | |
| 97 | - const bool& small_angle(void) const; | |
| 98 | - void radius(const double& radius); | |
| 99 | - void width(const double& width); | |
| 100 | - void small_angle(const bool& small_angle); | |
| 94 | + double radius(void) const; | |
| 95 | + double width(void) const; | |
| 96 | + void radius(const double& radius); | |
| 97 | + void width(const double& width); | |
| 101 | 98 | |
| 102 | 99 | protected: |
| 103 | 100 | // Protected methods |
| ... | ... | @@ -111,15 +108,14 @@ protected: |
| 111 | 108 | // Protected members |
| 112 | 109 | GModelPar m_radius; //!< Inner shell radius (deg) |
| 113 | 110 | GModelPar m_width; //!< Shell thickness (deg) |
| 114 | - bool m_small_angle; //!< Use small angle approximate formulae | |
| 115 | 111 | |
| 116 | 112 | // Cached members used for pre-computations |
| 117 | 113 | mutable double m_last_radius; //!< Last shell radius (deg) |
| 118 | 114 | mutable double m_last_width; //!< Last shell width (deg) |
| 119 | 115 | mutable double m_theta_in; //!< Inner shell radius (rad) |
| 120 | - mutable double m_x_in; //!< m_theta_in^2 or sin(m_theta_in)^2 | |
| 116 | + mutable double m_x_in; //!< sin(m_theta_in)^2 | |
| 121 | 117 | mutable double m_theta_out; //!< Outer shell radius (rad) |
| 122 | - mutable double m_x_out; //!< m_theta_out^2 or sin(m_theta_out)^2 | |
| 118 | + mutable double m_x_out; //!< sin(m_theta_out)^2 | |
| 123 | 119 | mutable double m_norm; //!< Shell normalization |
| 124 | 120 | }; |
| 125 | 121 | |
| ... | ... | @@ -207,35 +203,4 @@ void GModelSpatialRadialShell::width(const double& width) |
| 207 | 203 | return; |
| 208 | 204 | } |
| 209 | 205 | |
| 210 | - | |
| 211 | -/***********************************************************************//** | |
| 212 | - * @brief Return shell approximation flag | |
| 213 | - * | |
| 214 | - * @return True if small angle approximation is taken. | |
| 215 | - * | |
| 216 | - * Signals if the small angle approximation is taken. | |
| 217 | - ***************************************************************************/ | |
| 218 | -inline | |
| 219 | -const bool& GModelSpatialRadialShell::small_angle(void) const | |
| 220 | -{ | |
| 221 | - return (m_small_angle); | |
| 222 | -} | |
| 223 | - | |
| 224 | - | |
| 225 | -/***********************************************************************//** | |
| 226 | - * @brief Set shell approximation flag | |
| 227 | - * | |
| 228 | - * @param[in] small_angle Shell approximation flag. | |
| 229 | - * | |
| 230 | - * Sets the shell approximation flag. True specifies that the small angle | |
| 231 | - * approximation shall be taken, false specifies that the correct spherical | |
| 232 | - * computation shall be used. | |
| 233 | - ***************************************************************************/ | |
| 234 | -inline | |
| 235 | -void GModelSpatialRadialShell::small_angle(const bool& small_angle) | |
| 236 | -{ | |
| 237 | - m_small_angle = small_angle; | |
| 238 | - return; | |
| 239 | -} | |
| 240 | - | |
| 241 | 206 | #endif /* GMODELSPATIALRADIALSHELL_HPP */ | ... | ... |
pyext/GModelSpatialRadialShell.i
| ... | ... | @@ -40,8 +40,7 @@ public: |
| 40 | 40 | GModelSpatialRadialShell(void); |
| 41 | 41 | GModelSpatialRadialShell(const GSkyDir& dir, |
| 42 | 42 | const double& radius, |
| 43 | - const double& width, | |
| 44 | - const bool& small_angle = true); | |
| 43 | + const double& width); | |
| 45 | 44 | explicit GModelSpatialRadialShell(const GXmlElement& xml); |
| 46 | 45 | GModelSpatialRadialShell(const GModelSpatialRadialShell& model); |
| 47 | 46 | virtual ~GModelSpatialRadialShell(void); |
| ... | ... | @@ -69,10 +68,8 @@ public: |
| 69 | 68 | // Other methods |
| 70 | 69 | double radius(void) const; |
| 71 | 70 | double width(void) const; |
| 72 | - bool small_angle(void) const; | |
| 73 | 71 | void radius(const double& radius); |
| 74 | 72 | void width(const double& width); |
| 75 | - void small_angle(const bool& small_angle); | |
| 76 | 73 | }; |
| 77 | 74 | |
| 78 | 75 | ... | ... |
src/model/GModelSpatialRadialShell.cpp
| ... | ... | @@ -77,21 +77,13 @@ GModelSpatialRadialShell::GModelSpatialRadialShell(void) : GModelSpatialRadial() |
| 77 | 77 | * @param[in] dir Sky position of shell centre. |
| 78 | 78 | * @param[in] radius Inner shell radius (degrees). |
| 79 | 79 | * @param[in] width Shell width (degrees). |
| 80 | - * @param[in] small_angle Use small angle approximation (default to true). | |
| 81 | 80 | * |
| 82 | 81 | * Constructs the shell model from the shell centre (@p dir), the inner |
| 83 | - * shell @p radius, and the shell @p width. The optional parameters | |
| 84 | - * @p small_angle specifies whether the small angle approximation | |
| 85 | - * should be used or not. The small angle approximation is (a little) faster, | |
| 86 | - * but incorrect for shells larger than a few degrees. | |
| 87 | - * | |
| 88 | - * @todo Measure speed difference between small angle approximation and | |
| 89 | - * full computation. | |
| 82 | + * shell @p radius, and the shell @p width. | |
| 90 | 83 | ***************************************************************************/ |
| 91 | 84 | GModelSpatialRadialShell::GModelSpatialRadialShell(const GSkyDir& dir, |
| 92 | 85 | const double& radius, |
| 93 | - const double& width, | |
| 94 | - const bool& small_angle) : | |
| 86 | + const double& width) : | |
| 95 | 87 | GModelSpatialRadial() |
| 96 | 88 | { |
| 97 | 89 | // Initialise members |
| ... | ... | @@ -101,7 +93,6 @@ GModelSpatialRadialShell::GModelSpatialRadialShell(const GSkyDir& dir, |
| 101 | 93 | this->dir(dir); |
| 102 | 94 | this->radius(radius); |
| 103 | 95 | this->width(width); |
| 104 | - this->small_angle(small_angle); | |
| 105 | 96 | |
| 106 | 97 | // Return |
| 107 | 98 | return; |
| ... | ... | @@ -249,28 +240,7 @@ GModelSpatialRadialShell* GModelSpatialRadialShell::clone(void) const |
| 249 | 240 | * model is a radial function \f$f(\theta)\f$, where \f$\theta\f$ is the |
| 250 | 241 | * angular separation between shell centre and the actual location. |
| 251 | 242 | * |
| 252 | - * In the small angle approximation, | |
| 253 | - * \f[ | |
| 254 | - * S_{\rm p}(\vec{p} | E, t) = {\tt m\_norm} \left \{ | |
| 255 | - * \begin{array}{l l} | |
| 256 | - * \displaystyle | |
| 257 | - * \sqrt{ \theta_{\rm out}^2 - \theta^2 } - | |
| 258 | - * \sqrt{ \theta_{\rm in}^2 - \theta^2 } | |
| 259 | - * & \mbox{if $\theta \le \theta_{\rm in}$} \\ | |
| 260 | - * \\ | |
| 261 | - * \displaystyle | |
| 262 | - * \sqrt{ \theta_{\rm out}^2 - \theta^2 } | |
| 263 | - * & \mbox{if $\theta_{\rm in} < \theta \le \theta_{\rm out}$} \\ | |
| 264 | - * \\ | |
| 265 | - * \displaystyle | |
| 266 | - * 0 & \mbox{if $\theta > \theta_{\rm out}$} | |
| 267 | - * \end{array} | |
| 268 | - * \right . | |
| 269 | - * \f] | |
| 270 | - * where \f${\tt m\_norm}\f$ is a normalization constant (see the update() | |
| 271 | - * method). | |
| 272 | - * | |
| 273 | - * In the general form that is also valid for large angles | |
| 243 | + * The function is given by | |
| 274 | 244 | * \f[ |
| 275 | 245 | * S_{\rm p}(\vec{p} | E, t) = {\tt m\_norm} \left \{ |
| 276 | 246 | * \begin{array}{l l} |
| ... | ... | @@ -299,28 +269,20 @@ double GModelSpatialRadialShell::eval(const double& theta, |
| 299 | 269 | // Update precomputation cache |
| 300 | 270 | update(); |
| 301 | 271 | |
| 302 | - // Set x appropriately for the small angle approximation or not | |
| 303 | - double x; | |
| 304 | - if (m_small_angle) { | |
| 305 | - x = theta * theta; | |
| 306 | - } | |
| 307 | - else { | |
| 308 | - x = std::sin(theta); | |
| 309 | - x *= x; | |
| 310 | - } | |
| 272 | + // Set x appropriately | |
| 273 | + double x = std::sin(theta); | |
| 274 | + x *= x; | |
| 311 | 275 | |
| 312 | - // Compute value | |
| 313 | - double value = 0.0; | |
| 276 | + // Compute result | |
| 277 | + double result = 0.0; | |
| 314 | 278 | if (x < m_x_out) { |
| 315 | - value = std::sqrt(m_x_out - x); | |
| 279 | + result = std::sqrt(m_x_out - x); | |
| 316 | 280 | if (x < m_x_in) { |
| 317 | - value -= std::sqrt(m_x_in - x); | |
| 281 | + result -= std::sqrt(m_x_in - x); | |
| 318 | 282 | } |
| 283 | + result *= m_norm; | |
| 319 | 284 | } |
| 320 | 285 | |
| 321 | - // Normalise value | |
| 322 | - double result = m_norm * value; | |
| 323 | - | |
| 324 | 286 | // Compile option: Check for NaN/Inf |
| 325 | 287 | #if defined(G_NAN_CHECK) |
| 326 | 288 | if (gammalib::is_notanumber(result) || gammalib::is_infinite(result)) { |
| ... | ... | @@ -328,11 +290,9 @@ double GModelSpatialRadialShell::eval(const double& theta, |
| 328 | 290 | std::cout << "(theta=" << theta << "): NaN/Inf encountered"; |
| 329 | 291 | std::cout << " (result=" << result; |
| 330 | 292 | std::cout << ", m_norm=" << m_norm; |
| 331 | - std::cout << ", value=" << value; | |
| 332 | 293 | std::cout << ", x=" << x; |
| 333 | 294 | std::cout << ", m_x_out=" << m_x_out; |
| 334 | 295 | std::cout << ", m_x_in=" << m_x_in; |
| 335 | - std::cout << ", m_small_angle=" << m_small_angle; | |
| 336 | 296 | std::cout << ")" << std::endl; |
| 337 | 297 | } |
| 338 | 298 | #endif |
| ... | ... | @@ -381,17 +341,15 @@ GSkyDir GModelSpatialRadialShell::mc(const GEnergy& energy, |
| 381 | 341 | |
| 382 | 342 | // Simulate offset from photon arrival direction |
| 383 | 343 | #if defined(G_DEBUG_MC) |
| 384 | - int n_samples = 0; | |
| 344 | + int n_samples = 0; | |
| 385 | 345 | #endif |
| 386 | - double theta_max = this->theta_max(); | |
| 387 | - double sin_theta_max = std::sin(theta_max); | |
| 388 | - double u_max = (m_small_angle) ? m_norm * sin_theta_max * theta_max | |
| 389 | - : m_norm * sin_theta_max * sin_theta_max; | |
| 346 | + double sin_theta_max = std::sin(m_theta_out); | |
| 347 | + double u_max = m_norm * sin_theta_max * sin_theta_max; | |
| 390 | 348 | double value = 0.0; |
| 391 | 349 | double u = 1.0; |
| 392 | 350 | double theta = 0.0; |
| 393 | 351 | do { |
| 394 | - theta = ran.uniform() * theta_max; | |
| 352 | + theta = ran.uniform() * m_theta_out; | |
| 395 | 353 | value = eval(theta, energy, time) * std::sin(theta); |
| 396 | 354 | u = ran.uniform() * u_max; |
| 397 | 355 | #if defined(G_DEBUG_MC) |
| ... | ... | @@ -684,9 +642,6 @@ void GModelSpatialRadialShell::init_members(void) |
| 684 | 642 | m_pars.push_back(&m_radius); |
| 685 | 643 | m_pars.push_back(&m_width); |
| 686 | 644 | |
| 687 | - // Initialise other members | |
| 688 | - m_small_angle = false; | |
| 689 | - | |
| 690 | 645 | // Initialise precomputation cache. Note that zero values flag |
| 691 | 646 | // uninitialised as a zero radius and width shell is not meaningful |
| 692 | 647 | m_last_radius = 0.0; |
| ... | ... | @@ -716,7 +671,6 @@ void GModelSpatialRadialShell::copy_members(const GModelSpatialRadialShell& mode |
| 716 | 671 | // Copy members |
| 717 | 672 | m_radius = model.m_radius; |
| 718 | 673 | m_width = model.m_width; |
| 719 | - m_small_angle = model.m_small_angle; | |
| 720 | 674 | |
| 721 | 675 | // Copy precomputation cache |
| 722 | 676 | m_last_radius = model.m_last_radius; |
| ... | ... | @@ -753,13 +707,6 @@ void GModelSpatialRadialShell::free_members(void) |
| 753 | 707 | * m_theta_in contains the inner shell radius in radians, while m_theta_out |
| 754 | 708 | * contains the outer shell radius in radians. |
| 755 | 709 | * |
| 756 | - * In the small angle approximation, | |
| 757 | - * \f${\tt m\_x\_in} = {\tt m\_theta\_in}^2\f$, | |
| 758 | - * \f${\tt m\_x\_out} = {\tt m\_theta\_out}^2\f$, and | |
| 759 | - * \f[{\tt m\_norm} = \frac{3}{2 \pi} | |
| 760 | - * \frac{1}{\left( {\tt m\_theta\_out}^3 - {\tt m\_theta\_in}^3 \right)}\f]. | |
| 761 | - * | |
| 762 | - * In the general case that is also valid for large angles, | |
| 763 | 710 | * \f${\tt m\_x\_in} = \sin^2 {\tt m\_theta\_in}\f$, |
| 764 | 711 | * \f${\tt m\_x\_out} = \sin^2 {\tt m\_theta\_out}\f$, and |
| 765 | 712 | * \f[{\tt m\_norm} = \frac{1}{2 \pi} |
| ... | ... | @@ -786,25 +733,17 @@ void GModelSpatialRadialShell::update() const |
| 786 | 733 | m_last_width = width(); |
| 787 | 734 | |
| 788 | 735 | // Perform precomputations |
| 789 | - m_theta_in = radius() * gammalib::deg2rad; | |
| 790 | - m_theta_out = (radius() + width()) * gammalib::deg2rad; | |
| 791 | - if (m_small_angle) { | |
| 792 | - m_x_in = m_theta_in * m_theta_in; | |
| 793 | - m_x_out = m_theta_out * m_theta_out; | |
| 794 | - double denom = c1 * (m_x_out*m_theta_out - m_x_in*m_theta_in); | |
| 795 | - m_norm = (denom > 0.0) ? 1.0 / denom : 0.0; | |
| 796 | - } | |
| 797 | - else { | |
| 798 | - double sin_theta_in = std::sin(m_theta_in); | |
| 799 | - double sin_theta_out = std::sin(m_theta_out); | |
| 800 | - double term1 = (f1(m_theta_out) - f1(m_theta_in)) * c2; | |
| 801 | - double term2 = f2(m_theta_out); | |
| 802 | - double term3 = f2(m_theta_in); | |
| 803 | - double denom = gammalib::twopi * (term1 + term2 - term3); | |
| 804 | - m_norm = (denom > 0.0) ? 1.0 / denom : 0.0; | |
| 805 | - m_x_in = sin_theta_in*sin_theta_in; | |
| 806 | - m_x_out = sin_theta_out * sin_theta_out; | |
| 807 | - } | |
| 736 | + m_theta_in = radius() * gammalib::deg2rad; | |
| 737 | + m_theta_out = (radius() + width()) * gammalib::deg2rad; | |
| 738 | + double sin_theta_in = std::sin(m_theta_in); | |
| 739 | + double sin_theta_out = std::sin(m_theta_out); | |
| 740 | + double term1 = (f1(m_theta_out) - f1(m_theta_in)) * c2; | |
| 741 | + double term2 = f2(m_theta_out); | |
| 742 | + double term3 = f2(m_theta_in); | |
| 743 | + double denom = gammalib::twopi * (term1 + term2 - term3); | |
| 744 | + m_norm = (denom > 0.0) ? 1.0 / denom : 0.0; | |
| 745 | + m_x_in = sin_theta_in * sin_theta_in; | |
| 746 | + m_x_out = sin_theta_out * sin_theta_out; | |
| 808 | 747 | |
| 809 | 748 | } // endif: update required |
| 810 | 749 | ... | ... |