Commit c4ca5cebf186ac6c4eb178cd6c9cb39049157f38

Authored by Jürgen Knödlseder
1 parent 48035849

Restrict Monte Carlo simulations of GModelSpatialDiffuseConst to simulation cone (#1674).

ChangeLog
... ... @@ -3,6 +3,7 @@
3 3 * Version 1.1.0 released
4 4 =========================
5 5  
  6 + Restrict Monte Carlo simulations in GModelSpatialDiffuseConst to simulation cone (#1674)
6 7 Use default GTime in GModelSpectral eval() and eval_gradients() methods (#1672)
7 8 Optimise GModelSpatialDiffuseMap::set_mc_cone() method (#1673)
8 9 Optimise GModelSpatialDiffuseCube::set_mc_cone() method (#1673)
... ...
... ... @@ -111,6 +111,11 @@ None
111 111  
112 112 8. Model module
113 113 ---------------
  114 +Sky directions drawn by GModelSpatialDiffuseConst::mc() are now restricted
  115 +to the simulation cone that has previously been defined using the mc_norm()
  116 +method. This speeds up considerbly the Monte Carlo simulations for an
  117 +isotropic diffuse model (#1674).
  118 +
114 119 The GModelSpectral eval() and eval_gradients() methods use an empty GTim()
115 120 object as default time argument since all spectral models are so far time-
116 121 independent. This avoids that a user needs to specify a dummy time argument
... ...
include/GModelSpatialDiffuseConst.hpp
1 1 /***************************************************************************
2 2 * GModelSpatialDiffuseConst.hpp - Spatial isotropic model class *
3 3 * ----------------------------------------------------------------------- *
4   - * copyright (C) 2010-2015 by Juergen Knoedlseder *
  4 + * copyright (C) 2010-2016 by Juergen Knoedlseder *
5 5 * ----------------------------------------------------------------------- *
6 6 * *
7 7 * This program is free software: you can redistribute it and/or modify *
... ... @@ -86,7 +86,9 @@ protected:
86 86 void free_members(void);
87 87  
88 88 // Protected members
89   - GModelPar m_value; //!< Value
  89 + GModelPar m_value; //!< Value
  90 + mutable GSkyDir m_mc_centre; //!< Simulation cone centre
  91 + mutable double m_mc_cos_radius; //!< Cosine of simulation cone radius
90 92 };
91 93  
92 94  
... ... @@ -146,29 +148,10 @@ void GModelSpatialDiffuseConst::value(const double&amp; value)
146 148  
147 149  
148 150 /***********************************************************************//**
149   - * @brief Return normalization of constant diffuse source for Monte Carlo
150   - * simulations
151   - *
152   - * @param[in] dir Centre of simulation cone.
153   - * @param[in] radius Radius of simulation cone (degrees).
154   - * @return Normalization.
155   - *
156   - * Returns the normalization of a constant diffuse source. The normalization
157   - * is given by the model value and does not depend on @p dir and @p radius.
158   - ***************************************************************************/
159   -inline
160   -double GModelSpatialDiffuseConst::mc_norm(const GSkyDir& dir,
161   - const double& radius) const
162   -{
163   - return (value());
164   -}
165   -
166   -
167   -/***********************************************************************//**
168 151 * @brief Signals whether model contains sky direction
169 152 *
170 153 * @param[in] dir Sky direction.
171   - * @param[in] margin Margin to be added to sky direction (degrees)
  154 + * @param[in] margin Margin to be added to sky direction (deg, default: 0.0).
172 155 * @return True.
173 156 *
174 157 * Signals whether a sky direction falls within the bounding circle of
... ...
src/model/GModelSpatialDiffuseConst.cpp
1 1 /***************************************************************************
2 2 * GModelSpatialDiffuseConst.cpp - Spatial isotropic model class *
3 3 * ----------------------------------------------------------------------- *
4   - * copyright (C) 2010-2015 by Juergen Knoedlseder *
  4 + * copyright (C) 2010-2016 by Juergen Knoedlseder *
5 5 * ----------------------------------------------------------------------- *
6 6 * *
7 7 * This program is free software: you can redistribute it and/or modify *
... ... @@ -41,7 +41,7 @@ const GModelSpatialDiffuseConst g_spatial_const_seed;
41 41 const GModelSpatialRegistry g_spatial_const_registry(&g_spatial_const_seed);
42 42  
43 43 /* __ Method name definitions ____________________________________________ */
44   -#define G_MC "GModelSpatialDiffuseConst::mc(GRan&)"
  44 +#define G_MC_NORM "GModelSpatialDiffuseConst::mc_norm(GSkyDir&, double&)"
45 45 #define G_READ "GModelSpatialDiffuseConst::read(GXmlElement&)"
46 46 #define G_WRITE "GModelSpatialDiffuseConst::write(GXmlElement&)"
47 47  
... ... @@ -60,6 +60,8 @@ const GModelSpatialRegistry g_spatial_const_registry(&amp;g_spatial_const_seed);
60 60  
61 61 /***********************************************************************//**
62 62 * @brief Void constructor
  63 + *
  64 + * Construct empty isotropic spatial model.
63 65 ***************************************************************************/
64 66 GModelSpatialDiffuseConst::GModelSpatialDiffuseConst(void) :
65 67 GModelSpatialDiffuse()
... ... @@ -98,11 +100,11 @@ GModelSpatialDiffuseConst::GModelSpatialDiffuseConst(const GXmlElement&amp; xml) :
98 100 /***********************************************************************//**
99 101 * @brief Value constructor
100 102 *
101   - * @param[in] value Isotropic intensity value (units sr^-1).
  103 + * @param[in] value Isotropic intensity value (\f$sr^{-1}\f$).
102 104 *
103   - * Constructs isotropic spatial model by assigning the intensity @p value of
104   - * the diffuse emission. This constructor explicitly sets the m_value
105   - * parameter of the model.
  105 + * Constructs isotropic spatial model by assigning an intensity of @p value
  106 + * in units of \f$sr^{-1}\f$ to the diffuse emission. This constructor
  107 + * explicitly sets the @a m_value member of the model.
106 108 ***************************************************************************/
107 109 GModelSpatialDiffuseConst::GModelSpatialDiffuseConst(const double& value) :
108 110 GModelSpatialDiffuse()
... ... @@ -125,6 +127,9 @@ GModelSpatialDiffuseConst::GModelSpatialDiffuseConst(const double&amp; value) :
125 127 * @brief Copy constructor
126 128 *
127 129 * @param[in] model Isotropic spatial model.
  130 + *
  131 + * Constructs isotropic spatial model by copying another isotropic spatial
  132 + * model.
128 133 ***************************************************************************/
129 134 GModelSpatialDiffuseConst::GModelSpatialDiffuseConst(const GModelSpatialDiffuseConst& model) :
130 135 GModelSpatialDiffuse(model)
... ... @@ -142,6 +147,8 @@ GModelSpatialDiffuseConst::GModelSpatialDiffuseConst(const GModelSpatialDiffuseC
142 147  
143 148 /***********************************************************************//**
144 149 * @brief Destructor
  150 + *
  151 + * Destructs isotropic spatial model.
145 152 ***************************************************************************/
146 153 GModelSpatialDiffuseConst::~GModelSpatialDiffuseConst(void)
147 154 {
... ... @@ -164,6 +171,8 @@ GModelSpatialDiffuseConst::~GModelSpatialDiffuseConst(void)
164 171 *
165 172 * @param[in] model Isotropic spatial model.
166 173 * @return Isotropic spatial model.
  174 + *
  175 + * Assigns an isotropic spatial model.
167 176 ***************************************************************************/
168 177 GModelSpatialDiffuseConst& GModelSpatialDiffuseConst::operator=(const GModelSpatialDiffuseConst& model)
169 178 {
... ... @@ -197,10 +206,13 @@ GModelSpatialDiffuseConst&amp; GModelSpatialDiffuseConst::operator=(const GModelSpat
197 206  
198 207 /***********************************************************************//**
199 208 * @brief Clear isotropic spatial model
  209 + *
  210 + * Clears the isotropic spatial model. This method is equivalent to creating
  211 + * an isotropic spatial model using the void constructor.
200 212 ***************************************************************************/
201 213 void GModelSpatialDiffuseConst::clear(void)
202 214 {
203   - // Free class members (base and derived classes, derived class first)
  215 + // Free class members
204 216 free_members();
205 217 this->GModelSpatialDiffuse::free_members();
206 218 this->GModelSpatial::free_members();
... ... @@ -219,6 +231,8 @@ void GModelSpatialDiffuseConst::clear(void)
219 231 * @brief Clone isotropic spatial model
220 232 *
221 233 * @return Pointer to deep copy of isotropic spatial model.
  234 + *
  235 + * Returns a pointer to a deep copy of the isotropic spatial model.
222 236 ***************************************************************************/
223 237 GModelSpatialDiffuseConst* GModelSpatialDiffuseConst::clone(void) const
224 238 {
... ... @@ -228,15 +242,22 @@ GModelSpatialDiffuseConst* GModelSpatialDiffuseConst::clone(void) const
228 242  
229 243  
230 244 /***********************************************************************//**
231   - * @brief Evaluate function (in units of sr^-1)
  245 + * @brief Evaluate isotropic spatial model value
  246 + *
  247 + * @param[in] photon Incident photon.
  248 + * @return Model value (\f$sr^{-1}\f$).
  249 + *
  250 + * Evaluates the isotropic spatial model for a given @p photon, characterised
  251 + * by a sky direction, energy and arrival time \f$(\vec{p},E,t)\f$. By
  252 + * definition, the isotropic spatial model and gradient are independent of
  253 + * sky direction, energy and time. The model value is given by
232 254 *
233   - * @param[in] photon Incident photon (ignored).
234   - * @return Model value (units of sr^-1).
  255 + * \f[
  256 + * M_\mathrm{S}(\vec{p}|E,t) = \frac{v}{4\pi}
  257 + * \f]
235 258 *
236   - * Evaluates the spatial part for an isotropic source model. By definition
237   - * the model value is independent from the sky direction. The model value is
238   - * given by the value parameter divided by the solid angle of the sphere
239   - * \f$4 \pi\f$.
  259 + * where \f$v\f$ is the value() parameter, which is divided by the solid
  260 + * angle \f$4\pi\f$ of the celestial sphere.
240 261 ***************************************************************************/
241 262 double GModelSpatialDiffuseConst::eval(const GPhoton& photon) const
242 263 {
... ... @@ -252,14 +273,32 @@ double GModelSpatialDiffuseConst::eval(const GPhoton&amp; photon) const
252 273  
253 274  
254 275 /***********************************************************************//**
255   - * @brief Evaluate function and gradients (in units of sr^-1)
  276 + * @brief Evaluate isotropic spatial model value and parameter gradient
  277 + *
  278 + * @param[in] photon Incident photon.
  279 + * @return Model value (\f$sr^{-1}\f$).
  280 + *
  281 + * Evaluates the isotropic spatial model for a given @p photon, characterised
  282 + * by a sky direction, energy and arrival time \f$(\vec{p},E,t)\f$, and
  283 + * computes the gradient of the value() parameter. By definition, the
  284 + * isotropic spatial model and gradient are independent of sky direction,
  285 + * energy and time. The model value is given by
256 286 *
257   - * @param[in] photon Incident photon (ignored).
258   - * @return Model value (units of sr^-1).
  287 + * \f[
  288 + * M_\mathrm{S}(\vec{p}|E,t) = \frac{v}{4\pi}
  289 + * \f]
259 290 *
260   - * Evaluates the spatial part for an isotropic source model and sets the
261   - * parameter gradient. By definition, the model value and gradient are
262   - * independent from the sky direction.
  291 + * where \f$v\f$ is the value() parameter, which is divided by the solid
  292 + * angle \f$4\pi\f$ of the celestial sphere. The value() gradient is given
  293 + * by
  294 + *
  295 + * \f[
  296 + * \frac{\partial M_\mathrm{S}(\vec{p}|E,t)}{\partial v_v} =
  297 + * \frac{v_s}{4\pi}
  298 + * \f]
  299 + *
  300 + * where \f$v=v_v v_s\f$ is the factorisation of the value() parameter into
  301 + * a value \f$v_v\f$ and scale \f$v_s\f$ term.
263 302 ***************************************************************************/
264 303 double GModelSpatialDiffuseConst::eval_gradients(const GPhoton& photon) const
265 304 {
... ... @@ -283,41 +322,91 @@ double GModelSpatialDiffuseConst::eval_gradients(const GPhoton&amp; photon) const
283 322 /***********************************************************************//**
284 323 * @brief Return MC sky direction
285 324 *
286   - * @param[in] energy Photon energy (ignored).
287   - * @param[in] time Photon arrival time (ignored).
  325 + * @param[in] energy Photon energy.
  326 + * @param[in] time Photon arrival time.
288 327 * @param[in,out] ran Random number generator.
289 328 * @return Sky direction.
290 329 *
291   - * Returns an arbitrary position on the celestial sphere. This position is
292   - * independent of event @p energy and arrival @p time.
  330 + * Returns an arbitrary direction on the celestial sphere within a simulation
  331 + * cone region that has been defined by a previous call to the mc_norm()
  332 + * method (if no such call was made the entire sky will be assumed as the
  333 + * simulation cone). The sky direction is independent of event @p energy and
  334 + * arrival @p time.
293 335 ***************************************************************************/
294 336 GSkyDir GModelSpatialDiffuseConst::mc(const GEnergy& energy,
295 337 const GTime& time,
296 338 GRan& ran) const
297 339 {
298   - // Simulate Right Ascension and Declination
299   - double ra = gammalib::twopi * ran.uniform();
300   - double dec = std::asin(2.0 * ran.uniform() - 1.0);
  340 + // Simulate offset from simulation cone centre
  341 + double theta = std::acos(1.0 - ran.uniform() * (1.0 - m_mc_cos_radius)) *
  342 + gammalib::rad2deg;
  343 + double phi = 360.0 * ran.uniform();
301 344  
302   - // Set sky direction
303   - GSkyDir dir;
304   - dir.radec(ra, dec);
  345 + // Initialise sky direction with simulation cone centre
  346 + GSkyDir dir(m_mc_centre);
305 347  
  348 + // Rotate sky direction by offset angles (phi, theta)
  349 + dir.rotate_deg(phi, theta);
  350 +
306 351 // Return sky direction
307 352 return dir;
308 353 }
309 354  
310 355  
311 356 /***********************************************************************//**
  357 + * @brief Return normalization of constant diffuse source for Monte Carlo
  358 + * simulations
  359 + *
  360 + * @param[in] dir Centre of simulation cone.
  361 + * @param[in] radius Radius of simulation cone (deg).
  362 + * @return Model normalization.
  363 + *
  364 + * @exception GException::invalid_argument
  365 + * Radius of simulation cone not coprised in [0,180] degrees.
  366 + *
  367 + * Returns the normalization of a constant diffuse source. The normalization
  368 + * is given by the product between the fraction \f$f\f$ of the sky covered
  369 + * by the simulation cone
  370 + *
  371 + * \f[
  372 + * f = \frac{2\pi \left( 1-\cos(r) \right)}{4\pi}
  373 + * \f]
  374 + *
  375 + * (where \f$r\f$ is the radius of the simulation cone) and the model
  376 + * parameter value(). The normalization only depends of the radius of the
  377 + * simulation cone and is invariant to its centre.
  378 + ***************************************************************************/
  379 +double GModelSpatialDiffuseConst::mc_norm(const GSkyDir& dir,
  380 + const double& radius) const
  381 +{
  382 + // Throw exception if the radius is invalid
  383 + if (radius < 0.0 || radius > 180.0) {
  384 + std::string msg = "Invalid simulation cone radius "+
  385 + gammalib::str(radius)+" specified. Please provide "
  386 + "a value comprised within 0 and 180 degrees.";
  387 + throw GException::invalid_argument(G_MC_NORM, msg);
  388 + }
  389 +
  390 + // Store cosine of simulation cone radius and cone centre
  391 + m_mc_centre = dir;
  392 + m_mc_cos_radius = std::cos(radius * gammalib::deg2rad);
  393 +
  394 + // Compute fraction of sky covered by the simulation cone
  395 + double fraction = 0.5 * (1.0 - m_mc_cos_radius);
  396 +
  397 + // Multiply by normalization value of model
  398 + double norm = fraction * value();
  399 +
  400 + // Return normalization
  401 + return (norm);
  402 +}
  403 +
  404 +
  405 +/***********************************************************************//**
312 406 * @brief Read model from XML element
313 407 *
314 408 * @param[in] xml XML element.
315 409 *
316   - * @exception GException::model_invalid_parnum
317   - * Invalid number of model parameters found in XML element.
318   - * @exception GException::model_invalid_parnames
319   - * Invalid model parameter names found in XML element.
320   - *
321 410 * Read the isotropic source model information from an XML element. The XML
322 411 * element is expected to have the following format:
323 412 *
... ... @@ -331,23 +420,11 @@ void GModelSpatialDiffuseConst::read(const GXmlElement&amp; xml)
331 420 // Clear model
332 421 clear();
333 422  
334   - // Verify that XML element has exactly 1 parameters
335   - if (xml.elements() != 1 || xml.elements("parameter") != 1) {
336   - throw GException::model_invalid_parnum(G_READ, xml,
337   - "Isotropic source model requires exactly 1 parameter.");
338   - }
339   -
340   - // Get pointer on model parameter
341   - const GXmlElement* par = xml.element("parameter", 0);
  423 + // Get value parameter
  424 + const GXmlElement* par = gammalib::xml_get_par(G_READ, xml, "Value");
342 425  
343   - // Get value
344   - if (par->attribute("name") == "Value") {
345   - m_value.read(*par);
346   - }
347   - else {
348   - throw GException::model_invalid_parnames(G_READ, xml,
349   - "Isotropic source model requires \"Value\" parameter.");
350   - }
  426 + // Read value parameter
  427 + m_value.read(*par);
351 428  
352 429 // Return
353 430 return;
... ... @@ -361,10 +438,6 @@ void GModelSpatialDiffuseConst::read(const GXmlElement&amp; xml)
361 438 *
362 439 * @exception GException::model_invalid_spatial
363 440 * Existing XML element is not of type "ConstantValue"
364   - * @exception GException::model_invalid_parnum
365   - * Invalid number of model parameters found in XML element.
366   - * @exception GException::model_invalid_parnames
367   - * Invalid model parameter names found in XML element.
368 441 *
369 442 * Write the isotropic source model information into an XML element. The XML
370 443 * element will have the following format:
... ... @@ -387,28 +460,11 @@ void GModelSpatialDiffuseConst::write(GXmlElement&amp; xml) const
387 460 "Spatial model is not of type \"ConstantValue\".");
388 461 }
389 462  
390   - // If XML element has 0 nodes then append 1 parameter node
391   - if (xml.elements() == 0) {
392   - xml.append(GXmlElement("parameter name=\"Value\""));
393   - }
394   -
395   - // Verify that XML element has exactly 1 parameter
396   - if (xml.elements() != 1 || xml.elements("parameter") != 1) {
397   - throw GException::model_invalid_parnum(G_WRITE, xml,
398   - "Isotropic source model requires exactly 1 parameter.");
399   - }
  463 + // Get or create Value parameter
  464 + GXmlElement* par = gammalib::xml_need_par(G_WRITE, xml, "Value");
400 465  
401   - // Get pointers on both model parameters
402   - GXmlElement* par = xml.element("parameter", 0);
403   -
404   - // Set or update parameter
405   - if (par->attribute("name") == "Value") {
406   - m_value.write(*par);
407   - }
408   - else {
409   - throw GException::model_invalid_parnames(G_WRITE, xml,
410   - "Isotropic source model requires \"Value\" parameter.");
411   - }
  466 + // Write parameter
  467 + m_value.write(*par);
412 468  
413 469 // Return
414 470 return;
... ... @@ -467,6 +523,10 @@ void GModelSpatialDiffuseConst::init_members(void)
467 523 m_value.gradient(0.0);
468 524 m_value.has_grad(true);
469 525  
  526 + // Initialise other members
  527 + m_mc_centre.clear();
  528 + m_mc_cos_radius = -1.0; // Set simulation cone to allsky
  529 +
470 530 // Set parameter pointer(s)
471 531 m_pars.clear();
472 532 m_pars.push_back(&m_value);
... ... @@ -484,7 +544,9 @@ void GModelSpatialDiffuseConst::init_members(void)
484 544 void GModelSpatialDiffuseConst::copy_members(const GModelSpatialDiffuseConst& model)
485 545 {
486 546 // Copy members
487   - m_value = model.m_value;
  547 + m_value = model.m_value;
  548 + m_mc_centre = model.m_mc_centre;
  549 + m_mc_cos_radius = model.m_mc_cos_radius;
488 550  
489 551 // Set parameter pointer(s)
490 552 m_pars.clear();
... ...