Commit 0a0628b475a93ea29f67bf8eee289a127dfe3bdc

Authored by Jürgen Knödlseder
1 parent 86b32056

Remove small angle approximation (always compute in spherical system).

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
... ...
... ... @@ -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&amp; 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&amp; 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&amp; 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&amp; 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&amp; 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&amp; 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  
... ...